tktreectrl-2.2.8/0000755000175600010010000000000011073207471012115 5ustar TimNonetktreectrl-2.2.8/aclocal.m40000664000175600010010000000025710753137620013765 0ustar TimNone# # Include the TEA standard macro set # builtin(include,tclconfig/tcl.m4) # # Add here whatever m4 macros you want to define for your package # builtin(include,winrc.m4) tktreectrl-2.2.8/ChangeLog0000700000175600010010000001465510762067113013674 0ustar TimNone2008-02-27 Jeff Hobbs * generic/tkTreeTheme.c: use Get|SetWindowLongPtr to work with Win64. Requires latest Windows headers. 2008-02-23 Jeff Hobbs * generic/tkTreeTheme.c (DllMain): get module at dll load time to avoid GetModuleHandleEx call. 2008-02-22 Jeff Hobbs * demos/demo.tcl, doc/What's New in TkTreeCtrl.html: * doc/treectrl.html, doc/treectrl.man, doc/treectrl.n * shellicon/configure, shellicon/configure.ac: * configure, configure.ac: bump version to 2.2.5 * winrc.m4: correct RC_DEPARG definition for !gcc case. * generic/tkTreeNotify.c (Percents_ItemDelete, ExpandItemList) (Percents_ItemVisibility, Percents_Selection): remove TclFormatInt * generic/qebind.c (QE_ExpandNumber): references and add ExpandItemList to simplify item list expansion. Corrects crash with 8.4-built treectrl used in 8.5. 2007-05-10 Jeff Hobbs * generic/tkTreeUtils.c (Tree_FillRegion): disable OS X specific code as Tk improvements have made it unnecessary, and it actually made it act funny in 8.5. 2007-01-26 Jeff Hobbs * generic/tkTreeCtrl.h (vsnprintf): _vsnprintf on Windows. 2006-08-15 Jeff Hobbs * library/filelist-bindings.tcl (::TreeCtrl::EditClose): rewrote bindings of edit widget helpers to use TreeCtrlEntry and TreeCtrlText classes. Fix for binding possibly triggering . * generic/tkTreeDisplay.c (Tree_Display): Allow Tree_DeselectHidden * generic/tkTreeItem.c (Item_Configure): to be deferred to next * generic/tkTreeCtrl.h: redraw by calling Tree_DInfoChanged(tree, DINFO_REDO_SELECTION). Significantly improves performance of multiple item visibility changes. 2006-08-14 Jeff Hobbs * generic/tkTreeItem.c (Item_Configure): on checking for -visible, verify that the value actually changed, because it can be expensive. 2006-08-04 Jeff Hobbs * generic/tkTreeCtrl.c (TreeWidgetCmd): set the tk caret when the active item changes. 2006-04-05 Jeff Hobbs * generic/tkTreeCtrl.c (LoupeCmd): correct loupe on OS X x86. * configure, configure.ac: add AC_C_BIGENDIAN check * tclconfig/tcl.m4: TEA rcs 1.91 2006/03/28 21:07:09 2006-01-25 Jeff Hobbs * configure, configure.ac: update to TEA 3.5 * tclconfig/tcl.m4: TEA rcs 1.89 2006/01/25 21:25:02 2005-12-02 Jeff Hobbs * tclconfig/tcl.m4, configure.ac, configure: update to TEA 3.4 2005-09-27 Jeff Hobbs * generic/tkTreeCtrl.c (LoupeCmd): don't capture display (it causes flashing) on OS X. 2005-09-26 Jeff Hobbs * generic/tkTreeCtrl.c (LoupeCmd): add OS X support. Correct Win32 code to use grab size constraints and honor the virtual system metrics (OS X needs similar correction still). Hide cursor on OS X and capture display while grabbing. 2005-09-25 Jeff Hobbs * demos/demo.tcl: just check for 'loupe' to run loupe demo * generic/tkTreeCtrl.c (LoupeCmd): add Win32 code to enable loupe functionality on Windows. 2005-08-22 Jeff Hobbs * Makefile.in: install man pages with html docs * configure, configure.ac, tclconfig/tcl.m4: updated to newer TEA system 2005-08-09 Jeff Hobbs * generic/tkTreeStyle.c (Style_DoLayout): use if instead of tertiary ?: operator for funcs with different return types. *** other mods by Tim Baker (treectrl) to this point *** 2005-05-02 Jeff Hobbs * generic/tkTreeTheme.c: correct headers to build on unix and use of c++-style var decls. 2005-03-25 Jeff Hobbs * Makefile.in, generic/tkTreeCtrl.h: OS X patch from * configure, configure.ac, tclconfig/tcl.m4: Steffen * license.terms (new): 2005-03-18 Jeff Hobbs * Makefile.in (AR): use @AR@ * configure, configure.ac, tclconfig/tcl.m4: TEA 3.2 update 2005-02-14 Jeff Hobbs * demos/demo.tcl: try loading treectrl before trying the IsDevelopment branch of loading. * generic/tkTreeItem.c (CompareAscii, CompareDict): handle the case where no text value has been set for sorting *** other mods by Tim Baker (treectrl) to this point *** 2004-11-30 Jeff Hobbs * generic/tkTreeItem.c (TreeItem_FromObj): s/MOD_/TMOD_ to prevent existing defined name conflict * generic/tkTreeElem.c: add "Elem" to a few names to prevent name collision (notable CreateBitmap on Windows). 2004-11-29 Jeff Hobbs * generic/tkTreeItem.c, generic/tkTreeElem.c: whitespace police * generic/tkTreeCtrl.c: adapt to Tk_PhotoPut(Zoomed)Block API changes for 8.5 (TIP #116). 2004-10-09 Jeff Hobbs * Makefile.in: Revamp build system to use TEA 3.1 setup. * configure: * configure.ac: * tclconfig/tcl.m4: * pkgIndex.tcl.in: Automate creation of pkgIndex.tcl and use * demos/demo.tcl: tcl_findLibrary to avoid the issue of build vs. * tests/all.tcl: install package. * generic/tkTreeCtrl.c: * generic/tkTreeDisplay.c: correctly handle the damageRgn var. * generic/tkTreeUtils.c: Implement Tk_OffsetRegion as XOffsetRegion on unix. (werner) * library/filelist-bindings.tcl: ensure TreeCtrl namespace exists * library/treectrl.tcl: source filelist-bindings *** Tim Baker (treectrl) made numerous changes for 1.1 *** 2004-02-09 Jeff Hobbs * generic/tkTreeCtrl.c (ImageChangedProc): cause image change to * generic/tkTreeColumn.c (ImageChangedProc): refresh window. Could narrow down the full update, but better than nothing. 2003-12-02 Jeff Hobbs * library/filelist-bindings.tcl: whitespace police added check for Priv(buttonMode) before use in bindings that may not get an associated button-down event * library/treectrl.tcl: whitespace police 2003-11-26 Jeff Hobbs * generic/tkTreeCtrl.c (LoupeCmd): remove extra interp arg to Tk_PhotoPutZoomedBlock. 2003-11-25 Jeff Hobbs * generic/tkTreeColumn.c: whitespace police * generic/tkTreeCtrl.h: * generic/tkTreeCtrl.c: whitespace police (TreeWorldChanged): add calls to TreeStyle_TreeChanged and TreeColumn_TreeChanged to correctly display font size changes * ChangeLog: created tktreectrl-2.2.8/configure0000775000175600010010000130142211073204663014031 0ustar TimNone#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for treectrl 2.2. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 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=: # Zsh 3.x and 4.x performs 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 # PATH needs CR # 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 # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false 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.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. 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 echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. 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 # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH if test "x$CONFIG_SHELL" = x; then if (eval ":") 2>/dev/null; then as_have_required=yes else as_have_required=no fi if test $as_have_required = yes && (eval ": (as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=\$LINENO as_lineno_2=\$LINENO test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } ") 2> /dev/null; then : else as_candidate_shells= as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. case $as_dir in /*) for as_base in sh bash ksh sh5; do as_candidate_shells="$as_candidate_shells $as_dir/$as_base" done;; esac done IFS=$as_save_IFS for as_shell in $as_candidate_shells $SHELL; do # Try only shells that exist, to save several forks. if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { ("$as_shell") 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs 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 : _ASEOF }; then CONFIG_SHELL=$as_shell as_have_required=yes if { "$as_shell" 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs 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_func_return () { (exit $1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = "$1" ); then : else exitcode=1 echo positional parameters were not saved. fi test $exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } _ASEOF }; then break fi fi done if test "x$CONFIG_SHELL" != x; then for as_var in BASH_ENV ENV do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test $as_have_required = no; then echo This script requires a shell more modern than all the echo shells that I found on your system. Please install a echo modern shell, or manually run the script under such a echo shell if you do have one. { (exit 1); exit 1; } fi fi fi (eval "as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0") || { echo No shell found that supports shell functions. echo Please tell autoconf@gnu.org about your system, echo including any error possibly output before this echo message } as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. 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" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # 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 } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi 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 fi echo >conf$$.file 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 -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' 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=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # 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 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, 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= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='treectrl' PACKAGE_TARNAME='treectrl' PACKAGE_VERSION='2.2' PACKAGE_STRING='treectrl 2.2' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datarootdir datadir sysconfdir sharedstatedir localstatedir includedir oldincludedir docdir infodir htmldir dvidir pdfdir psdir libdir localedir mandir DEFS ECHO_C ECHO_N ECHO_T LIBS build_alias host_alias target_alias PACKAGE_PATCHLEVEL CYGPATH EXEEXT PKG_LIB_FILE PKG_STUB_LIB_FILE PKG_STUB_SOURCES PKG_STUB_OBJECTS PKG_TCL_SOURCES PKG_HEADERS PKG_INCLUDES PKG_LIBS PKG_CFLAGS TCL_VERSION TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_LIBS TCL_DEFS TCL_EXTRA_CFLAGS TCL_LD_FLAGS TCL_SHLIB_LD_LIBS TK_VERSION TK_BIN_DIR TK_SRC_DIR TK_LIB_FILE TK_LIB_FLAG TK_LIB_SPEC TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_STUB_LIB_SPEC TK_LIBS TK_XINCLUDES CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC OBJEXT CPP INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA SET_MAKE RANLIB GREP EGREP MATH_LIBS PKG_SOURCES PKG_OBJECTS TCL_TOP_DIR_NATIVE TCL_GENERIC_DIR_NATIVE TCL_UNIX_DIR_NATIVE TCL_WIN_DIR_NATIVE TCL_BMAP_DIR_NATIVE TCL_TOOL_DIR_NATIVE TCL_PLATFORM_DIR_NATIVE TCL_INCLUDES TK_TOP_DIR_NATIVE TK_UNIX_DIR_NATIVE TK_WIN_DIR_NATIVE TK_GENERIC_DIR_NATIVE TK_XLIB_DIR_NATIVE TK_PLATFORM_DIR_NATIVE TK_INCLUDES XMKMF subdirs RC RC_OUT RC_TYPE RC_INCLUDE RC_DEFINE RC_DEPARG RES MACHINE CLEANFILES TCL_THREADS SHARED_BUILD AR CELIB_DIR LIBOBJS DL_LIBS CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING STLIB_LD SHLIB_LD SHLIB_LD_LIBS SHLIB_CFLAGS LD_LIBRARY_PATH_VAR TCL_DBGX CFLAGS_DEFAULT LDFLAGS_DEFAULT MAKE_LIB MAKE_SHARED_LIB MAKE_STATIC_LIB MAKE_STUB_LIB RANLIB_STUB TCLSH_PROG WISH_PROG LTLIBOBJS' ac_subst_files='' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP XMKMF' ac_subdirs_all='shellicon' # Initialize some variables set by options. ac_init_help= ac_init_version=false # 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=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_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=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_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=\$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_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=\$ac_optarg ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=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 ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && 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'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute directory names. 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 case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; } 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 echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 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 .` || { echo "$as_me: error: Working directory cannot be determined" >&2 { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || { echo "$as_me: error: pwd does not report name of working directory" >&2 { (exit 1); exit 1; }; } # 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 -- "$0" || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X"$0" | 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 .." { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 { (exit 1); exit 1; }; } 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 treectrl 2.2 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/treectrl] --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 treectrl 2.2:";; esac cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-shellicon build the shellicon extension (default: no) --enable-threads build with threads --enable-shared build and link with shared libraries (default: on) --enable-64bit enable 64bit support (default: off) --enable-64bit-vis enable 64bit Sparc VIS support (default: off) --enable-wince enable Win/CE support (where applicable) --disable-load disallow dynamic loading and "load" command (default: enabled) --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-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 if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory 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. _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" || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`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 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 treectrl configure 2.2 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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 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 treectrl $as_me 2.2, which was generated by GNU Autoconf 2.61. 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=. 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=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$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 ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export 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 cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX 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_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_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 cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" 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'; { (exit 1); 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 # 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 # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then set x "$CONFIG_SITE" elif test "x$prefix" != xNONE; then set x "$prefix/share/config.site" "$prefix/etc/config.site" else set x "$ac_default_prefix/share/config.site" \ "$ac_default_prefix/etc/config.site" fi shift for ac_site_file do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" 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. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 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,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 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 { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`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. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } 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 PACKAGE_PATCHLEVEL=2.2.8 cat >>confdefs.h <<_ACEOF #define PACKAGE_PATCHLEVEL "$PACKAGE_PATCHLEVEL" _ACEOF # TEA extensions pass this us the version of TEA they think they # are compatible with. TEA_VERSION="3.5" { echo "$as_me:$LINENO: checking for correct TEA configuration" >&5 echo $ECHO_N "checking for correct TEA configuration... $ECHO_C" >&6; } if test x"${PACKAGE_NAME}" = x ; then { { echo "$as_me:$LINENO: error: The PACKAGE_NAME variable must be defined by your TEA configure.in" >&5 echo "$as_me: error: The PACKAGE_NAME variable must be defined by your TEA configure.in" >&2;} { (exit 1); exit 1; }; } fi if test x"3.5" = x ; then { { echo "$as_me:$LINENO: error: TEA version not specified." >&5 echo "$as_me: error: TEA version not specified." >&2;} { (exit 1); exit 1; }; } elif test "3.5" != "${TEA_VERSION}" ; then { echo "$as_me:$LINENO: result: warning: requested TEA version \"3.5\", have \"${TEA_VERSION}\"" >&5 echo "${ECHO_T}warning: requested TEA version \"3.5\", have \"${TEA_VERSION}\"" >&6; } else { echo "$as_me:$LINENO: result: ok (TEA ${TEA_VERSION})" >&5 echo "${ECHO_T}ok (TEA ${TEA_VERSION})" >&6; } fi case "`uname -s`" in *win32*|*WIN32*|*CYGWIN_NT*|*CYGWIN_9*|*CYGWIN_ME*|*MINGW32_*) # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CYGPATH+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CYGPATH="cygpath -w" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $CYGPATH" >&5 echo "${ECHO_T}$CYGPATH" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi EXEEXT=".exe" TEA_PLATFORM="windows" ;; *) CYGPATH=echo EXEEXT="" TEA_PLATFORM="unix" ;; 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 # 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_... 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 { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in tclconfig \"$srcdir\"/tclconfig" >&5 echo "$as_me: error: cannot find install-sh or install.sh in tclconfig \"$srcdir\"/tclconfig" >&2;} { (exit 1); exit 1; }; } 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 { echo "$as_me:$LINENO: checking for Tcl configuration" >&5 echo $ECHO_N "checking for Tcl configuration... $ECHO_C" >&6; } if test "${ac_cv_c_tclconfig+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { echo "$as_me:$LINENO: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 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 { { echo "$as_me:$LINENO: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&5 echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&2;} { (exit 1); exit 1; }; } 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 -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` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig=`(cd $i/Tcl.framework; pwd)` break fi done fi # 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/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 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 -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" { echo "$as_me:$LINENO: WARNING: Can't find Tcl configuration definitions" >&5 echo "$as_me: WARNING: Can't find Tcl configuration definitions" >&2;} exit 0 else no_tcl= TCL_BIN_DIR=${ac_cv_c_tclconfig} { echo "$as_me:$LINENO: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 echo "${ECHO_T}found ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi fi { echo "$as_me:$LINENO: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 echo $ECHO_N "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... $ECHO_C" >&6; } if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then { echo "$as_me:$LINENO: result: loading" >&5 echo "${ECHO_T}loading" >&6; } . ${TCL_BIN_DIR}/tclConfig.sh else { echo "$as_me:$LINENO: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 echo "${ECHO_T}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 arbitary 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"` -framework ${TCL_LIB_FILE}" break fi done fi if test -f ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}; then TCL_STUB_LIB_SPEC="-L${TCL_BIN_DIR} ${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}\"" #-------------------------------------------------------------------- # 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 { echo "$as_me:$LINENO: checking for Tk configuration" >&5 echo $ECHO_N "checking for Tk configuration... $ECHO_C" >&6; } if test "${ac_cv_c_tkconfig+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { echo "$as_me:$LINENO: WARNING: --with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself" >&5 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 { { echo "$as_me:$LINENO: error: ${with_tkconfig} directory doesn't contain tkConfig.sh" >&5 echo "$as_me: error: ${with_tkconfig} directory doesn't contain tkConfig.sh" >&2;} { (exit 1); exit 1; }; } 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 -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` \ ; 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/lib 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig=`(cd $i; pwd)` break fi done fi # 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 -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" { echo "$as_me:$LINENO: WARNING: Can't find Tk configuration definitions" >&5 echo "$as_me: WARNING: Can't find Tk configuration definitions" >&2;} exit 0 else no_tk= TK_BIN_DIR=${ac_cv_c_tkconfig} { echo "$as_me:$LINENO: result: found ${TK_BIN_DIR}/tkConfig.sh" >&5 echo "${ECHO_T}found ${TK_BIN_DIR}/tkConfig.sh" >&6; } fi fi { echo "$as_me:$LINENO: checking for existence of ${TK_BIN_DIR}/tkConfig.sh" >&5 echo $ECHO_N "checking for existence of ${TK_BIN_DIR}/tkConfig.sh... $ECHO_C" >&6; } if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then { echo "$as_me:$LINENO: result: loading" >&5 echo "${ECHO_T}loading" >&6; } . ${TK_BIN_DIR}/tkConfig.sh else { echo "$as_me:$LINENO: result: could not find ${TK_BIN_DIR}/tkConfig.sh" >&5 echo "${ECHO_T}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 arbitary 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"` -framework ${TK_LIB_FILE}" break fi done fi if test -f ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}; then TK_STUB_LIB_SPEC="-L${TK_BIN_DIR} ${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}\"" # Ensure windowingsystem is defined if test "${TEA_PLATFORM}" = "unix" ; then case ${TK_DEFS} in *MAC_OSX_TK*) cat >>confdefs.h <<\_ACEOF #define MAC_OSX_TK 1 _ACEOF TEA_WINDOWINGSYSTEM="aqua" ;; *) TEA_WINDOWINGSYSTEM="x11" ;; esac elif test "${TEA_PLATFORM}" = "windows" ; then TEA_WINDOWINGSYSTEM="win32" fi #----------------------------------------------------------------------- # 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 { echo "$as_me:$LINENO: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&5 echo "$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&6;} prefix=${TCL_PREFIX} else { echo "$as_me:$LINENO: --prefix defaulting to /usr/local" >&5 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 { echo "$as_me:$LINENO: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&5 echo "$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&6;} exec_prefix=${TCL_EXEC_PREFIX} else { echo "$as_me:$LINENO: --exec-prefix defaulting to ${prefix}" >&5 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, AC_PROG_INSTALL 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. # If the user did not set CFLAGS, set it now to keep # the AC_PROG_CC macro from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" 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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO: checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out 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. { echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # # List of possible output files, starting from the most likely. # The algorithm is not robust to junk in `.', hence go to wildcards (a.*) # only as a last resort. b.out is created by i960 compilers. ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' # # The IRIX 6 linker writes into existing files which may not be # executable, retaining their permissions. Remove them first so a # subsequent execution test works. ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link_default") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; 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 | *.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 { echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6; } if test -z "$ac_file"; then echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } { echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6; } { echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; 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 | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext { echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT { echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; 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 ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 { echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$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 { echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* 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" 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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) { echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6; } ;; xno) { echo "$as_me:$LINENO: result: unsupported" >&5 echo "${ECHO_T}unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; esac 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 { echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 to if __STDC__ is defined, since # 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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f 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 { echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$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 to if __STDC__ is defined, since # 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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } 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 # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. { echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done IFS=$as_save_IFS fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&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 { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } SET_MAKE= else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 echo "${ECHO_T}$ac_ct_RANLIB" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&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.) #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Extract the first word of "grep ggrep" to use in msg output if test -z "$GREP"; then set dummy grep ggrep; ac_prog_name=$2 if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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" { test -f "$ac_path_GREP" && $as_test_x "$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 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" 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 ac_count=`expr $ac_count + 1` 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 fi GREP="$ac_cv_path_GREP" if test -z "$GREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_GREP=$GREP fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 echo "${ECHO_T}$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else # Extract the first word of "egrep" to use in msg output if test -z "$EGREP"; then set dummy egrep; ac_prog_name=$2 if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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" { test -f "$ac_path_EGREP" && $as_test_x "$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 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" 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 ac_count=`expr $ac_count + 1` 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 fi EGREP="$ac_cv_path_EGREP" if test -z "$EGREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_EGREP=$EGREP fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #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 rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF 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=`echo "ac_cv_header_$ac_header" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `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 { echo "$as_me:$LINENO: checking if the compiler understands -pipe" >&5 echo $ECHO_N "checking if the compiler understands -pipe... $ECHO_C" >&6; } OLDCC="$CC" CC="$CC -pipe" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CC="$OLDCC" { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi #-------------------------------------------------------------------- # Common compiler flag setup #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; } if test "${ac_cv_c_bigendian+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # See if sys/param.h defines the BYTE_ORDER macro. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then # It does; now see whether it defined to BIG_ENDIAN or not. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_c_bigendian=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # It does not; compile a test program. if test "$cross_compiling" = yes; then # try to guess the endianness by grepping values into an object file ac_cv_c_bigendian=unknown cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 }; void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } int main () { _ascii (); _ebcdic (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_bigendian=no else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 echo "${ECHO_T}$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in yes) cat >>confdefs.h <<\_ACEOF #define WORDS_BIGENDIAN 1 _ACEOF ;; no) ;; *) { { echo "$as_me:$LINENO: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&5 echo "$as_me: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} { (exit 1); exit 1; }; } ;; esac if test "${TEA_PLATFORM}" = "unix" ; then #-------------------------------------------------------------------- # On a few very rare systems, all of the libm.a stuff is # already in libc.a. Set compiler flags accordingly. # Also, Linux requires the "ieee" library for math to work # right (and it must appear before "-lm"). #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking for sin" >&5 echo $ECHO_N "checking for sin... $ECHO_C" >&6; } if test "${ac_cv_func_sin+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define sin to an innocuous variant, in case declares sin. For example, HP-UX 11i declares gettimeofday. */ #define sin innocuous_sin /* System header to define __stub macros and hopefully few prototypes, which can conflict with char sin (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef sin /* 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 sin (); /* 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_sin || defined __stub___sin choke me #endif int main () { return sin (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_sin=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_sin=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_sin" >&5 echo "${ECHO_T}$ac_cv_func_sin" >&6; } if test $ac_cv_func_sin = yes; then MATH_LIBS="" else MATH_LIBS="-lm" fi { echo "$as_me:$LINENO: checking for main in -lieee" >&5 echo $ECHO_N "checking for main in -lieee... $ECHO_C" >&6; } if test "${ac_cv_lib_ieee_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lieee $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_ieee_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_ieee_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_ieee_main" >&5 echo "${ECHO_T}$ac_cv_lib_ieee_main" >&6; } if test $ac_cv_lib_ieee_main = yes; then MATH_LIBS="-lieee $MATH_LIBS" fi #-------------------------------------------------------------------- # Interactive UNIX requires -linet instead of -lsocket, plus it # needs net/errno.h to define the socket-related error codes. #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking for main in -linet" >&5 echo $ECHO_N "checking for main in -linet... $ECHO_C" >&6; } if test "${ac_cv_lib_inet_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-linet $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_inet_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_inet_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_inet_main" >&5 echo "${ECHO_T}$ac_cv_lib_inet_main" >&6; } if test $ac_cv_lib_inet_main = yes; then LIBS="$LIBS -linet" fi if test "${ac_cv_header_net_errno_h+set}" = set; then { echo "$as_me:$LINENO: checking for net/errno.h" >&5 echo $ECHO_N "checking for net/errno.h... $ECHO_C" >&6; } if test "${ac_cv_header_net_errno_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_net_errno_h" >&5 echo "${ECHO_T}$ac_cv_header_net_errno_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking net/errno.h usability" >&5 echo $ECHO_N "checking net/errno.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking net/errno.h presence" >&5 echo $ECHO_N "checking net/errno.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: net/errno.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: net/errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: net/errno.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: net/errno.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: net/errno.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: net/errno.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: net/errno.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: net/errno.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: net/errno.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: net/errno.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: net/errno.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: net/errno.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: net/errno.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: net/errno.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: net/errno.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: net/errno.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for net/errno.h" >&5 echo $ECHO_N "checking for net/errno.h... $ECHO_C" >&6; } if test "${ac_cv_header_net_errno_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_net_errno_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_net_errno_h" >&5 echo "${ECHO_T}$ac_cv_header_net_errno_h" >&6; } fi if test $ac_cv_header_net_errno_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_NET_ERRNO_H 1 _ACEOF fi #-------------------------------------------------------------------- # Check for the existence of the -lsocket and -lnsl libraries. # The order here is important, so that they end up in the right # order in the command line generated by make. Here are some # special considerations: # 1. Use "connect" and "accept" to check for -lsocket, and # "gethostbyname" to check for -lnsl. # 2. Use each function name only once: can't redo a check because # autoconf caches the results of the last check and won't redo it. # 3. Use -lnsl and -lsocket only if they supply procedures that # aren't already present in the normal libraries. This is because # IRIX 5.2 has libraries, but they aren't needed and they're # bogus: they goof up name resolution if used. # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. # To get around this problem, check for both libraries together # if -lsocket doesn't work by itself. #-------------------------------------------------------------------- tcl_checkBoth=0 { echo "$as_me:$LINENO: checking for connect" >&5 echo $ECHO_N "checking for connect... $ECHO_C" >&6; } if test "${ac_cv_func_connect+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define connect to an innocuous variant, in case declares connect. For example, HP-UX 11i declares gettimeofday. */ #define connect innocuous_connect /* System header to define __stub macros and hopefully few prototypes, which can conflict with char connect (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef connect /* 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 connect (); /* 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_connect || defined __stub___connect choke me #endif int main () { return connect (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_connect=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_connect=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 echo "${ECHO_T}$ac_cv_func_connect" >&6; } if test $ac_cv_func_connect = yes; then tcl_checkSocket=0 else tcl_checkSocket=1 fi if test "$tcl_checkSocket" = 1; then { echo "$as_me:$LINENO: checking for setsockopt" >&5 echo $ECHO_N "checking for setsockopt... $ECHO_C" >&6; } if test "${ac_cv_func_setsockopt+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define setsockopt to an innocuous variant, in case declares setsockopt. For example, HP-UX 11i declares gettimeofday. */ #define setsockopt innocuous_setsockopt /* System header to define __stub macros and hopefully few prototypes, which can conflict with char setsockopt (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef setsockopt /* 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 setsockopt (); /* 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_setsockopt || defined __stub___setsockopt choke me #endif int main () { return setsockopt (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_setsockopt=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_setsockopt=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_setsockopt" >&5 echo "${ECHO_T}$ac_cv_func_setsockopt" >&6; } if test $ac_cv_func_setsockopt = yes; then : else { echo "$as_me:$LINENO: checking for setsockopt in -lsocket" >&5 echo $ECHO_N "checking for setsockopt in -lsocket... $ECHO_C" >&6; } if test "${ac_cv_lib_socket_setsockopt+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 setsockopt (); int main () { return setsockopt (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_socket_setsockopt=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_socket_setsockopt=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_socket_setsockopt" >&5 echo "${ECHO_T}$ac_cv_lib_socket_setsockopt" >&6; } if test $ac_cv_lib_socket_setsockopt = yes; then LIBS="$LIBS -lsocket" else tcl_checkBoth=1 fi fi fi if test "$tcl_checkBoth" = 1; then tk_oldLibs=$LIBS LIBS="$LIBS -lsocket -lnsl" { echo "$as_me:$LINENO: checking for accept" >&5 echo $ECHO_N "checking for accept... $ECHO_C" >&6; } if test "${ac_cv_func_accept+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define accept to an innocuous variant, in case declares accept. For example, HP-UX 11i declares gettimeofday. */ #define accept innocuous_accept /* System header to define __stub macros and hopefully few prototypes, which can conflict with char accept (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef accept /* 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 accept (); /* 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_accept || defined __stub___accept choke me #endif int main () { return accept (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_accept=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_accept=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_accept" >&5 echo "${ECHO_T}$ac_cv_func_accept" >&6; } if test $ac_cv_func_accept = yes; then tcl_checkNsl=0 else LIBS=$tk_oldLibs fi fi { echo "$as_me:$LINENO: checking for gethostbyname" >&5 echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6; } if test "${ac_cv_func_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define gethostbyname to an innocuous variant, in case declares gethostbyname. For example, HP-UX 11i declares gettimeofday. */ #define gethostbyname innocuous_gethostbyname /* System header to define __stub macros and hopefully few prototypes, which can conflict with char gethostbyname (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef gethostbyname /* 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 gethostbyname (); /* 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_gethostbyname || defined __stub___gethostbyname choke me #endif int main () { return gethostbyname (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6; } if test $ac_cv_func_gethostbyname = yes; then : else { echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6; } if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_nsl_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_nsl_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6; } if test $ac_cv_lib_nsl_gethostbyname = yes; then LIBS="$LIBS -lnsl" fi fi # Don't perform the eval of the libraries here because DL_LIBS # won't be set until we call TEA_CONFIG_CFLAGS TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}' { echo "$as_me:$LINENO: checking dirent.h" >&5 echo $ECHO_N "checking dirent.h... $ECHO_C" >&6; } if test "${tcl_cv_dirent_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { #ifndef _POSIX_SOURCE # ifdef __Lynx__ /* * Generate compilation error to make the test fail: Lynx headers * are only valid if really in the POSIX environment. */ missing_procedure(); # endif #endif DIR *d; struct dirent *entryPtr; char *p; d = opendir("foobar"); entryPtr = readdir(d); p = entryPtr->d_name; closedir(d); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then tcl_cv_dirent_h=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_dirent_h=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $tcl_cv_dirent_h" >&5 echo "${ECHO_T}$tcl_cv_dirent_h" >&6; } if test $tcl_cv_dirent_h = no; then cat >>confdefs.h <<\_ACEOF #define NO_DIRENT_H 1 _ACEOF fi if test "${ac_cv_header_errno_h+set}" = set; then { echo "$as_me:$LINENO: checking for errno.h" >&5 echo $ECHO_N "checking for errno.h... $ECHO_C" >&6; } if test "${ac_cv_header_errno_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5 echo "${ECHO_T}$ac_cv_header_errno_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking errno.h usability" >&5 echo $ECHO_N "checking errno.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking errno.h presence" >&5 echo $ECHO_N "checking errno.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: errno.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: errno.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: errno.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: errno.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: errno.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: errno.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: errno.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: errno.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for errno.h" >&5 echo $ECHO_N "checking for errno.h... $ECHO_C" >&6; } if test "${ac_cv_header_errno_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_errno_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5 echo "${ECHO_T}$ac_cv_header_errno_h" >&6; } fi if test $ac_cv_header_errno_h = yes; then : else cat >>confdefs.h <<\_ACEOF #define NO_ERRNO_H 1 _ACEOF fi if test "${ac_cv_header_float_h+set}" = set; then { echo "$as_me:$LINENO: checking for float.h" >&5 echo $ECHO_N "checking for float.h... $ECHO_C" >&6; } if test "${ac_cv_header_float_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_float_h" >&5 echo "${ECHO_T}$ac_cv_header_float_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking float.h usability" >&5 echo $ECHO_N "checking float.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking float.h presence" >&5 echo $ECHO_N "checking float.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: float.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: float.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: float.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: float.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: float.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: float.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: float.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: float.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: float.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: float.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: float.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: float.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: float.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: float.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: float.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: float.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for float.h" >&5 echo $ECHO_N "checking for float.h... $ECHO_C" >&6; } if test "${ac_cv_header_float_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_float_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_float_h" >&5 echo "${ECHO_T}$ac_cv_header_float_h" >&6; } fi if test $ac_cv_header_float_h = yes; then : else cat >>confdefs.h <<\_ACEOF #define NO_FLOAT_H 1 _ACEOF fi if test "${ac_cv_header_values_h+set}" = set; then { echo "$as_me:$LINENO: checking for values.h" >&5 echo $ECHO_N "checking for values.h... $ECHO_C" >&6; } if test "${ac_cv_header_values_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_values_h" >&5 echo "${ECHO_T}$ac_cv_header_values_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking values.h usability" >&5 echo $ECHO_N "checking values.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking values.h presence" >&5 echo $ECHO_N "checking values.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: values.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: values.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: values.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: values.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: values.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: values.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: values.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: values.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: values.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: values.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: values.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: values.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: values.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: values.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: values.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: values.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for values.h" >&5 echo $ECHO_N "checking for values.h... $ECHO_C" >&6; } if test "${ac_cv_header_values_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_values_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_values_h" >&5 echo "${ECHO_T}$ac_cv_header_values_h" >&6; } fi if test $ac_cv_header_values_h = yes; then : else cat >>confdefs.h <<\_ACEOF #define NO_VALUES_H 1 _ACEOF fi if test "${ac_cv_header_limits_h+set}" = set; then { echo "$as_me:$LINENO: checking for limits.h" >&5 echo $ECHO_N "checking for limits.h... $ECHO_C" >&6; } if test "${ac_cv_header_limits_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_limits_h" >&5 echo "${ECHO_T}$ac_cv_header_limits_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking limits.h usability" >&5 echo $ECHO_N "checking limits.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking limits.h presence" >&5 echo $ECHO_N "checking limits.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: limits.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: limits.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: limits.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: limits.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: limits.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: limits.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: limits.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: limits.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: limits.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: limits.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for limits.h" >&5 echo $ECHO_N "checking for limits.h... $ECHO_C" >&6; } if test "${ac_cv_header_limits_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_limits_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_limits_h" >&5 echo "${ECHO_T}$ac_cv_header_limits_h" >&6; } fi if test $ac_cv_header_limits_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_LIMITS_H 1 _ACEOF else cat >>confdefs.h <<\_ACEOF #define NO_LIMITS_H 1 _ACEOF fi if test "${ac_cv_header_stdlib_h+set}" = set; then { echo "$as_me:$LINENO: checking for stdlib.h" >&5 echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6; } if test "${ac_cv_header_stdlib_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking stdlib.h usability" >&5 echo $ECHO_N "checking stdlib.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking stdlib.h presence" >&5 echo $ECHO_N "checking stdlib.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: stdlib.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: stdlib.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: stdlib.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: stdlib.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: stdlib.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: stdlib.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: stdlib.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for stdlib.h" >&5 echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6; } if test "${ac_cv_header_stdlib_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_stdlib_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6; } fi if test $ac_cv_header_stdlib_h = yes; then tcl_ok=1 else tcl_ok=0 fi cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strtol" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strtoul" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strtod" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* if test $tcl_ok = 0; then cat >>confdefs.h <<\_ACEOF #define NO_STDLIB_H 1 _ACEOF fi if test "${ac_cv_header_string_h+set}" = set; then { echo "$as_me:$LINENO: checking for string.h" >&5 echo $ECHO_N "checking for string.h... $ECHO_C" >&6; } if test "${ac_cv_header_string_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5 echo "${ECHO_T}$ac_cv_header_string_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking string.h usability" >&5 echo $ECHO_N "checking string.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking string.h presence" >&5 echo $ECHO_N "checking string.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: string.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: string.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: string.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: string.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: string.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: string.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: string.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for string.h" >&5 echo $ECHO_N "checking for string.h... $ECHO_C" >&6; } if test "${ac_cv_header_string_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_string_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5 echo "${ECHO_T}$ac_cv_header_string_h" >&6; } fi if test $ac_cv_header_string_h = yes; then tcl_ok=1 else tcl_ok=0 fi cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strstr" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strerror" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* # See also memmove check below for a place where NO_STRING_H can be # set and why. if test $tcl_ok = 0; then cat >>confdefs.h <<\_ACEOF #define NO_STRING_H 1 _ACEOF fi if test "${ac_cv_header_sys_wait_h+set}" = set; then { echo "$as_me:$LINENO: checking for sys/wait.h" >&5 echo $ECHO_N "checking for sys/wait.h... $ECHO_C" >&6; } if test "${ac_cv_header_sys_wait_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking sys/wait.h usability" >&5 echo $ECHO_N "checking sys/wait.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking sys/wait.h presence" >&5 echo $ECHO_N "checking sys/wait.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: sys/wait.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: sys/wait.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: sys/wait.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: sys/wait.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: sys/wait.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: sys/wait.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: sys/wait.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: sys/wait.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: sys/wait.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: sys/wait.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: sys/wait.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: sys/wait.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: sys/wait.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: sys/wait.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: sys/wait.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: sys/wait.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for sys/wait.h" >&5 echo $ECHO_N "checking for sys/wait.h... $ECHO_C" >&6; } if test "${ac_cv_header_sys_wait_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_sys_wait_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; } fi if test $ac_cv_header_sys_wait_h = yes; then : else cat >>confdefs.h <<\_ACEOF #define NO_SYS_WAIT_H 1 _ACEOF fi if test "${ac_cv_header_dlfcn_h+set}" = set; then { echo "$as_me:$LINENO: checking for dlfcn.h" >&5 echo $ECHO_N "checking for dlfcn.h... $ECHO_C" >&6; } if test "${ac_cv_header_dlfcn_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_dlfcn_h" >&5 echo "${ECHO_T}$ac_cv_header_dlfcn_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking dlfcn.h usability" >&5 echo $ECHO_N "checking dlfcn.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking dlfcn.h presence" >&5 echo $ECHO_N "checking dlfcn.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: dlfcn.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: dlfcn.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: dlfcn.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: dlfcn.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: dlfcn.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: dlfcn.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: dlfcn.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: dlfcn.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: dlfcn.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: dlfcn.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: dlfcn.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: dlfcn.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: dlfcn.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: dlfcn.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: dlfcn.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: dlfcn.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for dlfcn.h" >&5 echo $ECHO_N "checking for dlfcn.h... $ECHO_C" >&6; } if test "${ac_cv_header_dlfcn_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_dlfcn_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_dlfcn_h" >&5 echo "${ECHO_T}$ac_cv_header_dlfcn_h" >&6; } fi if test $ac_cv_header_dlfcn_h = yes; then : else cat >>confdefs.h <<\_ACEOF #define NO_DLFCN_H 1 _ACEOF fi # OS/390 lacks sys/param.h (and doesn't need it, by chance). for ac_header in sys/param.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Let the user call this, because if it triggers, they will # need a compat/strtod.c that is correct. Users can also # use Tcl_GetDouble(FromObj) instead. #TEA_BUGGY_STRTOD fi #----------------------------------------------------------------------- # __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="qebind.c tkTreeColumn.c tkTreeCtrl.c tkTreeDisplay.c tkTreeDrag.c tkTreeElem.c tkTreeItem.c tkTreeMarquee.c tkTreeNotify.c tkTreeStyle.c tkTreeTheme.c tkTreeUtils.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 if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ ; then { { echo "$as_me:$LINENO: error: could not find source file '$i'" >&5 echo "$as_me: error: could not find source file '$i'" >&2;} { (exit 1); exit 1; }; } 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 { { echo "$as_me:$LINENO: error: could not find header file '${srcdir}/$i'" >&5 echo "$as_me: error: could not find header file '${srcdir}/$i'" >&2;} { (exit 1); exit 1; }; } fi PKG_HEADERS="$PKG_HEADERS $i" done #TEA_ADD_INCLUDES([-I. -I\"`${CYGPATH} ${srcdir}/generic`\"]) 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" \ ; then { { echo "$as_me:$LINENO: error: could not find stub source file '$i'" >&5 echo "$as_me: error: could not find stub source file '$i'" >&2;} { (exit 1); exit 1; }; } 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/treectrl.tcl library/filelist-bindings.tcl" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then { { echo "$as_me:$LINENO: error: could not find tcl source file '${srcdir}/$i'" >&5 echo "$as_me: error: could not find tcl source file '${srcdir}/$i'" >&2;} { (exit 1); exit 1; }; } fi PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" done #-------------------------------------------------------------------- # __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 { echo "$as_me:$LINENO: checking for Tcl private include files" >&5 echo $ECHO_N "checking for Tcl private include files... $ECHO_C" >&6; } TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}` TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\" TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" TCL_UNIX_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" TCL_WIN_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" TCL_BMAP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/bitmaps\" TCL_TOOL_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/tools\" TCL_COMPAT_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/compat\" if test "${TEA_PLATFORM}" = "windows"; then TCL_PLATFORM_DIR_NATIVE=${TCL_WIN_DIR_NATIVE} else TCL_PLATFORM_DIR_NATIVE=${TCL_UNIX_DIR_NATIVE} fi # 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 fi { echo "$as_me:$LINENO: result: Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" >&5 echo "${ECHO_T}Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" >&6; } #TEA_PUBLIC_TK_HEADERS { echo "$as_me:$LINENO: checking for Tk private include files" >&5 echo $ECHO_N "checking for Tk private include files... $ECHO_C" >&6; } TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}` TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\" TK_UNIX_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\" TK_WIN_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\" 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_WIN_DIR_NATIVE} else TK_PLATFORM_DIR_NATIVE=${TK_UNIX_DIR_NATIVE} fi # 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}" if test "${TEA_WINDOWINGSYSTEM}" = "win32" \ -o "${TEA_WINDOWINGSYSTEM}" = "aqua"; 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}"; fi ;; esac fi { echo "$as_me:$LINENO: result: Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}" >&5 echo "${ECHO_T}Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}" >&6; } #-------------------------------------------------------------------- # For Unix/Tk builds, make sure that the X libraries/headers are found. #-------------------------------------------------------------------- if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then { echo "$as_me:$LINENO: checking for X" >&5 echo $ECHO_N "checking for X... $ECHO_C" >&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 #( *\'*) { { echo "$as_me:$LINENO: error: Cannot use X directory names containing '" >&5 echo "$as_me: error: Cannot use X directory names containing '" >&2;} { (exit 1); exit 1; }; };; #( *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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; 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 | /lib) ;; *) 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/X11R6/include /usr/X11R5/include /usr/X11R4/include /usr/include/X11 /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 /usr/local/X11/include /usr/local/X11R6/include /usr/local/X11R5/include /usr/local/X11R4/include /usr/local/include/X11 /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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # We can compile using X headers with no special include directory. ac_x_includes= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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.$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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { XrmInitialize () ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then LIBS=$ac_save_LIBS # We can link X programs with no special library path. ac_x_libraries= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS=$ac_save_LIBS for ac_dir in `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; 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_ipa8_conftest.oo \ 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 { echo "$as_me:$LINENO: result: $have_x" >&5 echo "${ECHO_T}$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'" { echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6; } fi not_really_there="" if test "$no_x" = ""; then if test "$x_includes" = ""; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 not_really_there="yes" fi rm -f conftest.err conftest.$ac_ext else if test ! -r $x_includes/X11/Intrinsic.h; then not_really_there="yes" fi fi fi if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then { echo "$as_me:$LINENO: checking for X11 header files" >&5 echo $ECHO_N "checking for X11 header files... $ECHO_C" >&6; } found_xincludes="no" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then found_xincludes="yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 found_xincludes="no" fi rm -f conftest.err 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/Intrinsic.h; then { echo "$as_me:$LINENO: result: $i" >&5 echo "${ECHO_T}$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 { echo "$as_me:$LINENO: result: couldn't find any!" >&5 echo "${ECHO_T}couldn't find any!" >&6; } fi if test "$no_x" = yes; then { echo "$as_me:$LINENO: checking for X11 libraries" >&5 echo $ECHO_N "checking for X11 libraries... $ECHO_C" >&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; then { echo "$as_me:$LINENO: result: $i" >&5 echo "${ECHO_T}$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 { echo "$as_me:$LINENO: checking for XCreateWindow in -lXwindow" >&5 echo $ECHO_N "checking for XCreateWindow in -lXwindow... $ECHO_C" >&6; } if test "${ac_cv_lib_Xwindow_XCreateWindow+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lXwindow $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_Xwindow_XCreateWindow=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_Xwindow_XCreateWindow=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_Xwindow_XCreateWindow" >&5 echo "${ECHO_T}$ac_cv_lib_Xwindow_XCreateWindow" >&6; } if test $ac_cv_lib_Xwindow_XCreateWindow = yes; then XLIBSW=-lXwindow fi fi if test "$XLIBSW" = nope ; then { echo "$as_me:$LINENO: result: could not find any! Using -lX11." >&5 echo "${ECHO_T}could not find any! Using -lX11." >&6; } XLIBSW=-lX11 fi if test x"${XLIBSW}" != x ; then PKG_LIBS="${PKG_LIBS} ${XLIBSW}" fi fi # Needed for OS X ppx/intel image handling { echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; } if test "${ac_cv_c_bigendian+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # See if sys/param.h defines the BYTE_ORDER macro. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then # It does; now see whether it defined to BIG_ENDIAN or not. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_c_bigendian=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # It does not; compile a test program. if test "$cross_compiling" = yes; then # try to guess the endianness by grepping values into an object file ac_cv_c_bigendian=unknown cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 }; void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } int main () { _ascii (); _ebcdic (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_bigendian=no else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 echo "${ECHO_T}$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in yes) cat >>confdefs.h <<\_ACEOF #define WORDS_BIGENDIAN 1 _ACEOF ;; no) ;; *) { { echo "$as_me:$LINENO: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&5 echo "$as_me: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} { (exit 1); exit 1; }; } ;; esac #-------------------------------------------------------------------- # __CHANGE__ # A few miscellaneous platform-specific items: # # Define a special symbol for Windows (BUILD_sample in this case) so # that we create the export library with the dll. See sha1.h on how # to use this. # # Windows creates a few extra files that need to be cleaned up. # You can add more files to clean if your extension creates any extra # files. # # Define any extra compiler flags in the PACKAGE_CFLAGS variable. # These will be appended to the current set of compiler flags for # your system. #-------------------------------------------------------------------- OUTPUTFILES=Makefile if test "${TEA_PLATFORM}" = "windows" ; then cat >>confdefs.h <<\_ACEOF #define BUILD_treectrl 1 _ACEOF CLEANFILES="pkgIndex.tcl *.lib *.dll *.exp *.ilk *.pdb vc*.pch" vars="gdi32.lib user32.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 # Check whether --enable-shellicon was given. if test "${enable_shellicon+set}" = set; then enableval=$enable_shellicon; tcl_ok=$enableval else tcl_ok=no fi if test "$tcl_ok" = "yes" ; then subdirs="$subdirs shellicon" fi # Find rc.exe or windres.exe. # Defined in winrc.m4. # AC_MSG_CHECKING([for windows resource compiler]) RC_DEPARG='"$<"' if test "${GCC}" = "yes" ; then # Extract the first word of "windres", so it can be a program name with args. set dummy windres; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_RC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RC="windres" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $RC" >&5 echo "${ECHO_T}$RC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "${RC}" = "" ; then { { echo "$as_me:$LINENO: error: Required resource tool 'windres' not found on PATH." >&5 echo "$as_me: error: Required resource tool 'windres' not found on PATH." >&2;} { (exit 1); exit 1; }; } fi RC_OUT=-o RC_TYPE= RC_INCLUDE=--include RC_DEFINE=--define RES=res.o # Check for a bug in gcc's windres that causes the # compile to fail when a Windows native path is # passed into windres. The mingw toolchain requires # Windows native paths while Cygwin should work # with both. Avoid the bug by passing a POSIX # path when using the Cygwin toolchain. if test "$ac_cv_cygwin" != "yes" -a "$CYGPATH" != "echo" ; then conftest=/tmp/conftest.rc echo "STRINGTABLE BEGIN" > $conftest echo "101 \"name\"" >> $conftest echo "END" >> $conftest { echo "$as_me:$LINENO: checking for Windows native path bug in windres" >&5 echo $ECHO_N "checking for Windows native path bug in windres... $ECHO_C" >&6; } cyg_conftest=`$CYGPATH $conftest` if { ac_try='$RC -o conftest.res.o $cyg_conftest' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } ; then { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } RC_DEPARG='"$(shell $(CYGPATH) $<)"' else { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } fi conftest= cyg_conftest= fi else if test "$do64bit" != "no" ; then RC="\"${MSSDK}/bin/rc.exe\"" elif test "$doWince" != "no" ; then RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" else RC="rc" fi RC_OUT=-fo RC_TYPE=-r RC_INCLUDE=-i RC_DEFINE=-d RES=res fi # X86|AMD64|IA64 for manifest # Create treectrl.dll.manifest from treectrl.dll.manifest.in. # treectrl.dll.manifest is included by treectrl.rc. # If building with a Microsoft compiler that generates # treectrlNN.dll.manifest (to pick the correct MSVCRT runtime) then # that manifest is merged with mine using mt.exe (see the Makefile # rule for PKG_LIB_FILE). OUTPUTFILES="Makefile treectrl.dll.manifest" vars="treectrl.rc" 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 if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ ; then { { echo "$as_me:$LINENO: error: could not find source file '$i'" >&5 echo "$as_me: error: could not find source file '$i'" >&2;} { (exit 1); exit 1; }; } 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"${RES}" != x ; then j="`echo $i | sed -e 's/\.[^.]*$//'`.${RES}" else j="`echo $i | sed -e 's/\.[^.]*$//'`.\${RES}" fi PKG_OBJECTS="$PKG_OBJECTS $j" ;; esac done else CLEANFILES="pkgIndex.tcl" fi if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then vars="-framework Carbon" 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 fi #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. #-------------------------------------------------------------------- # 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 cat >>confdefs.h <<\_ACEOF #define USE_THREAD_ALLOC 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define _REENTRANT 1 _ACEOF if test "`uname -s`" = "SunOS" ; then cat >>confdefs.h <<\_ACEOF #define _POSIX_PTHREAD_SEMANTICS 1 _ACEOF fi cat >>confdefs.h <<\_ACEOF #define _THREAD_SAFE 1 _ACEOF { echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthread" >&5 echo $ECHO_N "checking for pthread_mutex_init in -lpthread... $ECHO_C" >&6; } if test "${ac_cv_lib_pthread_pthread_mutex_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_pthread_pthread_mutex_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthread_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 echo "${ECHO_T}$ac_cv_lib_pthread_pthread_mutex_init" >&6; } if test $ac_cv_lib_pthread_pthread_mutex_init = yes; 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] { echo "$as_me:$LINENO: checking for __pthread_mutex_init in -lpthread" >&5 echo $ECHO_N "checking for __pthread_mutex_init in -lpthread... $ECHO_C" >&6; } if test "${ac_cv_lib_pthread___pthread_mutex_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_pthread___pthread_mutex_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthread___pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 echo "${ECHO_T}$ac_cv_lib_pthread___pthread_mutex_init" >&6; } if test $ac_cv_lib_pthread___pthread_mutex_init = yes; then tcl_ok=yes else tcl_ok=no fi fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthread" else { echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthreads" >&5 echo $ECHO_N "checking for pthread_mutex_init in -lpthreads... $ECHO_C" >&6; } if test "${ac_cv_lib_pthreads_pthread_mutex_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthreads $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_pthreads_pthread_mutex_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthreads_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 echo "${ECHO_T}$ac_cv_lib_pthreads_pthread_mutex_init" >&6; } if test $ac_cv_lib_pthreads_pthread_mutex_init = yes; then tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthreads" else { echo "$as_me:$LINENO: checking for pthread_mutex_init in -lc" >&5 echo $ECHO_N "checking for pthread_mutex_init in -lc... $ECHO_C" >&6; } if test "${ac_cv_lib_c_pthread_mutex_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_c_pthread_mutex_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_c_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_c_pthread_mutex_init" >&5 echo "${ECHO_T}$ac_cv_lib_c_pthread_mutex_init" >&6; } if test $ac_cv_lib_c_pthread_mutex_init = yes; then tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "no"; then { echo "$as_me:$LINENO: checking for pthread_mutex_init in -lc_r" >&5 echo $ECHO_N "checking for pthread_mutex_init in -lc_r... $ECHO_C" >&6; } if test "${ac_cv_lib_c_r_pthread_mutex_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc_r $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_c_r_pthread_mutex_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_c_r_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 echo "${ECHO_T}$ac_cv_lib_c_r_pthread_mutex_init" >&6; } if test $ac_cv_lib_c_r_pthread_mutex_init = yes; 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 { echo "$as_me:$LINENO: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&5 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 { echo "$as_me:$LINENO: checking for building with threads" >&5 echo $ECHO_N "checking for building with threads... $ECHO_C" >&6; } if test "${TCL_THREADS}" = 1; then cat >>confdefs.h <<\_ACEOF #define TCL_THREADS 1 _ACEOF { echo "$as_me:$LINENO: result: yes (default)" >&5 echo "${ECHO_T}yes (default)" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: WARNING: Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads." >&5 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 ;; *) if test "${TCL_THREADS}" = "1"; then { echo "$as_me:$LINENO: WARNING: --enable-threads requested, but building against a Tcl that is NOT thread-enabled. This is an OK configuration that will also run in a thread-enabled core." >&5 echo "$as_me: WARNING: --enable-threads requested, but building against a Tcl that is NOT thread-enabled. This is an OK configuration that will also run in a thread-enabled core." >&2;} fi ;; esac #-------------------------------------------------------------------- # The statement below defines a collection of symbols related to # building as a shared library instead of a static library. #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking how to build libraries" >&5 echo $ECHO_N "checking how to build libraries... $ECHO_C" >&6; } # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then enableval=$enable_shared; tcl_ok=$enableval else tcl_ok=yes fi if test "${enable_shared+set}" = set; then enableval="$enable_shared" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" ; then { echo "$as_me:$LINENO: result: shared" >&5 echo "${ECHO_T}shared" >&6; } SHARED_BUILD=1 else { echo "$as_me:$LINENO: result: static" >&5 echo "${ECHO_T}static" >&6; } SHARED_BUILD=0 cat >>confdefs.h <<\_ACEOF #define STATIC_BUILD 1 _ACEOF 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. #-------------------------------------------------------------------- # Step 0.a: Enable 64 bit support? { echo "$as_me:$LINENO: checking if 64bit support is requested" >&5 echo $ECHO_N "checking if 64bit support is requested... $ECHO_C" >&6; } # Check whether --enable-64bit was given. if test "${enable_64bit+set}" = set; then enableval=$enable_64bit; do64bit=$enableval else do64bit=no fi { echo "$as_me:$LINENO: result: $do64bit" >&5 echo "${ECHO_T}$do64bit" >&6; } # Step 0.b: Enable Solaris 64 bit VIS support? { echo "$as_me:$LINENO: checking if 64bit Sparc VIS support is requested" >&5 echo $ECHO_N "checking if 64bit Sparc VIS support is requested... $ECHO_C" >&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 { echo "$as_me:$LINENO: result: $do64bitVIS" >&5 echo "${ECHO_T}$do64bitVIS" >&6; } if test "$do64bitVIS" = "yes"; then # Force 64bit on with VIS do64bit=yes fi # Step 0.c: Cross-compiling options for Windows/CE builds? if test "${TEA_PLATFORM}" = "windows" ; then { echo "$as_me:$LINENO: checking if Windows/CE build is requested" >&5 echo $ECHO_N "checking if Windows/CE build is requested... $ECHO_C" >&6; } # Check whether --enable-wince was given. if test "${enable_wince+set}" = set; then enableval=$enable_wince; doWince=$enableval else doWince=no fi { echo "$as_me:$LINENO: result: $doWince" >&5 echo "${ECHO_T}$doWince" >&6; } fi # Step 1: set the variable "system" to hold the name and version number # for the system. { echo "$as_me:$LINENO: checking system version" >&5 echo $ECHO_N "checking system version... $ECHO_C" >&6; } if test "${tcl_cv_sys_version+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows elif test -f /usr/lib/NextStep/software_version; then tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { echo "$as_me:$LINENO: WARNING: can't find uname command" >&5 echo "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else # Special check for weird MP-RAS system (uname returns weird # results, and the version is kept in special file). if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then tcl_cv_sys_version=MP-RAS-`awk '{print }' /etc/.relid` fi if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi fi fi fi { echo "$as_me:$LINENO: result: $tcl_cv_sys_version" >&5 echo "${ECHO_T}$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version # Step 2: check for existence of -ldl library. This is needed because # Linux can use either -ldl or -ldld for dynamic loading. { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } if test $ac_cv_lib_dl_dlopen = yes; then have_dl=yes else have_dl=no fi # Require ranlib early so we can override it in special cases below. # Step 3: 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. do64bit_ok=no LDFLAGS_ORIG="$LDFLAGS" # 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="" TCL_EXPORT_FILE_SUFFIX="" UNSHARED_LIB_SUFFIX="" TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ECHO_VERSION='`echo ${PACKAGE_VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g CFLAGS_OPTIMIZE=-O if test "$GCC" = "yes" ; then CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall -Wno-implicit-int" else CFLAGS_WARNING="" fi TCL_NEEDS_EXP_FILE=0 TCL_BUILD_EXP_FILE="" TCL_EXP_FILE="" # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_AR+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AR="ar" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $AR" >&5 echo "${ECHO_T}$AR" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" case $system in 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 ! -d "${PATH64}" ; then { echo "$as_me:$LINENO: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&5 echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&2;} { echo "$as_me:$LINENO: WARNING: Ensure latest Platform SDK is installed" >&5 echo "$as_me: WARNING: Ensure latest Platform SDK is installed" >&2;} do64bit="no" else { echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6; } do64bit_ok="yes" fi fi if test "$doWince" != "no" ; then if test "$do64bit" != "no" ; then { { echo "$as_me:$LINENO: error: Windows/CE and 64-bit builds incompatible" >&5 echo "$as_me: error: Windows/CE and 64-bit builds incompatible" >&2;} { (exit 1); exit 1; }; } fi if test "$GCC" = "yes" ; then { { echo "$as_me:$LINENO: error: Windows/CE and GCC builds incompatible" >&5 echo "$as_me: error: Windows/CE and GCC builds incompatible" >&2;} { (exit 1); exit 1; }; } 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 { echo "$as_me:$LINENO: checking for Windows/CE celib directory" >&5 echo $ECHO_N "checking for Windows/CE celib directory... $ECHO_C" >&6; } if test "${ac_cv_c_celibconfig+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { { echo "$as_me:$LINENO: error: ${with_celibconfig} directory doesn't contain inc directory" >&5 echo "$as_me: error: ${with_celibconfig} directory doesn't contain inc directory" >&2;} { (exit 1); exit 1; }; } 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 { { echo "$as_me:$LINENO: error: Cannot find celib support library directory" >&5 echo "$as_me: error: Cannot find celib support library directory" >&2;} { (exit 1); exit 1; }; } else no_celib= CELIB_DIR=${ac_cv_c_celibconfig} CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` { echo "$as_me:$LINENO: result: found $CELIB_DIR" >&5 echo "${ECHO_T}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 { { echo "$as_me:$LINENO: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" >&5 echo "$as_me: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" >&2;} { (exit 1); exit 1; }; } 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 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="-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="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" LINKBIN="\"${CEBINROOT}/link.exe\"" else RC="rc" 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 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}" 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 # This essentially turns it all on. LDFLAGS_DEBUG="-debug:full -debugtype:both -warn:2" 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_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".dll" SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' TCL_LIB_VERSIONS_OK=nodots # Bogus to avoid getting this turned off DL_OBJS="tclLoadNone.obj" ;; 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) # ok ... ;; *) CC=${CC}_r ;; esac { echo "$as_me:$LINENO: result: Using $CC for compiling with threads" >&5 echo "${ECHO_T}Using $CC for compiling with threads" >&6; } fi LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" LD_LIBRARY_PATH_VAR="LIBPATH" # Check to enable 64-bit flags for compiler/linker on AIX 4+ if test "$do64bit" = "yes" -a "`uname -v`" -gt "3" ; then if test "$GCC" = "yes" ; then { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5 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" # AIX-5 has dl* in libc.so DL_LIBS="" 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="gcc -shared" else SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry" fi SHLIB_LD="${TCL_SRC_DIR}/unix/ldAix ${SHLIB_LD} ${SHLIB_LD_FLAGS}" DL_LIBS="-ldl" CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} TCL_NEEDS_EXP_FILE=1 TCL_EXPORT_FILE_SUFFIX='${PACKAGE_VERSION}.exp' fi # AIX v<=4.1 has some different flags than 4.2+ if test "$system" = "AIX-4.1" -o "`uname -v`" -lt "4" ; then case " $LIBOBJS " in *" tclLoadAix.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS tclLoadAix.$ac_objext" ;; esac DL_LIBS="-lld" fi # On AIX <=v4 systems, libbsd.a has to be linked in to support # non-blocking file IO. This library has to be linked in after # the MATH_LIBS or it breaks the pow() function. The way to # insure proper sequencing, is to add it to the tail of MATH_LIBS. # This library also supplies gettimeofday. # # AIX does not have a timezone field in struct tm. When the AIX # bsd library is used, the timezone global and the gettimeofday # methods are to be avoided for timezone deduction instead, we # deduce the timezone by comparing the localtime result on a # known GMT value. { echo "$as_me:$LINENO: checking for gettimeofday in -lbsd" >&5 echo $ECHO_N "checking for gettimeofday in -lbsd... $ECHO_C" >&6; } if test "${ac_cv_lib_bsd_gettimeofday+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 gettimeofday (); int main () { return gettimeofday (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_bsd_gettimeofday=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_bsd_gettimeofday=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gettimeofday" >&5 echo "${ECHO_T}$ac_cv_lib_bsd_gettimeofday" >&6; } if test $ac_cv_lib_bsd_gettimeofday = yes; then libbsd=yes else libbsd=no fi if test $libbsd = yes; then MATH_LIBS="$MATH_LIBS -lbsd" cat >>confdefs.h <<\_ACEOF #define USE_DELTA_FOR_TZ 1 _ACEOF fi ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD="${CC} -nostart" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" #----------------------------------------------------------- # 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. #----------------------------------------------------------- { echo "$as_me:$LINENO: checking for inet_ntoa in -lbind" >&5 echo $ECHO_N "checking for inet_ntoa in -lbind... $ECHO_C" >&6; } if test "${ac_cv_lib_bind_inet_ntoa+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbind $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_bind_inet_ntoa=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_bind_inet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_bind_inet_ntoa" >&5 echo "${ECHO_T}$ac_cv_lib_bind_inet_ntoa" >&6; } if test $ac_cv_lib_bind_inet_ntoa = yes; then LIBS="$LIBS -lbind -lsocket" fi ;; BSD/OS-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD="cc -shared" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; HP-UX-*.11.*) # Use updated header definitions where possible cat >>confdefs.h <<\_ACEOF #define _XOPEN_SOURCE_EXTENDED 1 _ACEOF # 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 SHLIB_SUFFIX=".sl" { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } if test "${ac_cv_lib_dld_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } if test $ac_cv_lib_dld_shl_load = yes; then tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = yes; then SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS='${LIBS}' DL_OBJS="tclLoadShl.o" DL_LIBS="-ldld" 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="gcc -shared" SHLIB_LD_LIBS='${LIBS}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} fi # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc #CFLAGS="$CFLAGS +DAportable" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes" ; then if test "$GCC" = "yes" ; then hpux_arch=`${CC} -dumpmachine` case $hpux_arch in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD="${CC} -shared" SHLIB_LD_LIBS='${LIBS}' CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; *) { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5 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 ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } if test "${ac_cv_lib_dld_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } if test $ac_cv_lib_dld_shl_load = yes; then tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = yes; then SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" DL_OBJS="tclLoadShl.o" DL_LIBS="-ldld" 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 ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' 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_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes" ; then if test "$GCC" = "yes" ; then { echo "$as_me:$LINENO: WARNING: 64bit mode not supported by gcc" >&5 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*) SHLIB_CFLAGS="-fPIC" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings # when you inline the string and math operations. Turn this off to # get rid of the warnings. #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES" SHLIB_LD="${CC} -shared" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,--export-dynamic" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "`uname -m`" = "alpha" ; then CFLAGS="$CFLAGS -mieee" 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 ;; GNU*) SHLIB_CFLAGS="-fPIC" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" SHLIB_LD="${CC} -shared" DL_OBJS="" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,--export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" if test "`uname -m`" = "alpha" ; then CFLAGS="$CFLAGS -mieee" fi ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD="${CC} -shared " DL_OBJS="tclLoadDl.o" DL_LIBS="-mshared -ldl" LD_FLAGS="-Wl,--export-dynamic" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ;; MP-RAS-02*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; MP-RAS-*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,-Bexport" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; NetBSD-*|FreeBSD-[1-2].*) # NetBSD/SPARC needs -fPIC, -fpic will not do. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' { echo "$as_me:$LINENO: checking for ELF" >&5 echo $ECHO_N "checking for ELF... $ECHO_C" >&6; } if test "${tcl_cv_ld_elf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __ELF__ yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then tcl_cv_ld_elf=yes else tcl_cv_ld_elf=no fi rm -f conftest* fi { echo "$as_me:$LINENO: result: $tcl_cv_ld_elf" >&5 echo "${ECHO_T}$tcl_cv_ld_elf" >&6; } if test $tcl_cv_ld_elf = yes; then SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' else SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0' fi # Ancient FreeBSD doesn't handle version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; OpenBSD-*) # OpenBSD/SPARC[64] needs -fPIC, -fpic will not do. case `machine` in sparc|sparc64) SHLIB_CFLAGS="-fPIC";; *) SHLIB_CFLAGS="-fpic";; esac SHLIB_LD="${CC} -shared ${SHLIB_CFLAGS}" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0' { echo "$as_me:$LINENO: checking for ELF" >&5 echo $ECHO_N "checking for ELF... $ECHO_C" >&6; } if test "${tcl_cv_ld_elf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __ELF__ yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then tcl_cv_ld_elf=yes else tcl_cv_ld_elf=no fi rm -f conftest* fi { echo "$as_me:$LINENO: result: $tcl_cv_ld_elf" >&5 echo "${ECHO_T}$tcl_cv_ld_elf" >&6; } if test $tcl_cv_ld_elf = yes; then LDFLAGS=-Wl,-export-dynamic else LDFLAGS="" fi # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; FreeBSD-*) # FreeBSD 3.* and greater have ELF. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' 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 case $system in FreeBSD-3.*) # FreeBSD-3 doesn't handle version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' TCL_LIB_VERSIONS_OK=nodots ;; esac ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" SHLIB_CFLAGS="-fno-common" if test $do64bit = yes; then do64bit_ok=yes CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" fi # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS here: SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' { echo "$as_me:$LINENO: checking if ld accepts -single_module flag" >&5 echo $ECHO_N "checking if ld accepts -single_module flag... $ECHO_C" >&6; } if test "${tcl_cv_ld_single_module+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then tcl_cv_ld_single_module=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_ld_single_module=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { echo "$as_me:$LINENO: result: $tcl_cv_ld_single_module" >&5 echo "${ECHO_T}$tcl_cv_ld_single_module" >&6; } if test $tcl_cv_ld_single_module = yes; then SHLIB_LD="${SHLIB_LD} -Wl,-single_module" fi SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".dylib" DL_OBJS="tclLoadDyld.o" DL_LIBS="" # Don't use -prebind when building for Mac OS X 10.4 or later only: test -z "${MACOSX_DEPLOYMENT_TARGET}" || \ test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F. '{print $2}'`" -lt 4 && \ LDFLAGS="$LDFLAGS -prebind" LDFLAGS="$LDFLAGS -headerpad_max_install_names" { echo "$as_me:$LINENO: checking if ld accepts -search_paths_first flag" >&5 echo $ECHO_N "checking if ld accepts -search_paths_first flag... $ECHO_C" >&6; } if test "${tcl_cv_ld_search_paths_first+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-search_paths_first" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then tcl_cv_ld_search_paths_first=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_ld_search_paths_first=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { echo "$as_me:$LINENO: result: $tcl_cv_ld_search_paths_first" >&5 echo "${ECHO_T}$tcl_cv_ld_search_paths_first" >&6; } if test $tcl_cv_ld_search_paths_first = yes; then LDFLAGS="$LDFLAGS -Wl,-search_paths_first" fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" # TEA specific: for Tk extensions, remove -arch ppc64 from CFLAGS # for fat builds, as neither TkAqua nor TkX11 can be built for 64bit # at present (no 64bit GUI libraries). test $do64bit_ok = no && test -n "${TK_BIN_DIR}" && \ CFLAGS="`echo "$CFLAGS" | sed -e 's/-arch ppc64/-arch ppc/g'`" ;; NEXTSTEP-*) SHLIB_CFLAGS="" SHLIB_LD="cc -nostdlib -r" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadNext.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OS/390-*) CFLAGS_OPTIMIZE="" # Optimizer is buggy cat >>confdefs.h <<\_ACEOF #define _OE_SOCKETS 1 _ACEOF ;; OSF1-1.0|OSF1-1.1|OSF1-1.2) # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 SHLIB_CFLAGS="" # Hack: make package name same as library name SHLIB_LD='ld -R -export :' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadOSF.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OSF1-1.*) # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 SHLIB_CFLAGS="-fPIC" if test "$SHARED_BUILD" = "1" ; then SHLIB_LD="ld -shared" else SHLIB_LD="ld -non_shared" fi SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; 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_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' 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" DL_OBJS="tclLoadDl.o" # dlopen is in -lc on QNX DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) # Note, dlopen is available only on SCO 3.2.5 and greater. However, # this test works, since "uname -s" was non-standard in 3.2.4 and # below. 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" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SINIX*5.4*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-4*) SHLIB_CFLAGS="-PIC" SHLIB_LD="ld" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # SunOS can't handle version numbers with dots in them in library # specs, like -ltcl7.5, so use -ltcl75 instead. Also, it # requires an extra version number at the end of .so file names. # So, the library has to have a name like libtcl75.so.1.0 SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; 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. cat >>confdefs.h <<\_ACEOF #define _REENTRANT 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define _POSIX_PTHREAD_SEMANTICS 1 _ACEOF SHLIB_CFLAGS="-KPIC" # Note: need the LIBS below, otherwise Tk won't find Tcl's # symbols when dynamically loaded into tclsh. SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" 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. cat >>confdefs.h <<\_ACEOF #define _REENTRANT 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define _POSIX_PTHREAD_SEMANTICS 1 _ACEOF 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 "`gcc -dumpversion | awk -F. '{print $1}'`" -lt "3" ; then { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 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 elif test "$arch" = "amd64 i386" ; then if test "$GCC" = "yes" ; then { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5 echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} else do64bit_ok=yes CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64" fi else { echo "$as_me:$LINENO: WARNING: 64bit mode not supported for $arch" >&5 echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} fi fi # Note: need the LIBS below, otherwise Tk won't find Tcl's # symbols when dynamically loaded into tclsh. SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" 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 # 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" fi else SHLIB_LD="/usr/ccs/bin/ld -G -z text" 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" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers # that don't grok the -Bexport option. Test that it does. { echo "$as_me:$LINENO: checking for ld accepts -Bexport flag" >&5 echo $ECHO_N "checking for ld accepts -Bexport flag... $ECHO_C" >&6; } if test "${tcl_cv_ld_Bexport+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-Bexport" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then tcl_cv_ld_Bexport=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_ld_Bexport=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { echo "$as_me:$LINENO: result: $tcl_cv_ld_Bexport" >&5 echo "${ECHO_T}$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 { echo "$as_me:$LINENO: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} fi # Step 4: disable dynamic loading if requested via a command-line switch. # Check whether --enable-load was given. if test "${enable_load+set}" = set; then enableval=$enable_load; tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "no"; then DL_OBJS="" fi if test "x$DL_OBJS" != "x" ; then BUILD_DLTEST="\$(DLTEST_TARGETS)" else echo "Can't figure out how to do dynamic loading or shared libraries" echo "on this system." SHLIB_CFLAGS="" SHLIB_LD="" SHLIB_SUFFIX="" DL_OBJS="tclLoadNone.o" DL_LIBS="" LDFLAGS="$LDFLAGS_ORIG" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" BUILD_DLTEST="" fi 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 "$DL_OBJS" != "tclLoadNone.o" ; then if test "$GCC" = "yes" ; then case $system in AIX-*) ;; BSD/OS*) ;; IRIX*) ;; NetBSD-*|FreeBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; windows) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac fi fi if test "$SHARED_LIB_SUFFIX" = "" ; then SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}' fi if test "$UNSHARED_LIB_SUFFIX" = "" ; then UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a' fi # These must be called after we do the basic CFLAGS checks and # verify any possible 64-bit or similar switches are necessary { echo "$as_me:$LINENO: checking for required early compiler flags" >&5 echo $ECHO_N "checking for required early compiler flags... $ECHO_C" >&6; } tcl_flags="" if test "${tcl_cv_flag__isoc99_source+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_flag__isoc99_source=no else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _ISOC99_SOURCE 1 #include int main () { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_flag__isoc99_source=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 cat >>confdefs.h <<\_ACEOF #define _ISOC99_SOURCE 1 _ACEOF tcl_flags="$tcl_flags _ISOC99_SOURCE" fi if test "${tcl_cv_flag__largefile64_source+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { struct stat64 buf; int i = stat64("/", &buf); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_flag__largefile64_source=no else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _LARGEFILE64_SOURCE 1 #include int main () { struct stat64 buf; int i = stat64("/", &buf); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_flag__largefile64_source=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 cat >>confdefs.h <<\_ACEOF #define _LARGEFILE64_SOURCE 1 _ACEOF tcl_flags="$tcl_flags _LARGEFILE64_SOURCE" fi if test "${tcl_cv_flag__largefile_source64+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { char *p = (char *)open64; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_flag__largefile_source64=no else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _LARGEFILE_SOURCE64 1 #include int main () { char *p = (char *)open64; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_flag__largefile_source64=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 cat >>confdefs.h <<\_ACEOF #define _LARGEFILE_SOURCE64 1 _ACEOF tcl_flags="$tcl_flags _LARGEFILE_SOURCE64" fi if test "x${tcl_flags}" = "x" ; then { echo "$as_me:$LINENO: result: none" >&5 echo "${ECHO_T}none" >&6; } else { echo "$as_me:$LINENO: result: ${tcl_flags}" >&5 echo "${ECHO_T}${tcl_flags}" >&6; } fi { echo "$as_me:$LINENO: checking for 64-bit integer type" >&5 echo $ECHO_N "checking for 64-bit integer type... $ECHO_C" >&6; } if test "${tcl_cv_type_64bit+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else tcl_cv_type_64bit=none # See if the compiler knows natively about __int64 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { __int64 value = (__int64) 0; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_type_64bit=__int64 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { switch (0) { case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; } ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_type_64bit=${tcl_type_64bit} else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "${tcl_cv_type_64bit}" = none ; then cat >>confdefs.h <<\_ACEOF #define TCL_WIDE_INT_IS_LONG 1 _ACEOF { echo "$as_me:$LINENO: result: using long" >&5 echo "${ECHO_T}using long" >&6; } elif test "${tcl_cv_type_64bit}" = "__int64" \ -a "${TEA_PLATFORM}" = "windows" ; then # We actually want to use the default tcl.h checks in this # case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* { echo "$as_me:$LINENO: result: using Tcl header defaults" >&5 echo "${ECHO_T}using Tcl header defaults" >&6; } else cat >>confdefs.h <<_ACEOF #define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit} _ACEOF { echo "$as_me:$LINENO: result: ${tcl_cv_type_64bit}" >&5 echo "${ECHO_T}${tcl_cv_type_64bit}" >&6; } # Now check for auxiliary declarations { echo "$as_me:$LINENO: checking for struct dirent64" >&5 echo $ECHO_N "checking for struct dirent64... $ECHO_C" >&6; } if test "${tcl_cv_struct_dirent64+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { struct dirent64 p; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_struct_dirent64=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_struct_dirent64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $tcl_cv_struct_dirent64" >&5 echo "${ECHO_T}$tcl_cv_struct_dirent64" >&6; } if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then cat >>confdefs.h <<\_ACEOF #define HAVE_STRUCT_DIRENT64 1 _ACEOF fi { echo "$as_me:$LINENO: checking for struct stat64" >&5 echo $ECHO_N "checking for struct stat64... $ECHO_C" >&6; } if test "${tcl_cv_struct_stat64+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { struct stat64 p; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_struct_stat64=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_struct_stat64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $tcl_cv_struct_stat64" >&5 echo "${ECHO_T}$tcl_cv_struct_stat64" >&6; } if test "x${tcl_cv_struct_stat64}" = "xyes" ; then cat >>confdefs.h <<\_ACEOF #define HAVE_STRUCT_STAT64 1 _ACEOF fi for ac_func in open64 lseek64 do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* 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 $ac_func (); /* 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_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { echo "$as_me:$LINENO: checking for off64_t" >&5 echo $ECHO_N "checking for off64_t... $ECHO_C" >&6; } if test "${tcl_cv_type_off64_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { off64_t offset; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_type_off64_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 cat >>confdefs.h <<\_ACEOF #define HAVE_TYPE_OFF64_T 1 _ACEOF { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi #-------------------------------------------------------------------- # Set the default compiler switches based on the --enable-symbols option. #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking for build with symbols" >&5 echo $ECHO_N "checking for build with symbols... $ECHO_C" >&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}" LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } else CFLAGS_DEFAULT="${CFLAGS_DEBUG}" LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" if test "$tcl_ok" = "yes"; then { echo "$as_me:$LINENO: result: yes (standard debugging)" >&5 echo "${ECHO_T}yes (standard debugging)" >&6; } fi fi if test "${TEA_PLATFORM}" != "windows" ; then LDFLAGS_DEFAULT="${LDFLAGS}" fi if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then cat >>confdefs.h <<\_ACEOF #define TCL_MEM_DEBUG 1 _ACEOF fi if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then { echo "$as_me:$LINENO: result: enabled symbols mem debugging" >&5 echo "${ECHO_T}enabled symbols mem debugging" >&6; } else { echo "$as_me:$LINENO: result: enabled $tcl_ok debugging" >&5 echo "${ECHO_T}enabled $tcl_ok debugging" >&6; } fi fi if test "${enable_symbols+set}" = set && test "$enable_symbols" != no; then PKG_CFLAGS="$PKG_CFLAGS -DTREECTRL_DEBUG" fi #-------------------------------------------------------------------- # Everyone should be linking against the Tcl stub library. If you # can't for some reason, remove this definition. If you aren't using # stubs, you also need to modify the SHLIB_LD_LIBS setting below to # link against the non-stubbed Tcl library. Add Tk too if necessary. #-------------------------------------------------------------------- cat >>confdefs.h <<\_ACEOF #define USE_TCL_STUBS 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define USE_TK_STUBS 1 _ACEOF #-------------------------------------------------------------------- # 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)" MAKE_STUB_LIB="\${STLIB_LD} -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. SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" fi eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" else eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries eval eval "PKG_STUB_LIB_FILE=${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_NAME}${SHARED_LIB_SUFFIX}" RANLIB=: else eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries eval eval "PKG_STUB_LIB_FILE=lib${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 #-------------------------------------------------------------------- # Find tclsh so that we can run pkg_mkIndex to generate the pkgIndex.tcl # file during the install process. Don't run the TCLSH_PROG through # ${CYGPATH} because it's being used directly by make. # Require that we use a tclsh shell version 8.2 or later since earlier # versions have bugs in the pkg_mkIndex routine. # Add WISH as well if this is a Tk extension. #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking for tclsh" >&5 echo $ECHO_N "checking for tclsh... $ECHO_C" >&6; } if test -f "${TCL_BIN_DIR}/Makefile" ; then # tclConfig.sh is in Tcl build directory if test "${TEA_PLATFORM}" = "windows"; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" 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 { echo "$as_me:$LINENO: result: ${TCLSH_PROG}" >&5 echo "${ECHO_T}${TCLSH_PROG}" >&6; } { echo "$as_me:$LINENO: checking for wish" >&5 echo $ECHO_N "checking for wish... $ECHO_C" >&6; } if test -f "${TK_BIN_DIR}/Makefile" ; then # tkConfig.sh is in Tk build directory if test "${TEA_PLATFORM}" = "windows"; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" 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 { echo "$as_me:$LINENO: result: ${WISH_PROG}" >&5 echo "${ECHO_T}${WISH_PROG}" >&6; } #-------------------------------------------------------------------- # Finally, substitute all of the various values into the Makefile. # You may alternatively have a special pkgIndex.tcl.in or other files # which require substituting th AC variables in. Include these here. #-------------------------------------------------------------------- ac_config_files="$ac_config_files $OUTPUTFILES" 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_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_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 test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 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=' 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= 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=`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. ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $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} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## 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=: # Zsh 3.x and 4.x performs 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 # PATH needs CR # 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 # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false 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.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. 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 echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. 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 # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. 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" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # 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 } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi 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 fi echo >conf$$.file 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 -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' 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=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # 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 # 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 treectrl $as_me 2.2, which was generated by GNU Autoconf 2.61. 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 cat >>$CONFIG_STATUS <<_ACEOF # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit -q, --quiet 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 ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ treectrl config.status 2.2 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2006 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' INSTALL='$INSTALL' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. 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=$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 ) echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) 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. -*) { echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *) ac_config_targets="$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 if \$ac_cs_recheck; then echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 CONFIG_SHELL=$SHELL export CONFIG_SHELL exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "$OUTPUTFILES") CONFIG_FILES="$CONFIG_FILES $OUTPUTFILES" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; 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= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } # # Set up the sed scripts for CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "$CONFIG_FILES"; then _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF SHELL!$SHELL$ac_delim PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim PACKAGE_NAME!$PACKAGE_NAME$ac_delim PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim PACKAGE_STRING!$PACKAGE_STRING$ac_delim PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim exec_prefix!$exec_prefix$ac_delim prefix!$prefix$ac_delim program_transform_name!$program_transform_name$ac_delim bindir!$bindir$ac_delim sbindir!$sbindir$ac_delim libexecdir!$libexecdir$ac_delim datarootdir!$datarootdir$ac_delim datadir!$datadir$ac_delim sysconfdir!$sysconfdir$ac_delim sharedstatedir!$sharedstatedir$ac_delim localstatedir!$localstatedir$ac_delim includedir!$includedir$ac_delim oldincludedir!$oldincludedir$ac_delim docdir!$docdir$ac_delim infodir!$infodir$ac_delim htmldir!$htmldir$ac_delim dvidir!$dvidir$ac_delim pdfdir!$pdfdir$ac_delim psdir!$psdir$ac_delim libdir!$libdir$ac_delim localedir!$localedir$ac_delim mandir!$mandir$ac_delim DEFS!$DEFS$ac_delim ECHO_C!$ECHO_C$ac_delim ECHO_N!$ECHO_N$ac_delim ECHO_T!$ECHO_T$ac_delim LIBS!$LIBS$ac_delim build_alias!$build_alias$ac_delim host_alias!$host_alias$ac_delim target_alias!$target_alias$ac_delim PACKAGE_PATCHLEVEL!$PACKAGE_PATCHLEVEL$ac_delim CYGPATH!$CYGPATH$ac_delim EXEEXT!$EXEEXT$ac_delim PKG_LIB_FILE!$PKG_LIB_FILE$ac_delim PKG_STUB_LIB_FILE!$PKG_STUB_LIB_FILE$ac_delim PKG_STUB_SOURCES!$PKG_STUB_SOURCES$ac_delim PKG_STUB_OBJECTS!$PKG_STUB_OBJECTS$ac_delim PKG_TCL_SOURCES!$PKG_TCL_SOURCES$ac_delim PKG_HEADERS!$PKG_HEADERS$ac_delim PKG_INCLUDES!$PKG_INCLUDES$ac_delim PKG_LIBS!$PKG_LIBS$ac_delim PKG_CFLAGS!$PKG_CFLAGS$ac_delim TCL_VERSION!$TCL_VERSION$ac_delim TCL_BIN_DIR!$TCL_BIN_DIR$ac_delim TCL_SRC_DIR!$TCL_SRC_DIR$ac_delim TCL_LIB_FILE!$TCL_LIB_FILE$ac_delim TCL_LIB_FLAG!$TCL_LIB_FLAG$ac_delim TCL_LIB_SPEC!$TCL_LIB_SPEC$ac_delim TCL_STUB_LIB_FILE!$TCL_STUB_LIB_FILE$ac_delim TCL_STUB_LIB_FLAG!$TCL_STUB_LIB_FLAG$ac_delim TCL_STUB_LIB_SPEC!$TCL_STUB_LIB_SPEC$ac_delim TCL_LIBS!$TCL_LIBS$ac_delim TCL_DEFS!$TCL_DEFS$ac_delim TCL_EXTRA_CFLAGS!$TCL_EXTRA_CFLAGS$ac_delim TCL_LD_FLAGS!$TCL_LD_FLAGS$ac_delim TCL_SHLIB_LD_LIBS!$TCL_SHLIB_LD_LIBS$ac_delim TK_VERSION!$TK_VERSION$ac_delim TK_BIN_DIR!$TK_BIN_DIR$ac_delim TK_SRC_DIR!$TK_SRC_DIR$ac_delim TK_LIB_FILE!$TK_LIB_FILE$ac_delim TK_LIB_FLAG!$TK_LIB_FLAG$ac_delim TK_LIB_SPEC!$TK_LIB_SPEC$ac_delim TK_STUB_LIB_FILE!$TK_STUB_LIB_FILE$ac_delim TK_STUB_LIB_FLAG!$TK_STUB_LIB_FLAG$ac_delim TK_STUB_LIB_SPEC!$TK_STUB_LIB_SPEC$ac_delim TK_LIBS!$TK_LIBS$ac_delim TK_XINCLUDES!$TK_XINCLUDES$ac_delim CC!$CC$ac_delim CFLAGS!$CFLAGS$ac_delim LDFLAGS!$LDFLAGS$ac_delim CPPFLAGS!$CPPFLAGS$ac_delim ac_ct_CC!$ac_ct_CC$ac_delim OBJEXT!$OBJEXT$ac_delim CPP!$CPP$ac_delim INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim INSTALL_DATA!$INSTALL_DATA$ac_delim SET_MAKE!$SET_MAKE$ac_delim RANLIB!$RANLIB$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim MATH_LIBS!$MATH_LIBS$ac_delim PKG_SOURCES!$PKG_SOURCES$ac_delim PKG_OBJECTS!$PKG_OBJECTS$ac_delim TCL_TOP_DIR_NATIVE!$TCL_TOP_DIR_NATIVE$ac_delim TCL_GENERIC_DIR_NATIVE!$TCL_GENERIC_DIR_NATIVE$ac_delim TCL_UNIX_DIR_NATIVE!$TCL_UNIX_DIR_NATIVE$ac_delim TCL_WIN_DIR_NATIVE!$TCL_WIN_DIR_NATIVE$ac_delim TCL_BMAP_DIR_NATIVE!$TCL_BMAP_DIR_NATIVE$ac_delim TCL_TOOL_DIR_NATIVE!$TCL_TOOL_DIR_NATIVE$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF CEOF$ac_eof _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF TCL_PLATFORM_DIR_NATIVE!$TCL_PLATFORM_DIR_NATIVE$ac_delim TCL_INCLUDES!$TCL_INCLUDES$ac_delim TK_TOP_DIR_NATIVE!$TK_TOP_DIR_NATIVE$ac_delim TK_UNIX_DIR_NATIVE!$TK_UNIX_DIR_NATIVE$ac_delim TK_WIN_DIR_NATIVE!$TK_WIN_DIR_NATIVE$ac_delim TK_GENERIC_DIR_NATIVE!$TK_GENERIC_DIR_NATIVE$ac_delim TK_XLIB_DIR_NATIVE!$TK_XLIB_DIR_NATIVE$ac_delim TK_PLATFORM_DIR_NATIVE!$TK_PLATFORM_DIR_NATIVE$ac_delim TK_INCLUDES!$TK_INCLUDES$ac_delim XMKMF!$XMKMF$ac_delim subdirs!$subdirs$ac_delim RC!$RC$ac_delim RC_OUT!$RC_OUT$ac_delim RC_TYPE!$RC_TYPE$ac_delim RC_INCLUDE!$RC_INCLUDE$ac_delim RC_DEFINE!$RC_DEFINE$ac_delim RC_DEPARG!$RC_DEPARG$ac_delim RES!$RES$ac_delim MACHINE!$MACHINE$ac_delim CLEANFILES!$CLEANFILES$ac_delim TCL_THREADS!$TCL_THREADS$ac_delim SHARED_BUILD!$SHARED_BUILD$ac_delim AR!$AR$ac_delim CELIB_DIR!$CELIB_DIR$ac_delim LIBOBJS!$LIBOBJS$ac_delim DL_LIBS!$DL_LIBS$ac_delim CFLAGS_DEBUG!$CFLAGS_DEBUG$ac_delim CFLAGS_OPTIMIZE!$CFLAGS_OPTIMIZE$ac_delim CFLAGS_WARNING!$CFLAGS_WARNING$ac_delim STLIB_LD!$STLIB_LD$ac_delim SHLIB_LD!$SHLIB_LD$ac_delim SHLIB_LD_LIBS!$SHLIB_LD_LIBS$ac_delim SHLIB_CFLAGS!$SHLIB_CFLAGS$ac_delim LD_LIBRARY_PATH_VAR!$LD_LIBRARY_PATH_VAR$ac_delim TCL_DBGX!$TCL_DBGX$ac_delim CFLAGS_DEFAULT!$CFLAGS_DEFAULT$ac_delim LDFLAGS_DEFAULT!$LDFLAGS_DEFAULT$ac_delim MAKE_LIB!$MAKE_LIB$ac_delim MAKE_SHARED_LIB!$MAKE_SHARED_LIB$ac_delim MAKE_STATIC_LIB!$MAKE_STATIC_LIB$ac_delim MAKE_STUB_LIB!$MAKE_STUB_LIB$ac_delim RANLIB_STUB!$RANLIB_STUB$ac_delim TCLSH_PROG!$TCLSH_PROG$ac_delim WISH_PROG!$WISH_PROG$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 45; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b end _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF :end s/|#_!!_#|//g CEOF$ac_eof _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ 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[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF fi # test -n "$CONFIG_FILES" for ac_tag in :F $CONFIG_FILES do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 echo "$as_me: error: Invalid tag $ac_tag." >&2;} { (exit 1); exit 1; }; };; :[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="$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 || { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 echo "$as_me: error: cannot find input file: $ac_f" >&2;} { (exit 1); exit 1; }; };; esac ac_file_inputs="$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 "`IFS=: echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} fi case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin";; 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 || 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" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`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 || 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" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`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 # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # 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= case `sed -n '/datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p ' $ac_file_inputs` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF 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 sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s&@configure_input@&$configure_input&;t t s&@top_builddir@&$ac_top_builddir_sub&;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 s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 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 "$tmp/stdin" case $ac_file in -) cat "$tmp/out"; rm -f "$tmp/out";; *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; esac ;; esac done # for ac_tag { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # 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 || { (exit 1); exit 1; } fi # # CONFIG_SUBDIRS section. # if test "$no_recursion" != yes; then # Remove --cache-file and --srcdir arguments so they do not pile up. ac_sub_configure_args= ac_prev= eval "set x $ac_configure_args" shift for ac_arg do if test -n "$ac_prev"; then ac_prev= continue fi case $ac_arg in -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=*) ;; --config-cache | -C) ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) ;; *) case $ac_arg in *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac ac_sub_configure_args="$ac_sub_configure_args '$ac_arg'" ;; esac done # Always prepend --prefix to ensure using the same prefix # in subdir configurations. ac_arg="--prefix=$prefix" case $ac_arg in *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" # Pass --silent if test "$silent" = yes; then ac_sub_configure_args="--silent $ac_sub_configure_args" fi ac_popdir=`pwd` for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue # Do not complain, so a configure script can configure whichever # parts of a large source tree are present. test -d "$srcdir/$ac_dir" || continue ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" echo "$as_me:$LINENO: $ac_msg" >&5 echo "$ac_msg" >&6 { as_dir="$ac_dir" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`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 || 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" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`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" # Check for guested configure; otherwise get Cygnus style configure. if test -f "$ac_srcdir/configure.gnu"; then ac_sub_configure=$ac_srcdir/configure.gnu elif test -f "$ac_srcdir/configure"; then ac_sub_configure=$ac_srcdir/configure elif test -f "$ac_srcdir/configure.in"; then # This should be Cygnus configure. ac_sub_configure=$ac_aux_dir/configure else { echo "$as_me:$LINENO: WARNING: no configuration information is in $ac_dir" >&5 echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} ac_sub_configure= fi # The recursion is here. if test -n "$ac_sub_configure"; then # Make the cache file name correct relative to the subdirectory. case $cache_file in [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; *) # Relative name. ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; esac { echo "$as_me:$LINENO: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} # The eval makes quoting arguments work. eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || { { echo "$as_me:$LINENO: error: $ac_sub_configure failed for $ac_dir" >&5 echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;} { (exit 1); exit 1; }; } fi cd "$ac_popdir" done fi tktreectrl-2.2.8/configure.ac0000775000175600010010000002100111073207242014376 0ustar TimNone#!/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. # # RCS: @(#) $Id: configure.ac,v 1.28 2008/10/08 19:48:50 treectrl Exp $ #----------------------------------------------------------------------- # Sample configure.in for Tcl Extensions. # See the TEA sample extension for description of structure and items. #----------------------------------------------------------------------- #----------------------------------------------------------------------- # __CHANGE__ # This very first macro is used to verify that the configure script can # find the sources. The argument to AC_INIT should be a unique filename # for this package, and can be a relative path, such as: # # AC_INIT(generic/tcl.h) #----------------------------------------------------------------------- AC_INIT([treectrl], [2.2]) AC_SUBST([PACKAGE_PATCHLEVEL], [2.2.8]) AC_DEFINE_UNQUOTED(PACKAGE_PATCHLEVEL, "$PACKAGE_PATCHLEVEL") TEA_INIT([3.5]) 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, AC_PROG_INSTALL 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([qebind.c tkTreeColumn.c tkTreeCtrl.c tkTreeDisplay.c tkTreeDrag.c tkTreeElem.c tkTreeItem.c tkTreeMarquee.c tkTreeNotify.c tkTreeStyle.c tkTreeTheme.c tkTreeUtils.c]) TEA_ADD_HEADERS([]) #TEA_ADD_INCLUDES([-I. -I\"`${CYGPATH} ${srcdir}/generic`\"]) TEA_ADD_CFLAGS([]) TEA_ADD_STUB_SOURCES([]) TEA_ADD_TCL_SOURCES([library/treectrl.tcl library/filelist-bindings.tcl]) #-------------------------------------------------------------------- # __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 #-------------------------------------------------------------------- # For Unix/Tk builds, make sure that the X libraries/headers are found. #-------------------------------------------------------------------- TEA_PATH_X # Needed for OS X ppx/intel image handling AC_C_BIGENDIAN #-------------------------------------------------------------------- # __CHANGE__ # A few miscellaneous platform-specific items: # # Define a special symbol for Windows (BUILD_sample in this case) so # that we create the export library with the dll. See sha1.h on how # to use this. # # Windows creates a few extra files that need to be cleaned up. # You can add more files to clean if your extension creates any extra # files. # # Define any extra compiler flags in the PACKAGE_CFLAGS variable. # These will be appended to the current set of compiler flags for # your system. #-------------------------------------------------------------------- OUTPUTFILES=Makefile if test "${TEA_PLATFORM}" = "windows" ; then AC_DEFINE(BUILD_treectrl) CLEANFILES="pkgIndex.tcl *.lib *.dll *.exp *.ilk *.pdb vc*.pch" TEA_ADD_LIBS([gdi32.lib user32.lib]) AC_ARG_ENABLE(shellicon, AC_HELP_STRING([--enable-shellicon], [build the shellicon extension (default: no)]), [tcl_ok=$enableval], [tcl_ok=no]) if test "$tcl_ok" = "yes" ; then AC_CONFIG_SUBDIRS(shellicon) fi # Find rc.exe or windres.exe. # Defined in winrc.m4. TREECTRL_PROG_RC # X86|AMD64|IA64 for manifest AC_SUBST(MACHINE) # Create treectrl.dll.manifest from treectrl.dll.manifest.in. # treectrl.dll.manifest is included by treectrl.rc. # If building with a Microsoft compiler that generates # treectrlNN.dll.manifest (to pick the correct MSVCRT runtime) then # that manifest is merged with mine using mt.exe (see the Makefile # rule for PKG_LIB_FILE). OUTPUTFILES="Makefile treectrl.dll.manifest" TREECTRL_ADD_RC([treectrl.rc]) else CLEANFILES="pkgIndex.tcl" fi if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then TEA_ADD_LIBS([-framework Carbon]) fi AC_SUBST(CLEANFILES) #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. #-------------------------------------------------------------------- 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 if test "${enable_symbols+set}" = set && test "$enable_symbols" != no; then TEA_ADD_CFLAGS([-DTREECTRL_DEBUG]) fi #-------------------------------------------------------------------- # Everyone should be linking against the Tcl stub library. If you # can't for some reason, remove this definition. If you aren't using # stubs, you also need to modify the SHLIB_LD_LIBS setting below to # link against the non-stubbed Tcl library. Add Tk too if necessary. #-------------------------------------------------------------------- AC_DEFINE(USE_TCL_STUBS) AC_DEFINE(USE_TK_STUBS) #-------------------------------------------------------------------- # 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 #-------------------------------------------------------------------- # Find tclsh so that we can run pkg_mkIndex to generate the pkgIndex.tcl # file during the install process. Don't run the TCLSH_PROG through # ${CYGPATH} because it's being used directly by make. # Require that we use a tclsh shell version 8.2 or later since earlier # versions have bugs in the pkg_mkIndex routine. # Add WISH as well if this is a Tk extension. #-------------------------------------------------------------------- TEA_PROG_TCLSH TEA_PROG_WISH #-------------------------------------------------------------------- # Finally, substitute all of the various values into the Makefile. # You may alternatively have a special pkgIndex.tcl.in or other files # which require substituting th AC variables in. Include these here. #-------------------------------------------------------------------- AC_OUTPUT([$OUTPUTFILES]) tktreectrl-2.2.8/demos/0000755000175600010010000000000011073207471013224 5ustar TimNonetktreectrl-2.2.8/demos/biglist.tcl0000700000175600010010000002742210536414401015361 0ustar TimNone# RCS: @(#) $Id: biglist.tcl,v 1.14 2006/12/07 03:47:42 treectrl Exp $ set ::clip 1 proc DemoBigList {} { global BigList set T [DemoList] # # Configure the treectrl widget # $T configure -selectmode extended \ -showroot no -showbuttons no -showlines no \ -showrootlines no if {$::clip} { $T configure -xscrollincrement 4 -yscrollincrement 4 } else { # Hide the borders because child windows appear on top of them $T configure -borderwidth 0 -highlightthickness 0 } # # Create columns # $T column create -expand yes -text Item -itembackground {#F7F7F7} -tags colItem $T column create -text "Item ID" -justify center -itembackground {} -tags colID $T column create -text "Parent ID" -justify center -itembackground {} -tags colParent # Specify the column that will display the heirarchy buttons and lines $T configure -treecolumn colItem # # Create elements # set BigList(bg) $::SystemButtonFace set outline gray70 $T element create eRectTop.e rect -outline $outline -fill $BigList(bg) \ -outlinewidth 1 -open es $T element create eRectTop.we rect -outline $outline -fill $BigList(bg) \ -outlinewidth 1 -open wes $T element create eRectTop.w rect -outline $outline -fill $BigList(bg) \ -outlinewidth 1 -open ws $T element create eRectBottom rect -outline $outline -fill $BigList(bg) \ -outlinewidth 1 -open n # Title $T element create elemBorderTitle border -relief {sunken open raised {}} -thickness 1 \ -filled yes -background $::SystemButtonFace $T element create elemTxtTitle text \ -font [list DemoFontBold] # Citizen $T element create elemRectSel rect -showfocus no \ -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] $T element create elemTxtItem text \ -fill [list $::SystemHighlightText {selected focus}] $T element create elemTxtName text \ -fill [list $::SystemHighlightText {selected focus} blue {}] # Citizen info $T element create elemWindow window if {$::clip} { $T element configure elemWindow -clip yes } # # Create styles using the elements # set S [$T style create styTitle] $T style elements $S {elemBorderTitle elemTxtTitle} $T style layout $S elemTxtTitle -expand news $T style layout $S elemBorderTitle -detach yes -indent no -iexpand xy set S [$T style create styItem] $T style elements $S {eRectTop.e elemRectSel elemTxtItem elemTxtName} $T style layout $S eRectTop.e -detach yes -indent no -iexpand xy -draw {yes open no {}} $T style layout $S elemTxtItem -expand ns $T style layout $S elemTxtName -expand ns -padx {20} $T style layout $S elemRectSel -detach yes -indent no -iexpand xy set S [$T style create styID] $T style elements $S {eRectTop.we elemRectSel elemTxtItem} $T style layout $S eRectTop.we -detach yes -indent yes -iexpand xy -draw {yes open no {}} $T style layout $S elemTxtItem -padx 6 -expand ns $T style layout $S elemRectSel -detach yes -indent no -iexpand xy set S [$T style create styParent] $T style elements $S {eRectTop.w elemRectSel elemTxtItem} $T style layout $S eRectTop.w -detach yes -indent yes -iexpand xy -draw {yes open no {}} $T style layout $S elemTxtItem -padx 6 -expand ns $T style layout $S elemRectSel -detach yes -indent no -iexpand xy set S [$T style create styCitizen] $T style elements $S {eRectBottom elemWindow} $T style layout $S eRectBottom -detach yes -indent no -iexpand xy $T style layout $S elemWindow -pady {0 1} # # Create 10000 items. Each of these items will hold 10 child items. # set index 1 foreach I [$T item create -count 10000 -parent root -button yes -open no \ -height 20 -tags title] { set BigList(titleIndex,$I) $index incr index 10 } # This binding will add child items to an item just before it is expanded. $T notify bind $T { BigListExpandBefore %T %I } # This binding will assign styles to items when they are displayed and # clear the styles when they are no longer displayed. $T notify bind $T { BigListItemVisibility %T %v %h } set BigList(freeWindows) {} set BigList(nextWindowId) 0 set BigList(prev) "" BigListGetWindowHeight $T if {$::tile} { bind DemoBigList <> { BigListGetWindowHeight [DemoList] if {[[DemoList] item id {first visible tag info}] ne ""} { [DemoList] item conf {tag info} -height $BigList(windowHeight) } } } bind DemoBigList { if {[lindex [%W identify %x %y] 0] eq "header"} { TreeCtrl::DoubleButton1 %W %x %y } else { BigListButton1 %W %x %y } break } bind DemoBigList { BigListButton1 %W %x %y break } bind DemoBigList { BigListMotion %W %x %y } bind DemoBigListChildWindow { set x [expr {%X - [winfo rootx [DemoList]]}] set y [expr {%Y - [winfo rooty [DemoList]]}] BigListMotion [DemoList] $x $y } bindtags $T [list $T DemoBigList TreeCtrl [winfo toplevel $T] all] return } proc BigListGetWindowHeight {T} { global BigList # Create a new window just to get the requested size. This will be the # value of the item -height option for some items. set w [BigListNewWindow $T root] update idletasks if {$::clip} { set height [winfo reqheight [lindex [winfo children $w] 0]] } else { set height [winfo reqheight $w] } # Add 1 pixel for the border incr height set BigList(windowHeight) $height BigListFreeWindow $T $w return } proc BigListExpandBefore {T I} { global BigList set parent [$T item parent $I] if {[$T item numchildren $I]} return # Title if {[$T item tag expr $I title]} { set index $BigList(titleIndex,$I) set threats {Severe High Elevated Guarded Low} set names1 {Bill John Jack Bob Tim Sam Mary Susan Lilian Jeff Gary Neil Margaret} set names2 {Smith Hobbs Baker Furst Newel Gates Marshal McNoodle Marley} # Add 10 child items to this item. Each item represents 1 citizen. # The styles will be assigned in BigListItemVisibility. foreach I [$T item create -count 10 -parent $I -open no -button yes \ -height 20 -tags citizen] { set name1 [lindex $names1 [expr {int(rand() * [llength $names1])}]] set name2 [lindex $names2 [expr {int(rand() * [llength $names2])}]] set BigList(itemIndex,$I) $index set BigList(name,$I) "$name1 $name2" set BigList(threat,$I) [lindex $threats [expr {int(rand() * 5)}]] incr index } return } # Citizen if {[$T item tag expr $I citizen]} { # Add 1 child item to this item. # The styles will be assigned in BigListItemVisibility. $T item create -parent $I -height $BigList(windowHeight) -tags info } return } proc BigListItemVisibility {T visible hidden} { global BigList # Assign styles and configure elements in each item that is now # visible on screen. foreach I $visible { set parent [$T item parent $I] # Title if {[$T item tag expr $I title]} { set first $BigList(titleIndex,$I) set last [expr {$first + 10 - 1}] set first [format %06d $first] set last [format %06d $last] $T item span $I colItem 3 $T item style set $I colItem styTitle $T item element configure $I \ colItem elemTxtTitle -text "Citizens $first-$last" continue } # Citizen if {[$T item tag expr $I citizen]} { set index $BigList(itemIndex,$I) $T item style set $I colItem styItem colID styID colParent styParent $T item element configure $I \ colItem elemTxtItem -text "Citizen $index" + elemTxtName -textvariable ::BigList(name,$I) , \ colParent elemTxtItem -text $parent , \ colID elemTxtItem -text $I continue } # Citizen info if {[$T item tag expr $I info]} { set w [BigListNewWindow $T $parent] $T item style set $I colItem styCitizen $T item span $I colItem 3 $T item element configure $I colItem \ elemWindow -window $w } } # Clear the styles of each item that is no longer visible on screen. foreach I $hidden { # Citizen info if {[$T item tag expr $I info]} { # Add this window to the list of unused windows set w [$T item element cget $I colItem elemWindow -window] BigListFreeWindow $T $w } $T item style set $I colItem "" colParent "" colID "" } return } proc BigListNewWindow {T I} { global BigList # Check the list of unused windows if {[llength $BigList(freeWindows)]} { set w [lindex $BigList(freeWindows) 0] set BigList(freeWindows) [lrange $BigList(freeWindows) 1 end] if {$::clip} { set f $w set w [lindex [winfo children $f] 0] } puts "reuse window $w" # No unused windows exist. Create a new one. } else { set id [incr BigList(nextWindowId)] if {$::clip} { set f [frame $T.clip$id -background blue] set w [frame $f.frame$id -background $BigList(bg)] } else { set w [frame $T.frame$id -background $BigList(bg)] } # Name: label + entry label $w.label1 -text "Name:" -anchor w -background $BigList(bg) $::entryCmd $w.entry1 -width 24 # Threat Level: label + menubutton label $w.label2 -text "Threat Level:" -anchor w -background $BigList(bg) if {$::tile} { ttk::combobox $w.mb2 -values {Severe High Elevated Guarded Low} \ -state readonly -width [string length "Elevated"] } else { menubutton $w.mb2 -indicatoron yes -menu $w.mb2.m \ -width [string length Elevated] -relief raised menu $w.mb2.m -tearoff no foreach label {Severe High Elevated Guarded Low} { $w.mb2.m add radiobutton -label $label \ -value $label \ -command [list $w.mb2 configure -text $label] } } # Button set message \ "After abducting and probing these people over the last\n\ 50 years, the only thing we've learned for certain is that\n\ one in ten just doesn't seem to mind." if {$::thisPlatform ne "windows"} { set message [string map {\n ""} $message] } $::buttonCmd $w.b3 -text "Anal Probe Wizard..." -command [list tk_messageBox \ -parent . -message $message -title "Anal Probe 2.0"] grid $w.label1 -row 0 -column 0 -sticky w -padx {0 8} grid $w.entry1 -row 0 -column 1 -sticky w -pady 4 grid $w.label2 -row 1 -column 0 -sticky w -padx {0 8} grid $w.mb2 -row 1 -column 1 -sticky w -pady 4 grid $w.b3 -row 3 -column 0 -columnspan 2 -sticky we -pady {0 4} AddBindTag $w DemoBigListChildWindow AddBindTag $w TagIdentify puts "create window $w" } # Tie the widgets to the global variables for this citizen $w.entry1 configure -textvariable BigList(name,$I) $w.mb2 configure -textvariable BigList(threat,$I) if {!$::tile} { foreach label {Severe High Elevated Guarded Low} { $w.mb2.m entryconfigure $label -variable BigList(threat,$I) } } if {$::clip} { return $f } return $w } proc BigListFreeWindow {T w} { global BigList # Add the window to our list of free windows. DemoClear will actually # delete the window when the demo changes. lappend BigList(freeWindows) $w puts "free window $w" return } proc BigListButton1 {w x y} { variable TreeCtrl::Priv focus $w set id [$w identify $x $y] set Priv(buttonMode) "" if {[lindex $id 0] eq "header"} { TreeCtrl::ButtonPress1 $w $x $y } elseif {[lindex $id 0] eq "item"} { set item [lindex $id 1] # click a button if {[llength $id] != 6} { TreeCtrl::ButtonPress1 $w $x $y return } if {[$w item tag expr $item !info]} { $w item toggle $item } } return } proc BigListMotion {w x y} { global BigList set id [$w identify $x $y] if {[lindex $id 0] eq "item"} { set item [lindex $id 1] if {[$w item tag expr $item !info]} { if {$item ne $BigList(prev)} { $w configure -cursor hand2 set BigList(prev) $item } return } } if {$BigList(prev) ne ""} { $w configure -cursor "" set BigList(prev) "" } return } tktreectrl-2.2.8/demos/bitmaps.tcl0000700000175600010010000000421610536414401015357 0ustar TimNone# RCS: @(#) $Id: bitmaps.tcl,v 1.11 2006/11/30 02:41:38 treectrl Exp $ # # Demo: Bitmaps # proc DemoBitmaps {} { set T [DemoList] # # Configure the treectrl widget # $T configure -showroot no -showbuttons no -showlines no \ -selectmode browse -orient horizontal -wrap "5 items" \ -showheader no -backgroundimage sky # # Create columns # $T column create -itembackground {gray90 {}} -tags C0 # # Create elements # $T element create elemTxt text -fill [list $::SystemHighlightText {selected focus}] $T element create elemSelTxt rect -fill [list $::SystemHighlight {selected focus}] \ -showfocus yes $T element create elemSelBmp rect -outline [list $::SystemHighlight {selected focus}] \ -outlinewidth 4 $T element create elemBmp bitmap \ -foreground [list $::SystemHighlight {selected focus}] \ -background linen \ -bitmap {question {selected}} # # Create styles using the elements # set S [$T style create STYLE -orient vertical] $T style elements $S {elemSelBmp elemBmp elemSelTxt elemTxt} $T style layout $S elemSelBmp -union elemBmp \ -ipadx 6 -ipady 6 $T style layout $S elemBmp -pady {0 6} -expand we $T style layout $S elemSelTxt -union elemTxt -ipadx 2 $T style layout $S elemTxt -expand we # Set default item style $T column configure C0 -itemstyle $S # # Create items and assign styles # set bitmapNames [list error gray75 gray50 gray25 gray12 hourglass info \ questhead question warning] foreach name $bitmapNames { set I [$T item create] # $T item style set $I 0 $S $T item text $I C0 $name $T item element configure $I C0 elemBmp -bitmap $name $T item lastchild root $I } foreach name $bitmapNames { set I [$T item create] $T item style set $I C0 $S $T item text $I C0 $name if 1 { $T item element configure $I C0 elemBmp -bitmap $name \ -foreground [list brown {}] \ -background {"" {}} } else { $T item element configure $I C0 elemBmp -bitmap $name \ -foreground [list $::SystemHighlight {selected focus} brown {}] \ -background {"" {}} } $T item lastchild root $I } return } tktreectrl-2.2.8/demos/column-lock.tcl0000700000175600010010000002672110536414401016150 0ustar TimNone# RCS: @(#) $Id: column-lock.tcl,v 1.11 2006/12/07 03:48:06 treectrl Exp $ proc DemoColumnLock {} { global ColumnLock set T [DemoList] InitPics *checked # # Configure the treectrl widget # $T configure \ -showbuttons no \ -showlines no \ -showroot no \ -xscrollincrement 6 -xscrolldelay 30 \ -yscrollincrement 6 -yscrolldelay 30 # # Create columns # for {set i 0} {$i < 100} {incr i} { $T column create -text "C$i" -tags C$i -width [expr {40 + 20 * ($i % 2)}] -justify center } $T column configure first -text LEFT -lock left -width "" $T column configure last -text RIGHT -lock right -width "" $T state define CHECK $T state define mouseover # # Create styles for the left-locked column, and create items # $T element create label1.bg rect -fill {gray80 mouseover gray {}} $T element create label1.text text $T style create label1 -orient horizontal $T style elements label1 {label1.bg label1.text} $T style layout label1 label1.bg -detach yes -iexpand xy $T style layout label1 label1.text -expand wns -padx 2 for {set i 1} {$i <= 10} {incr i} { set I [$T item create -tags R$i -parent root] $T item style set $I C0 label1 $T item text $I C0 "R$i" } $T element create label2.bd border -background $::SystemButtonFace \ -relief raised -thickness 2 -filled yes $T element create label2.text text $T style create label2 -orient horizontal $T style elements label2 {label2.bd label2.text} $T style layout label2 label2.bd -detach yes -iexpand xy $T style layout label2 label2.text -expand news -padx 2 -pady 2 for {set i 11} {$i <= 20} {incr i} { set I [$T item create -tags R$i -parent root] $T item style set $I C0 label2 $T item text $I C0 "R$i" } $T element create label3.div rect -fill black -height 2 $T element create label3.text text $T style create label3 -orient horizontal $T style elements label3 {label3.div label3.text} $T style layout label3 label3.div -detach yes -expand n -iexpand x $T style layout label3 label3.text -expand ws -padx 2 -pady 2 for {set i 21} {$i <= 30} {incr i} { set I [$T item create -tags R$i -parent root] $T item style set $I C0 label3 $T item text $I C0 "R$i" } $T element create label4.rect rect -fill {#e0e8f0 mouseover} $T element create label4.text text $T element create label4.w window -clip yes -destroy yes $T style create label4 -orient vertical $T style elements label4 {label4.rect label4.text label4.w} $T style layout label4 label4.rect -detach yes -iexpand xy $T style layout label4 label4.text -expand we -padx 2 -pady 2 $T style layout label4 label4.w -iexpand x -padx 2 -pady {0 2} for {set i 31} {$i <= 40} {incr i} { set I [$T item create -tags R$i -parent root] $T item style set $I C0 label4 $T item element configure $I C0 label4.text -textvariable ::DemoColumnLock(R$i) set clip [frame $T.clipR${I}C0 -borderwidth 0] $::entryCmd $clip.e -width 4 -textvariable ::DemoColumnLock(R$i) $T item element configure $I C0 label4.w -window $clip set ::DemoColumnLock(R$i) "R$i" } # # Create styles for the right-locked column # $T element create labelR1.bg rect -fill {gray80 mouseover gray {}} $T element create labelR1.img image -image {checked CHECK unchecked {}} $T style create labelR1 -orient horizontal $T style elements labelR1 {labelR1.bg labelR1.img} $T style layout labelR1 labelR1.bg -detach yes -iexpand xy $T style layout labelR1 labelR1.img -expand news -padx 2 -pady 2 $T element create labelR2.bd border -background $::SystemButtonFace \ -relief raised -thickness 2 -filled yes $T element create labelR2.img image -image {checked CHECK unchecked {}} $T style create labelR2 -orient horizontal $T style elements labelR2 {labelR2.bd labelR2.img} $T style layout labelR2 labelR2.bd -detach yes -iexpand xy $T style layout labelR2 labelR2.img -expand news -padx 2 -pady 2 $T element create labelR3.div rect -fill black -height 2 $T element create labelR3.img image -image {checked CHECK unchecked {}} $T style create labelR3 -orient horizontal $T style elements labelR3 {labelR3.div labelR3.img} $T style layout labelR3 labelR3.div -detach yes -expand n -iexpand x $T style layout labelR3 labelR3.img -expand news -padx 2 -pady 2 $T element create labelR4.rect rect -fill {#e0e8f0 mouseover} $T element create labelR4.img image -image {checked CHECK unchecked {}} $T style create labelR4 -orient vertical $T style elements labelR4 {labelR4.rect labelR4.img} $T style layout labelR4 labelR4.rect -detach yes -iexpand xy $T style layout labelR4 labelR4.img -expand news -padx 2 -pady 2 $T item style set {range R1 R10} last labelR1 $T item style set {range R11 R20} last labelR2 $T item style set {range R21 R30} last labelR3 $T item style set {range R31 R40} last labelR4 # # Create styles for the non-locked columns # $T state define selN $T state define selS $T state define selW $T state define selE $T element create cell.bd rect -outline gray -outlinewidth 1 -open wn \ -fill {gray80 mouseover #F7F7F7 CHECK} set fill [list gray !focus $::SystemHighlight {}] $T element create cell.selN rect -height 2 -fill $fill $T element create cell.selS rect -height 2 -fill $fill $T element create cell.selW rect -width 2 -fill $fill $T element create cell.selE rect -width 2 -fill $fill $T style create cell -orient horizontal $T style elements cell {cell.bd cell.selN cell.selS cell.selW cell.selE} $T style layout cell cell.bd -detach yes -iexpand xy $T style layout cell cell.selN -detach yes -expand s -iexpand x -draw {no !selN} $T style layout cell cell.selS -detach yes -expand n -iexpand x -draw {no !selS} $T style layout cell cell.selW -detach yes -expand e -iexpand y -draw {no !selW} $T style layout cell cell.selE -detach yes -expand w -iexpand y -draw {no !selE} # NOTE 1: the following column descriptions are equivalent in this demo: # "range {first next} {last prev}" # "all lock none" (see note #2 below) # "lock none !tail" # The above item descriptions all specify the unlocked columns between # the left-locked and right-locked columns. $T item style set "root children" "range {first next} {last prev}" cell $T element create windowStyle.rect rect -fill {#e0e8f0 mouseover #F7F7F7 CHECK} $T element create windowStyle.text text $T element create windowStyle.window window -clip yes -destroy yes $T style create windowStyle -orient vertical $T style elements windowStyle {windowStyle.rect windowStyle.text windowStyle.window} $T style layout windowStyle windowStyle.rect -detach yes -iexpand xy $T style layout windowStyle windowStyle.text -expand we -padx 2 -pady 2 $T style layout windowStyle windowStyle.window -iexpand x -padx 2 -pady {0 2} # NOTE 2: "all lock none" also matches the tail column, however the # [item style set] command does not operate on the tail column so it is # ignored. Explicitly naming the tail column would result in an error # however. Another example of this behaviour is [column delete all]. $T item style set "list {R2 R22}" "all lock none" windowStyle foreach C [$T column id "lock none !tail"] { set ::DemoColumnLock(C$C) [$T column cget $C -tags] set I R2 set clip [frame $T.clipR${I}C$C -borderwidth 0] $::entryCmd $clip.e -width 4 -textvariable ::DemoColumnLock(C$C) $T item element configure $I $C windowStyle.window -window $clip + \ windowStyle.text -textvariable ::DemoColumnLock(C$C) set I R22 set clip [frame $T.clipR${I}C$C -borderwidth 0] $::entryCmd $clip.e -width 4 -textvariable ::DemoColumnLock(C$C) $T item element configure $I $C windowStyle.window -window $clip + \ windowStyle.text -textvariable ::DemoColumnLock(C$C) } bind DemoColumnLock { ColumnLockButton1 %W %x %y } bind DemoColumnLock { ColumnLockMotion1 %W %x %y ColumnLockMotion %W %x %y } bind DemoColumnLock { ColumnLockMotion %W %x %y } set ColumnLock(prev) "" set ColumnLock(selection) {} bindtags $T [list $T DemoColumnLock TreeCtrl [winfo toplevel $T] all] return } proc ColumnLockButton1 {w x y} { global ColumnLock set id [$w identify $x $y] set ColumnLock(selecting) 0 if {[lindex $id 0] eq "item"} { lassign $id what item where arg1 arg2 arg3 if {$where eq "column"} { if {[$w column compare $arg1 == last]} { $w item state set $item ~CHECK return } if {[$w column cget $arg1 -lock] eq "none"} { set ColumnLock(corner1) [list $item $arg1] set ColumnLock(corner2) $ColumnLock(corner1) set ColumnLock(selecting) 1 ColumnLockUpdateSelection $w } } } return } proc ColumnLockMotion1 {w x y} { global ColumnLock set id [$w identify $x $y] if {[lindex $id 0] eq "item"} { lassign $id what item where arg1 arg2 arg3 if {$where eq "column"} { if {[$w column cget $arg1 -lock] eq "none"} { if {$ColumnLock(selecting)} { set corner [list $item $arg1] if {$corner ne $ColumnLock(corner2)} { set ColumnLock(corner2) $corner ColumnLockUpdateSelection $w } } } } } return } proc ColumnLockMotion {w x y} { global ColumnLock set id [$w identify $x $y] if {$id eq ""} { } elseif {[lindex $id 0] eq "header"} { } elseif {[lindex $id 0] eq "item"} { set item [lindex $id 1] if {[lindex $id 2] eq "column"} { set column [lindex $id 3] } else { set column [$w cget -treecolumn] } set curr [list $item $column] if {$curr ne $ColumnLock(prev)} { if {$ColumnLock(prev) ne ""} { eval $w item state forcolumn $ColumnLock(prev) !mouseover } $w item state forcolumn $item $column mouseover set ColumnLock(prev) $curr } return } if {$ColumnLock(prev) ne ""} { eval $w item state forcolumn $ColumnLock(prev) !mouseover set ColumnLock(prev) "" } return } proc ColumnLockUpdateSelection {w} { global ColumnLock # Clear the old selection. foreach {item column} $ColumnLock(selection) { $w item state forcolumn $item $column {!selN !selS !selE !selW} } set ColumnLock(selection) {} # Order the 2 corners. foreach {item1 column1} $ColumnLock(corner1) {} foreach {item2 column2} $ColumnLock(corner2) {} if {[$w item compare $item1 > $item2]} { set swap $item1 set item1 $item2 set item2 $swap } if {[$w column compare $column1 > $column2]} { set swap $column1 set column1 $column2 set column2 $swap } # Set the state of every item-column on the edges of the selection. $w item state forcolumn $item1 "range $column1 $column2" selN $w item state forcolumn $item2 "range $column1 $column2" selS $w item state forcolumn "range $item1 $item2" $column1 selW $w item state forcolumn "range $item1 $item2" $column2 selE # Remember every item-column on the edges of the selection. foreach item [list $item1 $item2] { foreach column [$w column id "range $column1 $column2"] { lappend ColumnLock(selection) $item $column } } foreach item [$w item id "range $item1 $item2"] { foreach column [list $column1 $column2] { lappend ColumnLock(selection) $item $column } } return } proc ColumnLockAddText {} { set w [DemoList] $w style elements cell {cell.bd label1.text cell.selN cell.selS cell.selW cell.selE} $w item text visible {lock none} abc } tktreectrl-2.2.8/demos/demo.tcl0000700000175600010010000015324311073207242014651 0ustar TimNone#!/bin/wish84.exe # RCS: @(#) $Id: demo.tcl,v 1.71 2008/10/08 19:48:50 treectrl Exp $ set VERSION 2.2.8 package require Tk 8.4 set thisPlatform $::tcl_platform(platform) if {$thisPlatform eq "unix" && [tk windowingsystem] eq "aqua"} { set thisPlatform "macosx" } switch -- [tk windowingsystem] { aqua { set thisPlatform "macosx" } classic { set thisPlatform "macintosh" } win32 { set thisPlatform "windows" } x11 { set thisPlatform "unix" } } # Get full pathname to this file set ScriptDir [file normalize [file dirname [info script]]] # Command to create a full pathname in this file's directory proc Path {args} { return [file normalize [eval [list file join $::ScriptDir] $args]] } # Create some photo images on demand proc InitPics {args} { foreach pattern $args { if {[lsearch [image names] $pattern] == -1} { foreach file [glob -directory [Path pics] $pattern.gif] { set imageName [file root [file tail $file]] # I created an image called "file", which clobbered the # original Tcl command "file". Then I got confused. if {[llength [info commands $imageName]]} { error "don't want to create image called \"$imageName\"" } image create photo $imageName -file $file # Hack -- Create a "selected" version too image create photo ${imageName}Sel ${imageName}Sel copy $imageName imagetint ${imageName}Sel $::SystemHighlight 128 } } } return } # http://wiki.tcl.tk/1530 if {[info procs lassign] eq ""} { proc lassign {values args} { uplevel 1 [list foreach $args [linsert $values end {}] break] lrange $values [llength $args] end } } if {[catch { package require dbwin }]} { proc dbwin {s} { puts [string trimright $s "\n"] } } proc dbwintrace {name1 name2 op} { dbwin $::dbwin } trace add variable ::dbwin write dbwintrace # This gets called if 'package require' won't work during development. proc LoadSharedLibrary {} { switch -- $::thisPlatform { macintosh { set pattern treectrl*.shlb } macosx { set pattern treectrl*.dylib } unix { set pattern libtreectrl*[info sharedlibextension]* } windows { set pattern treectrl*[info sharedlibextension] } } set SHLIB [glob -nocomplain -directory [Path ..] $pattern] if {[llength $SHLIB] != 1} { return 0 } # When using configure/make, the "make demo" Makefile target sets the value of # the TREECTRL_LIBRARY environment variable which is used by tcl_findLibrary to # find our treectrl.tcl file. When *not* using configure/make, we set the value # of TREECTRL_LIBRARY and load the shared library manually. Note that # tcl_findLibrary is called by the Treectrl_Init() routine in C. set ::env(TREECTRL_LIBRARY) [Path .. library] load $SHLIB return 1 } # See if treectrl is already loaded for some reason if {[llength [info commands treectrl]]} { puts "demo.tcl: using previously-loaded treectrl package v[package provide treectrl]" if {$VERSION ne [package provide treectrl]} { puts "demo.tcl: WARNING: expected v$VERSION" } # For 'package require' to work with the development version, make sure the # TCLLIBPATH and TREECTRL_LIBRARY environment variables are set by your # Makefile/Jamfile/IDE etc. } elseif {![catch {package require treectrl $VERSION} err]} { puts "demo.tcl: 'package require' succeeded" } else { puts "demo.tcl: 'package require' failed: >>> $err <<<" if {[LoadSharedLibrary]} { puts "demo.tcl: loaded treectrl library by hand" } else { error "demo.tcl: can't load treectrl package" } } # Display path of shared library that was loaded foreach list [info loaded] { set file [lindex $list 0] set pkg [lindex $list 1] if {$pkg ne "Treectrl"} continue puts "demo.tcl: using '$file'" break } if {[info exists env(TREECTRL_LIBRARY)]} { puts "demo.tcl: TREECTRL_LIBRARY=$env(TREECTRL_LIBRARY)" } else { puts "demo.tcl: TREECTRL_LIBRARY undefined" } puts "demo.tcl: treectrl_library=$treectrl_library" set tile 0 set tileFull 0 ; # 1 if using tile-aware treectrl catch { if {[ttk::style layout TreeCtrl] ne ""} { set tile 1 set tileFull 1 } } if {$tile == 0} { catch { package require tile 0.7.8 namespace export style namespace eval ::tile { namespace export setTheme } namespace eval ::ttk { namespace import ::style namespace import ::tile::setTheme } set tile 1 } } if {$tile} { # Don't import ttk::entry, it messes up the edit bindings, and I'm not # sure how to get/set the equivalent -borderwidth, -selectborderwidth # etc options of a TEntry. set entryCmd ::ttk::entry set buttonCmd ::ttk::button set checkbuttonCmd ::ttk::checkbutton set radiobuttonCmd ttk::radiobutton set scrollbarCmd ::ttk::scrollbar } else { set entryCmd ::entry set buttonCmd ::button set checkbuttonCmd ::checkbutton set radiobuttonCmd ::radiobutton set scrollbarCmd ::scrollbar } option add *TreeCtrl.useTheme 1 #option add *TreeCtrl.itemPrefix item #option add *TreeCtrl.ColumnPrefix col # Resizing columns can be done in realtime or by displaying a proxy line switch -- $::thisPlatform { macosx - unix { option add *TreeCtrl.columnResizeMode realtime } windows { if {$::tcl_platform(os) eq "Windows NT"} { option add *TreeCtrl.columnResizeMode realtime } } } if {$tile} { set font TkDefaultFont } else { switch -- $::thisPlatform { macintosh { set font {Geneva 9} } macosx { set font {{Lucida Grande} 11} } unix { set font {Helvetica -12} } default { # There is a bug on my Win98 box with Tk_MeasureChars() and # MS Sans Serif 8. set font {{MS Sans} 8} } } } array set fontInfo [font actual $font] eval font create DemoFont [array get fontInfo] option add *TreeCtrl.font DemoFont array set fontInfo [font actual $font] set fontInfo(-weight) bold eval font create DemoFontBold [array get fontInfo] array set fontInfo [font actual $font] set fontInfo(-underline) 1 eval font create DemoFontUnderline [array get fontInfo] proc SetDemoFontSize {size} { font configure DemoFont -size $size font configure DemoFontBold -size $size font configure DemoFontUnderline -size $size return } proc IncreaseFontSize {} { set size [font configure DemoFont -size] SetDemoFontSize [incr size] return } proc DecreaseFontSize {} { set size [font configure DemoFont -size] SetDemoFontSize [incr size -1] return } # Demo sources foreach file { biglist bitmaps column-lock explorer firefox help imovie layout mailwasher mycomputer outlook-folders outlook-newgroup random span textvariable www-options } { source [Path $file.tcl] } # Get default colors set w [listbox .listbox] set SystemButtonFace [$w cget -highlightbackground] set SystemHighlight [$w cget -selectbackground] set SystemHighlightText [$w cget -selectforeground] destroy $w if {$thisPlatform == "unix"} { # I hate that gray selection color set SystemHighlight #316ac5 set SystemHighlightText White } proc MakeMenuBar {} { set m [menu .menubar] . configure -menu $m set m2 [menu $m.mFile -tearoff no] if {$::thisPlatform ne "unix" && [info commands console] ne ""} { console eval { wm title . "TkTreeCtrl Console" if {[info tclversion] == 8.4} { .console configure -font {Courier 9} } .console configure -height 8 # ::tk::ConsolePrompt wm geometry . +0-100 } $m2 add command -label "Console" -command { if {[console eval {winfo ismapped .}]} { console hide } else { console show } } } $m2 add command -label "Event Browser" -command ToggleEventsWindow $m2 add command -label "Identify" -command ToggleIdentifyWindow $m2 add command -label "Style Editor" -command ToggleStyleEditorWindow $m2 add command -label "View Source" -command ToggleSourceWindow $m2 add command -label "Magnifier" -command ToggleLoupeWindow $m2 add separator $m2 add command -label "Increase Font Size" -command IncreaseFontSize $m2 add command -label "Decrease Font Size" -command DecreaseFontSize $m2 add separator $m2 add command -label "Quit" -command exit $m add cascade -label "File" -menu $m2 if {$::tile} { set m2 [menu $m.mTheme -tearoff no] $m add cascade -label "Theme" -menu $m2 foreach theme [lsort -dictionary [ttk::style theme names]] { $m2 add radiobutton -label $theme -command [list ttk::setTheme $theme] \ -variable ::DemoTheme -value $theme } $m2 add separator $m2 add command -label "Inspector" -command ToggleThemeWindow } return } proc MakeEventsWindow {} { set w [toplevel .events] wm withdraw $w # wm transient $w . wm title $w "TkTreeCtrl Events" set m [menu $w.menubar] $w configure -menu $m set m1 [menu $m.m1 -tearoff 0] $m1 add cascade -label "Static" -menu [menu $m1.m1 -tearoff 0] $m1 add cascade -label "Dynamic" -menu [menu $m1.m2 -tearoff 0] $m1 add command -label "Clear Window" -command "$w.f.t item delete all" \ -accelerator Ctrl+X $m1 add command -label "Rebuild Menus" -command "RebuildEventsMenus $w.f.t $m" $m add cascade -label "Events" -menu $m1 bind $w "$w.f.t item delete all" TreePlusScrollbarsInAFrame $w.f 1 1 pack $w.f -expand yes -fill both set T $w.f.t $T configure -showheader no -showroot no -showrootlines no -height 300 $T column create -tags C0 $T configure -treecolumn C0 $T element create e1 text -fill [list $::SystemHighlightText {selected focus}] $T element create e2 text -fill [list $::SystemHighlightText {selected focus}] $T element create e3 rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] \ -showfocus yes $T element create e4 rect -fill blue -width 100 -height 2 set S [$T style create s1] $T style elements $S {e3 e1} $T style layout $S e3 -union [list e1] -ipadx 1 -ipady {0 1} set S [$T style create s2] $T style elements $S {e3 e1 e2} $T style layout $S e1 -width 20 -sticky w $T style layout $S e3 -union [list e1 e2] -ipadx 1 -ipady {0 1} set S [$T style create s3] $T style elements $S {e4} $T column configure C0 -itemstyle s1 RebuildEventsMenus $T $m wm protocol $w WM_DELETE_WINDOW "ToggleEventsWindow" switch -- $::thisPlatform { macintosh - macosx { wm geometry $w -40+40 } default { wm geometry $w -0+0 } } return } proc RebuildEventsMenus {T m} { foreach event [lsort -dictionary [[DemoList] notify eventnames]] { set details [lsort -dictionary [[DemoList] notify detailnames $event]] foreach detail $details { set pattern <$event-$detail> set linkage [[DemoList] notify linkage $pattern] lappend patterns $pattern $linkage lappend patterns2($linkage) $pattern } if {![llength $details]} { set pattern <$event> set linkage [[DemoList] notify linkage $pattern] lappend patterns $pattern $linkage lappend patterns2($linkage) $pattern } } $m.m1.m1 delete 0 end $m.m1.m2 delete 0 end set menu(static) $m.m1.m1 set menu(dynamic) $m.m1.m2 foreach {pattern linkage} $patterns { if {![info exists ::EventTrack($pattern)]} { set ::EventTrack($pattern) 1 } $menu($linkage) add checkbutton -label $pattern \ -variable EventTrack($pattern) \ -command [list ToggleEvent $T $pattern] } foreach linkage {static dynamic} { $menu($linkage) add separator $menu($linkage) add command -label "Toggle All" \ -command [list ToggleEvents $T $patterns2($linkage)] } set ::Events {} set ::EventsId "" foreach {pattern linkage} $patterns { [DemoList] notify bind $T $pattern { lappend Events %? if {$EventsId eq ""} { set EventsId [after idle [list RecordEvents %W]] } } } return } proc RecordEvents {T} { set ::EventsId "" set events $::Events set ::Events {} if {![winfo ismapped .events]} return if {[$T item numchildren root] > 2000} { set N [expr {[$T item numchildren root] - 2000}] $T item delete "root firstchild" "root child $N" } if {0 && [$T item count] > 1} { set I [$T item create] $T item style set $I 0 s3 $T item lastchild root $I } set open 1 if {[llength $events] > 50} { set open 0 } foreach list $events { RecordEvent $T $list $open } $T see "last visible" return } proc RecordEvent {T list open} { set I [$T item create -open $open] array set map $list $T item text $I C0 $map(P) $T item lastchild root $I foreach {char value} $list { if {[string first $char "TWPed"] != -1} continue set I2 [$T item create] $T item style set $I2 C0 s2 $T item element configure $I2 C0 e1 -text $char + e2 -text $value $T item lastchild $I $I2 $T item configure $I -button yes } return } proc ToggleEventsWindow {} { set w .events if {![winfo exists $w]} { MakeEventsWindow } if {[winfo ismapped $w]} { wm withdraw $w } else { wm deiconify $w } return } proc ToggleEvent {T pattern} { [DemoList] notify configure $T $pattern -active $::EventTrack($pattern) return } proc ToggleEvents {T patterns} { foreach pattern $patterns { set ::EventTrack($pattern) [expr {!$::EventTrack($pattern)}] ToggleEvent $T $pattern } return } proc MakeIdentifyWindow {} { set w .identify toplevel $w wm withdraw $w wm title $w "TkTreeCtrl Identify" set wText $w.text text $wText -state disabled -width 50 -height 2 -font [[DemoList] cget -font] $wText tag configure tagBold -font DemoFontBold pack $wText -expand yes -fill both wm protocol $w WM_DELETE_WINDOW "ToggleIdentifyWindow" return } proc UpdateIdentifyWindow {T x y} { set w .identify if {![winfo exists $w]} return set wText $w.text $wText configure -state normal $wText delete 1.0 end $wText insert end x= tagBold "$x " {} y= tagBold $y\n foreach {key val} [$T identify $x $y] { $wText insert end $key tagBold " $val " } $wText configure -state disabled return } proc ToggleIdentifyWindow {} { set w .identify if {![winfo exists $w]} { MakeIdentifyWindow } if {[winfo ismapped $w]} { wm withdraw $w } else { wm deiconify $w } return } proc MakeSourceWindow {} { set w [toplevel .source] wm withdraw $w # wm transient $w . set f [frame $w.f -borderwidth 0] switch -- $::thisPlatform { macintosh - macosx { set font {Geneva 9} } unix { set font {Courier -12} } default { set font {Courier 9} } } text $f.t -font $font -tabs [font measure $font 12345678] -wrap none \ -yscrollcommand "$f.sv set" -xscrollcommand "$f.sh set" $::scrollbarCmd $f.sv -orient vertical -command "$f.t yview" $::scrollbarCmd $f.sh -orient horizontal -command "$f.t xview" pack $f -expand yes -fill both grid columnconfigure $f 0 -weight 1 grid rowconfigure $f 0 -weight 1 grid configure $f.t -row 0 -column 0 -sticky news grid configure $f.sh -row 1 -column 0 -sticky we grid configure $f.sv -row 0 -column 1 -sticky ns wm protocol $w WM_DELETE_WINDOW "ToggleSourceWindow" switch -- $::thisPlatform { macintosh - macosx { wm geometry $w -40+40 } default { wm geometry $w -0+0 } } return } proc ShowSource {file} { wm title .source "TkTreeCtrl Source: $file" set path [Path $file] set t .source.f.t set chan [open $path] $t delete 1.0 end $t insert end [read $chan] $t mark set insert 1.0 close $chan return } proc ToggleSourceWindow {} { set w .source if {[winfo ismapped $w]} { wm withdraw $w } else { wm deiconify $w } return } proc ToggleStyleEditorWindow {} { set w .styleEditor if {![winfo exists $w]} { source [Path style-editor.tcl] StyleEditor::Init [DemoList] StyleEditor::SetListOfStyles } elseif {[winfo ismapped $w]} { wm withdraw $w } else { wm deiconify $w StyleEditor::SetListOfStyles } return } proc MakeThemeWindow {} { set w [toplevel .theme] wm withdraw $w # wm transient $w . wm title $w "TkTreeCtrl Themes" set m [menu $w.menubar] $w configure -menu $m set m1 [menu $m.m1 -tearoff 0] $m1 add command -label "Set List" -command SetThemeWindow $m add cascade -label "Theme" -menu $m1 TreePlusScrollbarsInAFrame $w.f 1 1 pack $w.f -expand yes -fill both set T $w.f.t $T configure -showheader no -showroot no -showrootlines no -height 300 $T column create -tags C0 $T configure -treecolumn C0 $T element create e1 text -fill [list $::SystemHighlightText {selected focus}] $T element create e3 rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] \ -showfocus yes set S [$T style create s1] $T style elements $S {e3 e1} $T style layout $S e3 -union [list e1] -ipadx 1 -ipady {0 1} $T column configure C0 -itemstyle s1 SetThemeWindow wm protocol $w WM_DELETE_WINDOW "ToggleThemeWindow" return } proc ToggleThemeWindow {} { set w .theme if {![winfo exists $w]} { MakeThemeWindow } if {[winfo ismapped $w]} { wm withdraw $w } else { wm deiconify $w } return } proc SetThemeWindow {} { set w .theme set T $w.f.t $T item delete all # # Themes # foreach theme [lsort -dictionary [ttk::style theme names]] { set I [$T item create -button yes -open no -tags theme -parent root] $T item text $I C0 $theme ttk::style theme settings $theme { set I2 [$T item create -button yes -open no -parent $I] $T item text $I2 C0 ELEMENTS # # Elements # foreach element [lsort -dictionary [ttk::style element names]] { # # Element options # set options [ttk::style element options $element] set I3 [$T item create -button [llength $options] -open no -tags element -parent $I2] $T item text $I3 C0 $element foreach option [lsort -dictionary $options] { set I4 [$T item create -open no -tags {element option} -parent $I3] $T item text $I4 C0 $option } } # # Styles # set I2 [$T item create -button yes -open no -parent $I] $T item text $I2 C0 STYLES set styles [list "."] ; # [ttk::style names] please! foreach style [lsort -dictionary $styles] { # # Style options # set cfg [ttk::style configure $style] set I3 [$T item create -button [llength $cfg] -open no -tags style -parent $I2] $T item text $I3 C0 $style foreach {option value} $cfg { set I4 [$T item create -open no -tags {style option} -parent $I3] $T item text $I4 C0 "$option $value" } } } } return } MakeSourceWindow MakeMenuBar # http://wiki.tcl.tk/950 proc sbset {sb first last} { if {$first <= 0 && $last >= 1} { grid remove $sb } else { grid $sb } $sb set $first $last return } proc TreePlusScrollbarsInAFrame {f h v} { if {$::tileFull} { frame $f -borderwidth 0 } else { frame $f -borderwidth 1 -relief sunken } treectrl $f.t -highlightthickness 0 -borderwidth 0 $f.t configure -xscrollincrement 20 # $f.t configure -itemprefix item# -columnprefix column# $f.t debug configure -enable no -display yes -erasecolor pink \ -drawcolor orange -displaydelay 30 -textlayout 0 -data 0 -span 0 if {$h} { $::scrollbarCmd $f.sh -orient horizontal -command "$f.t xview" # $f.t configure -xscrollcommand "$f.sh set" $f.t notify bind $f.sh { sbset %W %l %u } bind $f.sh "focus $f.t" } if {$v} { $::scrollbarCmd $f.sv -orient vertical -command "$f.t yview" # $f.t configure -yscrollcommand "$f.sv set" $f.t notify bind $f.sv { sbset %W %l %u } bind $f.sv "focus $f.t" } grid columnconfigure $f 0 -weight 1 grid rowconfigure $f 0 -weight 1 grid configure $f.t -row 0 -column 0 -sticky news if {$h} { grid configure $f.sh -row 1 -column 0 -sticky we } if {$v} { grid configure $f.sv -row 0 -column 1 -sticky ns } bind $f.t { TreeCtrl::MarqueeBegin %W %x %y set DebugExpose(x1) %x set DebugExpose(y1) %y break } bind $f.t { TreeCtrl::MarqueeUpdate %W %x %y set DebugExpose(x2) %x set DebugExpose(y2) %y break } bind $f.t { TreeCtrl::MarqueeEnd %W %x %y %W debug expose $DebugExpose(x1) $DebugExpose(y1) $DebugExpose(x2) $DebugExpose(y2) break } MakeListPopup $f.t MakeHeaderPopup $f.t bind $f.t { ShowPopup %W %x %y %X %Y } if {[tk windowingsystem] eq "aqua"} { bind $f.t { ShowPopup %W %x %y %X %Y } } return } proc MakeMainWindow {} { wm title . "TkTreeCtrl Demo" switch -- $::thisPlatform { macintosh - macosx { wm geometry . +40+40 set ::ShowLines 0 } default { wm geometry . +0+0 set ::ShowLines 1 } } panedwindow .pw2 -orient horizontal -borderwidth 0 panedwindow .pw1 -orient vertical -borderwidth 0 # Tree + scrollbar: demos TreePlusScrollbarsInAFrame .f1 1 1 .f1.t configure -showbuttons no -showlines no -showroot no -height 100 .f1.t column create -text "List of Demos" -expand yes -button no -tags C0 .f1.t configure -treecolumn C0 # Tree + scrollbar: styles + elements in list TreePlusScrollbarsInAFrame .f4 1 1 .f4.t configure -showlines $::ShowLines -showroot no -height 140 .f4.t column create -text "Elements and Styles" -expand yes -button no -tags C0 .f4.t configure -treecolumn C0 # Tree + scrollbar: styles + elements in selected item TreePlusScrollbarsInAFrame .f3 1 1 .f3.t configure -showlines $::ShowLines -showroot no .f3.t column create -text "Styles in Item" -expand yes -button no -tags C0 .f3.t configure -treecolumn C0 .pw1 add .f1 .f4 .f3 -height 150 # Frame on right frame .f2 # Tree + scrollbars TreePlusScrollbarsInAFrame .f2.f1 1 1 [DemoList] configure -indent 19 # Give it a big border to debug drawing if {!$::tileFull} { [DemoList] configure -borderwidth 6 -relief ridge -highlightthickness 3 } grid columnconfigure .f2 0 -weight 1 grid rowconfigure .f2 0 -weight 1 grid configure .f2.f1 -row 0 -column 0 -sticky news -pady 0 # Window to display result of "T identify" bind TagIdentify { if {"%W" ne [DemoList]} { set x [expr {%X - [winfo rootx [DemoList]]}] set y [expr {%Y - [winfo rooty [DemoList]]}] } else { set x %x set y %y } UpdateIdentifyWindow [DemoList] $x $y } AddBindTag [DemoList] TagIdentify .pw2 add .pw1 -width 200 .pw2 add .f2 -width 450 pack .pw2 -expand yes -fill both ### # A treectrl widget can generate the following built-in events: # called when the active item changes # called before an item is closed # called after an item is closed # called before an item is opened # called after an item is opened # called before items are deleted # called when horizontal scroll position changes # called when vertical scroll position changes # called when items are added to or removed from the selection # # The application programmer can define custom events to be # generated by the "notify generate" command. The following events # are generated by the library scripts. [DemoList] notify install [DemoList] notify install [DemoList] notify install [DemoList] notify install [DemoList] notify install [DemoList] notify install [DemoList] notify install [DemoList] notify install [DemoList] notify install [DemoList] notify install ### return } proc DemoList {} { return .f2.f1.t } proc MakeListPopup {T} { set m [menu $T.mTree -tearoff no] set m2 [menu $m.mCollapse -tearoff no] $m add cascade -label Collapse -menu $m2 set m2 [menu $m.mExpand -tearoff no] $m add cascade -label Expand -menu $m2 set m2 [menu $m.mBgImg -tearoff no] $m2 add radiobutton -label none -variable Popup(bgimg) -value none \ -command {$Popup(T) configure -backgroundimage ""} $m2 add radiobutton -label sky -variable Popup(bgimg) -value sky \ -command {$Popup(T) configure -backgroundimage $Popup(bgimg)} $m add cascade -label "Background Image" -menu $m2 set m2 [menu $m.mBgMode -tearoff no] foreach value {column order ordervisible row} { $m2 add radiobutton -label $value -variable Popup(bgmode) -value $value \ -command {$Popup(T) configure -backgroundmode $Popup(bgmode)} } $m add cascade -label "Background Mode" -menu $m2 set m2 [menu $m.mVisible -tearoff no] $m add cascade -label Columns -menu $m2 set m2 [menu $m.mColumnResizeMode -tearoff no] $m2 add radiobutton -label proxy -variable Popup(columnresizemode) -value proxy \ -command {$Popup(T) configure -columnresizemode $Popup(columnresizemode)} $m2 add radiobutton -label realtime -variable Popup(columnresizemode) -value realtime \ -command {$Popup(T) configure -columnresizemode $Popup(columnresizemode)} $m add cascade -label "Column Resize Mode" -menu $m2 set m2 [menu $m.mDebug -tearoff no] $m2 add checkbutton -label Data -variable Popup(debug,data) \ -command {$Popup(T) debug configure -data $Popup(debug,data)} $m2 add checkbutton -label Display -variable Popup(debug,display) \ -command {$Popup(T) debug configure -display $Popup(debug,display)} $m2 add checkbutton -label Span -variable Popup(debug,span) \ -command {$Popup(T) debug configure -span $Popup(debug,span)} $m2 add checkbutton -label "Text Layout" -variable Popup(debug,textlayout) \ -command {$Popup(T) debug configure -textlayout $Popup(debug,textlayout)} $m2 add separator set m3 [menu $m2.mDelay -tearoff no] foreach n {10 20 30 40 50 60 70 80 90 100} { $m3 add radiobutton -label $n -variable Popup(debug,displaydelay) -value $n \ -command {$Popup(T) debug configure -displaydelay $Popup(debug,displaydelay)} } $m2 add cascade -label "Display Delay" -menu $m3 $m2 add separator $m2 add checkbutton -label Enable -variable Popup(debug,enable) \ -command {$Popup(T) debug configure -enable $Popup(debug,enable)} $m add cascade -label Debug -menu $m2 set m2 [menu $m.mBuffer -tearoff no] $m2 add radiobutton -label "none" -variable Popup(doublebuffer) -value none \ -command {$Popup(T) configure -doublebuffer $Popup(doublebuffer)} $m2 add radiobutton -label "item" -variable Popup(doublebuffer) -value item \ -command {$Popup(T) configure -doublebuffer $Popup(doublebuffer)} $m2 add radiobutton -label "window" -variable Popup(doublebuffer) -value window \ -command {$Popup(T) configure -doublebuffer $Popup(doublebuffer)} $m add cascade -label Buffering -menu $m2 set m2 [menu $m.mLineStyle -tearoff no] $m2 add radiobutton -label "dot" -variable Popup(linestyle) -value dot \ -command {$Popup(T) configure -linestyle $Popup(linestyle)} $m2 add radiobutton -label "solid" -variable Popup(linestyle) -value solid \ -command {$Popup(T) configure -linestyle $Popup(linestyle)} $m add cascade -label "Line style" -menu $m2 set m2 [menu $m.mOrient -tearoff no] $m2 add radiobutton -label "Horizontal" -variable Popup(orient) -value horizontal \ -command {$Popup(T) configure -orient $Popup(orient)} $m2 add radiobutton -label "Vertical" -variable Popup(orient) -value vertical \ -command {$Popup(T) configure -orient $Popup(orient)} $m add cascade -label Orient -menu $m2 set m2 [menu $m.mSelectMode -tearoff no] foreach mode [list browse extended multiple single] { $m2 add radiobutton -label $mode -variable Popup(selectmode) -value $mode \ -command {$Popup(T) configure -selectmode $Popup(selectmode)} } $m add cascade -label Selectmode -menu $m2 set m2 [menu $m.mShow -tearoff no] $m2 add checkbutton -label "Buttons" -variable Popup(showbuttons) \ -command {$Popup(T) configure -showbuttons $Popup(showbuttons)} $m2 add checkbutton -label "Header" -variable Popup(showheader) \ -command {$Popup(T) configure -showheader $Popup(showheader)} $m2 add checkbutton -label "Lines" -variable Popup(showlines) \ -command {$Popup(T) configure -showlines $Popup(showlines)} $m2 add checkbutton -label "Root" -variable Popup(showroot) \ -command {$Popup(T) configure -showroot $Popup(showroot)} $m2 add checkbutton -label "Root Button" -variable Popup(showrootbutton) \ -command {$Popup(T) configure -showrootbutton $Popup(showrootbutton)} $m2 add checkbutton -label "Root Child Buttons" -variable Popup(showrootchildbuttons) \ -command {$Popup(T) configure -showrootchildbuttons $Popup(showrootchildbuttons)} $m2 add checkbutton -label "Root Child Lines" -variable Popup(showrootlines) \ -command {$Popup(T) configure -showrootlines $Popup(showrootlines)} $m add cascade -label Show -menu $m2 set m2 [menu $m.mSpan -tearoff no] $m add cascade -label Span -menu $m2 $m add checkbutton -label "Use Theme" -variable Popup(usetheme) \ -command {$Popup(T) configure -usetheme $Popup(usetheme)} return } proc MakeHeaderPopup {T} { set m [menu $T.mHeader -tearoff no] set m2 [menu $m.mArrow -tearoff no] $m add cascade -label Arrow -menu $m2 $m2 add radiobutton -label "None" -variable Popup(arrow) -value none \ -command {$Popup(T) column configure $Popup(column) -arrow none} $m2 add radiobutton -label "Up" -variable Popup(arrow) -value up \ -command {$Popup(T) column configure $Popup(column) -arrow up} $m2 add radiobutton -label "Down" -variable Popup(arrow) -value down \ -command {$Popup(T) column configure $Popup(column) -arrow down} $m2 add separator $m2 add radiobutton -label "Side Left" -variable Popup(arrow,side) -value left \ -command {$Popup(T) column configure $Popup(column) -arrowside left} $m2 add radiobutton -label "Side Right" -variable Popup(arrow,side) -value right \ -command {$Popup(T) column configure $Popup(column) -arrowside right} $m2 add separator $m2 add radiobutton -label "Gravity Left" -variable Popup(arrow,gravity) -value left \ -command {$Popup(T) column configure $Popup(column) -arrowgravity left} $m2 add radiobutton -label "Gravity Right" -variable Popup(arrow,gravity) -value right \ -command {$Popup(T) column configure $Popup(column) -arrowgravity right} $m add checkbutton -label "Button" -variable Popup(button) \ -command {$Popup(T) column configure $Popup(column) -button $Popup(button)} $m add checkbutton -label "Expand" -variable Popup(expand) \ -command {$Popup(T) column configure $Popup(column) -expand $Popup(expand)} set m2 [menu $m.mItemJustify -tearoff no] $m add cascade -label "Item Justify" -menu $m2 $m2 add radiobutton -label "Left" -variable Popup(itemjustify) -value left \ -command {$Popup(T) column configure $Popup(column) -itemjustify left} $m2 add radiobutton -label "Center" -variable Popup(itemjustify) -value center \ -command {$Popup(T) column configure $Popup(column) -itemjustify center} $m2 add radiobutton -label "Right" -variable Popup(itemjustify) -value right \ -command {$Popup(T) column configure $Popup(column) -itemjustify right} $m2 add radiobutton -label "Unspecified" -variable Popup(itemjustify) -value none \ -command {$Popup(T) column configure $Popup(column) -itemjustify {}} set m2 [menu $m.mJustify -tearoff no] $m add cascade -label Justify -menu $m2 $m2 add radiobutton -label "Left" -variable Popup(justify) -value left \ -command {$Popup(T) column configure $Popup(column) -justify left} $m2 add radiobutton -label "Center" -variable Popup(justify) -value center \ -command {$Popup(T) column configure $Popup(column) -justify center} $m2 add radiobutton -label "Right" -variable Popup(justify) -value right \ -command {$Popup(T) column configure $Popup(column) -justify right} set m2 [menu $m.mLock -tearoff no] $m add cascade -label Lock -menu $m2 $m2 add radiobutton -label "Left" -variable Popup(lock) -value left \ -command {$Popup(T) column configure $Popup(column) -lock left} $m2 add radiobutton -label "None" -variable Popup(lock) -value none \ -command {$Popup(T) column configure $Popup(column) -lock none} $m2 add radiobutton -label "Right" -variable Popup(lock) -value right \ -command {$Popup(T) column configure $Popup(column) -lock right} $m add checkbutton -label "Resize" -variable Popup(resize) \ -command {$Popup(T) column configure $Popup(column) -resize $Popup(resize)} $m add checkbutton -label "Squeeze" -variable Popup(squeeze) \ -command {$Popup(T) column configure $Popup(column) -squeeze $Popup(squeeze)} $m add checkbutton -label "Tree Column" -variable Popup(treecolumn) \ -command {$Popup(T) configure -treecolumn [expr {$Popup(treecolumn) ? $Popup(column) : ""}]} return } proc AddBindTag {w tag} { if {[lsearch -exact [bindtags $w] $tag] == -1} { bindtags $w [concat [bindtags $w] $tag] } foreach child [winfo children $w] { AddBindTag $child $tag } return } MakeMainWindow InitPics sky proc ShowPopup {T x y X Y} { global Popup set Popup(T) $T set id [$T identify $x $y] if {$id ne ""} { if {[lindex $id 0] eq "header"} { set Popup(column) [lindex $id 1] set Popup(arrow) [$T column cget $Popup(column) -arrow] set Popup(arrow,side) [$T column cget $Popup(column) -arrowside] set Popup(arrow,gravity) [$T column cget $Popup(column) -arrowgravity] set Popup(button) [$T column cget $Popup(column) -button] set Popup(expand) [$T column cget $Popup(column) -expand] set Popup(resize) [$T column cget $Popup(column) -resize] set Popup(squeeze) [$T column cget $Popup(column) -squeeze] set Popup(itemjustify) [$T column cget $Popup(column) -itemjustify] if {$Popup(itemjustify) eq ""} { set Popup(itemjustify) none } set Popup(justify) [$T column cget $Popup(column) -justify] set Popup(lock) [$T column cget $Popup(column) -lock] set Popup(treecolumn) [expr {[$T column id tree] eq $Popup(column)}] tk_popup $T.mHeader $X $Y return } } set menu $T.mTree set m $menu.mCollapse $m delete 0 end $m add command -label "All" -command {$Popup(T) item collapse all} if {$id ne ""} { if {[lindex $id 0] eq "item"} { set item [lindex $id 1] $m add command -label "Item $item" -command "$T item collapse $item" $m add command -label "Item $item (recurse)" -command "$T item collapse $item -recurse" } } set m $menu.mExpand $m delete 0 end $m add command -label "All" -command {$Popup(T) item expand all} if {$id ne ""} { if {[lindex $id 0] eq "item"} { set item [lindex $id 1] $m add command -label "Item $item" -command "$T item expand $item" $m add command -label "Item $item (recurse)" -command "$T item expand $item -recurse" } } foreach option {data display displaydelay enable span textlayout} { set Popup(debug,$option) [$T debug cget -$option] } set Popup(bgimg) [$T cget -backgroundimage] if {$Popup(bgimg) eq ""} { set Popup(bgimg) none } set Popup(bgmode) [$T cget -backgroundmode] set Popup(columnresizemode) [$T cget -columnresizemode] set Popup(doublebuffer) [$T cget -doublebuffer] set Popup(linestyle) [$T cget -linestyle] set Popup(orient) [$T cget -orient] set Popup(selectmode) [$T cget -selectmode] set Popup(showbuttons) [$T cget -showbuttons] set Popup(showheader) [$T cget -showheader] set Popup(showlines) [$T cget -showlines] set Popup(showroot) [$T cget -showroot] set Popup(showrootbutton) [$T cget -showrootbutton] set Popup(showrootchildbuttons) [$T cget -showrootchildbuttons] set Popup(showrootlines) [$T cget -showrootlines] set m $menu.mVisible $m delete 0 end foreach C [$T column list] { set break [expr {!([$T column order $C] % 20)}] set Popup(visible,$C) [$T column cget $C -visible] $m add checkbutton -label "Column $C \"[$T column cget $C -text]\" \[[$T column cget $C -image]\]" -variable Popup(visible,$C) \ -command "$T column configure $C -visible \$Popup(visible,$C)" \ -columnbreak $break } set m $menu.mSpan $m delete 0 end if {[llength $id] >= 4 && [lindex $id 2] eq "column"} { set item [lindex $id 1] set column [lindex $id 3] set lock [$T column cget $column -lock] for {set i 1} {$i <= [$T column order "last lock $lock"] - [$T column order $column] + 1} {incr i} { set break [expr {!(($i - 1) % 20)}] $m add radiobutton -label $i -command "$T item span $item $column $i" \ -variable Popup(span) -value $i -columnbreak $break } set Popup(span) [$T item span $item $column] } else { $m add command -label "no item column" -state disabled } set Popup(usetheme) [$T cget -usetheme] tk_popup $menu $X $Y return } # Allow "scan" bindings if {$::thisPlatform eq "windows"} { bind [DemoList] { } } # # List of demos # proc InitDemoList {} { global DemoCmd global DemoFile set t .f1.t $t element create e1 text -fill [list $::SystemHighlightText {selected focus}] $t element create e2 rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] \ -showfocus yes $t style create s1 $t style elements s1 {e2 e1} # Tk listbox has linespace + 1 height $t style layout s1 e2 -union [list e1] -ipadx 2 -ipady {0 1} -iexpand e $t column configure C0 -itemstyle s1 # "Picture Catalog" DemoPictureCatalog # "Picture Catalog 2" DemoPictureCatalog2 # "Folder Contents (Vertical)" DemoExplorerFilesV foreach {label command file} [list \ "Random $::RandomN Items" DemoRandom random.tcl \ "Random $::RandomN Items, Button Images" DemoRandom2 random.tcl \ "Outlook Express (Folders)" DemoOutlookFolders outlook-folders.tcl \ "Outlook Express (Newsgroup)" DemoOutlookNewsgroup outlook-newgroup.tcl \ "Explorer (Details)" DemoExplorerDetails explorer.tcl \ "Explorer (List)" DemoExplorerList explorer.tcl \ "Explorer (Large icons)" DemoExplorerLargeIcons explorer.tcl \ "Explorer (Small icons)" DemoExplorerSmallIcons explorer.tcl \ "Internet Options" DemoInternetOptions www-options.tcl \ "Help Contents" DemoHelpContents help.tcl \ "Layout" DemoLayout layout.tcl \ "MailWasher" DemoMailWasher mailwasher.tcl \ "Bitmaps" DemoBitmaps bitmaps.tcl \ "iMovie" DemoIMovie imovie.tcl \ "Firefox Privacy" DemoFirefoxPrivacy firefox.tcl \ "Textvariable" DemoTextvariable textvariable.tcl \ "Big List" DemoBigList biglist.tcl \ "Column Spanning" DemoSpan span.tcl \ "My Computer" DemoMyComputer mycomputer.tcl \ "Column Locking" DemoColumnLock column-lock.tcl ] { set item [$t item create] $t item lastchild root $item # $t item style set $item C0 s1 $t item text $item C0 $label set DemoCmd($item) $command set DemoFile($item) $file } $t yview moveto 0.0 return } InitDemoList proc ClicksToSeconds {clicks} { return [format "%.2g" [expr {$clicks / 1000000.0}]] } proc DemoSet {cmd file} { DemoClear set clicks [clock clicks] uplevel #0 $cmd set clicks [expr {[clock clicks] - $clicks}] dbwin "set list in [ClicksToSeconds $clicks] seconds ($clicks clicks)\n" [DemoList] xview moveto 0 [DemoList] yview moveto 0 update DisplayStylesInList ShowSource $file catch { if {[winfo ismapped .styleEditor]} { StyleEditor::SetListOfStyles } } AddBindTag [DemoList] TagIdentify return } .f1.t notify bind .f1.t { if {%c == 1} { set item [%T selection get 0] DemoSet $DemoCmd($item) $DemoFile($item) } } proc DisplayStylesInList {} { set T [DemoList] set t .f4.t # Create elements and styles the first time this is called if {[llength [$t style names]] == 0} { $t element create e1 text -fill [list $::SystemHighlightText {selected focus}] $t element create e2 text -fill [list $::SystemHighlightText {selected focus} "" {selected !focus} blue {}] $t element create e3 rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] \ -showfocus yes $t style create s1 $t style elements s1 {e3 e1} $t style layout s1 e3 -union [list e1] -ipadx 1 -ipady {0 1} $t style create s2 $t style elements s2 {e3 e1 e2} $t style layout s2 e1 -padx {0 4} $t style layout s2 e3 -union [list e1 e2] -ipadx 1 -ipady {0 1} } # Clear the list $t item delete all # One item for each element in the demo list foreach elem [lsort -dictionary [$T element names]] { set item [$t item create -button yes -open no] $t item style set $item C0 s1 $t item text $item C0 "Element $elem ([$T element type $elem])" # One item for each configuration option for this element foreach list [$T element configure $elem] { lassign $list name x y default current set item2 [$t item create] if {[string equal $default $current]} { $t item style set $item2 C0 s1 $t item element configure $item2 C0 e1 -text [list $name $current] } else { $t item style set $item2 C0 s2 $t item element configure $item2 C0 e1 -text $name + e2 -text [list $current] } $t item lastchild $item $item2 } $t item lastchild root $item } # One item for each style in the demo list foreach style [lsort -dictionary [$T style names]] { set item [$t item create -button yes -open no] $t item style set $item C0 s1 $t item text $item C0 "Style $style" # One item for each element in the style foreach elem [$T style elements $style] { set item2 [$t item create -button yes -open no] $t item style set $item2 C0 s1 $t item text $item2 C0 "Element $elem ([$T element type $elem])" # One item for each layout option for this element in this style foreach {option value} [$T style layout $style $elem] { set item3 [$t item create] # $t item hasbutton $item3 no $t item style set $item3 C0 s1 $t item text $item3 C0 [list $option $value] $t item lastchild $item2 $item3 } $t item lastchild $item $item2 } $t item lastchild root $item } $t xview moveto 0 $t yview moveto 0 return } proc DisplayStylesInItem {item} { set T [DemoList] set t .f3.t $t column configure C0 -text "Styles in item [$T item id $item]" # Create elements and styles the first time this is called if {[llength [$t style names]] == 0} { $t element create e1 text -fill [list $::SystemHighlightText {selected focus}] $t element create e2 text -fill [list $::SystemHighlightText {selected focus} "" {selected !focus} blue {}] $t element create e3 rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] \ -showfocus yes $t style create s1 $t style elements s1 {e3 e1} $t style layout s1 e3 -union [list e1] -ipadx {1 2} -ipady {0 1} $t style create s2 $t style elements s2 {e3 e1 e2} $t style layout s2 e1 -padx {0 4} $t style layout s2 e3 -union [list e1 e2] -ipadx 1 -ipady {0 1} } # Clear the list $t item delete all # One item for each item-column foreach style [$T item style set $item] column [$T column list] { set item2 [$t item create -open no] $t item style set $item2 C0 s1 if {$style ne ""} { $t item element configure $item2 C0 e1 \ -text "Column $column: Style $style" } else { $t item element configure $item2 C0 e1 \ -text "Column $column: no style" } # One item for each element in this style if {[string length $style]} { set button 0 foreach elem [$T item style elements $item $column] { set button 1 set item3 [$t item create -button yes -open no] $t item style set $item3 C0 s1 $t item element configure $item3 C0 e1 \ -text "Element $elem ([$T element type $elem])" # One item for each configuration option in this element foreach list [$T item element configure $item $column $elem] { lassign $list name x y default current set item4 [$t item create] set masterDefault [$T element cget $elem $name] set sameAsMaster [string equal $masterDefault $current] if {!$sameAsMaster && ![string length $current]} { set sameAsMaster 1 set current $masterDefault } if {$sameAsMaster} { $t item style set $item4 C0 s1 $t item element configure $item4 C0 e1 -text "$name [list $current]" } else { $t item style set $item4 C0 s2 $t item element configure $item4 C0 e1 -text $name + e2 -text [list $current] } $t item lastchild $item3 $item4 } $t item lastchild $item2 $item3 } if {$button} { $t item configure $item2 -button yes } } $t item lastchild root $item2 } $t xview moveto 0 $t yview moveto 0 return } # When one item is selected in the demo list, display the styles in that item. # See DemoClear for why the tag "DontDelete" is used. set DisplayStylesInItem(item) "" set MouseIsDown 0 bind [DemoList] { set MouseIsDown 1 } bind [DemoList] { set MouseIsDown 0 if {$DisplayStylesInItem(item) ne ""} { DisplayStylesInItem $DisplayStylesInItem(item) set DisplayStylesInItem(item) "" } } [DemoList] notify bind DontDelete { if {%c == 1} { if {$MouseIsDown} { set DisplayStylesInItem(item) [%T selection get 0] } else { DisplayStylesInItem [%T selection get 0] } } } # Move columns when ColumnDrag-receive is generated. # See DemoClear for why the tag "DontDelete" is used. [DemoList] notify bind DontDelete { %T column move %C %b } proc DemoClear {} { set T [DemoList] # Clear the demo list $T item delete all # Clear all bindings on the demo list added by the previous demo. # The bindings are removed from the tag $T only. For those # bindings that should not be deleted we use the tag DontDelete. # DontDelete is not a special name it just needs to be different # than $T. $T notify unbind $T # Clear all run-time states eval $T state undefine [$T state names] # Clear the styles-in-item list .f3.t item delete all # Delete columns in demo list $T column delete all # Delete all styles in demo list eval $T style delete [$T style names] # Delete all elements in demo list eval $T element delete [$T element names] # Delete -window windows foreach child [winfo children $T] { if {[string equal $child $T.mTree] || [string equal $child $T.mHeader]} continue destroy $child } $T item configure root -button no $T item expand root # Restore some happy defaults to the demo list $T configure -orient vertical -wrap "" -xscrollincrement 0 \ -yscrollincrement 0 -itemheight 0 -showheader yes \ -background white -scrollmargin 0 -xscrolldelay 50 -yscrolldelay 50 \ -buttonbitmap "" -buttonimage "" -backgroundmode row \ -indent 19 -backgroundimage "" -showrootchildbuttons yes \ -showrootlines yes -minitemheight 0 -borderwidth [expr {$::tileFull ? 0 : 6}] \ -highlightthickness [expr {$::tileFull ? 0 : 3}] -usetheme yes -cursor {} \ -itemwidth 0 -itemwidthequal no -itemwidthmultiple 0 \ -font [.f4.t cget -font] # Undo "column configure all" in a demo $T column configure tail -background \ [lindex [$T column configure tail -background] 3] # Enable drag-and-drop column reordering. This also requires the # event be installed. $T column dragconfigure -enable yes # Restore default bindings to the demo list bindtags $T [list $T TreeCtrl [winfo toplevel $T] all DisplayStylesInItemBindTag] catch {destroy $T.entry} catch {destroy $T.text} return } # # Demo: Picture catalog # proc DemoPictureCatalog {} { set T [DemoList] $T configure -showroot no -showbuttons no -showlines no \ -selectmode multiple -orient horizontal -wrap window \ -yscrollincrement 50 -showheader no $T element create elemTxt text -fill {SystemHighlightText {selected focus}} $T element create elemSelTxt rect -fill {SystemHighlight {selected focus}} $T element create elemSelImg rect -outline {SystemHighlight {selected focus}} \ -outlinewidth 4 $T element create elemImg rect -fill gray -width 80 -height 120 set S [$T style create STYLE -orient vertical] $T style elements $S {elemSelImg elemImg elemSelTxt elemTxt} $T style layout $S elemSelImg -union elemImg -ipadx 6 -ipady 6 $T style layout $S elemSelTxt -union elemTxt $T style layout $S elemImg -pady {0 6} for {set i 1} {$i <= 10} {incr i} { set I [$T item create] $T item style set $I 0 $S $T item text $I 0 "Picture #$i" $T item lastchild root $I } return } # # Demo: Picture catalog # proc DemoPictureCatalog2 {} { set T [DemoList] $T configure -showroot no -showbuttons no -showlines no \ -selectmode multiple -orient horizontal -wrap window \ -yscrollincrement 50 -showheader no $T element create elemTxt text -fill {SystemHighlightText {selected focus}} \ -justify left -wrap word -lines 2 $T element create elemSelTxt rect -fill {SystemHighlight {selected focus}} $T element create elemSelImg rect -outline {SystemHighlight {selected focus}} \ -outlinewidth 4 $T element create elemImg rect -fill gray set S [$T style create STYLE -orient vertical] $T style elements $S {elemSelImg elemImg elemSelTxt elemTxt} $T style layout $S elemSelImg -union elemImg \ -ipadx 6 -ipady 6 $T style layout $S elemSelTxt -union elemTxt $T style layout $S elemImg -pady {0 6} $T style layout $S elemImg -expand n $T style layout $S elemTxt -expand s for {set i 1} {$i <= 10} {incr i} { set I [$T item create] $T item style set $I 0 $S $T item text $I 0 "This is\nPicture\n#$i" $T item element configure $I 0 elemImg -width [expr int(20 + rand() * 80)] \ -height [expr int(20 + rand() * 120)] $T item lastchild root $I } return } proc CursorWindow {} { set w .cursors if {[winfo exists $w]} { destroy $w } toplevel $w set c [canvas $w.canvas -background white -width [expr {50 * 10}] \ -highlightthickness 0 -borderwidth 0] pack $c -expand yes -fill both set cursors { X_cursor arrow based_arrow_down based_arrow_up boat bogosity bottom_left_corner bottom_right_corner bottom_side bottom_tee box_spiral center_ptr circle clock coffee_mug cross cross_reverse crosshair diamond_cross dot dotbox double_arrow draft_large draft_small draped_box exchange fleur gobbler gumby hand1 hand2 heart icon iron_cross left_ptr left_side left_tee leftbutton ll_angle lr_angle man middlebutton mouse pencil pirate plus question_arrow right_ptr right_side right_tee rightbutton rtl_logo sailboat sb_down_arrow sb_h_double_arrow sb_left_arrow sb_right_arrow sb_up_arrow sb_v_double_arrow shuttle sizing spider spraycan star target tcross top_left_arrow top_left_corner top_right_corner top_side top_tee trek ul_angle umbrella ur_angle watch xterm } set col 0 set row 0 foreach cursor $cursors { set x [expr {$col * 50}] set y [expr {$row * 40}] $c create rectangle $x $y [expr {$x + 50}] [expr {$y + 40}] \ -fill gray90 -outline black -width 2 -tags $cursor.rect $c create text [expr {$x + 50 / 2}] [expr {$y + 4}] -text $cursor \ -anchor n -width 42 -tags $cursor.text if {[incr col] == 10} { set col 0 incr row } $c bind $cursor.rect " $c configure -cursor $cursor $c itemconfigure $cursor.rect -fill linen " $c bind $cursor.rect " $c configure -cursor {} $c itemconfigure $cursor.rect -fill gray90 " $c bind $cursor.text " $c configure -cursor $cursor " $c bind $cursor.text " $c configure -cursor {} " } $c configure -height [expr {($row + 1) * 40}] return } # A little screen magnifier if {[llength [info commands loupe]]} { set Loupe(zoom) 2 set Loupe(x) 0 set Loupe(y) 0 set Loupe(auto) 1 set Loupe(afterId) "" proc LoupeAfter {} { global Loupe set x [winfo pointerx .] set y [winfo pointery .] if {$Loupe(auto) || ($Loupe(x) != $x) || ($Loupe(y) != $y)} { set w [image width $Loupe(image)] set h [image height $Loupe(image)] loupe $Loupe(image) $x $y $w $h $::Loupe(zoom) set Loupe(x) $x set Loupe(y) $y } set Loupe(afterId) [after $Loupe(delay) LoupeAfter] return } proc MakeLoupeWindow {} { global Loupe set w [toplevel .loupe] wm title $w "TreeCtrl Magnifier" wm withdraw $w wm geometry $w -0+0 image create photo ImageLoupe -width 280 -height 150 pack [label $w.label -image ImageLoupe -borderwidth 1 -relief sunken] \ -expand yes -fill both set f [frame $w.zoom -borderwidth 0] radiobutton $f.r1 -text "1x" -variable ::Loupe(zoom) -value 1 radiobutton $f.r2 -text "2x" -variable ::Loupe(zoom) -value 2 radiobutton $f.r4 -text "4x" -variable ::Loupe(zoom) -value 4 radiobutton $f.r8 -text "8x" -variable ::Loupe(zoom) -value 8 pack $f.r1 $f.r2 $f.r4 $f.r8 -side left pack $f -side bottom -anchor e # Resize the image with the window bind LoupeWindow { set w [expr {%w - 2}] set h [expr {%h - 2}] if {$w != [$Loupe(image) cget -width] || $h != [$Loupe(image) cget -height]} { $Loupe(image) configure -width $w -height $h loupe $Loupe(image) $Loupe(x) $Loupe(y) $w $h $Loupe(zoom) } } bindtags $w.label [concat [bindtags .loupe] LoupeWindow] wm protocol $w WM_DELETE_WINDOW "ToggleLoupeWindow" set Loupe(image) ImageLoupe set Loupe(delay) 500 return } proc ToggleLoupeWindow {} { global Loupe set w .loupe if {![winfo exists $w]} { MakeLoupeWindow } if {[winfo ismapped $w]} { after cancel $Loupe(afterId) wm withdraw $w } else { LoupeAfter wm deiconify $w } return } } proc RandomPerfTest {} { set ::RandomN 15000 DemoSet DemoRandom random.tcl [DemoList] item expand all [DemoList] style layout styFolder elemTxtName -squeeze x [DemoList] style layout styFile elemTxtName -squeeze x [DemoList] elem conf elemTxtName -lines 1 update puts [time {[DemoList] colu conf 0 -width 160 ; update}] return } tktreectrl-2.2.8/demos/explorer.tcl0000700000175600010010000004310410555004561015562 0ustar TimNone# RCS: @(#) $Id: explorer.tcl,v 1.25 2006/12/07 03:52:40 treectrl Exp $ set Dir [file dirname [file dirname [info script]]] set shellicon 0 # Might work on other windows versions, but only tested on XP if {$tcl_platform(os) eq "Windows NT" && $tcl_platform(osVersion) == 5.1} { catch { lappend auto_path $treectrl_library package require shellicon $VERSION set shellicon 1 } } proc DemoExplorerAux {scriptDir scriptFile} { global Explorer global Dir set T [DemoList] set clicks [clock clicks] set globDirs [glob -nocomplain -types d -dir $Dir *] set clickGlobDirs [expr {[clock clicks] - $clicks}] set clicks [clock clicks] set list [lsort -dictionary $globDirs] set clickSortDirs [expr {[clock clicks] - $clicks}] if {[file dirname $Dir] ne $Dir} { lappend globDirs ".." set list [concat ".." $list] } set clicks [clock clicks] foreach file $list $scriptDir set clickAddDirs [expr {[clock clicks] - $clicks}] $T item tag add "root children" directory set clicks [clock clicks] set globFiles [glob -nocomplain -types f -dir $Dir *] set clickGlobFiles [expr {[clock clicks] - $clicks}] set clicks [clock clicks] set list [lsort -dictionary $globFiles] set clickSortFiles [expr {[clock clicks] - $clicks}] set clicks [clock clicks] foreach file $list $scriptFile set clickAddFiles [expr {[clock clicks] - $clicks}] set gd [ClicksToSeconds $clickGlobDirs] set sd [ClicksToSeconds $clickSortDirs] set ad [ClicksToSeconds $clickAddDirs] set gf [ClicksToSeconds $clickGlobFiles] set sf [ClicksToSeconds $clickSortFiles] set af [ClicksToSeconds $clickAddFiles] puts "dirs([llength $globDirs]) glob/sort/add $gd/$sd/$ad files([llength $globFiles]) glob/sort/add $gf/$sf/$af" set ::TreeCtrl::Priv(DirCnt,$T) [llength $globDirs] # Double-clicking a directory displays its contents. set Explorer(scriptDir) $scriptDir set Explorer(scriptFile) $scriptFile bind DemoExplorer { ExplorerDoubleButton1 %W %x %y } return } # # Demo: explorer files # proc DemoExplorerDetails {} { set T [DemoList] set height [font metrics [$T cget -font] -linespace] if {$height < 18} { set height 18 } # # Configure the treectrl widget # $T configure -showroot no -showbuttons no -showlines no -itemheight $height \ -selectmode extended -xscrollincrement 20 \ -scrollmargin 16 -xscrolldelay "500 50" -yscrolldelay "500 50" InitPics small-* # # Create columns # $T column create -text Name -tags name -width 200 \ -arrow up -itembackground #F7F7F7 $T column create -text Size -tags size -justify right -width 60 \ -arrowside left -arrowgravity right $T column create -text Type -tags type -width 120 $T column create -text Modified -tags modified -width 120 # Demonstration of per-state column options and configure "all" $T column configure all -background {gray90 active gray70 normal gray50 pressed} # # Create elements # if {$::shellicon} { $T element create elemImg shellicon -size small } else { $T element create elemImg image -image {small-folderSel {selected} small-folder {}} } $T element create txtName text -fill [list $::SystemHighlightText {selected focus}] \ -lines 1 $T element create txtType text -lines 1 $T element create txtSize text -datatype integer -format "%dKB" -lines 1 $T element create txtDate text -datatype time -format "%d/%m/%y %I:%M %p" -lines 1 $T element create elemRectSel rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] -showfocus yes # # Create styles using the elements # # column 0: image + text set S [$T style create styName -orient horizontal] $T style elements $S {elemRectSel elemImg txtName} $T style layout $S elemImg -padx {2 0} -expand ns $T style layout $S txtName -squeeze x -expand ns $T style layout $S elemRectSel -union [list txtName] -ipadx 2 -iexpand ns # column 1: text set S [$T style create stySize] $T style elements $S txtSize $T style layout $S txtSize -padx 6 -squeeze x -expand ns # column 2: text set S [$T style create styType] $T style elements $S txtType $T style layout $S txtType -padx 6 -squeeze x -expand ns # column 3: text set S [$T style create styDate] $T style elements $S txtDate $T style layout $S txtDate -padx 6 -squeeze x -expand ns # List of lists: {column style element ...} specifying text elements # the user can edit TreeCtrl::SetEditable $T { {name styName txtName} } # List of lists: {column style element ...} specifying elements # the user can click on or select with the selection rectangle TreeCtrl::SetSensitive $T { {name styName elemImg txtName} } # List of lists: {column style element ...} specifying elements # added to the drag image when dragging selected items TreeCtrl::SetDragImage $T { {name styName elemImg txtName} } # During editing, hide the text and selection-rectangle elements. $T state define edit $T style layout styName txtName -draw {no edit} $T style layout styName elemRectSel -draw {no edit} $T notify bind $T { %T item state set %I ~edit } $T notify bind $T { %T item element configure %I %C %E -text %t } $T notify bind $T { %T item state set %I ~edit } # # Create items and assign styles # set scriptDir { set item [$T item create -open no] $T item style set $item name styName type styType modified styDate $T item element configure $item \ name txtName -text [file tail $file] , \ type txtType -text "Folder" , \ modified txtDate -data [file mtime $file] if {$::shellicon} { # The shellicon extension fails randomly (by putting GDB into the # background!?) if the filename is not valid. MSDN says "relative # paths are valid" but perhaps that is misinformation. if {$file eq ".."} { set file [file dirname $::Dir] } $T item element configure $item \ name elemImg -path $file } $T item lastchild root $item } set scriptFile { set item [$T item create -open no] $T item style set $item name styName size stySize type styType modified styDate switch [file extension $file] { .dll { set img small-dll } .exe { set img small-exe } .txt { set img small-txt } default { set img small-file } } set type [string toupper [file extension $file]] if {$type ne ""} { set type "[string range $type 1 end] " } append type "File" if {$::shellicon} { $T item element configure $item \ name elemImg -path $file + txtName -text [file tail $file] , \ size txtSize -data [expr {[file size $file] / 1024 + 1}] , \ type txtType -text $type , \ modified txtDate -data [file mtime $file] } else { $T item element configure $item \ name elemImg -image [list ${img}Sel {selected} $img {}] + txtName -text [file tail $file] , \ size txtSize -data [expr {[file size $file] / 1024 + 1}] , \ type txtType -text $type , \ modified txtDate -data [file mtime $file] } $T item lastchild root $item } DemoExplorerAux $scriptDir $scriptFile set ::SortColumn name $T notify bind $T { ExplorerHeaderInvoke %T %C } bindtags $T [list $T DemoExplorer TreeCtrlFileList TreeCtrl [winfo toplevel $T] all] return } proc ExplorerHeaderInvoke {T C} { global SortColumn if {[$T column compare $C == $SortColumn]} { if {[$T column cget $SortColumn -arrow] eq "down"} { set order -increasing set arrow up } else { set order -decreasing set arrow down } } else { if {[$T column cget $SortColumn -arrow] eq "down"} { set order -decreasing set arrow down } else { set order -increasing set arrow up } $T column configure $SortColumn -arrow none -itembackground {} set SortColumn $C } $T column configure $C -arrow $arrow -itembackground #F7F7F7 set dirCount $::TreeCtrl::Priv(DirCnt,$T) set fileCount [expr {[$T item count] - 1 - $dirCount}] set lastDir [expr {$dirCount - 1}] switch [$T column cget $C -tags] { name { if {$dirCount} { $T item sort root $order -last "root child $lastDir" -column $C -dictionary } if {$fileCount} { $T item sort root $order -first "root child $dirCount" -column $C -dictionary } } size { if {$fileCount} { $T item sort root $order -first "root child $dirCount" -column $C -integer -column name -dictionary } } type { if {$fileCount} { $T item sort root $order -first "root child $dirCount" -column $C -dictionary -column name -dictionary } } modified { if {$dirCount} { $T item sort root $order -last "root child $lastDir" -column $C -integer -column name -dictionary } if {$fileCount} { $T item sort root $order -first "root child $dirCount" -column $C -integer -column name -dictionary } } } return } proc DemoExplorerLargeIcons {} { set T [DemoList] # Item height is 32 for icon, 4 padding, 3 lines of text set itemHeight [expr {32 + 4 + [font metrics [$T cget -font] -linespace] * 3}] # # Configure the treectrl widget # $T configure -showroot no -showbuttons no -showlines no \ -selectmode extended -wrap window -orient horizontal \ -itemheight $itemHeight -itemwidth 75 -showheader no \ -scrollmargin 16 -xscrolldelay "500 50" -yscrolldelay "500 50" InitPics big-* # # Create columns # $T column create -tags C0 # # Create elements # if {$::shellicon} { $T element create elemImg shellicon -size large } else { $T element create elemImg image -image {big-folderSel {selected} big-folder {}} } $T element create elemTxt text -fill [list $::SystemHighlightText {selected focus}] \ -justify center -lines 1 -width 71 -wrap word $T element create elemSel rect -fill [list $::SystemHighlight {selected focus} gray {selected}] -showfocus yes # # Create styles using the elements # # image + text set S [$T style create STYLE -orient vertical] $T style elements $S {elemSel elemImg elemTxt} $T style layout $S elemImg -expand we $T style layout $S elemTxt -pady {4 0} -squeeze x -expand we $T style layout $S elemSel -union [list elemTxt] -ipadx 2 # List of lists: {column style element ...} specifying text elements # the user can edit TreeCtrl::SetEditable $T { {C0 STYLE elemTxt} } # List of lists: {column style element ...} specifying elements # the user can click on or select with the selection rectangle TreeCtrl::SetSensitive $T { {C0 STYLE elemImg elemTxt} } # List of lists: {column style element ...} specifying elements # added to the drag image when dragging selected items TreeCtrl::SetDragImage $T { {C0 STYLE elemImg elemTxt} } # During editing, hide the text and selection-rectangle elements. $T state define edit $T style layout STYLE elemTxt -draw {no edit} $T style layout STYLE elemSel -draw {no edit} $T notify bind $T { %T item state set %I ~edit } $T notify bind $T { %T item element configure %I %C %E -text %t } $T notify bind $T { %T item state set %I ~edit } # # Create items and assign styles # set scriptDir { set item [$T item create -open no] $T item style set $item C0 STYLE $T item text $item C0 [file tail $file] if {$::shellicon} { # The shellicon extension fails randomly (by putting GDB into the # background!?) if the filename is not valid. MSDN says "relative # paths are valid" but perhaps that is misinformation. if {$file eq ".."} { set file [file dirname $::Dir] } $T item element configure $item C0 \ elemImg -path $file } $T item lastchild root $item } set scriptFile { set item [$T item create -open no] $T item style set $item C0 STYLE switch [file extension $file] { .dll { set img big-dll } .exe { set img big-exe } .txt { set img big-txt } default { set img big-file } } set type [string toupper [file extension $file]] if {$type ne ""} { set type "[string range $type 1 end] " } append type "File" if {$::shellicon} { $T item element configure $item C0 \ elemImg -path $file + \ elemTxt -text [file tail $file] } else { $T item element configure $item C0 \ elemImg -image [list ${img}Sel {selected} $img {}] + \ elemTxt -text [file tail $file] } $T item lastchild root $item } DemoExplorerAux $scriptDir $scriptFile $T activate [$T item id "root firstchild"] $T notify bind $T { if {[%T item compare %p != root]} { %T item element configure %p C0 elemTxt -lines {} } if {[%T item compare %c != root]} { %T item element configure %c C0 elemTxt -lines 3 } } $T item element configure active C0 elemTxt -lines 3 bindtags $T [list $T DemoExplorer TreeCtrlFileList TreeCtrl [winfo toplevel $T] all] return } # Tree is horizontal, wrapping occurs at right edge of window, each item # is as wide as the smallest needed multiple of 110 pixels proc DemoExplorerSmallIcons {} { set T [DemoList] DemoExplorerList $T configure -orient horizontal \ -itemwidthmultiple 110 -itemwidthequal no return } # Tree is vertical, wrapping occurs at bottom of window, each range has the # same width (as wide as the longest item), xscrollincrement is by range proc DemoExplorerList {} { set T [DemoList] set height [font metrics [$T cget -font] -linespace] if {$height < 18} { set height 18 } # # Configure the treectrl widget # $T configure -showroot no -showbuttons no -showlines no -itemheight $height \ -selectmode extended -wrap window -showheader no \ -scrollmargin 16 -xscrolldelay "500 50" -yscrolldelay "500 50" \ -itemwidthequal yes InitPics small-* # # Create columns # $T column create -tags C0 # # Create elements # if {$::shellicon} { $T element create elemImg shellicon -size small } else { $T element create elemImg image -image {small-folderSel {selected} small-folder {}} } $T element create elemTxt text -fill [list $::SystemHighlightText {selected focus}] \ -lines 1 $T element create elemSel rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] -showfocus yes # # Create styles using the elements # # image + text set S [$T style create STYLE] $T style elements $S {elemSel elemImg elemTxt} $T style layout $S elemImg -expand ns $T style layout $S elemTxt -squeeze x -expand ns -padx {2 0} $T style layout $S elemSel -union [list elemTxt] -iexpand ns -ipadx 2 # List of lists: {column style element ...} specifying text elements # the user can edit TreeCtrl::SetEditable $T { {C0 STYLE elemTxt} } # List of lists: {column style element ...} specifying elements # the user can click on or select with the selection rectangle TreeCtrl::SetSensitive $T { {C0 STYLE elemImg elemTxt} } # List of lists: {column style element ...} specifying elements # added to the drag image when dragging selected items TreeCtrl::SetDragImage $T { {C0 STYLE elemImg elemTxt} } # During editing, hide the text and selection-rectangle elements. $T state define edit $T style layout STYLE elemTxt -draw {no edit} $T style layout STYLE elemSel -draw {no edit} $T notify bind $T { %T item state set %I ~edit } $T notify bind $T { %T item element configure %I %C %E -text %t } $T notify bind $T { %T item state set %I ~edit } # # Create items and assign styles # set scriptDir { set item [$T item create -open no] $T item style set $item C0 STYLE $T item text $item C0 [file tail $file] if {$::shellicon} { # The shellicon extension fails randomly (by putting GDB into the # background!?) if the filename is not valid. MSDN says "relative # paths are valid" but perhaps that is misinformation. if {$file eq ".."} { set file [file dirname $::Dir] } $T item element configure $item C0 \ elemImg -path $file } $T item lastchild root $item } set scriptFile { set item [$T item create -open no] $T item style set $item C0 STYLE switch [file extension $file] { .dll { set img small-dll } .exe { set img small-exe } .txt { set img small-txt } default { set img small-file } } set type [string toupper [file extension $file]] if {$type ne ""} { set type "[string range $type 1 end] " } append type "File" if {$::shellicon} { $T item element configure $item C0 \ elemImg -path $file + \ elemTxt -text [file tail $file] } else { $T item element configure $item C0 \ elemImg -image [list ${img}Sel {selected} $img {}] + \ elemTxt -text [file tail $file] } $T item lastchild root $item } DemoExplorerAux $scriptDir $scriptFile $T activate [$T item firstchild root] bindtags $T [list $T DemoExplorer TreeCtrlFileList TreeCtrl [winfo toplevel $T] all] return } proc ExplorerDoubleButton1 {w x y} { global Explorer global Dir set id [$w identify $x $y] if {[TreeCtrl::IsSensitive $w $x $y]} { set item [lindex $id 1] set column [lindex $id 3] if {[$w item tag expr $item directory]} { set name [$w item text $item $column] if {$name eq ".."} { set Dir [file dirname $Dir] } else { set Dir [file join $Dir $name] } $w item delete all DemoExplorerAux $Explorer(scriptDir) $Explorer(scriptFile) $w activate "root firstchild" $w xview moveto 0.0 $w yview moveto 0.0 } } return } tktreectrl-2.2.8/demos/firefox.tcl0000700000175600010010000003614510536414402015371 0ustar TimNone# RCS: @(#) $Id: firefox.tcl,v 1.20 2006/12/07 03:53:05 treectrl Exp $ proc DemoFirefoxPrivacy {} { global FirefoxPrivacy set T [DemoList] # # Configure the treectrl widget # $T configure -showroot no -showbuttons yes -showlines no \ -selectmode extended -xscrollincrement 20 -showheader yes if {$::clip} { $T configure -xscrollincrement 4 -yscrollincrement 4 } else { # Hide the borders because child windows appear on top of them $T configure -borderwidth 0 -highlightthickness 0 } # # Create columns # # Create 2 new images for the button sort arrow if {[lsearch -exact [image names] arrow-up] == -1} { set color #ACA899 ; # WinXP arrow color set img arrow-down image create photo $img $img put [list [string repeat "$color " 9]] -to 0 0 $img put [list [string repeat "$color " 7]] -to 1 1 $img put [list [string repeat "$color " 5]] -to 2 2 $img put [list [string repeat "$color " 3]] -to 3 3 $img put [list [string repeat "$color " 1]] -to 4 4 set img arrow-up image create photo $img $img put [list [string repeat "$color " 1]] -to 4 0 $img put [list [string repeat "$color " 3]] -to 3 1 $img put [list [string repeat "$color " 5]] -to 2 2 $img put [list [string repeat "$color " 7]] -to 1 3 $img put [list [string repeat "$color " 9]] -to 0 4 } $T column create -expand yes -arrowimage {arrow-down !up arrow-up {}} \ -arrow up -arrowpadx {10 2} -textlines 0 -tags C0 \ -text "This is a multi-line column title\nwith an image for the arrow" $T configure -treecolumn C0 # This binding toggles the sort arrow $T notify bind $T { if {[%T column cget %C -arrow] eq "up"} { %T column configure %C -arrow down } else { %T column configure %C -arrow up } } # # Create elements # $T element create eWindow window if {$::clip} { $T element configure eWindow -clip yes } $T element create eText1 text -font [list DemoFontBold] $T element create eRectTop rect -outline black -fill #FFFFCC \ -outlinewidth 1 -open s $T element create eRectBottom rect -outline black -fill #FFFFCC \ -outlinewidth 1 -open n # Destroy the window when the element is deleted. Could also bind to the # event. $T element configure eWindow -destroy yes # # Create styles using the elements # set S [$T style create styCategory -orient horizontal] $T style elements $S {eRectTop eText1 eWindow} $T style layout $S eRectTop -detach yes -indent no -iexpand xy -draw {yes open no {}} # note: using -iexpand x so clicking in the text works better $T style layout $S eText1 -expand ns -iexpand x -sticky w $T style layout $S eWindow -expand ns -padx 10 -pady 6 set S [$T style create styFrame -orient horizontal] $T style elements $S {eRectBottom eWindow} $T style layout $S eRectBottom -detach yes -indent no -iexpand xy $T style layout $S eWindow -iexpand x -squeeze x -padx {0 2} -pady {0 8} # # Create items and assign styles # foreach category { "History" "Saved Form Information" "Saved Passwords" "Download Manager History" "Cookies" "Cache"} { set I [$T item create -button yes] $T item style set $I C0 styCategory $T item element configure $I C0 eText1 -text $category if {$::clip} { set wClip [frame $T.clip$I -background red] set b [$::buttonCmd $wClip.b$I -text "Clear" -command "" -width 11] $T item element configure $I C0 eWindow -window $wClip } else { set b [$::buttonCmd $T.b$I -text "Clear" -command "" -width 11] $T item element configure $I C0 eWindow -window $b } $T item lastchild root $I } set bg #FFFFCC set textBg $bg if {$::tile} { ttk::style configure DemoCheckbutton -background $bg ttk::style layout DemoCheckbutton [ttk::style layout TCheckbutton] } # History set I [$T item create] $T item style set $I C0 styFrame if {$::clip} { set wClip [frame $T.clip$I -background red] set f [frame $wClip.f$I -borderwidth 0 -background $bg] } else { set f [frame $T.f$I -borderwidth 0 -background $bg] } label $f.l1 -background $bg -text "Remember visited pages for the last" $::entryCmd $f.e1 -width 6 $f.e1 insert end 20 label $f.l2 -background $bg -text "days" -background $bg pack $f.l1 -side left pack $f.e1 -side left -padx 8 pack $f.l2 -side left if {$::clip} { $T item element configure $I C0 eWindow -window $wClip } else { $T item element configure $I C0 eWindow -window $f } $T item lastchild "root child 0" $I # Saved Form Information set I [$T item create] $T item style set $I C0 styFrame if {$::clip} { set wClip [frame $T.clip$I -background red] set f [frame $wClip.f$I -borderwidth 0 -background $bg] } else { set f [frame $T.f$I -borderwidth 0 -background $bg] } text $f.t1 -background $textBg -borderwidth 0 -highlightthickness 0 \ -width 10 -height 1 -wrap word -cursor "" $f.t1 insert end "Information entered in web page forms and the Search\ Bar is saved to make filling out forms and searching faster." bindtags $f.t1 TextWrapBindTag if {$::tile} { $::checkbuttonCmd $f.cb1 -text "Save information I enter in web page forms and the Search Bar" \ -variable ::cbvar($f.cb1) -style DemoCheckbutton } else { checkbutton $f.cb1 -background $bg -highlightthickness 0 -text "Save\ information I enter in web page forms and the Search Bar" \ -variable ::cbvar($f.cb1) } set ::cbvar($f.cb1) 1 pack $f.t1 -side top -anchor w -fill x -padx {0 8} -pady {0 4} pack $f.cb1 -side top -anchor w if {$::clip} { $T item element configure $I C0 eWindow -window $wClip } else { $T item element configure $I C0 eWindow -window $f } $T item lastchild "root child 1" $I # Saved Passwords set I [$T item create] $T item style set $I C0 styFrame if {$::clip} { set wClip [frame $T.clip$I -background red] set f [frame $wClip.f$I -borderwidth 0 -background $bg] } else { set f [frame $T.f$I -borderwidth 0 -background $bg] } set fLeft [frame $f.fLeft -borderwidth 0 -background $bg] text $fLeft.t1 -background $textBg -borderwidth 0 -highlightthickness 0 \ -width 10 -height 1 -wrap word -cursor "" $fLeft.t1 insert end "Login information for web pages can be kept in the\ Password Manager so that you do not need to re-enter your login\ details every time you visit." bindtags $fLeft.t1 TextWrapBindTag if {$::tile} { $::checkbuttonCmd $fLeft.cb1 -text "Remember Passwords" \ -variable ::cbvar($fLeft.cb1) -style DemoCheckbutton } else { checkbutton $fLeft.cb1 -background $bg -highlightthickness 0 \ -text "Remember Passwords" -variable ::cbvar($fLeft.cb1) } set ::cbvar($fLeft.cb1) 1 pack $fLeft.t1 -side top -expand yes -fill x -pady {0 6} pack $fLeft.cb1 -side top -anchor w set fRight [frame $f.fRight -borderwidth 0 -background $bg] $::buttonCmd $fRight.b1 -text "View Saved Passwords" $::buttonCmd $fRight.b2 -text "Change Master Password..." pack $fRight.b1 -side top -expand yes -fill x pack $fRight.b2 -side top -expand yes -fill x -pady {8 0} pack $fLeft -side left -expand yes -fill x pack $fRight -side right -padx 12 -anchor n if {$::clip} { $T item element configure $I C0 eWindow -window $wClip } else { $T item element configure $I C0 eWindow -window $f } $T item lastchild "root child 2" $I # Download Manager History set I [$T item create] $T item style set $I C0 styFrame if {$::clip} { set wClip [frame $T.clip$I -background red] set f [frame $wClip.f$I -borderwidth 0 -background $bg] } else { set f [frame $T.f$I -borderwidth 0 -background $bg] } text $f.t1 -background $textBg -borderwidth 0 -highlightthickness 0 \ -width 10 -height 1 -wrap word -cursor "" $f.t1 insert end "The Download Manager keeps track of recently downloaded files." bindtags $f.t1 TextWrapBindTag set f1 [frame $f.f1 -borderwidth 0 -background $bg] label $f1.l1 -background $bg -text "Remove files from the Download Manager:" if {$::tile} { ttk::combobox $f1.mb1 -values { "Upon successful download" "When firefox exits" Manually } -state readonly -width [string length "Upon successful download"] $f1.mb1 current 2 } else { menubutton $f1.mb1 -indicatoron yes -menu $f1.mb1.m -text Manually \ -width [string length "Upon successful download"] -justify left set m [menu $f1.mb1.m -tearoff no] foreach label { "Upon successful download" "When firefox exits" Manually} { $m add command -label $label -command [list $f1.mb1 configure\ -text $label] } } pack $f1.l1 -side left pack $f1.mb1 -side left -padx {8 10} pack $f.t1 -side top -expand yes -fill x -padx {0 10} pack $f1 -side top -anchor w if {$::clip} { $T item element configure $I C0 eWindow -window $wClip } else { $T item element configure $I C0 eWindow -window $f } $T item lastchild "root child 3" $I # Cookies set I [$T item create] $T item style set $I C0 styFrame if {$::clip} { set wClip [frame $T.clip$I -background red] set f [frame $wClip.f$I -borderwidth 0 -background $bg] } else { set f [frame $T.f$I -borderwidth 0 -background $bg] } text $f.t1 -background $textBg -borderwidth 0 -highlightthickness 0 \ -width 10 -height 1 -wrap word -cursor "" $f.t1 insert end "Cookies are pieces of information stored by web pages\ on your computer. They are used to remember login information and\ other data." bindtags $f.t1 TextWrapBindTag set fLeft [frame $f.fLeft -borderwidth 0 -background $bg] if {$::tile} { $::checkbuttonCmd $fLeft.cb1 -style DemoCheckbutton \ -text "Allow sites to set cookies" -variable ::cbvar($fLeft.cb1) } else { checkbutton $fLeft.cb1 -background $bg -highlightthickness 0 \ -text "Allow sites to set cookies" -variable ::cbvar($fLeft.cb1) } set ::cbvar($fLeft.cb1) 1 if {$::tile} { $::checkbuttonCmd $fLeft.cb2 -style DemoCheckbutton \ -text "for the originating web site only" \ -variable ::cbar($fLeft.cb2) } else { checkbutton $fLeft.cb2 -background $bg -highlightthickness 0 \ -text "for the originating web site only" \ -variable ::cbar($fLeft.cb2) } set ::cbar($fLeft.cb2) 0 pack $fLeft.cb1 -side top -anchor w pack $fLeft.cb2 -side top -anchor w -padx {20 0} set fRight [frame $f.fRight -borderwidth 0 -background $bg] $::buttonCmd $fRight.b1 -text "Exceptions" $::buttonCmd $fRight.b2 -text "View Cookies" pack $fRight.b1 -side left -padx {0 10} pack $fRight.b2 -side left set f1 [frame $fLeft.f1 -borderwidth 0 -background $bg] label $f1.l1 -background $bg -text "Keep Cookies:" if {$::tile} { ttk::combobox $f1.mb1 -values { "until they expire" "until I close Firefox" "ask me every time" } -state readonly -width [string length "until I close Firefox"] $f1.mb1 current 0 } else { menubutton $f1.mb1 -indicatoron yes -menu $f1.mb1.m \ -text "until they expire" \ -width [string length "until I close Firefox"] -justify left set m [menu $f1.mb1.m -tearoff no] foreach label { "until they expire" "until I close Firefox" "ask me every time" } { $m add command -label $label -command [list $f1.mb1 configure -text $label] } } pack $f1.l1 -side left pack $f1.mb1 -side left -padx {8 0} pack $f1 -side top -anchor w pack $f.t1 -side top -expand yes -fill x -padx {0 10} -pady {0 8} pack $fLeft -side left -expand yes -fill x pack $fRight -side right -padx 14 -anchor n if {$::clip} { $T item element configure $I C0 eWindow -window $wClip } else { $T item element configure $I C0 eWindow -window $f } $T item lastchild "root child 4" $I # Cache set I [$T item create] $T item style set $I C0 styFrame if {$::clip} { set wClip [frame $T.clip$I -background red] set f [frame $wClip.f$I -borderwidth 0 -background $bg] } else { set f [frame $T.f$I -borderwidth 0 -background $bg] } text $f.t1 -background $textBg -borderwidth 0 -highlightthickness 0 \ -width 10 -height 1 -wrap word -cursor "" $f.t1 insert end "Pages you view are stored in the cache for quicker\ viewing later on." bindtags $f.t1 TextWrapBindTag set f1 [frame $f.f1 -borderwidth 0 -background $bg] label $f1.l1 -background $bg -text "Use up to:" $::entryCmd $f1.e1 -width 10 $f1.e1 insert end 50000 label $f1.l2 -background $bg -text "KB of disk space for the cache." \ -background $bg pack $f1.l1 -side left pack $f1.e1 -side left -padx 8 pack $f1.l2 -side left pack $f.t1 -side top -expand yes -fill x -padx {0 10} pack $f1 -side top -anchor w if {$::clip} { $T item element configure $I C0 eWindow -window $wClip } else { $T item element configure $I C0 eWindow -window $f } $T item lastchild "root child 5" $I # This binding configures the -height option of a Text widget to the # number of lines it is displaying bind TextWrapBindTag { scan [textlayout [%W cget -font] [%W get 1.0 "end - 1 chars"] \ -width %w] "%%d %%d" width height set height [expr {$height / [font metrics [%W cget -font] -linespace]}] if {$height != [%W cget -height]} { %W configure -height $height } } # This binding collapses all items before expanding a new one $T notify bind $T { %T item collapse all } $T item collapse all bind DemoFirefoxPrivacy { if {[lindex [%W identify %x %y] 0] eq "header"} { TreeCtrl::DoubleButton1 %W %x %y } else { DemoFirefoxPrivacyButton1 %W %x %y } break } bind DemoFirefoxPrivacy { DemoFirefoxPrivacyButton1 %W %x %y break } bind DemoFirefoxPrivacy { # noop } bind DemoFirefoxPrivacy { # noop } bind DemoFirefoxPrivacy { DemoFirefoxPrivacyMotion %W %x %y } bind DemoFirefoxPrivacy { DemoFirefoxPrivacyMotion %W %x %y } if {$::tile} { bind DemoFirefoxPrivacy <> { ttk::style configure DemoCheckbutton -background #FFFFCC ttk::style layout DemoCheckbutton [ttk::style layout TCheckbutton] } } set FirefoxPrivacy(prev) "" bindtags $T [list $T DemoFirefoxPrivacy TreeCtrl [winfo toplevel $T] all] return } proc DemoFirefoxPrivacyButton1 {w x y} { variable TreeCtrl::Priv focus $w set id [$w identify $x $y] set Priv(buttonMode) "" if {[lindex $id 0] eq "header"} { TreeCtrl::ButtonPress1 $w $x $y } elseif {[lindex $id 0] eq "item"} { set item [lindex $id 1] # click a button if {[llength $id] != 6} { TreeCtrl::ButtonPress1 $w $x $y return } if {[lindex $id 5] eq "eText1"} { $w item toggle $item DisplayStylesInItem $item } } return } proc DemoFirefoxPrivacyMotion {w x y} { global FirefoxPrivacy set id [$w identify $x $y] if {[lindex $id 0] eq "item"} { set item [lindex $id 1] if {[llength $id] == 6 && [lindex $id 5] eq "eText1"} { if {$item ne $FirefoxPrivacy(prev)} { $w configure -cursor hand2 set FirefoxPrivacy(prev) $item } return } } if {$FirefoxPrivacy(prev) ne ""} { $w configure -cursor "" set FirefoxPrivacy(prev) "" } return } tktreectrl-2.2.8/demos/help.tcl0000700000175600010010000002342410536414402014653 0ustar TimNone# RCS: @(#) $Id: help.tcl,v 1.22 2006/12/04 00:16:02 treectrl Exp $ # # Demo: Help contents # proc DemoHelpContents {} { global HelpContents set T [DemoList] set height [font metrics [$T cget -font] -linespace] if {$height < 18} { set height 18 } # # Configure the treectrl widget # $T configure -showroot no -showbuttons no -showlines no -itemheight $height \ -selectmode browse InitPics help-* # # Create columns # $T column create -text "Help Contents" -tags C0 $T configure -treecolumn C0 # # Create elements # # Define a new item state $T state define mouseover $T element create elemImgPage image -image help-page $T element create elemImgBook image -image {help-book-open {open} help-book-closed {}} $T element create elemTxt text -fill [list $::SystemHighlightText {selected focus} blue {mouseover}] \ -font [list DemoFontUnderline {mouseover}] $T element create elemRectSel rect -fill [list $::SystemHighlight {selected focus}] -showfocus yes # # Create styles using the elements # # book set S [$T style create styBook] $T style elements $S {elemRectSel elemImgBook elemTxt} $T style layout $S elemImgBook -padx {0 4} -expand ns $T style layout $S elemTxt -expand ns $T style layout $S elemRectSel -union [list elemTxt] -iexpand ns -ipadx 2 # page set S [$T style create styPage] $T style elements $S {elemRectSel elemImgPage elemTxt} $T style layout $S elemImgPage -padx {0 4} -expand ns $T style layout $S elemTxt -expand ns $T style layout $S elemRectSel -union [list elemTxt] -iexpand ns -ipadx 2 # # Create items and assign styles # set parentList [list root {} {} {} {} {} {}] set parent root foreach {depth style text} { 0 styPage "Welcome to Help" 0 styBook "Introducing Windows 98" 1 styBook "How to Use Help" 2 styPage "Find a topic" 2 styPage "Get more out of help" 1 styBook "Register Your Software" 2 styPage "Registering Windows 98 online" 1 styBook "What's New in Windows 98" 2 styPage "Innovative, easy-to-use features" 2 styPage "Improved reliability" 2 styPage "A faster operating system" 2 styPage "True Web integration" 2 styPage "More entertaining and fun" 1 styBook "If You're New to Windows 98" 2 styBook "Tips for Macintosh Users" 3 styPage "Why does the mouse have two buttons?" } { set item [$T item create -open no] $T item style set $item C0 $style $T item element configure $item C0 elemTxt -text $text $T item lastchild [lindex $parentList $depth] $item incr depth set parentList [lreplace $parentList $depth $depth $item] } bind DemoHelpContents { if {[lindex [%W identify %x %y] 0] eq "header"} { TreeCtrl::DoubleButton1 %W %x %y } else { HelpButton1 %W %x %y } break } bind DemoHelpContents { HelpButton1 %W %x %y break } bind DemoHelpContents { # noop } bind DemoHelpContents { # noop } bind DemoHelpContents { HelpMotion %W %x %y } bind DemoHelpContents { HelpMotion %W %x %y } bind DemoHelpContents { if {[%W selection count] == 1} { %W item toggle [%W selection get 0] } break } set HelpContents(prev) "" bindtags $T [list $T DemoHelpContents TreeCtrl [winfo toplevel $T] all] return } # This is an alternate implementation that does not define a new item state # to change the appearance of the item under the cursor. proc DemoHelpContents_2 {} { global HelpContents set T [DemoList] set height [font metrics [$T cget -font] -linespace] if {$height < 18} { set height 18 } # # Configure the treectrl widget # $T configure -showroot no -showbuttons no -showlines no -itemheight $height \ -selectmode browse InitPics help-* # # Create columns # $T column create -text "Help Contents" # # Create elements # $T element create elemImgPage image -image help-page $T element create elemImgBook image -image {help-book-open {open} help-book-closed {}} $T element create elemTxt text -fill [list $::SystemHighlightText {selected focus}] $T element create elemRectSel rect -fill [list $::SystemHighlight {selected focus}] -showfocus yes $T element create elemTxtOver text -fill [list $::SystemHighlightText {selected focus} blue {}] \ -font "[$T cget -font] underline" # # Create styles using the elements # # book set S [$T style create styBook] $T style elements $S {elemRectSel elemImgBook elemTxt} $T style layout $S elemImgBook -padx {0 4} -expand ns $T style layout $S elemTxt -expand ns $T style layout $S elemRectSel -union [list elemTxt] -iexpand ns -ipadx 2 # page set S [$T style create styPage] $T style elements $S {elemRectSel elemImgPage elemTxt} $T style layout $S elemImgPage -padx {0 4} -expand ns $T style layout $S elemTxt -expand ns $T style layout $S elemRectSel -union [list elemTxt] -iexpand ns -ipadx 2 # book (focus) set S [$T style create styBook.f] $T style elements $S {elemRectSel elemImgBook elemTxtOver} $T style layout $S elemImgBook -padx {0 4} -expand ns $T style layout $S elemTxtOver -expand ns $T style layout $S elemRectSel -union [list elemTxtOver] -iexpand ns -ipadx {1 2} # page (focus) set S [$T style create styPage.f] $T style elements $S {elemRectSel elemImgPage elemTxtOver} $T style layout $S elemImgPage -padx {0 4} -expand ns $T style layout $S elemTxtOver -expand ns $T style layout $S elemRectSel -union [list elemTxtOver] -iexpand ns -ipadx {1 2} # # Create items and assign styles # set parentList [list root {} {} {} {} {} {}] set parent root foreach {depth style text} { 0 styPage "Welcome to Help" 0 styBook "Introducing Windows 98" 1 styBook "How to Use Help" 2 styPage "Find a topic" 2 styPage "Get more out of help" 1 styBook "Register Your Software" 2 styPage "Registering Windows 98 online" 1 styBook "What's New in Windows 98" 2 styPage "Innovative, easy-to-use features" 2 styPage "Improved reliability" 2 styPage "A faster operating system" 2 styPage "True Web integration" 2 styPage "More entertaining and fun" 1 styBook "If You're New to Windows 98" 2 styBook "Tips for Macintosh Users" 3 styPage "Why does the mouse have two buttons?" } { set item [$T item create -open no] $T item style set $item 0 $style $T item element configure $item 0 elemTxt -text $text $T item lastchild [lindex $parentList $depth] $item incr depth set parentList [lreplace $parentList $depth $depth $item] } bind DemoHelpContents { if {[lindex [%W identify %x %y] 0] eq "header"} { TreeCtrl::DoubleButton1 %W %x %y } else { HelpButton1 %W %x %y } break } bind DemoHelpContents { HelpButton1 %W %x %y break } bind DemoHelpContents { # noop } bind DemoHelpContents { # noop } bind DemoHelpContents { HelpMotion_2 %W %x %y } bind DemoHelpContents { HelpMotion_2 %W %x %y } bind DemoHelpContents { if {[%W selection count] == 1} { %W item toggle [%W selection get 0] } break } set HelpContents(prev) "" bindtags $T [list $T DemoHelpContents TreeCtrl [winfo toplevel $T] all] return } proc HelpButton1 {w x y} { variable TreeCtrl::Priv focus $w set id [$w identify $x $y] set Priv(buttonMode) "" if {[lindex $id 0] eq "header"} { TreeCtrl::ButtonPress1 $w $x $y } elseif {[lindex $id 0] eq "item"} { set item [lindex $id 1] # didn't click an element if {[llength $id] != 6} return if {[$w selection includes $item]} { $w item toggle $item return } if {[$w selection count]} { set item2 [$w selection get 0] $w item collapse $item2 foreach item2 [$w item ancestors $item2] { if {[$w item compare $item != $item2]} { $w item collapse $item2 } } } $w activate $item $w item expand [list $item ancestors] $w item toggle $item $w selection modify $item all } return } proc HelpMotion {w x y} { global HelpContents set id [$w identify $x $y] if {$id eq ""} { } elseif {[lindex $id 0] eq "header"} { } elseif {[lindex $id 0] eq "item"} { set item [lindex $id 1] if {[llength $id] == 6} { if {$item ne $HelpContents(prev)} { if {$HelpContents(prev) ne ""} { $w item state set $HelpContents(prev) !mouseover } $w item state set $item mouseover $w configure -cursor hand2 set HelpContents(prev) $item } return } } if {$HelpContents(prev) ne ""} { $w item state set $HelpContents(prev) !mouseover $w configure -cursor "" set HelpContents(prev) "" } return } # Alternate implementation that does not rely on run-time states proc HelpMotion_2 {w x y} { variable TreeCtrl::Priv global HelpContents set id [$w identify $x $y] if {[lindex $id 0] eq "header"} { } elseif {$id ne ""} { set item [lindex $id 1] if {[llength $id] == 6} { if {$item ne $HelpContents(prev)} { if {$HelpContents(prev) ne ""} { set style [$w item style set $HelpContents(prev) 0] set style [string trim $style .f] $w item style map $HelpContents(prev) 0 $style {elemTxtOver elemTxt} } set style [$w item style set $item 0] $w item style map $item 0 $style.f {elemTxt elemTxtOver} set HelpContents(prev) $item } return } } if {$HelpContents(prev) ne ""} { set style [$w item style set $HelpContents(prev) 0] set style [string trim $style .f] $w item style map $HelpContents(prev) 0 $style {elemTxtOver elemTxt} set HelpContents(prev) "" } return } tktreectrl-2.2.8/demos/imovie.tcl0000700000175600010010000000711210536414402015207 0ustar TimNone# RCS: @(#) $Id: imovie.tcl,v 1.16 2006/11/30 02:41:38 treectrl Exp $ # # Demo: iMovie # proc DemoIMovie {} { set T [DemoList] # # Configure the treectrl widget # $T configure -showroot no -showbuttons no -showlines no \ -selectmode browse -orient horizontal -wrap window \ -showheader no -background #dcdcdc # # Create columns # $T column create -tags C0 InitPics imovie-* switch -- $::thisPlatform { macintosh - macosx { set font1 {Geneva 9} set font2 {Geneva 10} } unix { set font1 {Helvetica 12} set font2 {Helvetica 14} } default { set font1 {Helvetica 8} set font2 {Helvetica 10} } } # # Create elements # $T element create elemTime text -font [list $font1] $T element create elemName text -font [list $font2] -lines 1 -width 80 $T element create elemRect rect -fill {#ffdc5a {selected} white {}} \ -outline #827878 -outlinewidth 1 $T element create elemImg image $T element create elemShadow rect -outline gray -outlinewidth 1 -open wn # # Create styles using the elements # set S [$T style create STYLE -orient vertical] $T style elements $S {elemShadow elemRect elemTime elemImg elemName} $T style layout $S elemShadow -detach yes -padx {1 2} -pady {1 2} -iexpand xy $T style layout $S elemTime -padx {2 0} $T style layout $S elemImg -pady {0 1} $T style layout $S elemName -expand we -ipady {0 2} -padx {0 3} -squeeze x $T style layout $S elemRect -union {elemTime elemImg elemName} \ -ipadx 6 -padx {0 3} -pady {0 3} # Set default item style $T column configure C0 -itemstyle $S # # Create items and assign styles # for {set i 0} {$i < 5} {incr i} { foreach {time name image} { 15:20 "Clip 1" imovie-01 19:18 "Clip 2" imovie-02 07:20 "Clip 3" imovie-03 07:20 "Clip 4" imovie-04 07:20 "Clip 5" imovie-05 07:20 "Clip 6" imovie-06 07:20 "Clip 7" imovie-07 } { set I [$T item create] # $T item style set $I C0 $S $T item element configure $I C0 \ elemTime -text $time + \ elemImg -image $image + \ elemName -text $name $T item lastchild root $I } } $T notify bind $T { %T item element configure %I %C %E -text %t } bind DemoIMovie { iMovieButton1 %W %x %y } bindtags $T [list $T DemoIMovie TreeCtrl [winfo toplevel $T] all] return } proc iMovieButton1 {T x y} { focus $T set id [$T identify $x $y] # Click outside any item if {$id eq ""} { # Click in header } elseif {[lindex $id 0] eq "header"} { ::TreeCtrl::ButtonPress1 $T $x $y # Click in item } elseif {[lindex $id 0] eq "item"} { ::TreeCtrl::ButtonPress1 $T $x $y update lassign $id where item arg1 arg2 arg3 arg4 switch $arg1 { column { set I [lindex $id 1] if {[llength $id] == 6} { set E [lindex $id end] if {$E eq "elemName"} { set exists [winfo exists $T.entry] ::TreeCtrl::EntryOpen $T $I C0 $E if {!$exists} { $T.entry configure -borderwidth 0 -justify center \ -background #ffdc5a scan [$T item bbox $I C0 $E] "%d %d %d %d" x1 y1 x2 y2 place $T.entry -y [expr {$y1 - 1}] } $T.entry selection clear scan [$T item bbox $I] "%d %d %d %d" x1 y1 x2 y2 set left [expr {$x1 + 6 - 1}] set right [expr {$x2 - 3 - 6 + 1}] place $T.entry -x $left -width [expr {$right - $left}] $T.entry icursor [$T.entry index @[expr {$x - ($x1 + 1)}]] # Disable mouse tracking unset ::TreeCtrl::Priv(buttonMode) } } } } } return -code break } tktreectrl-2.2.8/demos/layout.tcl0000700000175600010010000001010110536414402015224 0ustar TimNone# RCS: @(#) $Id: layout.tcl,v 1.15 2006/12/07 03:54:06 treectrl Exp $ # # Demo: Layout # proc DemoLayout {} { set T [DemoList] # # Configure the treectrl widget # $T configure -showroot no -showrootbutton yes -showbuttons yes \ -showlines $::ShowLines -itemheight 0 -selectmode browse # # Create columns # $T column create -text Layout -itemjustify left -justify center -tags C0 $T configure -treecolumn C0 # # Create elements # $T element create e1 rect -width 30 -height 30 -fill gray20 $T element create e2 rect -width 30 -height 30 -fill gray40 \ -outline blue -outlinewidth 3 $T element create e3 rect -fill gray60 $T element create e4 rect -fill [list $::SystemHighlight {selected focus} gray80 {}] \ -showfocus yes $T element create e5 rect -fill {"sky blue"} -width 20 -height 20 $T element create e6 rect -fill {"sea green"} -width 30 -height 16 $T element create e7 rect -fill {"sky blue"} -width 30 -height 16 $T element create e8 rect -fill gray70 -height 1 # # Create styles using the elements # set S [$T style create s1] $T style elements $S {e4 e3 e1 e2 e5 e6 e7} $T style layout $S e1 -padx {28 4} -pady 4 $T style layout $S e2 -expand es -padx {0 38} $T style layout $S e3 -union [list e1 e2] -ipadx 4 -ipady 4 -pady 2 $T style layout $S e4 -detach yes -iexpand xy $T style layout $S e5 -detach yes -padx {2 0} -pady 2 -iexpand y $T style layout $S e6 -detach yes -expand ws -padx {0 2} -pady {2 0} $T style layout $S e7 -detach yes -expand wn -padx {0 2} -pady {0 2} # # Create items and assign styles # set I [$T item create -button yes] $T item style set $I C0 $S $T item lastchild root $I set parent $I set I [$T item create] $T item style set $I C0 $S $T item lastchild $parent $I ### set S [$T style create s2] $T style elements $S {e4 e3 e1} $T style layout $S e1 -padx 8 -pady 8 -iexpand x $T style layout $S e3 -union e1 -ipadx {20 4} -ipady {4 12} $T style layout $S e4 -detach yes -iexpand xy set I [$T item create -button yes] $T item style set $I C0 $S $T item lastchild root $I set I2 [$T item create] $T item style set $I2 C0 $S $T item lastchild $I $I2 ### set S [$T style create s3] $T style elements $S {e4 e3 e1 e5 e6} $T style layout $S e4 -union {e1 e6} -ipadx 8 -ipady {8 0} $T style layout $S e3 -union {e1 e5} -ipadx 4 -ipady 4 $T style layout $S e5 -height 40 set I [$T item create -button yes] $T item style set $I C0 $S $T item lastchild root $I set I2 [$T item create] $T item style set $I2 C0 $S $T item lastchild $I $I2 ### $T element create eb border -background $::SystemButtonFace \ -relief {sunken {selected} raised {}} -thickness 2 -filled yes $T element create et text set text "Here is a text element surrounded by a border element.\nResize the column to watch me wrap." set S [$T style create s4] $T style elements $S {eb et} $T style layout $S eb -union et -ipadx 2 -ipady 2 $T style layout $S et -squeeze x set I [$T item create -button yes] $T item style set $I C0 $S $T item text $I C0 $text $T item lastchild root $I set parent $I set I [$T item create] $T item style set $I C0 $S $T item text $I C0 $text $T item lastchild $parent $I ### set styleNum 5 foreach {orient expandList} {horizontal {s ns n} vertical {e we w}} { foreach expand $expandList { set S [$T style create s$styleNum -orient $orient] $T style elements $S {e4 e8 e3 e2 e5 e6} $T style layout $S e4 -detach yes -iexpand xy $T style layout $S e8 -detach yes -expand n -iexpand x $T style layout $S e3 -union {e2 e5 e6} -ipadx 5 -ipady 5 $T style layout $S e2 -expand $expand $T style layout $S e5 -expand $expand -visible {no !selected} $T style layout $S e6 -expand $expand incr styleNum set I [$T item create] $T item style set $I C0 $S $T item lastchild root $I } } return } tktreectrl-2.2.8/demos/mailwasher.tcl0000700000175600010010000001463610536414402016064 0ustar TimNone# RCS: @(#) $Id: mailwasher.tcl,v 1.17 2006/11/30 02:41:38 treectrl Exp $ # # Demo: MailWasher # proc DemoMailWasher {} { set T [DemoList] InitPics *checked set height [font metrics [$T cget -font] -linespace] if {$height < 18} { set height 18 } # # Configure the treectrl widget # $T configure -showroot no -showrootbutton no -showbuttons no \ -showlines no -itemheight $height -selectmode browse \ -xscrollincrement 20 # # Create columns # set pad 4 $T column create -text Delete -textpadx $pad -justify center -tags delete $T column create -text Bounce -textpadx $pad -justify center -tags bounce $T column create -text Status -width 80 -textpadx $pad -tags status $T column create -text Size -width 40 -textpadx $pad -justify right -tags size $T column create -text From -width 140 -textpadx $pad -tags from $T column create -text Subject -width 240 -textpadx $pad -tags subject $T column create -text Received -textpadx $pad -arrow up -tags received $T column create -text Attachments -textpadx $pad -tags attachments $T state define CHECK # # Create elements # $T element create border rect -open nw -outline gray -outlinewidth 1 \ -fill [list $::SystemHighlight {selected}] $T element create imgCheck image -image {checked CHECK unchecked {}} $T element create txtAny text \ -fill [list $::SystemHighlightText {selected}] -lines 1 $T element create txtNone text -text "none" \ -fill [list $::SystemHighlightText {selected}] -lines 1 $T element create txtYes text -text "yes" \ -fill [list $::SystemHighlightText {selected}] -lines 1 $T element create txtNormal text -text "Normal" \ -fill [list $::SystemHighlightText {selected} #006800 {}] -lines 1 $T element create txtPossSpam text -text "Possible Spam" \ -fill [list $::SystemHighlightText {selected} #787800 {}] -lines 1 $T element create txtProbSpam text -text "Probably Spam" \ -fill [list $::SystemHighlightText {selected} #FF9000 {}] -lines 1 $T element create txtBlacklist text -text "Blacklisted" \ -fill [list $::SystemHighlightText {selected} #FF5800 {}] -lines 1 # # Create styles using the elements # set S [$T style create styCheck] $T style elements $S [list border imgCheck] $T style layout $S border -detach yes -iexpand xy $T style layout $S imgCheck -expand news set pad 4 foreach name {Any None Yes Normal PossSpam ProbSpam Blacklist} { set S [$T style create sty$name] $T style elements $S [list border txt$name] $T style layout $S border -detach yes -iexpand xy $T style layout $S txt$name -padx $pad -squeeze x -expand ns } # # Create items and assign styles # for {set i 0} {$i < 1} {incr i} { foreach {from subject} { baldy@spammer.com "Your hair is thinning" flat@spammer.com "Your breasts are too small" tiny@spammer.com "Your penis is too small" dumbass@spammer.com "You are not very smart" bankrobber@spammer.com "You need more money" loser@spammer.com "You need better friends" gossip@spammer.com "Find out what your coworkers think about you" whoami@spammer.com "Find out what you think about yourself" downsized@spammer.com "You need a better job" poorhouse@spammer.com "Your mortgage is a joke" spam4ever@spammer.com "You need more spam" } { set item [$T item create] set status [lindex [list styNormal styPossSpam styProbSpam styBlacklist] [expr int(rand() * 4)]] set delete [expr int(rand() * 2)] set bounce [expr int(rand() * 2)] set attachments [lindex [list styNone styYes] [expr int(rand() * 2)]] $T item style set $item delete styCheck bounce styCheck \ status $status size styAny \ from styAny subject styAny received styAny \ attachments $attachments if {$delete} { $T item state forcolumn $item delete CHECK } if {$bounce} { $T item state forcolumn $item bounce CHECK } set bytes [expr {512 + int(rand() * 1024 * 12)}] set size [expr {$bytes / 1024 + 1}]KB set seconds [expr {[clock seconds] - int(rand() * 100000)}] set received [clock format $seconds -format "%d/%m/%y %I:%M %p"] $T item text $item size $size from $from subject $subject received $received $T item lastchild root $item } } if 0 { $T notify bind MailWasher { %T item style set %I %C styOff } $T notify bind MailWasher { %T item style set %I %C styOn } } set ::SortColumn received $T notify bind $T { if {[%T column compare %C == $SortColumn]} { if {[%T column cget $SortColumn -arrow] eq "down"} { set order -increasing set arrow up } else { set order -decreasing set arrow down } } else { if {[%T column cget $SortColumn -arrow] eq "down"} { set order -decreasing set arrow down } else { set order -increasing set arrow up } %T column configure $SortColumn -arrow none set SortColumn %C } %T column configure %C -arrow $arrow switch [%T column cget %C -tags] { bounce - delete { %T item sort root $order -column %C -command [list CompareOnOff %T %C] -column subject -dictionary } status { %T item sort root $order -column %C -dictionary } from { %T item sort root $order -column %C -dictionary -column subject -dictionary } subject { %T item sort root $order -column %C -dictionary } size { %T item sort root $order -column %C -dictionary -column subject -dictionary } received { %T item sort root $order -column %C -dictionary -column subject -dictionary } attachments { %T item sort root $order -column %C -dictionary -column subject -dictionary } } } bind DemoMailWasher { set id [%W identify %x %y] if {$id eq ""} { } elseif {[lindex $id 0] eq "header"} { } else { lassign $id what item where arg1 arg2 arg3 if {$where eq "column"} { if {[%W column tag expr $arg1 {delete || bounce}]} { %W item state forcolumn $item $arg1 ~CHECK # return -code break } } } } bindtags $T [list $T DemoMailWasher TreeCtrl [winfo toplevel $T] all] return } proc CompareOnOff {T C item1 item2} { set s1 [$T item state forcolumn $item1 $C] set s2 [$T item state forcolumn $item2 $C] if {$s1 eq $s2} { return 0 } if {[lsearch -exact $s1 CHECK] == -1} { return -1 } return 1 } tktreectrl-2.2.8/demos/mycomputer.tcl0000700000175600010010000000750510536414402016131 0ustar TimNone# RCS: @(#) $Id: mycomputer.tcl,v 1.6 2006/12/04 00:16:02 treectrl Exp $ proc DemoMyComputer {} { set T [DemoList] set font [.menubar cget -font] if {[lsearch -exact [font names] DemoMyComputerHeaderFont] == -1} { array set fontInfo [font actual $font] set fontInfo(-weight) bold eval font create DemoMyComputerHeaderFont [array get fontInfo] } # # Configure the treectrl widget # $T configure -showroot no -showbuttons no -showlines no \ -selectmode browse -xscrollincrement 20 \ -font $font # # Create columns # $T column create -text Name -tags name -width 200 $T column create -text Type -tags type -width 120 $T column create -text "Total Size" -tags size -justify right -width 100 \ -arrowside left -arrowgravity right $T column create -text "Free Space" -tags free -justify right -width 100 $T column create -text Comments -tags comment -width 120 # # Create elements # $T element create txtHeader text -font [list DemoMyComputerHeaderFont] $T element create txtName text -fill [list $::SystemHighlightText {selected focus}] \ -lines 1 $T element create txtOther text -lines 1 $T element create elemRectSel rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] -showfocus yes $T element create rectDivider rect -fill blue -height 1 -width 250 # # Create styles using the elements # # header set S [$T style create styHeader -orient vertical] $T style elements $S {txtHeader rectDivider} $T style layout $S txtHeader -padx 10 -pady {10 0} -expand ns $T style layout $S rectDivider -pady {2 8} # name set S [$T style create styName -orient horizontal] $T style elements $S {elemRectSel txtName} $T style layout $S txtName -padx {16 0} -squeeze x -expand ns $T style layout $S elemRectSel -union [list txtName] -ipadx 2 -pady 1 -iexpand ns # other text set S [$T style create styOther] $T style elements $S txtOther $T style layout $S txtOther -padx 6 -squeeze x -expand ns # List of lists: {column style element ...} specifying text elements # the user can edit TreeCtrl::SetEditable $T { } # List of lists: {column style element ...} specifying elements # the user can click on or select with the selection rectangle TreeCtrl::SetSensitive $T { {name styName txtName} } # List of lists: {column style element ...} specifying elements # added to the drag image when dragging selected items TreeCtrl::SetDragImage $T { {name styName txtName} } # # Create items and assign styles # foreach {name type size free comment} { "Files Stored on This Computer" "" "" "" "" "Shared Documents" "File Folder" "" "" "" "Tim's Documents" "File Folder" "" "" "" "Hard Disk Drives" "" "" "" "" "Local Disk (C:)" "Local Disk" "55.8 GB" "1.84 GB" "" "Devices with Removable Storage" "" "" "" "" "3.5 Floppy (A:)" "3.5-Inch Floppy Disk" "" "" "" "DVD Drive (D:)" "CD Drive" "" "" "" "CD-RW Drive (E:)" "CD Drive" "" "" "" "Other" "" "" "" "" "My Logitech Pictures" "System Folder" "" "" "" "Scanners and Cameras" "" "" "" "" "Logitech QuickCam Messenger" "Digital camera" "" "" "" } { set I [$T item create] if {$type eq ""} { $T item style set $I first styHeader $T item span $I first [$T column count] # The headers are disabled so they can't be selected and # keyboard navigation skips over them. $T item enabled $I false $T item text $I name $name } else { $T item style set $I name styName type styOther $T item text $I name $name type $type if {$size ne ""} { $T item style set $I size styOther free styOther $T item text $I size $size free $free } } $T item lastchild root $I } # bindtags $T [list $T TreeCtrlFileList TreeCtrl [winfo toplevel $T] all] } tktreectrl-2.2.8/demos/outlook-folders.tcl0000700000175600010010000001033510536414402017050 0ustar TimNone# RCS: @(#) $Id: outlook-folders.tcl,v 1.14 2006/12/04 00:16:02 treectrl Exp $ # # Demo: Outlook Express folder list # proc DemoOutlookFolders {} { InitPics outlook-* set T [DemoList] set height [font metrics [$T cget -font] -linespace] if {$height < 18} { set height 18 } # # Configure the treectrl widget # $T configure -itemheight $height -selectmode browse \ -showroot yes -showrootbutton no -showbuttons yes -showlines $::ShowLines # # Create columns # $T column create -text Folders -tags C0 $T configure -treecolumn C0 # # Create elements # $T element create elemImgAny image $T element create elemTxtRead text -fill [list $::SystemHighlightText {selected focus}] \ -lines 1 $T element create elemTxtUnread text -fill [list $::SystemHighlightText {selected focus}] \ -font [list DemoFontBold] -lines 1 $T element create elemTxtCount text -fill blue $T element create elemImgFolder image -image outlook-folder $T element create elemRectSel rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] \ -showfocus yes # # Create styles using the elements # # image + text set S [$T style create styAnyRead] $T style elements $S {elemRectSel elemImgAny elemTxtRead} $T style layout $S elemImgAny -expand ns $T style layout $S elemTxtRead -padx {4 0} -expand ns -squeeze x $T style layout $S elemRectSel -union [list elemTxtRead] -iexpand ns -ipadx 2 # image + text + text set S [$T style create styAnyUnread] $T style elements $S {elemRectSel elemImgAny elemTxtUnread elemTxtCount} $T style layout $S elemImgAny -expand ns $T style layout $S elemTxtUnread -padx 4 -expand ns -squeeze x $T style layout $S elemTxtCount -expand ns $T style layout $S elemRectSel -union [list elemTxtUnread] -iexpand ns -ipadx 2 # folder + text set S [$T style create styFolderRead] $T style elements $S {elemRectSel elemImgFolder elemTxtRead} $T style layout $S elemImgFolder -expand ns $T style layout $S elemTxtRead -padx {4 0} -expand ns -squeeze x $T style layout $S elemRectSel -union [list elemTxtRead] -iexpand ns -ipadx 2 # folder + text + text set S [$T style create styFolderUnread] $T style elements $S {elemRectSel elemImgFolder elemTxtUnread elemTxtCount} $T style layout $S elemImgFolder -expand ns $T style layout $S elemTxtUnread -padx 4 -expand ns -squeeze x $T style layout $S elemTxtCount -expand ns $T style layout $S elemRectSel -union [list elemTxtUnread] -iexpand ns -ipadx 2 # # Create items and assign styles # $T item style set root C0 styAnyRead $T item element configure root C0 \ elemImgAny -image outlook-main + \ elemTxtRead -text "Outlook Express" set parentList [list root {} {} {} {} {} {}] set parent root foreach {depth img text button unread} { 0 local "Local Folders" yes 0 1 inbox Inbox no 5 1 outbox Outbox no 0 1 sent "Sent Items" no 0 1 deleted "Deleted Items" no 50 1 draft Drafts no 0 1 folder "Messages to Dad" no 0 1 folder "Messages to Sis" no 0 1 folder "Messages to Me" yes 5 2 folder "2001" no 0 2 folder "2000" no 0 2 folder "1999" no 0 0 server "news.gmane.org" yes 0 1 group "gmane.comp.lang.lua.general" no 498 } { set item [$T item create -button $button] if {[string equal $img folder]} { if {$unread} { $T item style set $item C0 styFolderUnread $T item element configure $item C0 \ elemTxtUnread -text $text + \ elemTxtCount -text "($unread)" } else { $T item style set $item C0 styFolderRead $T item element configure $item C0 elemTxtRead -text $text } } else { if {$unread} { $T item style set $item C0 styAnyUnread $T item element configure $item C0 \ elemImgAny -image outlook-$img + \ elemTxtUnread -text $text + \ elemTxtCount -text "($unread)" } else { $T item style set $item C0 styAnyRead $T item element configure $item C0 \ elemImgAny -image outlook-$img + \ elemTxtRead -text $text } } $T item lastchild [lindex $parentList $depth] $item incr depth set parentList [lreplace $parentList $depth $depth $item] } return } tktreectrl-2.2.8/demos/outlook-newgroup.tcl0000700000175600010010000003064010536414402017261 0ustar TimNone# RCS: @(#) $Id: outlook-newgroup.tcl,v 1.20 2006/12/04 00:16:02 treectrl Exp $ # # Demo: Outlook Express newsgroup messages # proc DemoOutlookNewsgroup {} { global Message InitPics outlook-* set T [DemoList] set height [font metrics [$T cget -font] -linespace] if {$height < 18} { set height 18 } # # Configure the treectrl widget # $T configure -itemheight $height -selectmode browse \ -showroot no -showrootbutton no -showbuttons yes -showlines no \ -xscrollincrement 20 # # Create columns # $T column create -image outlook-clip -tags clip $T column create -image outlook-arrow -tags arrow $T column create -image outlook-watch -tags watch $T column create -text Subject -width 250 -tags subject $T column create -text From -width 150 -tags from $T column create -text Sent -width 150 -tags sent $T column create -text Size -width 60 -justify right -tags size # Would be nice if I could specify a column -tag too # *blink* The amazing code Genie makes it so!!! $T configure -treecolumn subject # State for a read message $T state define read # State for a message with unread descendants $T state define unread # # Create elements # $T element create elemImg image -image { outlook-read-2Sel {selected read unread !open} outlook-read-2 {read unread !open} outlook-readSel {selected read} outlook-read {read} outlook-unreadSel {selected} outlook-unread {} } $T element create elemTxt text -fill [list $::SystemHighlightText {selected focus}] \ -font [list DemoFontBold {read unread !open} DemoFontBold {!read}] -lines 1 $T element create sel.e rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] -open e -showfocus yes $T element create sel.w rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] -open w -showfocus yes $T element create sel.we rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] -open we -showfocus yes # # Create styles using the elements # # Image + text set S [$T style create s1] $T style elements $S {sel.e elemImg elemTxt} $T style layout $S elemImg -expand ns $T style layout $S elemTxt -padx {2 6} -squeeze x -expand ns $T style layout $S sel.e -union [list elemTxt] -iexpand nes -ipadx {2 0} # Text set S [$T style create s2.we] $T style elements $S {sel.we elemTxt} $T style layout $S elemTxt -padx 6 -squeeze x -expand ns $T style layout $S sel.we -detach yes -iexpand xy # Text set S [$T style create s2.w] $T style elements $S {sel.w elemTxt} $T style layout $S elemTxt -padx 6 -squeeze x -expand ns $T style layout $S sel.w -detach yes -iexpand xy # Set default item styles $T column configure subject -itemstyle s1 $T column configure from -itemstyle s2.we $T column configure sent -itemstyle s2.we $T column configure size -itemstyle s2.w # # Create items and assign styles # set msgCnt 100 set thread 0 set Message(count,0) 0 set items [$T item id root] for {set i 1} {$i < $msgCnt} {incr i} { set itemi [$T item create] while 1 { set j [expr {int(rand() * $i)}] set itemj [lindex $items $j] if {$j == 0} break if {[$T depth $itemj] == 5} continue if {$Message(count,$Message(thread,$itemj)) == 15} continue break } $T item lastchild $itemj $itemi set Message(read,$itemi) [expr rand() * 2 > 1] if {$j == 0} { set Message(thread,$itemi) [incr thread] set Message(seconds,$itemi) [expr {[clock seconds] - int(rand() * 500000)}] set Message(seconds2,$itemi) $Message(seconds,$itemi) set Message(count,$thread) 1 } else { set Message(thread,$itemi) $Message(thread,$itemj) set Message(seconds,$itemi) [expr {$Message(seconds2,$itemj) + int(rand() * 10000)}] set Message(seconds2,$itemi) $Message(seconds,$itemi) set Message(seconds2,$itemj) $Message(seconds,$itemi) incr Message(count,$Message(thread,$itemj)) } lappend items $itemi } for {set i 1} {$i < $msgCnt} {incr i} { set itemi [lindex $items $i] set subject "This is thread number $Message(thread,$itemi)" set from somebody@somewhere.net set sent [clock format $Message(seconds,$itemi) -format "%d/%m/%y %I:%M %p"] set size [expr {1 + int(rand() * 10)}]KB # This message has been read if {$Message(read,$itemi)} { $T item state set $itemi read } # This message has unread descendants if {[AnyUnreadDescendants $T $itemi]} { $T item state set $itemi unread } if {[$T item numchildren $itemi]} { $T item configure $itemi -button yes # Collapse some messages if {rand() * 2 > 1} { $T item collapse $itemi } } # $T item style set $i 3 s1 4 s2.we 5 s2.we 6 s2.w $T item text $itemi subject $subject from $from sent $sent size $size } # Do something when the selection changes $T notify bind $T { # One item is selected if {[%T selection count] == 1} { if {[info exists Message(afterId)]} { after cancel $Message(afterId) } set Message(afterId,item) [%T selection get 0] set Message(afterId) [after 500 MessageReadDelayed] } } return } proc MessageReadDelayed {} { global Message set T [DemoList] unset Message(afterId) set I $Message(afterId,item) if {![$T selection includes $I]} return # This message is not read if {!$Message(read,$I)} { # Read the message $T item state set $I read set Message(read,$I) 1 # Check ancestors (except root) foreach I2 [lrange [$T item ancestors $I] 0 end-1] { # This ancestor has no more unread descendants if {![AnyUnreadDescendants $T $I2]} { $T item state set $I2 !unread } } } } # Alternate implementation that does not rely on run-time states proc DemoOutlookNewsgroup_2 {} { global Message InitPics outlook-* set T [DemoList] set height [font metrics [$T cget -font] -linespace] if {$height < 18} { set height 18 } # # Configure the treectrl widget # $T configure -itemheight $height -selectmode browse \ -showroot no -showrootbutton no -showbuttons yes -showlines no # # Create columns # $T column create -image outlook-clip -tags clip $T column create -image outlook-arrow -tags arrow $T column create -image outlook-watch -tags watch $T column create -text Subject -width 250 -tags subject $T column create -text From -width 150 -tags from $T column create -text Sent -width 150 -tags sent $T column create -text Size -width 60 -justify right -tags size $T configure -treecolumn 3 # # Create elements # $T element create image.unread image -image outlook-unread $T element create image.read image -image outlook-read $T element create image.read2 image -image outlook-read-2 $T element create text.read text -fill [list $::SystemHighlightText {selected focus}] \ -lines 1 $T element create text.unread text -fill [list $::SystemHighlightText {selected focus}] \ -font [list DemoFontBold] -lines 1 $T element create sel.e rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] -open e -showfocus yes $T element create sel.w rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] -open w -showfocus yes $T element create sel.we rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] -open we -showfocus yes # # Create styles using the elements # # Image + text set S [$T style create unread] $T style elements $S {sel.e image.unread text.unread} $T style layout $S image.unread -expand ns $T style layout $S text.unread -padx {2 6} -squeeze x -expand ns $T style layout $S sel.e -union [list text.unread] -iexpand nes -ipadx {2 0} # Image + text set S [$T style create read] $T style elements $S {sel.e image.read text.read} $T style layout $S image.read -expand ns $T style layout $S text.read -padx {2 6} -squeeze x -expand ns $T style layout $S sel.e -union [list text.read] -iexpand nes -ipadx {2 0} # Image + text set S [$T style create read2] $T style elements $S {sel.e image.read2 text.unread} $T style layout $S image.read2 -expand ns $T style layout $S text.unread -padx {2 6} -squeeze x -expand ns $T style layout $S sel.e -union [list text.unread] -iexpand nes -ipadx {2 0} # Text set S [$T style create unread.we] $T style elements $S {sel.we text.unread} $T style layout $S text.unread -padx 6 -squeeze x -expand ns $T style layout $S sel.we -detach yes -iexpand xy # Text set S [$T style create read.we] $T style elements $S {sel.we text.read} $T style layout $S text.read -padx 6 -squeeze x -expand ns $T style layout $S sel.we -detach yes -iexpand xy # Text set S [$T style create unread.w] $T style elements $S {sel.w text.unread} $T style layout $S text.unread -padx 6 -squeeze x -expand ns $T style layout $S sel.w -detach yes -iexpand xy # Text set S [$T style create read.w] $T style elements $S {sel.w text.read} $T style layout $S text.read -padx 6 -squeeze x -expand ns $T style layout $S sel.w -detach yes -iexpand xy # # Create items and assign styles # set msgCnt 100 set thread 0 set Message(count,0) 0 for {set i 1} {$i < $msgCnt} {incr i} { $T item create while 1 { set j [expr {int(rand() * $i)}] if {$j == 0} break if {[$T depth $j] == 5} continue if {$Message(count,$Message(thread,$j)) == 15} continue break } $T item lastchild $j $i set Message(read,$i) [expr rand() * 2 > 1] if {$j == 0} { set Message(thread,$i) [incr thread] set Message(seconds,$i) [expr {[clock seconds] - int(rand() * 500000)}] set Message(seconds2,$i) $Message(seconds,$i) set Message(count,$thread) 1 } else { set Message(thread,$i) $Message(thread,$j) set Message(seconds,$i) [expr {$Message(seconds2,$j) + int(rand() * 10000)}] set Message(seconds2,$i) $Message(seconds,$i) set Message(seconds2,$j) $Message(seconds,$i) incr Message(count,$Message(thread,$j)) } } for {set i 1} {$i < $msgCnt} {incr i} { set subject "This is thread number $Message(thread,$i)" set from somebody@somewhere.net set sent [clock format $Message(seconds,$i) -format "%d/%m/%y %I:%M %p"] set size [expr {1 + int(rand() * 10)}]KB if {$Message(read,$i)} { set style read set style2 read } else { set style unread set style2 unread } $T item style set $i 3 $style 4 $style2.we 5 $style2.we 6 $style2.w $T item text $i 3 $subject 4 $from 5 $sent 6 $size if {[$T item numchildren $i]} { $T item configure $i -button yes } } $T notify bind $T { if {[%T selection count] == 1} { set I [%T selection get 0] if {!$Message(read,$I)} { if {[%T item isopen $I] || ![AnyUnreadDescendants %T $I]} { # unread ->read %T item style map $I subject read {text.unread text.read} %T item style map $I from read.we {text.unread text.read} %T item style map $I sent read.we {text.unread text.read} %T item style map $I size read.w {text.unread text.read} } else { # unread -> read2 %T item style map $I subject read2 {text.unread text.unread} } set Message(read,$I) 1 DisplayStylesInItem $I } } } $T notify bind $T { if {$Message(read,%I) && [AnyUnreadDescendants %T %I]} { # read2 -> read %T item style map %I subject read {text.unread text.read} # unread -> read %T item style map %I from read.we {text.unread text.read} %T item style map %I sent read.we {text.unread text.read} %T item style map %I size read.w {text.unread text.read} } } $T notify bind $T { if {$Message(read,%I) && [AnyUnreadDescendants %T %I]} { # read -> read2 %T item style map %I subject read2 {text.read text.unread} # read -> unread %T item style map %I from unread.we {text.read text.unread} %T item style map %I sent unread.we {text.read text.unread} %T item style map %I size unread.w {text.read text.unread} } } for {set i 1} {$i < $msgCnt} {incr i} { if {rand() * 2 > 1} { if {[$T item numchildren $i]} { $T item collapse $i } } } return } proc AnyUnreadDescendants {T I} { global Message foreach item [$T item descendants $I] { if {!$Message(read,$item)} { return 1 } } return 0 } tktreectrl-2.2.8/demos/pics/0000755000175600010010000000000011073207471014162 5ustar TimNonetktreectrl-2.2.8/demos/pics/big-dll.gif0000700000175600010010000000066507577521106016173 0ustar TimNoneGIF89a ²3f™Ìÿ333!ù, ‚ÿÿÿ¿¿¿ÿÿÿÇ8*ÜþOÉ)…¹8k,ýÖ&fŒ÷UcjEw.êhµ&‹!}†7 ü@[/U¨¡†£¢×SRx@J%a¤âêW9'ÐêtªM^ÐNg X›—Òˆ™zÏÐö4Dæk¾Gu-\?v€Xs[z„‘ŠŒh‡?†lRŠ—a…žS” )…¤­«¨x*¬R‰©#³ˆ›†°p‡¿\ÀO=tºHʱÌÍÁÏ–ÎÒÆ`Õ¹xÛÜÝÞßÜg@ãäåæ5 !þ€This animated GIF file was constructed using Ulead GIF Animator Lite, visit us at http://www.ulead.com to find out more.USSPCMT!ÿ PIANYGIF2.0Image;tktreectrl-2.2.8/demos/pics/big-exe.gif0000700000175600010010000000056007577521110016166 0ustar TimNoneGIF89a ²3f™Ìÿ333!ù, ‚¿ÿ¿¿¿ÿÿÿ‚8ºÜþ,ÈI«½»ÿ`H!œhª®,¹±pÊóìšq\4ç1€p8¼‰ŽÈQ Ãl*7‚tJ­Z«ÏÑuË•f£Ý0õ+.Èæ0:Í]³¯î7ö–[ãv/=ßóÇ~zK‚Sxy‡v‰r‹oYI.M”LD—˜™šCžŸ ¡ !þ€This animated GIF file was constructed using Ulead GIF Animator Lite, visit us at http://www.ulead.com to find out more.USSPCMT!ÿ PIANYGIF2.0Image;tktreectrl-2.2.8/demos/pics/big-file.gif0000700000175600010010000000072207577521110016324 0ustar TimNoneGIF89a ²3f™Ìÿ333!ù, ƒÿèÿÿÿ¿¿¿ÿÿÿÌÐHB«½Wê­‰ú`(‚ÀÞ¨†”yvk¬IùNòêÕ.š«)Þ+õcŽH_1–èÁ–«¦:’rˆ2$ êÄeµÈuƒÝ†€@þŒŸŸ­^³ÍŠ·÷¬=øÕkG zX"Hwƒ]…!‡‘i`myŽX~Š–„Xˆž ¡x£!¥®ž±Ÿ ‚n˜#±²²HªS xq•µ—¿rÀZ|«·¦–ˆ¾WT*¬Ó"ÕÖÑdÙbÍÜÆÒßàd åæçèéæŽÄíîG!þ€This animated GIF file was constructed using Ulead GIF Animator Lite, visit us at http://www.ulead.com to find out more.USSPCMT!ÿ PIANYGIF2.0Image;tktreectrl-2.2.8/demos/pics/big-folder.gif0000700000175600010010000000071307577521110016660 0ustar TimNoneGIF89a ²3f™Ìÿ333!ù, ƒ//ÿÏÏ`ÿÏÿÿÿðïðððÅPÈI«½8ë-‡ÿÀebœè9ˆcU¦°±¶ÓpÄñÜDïÿ@PØAȤr‰½pPTá4¥€gÔ:­¼]B@»ÅU ^1¹üm[¥jS´ëŽÑ qvê^ŸæÍ{€_acrs\o`W…vetƒTw‰~ŒRz]›„k}mgTh’h¨—/¡n•£ªhx˜‚›°r­ˆ®ª£q^–¼²ƒ²³Z»¾¨ÅÅÇ| ™g”@Öר?ÝÞßàáâÝ4åæçè!þ€This animated GIF file was constructed using Ulead GIF Animator Lite, visit us at http://www.ulead.com to find out more.USSPCMT!ÿ PIANYGIF2.0Image;tktreectrl-2.2.8/demos/pics/big-txt.gif0000700000175600010010000000061007577521110016220 0ustar TimNoneGIF89a ²3f™Ìÿ333!ù, ‚ÿ¿¿¿ÿÿÿš(*ÔÏÁ)åº* ùîà'&hÎC¨lê®äP^èú¶v¾2¦­À pHõhÄ$Ñ8[ü”Ð"¯™±5®ÄJŠé‹F¹ÈÈ5å;½PsTŸØíiWŒE»Ÿðà=?ÜÓÇ€€+~|@~ˆ‚RGg…†ra‰’[Ž‹To“u„Žž…‡Še•k—¢cl |«yn'±²³´µ¥œ¹ !þ€This animated GIF file was constructed using Ulead GIF Animator Lite, visit us at http://www.ulead.com to find out more.USSPCMT!ÿ PIANYGIF2.0Image;tktreectrl-2.2.8/demos/pics/checked.gif0000700000175600010010000000011607577521110016231 0ustar TimNoneGIF89a , ßßßÿÿÿ'Œ6í/´ÖÈlxê6tƒ7‚"èPçsITÚf¯&j±€çzd÷;tktreectrl-2.2.8/demos/pics/file.gif0000700000175600010010000000042707577521110015567 0ustar TimNoneGIF89a Òttt¼¼¼ÿÿÿÀÀ!ÿ NETSCAPE2.0!þahttp://www.rtlsoft.com/animagic Created with Animagic GIF V 1.02a by Right to Left Software Inc.!ù d, (ºK#ÊÀ›Zˆø× B8F¥Ø¥'iž,üŽ1=¯¡ ï<èÿ€!ù d, &º;.>ðd„Ú:ÐÛ |¡3‚ÛYŠd©ºmøÊqú x®{|$;tktreectrl-2.2.8/demos/pics/folder-closed.gif0000700000175600010010000000015707577521110017372 0ustar TimNoneGIF89a Ò„„„ÆÆÆÿÿÿÿÿÿ!ù , 3XÌú0ˆ1E€OÒm› D(Ža€\:™`¥R,ñº±kç|ÓùÎų ËCô €¤r¹L;tktreectrl-2.2.8/demos/pics/folder-open.gif0000700000175600010010000000017007577521110017055 0ustar TimNoneGIF89a Ò„„„ÆÆÆÿÿÿÿÿÿ!ù , DWEHB+JD8NQ6UE+UH8VR=oBeE+cI:kW$gT:vI*xU%tW8yaJGCAOZNPGMRWSLEWNQXSGZXSKYdQYc]aQ\jl\wneLCdYJf\TvXJt[Qv^gibJidVveLthWzrZhifimxgqljuuviftnpyuguwwlyŠxx’v„Qz†i}‚wC‹N1†Z-‡X6‘Z;l5¡_+‰ZRŠpTok…xh†{sŸli–yg¢WR©rL²rlÈHÈ}{É}‰X™ˆJ—…Zš•]Œ„l‰…všb‰q”†l–‰vš–m›”{¡Y³_—¦dœ¥y³cŸ²pªŒC¦›Y§’k¨—|®­r¤¸pµ¡o¶¤wµ²vДṖvÒ©SÒ³oê³Xé®jÜÆ}îÈgæÍqôÄgóÈzôÑu‡ˆ„Œ’˜•Œ„™–ˆš•”““£Ÿ¢‹­‰…¥™ˆ¥•³‡§¦‰ª§”µ¦Š¶©”´²€¸³—ª¤ ¸®­º±¤¼·°ºÉ²Í“Ȭ‰Ãª–ʵ†Å·šÐª•Ò¿‡Ò¸šÌ£¡Äº¦Ç¾·Ñ»¥à‘å°­ÉÈ’ÛÂŒÚÉ“ÈĪËŵկ©ÖË·ÚÓ©ÙÓ¹äɈãÍšíÛëÔ—ôΈøÙˆøÚ—åŪåıéÔ¦åÚ·õˤüÚ¥óÝ·úâ‰ýä—ÿõŽèæ«èá»ùæ¦÷æ»ÿó¬ÿô¶ÇÄÈÌÕÜÔÍÁÛ×ÅÞÛÒÛâÄÜåàìÄÄåÙÅãßÓùÃÆóÝÂûØØäÝíêäÈéæÔïðÎõéÊöëÔøóÉúô×èçâëâóîðïìô÷ûøçüü÷þï,z“ÂÁ (@ ÁƒÑ”9ËöŒ Š)T´!ƒÅ N°@qÅ’)kÚ¨\“¥Íš—k´d™™EæÌ'Y¦DÉÂäf”)S¨ó@:©e‡Â3Õ﨓µ9É2#©ì£ÈP‹©n£òL&=ŠX@A‹ p2w`„ìcO/þApp@!Œ@Ä= Œðj€Â < ‹i)¤Bþ¨¥˜›ã5${¨êÚô\CÍ#ÑLž7ìœrxPü}A 5Øð‚)ûäó 9”Q‚2QDЇ`|=ÆÌÄ'ã<ªÙ¡ŽrÈð$cˆ·¼°PP¡†¨"þ-Ñ\#Í-lœÐ#‹Àþ7NÄ¡F  è} fÈo UD} 4Ðx-Rؘ&51£`ØÂª… íAvXÄ ¢ … üÄ Thœ)HÁ0( 'ÀnÁÁ|÷}”#ÐÔP4aZþðƒЬE8À(p‚b€ìlòC÷*HÅ*ô„Ć  Á K`‚”À'L0¸Àb³¸†0A R`RˆÍ  A èèY/ú@ò! U‰€C B0^*B]Qù ¡«.ˆ Byʃ€°0°§†àÅMJ«'x@3òfí b‘›M mø„>ö-ÒŒ=ËD0¨U ‚Æ ¨@/°Ý \€ìø0˜Á4É`ºbUÈ3ˆpÄšO\Ø}hÖ° &˜€&î²à‹}àÃ2èˆð‚t èÌ„þZPzà,`„ð‚:¡¿/0X_d%T@£3`lG±J 0€Â*t2?p€`P«`ÃTØ#<€ ‹q/²`ƒ&0¬âÇm7@€Ÿ,z˜0!áÕô‘A{°g¡D˜¬'œÀºbM4:å;LÁ;`€Ñà7A#¶Ç)ÊP†Pæ ¦K5ËèÈ>– ‚z„¼šÜÂff „-v”®Gò&OÀ @…`%£ e?èb1`:ŠP8®´ŒÆÐqÀÉ€qBÀÆklÌnsÓÖÂ|8ðÿƒ@¡±tr\€00ä³p#d  ]Üá«ðl4ðU­–ˆ„Ä©s€¯1Ó€8‚:'v tíÁnäê´ˆ{ê0B~°Ñxu Q˜ Ús€WàÉž½@ v@‹[Háã|%1Ûà‹yˆM‘˜CâÐ2´¯/ØÀJ÷û§ ™±tùÔéÓƒqA ´:ŽÀ a A„ÝéYVí;ÀÁ0!(x œJG+Œ! ±I#b hðVòÃpЀ{ vxòæöxã=~£@þQ`n|ä¼\€nùv!Ú-]‚øB 3˜ÁñþTáÆ –>’ñ†êçÀ À¶ù‘O \\ÏKàzt_àjXOÜåÂ?„<Ó *" po¶÷Ypp S/Àh= ¯° ·c“+àM` ß…N±óð=Ð̵qƒSnU÷j7ruJà@ }p/4¶*xoFãdŸEà3öæd 0Ÿ0 · ï°N°,°ÊfíÃÀ~ºçœâ_ÒtÕ)C°x]øjtE´Lg0Ap aáÒÇJð`[° °¬T Àl ¸à wx®ôJ Àÿ‚wæXG`xCW'nT7JÀ€;rg‡Ô:†vÑ×yÃÆ° pae4ó¢‡ °p`RàCøh®âwPN­oöB†UC`k‘˜x 7WC° NЀîÑŠú¦oóò‡Gð°ÀOФ 5° J ít.dˆ,pWgF–x­6u_ˆSGJ@iÖ4#eíÑ×}ŸÕ>°Ô¨È*p*ÀN@ è0 À°è *ð)` ]¶çÌv`'àtÌå‹^†Ò)WÅAC,e¸>µø¯d4`u Á*ÿ» ¿Ðí° ¤Ž 怊FsˆÐGƒÕ_4Æj‰gn_x#­Ö…K@#@ ÀRRvÐRýøYïtü`  ^eiànP¿p–í0 i°)€j` ”~‡ap`…ÅŽG]ögx|9uWõhC©šØ*-UaZÙyù¶B2 c§irPr@§à5ào óc1€síÓ];–þÅH©—|ŒâKpà(@ÈÓs“•¬$ŸùJ `JÀ`cYt+€ Ñ´p ~ðj Nðö†› N©Ø2`!HÙ)b‰©i|ÿ¶* DµÈY9¨•0×$16 –“)™p  Ò ¸€ ‹°Q6" ñN°_…\uvX%‰†7WÛ)]†€~³4êÔRŸ…N†NRv2 cäk¹rð §°à ¼@ K`C°2ðKî„›­s —&gÑ%? ⦰FŒK@p] `ˆ†8/1£Š~çw®Tq@ׄ*•ë9j  o0z°]5&p]Vv+Úp&Pš¾øŽ4Új6*—']°¤5håB†¹)Z 9^I`M½¦ `šç« ¦ðl°zð_ÿz@ESvÀÐt0PX2pUÑ °ÆE†§…KP'®âhkzoe‡mØV €&Ùt…/*R]pN p T°kÐQlð3pª¯BP=6`W¦Á(oøjW…ô‚›hõhëçY§»òDBQðQÜú6 `JêP 'Aa SÐ#3sJ=vc2`XuMÂèŽ3¬WUžzޱcŽØ†Nž¥i]ÜSzàC1¦„µ { 6¨a@ao#¬àÄ6@©a‰‘X¯ë–š4öht’Vê:'ŸåY‹†@ÀúTT@lð²ÿTP Æ@ TP(p °¥P PoÀ®÷(D )|–r30Ǻ Õhîó60£•†aðZð{Ð=~X ‹ Rpzá­°`P =ûœ(­C”…Jt5©zY¯\$ŒÙ ‘o bˆXûdðñ9ASð¥§Ð¡l€(`h`W ¸òš[¹ÃžËt§N¼¸·J`¦3€zËE0 Ä3.}:8ª¡#P¦É(kðSP«È¶D€ A°»~À=ÄFž[PÎKX½™x4ú´óa”åFcrÓN0ZÿeÇt»¢Ú•@ÄØª'Qzzà ª0lð”ð´0³k vHvਠP0p&%Ç‹AÀ®‰B@£Ö ;¦N¤uaëôNntvf$'1\¥» R€Qp•ùlð P2ÀW9Z {úk•íÑQ`?@5k*òj,,€mŒÆ¦j§Ç¦R¨héÔG?|0À=UÕ»J`;}Ô#A@f'М Ü'ZÈs«ƒÂP÷Ó$p:ÅgÀ«+7àRq¸Ò¸h%Šèdðñ'1#:bÅÔã[`´uæÿŽf1€gpj€g<[#0À´Fg +.3³+pˆP(ûdèD´òÉwMS°.€Ps3”ã&r!@€Ø,~@ÝÀ à€P·1°?Yg«b$ kCZ^9=âNÊÜe£¼hïD4h­)R©Ð 0ApÚÅÃðl@ÓÐ à€ yðÍ ¶Ð-p @ác'k"ZÐê*¤¥N±3»eÅ]þZÄUPæêQ.ðKà=€’RfMÇåB±3c±Q0à Ù@&Êð Ù0 —pÓÐ ÓÀC-p)°c( 7rÓdÑ·lÿ\ø:l(›N0W@`°u¸áºŽŠ’ UY ¥Ú]å40ð¶À •@¬0 ™À Ø ØÀ ØÀÌ g 7ÀÖ)…lZæ´]iåFj½]Þ5lÀG` •Ô  0Ÿ°.3°¿.0. BÀYÄ G Îp˜ —° –0 –` Ê@ ÐËß° ´` Ê0€¯$VKc4 ‘ƉùÒð· UÐ |  ¬  5· ´P oðM`rĪ_(iঠS@ Õ` ˜0 š  “ •  ߀”à Òý Í  Ø  ;tktreectrl-2.2.8/demos/pics/imovie-02.gif0000700000175600010010000001343007577521106016362 0ustar TimNoneGIF89aP<w!ù ÿ,P<‡      .$9 $#'%64%$1!$ &'07 5)"2 #& %'%7 %74*5%0?46(&%'%3)6%)645(&6,376(865.(D:5DB ,G*C$+V#7H'9E68U(;V3@%EúÈ$h4XàဃM”+"0™4ÝÂ%H£H‹¼iÃfÄ œ?‚ @©a:@`¨PAE›ÛllŒ8éZ65{àù«èŸG‡ FŠôÕ<8XpÀ:‚p“"eY™L¸rþUZ¦)#D8@"åˆ*TjÐ@»$Loð4Q¤" Hd³Fpñ‰",Ås…9Ë 0 Ð5@"„ˆ"™€È.•äÂE%1¼ Ç(Ø€Áœt "ð¢HÌæRn¬Ñ F¨àF#ÚhcFD˜`€9² s޼òÈ/0à€àÁ‰è‚H™‰Þc€!"ˆ"‚ £\cKp:h€Á>È©pbpçzð¡ ( àF$(ª‘@ Ç ‚òÊ-bØ+¯ü2‚%HÉ‚€†Ëd‘ K1cc 4†ô@„ÿ³ óŠ,BtqÁ}tQÄ®»âK)] !D]œ¢ÇªµÑH$ÚáX }ý¥œ’HAâà#°œQš u0¡ !ˆ„‘Ée”q "ºìrË3¤<à )ª<£J+ÐÔR‹)©Ð¢Ê¾]¨ÒE¦ø¡ê]‚ *Âì† Sˆ'Ù°@$´ƒ&é#‹@âWµ°TÚF&0"N"šd±¥½Ü"M&*Ÿ£/Ò°âE4ÑqË.Ò<3†4í޲Ĥì#HHDÒRxøgƒtò  €G‹òÁÈލ±† fL Ë/x¼‘† ┣KÒ`d!M/Ñ”¡ËRär… \P‘….þÀ$‘I/dìÀ JxqDGÜ ƒ -<àãOÔà‚ _ÆÏH“È {¥0œ`@9ru( ËØhzÌ'!Ä Ë2N ‘ !„ÄáÁä/Ü!†1PQ !\Ð1Ã. !†._8AE tàÁ ÄÀA 1ˆðDõVh¢E%.tÈ/*´hƒ"Œàé"mÈÀ‚6¤q,²l#Ç8ãdL Z$Â"hÁD‹yA ƒÄ  †.´àæ-`!AfÀ¼là 0ÈcˆÀÆ ž€Nü¢ ^;ÃmÚ€6… m@$ÎðˆWÀbÛÀý´Áˆ'ìAþ0€ À . Ø@Dž`€0ؘGˆ¸`‹ñÒ¤@HRÀ)|0 ˆ²¬ %t0Â"J€\ÃI”ÚÆ"ÌA¿npÀQ䀦„ô¡PÄ`@Ð|àÄä€ 0‚ê,T€Ž€½$ `¦8PˆRçˆhh@ D,e f`TÌp[éj8„Lá Wœâ 8Ç9 ;x² €x`ˆVô ˆß„(ö" lÒ1Š@€ £è” ƒl z€@ ê3¨ .F0ƒdð†xœ!jЃ#hê YÔ´<…¬à@Rú@j!uø  Hf'# &¢HÀ^Fª¤€ S 4ɸ9¼€ O‘b q5 ŠÀƒÆ"ÁtØ¢j€Eþöð‡RÔô€€ ^=Pi©Áha y䀑=FƒÊ« µJ%h‚&@€¿ŠÀ)ßìè&µø€Bl@¡|7¢ 9¾A‹€E7âAwØâëp©9Ä&A :ê€ )èÂ3äÑŽƒ`/ëáä«TH BÁ LÀ€LB€Î”žPˆBÐÁL0€ Ñ ¯­A®< ºÁŽnãÅêØ†^qˆWDö@X°Tf.@õÐ<ê‘40àÈ‘…¤ôœ½p@XhÒàˆÔÁ €@p‡xÀOà@Ñ 7!†?8þa "Дzˆ?ý ØÀ褕?阃Ÿ€î˜ Ü(YÕ1°šX D`”%ø&(K@ƒ$¶ØG_Ñùð)Í5:0@!ŒÚúøÃ*Kha%z~ûk@Ûš œ<2 P€ç\s/&0ÃñpàÁ˜¹uf ðdÌ hÜ@ ¸ ø€Cð©ð‡aÌä€4Ü1|Ì#¸ƒfP+Ð OÁcak~æƒAdÀUìX)íƒgÀV ¤h(8ª‚ƒÌƒiL ~#\›]ˆE9î{pÜŸGÈ¡Aÿ; ƒ¢ÀD ð€)B ö4:î‘D `©ÕåóÌ€H°'ï`À}Ë[âøD!˜çafCzø4Ô¡ŽZœB²`‡Ç;.rß#(2D‘Œ”S‚4€Àš‚‹zÄcŸõhK¥s³HPÁ |4pµÊ{©B•x@%ÊŠ0Gǽ~v¨#îPÇÔ©Nõv¸£(D0âð‚Aº¿È( ìP- #Èå‡npó½ `m8ñ®iCEÓy}–À¨€Ï@Ë/b‹>³0‡,báŠX¼ÜîÀG,€0‚'Xaj—õíØþˆãŸ¸ q‡FÜàÇpÍ‹Ào@' @Ä@Z¾Ãц¿hp8@ÐÀì_¥FD}ÀøP@@@.€}Ù·{kgvPç åÐ Ž€ Ú Ðé`A‚j%å¥#RÆ`I—öhàLßÀ(€p'v¢0B¨?@„?àLv€ ¢ðãIGpž 2ãÐ Œhö@£á ã`ü”V(,À @$ÀO ðŽ5 "°{Ày@?0€qrЇP.Á(‘Qu¢  ÊÀ ÿ5мXÀ‰"x|ÄiÐi0 ô“%hôp^TSwn ð°A$E%ƒ°4•B@äpæ@‚Ȉ½XP¢` É ¡ ¢Ï! `>x€ž~æ0 x0 :é`ƒàB|~áo°2 jä]"°ˆáÁWF€‡ó-$°@/‘NÆ…À Æ i ÿx —Ð8-ðŒ0rÐ vŒ€Ý€xPim`m'wmŽØ0"àIlÀ¸–ú†PP­qPEˆ‚ÿi¶(7©`Î` Ô0 ¡ Æ0 ‰ àVð ð hð h )à  ,%˜ ¿0$ ×tn@ÎdVFÎ4 =a “´!'€è@(ˆ%¡7é‰à Í  ÉP ÊРƀ Ê @™rÁ0Áð ¿À×Оп€ã`æÐ P@ÐCphfp` õd¥jÐ}¢:ðz2´Ñ‹.º€/™–`— Ê”›”¢ÀÄ¿ Á ÝÜðfh>•A€Y)52DHDbÆ’> žè ñÁ?ˆÿmÉ©™wÀ ›`›· x) W0$"ÀÀåà å  Ýp Uh ~–#ÐL y€Y#D°Là’€:p,ñ71,(/ÒH@$t`žWÐ-à0qVà1àSð 3ž6ãœÙÀ |`()оÐ9fôSp4< @) ®àBx 02“"—ó¡{¡˜° ˜¢Ðjçr  ðAMoMà Ü@?5ºB=1R†À „h0M j0 ƒ@‡@°®Säð@ .I9(ˆÿ/R¥/¡\vàÍpí9 4D÷IYUPŸÄQh@b¾1mÀdDL ©L"€F jà Û ‡@H:p>°y¤>`qIWº/Q…Г— ’PVPZ4h TýuÍõXTÁï!SP‚Ð<ÃÐPâAz jyà /6 äP ï: Û ÞvQ@>à’€Èš.± œ°0pv3ÐyòIKx ¯QæL@VÁ“9p C 7õæP÷úŽu²Pää@²Ã0 ]G²®ÀÛÿ/¢$Р\l€1P3ŸP$}ÒAh°{‘Ű @}𤠱nä SÛð ~r:³ð ]쪎 5}^W =P %+—s)fð3°83PÏÃ[. cSÂcEIT°°Á€>¯r‡PD°èf`y+³0SD°ç~0 ëàìð }ð| ¶À*6A4€s ʆϦYF%Æ\|p({»°´p¯D±±@pMj!WŽ_j€M`­z{~À€zÐzp™A ®  ÿq` \0§û5P0P1 ´#%f)9¨b–Q°’iI# #A@)ð¡¯Á¼|ÐiWj[b)Vp ½K‹øPä`ØI÷ð ‰P½À ¸  ›! ç  ¾04`®†p Q&‘ M€¯.PpiÉmë+a)Aмû«¬Ôªf°^óŽ’›N°@ñä ¾p yp€ø0 ðÐó ëÐX¼Z, + P`]àl0Ö–(Ч§p à{À+™¯`' þ+a'g¡/²põŽÎK­Š®: ì0ÿ†|‡00ðpðòPÅWóð@,ì`C@ÆÙë† § +9ÀC°6üëËî+#˜éÃ@€ApÎ*À¼ W€Ä÷ëpë <ÚñPôPõpù`‹ÅÄ÷@™ : ®C÷jm]P «° Ò°ê`ÂCP¦@ЫœÊ @°¾>[å yÀàµ_% 60)À³2+àVìæ û”ѬOñ€çV-Æ2`-"'`{©\ ~ î nµ° µÐ ­° ê Å¦0‹»úM€'œÿ{ɹ !`AàÓ´_ðûõ0IƒÐúÍCMôPÛ m€, (€IMÙ S`¹êÐ&Ýа/ë «p¹ÐP>ÐÄëªäŠ{0ÈP ¹° »s¾BÛKmÀ êæw ¯‡l72àe‡º“ã2ðeaõ80-P—p y7.гO0Uâ^¸OX¨^èÌόۀfP£×0m ‘ÐÛ(ƒp îjP Gz”ºuë0à¢}.´3@ìÔÚI°œ •0 Æp [pP~”3 æÐKõh“Þ×údØÐ Ùˆ ‡}, º ]Û06Ì£Oðwð¼õ=”á7Íl:ö£ý Ç ŸÀ ÀÀ º°S ÄU4;tktreectrl-2.2.8/demos/pics/imovie-03.gif0000700000175600010010000001113007577521112016353 0ustar TimNoneGIF89aP<w!ù ÿ,P<‡       $'2 #'&$79%%=-& & '4 4(*)&("&= %67#,&&),8*1*#387(&8.271+769(/B(9G6=G&E.K4N8U:I*:V$?i-AL8DE:GV:Ea:VkC G,E%P,V5H)#K4+F:7W4(W<4d9*g;2t=(I;ADTv%Xy6eD,fE6fU6vF9tQ>e>KEGCLZDP\UHGXWMXXVBKaKWfJVsT\gU]uEcDOqPXfETuFKjeNbzZdlXfwdLEbNYkRGjZVzMGyTFs^Vd]fq]hdnDbvIfwUrc\wxNffgblyhsyxgmWiƒ[r‡\r’cm…em’hw‡gx”sy‰s}“g}¢r}¤^…([†7cˆ.e‡0`”0qŽhŒGm‘Tt‡Sv—H{˜Xt A´Hnk‚™r†u†™}‘žj„¤o³vЦ}†²|’ª{”´}œÁ…L8„YF]Q“[J…bVšbR†ifŒwv“mbŸyn›}}¡i[£}r†[™€{…¥V‰¿O€¸Y“¶\ªf‹­z†¶eŽ´y•¿k¿y’ÄZ™Ìm®Ê¥ÙeŒœƒ¤‚„·…–ª†š·‘œ©”Ÿ±‹£¯Š¢º”¦¸˜±½§Œ£®»¤²¹‹ŸÀŠ¦ÅˆªÐµÊ²Ü•ªÇ–­Ò›³Ë›¶Õœºá ®È¥·Ê¥»Ø²¼É²¿Ò§½â±¿â—ψ£Á¿ÂØÂâªÁË©ÂÛµÃÌ´ÆÚ»ÑÞªÃå¬ÇñµÉçµÌñ¼ÒèºÒóÁÌÝÆÑÚÂÎçÆ×êÈÚñÑÝêÑÞòÌáêÍâöÕäì׿óÚðóðõ÷þ¿ìÂUé’/F·*U¢ŒV%-Qða%J¥) ±D $2ÐP…;|ôè¡£ %J ØâÌ–":¬P’gO :wj8àÁÐôÂõ S­H-ªt‹ÖLRà¿!k$)¤F6VCg$4¢Q k`F5¦ak`ãÚØß;…x?ÁùRÀE>E aìÓhFÄ žÉ‰@ÌŒž( ˆ  îB© iLÃiŒÆ'•1 ldã†ÜP‡:ÌÑ6nœt†¥,cA1Œ¡r‚š@„!‘ M°°~ØÄ[{J@xBl=È0H4ft•Ó¨ê5<êUn|CäÐêV·ÊqxÕa…4äÇRV‚ûåñ†WM •®5+D&ê ;»ÒTÃèþ  iƒ œj4LjYn\«•U;ÖAÜupUŽM.8¾Á’ÚP£E1ê¶Ê{v¢¸®&2×¹¢®ê›Ý@Å«OC|B¸Ý&)ªŠ¬’ãªUÇ7ÖÁŽv´ãï°o;·ú ph•VÍ¡j¤R¨p5†uAAÓb vp*ƒ³K?Žή£8F–±ÊhXòØ`n6²¡ú‚ƒ¾ÂÕ¯9,×Àì°Œ½zÑTÒ4}ñ…2VÙÊ—‰B¦2å±2.Z i\c†žÄ!üp fŒƒãl‰¿Aåƒ#Æìp‡<¶,yÔƒõ˜—åqetÄhÆj)£þÑÊ6BŸh³œU¹Æep´”Ô:±ñ ?°Ä‘•lq¿±âvȃô°‡>}èƒÖG=ÂÌŽû÷ÒÌe®o=Šj€4Ÿ…'B UjVÐx%:¯A“šòÝðƒ;b Yã:–ÐudG:Ü1{(úÑæ‡°‡­hz¼Ã9®ŒÜoŒ8Ö°•iÝD•Œ­„†gÑG6¹ªÛ8„7V Ù*C–«è@ö< ì| ØïžÇ<²ÌŽä"÷†Ù r6°h“ØÞ|YP?¡ÊÎÐ^½F6dhJi„ûì(±9ÆaŽÇ¢Àî ;ðaH;šî†÷°]ÿK?–¾Ù@ó´¥½Ž~?¤¦„F(®ÍàQh[Ž‹-åb§± ?”ƒ«ß‡e{\d£ãõèx»…-r¦ÏÃ1þ(7Ð,`i«\ýöí7ÚíϪr­·ƒj)EZJ=ocåðFÛ(ñ(³#×+†GÒ­h~L:Ãv>âytа¡€µ¡éÇ:›ÊúþÂ/[RÌ¢rv@Fu5BùŒCü\«n_G,uXGo€#ò˜tÉí.zw ;Ý0`1Ê01@CÀ6¼ár?íþ:–êà 77  ¡õÇ¡t†ÏÕþ rÖêœ:ÔåáëÐÛ#ô[ŽÇ¤áñŒc°b˜MD!†Œ±þ¦ôÖ³§}…‹å77¨üD"‘‚¯îòô¸¦9@w‚cËÏçrßéùRe@Ce0 ºÄ ßg{7Ô_—F~0`ÍUdøä 8 ~:´ã€äðX›·luÄ gi„eðþƒD¤ †D}ÐlÐCÐËT`‹w{†uÌ–eôõbÃUqœf ¤p^~p•ž•UgVG+–Uíl*è_FKì  ÇðG p/ËÓ]€ap(€€9È æ÷_ÈÆ–_æl h ûÆ ~à –e7q²$Kê€{¸‡·‚ìäyýÇ Åp ÇcS™ÿÎŒƒà º”ƒWV_úU_ù…_ô`_þ¥yýµoààsz¨BWYu˜‡è¶‡íÔN$ýDèàGÅ  <öRb0`x Ú` † ÷Åbùµ2–Œ@È™¶ué0‡x8Š!XG}˜0–lyäé GúS|„?ËÐSÍ3€\' ž¥ íµ6öU‰ôõò ŒÃubT§UòŠæY–…‡o'\˜eZ¦e[Æk„éà?wT¯È Å0Lj2'ÐGØ@~ç¨_í°+Ór9\Xw‘ët$tõ‚v$\ÈÆkòæeò¦ey”¹G¸$HGE0ÐÿƒP r„ ìðß°2 íàŽ'6\BY_9~ D\%t²t‡vqYv’òVøpñàñóðì@÷ƒÖIɰ'pKÜp_Áh_¹–-ç€j `%Öõp”B'Š•%K|ØNQ(fó@ópë¦(IÕÈ’Ø?þÓ?±ôvéÔd·O)6‘jéŽ?¹Tf‘Âxbï@G©‡¥¸yv”eï o‰ÖkŽvøT9ñîpqÉ–Šp‰Šu”v:ä“yŽlY\'Fe'Ör¶£y”¤h\'Õ¨˜n~IŽf“¦ù z}Y’ÔXG×’º–exé?ÿ¥–ÿ˜Y‘éŽóÕrý†f%öø Q¶ULJé–eËI÷0iùPŸùð—òæš»&Ô ˆì¤‡þƒ{• ž¿Ù›hF\q©–í`~°?QF:´Uy©eÇqŒ¦û°õy€ÉP Yöžô¦Gä'\ýE_É›¾I\œÄe”7$täYx¸ÈÆqŽVöIrö€’P •»¶úøšÐ—Ëueäi –IuÙ_1VbFY¤¨U¦ˆŠ,&oø ÷޶::Ÿ?:Xy’X‰È¦0&_X×rMŠ‘ã鎘ù¢G‰ 2 ¡Ûùž}Énõ™¡*iÒfa&oñ o]ÆeÔéÿç`<è“õX·¦”Ù›F‰? ’7”‡º†X*iÑ™º¡“æeù`÷PŸõÀ¡_Ö¡)¹†êX‰+6‰+ãŽVæ¨j™ñht:£vºb°ÉkÌ÷kžš¡–£ì¶h¾¶h>f~©n¬Ú”0†fš¸¤ÂÅ¢¿©FY§w(Šx©k,i’[ºЩ¡ ·Â®ÁÖ§:ZŸQ)oö€hîºbôcò Žž< crêd3Z©˜šn%ù—{š¡ü@®îF®çªw ‡¡6ª€Ù®ö°™¯i_øul•¶em(hæŽ:} ذ¯J‰ni˜ù­ r劲y7l›¡Åj¬)©ÿî:šó0šó:›/ÆŸïÀ» ã •*ŠèeÙ­¥Š²¦·²J»²F®à ®Í9ȶ™ˆÖ®}9wôà;{lY;µí€}0 ¬F ‰õsºFÔȡ󉡻´n»´äúh¶¤:o}鮾¦h:ú|Ç…4«µïplÀ G§Ó’·k»6Ÿžú¶Žë¶M;°ú0•'ŸÎÉnêœÓ9š‹šøÀœ}@¸#6 å@q§,É¡û¸¬ë¶ÂŠó€øtlê®øpl²»»;¸Ó Ôp ÓKB§¸îPªlۺʻ²àÚ®³ûk‘æ´¼›µø µ[*»ø°` U<‰U©åp†™[Ú¶Ë[¾åÚ©÷À§LDzŸ:•*°Ët7)Cß ¾|§£æ»¿ç륎˧êë´Â;tktreectrl-2.2.8/demos/pics/imovie-04.gif0000700000175600010010000001322707577521114016367 0ustar TimNoneGIF89aP<w!ù ÿ,P<‡     " ! # #05$#* ) %?5 9(##+#%%9 '79% 6&:4&&#),1,4%/067*'3-767)665%@83LG(4G8G+?`4i-/_O2f-h:,L?IO?`o/EIKGG'DG9EX(HT:WF*XH8VX(XV7GgTo1@mJ5gs7GHDJJRITGOW_TMHUOZ[SL[TPXOfYhJVmmeKBcWKa]TzO@vWFwZZmYlfcGkbWiyDgwSwhKviVvvJ{wZjeh`opewek{sthip`p{skzxx_wt”Z„5f‡:M‹CWgZ¥OqKo€o`‡poŸp|ƒfƒwpŸoŸwmªXy¯gwÀgw‹‡jªo °ϰŸ0P€O†Q;`7‰\J’iS‘ti _P¢nZ¦ubÀ üÀ0Pï?PÀotÿ@_‹x¯°€Ÿ /¯/†ŽUŠ‚g†„y†“f‡—w–ˆo“x—lœ”v W‘«m­u°¯@ª¥tŽÏx ÏÀŸ@Ó“sï¿oßÀ_ßÐpðÏ`úïtŠ…ˆ……•—•Œ‚šŠš”˜••¦“§“’¥¯¬—ˆ¬›©¶§‹«£§§§°¯°§«°³·§§°¯¿µ°¬··³Ÿ¯Ó³¯Ï—Ò…Ï·˜åŽŸï°¨×‹´Êª­ê˜´ó¢ ÀÏ¿ÀÀ·ÇаßßÉ™‰È—°É®•Ò·ªç—ç¯å¶¬À¿ÀÀ¿àè°ÇÑÏ–ÑË®ÀàŸÌñ°ïÏ‹ì˯ôï”èí±ÉÇÄÀÀ×ÅÐÅË×ÐÐÏÇßÐÏÔØÕÚàßßïðõ×ÕåÚàìïÑëëëëðëë÷ùõïêõêõýûíûüûþ©¸adŠ5_¶àä‚ÇÏ×” ‚„ÉRæÆ A&ˆ¸0!Ž/¤¼XA"Ä„''R&Íž!%V¾|Á‚ÅGVhfÁò…Ì‹\@IôB¢ ¬Z1e„»wïæº¦ï pôÈ¢DG…:D¸0âV¼ÐQÂÃP*À¥,™>@X˜(ÁÒå‹— {¿tÙÙ÷ DãžЏˆ ¢4¬p`ˆ b¹Úù3â†Tº€ÙALŽ $`»à‚Ž ^|ŒàpCƒ ÕÝÈJß-Y²xÁ\¦_/e”d¸À%‚“ >”@ bD>K0l÷Þ»bÖòþYÓ1bƒ8>†PÀDŒ…²wà€`AI—.J<”ñÀå„?ÖÃ^2yœ_7œ_X”1Å#|Š…0!\ ‚IHä7Â(ÀìbÊÒì# d‘Ã`‘6±DP„±ÄÐDK$¡Jt4rð¢L>·`±Å`Á WM3…„&… ÔQÕÐ!€ ƒ9AD P¨±Ä|ÒQ, œ¹QÜqGj4A„#k„ñÇ LpàAÜàEÊàóÆ}Mö%‚P~QDÎe€€P …R$øPD5FñH›Q¨Ét6±ÄQDÁB'ÿv4ÁBw|Lè°ÅH8±„PAÄ'iü!Ì'S~(é \ðÁG1‡sCuðKܺÄ'w,"l·p«M8ÁÂ,°«D8‘D\¨C08á«f¨Ám{³Æ3!ØM<%ÈSb¼`s!t€ØPDqù¨ AD´;k h@Æq„Gd¼P±Â\pƒ ¬P*¨ Ê(Ïé„HX1q ×—£XŒqYH˜AJ `ÝS¬2ËðŠ‚„ -hÀL`°Â*8‚g0ÐÀ%ÀA'Ü`Á \Ph‚lqÆþ+ qÄ^Øäà2±1Kes(eðAsFd¬Á[¬°B9op¹ +là@/T®*¤s ``Á8^à AÄdVø`DK”AFÀYqVm^°ñ#˜0Á5ÔPA4°E /À¹ „pFßß;Ð€ß $°)40Âä C;Äl¡ H8 6޼èÃJHñ…? ²P…™L" AP&Ä ÀR ÁŒp„x EX@€¬@ X¶`¿-„  ˜ðÖÜÀJ,`„À% × Âð üàƒþñ‚Œ ‚¼4bÖ3 DìÐ/4…„`PšÖlà3+øа 8@“ ÁE€ƒŒ6ƒ ~`ƒ|Àrð€xÈF@öÁ‚M‚Pá Y8OD‚Å„1 PàID #€`_İ€@ è@L %„°~ @@ù øàø,&‘Œé°A†'ôñíÑÁZ6t…àM¡˜Á!´®Å€Là! Ê…@°€ˆ­ (Y  À:à€‘À`E8JBà4@!Œx…$82@ÿÂ/}ùC0à@ŠE Ž9…ã…àBy@0D” ÓX@J°O;˜€@€äÀ†ÍËC`„¾ùàEBˆ€-ЀÀtD$±ˆ<áY ƒG¡ÉJЙæTgC4ɶ`akë‹(r‚`àŠ[ v%#(,¢ > Bð°>¬4ø##1‰F<¡8 „ù‚+LAhÁQ ™@e‚€%AÌ0$àpY€an²/ØtB„`-D–PÊ£_€åˆ0ÇE€a­XD#Ñ1€FÔÁ!þù…)àB#)©èV+°Î¨EœÑ0`Û6j€H`”e€Š $@TpÀ¬…`!¸@‚4€;(x5 ?HmÀP†2`á!?YË p$D3•ØkøF*4 t€û€¬ l €0€À:Ø‘à7À '€â Ê`}ìCUP’…I¨¢“@ƒ#ȇ¤ò!Ax L^0Ø1 @Àð€W¸€®¸Ñs¾ÀºËrĘ $à*Ø„€€  @–·l© Žp#aƒ$tÁ_(çrþšºê¨ÑÌo*µz i¨ dÀôl‚$WT} 0À€ŠcNsE`€À¢Àᇤ™!¤ h #ÀàH@ ø‚2@‚À$xXÌZsQÚm rØ….B!†X€H¨‚ ›dN Àøñ ƒÎUNì †=z‘‹{øƒÐîG?4„î5 š&êQ~¬¡:èÀÒf¶´èàšYtP nlãà†*€ðH!(Æ•ûàgàhà û ¡ö°?ìq cpCÁØÄ-4q…RXÎ(LUQtÜããG0Á þÙÿ[ §S&¸ p°x—#àø†.Há<@0@Y‚·t”8À”Œm$#œ€Ä$æNP2›6sØÊ$+À!`„p”@ŒÀ&¼Áxn'\¼›A fЂ}™ãÔ¸<5žAs¤£ÀpDlà „Õ7Ã#Žsp¸>ˆÀ2€Úkñ!dd/@\to p€?¢‚ˆÒ~¶>ôñl6PA”oÁðà W\þ˜Æ9àApþ”Üø¾*Äàƒ:†A ÷¹H‘ `Üè°Í  l¢Š= HÀŸlApÁ€ ½  c0WPq Tà zÐ ƒPÑ Ó`ÔpÑÐ Í ¬À °À Ùés#Ú  PPmä> >0\l° v°c 4%ö³[J[à†0Uv$UPSpR`ð œ7 Ï0 VxV8 ƒÐ Ó°}tZŒ¢ŽÐC9€%àFoT/@\­¡Ey7´l %R%°`< –p ™Ð ÝPà0/ÿxÐ zpS8 Ô`…® \xa°i`Ài¼tZCP5p·¶oû¦QµWŠx˜µw)ØÄ0 ÀA06 `:0J` õðqó°îP p`®Ð …`UH щ ÏP…ð {À4@;p=°@P@p35†ÌT"l©ˆprxr˜w@fQ @Ô5FÀt@c '€aB çPx0…‰Æ¸Œz‰Û° èoŒðRÀÐPЏ1Ø´Žâ˜wrÀ™w@P‡0:ð‰v' BpA æð ÿÍЉȉϠx‰Ò° äÀ ä° Ù Ù 9@pØ"‡²G‘:vc¥ˆyWh°sÁ¶c[ š Ú0Úà d© šÐ¢0 ¬Ð{Ð ˆ“›g€H€°$wÀ  í— ª G7 E'ÐM4ƒ5ycpe¶Ç>ˆŽË“d­8`…šÀú  bN7,*°À…Ó TÈyÐN|`90z4## ­VÑ• Áœ€˜E’µw…c|  pPc"0†A‘…„e0 P'©ŒUh…ÏÐÿj  ? aà£á+‡#™ž hAÁ )à À¹QµçЛ$ÉV´sqál ñò–x€\ðA  é dð fà ÏÐ RÈyƒ€°†¥‡?@6PG#P0Iˆ1œ´s-ç«TcÍqi{8("`=ÐíÀþð£ô` \0 `<Ýð õ°k Z…Ï Ñ€˜ s' ’0SŒ@G40(Q½é%@px`- 1ø§d66£µB tÀ p<AZÀZ @À) ßÛÐwŒÿ­0 ® ä ’€— S‘ àGOàЦÐ¥½¹Q @ j€úRy, >@§Œ† Ÿ`œ   ÇÀ šbPC0À<€ `k Â@¬€ ¨Ð ÚIò–Ž`V†2åð-RG\ ¦aŠª P ž0jp-°-`(3:;XŠáxŸràÇmÐæú` q€APƒLp°„èÀ «à ÍH“° yt…2z;b Tú¬hE‘À>IV f°v`N0±ï¢.-p9kjwXhǰ—‚¢JÐ'J@]š³[€{ ä°Âà ÿëР«0 I@…âud;`×øC ©‘ ¢Ÿe•`{°w ´ƒ ;±N€iº£Ó;7`»À ¦ a@d IÀ]°T° x *Ÿ”ê°à ¬ jÐd PP~/µ=K5°?°{‹ž"”­MÛ´­¢´w`R{¦úâ[€â…=` §   ±³d KP^°n@xÀ²{ ²ð é ¥K ‚ @¥³ûaû¡ê¡~k4Л:V ubvB¼Më¸Mk¢š.‘ëQÐw ^» Âh |Á9ÀCÿrð 1-0« µ0¨CP-àj©ì Kî©5õ¡p V g°´v±{{€ ›¼›¼âú ¢` ÛÀ Û@ªðL,ª À.ÓP ´ ªÀ ¥Ð.r0©“j¥ëÛVê<ä¬P` œ´úÃKû¿vb'['M+±Nð ¦ ¬ Âð ¼>‚r÷u@‚ µà ŸÀ ÚP Ø€ Uà‘* &,»°4©ì[†y‰~f•°´ƒ€ ƒpNPÆKkŸ°´NЭ²´Ž»fð § m— j@½¦ÀEài pU ÿ÷P 0È›ð Ëp 1`ÅV: V:SX|Âh¥Oh b° (I;±ÿ‹ µ²´¢Œ LÛÆgÐ*Íë¢àÃò¦ kÀ Ü` I€zp Ÿ@} ë€ÈmpËÌÌ l ÁVɶëùdzÌì·;PËP Ÿ Q»´¶BÊ¦ÜÆn¼f‚¤ð À—¬  _«¹¬*àµ+¶@ˆ /€\pˆp¿@År@a0 €°‘ìV Ž`PÀð0 ̓@±h<Ã-±Ë*HàP4ðJª0Î=ÙÀ ¬ÐEmuð ¼`ZpÒËð ÄÒÿe@   a ˼ըa bà8@7c¼Ê{Æ9lÍLfpd@ý¦pF€º Àðd°w¬ D ¬WÊ r  Ã0 k1qq Á]`Ó³K¥‚ìÅ4=8r¤Çi`å»c,{@Lë¼¥Ò/j ;pF'19RBM ° rwºÀ »`dè]0»@ Í ’,ÈíQ»’f¼f‘š@À•Àû²/Ä«´P#°Ô•°Î ‚ÍfE@¾0ÒöÞìí®?êÞÒÆ|úÐòÀ rÞr0w³»šàÜ¥ñÛ€ ›öÍ= 3åÅ9ÝGu½”4.BÔé°ä`+Îû žk ñðÞ>zâTþ£#~â>Ê|×à î` ªÐV sÀ @ å0´‘ œ ý,f@Cð³¯I·ö­†O-ráëà ªp…í£à{ùU~èˆNåÌçùð¾€ €P Ê` À6 Ù qN¥’\àÑÝ¡CCà]ÔÀ­á¤^ ê ͰDò°âU>åXžèµþ£Ë7óì»ÐJ Ùàæl>w<  ð`µs›4`kº)3;tktreectrl-2.2.8/demos/pics/imovie-05.gif0000700000175600010010000000624607577521120016370 0ustar TimNoneGIF89aP<f!ù ,P<† 0 ?0O/_/O0/_? P@O@0_O?`O o@0p@/pO0P0o/___oP@p`P€O/P0_@oO`p oO _¿PŸ€?¯ŸP¿o¿¯`ÏpÏ¿pß ÐÏŸ€ Ÿ¿ Ÿ¯¯¯°  ÏŸ€Ï ŸÀ°€Ð¯Ð¯Ÿß°ŸÏ¯ À°°à°ï¿Ÿà¿ Ï¿ÀßЀßÀ¿ïßïÀ ïÀ°ïпÿÏ ÿЯðаÿß°ààïïŸàà ïà¯ðð¯ÐÏÏßßïàÏÏïßßðÐÏðßßïßïïßðïàÀÿàÏÿïßÿðÏïàïïàððààðàïðïàðïïÿïàÿïïðàððïðÿïðÿðïðððÿððÿðÿÿÿðÿÿÿþ€‚ƒ„…†‡ˆ‰Š‹ŒƒS\\T“\`–——c_šcžœŸž`¡£¢ c¥¡ª¢bž‚TTSV”\X`¶`·–¨ž›©½À¼­Å½­£É b¿›¥£­Àb‚X\ÕX¶\cX½Íb`ΦКћ̜¿¼½`ÈéÀcbƂ׵]V]—•–˜KEðãB…¸Ð ¯dÁV¡6‰¿[ýY8j¼M_¡Š§ìá—/ݾtìØìݳzžZQ{4eß>.]¶åSé9a%ë‘4Þ¯JõTjZ),]0™¬ÑÂÙ/'–mXº„y'PèCSô ™Ääó]4eÅA2‹‹,þoùÙ’‹ ”»ŸÿH¾Ä¤‹ïÈ‚@cŽ‹6î•ÔkY­æÓ…”ð¼ëxkäRr`¼$ØÌÄŽ0aŠ„9ÓŠéGüºäT+àB¼ nmøoÝÏôTE4Øé•éjp÷aÑbL?㣾¡<øãÈ]·z’åË bh¡‘#¿4ìÖôi›ªo-îViÓcoýÂ<®üä%/Z$ËýÉi<Á¯´á„Tsξ}5fÛ€|iá×_–¥¥ +dc‘-5 §Ø(Ü\%geY’•†^`_fã¸gY)gÙ“Ih$NÕ,Û &áE—ÕU`8œ%^„§á{5"‡;ÄÜgƒ“‰¾™þÆÍ#ªQ•NÆ ØØ.5Ø…"—%&£VBâ#Ê+M˜V&MTuUj·¼Å™‰g ò¨E‡¨ˆäÔ1áÆ¥:3A˜-SÀu•M3ªœW,*ãUWi†8SN&J¡ZšÚƒÌ(ùÑt’” žjÂÁyå•;r9TžÚx]˜žŠÙ 5NlÑD×:ê5]ZiWB )œnxÕHÎ(5Vuy&¤^ÉLÓ`™¼Î2ŧa—[UDZ¶ÜRg_XŽórö¨T³%´ihk±eE[lëwsMÅ…nms܆ZÄX ‚Ê]ò‹)^4åð'3±ÕÄþ+yZÀnŠ‹•UËÙ£W\ñqÃÍQé×g`^zkƒSPQæ,z/bYik,=òUEQD±>GAç.J¹; ‘– £Ù0ÒÆÃÄÚŠqNû I£\ ÄÄ‘ÀDgDð€ |”yœaé¨ÃA(‚ä3)5'Ö¹5Ýì ZTPàÿ…†àª!€#€Î ˜0&0ÚÂQb >s‚j£îfŠoW;t`ÜàâT›‹Ô`V` p «½ì%)@€–h@áhp½(ˆ¬F.œ§Z˜…µbÁ0™ƒ J·àÏm]ÅŒ\T^E˳<ïn\-@Xxõ À;A‰=yViQj”HçÙ(2M¡ ™ƒÛÛªù÷팑UÈÂݪp…»EÁ´›Ô@9z†êô« hÀ>0‚cj”¹;«,s%Ïñfá²Q¹¶ªÀ„¸Q ¸£e$^›«A-„Œ Í»€|YÎ nè´û„”YPnrÌÜþ7÷¸Íµ[Ü7±&× ;», á*GoXhîd`ZÃuÒ¬kÀW¿ŠÉPÀ!ð @ùàñ‚ׯÇe”ð %üÖÂLxp'¦ããþVÁªÈfP…%˜`àäà*=ˆ à XÀ(p°`ïƒuÌö’Y LHBŽ`¹]nÀš0ç cø¸£Ã[îæ…ðPžîpI×€Ž<]€'}ðƒô€Ì;Ö1šÓœæ5¯ùl^‘[-¼é »Ëìp}Cv·'<Á.Ø ¢LV_˜Ѐpà“ðìÛŽ•„¬`'À@2° ÿ ؘ@7 A% ù·¿-ó]9ïì Y‚p@ˆ@/@-ëÊÙS(@8â4Àh&,×¼FÁÔ; È7½ñÝcZá¨eš³úæÜÛ+ÚÈͶtÀpà@.èx °à¸ ðHÀ¦;¯™pƒD@Ò“^VÎò•ç»ÇG¸¿!h\ _˜Ãö‚¤`„!ô\CØ6·I€jxàèGï,€¸Áa`òÎwËñ-yWµ€ wð¾õ­Ù/8³åœÜ(ì¼çCðù„ t‡“àÛ ˆ;ÒݸX';ëUϸë§›".lþ÷c ®c¾c®»™ÎhøœÑ\)<ç>ï9Ú×Þpàá"ˆ»Ñ;°÷Ö©îp#`6pÕu v­S6nÀúÖÏàõ3PÁëpÖ'Á뿲ý!?WûÚÙÞö¡ÃÝè|ß.éCÀ‚|àâ#¸jôGÀXF÷@(Èþ±O€x%0AJò›ÞÏÀã‹`i÷½æ?ÿ"!íB·¼åEàüàA€€(€AP€ø×( Å&{j¦´‡i¨-D/bàxóGï—v‘7iG÷§Càp&ˆyCð;`1>à;;°ÿ54X0ð1-0×7j¦f˜69Àz9p„Hˆ„L°siÇm¾çôçl7| ·mhE0ƒ7X6À‚5Pƒ-†<Ø‚2 h{7@„$Fb- -0 q˜ƒ1ðX tPHh§‡ABtF $]Hƒ]h\ˆƒ=øޏƒ>°ç†2P‰-p‰˜X‰98†;h`€æÛo¤Éy·Á]aB,4Ù[ÊlåÝVh‘gÅPDH^@æ¥7!îphõÕ'@~Ø7€þIÁVzWŒwÅcYèf’wÅDA`p (ˆP0‘#„žÅS¤!†P(¡;þÐá‡æçöå€ÄKT¹ƒ;ÀÃ\^Éă9U.a•L(Q¦ 1°ÀÀpÆ Á ̹À ;ŒÅ+(ç0i€ (hÅ9§ŸÅ-Ð(œsBP )˜bº¦v.*–ÚÙé(0gŠ> ©l¦€ó=Y¨„hß¼*Zq{ñÚhqÀúç’Jê(¯Ç ¢Ä:Ô Ã 7” ƒ "Ì„\`d@Â\ ‚%XМ¹ IÀAg |0¸ŒË­¶tð¶LPÁ4ðÀ®üÛïU¢w€²C Q„ÂEq„ÃG Ñ„þ(ÐDHd1=”ð4aÀnU˜0S 7x[ (ˆAË|@‚$x›X âÞ•³øJ ÂC¡G7\=¸~@4lÄÔGô‡ñX€ÁÖÞŽ A$”ÀC<ø ¶Ùd—PÍ.[à€t }äšë€q‚,„ ^´=äPø Dñ°Ò3íÀìFðA”€1`I`¬1ŠAx=ö< PºÛX•µXeª 9þ=„ìBa;=ÔŽt:ô@Äï‰÷@ƒébÌ6ÄŠGœ1™c.qÐvqæØ'Q:oG‹ƒ þL¾pÑCÜ.DB‘ƒí¡ADÔ4àè  ÈdBÍ.<Ü<çœkþ¼æÑ»õ¢—9aLsG Zí—¾:ðv@Ð öbj>œ±Š<РOlcÞþþ½Œa¯„ÿ;¡²p‡4F}·kÇ„Pâ@I(€¡ê3¨‹=0‚þ~§¸†%NÍK"÷¼ª•F@‚ `PƒÜàv½k! ÛÇ>ÐU@>9 #sxC?@aBø.pÈàç3b€p„Ä9ì}ELŸâþ'ˆôN:¸A º£E0t t_l˜Ð`>ZÎrЂ¢ÏŽéd=þ—8$Áa"LâÃŒÐGBön90\m·ÊÐõòiä}Ž3F-98áâÈÉÜFÔ_ÃÒX;ůŽE(åÑ ×¾?Âð…/Ô ©¤^ÙÇÆ):è;±˜r&½©¿:"SÀ<‚† L@.“…½K$û„ä()98ì$ç³bÑ vœLc@#èÍß Š¿C_BÓGJìwïÄ]ûùBŽÕð>xä  Qå àõS t »Ðy.ŽLŸçlGL’~Îs=`'”€;îpÎ+¶âCa¤ #“#? „ wïsŸJÝDZ“*T #fY ÿº>¦òL¥Vy§SÎÀ†…ʨ#¯Ù«ìåžË¡@jpSŠš/ª™TjJ3:™î`«©¬¢VuJNð†øPFÃHTù•ŠP,ª z§ÊAvUwŸƒë/ç*«öN©äë RéØ?~° ¨OF¯IÆIB >d\€ÖÊWÃqÕ¦ueú"˜H¸Á®9¨´6»Y+Þ ·¼ ¤y8R£a´° på*€îĪ){€ƒ¶Æ¶}³…lí¦XETNkZ3˜ r€Jé ó-e XZÊRîªÈXB î,dg›;_Æ´2 xeЄ ¼âÁ´6{³Îþ€P3X#í3ô€‡Øt˜™Êû2¸œÍïkçKÂq—ºox¿ë Xh20ƒ '–Ëid¯ Pƒê†(47HA ppTæ÷åtƒ‹_þÞÔvStÁ‚U,ƒ» -žÖdü*IeÓ ˜%°Ìz«92@ „̬ΠoäÝ‘å¬ä¬«Óªî‰¿+ÞˆÀÙ!hq2"ê09f5NŒ³bkW†³š#dÓe–7 ä÷ªi+ŠwÜ}±€û‚€ ÔP€ÃH€˜jNxÀ°`©DcywÓËPÀ;$ßVTò €ýÛÞþÿZ3ÐA”§çi Î%¸À}VÃŒ  V¯ÒæU¯ Š2 PPlÞöÙX öVÓ[A¼ €Îr #r‚½Ô®v«¯}m¡o°«3 𵄷ÃG¾³Â¯jîg%»‚`•ã ‚T@Æg¬¾-hA~ç¸ÈÅh pà@Á PP"ÙGæ-Ã}ˆ-ÀrD¢R <€(4«ËïŽüè׿¸¡In€ðå*HÚNPnbWýØ7p±t#žóy—ÚÔ7øÁ|ûT[‡÷8ÒÕnÁ¥‡qžùèÖ`‚° •.‡¹oUìi›¿ËþQé€ f€±Aì*(Ä(ò}«ýÚ OºÒ p€  ÀhË€Ìu¸íåƒç+‘Ëkìø=çîAVÿƒ ¨M&ÀÀ@mC‘19ø|ÿј@À÷ ‚ð¶ˆÜà„ÇA†Md «E6½»[ à¡õDp½ÚR`‚|ä«^£i©¤V‹<à‹·Lp‚¨óÒzãxw{ü7»P…~‘#îß1ûc{€^³Rt”·7 Ð ¸+$Xüy`Éc¿çG€ÒRnƒG^ÇÆ!P€2Ðb‚0‰ó;¬u&èÅ €€öf0ƒÿ {Ó/{(×F+D( °5#°f)G2Pv`w Ð €)‡„û&xxÂw¨q4ø8ð8šñ0ehƒ]ˆ,±tOW#À~*ÐzH€„ß^Ó².ñâeSUÖG<€…# …2–eÈpˆš¡/Ð*cXƒ¬R†4è/_‰¼ÂCmHí‡AÐ16`! 3@eCÓB‚@& ¨³P`ÀŒ(† ‹=Wg؈58†(‹_èŠ 4È‘~7o¨'xp4"#9 93ãb.  09·’‹_¸ˆ¯Øsd8ÿLj°±ŽPƒâhj¶(‹Àˆ{Ó\\È5H$0P;39ÞâlÓŒæ…úŒáØsàŠ/ŠØ*±8±¸Џ°øŠâ(‹±Ø*íhyA9 p5“4qsC7ðgW&†U‹·8†‹X†Ú¨šÑ*ÚÈÇú2 0× “€“I†Äs+2Ö\C/üâ0Rfe‚@,&¹ˆP†à”‡hq™’‰X‹;©“ð{ãYé;yŽã8ƒôQ€tÐFÀ3ðfƒ·s‚€)⎠Ùs‰ˆWɈâ8•±• àY`„ù)™ƒ8¦€ê2.õh o.à0™”Y™–i;tktreectrl-2.2.8/demos/pics/imovie-07.gif0000700000175600010010000000405307577521122016366 0ustar TimNoneGIF89aP<D!ù ,P<„?/ _O0p_?___`@`O€`OoPpPp_Ÿ` €o¯p¯°ŸŸ¿ Ÿ¿¿¿À  À¯ À¯¯Ï°¯Ï°°Ð°°Ð¿°ß¿¿àÀÀïÐÏïßßþ Ždižhª®ì8a–…Í­m7ÎmœÖóNg8ä…Ecpéi:ŸÐ¨³ã¡:E¯X¬†Ñxw¾ÛnÇS—g"=”º«Q"\4»Àf²Y7<öõŒ€jc€kHkpSoOigtu1‘9•–•^–J`a@IŒVŠUgš•€XzZ0v”^5µ´³·c<žmÃVgd²¼¼°X1Αv·]]ÉÙ³¸^½´šdF@…TÄ–´Ù‘"õõîÏû’ÚÙÏb$kÕË–-\´4p»ä' L !U PÁ^½y""h¤'Ac ó@Î9‘Å‘þÛ•Üå $n·r2â…W;õ4Bð¨1ãÆyEÒ«ˆ³^ʼn" )2[-§üÚíjEiÇS~,vŒ°s'×" ˆõØQëÇ‹íBrLªõ"È1ú}‹ k[TzuŠÝ»Wă±^¿nÔX–Þœ9æõŠ6$¾‚»zí»Y¯+W±ùBð«y¯` Ë"–àYgÞ¼Fµã§¡Âºl.P´§·+`¯a;wþ ˜pG¯Œ·æ¼˜ržÊvÒ&NÄyx+Osëæ{øô±9Z4,¡¢öìÐÉŠ~7€Ì˜÷fF½óè¯!Ë¢>}™÷YÔÎy÷pàÿÿ{˜ýwÀþ À‚à ƒ &((È x&þØ€B`À J(„¦˜b‚%’há…Æ(ãŒ4Ž.H£ƒ"܈Ž@)d$ 9#ŽG"ƒ;*yd“<ö(£”7>褑IB¸$“A6¸dŽ:é¥ .8€™œÙàš_ú#“cÊÈå› `&–]–¹¦ž^†é&3òÉæ–€€Ÿ4ÆI掊Æx"|¦9€$P€gJjè¤  €¦i€©¤[ :f™`"ê(¢&ð)£fš¦¥$°À­¶&€@’ ¥išªã§  ê®iÀ«¦ËŠ`@ (m® þ0P- $À€µÛZ{-·h‹«¥•† í®Tz)¦Óêm´H‹À¼ k½ËžéWØv»m|m÷»íµb0¿+ì@ÀD,±ÄNlqÄûÛ€" @µÕòÛíµ·.@pÃ#+Àm·"³ü0ÊÇ|qà W¬q·*w¼²Á/ÌïÃÜÚz­¶›Üí´ í­Éíï¿c 5Ð è|ëÊ /­·âzk­Ê;?Ý/Í(lí¼I|õÒ ¬ÀÇòº«+V«\òÕ ÌòØ_<1À·ZÌï­µF 6Æ ;ÝmÙ ”M0Ÿ÷aÔ~Wn9åã]²»*‹ÀÝþ=·œô¼ôù.[~13Ḭ̈ÄýÚ}5´pï¶Ú~n-Ê_/ íÛûN~¹ê–7.8ãXW«k¦ÄÎ{+¿¶¦ü¬¶UKÞ÷ß4¿±à #Î0¶ O«6éµ–¯«²Éz~n­¼BkÀ¾RO±Ã}ËOñËoºòb͵®ó*À¼à©5=+^š@X*V1“ù s ûWÉ®’Œ[ øÔÁd7®õUj^”Råõ>É-Ž÷«ŸØÆÅ6ÝÉn[ƒÖ­Þö.jiÍVœ;—Û5­Zéì{ Þà‡«j/z¾S“¸f·ßI*^¹’á µFC„‹sáBßéD²m9zšÃÿ Öî¦+0h¸ª]ö.¸EkŒSL“´zø6RPçÛÈ’6­Š Wj£¡ãõA(Þ°]…C$éàå®ò)kõ@ÇÞ(´q•‚£ïØø9¡I«vîûÔ“X&CÙnY‰\²že¦_u¬ˆï£ £¸I[ÕJmÜá, 7EWm Så+Ÿ%ÀGZq‡$ú u>}ñçšTÄ&£˜ÉýÁÒ‚g"¯ÊW,uÑkZjÚÔCeEsÀ]u¤¦´`)EúN\B;ÛfEMYMêS¯ª”ûð *>ÑŠ˜$þÛÅLuRr ´ë!µ~G.öuŽ€Þ´¢({(Q‹†J€%<Àôx˜HÎñm€t£´&µ+Žú._;LÓ=e©«9Îð\m´]&i¾TŠo¨a»$ Èr©)]B-/c8AÃQŠv\*ìµQ­nT‘m¬!M]%{ñê‘ɺ¦H©éT]®cÓKä"‘j>rrôšzµè¥L9¯·Åë°â›Tí HH½ Z" @#³)·D Õ¯êŒ[á$åÍô™õžØ Wé¸+XÎùVLU:µ¬o]VlI;-pŠg…U7W›Z{‘µVÏ: h µ×É’Ž€Äu×E{zÛE¶µåU[{®5¯ÈŠÊ·À$Ýuëõ©ßNÖ°Ô¥«HÖF–.‡ÚÍW° …¾Òyð€Í=m7•E)QY7Ÿ ^—¹V{>è®öRßÜ&gµJ/Ë­UõÚ‚Ý:©ÈNêÀ˜šo}K«,cZ˜|·}¤=@H‚È1§±ZÀä&;ùÉ&;tktreectrl-2.2.8/demos/pics/internet-check-off.gif0000700000175600010010000000010607577521110020315 0ustar TimNoneGIF89a,€ÿÿÿ%ŒiÀí}žd¨Šo Ëj¾y*¤hŠerja6ªÓSÍ‹çG;tktreectrl-2.2.8/demos/pics/internet-check-on.gif0000700000175600010010000000011407577521110020156 0ustar TimNoneGIF89a,€ÿÿÿ+ŒiÀí}žd¨Š•¥Ë&Ê`µybyz!èdgg¾]ô™¡fO©ß×T;tktreectrl-2.2.8/demos/pics/internet-print.gif0000700000175600010010000000017407577521110017631 0ustar TimNoneGIF89a",‚ÿÿ¿¿¿ÿÿÿIXºΰµ%¾«)eÙTäXñ‚@ÎS„B ÃëÌ#iÃ;Þ«ÜC`0¥BcÇÐ Ä@˜’5À¼È¸¡Šf$;tktreectrl-2.2.8/demos/pics/internet-radio-off.gif0000700000175600010010000000010407577521110020334 0ustar TimNoneGIF89a,€ÿÿÿ#Œ©ËZ€4*ˆpz×¾€Ž·‘b™‘)ʦæùUp9K¶];tktreectrl-2.2.8/demos/pics/internet-radio-on.gif0000700000175600010010000000010707577521110020201 0ustar TimNoneGIF89a,€ÿÿÿ&Œ©ËZ€4*ˆpz×îx`‚ãdQä'¶›Çv°öV°|Kú^;tktreectrl-2.2.8/demos/pics/internet-search.gif0000700000175600010010000000016207577521110017737 0ustar TimNoneGIF89a",‚ÿÿÿÿÿ¿¿¿ÿÿÿ?x* úp1]|bN3lÌTÈyX¸ )‰hw -'«KŒÁUÏD‘ë€×ûéDß’4.›Kd€pq´«";tktreectrl-2.2.8/demos/pics/internet-security.gif0000700000175600010010000000015407577521110020342 0ustar TimNoneGIF89a",‚ÿÿ¿¿¿ÿÿÿ9HºÑ±†@QRÕp&—äe!3F—Ó=¨êžìWr„`ßö ‚î¤?8Üç ƒ·_Ouª8Ÿ•’;tktreectrl-2.2.8/demos/pics/mac-collapse.gif0000700000175600010010000000042307577521110017204 0ustar TimNoneGIF89a²3f™Ìÿ333!ù,‚ff̈ˆˆ»»»™™ÿÌÌÿÿÿÿ%hºÜþ0ÊI¸8Šÿ aH>€™Žð®1\ÑU®ïR!þ€This animated GIF file was constructed using Ulead GIF Animator Lite, visit us at http://www.ulead.com to find out more.USSPCMT!ÿ PIANYGIF2.0Image;tktreectrl-2.2.8/demos/pics/mac-expand.gif0000700000175600010010000000042507577521110016663 0ustar TimNoneGIF89a²3f™Ìÿ333!ù,‚ff̈ˆˆ»»»™™ÿÌÌÿÿÿÿ'hºÜþPèÀ¤ ”‹5á‘÷uA`U¢Â¬~mÔŽòîû !þ€This animated GIF file was constructed using Ulead GIF Animator Lite, visit us at http://www.ulead.com to find out more.USSPCMT!ÿ PIANYGIF2.0Image;tktreectrl-2.2.8/demos/pics/outlook-arrow.gif0000700000175600010010000000016110234532777017474 0ustar TimNoneGIF89a ³¿¿¿ÿÿÿ!ù, 0ˆj {3ئ…Ø—ømª÷Iî{Êf†\;tktreectrl-2.2.8/demos/pics/outlook-clip.gif0000700000175600010010000000016110234532775017267 0ustar TimNoneGIF89a ³¿¿¿ÿÿÿ!ù, 0HAåXX@^ÇycFRfZ®èYváy‚XfÁR;tktreectrl-2.2.8/demos/pics/outlook-deleted.gif0000700000175600010010000000021207577521110017740 0ustar TimNoneGIF89a"!ù ,‚¿¿¿ÿÿÿOxºÜK"%d1“1$D„#Å aw#KrÀ)ŠmÃÛ©ÚµÙ|‡‡N>E0¹„ä‚ÊÇÆX²ŠÈÄ;aDß›cÝH;tktreectrl-2.2.8/demos/pics/outlook-draft.gif0000700000175600010010000000020607577521110017435 0ustar TimNoneGIF89a"!ù ,‚ÿÿ¿¿¿ÿÿÿKxºÜW0‚Ig¼Œ¸ÁµEàmW–Ó`vç@@‚ffåë!oqy‚‚ÎÔËn‚Ž×IB8V*MuˆùTAÝÏ,ì(›ÏŠ;tktreectrl-2.2.8/demos/pics/outlook-folder.gif0000700000175600010010000000020507577521110017607 0ustar TimNoneGIF89a"!ù ,‚ÿÿ¿¿¿ÿÿÿJxºÜG0J¤Ö¹3¦iÛ ˜C÷ Pà¾.°§à~@PNØCÙvA$¡ƒº)wLSR7ù€²¬g9H‰.˜ïÅA.› ;tktreectrl-2.2.8/demos/pics/outlook-group.gif0000700000175600010010000000022007577521110017465 0ustar TimNoneGIF89a"!ù ,‚ÿÿÿ¿¿¿ÿÿÿUhº Àp9õZ†”Ji-š6 Æ£)!X k™šÁø© ë,P2Ábd“¨„ŠÚÀ% ! dz¤yn œR¡0%`!ÒŒX“]¼èoD°moˇ|’;tktreectrl-2.2.8/demos/pics/outlook-inbox.gif0000700000175600010010000000020507577521110017453 0ustar TimNoneGIF89a"!ù ,‚ÿÿ¿¿¿ÿÿÿJxºÜW0$|’Â*ñä›õhÖÔTªR* \À …Î<9ÝgΛ¯'=zo”Õ³ûÖÎýºõîº/‚ÿúøó•Ñ«ßL~}h÷íK“†O¿ímºÓ™aÂÿ°ìu)¥g $À0  -”P‚ 4xPƒ ¶SC "¨Y…=Gb-€p /x€L TðB TPÁ:@€Â¸ðA .ºPÂr2a¨2Ü0æA:èà‚-% pÀ9 i@ÿLn Ã ä`À,Zp#O:UMá7_^| $ 2\P’Læ@ààf’G2y¤Ä ž3"(X‚=[êdá2’ÙYË *$yhà&m²Ùfà“l°Á 5xð áˆà‚Š(„ðÂ{ö)T€|ö…Ž ¬à§LFiE¾.ʨ›“ °À’9±¤‰? ¹ ˜z£ŽOý)«"ˆj©“¤É¤ŠFê+›¿þŠC¹è¶i„’⮵²TÄœ¥êK÷i™W /æé»9 @è&¬°ÂçòÚ+“ê*å.ˆ ÿ YR[ÓæÅÅŒ,)烯¿¢¬0¯ç.L²óæó¹8\ð¤@pã ­i|S<=ó%ƒ0y2¯¿"Œ°Ëì²äp :¨¸í™6'©C ùò·/Púu¼ϵ”ðÁ'®¨h› £ŒtÂH/p’Mz{‹õn œ| ˜¿[8Z-|`·BÛ¬›å¶œ®Â8ŒnN®(¥š1k­bÑ“£ £×~‰êB%ªÈ€”‘:^.›Œ§ÜæìæÂˆ€å¹¾‰w·‰fÑÔРùŠ®œ¾pYH¢©!l޵¤N—[@ —ük½öùdšÊd;Ü:jÿÔWЂ‚û¼±×ö¡SC(L´:øÐúÑ*“Lrìæûk§!Øö65J=éI,êBp« à@7X‰ñxD¾äëG·b’FÖ°^É­GKíæ­ oQûž Y$0Rª,¡¾ÑQ/‚¸G¥ƒ½iÄj”õ‚•ƒ$€›SaÕnw;À^/Ü€>€Œõ)8{¹ L°H IŒs]ÂvUêÉ­e:àÀ 8ð°áÛçÁ1|òÓ 2ÐŒ/]ÑŠcyP€,5íƒ £YÊÐu®p@ˆ¤ü$ pÐ]‚Iò°ÿb6ØÓ k¸1·0c†$°Xh€,‘…‘il{\ã°‚H`è€$ˆIäà{O _'›ç;”È¢$åϦ²ud.8Ý \€Ð@"˜’ )þ­ÌdŒRÊpËØ’`cóLèK"uo¬ï6„\ipëñ#T.ƒ"… \˜£\œìw¹Eåïu‘#ÃBÀà—!àA@XH1B"©6¾4ÏFçÐçxÄV­“”€SÝJ|°¤–¶IR†¤ÞÂt¥ÐD&‰À'PIŒÎ‘—ntcÑXd/¼à¨¨˜2Y³\`Xû–Œ)y©)¦SÿÍÕAI6)7ýr‹‚Q´8 "m >`Ò“Bæ­49 0•0%‚Üi‚QII L¿À$V»jf£Iɪád$²Z1t±Éd#+”,‡¿–ÑîdÄ¢›Ô„Ó¡íš¡Û×VÞAƒÍ¥4w4Mm» Û®·M¯{"ƒÔÛ)H륯ÔßÊtU¬,©j¦’ÀQ/‚¥mŸ‚GØÃn-‰X¬¢ÚÐy +³š©`'U°vAÖWŒ•©Ê ë®_ê jPÔi^ ƒŽ+µ@Û“ØÖoѱÜ-¬ÄX—¬•uÊ‚)ëx{?ÞÆN‘óâî2¤Þê8nÿ>›R ?¥m<½UØßs/Ê2¬ÈÒt7g±hA’Zë+%è –¦¿¢ž›Œ3µ2WE;æ H¼ºä|û±A v¼‚£¾@~¤ÌJ¥Ë9yª…4ày)õË$~ïn8 ½EÕdµ«›À‚ia¥G{ÍQ˜XªŒ‹ÏŸ]¢B$A5ŠKÈÏ^U“§ö¶'€Ó¦)j}Æ·îÖB"`rÃ*Ü3WŒÚíÖ¶¿TBÜlT5^ÎlFJ:"” £ÞRÂup1™Ií-j¨öëZ¨ƒ'&úИ¬è%1©¢ U`~]ñ¤¨:ædõWϧ“ßéLƒiù'ÇPnŒdÿP÷¨…ä‘EÍÀ9æù€'ì!¿§"$ÔñŽ“¦¶ƒG7"jTfÒ˜Yˆ-P;Œ+…ç‘bÉB-° J£:6@Ø&j¨´×„Iò’³MÜöüËíK¶‘Gœh$#é€]2Ô¯èž ½='U :¨#/p™m/XÁ¥÷ao?¥Dx€ïJ ¾hÑ™Î|¤:ÛX"ÔZ?p§½„é`Šv2’Lº&nK]Nœ’/¬ã·ó Eξðš‚0öT‚LèZ>F‰¨ž„Qli·¼R‚XÕy¿¤—>ŠN¼¡w—€ôÞZÖÒœæÌ%¨% ÿ 8}mö 0éiC˜@[GP*T¡áµyUì›ÍÇÆ‡èDuHÖ.úäÜàð¬µÈD;—€ÿ{ìßws¦ ·Ÿý§WP&´=ût9vA¨<¡P äÊÃâ]m‚ AõÓÅUG þÆŸ¹Êm<1ݽú ¨\ôÁèé|w$ ’çŸø-#€Í2Þ¡´èË$~ñ³ýþl§½C#\ l]5àQjôeRh³cR\ýâ#A0p1àT4 v%@% >°÷šveTEÆKHÄzá—-"à~$!$§r;+$—"@""~Ø”ÿ-¡”-ù²u£‡øwæÄ{øÖ!!G%JÑgW¶€1(¤Á#És€]‹RUL‚„~1î¸c2€6APp!kÄ{•Ç3&Ç€ÒyR £Ç«Ð3<óÙBzl'm—‚©b-µ€ yéC6Í –‘ 7P$Ñ1nrPe9Jå^Ì«R NX‡Ik”K—–>ȆÑ×%ÑN‡p|8‡ €}$  €_‚ ^R„$@<-°°4/…02ÅH€à °5ËÁG›‡¡hÖ×Lï° ¦‡K@\Ã|`w†oè@!ÙB!`$ÿ4—a |„1ë"°*ðEƒ2eÔX.óA={t vu^—f)¨hcO‰ûv6+Ø„ I‘NxWéSAþb‰×Â3¡·¡ŒlH ÍÐOàR5àÂ]`–H¿Ò‘‘B„@"vt+PI2"R±á'oXR$ŠO÷v'—x'uR–2Í#Ç@ÜÒ\)–+9V^&)ØS!ï£DwW1²r¦¸|UÑc™—?Æ>âH.wC£h à õr+ÎÕ$/@1P~µMZv7ý5ÑÃUj6):p~¤= ”=9Ö^RHÎØÛH˜0¡}$˜,¹ˆ ÿr¦ìbA$.Ä((%'vóg¶E=e´báòKÄs:€Bõqˆ,7:˜W“U™•‰˜„•É/-0*€—@Òb«µ! ”GÐa55KÒ-’R.”ó$ `•BÑTIáG¦‚iÆ%;2˜1Ù—·˜¬™#$PÓ„QV5°ÃU0u'$œÉ’_ï‰YÀÈžS&5ZÖgU³^+. ?fl²é’aa•5ù7[YU‰vb6HDuQƒYãòKZ¦BÔk_†0&c`B ×-ÜÕ_G°žˆs6}6ù¢ÈLÌt˜2)RÜ9l(ʶaÌu^NSÿ[ ·(F™–”T%)F IºHp^òò¡°§B\)ˆUd‹¥4 ¶›Šæ•©”MK¶MA²£¾42‘SX­æ¥÷‰nR¢__ÖjP¤™5ì‚98à›Ø„>òÈÆ€6y‹â “ÊѢ˴¦˜o^ܲp¶e/ök@ ¦BG0œgú¦Fà_^º£Ü„,Gà@™‹|² —asŠÜ8›¯ Zi•Èõf,pv6lÚã_q9œ SÝ#Zšn4ô9¡¶X¿„^ŠmS6©:ÙbaÈS˜úÒ÷`§Êj˜Ý9“à‰ .‘‡yòwV£ çK°zU° >¦¹ÿI(¬Q©­³­ø©DP#$€ y8ª=B­€R ñ:ŽÀaª±©ü±'6 WEvTÆ\”ª ç_)Õ¥…€p«Až°p²êkjLãº`(&G!:m¶š„©!n¸!úÊ¢Þ9­>qr§â ±bg:eg×BêDáŠI½4¦õbkŸ{@;êWÃY5&ôK˜Ò¯÷qŠŽ¡:ŠˆEðE¥ˆÙµÀcxtˆÿº^/°tltDA¥£Û°е˜d©,4œ –UëJ°ôW¿”e=T®(&%UÓ^ž*²á™§øÐ*£E²Òª¯6pd0d”·²F÷H¦ÇF±vÿ†!Pj< €qtÜÔe]5fôÉMùkÁ™B½v u;‘Oº ójê´)º˜rP+- B`zûåÔ@P/ËP…tðæQ;¹.5óg”©eTEPéj©G€×G:+ ²á%¶Ñ¢Sêv/˜-2`z}'¾áæABA0qNCI ¹aK™÷óž0°›&®Wv^þ…$y©%Ð6¦K‘ת£äŒ§zrKâ!%Kt¦v¡¢\À`{l”Kü¸! èëK1e¦š¤£= hÿ»aÛ°2+Lp¶€?¶Ø ÿ² LŽP»ºD§É¥)75 òGr * ¸ÀpKò×PºIáÓÂÎk^T;º£ìÉIäv«+@-ØH[ÀXJ¯Ö@:úŒG«‰Ù-hzÓ+ò'*7ð(G0»A`{gxešÀÊ£þe«&´‘¬(À™dDŠ;¶.Œ««·´HÀÏÚ€]‚ÃóÀ*›L:ì…­¢ 0ÀiØ'†t˜¡Ò¸gDG´Á¸·Zk~gÈÀ h­V¤nÄçµI@GÔz‰lD˜Ä°C@ "pÉÕ»>ÇsÀR˜ÀI›Æœ ±©[GÇ·wi£'ÿ"˜N—vfKUq‰<¹²ªI¦¹×‘Ô»ÜB@Î˵áÚ΀q@·ÇÃÉÚ¬ùàÉ×;¥ ¬½€átL‡¬øásD½üBä\~‘dÎl„b¤I¯|w =ÐÑ<À<  àÁ‘´t÷L³ ¥µBa£j¯‹ÍJ;ÍÐPºµÉ ú„耈éðy’-l4IjDQÛPQû-þ%L@ÏBÐ=„­}Çt³ÏUq†‡tt+Æ&‹#!%Ðô@ЙW*z‹E{?/œ˜"MÑÝÐv?¸¾ì<€b ×Α4Õµ7mçPBHðgÿÒ‘TKˆ»6G1ÖJkÆÔ\Ƙ¸OPˆ#šÝ#0‰«~Bp{ø—‚k·²´ŒÂnô×Ríwì‡ie"„€MkWØßw†}Ô*‡¥8À;\Ój}½7<ÖaMº}¢¡L 6€Û·Ø¢÷Üà~2{= ×¯|†­çzÈgƒÈ »æTÇÏ”‚"{riN~„‡‚CÃK;ÓÒ¬Ù§;²˜mÀ}ëNÕ‚NL‡?¸v£wum¾Cøw=ÕDˆ ¥8ˆ²íP¢'}ŠÁQ\’ Pyÿü¢y;ÐzŠúÊÃ[9ÃpHz†Ý£7â?Èv|˜)PØ2XÜØkÐÕÂᲉ´(ÁÓûј¹§ ‰¯y§^Hç”]Ówî ¼çANªÈÓ/ƒ® ~DçËŠ§d ¨’-ܲå Üå’Êó±ÞŸÌ*ðJ¥½±X ¯.ªñÝÆ“-êÛKߥͧ.©~‡_™Ù ªÃÎé¾þÉŒîç©úèjÿë;…g}íFËTi›¢Ì%Ÿnìñ½¢ó äW¹Æ,Ê·7 ß­Ní>ŽãšnÃ³Ž·\~Ü·þåçßéÊzñÛè~ŠvnÙòýã3ýî0­®ËŽ‹Oh¥˜—áy[Ö´îè»éÞðB.‚ækŽÉ |ð¢\ºdÓL{ì—íð >ŽFÁ•\BèÉ´ ŒéÖÇëžlÖûNÜnëZ>8ã­ŽòÀ-ìEqÓð½ð0ßðz®ìçx¥|nñ;Ϙ4ì†ší»¾íßí¯ÆG¯í8ìÚóönÀ@þô4Íî2¯îæÎÆM_ÖÌ>ëmñföÐÈñü^ëþ^ôµ(òj¬ÿöJøÆ}¯qïôP¿î8=õî~´5?çx•:Ÿêåz¢/­í¥Êí^nô†ÿ±uººû^î#ÿêŽïòpoºr/ùOùaùãžób­ù’ÞõëâúW:øŒÎõÖ{î’žöÏôyû­?óQûyEêU_ùwûš|ùË¿L<¼|ü`ÖÅ}óÂô<_W~úA“úáž÷*íͯî,õÑOõ´Ÿ‰Õoê§ý|¿òÜÿõâüh $-‚„ƒ†…ˆ†-‹‚ŒŒ…‡‘‘‰‰Ž”“Šƒ•ˆ$„˜”—¤Ÿš©š«‡§Ÿ®¢±—²´©  –¤¥£»¢§“’¿ž°¥µÀ‹ŽÊÿɜʰËǽ¸Ò´ÌÖ«ž˜Ñ™Ô؊͸ءÒÝ™¨­Á®Ù¯¨æ½Û»îôíºòÅÑíüœÙèñàAÛGœ3o¡äÕ8k1ƒ›¶Y’ø­ÝÄaâô)¼õðV?q_1ŒµÑ;ûécH°â¦ôªL'IØAnÉJÞé ç7’æ.KîbÇ‚óª# p«1yBÔù =_øXZ,öò µ’-N4øóœÔuTü9+(Ø”6Af,·Ñ£Ëu(ë哚VÔ\X»í]¸íCpƒ# ¤‰lÇkByž5{íY[Š‹áÅÈJcP»\ñ>µšìd‘VÊZ·°ÊÃľò›ÔÓ}§õ…ü(f¥š§rþåY"hUÓòž<-\§^Ú;W¶6ú𱩡ðN ³±µÓÌyß¾üõm¾¸Oç.þ7¤S‚Ës7×ú·ºîrZ©ß·ÞÔØbïÁteàÉ'[Ú¸•Ùy›õ,g±³TrÐq$ßVÎ]`ÒeçÚ~£õçÛLbÙ„˜O‘9g Cã%ø›‚ŠQçTІ ;tktreectrl-2.2.8/demos/pics/small-dll.gif0000700000175600010010000000046707577521110016535 0ustar TimNoneGIF89a²3f™Ìÿ333!ù,‚ÿÿÿ¿¿¿ÿÿÿI8²ÜóP˜IgðÉJ‹ÁG$Š©MAp…ªLáVqÀòZ² öùåVIOð:ÎF¢Á¹ý¦ATꤥF¿à¨¬D.«!þ€This animated GIF file was constructed using Ulead GIF Animator Lite, visit us at http://www.ulead.com to find out more.USSPCMT!ÿ PIANYGIF2.0Image;tktreectrl-2.2.8/demos/pics/small-exe.gif0000700000175600010010000000016307577521106016541 0ustar TimNoneGIF89a"!ù ,‚¿¿¿¿ÿÿÿ8xºÜ0Ê ‡½ø†ø`øm(Š’år!Ï´ÌÖ8qçôÎÛ°ßÌ÷#òH®`Él:Žè";tktreectrl-2.2.8/demos/pics/small-file.gif0000700000175600010010000000052207577521106016676 0ustar TimNoneGIF89a²3f™Ìÿ333!ù,ƒÿèÿÿÿ¿¿¿ÿÿÿLˆI+¹X Í÷Ø¥uÜ€É,ª¥+ÂqZ¬¬'K[Q¿qØiÄV®ø OÃ9›*­/–ÀTL¾hTÍ+:˜ÏèðuͺD!þ€This animated GIF file was constructed using Ulead GIF Animator Lite, visit us at http://www.ulead.com to find out more.USSPCMT!ÿ PIANYGIF2.0Image;tktreectrl-2.2.8/demos/pics/small-folder.gif0000700000175600010010000000046307577521106017236 0ustar TimNoneGIF89a²3f™Ìÿ333!ù,‚ÿÏÏ`ÿÏÿÿÿÿÏïïïEºÜ+÷Ž1¥ˆéÄøàEŠpèU “™½pA°Ë8mß„¬c°žpÕq³âk(LÖ L$Áé YA€vËåR¾`p!þ€This animated GIF file was constructed using Ulead GIF Animator Lite, visit us at http://www.ulead.com to find out more.USSPCMT!ÿ PIANYGIF2.0Image;tktreectrl-2.2.8/demos/pics/small-txt.gif0000700000175600010010000000045607577521104016602 0ustar TimNoneGIF89a²3f™Ìÿ333!ù,‚ÿ¿¿¿ÿÿÿ@( ÄÞ* H½0Ödz¨D(Š (Qž à0ª©€i¸Î¡«Ã÷W“2_kg Òj=ÐÎUdý’¿æl@­Z{“å2’!þ€This animated GIF file was constructed using Ulead GIF Animator Lite, visit us at http://www.ulead.com to find out more.USSPCMT!ÿ PIANYGIF2.0Image;tktreectrl-2.2.8/demos/pics/unchecked.gif0000700000175600010010000000011007577521110016566 0ustar TimNoneGIF89a , ßßßÿÿÿ!Œ6í/´ÖȬÆS_é}Y8pd ’¦š†˜ÇrtZ;tktreectrl-2.2.8/demos/random.tcl0000700000175600010010000002503010536414402015176 0ustar TimNone# RCS: @(#) $Id: random.tcl,v 1.26 2006/12/07 03:55:27 treectrl Exp $ set RandomN 500 set RandomDepth 5 # # Demo: random N items # proc DemoRandom {} { set T [DemoList] InitPics folder-* small-* set height [font metrics [$T cget -font] -linespace] if {$height < 18} { set height 18 } # # Configure the treectrl widget # $T configure -itemheight $height -selectmode extended \ -showroot yes -showrootbutton yes -showbuttons yes -showlines $::ShowLines \ -scrollmargin 16 -xscrolldelay "500 50" -yscrolldelay "500 50" # # Create columns # $T column create -expand yes -weight 4 -text Item -itembackground {#e0e8f0 {}} \ -tags colItem $T column create -text Parent -justify center -itembackground {gray90 {}} \ -uniform a -expand yes -tags colParent $T column create -text Depth -justify center -itembackground {linen {}} \ -uniform a -expand yes -tags colDepth $T configure -treecolumn colItem # # Create elements # $T element create elemImgFolder image -image {folder-open {open} folder-closed {}} $T element create elemImgFile image -image small-file $T element create elemTxtName text -wrap none \ -fill [list $::SystemHighlightText {selected focus}] $T element create elemTxtCount text -fill blue $T element create elemTxtAny text $T element create elemRectSel rect -showfocus yes \ -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] # # Create styles using the elements # set S [$T style create styFolder] $T style elements $S {elemRectSel elemImgFolder elemTxtName elemTxtCount} $T style layout $S elemImgFolder -padx {0 4} -expand ns $T style layout $S elemTxtName -minwidth 12 -padx {0 4} -expand ns -squeeze x $T style layout $S elemTxtCount -padx {0 6} -expand ns $T style layout $S elemRectSel -union [list elemTxtName] -iexpand ns -ipadx 2 set S [$T style create styFile] $T style elements $S {elemRectSel elemImgFile elemTxtName} $T style layout $S elemImgFile -padx {0 4} -expand ns $T style layout $S elemTxtName -minwidth 12 -padx {0 4} -expand ns -squeeze x $T style layout $S elemRectSel -union [list elemTxtName] -iexpand ns -ipadx 2 set S [$T style create styAny] $T style elements $S {elemTxtAny} $T style layout $S elemTxtAny -padx 6 -expand ns TreeCtrl::SetSensitive $T { {colItem styFolder elemRectSel elemImgFolder elemTxtName} {colItem styFile elemRectSel elemImgFile elemTxtName} } TreeCtrl::SetDragImage $T { {colItem styFolder elemImgFolder elemTxtName} {colItem styFile elemImgFile elemTxtName} } # # Create items and assign styles # set clicks [clock clicks] $T item configure root -button auto set items [$T item create -count [expr {$::RandomN - 1}] -button auto] set added root foreach itemi $items { set j [expr {int(rand() * [llength $added])}] set itemj [lindex $added $j] if {[$T depth $itemj] < $::RandomDepth - 1} { lappend added $itemi } if {rand() * 2 > 1} { $T item collapse $itemi } if {rand() * 2 > 1} { $T item lastchild $itemj $itemi } else { $T item firstchild $itemj $itemi } } puts "created $::RandomN-1 items in [expr [clock clicks] - $clicks] clicks" set clicks [clock clicks] lappend items [$T item id root] foreach item $items { set numChildren [$T item numchildren $item] if {$numChildren} { $T item style set $item colItem styFolder colParent styAny colDepth styAny $T item element configure $item \ colItem elemTxtName -text "Item $item" + elemTxtCount -text "($numChildren)" , \ colParent elemTxtAny -text "[$T item parent $item]" , \ colDepth elemTxtAny -text "[$T depth $item]" } else { $T item style set $item colItem styFile colParent styAny colDepth styAny $T item element configure $item \ colItem elemTxtName -text "Item $item" , \ colParent elemTxtAny -text "[$T item parent $item]" , \ colDepth elemTxtAny -text "[$T depth $item]" } } puts "configured $::RandomN items in [expr [clock clicks] - $clicks] clicks" bind DemoRandom { TreeCtrl::DoubleButton1 %W %x %y break } bind DemoRandom { set TreeCtrl::Priv(selectMode) toggle RandomButton1 %W %x %y break } bind DemoRandom { set TreeCtrl::Priv(selectMode) add RandomButton1 %W %x %y break } bind DemoRandom { set TreeCtrl::Priv(selectMode) set RandomButton1 %W %x %y break } bind DemoRandom { RandomMotion1 %W %x %y break } bind DemoRandom { RandomRelease1 %W %x %y break } bindtags $T [list $T DemoRandom TreeCtrl [winfo toplevel $T] all] return } proc RandomButton1 {T x y} { variable TreeCtrl::Priv focus $T set id [$T identify $x $y] set Priv(buttonMode) "" # Click outside any item if {$id eq ""} { $T selection clear # Click in header } elseif {[lindex $id 0] eq "header"} { TreeCtrl::ButtonPress1 $T $x $y # Click in item } else { lassign $id where item arg1 arg2 arg3 arg4 switch $arg1 { button { $T item toggle $item } line { $T item toggle $arg2 } column { if {![TreeCtrl::IsSensitive $T $x $y]} { $T selection clear return } set Priv(drag,motion) 0 set Priv(drag,click,x) $x set Priv(drag,click,y) $y set Priv(drag,x) [$T canvasx $x] set Priv(drag,y) [$T canvasy $y] set Priv(drop) "" if {$Priv(selectMode) eq "add"} { TreeCtrl::BeginExtend $T $item } elseif {$Priv(selectMode) eq "toggle"} { TreeCtrl::BeginToggle $T $item } elseif {![$T selection includes $item]} { TreeCtrl::BeginSelect $T $item } $T activate $item if {[$T selection includes $item]} { set Priv(buttonMode) drag } } } } return } proc RandomMotion1 {T x y} { variable TreeCtrl::Priv switch $Priv(buttonMode) { "drag" { set Priv(autoscan,command,$T) {RandomMotion %T %x %y} TreeCtrl::AutoScanCheck $T $x $y RandomMotion $T $x $y } default { TreeCtrl::Motion1 $T $x $y } } return } proc RandomMotion {T x y} { variable TreeCtrl::Priv switch $Priv(buttonMode) { "drag" { if {!$Priv(drag,motion)} { # Detect initial mouse movement if {(abs($x - $Priv(drag,click,x)) <= 4) && (abs($y - $Priv(drag,click,y)) <= 4)} return set Priv(selection) [$T selection get] set Priv(drop) "" $T dragimage clear # For each selected item, add 2nd and 3rd elements of # column "item" to the dragimage foreach I $Priv(selection) { foreach list $Priv(dragimage,$T) { set C [lindex $list 0] set S [lindex $list 1] if {[$T item style set $I $C] eq $S} { eval $T dragimage add $I $C [lrange $list 2 end] } } } set Priv(drag,motion) 1 } # Find the item under the cursor set cursor X_cursor set drop "" set id [$T identify $x $y] if {[TreeCtrl::IsSensitive $T $x $y]} { set item [lindex $id 1] # If the item is not in the pre-drag selection # (i.e. not being dragged) see if we can drop on it if {[lsearch -exact $Priv(selection) $item] == -1} { set drop $item # We can drop if dragged item isn't an ancestor foreach item2 $Priv(selection) { if {[$T item isancestor $item2 $item]} { set drop "" break } } if {$drop ne ""} { scan [$T item bbox $drop] "%d %d %d %d" x1 y1 x2 y2 if {$y < $y1 + 3} { set cursor top_side set Priv(drop,pos) prevsibling } elseif {$y >= $y2 - 3} { set cursor bottom_side set Priv(drop,pos) nextsibling } else { set cursor "" set Priv(drop,pos) lastchild } } } } if {[$T cget -cursor] ne $cursor} { $T configure -cursor $cursor } # Select the item under the cursor (if any) and deselect # the previous drop-item (if any) $T selection modify $drop $Priv(drop) set Priv(drop) $drop # Show the dragimage in its new position set x [expr {[$T canvasx $x] - $Priv(drag,x)}] set y [expr {[$T canvasy $y] - $Priv(drag,y)}] $T dragimage offset $x $y $T dragimage configure -visible yes } default { TreeCtrl::Motion1 $T $x $y } } return } proc RandomRelease1 {T x y} { variable TreeCtrl::Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { "drag" { TreeCtrl::AutoScanCancel $T $T dragimage configure -visible no $T selection modify {} $Priv(drop) $T configure -cursor "" if {$Priv(drop) ne ""} { RandomDrop $T $Priv(drop) $Priv(selection) $Priv(drop,pos) } unset Priv(buttonMode) } default { TreeCtrl::Release1 $T $x $y } } return } proc RandomDrop {T target source pos} { set parentList {} switch -- $pos { lastchild { set parent $target } prevsibling { set parent [$T item parent $target] } nextsibling { set parent [$T item parent $target] } } foreach item $source { # Ignore any item whose ancestor is also selected set ignore 0 foreach ancestor [$T item ancestors $item] { if {[lsearch -exact $source $ancestor] != -1} { set ignore 1 break } } if {$ignore} continue # Update the old parent of this moved item later if {[lsearch -exact $parentList $item] == -1} { lappend parentList [$T item parent $item] } # Add to target $T item $pos $target $item # Update text: parent $T item element configure $item colParent elemTxtAny -text $parent # Update text: depth $T item element configure $item colDepth elemTxtAny -text [$T depth $item] # Recursively update text: depth foreach item [$T item descendants $item] { $T item element configure $item colDepth elemTxtAny -text [$T depth $item] } } # Update items that lost some children foreach item $parentList { set numChildren [$T item numchildren $item] if {$numChildren == 0} { $T item style map $item colItem styFile {elemTxtName elemTxtName} } else { $T item element configure $item colItem elemTxtCount -text "($numChildren)" } } # Update the target that gained some children if {[$T item style set $parent colItem] ne "styFolder"} { $T item style map $parent colItem styFolder {elemTxtName elemTxtName} } set numChildren [$T item numchildren $parent] $T item element configure $parent colItem elemTxtCount -text "($numChildren)" return } # # Demo: random N items, button images # proc DemoRandom2 {} { set T [DemoList] DemoRandom InitPics mac-* $T configure -buttonimage {mac-collapse open mac-expand {}} \ -showlines no return } tktreectrl-2.2.8/demos/span.tcl0000700000175600010010000000420510536414402014660 0ustar TimNone# RCS: @(#) $Id: span.tcl,v 1.5 2006/12/07 03:56:00 treectrl Exp $ # # Demo: Column span # proc DemoSpan {} { set T [DemoList] # # Configure the treectrl widget # $T configure \ -showbuttons no \ -showlines no \ -showroot no \ -xscrollincrement 40 # # Create columns # for {set i 0} {$i < 100} {incr i} { $T column create -itemjustify left -justify center -text "$i" \ -width 40 -tags C$i } # # Create elements # $T state define mouseover for {set i 1} {$i <= 20} {incr i} { set color gray[expr {50 + $i * 2}] $T element create e$i rect -width [expr {$i * 40}] -height 20 \ -fill [list white mouseover $color {}] -outlinewidth 1 \ -outline gray70 $T element create t$i text -text "Span $i" } # # Create styles using the elements # for {set i 1} {$i <= 20} {incr i} { set S [$T style create s$i] $T style elements $S [list e$i t$i] $T style layout $S e$i -detach yes $T style layout $S t$i -expand ns -padx 2 } # # Create items and assign styles # foreach I [$T item create -count 100 -parent root] { for {set i 0} {$i < [$T column count]} {} { set span [expr {int(rand() * 20) + 1}] if {$span > [$T column count] - $i} { set span [expr {[$T column count] - $i}] } $T item style set $I C$i s$span $T item span $I C$i $span incr i $span } } bind DemoSpan { SpanMotion %W %x %y } set ::Span(prev) "" bindtags $T [list $T DemoSpan TreeCtrl [winfo toplevel $T] all] return } proc SpanMotion {w x y} { global Span set id [$w identify $x $y] if {$id eq ""} { } elseif {[lindex $id 0] eq "header"} { } elseif {[lindex $id 0] eq "item"} { set item [lindex $id 1] set column [lindex $id 3] set curr [list $item $column] if {$curr ne $Span(prev)} { if {$Span(prev) ne ""} { eval $w item state forcolumn $Span(prev) !mouseover } $w item state forcolumn $item $column mouseover set Span(prev) $curr } return } if {$Span(prev) ne ""} { eval $w item state forcolumn $Span(prev) !mouseover set Span(prev) "" } return } tktreectrl-2.2.8/demos/style-editor.tcl0000700000175600010010000005241011010124250016327 0ustar TimNone# RCS: @(#) $Id: style-editor.tcl,v 1.16 2007/01/21 22:58:57 treectrl Exp $ namespace eval StyleEditor { variable Info array unset Info } proc StyleEditor::Info {info args} { variable Info if {[llength $args]} { set Info($info) [lindex $args 0] } return $Info($info) } proc StyleEditor::Init {Tdemo} { set w .styleEditor toplevel $w wm title $w "TkTreeCtrl Style Editor" Info Tdemo $Tdemo panedwindow $w.pwH -orient horizontal -borderwidth 0 panedwindow $w.pwH.pwV -orient vertical -borderwidth 0 TreePlusScrollbarsInAFrame $w.pwH.pwV.styleList 1 1 set T $w.pwH.pwV.styleList.t $T configure -showbuttons no -showlines no -showroot no -width 100 -height 200 $T column create -text "Styles" -expand yes -button no -tags C0 $T configure -treecolumn C0 $T notify bind $T { StyleEditor::SelectStyle } Info styleList $T TreePlusScrollbarsInAFrame $w.pwH.pwV.elementList 1 1 set T $w.pwH.pwV.elementList.t $T configure -showbuttons no -showlines no -showroot no -width 100 -height 200 $T column create -text "Elements" -expand yes -button no -tags C0 $T configure -treecolumn C0 $T notify bind $T { StyleEditor::SelectElement } Info elementList $T $w.pwH.pwV add $w.pwH.pwV.styleList $w.pwH.pwV.elementList set fRight [panedwindow $w.pwH.pwV2 -orient vertical] # # Property editor # TreePlusScrollbarsInAFrame $fRight.propertyList 1 1 set T $fRight.propertyList.t $T configure -showbuttons no -showlines no -showroot no $T column create -text "Property" -expand yes -button no -tags {C0 property} \ -itembackground {#E8E8E8 ""} $T column create -text "Value" -expand yes -button no -tags {C1 value} \ -itembackground {#E8E8E8 ""} $T configure -treecolumn property $T notify bind $T { StyleEditor::SelectProperty %S %D } Info propertyList $T # # Style canvas # set fCanvas [frame $fRight.fCanvas -borderwidth 0] set canvas [canvas $fCanvas.canvas -background white \ -scrollregion {0 0 0 0} -borderwidth 0 -highlightthickness 0 \ -xscrollcommand [list sbset $fCanvas.xscroll] \ -yscrollcommand [list sbset $fCanvas.yscroll]] scrollbar $fCanvas.xscroll -orient horizontal \ -command [list $canvas xview] scrollbar $fCanvas.yscroll -orient vertical \ -command [list $canvas yview] # Copy element config info from the selected item in the demo list $Tdemo notify bind StyleEditor { if {[winfo ismapped .styleEditor]} { StyleEditor::StyleToCanvas } } Info canvas $canvas # Create a new treectrl to copy the states/style/elements into, so I don't # have to worry about column width or item visibility in the demo list set T [treectrl $canvas.t] $T configure -itemheight 0 -minitemheight 0 -showbuttons no -showlines no \ -font [$Tdemo cget -font] $T column create grid rowconfigure $fCanvas 0 -weight 1 grid columnconfigure $fCanvas 0 -weight 1 grid $canvas -row 0 -column 0 -sticky news grid $fCanvas.xscroll -row 1 -column 0 -sticky we grid $fCanvas.yscroll -row 0 -column 1 -sticky ns $w.pwH.pwV2 add $fRight.propertyList $fCanvas $w.pwH add $w.pwH.pwV $w.pwH.pwV2 grid rowconfigure $w 0 -weight 1 grid columnconfigure $w 0 -weight 1 grid $w.pwH -row 0 -column 0 -sticky news Info selectedStyle "" Info selectedElement "" wm protocol $w WM_DELETE_WINDOW "ToggleStyleEditorWindow" wm geometry $w -0+0 return } proc StyleEditor::SetListOfStyles {} { set T [Info styleList] set Tdemo [Info Tdemo] # Create elements and styles the first time this is called if {[llength [$T style names]] == 0} { $T element create e1 text -fill [list $::SystemHighlightText {selected focus}] $T element create e2 rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] \ -showfocus yes $T style create s1 $T style elements s1 {e2 e1} $T style layout s1 e2 -union [list e1] -ipadx 2 -ipady 2 -iexpand e $T column configure C0 -itemstyle s1 } # Clear the list $T item delete all # One item for each style in the demo list foreach style [lsort -dictionary [$Tdemo style names]] { set I [$T item create] $T item text $I C0 $style $T item lastchild root $I Info item2style,$I $style } return } proc StyleEditor::SelectStyle {} { set T [Info styleList] set Tdemo [Info Tdemo] set selection [$T selection get] if {![llength $selection]} { [Info elementList] item delete all Info selectedStyle "" StyleToCanvas return } set I [lindex $selection 0] set style [Info item2style,$I] Info selectedStyle $style SetListOfElements $style Info -orient [$Tdemo style cget $style -orient] StyleToCanvas 1 return } proc StyleEditor::SetListOfElements {style} { set T [Info elementList] set Tdemo [Info Tdemo] # Create elements and styles the first time this is called if {[llength [$T style names]] == 0} { $T element create e1 text -fill [list $::SystemHighlightText {selected focus}] $T element create e2 rect -fill [list $::SystemHighlight {selected focus} gray {selected !focus}] \ -showfocus yes $T style create s1 $T style elements s1 {e2 e1} $T style layout s1 e2 -union [list e1] -ipadx 2 -ipady 2 -iexpand e $T column configure C0 -itemstyle s1 } # Clear the list $T item delete all # One item for each element in the style foreach E [$Tdemo style elements $style] { set I [$T item create] $T item text $I C0 "$E ([$Tdemo element type $E])" $T item lastchild root $I Info item2element,$I $E } return } proc StyleEditor::SelectElement {} { set T [Info elementList] set Tdemo [Info Tdemo] set style [Info selectedStyle] set selection [$T selection get] if {![llength $selection]} { Info selectedElement "" SetPropertyList CanvasSelectElement return } set I [lindex $selection 0] set element [Info item2element,$I] Info selectedElement $element SetPropertyList CanvasSelectElement return } proc StyleEditor::SetPropertyList {} { set T [Info propertyList] set Tdemo [Info Tdemo] set style [Info selectedStyle] set element [Info selectedElement] # Create elements and styles the first time this is called if {[llength [$T style names]] == 0} { $T state define header $T element create e1 text \ -fill [list $::SystemHighlightText selected white header] \ -font [list DemoFontBold header] $T element create e2 rect \ -fill [list #ACA899 header $::SystemHighlight selected] \ -outline black -outlinewidth 1 -open nw -showfocus no $T element create eWindow window set S [$T style create s1] $T style elements $S {e2 e1} $T style layout $S e2 -detach yes -indent no -iexpand xy $T style layout $S e1 -expand ns -padx {4 0} set S [$T style create sWindow] $T style elements $S {e2 eWindow} $T style layout $S e2 -detach yes -indent no -iexpand xy $T style layout $S eWindow -expand ns -padx {0 1} -pady {0 1} set S [$T style create sHeader] $T style elements $S {e2 e1} $T style layout $S e2 -detach yes -iexpand xy $T style layout $S e1 -expand ns -padx {4 0} Info editor,pad [MakePadEditor $T] Info editor,expand [MakeExpandEditor $T] Info editor,iexpand [MakeIExpandEditor $T] Info editor,squeeze [MakeSqueezeEditor $T] Info editor,boolean [MakeBooleanEditor $T] Info editor,pixels [MakePixelsEditor $T] update idletasks set height 0 foreach editor {pad expand iexpand squeeze boolean pixels} { set heightWin [winfo reqheight [Info editor,$editor]] incr heightWin if {$heightWin > $height} { set height $heightWin } } $T configure -font [[Info editor,pad].v1 cget -font] \ -minitemheight $height $T column configure C0 -itemstyle s1 } $T item delete all if {$element eq ""} return foreach {header option} { "Draw and Visible" "" "" -draw "" -visible "Detach" "" "" -detach "" -indent "Union" "" "" -union "Expand and Squeeze" "" "" -expand "" -iexpand "" -squeeze "Sticky" "" "" -sticky "Padding" "" "" -ipadx "" -ipady "" -padx "" -pady "Height" "" "" -minheight "" -height "" -maxheight "Width" "" "" -minwidth "" -width "" -maxwidth } { set I [$T item create] if {$header ne ""} { $T item style set $I C0 sHeader $T item span $I C0 2 $T item element configure $I C0 e1 -text $header -fill White $T item state set $I header $T item enabled $I false $T item tag add $I header } else { $T item style set $I value s1 $T item text $I property $option value [$Tdemo style layout $style $element $option] } $T item lastchild root $I } $T column configure C0 -width [expr {[$T column neededwidth C0] * 1.0}] return } proc StyleEditor::SelectProperty {select deselect} { set T [Info propertyList] set Tdemo [Info Tdemo] set style [Info selectedStyle] set element [Info selectedElement] if {[llength $deselect] && ($element ne "")} { set I [lindex $deselect 0] if {[$T item tag expr $I !header]} { set option [$T item text $I property] $T item style set $I value s1 $T item text $I value [$Tdemo style layout $style $element $option] } } set selection [$T selection get] if {![llength $selection]} { Info selectedOption "" return } set I [lindex $selection 0] if {[$T item tag expr $I header]} { Info selectedOption "" return } set option [$T item text $I property] Info selectedOption $option $T item style set $I value sWindow switch -- $option { -draw - -visible { } -padx - -pady - -ipadx - -ipady { $T item element configure $I value eWindow -window [Info editor,pad] set pad [$Tdemo style layout $style $element $option] if {[llength $pad] == 2} { Info -pad,1 [lindex $pad 0] Info -pad,2 [lindex $pad 1] Info -pad,equal 0 } else { Info -pad,1 $pad Info -pad,2 $pad Info -pad,equal 1 } Info -pad,edit "" } -expand - -sticky { $T item element configure $I value eWindow -window [Info editor,expand] set value [$Tdemo style layout $style $element $option] foreach flag {n s w e} { Info -expand,$flag [expr {[string first $flag $value] != -1}] } } -iexpand { $T item element configure $I value eWindow -window [Info editor,iexpand] set value [$Tdemo style layout $style $element $option] foreach flag {x y n s w e} { Info -iexpand,$flag [expr {[string first $flag $value] != -1}] } } -detach - -indent { $T item element configure $I value eWindow -window [Info editor,boolean] Info -boolean [$Tdemo style layout $style $element $option] } -squeeze { $T item element configure $I value eWindow -window [Info editor,squeeze] set value [$Tdemo style layout $style $element $option] foreach flag {x y} { Info -squeeze,$flag [expr {[string first $flag $value] != -1}] } } -minheight - -height - -maxheight - -minwidth - -width - -maxwidth { $T item element configure $I value eWindow -window [Info editor,pixels] Info -pixels [$Tdemo style layout $style $element $option] if {[Info -pixels] eq ""} { Info -pixels,empty 1 [Info editor,pixels].v1 conf -state disabled } else { Info -pixels,empty 0 [Info editor,pixels].v1 conf -state normal } } } return } proc StyleEditor::MakePadEditor {parent} { set f [frame $parent.editPad -borderwidth 0] spinbox $f.v1 -from 0 -to 100 -width 3 \ -command {StyleEditor::Sync_pad 1} \ -textvariable ::StyleEditor::Info(-pad,1) spinbox $f.v2 -from 0 -to 100 -width 3 \ -command {StyleEditor::Sync_pad 2} \ -textvariable ::StyleEditor::Info(-pad,2) $::checkbuttonCmd $f.cb -text "Equal" \ -command {StyleEditor::Sync_pad_equal} \ -variable ::StyleEditor::Info(-pad,equal) pack $f.v1 -side left -padx {0 10} -pady 0 pack $f.v2 -side left -padx {0 10} -pady 0 pack $f.cb -side left -padx 0 -pady 0 bind $f.v1 { StyleEditor::Sync_pad 1 } bind $f.v2 { StyleEditor::Sync_pad 2 } return $f } proc StyleEditor::MakeExpandEditor {parent} { set f [frame $parent.editExpand -borderwidth 0] foreach flag {w n e s} { $::checkbuttonCmd $f.$flag -text $flag -width 1 \ -variable ::StyleEditor::Info(-expand,$flag) \ -command {StyleEditor::Sync_expand} pack $f.$flag -side left -padx 10 } return $f } proc StyleEditor::MakeIExpandEditor {parent} { set f [frame $parent.editIExpand -borderwidth 0] foreach flag {x y w n e s} { $::checkbuttonCmd $f.$flag -text $flag -width 1 \ -variable ::StyleEditor::Info(-iexpand,$flag) \ -command {StyleEditor::Sync_iexpand} pack $f.$flag -side left -padx 10 } return $f } proc StyleEditor::MakePixelsEditor {parent} { set f [frame $parent.editPixels -borderwidth 0] spinbox $f.v1 -from 0 -to 10000 -width 10 \ -command {StyleEditor::Sync_pixels} \ -textvariable ::StyleEditor::Info(-pixels) \ -validate key -validatecommand {string is integer %P} $::checkbuttonCmd $f.cb -text "Unspecified" \ -command {StyleEditor::Sync_pixels} \ -variable ::StyleEditor::Info(-pixels,empty) pack $f.v1 -side left -padx 0 -pady 0 pack $f.cb -side left -padx 0 -pady 0 bind $f.v1 { StyleEditor::Sync_pixels } return $f } proc StyleEditor::MakeSqueezeEditor {parent} { set f [frame $parent.editSqueeze -borderwidth 0] foreach flag {x y} { $::checkbuttonCmd $f.$flag -text $flag -width 1 \ -variable ::StyleEditor::Info(-squeeze,$flag) \ -command {StyleEditor::Sync_squeeze} pack $f.$flag -side left -padx 10 } return $f } proc StyleEditor::MakeBooleanEditor {parent} { set f [frame $parent.editBoolean -borderwidth 0] foreach value {yes no} { $::radiobuttonCmd $f.$value -text $value \ -variable ::StyleEditor::Info(-boolean) \ -value $value \ -command {StyleEditor::Sync_boolean} pack $f.$value -side left -padx 10 } return $f } proc StyleEditor::Sync_orient {} { set Tdemo [Info Tdemo] set style [Info selectedStyle] $Tdemo style configure $style -orient [Info -orient] return } proc StyleEditor::Sync_pad {index} { set Tdemo [Info Tdemo] set style [Info selectedStyle] set element [Info selectedElement] set option [Info selectedOption] if {[Info -pad,equal]} { if {$index == 1} { Info -pad,2 [Info -pad,1] } else { Info -pad,1 [Info -pad,2] } } $Tdemo style layout $style $element $option [list [Info -pad,1] [Info -pad,2]] Info -pad,edit $index StyleToCanvas return } proc StyleEditor::Sync_pad_equal {} { if {![Info -pad,equal]} return if {[Info -pad,edit] eq ""} { Info -pad,edit 1 } if {[Info -pad,edit] == 1} { Info -pad,2 [Info -pad,1] } else { Info -pad,1 [Info -pad,2] } Sync_pad [Info -pad,edit] return } proc StyleEditor::Sync_expand {} { set Tdemo [Info Tdemo] set style [Info selectedStyle] set element [Info selectedElement] set option [Info selectedOption] set value "" foreach flag {n s w e} { if {[Info -expand,$flag]} { append value $flag } } $Tdemo style layout $style $element $option $value StyleToCanvas return } proc StyleEditor::Sync_iexpand {} { set Tdemo [Info Tdemo] set style [Info selectedStyle] set element [Info selectedElement] set option [Info selectedOption] set value "" foreach flag {x y n s w e} { if {[Info -iexpand,$flag]} { append value $flag } } $Tdemo style layout $style $element $option $value StyleToCanvas return } proc StyleEditor::Sync_squeeze {} { set Tdemo [Info Tdemo] set style [Info selectedStyle] set element [Info selectedElement] set option [Info selectedOption] set value "" foreach flag {x y} { if {[Info -squeeze,$flag]} { append value $flag } } $Tdemo style layout $style $element -squeeze $value StyleToCanvas return } proc StyleEditor::Sync_boolean {} { set Tdemo [Info Tdemo] set style [Info selectedStyle] set element [Info selectedElement] set option [Info selectedOption] $Tdemo style layout $style $element $option [Info -boolean] StyleToCanvas return } proc StyleEditor::Sync_pixels {} { set Tdemo [Info Tdemo] set style [Info selectedStyle] set element [Info selectedElement] set option [Info selectedOption] set value [Info -pixels] if {[Info -pixels,empty]} { set value {} [Info editor,pixels].v1 conf -state disabled } else { [Info editor,pixels].v1 conf -state normal } $Tdemo style layout $style $element $option $value StyleToCanvas return } proc StyleEditor::StyleToCanvas {{scroll 0}} { set Tdemo [Info Tdemo] set canvas [Info canvas] set style [Info selectedStyle] $canvas delete all if {$style eq ""} { $canvas configure -scrollregion {0 0 0 0} return } set T $canvas.t $T configure -itemheight 0 $T column configure 0 -width {} eval $T state undefine [$T state names] eval $T style delete [$T style names] eval $T element delete [$T element names] # Copy states foreach state [$Tdemo state names] { $T state define $state } # Copy elements foreach E [$Tdemo style elements $style] { $T element create $E [$Tdemo element type $E] foreach list [$Tdemo element configure $E] { lassign $list name x y default current $T element configure $E $name $current } } # Copy style $T style create $style -orient [$Tdemo style cget $style -orient] $T style elements $style [$Tdemo style elements $style] foreach E [$T style elements $style] { eval $T style layout $style $E [$Tdemo style layout $style $E] $T style layout $style $E -visible {} } # Find a selected item using the style to copy element config info from set match "" foreach I [$Tdemo selection get] { foreach S [$Tdemo item style set $I] C [$Tdemo column list] { if {$S eq $style} { set match $I break } } if {$match ne ""} break } # No selected item uses the current style, look for an unselected item if {$match eq ""} { foreach I [$Tdemo item range first last] { foreach S [$Tdemo item style set $I] C [$Tdemo column list] { if {$S eq $style} { set match $I break } } if {$match ne ""} break } } if {$match ne ""} { set I $match foreach state [$Tdemo item state get $I] { if {[lsearch -exact [$Tdemo state names] $state] != -1} { $T item state set root $state } } foreach state [$Tdemo item state forcolumn $I $C] { $T item state set root $state } foreach E [$Tdemo item style elements $I $C] { foreach list [$Tdemo item element configure $I $C $E] { lassign $list name x y default current set masterDefault [$Tdemo element cget $E $name] set sameAsMaster [string equal $masterDefault $current] if {!$sameAsMaster && ![string length $current]} { set sameAsMaster 1 set current $masterDefault } if {$sameAsMaster} { } elseif {$name eq "-window"} { $T style layout $style $E -width [winfo width $current] \ -height [winfo height $current] } else { $T element configure $E $name $current } } } } if 0 { # Do this after creating styles so -defaultstyle works foreach list [$Tdemo configure] { if {[llength $list] == 2} continue lassign $list name x y default current $T configure $name $current } } set I root $T item style set $I 0 $style set scale 2 set dx 10 set dy 10 scan [$T item bbox $I 0] "%d %d %d %d" x1 y1 x2 y2 $canvas create rectangle \ [expr {$dx + $x1 * $scale}] [expr {$dy + $y1 * $scale}] \ [expr {$dx + $x2 * $scale}] [expr {$dy + $y2 * $scale}] \ -outline gray90 foreach E [$T style elements $style] { scan [$T item bbox $I 0 $E] "%d %d %d %d" x1 y1 x2 y2 $canvas create rectangle \ [expr {$dx + $x1 * $scale}] [expr {$dy + $y1 * $scale}] \ [expr {$dx + $x2 * $scale}] [expr {$dy + $y2 * $scale}] \ -tags $E } scan [$T item bbox $I 0] "%d %d %d %d" x1 y1 x2 y2 incr dy [expr {($y2 - $y1) * $scale + 20}] # Now give the style 1.5 times its needed space to test expansion scan [$T item bbox $I 0] "%d %d %d %d" x1 y1 x2 y2 $T column configure 0 -width [expr {($x2 - $x1) * 1.5}] $T configure -itemheight [expr {($y2 - $y1) * 1.5}] scan [$T item bbox $I 0] "%d %d %d %d" x1 y1 x2 y2 $canvas create rectangle \ [expr {$dx + $x1 * $scale}] [expr {$dy + $y1 * $scale}] \ [expr {$dx + $x2 * $scale}] [expr {$dy + $y2 * $scale}] \ -outline gray90 foreach E [$T style elements $style] { scan [$T item bbox $I 0 $E] "%d %d %d %d" x1 y1 x2 y2 $canvas create rectangle \ [expr {$dx + $x1 * $scale}] [expr {$dy + $y1 * $scale}] \ [expr {$dx + $x2 * $scale}] [expr {$dy + $y2 * $scale}] \ -tags $E } scan [$canvas bbox all] "%d %d %d %d" x1 y1 x2 y2 incr x2 10 incr y2 10 $canvas configure -scrollregion [list 0 0 $x2 $y2] if {$scroll} { $canvas xview moveto 0.0 $canvas yview moveto 0.0 } CanvasSelectElement return } proc StyleEditor::CanvasSelectElement {} { set canvas [Info canvas] set style [Info selectedStyle] set element [Info selectedElement] $canvas itemconfigure all -fill "" if {$element ne ""} { $canvas itemconfigure $element -fill gray75 } return } tktreectrl-2.2.8/demos/textvariable.tcl0000700000175600010010000000430410536414402016411 0ustar TimNone# RCS: @(#) $Id: textvariable.tcl,v 1.7 2006/11/30 02:41:39 treectrl Exp $ proc DemoTextvariable {} { set T [DemoList] # # Configure the treectrl widget # $T configure -showroot no -showbuttons no -showlines no \ -selectmode extended -xscrollincrement 20 \ -yscrollincrement 10 -showheader yes if {!$::clip} { # Hide the borders because child windows appear on top of them $T configure -borderwidth 0 -highlightthickness 0 } # # Create columns # $T column create -text "Resize Me!" -justify center -tags C0 $T configure -treecolumn C0 # # Create elements # $T element create eWindow window $T element create eRect rect $T element create eText1 text -width 300 $T element create eText2 text -wrap none # # Create styles using the elements # set S [$T style create s1 -orient horizontal] $T style elements $S eText1 $T style layout $S eText1 -padx 10 -pady 6 -squeeze x set S [$T style create s2 -orient vertical] $T style elements $S {eRect eText2 eWindow} $T style layout $S eRect -union {eText2 eWindow} -ipadx 8 -ipady 8 -padx 4 -pady {0 4} $T style layout $S eText2 -pady {0 6} -squeeze x $T style layout $S eWindow -iexpand x -squeeze x # # Create items and assign styles # set I [$T item create] $T item style set $I C0 s1 $T item element configure $I C0 eText1 -text "Each text element and entry widget share the same -textvariable. Editing the text in the entry automatically updates the text element." $T item lastchild root $I foreach i {0 1} color {gray75 "light blue"} { set I [$T item create] $T item style set $I C0 s2 if {$::clip} { set clip [frame $T.clip$I -borderwidth 0] set e [$::entryCmd $clip.e -width 48 -textvariable tvar$I] $T item element configure $I C0 \ eRect -fill [list $color] + \ eText2 -textvariable tvar$I + \ eWindow -window $clip -clip yes } else { set e [$::entryCmd $T.e$I -width 48 -textvariable tvar$I] $T item element configure $I C0 \ eRect -fill [list $color] + \ eText2 -textvariable tvar$I + \ eWindow -window $e } $T item lastchild root $I set ::tvar$I "This is item $I" } return } tktreectrl-2.2.8/demos/www-options.tcl0000700000175600010010000001743510536414402016245 0ustar TimNone# RCS: @(#) $Id: www-options.tcl,v 1.14 2006/11/30 02:41:39 treectrl Exp $ proc DemoInternetOptions {} { global Options set T [DemoList] set height [font metrics [$T cget -font] -linespace] if {$height < 18} { set height 18 } # # Configure the treectrl widget # $T configure -showroot no -showbuttons no -showlines no -itemheight $height \ -selectmode browse InitPics internet-* # # Create columns # $T column create -text "Internet Options" -tags C0 $T configure -treecolumn C0 # # Create elements # $T state define check $T state define radio $T state define on $T element create elemImg image -image { internet-check-on {check on} internet-check-off {check} internet-radio-on {radio on} internet-radio-off {radio} } $T element create elemTxt text -fill [list $::SystemHighlightText {selected focus}] $T element create elemRectSel rect -fill [list $::SystemHighlight {selected focus}] -showfocus yes # # Create styles using the elements # set S [$T style create STYLE] $T style elements $S {elemRectSel elemImg elemTxt} $T style layout $S elemImg -padx {0 4} -expand ns $T style layout $S elemTxt -expand ns $T style layout $S elemRectSel -union [list elemTxt] -iexpand ns -ipadx 2 # # Create items and assign styles # set parentList [list root {} {} {} {} {} {}] set parent root foreach {depth setting text option group} { 0 print "Printing" "" "" 1 off "Print background colors and images" "o1" "" 0 search "Search from Address bar" "" "" 1 search "When searching" "" "" 2 off "Display results, and go to the most likely sites" "o2" "r1" 2 off "Do not search from the Address bar" "o3" "r1" 2 off "Just display the results in the main window" "o4" "r1" 2 on "Just go to the most likely site" "o5" "r1" 0 security "Security" "" "" 1 on "Check for publisher's certificate revocation" "o5" "" 1 off "Check for server certificate revocation (requires restart)" "o6" "" } { set item [$T item create] $T item style set $item C0 STYLE $T item element configure $item C0 elemTxt -text $text set Options(option,$item) $option set Options(group,$item) $group if {($setting eq "on") || ($setting eq "off")} { set Options(setting,$item) $setting if {$group eq ""} { $T item state set $item check if {$setting eq "on"} { $T item state set $item on } } else { if {$setting eq "on"} { set Options(current,$group) $item $T item state set $item on } $T item state set $item radio } } else { $T item element configure $item C0 elemImg -image internet-$setting } $T item lastchild [lindex $parentList $depth] $item incr depth set parentList [lreplace $parentList $depth $depth $item] } bind DemoInternetOptions { TreeCtrl::DoubleButton1 %W %x %y } bind DemoInternetOptions { OptionButton1 %W %x %y break } bindtags $T [list $T DemoInternetOptions TreeCtrl [winfo toplevel $T] all] return } proc OptionButton1 {T x y} { variable TreeCtrl::Priv global Options focus $T set id [$T identify $x $y] if {[lindex $id 0] eq "header"} { TreeCtrl::ButtonPress1 $T $x $y } elseif {$id eq ""} { set Priv(buttonMode) "" } else { set Priv(buttonMode) "" set item [lindex $id 1] $T selection modify $item all $T activate $item if {$Options(option,$item) eq ""} return set group $Options(group,$item) # a checkbutton if {$group eq ""} { $T item state set $item ~on if {$Options(setting,$item) eq "on"} { set setting off } else { set setting on } set Options(setting,$item) $setting # a radiobutton } else { set current $Options(current,$group) if {$current eq $item} return $T item state set $current !on $T item state set $item on set Options(setting,$item) on set Options(current,$group) $item } } return } # Alternate implementation that does not rely on run-time states proc DemoInternetOptions_2 {} { global Options set T [DemoList] set height [font metrics [$T cget -font] -linespace] if {$height < 18} { set height 18 } # # Configure the treectrl widget # $T configure -showroot no -showbuttons no -showlines no -itemheight $height \ -selectmode browse InitPics internet-* # # Create columns # $T column create -text "Internet Options" # # Create elements # $T element create elemImg image $T element create elemTxt text -fill [list $::SystemHighlightText {selected focus}] $T element create elemRectSel rect -fill [list $::SystemHighlight {selected focus}] -showfocus yes # # Create styles using the elements # set S [$T style create STYLE] $T style elements $S {elemRectSel elemImg elemTxt} $T style layout $S elemImg -padx {0 4} -expand ns $T style layout $S elemTxt -expand ns $T style layout $S elemRectSel -union [list elemTxt] -iexpand ns -ipadx 2 # # Create items and assign styles # set parentList [list root {} {} {} {} {} {}] set parent root foreach {depth setting text option group} { 0 print "Printing" "" "" 1 off "Print background colors and images" "o1" "" 0 search "Search from Address bar" "" "" 1 search "When searching" "" "" 2 off "Display results, and go to the most likely sites" "o2" "r1" 2 off "Do not search from the Address bar" "o3" "r1" 2 off "Just display the results in the main window" "o4" "r1" 2 on "Just go to the most likely site" "o5" "r1" 0 security "Security" "" "" 1 on "Check for publisher's certificate revocation" "o5" "" 1 off "Check for server certificate revocation (requires restart)" "o6" "" } { set item [$T item create] $T item style set $item 0 STYLE $T item element configure $item 0 elemTxt -text $text set Options(option,$item) $option set Options(group,$item) $group if {$setting eq "on" || $setting eq "off"} { set Options(setting,$item) $setting if {$group eq ""} { set img internet-check-$setting $T item element configure $item 0 elemImg -image $img } else { if {$setting eq "on"} { set Options(current,$group) $item } set img internet-radio-$setting $T item element configure $item 0 elemImg -image $img } } else { $T item element configure $item 0 elemImg -image internet-$setting } $T item lastchild [lindex $parentList $depth] $item incr depth set parentList [lreplace $parentList $depth $depth $item] } bind DemoInternetOptions { TreeCtrl::DoubleButton1 %W %x %y } bind DemoInternetOptions { OptionButton1 %W %x %y break } bindtags $T [list $T DemoInternetOptions TreeCtrl [winfo toplevel $T] all] return } proc OptionButton1_2 {T x y} { variable TreeCtrl::Priv global Options focus $T set id [$T identify $x $y] if {[lindex $id 0] eq "header"} { TreeCtrl::ButtonPress1 $T $x $y } elseif {$id eq ""} { set Priv(buttonMode) "" } else { set Priv(buttonMode) "" set item [lindex $id 1] $T selection modify $item all $T activate $item if {$Options(option,$item) eq ""} return set group $Options(group,$item) # a checkbutton if {$group eq ""} { if {$Options(setting,$item) eq "on"} { set setting off } else { set setting on } $T item element configure $item 0 elemImg -image internet-check-$setting set Options(setting,$item) $setting # a radiobutton } else { set current $Options(current,$group) if {$current eq $item} return $T item element configure $current 0 elemImg -image internet-radio-off $T item element configure $item 0 elemImg -image internet-radio-on set Options(setting,$item) on set Options(current,$group) $item } } return } tktreectrl-2.2.8/doc/0000755000175600010010000000000011073207472012663 5ustar TimNonetktreectrl-2.2.8/doc/man.macros0000700000175600010010000001153107602147340014636 0ustar TimNone'\" The definitions below are for supplemental macros used in Tcl/Tk '\" manual entries. '\" '\" .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 ?version? ?br? '\" Begin vertical sidebar, for use in marking newly-changed parts '\" of man pages. The first argument is ignored and used for recording '\" the version when the .VS was added, so that the sidebars can be '\" found and removed when they reach a certain age. If another 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. '\" '\" RCS: @(#) $Id: man.macros,v 1.1 2002/12/24 22:17:19 krischan Exp $ '\" '\" # 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 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$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 !"\\$2"" .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 5.5c 11c .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 .. tktreectrl-2.2.8/doc/treectrl.html0000700000175600010010000067623111073207242015400 0ustar TimNone treectrl - Tk Commands

treectrl(n) 2.2.8 treectrl "Tk Commands"

NAME

treectrl - Create and manipulate hierarchical multicolumn widgets

TABLE OF CONTENTS

    TABLE OF CONTENTS
    SYNOPSIS
    DESCRIPTION
    STANDARD OPTIONS
    WIDGET SPECIFIC OPTIONS
    ITEM AND COLUMN TAGS
    WIDGET COMMAND
    COLUMNS
    COLUMN DESCRIPTION
    STATES
    PER-STATE OPTIONS
    ELEMENTS
    BITMAP ELEMENT
    BORDER ELEMENT
    IMAGE ELEMENT
    RECTANGLE ELEMENT
    TEXT ELEMENT
    WINDOW ELEMENT
    ITEM DESCRIPTION
    EVENTS AND SCRIPT SUBSTITUTIONS
    DYNAMIC EVENTS
    DEFAULT BINDINGS
    EXAMPLES
    SEE ALSO
    KEYWORDS

SYNOPSIS

package require treectrl 2.2.8

treectrl pathName ?options?
pathName activate itemDesc
pathName bbox ?area?
pathName canvasx screenx
pathName canvasy screeny
pathName cget option
pathName collapse ?-recurse? ?itemDesc ...?
pathName column option column ?arg ...?
pathName column bbox columnDesc
pathName column cget columnDesc option
pathName column configure columnDesc ?option? ?value? ?option value ...?
pathName column compare column1 op column2
pathName column count ?columnDesc?
pathName column create ?option value ...?
pathName column delete first ?last?
pathName column dragcget option
pathName column dragconfigure ?option? ?value? ?option value ...?
pathName column index columnDesc
pathName column id columnDesc
pathName column list ?-visible?
pathName column move columnDesc beforeDesc
pathName column neededwidth columnDesc
pathName column order columnDesc ?-visible?
pathName column tag option ?arg arg ...?
pathName column tag add columnDesc tagList
pathName column tag expr columnDesc tagExpr
pathName column tag names columnDesc
pathName column tag remove columnDesc tagList
pathName column width columnDesc
pathName compare itemDesc1 op itemDesc2
pathName configure ?option? ?value option value ...?
pathName contentbox
pathName debug option ?arg arg ...?
pathName debug alloc
pathName debug cget option
pathName debug configure ?option? ?value? ?option value ...?
pathName debug dinfo option
pathName debug expose x1 y1 x2 y2
pathName debug scroll
pathName depth ?itemDesc?
pathName dragimage option ?arg ...?
pathName dragimage add itemDesc ?column? ?element?
pathName dragimage cget option
pathName dragimage clear
pathName dragimage configure ?option? ?value? ?option value ...?
pathName dragimage offset ?x y?
pathName element option ?element? ?arg arg ...?
pathName element cget element option
pathName element configure element ?option? ?value? ?option value ...?
pathName element create element type ?option value ...?
pathName element delete ?element ...?
pathName element names
pathName element perstate element option stateList
pathName element type element
pathName expand ?-recurse? ?itemDesc ...?
pathName identify x y
pathName index itemDesc
pathName item option ?arg ...?
pathName item ancestors itemDesc
pathName item bbox itemDesc ?column? ?element?
pathName item cget itemDesc option
pathName item children itemDesc
pathName item collapse itemDesc ?-recurse?
pathName item compare itemDesc1 op itemDesc2
pathName item complex itemDesc ?list...?
pathName item configure itemDesc ?option? ?value? ?option value ...?
pathName item count ?itemDesc?
pathName item create ?option value ...?
pathName item delete first ?last?
pathName item descendants itemDesc
pathName item dump itemDesc
pathName item element command itemDesc column element ?arg ...?
pathName item element actual itemDesc column element option
pathName item element cget itemDesc column element option
pathName item element configure itemDesc column element ?option? ?value? ?option value ...?
pathName item element perstate itemDesc column element option ?stateList?
pathName item enabled itemDesc ?boolean?
pathName item expand itemDesc ?-recurse?
pathName item firstchild parent ?child?
pathName item id itemDesc
pathName item image itemDesc ?column? ?image? ?column image ...?
pathName item isancestor itemDesc descendant
pathName item isopen itemDesc
pathName item lastchild parent ?child?
pathName item nextsibling sibling ?next?
pathName item numchildren itemDesc
pathName item order itemDesc ?-visible?
pathName item parent itemDesc
pathName item prevsibling sibling ?prev?
pathName item range first last
pathName item remove itemDesc
pathName item rnc itemDesc
pathName item sort itemDesc ?option ...?
pathName item span itemDesc ?column? ?numColumns? ?column numColumns ...?
pathName item state command itemDesc ?arg ...?
pathName item state forcolumn itemDesc column ?stateDescList?
pathName item state get itemDesc ?stateName?
pathName item state set itemDesc ?lastItem? stateDescList
pathName item style command itemDesc ?arg ...?
pathName item style elements itemDesc column
pathName item style map itemDesc column style map
pathName item style set itemDesc ?column? ?style? ?column style ...?
pathName item tag option ?arg arg ...?
pathName item tag add itemDesc tagList
pathName item tag expr itemDesc tagExpr
pathName item tag names itemDesc
pathName item tag remove itemDesc tagList
pathName item text itemDesc ?column? ?text? ?column text ...?
pathName item toggle itemDesc ?-recurse?
pathName marquee option ?arg ...?
pathName marquee anchor ?x y?
pathName marquee cget option
pathName marquee configure ?option? ?value? ?option value ...?
pathName marquee coords ?x1 y1 x2 y2?
pathName marquee corner ?x y?
pathName marquee identify
pathName notify option ?arg ...?
pathName notify bind ?object? ?pattern? ?+??script?
pathName notify configure object pattern ?option? ?value? ?option value ...?
pathName notify detailnames eventName
pathName notify eventnames
pathName notify generate pattern ?charMap? ?percentsCommand?
pathName notify install pattern ?percentsCommand?
pathName notify install detail eventName detail ?percentsCommand?
pathName notify install event eventName ?percentsCommand?
pathName notify linkage pattern
pathName notify linkage eventName ?detail?
pathName notify unbind object ?pattern?
pathName notify uninstall pattern
pathName notify uninstall detail eventName detail
pathName notify uninstall event eventName
pathName numcolumns
pathName numitems
pathName orphans
pathName range first last
pathName scan option args
pathName scan mark x y
pathName scan dragto x y ?gain?
pathName state option args
pathName state define stateName
pathName state linkage stateName
pathName state names
pathName state undefine ?stateName ...?
pathName see itemDesc
pathName selection option args
pathName selection add first ?last?
pathName selection anchor ?itemDesc?
pathName selection clear ?first? ?last?
pathName selection count
pathName selection get ?first? ?last?
pathName selection includes itemDesc
pathName selection modify select deselect
pathName style option ?element? ?arg arg ...?
pathName style cget style option
pathName style configure style ?option? ?value? ?option value ...?
pathName style create style ?option value ...?
pathName style delete ?style ...?
pathName style elements style ?elementList?
pathName style layout style element ?option? ?value? ?option value ...?
pathName style names
pathName toggle ?-recurse? ?itemDesc ...?
pathName xview ?args?
pathName xview
pathName xview moveto fraction
pathName xview scroll number what
pathName yview ?args?
pathName yview
pathName yview moveto fraction
pathName yview scroll number what

DESCRIPTION

treectrl pathName ?options?

The treectrl command creates a new window (given by the pathName argument) and makes it into a treectrl widget. Additional options, described above, may be specified on the command line or in the option database to configure aspects of the treectrl such as its background color and relief. The treectrl command returns the path name of the new window. At the time this command is invoked, there must not exist a window named pathName, but pathName's parent must exist.

A treectrl is a widget which displays items in a one- or two-dimensional arrangement. Items have a parent-child relationship with other items. Items have a set of states, which are boolean properties. Items may be spread about one or more columns. For each column of an item there is a style associated, which determines how to display the item's column taking into account the item's current state set. One column can be defined to display the data in a hierarchical structure.

Normally the origin of the coordinate system is at the upper-left corner of the window containing the treectrl. It is possible to adjust the origin of the coordinate system relative to the origin of the window using the xview and yview widget commands; this is typically used for scrolling.

A treectrl widget can be horizontal or vertical oriented like many other Tk widgets. For displaying hierarchical data only vertical orientation is useful, since only then the children of an item are displayed directly below their parent. If the treectrl widget is used only to display data in a multicolumn listbox, the specification of an orientation will give useful results.

STANDARD OPTIONS

-background
-borderwidth
-cursor
-font
-highlightbackground
-highlightcolor
-highlightthickness
-orient
-relief
-takefocus
-xscrollcommand
-yscrollcommand
-foreground
See the option manual entry for details on the standard options.

WIDGET SPECIFIC OPTIONS

Command-Line Switch: -backgroundimage
Database Name: backgroundImage
Database Class: BackgroundImage
Specifies the name of an image to draw as the list background. The image is tiled horizontally and vertically to fill the content area of the list. If the image is transparent it is drawn on top of the background color(s).

Command-Line Switch: -backgroundmode
Database Name: backgroundMode
Database Class: BackgroundMode
Specifies how the background color of items is chosen in each column. The value should be one of row, column, order, or ordervisible. The default is row. This option has only an effect for columns which have -itembackground defined as list of two or more colors (see section COLUMNS below for more on this). If row or column is specified, the background color is chosen based on the location of the item in the 1- or 2-dimensional grid of items as layed out on the screen; this layout of items is affected by the -orient and -wrap options as well as item visibility. When order or ordervisible is specified, the background color is chosen based on the result of the item order command, regardless of the layout of items.

Command-Line Switch: -buttonbitmap
Database Name: buttonBitmap
Database Class: ButtonBitmap
Specifies the bitmap to be used as the expand/collapse button to the left of an item. This is a per-state option. If a bitmap is specified for a certain item state, it overrides the effects of -usetheme.

Command-Line Switch: -buttoncolor
Database Name: buttonColor
Database Class: ButtonColor
Specifies the foreground color which should be used for drawing the outline and the plus or minus sign of the button to the left of an item.

Command-Line Switch: -buttonimage
Database Name: buttonImage
Database Class: ButtonImage
Specifies the image to be used as the expand/collapse button to the left of an item. This is a per-state option. If an image is specified for a certain item state, it overrides the effects of -buttonbitmap and -usetheme.

Command-Line Switch: -buttonsize
Database Name: buttonSize
Database Class: ButtonSize
Specifies the width and height of the button drawn to the left of an item in any of the forms acceptable to Tk_GetPixels.

Command-Line Switch: -buttonthickness
Database Name: buttonThickness
Database Class: ButtonThickness
Specifies the width of the outline and the plus or minus sign of the button to the left of an item in any of the forms acceptable to Tk_GetPixels.

Command-Line Switch: -columnprefix
Database Name: columnPrefix
Database Class: ColumnPrefix
Specifies an ascii string that changes the way column ids are reported and processed. If this option is a non-empty string, the usual integer value of a column id is prefixed with the given string. This can aid debugging but it is important your code doesn't assume column ids are integers if you use it.

Command-Line Switch: -columnproxy
Database Name: columnProxy
Database Class: ColumnProxy
If this option specifies a non empty value, it should be a screen distance in any of the forms acceptable to Tk_GetPixels. Then a 1 pixel thick vertical line will be drawn at the specified screen distance from the left edge of the treectrl widget, which reaches from top to bottom of the treectrl widget and uses an inverting color (i.e black on lighter background, white on darker background). This line can be used to give the user a visual feedback during column resizing.

Command-Line Switch: -columnresizemode
Database Name: columnResizeMode
Database Class: ColumnResizeMode
Specifies the visual feedback used when resizing columns. The value should be one of proxy or realtime. For proxy, a 1-pixel thick vertical line is drawn representing where the right edge of the column will be after resizing. For realtime, the column's size is changed while the user is dragging the right edge of the column.

Command-Line Switch: -columntagexpr
Database Name: columnTagExpr
Database Class: ColumnTagExpr
Specifies a boolean that enables or disables tag expressions in column descriptions. See ITEM AND COLUMN TAGS.

Command-Line Switch: -defaultstyle
Database Name: defaultStyle
Database Class: DefaultStyle
This option is deprecated; use the column option -itemstyle instead. Specifies a list of styles, one per column, to apply to each item created by the item create command. The number of styles in the list can be different from the number of tree columns. Each list element should be a valid style name or an empty string to indicate no style should be applied to a specific column. The list of styles is updated if a style is deleted or if a column is moved.

Command-Line Switch: -doublebuffer
Database Name: doubleBuffer
Database Class: DoubleBuffer
Specifies if double-buffering should be used to improve displaying. The value should be one of none, window, or item. For none no double-buffering is used at all, which may be most memory efficient, but will probably generate some flickering on the screen. For window the complete tree is double-buffered, which requires a buffer big enough to contain the complete widget. For item, which is the default, every item is separately double-buffered, so it works with a buffer size as big as the biggest item.

Command-Line Switch: -height
Database Name: height
Database Class: Height
Specifies the desired height for the window in any of the forms acceptable to Tk_GetPixels. The default is 200 pixels. If this option is less than or equal to zero then the window will not request any size at all.

Command-Line Switch: -indent
Database Name: indent
Database Class: Indent
Specifies the screen distance an item is indented relative to its parent item in any of the forms acceptable to Tk_GetPixels. The default is 19 pixels.

Command-Line Switch: -itemheight
Database Name: itemHeight
Database Class: ItemHeight
Specifies a fixed height for every item in any of the forms acceptable to Tk_GetPixels. If non-zero, this option overrides the requested height of an item and the -minitemheight option. The default is 0, which means that every item has the height requested by the arrangement of elements in each column. Items are never shorter than the maximum height of a button.

Command-Line Switch: -itemprefix
Database Name: itemPrefix
Database Class: ItemPrefix
Specifies an ascii string that changes the way item ids are reported and processed. If this option is a non-empty string, the usual integer value of an item id is prefixed with the given string. This can aid debugging but it is important your code doesn't assume item ids are integers if you use it.

Command-Line Switch: -itemtagexpr
Database Name: itemTagExpr
Database Class: ItemTagExpr
Specifies a boolean that enables or disables tag expressions in item descriptions. See ITEM AND COLUMN TAGS.

Command-Line Switch: -itemwidth
Database Name: itemWidth
Database Class: ItemWidth
Specifies a fixed width for every item in any of the forms acceptable to Tk_GetPixels. If more than one column is visible, then this option has no effect. If the -orient option is vertical, and the -wrap option is unspecified, then this option has no effect (in that case all items are as wide as the column).

Command-Line Switch: -itemwidthequal
Database Name: itemWidthEqual
Database Class: ItemWidthEqual
Specifies a boolean that says whether all items should have the same width. If more than one column is visible, then this option has no effect. If the -orient option is vertical, and the -wrap option is unspecified, then this option has no effect (in that case all items are as wide as the column). If the -itemwidth option is specified, then this option has no effect.

Command-Line Switch: -itemwidthmultiple
Database Name: itemWidthMultiple
Database Class: ItemWidthMultiple
Specifies a screen distance that every item's width will be evenly divisible by in any of the forms acceptable to Tk_GetPixels. If more than one column is visible, then this option has no effect. If the -orient option is vertical, and the -wrap option is unspecified, then this option has no effect (in that case all items are as wide as the column). If the -itemwidth option is specified, then this option has no effect.

Command-Line Switch: -linecolor
Database Name: lineColor
Database Class: LineColor
Specifies the color which should be used for drawing the connecting lines between related items.

Command-Line Switch: -linestyle
Database Name: lineStyle
Database Class: LineStyle
Specifies the style of the connecting lines between related items, should be dot which is the default, or solid.

Command-Line Switch: -linethickness
Database Name: lineThickness
Database Class: LineThickness
Specifies the thickness of the connecting lines between related items in any of the forms acceptable to Tk_GetPixels.

Command-Line Switch: -minitemheight
Database Name: minItemHeight
Database Class: MinItemHeight
Specifies a minimum height for every item in any of the forms acceptable to Tk_GetPixels. The default is 0, which means that every item has the height requested by the arrangement of elements in each column. This option has no effect if the -itemheight option is specified. Items are never shorter than the maximum height of a button.

Command-Line Switch: -rowproxy
Database Name: rowProxy
Database Class: RowProxy
If this option specifies a non empty value, it should be a screen distance in any of the forms acceptable to Tk_GetPixels. Then a 1 pixel thick horizontal line will be drawn at the specified screen distance from the top edge of the treectrl widget, which reaches from left to right of the treectrl widget and uses an inverting color (i.e black on lighter background, white on darker background). This line can be used to give the user a visual feedback during row resizing.

Command-Line Switch: -scrollmargin
Database Name: scrollMargin
Database Class: ScrollMargin
Specifies a positive screen distance in any of the forms acceptable to Tk_GetPixels. This option is used by the default bindings to determine how close to the edges of the contentbox the mouse pointer must be before scrolling occurs. Specifying a positive value is useful when items may be drag-and-dropped. Defaults to 0.

Command-Line Switch: -selectmode
Database Name: selectMode
Database Class: 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 single, browse, multiple, or extended; the default value is browse.

Command-Line Switch: -showbuttons
Database Name: showButtons
Database Class: ShowButtons
Specifies a boolean value that determines whether this widget leaves indentation space to display the expand/collapse buttons next to items. The default value is true. The item option -button determines whether any item has a button. See also the treectrl option -showrootbutton.

Command-Line Switch: -showheader
Database Name: showHeader
Database Class: ShowHeader
Specifies a boolean value that determines whether this widget should display the header line with the column names at the top of the widget. The default value is true.

Command-Line Switch: -showlines
Database Name: showLines
Database Class: ShowLines
Specifies a boolean value that determines whether this widget should draw the connecting lines between related items. The default value is true.

Command-Line Switch: -showroot
Database Name: showRoot
Database Class: ShowRoot
Specifies a boolean value that determines whether this widget should draw the root item. By suppressing the drawing of the root item the widget can have multiple items that appear as toplevel items. The default value is true.

Command-Line Switch: -showrootbutton
Database Name: showRootButton
Database Class: ShowRootButton
Specifies a boolean value that determines whether this widget leaves indentation space to display the expand/collapse button next to the root item. The default value is false. The item option -button determines whether the root item has a button.

Command-Line Switch: -showrootchildbuttons
Database Name: showRootChildButtons
Database Class: ShowRootChildButtons
Specifies a boolean value that determines whether this widget should draw the expand/collapse buttons next to children of the root item. The default value is true.

Command-Line Switch: -showrootlines
Database Name: showRootLines
Database Class: ShowRootLines
Specifies a boolean value that determines whether this widget should draw the connecting lines between children of the root item. The default value is true.

Command-Line Switch: -treecolumn
Database Name: treeColumn
Database Class: TreeColumn
Specifies a column description that determines which column displays the buttons and lines. The default is unspecified.

Command-Line Switch: -usetheme
Database Name: useTheme
Database Class: UseTheme
Specifies a boolean value that determines whether this widget should draw parts of itself using a platform-specific theme manager. The default is false.

Command-Line Switch: -width
Database Name: width
Database Class: Width
Specifies the desired width for the window in any of the forms acceptable to Tk_GetPixels. The default is 200 pixel. If this option is less than or equal to zero then the window will not request any size at all.

Command-Line Switch: -wrap
Database Name: wrap
Database Class: Wrap
Specifies whether items are arranged in a 1- or 2-dimensional layout. If the value is an empty string (the default), then items are arranged from top to bottom (-orient vertical) or from left to right (-orient horizontal) in a 1-dimensional layout. If the value is "N items", then a no more than N items will appear in a vertical group (-orient vertical) or horizontal group (-orient horizontal). If the value is "N pixels", then a no vertical group of items will be taller than N pixels (-orient vertical) or no horizontal group of items will be wider than N pixels (-orient horizontal). If the value is window, then a no vertical group of items will be taller than the window (-orient vertical) or no horizontal group of items will be wider than the window (-orient horizontal).

Command-Line Switch: -xscrolldelay
Database Name: xScrollDelay
Database Class: ScrollDelay
This option controls how quickly horizontal scrolling occurs while dragging the mouse with button 1 pressed. The value should be a list of 1 or 2 integers interpreted as microseconds. If 2 values are specified, then the first value determines the intial delay after the first scroll, and the second value determines the delay for all scrolling after the first. If only 1 value is specified, each scroll takes place after that delay.

Command-Line Switch: -xscrollincrement
Database Name: xScrollIncrement
Database Class: ScrollIncrement
Specifies an increment for horizontal scrolling, in any of the usual forms permitted for screen distances. If the value of this option is greater than zero, the horizontal view in the window will be constrained so that the x coordinate at the left edge of the window is always an even multiple of -xscrollincrement; furthermore, the units for scrolling (e.g., the change in view when the left and right arrows of a scrollbar are selected) will also be -xscrollincrement. If the value of this option is less than or equal to zero, then horizontal scrolling snaps to the left of an item, or part of an item if items are wider than the contentbox.

Command-Line Switch: -yscrolldelay
Database Name: yScrollDelay
Database Class: ScrollDelay
This option controls how quickly vertical scrolling occurs while dragging the mouse with button 1 pressed. The value should be a list of 1 or 2 integers interpreted as microseconds. If 2 values are specified, then the first value determines the intial delay after the first scroll, and the second value determines the delay for all scrolling after the first. If only 1 value is specified, each scroll takes place after that delay.

Command-Line Switch: -yscrollincrement
Database Name: yScrollIncrement
Database Class: ScrollIncrement
Specifies an increment for vertical scrolling, in any of the usual forms permitted for screen distances. If the value of this option is greater than zero, the vertical view in the window will be constrained so that the y coordinate at the top edge of the window is always an even multiple of -yscrollincrement; furthermore, the units for scrolling (e.g., the change in view when the top and bottom arrows of a scrollbar are selected) will also be -yscrollincrement. If the value of this option is less than or equal to zero, then vertical scrolling snaps to the top of an item, or part of an item if items are taller than the contentbox.

ITEM AND COLUMN TAGS

Columns and items may have any number of tags associated with them. A tag is just a string of characters, and it may take any form, including that of an integer, although the characters '(', ')', '&', '|', '^' and '!' should be avoided.

The same tag may be associated with many columns or items. This is commonly done to group items in various interesting ways; for example, in a file browser all directories might be given the tag "directory".

Tag expressions are used in column descriptions and item descriptions to specify which columns and items to operate on. A tag expression can be a single tag name or a logical expression of tags using operators '&&', '||', '^' and '!', and parenthesized subexpressions. For example:

 
.t item id "tag {(a && !b) || (!a && b)}"

or equivalently:

 
.t item id "tag {a ^ b}"

will return the unique ids of any items with either "a" or "b" tags, but not both.

Within a tag expression a tag name may be enclosed in double quotes to avoid special processing of the operator characters. For example:

 
.t item id {tag {"a&&b"||c}}

will return the unique ids of any items with either "a&&b" or "c" tags; in this example the && is not treated as an operator. A double-quote may be escaped within a quoted tag name using a backslash '\'.

Tag operators may be bypassed completely by setting the -columntagexpr and -itemtagexpr options. This can be useful if your application has column or item tags containing arbitrary text.

 
.t configure -itemtagexpr false
.t item delete "tag a&&b"

WIDGET COMMAND

The treectrl command creates a new Tcl command whose name is the same as the path name of the treectrl's window. This command may be used to invoke various operations on the widget. It has the following general form:

pathName option ?arg arg ...?

PathName is the name of the command, which is the same as the treectrl widget's path name. Option and the args determine the exact behavior of the command. The following commands are possible for treectrl widgets:

pathName activate itemDesc
Sets the active item to the one described by itemDesc, and switches on the state active for this item. From now on the item can be retrieved with the item description active. An <ActiveItem> event is generated.

pathName bbox ?area?
Returns a list with four elements giving the bounding box (left, top, right and bottom) of an area of the window. If area is not specified, then the result is the bounding box of the entire window. If area is content, then the result is the part of the window not including borders, headers, or locked columns. If area is header, then the result is the part of the window not including borders where column titles are displayed. If area is left, then the result is the part of the window not including borders or headers where left-locked columns are displayed. If area is right, then the result is the part of the window not including borders or headers where right-locked columns are displayed. An empty string is returned if the display area has no height or width, which can be true for various reasons such as the window is too small, or the header is not displayed, or there aren't any locked columns.

pathName canvasx screenx
Given a window x-coordinate in the treectrl screenx, this command returns the treectrl x-coordinate that is displayed at that location.

pathName canvasy screeny
Given a window y-coordinate in the treectrl screeny, this command returns the treectrl y-coordinate that is displayed at that location.

pathName cget option
Returns the current value of the configuration option given by option. Option may have any of the values accepted by the tree command.

pathName collapse ?-recurse? ?itemDesc ...?
Use item collapse instead.

pathName column option column ?arg ...?
This command is used to manipulate the columns of the treectrl widget (see section COLUMNS below). The exact behavior of the command depends on the option argument that follows the column argument. The following forms of the command are supported:

pathName column bbox columnDesc
Returns a list with four elements giving the bounding box of the header of the column specified by the column description columnDesc. If the treectrl is configured not to display the column headers by means of the -showheader option, then an empty list is returned instead.

pathName column cget columnDesc option
This command returns the current value of the option named option for the column specified by the column description columnDesc, ColumnDesc may also be the string tail to specify the tail column. Option may have any of the values accepted by the column configure widget command.

pathName column configure columnDesc ?option? ?value? ?option value ...?
This command is similar to the configure widget command except that it modifies options associated with the columns specified by the column description columnDesc instead of modifying options for the overall treectrl widget. ColumnDesc may be the string tail to specify the tail column. If columnDesc refers to more than one column, then at least one option-value pair must be given. If no option is specified, the command returns a list describing all of the available options for columnDesc (see Tk_ConfigureInfo for information on the format of this list). If option is specified with no value, 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 option is specified). If one or more option-value pairs are specified, then the command modifies the given option(s) to have the given value(s) for columnDesc; in this case the command returns an empty string.

See COLUMNS below for details on the options available for columns.

pathName column compare column1 op column2
For both column descriptions column1 and column2 the index is retrieved (as returned from the column order widget command). Then these indexes are compared using the operator op, which must be either <, <=, ==, >=, >, or !=. The return value of this command is 1 if the comparison evaluated to true, 0 otherwise.

pathName column count ?columnDesc?
If no additional arguments are given, the result is a decimal string giving the number of columns created by the column create widget command which haven't been deleted by the column delete widget command; in this case the tail column is not counted. If columnDesc is given, then the result is the number of columns that match that column description.

pathName column create ?option value ...?
This command creates a new column in the treectrl widget. The new column is placed to the right of all other columns (except the tail column). Any option-value arguments configure the new column according to the column configure command. The return value is the unique identifier of the new column.

pathName column delete first ?last?
Deletes the specified column(s). First and last must be valid column descriptions. If both first and last are specified, then they may refer to a single column only. The tail column cannot be deleted and it is an error to specify it. The order of first and last doesn't matter, and first may be equal to last.

pathName column dragcget option
pathName column dragconfigure ?option? ?value? ?option value ...?
The user can move a column within a treectrl by drag-and-drop. Feedback consists of a semi-transparent photo image of the header of the column being dragged and a 2-pixel-thick vertical line to indicate where the column may be dropped. The drag image consists of a colored background rectangle plus the image and/or text displayed in the column header. The 2-pixel-thick line will be drawn over the left edge of the column before which the dragged column may be dropped.

The library scripts generate a <ColumnDrag-accept> event when the user has successfully drag-and-drop'd a column. You will have to bind a script to this event if you want to move the dragged column.

The following configuration options are supported:

-enable boolean
Controls whether the user is allowed to rearrange columns by drag-and-drop.

-imagealpha alpha
Alpha is an integer from 0 (invisible) to 255 (opaque) controlling the transparency of the drag image. Any value outside this range is clipped.

-imagecolor background
Background is the color of the drag image background rectangle.

-imagecolumn column
Column specifies the column to create the drag image from.

-imageoffset offset
Offset is the horizontal screen distance the drag image is offset from its starting position.

-indicatorcolor color
Color is the color of the 2-pixel-thick line.

-indicatorcolumn column
The 2-pixel-thick line will be drawn over the left or right edge of column.

-indicatorside side
Specifies whether the 2-pixel-thick line will be drawn over the left or right edge of the column specified by -indicatorcolumn.
pathName column index columnDesc
Deprecated. Use column id instead.

pathName column id columnDesc
This command resolves the column description columnDesc into a list of unique column identifiers. If the column(s) described by columnDesc don't exist, this command returns an empty list.

pathName column list ?-visible?
This command returns a list of identifiers for every column (except the tail) from left to right. If -visible is given, only columns whose -visible option is true are returned.

pathName column move columnDesc beforeDesc
Moves the column specified by columnDesc to the left of the column specified by beforeDesc. Both columnDesc and beforeDesc must be valid column descriptions. If beforeDesc is the string tail, the column columnDesc will become the last column.

pathName column neededwidth columnDesc
This command returns a decimal string giving the needed width of the column specified by the column description columnDesc. The needed width is the maximum of the width of the column header and the width of the widest style in any visible item.

pathName column order columnDesc ?-visible?
This command returns a decimal string giving the position of the column specified by the column description columnDesc in the list of columns starting from zero for the leftmost column. If -visible is given, only columns whose -visible option is true are considered, and -1 is returned if columnDesc's -visible option is false.

pathName column tag option ?arg arg ...?
This command is used to manipulate tags on columns. The exact behavior of the command depends on the option argument that follows the column tag argument. The following forms of the command are supported:

pathName column tag add columnDesc tagList
Adds each tag in tagList to the columns specified by the column description columnDesc. Duplicate tags are ignored. The list of tags for a column can also be changed via a column's -tags option.

pathName column tag expr columnDesc tagExpr
Evaluates the tag expression tagExpr against every column specified by the column description columnDesc. The result is 1 if the tag expression evaluates to true for every column, 0 otherwise.

pathName column tag names columnDesc
Returns a list of tag names assigned to the columns specified by the column description columnDesc. The result is the union of any tags assigned to the columns.

pathName column tag remove columnDesc tagList
Removes each tag in tagList from the columns specified by the column description columnDesc. It is not an error if any of the columns do not use any of the tags. The list of tags for a column can also be changed via a column's -tags option.
pathName column width columnDesc
This command returns a decimal string giving the width in pixels of the column specified by the column description columnDesc, even if the treectrl is configured to not display the column headers by means of the -showheader option.
pathName compare itemDesc1 op itemDesc2
Deprecated. Use the item compare command instead.

pathName configure ?option? ?value option value ...?
Query or modify the configuration options of the widget. If no option is specified, returns a list describing all of the available options for pathName (see Tk_ConfigureInfo for information on the format of this list). If option is specified with no value, 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 option is specified). If one or more option-value 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. Option may have any of the values accepted by the treectrl command.

pathName contentbox
Returns a list with four elements giving the bounding box of the screen area used to display items. This is the area of the window not including borders, column headers, or locked columns. An empty string is returned if the display area has no height or width, which can happen if the window is too small.

pathName debug option ?arg arg ...?
This command is used to facilitate debugging of the treectrl widget. The exact behavior of the command depends on the option argument that follows the debug argument. The following forms of the command are supported:

pathName debug alloc
Returns a string giving partial statistics on memory allocations, if the package was built with TREECTRL_DEBUG defined.

pathName debug cget option
This command returns the current value of the debugging option named option. Option may have any of the values accepted by the debug configure widget command.

pathName debug configure ?option? ?value? ?option value ...?
This command is similar to the configure widget command except that it modifies debugging options instead of modifying options for the overall treectrl widget. If no option is specified, the command returns a list describing all of the available debugging options (see Tk_ConfigureInfo for information on the format of this list). If option is specified with no value, 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 option is specified). If one or more option-value pairs are specified, then the command modifies the given debugging option(s) to have the given value(s); in this case the command returns an empty string.

The following debugging options are supported:

-displaydelay millis
Specifies a time duration in milliseconds, which should be waited after something has been drawn to the screen. Setting this option has only an effect, if the debugging options -enable and -display are switched on.

-data boolean
If this option is switched on (together with the debugging option -enable), at various places a consistence check on the internal data structure is made (e.g. for every item is checked, if the registered number of children is equal to the number of child items). If an inconsistency was found, a Tcl background error is raised.

-display boolean
If this option is switched on (together with the debugging option -enable), at varios places additional debugging output is printed to stdout.

-drawcolor color
When specified, areas of the window are painted with this color when drawing in those areas is about to occur. Setting this option has only an effect if the debugging options -enable and -display are switched on.

-enable boolean
All other debugging options only take effect if this option is also switched on.

-erasecolor color
When specified, areas of the window which have been marked as "invalid" (for example, when part of the window is exposed) are painted with this color. If you use an unusual color for this option (like pink), superflous screen redraws can be spotted more easily. Setting this option has only an effect if the debugging options -enable and -display are switched on.

-span boolean
Debugging related to column spanning.

-textlayout boolean
Debugging related to text-element layout.
pathName debug dinfo option
Returns a string describing display-related stuff. Option must be one of alloc, ditem, onscreen or range.

pathName debug expose x1 y1 x2 y2
Causes the area of the window bounded by the given window-coords to be marked as invalid. This simulates uncovering part of the window.

pathName debug scroll
Returns a string useful for debugging vertical scrolling.
pathName depth ?itemDesc?
If the additional argument itemDesc is given, then the result is a decimal string giving the depth of the item described by itemDesc. If no itemDesc is specified, then the maximum depth of all items in the treectrl widget is returned instead. Depth is defined as the number of ancestors an item has.

pathName dragimage option ?arg ...?
This command is used to manipulate the dragimage, one or more dotted lines around rectangular regions of the treectrl widget. The exact behavior of the command depends on the option argument that follows the dragimage argument. The following forms of the command are supported:

pathName dragimage add itemDesc ?column? ?element?
Adds the shapes of the item described by itemDesc to the shapes of the dragimage. Specifying additional arguments reduces the number of rectangles that are added to the dragimage. If no additional arguments is specified, for every element of the item in every column a dotted rectangles is added. If column is specified, all elements in other columns are ignored. If also element is specified, only a rectangle for this one element of the specified item in the given column is added.

pathName dragimage cget option
This command returns the current value of the dragimage option named option. Option may have any of the values accepted by the dragimage configure widget command.

pathName dragimage clear
Removes all shapes (if there are any) from the dragimage. This command does not modify the dragimage offset.

pathName dragimage configure ?option? ?value? ?option value ...?
This command is similar to the configure widget command except that it modifies the dragimage options instead of modifying options for the overall treectrl widget. If no option is specified, the command returns a list describing all of the available dragimage options (see Tk_ConfigureInfo for information on the format of this list). If option is specified with no value, then the command returns a list describing the one named dragimage option (this list will be identical to the corresponding sublist of the value returned if no option is specified). If one or more option-value pairs are specified, then the command modifies the given dragimage option(s) to have the given value(s); in this case the command returns an empty string.

The following dragimage options are supported:

-visible boolean
Specifies a boolean value which determines whether the dragimage should currently be visible.
pathName dragimage offset ?x y?
Returns a list containing the x and y offsets of the dragimage, if no additional arguments are specified. The dragimage offset is the screen distance, the image is displayed relative to the item its shape is derived from. If two coordinates are specified, sets the dragimage offset to the given coordinates x and y.
pathName element option ?element? ?arg arg ...?
This command is used to manipulate elements (see ELEMENTS below). The exact behavior of the command depends on the option argument that follows the element argument. The following forms of the command are supported:

pathName element cget element option
This command returns the current value of the option named option associated with the element given by element. Option may have any of the values accepted by the element configure widget command.

pathName element configure element ?option? ?value? ?option value ...?
This command is similar to the configure widget command except that it modifies options associated with the element given by element instead of modifying options for the overall treectrl widget. If no option is specified, the command returns a list describing all of the available options for element (see Tk_ConfigureInfo for information on the format of this list). If option is specified with no value, 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 option is specified). If one or more option-value pairs are specified, then the command modifies the given option(s) to have the given value(s) in element; in this case the command returns an empty string. See ELEMENTS below for details on the options available for elements.

pathName element create element type ?option value ...?
Create a new elememt in pathName of type type with name element. The exact format of the arguments after type depends on type, but generally consist of specifications for zero or more element options. See the subsections on individual element types below for more on the syntax of this command. This command returns the name for the new element.

pathName element delete ?element ...?
Deletes each of the named elements and returns an empty string. If an element is deleted while it is still configured as an element of one or more styles by means of the style elements widget command, it is also removed from the element lists of these styles.

pathName element names
Returns a list containing the names of all existing elements.

pathName element perstate element option stateList
This command returns the value of the per-state option named option for element for a certain state. StateList is a list of state names (static and dynamic, see STATES) which specifies the state to use.

pathName element type element
Returns the type of the element given by element, such as rect or text.
pathName expand ?-recurse? ?itemDesc ...?
Use item expand instead.

pathName identify x y
Returns a list describing what is displayed at the given window coordinates x and y. If the coordinates are outside the window, over the borders, or over any whitespace in the window, then the result is an empty string; otherwise the first word of the result is header or item.

If the coordinates are over a column header, then the first word of the result is header, followed by the unique id of the column (or the string tail). If the x coordinate is near the left or right end of a column, then a third word left or right is appended to the result.

If the coordinates are over an item, then the first word of the result is item followed by the unique id of that item. If the coordinates are not over the area for displaying buttons and lines, then column and a unique column id are the 3rd and 4th words of the result. If the coordinates are over an element within that column, then element and an element name are the 5th and 6th words of the result.

If the coordinates are over a button, then the first word of the result is item, followed by the unique id of that item, followed by the word button.

If the coordinates are over a line descending from an ancestor of an item (but not the parent of that item), then the first word of the result is item, followed by the unique id of that item, followed by the word line, followed by the unique id of the item the line is coming from. This is used to collapse the ancestor when the line is clicked on.

pathName index itemDesc
Deprecated. Use item id instead.

pathName item option ?arg ...?
This command is used to manipulate items. The exact behavior of the command depends on the option argument that follows the item argument. The following forms of the command are supported:

pathName item ancestors itemDesc
Returns a list containing the item ids of the ancestors of the item specified by itemDesc. The first list value is the parent, the second is the parent's parent, an so on. The last list value will be the root item if itemDesc is a descendant of the root item.

pathName item bbox itemDesc ?column? ?element?
Returns a list with four elements giving the bounding box of the item described by itemDesc. If no further argument is specified, the bbox spans the area of the item over all non-locked columns. If a column is specified, only the area of the item in this column is considered. If an additional element is specified, the area of this element in column of the specified item is returned.

pathName item cget itemDesc option
Returns the current value of the configuration option for the item specified by itemDesc whose name is option. Option may have any of the values accepted by the item configure command.

pathName item children itemDesc
Returns a list containing the item ids of all children of the item specified by itemDesc in the correct order from the first child to the last child.

pathName item collapse itemDesc ?-recurse?
Switches off the open state of the item(s) described by itemDesc. If an item has descendants, then they are no longer displayed. If an item is already closed, then this command has no effect on that item. If -recurse is specified, then all descendants of the items described by itemDesc will also be collapsed. For every item that actually will be collapsed, two events are generated: a <Collapse-before> event before the item state is changed, and a <Collapse-after> event after the item state was changed.

pathName item compare itemDesc1 op itemDesc2
From both items described by the itemDescs the index is retrieved (as returned from the item order widget command). Then these indexes are compared using the operator op, which must be either <, <=, ==, >=, >, or !=. The return value of this command is 1 if the comparison evaluated to true, 0 otherwise.

pathName item complex itemDesc ?list...?
This horrible command is now deprecated. Use item element configure instead. For every column of the treectrl there may be specified one list. Each list should look like this:

 
{ {element option value ...} {element option value ...} ...}

Every option must be known by the element's type (see ELEMENTS below). Each option will be set to value for the element in this one column in this item.

pathName item configure itemDesc ?option? ?value? ?option value ...?
If no option is specified, returns a list describing all of the available options for the item given by itemDesc (see Tk_ConfigureInfo for information on the format of this list). If option is specified with no value, 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 option is specified).

If one or more option-value pairs are specified, then the command modifies the given item option(s) to have the given value(s); in this case the command returns an empty string. This is the only case where itemDesc may refer to multiple items.

The following options are supported by this command (see item create for the meaning of each option):

-button boolean|auto
-height height
-tags tagList
-visible boolean
pathName item count ?itemDesc?
If no additional arguments are given, the result is a decimal string giving the number of items created by the item create widget command which haven't been deleted by the item delete widget command, plus 1 for the ever-present root item. If the optional argument itemDesc is given, then the result is the number of items that match that item description.

pathName item create ?option value ...?
Creates some new items and optionally returns a list of unique identifiers for those items. The new items have the states open and enabled set by default. If the treectrl widget currently has the focus, the state focus is also set.

The following options are supported by this command:

-button boolean|auto
The value of this option must have one of the forms accepted by Tcl_GetBoolean or be the word auto (or any abbreviation of it). It indicates whether or not an expand/collapse button should be drawn next to the item, typically to indicate that the item has children. If the value of this option is auto, then a button is displayed next to the item whenever the item has any children whose item option -visible is true. The button will only be displayed if:

  1. the column specified by the treectrl option -treecolumn is visible, and

  2. the treectrl option -showbuttons is true, and

  3. for the root item, the treectrl option -showrootbutton is true.
-count numItems
Specifies the number of items to create. Must be >= 0. Defaults to 1.

-height height
Specifies a fixed height in any of the forms acceptable to Tk_GetPixels. Must be >= 0. If height is zero then the item's height is unspecified. Defaults to 0.

-nextsibling itemDesc
Specifies the item before which the new items will be inserted. The new items will have the same parent as itemDesc.

-open boolean
Specifies whether the items should be open or closed. Default is true.

-parent itemDesc
Specifies the item which the new items will be the children of. The new items will be appended to the list of children of itemDesc.

-prevsibling itemDesc
Specifies the item after which the new items will be inserted. The new items will have the same parent as itemDesc.

-returnid boolean
Specifies whether or not to return a list of item identifiers for the newly created items. Specifying false is useful when creating a large number of items in the console or to improve performance. Default is true.

-tags tagList
TagList is a list of tag names to be added to the new items.

-visible boolean
Boolean must have one of the forms accepted by Tcl_GetBoolean. It indicates that the item should be displayed in the list. The item will only be displayed if: a) each ancestor is a descendant of the root item (not an orphan); and b) each ancestor's -visible option is true
pathName item delete first ?last?
Deletes the specified item(s). First and last must be valid item descriptions. If last isn't specified, then first may specify multiple items. If both first and last are specified, they must each decribe a single item with a common ancestor; then the range of items between first and last is deleted. The order of first and last doesn't matter.

Deleting an item deletes any child items of the deleted item recursively. If the current active item is deleted, the root item becomes the new active item. If the current selection anchor item is deleted, the root item becomes the new anchor item. There is no way to delete the root item of the treectrl widget; in all cases the specification of the root item is ignored.

For each call to this command, two events may be generated. If any of the deleted items are selected, then a <Selection> event is generated just before the items are deleted. If any items are going to be deleted, then an <ItemDelete> event event is generated just before the items are deleted.

pathName item descendants itemDesc
Returns a list containing the item ids of the descendants of the item specified by itemDesc, i.e. the children, grandchildren, great-grandchildren etc, of the item.

pathName item dump itemDesc
Returns a list with 4 words in the form index index indexVis indexVis.

pathName item element command itemDesc column element ?arg ...?
This command is used to manipulate elements of the item. The exact behavior of the command depends on the command argument that follows the element argument. The following forms of the command are supported:

pathName item element actual itemDesc column element option
Deprecated. Use item element perstate instead.

pathName item element cget itemDesc column element option
This command returns the value of the option named option associated with element inside column of the item described by itemDesc, if it was already configured for the actual item. Option may have any of the values accepted by the type of the specified element (see ELEMENTS below)

pathName item element configure itemDesc column element ?option? ?value? ?option value ...?
This command modifies configuration options for an element in a column of an item. If no option is specified, the command returns a list describing all of the available options for the element (see Tk_ConfigureInfo for information on the format of this list). If option is specified with no value, 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 option is specified).

If one or more option-value pairs are specified, then the command modifies the given option(s) to have the given value(s) in the element inside column of the item(s) described by itemDesc; in this case the command returns an empty string. This is the only case where itemDesc may refer to multiple items.

It is possible to configure multiple elements in multiple columns with a single call. To configure another element in the same column, append a '+' argument followed by the element name. To configure elements in another column, append a ',' argument followed by the column. For example:

 
.t item element configure $I \
	$C1 $E1 -text "hello" + $E2 -text "world" , \
	$C2 $E3 -fill Blue , \
	$C3 $E1 -text "apples and oranges"

Each of the column description arguments to this command may refer to multiple columns if at least one option-value pair is given.

pathName item element perstate itemDesc column element option ?stateList?
This command returns the current value of the per-state option named option for element inside column of the item described by itemDesc. If stateList is specified, the list of state names (static and dynamic, see STATES) is used in place of the current state for item and column.
pathName item enabled itemDesc ?boolean?
Returns 1 if the item described by itemDesc has the state enabled switched on, 0 otherwise. If boolean is specified, then the enabled state of every item described by the item description itemDesc is set accordingly. All items are enabled when first created. Disabled items cannot be selected, and are ignored by the default key-navigation and mouse bindings.

pathName item expand itemDesc ?-recurse?
Switches on the open state of the item(s) described by itemDesc. If an item has descendants, then they are now displayed. If an item is already open, then this command has no effect on that item. If -recurse is specified, then all descendants of the items described by itemDesc will also be expanded. For every item that actually will be expanded, two events are generated: an <Expand-before> event before the item state is changed, and an <Expand-after> event after the item state was changed.

pathName item firstchild parent ?child?
If child is not specified, returns the item id of the first child of the item described by parent. If child is specified, it must describe an item that is neither the root item nor an ancestor of parent. Then it will become the new first child of parent.

pathName item id itemDesc
This command resolves the item description itemDesc into a list of unique item identifiers. If itemDesc doesn't refer to any existing items, then this command returns an empty list.

pathName item image itemDesc ?column? ?image? ?column image ...?
This command sets or retrieves the value of the per-state -image option for the first image element in one or more columns. If no column is specified, this command returns a list of values, one per column. If no image is specified, this command returns the value for column.

If one or more column-image pairs is specified, then the value of the -image option in each column is set to image. In this case itemDesc may refer to multiple items and each column may refer to multiple columns.

Note that this command is provided as a convenience. Use the item element configure or item element cget commands if you want to set or retrieve the value of the -image option for a specific image element.

pathName item isancestor itemDesc descendant
Returns 1 if the item described by itemDesc is a direct or indirect parent of the item decribed by descendant, 0 otherwise.

pathName item isopen itemDesc
Returns 1 if the item described by itemDesc has the state open switched on, 0 otherwise.

pathName item lastchild parent ?child?
If child is not specified, returns the item id of the last child of the item described by parent. If child is specified, it must describe an item that is not an ancestor of parent. Then it will become the new last child of parent.

pathName item nextsibling sibling ?next?
If next is not specified, returns the item id of the next sibling of the item described by sibling. If next is specified, it must describe an item that is not an ancestor of sibling. Then it will become the new next sibling of sibling.

pathName item numchildren itemDesc
Returns the number of children of the item described by itemDesc.

pathName item order itemDesc ?-visible?
This command returns the position of the item itemDesc relative to its toplevel ancestor (usually the root item, unless the ancestor is an orphan). If you imagine all the items flattened into a vertical list, the result of this command is the row the item falls in. If the optional argument -visible is given, only the items whose ancestors are expanded, and whose -visible option is true, get counted; in this case -1 is returned if the item is not visible.

pathName item parent itemDesc
Returns the item id of the parent of the item described by itemDesc.

pathName item prevsibling sibling ?prev?
If prev is not specified, returns the item id of the previous sibling of the item described by sibling. If prev is specified, it must describe an item that is not an ancestor of sibling. Then it will become the new previous sibling of sibling.

pathName item range first last
Returns a list containing the item ids of all items in the range between first and last, inclusive. The order between first and last doesn't matter, and the result is always sorted by the increasing order of the items (as returned by the item order command). The items specified by first and last must share a common ancestor.

pathName item remove itemDesc
Removes the item described by itemDesc from the list of children of its parent, so that it will become an orphan.

pathName item rnc itemDesc
Returns a list of two integers, which corresponds to the row and column of the item described by itemDesc. The row and column corresponds to the on-screen arrangement of items as determined by the -orient and -wrap options. If the item is not displayed, this command returns an empty string.

pathName item sort itemDesc ?option ...?
Sorts the children of the item described by itemDesc, and redisplays the tree with the items in the new order.

The range of items which should be sorted can be restricted by means of the -first and/or -last options, which should be children of the item described by itemDesc; the order between these two limiting items doesn't matter.

The sort column can be specified by means of the -column option; this option can be used repeatedly to define a multicolumn sort. The sorting is done by looking at the text of the element specified by the -element option, which must be a text element defined in the style of the sorting column, by default the first text element is used.

If the -notreally option is specified, no rearranging of the items is done; instead the sorted items are returned as result of the command.

By default ASCII sorting is used with the result returned in increasing order. Any of the following options may be specified to control the sorting process of the previously specified column (unique abbreviations are accepted):

-ascii
Use string comparison with ASCII collation order. This is the default.

-command command
Use command as a comparison command. To compare two items, evaluate a Tcl script consisting of command with the numerical ids of the two items appended as additional arguments. The script should return an integer less than, equal to, or greater than zero if the first item is to be considered less than, equal to, or greater than the second, respectively.

-decreasing
Sort the items in decreasing order ("largest" items first).

-dictionary
Use dictionary-style comparison. This is the same as -ascii except (a) case is ignored except as a tie-breaker and (b) if two strings contain embedded numbers, the numbers compare as integers, not characters. For example, in -dictionary mode, bigBoy sorts between bigbang and bigboy, and x10y sorts between x9y and x11y.

-increasing
Sort the items in increasing order ("smallest" items first). This is the default.

-integer
Convert to integers and use integer comparison.

-real
Convert to floating-point values and use floating comparison.
pathName item span itemDesc ?column? ?numColumns? ?column numColumns ...?
This command sets or retrieves the number of columns that a style covers. If no column is specified, the return value is a list of spans, one per column. If no numColumns is specified, the return value is the span for column.

If one or more column-numColumns pairs is specified, the span for each column is set to numColumns. In this case itemDesc may refer to multiple items and each column may refer to multiple columns.

pathName item state command itemDesc ?arg ...?
This command is used to manipulate the states of an item. The exact behavior of the command depends on the command argument that follows the style argument. The following forms of the command are supported:

pathName item state forcolumn itemDesc column ?stateDescList?
Just like item state set but manipulates dynamic states for a single item column, not the item as a whole. If stateDescList is unspecified, this command returns a list containing the names of all the dynamic states which are switched on in column.

If stateDescList is specified, then itemDesc may refer to multiple items and column may refer to multiple columns.

pathName item state get itemDesc ?stateName?
If no stateName is specified, returns a list containing the names of all (static and dynamic) states which are currently switched on for the item described by itemDesc. If a stateName is specified, 1 is returned if the specified state is currently switched on for the item, 0 otherwise.

pathName item state set itemDesc ?lastItem? stateDescList
Every element of stateDescList must be the name of a dynamic state (see STATES below), optionally preceded by a ~ or ! character. Every state with a leading ! will be switched off for the item described by itemDesc, every state with a leading ~ will be toggled, and every state without leading ! or ~ will be switched on. If lastItem is specified, the state changes will be made for all items in the range between itemDesc and lastItem. If lastItem unspecified, then the state changes are made for all items described by itemDesc.
pathName item style command itemDesc ?arg ...?
This command is used to manipulate the styles of an item. The exact behavior of the command depends on the command argument that follows the style argument. The following forms of the command are supported:

pathName item style elements itemDesc column
This command returns a list containing the names of elements which were configured by the item element configure command for the item described by itemDesc in column. If there is no style assigned to column an error is returned.

pathName item style map itemDesc column style map
Like the item style set command, this command may be used to assign a style to a specific column of an item. Unlike item style set, this command can transfer configuration values of elements in the current style to elements in the new style specified by style. Map must be a list of elementOld-elementNew pairs, where elementOld is an element in the current style, and elementNew is an element in the style specified by style. Both elementOld and elementNew must be of the same type (bitmap, text etc). ItemDesc may refer to multiple items and column may refer to multiple columns.

pathName item style set itemDesc ?column? ?style? ?column style ...?
This command sets or retrieves the style assigned to one or more columns. If no column is specified, this command returns a list containing the names of the styles set for all columns of the item described by itemDesc. If no style is specified, this command returns the name of the style set for the item described by itemDesc in column.

If one or more column-style pairs is specified, then the style in each column is set to style. In this case itemDesc may refer to multiple items and each column may refer to multiple columns.
pathName item tag option ?arg arg ...?
This command is used to manipulate tags on items. The exact behavior of the command depends on the option argument that follows the item tag argument. The following forms of the command are supported:

pathName item tag add itemDesc tagList
Adds each tag in tagList to the items specified by the item description itemDesc. Duplicate tags are ignored. The list of tags for an item can also be changed via an item's -tags option.

pathName item tag expr itemDesc tagExpr
Evaluates the tag expression tagExpr against every item specified by the item description itemDesc. The result is 1 if the tag expression evaluates to true for every item, 0 otherwise.

pathName item tag names itemDesc
Returns a list of tag names assigned to the items specified by the item description itemDesc. The result is the union of any tags assigned to the items.

pathName item tag remove itemDesc tagList
Removes each tag in tagList from the items specified by the item description itemDesc. It is not an error if any of the items do not use any of the tags. The list of tags for an item can also be changed via an item's -tags option.
pathName item text itemDesc ?column? ?text? ?column text ...?
This command sets or retrieves the value of the -text option for the first text element in one or more columns. If no column is specified, this command returns a list of values, one per column. If no text is specified, this command returns the value for column.

If one or more column-text pairs is specified, then the value of the -text option in each column is set to text. In this case itemDesc may refer to multiple items and each column may refer to multiple columns.

Note that this command is provided as a convenience. Use the item element configure or item element cget commands if you want to set or retrieve the value of the -text option for a specific text element.

pathName item toggle itemDesc ?-recurse?
Changes the open state of the item(s) described by itemDesc. If the open state is currently switched off, then this command does the same as the item expand widget command; otherwise the same as the item collapse widget command. If -recurse is specified, then the open state of all descendants of the items described by itemDesc will also be toggled.
pathName marquee option ?arg ...?
This command is used to manipulate the marquee, a rectangular region of the treectrl widget optionally marked with a surrounding dotted line. One corner point of the marquee is fixed as long as the marquee is visible and called the anchor; the diagonally opposite corner is dragged with the mouse while resizing the marquee and simply called the corner. All coordinates handled by this widget command are treectrl coordinates, i.e. the canvasx or canvasy widget command should be used before any window coordinates can be used. The exact behavior of the command depends on the option argument that follows the marquee argument. The following forms of the command are supported:

pathName marquee anchor ?x y?
Returns a list containing the x and y coordinates of the anchor, if no additional arguments are specified. If two coordinates are specified, sets the anchor to the given coordinates x and y.

pathName marquee cget option
This command returns the current value of the marquee option named option. Option may have any of the values accepted by the marquee configure widget command.

pathName marquee configure ?option? ?value? ?option value ...?
This command is similar to the configure widget command except that it modifies the marquee options instead of modifying options for the overall treectrl widget. If no option is specified, the command returns a list describing all of the available marquee options (see Tk_ConfigureInfo for information on the format of this list). If option is specified with no value, then the command returns a list describing the one named marquee option (this list will be identical to the corresponding sublist of the value returned if no option is specified). If one or more option-value pairs are specified, then the command modifies the given marquee option(s) to have the given value(s); in this case the command returns an empty string.

The following marquee options are supported:

-visible boolean
Specifies a boolean value which determines whether the dotted line surrounding the region of the marquee should currently be visible.
pathName marquee coords ?x1 y1 x2 y2?
Returns a list containing the x and y coordinates of the anchor followed by the x and y coordinates of the corner, if no additional arguments are specified. If four coordinates are specified, sets the anchor to the given coordinates x1 and y1 and the corner to the coordinates x2 and y2.

pathName marquee corner ?x y?
Returns a list containing the x and y coordinates of the corner, if no additional arguments are specified. If two coordinates are specified, sets the corner to the given coordinates x and y.

pathName marquee identify
Returns a list with information about any items intersecting the marquee. The format of the returned list is:

 
{
    {item {column element element ...} {column element element ...} ...}
    {item {column element element ...} {column element element ...} ...}
    ...
}

There may be zero sublists following an item id if the marquee is in the button/line area of an item. There may be zero element names following a column id if the item-column has no style or if the marquee does not intersect any elements in that column.
pathName notify option ?arg ...?
Many Tk widgets communicate with the outside world via -command callbacks and/or virtual events. For example, the Text widget evaluates its -yscrollcommand when the view in the widget changes, and generates a <<Modified>> virtual event when text is inserted or deleted. A treectrl widget replaces both methods of communication with its own event mechanism accessed through the notify subcommands.

The exact behavior of the command depends on the option argument that follows the notify argument. The following forms of the command are supported:

pathName notify bind ?object? ?pattern? ?+??script?
This command associates Tcl scripts with events generated by a treectrl widget. If all three arguments are specified, notify bind will arrange for script (a Tcl script) to be evaluated whenever the event(s) specified by pattern are generated by this treectrl widget. If script is prefixed with a "+", then it is appended to any existing binding for pattern; otherwise script replaces any existing binding. If script is an empty string then the current binding for pattern is destroyed, leaving pattern unbound. In all of the cases where a script argument is provided, notify bind returns an empty string.

If pattern is specified without a script, then the script currently bound to pattern is returned, or an empty string is returned if there is no binding for pattern. If neither pattern nor script is specified, then the return value is a list whose elements are all the patterns for which there exist bindings for object.

The object argument determines which window(s) the binding applies to. If object begins with a dot, as in .a.b.c, then it must be the path name for a window; otherwise it may be an arbitrary string. Like the regular bind command, bindings on window names are automatically removed if that window is destroyed.

pathName notify configure object pattern ?option? ?value? ?option value ...?
This command sets and retrieves options for bindings created by the notify bind command.

If no option is specified, the command returns a list with option-value pairs describing all the available binding options for pattern on object. If option is specified with no value, then the command returns the current value of that option. If one or more option-value pairs are specified, then the command modifies the given option(s) to have the given value(s) for the binding; in this case the command returns an empty string.

The following binding options are supported:

-active boolean
Specifies if the binding should be active. As long as this option is specified as false, a binding script will not be evaluated when the corresponding event is generated.
pathName notify detailnames eventName
Returns a list containing the names of all details, which are installed for the event with the name eventName by means of the notify install widget command or by the treectrl widget itself.

pathName notify eventnames
Returns a list containing the names of all events, which are installed by means of the notify install widget command or by the treectrl widget itself.

pathName notify generate pattern ?charMap? ?percentsCommand?
This command causes the treectrl widget to generate an event. This command is typically used to generate dynamic events created by the notify install command, but may be used to generate static events also. The event specified by pattern is generated, and any active binding scripts on the event are evaluated after undergoing %-substitution. If there are details defined for the event, pattern must describe an <eventName-detail> pair, otherwise pattern should be <eventName>.

The optional charMap is a list of char-value pairs as in the form returned by array get. Each char has to be exactly one character. The charMap is used in %-substitution.

If percentsCommand is specified, then it will be used to perform %-substitution on any scripts bound to the event. If percentsCommand is not specified and the event is dynamic, then the %-subtitution command passed to notify install will be used if it was provided. If the event is static or no %-substitution command is available, then all %-substitution is done using charMap only . See notify install for a description of percentsCommand.

pathName notify install pattern ?percentsCommand?
This command installs a new event or detail specified by pattern. Events created by this command are called dynamic, whereas events created by the treectrl widget itself are called static. This command may be called to set or retrieve the percentsCommand for an existing dynamic event.

The optional percentsCommand is a list containing the name of a Tcl command, plus any optional arguments, to which five additional arguments will be appended. The command will be called to perform %-substitution on any scripts bound to the event specified by pattern (see EVENTS AND SCRIPT SUBSTITUTIONS). PercentsCommand should be defined as follows:

 
proc percentsCommand {?arg arg ...? char object event detail charMap} {
	switch -- $char {
		...
	}
	return $value
}

The optional arg arguments are part of the percentsCommand list. Char is the %-character to be substituted. Object is the same as the argument to notify bind. Event and detail specify the event. CharMap is the same as the argument to notify generate. PercentsCommand should return the value to replace the %-character by. If an error occurs evaluating percentsCommand, the %-character is replaced by itself.

notify install returns the current percentsCommand for the event, or an error if the event is not dynamic.

pathName notify install detail eventName detail ?percentsCommand?
Deprecated. Use notify install with a pattern of <eventName-detail> instead.

pathName notify install event eventName ?percentsCommand?
Deprecated. Use notify install with a pattern of <eventName> instead.

pathName notify linkage pattern
Returns a string indicating whether the specified event or detail is created by means of the notify install widget command (dynamic) or by the treectrl widget itself (static).

pathName notify linkage eventName ?detail?
Deprecated. Use notify linkage with a pattern of <eventName> or <eventName-detail> instead.

pathName notify unbind object ?pattern?
If no pattern is specified, all bindings on object are removed. If pattern is specified, then the current binding for pattern is destroyed, leaving pattern unbound.

pathName notify uninstall pattern
If the event or detail specified by pattern is static (i.e. created by the treectrl widget itself), an error is generated. Otherwise the dynamic event or detail is removed. If an event name is specified without a detail, all details for that event are also removed.

pathName notify uninstall detail eventName detail
Deprecated. Use notify uninstall with a pattern of <eventName-detail> instead.

pathName notify uninstall event eventName
Deprecated. Use notify uninstall with a pattern of <eventName> instead.
pathName numcolumns
Deprecated. Use the column count command instead.

pathName numitems
Deprecated. Use the item count command instead.

pathName orphans
Returns a list containing the item ids of all items which have no parent. When an item is created, it has no parent by default, and can later become an orphan by means of the item remove widget command. The root item is not returned.

pathName range first last
Deprecated. Use the item range command instead.

pathName scan option args
This command is used to implement scanning on treectrls. It has two forms, depending on option:

pathName scan mark x y
Records x and y and the treectrl's current view; used in conjunction with later scan dragto commands. Typically this command is associated with a mouse button press in the widget and x and y are the coordinates of the mouse. It returns an empty string.

pathName scan dragto x y ?gain?
This command computes the difference between its x and y arguments (which are typically mouse coordinates) and the x and y arguments to the last scan mark command for the widget. It then adjusts the view by gain times the difference in coordinates, where gain defaults to 10. This command is typically associated with mouse motion events in the widget, to produce the effect of dragging the treectrl at high speed through its window. The return value is an empty string.
pathName state option args
This command is used to manipulate the list of user-defined states, see section STATES below. The exact behavior of the command depends on the option argument that follows the state argument. The following forms of the command are supported:

pathName state define stateName
Defines a new state with the name stateName, which must not be the name of an existing state.

pathName state linkage stateName
Returns a string indicating whether the specified state is user-defined by means of the state define widget command (dynamic) or predefined by the treectrl widget itself (static).

pathName state names
Returns a list containing the names of all user-defined states.

pathName state undefine ?stateName ...?
Every stateName must be the name of a user-defined state. Removes this state from the list of user-defined states.
pathName see itemDesc
Adjust the view in the treectrl so that the item described by itemDesc is visible. If the item is already visible then the command has no effect; otherwise the treectrl scrolls to bring the item into view, and the corresponding <Scroll-x> and/or <Scroll-y> events are generated.

pathName selection option args
This command is used to adjust the selection within a treectrl. It has several forms, depending on option:

pathName selection add first ?last?
First and last (if specified) must be valid item descriptions. If both first and last are specified, then they may refer to a single item only; in this case the command adds every unselected item in the range between first and last, inclusive, to the selection without affecting the selected state of items outside that range. If only first is specified, then every unselected item specified by first is added to the selection. A <Selection> event is generated if any items were added to the selection.

pathName selection anchor ?itemDesc?
If itemDesc is specified, the selection anchor is set to the described item. The selection anchor is the end of the selection that is fixed while dragging out a selection with the mouse. The item description anchor may be used to refer to the anchor item. This command doesn't modify the selection state of any item. Returns the unique id of the selection anchor item.

pathName selection clear ?first? ?last?
First and last (if specified) must be valid item descriptions. If both first and last are specified, then they may refer to a single item only; in this case any selected items between first and last (inclusive) are removed from the selection without affecting the selected state of items outside that range. If only first is specified, then every selected item specified by first is removed from the selection. If neither first nor last are specified, then all selected items are removed from the selection. A <Selection> event is generated if any items were removed from the selection.

pathName selection count
Returns an integer indicating the number of items in the treectrl that are currently selected.

pathName selection get ?first? ?last?
When no additional arguments are given, the result is an unsorted list containing the item ids of all of the items in the treectrl that are currently selected. If there are no items selected in the treectrl, then an empty string is returned. The optional arguments first and last are treated as indices into the sorted list of selected items; these arguments allow in-place lindex and lrange operations on the selection. For example:

 
.t selection get 0       ; # return the first selected item
.t selection get end     ; # return the last selected item
.t selection get 1 end-1 ; # return every selected item except the first and last



pathName selection includes itemDesc
Returns 1 if the item described by itemDesc is currently selected, 0 if it isn't.

pathName selection modify select deselect
Both arguments select and deselect are a possibly-empty list of item descriptions. Any unselected items in select are added to the selection, and any selected items in deselect are removed from the selection (except for those items which are also in select). A <Selection> event is generated if any items were selected or deselected.
pathName style option ?element? ?arg arg ...?
This command is used to manipulate styles, which can be thought of as a geometry manager for elements. The exact behavior of the command depends on the option argument that follows the style argument. The following forms of the command are supported:

pathName style cget style option
This command returns the current value of the option named option associated with the style given by style. Option may have any of the values accepted by the style configure widget command.

pathName style configure style ?option? ?value? ?option value ...?
This command is similar to the configure widget command except that it modifies options associated with the style given by style instead of modifying options for the overall treectrl widget. If no option is specified, the command returns a list describing all of the available options for style (see Tk_ConfigureInfo for information on the format of this list). If option is specified with no value, 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 option is specified). If one or more option-value pairs are specified, then the command modifies the given option(s) to have the given value(s) in style; in this case the command returns an empty string.

The options of a style have effect on all elements managed by the style. The following options are supported:

-orient varName
This option specifies which orientation should be used when laying out the elements associated with this style. Must be either horizontal (the default) or vertical or an abbreviation of one of these.
pathName style create style ?option value ...?
Create a new style in pathName with name style. After style there may be any number of option-value pairs, each of which sets one of the configuration options for the style. These same option-value pairs may be used in style configure widget commands to change the style's configuration. Returns the name of the new style.

pathName style delete ?style ...?
Deletes each of the named styles and returns an empty string. If a style is deleted while it is still used to display one or more items, it is also removed from the style list of these items.

pathName style elements style ?elementList?
Specifies the elements which should be layed out by this style. Each element of elementList must be the name of an element created by the widget command element create. Duplicate names in elementList are ignored. An element which was specified in a former call of this command for style but is not included in elementList, will be deleted from the elements layed out by style.

If the elementList argument is not specified, a list is returned containing the currently defined elements of style.

pathName style layout style element ?option? ?value? ?option value ...?
This command is similar to the configure widget command except that it modifies options used by style for laying out element instead of modifying options for the overall treectrl widget. If no option is specified, the command returns a list with option-value pairs describing all of the available options for the layout. If option is specified with no value, then the command returns the value of the named option. If one or more option-value pairs are specified, then the command modifies the given option(s) to have the given value(s) for the layout; in this case the command returns an empty string.

The options of a layout have effect on exactly the one element element managed by style. The following options are supported:

-detach boolean
Specifies whether the element should be positioned by itself, i.e. independent from the other elements.

-draw boolean
This is a per-state option that determines whether an element should be drawn. If the value of the option evaluates to false for a given item state, then the element is not drawn, although it still consumes space in the layout.

-expand flags
This option allows the external padding around the element to increase when a style has more screen space than it needs. Flags is a string that contains zero or more of the characters n, s, w or e. Each letter refers to the padding on the top, bottom, left, or right that should be allowed to increase. This option is typically used to justify an element.

-iexpand flags
This option allows the internal padding of the element and the display area of the element to increase when a style has more screen space than it needs. Flags is a string that contains zero or more of the characters x, y, n, s, w or e. For n, s, w and e, each letter refers to the padding on the top, bottom, left, or right that should be allowed to increase. For x and y, each letter refers to the horizontal and vertical screen space the element can display itself in (i.e., the space between the padding). Note that if the -union option is specified for this element, then the x and y flags have no effect, since the size of an element with -union layout is determined by the elements it surrounds.

-indent boolean
Specifies whether the element should be positioned to the right of the button/line area in the tree column. This option is ignored unless the -detach option is true.

-ipadx amount
-ipady amount
Amount specifies how much internal padding to leave on the left and right (for -ipadx) or top and bottom (for -ipady) side of the element. Amount may be a list of two values to specify padding for the two sides separately, it defaults to 0.

-minheight pixels
-height pixels
-maxheight pixels
Specifies the minimum, fixed, and maximum height of the element.

-minwidth pixels
-width pixels
-maxwidth pixels
Specifies the minimum, fixed, and maximum width of the element.

-padx amount
-pady amount
Amount specifies how much external padding to leave on the left and right (for -padx) or top and bottom (for -pady) side of the element. Amount may be a list of two values to specify padding for the two sides separately, it defaults to 0.

-squeeze flags
This option allows the display area of an element to decrease when a style has less space than it needs. Flags is a string that contains zero or more of the characters x or y. x allows display area to decrease horizontally, y allows display area to decrease vertically. This option is typically used for text elements and will cause the text element to display an ellipsis (...) and/or wrap lines.

-sticky flags
This option controls how the actual display information (image, text, etc) of an element is positioned (or stretched) within its display area. Flags is a string that contains zero or more of the characters n, s, w or e. Each letter refers to the top, bottom, left or right side of the display area that the display information should "stick" to.

-union elementList
Specifies a list of other elements which this element will surround. The size of an element with -union layout is determined by the size and position of the elements in elementList. The -ipadx and -ipady options in this case refer to the distance of the edges of the display area of this element from those elements it surrounds. This option is typically used to display a selection rectangle around a piece of text. If none of the elements in elementList are visible, then the element is not displayed.

-visible boolean
This is a per-state option that controls visibility of an element. If the value of the option evaluates to false for a given item state, then the element is not displayed and consumes no space in the layout.
pathName style names
Returns a list containing the names of all existing styles.
pathName toggle ?-recurse? ?itemDesc ...?
Use item toggle instead.

pathName xview ?args?
This command is used to query and change the horizontal position of the information displayed in the treectrl's window. It can take any of the following forms:

pathName xview
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 tree's area is off-screen to the left, the middle 40% is visible in the window, and 40% of the tree is off-screen to the right. These are the same values passed to scrollbars via the -xscrollcommand option.

pathName xview moveto fraction
Adjusts the view in the window so that fraction of the total width of the tree is off-screen to the left. Fraction must be a fraction between 0 and 1. A <Scroll-x> event is generated.

pathName xview scroll number what
This command shifts the view in the window left or right according to number and what. Number must be an integer. What must be either units or pages or an abbreviation of one of these. If what is units, the view adjusts left or right in units determined by the -xscrollincrement option (which may be zero, see the description of that option). If what is pages then the view adjusts in units of nine-tenths the window's width. If number is negative then information farther to the left becomes visible; if it is positive then information farther to the right becomes visible. A <Scroll-x> event is generated.
pathName yview ?args?
This command is used to query and change the vertical position of the information displayed in the treectrl's window. It can take any of the following forms:

pathName yview
Returns a list containing two elements. Each element is a real fraction between 0 and 1; together they describe the vertical span that is visible in the window. For example, if the first element is .6 and the second element is 1.0, the lowest 40% of the tree's area is visible in the window. These are the same values passed to scrollbars via the -yscrollcommand option.

pathName yview moveto fraction
Adjusts the view in the window so that fraction of the tree's area is off-screen to the top. Fraction is a fraction between 0 and 1. A <Scroll-y> event is generated.

pathName yview scroll number what
This command adjusts the view in the window up or down according to number and what. Number must be an integer. What must be either units or pages. If what is units, the view adjusts up or down in units of the -yscrollincrement option (which may be zero, see the description of that option). If what is pages then the view adjusts in units of nine-tenths the window's height. If number is negative then higher information becomes visible; if it is positive then lower information becomes visible. A <Scroll-y> event is generated.

COLUMNS

A treectrl widget is capable of displaying multiple columns next to each other. An item can be considered as a row, which reaches over all columns.

Columns in a treectrl may be specified in a number of ways. See COLUMN DESCRIPTION below.

There is always one special column, the tail column, which fills all space to the right of the last ordinary column. This column has no number; it can only be specified by the keyword tail.

When a column configuration option is specified as per-state, the state names are normal, active, pressed or up, i.e. do not use item state names.

The following options are supported for columns:

-arrow direction
Indicates whether or not an arrow should be drawn in the column header. Direction must have one of the values none (the default), up, or down.

-arrowbitmap bitmap
Specifies as a per-state option the bitmap to use to draw the arrow if this column's -arrow option is not none.

-arrowimage image
Specifies as a per-state option the image to use to draw the arrow if this column's -arrow option is not none. If an image is specified for a certain state, it overrides the -arrowbitmap option.

-arrowside side
Indicates on which side of the bitmap/image/text the arrow should be drawn. Side must be either left or right (the default).

-arrowgravity side
Indicates onto which side an arrow should be packed, if there is more space available for drawing the arrow then needed. Side must be either left (the default) or right.

-arrowpadx amount
Amount specifies how much padding to leave on the left and right of the arrow. Amount may be a list of two values to specify padding for left and right separately; it defaults to 6.

-arrowpady amount
Amount specifies how much padding to leave on the top and bottom of the arrow. Amount may be a list of two values to specify padding for top and bottom separately; it defaults to 0.

-bitmap bitmap
Specifies the bitmap to display in the element to the left of the column title.

-background color
Specifies as a per-state option the color to use for the background of the column header.

-borderwidth size
Specifies a non-negative value indicating the width of the 3-D border to draw around the outside of the column header (if such a border is being drawn; the -relief column option determines this). The value may have any of the forms acceptable to Tk_GetPixels.

-button boolean
Indicates whether or not the column header should be treated like a pushbutton. When this option is true, the default bindings track <Button-1> events in the header and generate a <Header-invoke> event when a <ButtonRelease-1> event occurs in the header. See DYNAMIC EVENTS.

-expand boolean
Indicates whether or not any extra horizontal space should be distributed to this column. This option has no effect if the -width option is set.

-font fontName
Specifies the font to use for the column title inside the column header.

-image image
Specifies the image to display in the element to the left of the column title. This option overrides the -bitmap column option.

-imagepadx amount
Amount specifies how much padding to leave on the left and right of the image (or bitmap). Amount may be a list of two values to specify padding for left and right separately; it defaults to 6.

-imagepady amount
Amount specifies how much padding to leave on the top and bottom of the image (or bitmap). Amount may be a list of two values to specify padding for top and bottom separately; it defaults to 0.

-itembackground colorList
Specifies a list of zero or more colors, which are used as alternating background colors for items in this column. See also the -backgroundmode widget option for more on this.

-itemjustify justification
This option determines how the item styles in this column line up with each other. Must be one of left, center, or right. The default value is an empty string (for compatibility with older versions), in which case the column option -justify is used to align item styles in this column.

-itemstyle style
Style is the name of a style that should be set in this column for newly-created items.

-justify justification
This option determines how the image and text in the column header are positioned. It also affects the position of item styles in this column unless the column option -itemjustify is specified. Must be one of left (the default), center, or right.

-lock lock
This option allows a column to stick to the left or right edge of the window. A locked column scrolls vertically but not horizontally. Must be one of none (the default), left, or right.

-maxwidth size
Specifies the maximum size, in screen units, that will be permitted for this column. If size is an empty string, then there is no limit on the maximum size of the column. This option has no effect if the -width option is set.

-minwidth size
Specifies the minimum size, in screen units, that will be permitted for this column. If size is an empty string, then the minimum size of the column is zero. This option has no effect if the -width option is set.

-resize boolean
Specifies a boolean value that indicates whether the user should be allowed to resize the column by dragging the edge of the column's header. Default is true.

-squeeze boolean
Specifies a boolean value that indicates whether or not the column should shrink when the content width of the treectrl is less than the total needed width of all visible columns. Defaults to false, which means the column will not get smaller than its needed width. The column will not get smaller than the value of its -minwidth option, if specified. This option has no effect if the -width option is set.

-state state
Specifies one of three states for the column header: normal, active, or pressed. The active state is used when the mouse is over the header. The pressed state is used when the mouse button is pressed in the header.

-stepwidth size
Deprecated. Use the treectrl's -itemwidthmultiple option instead.

-tags tagList
TagList is a list of tag names that can be used to identify the column. See also the column tag command.

-text text
Specifies a text string to be displayed as the column title.

-textcolor color
Specifies a color, which should be used as foreground color to display the column title.

-textlines count
Specifies the maximum number of lines of text to display in the column title. If this value is zero, the number of lines displayed is determined by any newline characters and the effects of wrapping when the column width is less than needed. The default is 1. Note: Under OSX/Aqua this value is always set to 1 when the treectrl's -usetheme option is true, because the Appearance Manager uses a fixed height for the column header; there is only room for a single line of text.

-textpadx amount
Amount specifies how much padding to leave on the left and right of the text. Amount may be a list of two values to specify padding for left and right separately; it defaults to 6.

-textpady amount
Amount specifies how much padding to leave on the top and bottom of the text. Amount may be a list of two values to specify padding for top and bottom separately; it defaults to 0.

-uniform group
When a non-empty value is supplied, this option places the column in a uniform group with other columns that have the same value for -uniform. The space for columns belonging to a uniform group is allocated so that their sizes are always in strict proportion to their -weight values. This option is based on the grid geometry manager.

-visible boolean
Indicates whether or not the column should be displayed.

-weight integer
Sets the relative weight for apportioning any extra space among columns. A weight of zero (0) indicates the column will not deviate from its requested size. A column whose weight is two will grow at twice the rate as a column of weight one when extra space is allocated to columns. This option is based on the grid geometry manager.

-width size
Specifies a fixed width for the column. If this value is an empty string, then the column width is calculated as the maximum of: a) the width requested by items; b) the width requested by the column's header; and c) the column's -minwidth option. This calculated width is also affected by the -expand, -squeeze, -uniform and -weight options. In any case, the calculated width will not be greater than the -maxwidth option, if specified.

-widthhack boolean
Deprecated. Use the treectrl's -itemwidthequal option instead.

COLUMN DESCRIPTION

Many of the commands and options for a treectrl take as an argument a description of which column to operate on. See the EXAMPLES section for examples. The initial part of a column description must begin with one of the following terms:

id
Specifies the unique column identifier, where id should be the return value of a prior call of the column create widget command. See also the -columnprefix option.

QUALIFIERS
Specifies a list of qualifiers. This gives the same result as all followed by QUALIFIERS; i.e., every column is tested for a match.

tagExpr QUALIFIERS
TagExpr is a tag expression (see ITEM AND COLUMN TAGS) against which every column's tags are tested for a match. This keyword cannot be followed by any modifiers unless a single column is matched. You may run into trouble if tagExpr looks like a column id or other keyword; also, tagExpr must look like a single list element since column descriptions are properly-formed lists. To be safe you may want to use the tag qualifier followed by tagExpr.

all QUALIFIERS
Indicates every column, including the tail column if the command allows it, which match QUALIFIERS.

first QUALIFIERS
Indicates the leftmost column of the treectrl which matches QUALIFIERS.

end QUALIFIERS
last QUALIFIERS
Indicates the rightmost column of the treectrl (but not the tail column) which matches QUALIFIERS.

list columnDescs
ColumnDescs is a list (a single argument, i.e. "list {a b c}" not "list a b c") of other column descriptions. This keyword cannot be followed by any modifiers unless a single column is matched.

order n QUALIFIERS
Indicates the nth column in the list of columns as returned by the column order command.

range first last QUALIFIERS
First and last specify a range of columns. This keyword cannot be followed by any modifiers unless a single column is specified.

tail
Indicates the ever-present tail column of the treectrl.

tree
Indicates the column specified by the -treecolumn option of the treectrl.

The initial part of the column description (matching any of the values above) may be followed by one or more modifiers. A modifier changes the column used relative to the description up to this point. It may be specified in any of the following forms:

next QUALIFIERS
Use the column to the right matching QUALIFIERS.

prev QUALIFIERS
Use the column to the left matching QUALIFIERS.
The word QUALIFIERS above represents a sequence of zero or more of the following terms that changes which column is chosen:
state stateList
StateList is a list of column state names. Only columns that have the given states set (or unset if the '!' prefix is used) are considered.

tag tagExpr
TagExpr is a tag expression (see ITEM AND COLUMN TAGS) against which a column's tags are tested for a match.

!tail
When this qualifier is given, the tail column is not matched.

visible
When this qualifier is given, only columns whose -visible option is TRUE are considered.

!visible
When this qualifier is given, only columns whose -visible option is FALSE are considered.

STATES

For every item a set of boolean states is managed. These states play an integral role in the appearance of each item. The following states are predefined for every item:

active
At all times this state is set for exactly one item. The active item is used with keyboard navigation. When the treectrl widget is created or when the active item is deleted, the root item will become the active item. This state can be modified by means of the widget command activate.

enabled
This state is set for every item when it is created. Disabled items cannot be selected and are ignored by the default bindings when navigating via the keyboard. This state can be modified by means of the widget command item enabled.

focus
This state is set for every item, if the treectrl widget currently has the focus. It cannot be modified by means of a widget command, but is maintained in reaction to the <FocusIn> and <FocusOut> events.

open
If this state is switched on, the descendants of the item are displayed - the item is expanded. If this state is switched off, the descendants of the item are not displayed - the item is collapsed. For a new item this state is switched on by default. This state can be modified by means of the widget commands item expand, item collapse, or item toggle.

selected
This state is set for every item included in the selection. It can be modified by means of the widget command selection.

By means of the state define widget command up to 27 additional states can be defined.

PER-STATE OPTIONS

The visual appearance of an item can change depending on the state the item is in, such as being the active item, being included in the selection, being collapsed, or some combination of those or other states. When a configuration option is described as per-state, it means the option describes a value which varies depending on the state of the item. If a per-state option is specified as a single value, the value is used for all states. Otherwise the per-state option must be specified as an even-numbered list. For example, to use the font "Times 12 bold" in a text element regardless of the item state you can write:

 
$T element configure MyTextElement -font {{Times 12 bold}}

However, to use a different font when the item is selected you could write:

 
$T element configure MyTextElement -font {{Courier 10} selected {Times 12 bold} {}}

In the example above, the -font option reads "value stateList value stateList". If stateList is an empty list, the preceding value is used regardless of the item state. A non-empty stateList specifies a list of states which must be set for the item in order to use the preceding value. Each stateList can also include state names preceded by a ! sign, indicating the state must *not* be set for the item. For example:

 
$T element configure MyRectElement -fill {blue {selected focus} gray {selected !focus}}

In the example above, the rect element is filled with blue when the treectrl has the focus and the item is selected. If the treectrl does not have the focus, the example specifies that gray should be used for selected items. Also note that if the item is not selected, no color is specified for the -fill option.

Each value-stateList pair is checked in order from left to right. The value associated with the first stateList that matches the current item state is used. So stateLists should be listed from most-specific to least-specific.

 
$T element configure MyRectElement -fill {gray {selected} blue {selected focus}}

Written this way, gray will always be used for selected items since it appears first, and blue will never be used for selected items regardless of the focus.

A value followed by an empty stateList should always be last since it will be chosen regardless of the item's state.

ELEMENTS

Elements are the smallest building blocks which are handled by a treectrl widget. One or more elements together can be combined to a style, which can be considered as a blueprint for an item. An element can be of type bitmap, border, image, rect, text or window. For each element type there is a section below describing the options which can modify an element of that type.

All of the element configuration options described below are unspecified by default, meaning that no value whatsoever has been given to the option. It may seem strange to you that a boolean option would be unspecified instead of simply "true" or "false". The reason for this is that when an element displayed by an item has no value specified for an option, the element refers to the master element created by the element create command for a value for that option. This allows items which are displaying a certain element to be redisplayed when the master element's options change. The item element configure command can be used to override the master element's configuration options for a specific item.

BITMAP ELEMENT

An element of type bitmap can be used to display a bitmap in an item. The following options are supported for bitmap elements:

-background color
Specifies as a per-state option the color to use for each of the bitmap's '0' valued pixels. If the value for a certain state is an empty string (the default), the bitmap is drawn transparent.

-bitmap bitmap
Specifies as a per-state option the bitmap to display in the element.

-draw boolean
Deprecated; use the style layout option -draw instead. Specifies as a per-state option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn.

-foreground color
Specifies as a per-state option the color to use for each of the bitmap's '1' valued pixels. If the value for a certain state is an empty string (the default), the bitmap's foreground color is black.

BORDER ELEMENT

An element of type border can be used to display a 3D border in an item. The following options are supported for border elements:

-background color
Specifies as a per-state option the color to use for the background of the border. If the value for a certain state is an empty string (the default), the element will not be drawn.

-draw boolean
Deprecated; use the style layout option -draw instead. Specifies as a per-state option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn.

-filled boolean
Specifies whether the interior of the border should be filled with the background color. If this option is unspecified (the default), it it treated as false which means that only the edges of the border will be drawn.

-height size
Specifies the height of the border. If this value is unspecified (the default), the border will be exactly as tall as its display area as determined by the style layout options.

-relief relief
Specifies as a per-state option the relief of the border. If the value for a certain state is an empty string (the default), it is treated as flat. For acceptable values see the description of the -relief option in the options manual page.

-thickness thickness
Specifies the thickness of the edges of the border.

-width size
Specifies the width of the border. If this value is unspecified (the default), the border will be exactly as wide as its display area as determined by the style layout options.

IMAGE ELEMENT

An element of type image can be used to display an image in an item. The following options are supported for image elements:

-draw boolean
Deprecated; use the style layout option -draw instead. Specifies as a per-state option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn.

-height size
Specifies the requested height of the display area for this element. If unspecified (the default), the element requests a height equal to the height of the image, or zero if there is no image.

-image image
Specifies as a per-state option the image to display in the element.

-width size
Specifies the requested width of the display area for this element. If unspecified (the default), the element requests a width equal to the width of the image, or zero if there is no image.

RECTANGLE ELEMENT

An element of type rect can be used to display a rectangle in an item. The following options are supported for rectangle elements:

-draw boolean
Deprecated; use the style layout option -draw instead. Specifies as a per-state option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn.

-fill color
Specifies as a per-state option the color to be used to fill the rectangle's area. If the color for a certain state is an empty string (the default), then the rectangle will not be filled (but the outline may still be drawn).

-height size
Specifies the height of the rectangle. If this value is unspecified (the default), the rectangle will be exactly as tall as its display area as determined by the style layout options.

-open open
This option may be used to get an incomplete drawing of the outline. Open is a string that contains zero or more of the characters n, s, e or w. Each letter refers to a side (north, south, east, or west) that the outline will not be drawn. The default is the empty string, which causes the outline to be drawn completely.

-outline color
Specifies as a per-state option the color to be used to draw the outline of the rectangle. If the color for a certain state is an empty string (the default), then no outline is drawn for the rectangle.

-outlinewidth outlineWidth
Specifies the width of the outline to be drawn around the rectangle's region. outlineWidth may be in any of the forms acceptable to Tk_GetPixels. If this option is specified as an empty string (the default), then no outline is drawn.

-showfocus boolean
Specifies a boolean value indicating whether a "focus ring" should be drawn around the rectangle, if the item containing the rectangle is the active item and the treectrl widget currently has the focus. If this option is specified as an empty string (the default), then a focus rectangle is not drawn.

-width size
Specifies the width of the rectangle. If this value is unspecified (the default), the rectangle will be exactly as wide as its display area as determined by the style layout options.

TEXT ELEMENT

An element of type text can be used to display a text in an item. The following options are supported for text elements:

-draw boolean
Deprecated; use the style layout option -draw instead. Specifies as a per-state option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn.

-data data
Specifies a value that together with the -datatype and -format options will be displayed as text.

-datatype dataType
Specifies the type of information in the -data option. Acceptable values are double, integer, long, string, or time.

-fill color
Specifies as a per-state option the foreground color to use when displaying the text. If the color for a certain state is an empty string (the default), then the text will be displayed using the color specified by the treectrl's -foreground option.

-format formatString
This option specifies the format string used to display the value of the -data option. If -datatype is time, formatString should be a valid format string for the Tcl clock command. For all other -datatype values formatString should be a valid format string for the Tcl format command. If this value is unspecified the following defaults are used: for -datatype double "%g", for -datatype integer "%d", for -datatype long "%ld", for -datatype string "%s", and for -datatype time the default format string of the Tcl clock command.

-font font
Specifies as a per-state option the font to use when displaying the text. If the font for a certain state is an empty string, the text is displayed using the font specified by the treectrl's -font option.

-justify how
Specifies how to justify the text when multiple lines are displayed. How must be one of the values left, right, or center. If this option is specified as an empty string (the default), left is used.

-lines lineCount
Specifies the maximum number of lines to display. If more than lineCount lines would be displayed, the last line will be truncated with an ellipsis at the right. If this option is specified as zero or an empty string (the default), there is no limit to the number of lines displayed.

-text string
String specifies a string to be displayed by the element. String may contain newline characters in which case multiple lines of text will be displayed. If this option is specified, the -data, -datatype, -format, and -textvariable options are ignored.

-textvariable varName
Specifies the name of a variable. The value of the variable is a string to be displayed by the element; if the variable value changes then the element will automatically update itself to display the new value. If this option is specified, the -data, -datatype, and -format options are ignored.

-underline charIndex
Specifies the integer index of a character to underline. 0 corresponds to the first character. If charIndex is unspecified (the default), less than zero or greater than the index of the last displayed character, the underline is not drawn.

-width size
Specifies the maximum line length in any of the forms acceptable to Tk_GetPixels. For text to wrap lines the value of the -width option must be less than the needed width of the text, or the display area for this element must be less than the needed width of the text. For the display area to be less than the needed width of the text, one of the style layout options -maxwidth, -width or -squeeze must be used.

-wrap mode
Mode specifies how to handle lines in the text that are longer than the maximum line length. Acceptable values are none, char or word. If this option is unspecified (the default), word is used. See the -width option for a description of how the maximum line length is determined.

WINDOW ELEMENT

An element of type window can be used to display a Tk window in an item. The following options are supported for window elements:

-clip boolean
Specifies whether the associated Tk window is a borderless frame which should be used to clip its child window so it doesn't overlap the header, borders, or other items or columns. When this option is true, the treectrl manages the geometry of both the -window widget and its first child widget; in this case the -window widget (which should be a borderless frame) is kept sized and positioned so that it is never out-of-bounds.

-destroy boolean
Specifies whether the associated Tk window should be destroyed when the element is deleted. The element is deleted when the item containing the element is deleted, when the column containing the element is deleted, or when the style assigned to the item's column is changed. If this option is unspecified (the default), it is treated as false and the Tk window will not be destroyed.

-draw boolean
Deprecated; use the style layout option -draw instead. Specifies as a per-state option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn.

-window pathName
Specifies the window to associate with this element. The window specified by pathName must either be a child of the treectrl widget or a child of some ancestor of the treectrl widget. PathName may not refer to a top-level window. This option cannot be specified by the element create or element configure commands, only by the item element configure command; i.e., the element must be associated with a particular item.

ITEM DESCRIPTION

Many of the commands for a treectrl take as an argument a description of which items to operate on. An item description is a properly-formed tcl list of keywords and arguments. The first word of an item description must be one of the following:

id
Specifies the unique item identifier, where id should be the return value of a prior call of the item create widget command, or 0 to specify the ever-present root item. See also the -itemprefix option.

QUALIFIERS
Specifies a list of qualifiers. This gives the same result as all followed by QUALIFIERS; i.e., every item is tested for a match.

tagExpr QUALIFIERS
TagExpr is a tag expression (see ITEM AND COLUMN TAGS) against which every item's tags are tested for a match. This keyword cannot be followed by any modifiers unless a single item is matched. You may run into trouble if tagExpr looks like an item id or other keyword; also, tagExpr must look like a single list element since item descriptions are properly-formed lists. To be safe you may want to use the tag qualifier followed by tagExpr.

active
Indicates the item that is currently active, i.e. normally the item specified as argument of the last successful activate widget command, or the root item if no such call happened yet.

anchor
Indicates the anchor item of the selection, i.e. normally the item specified as argument of the last successful selection anchor widget command, or the root item if no such call happened yet.

all QUALIFIERS
Indicates every item including orphans which match QUALIFIERS. This keyword cannot be followed by any modifiers unless a single item is matched.

first QUALIFIERS
Indicates the first item of the treectrl (the root item), or the first item matching QUALIFIERS.

end QUALIFIERS
last QUALIFIERS
Indicates the last item which matches QUALIFIERS.

list itemDescs
ItemDescs is a list (a single argument, i.e. "list {a b c}" not "list a b c") of other item descriptions. This keyword cannot be followed by any modifiers unless a single item is matched.

nearest x y
Indicates the item nearest to the point given by x and y.

rnc row column
Indicates the item in the given row and column. The row and column corresponds to the on-screen arrangement of items as determined by the -orient and -wrap options. You can memorize rnc as an abbreviation of "row 'n' column".

range first last QUALIFIERS
First and last specify a range of items. This keyword cannot be followed by any modifiers unless a single item is matched.

root
Indicates the root item of the treectrl.

The initial part of the item description (matching any of the values above) may be followed by one or more modifiers. A modifier changes the item used relative to the description up to this point. It may be specified in any of the following forms:

above
Use the item one row above in this column.

ancestors QUALIFIERS
Use the ancestors of the item (like item ancestors but QUALIFIERS may change which ancestors match). This keyword cannot be followed by any modifiers.

below
Use the item one row below in this column.

bottom
Use the item in the last row of this column.

child n QUALIFIERS
Use the nth child of the item.

children QUALIFIERS
Use the children of the item (like item children but QUALIFIERS may change which children match). This keyword cannot be followed by any modifiers.

descendants QUALIFIERS
Use the descendants of the item (like item descendants but QUALIFIERS may change which descendants match). This keyword cannot be followed by any modifiers.

firstchild QUALIFIERS
Use the first child of the item.

lastchild QUALIFIERS
Use the last child of the item.

left
Use the item one column to the left in the same row.

leftmost
Use the item of the first column in the same row.

next QUALIFIERS
Use the next item, which is the first item from the following list: the first child, the next sibling or the next sibling of the nearest ancestor which has one.

nextsibling QUALIFIERS
Use the next sibling of the item.

parent
Use the parent of the item.

prev QUALIFIERS
Use the last child of the previous sibling, or the parent if there is no previous sibling.

prevsibling QUALIFIERS
Use the previous sibling of the item.

right
Use the item one column to the right in the same row.

rightmost
Use the item of the last column in the same row.

sibling n QUALIFIERS
Use the nth child of the item's parent.

top
Use the item in the first row of this column.
The word QUALIFIERS above represents a series of zero or more of the following terms that changes which item is chosen:
depth depth
Matches items whose depth (as returned by the depth command) is equal to depth.

state stateList
StateList is a list of item state names (static and dynamic, see STATES). Only items that have the given states set (or unset if the '!' prefix is used) are considered.

tag tagExpr
TagExpr is a tag expression (see ITEM AND COLUMN TAGS) against which an item's tags are tested for a match.

visible
When this qualifier is given, only items that are displayed are considered.

!visible
When this qualifier is given, only items that are *not* displayed are considered.
To get the first item in the list that is enabled:

 
$T item id "first state enabled"

To get the ancestors that are not open of the last item in the list:

 
$T item id "last ancestors state !open"

To get the visible descendants of the root item:

 
$T item id "root descendants visible"

To get the every hidden item with tag "a" or "b":

 
$T item id "all !visible tag a||b"
$T item id "!visible tag a||b"
$T item id "tag a||b !visible"
$T item id "a||b !visible"

EVENTS AND SCRIPT SUBSTITUTIONS

The script argument to notify bind is a Tcl script, which will be evaluated whenever the given event is generated. Script will be executed in the same interpreter that the notify bind command was executed in, and it will run at global level (only global variables will be accessible). If script contains any % characters, then the script will not be evaluated directly. Instead, a new script will be generated by replacing each %, and the character following it, with information from the current event. Unlike the regular Tk bind mechanism, each event generated by a treectrl widget has its own set of %-substitutions.

The following %-substitutions are valid for all static events:

%%
Replaced with a single %

%d
The detail name

%e
The event name

%P
The pattern, either <event> or <event-detail>

%W
The object argument to the notify bind command

%T
The treectrl widget which generated the event

%?
A list of the format {char value char value ...} for each %-substitution character and the value it is replaced by

The following events may be generated by a treectrl widget:

<ActiveItem>
Generated whenever the active item changes.

%c
The current active item

%p
The previous active item
<Collapse-before>
Generated before an item is collapsed.

%I
The item id
<Collapse-after>
Generated after an item is collapsed.

%I
The item id
<Expand-before>
Generated before an item is expanded. This event is useful if you want to add child items to the item just before the item is expanded.

%I
The item id
<Expand-after>
Generated after an item is expanded.

%I
The item id
<ItemDelete>
Generated when items are about to be deleted by the item delete command.

%i
List of items ids being deleted.
<ItemVisibility>
Generated when items become visible on screen and when items are no longer visible on screen. This event is useful if you have a very large number of items and want to assign styles only when items are actually going to be displayed.

%h
List of items ids which are no longer visible.

%v
List of items ids which are now visible.
<Scroll-x>
Generated whenever the view in the treectrl changes in such a way that a horizontal scrollbar should be redisplayed.

%l
Same as the first fraction appended to -xscrollcommand. Think lower.

%u
Same as the second fraction appended to -xscrollcommand. Think upper.
<Scroll-y>
Generated whenever the view in the treectrl changes in such a way that a vertical scrollbar should be redisplayed.

%l
Same as the first fraction appended to -yscrollcommand. Think lower.

%u
Same as the second fraction appended to -yscrollcommand. Think upper.
<Selection>
Generated whenever the selection changes. This event gives information about how the selection changed.

%c
Same as the selection count widget command

%D
List of newly-deselected item ids

%S
List of newly-selected item ids

DYNAMIC EVENTS

In addition to the pre-defined static events such as <ActiveItem> and <Selection>, new dynamic events can be created by using the notify install command.

The following events may be generated by the library scripts:

<ColumnDrag-begin>
<ColumnDrag-receive>
<ColumnDrag-end>
Generated whenever the user drag-and-drops a column header. The library scripts do not actually move a dragged column. You must bind to the receive event to move the column. See EXAMPLES.

%C
The column that was dragged

%b
The column to move the dragged column before
<Drag-begin>
<Drag-receive>
<Drag-end>
Generated whenever the user drag-and-drops a file into a directory. This event is generated by the filelist-bindings.tcl library code, which is not used by default. See the "Explorer" demos.

%I
The item that the user dropped the dragged items on.

%l
(lowercase L) The list of dragged items.
<Edit-begin>
<Edit-accept>
<Edit-end>
The filelist-bindings.tcl code will display a text-editing window if the user clicks on a selected file/folder name. See the "Explorer" demos.

%I
The item containing the edited text element

%C
The column containing the edited text element

%E
The name of the edited text element

%t
The edited text
<Header-invoke>
Generated whenever the user clicks and releases the left mouse button in a column header if the column's -button option is true. You can bind a script to this event to sort the list.

%C
The column whose header was clicked
The library scripts provide an example of using a dynamic event called <Header-invoke>, which is generated when the mouse button is released over a column header.

 
treectrl .t
.t notify install <Header-invoke>
.t notify bind ConsoleTag <Header-invoke> {
	puts "header %C clicked in treectrl %T"
}
proc ::TreeCtrl::Release1 {w x y} {
	...
	$w notify generate <Header-invoke> [list C $Priv(column)] \
		[list ::TreeCtrl::PercentsCmd $w]
	...
}

In the example a new treectrl widget is created and the <Header-invoke> event is installed. For convenience there is no percentsCommand argument to notify install; instead the call to notify generate specifies the %-substitution command. A script is bound to the event with notify bind which will print out the column number and widget name to the console (in the demos, <Header-invoke> is used to sort the list based on the column that was clicked). The charMap argument to notify generate provides a list of %-substitution characters and values which is used by ::TreeCtrl::PercentsCmd. In this example any %C in any script bound to the <Header-invoke> event will be replaced by the value of $Priv(column).

DEFAULT BINDINGS

Tk automatically creates class bindings for treectrl widgets that give them the following default behavior.

  1. Clicking mouse button 1 over an item positions the active cursor on the item, sets the input focus to this widget, and resets the selection of the widget to this item, if it is not already in the selection.

  2. Clicking mouse button 1 with the Control key down will reposition the active cursor and add the item to the selection without ever removing any items from the selection.

  3. If the mouse is dragged out of the widget while button 1 is pressed, the treectrl will automatically scroll to make more items visible (if there are more items off-screen on the side where the mouse left the window).

  4. The Left and Right keys move the active cursor one item to the left or right; for an hierarchical tree with vertical orientation nothing will happen, since it has no two items in the same row. The selection is set to include only the active item. If Left or Right is typed with the Shift key down, then the active cursor moves and the selection is extended to include the new item.

  5. The Up and Down keys move the active cursor one item up or down. The selection is set to include only the active item. If Up or Down is typed with the Shift key down, then the active cursor moves and the selection is extended to include the new item.

  6. The Next and Prior keys move the active cursor forward or backwards by one screenful, without affecting the selection.

  7. Control-Next and Control-Prior scroll the view right or left by one page without moving the active cursor or affecting the selection. Control-Left and Control-Right behave the same.

  8. The Home and End keys scroll to the left or right end of the widget without moving the active cursor or affecting the selection.

  9. The Control-Home and Control-End keys scroll to the top or bottom of the widget, they also activate and select the first or last item. If also the Shift key is down, then the active cursor moves and the selection is extended to include the new item.

  10. The Space and Select keys set the selection to the active item.

  11. Control-/ selects the entire contents of the widget.

  12. Control-\\ clears any selection in the widget.

  13. The + and - keys expand or collapse the active item, the Return key toggles the active item.

  14. The mousewheel scrolls the view of the widget four lines up or down depending on the direction, the wheel was turned. The active cursor or the selection is not affected.

EXAMPLES

Get the unique identifier for the leftmost visible column:

 
set id [$T column index "first visible"]

Delete the leftmost column:

 
$T column delete "order 0"

Take the visible column that is to the left of the last column, and move that column in front of the tail column:

 
$T column move "last prev visible" tail

Get the unique identifier for the first visible item:

 
set id [$T item index "first visible"]

Delete the parent of the item that is under the point x,y:

 
$T item delete "nearest $x $y parent"

Add the 10th child of the second child of the root item to the selection:

 
$T selection add "root firstchild nextsibling child 10"

Move a column that the user drag-and-dropped:

 
$T column dragconfigure -enable yes
$T notify install <ColumnDrag-receive>
$T notify bind MyTag <ColumnDrag-receive> {
	%T column move %C %b
}

SEE ALSO

bind(n), bitmap(n), image(n), listbox(n), options(n)

KEYWORDS

tree, widget tktreectrl-2.2.8/doc/treectrl.man0000700000175600010010000046366211073207242015211 0ustar TimNone[comment {Copyright (c) 2002-2003 Christian Krone. See the file "license.terms" for information on usage and redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. $Id: treectrl.man,v 1.57 2008/10/08 19:48:50 treectrl Exp $} ] [manpage_begin treectrl n 2.2.8] [moddesc {Tk Commands}] [titledesc {Create and manipulate hierarchical multicolumn widgets}] [require treectrl 2.2.8] [description] [list_begin definitions] [call [cmd treectrl] [arg pathName] [opt [arg options]]] [list_end] [para] The [cmd treectrl] command creates a new window (given by the [arg pathName] argument) and makes it into a treectrl widget. Additional options, described above, may be specified on the command line or in the option database to configure aspects of the treectrl such as its background color and relief. The [cmd treectrl] command returns the path name of the new window. At the time this command is invoked, there must not exist a window named [arg pathName], but [arg pathName]'s parent must exist. [para] A treectrl is a widget which displays items in a one- or two-dimensional arrangement. Items have a parent-child relationship with other items. Items have a set of states, which are boolean properties. Items may be spread about one or more columns. For each column of an item there is a style associated, which determines how to display the item's column taking into account the item's current state set. One column can be defined to display the data in a hierarchical structure. [para] Normally the origin of the coordinate system is at the upper-left corner of the window containing the treectrl. It is possible to adjust the origin of the coordinate system relative to the origin of the window using the [cmd xview] and [cmd yview] widget commands; this is typically used for scrolling. [para] A treectrl widget can be horizontal or vertical oriented like many other Tk widgets. For displaying hierarchical data only vertical orientation is useful, since only then the children of an item are displayed directly below their parent. If the treectrl widget is used only to display data in a multicolumn listbox, the specification of an orientation will give useful results. [section {STANDARD OPTIONS}] [list_begin opt] [opt_def [option -background]] [opt_def [option -borderwidth]] [opt_def [option -cursor]] [opt_def [option -font]] [opt_def [option -highlightbackground]] [opt_def [option -highlightcolor]] [opt_def [option -highlightthickness]] [opt_def [option -orient]] [opt_def [option -relief]] [opt_def [option -takefocus]] [opt_def [option -xscrollcommand]] [opt_def [option -yscrollcommand]] [opt_def [option -foreground]] [list_end] See the [cmd option] manual entry for details on the standard options. [section {WIDGET SPECIFIC OPTIONS}] [list_begin tkoption] [tkoption_def -backgroundimage backgroundImage BackgroundImage] Specifies the name of an image to draw as the list background. The image is tiled horizontally and vertically to fill the content area of the list. If the image is transparent it is drawn on top of the background color(s). [tkoption_def -backgroundmode backgroundMode BackgroundMode] Specifies how the background color of items is chosen in each column. The value should be one of [const row], [const column], [const order], or [const ordervisible]. The default is [const row]. This option has only an effect for columns which have [option -itembackground] defined as list of two or more colors (see section [sectref COLUMNS] below for more on this). If [const row] or [const column] is specified, the background color is chosen based on the location of the item in the 1- or 2-dimensional grid of items as layed out on the screen; this layout of items is affected by the [option -orient] and [option -wrap] options as well as item visibility. When [const order] or [const ordervisible] is specified, the background color is chosen based on the result of the [cmd {item order}] command, regardless of the layout of items. [tkoption_def -buttonbitmap buttonBitmap ButtonBitmap] Specifies the bitmap to be used as the expand/collapse button to the left of an item. This is a [sectref {PER-STATE OPTIONS} per-state] option. If a bitmap is specified for a certain item state, it overrides the effects of -usetheme. [tkoption_def -buttoncolor buttonColor ButtonColor] Specifies the foreground color which should be used for drawing the outline and the plus or minus sign of the button to the left of an item. [tkoption_def -buttonimage buttonImage ButtonImage] Specifies the image to be used as the expand/collapse button to the left of an item. This is a [sectref {PER-STATE OPTIONS} per-state] option. If an image is specified for a certain item state, it overrides the effects of -buttonbitmap and -usetheme. [tkoption_def -buttonsize buttonSize ButtonSize] Specifies the width and height of the button drawn to the left of an item in any of the forms acceptable to [fun Tk_GetPixels]. [tkoption_def -buttonthickness buttonThickness ButtonThickness] Specifies the width of the outline and the plus or minus sign of the button to the left of an item in any of the forms acceptable to [fun Tk_GetPixels]. [tkoption_def -columnprefix columnPrefix ColumnPrefix] Specifies an ascii string that changes the way column ids are reported and processed. If this option is a non-empty string, the usual integer value of a column id is prefixed with the given string. This can aid debugging but it is important your code doesn't assume column ids are integers if you use it. [tkoption_def -columnproxy columnProxy ColumnProxy] If this option specifies a non empty value, it should be a screen distance in any of the forms acceptable to [fun Tk_GetPixels]. Then a 1 pixel thick vertical line will be drawn at the specified screen distance from the left edge of the treectrl widget, which reaches from top to bottom of the treectrl widget and uses an inverting color (i.e black on lighter background, white on darker background). This line can be used to give the user a visual feedback during column resizing. [tkoption_def -columnresizemode columnResizeMode ColumnResizeMode] Specifies the visual feedback used when resizing columns. The value should be one of [const proxy] or [const realtime]. For [const proxy], a 1-pixel thick vertical line is drawn representing where the right edge of the column will be after resizing. For [const realtime], the column's size is changed while the user is dragging the right edge of the column. [tkoption_def -columntagexpr columnTagExpr ColumnTagExpr] Specifies a boolean that enables or disables tag expressions in column descriptions. See [sectref {ITEM AND COLUMN TAGS}]. [tkoption_def -defaultstyle defaultStyle DefaultStyle] This option is deprecated; use the column option [option -itemstyle] instead. Specifies a list of styles, one per column, to apply to each item created by the [cmd "item create"] command. The number of styles in the list can be different from the number of tree columns. Each list element should be a valid style name or an empty string to indicate no style should be applied to a specific column. The list of styles is updated if a style is deleted or if a column is moved. [tkoption_def -doublebuffer doubleBuffer DoubleBuffer] Specifies if double-buffering should be used to improve displaying. The value should be one of [const none], [const window], or [const item]. For [const none] no double-buffering is used at all, which may be most memory efficient, but will probably generate some flickering on the screen. For [const window] the complete tree is double-buffered, which requires a buffer big enough to contain the complete widget. For [const item], which is the default, every item is separately double-buffered, so it works with a buffer size as big as the biggest item. [tkoption_def -height height Height] Specifies the desired height for the window in any of the forms acceptable to [fun Tk_GetPixels]. The default is 200 pixels. If this option is less than or equal to zero then the window will not request any size at all. [tkoption_def -indent indent Indent] Specifies the screen distance an item is indented relative to its parent item in any of the forms acceptable to [fun Tk_GetPixels]. The default is 19 pixels. [tkoption_def -itemheight itemHeight ItemHeight] Specifies a fixed height for every item in any of the forms acceptable to [fun Tk_GetPixels]. If non-zero, this option overrides the requested height of an item and the -minitemheight option. The default is 0, which means that every item has the height requested by the arrangement of elements in each column. Items are never shorter than the maximum height of a button. [tkoption_def -itemprefix itemPrefix ItemPrefix] Specifies an ascii string that changes the way item ids are reported and processed. If this option is a non-empty string, the usual integer value of an item id is prefixed with the given string. This can aid debugging but it is important your code doesn't assume item ids are integers if you use it. [tkoption_def -itemtagexpr itemTagExpr ItemTagExpr] Specifies a boolean that enables or disables tag expressions in item descriptions. See [sectref {ITEM AND COLUMN TAGS}]. [tkoption_def -itemwidth itemWidth ItemWidth] Specifies a fixed width for every item in any of the forms acceptable to [fun Tk_GetPixels]. If more than one column is visible, then this option has no effect. If the -orient option is vertical, and the -wrap option is unspecified, then this option has no effect (in that case all items are as wide as the column). [tkoption_def -itemwidthequal itemWidthEqual ItemWidthEqual] Specifies a boolean that says whether all items should have the same width. If more than one column is visible, then this option has no effect. If the -orient option is vertical, and the -wrap option is unspecified, then this option has no effect (in that case all items are as wide as the column). If the -itemwidth option is specified, then this option has no effect. [tkoption_def -itemwidthmultiple itemWidthMultiple ItemWidthMultiple] Specifies a screen distance that every item's width will be evenly divisible by in any of the forms acceptable to [fun Tk_GetPixels]. If more than one column is visible, then this option has no effect. If the -orient option is vertical, and the -wrap option is unspecified, then this option has no effect (in that case all items are as wide as the column). If the -itemwidth option is specified, then this option has no effect. [tkoption_def -linecolor lineColor LineColor] Specifies the color which should be used for drawing the connecting lines between related items. [tkoption_def -linestyle lineStyle LineStyle] Specifies the style of the connecting lines between related items, should be [const dot] which is the default, or [const solid]. [tkoption_def -linethickness lineThickness LineThickness] Specifies the thickness of the connecting lines between related items in any of the forms acceptable to [fun Tk_GetPixels]. [tkoption_def -minitemheight minItemHeight MinItemHeight] Specifies a minimum height for every item in any of the forms acceptable to [fun Tk_GetPixels]. The default is 0, which means that every item has the height requested by the arrangement of elements in each column. This option has no effect if the -itemheight option is specified. Items are never shorter than the maximum height of a button. [tkoption_def -rowproxy rowProxy RowProxy] If this option specifies a non empty value, it should be a screen distance in any of the forms acceptable to [fun Tk_GetPixels]. Then a 1 pixel thick horizontal line will be drawn at the specified screen distance from the top edge of the treectrl widget, which reaches from left to right of the treectrl widget and uses an inverting color (i.e black on lighter background, white on darker background). This line can be used to give the user a visual feedback during row resizing. [tkoption_def -scrollmargin scrollMargin ScrollMargin] Specifies a positive screen distance in any of the forms acceptable to [fun Tk_GetPixels]. This option is used by the default bindings to determine how close to the edges of the contentbox the mouse pointer must be before scrolling occurs. Specifying a positive value is useful when items may be drag-and-dropped. Defaults to 0. [tkoption_def -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 [const single], [const browse], [const multiple], or [const extended]; the default value is [const browse]. [tkoption_def -showbuttons showButtons ShowButtons] Specifies a boolean value that determines whether this widget leaves indentation space to display the expand/collapse buttons next to items. The default value is true. The item option [option -button] determines whether any item has a button. See also the treectrl option [option -showrootbutton]. [tkoption_def -showheader showHeader ShowHeader] Specifies a boolean value that determines whether this widget should display the header line with the column names at the top of the widget. The default value is true. [tkoption_def -showlines showLines ShowLines] Specifies a boolean value that determines whether this widget should draw the connecting lines between related items. The default value is true. [tkoption_def -showroot showRoot ShowRoot] Specifies a boolean value that determines whether this widget should draw the root item. By suppressing the drawing of the root item the widget can have multiple items that appear as [emph toplevel] items. The default value is true. [tkoption_def -showrootbutton showRootButton ShowRootButton] Specifies a boolean value that determines whether this widget leaves indentation space to display the expand/collapse button next to the root item. The default value is false. The item option [option -button] determines whether the root item has a button. [tkoption_def -showrootchildbuttons showRootChildButtons ShowRootChildButtons] Specifies a boolean value that determines whether this widget should draw the expand/collapse buttons next to children of the root item. The default value is true. [tkoption_def -showrootlines showRootLines ShowRootLines] Specifies a boolean value that determines whether this widget should draw the connecting lines between children of the root item. The default value is true. [tkoption_def -treecolumn treeColumn TreeColumn] Specifies a [sectref {COLUMN DESCRIPTION} {column description}] that determines which column displays the buttons and lines. The default is unspecified. [tkoption_def -usetheme useTheme UseTheme] Specifies a boolean value that determines whether this widget should draw parts of itself using a platform-specific theme manager. The default is false. [tkoption_def -width width Width] Specifies the desired width for the window in any of the forms acceptable to [fun Tk_GetPixels]. The default is 200 pixel. If this option is less than or equal to zero then the window will not request any size at all. [tkoption_def -wrap wrap Wrap] Specifies whether items are arranged in a 1- or 2-dimensional layout. If the value is an empty string (the default), then items are arranged from top to bottom (-orient vertical) or from left to right (-orient horizontal) in a 1-dimensional layout. If the value is "[emph N] [const items]", then a no more than [emph N] items will appear in a vertical group (-orient vertical) or horizontal group (-orient horizontal). If the value is "[emph N] [const pixels]", then a no vertical group of items will be taller than [emph N] pixels (-orient vertical) or no horizontal group of items will be wider than [emph N] pixels (-orient horizontal). If the value is [const window], then a no vertical group of items will be taller than the window (-orient vertical) or no horizontal group of items will be wider than the window (-orient horizontal). [tkoption_def -xscrolldelay xScrollDelay ScrollDelay] This option controls how quickly horizontal scrolling occurs while dragging the mouse with button 1 pressed. The value should be a list of 1 or 2 integers interpreted as microseconds. If 2 values are specified, then the first value determines the intial delay after the first scroll, and the second value determines the delay for all scrolling after the first. If only 1 value is specified, each scroll takes place after that delay. [tkoption_def -xscrollincrement xScrollIncrement ScrollIncrement] Specifies an increment for horizontal scrolling, in any of the usual forms permitted for screen distances. If the value of this option is greater than zero, the horizontal view in the window will be constrained so that the x coordinate at the left edge of the window is always an even multiple of [option -xscrollincrement]; furthermore, the units for scrolling (e.g., the change in view when the left and right arrows of a scrollbar are selected) will also be [option -xscrollincrement]. If the value of this option is less than or equal to zero, then horizontal scrolling snaps to the left of an item, or part of an item if items are wider than the contentbox. [tkoption_def -yscrolldelay yScrollDelay ScrollDelay] This option controls how quickly vertical scrolling occurs while dragging the mouse with button 1 pressed. The value should be a list of 1 or 2 integers interpreted as microseconds. If 2 values are specified, then the first value determines the intial delay after the first scroll, and the second value determines the delay for all scrolling after the first. If only 1 value is specified, each scroll takes place after that delay. [tkoption_def -yscrollincrement yScrollIncrement ScrollIncrement] Specifies an increment for vertical scrolling, in any of the usual forms permitted for screen distances. If the value of this option is greater than zero, the vertical view in the window will be constrained so that the y coordinate at the top edge of the window is always an even multiple of [option -yscrollincrement]; furthermore, the units for scrolling (e.g., the change in view when the top and bottom arrows of a scrollbar are selected) will also be [option -yscrollincrement]. If the value of this option is less than or equal to zero, then vertical scrolling snaps to the top of an item, or part of an item if items are taller than the contentbox. [list_end] [section {ITEM AND COLUMN TAGS}] Columns and items may have any number of tags associated with them. A tag is just a string of characters, and it may take any form, including that of an integer, although the characters '(', ')', '&', '|', '^' and '!' should be avoided. [para] The same tag may be associated with many columns or items. This is commonly done to group items in various interesting ways; for example, in a file browser all directories might be given the tag "directory". [para] Tag expressions are used in [sectref {COLUMN DESCRIPTION} {column descriptions}] and [sectref {ITEM DESCRIPTION} {item descriptions}] to specify which columns and items to operate on. A tag expression can be a single tag name or a logical expression of tags using operators '&&', '||', '^' and '!', and parenthesized subexpressions. For example: [example_begin] .t item id "tag {(a && !b) || (!a && b)}" [example_end] or equivalently: [example_begin] .t item id "tag {a ^ b}" [example_end] will return the unique ids of any items with either "a" or "b" tags, but not both. [para] Within a tag expression a tag name may be enclosed in double quotes to avoid special processing of the operator characters. For example: [example_begin] .t item id {tag {"a&&b"||c}} [example_end] will return the unique ids of any items with either "a&&b" or "c" tags; in this example the && is not treated as an operator. A double-quote may be escaped within a quoted tag name using a backslash '\'. [para] Tag operators may be bypassed completely by setting the [option -columntagexpr] and [option -itemtagexpr] options. This can be useful if your application has column or item tags containing arbitrary text. [example_begin] .t configure -itemtagexpr false .t item delete "tag a&&b" [example_end] [section {WIDGET COMMAND}] The [cmd treectrl] command creates a new Tcl command whose name is the same as the path name of the treectrl's window. This command may be used to invoke various operations on the widget. It has the following general form: [para] [arg pathName] [arg option] [opt [arg {arg arg ...}]] [para] [arg PathName] is the name of the command, which is the same as the treectrl widget's path name. [arg Option] and the [arg arg]s determine the exact behavior of the command. The following commands are possible for treectrl widgets: [list_begin definitions] [call [arg pathName] [cmd activate] [arg itemDesc]] Sets the active item to the one described by [arg itemDesc], and switches on the state [const active] for this item. From now on the item can be retrieved with the item description [const active]. An [const ] event is generated. [call [arg pathName] [cmd bbox] [opt [arg area]]] Returns a list with four elements giving the bounding box (left, top, right and bottom) of an area of the window. If [arg area] is not specified, then the result is the bounding box of the entire window. If [arg area] is [const content], then the result is the part of the window not including borders, headers, or locked columns. If [arg area] is [const header], then the result is the part of the window not including borders where column titles are displayed. If [arg area] is [const left], then the result is the part of the window not including borders or headers where left-locked columns are displayed. If [arg area] is [const right], then the result is the part of the window not including borders or headers where right-locked columns are displayed. An empty string is returned if the display area has no height or width, which can be true for various reasons such as the window is too small, or the header is not displayed, or there aren't any locked columns. [call [arg pathName] [cmd canvasx] [arg screenx]] Given a window x-coordinate in the treectrl [arg screenx], this command returns the treectrl x-coordinate that is displayed at that location. [call [arg pathName] [cmd canvasy] [arg screeny]] Given a window y-coordinate in the treectrl [arg screeny], this command returns the treectrl y-coordinate that is displayed at that location. [call [arg pathName] [cmd cget] [arg option]] Returns the current value of the configuration option given by [arg option]. [arg Option] may have any of the values accepted by the [cmd tree] command. [call [arg pathName] [cmd collapse] [opt [option -recurse]] \ [opt [arg {itemDesc ...}]]] Use [cmd {item collapse}] instead. [call [arg pathName] [cmd column] [arg option] [arg column] \ [opt [arg {arg ...}]]] This command is used to manipulate the columns of the treectrl widget (see section [sectref COLUMNS] below). The exact behavior of the command depends on the [arg option] argument that follows the [cmd column] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {column bbox}] [arg columnDesc]] Returns a list with four elements giving the bounding box of the header of the column specified by the [sectref {COLUMN DESCRIPTION} {column description}] [arg columnDesc]. If the treectrl is configured not to display the column headers by means of the [option -showheader] option, then an empty list is returned instead. [call [arg pathName] [cmd {column cget}] [arg columnDesc] [arg option]] This command returns the current value of the option named [arg option] for the column specified by the [sectref {COLUMN DESCRIPTION} {column description}] [arg columnDesc], [arg ColumnDesc] may also be the string [const tail] to specify the tail column. [arg Option] may have any of the values accepted by the [cmd {column configure}] widget command. [call [arg pathName] [cmd {column configure}] [arg columnDesc] \ [opt [arg option]] [opt [arg value]] [opt [arg {option value ...}]]] This command is similar to the [cmd configure] widget command except that it modifies options associated with the columns specified by the [sectref {COLUMN DESCRIPTION} {column description}] [arg columnDesc] instead of modifying options for the overall treectrl widget. [arg ColumnDesc] may be the string [const tail] to specify the tail column. If [arg columnDesc] refers to more than one column, then at least one option-value pair must be given. If no [arg option] is specified, the command returns a list describing all of the available options for [arg columnDesc] (see [fun Tk_ConfigureInfo] for information on the format of this list). If [arg option] is specified with no [arg value], 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 [arg option] is specified). If one or more [arg option]-[arg value] pairs are specified, then the command modifies the given option(s) to have the given value(s) for [arg columnDesc]; in this case the command returns an empty string. [nl] See [sectref COLUMNS] below for details on the options available for columns. [call [arg pathName] [cmd {column compare}] [arg column1] [arg op] [arg column2]] For both [sectref {COLUMN DESCRIPTION} {column descriptions}] [arg column1] and [arg column2] the index is retrieved (as returned from the [cmd {column order}] widget command). Then these indexes are compared using the operator [arg op], which must be either [const <], [const <=], [const ==], [const >=], [const >], or [const !=]. The return value of this command is 1 if the comparison evaluated to true, 0 otherwise. [call [arg pathName] [cmd {column count}] [opt [arg columnDesc]]] If no additional arguments are given, the result is a decimal string giving the number of columns created by the [cmd "column create"] widget command which haven't been deleted by the [cmd "column delete"] widget command; in this case the [const tail] column is not counted. If [arg columnDesc] is given, then the result is the number of columns that match that [sectref {COLUMN DESCRIPTION} {column description}]. [call [arg pathName] [cmd {column create}] [opt [arg {option value ...}]]] This command creates a new column in the treectrl widget. The new column is placed to the right of all other columns (except the [const tail] column). Any [arg option]-[arg value] arguments configure the new column according to the [cmd "column configure"] command. The return value is the unique identifier of the new column. [call [arg pathName] [cmd {column delete}] [arg first] [opt [arg last]]] Deletes the specified column(s). [arg First] and [arg last] must be valid [sectref {COLUMN DESCRIPTION} {column descriptions}]. If both [arg first] and [arg last] are specified, then they may refer to a single column only. The [const tail] column cannot be deleted and it is an error to specify it. The order of [arg first] and [arg last] doesn't matter, and [arg first] may be equal to [arg last]. [call [arg pathName] [cmd {column dragcget}] [arg option]] [call [arg pathName] [cmd {column dragconfigure}] \ [opt [arg option]] [opt [arg value]] [opt [arg {option value ...}]]] The user can move a column within a treectrl by drag-and-drop. Feedback consists of a semi-transparent photo image of the header of the column being dragged and a 2-pixel-thick vertical line to indicate where the column may be dropped. The drag image consists of a colored background rectangle plus the image and/or text displayed in the column header. The 2-pixel-thick line will be drawn over the left edge of the column before which the dragged column may be dropped. [nl] The library scripts generate a event when the user has successfully drag-and-drop'd a column. You will have to bind a script to this event if you want to move the dragged column. [nl] The following configuration options are supported: [list_begin opt] [opt_def [option -enable] [arg boolean]] Controls whether the user is allowed to rearrange columns by drag-and-drop. [opt_def [option -imagealpha] [arg alpha]] [arg Alpha] is an integer from 0 (invisible) to 255 (opaque) controlling the transparency of the drag image. Any value outside this range is clipped. [opt_def [option -imagecolor] [arg background]] [arg Background] is the color of the drag image background rectangle. [opt_def [option -imagecolumn] [arg column]] [arg Column] specifies the column to create the drag image from. [opt_def [option -imageoffset] [arg offset]] [arg Offset] is the horizontal screen distance the drag image is offset from its starting position. [opt_def [option -indicatorcolor] [arg color]] [arg Color] is the color of the 2-pixel-thick line. [opt_def [option -indicatorcolumn] [arg column]] The 2-pixel-thick line will be drawn over the left or right edge of [arg column]. [opt_def [option -indicatorside] [arg side]] Specifies whether the 2-pixel-thick line will be drawn over the [const left] or [const right] edge of the column specified by [option -indicatorcolumn]. [list_end] [call [arg pathName] [cmd {column index}] [arg columnDesc]] Deprecated. Use [cmd {column id}] instead. [call [arg pathName] [cmd {column id}] [arg columnDesc]] This command resolves the [sectref {COLUMN DESCRIPTION} {column description}] [arg columnDesc] into a list of unique column identifiers. If the column(s) described by [arg columnDesc] don't exist, this command returns an empty list. [call [arg pathName] [cmd {column list}] [opt [arg -visible]]] This command returns a list of identifiers for every column (except the tail) from left to right. If [arg -visible] is given, only columns whose -visible option is true are returned. [call [arg pathName] [cmd {column move}] [arg columnDesc] [arg beforeDesc]] Moves the column specified by [arg columnDesc] to the left of the column specified by [arg beforeDesc]. Both [arg columnDesc] and [arg beforeDesc] must be valid [sectref {COLUMN DESCRIPTION} {column descriptions}]. If [arg beforeDesc] is the string [const tail], the column [arg columnDesc] will become the last column. [call [arg pathName] [cmd {column neededwidth}] [arg columnDesc]] This command returns a decimal string giving the needed width of the column specified by the [sectref {COLUMN DESCRIPTION} {column description}] [arg columnDesc]. The needed width is the maximum of the width of the column header and the width of the widest style in any visible item. [call [arg pathName] [cmd {column order}] [arg columnDesc] [opt [arg -visible]]] This command returns a decimal string giving the position of the column specified by the [sectref {COLUMN DESCRIPTION} {column description}] [arg columnDesc] in the list of columns starting from zero for the leftmost column. If [arg -visible] is given, only columns whose -visible option is true are considered, and -1 is returned if [arg columnDesc]'s -visible option is false. [call [arg pathName] [cmd {column tag}] [arg option] [opt [arg {arg arg ...}]]] This command is used to manipulate tags on columns. The exact behavior of the command depends on the [arg option] argument that follows the [cmd {column tag}] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {column tag add}] [arg columnDesc] [arg tagList]] Adds each tag in [arg tagList] to the columns specified by the [sectref {COLUMN DESCRIPTION} {column description}] [arg columnDesc]. Duplicate tags are ignored. The list of tags for a column can also be changed via a column's [option -tags] option. [call [arg pathName] [cmd {column tag expr}] [arg columnDesc] [arg tagExpr]] Evaluates the tag expression [arg tagExpr] against every column specified by the [sectref {COLUMN DESCRIPTION} {column description}] [arg columnDesc]. The result is 1 if the tag expression evaluates to true for every column, 0 otherwise. [call [arg pathName] [cmd {column tag names}] [arg columnDesc]] Returns a list of tag names assigned to the columns specified by the [sectref {COLUMN DESCRIPTION} {column description}] [arg columnDesc]. The result is the union of any tags assigned to the columns. [call [arg pathName] [cmd {column tag remove}] [arg columnDesc] [arg tagList]] Removes each tag in [arg tagList] from the columns specified by the [sectref {COLUMN DESCRIPTION} {column description}] [arg columnDesc]. It is not an error if any of the columns do not use any of the tags. The list of tags for a column can also be changed via a column's [option -tags] option. [list_end] [call [arg pathName] [cmd {column width}] [arg columnDesc]] This command returns a decimal string giving the width in pixels of the column specified by the [sectref {COLUMN DESCRIPTION} {column description}] [arg columnDesc], even if the treectrl is configured to not display the column headers by means of the [option -showheader] option. [list_end] [call [arg pathName] [cmd compare] [arg itemDesc1] [arg op] [arg itemDesc2]] Deprecated. Use the [cmd {item compare}] command instead. [call [arg pathName] [cmd configure] [opt [arg option]] \ [opt [arg {value option value ...}]]] Query or modify the configuration options of the widget. If no [arg option] is specified, returns a list describing all of the available options for [arg pathName] (see [fun Tk_ConfigureInfo] for information on the format of this list). If [arg option] is specified with no [arg value], 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 [arg option] is specified). If one or more [arg option]-[arg value] 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. [arg Option] may have any of the values accepted by the [cmd treectrl] command. [call [arg pathName] [cmd contentbox]] Returns a list with four elements giving the bounding box of the screen area used to display items. This is the area of the window not including borders, column headers, or locked columns. An empty string is returned if the display area has no height or width, which can happen if the window is too small. [call [arg pathName] [cmd debug] [arg option] [opt [arg {arg arg ...}]]] This command is used to facilitate debugging of the treectrl widget. The exact behavior of the command depends on the [arg option] argument that follows the [cmd debug] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {debug alloc}]] Returns a string giving partial statistics on memory allocations, if the package was built with TREECTRL_DEBUG defined. [call [arg pathName] [cmd {debug cget}] [arg option]] This command returns the current value of the debugging option named [arg option]. [arg Option] may have any of the values accepted by the [cmd {debug configure}] widget command. [call [arg pathName] [cmd {debug configure}] \ [opt [arg option]] [opt [arg value]] [opt [arg {option value ...}]]] This command is similar to the [cmd configure] widget command except that it modifies debugging options instead of modifying options for the overall treectrl widget. If no [arg option] is specified, the command returns a list describing all of the available debugging options (see [fun Tk_ConfigureInfo] for information on the format of this list). If [arg option] is specified with no [arg value], 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 [arg option] is specified). If one or more [arg option]-[arg value] pairs are specified, then the command modifies the given debugging option(s) to have the given value(s); in this case the command returns an empty string. [nl] The following debugging options are supported: [list_begin opt] [opt_def [option -displaydelay] [arg millis]] Specifies a time duration in milliseconds, which should be waited after something has been drawn to the screen. Setting this option has only an effect, if the debugging options [option -enable] and [option -display] are switched on. [opt_def [option -data] [arg boolean]] If this option is switched on (together with the debugging option [option -enable]), at various places a consistence check on the internal data structure is made (e.g. for every item is checked, if the registered number of children is equal to the number of child items). If an inconsistency was found, a Tcl background error is raised. [opt_def [option -display] [arg boolean]] If this option is switched on (together with the debugging option [option -enable]), at varios places additional debugging output is printed to stdout. [opt_def [option -drawcolor] [arg color]] When specified, areas of the window are painted with this color when drawing in those areas is about to occur. Setting this option has only an effect if the debugging options [option -enable] and [option -display] are switched on. [opt_def [option -enable] [arg boolean]] All other debugging options only take effect if this option is also switched on. [opt_def [option -erasecolor] [arg color]] When specified, areas of the window which have been marked as "invalid" (for example, when part of the window is exposed) are painted with this color. If you use an unusual color for this option (like [const pink]), superflous screen redraws can be spotted more easily. Setting this option has only an effect if the debugging options [option -enable] and [option -display] are switched on. [opt_def [option -span] [arg boolean]] Debugging related to column spanning. [opt_def [option -textlayout] [arg boolean]] Debugging related to text-element layout. [list_end] [call [arg pathName] [cmd {debug dinfo}] [arg option]] Returns a string describing display-related stuff. [arg Option] must be one of [const alloc], [const ditem], [const onscreen] or [const range]. [call [arg pathName] [cmd {debug expose}] [arg x1] [arg y1] [arg x2] [arg y2]] Causes the area of the window bounded by the given window-coords to be marked as invalid. This simulates uncovering part of the window. [call [arg pathName] [cmd {debug scroll}]] Returns a string useful for debugging vertical scrolling. [list_end] [call [arg pathName] [cmd depth] [opt [arg itemDesc]]] If the additional argument [arg itemDesc] is given, then the result is a decimal string giving the depth of the item described by [arg itemDesc]. If no [arg itemDesc] is specified, then the maximum depth of all items in the treectrl widget is returned instead. Depth is defined as the number of ancestors an item has. [call [arg pathName] [cmd dragimage] [arg option] [opt [arg {arg ...}]]] This command is used to manipulate the dragimage, one or more dotted lines around rectangular regions of the treectrl widget. The exact behavior of the command depends on the [arg option] argument that follows the [cmd dragimage] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {dragimage add}] [arg itemDesc] \ [opt [arg column]] [opt [arg element]]] Adds the shapes of the item described by [arg itemDesc] to the shapes of the dragimage. Specifying additional arguments reduces the number of rectangles that are added to the dragimage. If no additional arguments is specified, for every element of the item in every column a dotted rectangles is added. If [arg column] is specified, all elements in other columns are ignored. If also [arg element] is specified, only a rectangle for this one element of the specified item in the given column is added. [call [arg pathName] [cmd {dragimage cget}] [arg option]] This command returns the current value of the dragimage option named [arg option]. [arg Option] may have any of the values accepted by the [cmd {dragimage configure}] widget command. [call [arg pathName] [cmd {dragimage clear}]] Removes all shapes (if there are any) from the dragimage. This command does not modify the dragimage offset. [call [arg pathName] [cmd {dragimage configure}] [opt [arg option]] \ [opt [arg value]] [opt [arg {option value ...}]]] This command is similar to the [cmd configure] widget command except that it modifies the dragimage options instead of modifying options for the overall treectrl widget. If no [arg option] is specified, the command returns a list describing all of the available dragimage options (see [fun Tk_ConfigureInfo] for information on the format of this list). If [arg option] is specified with no [arg value], then the command returns a list describing the one named dragimage option (this list will be identical to the corresponding sublist of the value returned if no [arg option] is specified). If one or more [arg option]-[arg value] pairs are specified, then the command modifies the given dragimage option(s) to have the given value(s); in this case the command returns an empty string. [nl] The following dragimage options are supported: [list_begin opt] [opt_def [option -visible] [arg boolean]] Specifies a boolean value which determines whether the dragimage should currently be visible. [list_end] [call [arg pathName] [cmd {dragimage offset}] [opt [arg {x y}]]] Returns a list containing the x and y offsets of the dragimage, if no additional arguments are specified. The dragimage offset is the screen distance, the image is displayed relative to the item its shape is derived from. If two coordinates are specified, sets the dragimage offset to the given coordinates [arg x] and [arg y]. [list_end] [call [arg pathName] [cmd element] [arg option] [opt [arg element]] \ [opt [arg {arg arg ...}]]] This command is used to manipulate elements (see [sectref ELEMENTS] below). The exact behavior of the command depends on the [arg option] argument that follows the [cmd element] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {element cget}] [arg element] [arg option]] This command returns the current value of the option named [arg option] associated with the element given by [arg element]. [arg Option] may have any of the values accepted by the [cmd {element configure}] widget command. [call [arg pathName] [cmd {element configure}] [arg element] \ [opt [arg option]] [opt [arg value]] [opt [arg {option value ...}]]] This command is similar to the [cmd configure] widget command except that it modifies options associated with the element given by [arg element] instead of modifying options for the overall treectrl widget. If no [arg option] is specified, the command returns a list describing all of the available options for [arg element] (see [fun Tk_ConfigureInfo] for information on the format of this list). If [arg option] is specified with no [arg value], 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 [arg option] is specified). If one or more [arg option]-[arg value] pairs are specified, then the command modifies the given option(s) to have the given value(s) in [arg element]; in this case the command returns an empty string. See [sectref ELEMENTS] below for details on the options available for elements. [call [arg pathName] [cmd {element create}] [arg element] [arg type] \ [opt [arg {option value ...}]]] Create a new elememt in [arg pathName] of type [arg type] with name [arg element]. The exact format of the arguments after [arg type] depends on [arg type], but generally consist of specifications for zero or more element options. See the subsections on individual element types below for more on the syntax of this command. This command returns the name for the new element. [call [arg pathName] [cmd {element delete}] [opt [arg {element ...}]]] Deletes each of the named elements and returns an empty string. If an element is deleted while it is still configured as an element of one or more styles by means of the [cmd {style elements}] widget command, it is also removed from the element lists of these styles. [call [arg pathName] [cmd {element names}]] Returns a list containing the names of all existing elements. [call [arg pathName] [cmd {element perstate}] [arg element] [arg option] [arg stateList]] This command returns the value of the [sectref {PER-STATE OPTIONS} per-state] option named [arg option] for [arg element] for a certain state. [arg StateList] is a list of state names (static and dynamic, see [sectref STATES]) which specifies the state to use. [call [arg pathName] [cmd {element type}] [arg element]] Returns the type of the element given by [arg element], such as [const rect] or [const text]. [list_end] [call [arg pathName] [cmd expand] [opt [option -recurse]] \ [opt [arg {itemDesc ...}]]] Use [cmd {item expand}] instead. [call [arg pathName] [cmd identify] [arg x] [arg y]] Returns a list describing what is displayed at the given window coordinates [arg x] and [arg y]. If the coordinates are outside the window, over the borders, or over any whitespace in the window, then the result is an empty string; otherwise the first word of the result is [const header] or [const item]. [nl] If the coordinates are over a column header, then the first word of the result is [const header], followed by the unique id of the column (or the string [const tail]). If the x coordinate is near the left or right end of a column, then a third word [const left] or [const right] is appended to the result. [nl] If the coordinates are over an item, then the first word of the result is [const item] followed by the unique id of that item. If the coordinates are not over the area for displaying buttons and lines, then [const column] and a unique column id are the 3rd and 4th words of the result. If the coordinates are over an element within that column, then [const element] and an element name are the 5th and 6th words of the result. [nl] If the coordinates are over a button, then the first word of the result is [const item], followed by the unique id of that item, followed by the word [const button]. [nl] If the coordinates are over a line descending from an ancestor of an item (but not the parent of that item), then the first word of the result is [const item], followed by the unique id of that item, followed by the word [const line], followed by the unique id of the item the line is coming from. This is used to collapse the ancestor when the line is clicked on. [call [arg pathName] [cmd index] [arg itemDesc]] Deprecated. Use [cmd {item id}] instead. [call [arg pathName] [cmd item] [arg option] [opt [arg {arg ...}]]] This command is used to manipulate items. The exact behavior of the command depends on the [arg option] argument that follows the [cmd item] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {item ancestors}] [arg itemDesc]] Returns a list containing the item ids of the ancestors of the item specified by [arg itemDesc]. The first list value is the parent, the second is the parent's parent, an so on. The last list value will be the root item if [arg itemDesc] is a descendant of the root item. [call [arg pathName] [cmd {item bbox}] [arg itemDesc] [opt [arg column]] \ [opt [arg element]]] Returns a list with four elements giving the bounding box of the item described by [arg itemDesc]. If no further argument is specified, the bbox spans the area of the item over all non-locked columns. If a [arg column] is specified, only the area of the item in this column is considered. If an additional [arg element] is specified, the area of this [arg element] in [arg column] of the specified item is returned. [call [arg pathName] [cmd {item cget}] [arg itemDesc] [arg option]] Returns the current value of the configuration option for the item specified by [arg itemDesc] whose name is [arg option]. [arg Option] may have any of the values accepted by the [cmd "item configure"] command. [call [arg pathName] [cmd {item children}] [arg itemDesc]] Returns a list containing the item ids of all children of the item specified by [arg itemDesc] in the correct order from the first child to the last child. [call [arg pathName] [cmd {item collapse}] [arg itemDesc] [opt [option -recurse]]] Switches off the [const open] state of the item(s) described by [arg itemDesc]. If an item has descendants, then they are no longer displayed. If an item is already closed, then this command has no effect on that item. If [option -recurse] is specified, then all descendants of the items described by [arg itemDesc] will also be collapsed. For every item that actually will be collapsed, two events are generated: a [const ] event before the item state is changed, and a [const ] event after the item state was changed. [call [arg pathName] [cmd {item compare}] [arg itemDesc1] [arg op] [arg itemDesc2]] From both items described by the [arg itemDesc]s the index is retrieved (as returned from the [cmd {item order}] widget command). Then these indexes are compared using the operator [arg op], which must be either [const <], [const <=], [const ==], [const >=], [const >], or [const !=]. The return value of this command is 1 if the comparison evaluated to true, 0 otherwise. [call [arg pathName] [cmd {item complex}] [arg itemDesc] [opt [arg list...]]] This horrible command is now deprecated. Use [cmd {item element configure}] instead. For every column of the treectrl there may be specified one [arg list]. Each [arg list] should look like this: [example_begin] { {element option value ...} {element option value ...} ...} [example_end] Every [arg option] must be known by the element's type (see [sectref ELEMENTS] below). Each [arg option] will be set to [arg value] for the element in this one column in this item. [call [arg pathName] [cmd {item configure}] [arg itemDesc] [opt [arg option]] [opt [arg value]] [opt [arg {option value ...}]]] If no [arg option] is specified, returns a list describing all of the available options for the item given by [arg itemDesc] (see [fun Tk_ConfigureInfo] for information on the format of this list). If [arg option] is specified with no value, 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 [arg option] is specified). [nl] If one or more [arg option]-[arg value] pairs are specified, then the command modifies the given item option(s) to have the given value(s); in this case the command returns an empty string. This is the only case where [arg itemDesc] may refer to multiple items. [nl] The following options are supported by this command (see [cmd {item create}] for the meaning of each option): [list_begin opt] [opt_def [option -button] [arg boolean|auto]] [opt_def [option -height] [arg height]] [opt_def [option -tags] [arg tagList]] [opt_def [option -visible] [arg boolean]] [list_end] [call [arg pathName] [cmd {item count}] [opt [arg itemDesc]]] If no additional arguments are given, the result is a decimal string giving the number of items created by the [cmd "item create"] widget command which haven't been deleted by the [cmd "item delete"] widget command, plus 1 for the ever-present root item. If the optional argument [arg itemDesc] is given, then the result is the number of items that match that [sectref {ITEM DESCRIPTION} {item description}]. [call [arg pathName] [cmd {item create}] [opt [arg {option value ...}]]] Creates some new items and optionally returns a list of unique identifiers for those items. The new items have the states [const open] and [const enabled] set by default. If the treectrl widget currently has the focus, the state [const focus] is also set. [nl] The following options are supported by this command: [list_begin opt] [opt_def [option -button] [arg boolean|auto]] The value of this option must have one of the forms accepted by [fun Tcl_GetBoolean] or be the word [const auto] (or any abbreviation of it). It indicates whether or not an expand/collapse button should be drawn next to the item, typically to indicate that the item has children. If the value of this option is [const auto], then a button is displayed next to the item whenever the item has any children whose item option [option -visible] is true. The button will only be displayed if: [list_begin enum] [enum] the column specified by the treectrl option [option -treecolumn] is visible, and [enum] the treectrl option [option -showbuttons] is true, and [enum] for the root item, the treectrl option [option -showrootbutton] is true. [list_end] [opt_def [option -count] [arg numItems]] Specifies the number of items to create. Must be >= 0. Defaults to 1. [opt_def [option -height] [arg height]] Specifies a fixed height in any of the forms acceptable to [fun Tk_GetPixels]. Must be >= 0. If [arg height] is zero then the item's height is unspecified. Defaults to 0. [opt_def [option -nextsibling] [arg itemDesc]] Specifies the item before which the new items will be inserted. The new items will have the same parent as [arg itemDesc]. [opt_def [option -open] [arg boolean]] Specifies whether the items should be open or closed. Default is true. [opt_def [option -parent] [arg itemDesc]] Specifies the item which the new items will be the children of. The new items will be appended to the list of children of [arg itemDesc]. [opt_def [option -prevsibling] [arg itemDesc]] Specifies the item after which the new items will be inserted. The new items will have the same parent as [arg itemDesc]. [opt_def [option -returnid] [arg boolean]] Specifies whether or not to return a list of item identifiers for the newly created items. Specifying false is useful when creating a large number of items in the console or to improve performance. Default is true. [opt_def [option -tags] [arg tagList]] [arg TagList] is a list of tag names to be added to the new items. [opt_def [option -visible] [arg boolean]] [arg Boolean] must have one of the forms accepted by [fun Tcl_GetBoolean]. It indicates that the item should be displayed in the list. The item will only be displayed if: a) each ancestor is a descendant of the root item (not an orphan); and b) each ancestor's [option -visible] option is true [list_end] [call [arg pathName] [cmd {item delete}] [arg first] [opt [arg last]]] Deletes the specified item(s). [arg First] and [arg last] must be valid [sectref {ITEM DESCRIPTION} {item descriptions}]. If [arg last] isn't specified, then [arg first] may specify multiple items. If both [arg first] and [arg last] are specified, they must each decribe a single item with a common ancestor; then the range of items between [arg first] and [arg last] is deleted. The order of [arg first] and [arg last] doesn't matter. [nl] Deleting an item deletes any child items of the deleted item recursively. If the current [const active] item is deleted, the root item becomes the new active item. If the current selection [const anchor] item is deleted, the root item becomes the new anchor item. There is no way to delete the root item of the treectrl widget; in all cases the specification of the root item is ignored. [nl] For each call to this command, two events may be generated. If any of the deleted items are selected, then a [const ] event is generated just before the items are deleted. If any items are going to be deleted, then an [const ] event event is generated just before the items are deleted. [call [arg pathName] [cmd {item descendants}] [arg itemDesc]] Returns a list containing the item ids of the descendants of the item specified by [arg itemDesc], i.e. the children, grandchildren, great-grandchildren etc, of the item. [call [arg pathName] [cmd {item dump}] [arg itemDesc]] Returns a list with 4 words in the form [const index] [emph index] [const indexVis] [emph indexVis]. [call [arg pathName] [cmd {item element}] [arg command] [arg itemDesc] \ [arg column] [arg element] [opt [arg {arg ...}]]] This command is used to manipulate elements of the item. The exact behavior of the command depends on the [arg command] argument that follows the [cmd element] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {item element actual}] [arg itemDesc] [arg column] \ [arg element] [arg option]] Deprecated. Use [cmd {item element perstate}] instead. [call [arg pathName] [cmd {item element cget}] [arg itemDesc] [arg column] \ [arg element] [arg option]] This command returns the value of the option named [arg option] associated with [arg element] inside [arg column] of the item described by [arg itemDesc], if it was already configured for the actual item. [arg Option] may have any of the values accepted by the type of the specified element (see [sectref ELEMENTS] below) [call [arg pathName] [cmd {item element configure}] [arg itemDesc] \ [arg column] [arg element] [opt [arg option]] [opt [arg value]] \ [opt [arg {option value ...}]]] This command modifies configuration options for an element in a column of an item. If no [arg option] is specified, the command returns a list describing all of the available options for the element (see [fun Tk_ConfigureInfo] for information on the format of this list). If [arg option] is specified with no [arg value], 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 [arg option] is specified). [nl] If one or more [arg option]-[arg value] pairs are specified, then the command modifies the given option(s) to have the given value(s) in the [arg element] inside [arg column] of the item(s) described by [arg itemDesc]; in this case the command returns an empty string. This is the only case where [arg itemDesc] may refer to multiple items. [nl] It is possible to configure multiple elements in multiple columns with a single call. To configure another element in the same column, append a '[const +]' argument followed by the element name. To configure elements in another column, append a '[const ,]' argument followed by the column. For example: [example_begin] .t item element configure $I \ $C1 $E1 -text "hello" + $E2 -text "world" , \ $C2 $E3 -fill Blue , \ $C3 $E1 -text "apples and oranges" [example_end] Each of the [sectref {COLUMN DESCRIPTION} {column description}] arguments to this command may refer to multiple columns if at least one [arg option]-[arg value] pair is given. [call [arg pathName] [cmd {item element perstate}] [arg itemDesc] [arg column] \ [arg element] [arg option] [opt [arg stateList]]] This command returns the current value of the [sectref {PER-STATE OPTIONS} per-state] option named [arg option] for [arg element] inside [arg column] of the item described by [arg itemDesc]. If [arg stateList] is specified, the list of state names (static and dynamic, see [sectref STATES]) is used in place of the current state for [arg item] and [arg column.] [list_end] [call [arg pathName] [cmd {item enabled}] [arg itemDesc] [opt [arg boolean]]] Returns 1 if the item described by [arg itemDesc] has the state [const enabled] switched on, 0 otherwise. If [arg boolean] is specified, then the [const enabled] state of every item described by the [sectref {ITEM DESCRIPTION} {item description}] [arg itemDesc] is set accordingly. All items are enabled when first created. Disabled items cannot be selected, and are ignored by the default key-navigation and mouse bindings. [call [arg pathName] [cmd {item expand}] [arg itemDesc] [opt [option -recurse]]] Switches on the [const open] state of the item(s) described by [arg itemDesc]. If an item has descendants, then they are now displayed. If an item is already open, then this command has no effect on that item. If [option -recurse] is specified, then all descendants of the items described by [arg itemDesc] will also be expanded. For every item that actually will be expanded, two events are generated: an [const ] event before the item state is changed, and an [const ] event after the item state was changed. [call [arg pathName] [cmd {item firstchild}] [arg parent] [opt [arg child]]] If [arg child] is not specified, returns the item id of the first child of the item described by [arg parent]. If [arg child] is specified, it must describe an item that is neither the root item nor an ancestor of [arg parent]. Then it will become the new first child of [arg parent]. [call [arg pathName] [cmd {item id}] [arg itemDesc]] This command resolves the [sectref {ITEM DESCRIPTION} {item description}] [arg itemDesc] into a list of unique item identifiers. If [arg itemDesc] doesn't refer to any existing items, then this command returns an empty list. [call [arg pathName] [cmd {item image}] [arg itemDesc] [opt [arg column]] \ [opt [arg image]] [opt [arg {column image ...}]]] This command sets or retrieves the value of the [sectref {PER-STATE OPTIONS} per-state] -image option for the first image element in one or more columns. If no [arg column] is specified, this command returns a list of values, one per column. If no [arg image] is specified, this command returns the value for [arg column]. [nl] If one or more [arg column]-[arg image] pairs is specified, then the value of the -image option in each [arg column] is set to [arg image]. In this case [arg itemDesc] may refer to multiple items and each [arg column] may refer to multiple columns. [nl] Note that this command is provided as a convenience. Use the [cmd "item element configure"] or [cmd "item element cget"] commands if you want to set or retrieve the value of the -image option for a specific image element. [call [arg pathName] [cmd {item isancestor}] [arg itemDesc] [arg descendant]] Returns 1 if the item described by [arg itemDesc] is a direct or indirect parent of the item decribed by [arg descendant], 0 otherwise. [call [arg pathName] [cmd {item isopen}] [arg itemDesc]] Returns 1 if the item described by [arg itemDesc] has the state [const open] switched on, 0 otherwise. [call [arg pathName] [cmd {item lastchild}] [arg parent] [opt [arg child]]] If [arg child] is not specified, returns the item id of the last child of the item described by [arg parent]. If [arg child] is specified, it must describe an item that is not an ancestor of [arg parent]. Then it will become the new last child of [arg parent]. [call [arg pathName] [cmd {item nextsibling}] [arg sibling] [opt [arg next]]] If [arg next] is not specified, returns the item id of the next sibling of the item described by [arg sibling]. If [arg next] is specified, it must describe an item that is not an ancestor of [arg sibling]. Then it will become the new next sibling of [arg sibling]. [call [arg pathName] [cmd {item numchildren}] [arg itemDesc]] Returns the number of children of the item described by [arg itemDesc]. [call [arg pathName] [cmd {item order}] [arg itemDesc] [opt [arg -visible]]] This command returns the position of the item [arg itemDesc] relative to its toplevel ancestor (usually the root item, unless the ancestor is an orphan). If you imagine all the items flattened into a vertical list, the result of this command is the row the item falls in. If the optional argument [arg -visible] is given, only the items whose ancestors are expanded, and whose -visible option is true, get counted; in this case -1 is returned if the item is not visible. [call [arg pathName] [cmd {item parent}] [arg itemDesc]] Returns the item id of the parent of the item described by [arg itemDesc]. [call [arg pathName] [cmd {item prevsibling}] [arg sibling] [opt [arg prev]]] If [arg prev] is not specified, returns the item id of the previous sibling of the item described by [arg sibling]. If [arg prev] is specified, it must describe an item that is not an ancestor of [arg sibling]. Then it will become the new previous sibling of [arg sibling]. [call [arg pathName] [cmd {item range}] [arg first] [arg last]] Returns a list containing the item ids of all items in the range between [arg first] and [arg last], inclusive. The order between [arg first] and [arg last] doesn't matter, and the result is always sorted by the increasing order of the items (as returned by the [cmd {item order}] command). The items specified by [arg first] and [arg last] must share a common ancestor. [call [arg pathName] [cmd {item remove}] [arg itemDesc]] Removes the item described by [arg itemDesc] from the list of children of its parent, so that it will become an orphan. [call [arg pathName] [cmd {item rnc}] [arg itemDesc]] Returns a list of two integers, which corresponds to the row and column of the item described by [arg itemDesc]. The row and column corresponds to the on-screen arrangement of items as determined by the -orient and -wrap options. If the item is not displayed, this command returns an empty string. [call [arg pathName] [cmd {item sort}] [arg itemDesc] [opt [arg {option ...}]]] Sorts the children of the item described by [arg itemDesc], and redisplays the tree with the items in the new order. [nl] The range of items which should be sorted can be restricted by means of the [option -first] and/or [option -last] options, which should be children of the item described by [arg itemDesc]; the order between these two limiting items doesn't matter. [nl] The sort column can be specified by means of the [option -column] option; this option can be used repeatedly to define a multicolumn sort. The sorting is done by looking at the [arg text] of the element specified by the [option -element] option, which must be a text element defined in the style of the sorting column, by default the first text element is used. [nl] If the [option -notreally] option is specified, no rearranging of the items is done; instead the sorted items are returned as result of the command. [nl] By default ASCII sorting is used with the result returned in increasing order. Any of the following options may be specified to control the sorting process of the previously specified column (unique abbreviations are accepted): [list_begin opt] [opt_def [option -ascii]] Use string comparison with ASCII collation order. This is the default. [opt_def [option -command] [arg command]] Use [arg command] as a comparison command. To compare two items, evaluate a Tcl script consisting of [arg command] with the numerical ids of the two items appended as additional arguments. The script should return an integer less than, equal to, or greater than zero if the first item is to be considered less than, equal to, or greater than the second, respectively. [opt_def [option -decreasing]] Sort the items in decreasing order ("largest" items first). [opt_def [option -dictionary]] Use dictionary-style comparison. This is the same as [option -ascii] except (a) case is ignored except as a tie-breaker and (b) if two strings contain embedded numbers, the numbers compare as integers, not characters. For example, in [option -dictionary] mode, [term bigBoy] sorts between [term bigbang] and [term bigboy], and [term x10y] sorts between [term x9y] and [term x11y]. [opt_def [option -increasing]] Sort the items in increasing order ("smallest" items first). This is the default. [opt_def [option -integer]] Convert to integers and use integer comparison. [opt_def [option -real]] Convert to floating-point values and use floating comparison. [list_end] [call [arg pathName] [cmd {item span}] [arg itemDesc] [opt [arg column]] \ [opt [arg numColumns]] [opt [arg {column numColumns ...}]]] This command sets or retrieves the number of columns that a style covers. If no [arg column] is specified, the return value is a list of spans, one per column. If no [arg numColumns] is specified, the return value is the span for [arg column]. [nl] If one or more [arg column]-[arg numColumns] pairs is specified, the span for each [arg column] is set to [arg numColumns]. In this case [arg itemDesc] may refer to multiple items and each [arg column] may refer to multiple columns. [call [arg pathName] [cmd {item state}] [arg command] [arg itemDesc] \ [opt [arg {arg ...}]]] This command is used to manipulate the states of an item. The exact behavior of the command depends on the [arg command] argument that follows the [cmd style] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {item state forcolumn}] [arg itemDesc] [arg column] \ [opt [arg stateDescList]]] Just like [cmd {item state set}] but manipulates dynamic states for a single item column, not the item as a whole. If [arg stateDescList] is unspecified, this command returns a list containing the names of all the dynamic states which are switched on in [arg column]. [nl] If [arg stateDescList] is specified, then [arg itemDesc] may refer to multiple items and [arg column] may refer to multiple columns. [call [arg pathName] [cmd {item state get}] [arg itemDesc] \ [opt [arg {stateName}]]] If no [arg stateName] is specified, returns a list containing the names of all (static and dynamic) states which are currently switched on for the item described by [arg itemDesc]. If a [arg stateName] is specified, 1 is returned if the specified state is currently switched on for the item, 0 otherwise. [call [arg pathName] [cmd {item state set}] [arg itemDesc] \ [opt [arg lastItem]] [arg stateDescList]] Every element of [arg stateDescList] must be the name of a dynamic state (see [sectref STATES] below), optionally preceded by a [const ~] or [const !] character. Every state with a leading [const !] will be switched off for the item described by [arg itemDesc], every state with a leading [const ~] will be toggled, and every state without leading [const !] or [const ~] will be switched on. If [arg lastItem] is specified, the state changes will be made for all items in the range between [arg itemDesc] and [arg lastItem]. If [arg lastItem] unspecified, then the state changes are made for all items described by [arg itemDesc]. [list_end] [call [arg pathName] [cmd {item style}] [arg command] [arg itemDesc] \ [opt [arg {arg ...}]]] This command is used to manipulate the styles of an item. The exact behavior of the command depends on the [arg command] argument that follows the [cmd style] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {item style elements}] [arg itemDesc] [arg column]] This command returns a list containing the names of elements which were configured by the [cmd {item element configure}] command for the item described by [arg itemDesc] in [arg column]. If there is no style assigned to [arg column] an error is returned. [call [arg pathName] [cmd {item style map}] [arg itemDesc] [arg column] \ [arg style] [arg map]] Like the [cmd "item style set"] command, this command may be used to assign a style to a specific column of an item. Unlike [cmd "item style set"], this command can transfer configuration values of elements in the current style to elements in the new style specified by [arg style]. [arg Map] must be a list of [arg elementOld]-[arg elementNew] pairs, where [arg elementOld] is an element in the current style, and [arg elementNew] is an element in the style specified by [arg style]. Both [arg elementOld] and [arg elementNew] must be of the same type ([const bitmap], [const text] etc). [arg ItemDesc] may refer to multiple items and [arg column] may refer to multiple columns. [call [arg pathName] [cmd {item style set}] [arg itemDesc] [opt [arg column]] \ [opt [arg style]] [opt [arg {column style ...}]]] This command sets or retrieves the style assigned to one or more columns. If no [arg column] is specified, this command returns a list containing the names of the styles set for all columns of the item described by [arg itemDesc]. If no [arg style] is specified, this command returns the name of the style set for the item described by [arg itemDesc] in [arg column]. [nl] If one or more [arg column]-[arg style] pairs is specified, then the style in each [arg column] is set to [arg style]. In this case [arg itemDesc] may refer to multiple items and each [arg column] may refer to multiple columns. [list_end] [call [arg pathName] [cmd {item tag}] [arg option] [opt [arg {arg arg ...}]]] This command is used to manipulate tags on items. The exact behavior of the command depends on the [arg option] argument that follows the [cmd {item tag}] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {item tag add}] [arg itemDesc] [arg tagList]] Adds each tag in [arg tagList] to the items specified by the [sectref {ITEM DESCRIPTION} {item description}] [arg itemDesc]. Duplicate tags are ignored. The list of tags for an item can also be changed via an item's [option -tags] option. [call [arg pathName] [cmd {item tag expr}] [arg itemDesc] [arg tagExpr]] Evaluates the tag expression [arg tagExpr] against every item specified by the [sectref {ITEM DESCRIPTION} {item description}] [arg itemDesc]. The result is 1 if the tag expression evaluates to true for every item, 0 otherwise. [call [arg pathName] [cmd {item tag names}] [arg itemDesc]] Returns a list of tag names assigned to the items specified by the [sectref {ITEM DESCRIPTION} {item description}] [arg itemDesc]. The result is the union of any tags assigned to the items. [call [arg pathName] [cmd {item tag remove}] [arg itemDesc] [arg tagList]] Removes each tag in [arg tagList] from the items specified by the [sectref {ITEM DESCRIPTION} {item description}] [arg itemDesc]. It is not an error if any of the items do not use any of the tags. The list of tags for an item can also be changed via an item's [option -tags] option. [list_end] [call [arg pathName] [cmd {item text}] [arg itemDesc] [opt [arg column]] \ [opt [arg text]] [opt [arg {column text ...}]]] This command sets or retrieves the value of the -text option for the first text element in one or more columns. If no [arg column] is specified, this command returns a list of values, one per column. If no [arg text] is specified, this command returns the value for [arg column]. [nl] If one or more [arg column]-[arg text] pairs is specified, then the value of the -text option in each [arg column] is set to [arg text]. In this case [arg itemDesc] may refer to multiple items and each [arg column] may refer to multiple columns. [nl] Note that this command is provided as a convenience. Use the [cmd "item element configure"] or [cmd "item element cget"] commands if you want to set or retrieve the value of the -text option for a specific text element. [call [arg pathName] [cmd {item toggle}] [arg itemDesc] [opt [option -recurse]]] Changes the [const open] state of the item(s) described by [arg itemDesc]. If the [const open] state is currently switched off, then this command does the same as the [cmd {item expand}] widget command; otherwise the same as the [cmd {item collapse}] widget command. If [option -recurse] is specified, then the [const open] state of all descendants of the items described by [arg itemDesc] will also be toggled. [list_end] [call [arg pathName] [cmd marquee] [arg option] [opt [arg {arg ...}]]] This command is used to manipulate the marquee, a rectangular region of the treectrl widget optionally marked with a surrounding dotted line. One corner point of the marquee is fixed as long as the marquee is visible and called the anchor; the diagonally opposite corner is dragged with the mouse while resizing the marquee and simply called the corner. All coordinates handled by this widget command are treectrl coordinates, i.e. the [cmd canvasx] or [cmd canvasy] widget command should be used before any window coordinates can be used. The exact behavior of the command depends on the [arg option] argument that follows the [cmd marquee] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {marquee anchor}] [opt [arg {x y}]]] Returns a list containing the x and y coordinates of the anchor, if no additional arguments are specified. If two coordinates are specified, sets the anchor to the given coordinates [arg x] and [arg y]. [call [arg pathName] [cmd {marquee cget}] [arg option]] This command returns the current value of the marquee option named [arg option]. [arg Option] may have any of the values accepted by the [cmd {marquee configure}] widget command. [call [arg pathName] [cmd {marquee configure}] [opt [arg option]] \ [opt [arg value]] [opt [arg {option value ...}]]] This command is similar to the [cmd configure] widget command except that it modifies the marquee options instead of modifying options for the overall treectrl widget. If no [arg option] is specified, the command returns a list describing all of the available marquee options (see [fun Tk_ConfigureInfo] for information on the format of this list). If [arg option] is specified with no [arg value], then the command returns a list describing the one named marquee option (this list will be identical to the corresponding sublist of the value returned if no [arg option] is specified). If one or more [arg option]-[arg value] pairs are specified, then the command modifies the given marquee option(s) to have the given value(s); in this case the command returns an empty string. [nl] The following marquee options are supported: [list_begin opt] [opt_def [option -visible] [arg boolean]] Specifies a boolean value which determines whether the dotted line surrounding the region of the marquee should currently be visible. [list_end] [call [arg pathName] [cmd {marquee coords}] [opt [arg {x1 y1 x2 y2}]]] Returns a list containing the x and y coordinates of the anchor followed by the x and y coordinates of the corner, if no additional arguments are specified. If four coordinates are specified, sets the anchor to the given coordinates [arg x1] and [arg y1] and the corner to the coordinates [arg x2] and [arg y2]. [call [arg pathName] [cmd {marquee corner}] [opt [arg {x y}]]] Returns a list containing the x and y coordinates of the corner, if no additional arguments are specified. If two coordinates are specified, sets the corner to the given coordinates [arg x] and [arg y]. [call [arg pathName] [cmd {marquee identify}]] Returns a list with information about any items intersecting the marquee. The format of the returned list is: [example_begin] { {item {column element element ...} {column element element ...} ...} {item {column element element ...} {column element element ...} ...} ... } [example_end] There may be zero sublists following an item id if the marquee is in the button/line area of an item. There may be zero element names following a column id if the item-column has no style or if the marquee does not intersect any elements in that column. [list_end] [call [arg pathName] [cmd notify] [arg option] [opt [arg {arg ...}]]] Many Tk widgets communicate with the outside world via [option -command] callbacks and/or virtual events. For example, the Text widget evaluates its [option -yscrollcommand] when the view in the widget changes, and generates a <> virtual event when text is inserted or deleted. A treectrl widget replaces both methods of communication with its own event mechanism accessed through the [cmd notify] subcommands. [nl] The exact behavior of the command depends on the [arg option] argument that follows the [cmd notify] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {notify bind}] [opt [arg object]] \ [opt [arg pattern]] [opt +][opt [arg script]]] This command associates Tcl scripts with events generated by a treectrl widget. If all three arguments are specified, [cmd {notify bind}] will arrange for [arg script] (a Tcl script) to be evaluated whenever the event(s) specified by [arg pattern] are generated by this treectrl widget. If [arg script] is prefixed with a "+", then it is appended to any existing binding for [arg pattern]; otherwise [arg script] replaces any existing binding. If [arg script] is an empty string then the current binding for [arg pattern] is destroyed, leaving [arg pattern] unbound. In all of the cases where a script argument is provided, [cmd {notify bind}] returns an empty string. [nl] If [arg pattern] is specified without a [arg script], then the script currently bound to [arg pattern] is returned, or an empty string is returned if there is no binding for [arg pattern]. If neither [arg pattern] nor [arg script] is specified, then the return value is a list whose elements are all the patterns for which there exist bindings for [arg object]. [nl] The [arg object] argument determines which window(s) the binding applies to. If [arg object] begins with a dot, as in .a.b.c, then it must be the path name for a window; otherwise it may be an arbitrary string. Like the regular [cmd bind] command, bindings on window names are automatically removed if that window is destroyed. [call [arg pathName] [cmd {notify configure}] [arg object] \ [arg pattern] [opt [arg option]] [opt [arg value]] \ [opt [arg {option value ...}]]] This command sets and retrieves options for bindings created by the [cmd {notify bind}] command. [nl] If no [arg option] is specified, the command returns a list with [arg option]-[arg value] pairs describing all the available binding options for [arg pattern] on [arg object]. If [arg option] is specified with no [arg value], then the command returns the current value of that option. If one or more [arg option]-[arg value] pairs are specified, then the command modifies the given option(s) to have the given value(s) for the binding; in this case the command returns an empty string. [nl] The following binding options are supported: [list_begin opt] [opt_def [option -active] [arg boolean]] Specifies if the binding should be active. As long as this option is specified as false, a binding script will not be evaluated when the corresponding event is generated. [list_end] [call [arg pathName] [cmd {notify detailnames}] [arg eventName]] Returns a list containing the names of all details, which are installed for the event with the name [arg eventName] by means of the [cmd {notify install}] widget command or by the treectrl widget itself. [call [arg pathName] [cmd {notify eventnames}]] Returns a list containing the names of all events, which are installed by means of the [cmd {notify install}] widget command or by the treectrl widget itself. [call [arg pathName] [cmd {notify generate}] [arg pattern] \ [opt [arg charMap]] [opt [arg percentsCommand]]] This command causes the treectrl widget to generate an event. This command is typically used to generate dynamic events created by the [cmd {notify install}] command, but may be used to generate static events also. The event specified by [arg pattern] is generated, and any active binding scripts on the event are evaluated after undergoing %-substitution. If there are details defined for the event, [arg pattern] must describe an <[arg eventName]-[arg detail]> pair, otherwise [arg pattern] should be <[arg eventName]>. [nl] The optional [arg charMap] is a list of [arg char]-[arg value] pairs as in the form returned by [cmd {array get}]. Each [arg char] has to be exactly one character. The [arg charMap] is used in %-substitution. [nl] If [arg percentsCommand] is specified, then it will be used to perform %-substitution on any scripts bound to the event. If [arg percentsCommand] is not specified and the event is dynamic, then the %-subtitution command passed to [cmd {notify install}] will be used if it was provided. If the event is static or no %-substitution command is available, then all %-substitution is done using [arg charMap] only . See [cmd {notify install}] for a description of [arg percentsCommand]. [call [arg pathName] [cmd {notify install}] [arg pattern] [opt [arg percentsCommand]]] This command installs a new event or detail specified by [arg pattern]. Events created by this command are called dynamic, whereas events created by the treectrl widget itself are called static. This command may be called to set or retrieve the [arg percentsCommand] for an existing dynamic event. [nl] The optional [arg percentsCommand] is a list containing the name of a Tcl command, plus any optional arguments, to which five additional arguments will be appended. The command will be called to perform %-substitution on any scripts bound to the event specified by [arg pattern] (see [sectref {EVENTS AND SCRIPT SUBSTITUTIONS}]). [arg PercentsCommand] should be defined as follows: [example_begin] proc percentsCommand {?arg arg ...? char object event detail charMap} { switch -- $char { ... } return $value } [example_end] The optional [arg arg] arguments are part of the [arg percentsCommand] list. [arg Char] is the %-character to be substituted. [arg Object] is the same as the argument to [cmd {notify bind}]. [arg Event] and [arg detail] specify the event. [arg CharMap] is the same as the argument to [cmd {notify generate}]. [arg PercentsCommand] should return the value to replace the %-character by. If an error occurs evaluating [arg percentsCommand], the %-character is replaced by itself. [nl] [cmd {notify install}] returns the current [arg percentsCommand] for the event, or an error if the event is not dynamic. [call [arg pathName] [cmd {notify install detail}] [arg eventName] \ [arg detail] [opt [arg percentsCommand]]] Deprecated. Use [cmd {notify install}] with a [arg pattern] of <[arg eventName]-[arg detail]> instead. [call [arg pathName] [cmd {notify install event}] [arg eventName] \ [opt [arg percentsCommand]]] Deprecated. Use [cmd {notify install}] with a [arg pattern] of <[arg eventName]> instead. [call [arg pathName] [cmd {notify linkage}] [arg pattern]] Returns a string indicating whether the specified event or detail is created by means of the [cmd {notify install}] widget command ([const dynamic]) or by the treectrl widget itself ([const static]). [call [arg pathName] [cmd {notify linkage}] [arg eventName] [opt [arg detail]]] Deprecated. Use [cmd {notify linkage}] with a [arg pattern] of <[arg eventName]> or <[arg eventName]-[arg detail]> instead. [call [arg pathName] [cmd {notify unbind}] [arg object] [opt [arg pattern]]] If no [arg pattern] is specified, all bindings on [arg object] are removed. If [arg pattern] is specified, then the current binding for [arg pattern] is destroyed, leaving [arg pattern] unbound. [call [arg pathName] [cmd {notify uninstall}] [arg pattern]] If the event or detail specified by [arg pattern] is static (i.e. created by the treectrl widget itself), an error is generated. Otherwise the dynamic event or detail is removed. If an event name is specified without a detail, all details for that event are also removed. [call [arg pathName] [cmd {notify uninstall detail}] \ [arg eventName] [arg detail]] Deprecated. Use [cmd {notify uninstall}] with a [arg pattern] of <[arg eventName]-[arg detail]> instead. [call [arg pathName] [cmd {notify uninstall event}] [arg eventName]] Deprecated. Use [cmd {notify uninstall}] with a [arg pattern] of <[arg eventName]> instead. [list_end] [call [arg pathName] [cmd numcolumns]] Deprecated. Use the [cmd {column count}] command instead. [call [arg pathName] [cmd numitems]] Deprecated. Use the [cmd {item count}] command instead. [call [arg pathName] [cmd orphans]] Returns a list containing the item ids of all items which have no parent. When an item is created, it has no parent by default, and can later become an orphan by means of the [cmd {item remove}] widget command. The root item is not returned. [call [arg pathName] [cmd range] [arg first] [arg last]] Deprecated. Use the [cmd {item range}] command instead. [call [arg pathName] [cmd scan] [arg option] [arg args]] This command is used to implement scanning on treectrls. It has two forms, depending on [arg option]: [list_begin definitions] [call [arg pathName] [cmd {scan mark}] [arg x] [arg y]] Records [arg x] and [arg y] and the treectrl's current view; used in conjunction with later [cmd {scan dragto}] commands. Typically this command is associated with a mouse button press in the widget and [arg x] and [arg y] are the coordinates of the mouse. It returns an empty string. [call [arg pathName] [cmd {scan dragto}] [arg x] [arg y] [opt [arg gain]]] This command computes the difference between its [arg x] and [arg y] arguments (which are typically mouse coordinates) and the [arg x] and [arg y] arguments to the last [cmd {scan mark}] command for the widget. It then adjusts the view by [arg gain] times the difference in coordinates, where [arg gain] defaults to 10. This command is typically associated with mouse motion events in the widget, to produce the effect of dragging the treectrl at high speed through its window. The return value is an empty string. [list_end] [call [arg pathName] [cmd state] [arg option] [arg args]] This command is used to manipulate the list of user-defined states, see section [sectref STATES] below. The exact behavior of the command depends on the [arg option] argument that follows the [cmd state] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {state define}] [arg stateName]] Defines a new state with the name [arg stateName], which must not be the name of an existing state. [call [arg pathName] [cmd {state linkage}] [arg stateName]] Returns a string indicating whether the specified state is user-defined by means of the [cmd {state define}] widget command ([const dynamic]) or predefined by the treectrl widget itself ([const static]). [call [arg pathName] [cmd {state names}]] Returns a list containing the names of all user-defined states. [call [arg pathName] [cmd {state undefine}] [opt [arg {stateName ...}]]] Every [arg stateName] must be the name of a user-defined state. Removes this state from the list of user-defined states. [list_end] [call [arg pathName] [cmd see] [arg itemDesc]] Adjust the view in the treectrl so that the item described by [arg itemDesc] is visible. If the item is already visible then the command has no effect; otherwise the treectrl scrolls to bring the item into view, and the corresponding [const ] and/or [const ] events are generated. [call [arg pathName] [cmd selection] [arg option] [arg args]] This command is used to adjust the selection within a treectrl. It has several forms, depending on [arg option]: [list_begin definitions] [call [arg pathName] [cmd {selection add}] [arg first] [opt [arg last]]] [arg First] and [arg last] (if specified) must be valid [sectref {ITEM DESCRIPTION} {item descriptions}]. If both [arg first] and [arg last] are specified, then they may refer to a single item only; in this case the command adds every unselected item in the range between [arg first] and [arg last], inclusive, to the selection without affecting the selected state of items outside that range. If only [arg first] is specified, then every unselected item specified by [arg first] is added to the selection. A [const ] event is generated if any items were added to the selection. [call [arg pathName] [cmd {selection anchor}] [opt [arg itemDesc]]] If [arg itemDesc] is specified, the selection anchor is set to the described item. The selection anchor is the end of the selection that is fixed while dragging out a selection with the mouse. The item description [const anchor] may be used to refer to the anchor item. This command doesn't modify the selection state of any item. Returns the unique id of the selection anchor item. [call [arg pathName] [cmd {selection clear}] [opt [arg first]] [opt [arg last]]] [arg First] and [arg last] (if specified) must be valid [sectref {ITEM DESCRIPTION} {item descriptions}]. If both [arg first] and [arg last] are specified, then they may refer to a single item only; in this case any selected items between [arg first] and [arg last] (inclusive) are removed from the selection without affecting the selected state of items outside that range. If only [arg first] is specified, then every selected item specified by [arg first] is removed from the selection. If neither [arg first] nor [arg last] are specified, then all selected items are removed from the selection. A [const ] event is generated if any items were removed from the selection. [call [arg pathName] [cmd {selection count}]] Returns an integer indicating the number of items in the treectrl that are currently selected. [call [arg pathName] [cmd {selection get}] [opt [arg first]] [opt [arg last]]] When no additional arguments are given, the result is an unsorted list containing the item ids of all of the items in the treectrl that are currently selected. If there are no items selected in the treectrl, then an empty string is returned. The optional arguments [arg first] and [arg last] are treated as indices into the sorted list of selected items; these arguments allow in-place [cmd lindex] and [cmd lrange] operations on the selection. For example: [example_begin] .t selection get 0 ; # return the first selected item .t selection get end ; # return the last selected item .t selection get 1 end-1 ; # return every selected item except the first and last [example_end] [call [arg pathName] [cmd {selection includes}] [arg itemDesc]] Returns 1 if the item described by [arg itemDesc] is currently selected, 0 if it isn't. [call [arg pathName] [cmd {selection modify}] [arg select] [arg deselect]] Both arguments [arg select] and [arg deselect] are a possibly-empty list of [sectref {ITEM DESCRIPTION} {item descriptions}]. Any unselected items in [arg select] are added to the selection, and any selected items in [arg deselect] are removed from the selection (except for those items which are also in [arg select]). A [const ] event is generated if any items were selected or deselected. [list_end] [call [arg pathName] [cmd style] [arg option] [opt [arg element]] \ [opt [arg {arg arg ...}]]] This command is used to manipulate styles, which can be thought of as a geometry manager for elements. The exact behavior of the command depends on the [arg option] argument that follows the [cmd style] argument. The following forms of the command are supported: [list_begin definitions] [call [arg pathName] [cmd {style cget}] [arg style] [arg option]] This command returns the current value of the option named [arg option] associated with the style given by [arg style]. [arg Option] may have any of the values accepted by the [cmd {style configure}] widget command. [call [arg pathName] [cmd {style configure}] [arg style] [opt [arg option]] \ [opt [arg value]] [opt [arg {option value ...}]]] This command is similar to the [cmd configure] widget command except that it modifies options associated with the style given by [arg style] instead of modifying options for the overall treectrl widget. If no [arg option] is specified, the command returns a list describing all of the available options for [arg style] (see [fun Tk_ConfigureInfo] for information on the format of this list). If [arg option] is specified with no [arg value], 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 [arg option] is specified). If one or more [arg option]-[arg value] pairs are specified, then the command modifies the given option(s) to have the given value(s) in [arg style]; in this case the command returns an empty string. [nl] The options of a style have effect on all elements managed by the style. The following options are supported: [list_begin opt] [opt_def [option -orient] [arg varName]] This option specifies which orientation should be used when laying out the elements associated with this style. Must be either [const horizontal] (the default) or [const vertical] or an abbreviation of one of these. [list_end] [call [arg pathName] [cmd {style create}] [arg style] \ [opt [arg {option value ...}]]] Create a new style in [arg pathName] with name [arg style]. After [arg style] there may be any number of [arg option]-[arg value] pairs, each of which sets one of the configuration options for the style. These same [arg option]-[arg value] pairs may be used in [cmd {style configure}] widget commands to change the style's configuration. Returns the name of the new style. [call [arg pathName] [cmd {style delete}] [opt [arg {style ...}]]] Deletes each of the named styles and returns an empty string. If a style is deleted while it is still used to display one or more items, it is also removed from the style list of these items. [call [arg pathName] [cmd {style elements}] [arg style] \ [opt [arg elementList]]] Specifies the elements which should be layed out by this style. Each element of [arg elementList] must be the name of an element created by the widget command [cmd {element create}]. Duplicate names in [arg elementList] are ignored. An element which was specified in a former call of this command for [arg style] but is not included in [arg elementList], will be deleted from the elements layed out by [arg style]. [nl] If the [arg elementList] argument is not specified, a list is returned containing the currently defined elements of [arg style]. [call [arg pathName] [cmd {style layout}] [arg style] [arg element] \ [opt [arg option]] [opt [arg value]] [opt [arg {option value ...}]]] This command is similar to the [cmd configure] widget command except that it modifies options used by [arg style] for laying out [arg element] instead of modifying options for the overall treectrl widget. If no [arg option] is specified, the command returns a list with [arg option]-[arg value] pairs describing all of the available options for the layout. If [arg option] is specified with no [arg value], then the command returns the value of the named option. If one or more [arg option]-[arg value] pairs are specified, then the command modifies the given option(s) to have the given value(s) for the layout; in this case the command returns an empty string. [nl] The options of a layout have effect on exactly the one element [arg element] managed by [arg style]. The following options are supported: [list_begin opt] [opt_def [option -detach] [arg boolean]] Specifies whether the element should be positioned by itself, i.e. independent from the other elements. [opt_def [option -draw] [arg boolean]] This is a [sectref {PER-STATE OPTIONS} per-state] option that determines whether an element should be drawn. If the value of the option evaluates to false for a given item state, then the element is not drawn, although it still consumes space in the layout. [opt_def [option -expand] [arg flags]] This option allows the external padding around the element to increase when a style has more screen space than it needs. [arg Flags] is a string that contains zero or more of the characters [const n], [const s], [const w] or [const e]. Each letter refers to the padding on the top, bottom, left, or right that should be allowed to increase. This option is typically used to justify an element. [opt_def [option -iexpand] [arg flags]] This option allows the internal padding of the element and the display area of the element to increase when a style has more screen space than it needs. [arg Flags] is a string that contains zero or more of the characters [const x], [const y], [const n], [const s], [const w] or [const e]. For [const n], [const s], [const w] and [const e], each letter refers to the padding on the top, bottom, left, or right that should be allowed to increase. For [const x] and [const y], each letter refers to the horizontal and vertical screen space the element can display itself in (i.e., the space between the padding). Note that if the [option -union] option is specified for this element, then the [const x] and [const y] flags have no effect, since the size of an element with [option -union] layout is determined by the elements it surrounds. [opt_def [option -indent] [arg boolean]] Specifies whether the element should be positioned to the right of the button/line area in the tree column. This option is ignored unless the [option -detach] option is true. [opt_def [option -ipadx] [arg amount]] [opt_def [option -ipady] [arg amount]] [arg Amount] specifies how much internal padding to leave on the left and right (for [option -ipadx]) or top and bottom (for [option -ipady]) side of the element. [arg Amount] may be a list of two values to specify padding for the two sides separately, it defaults to 0. [opt_def [option -minheight] [arg pixels]] [opt_def [option -height] [arg pixels]] [opt_def [option -maxheight] [arg pixels]] Specifies the minimum, fixed, and maximum height of the element. [opt_def [option -minwidth] [arg pixels]] [opt_def [option -width] [arg pixels]] [opt_def [option -maxwidth] [arg pixels]] Specifies the minimum, fixed, and maximum width of the element. [opt_def [option -padx] [arg amount]] [opt_def [option -pady] [arg amount]] [arg Amount] specifies how much external padding to leave on the left and right (for [option -padx]) or top and bottom (for [option -pady]) side of the element. [arg Amount] may be a list of two values to specify padding for the two sides separately, it defaults to 0. [opt_def [option -squeeze] [arg flags]] This option allows the display area of an element to decrease when a style has less space than it needs. [arg Flags] is a string that contains zero or more of the characters [const x] or [const y]. [const x] allows display area to decrease horizontally, [const y] allows display area to decrease vertically. This option is typically used for [const text] elements and will cause the text element to display an ellipsis (...) and/or wrap lines. [opt_def [option -sticky] [arg flags]] This option controls how the actual display information (image, text, etc) of an element is positioned (or stretched) within its display area. [arg Flags] is a string that contains zero or more of the characters [const n], [const s], [const w] or [const e]. Each letter refers to the top, bottom, left or right side of the display area that the display information should "stick" to. [opt_def [option -union] [arg elementList]] Specifies a list of other elements which this element will surround. The size of an element with [option -union] layout is determined by the size and position of the elements in [arg elementList]. The [option -ipadx] and [option -ipady] options in this case refer to the distance of the edges of the display area of this element from those elements it surrounds. This option is typically used to display a selection rectangle around a piece of text. If none of the elements in [arg elementList] are visible, then the element is not displayed. [opt_def [option -visible] [arg boolean]] This is a [sectref {PER-STATE OPTIONS} per-state] option that controls visibility of an element. If the value of the option evaluates to false for a given item state, then the element is not displayed and consumes no space in the layout. [list_end] [call [arg pathName] [cmd {style names}]] Returns a list containing the names of all existing styles. [list_end] [call [arg pathName] [cmd toggle] [opt [option -recurse]] \ [opt [arg {itemDesc ...}]]] Use [cmd {item toggle}] instead. [call [arg pathName] [cmd xview] [opt [arg args]]] This command is used to query and change the horizontal position of the information displayed in the treectrl's window. It can take any of the following forms: [list_begin definitions] [call [arg pathName] [cmd xview]] 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 tree's area is off-screen to the left, the middle 40% is visible in the window, and 40% of the tree is off-screen to the right. These are the same values passed to scrollbars via the [option -xscrollcommand] option. [call [arg pathName] [cmd {xview moveto}] [arg fraction]] Adjusts the view in the window so that [arg fraction] of the total width of the tree is off-screen to the left. [arg Fraction] must be a fraction between 0 and 1. A [const ] event is generated. [call [arg pathName] [cmd {xview scroll}] [arg number] [arg what]] This command shifts the view in the window left or right according to [arg number] and [arg what]. [arg Number] must be an integer. [arg What] must be either [const units] or [const pages] or an abbreviation of one of these. If [arg what] is [const units], the view adjusts left or right in units determined by the [option -xscrollincrement] option (which may be zero, see the description of that option). If [arg what] is [const pages] then the view adjusts in units of nine-tenths the window's width. If [arg number] is negative then information farther to the left becomes visible; if it is positive then information farther to the right becomes visible. A [const ] event is generated. [list_end] [call [arg pathName] [cmd yview] [opt [arg args]]] This command is used to query and change the vertical position of the information displayed in the treectrl's window. It can take any of the following forms: [list_begin definitions] [call [arg pathName] [cmd yview]] Returns a list containing two elements. Each element is a real fraction between 0 and 1; together they describe the vertical span that is visible in the window. For example, if the first element is .6 and the second element is 1.0, the lowest 40% of the tree's area is visible in the window. These are the same values passed to scrollbars via the [option -yscrollcommand] option. [call [arg pathName] [cmd {yview moveto}] [arg fraction]] Adjusts the view in the window so that [arg fraction] of the tree's area is off-screen to the top. [arg Fraction] is a fraction between 0 and 1. A [const ] event is generated. [call [arg pathName] [cmd {yview scroll}] [arg number] [arg what]] This command adjusts the view in the window up or down according to [arg number] and [arg what]. [arg Number] must be an integer. [arg What] must be either [const units] or [const pages]. If [arg what] is [const units], the view adjusts up or down in units of the [option -yscrollincrement] option (which may be zero, see the description of that option). If [arg what] is [const pages] then the view adjusts in units of nine-tenths the window's height. If [arg number] is negative then higher information becomes visible; if it is positive then lower information becomes visible. A [const ] event is generated. [list_end] [list_end] [section COLUMNS] A treectrl widget is capable of displaying multiple columns next to each other. An item can be considered as a row, which reaches over all columns. [para] Columns in a treectrl may be specified in a number of ways. See [sectref {COLUMN DESCRIPTION}] below. [para] There is always one special column, the [const tail] column, which fills all space to the right of the last ordinary column. This column has no number; it can only be specified by the keyword [const tail]. [para] When a column configuration option is specified as [sectref {PER-STATE OPTIONS} per-state], the state names are [const normal], [const active], [const pressed] or [const up], i.e. do not use item state names. [para] The following options are supported for columns: [list_begin opt] [opt_def [option -arrow] [arg direction]] Indicates whether or not an arrow should be drawn in the column header. [arg Direction] must have one of the values [const none] (the default), [const up], or [const down]. [opt_def [option -arrowbitmap] [arg bitmap]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the bitmap to use to draw the arrow if this column's -arrow option is not [const none]. [opt_def [option -arrowimage] [arg image]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the image to use to draw the arrow if this column's -arrow option is not [const none]. If an image is specified for a certain state, it overrides the -arrowbitmap option. [opt_def [option -arrowside] [arg side]] Indicates on which side of the bitmap/image/text the arrow should be drawn. [arg Side] must be either [const left] or [const right] (the default). [opt_def [option -arrowgravity] [arg side]] Indicates onto which side an arrow should be packed, if there is more space available for drawing the arrow then needed. [arg Side] must be either [const left] (the default) or [const right]. [opt_def [option -arrowpadx] [arg amount]] [arg Amount] specifies how much padding to leave on the left and right of the arrow. [arg Amount] may be a list of two values to specify padding for left and right separately; it defaults to 6. [opt_def [option -arrowpady] [arg amount]] [arg Amount] specifies how much padding to leave on the top and bottom of the arrow. [arg Amount] may be a list of two values to specify padding for top and bottom separately; it defaults to 0. [opt_def [option -bitmap] [arg bitmap]] Specifies the bitmap to display in the element to the left of the column title. [opt_def [option -background] [arg color]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the color to use for the background of the column header. [opt_def [option -borderwidth] [arg size]] Specifies a non-negative value indicating the width of the 3-D border to draw around the outside of the column header (if such a border is being drawn; the [option -relief] column option determines this). The value may have any of the forms acceptable to [fun Tk_GetPixels]. [opt_def [option -button] [arg boolean]] Indicates whether or not the column header should be treated like a pushbutton. When this option is true, the default bindings track events in the header and generate a event when a event occurs in the header. See [sectref {DYNAMIC EVENTS}]. [opt_def [option -expand] [arg boolean]] Indicates whether or not any extra horizontal space should be distributed to this column. This option has no effect if the [option -width] option is set. [opt_def [option -font] [arg fontName]] Specifies the font to use for the column title inside the column header. [opt_def [option -image] [arg image]] Specifies the image to display in the element to the left of the column title. This option overrides the [option -bitmap] column option. [opt_def [option -imagepadx] [arg amount]] [arg Amount] specifies how much padding to leave on the left and right of the image (or bitmap). [arg Amount] may be a list of two values to specify padding for left and right separately; it defaults to 6. [opt_def [option -imagepady] [arg amount]] [arg Amount] specifies how much padding to leave on the top and bottom of the image (or bitmap). [arg Amount] may be a list of two values to specify padding for top and bottom separately; it defaults to 0. [opt_def [option -itembackground] [arg colorList]] Specifies a list of zero or more colors, which are used as alternating background colors for items in this column. See also the [option -backgroundmode] widget option for more on this. [opt_def [option -itemjustify] [arg justification]] This option determines how the item styles in this column line up with each other. Must be one of [const left], [const center], or [const right]. The default value is an empty string (for compatibility with older versions), in which case the column option [option -justify] is used to align item styles in this column. [opt_def [option -itemstyle] [arg style]] [arg Style] is the name of a style that should be set in this column for newly-created items. [opt_def [option -justify] [arg justification]] This option determines how the image and text in the column header are positioned. It also affects the position of item styles in this column unless the column option [option -itemjustify] is specified. Must be one of [const left] (the default), [const center], or [const right]. [opt_def [option -lock] [arg lock]] This option allows a column to stick to the left or right edge of the window. A locked column scrolls vertically but not horizontally. Must be one of [const none] (the default), [const left], or [const right]. [opt_def [option -maxwidth] [arg size]] Specifies the maximum size, in screen units, that will be permitted for this column. If [arg size] is an empty string, then there is no limit on the maximum size of the column. This option has no effect if the [option -width] option is set. [opt_def [option -minwidth] [arg size]] Specifies the minimum size, in screen units, that will be permitted for this column. If [arg size] is an empty string, then the minimum size of the column is zero. This option has no effect if the [option -width] option is set. [opt_def [option -resize] [arg boolean]] Specifies a boolean value that indicates whether the user should be allowed to resize the column by dragging the edge of the column's header. Default is true. [opt_def [option -squeeze] [arg boolean]] Specifies a boolean value that indicates whether or not the column should shrink when the content width of the treectrl is less than the total needed width of all visible columns. Defaults to false, which means the column will not get smaller than its needed width. The column will not get smaller than the value of its [option -minwidth] option, if specified. This option has no effect if the [option -width] option is set. [opt_def [option -state] [arg state]] Specifies one of three states for the column header: [const normal], [const active], or [const pressed]. The active state is used when the mouse is over the header. The pressed state is used when the mouse button is pressed in the header. [opt_def [option -stepwidth] [arg size]] Deprecated. Use the treectrl's [option -itemwidthmultiple] option instead. [opt_def [option -tags] [arg tagList]] [arg TagList] is a list of tag names that can be used to identify the column. See also the [cmd {column tag}] command. [opt_def [option -text] [arg text]] Specifies a text string to be displayed as the column title. [opt_def [option -textcolor] [arg color]] Specifies a color, which should be used as foreground color to display the column title. [opt_def [option -textlines] [arg count]] Specifies the maximum number of lines of text to display in the column title. If this value is zero, the number of lines displayed is determined by any newline characters and the effects of wrapping when the column width is less than needed. The default is 1. Note: Under OSX/Aqua this value is always set to 1 when the treectrl's [option -usetheme] option is true, because the Appearance Manager uses a fixed height for the column header; there is only room for a single line of text. [opt_def [option -textpadx] [arg amount]] [arg Amount] specifies how much padding to leave on the left and right of the text. [arg Amount] may be a list of two values to specify padding for left and right separately; it defaults to 6. [opt_def [option -textpady] [arg amount]] [arg Amount] specifies how much padding to leave on the top and bottom of the text. [arg Amount] may be a list of two values to specify padding for top and bottom separately; it defaults to 0. [opt_def [option -uniform] [arg group]] When a non-empty value is supplied, this option places the column in a [emph "uniform group"] with other columns that have the same value for [option -uniform]. The space for columns belonging to a uniform group is allocated so that their sizes are always in strict proportion to their [option -weight] values. This option is based on the grid geometry manager. [opt_def [option -visible] [arg boolean]] Indicates whether or not the column should be displayed. [opt_def [option -weight] [arg integer]] Sets the relative weight for apportioning any extra space among columns. A weight of zero (0) indicates the column will not deviate from its requested size. A column whose weight is two will grow at twice the rate as a column of weight one when extra space is allocated to columns. This option is based on the grid geometry manager. [opt_def [option -width] [arg size]] Specifies a fixed width for the column. If this value is an empty string, then the column width is calculated as the maximum of: a) the width requested by items; b) the width requested by the column's header; and c) the column's [option -minwidth] option. This calculated width is also affected by the [option -expand], [option -squeeze], [option -uniform] and [option -weight] options. In any case, the calculated width will not be greater than the [option -maxwidth] option, if specified. [opt_def [option -widthhack] [arg boolean]] Deprecated. Use the treectrl's [option -itemwidthequal] option instead. [list_end] [section {COLUMN DESCRIPTION}] Many of the commands and options for a treectrl take as an argument a description of which column to operate on. See the [sectref EXAMPLES] section for examples. The initial part of a column description must begin with one of the following terms: [list_begin definitions] [lst_item [arg id]] Specifies the unique column identifier, where [arg id] should be the return value of a prior call of the [cmd {column create}] widget command. See also the [option -columnprefix] option. [lst_item [arg QUALIFIERS]] Specifies a list of qualifiers. This gives the same result as [const all] followed by [arg QUALIFIERS]; i.e., every column is tested for a match. [lst_item "[arg tagExpr] [arg QUALIFIERS]"] [arg TagExpr] is a tag expression (see [sectref {ITEM AND COLUMN TAGS}]) against which every column's tags are tested for a match. This keyword cannot be followed by any modifiers unless a single column is matched. You may run into trouble if [arg tagExpr] looks like a column id or other keyword; also, [arg tagExpr] must look like a single list element since column descriptions are properly-formed lists. To be safe you may want to use the [const tag] qualifier followed by [arg tagExpr]. [lst_item "[const all] [arg QUALIFIERS]"] Indicates every column, including the tail column if the command allows it, which match [arg QUALIFIERS]. [lst_item "[const first] [arg QUALIFIERS]"] Indicates the leftmost column of the treectrl which matches [arg QUALIFIERS]. [lst_item "[const end] [arg QUALIFIERS]"] [lst_item "[const last] [arg QUALIFIERS]"] Indicates the rightmost column of the treectrl (but not the tail column) which matches [arg QUALIFIERS]. [lst_item "[const list] [arg columnDescs]"] [arg ColumnDescs] is a list (a single argument, i.e. "list {a b c}" not "list a b c") of other column descriptions. This keyword cannot be followed by any modifiers unless a single column is matched. [lst_item "[const order] [arg n] [arg QUALIFIERS]"] Indicates the [arg n]th column in the list of columns as returned by the [cmd {column order}] command. [lst_item "[const range] [arg {first last}] [arg QUALIFIERS]"] [arg First] and [arg last] specify a range of columns. This keyword cannot be followed by any modifiers unless a single column is specified. [lst_item [const tail]] Indicates the ever-present tail column of the treectrl. [lst_item [const tree]] Indicates the column specified by the -treecolumn option of the treectrl. [list_end] [para] The initial part of the column description (matching any of the values above) may be followed by one or more [arg modifier]s. A modifier changes the column used relative to the description up to this point. It may be specified in any of the following forms: [list_begin definitions] [lst_item "[const next] [arg QUALIFIERS]"] Use the column to the right matching [arg QUALIFIERS]. [lst_item "[const prev] [arg QUALIFIERS]"] Use the column to the left matching [arg QUALIFIERS]. [list_end] The word [arg QUALIFIERS] above represents a sequence of zero or more of the following terms that changes which column is chosen: [list_begin definitions] [lst_item "[const state] [arg stateList]"] [arg StateList] is a list of column state names. Only columns that have the given states set (or unset if the '!' prefix is used) are considered. [lst_item "[const tag] [arg tagExpr]"] [arg TagExpr] is a tag expression (see [sectref {ITEM AND COLUMN TAGS}]) against which a column's tags are tested for a match. [lst_item [const !tail]] When this qualifier is given, the tail column is not matched. [lst_item [const visible]] When this qualifier is given, only columns whose [option -visible] option is TRUE are considered. [lst_item [const !visible]] When this qualifier is given, only columns whose [option -visible] option is FALSE are considered. [list_end] [section STATES] For every item a set of boolean states is managed. These states play an integral role in the appearance of each item. The following states are predefined for every item: [list_begin definitions] [lst_item [const active]] At all times this state is set for exactly one item. The active item is used with keyboard navigation. When the treectrl widget is created or when the active item is deleted, the root item will become the active item. This state can be modified by means of the widget command [cmd activate]. [lst_item [const enabled]] This state is set for every item when it is created. Disabled items cannot be selected and are ignored by the default bindings when navigating via the keyboard. This state can be modified by means of the widget command [cmd {item enabled}]. [lst_item [const focus]] This state is set for every item, if the treectrl widget currently has the focus. It cannot be modified by means of a widget command, but is maintained in reaction to the and events. [lst_item [const open]] If this state is switched on, the descendants of the item are displayed - the item is expanded. If this state is switched off, the descendants of the item are not displayed - the item is collapsed. For a new item this state is switched on by default. This state can be modified by means of the widget commands [cmd {item expand}], [cmd {item collapse}], or [cmd {item toggle}]. [lst_item [const selected]] This state is set for every item included in the selection. It can be modified by means of the widget command [cmd selection]. [list_end] [para] By means of the [cmd {state define}] widget command up to 27 additional states can be defined. [section {PER-STATE OPTIONS}] The visual appearance of an item can change depending on the state the item is in, such as being the active item, being included in the selection, being collapsed, or some combination of those or other states. When a configuration option is described as [emph per-state], it means the option describes a value which varies depending on the state of the item. If a per-state option is specified as a single value, the value is used for all states. Otherwise the per-state option must be specified as an even-numbered list. For example, to use the font "Times 12 bold" in a [const text] element regardless of the item state you can write: [example_begin] $T element configure MyTextElement -font {{Times 12 bold}} [example_end] However, to use a different font when the item is selected you could write: [example_begin] $T element configure MyTextElement -font {{Courier 10} selected {Times 12 bold} {}} [example_end] In the example above, the -font option reads "value stateList value stateList". If [arg stateList] is an empty list, the preceding [arg value] is used regardless of the item state. A non-empty stateList specifies a list of states which must be set for the item in order to use the preceding value. Each stateList can also include state names preceded by a ! sign, indicating the state must *not* be set for the item. For example: [example_begin] $T element configure MyRectElement -fill {blue {selected focus} gray {selected !focus}} [example_end] In the example above, the [const rect] element is filled with blue when the treectrl has the focus and the item is selected. If the treectrl does not have the focus, the example specifies that gray should be used for selected items. Also note that if the item is not selected, no color is specified for the -fill option. [para] Each value-stateList pair is checked in order from left to right. The value associated with the first stateList that matches the current item state is used. So stateLists should be listed from most-specific to least-specific. [example_begin] $T element configure MyRectElement -fill {gray {selected} blue {selected focus}} [example_end] Written this way, gray will always be used for selected items since it appears first, and blue will never be used for selected items regardless of the focus. [para] A value followed by an empty stateList should always be last since it will be chosen regardless of the item's state. [section ELEMENTS] Elements are the smallest building blocks which are handled by a treectrl widget. One or more elements together can be combined to a style, which can be considered as a blueprint for an item. An element can be of type [const bitmap], [const border], [const image], [const rect], [const text] or [const window]. For each element type there is a section below describing the options which can modify an element of that type. [para] All of the element configuration options described below are unspecified by default, meaning that no value whatsoever has been given to the option. It may seem strange to you that a boolean option would be unspecified instead of simply "true" or "false". The reason for this is that when an element displayed by an item has no value specified for an option, the element refers to the master element created by the [cmd {element create}] command for a value for that option. This allows items which are displaying a certain element to be redisplayed when the master element's options change. The [cmd {item element configure}] command can be used to override the master element's configuration options for a specific item. [section {BITMAP ELEMENT}] An element of type [const bitmap] can be used to display a bitmap in an item. The following options are supported for bitmap elements: [list_begin opt] [opt_def [option -background] [arg color]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the color to use for each of the bitmap's '0' valued pixels. If the value for a certain state is an empty string (the default), the bitmap is drawn transparent. [opt_def [option -bitmap] [arg bitmap]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the bitmap to display in the element. [opt_def [option -draw] [arg boolean]] Deprecated; use the style layout option [option -draw] instead. Specifies as a [sectref {PER-STATE OPTIONS} per-state] option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn. [opt_def [option -foreground] [arg color]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the color to use for each of the bitmap's '1' valued pixels. If the value for a certain state is an empty string (the default), the bitmap's foreground color is black. [list_end] [section {BORDER ELEMENT}] An element of type [const border] can be used to display a 3D border in an item. The following options are supported for border elements: [list_begin opt] [opt_def [option -background] [arg color]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the color to use for the background of the border. If the value for a certain state is an empty string (the default), the element will not be drawn. [opt_def [option -draw] [arg boolean]] Deprecated; use the style layout option [option -draw] instead. Specifies as a [sectref {PER-STATE OPTIONS} per-state] option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn. [opt_def [option -filled] [arg boolean]] Specifies whether the interior of the border should be filled with the background color. If this option is unspecified (the default), it it treated as false which means that only the edges of the border will be drawn. [opt_def [option -height] [arg size]] Specifies the height of the border. If this value is unspecified (the default), the border will be exactly as tall as its display area as determined by the style layout options. [opt_def [option -relief] [arg relief]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the relief of the border. If the value for a certain state is an empty string (the default), it is treated as flat. For acceptable values see the description of the [option -relief] option in the [cmd options] manual page. [opt_def [option -thickness] [arg thickness]] Specifies the thickness of the edges of the border. [opt_def [option -width] [arg size]] Specifies the width of the border. If this value is unspecified (the default), the border will be exactly as wide as its display area as determined by the style layout options. [list_end] [section {IMAGE ELEMENT}] An element of type [const image] can be used to display an image in an item. The following options are supported for image elements: [list_begin opt] [opt_def [option -draw] [arg boolean]] Deprecated; use the style layout option [option -draw] instead. Specifies as a [sectref {PER-STATE OPTIONS} per-state] option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn. [opt_def [option -height] [arg size]] Specifies the requested height of the display area for this element. If unspecified (the default), the element requests a height equal to the height of the image, or zero if there is no image. [opt_def [option -image] [arg image]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the image to display in the element. [opt_def [option -width] [arg size]] Specifies the requested width of the display area for this element. If unspecified (the default), the element requests a width equal to the width of the image, or zero if there is no image. [list_end] [section {RECTANGLE ELEMENT}] An element of type [const rect] can be used to display a rectangle in an item. The following options are supported for rectangle elements: [list_begin opt] [opt_def [option -draw] [arg boolean]] Deprecated; use the style layout option [option -draw] instead. Specifies as a [sectref {PER-STATE OPTIONS} per-state] option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn. [opt_def [option -fill] [arg color]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the color to be used to fill the rectangle's area. If the color for a certain state is an empty string (the default), then the rectangle will not be filled (but the outline may still be drawn). [opt_def [option -height] [arg size]] Specifies the height of the rectangle. If this value is unspecified (the default), the rectangle will be exactly as tall as its display area as determined by the style layout options. [opt_def [option -open] [arg open]] This option may be used to get an incomplete drawing of the outline. [arg Open] is a string that contains zero or more of the characters [const n], [const s], [const e] or [const w]. Each letter refers to a side (north, south, east, or west) that the outline will not be drawn. The default is the empty string, which causes the outline to be drawn completely. [opt_def [option -outline] [arg color]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the color to be used to draw the outline of the rectangle. If the color for a certain state is an empty string (the default), then no outline is drawn for the rectangle. [opt_def [option -outlinewidth] [arg outlineWidth]] Specifies the width of the outline to be drawn around the rectangle's region. [arg outlineWidth] may be in any of the forms acceptable to [fun Tk_GetPixels]. If this option is specified as an empty string (the default), then no outline is drawn. [opt_def [option -showfocus] [arg boolean]] Specifies a boolean value indicating whether a "focus ring" should be drawn around the rectangle, if the item containing the rectangle is the active item and the treectrl widget currently has the focus. If this option is specified as an empty string (the default), then a focus rectangle is not drawn. [opt_def [option -width] [arg size]] Specifies the width of the rectangle. If this value is unspecified (the default), the rectangle will be exactly as wide as its display area as determined by the style layout options. [list_end] [section {TEXT ELEMENT}] An element of type [const text] can be used to display a text in an item. The following options are supported for text elements: [list_begin opt] [opt_def [option -draw] [arg boolean]] Deprecated; use the style layout option [option -draw] instead. Specifies as a [sectref {PER-STATE OPTIONS} per-state] option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn. [opt_def [option -data] [arg data]] Specifies a value that together with the [option -datatype] and [option -format] options will be displayed as text. [opt_def [option -datatype] [arg dataType]] Specifies the type of information in the [option -data] option. Acceptable values are [const double], [const integer], [const long], [const string], or [const time]. [opt_def [option -fill] [arg color]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the foreground color to use when displaying the text. If the color for a certain state is an empty string (the default), then the text will be displayed using the color specified by the treectrl's [option -foreground] option. [opt_def [option -format] [arg formatString]] This option specifies the format string used to display the value of the [option -data] option. If [option -datatype] is [const time], [arg formatString] should be a valid format string for the Tcl [cmd clock] command. For all other [option -datatype] values [arg formatString] should be a valid format string for the Tcl [cmd format] command. If this value is unspecified the following defaults are used: for -datatype double "%g", for -datatype integer "%d", for -datatype long "%ld", for -datatype string "%s", and for -datatype time the default format string of the Tcl [cmd clock] command. [opt_def [option -font] [arg font]] Specifies as a [sectref {PER-STATE OPTIONS} per-state] option the font to use when displaying the text. If the font for a certain state is an empty string, the text is displayed using the font specified by the treectrl's [option -font] option. [opt_def [option -justify] [arg how]] Specifies how to justify the text when multiple lines are displayed. [arg How] must be one of the values [const left], [const right], or [const center]. If this option is specified as an empty string (the default), [const left] is used. [opt_def [option -lines] [arg lineCount]] Specifies the maximum number of lines to display. If more than [arg lineCount] lines would be displayed, the last line will be truncated with an ellipsis at the right. If this option is specified as zero or an empty string (the default), there is no limit to the number of lines displayed. [opt_def [option -text] [arg string]] [arg String] specifies a string to be displayed by the element. [arg String] may contain newline characters in which case multiple lines of text will be displayed. If this option is specified, the [option -data], [option -datatype], [option -format], and [option -textvariable] options are ignored. [opt_def [option -textvariable] [arg varName]] Specifies the name of a variable. The value of the variable is a string to be displayed by the element; if the variable value changes then the element will automatically update itself to display the new value. If this option is specified, the [option -data], [option -datatype], and [option -format] options are ignored. [opt_def [option -underline] [arg charIndex]] Specifies the integer index of a character to underline. 0 corresponds to the first character. If [arg charIndex] is unspecified (the default), less than zero or greater than the index of the last displayed character, the underline is not drawn. [opt_def [option -width] [arg size]] Specifies the maximum line length in any of the forms acceptable to [fun Tk_GetPixels]. For text to wrap lines the value of the [option -width] option must be less than the needed width of the text, or the display area for this element must be less than the needed width of the text. For the display area to be less than the needed width of the text, one of the style layout options [option -maxwidth], [option -width] or [option -squeeze] must be used. [opt_def [option -wrap] [arg mode]] [arg Mode] specifies how to handle lines in the text that are longer than the maximum line length. Acceptable values are [const none], [const char] or [const word]. If this option is unspecified (the default), [const word] is used. See the [option -width] option for a description of how the maximum line length is determined. [list_end] [section {WINDOW ELEMENT}] An element of type [const window] can be used to display a Tk window in an item. The following options are supported for window elements: [list_begin opt] [opt_def [option -clip] [arg boolean]] Specifies whether the associated Tk window is a borderless frame which should be used to clip its child window so it doesn't overlap the header, borders, or other items or columns. When this option is true, the treectrl manages the geometry of both the [option -window] widget and its first child widget; in this case the [option -window] widget (which should be a borderless frame) is kept sized and positioned so that it is never out-of-bounds. [opt_def [option -destroy] [arg boolean]] Specifies whether the associated Tk window should be destroyed when the element is deleted. The element is deleted when the item containing the element is deleted, when the column containing the element is deleted, or when the style assigned to the item's column is changed. If this option is unspecified (the default), it is treated as false and the Tk window will not be destroyed. [opt_def [option -draw] [arg boolean]] Deprecated; use the style layout option [option -draw] instead. Specifies as a [sectref {PER-STATE OPTIONS} per-state] option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn. [opt_def [option -window] [arg pathName]] Specifies the window to associate with this element. The window specified by [arg pathName] must either be a child of the treectrl widget or a child of some ancestor of the treectrl widget. [arg PathName] may not refer to a top-level window. This option cannot be specified by the [cmd {element create}] or [cmd {element configure}] commands, only by the [cmd {item element configure}] command; i.e., the element must be associated with a particular item. [list_end] [section {ITEM DESCRIPTION}] Many of the commands for a treectrl take as an argument a description of which items to operate on. An item description is a properly-formed tcl list of keywords and arguments. The first word of an item description must be one of the following: [list_begin definitions] [lst_item [arg id]] Specifies the unique item identifier, where [arg id] should be the return value of a prior call of the [cmd {item create}] widget command, or [const 0] to specify the ever-present root item. See also the [option -itemprefix] option. [lst_item [arg QUALIFIERS]] Specifies a list of qualifiers. This gives the same result as [const all] followed by [arg QUALIFIERS]; i.e., every item is tested for a match. [lst_item "[arg tagExpr] [arg QUALIFIERS]"] [arg TagExpr] is a tag expression (see [sectref {ITEM AND COLUMN TAGS}]) against which every item's tags are tested for a match. This keyword cannot be followed by any modifiers unless a single item is matched. You may run into trouble if [arg tagExpr] looks like an item id or other keyword; also, [arg tagExpr] must look like a single list element since item descriptions are properly-formed lists. To be safe you may want to use the [const tag] qualifier followed by [arg tagExpr]. [lst_item [const active]] Indicates the item that is currently active, i.e. normally the item specified as argument of the last successful [cmd activate] widget command, or the root item if no such call happened yet. [lst_item [const anchor]] Indicates the anchor item of the selection, i.e. normally the item specified as argument of the last successful [cmd {selection anchor}] widget command, or the root item if no such call happened yet. [lst_item "[const all] [arg QUALIFIERS]"] Indicates every item including orphans which match [arg QUALIFIERS]. This keyword cannot be followed by any modifiers unless a single item is matched. [lst_item "[const first] [arg QUALIFIERS]"] Indicates the first item of the treectrl (the root item), or the first item matching [arg QUALIFIERS]. [lst_item "[const end] [arg QUALIFIERS]"] [lst_item "[const last] [arg QUALIFIERS]"] Indicates the last item which matches [arg QUALIFIERS]. [lst_item "[const list] [arg itemDescs]"] [arg ItemDescs] is a list (a single argument, i.e. "list {a b c}" not "list a b c") of other item descriptions. This keyword cannot be followed by any modifiers unless a single item is matched. [lst_item "[const nearest] [arg {x y}]"] Indicates the item nearest to the point given by [arg x] and [arg y]. [lst_item "[const rnc] [arg {row column}]"] Indicates the item in the given [arg row] and [arg column]. The row and column corresponds to the on-screen arrangement of items as determined by the -orient and -wrap options. You can memorize [const rnc] as an abbreviation of "row 'n' column". [lst_item "[const range] [arg {first last}] [arg QUALIFIERS]"] [arg First] and [arg last] specify a range of items. This keyword cannot be followed by any modifiers unless a single item is matched. [lst_item [const root]] Indicates the root item of the treectrl. [list_end] [para] The initial part of the item description (matching any of the values above) may be followed by one or more [arg modifier]s. A modifier changes the item used relative to the description up to this point. It may be specified in any of the following forms: [list_begin definitions] [lst_item [const above]] Use the item one row above in this column. [lst_item "[const ancestors] [arg QUALIFIERS]"] Use the ancestors of the item (like [cmd {item ancestors}] but QUALIFIERS may change which ancestors match). This keyword cannot be followed by any modifiers. [lst_item [const below]] Use the item one row below in this column. [lst_item [const bottom]] Use the item in the last row of this column. [lst_item "[const child] [arg n] [arg QUALIFIERS]"] Use the [arg n]th child of the item. [lst_item "[const children] [arg QUALIFIERS]"] Use the children of the item (like [cmd {item children}] but QUALIFIERS may change which children match). This keyword cannot be followed by any modifiers. [lst_item "[const descendants] [arg QUALIFIERS]"] Use the descendants of the item (like [cmd {item descendants}] but QUALIFIERS may change which descendants match). This keyword cannot be followed by any modifiers. [lst_item "[const firstchild] [arg QUALIFIERS]"] Use the first child of the item. [lst_item "[const lastchild] [arg QUALIFIERS]"] Use the last child of the item. [lst_item [const left]] Use the item one column to the left in the same row. [lst_item [const leftmost]] Use the item of the first column in the same row. [lst_item "[const next] [arg QUALIFIERS]"] Use the next item, which is the first item from the following list: the first child, the next sibling or the next sibling of the nearest ancestor which has one. [lst_item "[const nextsibling] [arg QUALIFIERS]"] Use the next sibling of the item. [lst_item [const parent]] Use the parent of the item. [lst_item "[const prev] [arg QUALIFIERS]"] Use the last child of the previous sibling, or the parent if there is no previous sibling. [lst_item "[const prevsibling] [arg QUALIFIERS]"] Use the previous sibling of the item. [lst_item [const right]] Use the item one column to the right in the same row. [lst_item [const rightmost]] Use the item of the last column in the same row. [lst_item "[const sibling] [arg n] [arg QUALIFIERS]"] Use the [arg n]th child of the item's parent. [lst_item [const top]] Use the item in the first row of this column. [list_end] The word [arg QUALIFIERS] above represents a series of zero or more of the following terms that changes which item is chosen: [list_begin definitions] [lst_item "[const depth] [arg depth]"] Matches items whose depth (as returned by the [cmd depth] command) is equal to [arg depth]. [lst_item "[const state] [arg stateList]"] [arg StateList] is a list of item state names (static and dynamic, see [sectref STATES]). Only items that have the given states set (or unset if the '!' prefix is used) are considered. [lst_item "[const tag] [arg tagExpr]"] [arg TagExpr] is a tag expression (see [sectref {ITEM AND COLUMN TAGS}]) against which an item's tags are tested for a match. [lst_item [const visible]] When this qualifier is given, only items that are displayed are considered. [lst_item [const !visible]] When this qualifier is given, only items that are *not* displayed are considered. [list_end] To get the first item in the list that is enabled: [example_begin] $T item id "first state enabled" [example_end] To get the ancestors that are not open of the last item in the list: [example_begin] $T item id "last ancestors state !open" [example_end] To get the visible descendants of the root item: [example_begin] $T item id "root descendants visible" [example_end] To get the every hidden item with tag "a" or "b": [example_begin] $T item id "all !visible tag a||b" $T item id "!visible tag a||b" $T item id "tag a||b !visible" $T item id "a||b !visible" [example_end] [section {EVENTS AND SCRIPT SUBSTITUTIONS}] The [arg script] argument to [cmd {notify bind}] is a Tcl script, which will be evaluated whenever the given event is generated. [arg Script] will be executed in the same interpreter that the [cmd {notify bind}] command was executed in, and it will run at global level (only global variables will be accessible). If [arg script] contains any [const %] characters, then the script will not be evaluated directly. Instead, a new script will be generated by replacing each [const %], and the character following it, with information from the current event. Unlike the regular Tk [cmd bind] mechanism, each event generated by a treectrl widget has its own set of %-substitutions. [para] The following %-substitutions are valid for all static events: [list_begin opt] [opt_def %%] Replaced with a single % [opt_def %d] The detail name [opt_def %e] The event name [opt_def %P] The pattern, either or [opt_def %W] The object argument to the [cmd "notify bind"] command [opt_def %T] The treectrl widget which generated the event [opt_def %?] A list of the format {char value char value ...} for each %-substitution character and the value it is replaced by [list_end] [para] The following events may be generated by a treectrl widget: [list_begin definitions] [lst_item [const ]] Generated whenever the active item changes. [list_begin opt] [opt_def %c] The current active item [opt_def %p] The previous active item [list_end] [lst_item [const ]] Generated before an item is collapsed. [list_begin opt] [opt_def %I] The item id [list_end] [lst_item [const ]] Generated after an item is collapsed. [list_begin opt] [opt_def %I] The item id [list_end] [lst_item [const ]] Generated before an item is expanded. This event is useful if you want to add child items to the item just before the item is expanded. [list_begin opt] [opt_def %I] The item id [list_end] [lst_item [const ]] Generated after an item is expanded. [list_begin opt] [opt_def %I] The item id [list_end] [lst_item [const ]] Generated when items are about to be deleted by the [cmd {item delete}] command. [list_begin opt] [opt_def %i] List of items ids being deleted. [list_end] [lst_item [const ]] Generated when items become visible on screen and when items are no longer visible on screen. This event is useful if you have a very large number of items and want to assign styles only when items are actually going to be displayed. [list_begin opt] [opt_def %h] List of items ids which are no longer visible. [opt_def %v] List of items ids which are now visible. [list_end] [lst_item [const ]] Generated whenever the view in the treectrl changes in such a way that a horizontal scrollbar should be redisplayed. [list_begin opt] [opt_def %l] Same as the first fraction appended to [const -xscrollcommand]. Think [emph lower]. [opt_def %u] Same as the second fraction appended to [const -xscrollcommand]. Think [emph upper]. [list_end] [lst_item [const ]] Generated whenever the view in the treectrl changes in such a way that a vertical scrollbar should be redisplayed. [list_begin opt] [opt_def %l] Same as the first fraction appended to [const -yscrollcommand]. Think [emph lower]. [opt_def %u] Same as the second fraction appended to [const -yscrollcommand]. Think [emph upper]. [list_end] [lst_item [const ]] Generated whenever the selection changes. This event gives information about how the selection changed. [list_begin opt] [opt_def %c] Same as the [cmd "selection count"] widget command [opt_def %D] List of newly-deselected item ids [opt_def %S] List of newly-selected item ids [list_end] [list_end] [section {DYNAMIC EVENTS}] In addition to the pre-defined static events such as and , new dynamic events can be created by using the [cmd {notify install}] command. [para] The following events may be generated by the library scripts: [list_begin definitions] [lst_item [const ]] [lst_item [const ]] [lst_item [const ]] Generated whenever the user drag-and-drops a column header. The library scripts do not actually move a dragged column. You must bind to the receive event to move the column. See [sectref EXAMPLES]. [list_begin opt] [opt_def %C] The column that was dragged [opt_def %b] The column to move the dragged column before [list_end] [lst_item [const ]] [lst_item [const ]] [lst_item [const ]] Generated whenever the user drag-and-drops a file into a directory. This event is generated by the filelist-bindings.tcl library code, which is not used by default. See the "Explorer" demos. [list_begin opt] [opt_def %I] The item that the user dropped the dragged items on. [opt_def %l] (lowercase L) The list of dragged items. [list_end] [lst_item [const ]] [lst_item [const ]] [lst_item [const ]] The filelist-bindings.tcl code will display a text-editing window if the user clicks on a selected file/folder name. See the "Explorer" demos. [list_begin opt] [opt_def %I] The item containing the edited text element [opt_def %C] The column containing the edited text element [opt_def %E] The name of the edited text element [opt_def %t] The edited text [list_end] [lst_item [const ]] Generated whenever the user clicks and releases the left mouse button in a column header if the column's -button option is true. You can bind a script to this event to sort the list. [list_begin opt] [opt_def %C] The column whose header was clicked [list_end] [list_end] The library scripts provide an example of using a dynamic event called , which is generated when the mouse button is released over a column header. [example_begin] treectrl .t .t notify install .t notify bind ConsoleTag { puts "header %C clicked in treectrl %T" } proc ::TreeCtrl::Release1 {w x y} { ... $w notify generate [lb]list C $Priv(column)[rb] \ [lb]list ::TreeCtrl::PercentsCmd $w[rb] ... } [example_end] In the example a new treectrl widget is created and the event is installed. For convenience there is no [arg percentsCommand] argument to [cmd {notify install}]; instead the call to [cmd {notify generate}] specifies the %-substitution command. A script is bound to the event with [cmd {notify bind}] which will print out the column number and widget name to the console (in the demos, is used to sort the list based on the column that was clicked). The [arg charMap] argument to [cmd {notify generate}] provides a list of %-substitution characters and values which is used by ::TreeCtrl::PercentsCmd. In this example any %C in any script bound to the event will be replaced by the value of $Priv(column). [section {DEFAULT BINDINGS}] Tk automatically creates class bindings for treectrl widgets that give them the following default behavior. [list_begin enum] [enum] Clicking mouse button 1 over an item positions the active cursor on the item, sets the input focus to this widget, and resets the selection of the widget to this item, if it is not already in the selection. [enum] Clicking mouse button 1 with the Control key down will reposition the active cursor and add the item to the selection without ever removing any items from the selection. [enum] If the mouse is dragged out of the widget while button 1 is pressed, the treectrl will automatically scroll to make more items visible (if there are more items off-screen on the side where the mouse left the window). [enum] The Left and Right keys move the active cursor one item to the left or right; for an hierarchical tree with vertical orientation nothing will happen, since it has no two items in the same row. The selection is set to include only the active item. If Left or Right is typed with the Shift key down, then the active cursor moves and the selection is extended to include the new item. [enum] The Up and Down keys move the active cursor one item up or down. The selection is set to include only the active item. If Up or Down is typed with the Shift key down, then the active cursor moves and the selection is extended to include the new item. [enum] The Next and Prior keys move the active cursor forward or backwards by one screenful, without affecting the selection. [enum] Control-Next and Control-Prior scroll the view right or left by one page without moving the active cursor or affecting the selection. Control-Left and Control-Right behave the same. [enum] The Home and End keys scroll to the left or right end of the widget without moving the active cursor or affecting the selection. [enum] The Control-Home and Control-End keys scroll to the top or bottom of the widget, they also activate and select the first or last item. If also the Shift key is down, then the active cursor moves and the selection is extended to include the new item. [enum] The Space and Select keys set the selection to the active item. [enum] Control-/ selects the entire contents of the widget. [enum] Control-\\ clears any selection in the widget. [enum] The + and - keys expand or collapse the active item, the Return key toggles the active item. [enum] The mousewheel scrolls the view of the widget four lines up or down depending on the direction, the wheel was turned. The active cursor or the selection is not affected. [list_end] [section EXAMPLES] Get the unique identifier for the leftmost visible column: [example_begin] set id [lb]$T column index "first visible"[rb] [example_end] Delete the leftmost column: [example_begin] $T column delete "order 0" [example_end] Take the visible column that is to the left of the last column, and move that column in front of the tail column: [example_begin] $T column move "last prev visible" tail [example_end] Get the unique identifier for the first visible item: [example_begin] set id [lb]$T item index "first visible"[rb] [example_end] Delete the parent of the item that is under the point x,y: [example_begin] $T item delete "nearest $x $y parent" [example_end] Add the 10th child of the second child of the root item to the selection: [example_begin] $T selection add "root firstchild nextsibling child 10" [example_end] Move a column that the user drag-and-dropped: [example_begin] $T column dragconfigure -enable yes $T notify install $T notify bind MyTag { %T column move %C %b } [example_end] [see_also listbox(n) image(n) bitmap(n) bind(n) options(n)] [keywords tree widget] [manpage_end] tktreectrl-2.2.8/doc/treectrl.n0000700000175600010010000050007611073207242014662 0ustar TimNone'\" '\" Generated from file 'doc/treectrl.man' by tcllib/doctools with format 'nroff' '\" '\" Copyright (c) 2002-2003 Christian Krone. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" '\" $Id: treectrl.n,v 1.74 2008/10/08 19:48:50 treectrl Exp $ .so man.macros .TH "treectrl" n 2.2.8 treectrl "Tk Commands" .BS .SH NAME treectrl \- Create and manipulate hierarchical multicolumn widgets .SH SYNOPSIS package require \fBtreectrl 2.2.8\fR .sp \fBtreectrl\fR \fIpathName\fR ?\fIoptions\fR? .sp \fIpathName\fR \fBactivate\fR \fIitemDesc\fR .sp \fIpathName\fR \fBbbox\fR ?\fIarea\fR? .sp \fIpathName\fR \fBcanvasx\fR \fIscreenx\fR .sp \fIpathName\fR \fBcanvasy\fR \fIscreeny\fR .sp \fIpathName\fR \fBcget\fR \fIoption\fR .sp \fIpathName\fR \fBcollapse\fR ?\fB-recurse\fR? ?\fIitemDesc ...\fR? .sp \fIpathName\fR \fBcolumn\fR \fIoption\fR \fIcolumn\fR ?\fIarg ...\fR? .sp \fIpathName\fR \fBcolumn bbox\fR \fIcolumnDesc\fR .sp \fIpathName\fR \fBcolumn cget\fR \fIcolumnDesc\fR \fIoption\fR .sp \fIpathName\fR \fBcolumn configure\fR \fIcolumnDesc\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? .sp \fIpathName\fR \fBcolumn compare\fR \fIcolumn1\fR \fIop\fR \fIcolumn2\fR .sp \fIpathName\fR \fBcolumn count\fR ?\fIcolumnDesc\fR? .sp \fIpathName\fR \fBcolumn create\fR ?\fIoption value ...\fR? .sp \fIpathName\fR \fBcolumn delete\fR \fIfirst\fR ?\fIlast\fR? .sp \fIpathName\fR \fBcolumn dragcget\fR \fIoption\fR .sp \fIpathName\fR \fBcolumn dragconfigure\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? .sp \fIpathName\fR \fBcolumn index\fR \fIcolumnDesc\fR .sp \fIpathName\fR \fBcolumn id\fR \fIcolumnDesc\fR .sp \fIpathName\fR \fBcolumn list\fR ?\fI-visible\fR? .sp \fIpathName\fR \fBcolumn move\fR \fIcolumnDesc\fR \fIbeforeDesc\fR .sp \fIpathName\fR \fBcolumn neededwidth\fR \fIcolumnDesc\fR .sp \fIpathName\fR \fBcolumn order\fR \fIcolumnDesc\fR ?\fI-visible\fR? .sp \fIpathName\fR \fBcolumn tag\fR \fIoption\fR ?\fIarg arg ...\fR? .sp \fIpathName\fR \fBcolumn tag add\fR \fIcolumnDesc\fR \fItagList\fR .sp \fIpathName\fR \fBcolumn tag expr\fR \fIcolumnDesc\fR \fItagExpr\fR .sp \fIpathName\fR \fBcolumn tag names\fR \fIcolumnDesc\fR .sp \fIpathName\fR \fBcolumn tag remove\fR \fIcolumnDesc\fR \fItagList\fR .sp \fIpathName\fR \fBcolumn width\fR \fIcolumnDesc\fR .sp \fIpathName\fR \fBcompare\fR \fIitemDesc1\fR \fIop\fR \fIitemDesc2\fR .sp \fIpathName\fR \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? .sp \fIpathName\fR \fBcontentbox\fR .sp \fIpathName\fR \fBdebug\fR \fIoption\fR ?\fIarg arg ...\fR? .sp \fIpathName\fR \fBdebug alloc\fR .sp \fIpathName\fR \fBdebug cget\fR \fIoption\fR .sp \fIpathName\fR \fBdebug configure\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? .sp \fIpathName\fR \fBdebug dinfo\fR \fIoption\fR .sp \fIpathName\fR \fBdebug expose\fR \fIx1\fR \fIy1\fR \fIx2\fR \fIy2\fR .sp \fIpathName\fR \fBdebug scroll\fR .sp \fIpathName\fR \fBdepth\fR ?\fIitemDesc\fR? .sp \fIpathName\fR \fBdragimage\fR \fIoption\fR ?\fIarg ...\fR? .sp \fIpathName\fR \fBdragimage add\fR \fIitemDesc\fR ?\fIcolumn\fR? ?\fIelement\fR? .sp \fIpathName\fR \fBdragimage cget\fR \fIoption\fR .sp \fIpathName\fR \fBdragimage clear\fR .sp \fIpathName\fR \fBdragimage configure\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? .sp \fIpathName\fR \fBdragimage offset\fR ?\fIx y\fR? .sp \fIpathName\fR \fBelement\fR \fIoption\fR ?\fIelement\fR? ?\fIarg arg ...\fR? .sp \fIpathName\fR \fBelement cget\fR \fIelement\fR \fIoption\fR .sp \fIpathName\fR \fBelement configure\fR \fIelement\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? .sp \fIpathName\fR \fBelement create\fR \fIelement\fR \fItype\fR ?\fIoption value ...\fR? .sp \fIpathName\fR \fBelement delete\fR ?\fIelement ...\fR? .sp \fIpathName\fR \fBelement names\fR .sp \fIpathName\fR \fBelement perstate\fR \fIelement\fR \fIoption\fR \fIstateList\fR .sp \fIpathName\fR \fBelement type\fR \fIelement\fR .sp \fIpathName\fR \fBexpand\fR ?\fB-recurse\fR? ?\fIitemDesc ...\fR? .sp \fIpathName\fR \fBidentify\fR \fIx\fR \fIy\fR .sp \fIpathName\fR \fBindex\fR \fIitemDesc\fR .sp \fIpathName\fR \fBitem\fR \fIoption\fR ?\fIarg ...\fR? .sp \fIpathName\fR \fBitem ancestors\fR \fIitemDesc\fR .sp \fIpathName\fR \fBitem bbox\fR \fIitemDesc\fR ?\fIcolumn\fR? ?\fIelement\fR? .sp \fIpathName\fR \fBitem cget\fR \fIitemDesc\fR \fIoption\fR .sp \fIpathName\fR \fBitem children\fR \fIitemDesc\fR .sp \fIpathName\fR \fBitem collapse\fR \fIitemDesc\fR ?\fB-recurse\fR? .sp \fIpathName\fR \fBitem compare\fR \fIitemDesc1\fR \fIop\fR \fIitemDesc2\fR .sp \fIpathName\fR \fBitem complex\fR \fIitemDesc\fR ?\fIlist...\fR? .sp \fIpathName\fR \fBitem configure\fR \fIitemDesc\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? .sp \fIpathName\fR \fBitem count\fR ?\fIitemDesc\fR? .sp \fIpathName\fR \fBitem create\fR ?\fIoption value ...\fR? .sp \fIpathName\fR \fBitem delete\fR \fIfirst\fR ?\fIlast\fR? .sp \fIpathName\fR \fBitem descendants\fR \fIitemDesc\fR .sp \fIpathName\fR \fBitem dump\fR \fIitemDesc\fR .sp \fIpathName\fR \fBitem element\fR \fIcommand\fR \fIitemDesc\fR \fIcolumn\fR \fIelement\fR ?\fIarg ...\fR? .sp \fIpathName\fR \fBitem element actual\fR \fIitemDesc\fR \fIcolumn\fR \fIelement\fR \fIoption\fR .sp \fIpathName\fR \fBitem element cget\fR \fIitemDesc\fR \fIcolumn\fR \fIelement\fR \fIoption\fR .sp \fIpathName\fR \fBitem element configure\fR \fIitemDesc\fR \fIcolumn\fR \fIelement\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? .sp \fIpathName\fR \fBitem element perstate\fR \fIitemDesc\fR \fIcolumn\fR \fIelement\fR \fIoption\fR ?\fIstateList\fR? .sp \fIpathName\fR \fBitem enabled\fR \fIitemDesc\fR ?\fIboolean\fR? .sp \fIpathName\fR \fBitem expand\fR \fIitemDesc\fR ?\fB-recurse\fR? .sp \fIpathName\fR \fBitem firstchild\fR \fIparent\fR ?\fIchild\fR? .sp \fIpathName\fR \fBitem id\fR \fIitemDesc\fR .sp \fIpathName\fR \fBitem image\fR \fIitemDesc\fR ?\fIcolumn\fR? ?\fIimage\fR? ?\fIcolumn image ...\fR? .sp \fIpathName\fR \fBitem isancestor\fR \fIitemDesc\fR \fIdescendant\fR .sp \fIpathName\fR \fBitem isopen\fR \fIitemDesc\fR .sp \fIpathName\fR \fBitem lastchild\fR \fIparent\fR ?\fIchild\fR? .sp \fIpathName\fR \fBitem nextsibling\fR \fIsibling\fR ?\fInext\fR? .sp \fIpathName\fR \fBitem numchildren\fR \fIitemDesc\fR .sp \fIpathName\fR \fBitem order\fR \fIitemDesc\fR ?\fI-visible\fR? .sp \fIpathName\fR \fBitem parent\fR \fIitemDesc\fR .sp \fIpathName\fR \fBitem prevsibling\fR \fIsibling\fR ?\fIprev\fR? .sp \fIpathName\fR \fBitem range\fR \fIfirst\fR \fIlast\fR .sp \fIpathName\fR \fBitem remove\fR \fIitemDesc\fR .sp \fIpathName\fR \fBitem rnc\fR \fIitemDesc\fR .sp \fIpathName\fR \fBitem sort\fR \fIitemDesc\fR ?\fIoption ...\fR? .sp \fIpathName\fR \fBitem span\fR \fIitemDesc\fR ?\fIcolumn\fR? ?\fInumColumns\fR? ?\fIcolumn numColumns ...\fR? .sp \fIpathName\fR \fBitem state\fR \fIcommand\fR \fIitemDesc\fR ?\fIarg ...\fR? .sp \fIpathName\fR \fBitem state forcolumn\fR \fIitemDesc\fR \fIcolumn\fR ?\fIstateDescList\fR? .sp \fIpathName\fR \fBitem state get\fR \fIitemDesc\fR ?\fIstateName\fR? .sp \fIpathName\fR \fBitem state set\fR \fIitemDesc\fR ?\fIlastItem\fR? \fIstateDescList\fR .sp \fIpathName\fR \fBitem style\fR \fIcommand\fR \fIitemDesc\fR ?\fIarg ...\fR? .sp \fIpathName\fR \fBitem style elements\fR \fIitemDesc\fR \fIcolumn\fR .sp \fIpathName\fR \fBitem style map\fR \fIitemDesc\fR \fIcolumn\fR \fIstyle\fR \fImap\fR .sp \fIpathName\fR \fBitem style set\fR \fIitemDesc\fR ?\fIcolumn\fR? ?\fIstyle\fR? ?\fIcolumn style ...\fR? .sp \fIpathName\fR \fBitem tag\fR \fIoption\fR ?\fIarg arg ...\fR? .sp \fIpathName\fR \fBitem tag add\fR \fIitemDesc\fR \fItagList\fR .sp \fIpathName\fR \fBitem tag expr\fR \fIitemDesc\fR \fItagExpr\fR .sp \fIpathName\fR \fBitem tag names\fR \fIitemDesc\fR .sp \fIpathName\fR \fBitem tag remove\fR \fIitemDesc\fR \fItagList\fR .sp \fIpathName\fR \fBitem text\fR \fIitemDesc\fR ?\fIcolumn\fR? ?\fItext\fR? ?\fIcolumn text ...\fR? .sp \fIpathName\fR \fBitem toggle\fR \fIitemDesc\fR ?\fB-recurse\fR? .sp \fIpathName\fR \fBmarquee\fR \fIoption\fR ?\fIarg ...\fR? .sp \fIpathName\fR \fBmarquee anchor\fR ?\fIx y\fR? .sp \fIpathName\fR \fBmarquee cget\fR \fIoption\fR .sp \fIpathName\fR \fBmarquee configure\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? .sp \fIpathName\fR \fBmarquee coords\fR ?\fIx1 y1 x2 y2\fR? .sp \fIpathName\fR \fBmarquee corner\fR ?\fIx y\fR? .sp \fIpathName\fR \fBmarquee identify\fR .sp \fIpathName\fR \fBnotify\fR \fIoption\fR ?\fIarg ...\fR? .sp \fIpathName\fR \fBnotify bind\fR ?\fIobject\fR? ?\fIpattern\fR? ?+??\fIscript\fR? .sp \fIpathName\fR \fBnotify configure\fR \fIobject\fR \fIpattern\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? .sp \fIpathName\fR \fBnotify detailnames\fR \fIeventName\fR .sp \fIpathName\fR \fBnotify eventnames\fR .sp \fIpathName\fR \fBnotify generate\fR \fIpattern\fR ?\fIcharMap\fR? ?\fIpercentsCommand\fR? .sp \fIpathName\fR \fBnotify install\fR \fIpattern\fR ?\fIpercentsCommand\fR? .sp \fIpathName\fR \fBnotify install detail\fR \fIeventName\fR \fIdetail\fR ?\fIpercentsCommand\fR? .sp \fIpathName\fR \fBnotify install event\fR \fIeventName\fR ?\fIpercentsCommand\fR? .sp \fIpathName\fR \fBnotify linkage\fR \fIpattern\fR .sp \fIpathName\fR \fBnotify linkage\fR \fIeventName\fR ?\fIdetail\fR? .sp \fIpathName\fR \fBnotify unbind\fR \fIobject\fR ?\fIpattern\fR? .sp \fIpathName\fR \fBnotify uninstall\fR \fIpattern\fR .sp \fIpathName\fR \fBnotify uninstall detail\fR \fIeventName\fR \fIdetail\fR .sp \fIpathName\fR \fBnotify uninstall event\fR \fIeventName\fR .sp \fIpathName\fR \fBnumcolumns\fR .sp \fIpathName\fR \fBnumitems\fR .sp \fIpathName\fR \fBorphans\fR .sp \fIpathName\fR \fBrange\fR \fIfirst\fR \fIlast\fR .sp \fIpathName\fR \fBscan\fR \fIoption\fR \fIargs\fR .sp \fIpathName\fR \fBscan mark\fR \fIx\fR \fIy\fR .sp \fIpathName\fR \fBscan dragto\fR \fIx\fR \fIy\fR ?\fIgain\fR? .sp \fIpathName\fR \fBstate\fR \fIoption\fR \fIargs\fR .sp \fIpathName\fR \fBstate define\fR \fIstateName\fR .sp \fIpathName\fR \fBstate linkage\fR \fIstateName\fR .sp \fIpathName\fR \fBstate names\fR .sp \fIpathName\fR \fBstate undefine\fR ?\fIstateName ...\fR? .sp \fIpathName\fR \fBsee\fR \fIitemDesc\fR .sp \fIpathName\fR \fBselection\fR \fIoption\fR \fIargs\fR .sp \fIpathName\fR \fBselection add\fR \fIfirst\fR ?\fIlast\fR? .sp \fIpathName\fR \fBselection anchor\fR ?\fIitemDesc\fR? .sp \fIpathName\fR \fBselection clear\fR ?\fIfirst\fR? ?\fIlast\fR? .sp \fIpathName\fR \fBselection count\fR .sp \fIpathName\fR \fBselection get\fR ?\fIfirst\fR? ?\fIlast\fR? .sp \fIpathName\fR \fBselection includes\fR \fIitemDesc\fR .sp \fIpathName\fR \fBselection modify\fR \fIselect\fR \fIdeselect\fR .sp \fIpathName\fR \fBstyle\fR \fIoption\fR ?\fIelement\fR? ?\fIarg arg ...\fR? .sp \fIpathName\fR \fBstyle cget\fR \fIstyle\fR \fIoption\fR .sp \fIpathName\fR \fBstyle configure\fR \fIstyle\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? .sp \fIpathName\fR \fBstyle create\fR \fIstyle\fR ?\fIoption value ...\fR? .sp \fIpathName\fR \fBstyle delete\fR ?\fIstyle ...\fR? .sp \fIpathName\fR \fBstyle elements\fR \fIstyle\fR ?\fIelementList\fR? .sp \fIpathName\fR \fBstyle layout\fR \fIstyle\fR \fIelement\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? .sp \fIpathName\fR \fBstyle names\fR .sp \fIpathName\fR \fBtoggle\fR ?\fB-recurse\fR? ?\fIitemDesc ...\fR? .sp \fIpathName\fR \fBxview\fR ?\fIargs\fR? .sp \fIpathName\fR \fBxview\fR .sp \fIpathName\fR \fBxview moveto\fR \fIfraction\fR .sp \fIpathName\fR \fBxview scroll\fR \fInumber\fR \fIwhat\fR .sp \fIpathName\fR \fByview\fR ?\fIargs\fR? .sp \fIpathName\fR \fByview\fR .sp \fIpathName\fR \fByview moveto\fR \fIfraction\fR .sp \fIpathName\fR \fByview scroll\fR \fInumber\fR \fIwhat\fR .sp .BE .SH DESCRIPTION .TP \fBtreectrl\fR \fIpathName\fR ?\fIoptions\fR? .PP The \fBtreectrl\fR command creates a new window (given by the \fIpathName\fR argument) and makes it into a treectrl widget. Additional options, described above, may be specified on the command line or in the option database to configure aspects of the treectrl such as its background color and relief. The \fBtreectrl\fR command returns the path name of the new window. At the time this command is invoked, there must not exist a window named \fIpathName\fR, but \fIpathName\fR's parent must exist. .PP A treectrl is a widget which displays items in a one- or two-dimensional arrangement. Items have a parent-child relationship with other items. Items have a set of states, which are boolean properties. Items may be spread about one or more columns. For each column of an item there is a style associated, which determines how to display the item's column taking into account the item's current state set. One column can be defined to display the data in a hierarchical structure. .PP Normally the origin of the coordinate system is at the upper-left corner of the window containing the treectrl. It is possible to adjust the origin of the coordinate system relative to the origin of the window using the \fBxview\fR and \fByview\fR widget commands; this is typically used for scrolling. .PP A treectrl widget can be horizontal or vertical oriented like many other Tk widgets. For displaying hierarchical data only vertical orientation is useful, since only then the children of an item are displayed directly below their parent. If the treectrl widget is used only to display data in a multicolumn listbox, the specification of an orientation will give useful results. .SH "STANDARD OPTIONS" .TP \fB\fB-background\fR\fR .TP \fB\fB-borderwidth\fR\fR .TP \fB\fB-cursor\fR\fR .TP \fB\fB-font\fR\fR .TP \fB\fB-highlightbackground\fR\fR .TP \fB\fB-highlightcolor\fR\fR .TP \fB\fB-highlightthickness\fR\fR .TP \fB\fB-orient\fR\fR .TP \fB\fB-relief\fR\fR .TP \fB\fB-takefocus\fR\fR .TP \fB\fB-xscrollcommand\fR\fR .TP \fB\fB-yscrollcommand\fR\fR .TP \fB\fB-foreground\fR\fR See the \fBoption\fR manual entry for details on the standard options. .SH "WIDGET SPECIFIC OPTIONS" .LP .nf .ta 6c Command-Line Switch: \fB-backgroundimage\fR Database Name: \fBbackgroundImage\fR Database Class: \fBBackgroundImage\fR .fi .IP Specifies the name of an image to draw as the list background. The image is tiled horizontally and vertically to fill the content area of the list. If the image is transparent it is drawn on top of the background color(s). .LP .nf .ta 6c Command-Line Switch: \fB-backgroundmode\fR Database Name: \fBbackgroundMode\fR Database Class: \fBBackgroundMode\fR .fi .IP Specifies how the background color of items is chosen in each column. The value should be one of \fBrow\fR, \fBcolumn\fR, \fBorder\fR, or \fBordervisible\fR. The default is \fBrow\fR. This option has only an effect for columns which have \fB-itembackground\fR defined as list of two or more colors (see section \fBCOLUMNS\fR below for more on this). If \fBrow\fR or \fBcolumn\fR is specified, the background color is chosen based on the location of the item in the 1- or 2-dimensional grid of items as layed out on the screen; this layout of items is affected by the \fB-orient\fR and \fB-wrap\fR options as well as item visibility. When \fBorder\fR or \fBordervisible\fR is specified, the background color is chosen based on the result of the \fBitem order\fR command, regardless of the layout of items. .LP .nf .ta 6c Command-Line Switch: \fB-buttonbitmap\fR Database Name: \fBbuttonBitmap\fR Database Class: \fBButtonBitmap\fR .fi .IP Specifies the bitmap to be used as the expand/collapse button to the left of an item. This is a \fBper-state\fR option. If a bitmap is specified for a certain item state, it overrides the effects of -usetheme. .LP .nf .ta 6c Command-Line Switch: \fB-buttoncolor\fR Database Name: \fBbuttonColor\fR Database Class: \fBButtonColor\fR .fi .IP Specifies the foreground color which should be used for drawing the outline and the plus or minus sign of the button to the left of an item. .LP .nf .ta 6c Command-Line Switch: \fB-buttonimage\fR Database Name: \fBbuttonImage\fR Database Class: \fBButtonImage\fR .fi .IP Specifies the image to be used as the expand/collapse button to the left of an item. This is a \fBper-state\fR option. If an image is specified for a certain item state, it overrides the effects of -buttonbitmap and -usetheme. .LP .nf .ta 6c Command-Line Switch: \fB-buttonsize\fR Database Name: \fBbuttonSize\fR Database Class: \fBButtonSize\fR .fi .IP Specifies the width and height of the button drawn to the left of an item in any of the forms acceptable to \fBTk_GetPixels\fR. .LP .nf .ta 6c Command-Line Switch: \fB-buttonthickness\fR Database Name: \fBbuttonThickness\fR Database Class: \fBButtonThickness\fR .fi .IP Specifies the width of the outline and the plus or minus sign of the button to the left of an item in any of the forms acceptable to \fBTk_GetPixels\fR. .LP .nf .ta 6c Command-Line Switch: \fB-columnprefix\fR Database Name: \fBcolumnPrefix\fR Database Class: \fBColumnPrefix\fR .fi .IP Specifies an ascii string that changes the way column ids are reported and processed. If this option is a non-empty string, the usual integer value of a column id is prefixed with the given string. This can aid debugging but it is important your code doesn't assume column ids are integers if you use it. .LP .nf .ta 6c Command-Line Switch: \fB-columnproxy\fR Database Name: \fBcolumnProxy\fR Database Class: \fBColumnProxy\fR .fi .IP If this option specifies a non empty value, it should be a screen distance in any of the forms acceptable to \fBTk_GetPixels\fR. Then a 1 pixel thick vertical line will be drawn at the specified screen distance from the left edge of the treectrl widget, which reaches from top to bottom of the treectrl widget and uses an inverting color (i.e black on lighter background, white on darker background). This line can be used to give the user a visual feedback during column resizing. .LP .nf .ta 6c Command-Line Switch: \fB-columnresizemode\fR Database Name: \fBcolumnResizeMode\fR Database Class: \fBColumnResizeMode\fR .fi .IP Specifies the visual feedback used when resizing columns. The value should be one of \fBproxy\fR or \fBrealtime\fR. For \fBproxy\fR, a 1-pixel thick vertical line is drawn representing where the right edge of the column will be after resizing. For \fBrealtime\fR, the column's size is changed while the user is dragging the right edge of the column. .LP .nf .ta 6c Command-Line Switch: \fB-columntagexpr\fR Database Name: \fBcolumnTagExpr\fR Database Class: \fBColumnTagExpr\fR .fi .IP Specifies a boolean that enables or disables tag expressions in column descriptions. See \fBITEM AND COLUMN TAGS\fR. .LP .nf .ta 6c Command-Line Switch: \fB-defaultstyle\fR Database Name: \fBdefaultStyle\fR Database Class: \fBDefaultStyle\fR .fi .IP This option is deprecated; use the column option \fB-itemstyle\fR instead. Specifies a list of styles, one per column, to apply to each item created by the \fBitem create\fR command. The number of styles in the list can be different from the number of tree columns. Each list element should be a valid style name or an empty string to indicate no style should be applied to a specific column. The list of styles is updated if a style is deleted or if a column is moved. .LP .nf .ta 6c Command-Line Switch: \fB-doublebuffer\fR Database Name: \fBdoubleBuffer\fR Database Class: \fBDoubleBuffer\fR .fi .IP Specifies if double-buffering should be used to improve displaying. The value should be one of \fBnone\fR, \fBwindow\fR, or \fBitem\fR. For \fBnone\fR no double-buffering is used at all, which may be most memory efficient, but will probably generate some flickering on the screen. For \fBwindow\fR the complete tree is double-buffered, which requires a buffer big enough to contain the complete widget. For \fBitem\fR, which is the default, every item is separately double-buffered, so it works with a buffer size as big as the biggest item. .LP .nf .ta 6c Command-Line Switch: \fB-height\fR Database Name: \fBheight\fR Database Class: \fBHeight\fR .fi .IP Specifies the desired height for the window in any of the forms acceptable to \fBTk_GetPixels\fR. The default is 200 pixels. If this option is less than or equal to zero then the window will not request any size at all. .LP .nf .ta 6c Command-Line Switch: \fB-indent\fR Database Name: \fBindent\fR Database Class: \fBIndent\fR .fi .IP Specifies the screen distance an item is indented relative to its parent item in any of the forms acceptable to \fBTk_GetPixels\fR. The default is 19 pixels. .LP .nf .ta 6c Command-Line Switch: \fB-itemheight\fR Database Name: \fBitemHeight\fR Database Class: \fBItemHeight\fR .fi .IP Specifies a fixed height for every item in any of the forms acceptable to \fBTk_GetPixels\fR. If non-zero, this option overrides the requested height of an item and the -minitemheight option. The default is 0, which means that every item has the height requested by the arrangement of elements in each column. Items are never shorter than the maximum height of a button. .LP .nf .ta 6c Command-Line Switch: \fB-itemprefix\fR Database Name: \fBitemPrefix\fR Database Class: \fBItemPrefix\fR .fi .IP Specifies an ascii string that changes the way item ids are reported and processed. If this option is a non-empty string, the usual integer value of an item id is prefixed with the given string. This can aid debugging but it is important your code doesn't assume item ids are integers if you use it. .LP .nf .ta 6c Command-Line Switch: \fB-itemtagexpr\fR Database Name: \fBitemTagExpr\fR Database Class: \fBItemTagExpr\fR .fi .IP Specifies a boolean that enables or disables tag expressions in item descriptions. See \fBITEM AND COLUMN TAGS\fR. .LP .nf .ta 6c Command-Line Switch: \fB-itemwidth\fR Database Name: \fBitemWidth\fR Database Class: \fBItemWidth\fR .fi .IP Specifies a fixed width for every item in any of the forms acceptable to \fBTk_GetPixels\fR. If more than one column is visible, then this option has no effect. If the -orient option is vertical, and the -wrap option is unspecified, then this option has no effect (in that case all items are as wide as the column). .LP .nf .ta 6c Command-Line Switch: \fB-itemwidthequal\fR Database Name: \fBitemWidthEqual\fR Database Class: \fBItemWidthEqual\fR .fi .IP Specifies a boolean that says whether all items should have the same width. If more than one column is visible, then this option has no effect. If the -orient option is vertical, and the -wrap option is unspecified, then this option has no effect (in that case all items are as wide as the column). If the -itemwidth option is specified, then this option has no effect. .LP .nf .ta 6c Command-Line Switch: \fB-itemwidthmultiple\fR Database Name: \fBitemWidthMultiple\fR Database Class: \fBItemWidthMultiple\fR .fi .IP Specifies a screen distance that every item's width will be evenly divisible by in any of the forms acceptable to \fBTk_GetPixels\fR. If more than one column is visible, then this option has no effect. If the -orient option is vertical, and the -wrap option is unspecified, then this option has no effect (in that case all items are as wide as the column). If the -itemwidth option is specified, then this option has no effect. .LP .nf .ta 6c Command-Line Switch: \fB-linecolor\fR Database Name: \fBlineColor\fR Database Class: \fBLineColor\fR .fi .IP Specifies the color which should be used for drawing the connecting lines between related items. .LP .nf .ta 6c Command-Line Switch: \fB-linestyle\fR Database Name: \fBlineStyle\fR Database Class: \fBLineStyle\fR .fi .IP Specifies the style of the connecting lines between related items, should be \fBdot\fR which is the default, or \fBsolid\fR. .LP .nf .ta 6c Command-Line Switch: \fB-linethickness\fR Database Name: \fBlineThickness\fR Database Class: \fBLineThickness\fR .fi .IP Specifies the thickness of the connecting lines between related items in any of the forms acceptable to \fBTk_GetPixels\fR. .LP .nf .ta 6c Command-Line Switch: \fB-minitemheight\fR Database Name: \fBminItemHeight\fR Database Class: \fBMinItemHeight\fR .fi .IP Specifies a minimum height for every item in any of the forms acceptable to \fBTk_GetPixels\fR. The default is 0, which means that every item has the height requested by the arrangement of elements in each column. This option has no effect if the -itemheight option is specified. Items are never shorter than the maximum height of a button. .LP .nf .ta 6c Command-Line Switch: \fB-rowproxy\fR Database Name: \fBrowProxy\fR Database Class: \fBRowProxy\fR .fi .IP If this option specifies a non empty value, it should be a screen distance in any of the forms acceptable to \fBTk_GetPixels\fR. Then a 1 pixel thick horizontal line will be drawn at the specified screen distance from the top edge of the treectrl widget, which reaches from left to right of the treectrl widget and uses an inverting color (i.e black on lighter background, white on darker background). This line can be used to give the user a visual feedback during row resizing. .LP .nf .ta 6c Command-Line Switch: \fB-scrollmargin\fR Database Name: \fBscrollMargin\fR Database Class: \fBScrollMargin\fR .fi .IP Specifies a positive screen distance in any of the forms acceptable to \fBTk_GetPixels\fR. This option is used by the default bindings to determine how close to the edges of the contentbox the mouse pointer must be before scrolling occurs. Specifying a positive value is useful when items may be drag-and-dropped. Defaults to 0. .LP .nf .ta 6c Command-Line Switch: \fB-selectmode\fR Database Name: \fBselectMode\fR Database Class: \fBSelectMode\fR .fi .IP 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. .LP .nf .ta 6c Command-Line Switch: \fB-showbuttons\fR Database Name: \fBshowButtons\fR Database Class: \fBShowButtons\fR .fi .IP Specifies a boolean value that determines whether this widget leaves indentation space to display the expand/collapse buttons next to items. The default value is true. The item option \fB-button\fR determines whether any item has a button. See also the treectrl option \fB-showrootbutton\fR. .LP .nf .ta 6c Command-Line Switch: \fB-showheader\fR Database Name: \fBshowHeader\fR Database Class: \fBShowHeader\fR .fi .IP Specifies a boolean value that determines whether this widget should display the header line with the column names at the top of the widget. The default value is true. .LP .nf .ta 6c Command-Line Switch: \fB-showlines\fR Database Name: \fBshowLines\fR Database Class: \fBShowLines\fR .fi .IP Specifies a boolean value that determines whether this widget should draw the connecting lines between related items. The default value is true. .LP .nf .ta 6c Command-Line Switch: \fB-showroot\fR Database Name: \fBshowRoot\fR Database Class: \fBShowRoot\fR .fi .IP Specifies a boolean value that determines whether this widget should draw the root item. By suppressing the drawing of the root item the widget can have multiple items that appear as \fItoplevel\fR items. The default value is true. .LP .nf .ta 6c Command-Line Switch: \fB-showrootbutton\fR Database Name: \fBshowRootButton\fR Database Class: \fBShowRootButton\fR .fi .IP Specifies a boolean value that determines whether this widget leaves indentation space to display the expand/collapse button next to the root item. The default value is false. The item option \fB-button\fR determines whether the root item has a button. .LP .nf .ta 6c Command-Line Switch: \fB-showrootchildbuttons\fR Database Name: \fBshowRootChildButtons\fR Database Class: \fBShowRootChildButtons\fR .fi .IP Specifies a boolean value that determines whether this widget should draw the expand/collapse buttons next to children of the root item. The default value is true. .LP .nf .ta 6c Command-Line Switch: \fB-showrootlines\fR Database Name: \fBshowRootLines\fR Database Class: \fBShowRootLines\fR .fi .IP Specifies a boolean value that determines whether this widget should draw the connecting lines between children of the root item. The default value is true. .LP .nf .ta 6c Command-Line Switch: \fB-treecolumn\fR Database Name: \fBtreeColumn\fR Database Class: \fBTreeColumn\fR .fi .IP Specifies a \fBcolumn description\fR that determines which column displays the buttons and lines. The default is unspecified. .LP .nf .ta 6c Command-Line Switch: \fB-usetheme\fR Database Name: \fBuseTheme\fR Database Class: \fBUseTheme\fR .fi .IP Specifies a boolean value that determines whether this widget should draw parts of itself using a platform-specific theme manager. The default is false. .LP .nf .ta 6c Command-Line Switch: \fB-width\fR Database Name: \fBwidth\fR Database Class: \fBWidth\fR .fi .IP Specifies the desired width for the window in any of the forms acceptable to \fBTk_GetPixels\fR. The default is 200 pixel. If this option is less than or equal to zero then the window will not request any size at all. .LP .nf .ta 6c Command-Line Switch: \fB-wrap\fR Database Name: \fBwrap\fR Database Class: \fBWrap\fR .fi .IP Specifies whether items are arranged in a 1- or 2-dimensional layout. If the value is an empty string (the default), then items are arranged from top to bottom (-orient vertical) or from left to right (-orient horizontal) in a 1-dimensional layout. If the value is "\fIN\fR \fBitems\fR", then a no more than \fIN\fR items will appear in a vertical group (-orient vertical) or horizontal group (-orient horizontal). If the value is "\fIN\fR \fBpixels\fR", then a no vertical group of items will be taller than \fIN\fR pixels (-orient vertical) or no horizontal group of items will be wider than \fIN\fR pixels (-orient horizontal). If the value is \fBwindow\fR, then a no vertical group of items will be taller than the window (-orient vertical) or no horizontal group of items will be wider than the window (-orient horizontal). .LP .nf .ta 6c Command-Line Switch: \fB-xscrolldelay\fR Database Name: \fBxScrollDelay\fR Database Class: \fBScrollDelay\fR .fi .IP This option controls how quickly horizontal scrolling occurs while dragging the mouse with button 1 pressed. The value should be a list of 1 or 2 integers interpreted as microseconds. If 2 values are specified, then the first value determines the intial delay after the first scroll, and the second value determines the delay for all scrolling after the first. If only 1 value is specified, each scroll takes place after that delay. .LP .nf .ta 6c Command-Line Switch: \fB-xscrollincrement\fR Database Name: \fBxScrollIncrement\fR Database Class: \fBScrollIncrement\fR .fi .IP Specifies an increment for horizontal scrolling, in any of the usual forms permitted for screen distances. If the value of this option is greater than zero, the horizontal view in the window will be constrained so that the x coordinate at the left edge of the window is always an even multiple of \fB-xscrollincrement\fR; furthermore, the units for scrolling (e.g., the change in view when the left and right arrows of a scrollbar are selected) will also be \fB-xscrollincrement\fR. If the value of this option is less than or equal to zero, then horizontal scrolling snaps to the left of an item, or part of an item if items are wider than the contentbox. .LP .nf .ta 6c Command-Line Switch: \fB-yscrolldelay\fR Database Name: \fByScrollDelay\fR Database Class: \fBScrollDelay\fR .fi .IP This option controls how quickly vertical scrolling occurs while dragging the mouse with button 1 pressed. The value should be a list of 1 or 2 integers interpreted as microseconds. If 2 values are specified, then the first value determines the intial delay after the first scroll, and the second value determines the delay for all scrolling after the first. If only 1 value is specified, each scroll takes place after that delay. .LP .nf .ta 6c Command-Line Switch: \fB-yscrollincrement\fR Database Name: \fByScrollIncrement\fR Database Class: \fBScrollIncrement\fR .fi .IP Specifies an increment for vertical scrolling, in any of the usual forms permitted for screen distances. If the value of this option is greater than zero, the vertical view in the window will be constrained so that the y coordinate at the top edge of the window is always an even multiple of \fB-yscrollincrement\fR; furthermore, the units for scrolling (e.g., the change in view when the top and bottom arrows of a scrollbar are selected) will also be \fB-yscrollincrement\fR. If the value of this option is less than or equal to zero, then vertical scrolling snaps to the top of an item, or part of an item if items are taller than the contentbox. .SH "ITEM AND COLUMN TAGS" Columns and items may have any number of tags associated with them. A tag is just a string of characters, and it may take any form, including that of an integer, although the characters '(', ')', '&', '|', '^' and '!' should be avoided. .PP The same tag may be associated with many columns or items. This is commonly done to group items in various interesting ways; for example, in a file browser all directories might be given the tag "directory". .PP Tag expressions are used in \fBcolumn descriptions\fR and \fBitem descriptions\fR to specify which columns and items to operate on. A tag expression can be a single tag name or a logical expression of tags using operators '&&', '||', '^' and '!', and parenthesized subexpressions. For example: .nf .t item id "tag {(a && !b) || (!a && b)}" .fi or equivalently: .nf .t item id "tag {a ^ b}" .fi will return the unique ids of any items with either "a" or "b" tags, but not both. .PP Within a tag expression a tag name may be enclosed in double quotes to avoid special processing of the operator characters. For example: .nf .t item id {tag {"a&&b"||c}} .fi will return the unique ids of any items with either "a&&b" or "c" tags; in this example the && is not treated as an operator. A double-quote may be escaped within a quoted tag name using a backslash '\\'. .PP Tag operators may be bypassed completely by setting the \fB-columntagexpr\fR and \fB-itemtagexpr\fR options. This can be useful if your application has column or item tags containing arbitrary text. .nf .t configure -itemtagexpr false .t item delete "tag a&&b" .fi .SH "WIDGET COMMAND" The \fBtreectrl\fR command creates a new Tcl command whose name is the same as the path name of the treectrl's window. This command may be used to invoke various operations on the widget. It has the following general form: .PP \fIpathName\fR \fIoption\fR ?\fIarg arg ...\fR? .PP \fIPathName\fR is the name of the command, which is the same as the treectrl widget's path name. \fIOption\fR and the \fIarg\fRs determine the exact behavior of the command. The following commands are possible for treectrl widgets: .TP \fIpathName\fR \fBactivate\fR \fIitemDesc\fR Sets the active item to the one described by \fIitemDesc\fR, and switches on the state \fBactive\fR for this item. From now on the item can be retrieved with the item description \fBactive\fR. An \fB\fR event is generated. .TP \fIpathName\fR \fBbbox\fR ?\fIarea\fR? Returns a list with four elements giving the bounding box (left, top, right and bottom) of an area of the window. If \fIarea\fR is not specified, then the result is the bounding box of the entire window. If \fIarea\fR is \fBcontent\fR, then the result is the part of the window not including borders, headers, or locked columns. If \fIarea\fR is \fBheader\fR, then the result is the part of the window not including borders where column titles are displayed. If \fIarea\fR is \fBleft\fR, then the result is the part of the window not including borders or headers where left-locked columns are displayed. If \fIarea\fR is \fBright\fR, then the result is the part of the window not including borders or headers where right-locked columns are displayed. An empty string is returned if the display area has no height or width, which can be true for various reasons such as the window is too small, or the header is not displayed, or there aren't any locked columns. .TP \fIpathName\fR \fBcanvasx\fR \fIscreenx\fR Given a window x-coordinate in the treectrl \fIscreenx\fR, this command returns the treectrl x-coordinate that is displayed at that location. .TP \fIpathName\fR \fBcanvasy\fR \fIscreeny\fR Given a window y-coordinate in the treectrl \fIscreeny\fR, this command returns the treectrl y-coordinate that is displayed at that location. .TP \fIpathName\fR \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 \fBtree\fR command. .TP \fIpathName\fR \fBcollapse\fR ?\fB-recurse\fR? ?\fIitemDesc ...\fR? Use \fBitem collapse\fR instead. .TP \fIpathName\fR \fBcolumn\fR \fIoption\fR \fIcolumn\fR ?\fIarg ...\fR? This command is used to manipulate the columns of the treectrl widget (see section \fBCOLUMNS\fR below). The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBcolumn\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBcolumn bbox\fR \fIcolumnDesc\fR Returns a list with four elements giving the bounding box of the header of the column specified by the \fBcolumn description\fR \fIcolumnDesc\fR. If the treectrl is configured not to display the column headers by means of the \fB-showheader\fR option, then an empty list is returned instead. .TP \fIpathName\fR \fBcolumn cget\fR \fIcolumnDesc\fR \fIoption\fR This command returns the current value of the option named \fIoption\fR for the column specified by the \fBcolumn description\fR \fIcolumnDesc\fR, \fIColumnDesc\fR may also be the string \fBtail\fR to specify the tail column. \fIOption\fR may have any of the values accepted by the \fBcolumn configure\fR widget command. .TP \fIpathName\fR \fBcolumn configure\fR \fIcolumnDesc\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 columns specified by the \fBcolumn description\fR \fIcolumnDesc\fR instead of modifying options for the overall treectrl widget. \fIColumnDesc\fR may be the string \fBtail\fR to specify the tail column. If \fIcolumnDesc\fR refers to more than one column, then at least one option-value pair must be given. If no \fIoption\fR is specified, the command returns a list describing all of the available options for \fIcolumnDesc\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\fR-\fIvalue\fR pairs are specified, then the command modifies the given option(s) to have the given value(s) for \fIcolumnDesc\fR; in this case the command returns an empty string. .sp See \fBCOLUMNS\fR below for details on the options available for columns. .TP \fIpathName\fR \fBcolumn compare\fR \fIcolumn1\fR \fIop\fR \fIcolumn2\fR For both \fBcolumn descriptions\fR \fIcolumn1\fR and \fIcolumn2\fR the index is retrieved (as returned from the \fBcolumn order\fR widget command). Then these indexes are compared using the operator \fIop\fR, which must be either \fB<\fR, \fB<=\fR, \fB==\fR, \fB>=\fR, \fB>\fR, or \fB!=\fR. The return value of this command is 1 if the comparison evaluated to true, 0 otherwise. .TP \fIpathName\fR \fBcolumn count\fR ?\fIcolumnDesc\fR? If no additional arguments are given, the result is a decimal string giving the number of columns created by the \fBcolumn create\fR widget command which haven't been deleted by the \fBcolumn delete\fR widget command; in this case the \fBtail\fR column is not counted. If \fIcolumnDesc\fR is given, then the result is the number of columns that match that \fBcolumn description\fR. .TP \fIpathName\fR \fBcolumn create\fR ?\fIoption value ...\fR? This command creates a new column in the treectrl widget. The new column is placed to the right of all other columns (except the \fBtail\fR column). Any \fIoption\fR-\fIvalue\fR arguments configure the new column according to the \fBcolumn configure\fR command. The return value is the unique identifier of the new column. .TP \fIpathName\fR \fBcolumn delete\fR \fIfirst\fR ?\fIlast\fR? Deletes the specified column(s). \fIFirst\fR and \fIlast\fR must be valid \fBcolumn descriptions\fR. If both \fIfirst\fR and \fIlast\fR are specified, then they may refer to a single column only. The \fBtail\fR column cannot be deleted and it is an error to specify it. The order of \fIfirst\fR and \fIlast\fR doesn't matter, and \fIfirst\fR may be equal to \fIlast\fR. .TP \fIpathName\fR \fBcolumn dragcget\fR \fIoption\fR .TP \fIpathName\fR \fBcolumn dragconfigure\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? The user can move a column within a treectrl by drag-and-drop. Feedback consists of a semi-transparent photo image of the header of the column being dragged and a 2-pixel-thick vertical line to indicate where the column may be dropped. The drag image consists of a colored background rectangle plus the image and/or text displayed in the column header. The 2-pixel-thick line will be drawn over the left edge of the column before which the dragged column may be dropped. .sp The library scripts generate a event when the user has successfully drag-and-drop'd a column. You will have to bind a script to this event if you want to move the dragged column. .sp The following configuration options are supported: .RS .TP \fB\fB-enable\fR\fR \fIboolean\fR Controls whether the user is allowed to rearrange columns by drag-and-drop. .TP \fB\fB-imagealpha\fR\fR \fIalpha\fR \fIAlpha\fR is an integer from 0 (invisible) to 255 (opaque) controlling the transparency of the drag image. Any value outside this range is clipped. .TP \fB\fB-imagecolor\fR\fR \fIbackground\fR \fIBackground\fR is the color of the drag image background rectangle. .TP \fB\fB-imagecolumn\fR\fR \fIcolumn\fR \fIColumn\fR specifies the column to create the drag image from. .TP \fB\fB-imageoffset\fR\fR \fIoffset\fR \fIOffset\fR is the horizontal screen distance the drag image is offset from its starting position. .TP \fB\fB-indicatorcolor\fR\fR \fIcolor\fR \fIColor\fR is the color of the 2-pixel-thick line. .TP \fB\fB-indicatorcolumn\fR\fR \fIcolumn\fR The 2-pixel-thick line will be drawn over the left or right edge of \fIcolumn\fR. .TP \fB\fB-indicatorside\fR\fR \fIside\fR Specifies whether the 2-pixel-thick line will be drawn over the \fBleft\fR or \fBright\fR edge of the column specified by \fB-indicatorcolumn\fR. .RE .TP \fIpathName\fR \fBcolumn index\fR \fIcolumnDesc\fR Deprecated. Use \fBcolumn id\fR instead. .TP \fIpathName\fR \fBcolumn id\fR \fIcolumnDesc\fR This command resolves the \fBcolumn description\fR \fIcolumnDesc\fR into a list of unique column identifiers. If the column(s) described by \fIcolumnDesc\fR don't exist, this command returns an empty list. .TP \fIpathName\fR \fBcolumn list\fR ?\fI-visible\fR? This command returns a list of identifiers for every column (except the tail) from left to right. If \fI-visible\fR is given, only columns whose -visible option is true are returned. .TP \fIpathName\fR \fBcolumn move\fR \fIcolumnDesc\fR \fIbeforeDesc\fR Moves the column specified by \fIcolumnDesc\fR to the left of the column specified by \fIbeforeDesc\fR. Both \fIcolumnDesc\fR and \fIbeforeDesc\fR must be valid \fBcolumn descriptions\fR. If \fIbeforeDesc\fR is the string \fBtail\fR, the column \fIcolumnDesc\fR will become the last column. .TP \fIpathName\fR \fBcolumn neededwidth\fR \fIcolumnDesc\fR This command returns a decimal string giving the needed width of the column specified by the \fBcolumn description\fR \fIcolumnDesc\fR. The needed width is the maximum of the width of the column header and the width of the widest style in any visible item. .TP \fIpathName\fR \fBcolumn order\fR \fIcolumnDesc\fR ?\fI-visible\fR? This command returns a decimal string giving the position of the column specified by the \fBcolumn description\fR \fIcolumnDesc\fR in the list of columns starting from zero for the leftmost column. If \fI-visible\fR is given, only columns whose -visible option is true are considered, and -1 is returned if \fIcolumnDesc\fR's -visible option is false. .TP \fIpathName\fR \fBcolumn tag\fR \fIoption\fR ?\fIarg arg ...\fR? This command is used to manipulate tags on columns. The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBcolumn tag\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBcolumn tag add\fR \fIcolumnDesc\fR \fItagList\fR Adds each tag in \fItagList\fR to the columns specified by the \fBcolumn description\fR \fIcolumnDesc\fR. Duplicate tags are ignored. The list of tags for a column can also be changed via a column's \fB-tags\fR option. .TP \fIpathName\fR \fBcolumn tag expr\fR \fIcolumnDesc\fR \fItagExpr\fR Evaluates the tag expression \fItagExpr\fR against every column specified by the \fBcolumn description\fR \fIcolumnDesc\fR. The result is 1 if the tag expression evaluates to true for every column, 0 otherwise. .TP \fIpathName\fR \fBcolumn tag names\fR \fIcolumnDesc\fR Returns a list of tag names assigned to the columns specified by the \fBcolumn description\fR \fIcolumnDesc\fR. The result is the union of any tags assigned to the columns. .TP \fIpathName\fR \fBcolumn tag remove\fR \fIcolumnDesc\fR \fItagList\fR Removes each tag in \fItagList\fR from the columns specified by the \fBcolumn description\fR \fIcolumnDesc\fR. It is not an error if any of the columns do not use any of the tags. The list of tags for a column can also be changed via a column's \fB-tags\fR option. .RE .TP \fIpathName\fR \fBcolumn width\fR \fIcolumnDesc\fR This command returns a decimal string giving the width in pixels of the column specified by the \fBcolumn description\fR \fIcolumnDesc\fR, even if the treectrl is configured to not display the column headers by means of the \fB-showheader\fR option. .RE .TP \fIpathName\fR \fBcompare\fR \fIitemDesc1\fR \fIop\fR \fIitemDesc2\fR Deprecated. Use the \fBitem compare\fR command instead. .TP \fIpathName\fR \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\fR-\fIvalue\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 \fBtreectrl\fR command. .TP \fIpathName\fR \fBcontentbox\fR Returns a list with four elements giving the bounding box of the screen area used to display items. This is the area of the window not including borders, column headers, or locked columns. An empty string is returned if the display area has no height or width, which can happen if the window is too small. .TP \fIpathName\fR \fBdebug\fR \fIoption\fR ?\fIarg arg ...\fR? This command is used to facilitate debugging of the treectrl widget. The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBdebug\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBdebug alloc\fR Returns a string giving partial statistics on memory allocations, if the package was built with TREECTRL_DEBUG defined. .TP \fIpathName\fR \fBdebug cget\fR \fIoption\fR This command returns the current value of the debugging option named \fIoption\fR. \fIOption\fR may have any of the values accepted by the \fBdebug configure\fR widget command. .TP \fIpathName\fR \fBdebug configure\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? This command is similar to the \fBconfigure\fR widget command except that it modifies debugging options instead of modifying options for the overall treectrl widget. If no \fIoption\fR is specified, the command returns a list describing all of the available debugging options (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\fR-\fIvalue\fR pairs are specified, then the command modifies the given debugging option(s) to have the given value(s); in this case the command returns an empty string. .sp The following debugging options are supported: .RS .TP \fB\fB-displaydelay\fR\fR \fImillis\fR Specifies a time duration in milliseconds, which should be waited after something has been drawn to the screen. Setting this option has only an effect, if the debugging options \fB-enable\fR and \fB-display\fR are switched on. .TP \fB\fB-data\fR\fR \fIboolean\fR If this option is switched on (together with the debugging option \fB-enable\fR), at various places a consistence check on the internal data structure is made (e.g. for every item is checked, if the registered number of children is equal to the number of child items). If an inconsistency was found, a Tcl background error is raised. .TP \fB\fB-display\fR\fR \fIboolean\fR If this option is switched on (together with the debugging option \fB-enable\fR), at varios places additional debugging output is printed to stdout. .TP \fB\fB-drawcolor\fR\fR \fIcolor\fR When specified, areas of the window are painted with this color when drawing in those areas is about to occur. Setting this option has only an effect if the debugging options \fB-enable\fR and \fB-display\fR are switched on. .TP \fB\fB-enable\fR\fR \fIboolean\fR All other debugging options only take effect if this option is also switched on. .TP \fB\fB-erasecolor\fR\fR \fIcolor\fR When specified, areas of the window which have been marked as "invalid" (for example, when part of the window is exposed) are painted with this color. If you use an unusual color for this option (like \fBpink\fR), superflous screen redraws can be spotted more easily. Setting this option has only an effect if the debugging options \fB-enable\fR and \fB-display\fR are switched on. .TP \fB\fB-span\fR\fR \fIboolean\fR Debugging related to column spanning. .TP \fB\fB-textlayout\fR\fR \fIboolean\fR Debugging related to text-element layout. .RE .TP \fIpathName\fR \fBdebug dinfo\fR \fIoption\fR Returns a string describing display-related stuff. \fIOption\fR must be one of \fBalloc\fR, \fBditem\fR, \fBonscreen\fR or \fBrange\fR. .TP \fIpathName\fR \fBdebug expose\fR \fIx1\fR \fIy1\fR \fIx2\fR \fIy2\fR Causes the area of the window bounded by the given window-coords to be marked as invalid. This simulates uncovering part of the window. .TP \fIpathName\fR \fBdebug scroll\fR Returns a string useful for debugging vertical scrolling. .RE .TP \fIpathName\fR \fBdepth\fR ?\fIitemDesc\fR? If the additional argument \fIitemDesc\fR is given, then the result is a decimal string giving the depth of the item described by \fIitemDesc\fR. If no \fIitemDesc\fR is specified, then the maximum depth of all items in the treectrl widget is returned instead. Depth is defined as the number of ancestors an item has. .TP \fIpathName\fR \fBdragimage\fR \fIoption\fR ?\fIarg ...\fR? This command is used to manipulate the dragimage, one or more dotted lines around rectangular regions of the treectrl widget. The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBdragimage\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBdragimage add\fR \fIitemDesc\fR ?\fIcolumn\fR? ?\fIelement\fR? Adds the shapes of the item described by \fIitemDesc\fR to the shapes of the dragimage. Specifying additional arguments reduces the number of rectangles that are added to the dragimage. If no additional arguments is specified, for every element of the item in every column a dotted rectangles is added. If \fIcolumn\fR is specified, all elements in other columns are ignored. If also \fIelement\fR is specified, only a rectangle for this one element of the specified item in the given column is added. .TP \fIpathName\fR \fBdragimage cget\fR \fIoption\fR This command returns the current value of the dragimage option named \fIoption\fR. \fIOption\fR may have any of the values accepted by the \fBdragimage configure\fR widget command. .TP \fIpathName\fR \fBdragimage clear\fR Removes all shapes (if there are any) from the dragimage. This command does not modify the dragimage offset. .TP \fIpathName\fR \fBdragimage configure\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? This command is similar to the \fBconfigure\fR widget command except that it modifies the dragimage options instead of modifying options for the overall treectrl widget. If no \fIoption\fR is specified, the command returns a list describing all of the available dragimage options (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 dragimage 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\fR-\fIvalue\fR pairs are specified, then the command modifies the given dragimage option(s) to have the given value(s); in this case the command returns an empty string. .sp The following dragimage options are supported: .RS .TP \fB\fB-visible\fR\fR \fIboolean\fR Specifies a boolean value which determines whether the dragimage should currently be visible. .RE .TP \fIpathName\fR \fBdragimage offset\fR ?\fIx y\fR? Returns a list containing the x and y offsets of the dragimage, if no additional arguments are specified. The dragimage offset is the screen distance, the image is displayed relative to the item its shape is derived from. If two coordinates are specified, sets the dragimage offset to the given coordinates \fIx\fR and \fIy\fR. .RE .TP \fIpathName\fR \fBelement\fR \fIoption\fR ?\fIelement\fR? ?\fIarg arg ...\fR? This command is used to manipulate elements (see \fBELEMENTS\fR below). The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBelement\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBelement cget\fR \fIelement\fR \fIoption\fR This command returns the current value of the option named \fIoption\fR associated with the element given by \fIelement\fR. \fIOption\fR may have any of the values accepted by the \fBelement configure\fR widget command. .TP \fIpathName\fR \fBelement configure\fR \fIelement\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 element given by \fIelement\fR instead of modifying options for the overall treectrl widget. If no \fIoption\fR is specified, the command returns a list describing all of the available options for \fIelement\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\fR-\fIvalue\fR pairs are specified, then the command modifies the given option(s) to have the given value(s) in \fIelement\fR; in this case the command returns an empty string. See \fBELEMENTS\fR below for details on the options available for elements. .TP \fIpathName\fR \fBelement create\fR \fIelement\fR \fItype\fR ?\fIoption value ...\fR? Create a new elememt in \fIpathName\fR of type \fItype\fR with name \fIelement\fR. The exact format of the arguments after \fItype\fR depends on \fItype\fR, but generally consist of specifications for zero or more element options. See the subsections on individual element types below for more on the syntax of this command. This command returns the name for the new element. .TP \fIpathName\fR \fBelement delete\fR ?\fIelement ...\fR? Deletes each of the named elements and returns an empty string. If an element is deleted while it is still configured as an element of one or more styles by means of the \fBstyle elements\fR widget command, it is also removed from the element lists of these styles. .TP \fIpathName\fR \fBelement names\fR Returns a list containing the names of all existing elements. .TP \fIpathName\fR \fBelement perstate\fR \fIelement\fR \fIoption\fR \fIstateList\fR This command returns the value of the \fBper-state\fR option named \fIoption\fR for \fIelement\fR for a certain state. \fIStateList\fR is a list of state names (static and dynamic, see \fBSTATES\fR) which specifies the state to use. .TP \fIpathName\fR \fBelement type\fR \fIelement\fR Returns the type of the element given by \fIelement\fR, such as \fBrect\fR or \fBtext\fR. .RE .TP \fIpathName\fR \fBexpand\fR ?\fB-recurse\fR? ?\fIitemDesc ...\fR? Use \fBitem expand\fR instead. .TP \fIpathName\fR \fBidentify\fR \fIx\fR \fIy\fR Returns a list describing what is displayed at the given window coordinates \fIx\fR and \fIy\fR. If the coordinates are outside the window, over the borders, or over any whitespace in the window, then the result is an empty string; otherwise the first word of the result is \fBheader\fR or \fBitem\fR. .sp If the coordinates are over a column header, then the first word of the result is \fBheader\fR, followed by the unique id of the column (or the string \fBtail\fR). If the x coordinate is near the left or right end of a column, then a third word \fBleft\fR or \fBright\fR is appended to the result. .sp If the coordinates are over an item, then the first word of the result is \fBitem\fR followed by the unique id of that item. If the coordinates are not over the area for displaying buttons and lines, then \fBcolumn\fR and a unique column id are the 3rd and 4th words of the result. If the coordinates are over an element within that column, then \fBelement\fR and an element name are the 5th and 6th words of the result. .sp If the coordinates are over a button, then the first word of the result is \fBitem\fR, followed by the unique id of that item, followed by the word \fBbutton\fR. .sp If the coordinates are over a line descending from an ancestor of an item (but not the parent of that item), then the first word of the result is \fBitem\fR, followed by the unique id of that item, followed by the word \fBline\fR, followed by the unique id of the item the line is coming from. This is used to collapse the ancestor when the line is clicked on. .TP \fIpathName\fR \fBindex\fR \fIitemDesc\fR Deprecated. Use \fBitem id\fR instead. .TP \fIpathName\fR \fBitem\fR \fIoption\fR ?\fIarg ...\fR? This command is used to manipulate items. The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBitem\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBitem ancestors\fR \fIitemDesc\fR Returns a list containing the item ids of the ancestors of the item specified by \fIitemDesc\fR. The first list value is the parent, the second is the parent's parent, an so on. The last list value will be the root item if \fIitemDesc\fR is a descendant of the root item. .TP \fIpathName\fR \fBitem bbox\fR \fIitemDesc\fR ?\fIcolumn\fR? ?\fIelement\fR? Returns a list with four elements giving the bounding box of the item described by \fIitemDesc\fR. If no further argument is specified, the bbox spans the area of the item over all non-locked columns. If a \fIcolumn\fR is specified, only the area of the item in this column is considered. If an additional \fIelement\fR is specified, the area of this \fIelement\fR in \fIcolumn\fR of the specified item is returned. .TP \fIpathName\fR \fBitem cget\fR \fIitemDesc\fR \fIoption\fR Returns the current value of the configuration option for the item specified by \fIitemDesc\fR whose name is \fIoption\fR. \fIOption\fR may have any of the values accepted by the \fBitem configure\fR command. .TP \fIpathName\fR \fBitem children\fR \fIitemDesc\fR Returns a list containing the item ids of all children of the item specified by \fIitemDesc\fR in the correct order from the first child to the last child. .TP \fIpathName\fR \fBitem collapse\fR \fIitemDesc\fR ?\fB-recurse\fR? Switches off the \fBopen\fR state of the item(s) described by \fIitemDesc\fR. If an item has descendants, then they are no longer displayed. If an item is already closed, then this command has no effect on that item. If \fB-recurse\fR is specified, then all descendants of the items described by \fIitemDesc\fR will also be collapsed. For every item that actually will be collapsed, two events are generated: a \fB\fR event before the item state is changed, and a \fB\fR event after the item state was changed. .TP \fIpathName\fR \fBitem compare\fR \fIitemDesc1\fR \fIop\fR \fIitemDesc2\fR From both items described by the \fIitemDesc\fRs the index is retrieved (as returned from the \fBitem order\fR widget command). Then these indexes are compared using the operator \fIop\fR, which must be either \fB<\fR, \fB<=\fR, \fB==\fR, \fB>=\fR, \fB>\fR, or \fB!=\fR. The return value of this command is 1 if the comparison evaluated to true, 0 otherwise. .TP \fIpathName\fR \fBitem complex\fR \fIitemDesc\fR ?\fIlist...\fR? This horrible command is now deprecated. Use \fBitem element configure\fR instead. For every column of the treectrl there may be specified one \fIlist\fR. Each \fIlist\fR should look like this: .nf { {element option value ...} {element option value ...} ...} .fi Every \fIoption\fR must be known by the element's type (see \fBELEMENTS\fR below). Each \fIoption\fR will be set to \fIvalue\fR for the element in this one column in this item. .TP \fIpathName\fR \fBitem configure\fR \fIitemDesc\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? If no \fIoption\fR is specified, returns a list describing all of the available options for the item given by \fIitemDesc\fR (see \fBTk_ConfigureInfo\fR for information on the format of this list). If \fIoption\fR is specified with no value, 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). .sp If one or more \fIoption\fR-\fIvalue\fR pairs are specified, then the command modifies the given item option(s) to have the given value(s); in this case the command returns an empty string. This is the only case where \fIitemDesc\fR may refer to multiple items. .sp The following options are supported by this command (see \fBitem create\fR for the meaning of each option): .RS .TP \fB\fB-button\fR\fR \fIboolean|auto\fR .TP \fB\fB-height\fR\fR \fIheight\fR .TP \fB\fB-tags\fR\fR \fItagList\fR .TP \fB\fB-visible\fR\fR \fIboolean\fR .RE .TP \fIpathName\fR \fBitem count\fR ?\fIitemDesc\fR? If no additional arguments are given, the result is a decimal string giving the number of items created by the \fBitem create\fR widget command which haven't been deleted by the \fBitem delete\fR widget command, plus 1 for the ever-present root item. If the optional argument \fIitemDesc\fR is given, then the result is the number of items that match that \fBitem description\fR. .TP \fIpathName\fR \fBitem create\fR ?\fIoption value ...\fR? Creates some new items and optionally returns a list of unique identifiers for those items. The new items have the states \fBopen\fR and \fBenabled\fR set by default. If the treectrl widget currently has the focus, the state \fBfocus\fR is also set. .sp The following options are supported by this command: .RS .TP \fB\fB-button\fR\fR \fIboolean|auto\fR The value of this option must have one of the forms accepted by \fBTcl_GetBoolean\fR or be the word \fBauto\fR (or any abbreviation of it). It indicates whether or not an expand/collapse button should be drawn next to the item, typically to indicate that the item has children. If the value of this option is \fBauto\fR, then a button is displayed next to the item whenever the item has any children whose item option \fB-visible\fR is true. The button will only be displayed if: .RS .IP [1] the column specified by the treectrl option \fB-treecolumn\fR is visible, and .IP [2] the treectrl option \fB-showbuttons\fR is true, and .IP [3] for the root item, the treectrl option \fB-showrootbutton\fR is true. .RE .TP \fB\fB-count\fR\fR \fInumItems\fR Specifies the number of items to create. Must be >= 0. Defaults to 1. .TP \fB\fB-height\fR\fR \fIheight\fR Specifies a fixed height in any of the forms acceptable to \fBTk_GetPixels\fR. Must be >= 0. If \fIheight\fR is zero then the item's height is unspecified. Defaults to 0. .TP \fB\fB-nextsibling\fR\fR \fIitemDesc\fR Specifies the item before which the new items will be inserted. The new items will have the same parent as \fIitemDesc\fR. .TP \fB\fB-open\fR\fR \fIboolean\fR Specifies whether the items should be open or closed. Default is true. .TP \fB\fB-parent\fR\fR \fIitemDesc\fR Specifies the item which the new items will be the children of. The new items will be appended to the list of children of \fIitemDesc\fR. .TP \fB\fB-prevsibling\fR\fR \fIitemDesc\fR Specifies the item after which the new items will be inserted. The new items will have the same parent as \fIitemDesc\fR. .TP \fB\fB-returnid\fR\fR \fIboolean\fR Specifies whether or not to return a list of item identifiers for the newly created items. Specifying false is useful when creating a large number of items in the console or to improve performance. Default is true. .TP \fB\fB-tags\fR\fR \fItagList\fR \fITagList\fR is a list of tag names to be added to the new items. .TP \fB\fB-visible\fR\fR \fIboolean\fR \fIBoolean\fR must have one of the forms accepted by \fBTcl_GetBoolean\fR. It indicates that the item should be displayed in the list. The item will only be displayed if: a) each ancestor is a descendant of the root item (not an orphan); and b) each ancestor's \fB-visible\fR option is true .RE .TP \fIpathName\fR \fBitem delete\fR \fIfirst\fR ?\fIlast\fR? Deletes the specified item(s). \fIFirst\fR and \fIlast\fR must be valid \fBitem descriptions\fR. If \fIlast\fR isn't specified, then \fIfirst\fR may specify multiple items. If both \fIfirst\fR and \fIlast\fR are specified, they must each decribe a single item with a common ancestor; then the range of items between \fIfirst\fR and \fIlast\fR is deleted. The order of \fIfirst\fR and \fIlast\fR doesn't matter. .sp Deleting an item deletes any child items of the deleted item recursively. If the current \fBactive\fR item is deleted, the root item becomes the new active item. If the current selection \fBanchor\fR item is deleted, the root item becomes the new anchor item. There is no way to delete the root item of the treectrl widget; in all cases the specification of the root item is ignored. .sp For each call to this command, two events may be generated. If any of the deleted items are selected, then a \fB\fR event is generated just before the items are deleted. If any items are going to be deleted, then an \fB\fR event event is generated just before the items are deleted. .TP \fIpathName\fR \fBitem descendants\fR \fIitemDesc\fR Returns a list containing the item ids of the descendants of the item specified by \fIitemDesc\fR, i.e. the children, grandchildren, great-grandchildren etc, of the item. .TP \fIpathName\fR \fBitem dump\fR \fIitemDesc\fR Returns a list with 4 words in the form \fBindex\fR \fIindex\fR \fBindexVis\fR \fIindexVis\fR. .TP \fIpathName\fR \fBitem element\fR \fIcommand\fR \fIitemDesc\fR \fIcolumn\fR \fIelement\fR ?\fIarg ...\fR? This command is used to manipulate elements of the item. The exact behavior of the command depends on the \fIcommand\fR argument that follows the \fBelement\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBitem element actual\fR \fIitemDesc\fR \fIcolumn\fR \fIelement\fR \fIoption\fR Deprecated. Use \fBitem element perstate\fR instead. .TP \fIpathName\fR \fBitem element cget\fR \fIitemDesc\fR \fIcolumn\fR \fIelement\fR \fIoption\fR This command returns the value of the option named \fIoption\fR associated with \fIelement\fR inside \fIcolumn\fR of the item described by \fIitemDesc\fR, if it was already configured for the actual item. \fIOption\fR may have any of the values accepted by the type of the specified element (see \fBELEMENTS\fR below) .TP \fIpathName\fR \fBitem element configure\fR \fIitemDesc\fR \fIcolumn\fR \fIelement\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? This command modifies configuration options for an element in a column of an item. If no \fIoption\fR is specified, the command returns a list describing all of the available options for the element (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). .sp If one or more \fIoption\fR-\fIvalue\fR pairs are specified, then the command modifies the given option(s) to have the given value(s) in the \fIelement\fR inside \fIcolumn\fR of the item(s) described by \fIitemDesc\fR; in this case the command returns an empty string. This is the only case where \fIitemDesc\fR may refer to multiple items. .sp It is possible to configure multiple elements in multiple columns with a single call. To configure another element in the same column, append a \'\fB+\fR' argument followed by the element name. To configure elements in another column, append a '\fB,\fR' argument followed by the column. For example: .nf .t item element configure $I \\ $C1 $E1 -text "hello" + $E2 -text "world" , \\ $C2 $E3 -fill Blue , \\ $C3 $E1 -text "apples and oranges" .fi Each of the \fBcolumn description\fR arguments to this command may refer to multiple columns if at least one \fIoption\fR-\fIvalue\fR pair is given. .TP \fIpathName\fR \fBitem element perstate\fR \fIitemDesc\fR \fIcolumn\fR \fIelement\fR \fIoption\fR ?\fIstateList\fR? This command returns the current value of the \fBper-state\fR option named \fIoption\fR for \fIelement\fR inside \fIcolumn\fR of the item described by \fIitemDesc\fR. If \fIstateList\fR is specified, the list of state names (static and dynamic, see \fBSTATES\fR) is used in place of the current state for \fIitem\fR and \fIcolumn.\fR .RE .TP \fIpathName\fR \fBitem enabled\fR \fIitemDesc\fR ?\fIboolean\fR? Returns 1 if the item described by \fIitemDesc\fR has the state \fBenabled\fR switched on, 0 otherwise. If \fIboolean\fR is specified, then the \fBenabled\fR state of every item described by the \fBitem description\fR \fIitemDesc\fR is set accordingly. All items are enabled when first created. Disabled items cannot be selected, and are ignored by the default key-navigation and mouse bindings. .TP \fIpathName\fR \fBitem expand\fR \fIitemDesc\fR ?\fB-recurse\fR? Switches on the \fBopen\fR state of the item(s) described by \fIitemDesc\fR. If an item has descendants, then they are now displayed. If an item is already open, then this command has no effect on that item. If \fB-recurse\fR is specified, then all descendants of the items described by \fIitemDesc\fR will also be expanded. For every item that actually will be expanded, two events are generated: an \fB\fR event before the item state is changed, and an \fB\fR event after the item state was changed. .TP \fIpathName\fR \fBitem firstchild\fR \fIparent\fR ?\fIchild\fR? If \fIchild\fR is not specified, returns the item id of the first child of the item described by \fIparent\fR. If \fIchild\fR is specified, it must describe an item that is neither the root item nor an ancestor of \fIparent\fR. Then it will become the new first child of \fIparent\fR. .TP \fIpathName\fR \fBitem id\fR \fIitemDesc\fR This command resolves the \fBitem description\fR \fIitemDesc\fR into a list of unique item identifiers. If \fIitemDesc\fR doesn't refer to any existing items, then this command returns an empty list. .TP \fIpathName\fR \fBitem image\fR \fIitemDesc\fR ?\fIcolumn\fR? ?\fIimage\fR? ?\fIcolumn image ...\fR? This command sets or retrieves the value of the \fBper-state\fR -image option for the first image element in one or more columns. If no \fIcolumn\fR is specified, this command returns a list of values, one per column. If no \fIimage\fR is specified, this command returns the value for \fIcolumn\fR. .sp If one or more \fIcolumn\fR-\fIimage\fR pairs is specified, then the value of the -image option in each \fIcolumn\fR is set to \fIimage\fR. In this case \fIitemDesc\fR may refer to multiple items and each \fIcolumn\fR may refer to multiple columns. .sp Note that this command is provided as a convenience. Use the \fBitem element configure\fR or \fBitem element cget\fR commands if you want to set or retrieve the value of the -image option for a specific image element. .TP \fIpathName\fR \fBitem isancestor\fR \fIitemDesc\fR \fIdescendant\fR Returns 1 if the item described by \fIitemDesc\fR is a direct or indirect parent of the item decribed by \fIdescendant\fR, 0 otherwise. .TP \fIpathName\fR \fBitem isopen\fR \fIitemDesc\fR Returns 1 if the item described by \fIitemDesc\fR has the state \fBopen\fR switched on, 0 otherwise. .TP \fIpathName\fR \fBitem lastchild\fR \fIparent\fR ?\fIchild\fR? If \fIchild\fR is not specified, returns the item id of the last child of the item described by \fIparent\fR. If \fIchild\fR is specified, it must describe an item that is not an ancestor of \fIparent\fR. Then it will become the new last child of \fIparent\fR. .TP \fIpathName\fR \fBitem nextsibling\fR \fIsibling\fR ?\fInext\fR? If \fInext\fR is not specified, returns the item id of the next sibling of the item described by \fIsibling\fR. If \fInext\fR is specified, it must describe an item that is not an ancestor of \fIsibling\fR. Then it will become the new next sibling of \fIsibling\fR. .TP \fIpathName\fR \fBitem numchildren\fR \fIitemDesc\fR Returns the number of children of the item described by \fIitemDesc\fR. .TP \fIpathName\fR \fBitem order\fR \fIitemDesc\fR ?\fI-visible\fR? This command returns the position of the item \fIitemDesc\fR relative to its toplevel ancestor (usually the root item, unless the ancestor is an orphan). If you imagine all the items flattened into a vertical list, the result of this command is the row the item falls in. If the optional argument \fI-visible\fR is given, only the items whose ancestors are expanded, and whose -visible option is true, get counted; in this case -1 is returned if the item is not visible. .TP \fIpathName\fR \fBitem parent\fR \fIitemDesc\fR Returns the item id of the parent of the item described by \fIitemDesc\fR. .TP \fIpathName\fR \fBitem prevsibling\fR \fIsibling\fR ?\fIprev\fR? If \fIprev\fR is not specified, returns the item id of the previous sibling of the item described by \fIsibling\fR. If \fIprev\fR is specified, it must describe an item that is not an ancestor of \fIsibling\fR. Then it will become the new previous sibling of \fIsibling\fR. .TP \fIpathName\fR \fBitem range\fR \fIfirst\fR \fIlast\fR Returns a list containing the item ids of all items in the range between \fIfirst\fR and \fIlast\fR, inclusive. The order between \fIfirst\fR and \fIlast\fR doesn't matter, and the result is always sorted by the increasing order of the items (as returned by the \fBitem order\fR command). The items specified by \fIfirst\fR and \fIlast\fR must share a common ancestor. .TP \fIpathName\fR \fBitem remove\fR \fIitemDesc\fR Removes the item described by \fIitemDesc\fR from the list of children of its parent, so that it will become an orphan. .TP \fIpathName\fR \fBitem rnc\fR \fIitemDesc\fR Returns a list of two integers, which corresponds to the row and column of the item described by \fIitemDesc\fR. The row and column corresponds to the on-screen arrangement of items as determined by the -orient and -wrap options. If the item is not displayed, this command returns an empty string. .TP \fIpathName\fR \fBitem sort\fR \fIitemDesc\fR ?\fIoption ...\fR? Sorts the children of the item described by \fIitemDesc\fR, and redisplays the tree with the items in the new order. .sp The range of items which should be sorted can be restricted by means of the \fB-first\fR and/or \fB-last\fR options, which should be children of the item described by \fIitemDesc\fR; the order between these two limiting items doesn't matter. .sp The sort column can be specified by means of the \fB-column\fR option; this option can be used repeatedly to define a multicolumn sort. The sorting is done by looking at the \fItext\fR of the element specified by the \fB-element\fR option, which must be a text element defined in the style of the sorting column, by default the first text element is used. .sp If the \fB-notreally\fR option is specified, no rearranging of the items is done; instead the sorted items are returned as result of the command. .sp By default ASCII sorting is used with the result returned in increasing order. Any of the following options may be specified to control the sorting process of the previously specified column (unique abbreviations are accepted): .RS .TP \fB\fB-ascii\fR\fR Use string comparison with ASCII collation order. This is the default. .TP \fB\fB-command\fR\fR \fIcommand\fR Use \fIcommand\fR as a comparison command. To compare two items, evaluate a Tcl script consisting of \fIcommand\fR with the numerical ids of the two items appended as additional arguments. The script should return an integer less than, equal to, or greater than zero if the first item is to be considered less than, equal to, or greater than the second, respectively. .TP \fB\fB-decreasing\fR\fR Sort the items in decreasing order ("largest" items first). .TP \fB\fB-dictionary\fR\fR Use dictionary-style comparison. This is the same as \fB-ascii\fR except (a) case is ignored except as a tie-breaker and (b) if two strings contain embedded numbers, the numbers compare as integers, not characters. For example, in \fB-dictionary\fR mode, \fIbigBoy\fR sorts between \fIbigbang\fR and \fIbigboy\fR, and \fIx10y\fR sorts between \fIx9y\fR and \fIx11y\fR. .TP \fB\fB-increasing\fR\fR Sort the items in increasing order ("smallest" items first). This is the default. .TP \fB\fB-integer\fR\fR Convert to integers and use integer comparison. .TP \fB\fB-real\fR\fR Convert to floating-point values and use floating comparison. .RE .TP \fIpathName\fR \fBitem span\fR \fIitemDesc\fR ?\fIcolumn\fR? ?\fInumColumns\fR? ?\fIcolumn numColumns ...\fR? This command sets or retrieves the number of columns that a style covers. If no \fIcolumn\fR is specified, the return value is a list of spans, one per column. If no \fInumColumns\fR is specified, the return value is the span for \fIcolumn\fR. .sp If one or more \fIcolumn\fR-\fInumColumns\fR pairs is specified, the span for each \fIcolumn\fR is set to \fInumColumns\fR. In this case \fIitemDesc\fR may refer to multiple items and each \fIcolumn\fR may refer to multiple columns. .TP \fIpathName\fR \fBitem state\fR \fIcommand\fR \fIitemDesc\fR ?\fIarg ...\fR? This command is used to manipulate the states of an item. The exact behavior of the command depends on the \fIcommand\fR argument that follows the \fBstyle\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBitem state forcolumn\fR \fIitemDesc\fR \fIcolumn\fR ?\fIstateDescList\fR? Just like \fBitem state set\fR but manipulates dynamic states for a single item column, not the item as a whole. If \fIstateDescList\fR is unspecified, this command returns a list containing the names of all the dynamic states which are switched on in \fIcolumn\fR. .sp If \fIstateDescList\fR is specified, then \fIitemDesc\fR may refer to multiple items and \fIcolumn\fR may refer to multiple columns. .TP \fIpathName\fR \fBitem state get\fR \fIitemDesc\fR ?\fIstateName\fR? If no \fIstateName\fR is specified, returns a list containing the names of all (static and dynamic) states which are currently switched on for the item described by \fIitemDesc\fR. If a \fIstateName\fR is specified, 1 is returned if the specified state is currently switched on for the item, 0 otherwise. .TP \fIpathName\fR \fBitem state set\fR \fIitemDesc\fR ?\fIlastItem\fR? \fIstateDescList\fR Every element of \fIstateDescList\fR must be the name of a dynamic state (see \fBSTATES\fR below), optionally preceded by a \fB~\fR or \fB!\fR character. Every state with a leading \fB!\fR will be switched off for the item described by \fIitemDesc\fR, every state with a leading \fB~\fR will be toggled, and every state without leading \fB!\fR or \fB~\fR will be switched on. If \fIlastItem\fR is specified, the state changes will be made for all items in the range between \fIitemDesc\fR and \fIlastItem\fR. If \fIlastItem\fR unspecified, then the state changes are made for all items described by \fIitemDesc\fR. .RE .TP \fIpathName\fR \fBitem style\fR \fIcommand\fR \fIitemDesc\fR ?\fIarg ...\fR? This command is used to manipulate the styles of an item. The exact behavior of the command depends on the \fIcommand\fR argument that follows the \fBstyle\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBitem style elements\fR \fIitemDesc\fR \fIcolumn\fR This command returns a list containing the names of elements which were configured by the \fBitem element configure\fR command for the item described by \fIitemDesc\fR in \fIcolumn\fR. If there is no style assigned to \fIcolumn\fR an error is returned. .TP \fIpathName\fR \fBitem style map\fR \fIitemDesc\fR \fIcolumn\fR \fIstyle\fR \fImap\fR Like the \fBitem style set\fR command, this command may be used to assign a style to a specific column of an item. Unlike \fBitem style set\fR, this command can transfer configuration values of elements in the current style to elements in the new style specified by \fIstyle\fR. \fIMap\fR must be a list of \fIelementOld\fR-\fIelementNew\fR pairs, where \fIelementOld\fR is an element in the current style, and \fIelementNew\fR is an element in the style specified by \fIstyle\fR. Both \fIelementOld\fR and \fIelementNew\fR must be of the same type (\fBbitmap\fR, \fBtext\fR etc). \fIItemDesc\fR may refer to multiple items and \fIcolumn\fR may refer to multiple columns. .TP \fIpathName\fR \fBitem style set\fR \fIitemDesc\fR ?\fIcolumn\fR? ?\fIstyle\fR? ?\fIcolumn style ...\fR? This command sets or retrieves the style assigned to one or more columns. If no \fIcolumn\fR is specified, this command returns a list containing the names of the styles set for all columns of the item described by \fIitemDesc\fR. If no \fIstyle\fR is specified, this command returns the name of the style set for the item described by \fIitemDesc\fR in \fIcolumn\fR. .sp If one or more \fIcolumn\fR-\fIstyle\fR pairs is specified, then the style in each \fIcolumn\fR is set to \fIstyle\fR. In this case \fIitemDesc\fR may refer to multiple items and each \fIcolumn\fR may refer to multiple columns. .RE .TP \fIpathName\fR \fBitem tag\fR \fIoption\fR ?\fIarg arg ...\fR? This command is used to manipulate tags on items. The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBitem tag\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBitem tag add\fR \fIitemDesc\fR \fItagList\fR Adds each tag in \fItagList\fR to the items specified by the \fBitem description\fR \fIitemDesc\fR. Duplicate tags are ignored. The list of tags for an item can also be changed via an item's \fB-tags\fR option. .TP \fIpathName\fR \fBitem tag expr\fR \fIitemDesc\fR \fItagExpr\fR Evaluates the tag expression \fItagExpr\fR against every item specified by the \fBitem description\fR \fIitemDesc\fR. The result is 1 if the tag expression evaluates to true for every item, 0 otherwise. .TP \fIpathName\fR \fBitem tag names\fR \fIitemDesc\fR Returns a list of tag names assigned to the items specified by the \fBitem description\fR \fIitemDesc\fR. The result is the union of any tags assigned to the items. .TP \fIpathName\fR \fBitem tag remove\fR \fIitemDesc\fR \fItagList\fR Removes each tag in \fItagList\fR from the items specified by the \fBitem description\fR \fIitemDesc\fR. It is not an error if any of the items do not use any of the tags. The list of tags for an item can also be changed via an item's \fB-tags\fR option. .RE .TP \fIpathName\fR \fBitem text\fR \fIitemDesc\fR ?\fIcolumn\fR? ?\fItext\fR? ?\fIcolumn text ...\fR? This command sets or retrieves the value of the -text option for the first text element in one or more columns. If no \fIcolumn\fR is specified, this command returns a list of values, one per column. If no \fItext\fR is specified, this command returns the value for \fIcolumn\fR. .sp If one or more \fIcolumn\fR-\fItext\fR pairs is specified, then the value of the -text option in each \fIcolumn\fR is set to \fItext\fR. In this case \fIitemDesc\fR may refer to multiple items and each \fIcolumn\fR may refer to multiple columns. .sp Note that this command is provided as a convenience. Use the \fBitem element configure\fR or \fBitem element cget\fR commands if you want to set or retrieve the value of the -text option for a specific text element. .TP \fIpathName\fR \fBitem toggle\fR \fIitemDesc\fR ?\fB-recurse\fR? Changes the \fBopen\fR state of the item(s) described by \fIitemDesc\fR. If the \fBopen\fR state is currently switched off, then this command does the same as the \fBitem expand\fR widget command; otherwise the same as the \fBitem collapse\fR widget command. If \fB-recurse\fR is specified, then the \fBopen\fR state of all descendants of the items described by \fIitemDesc\fR will also be toggled. .RE .TP \fIpathName\fR \fBmarquee\fR \fIoption\fR ?\fIarg ...\fR? This command is used to manipulate the marquee, a rectangular region of the treectrl widget optionally marked with a surrounding dotted line. One corner point of the marquee is fixed as long as the marquee is visible and called the anchor; the diagonally opposite corner is dragged with the mouse while resizing the marquee and simply called the corner. All coordinates handled by this widget command are treectrl coordinates, i.e. the \fBcanvasx\fR or \fBcanvasy\fR widget command should be used before any window coordinates can be used. The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBmarquee\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBmarquee anchor\fR ?\fIx y\fR? Returns a list containing the x and y coordinates of the anchor, if no additional arguments are specified. If two coordinates are specified, sets the anchor to the given coordinates \fIx\fR and \fIy\fR. .TP \fIpathName\fR \fBmarquee cget\fR \fIoption\fR This command returns the current value of the marquee option named \fIoption\fR. \fIOption\fR may have any of the values accepted by the \fBmarquee configure\fR widget command. .TP \fIpathName\fR \fBmarquee configure\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? This command is similar to the \fBconfigure\fR widget command except that it modifies the marquee options instead of modifying options for the overall treectrl widget. If no \fIoption\fR is specified, the command returns a list describing all of the available marquee options (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 marquee 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\fR-\fIvalue\fR pairs are specified, then the command modifies the given marquee option(s) to have the given value(s); in this case the command returns an empty string. .sp The following marquee options are supported: .RS .TP \fB\fB-visible\fR\fR \fIboolean\fR Specifies a boolean value which determines whether the dotted line surrounding the region of the marquee should currently be visible. .RE .TP \fIpathName\fR \fBmarquee coords\fR ?\fIx1 y1 x2 y2\fR? Returns a list containing the x and y coordinates of the anchor followed by the x and y coordinates of the corner, if no additional arguments are specified. If four coordinates are specified, sets the anchor to the given coordinates \fIx1\fR and \fIy1\fR and the corner to the coordinates \fIx2\fR and \fIy2\fR. .TP \fIpathName\fR \fBmarquee corner\fR ?\fIx y\fR? Returns a list containing the x and y coordinates of the corner, if no additional arguments are specified. If two coordinates are specified, sets the corner to the given coordinates \fIx\fR and \fIy\fR. .TP \fIpathName\fR \fBmarquee identify\fR Returns a list with information about any items intersecting the marquee. The format of the returned list is: .nf { {item {column element element ...} {column element element ...} ...} {item {column element element ...} {column element element ...} ...} ... } .fi There may be zero sublists following an item id if the marquee is in the button/line area of an item. There may be zero element names following a column id if the item-column has no style or if the marquee does not intersect any elements in that column. .RE .TP \fIpathName\fR \fBnotify\fR \fIoption\fR ?\fIarg ...\fR? Many Tk widgets communicate with the outside world via \fB-command\fR callbacks and/or virtual events. For example, the Text widget evaluates its \fB-yscrollcommand\fR when the view in the widget changes, and generates a <> virtual event when text is inserted or deleted. A treectrl widget replaces both methods of communication with its own event mechanism accessed through the \fBnotify\fR subcommands. .sp The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBnotify\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBnotify bind\fR ?\fIobject\fR? ?\fIpattern\fR? ?+??\fIscript\fR? This command associates Tcl scripts with events generated by a treectrl widget. If all three arguments are specified, \fBnotify bind\fR will arrange for \fIscript\fR (a Tcl script) to be evaluated whenever the event(s) specified by \fIpattern\fR are generated by this treectrl widget. If \fIscript\fR is prefixed with a "+", then it is appended to any existing binding for \fIpattern\fR; otherwise \fIscript\fR replaces any existing binding. If \fIscript\fR is an empty string then the current binding for \fIpattern\fR is destroyed, leaving \fIpattern\fR unbound. In all of the cases where a script argument is provided, \fBnotify bind\fR returns an empty string. .sp If \fIpattern\fR is specified without a \fIscript\fR, then the script currently bound to \fIpattern\fR is returned, or an empty string is returned if there is no binding for \fIpattern\fR. If neither \fIpattern\fR nor \fIscript\fR is specified, then the return value is a list whose elements are all the patterns for which there exist bindings for \fIobject\fR. .sp The \fIobject\fR argument determines which window(s) the binding applies to. If \fIobject\fR begins with a dot, as in .a.b.c, then it must be the path name for a window; otherwise it may be an arbitrary string. Like the regular \fBbind\fR command, bindings on window names are automatically removed if that window is destroyed. .TP \fIpathName\fR \fBnotify configure\fR \fIobject\fR \fIpattern\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? This command sets and retrieves options for bindings created by the \fBnotify bind\fR command. .sp If no \fIoption\fR is specified, the command returns a list with \fIoption\fR-\fIvalue\fR pairs describing all the available binding options for \fIpattern\fR on \fIobject\fR. If \fIoption\fR is specified with no \fIvalue\fR, then the command returns the current value of that option. If one or more \fIoption\fR-\fIvalue\fR pairs are specified, then the command modifies the given option(s) to have the given value(s) for the binding; in this case the command returns an empty string. .sp The following binding options are supported: .RS .TP \fB\fB-active\fR\fR \fIboolean\fR Specifies if the binding should be active. As long as this option is specified as false, a binding script will not be evaluated when the corresponding event is generated. .RE .TP \fIpathName\fR \fBnotify detailnames\fR \fIeventName\fR Returns a list containing the names of all details, which are installed for the event with the name \fIeventName\fR by means of the \fBnotify install\fR widget command or by the treectrl widget itself. .TP \fIpathName\fR \fBnotify eventnames\fR Returns a list containing the names of all events, which are installed by means of the \fBnotify install\fR widget command or by the treectrl widget itself. .TP \fIpathName\fR \fBnotify generate\fR \fIpattern\fR ?\fIcharMap\fR? ?\fIpercentsCommand\fR? This command causes the treectrl widget to generate an event. This command is typically used to generate dynamic events created by the \fBnotify install\fR command, but may be used to generate static events also. The event specified by \fIpattern\fR is generated, and any active binding scripts on the event are evaluated after undergoing %-substitution. If there are details defined for the event, \fIpattern\fR must describe an <\fIeventName\fR-\fIdetail\fR> pair, otherwise \fIpattern\fR should be <\fIeventName\fR>. .sp The optional \fIcharMap\fR is a list of \fIchar\fR-\fIvalue\fR pairs as in the form returned by \fBarray get\fR. Each \fIchar\fR has to be exactly one character. The \fIcharMap\fR is used in %-substitution. .sp If \fIpercentsCommand\fR is specified, then it will be used to perform %-substitution on any scripts bound to the event. If \fIpercentsCommand\fR is not specified and the event is dynamic, then the %-subtitution command passed to \fBnotify install\fR will be used if it was provided. If the event is static or no %-substitution command is available, then all %-substitution is done using \fIcharMap\fR only . See \fBnotify install\fR for a description of \fIpercentsCommand\fR. .TP \fIpathName\fR \fBnotify install\fR \fIpattern\fR ?\fIpercentsCommand\fR? This command installs a new event or detail specified by \fIpattern\fR. Events created by this command are called dynamic, whereas events created by the treectrl widget itself are called static. This command may be called to set or retrieve the \fIpercentsCommand\fR for an existing dynamic event. .sp The optional \fIpercentsCommand\fR is a list containing the name of a Tcl command, plus any optional arguments, to which five additional arguments will be appended. The command will be called to perform %-substitution on any scripts bound to the event specified by \fIpattern\fR (see \fBEVENTS AND SCRIPT SUBSTITUTIONS\fR). \fIPercentsCommand\fR should be defined as follows: .nf proc percentsCommand {?arg arg ...? char object event detail charMap} { switch -- $char { ... } return $value } .fi The optional \fIarg\fR arguments are part of the \fIpercentsCommand\fR list. \fIChar\fR is the %-character to be substituted. \fIObject\fR is the same as the argument to \fBnotify bind\fR. \fIEvent\fR and \fIdetail\fR specify the event. \fICharMap\fR is the same as the argument to \fBnotify generate\fR. \fIPercentsCommand\fR should return the value to replace the %-character by. If an error occurs evaluating \fIpercentsCommand\fR, the %-character is replaced by itself. .sp \fBnotify install\fR returns the current \fIpercentsCommand\fR for the event, or an error if the event is not dynamic. .TP \fIpathName\fR \fBnotify install detail\fR \fIeventName\fR \fIdetail\fR ?\fIpercentsCommand\fR? Deprecated. Use \fBnotify install\fR with a \fIpattern\fR of <\fIeventName\fR-\fIdetail\fR> instead. .TP \fIpathName\fR \fBnotify install event\fR \fIeventName\fR ?\fIpercentsCommand\fR? Deprecated. Use \fBnotify install\fR with a \fIpattern\fR of <\fIeventName\fR> instead. .TP \fIpathName\fR \fBnotify linkage\fR \fIpattern\fR Returns a string indicating whether the specified event or detail is created by means of the \fBnotify install\fR widget command (\fBdynamic\fR) or by the treectrl widget itself (\fBstatic\fR). .TP \fIpathName\fR \fBnotify linkage\fR \fIeventName\fR ?\fIdetail\fR? Deprecated. Use \fBnotify linkage\fR with a \fIpattern\fR of <\fIeventName\fR> or <\fIeventName\fR-\fIdetail\fR> instead. .TP \fIpathName\fR \fBnotify unbind\fR \fIobject\fR ?\fIpattern\fR? If no \fIpattern\fR is specified, all bindings on \fIobject\fR are removed. If \fIpattern\fR is specified, then the current binding for \fIpattern\fR is destroyed, leaving \fIpattern\fR unbound. .TP \fIpathName\fR \fBnotify uninstall\fR \fIpattern\fR If the event or detail specified by \fIpattern\fR is static (i.e. created by the treectrl widget itself), an error is generated. Otherwise the dynamic event or detail is removed. If an event name is specified without a detail, all details for that event are also removed. .TP \fIpathName\fR \fBnotify uninstall detail\fR \fIeventName\fR \fIdetail\fR Deprecated. Use \fBnotify uninstall\fR with a \fIpattern\fR of <\fIeventName\fR-\fIdetail\fR> instead. .TP \fIpathName\fR \fBnotify uninstall event\fR \fIeventName\fR Deprecated. Use \fBnotify uninstall\fR with a \fIpattern\fR of <\fIeventName\fR> instead. .RE .TP \fIpathName\fR \fBnumcolumns\fR Deprecated. Use the \fBcolumn count\fR command instead. .TP \fIpathName\fR \fBnumitems\fR Deprecated. Use the \fBitem count\fR command instead. .TP \fIpathName\fR \fBorphans\fR Returns a list containing the item ids of all items which have no parent. When an item is created, it has no parent by default, and can later become an orphan by means of the \fBitem remove\fR widget command. The root item is not returned. .TP \fIpathName\fR \fBrange\fR \fIfirst\fR \fIlast\fR Deprecated. Use the \fBitem range\fR command instead. .TP \fIpathName\fR \fBscan\fR \fIoption\fR \fIargs\fR This command is used to implement scanning on treectrls. It has two forms, depending on \fIoption\fR: .RS .TP \fIpathName\fR \fBscan mark\fR \fIx\fR \fIy\fR Records \fIx\fR and \fIy\fR and the treectrl's current view; used in conjunction with later \fBscan dragto\fR commands. Typically this command is associated with a mouse button press in the widget and \fIx\fR and \fIy\fR are the coordinates of the mouse. It returns an empty string. .TP \fIpathName\fR \fBscan dragto\fR \fIx\fR \fIy\fR ?\fIgain\fR? This command computes the difference between its \fIx\fR and \fIy\fR arguments (which are typically mouse coordinates) and the \fIx\fR and \fIy\fR arguments to the last \fBscan mark\fR command for the widget. It then adjusts the view by \fIgain\fR times the difference in coordinates, where \fIgain\fR defaults to 10. This command is typically associated with mouse motion events in the widget, to produce the effect of dragging the treectrl at high speed through its window. The return value is an empty string. .RE .TP \fIpathName\fR \fBstate\fR \fIoption\fR \fIargs\fR This command is used to manipulate the list of user-defined states, see section \fBSTATES\fR below. The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBstate\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBstate define\fR \fIstateName\fR Defines a new state with the name \fIstateName\fR, which must not be the name of an existing state. .TP \fIpathName\fR \fBstate linkage\fR \fIstateName\fR Returns a string indicating whether the specified state is user-defined by means of the \fBstate define\fR widget command (\fBdynamic\fR) or predefined by the treectrl widget itself (\fBstatic\fR). .TP \fIpathName\fR \fBstate names\fR Returns a list containing the names of all user-defined states. .TP \fIpathName\fR \fBstate undefine\fR ?\fIstateName ...\fR? Every \fIstateName\fR must be the name of a user-defined state. Removes this state from the list of user-defined states. .RE .TP \fIpathName\fR \fBsee\fR \fIitemDesc\fR Adjust the view in the treectrl so that the item described by \fIitemDesc\fR is visible. If the item is already visible then the command has no effect; otherwise the treectrl scrolls to bring the item into view, and the corresponding \fB\fR and/or \fB\fR events are generated. .TP \fIpathName\fR \fBselection\fR \fIoption\fR \fIargs\fR This command is used to adjust the selection within a treectrl. It has several forms, depending on \fIoption\fR: .RS .TP \fIpathName\fR \fBselection add\fR \fIfirst\fR ?\fIlast\fR? \fIFirst\fR and \fIlast\fR (if specified) must be valid \fBitem descriptions\fR. If both \fIfirst\fR and \fIlast\fR are specified, then they may refer to a single item only; in this case the command adds every unselected item in the range between \fIfirst\fR and \fIlast\fR, inclusive, to the selection without affecting the selected state of items outside that range. If only \fIfirst\fR is specified, then every unselected item specified by \fIfirst\fR is added to the selection. A \fB\fR event is generated if any items were added to the selection. .TP \fIpathName\fR \fBselection anchor\fR ?\fIitemDesc\fR? If \fIitemDesc\fR is specified, the selection anchor is set to the described item. The selection anchor is the end of the selection that is fixed while dragging out a selection with the mouse. The item description \fBanchor\fR may be used to refer to the anchor item. This command doesn't modify the selection state of any item. Returns the unique id of the selection anchor item. .TP \fIpathName\fR \fBselection clear\fR ?\fIfirst\fR? ?\fIlast\fR? \fIFirst\fR and \fIlast\fR (if specified) must be valid \fBitem descriptions\fR. If both \fIfirst\fR and \fIlast\fR are specified, then they may refer to a single item only; in this case any selected items between \fIfirst\fR and \fIlast\fR (inclusive) are removed from the selection without affecting the selected state of items outside that range. If only \fIfirst\fR is specified, then every selected item specified by \fIfirst\fR is removed from the selection. If neither \fIfirst\fR nor \fIlast\fR are specified, then all selected items are removed from the selection. A \fB\fR event is generated if any items were removed from the selection. .TP \fIpathName\fR \fBselection count\fR Returns an integer indicating the number of items in the treectrl that are currently selected. .TP \fIpathName\fR \fBselection get\fR ?\fIfirst\fR? ?\fIlast\fR? When no additional arguments are given, the result is an unsorted list containing the item ids of all of the items in the treectrl that are currently selected. If there are no items selected in the treectrl, then an empty string is returned. The optional arguments \fIfirst\fR and \fIlast\fR are treated as indices into the sorted list of selected items; these arguments allow in-place \fBlindex\fR and \fBlrange\fR operations on the selection. For example: .nf .t selection get 0 ; # return the first selected item .t selection get end ; # return the last selected item .t selection get 1 end-1 ; # return every selected item except the first and last .fi .TP \fIpathName\fR \fBselection includes\fR \fIitemDesc\fR Returns 1 if the item described by \fIitemDesc\fR is currently selected, 0 if it isn't. .TP \fIpathName\fR \fBselection modify\fR \fIselect\fR \fIdeselect\fR Both arguments \fIselect\fR and \fIdeselect\fR are a possibly-empty list of \fBitem descriptions\fR. Any unselected items in \fIselect\fR are added to the selection, and any selected items in \fIdeselect\fR are removed from the selection (except for those items which are also in \fIselect\fR). A \fB\fR event is generated if any items were selected or deselected. .RE .TP \fIpathName\fR \fBstyle\fR \fIoption\fR ?\fIelement\fR? ?\fIarg arg ...\fR? This command is used to manipulate styles, which can be thought of as a geometry manager for elements. The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBstyle\fR argument. The following forms of the command are supported: .RS .TP \fIpathName\fR \fBstyle cget\fR \fIstyle\fR \fIoption\fR This command returns the current value of the option named \fIoption\fR associated with the style given by \fIstyle\fR. \fIOption\fR may have any of the values accepted by the \fBstyle configure\fR widget command. .TP \fIpathName\fR \fBstyle configure\fR \fIstyle\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 style given by \fIstyle\fR instead of modifying options for the overall treectrl widget. If no \fIoption\fR is specified, the command returns a list describing all of the available options for \fIstyle\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\fR-\fIvalue\fR pairs are specified, then the command modifies the given option(s) to have the given value(s) in \fIstyle\fR; in this case the command returns an empty string. .sp The options of a style have effect on all elements managed by the style. The following options are supported: .RS .TP \fB\fB-orient\fR\fR \fIvarName\fR This option specifies which orientation should be used when laying out the elements associated with this style. Must be either \fBhorizontal\fR (the default) or \fBvertical\fR or an abbreviation of one of these. .RE .TP \fIpathName\fR \fBstyle create\fR \fIstyle\fR ?\fIoption value ...\fR? Create a new style in \fIpathName\fR with name \fIstyle\fR. After \fIstyle\fR there may be any number of \fIoption\fR-\fIvalue\fR pairs, each of which sets one of the configuration options for the style. These same \fIoption\fR-\fIvalue\fR pairs may be used in \fBstyle configure\fR widget commands to change the style's configuration. Returns the name of the new style. .TP \fIpathName\fR \fBstyle delete\fR ?\fIstyle ...\fR? Deletes each of the named styles and returns an empty string. If a style is deleted while it is still used to display one or more items, it is also removed from the style list of these items. .TP \fIpathName\fR \fBstyle elements\fR \fIstyle\fR ?\fIelementList\fR? Specifies the elements which should be layed out by this style. Each element of \fIelementList\fR must be the name of an element created by the widget command \fBelement create\fR. Duplicate names in \fIelementList\fR are ignored. An element which was specified in a former call of this command for \fIstyle\fR but is not included in \fIelementList\fR, will be deleted from the elements layed out by \fIstyle\fR. .sp If the \fIelementList\fR argument is not specified, a list is returned containing the currently defined elements of \fIstyle\fR. .TP \fIpathName\fR \fBstyle layout\fR \fIstyle\fR \fIelement\fR ?\fIoption\fR? ?\fIvalue\fR? ?\fIoption value ...\fR? This command is similar to the \fBconfigure\fR widget command except that it modifies options used by \fIstyle\fR for laying out \fIelement\fR instead of modifying options for the overall treectrl widget. If no \fIoption\fR is specified, the command returns a list with \fIoption\fR-\fIvalue\fR pairs describing all of the available options for the layout. If \fIoption\fR is specified with no \fIvalue\fR, then the command returns the value of the named option. If one or more \fIoption\fR-\fIvalue\fR pairs are specified, then the command modifies the given option(s) to have the given value(s) for the layout; in this case the command returns an empty string. .sp The options of a layout have effect on exactly the one element \fIelement\fR managed by \fIstyle\fR. The following options are supported: .RS .TP \fB\fB-detach\fR\fR \fIboolean\fR Specifies whether the element should be positioned by itself, i.e. independent from the other elements. .TP \fB\fB-draw\fR\fR \fIboolean\fR This is a \fBper-state\fR option that determines whether an element should be drawn. If the value of the option evaluates to false for a given item state, then the element is not drawn, although it still consumes space in the layout. .TP \fB\fB-expand\fR\fR \fIflags\fR This option allows the external padding around the element to increase when a style has more screen space than it needs. \fIFlags\fR is a string that contains zero or more of the characters \fBn\fR, \fBs\fR, \fBw\fR or \fBe\fR. Each letter refers to the padding on the top, bottom, left, or right that should be allowed to increase. This option is typically used to justify an element. .TP \fB\fB-iexpand\fR\fR \fIflags\fR This option allows the internal padding of the element and the display area of the element to increase when a style has more screen space than it needs. \fIFlags\fR is a string that contains zero or more of the characters \fBx\fR, \fBy\fR, \fBn\fR, \fBs\fR, \fBw\fR or \fBe\fR. For \fBn\fR, \fBs\fR, \fBw\fR and \fBe\fR, each letter refers to the padding on the top, bottom, left, or right that should be allowed to increase. For \fBx\fR and \fBy\fR, each letter refers to the horizontal and vertical screen space the element can display itself in (i.e., the space between the padding). Note that if the \fB-union\fR option is specified for this element, then the \fBx\fR and \fBy\fR flags have no effect, since the size of an element with \fB-union\fR layout is determined by the elements it surrounds. .TP \fB\fB-indent\fR\fR \fIboolean\fR Specifies whether the element should be positioned to the right of the button/line area in the tree column. This option is ignored unless the \fB-detach\fR option is true. .TP \fB\fB-ipadx\fR\fR \fIamount\fR .TP \fB\fB-ipady\fR\fR \fIamount\fR \fIAmount\fR specifies how much internal padding to leave on the left and right (for \fB-ipadx\fR) or top and bottom (for \fB-ipady\fR) side of the element. \fIAmount\fR may be a list of two values to specify padding for the two sides separately, it defaults to 0. .TP \fB\fB-minheight\fR\fR \fIpixels\fR .TP \fB\fB-height\fR\fR \fIpixels\fR .TP \fB\fB-maxheight\fR\fR \fIpixels\fR Specifies the minimum, fixed, and maximum height of the element. .TP \fB\fB-minwidth\fR\fR \fIpixels\fR .TP \fB\fB-width\fR\fR \fIpixels\fR .TP \fB\fB-maxwidth\fR\fR \fIpixels\fR Specifies the minimum, fixed, and maximum width of the element. .TP \fB\fB-padx\fR\fR \fIamount\fR .TP \fB\fB-pady\fR\fR \fIamount\fR \fIAmount\fR specifies how much external padding to leave on the left and right (for \fB-padx\fR) or top and bottom (for \fB-pady\fR) side of the element. \fIAmount\fR may be a list of two values to specify padding for the two sides separately, it defaults to 0. .TP \fB\fB-squeeze\fR\fR \fIflags\fR This option allows the display area of an element to decrease when a style has less space than it needs. \fIFlags\fR is a string that contains zero or more of the characters \fBx\fR or \fBy\fR. \fBx\fR allows display area to decrease horizontally, \fBy\fR allows display area to decrease vertically. This option is typically used for \fBtext\fR elements and will cause the text element to display an ellipsis (...) and/or wrap lines. .TP \fB\fB-sticky\fR\fR \fIflags\fR This option controls how the actual display information (image, text, etc) of an element is positioned (or stretched) within its display area. \fIFlags\fR is a string that contains zero or more of the characters \fBn\fR, \fBs\fR, \fBw\fR or \fBe\fR. Each letter refers to the top, bottom, left or right side of the display area that the display information should "stick" to. .TP \fB\fB-union\fR\fR \fIelementList\fR Specifies a list of other elements which this element will surround. The size of an element with \fB-union\fR layout is determined by the size and position of the elements in \fIelementList\fR. The \fB-ipadx\fR and \fB-ipady\fR options in this case refer to the distance of the edges of the display area of this element from those elements it surrounds. This option is typically used to display a selection rectangle around a piece of text. If none of the elements in \fIelementList\fR are visible, then the element is not displayed. .TP \fB\fB-visible\fR\fR \fIboolean\fR This is a \fBper-state\fR option that controls visibility of an element. If the value of the option evaluates to false for a given item state, then the element is not displayed and consumes no space in the layout. .RE .TP \fIpathName\fR \fBstyle names\fR Returns a list containing the names of all existing styles. .RE .TP \fIpathName\fR \fBtoggle\fR ?\fB-recurse\fR? ?\fIitemDesc ...\fR? Use \fBitem toggle\fR instead. .TP \fIpathName\fR \fBxview\fR ?\fIargs\fR? This command is used to query and change the horizontal position of the information displayed in the treectrl's window. It can take any of the following forms: .RS .TP \fIpathName\fR \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 tree's area is off-screen to the left, the middle 40% is visible in the window, and 40% of the tree is off-screen to the right. These are the same values passed to scrollbars via the \fB-xscrollcommand\fR option. .TP \fIpathName\fR \fBxview moveto\fR \fIfraction\fR Adjusts the view in the window so that \fIfraction\fR of the total width of the tree is off-screen to the left. \fIFraction\fR must be a fraction between 0 and 1. A \fB\fR event is generated. .TP \fIpathName\fR \fBxview scroll\fR \fInumber\fR \fIwhat\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 in units determined by the \fB-xscrollincrement\fR option (which may be zero, see the description of that option). If \fIwhat\fR is \fBpages\fR then the view adjusts in units of nine-tenths the window's width. If \fInumber\fR is negative then information farther to the left becomes visible; if it is positive then information farther to the right becomes visible. A \fB\fR event is generated. .RE .TP \fIpathName\fR \fByview\fR ?\fIargs\fR? This command is used to query and change the vertical position of the information displayed in the treectrl's window. It can take any of the following forms: .RS .TP \fIpathName\fR \fByview\fR Returns a list containing two elements. Each element is a real fraction between 0 and 1; together they describe the vertical span that is visible in the window. For example, if the first element is .6 and the second element is 1.0, the lowest 40% of the tree's area is visible in the window. These are the same values passed to scrollbars via the \fB-yscrollcommand\fR option. .TP \fIpathName\fR \fByview moveto\fR \fIfraction\fR Adjusts the view in the window so that \fIfraction\fR of the tree's area is off-screen to the top. \fIFraction\fR is a fraction between 0 and 1. A \fB\fR event is generated. .TP \fIpathName\fR \fByview scroll\fR \fInumber\fR \fIwhat\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 in units of the \fB-yscrollincrement\fR option (which may be zero, see the description of that option). If \fIwhat\fR is \fBpages\fR then the view adjusts in units of nine-tenths the window's height. If \fInumber\fR is negative then higher information becomes visible; if it is positive then lower information becomes visible. A \fB\fR event is generated. .RE .SH COLUMNS A treectrl widget is capable of displaying multiple columns next to each other. An item can be considered as a row, which reaches over all columns. .PP Columns in a treectrl may be specified in a number of ways. See \fBCOLUMN DESCRIPTION\fR below. .PP There is always one special column, the \fBtail\fR column, which fills all space to the right of the last ordinary column. This column has no number; it can only be specified by the keyword \fBtail\fR. .PP When a column configuration option is specified as \fBper-state\fR, the state names are \fBnormal\fR, \fBactive\fR, \fBpressed\fR or \fBup\fR, i.e. do not use item state names. .PP The following options are supported for columns: .TP \fB\fB-arrow\fR\fR \fIdirection\fR Indicates whether or not an arrow should be drawn in the column header. \fIDirection\fR must have one of the values \fBnone\fR (the default), \fBup\fR, or \fBdown\fR. .TP \fB\fB-arrowbitmap\fR\fR \fIbitmap\fR Specifies as a \fBper-state\fR option the bitmap to use to draw the arrow if this column's -arrow option is not \fBnone\fR. .TP \fB\fB-arrowimage\fR\fR \fIimage\fR Specifies as a \fBper-state\fR option the image to use to draw the arrow if this column's -arrow option is not \fBnone\fR. If an image is specified for a certain state, it overrides the -arrowbitmap option. .TP \fB\fB-arrowside\fR\fR \fIside\fR Indicates on which side of the bitmap/image/text the arrow should be drawn. \fISide\fR must be either \fBleft\fR or \fBright\fR (the default). .TP \fB\fB-arrowgravity\fR\fR \fIside\fR Indicates onto which side an arrow should be packed, if there is more space available for drawing the arrow then needed. \fISide\fR must be either \fBleft\fR (the default) or \fBright\fR. .TP \fB\fB-arrowpadx\fR\fR \fIamount\fR \fIAmount\fR specifies how much padding to leave on the left and right of the arrow. \fIAmount\fR may be a list of two values to specify padding for left and right separately; it defaults to 6. .TP \fB\fB-arrowpady\fR\fR \fIamount\fR \fIAmount\fR specifies how much padding to leave on the top and bottom of the arrow. \fIAmount\fR may be a list of two values to specify padding for top and bottom separately; it defaults to 0. .TP \fB\fB-bitmap\fR\fR \fIbitmap\fR Specifies the bitmap to display in the element to the left of the column title. .TP \fB\fB-background\fR\fR \fIcolor\fR Specifies as a \fBper-state\fR option the color to use for the background of the column header. .TP \fB\fB-borderwidth\fR\fR \fIsize\fR Specifies a non-negative value indicating the width of the 3-D border to draw around the outside of the column header (if such a border is being drawn; the \fB-relief\fR column option determines this). The value may have any of the forms acceptable to \fBTk_GetPixels\fR. .TP \fB\fB-button\fR\fR \fIboolean\fR Indicates whether or not the column header should be treated like a pushbutton. When this option is true, the default bindings track events in the header and generate a event when a event occurs in the header. See \fBDYNAMIC EVENTS\fR. .TP \fB\fB-expand\fR\fR \fIboolean\fR Indicates whether or not any extra horizontal space should be distributed to this column. This option has no effect if the \fB-width\fR option is set. .TP \fB\fB-font\fR\fR \fIfontName\fR Specifies the font to use for the column title inside the column header. .TP \fB\fB-image\fR\fR \fIimage\fR Specifies the image to display in the element to the left of the column title. This option overrides the \fB-bitmap\fR column option. .TP \fB\fB-imagepadx\fR\fR \fIamount\fR \fIAmount\fR specifies how much padding to leave on the left and right of the image (or bitmap). \fIAmount\fR may be a list of two values to specify padding for left and right separately; it defaults to 6. .TP \fB\fB-imagepady\fR\fR \fIamount\fR \fIAmount\fR specifies how much padding to leave on the top and bottom of the image (or bitmap). \fIAmount\fR may be a list of two values to specify padding for top and bottom separately; it defaults to 0. .TP \fB\fB-itembackground\fR\fR \fIcolorList\fR Specifies a list of zero or more colors, which are used as alternating background colors for items in this column. See also the \fB-backgroundmode\fR widget option for more on this. .TP \fB\fB-itemjustify\fR\fR \fIjustification\fR This option determines how the item styles in this column line up with each other. Must be one of \fBleft\fR, \fBcenter\fR, or \fBright\fR. The default value is an empty string (for compatibility with older versions), in which case the column option \fB-justify\fR is used to align item styles in this column. .TP \fB\fB-itemstyle\fR\fR \fIstyle\fR \fIStyle\fR is the name of a style that should be set in this column for newly-created items. .TP \fB\fB-justify\fR\fR \fIjustification\fR This option determines how the image and text in the column header are positioned. It also affects the position of item styles in this column unless the column option \fB-itemjustify\fR is specified. Must be one of \fBleft\fR (the default), \fBcenter\fR, or \fBright\fR. .TP \fB\fB-lock\fR\fR \fIlock\fR This option allows a column to stick to the left or right edge of the window. A locked column scrolls vertically but not horizontally. Must be one of \fBnone\fR (the default), \fBleft\fR, or \fBright\fR. .TP \fB\fB-maxwidth\fR\fR \fIsize\fR Specifies the maximum size, in screen units, that will be permitted for this column. If \fIsize\fR is an empty string, then there is no limit on the maximum size of the column. This option has no effect if the \fB-width\fR option is set. .TP \fB\fB-minwidth\fR\fR \fIsize\fR Specifies the minimum size, in screen units, that will be permitted for this column. If \fIsize\fR is an empty string, then the minimum size of the column is zero. This option has no effect if the \fB-width\fR option is set. .TP \fB\fB-resize\fR\fR \fIboolean\fR Specifies a boolean value that indicates whether the user should be allowed to resize the column by dragging the edge of the column's header. Default is true. .TP \fB\fB-squeeze\fR\fR \fIboolean\fR Specifies a boolean value that indicates whether or not the column should shrink when the content width of the treectrl is less than the total needed width of all visible columns. Defaults to false, which means the column will not get smaller than its needed width. The column will not get smaller than the value of its \fB-minwidth\fR option, if specified. This option has no effect if the \fB-width\fR option is set. .TP \fB\fB-state\fR\fR \fIstate\fR Specifies one of three states for the column header: \fBnormal\fR, \fBactive\fR, or \fBpressed\fR. The active state is used when the mouse is over the header. The pressed state is used when the mouse button is pressed in the header. .TP \fB\fB-stepwidth\fR\fR \fIsize\fR Deprecated. Use the treectrl's \fB-itemwidthmultiple\fR option instead. .TP \fB\fB-tags\fR\fR \fItagList\fR \fITagList\fR is a list of tag names that can be used to identify the column. See also the \fBcolumn tag\fR command. .TP \fB\fB-text\fR\fR \fItext\fR Specifies a text string to be displayed as the column title. .TP \fB\fB-textcolor\fR\fR \fIcolor\fR Specifies a color, which should be used as foreground color to display the column title. .TP \fB\fB-textlines\fR\fR \fIcount\fR Specifies the maximum number of lines of text to display in the column title. If this value is zero, the number of lines displayed is determined by any newline characters and the effects of wrapping when the column width is less than needed. The default is 1. Note: Under OSX/Aqua this value is always set to 1 when the treectrl's \fB-usetheme\fR option is true, because the Appearance Manager uses a fixed height for the column header; there is only room for a single line of text. .TP \fB\fB-textpadx\fR\fR \fIamount\fR \fIAmount\fR specifies how much padding to leave on the left and right of the text. \fIAmount\fR may be a list of two values to specify padding for left and right separately; it defaults to 6. .TP \fB\fB-textpady\fR\fR \fIamount\fR \fIAmount\fR specifies how much padding to leave on the top and bottom of the text. \fIAmount\fR may be a list of two values to specify padding for top and bottom separately; it defaults to 0. .TP \fB\fB-uniform\fR\fR \fIgroup\fR When a non-empty value is supplied, this option places the column in a \fIuniform group\fR with other columns that have the same value for \fB-uniform\fR. The space for columns belonging to a uniform group is allocated so that their sizes are always in strict proportion to their \fB-weight\fR values. This option is based on the grid geometry manager. .TP \fB\fB-visible\fR\fR \fIboolean\fR Indicates whether or not the column should be displayed. .TP \fB\fB-weight\fR\fR \fIinteger\fR Sets the relative weight for apportioning any extra space among columns. A weight of zero (0) indicates the column will not deviate from its requested size. A column whose weight is two will grow at twice the rate as a column of weight one when extra space is allocated to columns. This option is based on the grid geometry manager. .TP \fB\fB-width\fR\fR \fIsize\fR Specifies a fixed width for the column. If this value is an empty string, then the column width is calculated as the maximum of: a) the width requested by items; b) the width requested by the column's header; and c) the column's \fB-minwidth\fR option. This calculated width is also affected by the \fB-expand\fR, \fB-squeeze\fR, \fB-uniform\fR and \fB-weight\fR options. In any case, the calculated width will not be greater than the \fB-maxwidth\fR option, if specified. .TP \fB\fB-widthhack\fR\fR \fIboolean\fR Deprecated. Use the treectrl's \fB-itemwidthequal\fR option instead. .SH "COLUMN DESCRIPTION" Many of the commands and options for a treectrl take as an argument a description of which column to operate on. See the \fBEXAMPLES\fR section for examples. The initial part of a column description must begin with one of the following terms: .TP \fIid\fR Specifies the unique column identifier, where \fIid\fR should be the return value of a prior call of the \fBcolumn create\fR widget command. See also the \fB-columnprefix\fR option. .TP \fIQUALIFIERS\fR Specifies a list of qualifiers. This gives the same result as \fBall\fR followed by \fIQUALIFIERS\fR; i.e., every column is tested for a match. .TP \fItagExpr\fR \fIQUALIFIERS\fR \fITagExpr\fR is a tag expression (see \fBITEM AND COLUMN TAGS\fR) against which every column's tags are tested for a match. This keyword cannot be followed by any modifiers unless a single column is matched. You may run into trouble if \fItagExpr\fR looks like a column id or other keyword; also, \fItagExpr\fR must look like a single list element since column descriptions are properly-formed lists. To be safe you may want to use the \fBtag\fR qualifier followed by \fItagExpr\fR. .TP \fBall\fR \fIQUALIFIERS\fR Indicates every column, including the tail column if the command allows it, which match \fIQUALIFIERS\fR. .TP \fBfirst\fR \fIQUALIFIERS\fR Indicates the leftmost column of the treectrl which matches \fIQUALIFIERS\fR. .TP \fBend\fR \fIQUALIFIERS\fR .TP \fBlast\fR \fIQUALIFIERS\fR Indicates the rightmost column of the treectrl (but not the tail column) which matches \fIQUALIFIERS\fR. .TP \fBlist\fR \fIcolumnDescs\fR \fIColumnDescs\fR is a list (a single argument, i.e. "list {a b c}" not "list a b c") of other column descriptions. This keyword cannot be followed by any modifiers unless a single column is matched. .TP \fBorder\fR \fIn\fR \fIQUALIFIERS\fR Indicates the \fIn\fRth column in the list of columns as returned by the \fBcolumn order\fR command. .TP \fBrange\fR \fIfirst last\fR \fIQUALIFIERS\fR \fIFirst\fR and \fIlast\fR specify a range of columns. This keyword cannot be followed by any modifiers unless a single column is specified. .TP \fBtail\fR Indicates the ever-present tail column of the treectrl. .TP \fBtree\fR Indicates the column specified by the -treecolumn option of the treectrl. .PP The initial part of the column description (matching any of the values above) may be followed by one or more \fImodifier\fRs. A modifier changes the column used relative to the description up to this point. It may be specified in any of the following forms: .TP \fBnext\fR \fIQUALIFIERS\fR Use the column to the right matching \fIQUALIFIERS\fR. .TP \fBprev\fR \fIQUALIFIERS\fR Use the column to the left matching \fIQUALIFIERS\fR. The word \fIQUALIFIERS\fR above represents a sequence of zero or more of the following terms that changes which column is chosen: .TP \fBstate\fR \fIstateList\fR \fIStateList\fR is a list of column state names. Only columns that have the given states set (or unset if the '!' prefix is used) are considered. .TP \fBtag\fR \fItagExpr\fR \fITagExpr\fR is a tag expression (see \fBITEM AND COLUMN TAGS\fR) against which a column's tags are tested for a match. .TP \fB!tail\fR When this qualifier is given, the tail column is not matched. .TP \fBvisible\fR When this qualifier is given, only columns whose \fB-visible\fR option is TRUE are considered. .TP \fB!visible\fR When this qualifier is given, only columns whose \fB-visible\fR option is FALSE are considered. .SH STATES For every item a set of boolean states is managed. These states play an integral role in the appearance of each item. The following states are predefined for every item: .TP \fBactive\fR At all times this state is set for exactly one item. The active item is used with keyboard navigation. When the treectrl widget is created or when the active item is deleted, the root item will become the active item. This state can be modified by means of the widget command \fBactivate\fR. .TP \fBenabled\fR This state is set for every item when it is created. Disabled items cannot be selected and are ignored by the default bindings when navigating via the keyboard. This state can be modified by means of the widget command \fBitem enabled\fR. .TP \fBfocus\fR This state is set for every item, if the treectrl widget currently has the focus. It cannot be modified by means of a widget command, but is maintained in reaction to the and events. .TP \fBopen\fR If this state is switched on, the descendants of the item are displayed - the item is expanded. If this state is switched off, the descendants of the item are not displayed - the item is collapsed. For a new item this state is switched on by default. This state can be modified by means of the widget commands \fBitem expand\fR, \fBitem collapse\fR, or \fBitem toggle\fR. .TP \fBselected\fR This state is set for every item included in the selection. It can be modified by means of the widget command \fBselection\fR. .PP By means of the \fBstate define\fR widget command up to 27 additional states can be defined. .SH "PER-STATE OPTIONS" The visual appearance of an item can change depending on the state the item is in, such as being the active item, being included in the selection, being collapsed, or some combination of those or other states. When a configuration option is described as \fIper-state\fR, it means the option describes a value which varies depending on the state of the item. If a per-state option is specified as a single value, the value is used for all states. Otherwise the per-state option must be specified as an even-numbered list. For example, to use the font "Times 12 bold" in a \fBtext\fR element regardless of the item state you can write: .nf $T element configure MyTextElement -font {{Times 12 bold}} .fi However, to use a different font when the item is selected you could write: .nf $T element configure MyTextElement -font {{Courier 10} selected {Times 12 bold} {}} .fi In the example above, the -font option reads "value stateList value stateList". If \fIstateList\fR is an empty list, the preceding \fIvalue\fR is used regardless of the item state. A non-empty stateList specifies a list of states which must be set for the item in order to use the preceding value. Each stateList can also include state names preceded by a ! sign, indicating the state must *not* be set for the item. For example: .nf $T element configure MyRectElement -fill {blue {selected focus} gray {selected !focus}} .fi In the example above, the \fBrect\fR element is filled with blue when the treectrl has the focus and the item is selected. If the treectrl does not have the focus, the example specifies that gray should be used for selected items. Also note that if the item is not selected, no color is specified for the -fill option. .PP Each value-stateList pair is checked in order from left to right. The value associated with the first stateList that matches the current item state is used. So stateLists should be listed from most-specific to least-specific. .nf $T element configure MyRectElement -fill {gray {selected} blue {selected focus}} .fi Written this way, gray will always be used for selected items since it appears first, and blue will never be used for selected items regardless of the focus. .PP A value followed by an empty stateList should always be last since it will be chosen regardless of the item's state. .SH ELEMENTS Elements are the smallest building blocks which are handled by a treectrl widget. One or more elements together can be combined to a style, which can be considered as a blueprint for an item. An element can be of type \fBbitmap\fR, \fBborder\fR, \fBimage\fR, \fBrect\fR, \fBtext\fR or \fBwindow\fR. For each element type there is a section below describing the options which can modify an element of that type. .PP All of the element configuration options described below are unspecified by default, meaning that no value whatsoever has been given to the option. It may seem strange to you that a boolean option would be unspecified instead of simply "true" or "false". The reason for this is that when an element displayed by an item has no value specified for an option, the element refers to the master element created by the \fBelement create\fR command for a value for that option. This allows items which are displaying a certain element to be redisplayed when the master element's options change. The \fBitem element configure\fR command can be used to override the master element's configuration options for a specific item. .SH "BITMAP ELEMENT" An element of type \fBbitmap\fR can be used to display a bitmap in an item. The following options are supported for bitmap elements: .TP \fB\fB-background\fR\fR \fIcolor\fR Specifies as a \fBper-state\fR option the color to use for each of the bitmap's '0' valued pixels. If the value for a certain state is an empty string (the default), the bitmap is drawn transparent. .TP \fB\fB-bitmap\fR\fR \fIbitmap\fR Specifies as a \fBper-state\fR option the bitmap to display in the element. .TP \fB\fB-draw\fR\fR \fIboolean\fR Deprecated; use the style layout option \fB-draw\fR instead. Specifies as a \fBper-state\fR option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn. .TP \fB\fB-foreground\fR\fR \fIcolor\fR Specifies as a \fBper-state\fR option the color to use for each of the bitmap's '1' valued pixels. If the value for a certain state is an empty string (the default), the bitmap's foreground color is black. .SH "BORDER ELEMENT" An element of type \fBborder\fR can be used to display a 3D border in an item. The following options are supported for border elements: .TP \fB\fB-background\fR\fR \fIcolor\fR Specifies as a \fBper-state\fR option the color to use for the background of the border. If the value for a certain state is an empty string (the default), the element will not be drawn. .TP \fB\fB-draw\fR\fR \fIboolean\fR Deprecated; use the style layout option \fB-draw\fR instead. Specifies as a \fBper-state\fR option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn. .TP \fB\fB-filled\fR\fR \fIboolean\fR Specifies whether the interior of the border should be filled with the background color. If this option is unspecified (the default), it it treated as false which means that only the edges of the border will be drawn. .TP \fB\fB-height\fR\fR \fIsize\fR Specifies the height of the border. If this value is unspecified (the default), the border will be exactly as tall as its display area as determined by the style layout options. .TP \fB\fB-relief\fR\fR \fIrelief\fR Specifies as a \fBper-state\fR option the relief of the border. If the value for a certain state is an empty string (the default), it is treated as flat. For acceptable values see the description of the \fB-relief\fR option in the \fBoptions\fR manual page. .TP \fB\fB-thickness\fR\fR \fIthickness\fR Specifies the thickness of the edges of the border. .TP \fB\fB-width\fR\fR \fIsize\fR Specifies the width of the border. If this value is unspecified (the default), the border will be exactly as wide as its display area as determined by the style layout options. .SH "IMAGE ELEMENT" An element of type \fBimage\fR can be used to display an image in an item. The following options are supported for image elements: .TP \fB\fB-draw\fR\fR \fIboolean\fR Deprecated; use the style layout option \fB-draw\fR instead. Specifies as a \fBper-state\fR option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn. .TP \fB\fB-height\fR\fR \fIsize\fR Specifies the requested height of the display area for this element. If unspecified (the default), the element requests a height equal to the height of the image, or zero if there is no image. .TP \fB\fB-image\fR\fR \fIimage\fR Specifies as a \fBper-state\fR option the image to display in the element. .TP \fB\fB-width\fR\fR \fIsize\fR Specifies the requested width of the display area for this element. If unspecified (the default), the element requests a width equal to the width of the image, or zero if there is no image. .SH "RECTANGLE ELEMENT" An element of type \fBrect\fR can be used to display a rectangle in an item. The following options are supported for rectangle elements: .TP \fB\fB-draw\fR\fR \fIboolean\fR Deprecated; use the style layout option \fB-draw\fR instead. Specifies as a \fBper-state\fR option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn. .TP \fB\fB-fill\fR\fR \fIcolor\fR Specifies as a \fBper-state\fR option the color to be used to fill the rectangle's area. If the color for a certain state is an empty string (the default), then the rectangle will not be filled (but the outline may still be drawn). .TP \fB\fB-height\fR\fR \fIsize\fR Specifies the height of the rectangle. If this value is unspecified (the default), the rectangle will be exactly as tall as its display area as determined by the style layout options. .TP \fB\fB-open\fR\fR \fIopen\fR This option may be used to get an incomplete drawing of the outline. \fIOpen\fR is a string that contains zero or more of the characters \fBn\fR, \fBs\fR, \fBe\fR or \fBw\fR. Each letter refers to a side (north, south, east, or west) that the outline will not be drawn. The default is the empty string, which causes the outline to be drawn completely. .TP \fB\fB-outline\fR\fR \fIcolor\fR Specifies as a \fBper-state\fR option the color to be used to draw the outline of the rectangle. If the color for a certain state is an empty string (the default), then no outline is drawn for the rectangle. .TP \fB\fB-outlinewidth\fR\fR \fIoutlineWidth\fR Specifies the width of the outline to be drawn around the rectangle's region. \fIoutlineWidth\fR may be in any of the forms acceptable to \fBTk_GetPixels\fR. If this option is specified as an empty string (the default), then no outline is drawn. .TP \fB\fB-showfocus\fR\fR \fIboolean\fR Specifies a boolean value indicating whether a "focus ring" should be drawn around the rectangle, if the item containing the rectangle is the active item and the treectrl widget currently has the focus. If this option is specified as an empty string (the default), then a focus rectangle is not drawn. .TP \fB\fB-width\fR\fR \fIsize\fR Specifies the width of the rectangle. If this value is unspecified (the default), the rectangle will be exactly as wide as its display area as determined by the style layout options. .SH "TEXT ELEMENT" An element of type \fBtext\fR can be used to display a text in an item. The following options are supported for text elements: .TP \fB\fB-draw\fR\fR \fIboolean\fR Deprecated; use the style layout option \fB-draw\fR instead. Specifies as a \fBper-state\fR option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn. .TP \fB\fB-data\fR\fR \fIdata\fR Specifies a value that together with the \fB-datatype\fR and \fB-format\fR options will be displayed as text. .TP \fB\fB-datatype\fR\fR \fIdataType\fR Specifies the type of information in the \fB-data\fR option. Acceptable values are \fBdouble\fR, \fBinteger\fR, \fBlong\fR, \fBstring\fR, or \fBtime\fR. .TP \fB\fB-fill\fR\fR \fIcolor\fR Specifies as a \fBper-state\fR option the foreground color to use when displaying the text. If the color for a certain state is an empty string (the default), then the text will be displayed using the color specified by the treectrl's \fB-foreground\fR option. .TP \fB\fB-format\fR\fR \fIformatString\fR This option specifies the format string used to display the value of the \fB-data\fR option. If \fB-datatype\fR is \fBtime\fR, \fIformatString\fR should be a valid format string for the Tcl \fBclock\fR command. For all other \fB-datatype\fR values \fIformatString\fR should be a valid format string for the Tcl \fBformat\fR command. If this value is unspecified the following defaults are used: for -datatype double "%g", for -datatype integer "%d", for -datatype long "%ld", for -datatype string "%s", and for -datatype time the default format string of the Tcl \fBclock\fR command. .TP \fB\fB-font\fR\fR \fIfont\fR Specifies as a \fBper-state\fR option the font to use when displaying the text. If the font for a certain state is an empty string, the text is displayed using the font specified by the treectrl's \fB-font\fR option. .TP \fB\fB-justify\fR\fR \fIhow\fR Specifies how to justify the text when multiple lines are displayed. \fIHow\fR must be one of the values \fBleft\fR, \fBright\fR, or \fBcenter\fR. If this option is specified as an empty string (the default), \fBleft\fR is used. .TP \fB\fB-lines\fR\fR \fIlineCount\fR Specifies the maximum number of lines to display. If more than \fIlineCount\fR lines would be displayed, the last line will be truncated with an ellipsis at the right. If this option is specified as zero or an empty string (the default), there is no limit to the number of lines displayed. .TP \fB\fB-text\fR\fR \fIstring\fR \fIString\fR specifies a string to be displayed by the element. \fIString\fR may contain newline characters in which case multiple lines of text will be displayed. If this option is specified, the \fB-data\fR, \fB-datatype\fR, \fB-format\fR, and \fB-textvariable\fR options are ignored. .TP \fB\fB-textvariable\fR\fR \fIvarName\fR Specifies the name of a variable. The value of the variable is a string to be displayed by the element; if the variable value changes then the element will automatically update itself to display the new value. If this option is specified, the \fB-data\fR, \fB-datatype\fR, and \fB-format\fR options are ignored. .TP \fB\fB-underline\fR\fR \fIcharIndex\fR Specifies the integer index of a character to underline. 0 corresponds to the first character. If \fIcharIndex\fR is unspecified (the default), less than zero or greater than the index of the last displayed character, the underline is not drawn. .TP \fB\fB-width\fR\fR \fIsize\fR Specifies the maximum line length in any of the forms acceptable to \fBTk_GetPixels\fR. For text to wrap lines the value of the \fB-width\fR option must be less than the needed width of the text, or the display area for this element must be less than the needed width of the text. For the display area to be less than the needed width of the text, one of the style layout options \fB-maxwidth\fR, \fB-width\fR or \fB-squeeze\fR must be used. .TP \fB\fB-wrap\fR\fR \fImode\fR \fIMode\fR specifies how to handle lines in the text that are longer than the maximum line length. Acceptable values are \fBnone\fR, \fBchar\fR or \fBword\fR. If this option is unspecified (the default), \fBword\fR is used. See the \fB-width\fR option for a description of how the maximum line length is determined. .SH "WINDOW ELEMENT" An element of type \fBwindow\fR can be used to display a Tk window in an item. The following options are supported for window elements: .TP \fB\fB-clip\fR\fR \fIboolean\fR Specifies whether the associated Tk window is a borderless frame which should be used to clip its child window so it doesn't overlap the header, borders, or other items or columns. When this option is true, the treectrl manages the geometry of both the \fB-window\fR widget and its first child widget; in this case the \fB-window\fR widget (which should be a borderless frame) is kept sized and positioned so that it is never out-of-bounds. .TP \fB\fB-destroy\fR\fR \fIboolean\fR Specifies whether the associated Tk window should be destroyed when the element is deleted. The element is deleted when the item containing the element is deleted, when the column containing the element is deleted, or when the style assigned to the item's column is changed. If this option is unspecified (the default), it is treated as false and the Tk window will not be destroyed. .TP \fB\fB-draw\fR\fR \fIboolean\fR Deprecated; use the style layout option \fB-draw\fR instead. Specifies as a \fBper-state\fR option whether to draw the element. If the value for a certain state is an empty string (the default), it is treated as true and the element will be drawn. .TP \fB\fB-window\fR\fR \fIpathName\fR Specifies the window to associate with this element. The window specified by \fIpathName\fR must either be a child of the treectrl widget or a child of some ancestor of the treectrl widget. \fIPathName\fR may not refer to a top-level window. This option cannot be specified by the \fBelement create\fR or \fBelement configure\fR commands, only by the \fBitem element configure\fR command; i.e., the element must be associated with a particular item. .SH "ITEM DESCRIPTION" Many of the commands for a treectrl take as an argument a description of which items to operate on. An item description is a properly-formed tcl list of keywords and arguments. The first word of an item description must be one of the following: .TP \fIid\fR Specifies the unique item identifier, where \fIid\fR should be the return value of a prior call of the \fBitem create\fR widget command, or \fB0\fR to specify the ever-present root item. See also the \fB-itemprefix\fR option. .TP \fIQUALIFIERS\fR Specifies a list of qualifiers. This gives the same result as \fBall\fR followed by \fIQUALIFIERS\fR; i.e., every item is tested for a match. .TP \fItagExpr\fR \fIQUALIFIERS\fR \fITagExpr\fR is a tag expression (see \fBITEM AND COLUMN TAGS\fR) against which every item's tags are tested for a match. This keyword cannot be followed by any modifiers unless a single item is matched. You may run into trouble if \fItagExpr\fR looks like an item id or other keyword; also, \fItagExpr\fR must look like a single list element since item descriptions are properly-formed lists. To be safe you may want to use the \fBtag\fR qualifier followed by \fItagExpr\fR. .TP \fBactive\fR Indicates the item that is currently active, i.e. normally the item specified as argument of the last successful \fBactivate\fR widget command, or the root item if no such call happened yet. .TP \fBanchor\fR Indicates the anchor item of the selection, i.e. normally the item specified as argument of the last successful \fBselection anchor\fR widget command, or the root item if no such call happened yet. .TP \fBall\fR \fIQUALIFIERS\fR Indicates every item including orphans which match \fIQUALIFIERS\fR. This keyword cannot be followed by any modifiers unless a single item is matched. .TP \fBfirst\fR \fIQUALIFIERS\fR Indicates the first item of the treectrl (the root item), or the first item matching \fIQUALIFIERS\fR. .TP \fBend\fR \fIQUALIFIERS\fR .TP \fBlast\fR \fIQUALIFIERS\fR Indicates the last item which matches \fIQUALIFIERS\fR. .TP \fBlist\fR \fIitemDescs\fR \fIItemDescs\fR is a list (a single argument, i.e. "list {a b c}" not "list a b c") of other item descriptions. This keyword cannot be followed by any modifiers unless a single item is matched. .TP \fBnearest\fR \fIx y\fR Indicates the item nearest to the point given by \fIx\fR and \fIy\fR. .TP \fBrnc\fR \fIrow column\fR Indicates the item in the given \fIrow\fR and \fIcolumn\fR. The row and column corresponds to the on-screen arrangement of items as determined by the -orient and -wrap options. You can memorize \fBrnc\fR as an abbreviation of "row 'n' column". .TP \fBrange\fR \fIfirst last\fR \fIQUALIFIERS\fR \fIFirst\fR and \fIlast\fR specify a range of items. This keyword cannot be followed by any modifiers unless a single item is matched. .TP \fBroot\fR Indicates the root item of the treectrl. .PP The initial part of the item description (matching any of the values above) may be followed by one or more \fImodifier\fRs. A modifier changes the item used relative to the description up to this point. It may be specified in any of the following forms: .TP \fBabove\fR Use the item one row above in this column. .TP \fBancestors\fR \fIQUALIFIERS\fR Use the ancestors of the item (like \fBitem ancestors\fR but QUALIFIERS may change which ancestors match). This keyword cannot be followed by any modifiers. .TP \fBbelow\fR Use the item one row below in this column. .TP \fBbottom\fR Use the item in the last row of this column. .TP \fBchild\fR \fIn\fR \fIQUALIFIERS\fR Use the \fIn\fRth child of the item. .TP \fBchildren\fR \fIQUALIFIERS\fR Use the children of the item (like \fBitem children\fR but QUALIFIERS may change which children match). This keyword cannot be followed by any modifiers. .TP \fBdescendants\fR \fIQUALIFIERS\fR Use the descendants of the item (like \fBitem descendants\fR but QUALIFIERS may change which descendants match). This keyword cannot be followed by any modifiers. .TP \fBfirstchild\fR \fIQUALIFIERS\fR Use the first child of the item. .TP \fBlastchild\fR \fIQUALIFIERS\fR Use the last child of the item. .TP \fBleft\fR Use the item one column to the left in the same row. .TP \fBleftmost\fR Use the item of the first column in the same row. .TP \fBnext\fR \fIQUALIFIERS\fR Use the next item, which is the first item from the following list: the first child, the next sibling or the next sibling of the nearest ancestor which has one. .TP \fBnextsibling\fR \fIQUALIFIERS\fR Use the next sibling of the item. .TP \fBparent\fR Use the parent of the item. .TP \fBprev\fR \fIQUALIFIERS\fR Use the last child of the previous sibling, or the parent if there is no previous sibling. .TP \fBprevsibling\fR \fIQUALIFIERS\fR Use the previous sibling of the item. .TP \fBright\fR Use the item one column to the right in the same row. .TP \fBrightmost\fR Use the item of the last column in the same row. .TP \fBsibling\fR \fIn\fR \fIQUALIFIERS\fR Use the \fIn\fRth child of the item's parent. .TP \fBtop\fR Use the item in the first row of this column. The word \fIQUALIFIERS\fR above represents a series of zero or more of the following terms that changes which item is chosen: .TP \fBdepth\fR \fIdepth\fR Matches items whose depth (as returned by the \fBdepth\fR command) is equal to \fIdepth\fR. .TP \fBstate\fR \fIstateList\fR \fIStateList\fR is a list of item state names (static and dynamic, see \fBSTATES\fR). Only items that have the given states set (or unset if the '!' prefix is used) are considered. .TP \fBtag\fR \fItagExpr\fR \fITagExpr\fR is a tag expression (see \fBITEM AND COLUMN TAGS\fR) against which an item's tags are tested for a match. .TP \fBvisible\fR When this qualifier is given, only items that are displayed are considered. .TP \fB!visible\fR When this qualifier is given, only items that are *not* displayed are considered. To get the first item in the list that is enabled: .nf $T item id "first state enabled" .fi To get the ancestors that are not open of the last item in the list: .nf $T item id "last ancestors state !open" .fi To get the visible descendants of the root item: .nf $T item id "root descendants visible" .fi To get the every hidden item with tag "a" or "b": .nf $T item id "all !visible tag a||b" $T item id "!visible tag a||b" $T item id "tag a||b !visible" $T item id "a||b !visible" .fi .SH "EVENTS AND SCRIPT SUBSTITUTIONS" The \fIscript\fR argument to \fBnotify bind\fR is a Tcl script, which will be evaluated whenever the given event is generated. \fIScript\fR will be executed in the same interpreter that the \fBnotify bind\fR command was executed in, and it will run at global level (only global variables will be accessible). If \fIscript\fR contains any \fB%\fR characters, then the script will not be evaluated directly. Instead, a new script will be generated by replacing each \fB%\fR, and the character following it, with information from the current event. Unlike the regular Tk \fBbind\fR mechanism, each event generated by a treectrl widget has its own set of %-substitutions. .PP The following %-substitutions are valid for all static events: .TP \fB%%\fR Replaced with a single % .TP \fB%d\fR The detail name .TP \fB%e\fR The event name .TP \fB%P\fR The pattern, either or .TP \fB%W\fR The object argument to the \fBnotify bind\fR command .TP \fB%T\fR The treectrl widget which generated the event .TP \fB%?\fR A list of the format {char value char value ...} for each %-substitution character and the value it is replaced by .PP The following events may be generated by a treectrl widget: .TP \fB\fR Generated whenever the active item changes. .RS .TP \fB%c\fR The current active item .TP \fB%p\fR The previous active item .RE .TP \fB\fR Generated before an item is collapsed. .RS .TP \fB%I\fR The item id .RE .TP \fB\fR Generated after an item is collapsed. .RS .TP \fB%I\fR The item id .RE .TP \fB\fR Generated before an item is expanded. This event is useful if you want to add child items to the item just before the item is expanded. .RS .TP \fB%I\fR The item id .RE .TP \fB\fR Generated after an item is expanded. .RS .TP \fB%I\fR The item id .RE .TP \fB\fR Generated when items are about to be deleted by the \fBitem delete\fR command. .RS .TP \fB%i\fR List of items ids being deleted. .RE .TP \fB\fR Generated when items become visible on screen and when items are no longer visible on screen. This event is useful if you have a very large number of items and want to assign styles only when items are actually going to be displayed. .RS .TP \fB%h\fR List of items ids which are no longer visible. .TP \fB%v\fR List of items ids which are now visible. .RE .TP \fB\fR Generated whenever the view in the treectrl changes in such a way that a horizontal scrollbar should be redisplayed. .RS .TP \fB%l\fR Same as the first fraction appended to \fB-xscrollcommand\fR. Think \fIlower\fR. .TP \fB%u\fR Same as the second fraction appended to \fB-xscrollcommand\fR. Think \fIupper\fR. .RE .TP \fB\fR Generated whenever the view in the treectrl changes in such a way that a vertical scrollbar should be redisplayed. .RS .TP \fB%l\fR Same as the first fraction appended to \fB-yscrollcommand\fR. Think \fIlower\fR. .TP \fB%u\fR Same as the second fraction appended to \fB-yscrollcommand\fR. Think \fIupper\fR. .RE .TP \fB\fR Generated whenever the selection changes. This event gives information about how the selection changed. .RS .TP \fB%c\fR Same as the \fBselection count\fR widget command .TP \fB%D\fR List of newly-deselected item ids .TP \fB%S\fR List of newly-selected item ids .RE .SH "DYNAMIC EVENTS" In addition to the pre-defined static events such as and , new dynamic events can be created by using the \fBnotify install\fR command. .PP The following events may be generated by the library scripts: .TP \fB\fR .TP \fB\fR .TP \fB\fR Generated whenever the user drag-and-drops a column header. The library scripts do not actually move a dragged column. You must bind to the receive event to move the column. See \fBEXAMPLES\fR. .RS .TP \fB%C\fR The column that was dragged .TP \fB%b\fR The column to move the dragged column before .RE .TP \fB\fR .TP \fB\fR .TP \fB\fR Generated whenever the user drag-and-drops a file into a directory. This event is generated by the filelist-bindings.tcl library code, which is not used by default. See the "Explorer" demos. .RS .TP \fB%I\fR The item that the user dropped the dragged items on. .TP \fB%l\fR (lowercase L) The list of dragged items. .RE .TP \fB\fR .TP \fB\fR .TP \fB\fR The filelist-bindings.tcl code will display a text-editing window if the user clicks on a selected file/folder name. See the "Explorer" demos. .RS .TP \fB%I\fR The item containing the edited text element .TP \fB%C\fR The column containing the edited text element .TP \fB%E\fR The name of the edited text element .TP \fB%t\fR The edited text .RE .TP \fB\fR Generated whenever the user clicks and releases the left mouse button in a column header if the column's -button option is true. You can bind a script to this event to sort the list. .RS .TP \fB%C\fR The column whose header was clicked .RE The library scripts provide an example of using a dynamic event called , which is generated when the mouse button is released over a column header. .nf treectrl .t .t notify install .t notify bind ConsoleTag { puts "header %C clicked in treectrl %T" } proc ::TreeCtrl::Release1 {w x y} { ... $w notify generate [list C $Priv(column)] \\ [list ::TreeCtrl::PercentsCmd $w] ... } .fi In the example a new treectrl widget is created and the event is installed. For convenience there is no \fIpercentsCommand\fR argument to \fBnotify install\fR; instead the call to \fBnotify generate\fR specifies the %-substitution command. A script is bound to the event with \fBnotify bind\fR which will print out the column number and widget name to the console (in the demos, is used to sort the list based on the column that was clicked). The \fIcharMap\fR argument to \fBnotify generate\fR provides a list of %-substitution characters and values which is used by ::TreeCtrl::PercentsCmd. In this example any %C in any script bound to the event will be replaced by the value of $Priv(column). .SH "DEFAULT BINDINGS" Tk automatically creates class bindings for treectrl widgets that give them the following default behavior. .IP [1] Clicking mouse button 1 over an item positions the active cursor on the item, sets the input focus to this widget, and resets the selection of the widget to this item, if it is not already in the selection. .IP [2] Clicking mouse button 1 with the Control key down will reposition the active cursor and add the item to the selection without ever removing any items from the selection. .IP [3] If the mouse is dragged out of the widget while button 1 is pressed, the treectrl will automatically scroll to make more items visible (if there are more items off-screen on the side where the mouse left the window). .IP [4] The Left and Right keys move the active cursor one item to the left or right; for an hierarchical tree with vertical orientation nothing will happen, since it has no two items in the same row. The selection is set to include only the active item. If Left or Right is typed with the Shift key down, then the active cursor moves and the selection is extended to include the new item. .IP [5] The Up and Down keys move the active cursor one item up or down. The selection is set to include only the active item. If Up or Down is typed with the Shift key down, then the active cursor moves and the selection is extended to include the new item. .IP [6] The Next and Prior keys move the active cursor forward or backwards by one screenful, without affecting the selection. .IP [7] Control-Next and Control-Prior scroll the view right or left by one page without moving the active cursor or affecting the selection. Control-Left and Control-Right behave the same. .IP [8] The Home and End keys scroll to the left or right end of the widget without moving the active cursor or affecting the selection. .IP [9] The Control-Home and Control-End keys scroll to the top or bottom of the widget, they also activate and select the first or last item. If also the Shift key is down, then the active cursor moves and the selection is extended to include the new item. .IP [10] The Space and Select keys set the selection to the active item. .IP [11] Control-/ selects the entire contents of the widget. .IP [12] Control-\\\\ clears any selection in the widget. .IP [13] The + and - keys expand or collapse the active item, the Return key toggles the active item. .IP [14] The mousewheel scrolls the view of the widget four lines up or down depending on the direction, the wheel was turned. The active cursor or the selection is not affected. .SH EXAMPLES Get the unique identifier for the leftmost visible column: .nf set id [$T column index "first visible"] .fi Delete the leftmost column: .nf $T column delete "order 0" .fi Take the visible column that is to the left of the last column, and move that column in front of the tail column: .nf $T column move "last prev visible" tail .fi Get the unique identifier for the first visible item: .nf set id [$T item index "first visible"] .fi Delete the parent of the item that is under the point x,y: .nf $T item delete "nearest $x $y parent" .fi Add the 10th child of the second child of the root item to the selection: .nf $T selection add "root firstchild nextsibling child 10" .fi Move a column that the user drag-and-dropped: .nf $T column dragconfigure -enable yes $T notify install $T notify bind MyTag { %T column move %C %b } .fi .SH "SEE ALSO" bind(n), bitmap(n), image(n), listbox(n), options(n) .SH KEYWORDS tree, widgettktreectrl-2.2.8/doc/What's New in TkTreeCtrl.html0000700000175600010010000017254111073207242020011 0ustar TimNone What's New in TkTreeCtrl

What's New in TkTreeCtrl 2.2.8

Bug Fixes

  • Fixed a bug that caused a panic in Range_ItemUnderPoint. Thanks to SF.net user 'nobody' who found the problem.
  • Fixed reading an uninitialized variable when calculating column header layout.


What's New in TkTreeCtrl 2.2.7

TreeCtrl Configuration Options

New Comment
-showrootchildbuttons Similar to -showrootlines, this boolean option controls the display of expand/collapse buttons next to child items of the root item.

Indentation change/fix

Previously with -showroot=0, -showbuttons=0, and -showrootlines=0 there was still an extra level of indentation displayed to the left of the root's children. The only way to remove all indentation from the root's children was to set -showlines=0 as well.  This is no longer the case and now behaves as expected. With the new -showrootchildbuttons option it is now possible to remove all indentation from the root's children without affecting the display of buttons/lines on deeper items.

Library Script Changes

treectrl.tcl:

  • The <Left> and <Right> key bindings will collapse and expand the active item if -orient=vertical and -wrap={}.  Otherwise the previous behavior of setting the active item to an adjacent item is used.

Bug Fixes

  • Fixed corruption/crash with ".t column configure -foo" with no option value if -foo is an invalid option.

What's New in TkTreeCtrl 2.2.6

Bug Fixes

  • Fixed ".t item bbox" returning bogus values when asking for the bounds of a column or element in a list with many items (integer overflow).
  • Fixed a segfault on Win64 machines when the system theme changed.
  • Fixed a panic on Win64 when drawing the the marquee and drag-image dotted rectangles due to a too-small struct.

What's New in TkTreeCtrl 2.2.5

Issues regarding the incompatibility of 8.4 built TkTreeCtrl working in 8.5 were resolved. The Mac OS X API issues noted for 2.2.4 remain (they relate to difficult to reconcile core drawing changes).

A Windows DLL manifest is now embedded to address native theme drawing issues.


What's New in TkTreeCtrl 2.2.4

NOTE regarding Tk version compatibility

Under Mac OSX some internal changes to Tk 8.4.15 and Tk 8.4.17 result in incompatibilities:

  • This version of TkTreeCtrl built for Tk 8.4.15 will work with Tk 8.4.15 and 8.4.16 only (under Mac OSX).
  • This version of TkTreeCtrl built for Tk 8.4.17 will work with Tk 8.4.17 only (under Mac OSX).

TreeCtrl Configuration Options

New Comment
-columntagexpr
-itemtagexpr
These boolean options can be used to turn off tag expressions in column descriptions and item descriptions.  When the value of these options is false the characters (', ')', '&', '|', '^' and '!' have no special significance when using tags in column/item descriptions. This is useful for applications which may have arbitrary tags applied to columns or items.

Bug Fixes

  • Fixed partially-exposed transparent photo images not being redrawn when scrolling under X11.
  • Fixed potential crash with Windows theme if the system theme was changed.
  • Fixed ".t item cget -button" always returning 0 when the value of this option wasn't auto.
  • Fixed a drawing issue under Mac OSX where parts of the window would not be erased properly under Tk 8.4.15+ and Tk 8.5a7+.
  • Fixed crashes under Mac OSX with Tk 8.4.17 and Tk 8.5.0.
  • Fixed an old bug caused by a MSVC compiler optimization bug that stopped items being redrawn when the only change in appearance was the expand/collapse button needing to be redrawn.

Misc Changes

  • Changed the item sort code to be a "stable" sort. This means that the pre-sort order of two equal items is used as a tie-breaker.

Demo Changes

  • Added "Increase Font Size" and "Decrease Font Size" menu commands.  Also the Console font is not changed when running under Tk 8.5.

What's New in TkTreeCtrl 2.2.3

Build Changes

  • When building with configure on Windows the --enable-shellicon option will run configure in the shellicon/ subdirectory.
  • 'make dist' will create the source distribution tktreectrl-VERSION.tar.gz.
  • 'make dist-win' will create the Windows binary distribution tktreectrl-VERSION-win32.zip.

Bug Fixes

  • Fixed flickering when redrawing the borders with "-doublebuffer window" when the widget was resized or parts of it were exposed.
  • Fixed undefined reference to vsnprintf when building with the MS compiler under Windows; it should be _vsnprintf.
  • Fixed a symbol conflict with Python 2.5 on ELF-based systems which also defines a symbol "Ellipsis".

What's New in TkTreeCtrl 2.2.2

Column Configuration Options

New Comment
-itemjustify This option allows item styles to be justified separately from the image/text in the column header. If the value of this option is unspecified (the default), then item styles are justified according to the -justify option of the column.

Item Configuration Options

Usage Changed How it changed
-button The value of this option can now be the word auto (or any abbreviation) in which case a button is drawn only when the item has at least one child item with its item option -visible set to true.

Style Layout Changes

  • The element option -draw of every element type is now deprecated. Use the new style layout option -draw instead.
  • The new per-state style layout option -visible controls the visibility of an element. When the value of this option evaluates to false for a given state, the element consumes no space in the layout and is not displayed. If none of the elements surrounded by an element with -union layout are visible, then the element with -union layout is not displayed.

Item Descriptions

  • The index argument to the child and sibling modifiers can now take the form "end?-integer?".
.t item id "root child end-1" ; # get the second-to-last child of the root item

Bug Fixes

  • Text elements were requesting some height from the style layout when displaying an empty string. If you were depending on this behaviour, it is suggested that you set the height of the text element using the -minheight or -height style layout options.
  • Window elements might not be scrolled along with the rest of the list if the area needing to be redrawn due to scrolling was obscurred by other windows. This could only happen on Win32.
  • The ellipsis "..." in text elements is now always displayed if the text element has less space than is needed to display its string. Previously the ellipsis would disappear when there wasn't room for a single character plus the ellipsis.
  • Fixed a layout bug with multi-line text elements when the unsqueezed element did not require a multi-line layout but the squeezed element did.

What's New in TkTreeCtrl 2.2.1

Bug Fixes

  • Fixed panic with -xscrollincrement=0, -showheader=yes, no visible items and headers wider than the window.
  • Fixed the wrong loop variable being used when calculating onscreen columns for an item which resulted in a random crash.
  • Fixed a crash when invalidating a column of an item if the column wasn't the first in a span.
  • Fixed a leak on X11 where the clipping region was not being freed after drawing dotted rectangles.

What's New in TkTreeCtrl 2.2

TreeCtrl Configuration Options

Deprecated What to use instead
-defaultstyle The -itemstyle option of a column.

TreeCtrl Command

Arguments/Result Changed What changed
contentbox The return value is an empty string if the content area is totally obscurred by column headers, borders, and/or locked columns. Typically this will only happen if the window is too small.
selection get Accepts 2 optional arguments to allow in-place lindex and lrange queries of the selection. For example:
.t selection get 0       ; # the first selected item
.t selection get end     ; # the last selected item
.t selection get 1 end-1 ; # every selected item except the first and last
New Comment
bbox Returns the bounding box of different areas of the window. For example:
.t bbox
will return the bounds of the window, and:
.t bbox header
will return the bounds of the column headers, and:
.t bbox content
will return the same result as the [contentbox] command, and:
.t bbox left
.t bbox right
will return the bounds of the left-locked and right-locked columns.

Column Configuration Options

Renamed
New name
-tag -tags
New Comment
-lock This option allows columns to stick to the left or right edge of the window. Locked columns can scroll vertically but not horizontally. Valid values for this option are none (the default), left or right.
-itemstyle Specifies the name of a style to set in this column for newly-created items. This option replaces the treectrl option -defaultstyle.
-uniform These two options operate the same as the grid geometry manager options of the same name. For example:
.t column configure 0 -uniform a
.t column configure 1 -uniform a
will give columns 0 and 1 the same requested width, whichever is the larger of the two columns. And:
.t column configure 0 -uniform a -weight 2
.t column configure 1 -uniform a
will give column 0 twice the maximum of the requested widths of columns 0 and 1. And:
.t column configure 0 -expand yes -weight 2
.t column configure 1 -expand yes
will give column 0 twice the extra space as column 1.
-weight

Column Command

Arguments/Result Changed What changed
column count Takes an optional column-description argument; the result is the number of columns that match the column description. For example:
.t column count visible
will return the number of columns whose -visible option is true, and:
.t column count {tag a^b}
will return the number of columns with either tag "a" or "b", but not both.
New Comment
column tag add Columns can have a list of tag names. Previously only a single tag was allowed. The tail column no longer has the word "tail" as a tag, but it is still referred to by the word "tail" in column descriptions.
column tag expr
column tag names
column tag remove

Item Configuration Options

New Comment
-tags Tags are textual labels applied to items to group them. Tags do not affect the appearance or behaviour of items. Tags can be used in item descriptions to operate on multiple items. More information can be found in the man page.

Item Command

Arguments/Result Changed What changed
item count Takes an optional item-description argument; the result is the number of items that match the item description. For example:
.t item count visible
will return the number of items that are displayed (i.e., those whose ancestors are all expanded, -visible options are true, etc), and:
.t item count {tag a^b}
will return the number of items with either tag "a" or "b", but not both.
item create New option -tags specifies an initial list of tags for created items.
item id Returns a list of item ids if the item description matches multiple items. For example:
.t item id all
will return a list of ids for all items, and:
.t item id "$item children"
will return the ids of every child of an item.
New Comment
item descendants Returns the ids of the children, grandchildren, etc of an item.
item enabled Gets and sets the enabled state for items. All items are enabled when first created. Disabled items cannot be selected, and are ignored by the default key-navigation and mouse bindings.
item tag add Add tags to items. For example:
.t item tag add all {a b c}
will add tags "a", "b" and "c" to every item.
item tag expr Evaluate a tag expression against items. For example:
.t item tag expr $item a
returns 1 if an item has tag "a". Also:
.t item tag expr $item a||b
returns 1 if  an item has tag "a" or "b".
item tag names Return a list of tag names assigned to items. For example:
.t item tag names $item
returns the tag list for an item, and:
.t item tag names all
returns every tag assigned to any item.
item tag remove Remove tags from items. For example:
.t item tag remove all {b c}
will remove tags "b" and "c" from any items that have them.

Text Element

The new option -underline draws an underline under a single character of the displayed text.

Window Element

Window elements can now be properly clipped so they don't draw over the column header, borders, or outside the bounds of the item columns they occupy. This is accomplished by making the window you want to display a child of a borderless frame widget, and setting the new -clip option of the window element to TRUE. So if your program displays a canvas widget in a window element, you would change this code:
set canvas [canvas .t.canvas ...]
.t item element configure $item $column myElement -window $canvas
to this:
set frame [frame .t.clip -borderwidth 0]
set canvas [canvas $frame.canvas ...]
.t item element configure $item $column myElement -window $frame -clip yes
The -clip option tells the window element to manage the geometry of both the -window widget (i.e, the frame) and its first child widget (i.e., the canvas). In this case, the frame widget is kept sized and positioned so that it is never out-of-bounds. You can see this in the "Big List" and "Firefox Privacy" demos.

Item Descriptions

New keywords were added to allow multiple items to be specified by an item description:
  • The keyword list specifies a list of other item descriptions:
    .t item id "list [list $a $b $c]"
  • The keyword range operates like the item range command:
    .t item id "range $first $last"
New modifiers were added to match multiple items:
  • The modifier ancestors operates like the item ancestors command:
    .t item id "$item ancestors"
  • The modifier children operates like the item children command:
    .t item id "$item children"
  • The modifier descendants operates like the item descendants command:
    .t item id "$item descendants"
New qualifiers were added to refine which items are matched:
  • The qualifier depth matches items at a given depth in the heirarchy:
.t item id "all depth 2" ; # find all items that are children of the root's children
.t item id "depth 2" ; # ditto
  • The qualifier !visible matches items that are not displayed:
    .t item id "first !visible" ; # find the first item that is not displayed
  • The qualifier state matches items that have certain states set (or not set if '!' is used):
    .t item id "first state {selected !open}" ; # find the first item that is selected and collapsed
  • The qualifier tag matches items that meet a tag expression:
    .t item id "$item children tag {a && !b}" ; # find children of $item that have tag "a" but not tag "b"

The keyword all may now be followed by a list of qualifiers. For example:
.t item id "all !visible state myState" ; # find every item that is not displayed with user-defined state "myState"
A list of qualifiers may be used as the first part of an item description. This gives the same result as  "all" followed by the qualifiers. For example:
.t item id "!visible state myState" ; # same as the previous example

Column Descriptions

New keywords list and range can be used to match multiple columns.
New qualifiers state, tag, !tail and !visible can be used to restrict which columns are specified.
The keyword all may be followed by a list of qualifiers.
A list of qualifiers may used as the first part of a column description. This gives the same result as  "all" followed by the qualifiers.

Multi-item and multi-column commands

Many commands can now operate on multiple items and/or columns by using the improved item descriptions and column descriptions mentioned above. For example:
.t column configure "range 1 10" -tags {a b c}
.t column delete "tag a"
.t column id "tag {a || b}"
.t item configure "depth 1" -button yes
.t item count visible
.t item element configure "root children" all elem1 -text "Hello"
.t item id "visible"
.t item image all all image1
.t item style map "tag {a && !b}" "tag c" style2 {style1.elem1 style2.elem2}
.t item style set all all style1
.t item state forcolumn all all state1
.t item state set "tag current" ~mouseover
.t item remove "state selected"
.t item span "range 1 10" "range 10 last" 2
.t item text "root children" all "Hello"

Demo Changes

  • New demo "My Computer". Demonstrates disabled items used as headers.
  • New demo "Column Locking". Demonstrates columns that do not scroll horizontally.
  • The "Big List" and "Firefox Privacy" demos were changed to use the new -clip option of window elements.

Misc Changes

  • The tail column header will not be drawn if the tail column's -visible option is false. This can look nicer with some themes.
  • The -itembackground colors for a column are now extended below any items in the simplest (and most typical) case where the treectrl's -orient option is vertical and -wrap option is unspecified. The height of the rows is determined by the -itemheight or -minitemheight options; if neither of those options is specified, then -itembackground colors are not drawn below the items.
  • If -itembackground colors are specified for the tail column, then they are drawn.
  • Memory usage is improved, especially for text elements.

Bug Fixes

  • item create: Fixed bug where -nextsibling and -prevsibling options could specify an orphan item.
  • item delete: Stopped items possibly being double-deleted by nested calls through <Selection> and <ItemDelete> binding scripts.
  • item expanditem collapseitem toggle: Only operate on items which exist when the command is called, not any that might get created by <Expand> or <Collapse> binding scripts.
  • Fixed a crash and a redisplay problem when a master element was configured with a -textvariable and the associated variable changed.
  • When a style with window elements spanned more than one column, the window might be improperly sized during display updates.
  • Windows in window elements would not always be unmapped if columns or items were hidden, or if the span of an item-column changed.
  • The disclosure triangles (i.e., the item buttons) are drawn without a white background under OSX.

What's New in TkTreeCtrl 2.1.1

Column Command

Arguments/Result Changed What changed
column delete
Added an optional second argument allowing a range of columns to be deleted.

Bug Fixes

  • The item sort command will be much faster in many cases. There was a silly error in the pivot-finding code of quicksort which resulted in the slow-down.
  • A column header will be redisplayed if an image in the header is altered.
  • Fixed bus errors on some Unix systems due to alignment problems.

Other Changes

  • The Tk caret is now positioned over the active item when it changes. The Tk caret is used for the Magnifier accessibility application and IME on Windows, as well as XIM under Unix.
  • Improved the appearance of the column headers under OSX.
  • Added <MouseWheel> support to OSX.
  • Changing the -visible option of an item could be slow if any items were selected. That is because non-visible items may not be part of the selection. A change was made so that changes to the selection caused by modifying the -visible option of an item do not occur until the next display update.

Demo Changes

  • New demo "Column Spanning". Demonstrates a 100-column list where styles span from 1 to 20 columns each.
  • The loupe command (which performs screen capture to an image) is now implemented on Windows and OSX thanks to Jeff Hobbs.
  • The screen-magnifier image now resizes with the "loupe" window.

What's New in TkTreeCtrl 2.1

This version should be backwards compatible with 2.0, except for a few obscure changes.

TreeCtrl Configuration Options

New Comment
-itemwidth
-itemwidthequal Deprecates the column -widthhack option.
-itemwidthmultiple Deprecates the column -stepwidth option.

Column Configuration Options

Deprecated What to use instead
-stepwidth treectrl's -itemwidthmultiple option
-widthhack treectrl's -itemwidthequal option

Element Command

New Comment
element perstate Like [item element perstate].

Item Configuration Options

New Comment
-height Overrides the treectrl's -itemheight option

Item Command

Deprecated What to use instead
item element actual item element perstate
item complex item element configure
Behaviour Changed What changed
item bbox No longer returns an error if no style had been assigned to the column.
item state forcolumn No longer returns an error if no style had been assigned to the column.
item style set Does nothing when replacing a style with the same style. Previously the old style was freed before assigning the new style, losing the element config info if the old and new styles were the same.
Potential incompatibility
Arguments/Result Changed What changed
item create Added options: -count -height, -nextsibling, -open, -parent, -prevsibling, and -returnid. Multiple items may be created with one call using the -count option.
item element configure Multiple elements in multiple columns may be configured with a single call. Use '+' to separate elements, and ',' to separate columns. See the docs.
item style set When no column is specified, returns a list of one style name per column. Previously, the list would have less values than the number of columns if no styles had ever been assigned to the rightmost column(s).
Potential incompatibility
item text When no column is specified, returns a list of one string per column.
New Comment
item image Partner to the [item text] command.
item element perstate Not really new, just renamed from [item element actual] to better describe what it does. Accepts a new optional argument which specifies the state to use when determining the value of the per-state option.

The following options no longer return a default value if the per-state option itself does not have a value specified:
  • bitmap -foreground, -background
  • border -relief
  • text -fill, -font
Potential incompatibility
item span A style may now be displayed over multiple adjacent columns.

Notify Command

New Comment
notify unbind
Let's you unbind all scripts from an object with one call.

Style Layout Changes

  • Column justification will now affect the position of elements in 2 situations which previously had no effect (Potential incompatibility):
  1. If a -detach element had a fixed width larger than the other elements.
  2. If an element had -iexpand x specified as well as -maxwidth, leaving some space available.

Element Changes

  • Bitmap, image and text elements are drawn clipped if given less space than they need.
  • Fixed line wrapping of text elements. It did not work for single lines of text at all (Potential incompatibility).
  • The text -wrap option can now be none to disable line wrapping.

Event Changes

  • The new static event <ItemVisibility> is generated when items become visible on screen and when items are no longer visible on screen. This event allows you to create really big lists by only assigning styles when items are about to be displayed. See the EVENTS AND SCRIPT SUBSTITUTIONS section in the help file, and the new demo "Big List".

Other Changes

  • On WinXP, the column header sort arrow is drawn like Explorer draws it if -usetheme is true.

Demo Changes

  • New demo "Big List". Demonstrates the new <ItemVisibility> event, using <Expand-before> to add items on demand, and column spanning.
  • The context menu has a Span submenu that lets you manipulate column spanning in items. See the item span command in the help file.
  • Under WinXP, the "Explorer" demos will use the new shellicon extension if available. This extension allows a treectrl to display file/folder icons using the Win32 Shell API. It may work on other versions of Windows but it hasn't been tested.

What's New in TkTreeCtrl 2.0

TreeCtrl Configuration Options

Replaced What to use instead
-openbuttonimage -buttonimage
-closedbuttonimage -buttonimage
-openbuttonbitmap -buttonbitmap
-closedbuttonbitmap -buttonbitmap
Usage Changed How it changed
-backgroundmode The values "index" and "visindex" are deprecated. The value "order" should be used instead of "index", and "ordervisible" should be used instead of "visindex". This brings agreement with the new "item order" command which replaces the "item index" command.
-treecolumn This used to be any integer value which may or may not have corresponded to an actual column. Now the value must be a valid column description, or an empty string to indicate no column should display buttons/lines.
New
-backgroundimage
-columnprefix
-columnresizemode
-itemprefix
-minitemheight
-usetheme

TreeCtrl Commands

Deprecated What to use instead
compare item compare
index item id
numcolumns column count
numitems item count
range item range

Column Configuration Options

Removed What to use instead
-relief
-state
-sunken -state
Renamed
New name
-arrowpad -arrowpadx
Usage Changed How it changed
-background This is now a per-state option. See COLUMNS in the help file for valid state names.
New
-arrowbitmap
-arrowimage
-arrowpady
-maxwidth
-resize
-state
-textlines

Column Command

Deprecated What to use instead
column index column id
Arguments/Result Changed What changed
column configure
A column description of "all" is allowed if at least one option-value pair is given.
column create The result is a unique identifier. Previously the result was an index in the list of columns.
column delete A column description of "all" is allowed.
New Comment
column compare
column count replaces "numcolumns"
column dragconfigure
column dragcget
column id replaces "column index"
column list
column order

Item Command

Removed What to use instead
item index item order
New Comment
item compare replaces "compare"
item count replaces "numitems"
item id replaces "index"
item order replaces "item index"
item range replaces "range"

Notify Command

Arguments/Result Changed What changed
notify generate
Added optional percentsCommand argument
notify install Old syntax (supported but deprecated):
notify install event eventName
notify install detail eventName detail
New syntax:
notify install <eventName>
notify install <eventName-detail>
notify linkage Old syntax (supported but deprecated):
notify linkage eventName
notify linkage eventName detail
New syntax:
notify linkage <eventName>
notify linkage <eventName-detail>
notify uninstall see notify install above

Style Layout Options

Usage Changed How it changed
-iexpand Two new flags "x' and "y" are allowed. Previously, only the -ipadx and -ipady padding could be expanded by this option. The new xy flags expand the display area of the element, not the padding. To update your code, you will probably want to change this:
$T style layout $S $E -iexpand we
to this:
$T style layout $S $E -iexpand x
Keep in mind that -union elements are not affected by -iexpand xy, since the size of a -union element is determined by the elements it surrounds.
New
-height
-maxheight
-maxwidth
-minheight
-minwidth
-sticky
-width

Element Changes

  • A new element type window was added. See the new demo "Firefox Privacy" and the ELEMENTS section in the help file.
  • All element types have a new per-state boolean option called -draw.
  • The text element type has a new option called -textvariable. See the new demo "Textvariable" and the ELEMENTS section in the help file.

Event Changes

  • 2 new %-substitution characters %P and %? are allowed in binding scripts. See the EVENTS AND SCRIPT SUBSTITUTIONS section in the help file.
  • The new static event <ItemDelete> is generated when items are deleted. See the EVENTS AND SCRIPT SUBSTITUTIONS section in the help file.

Library Script Changes

filelist-bindings.tcl:

  • The Priv(edit) variable, which is used to specify which text elements may be edited, now has the same format as Priv(sensitive). Previously only elements in the first column could be edited.
  • 3 new commands in the TreeCtrl namespace should be used to access the Priv(dragimage), Priv(edit) and Priv(sensitive) variables. The commands are SetDragImage, SetEditable and SetSensitive.
  • Two new dynamic events <Edit-begin> and <Edit-end> are generated when editing a file name.

treectrl.tcl:

  • On OSX/Aqua, the Command key is used to perform discontinuous selection. Previously the Control key was used but Command is specified by Apple's user-interface guidelines.

Other Changes

  • On WinXP, the column headers and open/close buttons are drawn using the system theme if -usetheme is true. The sort arrow is drawn the old-fashioned way.
  • On OSX/Aqua,  the column headers and open/close buttons are drawn using the system theme if -usetheme is true. The sort arrow will be drawn by the Appearance Manager as well. This will override the -arrowside and -arrowgravity options.
  • Columns can be moved by drag-and-drop. See column dragconfigure in the help file.
  • Columns can be specified in new ways. See the COLUMN DESCRIPTION section in the help file.
  • Added new section DYNAMIC EVENTS to the help file.
  • Added new section PER-STATE OPTIONS to the help file.
  • The new style layout option -indent allows elements to be displayed in the button/line area. See the style layout command in the help file and the new demo "Firefox Privacy".
  • The new item description end is equivalent to last.
  • If you have version 1.1 installed, replace the old pkgIndex.tcl file with the one from this version (but replace the version number 2.0 with 1.1). Otherwise the old pkgIndex.tcl file will set the TREECTRL_LIBRARY variable which will override where the library scripts are found.

Demo Changes

  • New demo "Firefox Privacy". Demonstrates the new window element type and -indent style layout option.
  • New demo "Textvariable". Demonstrates the new -textvariable option of the text element.
  • Added a new Event Browser window to display events generated by the main treectrl widget.
  • The context menu can be popped up in all the demo lists. A <Control-ButtonPress-1> binding for this was added under OSX/Aqua.
  • In the "Explorer" demos, the file name is hidden while editing the file name.
tktreectrl-2.2.8/generic/0000755000175600010010000000000011073207472013532 5ustar TimNonetktreectrl-2.2.8/generic/qebind.c0000700000175600010010000016722610760347544015156 0ustar TimNone/* * qebind.c -- * * This module implements quasi-events. * * Copyright (c) 2002-2008 Tim Baker * * RCS: @(#) $Id: qebind.c,v 1.20 2008/02/22 20:02:25 hobbs2 Exp $ */ /* * A general purpose module that allows a program to send event-like * messages to scripts, and to bind Tcl commands to those quasi-events. * Each event has it's own detail field and other fields, and this * module performs %-substitution on bound scripts just like regular * Tk binding model. * * To use it first call QE_BindInit() to initialize the package. * Then call QE_InstallEvent() for each new event you wish to define. * For events with details, call QE_InstallDetail() to register each * detail associated with a specific event type. Then create a * binding table, which records all binding commands defined by your * scripts, with QE_CreateBindingTable(). QE_BindCmd() is * called to associate a Tcl script with a given event for a particular * object. The objects that commands are bound to can be a Tk widget or any * string, just like the usual "bind" command. Bindings on Tk widgets are * automatically deleted when the widget is destroyed. */ #include #include #include #include #include "qebind.h" #define dbwin TreeCtrl_dbwin extern void dbwin(char *fmt, ...); /* * The macro below is used to modify a "char" value (e.g. by casting * it to an unsigned character) so that it can be used safely with * macros such as isspace. */ #define UCHAR(c) ((unsigned char) (c)) int debug_bindings = 0; /* * Allow bindings to be deactivated. */ #define BIND_ACTIVE 1 /* * Allow new events to be added/removed by Tcl commands. */ #define ALLOW_INSTALL 1 /* * Delete scripts bound to a window when that window is destroyed. */ #define DELETE_WIN_BINDINGS 1 typedef struct BindValue { int type; /* Type of event, etc) */ int detail; /* Misc. other information, or 0 for none */ ClientData object; char *command; int specific; /* For less-specific events (detail=0), this is 1 * if a more-specific event (detail>0) exists. */ struct BindValue *nextValue; /* list of BindValues matching event */ #if BIND_ACTIVE int active; /* 1 if binding is "active", 0 otherwise */ #endif /* BIND_ACTIVE */ } BindValue; typedef struct Pattern { int type; /* Type of event */ int detail; /* Misc. other information, or 0 for none */ } Pattern; typedef struct PatternTableKey { int type; /* Type of event */ int detail; /* Misc. other information, or 0 for none */ } PatternTableKey; typedef struct ObjectTableKey { int type; /* Type of event */ int detail; /* Misc. other information, or 0 for none */ ClientData object; /* Object info */ } ObjectTableKey; typedef struct Detail { Tk_Uid name; /* Name of detail */ int code; /* Detail code */ struct EventInfo *event; /* Associated event */ QE_ExpandProc expandProc; /* Callback to expand % in scripts */ #if ALLOW_INSTALL int dynamic; /* Created by QE_InstallCmd() */ char *command; /* Tcl command to expand percents, or NULL */ #endif struct Detail *next; /* List of Details for event */ } Detail; typedef struct EventInfo { char *name; /* Name of event */ int type; /* Type of event */ QE_ExpandProc expandProc; /* Callback to expand % in scripts */ Detail *detailList; /* List of Details */ int nextDetailId; /* Next unique Detail.code */ #if ALLOW_INSTALL int dynamic; /* Created by QE_InstallCmd() */ char *command; /* Tcl command to expand percents, or NULL */ #endif struct EventInfo *next; /* List of all EventInfos */ } EventInfo; typedef struct GenerateField { char which; /* The %-char */ char *string; /* Replace %-char with it */ } GenerateField; typedef struct GenerateData { GenerateField staticField[20]; GenerateField *field; int count; char *command; /* Tcl command to expand percents, or NULL */ } GenerateData; typedef struct BindingTable { Tcl_Interp *interp; Tcl_HashTable patternTable; /* Key: PatternTableKey, Value: (BindValue *) */ Tcl_HashTable objectTable; /* Key: ObjectTableKey, Value: (BindValue *) */ Tcl_HashTable eventTableByName; /* Key: string, Value: EventInfo */ Tcl_HashTable eventTableByType; /* Key: int, Value: EventInfo */ Tcl_HashTable detailTableByType; /* Key: PatternTableKey, Value: Detail */ #if DELETE_WIN_BINDINGS Tcl_HashTable winTable; /* Key: Tk_Uid of window name, Value: WinTableValue */ #endif EventInfo *eventList; /* List of all EventInfos */ int nextEventId; /* Next unique EventInfo.type */ } BindingTable; static void ExpandPercents(BindingTable *bindPtr, ClientData object, char *command, QE_Event *eventPtr, QE_ExpandProc expandProc, Tcl_DString *result); static int ParseEventDescription(BindingTable *bindPtr, char *eventPattern, Pattern *patPtr, EventInfo **eventInfoPtr, Detail **detailPtr); static int FindSequence(BindingTable *bindPtr, ClientData object, char *eventString, int create, int *created, BindValue **result); static void Percents_CharMap(QE_ExpandArgs *args); static void Percents_Command(QE_ExpandArgs *args); #if ALLOW_INSTALL typedef struct PercentsData { GenerateData *gdPtr; char *command; EventInfo *eventPtr; Detail *detailPtr; } PercentsData; #endif static int DeleteBinding(BindingTable *bindPtr, BindValue *valuePtr); static EventInfo *FindEvent(BindingTable *bindPtr, int eventType); static int initialized = 0; int QE_BindInit(Tcl_Interp *interp) { if (initialized) return TCL_OK; initialized = 1; return TCL_OK; } static int CheckName(char *name) { char *p = name; if (*p == '\0') return TCL_ERROR; while ((*p != '\0') && (*p != '-') && !isspace(UCHAR(*p))) p++; if (*p == '\0') return TCL_OK; return TCL_ERROR; } int QE_InstallEvent(QE_BindingTable bindingTable, char *name, QE_ExpandProc expandProc) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; EventInfo *eiPtr; int isNew; int type; if (CheckName(name) != TCL_OK) { Tcl_AppendResult(bindPtr->interp, "bad event name \"", name, "\"", (char *) NULL); return 0; } hPtr = Tcl_CreateHashEntry(&bindPtr->eventTableByName, name, &isNew); if (!isNew) { Tcl_AppendResult(bindPtr->interp, "event \"", name, "\" already exists", NULL); return 0; } type = bindPtr->nextEventId++; eiPtr = (EventInfo *) Tcl_Alloc(sizeof(EventInfo)); eiPtr->name = Tcl_Alloc(strlen(name) + 1); strcpy(eiPtr->name, name); eiPtr->type = type; eiPtr->expandProc = expandProc; eiPtr->detailList = NULL; eiPtr->nextDetailId = 1; #ifdef ALLOW_INSTALL eiPtr->dynamic = 0; eiPtr->command = NULL; #endif Tcl_SetHashValue(hPtr, (ClientData) eiPtr); hPtr = Tcl_CreateHashEntry(&bindPtr->eventTableByType, (char *) type, &isNew); Tcl_SetHashValue(hPtr, (ClientData) eiPtr); /* List of EventInfos */ eiPtr->next = bindPtr->eventList; bindPtr->eventList = eiPtr; return type; } int QE_InstallDetail(QE_BindingTable bindingTable, char *name, int eventType, QE_ExpandProc expandProc) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; Detail *dPtr; EventInfo *eiPtr; PatternTableKey key; int isNew; int code; if (CheckName(name) != TCL_OK) { Tcl_AppendResult(bindPtr->interp, "bad detail name \"", name, "\"", (char *) NULL); return 0; } /* Find the event this detail goes with */ eiPtr = FindEvent(bindPtr, eventType); if (eiPtr == NULL) return 0; /* Verify the detail is not already defined for this event */ for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dPtr->next) { if (strcmp(dPtr->name, name) == 0) { Tcl_AppendResult(bindPtr->interp, "detail \"", name, "\" already exists for event \"", eiPtr->name, "\"", NULL); return 0; } } code = eiPtr->nextDetailId++; /* New Detail for detailTable */ dPtr = (Detail *) Tcl_Alloc(sizeof(Detail)); dPtr->name = Tk_GetUid(name); dPtr->code = code; dPtr->event = eiPtr; dPtr->expandProc = expandProc; #if ALLOW_INSTALL dPtr->dynamic = 0; dPtr->command = NULL; #endif /* Entry to find detail by event type and detail code */ key.type = eventType; key.detail = code; hPtr = Tcl_CreateHashEntry(&bindPtr->detailTableByType, (char *) &key, &isNew); Tcl_SetHashValue(hPtr, (ClientData) dPtr); /* List of Details */ dPtr->next = eiPtr->detailList; eiPtr->detailList = dPtr; return code; } static void DeleteEvent(BindingTable *bindPtr, EventInfo *eiPtr) { EventInfo *eiPrev; Detail *dPtr, *dNext; /* Free Details */ for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dNext) { dNext = dPtr->next; #ifdef ALLOW_INSTALL if (dPtr->command != NULL) Tcl_Free(dPtr->command); #endif memset((char *) dPtr, 0xAA, sizeof(Detail)); Tcl_Free((char *) dPtr); } if (bindPtr->eventList == eiPtr) bindPtr->eventList = eiPtr->next; else { for (eiPrev = bindPtr->eventList; eiPrev->next != eiPtr; eiPrev = eiPrev->next) { } eiPrev->next = eiPtr->next; } /* Free EventInfo */ Tcl_Free(eiPtr->name); #ifdef ALLOW_INSTALL if (eiPtr->command != NULL) Tcl_Free(eiPtr->command); #endif memset((char *) eiPtr, 0xAA, sizeof(EventInfo)); Tcl_Free((char *) eiPtr); } int QE_UninstallEvent(QE_BindingTable bindingTable, int eventType) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; Tcl_HashSearch search; EventInfo *eiPtr; BindValue *valuePtr, **valueList; Tcl_DString dString; int i, count = 0; /* Find the event */ hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByType, (char *) eventType); if (hPtr == NULL) return TCL_ERROR; eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); Tcl_DeleteHashEntry(hPtr); hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eiPtr->name); Tcl_DeleteHashEntry(hPtr); Tcl_DStringInit(&dString); /* Find all bindings to this event for any object */ hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); while (hPtr != NULL) { valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); while (valuePtr != NULL) { if (valuePtr->type == eiPtr->type) { Tcl_DStringAppend(&dString, (char *) &valuePtr, sizeof(valuePtr)); count++; } valuePtr = valuePtr->nextValue; } hPtr = Tcl_NextHashEntry(&search); } valueList = (BindValue **) Tcl_DStringValue(&dString); for (i = 0; i < count; i++) DeleteBinding(bindPtr, valueList[i]); Tcl_DStringFree(&dString); DeleteEvent(bindPtr, eiPtr); return TCL_OK; } int QE_UninstallDetail(QE_BindingTable bindingTable, int eventType, int detail) { BindingTable *bindPtr = (BindingTable *) bindingTable; PatternTableKey key; Tcl_HashEntry *hPtr; Detail *dPtr = NULL, *dPrev; EventInfo *eiPtr; /* Find the event */ eiPtr = FindEvent(bindPtr, eventType); if (eiPtr == NULL) return TCL_ERROR; if (eiPtr->detailList == NULL) return TCL_ERROR; /* Delete all bindings on this event/detail for all objects */ while (1) { key.type = eventType; key.detail = detail; hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key); if (hPtr == NULL) break; DeleteBinding(bindPtr, (BindValue *) Tcl_GetHashValue(hPtr)); } if (eiPtr->detailList->code == detail) { dPtr = eiPtr->detailList; eiPtr->detailList = eiPtr->detailList->next; } else { for (dPrev = eiPtr->detailList; dPrev != NULL; dPrev = dPrev->next) { if ((dPrev->next != NULL) && (dPrev->next->code == detail)) { dPtr = dPrev->next; dPrev->next = dPtr->next; break; } } if (dPtr == NULL) return TCL_ERROR; } #ifdef ALLOW_INSTALL if (dPtr->command != NULL) Tcl_Free(dPtr->command); #endif memset((char *) dPtr, 0xAA, sizeof(Detail)); Tcl_Free((char *) dPtr); key.type = eventType; key.detail = detail; hPtr = Tcl_FindHashEntry(&bindPtr->detailTableByType, (char *) &key); Tcl_DeleteHashEntry(hPtr); return TCL_OK; } static EventInfo *FindEvent(BindingTable *bindPtr, int eventType) { Tcl_HashEntry *hPtr; hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByType, (char *) eventType); if (hPtr == NULL) return NULL; return (EventInfo *) Tcl_GetHashValue(hPtr); } static Detail *FindDetail(BindingTable *bindPtr, int eventType, int code) { PatternTableKey key; Tcl_HashEntry *hPtr; key.type = eventType; key.detail = code; hPtr = Tcl_FindHashEntry(&bindPtr->detailTableByType, (char *) &key); if (hPtr == NULL) return NULL; return (Detail *) Tcl_GetHashValue(hPtr); } #if DELETE_WIN_BINDINGS typedef struct WinTableValue { BindingTable *bindPtr; ClientData object; Tk_Window tkwin; int count; /* Number of BindValues on object */ } WinTableValue; static void TkWinEventProc(ClientData clientData, XEvent *eventPtr) { WinTableValue *cd = (WinTableValue *) clientData; BindingTable *bindPtr = cd->bindPtr; ClientData object = cd->object; if (eventPtr->type != DestroyNotify) return; QE_DeleteBinding((QE_BindingTable) bindPtr, object, NULL); } #endif QE_BindingTable QE_CreateBindingTable(Tcl_Interp *interp) { BindingTable *bindPtr; bindPtr = (BindingTable *) Tcl_Alloc(sizeof(BindingTable)); bindPtr->interp = interp; Tcl_InitHashTable(&bindPtr->patternTable, sizeof(PatternTableKey) / sizeof(int)); Tcl_InitHashTable(&bindPtr->objectTable, sizeof(ObjectTableKey) / sizeof(int)); Tcl_InitHashTable(&bindPtr->eventTableByName, TCL_STRING_KEYS); Tcl_InitHashTable(&bindPtr->eventTableByType, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&bindPtr->detailTableByType, sizeof(PatternTableKey) / sizeof(int)); #if DELETE_WIN_BINDINGS Tcl_InitHashTable(&bindPtr->winTable, TCL_ONE_WORD_KEYS); #endif bindPtr->nextEventId = 1; bindPtr->eventList = NULL; return (QE_BindingTable) bindPtr; } void QE_DeleteBindingTable(QE_BindingTable bindingTable) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; Tcl_HashSearch search; EventInfo *eiPtr, *eiNext; Detail *dPtr, *dNext; hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); while (hPtr != NULL) { BindValue *valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); while (valuePtr != NULL) { BindValue *nextValue = valuePtr->nextValue; Tcl_Free((char *) valuePtr->command); memset((char *) valuePtr, 0xAA, sizeof(BindValue)); Tcl_Free((char *) valuePtr); valuePtr = nextValue; } hPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&bindPtr->patternTable); Tcl_DeleteHashTable(&bindPtr->objectTable); for (eiPtr = bindPtr->eventList; eiPtr != NULL; eiPtr = eiNext) { eiNext = eiPtr->next; /* Free Detail */ for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dNext) { dNext = dPtr->next; #ifdef ALLOW_INSTALL if (dPtr->command != NULL) Tcl_Free(dPtr->command); #endif memset((char *) dPtr, 0xAA, sizeof(Detail)); Tcl_Free((char *) dPtr); } /* Free EventInfo */ Tcl_Free(eiPtr->name); #ifdef ALLOW_INSTALL if (eiPtr->command != NULL) Tcl_Free(eiPtr->command); #endif memset((char *) eiPtr, 0xAA, sizeof(EventInfo)); Tcl_Free((char *) eiPtr); } Tcl_DeleteHashTable(&bindPtr->eventTableByName); Tcl_DeleteHashTable(&bindPtr->eventTableByType); Tcl_DeleteHashTable(&bindPtr->detailTableByType); #if DELETE_WIN_BINDINGS hPtr = Tcl_FirstHashEntry(&bindPtr->winTable, &search); while (hPtr != NULL) { WinTableValue *cd = (WinTableValue *) Tcl_GetHashValue(hPtr); Tk_DeleteEventHandler(cd->tkwin, StructureNotifyMask, TkWinEventProc, (ClientData) cd); Tcl_Free((char *) cd); hPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&bindPtr->winTable); #endif memset((char *) bindPtr, 0xAA, sizeof(BindingTable)); Tcl_Free((char *) bindPtr); } int QE_CreateBinding(QE_BindingTable bindingTable, ClientData object, char *eventString, char *command, int append) { BindingTable *bindPtr = (BindingTable *) bindingTable; BindValue *valuePtr; int isNew, length; char *cmdOld, *cmdNew; if (FindSequence(bindPtr, object, eventString, 1, &isNew, &valuePtr) != TCL_OK) return TCL_ERROR; /* created a new objectTable entry */ if (isNew) { Tcl_HashEntry *hPtr; PatternTableKey key; #if DELETE_WIN_BINDINGS char *winName = (char *) object; if (winName[0] == '.') { Tk_Window tkwin = Tk_MainWindow(bindPtr->interp); Tk_Window tkwin2; tkwin2 = Tk_NameToWindow(bindPtr->interp, winName, tkwin); if (tkwin2 != NULL) { WinTableValue *cd; hPtr = Tcl_CreateHashEntry(&bindPtr->winTable, object, &isNew); if (isNew) { cd = (WinTableValue *) Tcl_Alloc(sizeof(WinTableValue)); cd->bindPtr = bindPtr; cd->object = object; cd->tkwin = tkwin2; cd->count = 0; Tk_CreateEventHandler(tkwin2, StructureNotifyMask, TkWinEventProc, (ClientData) cd); Tcl_SetHashValue(hPtr, (ClientData) cd); } else { cd = (WinTableValue *) Tcl_GetHashValue(hPtr); } /* Number of BindValues for this window */ cd->count++; } } #endif key.type = valuePtr->type; key.detail = valuePtr->detail; hPtr = Tcl_CreateHashEntry(&bindPtr->patternTable, (char *) &key, &isNew); /* * A patternTable entry exists for each different type/detail. * The entry points to a BindValue which is the head of the list * of BindValue's with this same type/detail, but for different * objects. */ if (!isNew) { valuePtr->nextValue = (BindValue *) Tcl_GetHashValue(hPtr); } Tcl_SetHashValue(hPtr, (ClientData) valuePtr); } cmdOld = valuePtr->command; /* Append given command to any existing command */ if (append && cmdOld) { length = strlen(cmdOld) + strlen(command) + 2; cmdNew = Tcl_Alloc((unsigned) length); (void) sprintf(cmdNew, "%s\n%s", cmdOld, command); } /* Copy the given command */ else { cmdNew = (char *) Tcl_Alloc((unsigned) strlen(command) + 1); (void) strcpy(cmdNew, command); } /* Free the old command, if any */ if (cmdOld) Tcl_Free(cmdOld); /* Save command associated with this binding */ valuePtr->command = cmdNew; return TCL_OK; } int QE_DeleteBinding(QE_BindingTable bindingTable, ClientData object, char *eventString) { BindingTable *bindPtr = (BindingTable *) bindingTable; BindValue *valuePtr, **valueList; /* Delete all bindings on this object */ if (eventString == NULL) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_DString dString; int i, count = 0; Tcl_DStringInit(&dString); hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); while (hPtr != NULL) { valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); while (valuePtr != NULL) { if (valuePtr->object == object) { Tcl_DStringAppend(&dString, (char *) &valuePtr, sizeof(valuePtr)); count++; break; } valuePtr = valuePtr->nextValue; } hPtr = Tcl_NextHashEntry(&search); } valueList = (BindValue **) Tcl_DStringValue(&dString); for (i = 0; i < count; i++) DeleteBinding(bindPtr, valueList[i]); Tcl_DStringFree(&dString); return TCL_OK; } if (FindSequence(bindPtr, object, eventString, 0, NULL, &valuePtr) != TCL_OK) return TCL_ERROR; if (valuePtr == NULL) { Tcl_ResetResult(bindPtr->interp); return TCL_OK; } DeleteBinding(bindPtr, valuePtr); return TCL_OK; } static int DeleteBinding(BindingTable *bindPtr, BindValue *valuePtr) { Tcl_HashEntry *hPtr; BindValue *listPtr; ObjectTableKey keyObj; PatternTableKey keyPat; /* Delete the objectTable entry */ keyObj.type = valuePtr->type; keyObj.detail = valuePtr->detail; keyObj.object = valuePtr->object; hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) &keyObj); if (hPtr == NULL) return TCL_ERROR; /* fatal error */ Tcl_DeleteHashEntry(hPtr); /* Find the patternTable entry for this type/detail */ keyPat.type = valuePtr->type; keyPat.detail = valuePtr->detail; hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &keyPat); if (hPtr == NULL) return TCL_ERROR; /* fatal error */ /* * Get the patternTable value. This is the head of a list of * BindValue's that match the type/detail, but for different * objects; */ listPtr = (BindValue *) Tcl_GetHashValue(hPtr); /* The deleted BindValue is the first */ if (listPtr == valuePtr) { /* The deleted BindValue was the only one in the list */ if (valuePtr->nextValue == NULL) { if (debug_bindings) dbwin("QE_DeleteBinding: Deleted pattern type=%d detail=%d\n", valuePtr->type, valuePtr->detail); Tcl_DeleteHashEntry(hPtr); } /* The next BindValue is the new head of the list */ else { Tcl_SetHashValue(hPtr, valuePtr->nextValue); } } /* Look for the deleted BindValue in the list, and remove it */ else { while (1) { if (listPtr->nextValue == NULL) return TCL_ERROR; /* fatal */ if (listPtr->nextValue == valuePtr) { if (debug_bindings) dbwin("QE_DeleteBinding: Unlinked binding type=%d detail=%d\n", valuePtr->type, valuePtr->detail); listPtr->nextValue = valuePtr->nextValue; break; } listPtr = listPtr->nextValue; } } #if DELETE_WIN_BINDINGS { char *winName = (char *) valuePtr->object; if (winName[0] == '.') { WinTableValue *cd; hPtr = Tcl_FindHashEntry(&bindPtr->winTable, winName); if (hPtr == NULL) return TCL_ERROR; /* fatal error */ cd = (WinTableValue *) Tcl_GetHashValue(hPtr); cd->count--; if (cd->count == 0) { Tk_DeleteEventHandler(cd->tkwin, StructureNotifyMask, TkWinEventProc, (ClientData) cd); Tcl_Free((char *) cd); Tcl_DeleteHashEntry(hPtr); } } } #endif Tcl_Free((char *) valuePtr->command); memset((char *) valuePtr, 0xAA, sizeof(BindValue)); Tcl_Free((char *) valuePtr); return TCL_OK; } int QE_GetAllObjects(QE_BindingTable bindingTable) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_DString dString; ClientData *objectList; int i, count = 0; Tcl_Obj *listObj; Tcl_DStringInit(&dString); hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); while (hPtr != NULL) { BindValue *valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); while (valuePtr != NULL) { objectList = (ClientData *) Tcl_DStringValue(&dString); for (i = 0; i < count; i++) { if (objectList[i] == valuePtr->object) break; } if (i >= count) { Tcl_DStringAppend(&dString, (char *) &valuePtr->object, sizeof(ClientData)); count++; } valuePtr = valuePtr->nextValue; } hPtr = Tcl_NextHashEntry(&search); } if (count > 0) { listObj = Tcl_NewListObj(0, NULL); objectList = (ClientData *) Tcl_DStringValue(&dString); for (i = 0; i < count; i++) { Tcl_ListObjAppendElement(bindPtr->interp, listObj, Tcl_NewStringObj((char *) objectList[i], -1)); } Tcl_SetObjResult(bindPtr->interp, listObj); } Tcl_DStringFree(&dString); return TCL_OK; } int QE_GetBinding(QE_BindingTable bindingTable, ClientData object, char *eventString) { BindingTable *bindPtr = (BindingTable *) bindingTable; BindValue *valuePtr; if (FindSequence(bindPtr, object, eventString, 0, NULL, &valuePtr) != TCL_OK) return TCL_ERROR; if (valuePtr == NULL) return TCL_OK; Tcl_SetObjResult(bindPtr->interp, Tcl_NewStringObj(valuePtr->command, -1)); return TCL_OK; } static void GetPatternString(BindingTable *bindPtr, BindValue *bindValue, Tcl_DString *dString) { EventInfo *eiPtr; eiPtr = FindEvent(bindPtr, bindValue->type); if (eiPtr != NULL) { Tcl_DStringAppend(dString, "<", 1); Tcl_DStringAppend(dString, eiPtr->name, -1); if (bindValue->detail) { Detail *detail = FindDetail(bindPtr, bindValue->type, bindValue->detail); if (detail != NULL) { Tcl_DStringAppend(dString, "-", 1); Tcl_DStringAppend(dString, detail->name, -1); } } Tcl_DStringAppend(dString, ">", 1); } } int QE_GetAllBindings(QE_BindingTable bindingTable, ClientData object) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_DString dString; Tcl_DStringInit(&dString); hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); while (hPtr != NULL) { BindValue *valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); while (valuePtr != NULL) { if (valuePtr->object == object) { Tcl_DStringSetLength(&dString, 0); GetPatternString(bindPtr, valuePtr, &dString); Tcl_AppendElement(bindPtr->interp, Tcl_DStringValue(&dString)); break; } valuePtr = valuePtr->nextValue; } hPtr = Tcl_NextHashEntry(&search); } Tcl_DStringFree(&dString); return TCL_OK; } int QE_GetEventNames(QE_BindingTable bindingTable) { BindingTable *bindPtr = (BindingTable *) bindingTable; EventInfo *eiPtr; for (eiPtr = bindPtr->eventList; eiPtr != NULL; eiPtr = eiPtr->next) { Tcl_AppendElement(bindPtr->interp, eiPtr->name); } return TCL_OK; } int QE_GetDetailNames(QE_BindingTable bindingTable, char *eventName) { BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_HashEntry *hPtr; EventInfo *eiPtr; Detail *dPtr; hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown event \"", eventName, "\"", NULL); return TCL_ERROR; } eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dPtr->next) { Tcl_AppendElement(bindPtr->interp, dPtr->name); } return TCL_OK; } static void ExpandPercents(BindingTable *bindPtr, ClientData object, char *command, QE_Event *eventPtr, QE_ExpandProc expandProc, Tcl_DString *result) { char *string; QE_ExpandArgs expandArgs; #if 0 Tcl_DStringSetLength(result, 0); if (debug_bindings) dbwin("ExpandPercents on '%s' name=%s type=%d detail=%d expand=%lu\n", object, eiPtr->name, eiPtr->type, eventPtr->detail, eiPtr->expand); #endif expandArgs.bindingTable = (QE_BindingTable) bindPtr; expandArgs.object = object; expandArgs.event = eventPtr->type; expandArgs.detail = eventPtr->detail; expandArgs.result = result; expandArgs.clientData = eventPtr->clientData; while (1) { for (string = command; (*string != 0) && (*string != '%'); string++) { /* Empty loop body. */ } if (string != command) { Tcl_DStringAppend(result, command, string - command); command = string; } if (*command == 0) { break; } /* Expand % here */ expandArgs.which = command[1]; (*expandProc)(&expandArgs); command += 2; } } static void BindEvent(BindingTable *bindPtr, QE_Event *eventPtr, int wantDetail, EventInfo *eiPtr, Detail *dPtr, GenerateData *gdPtr) { Tcl_HashEntry *hPtr; BindValue *valuePtr; ObjectTableKey keyObj; PatternTableKey key; Tcl_DString scripts, savedResult; int code; char *p, *end; char *command = gdPtr ? gdPtr->command : NULL; /* Find the first BindValue for this event */ key.type = eventPtr->type; key.detail = wantDetail ? eventPtr->detail : 0; hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key); if (hPtr == NULL) return; /* Collect all scripts, with % expanded, separated by null characters. * Do it this way because anything could happen while evaluating, including * uninstalling events/details, even the interpreter being deleted. */ Tcl_DStringInit(&scripts); for (valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); valuePtr; valuePtr = valuePtr->nextValue) { if (wantDetail && valuePtr->detail) { keyObj.type = key.type; keyObj.detail = 0; keyObj.object = valuePtr->object; hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) &keyObj); if (hPtr != NULL) { BindValue *value2Ptr; value2Ptr = (BindValue *) Tcl_GetHashValue(hPtr); value2Ptr->specific = 1; } } /* * If a binding for a more-specific event exists for this object * and event-type, and this is a binding for a less-specific * event, then skip this binding, since the binding for the * more-specific event was already invoked. */ else if (!wantDetail && valuePtr->specific) { if (debug_bindings) dbwin("QE_BindEvent: Skipping less-specific event type=%d object='%s'\n", valuePtr->type, (char *) valuePtr->object); valuePtr->specific = 0; continue; } #if BIND_ACTIVE /* This binding isn't active */ if (valuePtr->active == 0) continue; #endif /* BIND_ACTIVE */ #if ALLOW_INSTALL if (command == NULL) { if ((dPtr != NULL) && (dPtr->command != NULL)) { command = dPtr->command; } else if (((dPtr == NULL) || ((dPtr != NULL) && (dPtr->expandProc == NULL))) && (eiPtr->command != NULL)) { command = eiPtr->command; } } #endif /* ALLOW_INSTALL */ /* called by QE_GenerateCmd */ if (command != NULL) { PercentsData data; data.gdPtr = gdPtr; data.command = command; data.eventPtr = eiPtr; data.detailPtr = dPtr; eventPtr->clientData = (ClientData) &data; ExpandPercents(bindPtr, valuePtr->object, valuePtr->command, eventPtr, Percents_Command, &scripts); } /* called by QE_GenerateCmd */ else if (gdPtr != NULL) { /* Called QE_GenerateCmd with: * a) a static event and no percentsCommand argument, or * b) a dynamic event with no percentsCommand installed and * no percentsCommand argument */ eventPtr->clientData = (ClientData) gdPtr; ExpandPercents(bindPtr, valuePtr->object, valuePtr->command, eventPtr, Percents_CharMap, &scripts); } else { QE_ExpandProc expandProc = ((dPtr != NULL) && (dPtr->expandProc != NULL)) ? dPtr->expandProc : eiPtr->expandProc; ExpandPercents(bindPtr, valuePtr->object, valuePtr->command, eventPtr, expandProc, &scripts); } /* Separate each script by '\0' */ Tcl_DStringAppend(&scripts, "", 1); Tcl_DStringAppend(&scripts, eiPtr->name, -1); Tcl_DStringAppend(&scripts, "", 1); Tcl_DStringAppend(&scripts, (valuePtr->detail && dPtr) ? dPtr->name : "", -1); Tcl_DStringAppend(&scripts, "", 1); Tcl_DStringAppend(&scripts, valuePtr->object, -1); Tcl_DStringAppend(&scripts, "", 1); } /* Nothing to do. No need to call Tcl_DStringFree(&scripts) */ if (Tcl_DStringLength(&scripts) == 0) return; /* * As in Tk bindings, we expect that bindings may be invoked * in the middle of Tcl commands. So we preserve the current * interpreter result and restore it later. */ Tcl_DStringInit(&savedResult); Tcl_DStringGetResult(bindPtr->interp, &savedResult); p = Tcl_DStringValue(&scripts); end = p + Tcl_DStringLength(&scripts); while (p < end) { code = Tcl_GlobalEval(bindPtr->interp, p); p += strlen(p); p++; if (code != TCL_OK) { if (code == TCL_CONTINUE) { /* Nothing */ } else if (code == TCL_BREAK) { /* Nothing */ } else { char buf[256]; char *eventName = p; char *detailName = p + strlen(p) + 1; char *object = detailName + strlen(detailName) + 1; (void) sprintf(buf, "\n (<%s%s%s> binding on %s)", eventName, detailName[0] ? "-" : "", detailName, object); Tcl_AddErrorInfo(bindPtr->interp, buf); Tcl_BackgroundError(bindPtr->interp); } } /* Skip event\0detail\0object\0 */ p += strlen(p); p++; p += strlen(p); p++; p += strlen(p); p++; } Tcl_DStringFree(&scripts); /* Restore the interpreter result */ Tcl_DStringResult(bindPtr->interp, &savedResult); } static int BindEventWrapper(QE_BindingTable bindingTable, QE_Event *eventPtr, GenerateData *gdPtr) { BindingTable *bindPtr = (BindingTable *) bindingTable; Detail *dPtr = NULL; EventInfo *eiPtr; /* Find the event */ eiPtr = FindEvent(bindPtr, eventPtr->type); if (eiPtr == NULL) return TCL_OK; /* Find the detail */ if (eventPtr->detail) { dPtr = FindDetail(bindPtr, eventPtr->type, eventPtr->detail); if (dPtr == NULL) return TCL_OK; } BindEvent(bindPtr, eventPtr, 1, eiPtr, dPtr, gdPtr); if (eventPtr->detail) BindEvent(bindPtr, eventPtr, 0, eiPtr, dPtr, gdPtr); return TCL_OK; } int QE_BindEvent(QE_BindingTable bindingTable, QE_Event *eventPtr) { return BindEventWrapper(bindingTable, eventPtr, NULL); } static char *GetField(char *p, char *copy, int size) { int ch = *p; while ((ch != '\0') && !isspace(UCHAR(ch)) && ((ch != '>') || (p[1] != '\0')) && (ch != '-') && (size > 1)) { *copy = ch; p++; copy++; size--; ch = *p; } *copy = '\0'; while ((*p == '-') || isspace(UCHAR(*p))) { p++; } return p; } #define FIELD_SIZE 48 static int ParseEventDescription1(BindingTable *bindPtr, char *pattern, char eventName[FIELD_SIZE], char detailName[FIELD_SIZE]) { Tcl_Interp *interp = bindPtr->interp; char *p = pattern; eventName[0] = detailName[0] = '\0'; /* First char must by opening < */ if (*p != '<') { Tcl_AppendResult(interp, "missing \"<\" in event pattern \"", pattern, "\"", (char *) NULL); return TCL_ERROR; } p++; /* Event name (required)*/ p = GetField(p, eventName, FIELD_SIZE); if (debug_bindings) dbwin("GetField='%s'\n", eventName); /* Terminating > */ if (*p == '>') return TCL_OK; /* Detail name (optional) */ p = GetField(p, detailName, FIELD_SIZE); if (debug_bindings) dbwin("GetField='%s'\n", detailName); /* Terminating > */ if (*p != '>') { Tcl_AppendResult(interp, "missing \">\" in event pattern \"", pattern, "\"", (char *) NULL); return TCL_ERROR; } return TCL_OK; } static int ParseEventDescription(BindingTable *bindPtr, char *eventString, Pattern *patPtr, EventInfo **eventInfoPtr, Detail **detailPtr) { Tcl_Interp *interp = bindPtr->interp; Tcl_HashEntry *hPtr; char eventName[FIELD_SIZE], detailName[FIELD_SIZE]; EventInfo *eiPtr; Detail *dPtr; char errorMsg[512]; if (eventInfoPtr) *eventInfoPtr = NULL; if (detailPtr) *detailPtr = NULL; patPtr->type = -1; patPtr->detail = 0; if (ParseEventDescription1(bindPtr, eventString, eventName, detailName) != TCL_OK) return TCL_ERROR; hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) { sprintf(errorMsg, "unknown event \"%.128s\"", eventName); Tcl_SetResult(interp, errorMsg, TCL_VOLATILE); return TCL_ERROR; } eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); patPtr->type = eiPtr->type; if (eventInfoPtr) *eventInfoPtr = eiPtr; if (detailName[0] != '\0') { /* Find detail for the matching event */ for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dPtr->next) { if (strcmp(dPtr->name, detailName) == 0) break; } if (dPtr == NULL) { sprintf(errorMsg, "unknown detail \"%.128s\" for event \"%.128s\"", detailName, eiPtr->name); Tcl_SetResult(interp, errorMsg, TCL_VOLATILE); return TCL_ERROR; } patPtr->detail = dPtr->code; if (detailPtr) *detailPtr = dPtr; } return TCL_OK; } static int FindSequence(BindingTable *bindPtr, ClientData object, char *eventString, int create, int *created, BindValue **result) { Tcl_HashEntry *hPtr; Pattern pats; ObjectTableKey key; BindValue *valuePtr; int isNew; if (debug_bindings) dbwin("FindSequence object='%s' pattern='%s'...\n", (char *) object, eventString); if (created) (*created) = 0; /* Event description -> Pattern */ if (ParseEventDescription(bindPtr, eventString, &pats, NULL, NULL) != TCL_OK) return TCL_ERROR; /* type + detail + object -> BindValue */ key.type = pats.type; key.detail = pats.detail; key.object = object; if (create) { hPtr = Tcl_CreateHashEntry(&bindPtr->objectTable, (char *) &key, &isNew); if (isNew) { if (debug_bindings) dbwin("New BindValue for '%s' type=%d detail=%d\n", (char *) object, pats.type, pats.detail); valuePtr = (BindValue *) Tcl_Alloc(sizeof(BindValue)); valuePtr->type = pats.type; valuePtr->detail = pats.detail; valuePtr->object = object; valuePtr->command = NULL; valuePtr->specific = 0; valuePtr->nextValue = NULL; #if BIND_ACTIVE /* This binding is active */ valuePtr->active = 1; #endif /* BIND_ACTIVE */ Tcl_SetHashValue(hPtr, (ClientData) valuePtr); } if (created) (*created) = isNew; (*result) = (BindValue *) Tcl_GetHashValue(hPtr); return TCL_OK; } /* Look for existing objectTable entry */ hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) &key); if (hPtr == NULL) { (*result) = NULL; return TCL_OK; } (*result) = (BindValue *) Tcl_GetHashValue(hPtr); return TCL_OK; } void QE_ExpandDouble(double number, Tcl_DString *result) { char numStorage[TCL_DOUBLE_SPACE]; Tcl_PrintDouble((Tcl_Interp *) NULL, number, numStorage); Tcl_DStringAppend(result, numStorage, -1); /* QE_ExpandString(numStorage, result); */ } void QE_ExpandNumber(long number, Tcl_DString *result) { char numStorage[TCL_INTEGER_SPACE]; (void) sprintf(numStorage, "%ld", number); Tcl_DStringAppend(result, numStorage, -1); /* QE_ExpandString(numStorage, result); */ } void QE_ExpandString(char *string, Tcl_DString *result) { int length, spaceNeeded, cvtFlags; spaceNeeded = Tcl_ScanElement(string, &cvtFlags); length = Tcl_DStringLength(result); Tcl_DStringSetLength(result, length + spaceNeeded); spaceNeeded = Tcl_ConvertElement(string, Tcl_DStringValue(result) + length, cvtFlags | TCL_DONT_USE_BRACES); Tcl_DStringSetLength(result, length + spaceNeeded); } void QE_ExpandUnknown(char which, Tcl_DString *result) { char string[2]; (void) sprintf(string, "%c", which); QE_ExpandString(string, result); } void QE_ExpandEvent(QE_BindingTable bindingTable, int eventType, Tcl_DString *result) { BindingTable *bindPtr = (BindingTable *) bindingTable; EventInfo *eiPtr = FindEvent(bindPtr, eventType); if (eiPtr != NULL) QE_ExpandString((char *) eiPtr->name, result); else QE_ExpandString("unknown", result); } void QE_ExpandDetail(QE_BindingTable bindingTable, int event, int detail, Tcl_DString *result) { BindingTable *bindPtr = (BindingTable *) bindingTable; Detail *dPtr; if (detail == 0) { QE_ExpandString("", result); return; } dPtr = FindDetail(bindPtr, event, detail); if (dPtr != NULL) QE_ExpandString((char *) dPtr->name, result); else QE_ExpandString("unknown", result); } void QE_ExpandPattern(QE_BindingTable bindingTable, int eventType, int detail, Tcl_DString *result) { BindingTable *bindPtr = (BindingTable *) bindingTable; EventInfo *eiPtr = FindEvent(bindPtr, eventType); Tcl_DStringAppend(result, "<", 1); Tcl_DStringAppend(result, eiPtr ? eiPtr->name : "unknown", -1); if (detail) { Detail *dPtr = FindDetail(bindPtr, eventType, detail); Tcl_DStringAppend(result, "-", 1); Tcl_DStringAppend(result, dPtr ? dPtr->name : "unknown", -1); } Tcl_DStringAppend(result, ">", 1); } int QE_BindCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; Tk_Window tkwin = Tk_MainWindow(bindPtr->interp); ClientData object; char *string; if ((objC < 1) || (objC > 4)) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "?object? ?pattern? ?script?"); return TCL_ERROR; } if (objC == 1) { QE_GetAllObjects(bindingTable); return TCL_OK; } string = Tcl_GetString(objV[1]); if (string[0] == '.') { Tk_Window tkwin2; tkwin2 = Tk_NameToWindow(bindPtr->interp, string, tkwin); if (tkwin2 == NULL) { return TCL_ERROR; } object = (ClientData) Tk_GetUid(Tk_PathName(tkwin2)); } else { object = (ClientData) Tk_GetUid(string); } if (objC == 4) { int append = 0; char *sequence = Tcl_GetString(objV[2]); char *script = Tcl_GetString(objV[3]); if (script[0] == 0) { return QE_DeleteBinding(bindingTable, object, sequence); } if (script[0] == '+') { script++; append = 1; } return QE_CreateBinding(bindingTable, object, sequence, script, append); } else if (objC == 3) { char *sequence = Tcl_GetString(objV[2]); return QE_GetBinding(bindingTable, object, sequence); } else { QE_GetAllBindings(bindingTable, object); } return TCL_OK; } int QE_UnbindCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; Tk_Window tkwin = Tk_MainWindow(bindPtr->interp); ClientData object; char *string, *sequence; if ((objC < 2) || (objC > 3)) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "object ?pattern?"); return TCL_ERROR; } string = Tcl_GetString(objV[1]); if (string[0] == '.') { Tk_Window tkwin2; tkwin2 = Tk_NameToWindow(bindPtr->interp, string, tkwin); if (tkwin2 == NULL) { return TCL_ERROR; } object = (ClientData) Tk_GetUid(Tk_PathName(tkwin2)); } else { object = (ClientData) Tk_GetUid(string); } if (objC == 2) { return QE_DeleteBinding(bindingTable, object, NULL); } sequence = Tcl_GetString(objV[2]); return QE_DeleteBinding(bindingTable, object, sequence); } /* * qegenerate -- Generate events from scripts. * Usage: qegenerate $pattern ?$charMap? ?$percentsCommand? * Desciption: Scripts can generate "fake" quasi-events by providing * a quasi-event pattern and option field/value pairs. */ int QE_GenerateCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; QE_Event fakeEvent; EventInfo *eiPtr; Detail *dPtr; GenerateData genData; GenerateField *fieldPtr; char *p, *t; int listObjc; int i; Tcl_Obj **listObjv; Pattern pats; int result; if (objC < 2 || objC > 4) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern ?charMap? ?percentsCommand?"); return TCL_ERROR; } p = Tcl_GetStringFromObj(objV[1], NULL); if (ParseEventDescription(bindPtr, p, &pats, &eiPtr, &dPtr) != TCL_OK) return TCL_ERROR; /* Can't generate an event without a detail */ if ((dPtr == NULL) && (eiPtr->detailList != NULL)) { Tcl_AppendResult(bindPtr->interp, "cannot generate \"", p, "\": missing detail", (char *) NULL); return TCL_ERROR; } if (objC >= 3) { if (Tcl_ListObjGetElements(bindPtr->interp, objV[2], &listObjc, &listObjv) != TCL_OK) return TCL_ERROR; if (listObjc & 1) { Tcl_AppendResult(bindPtr->interp, "char map must have even number of elements", (char *) NULL); return TCL_ERROR; } genData.count = listObjc / 2; genData.field = genData.staticField; if (genData.count > sizeof(genData.staticField) / sizeof(genData.staticField[0])) { genData.field = (GenerateField *) Tcl_Alloc(sizeof(GenerateField) * genData.count); } genData.count = 0; while (listObjc > 1) { int length; t = Tcl_GetStringFromObj(listObjv[0], &length); if (length != 1) { Tcl_AppendResult(bindPtr->interp, "invalid percent char \"", t, "\"", NULL); result = TCL_ERROR; goto done; } /* Duplicate %-chars result in last duplicate being used */ fieldPtr = NULL; for (i = 0; i < genData.count; i++) { if (genData.field[i].which == t[0]) { fieldPtr = &genData.field[i]; break; } } if (fieldPtr == NULL) fieldPtr = &genData.field[genData.count++]; fieldPtr->which = t[0]; fieldPtr->string = Tcl_GetStringFromObj(listObjv[1], NULL); listObjv += 2; listObjc -= 2; } } else { genData.count = 0; genData.field = genData.staticField; } if (objC == 4) { genData.command = Tcl_GetString(objV[3]); } else { genData.command = NULL; } fakeEvent.type = pats.type; fakeEvent.detail = pats.detail; fakeEvent.clientData = NULL; result = BindEventWrapper(bindingTable, &fakeEvent, &genData); done: if (genData.field != genData.staticField) Tcl_Free((char *) genData.field); return result; } #if BIND_ACTIVE /* qeconfigure $win -active no */ int QE_ConfigureCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; Tcl_Interp *interp = bindPtr->interp; Tk_Window tkwin = Tk_MainWindow(interp); static CONST char *configSwitch[] = {"-active", NULL}; Tcl_Obj *CONST *objPtr; BindValue *valuePtr; char *t, *eventString; int index; ClientData object; if (objC < 3) { Tcl_WrongNumArgs(interp, objOffset + 1, objv, "object pattern ?option? ?value? ?option value ...?"); return TCL_ERROR; } t = Tcl_GetStringFromObj(objV[1], NULL); eventString = Tcl_GetStringFromObj(objV[2], NULL); if (t[0] == '.') { Tk_Window tkwin2; tkwin2 = Tk_NameToWindow(interp, t, tkwin); if (tkwin2 == NULL) { return TCL_ERROR; } object = (ClientData) Tk_GetUid(Tk_PathName(tkwin2)); } else { object = (ClientData) Tk_GetUid(t); } if (FindSequence(bindPtr, object, eventString, 0, NULL, &valuePtr) != TCL_OK) return TCL_ERROR; if (valuePtr == NULL) return TCL_OK; objPtr = objv + objOffset + 3; objc -= objOffset + 3; if (objc == 0) { Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj("-active", -1)); Tcl_ListObjAppendElement(interp, listObj, Tcl_NewBooleanObj(valuePtr->active)); Tcl_SetObjResult(interp, listObj); return TCL_OK; } if (objc == 1) { if (Tcl_GetIndexFromObj(interp, objPtr[0], configSwitch, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case 0: /* -active */ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(valuePtr->active)); break; } return TCL_OK; } while (objc > 1) { if (Tcl_GetIndexFromObj(interp, objPtr[0], configSwitch, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case 0: /* -active */ if (Tcl_GetBooleanFromObj(interp, objPtr[1], &valuePtr->active) != TCL_OK) { return TCL_ERROR; } break; } objPtr += 2; objc -= 2; } return TCL_OK; } #endif /* BIND_ACTIVE */ /* Perform %-substitution with $charMap only */ static void Percents_CharMap(QE_ExpandArgs *args) { GenerateData *gdPtr = (GenerateData *) args->clientData; int i; for (i = 0; i < gdPtr->count; i++) { GenerateField *gfPtr = &gdPtr->field[i]; if (gfPtr->which == args->which) { QE_ExpandString(gfPtr->string, args->result); return; } } QE_ExpandUnknown(args->which, args->result); } /* Perform %-substitution by calling a Tcl command */ static void Percents_Command(QE_ExpandArgs *args) { BindingTable *bindPtr = (BindingTable *) args->bindingTable; Tcl_Interp *interp = bindPtr->interp; PercentsData *data = (PercentsData *) args->clientData; GenerateData *gdPtr = data->gdPtr; EventInfo *eiPtr = data->eventPtr; Detail *dPtr = data->detailPtr; Tcl_DString command; Tcl_SavedResult state; int i; Tcl_DStringInit(&command); Tcl_DStringAppend(&command, data->command, -1); Tcl_DStringAppend(&command, " ", 1); Tcl_DStringAppend(&command, &args->which, 1); Tcl_DStringAppend(&command, " ", 1); Tcl_DStringAppend(&command, (char *) args->object, -1); Tcl_DStringAppend(&command, " ", 1); Tcl_DStringAppend(&command, eiPtr->name, -1); Tcl_DStringAppend(&command, " ", 1); if (dPtr != NULL) Tcl_DStringAppend(&command, dPtr->name, -1); else Tcl_DStringAppend(&command, "{}", -1); Tcl_DStringStartSublist(&command); for (i = 0; i < gdPtr->count; i++) { GenerateField *genField = &gdPtr->field[i]; char string[2]; string[0] = genField->which; string[1] = '\0'; Tcl_DStringAppendElement(&command, string); Tcl_DStringAppendElement(&command, genField->string); } Tcl_DStringEndSublist(&command); Tcl_SaveResult(interp, &state); if (Tcl_EvalEx(interp, Tcl_DStringValue(&command), Tcl_DStringLength(&command), TCL_EVAL_GLOBAL) == TCL_OK) { QE_ExpandString(Tcl_GetStringFromObj(Tcl_GetObjResult(interp), NULL), args->result); } else { QE_ExpandUnknown(args->which, args->result); Tcl_AddErrorInfo(interp, "\n (expanding percents)"); Tcl_BackgroundError(interp); } Tcl_RestoreResult(interp, &state); Tcl_DStringFree(&command); } #if ALLOW_INSTALL int QE_InstallCmd_New(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *pattern, *command = NULL; char eventName[FIELD_SIZE], detailName[FIELD_SIZE]; int id, length; EventInfo *eiPtr; Detail *dPtr = NULL; Tcl_HashEntry *hPtr; if (objC < 2 || objC > 3) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern ?percentsCommand?"); return TCL_ERROR; } pattern = Tcl_GetString(objV[1]); if (ParseEventDescription1(bindPtr, pattern, eventName, detailName) != TCL_OK) return TCL_ERROR; hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); /* The event is not defined */ if (hPtr == NULL) { id = QE_InstallEvent(bindingTable, eventName, NULL); if (id == 0) return TCL_ERROR; /* Find the event we just installed */ hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) return TCL_ERROR; eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); /* Mark as installed-by-script */ eiPtr->dynamic = 1; } /* The event is already defined */ else { eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); } if (detailName[0]) { for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dPtr->next) { if (strcmp(dPtr->name, detailName) == 0) break; } /* The detail is not defined */ if (dPtr == NULL) { /* Define the new detail */ id = QE_InstallDetail(bindingTable, detailName, eiPtr->type, NULL); if (id == 0) return TCL_ERROR; /* Get the detail we just defined */ dPtr = FindDetail(bindPtr, eiPtr->type, id); if (dPtr == NULL) return TCL_ERROR; /* Mark as installed-by-script */ dPtr->dynamic = 1; } } if (objC == 3) command = Tcl_GetStringFromObj(objV[2], &length); if (dPtr != NULL) { if (!dPtr->dynamic) { Tcl_AppendResult(bindPtr->interp, pattern, " is not dynamic", NULL); return TCL_ERROR; } if (command != NULL) { if (dPtr->command) { Tcl_Free(dPtr->command); dPtr->command = NULL; } if (length) { dPtr->command = Tcl_Alloc(length + 1); (void) strcpy(dPtr->command, command); } } if (dPtr->command) Tcl_SetResult(bindPtr->interp, dPtr->command, TCL_VOLATILE); } else { if (!eiPtr->dynamic) { Tcl_AppendResult(bindPtr->interp, pattern, " is not dynamic", NULL); return TCL_ERROR; } if (command != NULL) { if (eiPtr->command) { Tcl_Free(eiPtr->command); eiPtr->command = NULL; } if (length) { eiPtr->command = Tcl_Alloc(length + 1); (void) strcpy(eiPtr->command, command); } } if (eiPtr->command) Tcl_SetResult(bindPtr->interp, eiPtr->command, TCL_VOLATILE); } return TCL_OK; } int QE_InstallCmd_Old(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; static CONST char *commandOption[] = {"detail", "event", NULL}; int index; if (objC < 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "option arg ..."); return TCL_ERROR; } if (Tcl_GetIndexFromObj(bindPtr->interp, objV[1], commandOption, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case 0: /* detail */ { char *eventName, *detailName, *command; int id, length; Detail *dPtr; EventInfo *eiPtr; Tcl_HashEntry *hPtr; if ((objC < 4) || (objC > 5)) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 2, objv, "event detail ?percentsCommand?"); return TCL_ERROR; } /* Find the event type */ eventName = Tcl_GetStringFromObj(objV[2], NULL); hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown event \"", eventName, "\"", NULL); return TCL_ERROR; } eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); /* Get the detail name */ detailName = Tcl_GetStringFromObj(objV[3], NULL); /* Define the new detail */ id = QE_InstallDetail(bindingTable, detailName, eiPtr->type, NULL); if (id == 0) return TCL_ERROR; /* Get the detail we just defined */ dPtr = FindDetail(bindPtr, eiPtr->type, id); if (dPtr == NULL) return TCL_ERROR; dPtr->dynamic = 1; if (objC == 4) break; /* Set the Tcl command for this detail */ command = Tcl_GetStringFromObj(objV[4], &length); if (length) { dPtr->command = Tcl_Alloc(length + 1); (void) strcpy(dPtr->command, command); } break; } case 1: /* event */ { char *eventName, *command; int id, length; EventInfo *eiPtr; Tcl_HashEntry *hPtr; if (objC < 3 || objC > 4) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 2, objv, "name ?percentsCommand?"); return TCL_ERROR; } eventName = Tcl_GetStringFromObj(objV[2], NULL); id = QE_InstallEvent(bindingTable, eventName, NULL); if (id == 0) return TCL_ERROR; /* Find the event we just installed */ hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) return TCL_ERROR; eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); /* Mark as installed-by-script */ eiPtr->dynamic = 1; if (objC == 3) break; /* Set the Tcl command for this event */ command = Tcl_GetStringFromObj(objV[3], &length); if (length) { eiPtr->command = Tcl_Alloc(length + 1); (void) strcpy(eiPtr->command, command); } break; } } return TCL_OK; } int QE_InstallCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *s; int length; if (objC < 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern ?percentsCommand?"); return TCL_ERROR; } s = Tcl_GetStringFromObj(objV[1], &length); if (length && (!strcmp(s, "detail") || !strcmp(s, "event"))) return QE_InstallCmd_Old(bindingTable, objOffset, objc, objv); return QE_InstallCmd_New(bindingTable, objOffset, objc, objv); } int QE_UninstallCmd_New(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *pattern; Pattern pats; EventInfo *eiPtr; Detail *dPtr; if (objC != 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern"); return TCL_ERROR; } pattern = Tcl_GetString(objV[1]); if (ParseEventDescription(bindPtr, pattern, &pats, &eiPtr, &dPtr) != TCL_OK) return TCL_ERROR; if (dPtr != NULL) { if (!dPtr->dynamic) { Tcl_AppendResult(bindPtr->interp, "can't uninstall static detail \"", dPtr->name, "\"", NULL); return TCL_ERROR; } return QE_UninstallDetail(bindingTable, eiPtr->type, dPtr->code); } if (!eiPtr->dynamic) { Tcl_AppendResult(bindPtr->interp, "can't uninstall static event \"", eiPtr->name, "\"", NULL); return TCL_ERROR; } return QE_UninstallEvent(bindingTable, eiPtr->type); } int QE_UninstallCmd_Old(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; static CONST char *commandOption[] = {"detail", "event", NULL}; int index; if (objC < 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "option arg ..."); return TCL_ERROR; } if (Tcl_GetIndexFromObj(bindPtr->interp, objV[1], commandOption, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case 0: /* detail */ { char *eventName, *detailName; Detail *dPtr; EventInfo *eiPtr; Tcl_HashEntry *hPtr; if (objC != 4) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 2, objv, "event detail"); return TCL_ERROR; } /* Find the event type */ eventName = Tcl_GetStringFromObj(objV[2], NULL); hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown event \"", eventName, "\"", NULL); return TCL_ERROR; } eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); /* Get the detail name */ detailName = Tcl_GetStringFromObj(objV[3], NULL); for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dPtr->next) { if (strcmp(dPtr->name, detailName) == 0) break; } if (dPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown detail \"", detailName, "\" for event \"", eiPtr->name, "\"", NULL); return TCL_ERROR; } if (!dPtr->dynamic) { Tcl_AppendResult(bindPtr->interp, "can't uninstall static detail \"", detailName, "\"", NULL); return TCL_ERROR; } return QE_UninstallDetail(bindingTable, eiPtr->type, dPtr->code); } case 1: /* event */ { Tcl_HashEntry *hPtr; EventInfo *eiPtr; char *eventName; if (objC != 3) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 2, objv, "name"); return TCL_ERROR; } /* Find the event type */ eventName = Tcl_GetStringFromObj(objV[2], NULL); hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown event \"", eventName, "\"", NULL); return TCL_ERROR; } eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); if (!eiPtr->dynamic) { Tcl_AppendResult(bindPtr->interp, "can't uninstall static event \"", eventName, "\"", NULL); return TCL_ERROR; } return QE_UninstallEvent(bindingTable, eiPtr->type); } } return TCL_OK; } int QE_UninstallCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *s; int length; if (objC < 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern"); return TCL_ERROR; } s = Tcl_GetStringFromObj(objV[1], &length); if (length && (!strcmp(s, "detail") || !strcmp(s, "event"))) return QE_UninstallCmd_Old(bindingTable, objOffset, objc, objv); return QE_UninstallCmd_New(bindingTable, objOffset, objc, objv); } int QE_LinkageCmd_New(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *pattern; Pattern pats; EventInfo *eiPtr; Detail *dPtr; if (objC != 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern"); return TCL_ERROR; } pattern = Tcl_GetString(objV[1]); if (ParseEventDescription(bindPtr, pattern, &pats, &eiPtr, &dPtr) != TCL_OK) return TCL_ERROR; if (dPtr != NULL) { Tcl_SetResult(bindPtr->interp, dPtr->dynamic ? "dynamic" : "static", TCL_STATIC); return TCL_OK; } Tcl_SetResult(bindPtr->interp, eiPtr->dynamic ? "dynamic" : "static", TCL_STATIC); return TCL_OK; } int QE_LinkageCmd_Old(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *eventName, *detailName; Detail *dPtr; EventInfo *eiPtr; Tcl_HashEntry *hPtr; if (objC < 2 || objC > 3) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "event ?detail?"); return TCL_ERROR; } /* Find the event type */ eventName = Tcl_GetStringFromObj(objV[1], NULL); hPtr = Tcl_FindHashEntry(&bindPtr->eventTableByName, eventName); if (hPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown event \"", eventName, "\"", NULL); return TCL_ERROR; } eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); if (objC == 2) { Tcl_SetResult(bindPtr->interp, eiPtr->dynamic ? "dynamic" : "static", TCL_STATIC); return TCL_OK; } /* Get the detail name */ detailName = Tcl_GetStringFromObj(objV[2], NULL); for (dPtr = eiPtr->detailList; dPtr != NULL; dPtr = dPtr->next) { if (strcmp(dPtr->name, detailName) == 0) break; } if (dPtr == NULL) { Tcl_AppendResult(bindPtr->interp, "unknown detail \"", detailName, "\" for event \"", eiPtr->name, "\"", NULL); return TCL_ERROR; } Tcl_SetResult(bindPtr->interp, dPtr->dynamic ? "dynamic" : "static", TCL_STATIC); return TCL_OK; } int QE_LinkageCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]) { int objC = objc - objOffset; Tcl_Obj *CONST *objV = objv + objOffset; BindingTable *bindPtr = (BindingTable *) bindingTable; char *s; int length; if (objC < 2) { Tcl_WrongNumArgs(bindPtr->interp, objOffset + 1, objv, "pattern"); return TCL_ERROR; } s = Tcl_GetStringFromObj(objV[1], &length); if ((objC == 3) || (length && s[0] != '<')) return QE_LinkageCmd_Old(bindingTable, objOffset, objc, objv); return QE_LinkageCmd_New(bindingTable, objOffset, objc, objv); } #endif /* ALLOW_INSTALL */ tktreectrl-2.2.8/generic/qebind.h0000700000175600010010000000571110745240306015140 0ustar TimNone/* * qebind.h -- * * This module is the header for quasi-events. * * Copyright (c) 2002-2008 Tim Baker * * RCS: @(#) $Id: qebind.h,v 1.7 2008/01/22 01:03:02 treectrl Exp $ */ #ifndef INCLUDED_QEBIND_H #define INCLUDED_QEBIND_H typedef struct QE_BindingTable_ *QE_BindingTable; /* Pass to QE_BindEvent */ typedef struct QE_Event { int type; int detail; ClientData clientData; } QE_Event; typedef struct QE_ExpandArgs { QE_BindingTable bindingTable; char which; ClientData object; Tcl_DString *result; int event; int detail; ClientData clientData; } QE_ExpandArgs; typedef void (*QE_ExpandProc)(QE_ExpandArgs *args); extern QE_BindingTable bindingTable; extern int debug_bindings; extern int QE_BindInit(Tcl_Interp *interp); extern QE_BindingTable QE_CreateBindingTable(Tcl_Interp *interp); extern void QE_DeleteBindingTable(QE_BindingTable bindingTable); extern int QE_InstallEvent(QE_BindingTable bindingTable, char *name, QE_ExpandProc expand); extern int QE_InstallDetail(QE_BindingTable bindingTable, char *name, int eventType, QE_ExpandProc expand); extern int QE_CreateBinding(QE_BindingTable bindingTable, ClientData object, char *eventString, char *command, int append); extern int QE_DeleteBinding(QE_BindingTable bindingTable, ClientData object, char *eventString); extern int QE_GetBinding(QE_BindingTable bindingTable, ClientData object, char *eventString); extern int QE_GetAllBindings(QE_BindingTable bindingTable, ClientData object); extern int QE_GetEventNames(QE_BindingTable bindingTable); extern int QE_GetDetailNames(QE_BindingTable bindingTable, char *eventName); extern int QE_BindEvent(QE_BindingTable bindingTable, QE_Event *eventPtr); extern void QE_ExpandDouble(double number, Tcl_DString *result); extern void QE_ExpandNumber(long number, Tcl_DString *result); extern void QE_ExpandString(char *string, Tcl_DString *result); extern void QE_ExpandEvent(QE_BindingTable bindingTable, int eventType, Tcl_DString *result); extern void QE_ExpandDetail(QE_BindingTable bindingTable, int event, int detail, Tcl_DString *result); extern void QE_ExpandPattern(QE_BindingTable bindingTable, int eventType, int detail, Tcl_DString *result); extern void QE_ExpandUnknown(char which, Tcl_DString *result); extern int QE_BindCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); extern int QE_ConfigureCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); extern int QE_GenerateCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); extern int QE_InstallCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); extern int QE_UnbindCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); extern int QE_UninstallCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); extern int QE_LinkageCmd(QE_BindingTable bindingTable, int objOffset, int objc, Tcl_Obj *CONST objv[]); #endif /* INCLUDED_QEBIND_H */ tktreectrl-2.2.8/generic/tkTreeColumn.c0000700000175600010010000045547311073204434016320 0ustar TimNone/* * tkTreeColumn.c -- * * This module implements treectrl widget's columns. * * Copyright (c) 2002-2008 Tim Baker * Copyright (c) 2002-2003 Christian Krone * Copyright (c) 2003 ActiveState Corporation * * RCS: @(#) $Id: tkTreeColumn.c,v 1.83 2008/10/08 19:25:16 treectrl Exp $ */ #include "tkTreeCtrl.h" typedef struct TreeColumn_ TreeColumn_; #ifdef UNIFORM_GROUP typedef struct UniformGroup { Tcl_HashEntry *hPtr; /* Entry in TreeCtrl.uniformGroupHash */ int refCount; /* Number of columns in this group. */ int minSize; /* Used during layout. */ } UniformGroup; #endif /* * The following structure holds information about a single * column in a TreeCtrl. */ struct TreeColumn_ { Tcl_Obj *textObj; /* -text */ char *text; /* -text */ int width; /* -width */ Tcl_Obj *widthObj; /* -width */ int minWidth; /* -minwidth */ Tcl_Obj *minWidthObj; /* -minwidth */ int maxWidth; /* -maxwidth */ Tcl_Obj *maxWidthObj; /* -maxwidth */ #ifdef DEPRECATED int stepWidth; /* -stepwidth */ Tcl_Obj *stepWidthObj; /* -stepwidth */ int widthHack; /* -widthhack */ #endif /* DEPRECATED */ Tk_Font tkfont; /* -font */ Tk_Justify justify; /* -justify */ int itemJustify; /* -itemjustify */ PerStateInfo border; /* -background */ Tcl_Obj *borderWidthObj; /* -borderwidth */ int borderWidth; /* -borderwidth */ XColor *textColor; /* -textcolor */ int expand; /* -expand */ int squeeze; /* -squeeze */ int visible; /* -visible */ int resize; /* -resize */ TagInfo *tagInfo; /* -tags */ char *imageString; /* -image */ PerStateInfo arrowBitmap; /* -arrowbitmap */ PerStateInfo arrowImage; /* -arrowimage */ Pixmap bitmap; /* -bitmap */ Tcl_Obj *itemBgObj; /* -itembackground */ TreeStyle itemStyle; /* -itemstyle */ int button; /* -button */ Tcl_Obj *textPadXObj; /* -textpadx */ int *textPadX; /* -textpadx */ Tcl_Obj *textPadYObj; /* -textpady */ int *textPadY; /* -textpady */ Tcl_Obj *imagePadXObj; /* -imagepadx */ int *imagePadX; /* -imagepadx */ Tcl_Obj *imagePadYObj; /* -imagepady */ int *imagePadY; /* -imagepady */ Tcl_Obj *arrowPadXObj; /* -arrowpadx */ int *arrowPadX; /* -arrowpadx */ Tcl_Obj *arrowPadYObj; /* -arrowpady */ int *arrowPadY; /* -arrowpady */ #define ARROW_NONE 0 #define ARROW_UP 1 #define ARROW_DOWN 2 int arrow; /* -arrow */ #define SIDE_LEFT 0 #define SIDE_RIGHT 1 int arrowSide; /* -arrowside */ int arrowGravity; /* -arrowgravity */ #define COLUMN_STATE_NORMAL 0 #define COLUMN_STATE_ACTIVE 1 #define COLUMN_STATE_PRESSED 2 int state; /* -state */ int lock; /* -lock */ TreeCtrl *tree; Tk_OptionTable optionTable; int id; /* unique column identifier */ int index; /* order in list of columns */ int textLen; int textWidth; Tk_Image image; int neededWidth; /* calculated from borders + image/bitmap + * text + arrow */ int neededHeight; /* calculated from borders + image/bitmap + * text */ int offset; /* Total width of preceding columns */ int useWidth; /* -width, -minwidth, or required+expansion */ int widthOfItems; /* width of all TreeItemColumns */ int itemBgCount; XColor **itemBgColor; GC bitmapGC; TreeColumn prev; TreeColumn next; TextLayout textLayout; /* multi-line titles */ int textLayoutWidth; /* width passed to TextLayout_Compute */ int textLayoutInvalid; #define TEXT_WRAP_NULL -1 #define TEXT_WRAP_CHAR 0 #define TEXT_WRAP_WORD 1 int textWrap; /* -textwrap */ int textLines; /* -textlines */ #ifdef UNIFORM_GROUP UniformGroup *uniform; /* -uniform */ int weight; /* -weight */ #endif TreeColumnDInfo dInfo; /* Display info. */ }; #ifdef UNIFORM_GROUP /* *---------------------------------------------------------------------- * * UniformGroupCO_Set -- * UniformGroupCO_Get -- * UniformGroupCO_Restore -- * UniformGroupCO_Free -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a UniformGroup. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int UniformGroupCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **valuePtr, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; int objEmpty; UniformGroup **internalPtr, *new; if (internalOffset >= 0) internalPtr = (UniformGroup **) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*valuePtr)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*valuePtr) = NULL; if (internalPtr != NULL) { if (*valuePtr != NULL) { int isNew; Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&tree->uniformGroupHash, Tcl_GetString(*valuePtr), &isNew); if (isNew) { new = (UniformGroup *) ckalloc(sizeof(UniformGroup)); new->refCount = 0; new->hPtr = hPtr; Tcl_SetHashValue(hPtr, (ClientData) new); } else { new = (UniformGroup *) Tcl_GetHashValue(hPtr); } new->refCount++; #ifdef TREECTRL_DEBUG if (tree->debug.enable) dbwin("UniformGroupCO_Set: %s refCount=%d\n", Tcl_GetString(*valuePtr), new->refCount); #endif } else { new = NULL; } *((UniformGroup **) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj * UniformGroupCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; UniformGroup *uniform = *(UniformGroup **) (recordPtr + internalOffset); if (uniform == NULL) return NULL; return Tcl_NewStringObj(Tcl_GetHashKey(&tree->uniformGroupHash, uniform->hPtr), -1); } static void UniformGroupCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { *(UniformGroup **) internalPtr = *(UniformGroup **) saveInternalPtr; } static void UniformGroupCO_Free( ClientData clientData, Tk_Window tkwin, char *internalPtr ) { UniformGroup *uniform = *(UniformGroup **) internalPtr; #ifdef TREECTRL_DEBUG TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; if (tree->debug.enable && uniform != NULL) { dbwin("UniformGroupCO_Free: %s refCount=%d\n", Tcl_GetHashKey(&tree->uniformGroupHash, uniform->hPtr), uniform->refCount - 1); } #endif if ((uniform != NULL) && (--uniform->refCount <= 0)) { Tcl_DeleteHashEntry(uniform->hPtr); ckfree((char *) uniform); *((UniformGroup **) internalPtr) = NULL; } } static Tk_ObjCustomOption uniformGroupCO = { "uniform group", UniformGroupCO_Set, UniformGroupCO_Get, UniformGroupCO_Restore, UniformGroupCO_Free, (ClientData) NULL }; #endif /* UNIFORM_GROUP */ static CONST char *arrowST[] = { "none", "up", "down", (char *) NULL }; static CONST char *arrowSideST[] = { "left", "right", (char *) NULL }; static CONST char *stateST[] = { "normal", "active", "pressed", (char *) NULL }; static CONST char *lockST[] = { "left", "none", "right", (char *) NULL }; static CONST char *justifyStrings[] = { "left", "right", "center", (char *) NULL }; #define COLU_CONF_IMAGE 0x0001 #define COLU_CONF_NWIDTH 0x0002 /* neededWidth */ #define COLU_CONF_NHEIGHT 0x0004 /* neededHeight */ #define COLU_CONF_TWIDTH 0x0008 /* totalWidth */ #define COLU_CONF_ITEMBG 0x0010 #define COLU_CONF_DISPLAY 0x0040 #define COLU_CONF_JUSTIFY 0x0080 #define COLU_CONF_TAGS 0x0100 #define COLU_CONF_TEXT 0x0200 #define COLU_CONF_BITMAP 0x0400 #define COLU_CONF_RANGES 0x0800 static Tk_OptionSpec columnSpecs[] = { {TK_OPTION_STRING_TABLE, "-arrow", (char *) NULL, (char *) NULL, "none", -1, Tk_Offset(TreeColumn_, arrow), 0, (ClientData) arrowST, COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-arrowbitmap", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, arrowBitmap.obj), Tk_Offset(TreeColumn_, arrowBitmap), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_STRING_TABLE, "-arrowgravity", (char *) NULL, (char *) NULL, "left", -1, Tk_Offset(TreeColumn_, arrowGravity), 0, (ClientData) arrowSideST, COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-arrowimage", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, arrowImage.obj), Tk_Offset(TreeColumn_, arrowImage), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-arrowpadx", (char *) NULL, (char *) NULL, "6", Tk_Offset(TreeColumn_, arrowPadXObj), Tk_Offset(TreeColumn_, arrowPadX), 0, (ClientData) &TreeCtrlCO_pad, COLU_CONF_NWIDTH | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-arrowpady", (char *) NULL, (char *) NULL, "0", Tk_Offset(TreeColumn_, arrowPadYObj), Tk_Offset(TreeColumn_, arrowPadY), 0, (ClientData) &TreeCtrlCO_pad, COLU_CONF_NWIDTH | COLU_CONF_DISPLAY}, {TK_OPTION_STRING_TABLE, "-arrowside", (char *) NULL, (char *) NULL, "right", -1, Tk_Offset(TreeColumn_, arrowSide), 0, (ClientData) arrowSideST, COLU_CONF_NWIDTH | COLU_CONF_DISPLAY}, /* NOTE: -background is a per-state option, so DEF_BUTTON_BG_COLOR * must be a list of one element */ {TK_OPTION_CUSTOM, "-background", (char *) NULL, (char *) NULL, (char *) NULL /* initialized later */, Tk_Offset(TreeColumn_, border.obj), Tk_Offset(TreeColumn_, border), 0, (ClientData) NULL, COLU_CONF_DISPLAY}, {TK_OPTION_BITMAP, "-bitmap", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, bitmap), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_BITMAP | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_PIXELS, "-borderwidth", (char *) NULL, (char *) NULL, "2", Tk_Offset(TreeColumn_, borderWidthObj), Tk_Offset(TreeColumn_, borderWidth), 0, (ClientData) NULL, COLU_CONF_TWIDTH | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_BOOLEAN, "-button", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeColumn_, button), 0, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-expand", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeColumn_, expand), 0, (ClientData) NULL, COLU_CONF_TWIDTH}, {TK_OPTION_FONT, "-font", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, tkfont), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY | COLU_CONF_TEXT}, {TK_OPTION_STRING, "-image", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, imageString), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_IMAGE | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-imagepadx", (char *) NULL, (char *) NULL, "6", Tk_Offset(TreeColumn_, imagePadXObj), Tk_Offset(TreeColumn_, imagePadX), 0, (ClientData) &TreeCtrlCO_pad, COLU_CONF_NWIDTH | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-imagepady", (char *) NULL, (char *) NULL, "0", Tk_Offset(TreeColumn_, imagePadYObj), Tk_Offset(TreeColumn_, imagePadY), 0, (ClientData) &TreeCtrlCO_pad, COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_STRING, "-itembackground", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, itemBgObj), -1, TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_ITEMBG}, {TK_OPTION_CUSTOM, "-itemjustify", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, itemJustify), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_JUSTIFY}, {TK_OPTION_CUSTOM, "-itemstyle", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, itemStyle), TK_OPTION_NULL_OK, (ClientData) &TreeCtrlCO_style, 0}, {TK_OPTION_JUSTIFY, "-justify", (char *) NULL, (char *) NULL, "left", -1, Tk_Offset(TreeColumn_, justify), 0, (ClientData) NULL, COLU_CONF_DISPLAY | COLU_CONF_JUSTIFY}, {TK_OPTION_STRING_TABLE, "-lock", (char *) NULL, (char *) NULL, "none", -1, Tk_Offset(TreeColumn_, lock), 0, (ClientData) lockST, 0}, {TK_OPTION_PIXELS, "-maxwidth", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, maxWidthObj), Tk_Offset(TreeColumn_, maxWidth), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_TWIDTH}, {TK_OPTION_PIXELS, "-minwidth", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, minWidthObj), Tk_Offset(TreeColumn_, minWidth), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_TWIDTH}, {TK_OPTION_BOOLEAN, "-resize", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeColumn_, resize), 0, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-squeeze", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeColumn_, squeeze), 0, (ClientData) NULL, COLU_CONF_TWIDTH}, {TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL, "normal", -1, Tk_Offset(TreeColumn_, state), 0, (ClientData) stateST, COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, #ifdef DEPRECATED {TK_OPTION_PIXELS, "-stepwidth", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, stepWidthObj), Tk_Offset(TreeColumn_, stepWidth), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_RANGES}, #endif /* DEPRECATED */ {TK_OPTION_CUSTOM, "-tags", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, tagInfo), TK_OPTION_NULL_OK, (ClientData) &TreeCtrlCO_tagInfo, COLU_CONF_TAGS}, {TK_OPTION_STRING, "-text", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, textObj), Tk_Offset(TreeColumn_, text), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_TEXT | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_COLOR, "-textcolor", (char *) NULL, (char *) NULL, DEF_BUTTON_FG, -1, Tk_Offset(TreeColumn_, textColor), 0, (ClientData) NULL, COLU_CONF_DISPLAY}, {TK_OPTION_INT, "-textlines", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeColumn_, textLines), 0, (ClientData) NULL, COLU_CONF_TEXT | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-textpadx", (char *) NULL, (char *) NULL, "6", Tk_Offset(TreeColumn_, textPadXObj), Tk_Offset(TreeColumn_, textPadX), 0, (ClientData) &TreeCtrlCO_pad, COLU_CONF_NWIDTH | COLU_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-textpady", (char *) NULL, (char *) NULL, "0", Tk_Offset(TreeColumn_, textPadYObj), Tk_Offset(TreeColumn_, textPadY), 0, (ClientData) &TreeCtrlCO_pad, COLU_CONF_NHEIGHT | COLU_CONF_DISPLAY}, #ifdef UNIFORM_GROUP {TK_OPTION_CUSTOM, "-uniform", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeColumn_, uniform), TK_OPTION_NULL_OK, (ClientData) &uniformGroupCO, COLU_CONF_TWIDTH}, {TK_OPTION_INT, "-weight", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeColumn_, weight), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_TWIDTH}, #endif {TK_OPTION_PIXELS, "-width", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeColumn_, widthObj), Tk_Offset(TreeColumn_, width), TK_OPTION_NULL_OK, (ClientData) NULL, COLU_CONF_TWIDTH}, {TK_OPTION_BOOLEAN, "-visible", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeColumn_, visible), 0, (ClientData) NULL, COLU_CONF_TWIDTH | COLU_CONF_DISPLAY}, #ifdef DEPRECATED {TK_OPTION_BOOLEAN, "-widthhack", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeColumn_, widthHack), 0, (ClientData) NULL, COLU_CONF_RANGES}, #endif /* DEPRECATED */ {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, 0, 0} }; #define IS_TAIL(C) ((C) == tree->columnTail) #define IS_ALL(C) (((C) == COLUMN_ALL) || ((C) == COLUMN_NTAIL)) /* *---------------------------------------------------------------------- * * ColumnCO_Set -- * * Tk_ObjCustomOption.setProc(). Converts a Tcl_Obj holding a * column description into a pointer to a Column. * * Results: * A standard Tcl result. * * Side effects: * May store a TreeColumn pointer into the internal representation * pointer. May change the pointer to the Tcl_Obj to NULL to indicate * that the specified string was empty and that is acceptable. * *---------------------------------------------------------------------- */ static int ColumnCO_Set( ClientData clientData, /* CFO_xxx flags to control the conversion. */ Tcl_Interp *interp, /* Current interpreter. */ Tk_Window tkwin, /* Window for which option is being set. */ Tcl_Obj **value, /* Pointer to the pointer to the value object. * We use a pointer to the pointer because * we may need to return a value (NULL). */ char *recordPtr, /* Pointer to storage for the widget record. */ int internalOffset, /* Offset within *recordPtr at which the * internal value is to be stored. */ char *saveInternalPtr, /* Pointer to storage for the old value. */ int flags /* Flags for the option, set Tk_SetOptions. */ ) { int cfoFlags = (int) clientData; TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; int objEmpty; TreeColumn new, *internalPtr; if (internalOffset >= 0) internalPtr = (TreeColumn *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*value)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*value) = NULL; else { if (TreeColumn_FromObj(tree, (*value), &new, cfoFlags) != TCL_OK) return TCL_ERROR; } if (internalPtr != NULL) { if ((*value) == NULL) new = NULL; *((TreeColumn *) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } /* *---------------------------------------------------------------------- * * ColumnCO_Get -- * * Tk_ObjCustomOption.getProc(). Converts a TreeColumn into a * Tcl_Obj string representation. * * Results: * Tcl_Obj containing the string representation of the column. * Returns NULL if the TreeColumn is NULL. * * Side effects: * May create a new Tcl_Obj. * *---------------------------------------------------------------------- */ static Tcl_Obj * ColumnCO_Get( ClientData clientData, /* Not used. */ Tk_Window tkwin, /* Window for which option is being set. */ char *recordPtr, /* Pointer to widget record. */ int internalOffset /* Offset within *recordPtr containing the * sticky value. */ ) { TreeColumn value = *(TreeColumn *) (recordPtr + internalOffset); TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; if (value == NULL) return NULL; #if 0 if (value == COLUMN_ALL) return Tcl_NewStringObj("all", -1); #endif return TreeColumn_ToObj(tree, value); } /* *---------------------------------------------------------------------- * * ColumnCO_Restore -- * * Tk_ObjCustomOption.restoreProc(). Restores a TreeColumn value * from a saved value. * * Results: * None. * * Side effects: * Restores the old value. * *---------------------------------------------------------------------- */ static void ColumnCO_Restore( ClientData clientData, /* Not used. */ Tk_Window tkwin, /* Not used. */ char *internalPtr, /* Where to store old value. */ char *saveInternalPtr) /* Pointer to old value. */ { *(TreeColumn *) internalPtr = *(TreeColumn *) saveInternalPtr; } /* * The following structure contains pointers to functions used for processing * a custom config option that handles Tcl_Obj<->TreeColumn conversion. * A column description must refer to a single column. */ Tk_ObjCustomOption TreeCtrlCO_column = { "column", ColumnCO_Set, ColumnCO_Get, ColumnCO_Restore, NULL, (ClientData) (CFO_NOT_NULL) }; /* * The following structure contains pointers to functions used for processing * a custom config option that handles Tcl_Obj<->TreeColumn conversion. * A column description must refer to a single column. * "tail" is not allowed. */ Tk_ObjCustomOption TreeCtrlCO_column_NOT_TAIL = { "column", ColumnCO_Set, ColumnCO_Get, ColumnCO_Restore, NULL, (ClientData) (CFO_NOT_NULL | CFO_NOT_TAIL) }; static Tk_OptionSpec dragSpecs[] = { {TK_OPTION_BOOLEAN, "-enable", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeCtrl, columnDrag.enable), 0, (ClientData) NULL, 0}, {TK_OPTION_INT, "-imagealpha", (char *) NULL, (char *) NULL, "128", -1, Tk_Offset(TreeCtrl, columnDrag.alpha), 0, (ClientData) NULL, 0}, {TK_OPTION_COLOR, "-imagecolor", (char *) NULL, (char *) NULL, "gray75", -1, Tk_Offset(TreeCtrl, columnDrag.color), 0, (ClientData) NULL, 0}, {TK_OPTION_CUSTOM, "-imagecolumn", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeCtrl, columnDrag.column), TK_OPTION_NULL_OK, (ClientData) &TreeCtrlCO_column_NOT_TAIL, 0}, {TK_OPTION_PIXELS, "-imageoffset", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TreeCtrl, columnDrag.offsetObj), Tk_Offset(TreeCtrl, columnDrag.offset), 0, (ClientData) NULL, 0}, {TK_OPTION_COLOR, "-indicatorcolor", (char *) NULL, (char *) NULL, "Black", -1, Tk_Offset(TreeCtrl, columnDrag.indColor), 0, (ClientData) NULL, 0}, {TK_OPTION_CUSTOM, "-indicatorcolumn", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeCtrl, columnDrag.indColumn), TK_OPTION_NULL_OK, (ClientData) &TreeCtrlCO_column, 0}, {TK_OPTION_STRING_TABLE, "-indicatorside", (char *) NULL, (char *) NULL, "left", -1, Tk_Offset(TreeCtrl, columnDrag.indSide), 0, (ClientData) arrowSideST, 0}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, 0, 0} }; /* *---------------------------------------------------------------------- * * ImageChangedProc -- * * This procedure is invoked by the image code whenever the manager * for an image does something that affects the size or contents * of an image displayed in a column header. * * Results: * None. * * Side effects: * Invalidates the size of the column and schedules a redisplay. * *---------------------------------------------------------------------- */ static void ImageChangedProc( ClientData clientData, /* Pointer to Column record. */ int x, int y, /* Upper left pixel (within image) * that must be redisplayed. */ int width, int height, /* Dimensions of area to redisplay * (may be <= 0). */ int imageWidth, int imageHeight /* New dimensions of image. */ ) { /* I would like to know the image was deleted... */ TreeColumn column = clientData; TreeCtrl *tree = column->tree; /* Duplicate the effects of configuring the -image option. */ column->neededWidth = -1; column->neededHeight = -1; tree->headerHeight = -1; tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_DInfoChanged(tree, DINFO_CHECK_COLUMN_WIDTH | DINFO_DRAW_HEADER); } /* *---------------------------------------------------------------------- * * ColumnStateFromObj -- * * Parses a string object containing "state" or "!state" to a * state bit flag. * This function is passed to PerStateInfo_FromObj(). * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int ColumnStateFromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *obj, /* String object to parse. */ int *stateOff, /* OR'd with state bit if "!state" is * specified. Caller must initialize. */ int *stateOn /* OR'd with state bit if "state" is * specified. Caller must initialize. */ ) { Tcl_Interp *interp = tree->interp; int i, op = STATE_OP_ON, op2, op3, length, state = 0; char ch0, *string; CONST char *stateNames[4] = { "normal", "active", "pressed", "up" }; int states[3]; states[STATE_OP_ON] = 0; states[STATE_OP_OFF] = 0; states[STATE_OP_TOGGLE] = 0; string = Tcl_GetStringFromObj(obj, &length); if (length == 0) goto unknown; ch0 = string[0]; if (ch0 == '!') { op = STATE_OP_OFF; ++string; ch0 = string[0]; } else if (ch0 == '~') { if (1) { FormatResult(interp, "can't specify '~' for this command"); return TCL_ERROR; } op = STATE_OP_TOGGLE; ++string; ch0 = string[0]; } for (i = 0; i < 4; i++) { if ((ch0 == stateNames[i][0]) && !strcmp(string, stateNames[i])) { state = 1L << i; break; } } if (state == 0) goto unknown; if (op == STATE_OP_ON) { op2 = STATE_OP_OFF; op3 = STATE_OP_TOGGLE; } else if (op == STATE_OP_OFF) { op2 = STATE_OP_ON; op3 = STATE_OP_TOGGLE; } else { op2 = STATE_OP_ON; op3 = STATE_OP_OFF; } states[op2] &= ~state; states[op3] &= ~state; states[op] |= state; *stateOn |= states[STATE_OP_ON]; *stateOff |= states[STATE_OP_OFF]; return TCL_OK; unknown: FormatResult(interp, "unknown state \"%s\"", string); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Column_MakeState -- * * Return a bit mask suitable for passing to the PerState_xxx * functions. * * Results: * State flags for the column's current state. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Column_MakeState( TreeColumn column /* Column record. */ ) { int state = 0; if (column->state == COLUMN_STATE_NORMAL) state |= 1L << 0; else if (column->state == COLUMN_STATE_ACTIVE) state |= 1L << 1; else if (column->state == COLUMN_STATE_PRESSED) state |= 1L << 2; if (column->arrow == ARROW_UP) state |= 1L << 3; return state; } /* *---------------------------------------------------------------------- * * TreeColumn_FirstAndLast -- * * Determine the order of two columns and swap them if needed. * * Results: * The return value is the number of columns in the range between * first and last. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_FirstAndLast( TreeColumn *first, /* Column token. */ TreeColumn *last /* Column token. */ ) { int indexFirst, indexLast, index; indexFirst = TreeColumn_Index(*first); indexLast = TreeColumn_Index(*last); if (indexFirst > indexLast) { TreeColumn column = *first; *first = *last; *last = column; index = indexFirst; indexFirst = indexLast; indexLast = index; } return indexLast - indexFirst + 1; } /* *---------------------------------------------------------------------- * * ColumnHasTag -- * * Checks whether a column has a certain tag. * * Results: * Returns TRUE if the column has the given tag. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int ColumnHasTag( TreeColumn column, /* The column to test. */ Tk_Uid tag /* Tag to look for. */ ) { TagInfo *tagInfo = column->tagInfo; Tk_Uid *tagPtr; int count; if (tagInfo == NULL) return 0; for (tagPtr = tagInfo->tagPtr, count = tagInfo->numTags; count > 0; tagPtr++, count--) { if (*tagPtr == tag) { return 1; } } return 0; } typedef struct Qualifiers { TreeCtrl *tree; int visible; /* 1 for -visible TRUE, 0 for -visible FALSE, -1 for unspecified. */ int states[3]; /* States that must be on or off. */ TagExpr expr; /* Tag expression. */ int exprOK; /* TRUE if expr is valid. */ int lock; /* COLUMN_LOCK_xxx or -1 */ int ntail; /* 1 for !tail, * 0 for unspecified. */ Tk_Uid tag; /* Tag (without operators) or NULL. */ } Qualifiers; /* *---------------------------------------------------------------------- * * Qualifiers_Init -- * * Helper routine for TreeItem_FromObj. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Qualifiers_Init( TreeCtrl *tree, /* Widget info. */ Qualifiers *q /* Out: Initialized qualifiers. */ ) { q->tree = tree; q->visible = -1; q->states[0] = q->states[1] = q->states[2] = 0; q->exprOK = FALSE; q->lock = -1; q->ntail = 0; q->tag = NULL; } /* *---------------------------------------------------------------------- * * Qualifiers_Scan -- * * Helper routine for TreeItem_FromObj. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Qualifiers_Scan( Qualifiers *q, /* Must call Qualifiers_Init first, * and Qualifiers_Free if result is TCL_OK. */ int objc, /* Number of arguments. */ Tcl_Obj **objv, /* Argument values. */ int startIndex, /* First objv[] index to look at. */ int *argsUsed /* Out: number of objv[] used. */ ) { TreeCtrl *tree = q->tree; Tcl_Interp *interp = tree->interp; int qual, j = startIndex; static CONST char *qualifiers[] = { "lock", "state", "tag", "visible", "!tail", "!visible", NULL }; enum qualEnum { QUAL_LOCK, QUAL_STATE, QUAL_TAG, QUAL_VISIBLE, QUAL_NOT_TAIL, QUAL_NOT_VISIBLE }; /* Number of arguments used by qualifiers[]. */ static int qualArgs[] = { 2, 2, 2, 1, 1, 1 }; *argsUsed = 0; for (; j < objc; ) { if (Tcl_GetIndexFromObj(NULL, objv[j], qualifiers, NULL, 0, &qual) != TCL_OK) break; if (objc - j < qualArgs[qual]) { Tcl_AppendResult(interp, "missing arguments to \"", Tcl_GetString(objv[j]), "\" qualifier", NULL); goto errorExit; } switch ((enum qualEnum) qual) { case QUAL_LOCK: { if (Tcl_GetIndexFromObj(interp, objv[j + 1], lockST, "lock", 0, &q->lock) != TCL_OK) goto errorExit; break; } case QUAL_STATE: { int i, listObjc; Tcl_Obj **listObjv; if (Tcl_ListObjGetElements(interp, objv[j + 1], &listObjc, &listObjv) != TCL_OK) goto errorExit; q->states[STATE_OP_OFF] = q->states[STATE_OP_ON] = 0; for (i = 0; i < listObjc; i++) { if (ColumnStateFromObj(tree, listObjv[i], &q->states[STATE_OP_OFF], &q->states[STATE_OP_ON]) != TCL_OK) goto errorExit; } break; } case QUAL_TAG: { if (tree->columnTagExpr) { if (q->exprOK) TagExpr_Free(&q->expr); if (TagExpr_Init(tree, objv[j + 1], &q->expr) != TCL_OK) return TCL_ERROR; q->exprOK = TRUE; } else { q->tag = Tk_GetUid(Tcl_GetString(objv[j + 1])); } break; } case QUAL_VISIBLE: { q->visible = 1; break; } case QUAL_NOT_TAIL: { q->ntail = 1; break; } case QUAL_NOT_VISIBLE: { q->visible = 0; break; } } *argsUsed += qualArgs[qual]; j += qualArgs[qual]; } return TCL_OK; errorExit: if (q->exprOK) TagExpr_Free(&q->expr); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Qualifies -- * * Helper routine for TreeItem_FromObj. * * Results: * Returns TRUE if the item meets the given criteria. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Qualifies( Qualifiers *q, /* Qualifiers to check. */ TreeColumn column /* The column to test. May be NULL. */ ) { /* Note: if the column is NULL it is a "match" because we have run * out of columns to check. */ if (column == NULL) return 1; if ((q->ntail == 1) && (column == column->tree->columnTail)) return 0; if ((q->visible == 1) && !column->visible) return 0; else if ((q->visible == 0) && column->visible) return 0; if (q->states[STATE_OP_OFF] & Column_MakeState(column)) return 0; if ((q->states[STATE_OP_ON] & Column_MakeState(column)) != q->states[STATE_OP_ON]) return 0; if (q->exprOK && !TagExpr_Eval(&q->expr, column->tagInfo)) return 0; if ((q->lock != -1) && (column->lock != q->lock)) return 0; if ((q->tag != NULL) && !ColumnHasTag(column, q->tag)) return 0; return 1; } /* *---------------------------------------------------------------------- * * Qualifiers_Free -- * * Helper routine for TreeItem_FromObj. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Qualifiers_Free( Qualifiers *q /* Out: Initialized qualifiers. */ ) { if (q->exprOK) TagExpr_Free(&q->expr); } /* *---------------------------------------------------------------------- * * TreeColumnList_FromObj -- * * Parse a Tcl_Obj column description to get a list of columns. * * -- returning a single column -- * ID MODIFIERS * first QUALIFIERS MODIFIERS * end|last QUALIFIERS MODIFIERS * order N QUALIFIERS MODIFIERS * tail * tree * -- returning multiple columns -- * all QUALIFIERS * QUALIFIERS (like "all QUALIFIERS") * list listOfDescs * range first last QUALIFIERS * tag tagExpr QUALIFIERS * TAG-EXPR QUALIFIERS MODIFIERS * * MODIFIERS: * -- returning a single column -- * next QUALIFIERS * prev QUALIFIERS * * QUALIFIERS: * state stateList * tag tagExpr * visible * !visible * !tail * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumnList_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *objPtr, /* Column description. */ TreeColumnList *columns, /* Uninitialized list. Caller must free * it with TreeColumnList_Free unless the * result of this function is TCL_ERROR. */ int flags /* CFO_xxx flags. */ ) { Tcl_Interp *interp = tree->interp; int i, objc, index, listIndex; Tcl_Obj **objv, *elemPtr; TreeColumn column = NULL; Qualifiers q; int qualArgsTotal; static CONST char *indexName[] = { "all", "end", "first", "last", "list", "order", "range", "tail", "tree", (char *) NULL }; enum indexEnum { INDEX_ALL, INDEX_END, INDEX_FIRST, INDEX_LAST, INDEX_LIST, INDEX_ORDER, INDEX_RANGE, INDEX_TAIL, INDEX_TREE } ; /* Number of arguments used by indexName[]. */ static int indexArgs[] = { 1, 1, 1, 1, 2, 2, 3, 1, 1 }; /* Boolean: can indexName[] be followed by 1 or more qualifiers. */ static int indexQual[] = { 1, 0, 1, 1, 0, 1, 1, 0, 0 }; static CONST char *modifiers[] = { "next", "prev", (char *) NULL }; enum modEnum { TMOD_NEXT, TMOD_PREV }; /* Number of arguments used by modifiers[]. */ static int modArgs[] = { 1, 1 }; /* Boolean: can modifiers[] be followed by 1 or more qualifiers. */ static int modQual[] = { 1, 1 }; TreeColumnList_Init(tree, columns, 0); Qualifiers_Init(tree, &q); if (Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK) goto badDesc; if (objc == 0) goto badDesc; listIndex = 0; elemPtr = objv[listIndex]; if (Tcl_GetIndexFromObj(NULL, elemPtr, indexName, NULL, 0, &index) == TCL_OK) { if (objc - listIndex < indexArgs[index]) { Tcl_AppendResult(interp, "missing arguments to \"", Tcl_GetString(elemPtr), "\" keyword", NULL); goto errorExit; } qualArgsTotal = 0; if (indexQual[index]) { if (Qualifiers_Scan(&q, objc, objv, listIndex + indexArgs[index], &qualArgsTotal) != TCL_OK) { goto errorExit; } } switch ((enum indexEnum) index) { case INDEX_ALL: { if (qualArgsTotal) { column = tree->columns; while (column != NULL) { if (Qualifies(&q, column)) { TreeColumnList_Append(columns, column); } column = column->next; } if (!(flags & CFO_NOT_TAIL) && Qualifies(&q, tree->columnTail)) { TreeColumnList_Append(columns, tree->columnTail); } column = NULL; } else if (flags & CFO_LIST_ALL) { column = tree->columns; while (column != NULL) { TreeColumnList_Append(columns, column); column = column->next; } if (!(flags & CFO_NOT_TAIL)) TreeColumnList_Append(columns, tree->columnTail); column = NULL; } else if (flags & CFO_NOT_TAIL) { column = COLUMN_NTAIL; } else { column = COLUMN_ALL; } break; } case INDEX_FIRST: { column = tree->columns; while (!Qualifies(&q, column)) column = column->next; break; } case INDEX_END: case INDEX_LAST: { column = tree->columnLast; while (!Qualifies(&q, column)) { column = column->prev; } break; } case INDEX_LIST: { int listObjc; Tcl_Obj **listObjv; int count; if (Tcl_ListObjGetElements(interp, objv[listIndex + 1], &listObjc, &listObjv) != TCL_OK) goto errorExit; for (i = 0; i < listObjc; i++) { TreeColumnList column2s; if (TreeColumnList_FromObj(tree, listObjv[i], &column2s, flags) != TCL_OK) goto errorExit; TreeColumnList_Concat(columns, &column2s); TreeColumnList_Free(&column2s); } /* If any of the column descriptions in the list is "all", then * clear the list of columns and use "all". */ count = TreeColumnList_Count(columns); for (i = 0; i < count; i++) { TreeColumn column = TreeColumnList_Nth(columns, i); if (IS_ALL(column)) break; } if (i < count) { TreeColumnList_Free(columns); if (flags & CFO_NOT_TAIL) column = COLUMN_NTAIL; else column = COLUMN_ALL; } else column = NULL; break; } case INDEX_ORDER: { int order; if (Tcl_GetIntFromObj(NULL, objv[listIndex + 1], &order) != TCL_OK) goto errorExit; column = tree->columns; while (column != NULL) { if (Qualifies(&q, column)) if (order-- <= 0) break; column = column->next; } break; } case INDEX_RANGE: { TreeColumn _first, _last; if (TreeColumn_FromObj(tree, objv[listIndex + 1], &_first, CFO_NOT_NULL) != TCL_OK) goto errorExit; if (TreeColumn_FromObj(tree, objv[listIndex + 2], &_last, CFO_NOT_NULL) != TCL_OK) goto errorExit; (void) TreeColumn_FirstAndLast(&_first, &_last); column = _first; while (1) { if (Qualifies(&q, column)) { TreeColumnList_Append(columns, column); } if (column == _last) break; column = column->next; if (column == NULL) column = tree->columnTail; } column = NULL; break; } case INDEX_TAIL: { column = tree->columnTail; break; } case INDEX_TREE: { column = tree->columnTree; break; } } listIndex += indexArgs[index] + qualArgsTotal; /* No indexName[] was found. */ } else { int gotId = FALSE, id; TagExpr expr; if (tree->columnPrefixLen) { char *end, *t = Tcl_GetString(elemPtr); if (strncmp(t, tree->columnPrefix, tree->columnPrefixLen) == 0) { t += tree->columnPrefixLen; id = strtoul(t, &end, 10); if ((end != t) && (*end == '\0')) gotId = TRUE; } } else if (Tcl_GetIntFromObj(NULL, elemPtr, &id) == TCL_OK) { gotId = TRUE; } if (gotId) { column = tree->columns; while (column) { if (column->id == id) break; column = column->next; } listIndex++; goto gotFirstPart; } /* Try a list of qualifiers. This has the same effect as * "all QUALIFIERS". */ if (Qualifiers_Scan(&q, objc, objv, listIndex, &qualArgsTotal) != TCL_OK) { goto errorExit; } if (qualArgsTotal) { column = tree->columns; while (column != NULL) { if (Qualifies(&q, column)) { TreeColumnList_Append(columns, column); } column = column->next; } if (!(flags & CFO_NOT_TAIL) && Qualifies(&q, tree->columnTail)) { TreeColumnList_Append(columns, tree->columnTail); } column = NULL; listIndex += qualArgsTotal; goto gotFirstPart; } /* Try a tag or tag expression followed by qualifiers. */ if (objc > 1) { if (Qualifiers_Scan(&q, objc, objv, listIndex + 1, &qualArgsTotal) != TCL_OK) { goto errorExit; } } if (tree->columnTagExpr) { if (TagExpr_Init(tree, elemPtr, &expr) != TCL_OK) goto errorExit; column = tree->columns; while (column != NULL) { if (TagExpr_Eval(&expr, column->tagInfo) && Qualifies(&q, column)) { TreeColumnList_Append(columns, column); } column = column->next; } if (!(flags & CFO_NOT_TAIL) && TagExpr_Eval(&expr, tree->columnTail->tagInfo) && Qualifies(&q, tree->columnTail)) { TreeColumnList_Append(columns, tree->columnTail); } TagExpr_Free(&expr); } else { Tk_Uid tag = Tk_GetUid(Tcl_GetString(elemPtr)); column = tree->columns; while (column != NULL) { if (ColumnHasTag(column, tag) && Qualifies(&q, column)) { TreeColumnList_Append(columns, column); } column = column->next; } if (!(flags & CFO_NOT_TAIL) && ColumnHasTag(tree->columnTail, tag) && Qualifies(&q, tree->columnTail)) { TreeColumnList_Append(columns, tree->columnTail); } } column = NULL; listIndex += 1 + qualArgsTotal; } gotFirstPart: /* If 1 column, use it and clear the list. */ if (TreeColumnList_Count(columns) == 1) { column = TreeColumnList_Nth(columns, 0); columns->count = 0; } /* If "all" but only tail column exists, use it. */ if (IS_ALL(column) && (tree->columns == NULL) && !(flags & CFO_NOT_TAIL)) column = tree->columnTail; /* If > 1 column, no modifiers may follow. */ if ((TreeColumnList_Count(columns) > 1) || IS_ALL(column)) { if (listIndex < objc) { Tcl_AppendResult(interp, "unexpected arguments after \"", (char *) NULL); for (i = 0; i < listIndex; i++) { Tcl_AppendResult(interp, Tcl_GetString(objv[i]), (char *) NULL); if (i != listIndex - 1) Tcl_AppendResult(interp, " ", (char *) NULL); } Tcl_AppendResult(interp, "\"", (char *) NULL); goto errorExit; } } /* This means a valid specification was given, but there is no such column */ if ((TreeColumnList_Count(columns) == 0) && (column == NULL)) { if (flags & CFO_NOT_NULL) goto notNull; /* Empty list returned */ goto goodExit; } /* Process any modifiers following the column we matched above. */ for (; listIndex < objc; /* nothing */) { int qualArgsTotal = 0; elemPtr = objv[listIndex]; if (Tcl_GetIndexFromObj(interp, elemPtr, modifiers, "modifier", 0, &index) != TCL_OK) { goto errorExit; } if (objc - listIndex < modArgs[index]) { Tcl_AppendResult(interp, "missing arguments to \"", Tcl_GetString(elemPtr), "\" modifier", NULL); goto errorExit; } if (modQual[index]) { Qualifiers_Free(&q); Qualifiers_Init(tree, &q); if (Qualifiers_Scan(&q, objc, objv, listIndex + modArgs[index], &qualArgsTotal) != TCL_OK) { goto errorExit; } } switch ((enum modEnum) index) { case TMOD_NEXT: { int isTail = IS_TAIL(column); if (isTail) { column = NULL; break; } column = column->next; while (!Qualifies(&q, column)) column = column->next; if (column == NULL) { column = tree->columnTail; if (!Qualifies(&q, column)) column = NULL; } break; } case TMOD_PREV: { int isTail = IS_TAIL(column); if (isTail) column = tree->columnLast; else column = column->prev; while (!Qualifies(&q, column)) column = column->prev; break; } } if ((TreeColumnList_Count(columns) == 0) && (column == NULL)) { if (flags & CFO_NOT_NULL) goto notNull; /* Empty list returned. */ goto goodExit; } listIndex += modArgs[index] + qualArgsTotal; } if ((flags & CFO_NOT_MANY) && (IS_ALL(column) || (TreeColumnList_Count(columns) > 1))) { FormatResult(interp, "can't specify > 1 column for this command"); goto errorExit; } if ((flags & CFO_NOT_NULL) && (TreeColumnList_Count(columns) == 0) && (column == NULL)) { notNull: FormatResult(interp, "column \"%s\" doesn't exist", Tcl_GetString(objPtr)); goto errorExit; } if (TreeColumnList_Count(columns)) { if (flags & (CFO_NOT_TAIL)) { int i; for (i = 0; i < TreeColumnList_Count(columns); i++) { column = TreeColumnList_Nth(columns, i); if ((flags & CFO_NOT_TAIL) && IS_TAIL(column)) goto notTail; } } } else if (IS_ALL(column)) { TreeColumnList_Append(columns, column); } else { if ((flags & CFO_NOT_TAIL) && IS_TAIL(column)) { notTail: FormatResult(interp, "can't specify \"tail\" for this command"); goto errorExit; } TreeColumnList_Append(columns, column); } goodExit: Qualifiers_Free(&q); return TCL_OK; badDesc: FormatResult(interp, "bad column description \"%s\"", Tcl_GetString(objPtr)); goto errorExit; errorExit: Qualifiers_Free(&q); TreeColumnList_Free(columns); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TreeColumn_FromObj -- * * Parse a Tcl_Obj column description to get a single column. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *objPtr, /* Object to parse to a column. */ TreeColumn *columnPtr, /* Returned column. */ int flags /* CFO_xxx flags */ ) { TreeColumnList columns; if (TreeColumnList_FromObj(tree, objPtr, &columns, flags | CFO_NOT_MANY) != TCL_OK) return TCL_ERROR; /* May be NULL. */ (*columnPtr) = TreeColumnList_Nth(&columns, 0); TreeColumnList_Free(&columns); return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeColumnForEach_Start -- * * Begin iterating over items. A command might accept two column * descriptions for a range of column, or a single column description * which may itself refer to multiple column. Either column * description could be "all". * * Results: * Returns the first column to iterate over. If an error occurs * then ColumnForEach.error is set to 1. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeColumn TreeColumnForEach_Start( TreeColumnList *columns, /* List of columns. */ TreeColumnList *column2s, /* List of columns or NULL. */ ColumnForEach *iter /* Returned info, pass to TreeColumnForEach_Next. */ ) { TreeCtrl *tree = columns->tree; TreeColumn column, column2 = NULL; column = TreeColumnList_Nth(columns, 0); if (column2s) column2 = TreeColumnList_Nth(column2s, 0); iter->tree = tree; iter->all = FALSE; iter->ntail = FALSE; iter->error = 0; iter->list = NULL; if (IS_ALL(column) || IS_ALL(column2)) { iter->all = TRUE; iter->ntail = (column == COLUMN_NTAIL) || (column2 == COLUMN_NTAIL); if (tree->columns == NULL) return iter->current = iter->ntail ? NULL : tree->columnTail; iter->next = TreeColumn_Next(tree->columns); return iter->current = tree->columns; } if (column2 != NULL) { if (TreeColumn_FirstAndLast(&column, &column2) == 0) { iter->error = 1; return NULL; } iter->next = TreeColumn_Next(column); iter->last = column2; return iter->current = column; } iter->list = columns; iter->index = 0; return iter->current = column; } /* *---------------------------------------------------------------------- * * TreeColumnForEach_Next -- * * Returns the next column to iterate over. Keep calling this until * the result is NULL. * * Results: * Returns the next column to iterate over or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeColumn TreeColumnForEach_Next( ColumnForEach *iter /* Initialized by TreeColumnForEach_Start. */ ) { TreeCtrl *tree = iter->tree; TreeColumn column; if (iter->all) { if (iter->current == tree->columnTail) return iter->current = NULL; column = iter->next; if (column == NULL) return iter->current = iter->ntail ? NULL : tree->columnTail; iter->next = TreeColumn_Next(column); return iter->current = column; } if (iter->list != NULL) { if (iter->index >= TreeColumnList_Count(iter->list)) return iter->current = NULL; return iter->current = TreeColumnList_Nth(iter->list, ++iter->index); } if (iter->current == iter->last) return iter->current = NULL; column = iter->next; iter->next = TreeColumn_Next(column); return iter->current = column; } /* *---------------------------------------------------------------------- * * TreeColumn_ToObj -- * * Return a Tcl_Obj representing a column. * * Results: * A Tcl_Obj. * * Side effects: * Allocates a Tcl_Obj. * *---------------------------------------------------------------------- */ Tcl_Obj * TreeColumn_ToObj( TreeCtrl *tree, /* Widget info. */ TreeColumn column /* Column token to get Tcl_Obj for. */ ) { if (column == tree->columnTail) return Tcl_NewStringObj("tail", -1); if (tree->columnPrefixLen) { char buf[100 + TCL_INTEGER_SPACE]; (void) sprintf(buf, "%s%d", tree->columnPrefix, column->id); return Tcl_NewStringObj(buf, -1); } return Tcl_NewIntObj(column->id); } /* *---------------------------------------------------------------------- * * Tree_FindColumn -- * * Get the N'th column in a TreeCtrl. * * Results: * Token for the N'th column. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeColumn Tree_FindColumn( TreeCtrl *tree, /* Widget info. */ int columnIndex /* 0-based index of the column to return. */ ) { TreeColumn column = tree->columns; while (column != NULL) { if (column->index == columnIndex) break; column = column->next; } return column; } /* *---------------------------------------------------------------------- * * TreeColumn_Next -- * * Return the column to the right of the given one. * * Results: * Token for the next column. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeColumn TreeColumn_Next( TreeColumn column /* Column token. */ ) { return column->next; } /* *---------------------------------------------------------------------- * * TreeColumn_Prev -- * * Return the column to the left of the given one. * * Results: * Token for the previous column. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeColumn TreeColumn_Prev( TreeColumn column /* Column token. */ ) { return column->prev; } /* *---------------------------------------------------------------------- * * Column_FreeColors -- * * Frees an array of XColors. This is used to free the -itembackground * array of colors. * * Results: * None. * * Side effects: * Memory is deallocated, colors are freed. * *---------------------------------------------------------------------- */ static void Column_FreeColors( XColor **colors, /* Array of colors. May be NULL. */ int count /* Number of colors. */ ) { int i; if (colors == NULL) { return; } for (i = 0; i < count; i++) { if (colors[i] != NULL) { Tk_FreeColor(colors[i]); } } WCFREE(colors, XColor *, count); } /* *---------------------------------------------------------------------- * * Column_Move -- * * Move a column before another. * * Results: * If the column is moved, then the list of item-columns for every item * is rearranged and the treectrl option -defaultstyles is rearranged. * Whether the column is moved or not, the .index field of every * column is recalculated. * * Side effects: * A redisplay is scheduled if the moved column is visible. * *---------------------------------------------------------------------- */ static void Column_Move( TreeColumn move, /* Column to move. */ TreeColumn before /* Column to place 'move' in front of. * May be the same as 'move'. */ ) { TreeCtrl *tree = move->tree; TreeColumn column, prev, next, last; Tcl_HashEntry *hPtr; Tcl_HashSearch search; TreeItem item; int index; #ifdef DEPRECATED int numStyles; #endif if (move == before) goto renumber; if (move->index == before->index - 1) goto renumber; /* Move the column in every item */ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); TreeItem_MoveColumn(tree, item, move->index, before->index); hPtr = Tcl_NextHashEntry(&search); } /* Indicate that all items must recalculate their list of spans. */ TreeItem_SpansInvalidate(tree, NULL); #ifdef DEPRECATED /* Re-order -defaultstyle */ numStyles = tree->defaultStyle.numStyles; if ((numStyles > 0) && ((before->index < numStyles) || (move->index < numStyles))) { TreeStyle style, *styles; int i, j; Tcl_Obj *staticObjv[STATIC_SIZE], **objv = staticObjv; /* Case 1: move existing */ if ((before->index <= numStyles) && (move->index < numStyles)) { styles = tree->defaultStyle.styles; style = styles[move->index]; for (i = move->index; i < numStyles - 1; i++) styles[i] = styles[i + 1]; j = before->index; if (move->index < before->index) j--; for (i = numStyles - 1; i > j; i--) styles[i] = styles[i - 1]; styles[j] = style; /* Case 2: insert empty between existing */ } else if (before->index < numStyles) { numStyles++; styles = (TreeStyle *) ckalloc(numStyles * sizeof(TreeStyle)); for (i = 0; i < before->index; i++) styles[i] = tree->defaultStyle.styles[i]; styles[i++] = NULL; for (; i < numStyles; i++) styles[i] = tree->defaultStyle.styles[i - 1]; /* Case 3: move existing past end */ } else { numStyles += before->index - numStyles; styles = (TreeStyle *) ckalloc(numStyles * sizeof(TreeStyle)); style = tree->defaultStyle.styles[move->index]; for (i = 0; i < move->index; i++) styles[i] = tree->defaultStyle.styles[i]; for (; i < tree->defaultStyle.numStyles - 1; i++) styles[i] = tree->defaultStyle.styles[i + 1]; for (; i < numStyles - 1; i++) styles[i] = NULL; styles[i] = style; } Tcl_DecrRefCount(tree->defaultStyle.stylesObj); STATIC_ALLOC(objv, Tcl_Obj *, numStyles); for (i = 0; i < numStyles; i++) { if (styles[i] != NULL) objv[i] = TreeStyle_ToObj(styles[i]); else objv[i] = Tcl_NewObj(); } tree->defaultStyle.stylesObj = Tcl_NewListObj(numStyles, objv); Tcl_IncrRefCount(tree->defaultStyle.stylesObj); STATIC_FREE(objv, Tcl_Obj *, numStyles); if (styles != tree->defaultStyle.styles) { ckfree((char *) tree->defaultStyle.styles); tree->defaultStyle.styles = styles; tree->defaultStyle.numStyles = numStyles; } } #endif /* DEPRECATED */ /* Unlink. */ prev = move->prev; next = move->next; if (prev == NULL) tree->columns = next; else prev->next = next; if (next == NULL) tree->columnLast = prev; else next->prev = prev; /* Link. */ if (before == tree->columnTail) { last = tree->columnLast; last->next = move; move->prev = last; move->next = NULL; tree->columnLast = move; } else { prev = before->prev; if (prev == NULL) tree->columns = move; else prev->next = move; before->prev = move; move->prev = prev; move->next = before; } /* Renumber columns */ renumber: tree->columnLockLeft = NULL; tree->columnLockNone = NULL; tree->columnLockRight = NULL; index = 0; column = tree->columns; while (column != NULL) { column->index = index++; if (column->lock == COLUMN_LOCK_LEFT && tree->columnLockLeft == NULL) tree->columnLockLeft = column; if (column->lock == COLUMN_LOCK_NONE && tree->columnLockNone == NULL) tree->columnLockNone = column; if (column->lock == COLUMN_LOCK_RIGHT && tree->columnLockRight == NULL) tree->columnLockRight = column; column = column->next; } if (move->visible) { /* Must update column widths because of expansion. */ /* Also update columnTreeLeft. */ tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_DInfoChanged(tree, DINFO_CHECK_COLUMN_WIDTH); } } /* *---------------------------------------------------------------------- * * Column_Config -- * * This procedure is called to process an objc/objv list to set * configuration options for a Column. * * Results: * The return value is a standard Tcl result. If TCL_ERROR is * returned, then an error message is left in interp's result. * * Side effects: * Configuration information, such as text string, colors, font, * etc. get set for column; old resources get freed, if there * were any. Display changes may occur. * *---------------------------------------------------------------------- */ static int Column_Config( TreeColumn column, /* Column record. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[], /* Argument values. */ int createFlag /* TRUE if the Column is being created. */ ) { TreeCtrl *tree = column->tree; TreeColumn_ saved; TreeColumn walk; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; int mask, maskFree = 0; XGCValues gcValues; unsigned long gcMask; /* int stateOld = Column_MakeState(column), stateNew;*/ int visible = column->visible; int lock = column->lock; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) column, column->optionTable, objc, objv, tree->tkwin, &savedOptions, &mask) != TCL_OK) { mask = 0; continue; } /* Wouldn't have to do this if Tk_InitOptions() would return * a mask of configured options like Tk_SetOptions() does. */ if (createFlag) { if (column->imageString != NULL) mask |= COLU_CONF_IMAGE; if (column->itemBgObj != NULL) mask |= COLU_CONF_ITEMBG; } /* * Step 1: Save old values */ if (mask & COLU_CONF_IMAGE) saved.image = column->image; if (mask & COLU_CONF_ITEMBG) { saved.itemBgColor = column->itemBgColor; saved.itemBgCount = column->itemBgCount; } if (column == tree->columnTail) { if (column->itemStyle != NULL) { FormatResult(tree->interp, "can't change the -itemstyle option of the tail column"); continue; } if (column->lock != COLUMN_LOCK_NONE) { FormatResult(tree->interp, "can't change the -lock option of the tail column"); continue; } } /* * Step 2: Process new values */ if (mask & COLU_CONF_IMAGE) { if (column->imageString == NULL) { column->image = NULL; } else { column->image = Tk_GetImage(tree->interp, tree->tkwin, column->imageString, ImageChangedProc, (ClientData) column); if (column->image == NULL) continue; maskFree |= COLU_CONF_IMAGE; } } if (mask & COLU_CONF_ITEMBG) { if (column->itemBgObj == NULL) { column->itemBgColor = NULL; column->itemBgCount = 0; } else { int i, length, listObjc; Tcl_Obj **listObjv; XColor **colors; if (Tcl_ListObjGetElements(tree->interp, column->itemBgObj, &listObjc, &listObjv) != TCL_OK) continue; colors = (XColor **) ckalloc(sizeof(XColor *) * listObjc); for (i = 0; i < listObjc; i++) colors[i] = NULL; for (i = 0; i < listObjc; i++) { /* Can specify "" for tree background */ (void) Tcl_GetStringFromObj(listObjv[i], &length); if (length != 0) { colors[i] = Tk_AllocColorFromObj(tree->interp, tree->tkwin, listObjv[i]); if (colors[i] == NULL) break; } } if (i < listObjc) { Column_FreeColors(colors, listObjc); continue; } column->itemBgColor = colors; column->itemBgCount = listObjc; maskFree |= COLU_CONF_ITEMBG; } } /* * Step 3: Free saved values */ if (mask & COLU_CONF_IMAGE) { if (saved.image != NULL) Tk_FreeImage(saved.image); } if (mask & COLU_CONF_ITEMBG) Column_FreeColors(saved.itemBgColor, saved.itemBgCount); Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); /* * Free new values. */ if (maskFree & COLU_CONF_IMAGE) Tk_FreeImage(column->image); if (maskFree & COLU_CONF_ITEMBG) Column_FreeColors(column->itemBgColor, column->itemBgCount); /* * Restore old values. */ if (mask & COLU_CONF_IMAGE) column->image = saved.image; if (mask & COLU_CONF_ITEMBG) { column->itemBgColor = saved.itemBgColor; column->itemBgCount = saved.itemBgCount; } Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } /* Indicate that all items must recalculate their list of spans. */ if (visible != column->visible || lock != column->lock) TreeItem_SpansInvalidate(tree, NULL); /* Wouldn't have to do this if Tk_InitOptions() would return * a mask of configured options like Tk_SetOptions() does. */ if (createFlag) { if (column->textObj != NULL) mask |= COLU_CONF_TEXT; if (column->bitmap != None) mask |= COLU_CONF_BITMAP; } if (mask & COLU_CONF_TEXT) { if (column->textObj != NULL) (void) Tcl_GetStringFromObj(column->textObj, &column->textLen); else column->textLen = 0; if (column->textLen) { Tk_Font tkfont = column->tkfont ? column->tkfont : tree->tkfont; column->textWidth = Tk_TextWidth(tkfont, column->text, column->textLen); } else column->textWidth = 0; } if (mask & COLU_CONF_BITMAP) { if (column->bitmapGC != None) { Tk_FreeGC(tree->display, column->bitmapGC); column->bitmapGC = None; } if (column->bitmap != None) { gcValues.clip_mask = column->bitmap; gcValues.graphics_exposures = False; gcMask = GCClipMask | GCGraphicsExposures; column->bitmapGC = Tk_GetGC(tree->tkwin, gcMask, &gcValues); } } if (mask & COLU_CONF_ITEMBG) { if (!createFlag) { /* Set max -itembackground */ tree->columnBgCnt = 0; walk = tree->columns; while (walk != NULL) { if (walk->visible) { if (walk->itemBgCount > tree->columnBgCnt) tree->columnBgCnt = walk->itemBgCount; } walk = walk->next; } } Tree_DInfoChanged(tree, DINFO_INVALIDATE); } if (!createFlag && (column->lock != lock)) { TreeColumn before = NULL; switch (column->lock) { case COLUMN_LOCK_LEFT: before = tree->columnLockNone; if (before == NULL) before = tree->columnLockRight; break; case COLUMN_LOCK_NONE: if (lock == COLUMN_LOCK_LEFT) { before = tree->columnLockNone; if (before == NULL) before = tree->columnLockRight; } else before = tree->columnLockRight; break; case COLUMN_LOCK_RIGHT: before = NULL; break; } if (before == NULL) before = tree->columnTail; Column_Move(column, before); Tree_DInfoChanged(tree, DINFO_REDO_COLUMN_WIDTH); } if (mask & (COLU_CONF_NWIDTH | COLU_CONF_TWIDTH)) mask |= COLU_CONF_NHEIGHT; if (mask & (COLU_CONF_JUSTIFY | COLU_CONF_TEXT)) column->textLayoutInvalid = TRUE; if (mask & COLU_CONF_NWIDTH) column->neededWidth = -1; if (mask & COLU_CONF_NHEIGHT) { column->neededHeight = -1; tree->headerHeight = -1; } /* FIXME: only this column needs to be redisplayed. */ if (mask & COLU_CONF_JUSTIFY) Tree_DInfoChanged(tree, DINFO_INVALIDATE); /* -stepwidth and -widthhack */ if (mask & COLU_CONF_RANGES) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); /* Redraw everything */ if (mask & (COLU_CONF_TWIDTH | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT)) { tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_DInfoChanged(tree, DINFO_CHECK_COLUMN_WIDTH | DINFO_DRAW_HEADER); } /* Redraw header only */ else if (mask & COLU_CONF_DISPLAY) { Tree_DInfoChanged(tree, DINFO_DRAW_HEADER); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Column_Alloc -- * * Allocate and initialize a new Column record. * * Results: * Pointer to the new Column, or NULL if errors occurred. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static TreeColumn Column_Alloc( TreeCtrl *tree /* Widget info. */ ) { TreeColumn column; column = (TreeColumn) ckalloc(sizeof(TreeColumn_)); memset(column, '\0', sizeof(TreeColumn_)); column->tree = tree; column->optionTable = Tk_CreateOptionTable(tree->interp, columnSpecs); column->itemJustify = -1; if (Tk_InitOptions(tree->interp, (char *) column, column->optionTable, tree->tkwin) != TCL_OK) { WFREE(column, TreeColumn_); return NULL; } #if 0 if (Tk_SetOptions(header->tree->interp, (char *) column, column->optionTable, 0, NULL, header->tree->tkwin, &savedOptions, (int *) NULL) != TCL_OK) { WFREE(column, TreeColumn_); return NULL; } #endif column->neededWidth = column->neededHeight = -1; tree->headerHeight = tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; column->id = tree->nextColumnId++; tree->columnCount++; return column; } /* *---------------------------------------------------------------------- * * Column_Free -- * * Free a Column. * * Results: * Pointer to the next column. * * Side effects: * Memory is deallocated. If this is the last column being * deleted, the TreeCtrl.nextColumnId field is reset to zero. * *---------------------------------------------------------------------- */ static TreeColumn Column_Free( TreeColumn column /* Column record. */ ) { TreeCtrl *tree = column->tree; TreeColumn next = column->next; Column_FreeColors(column->itemBgColor, column->itemBgCount); if (column->bitmapGC != None) Tk_FreeGC(tree->display, column->bitmapGC); if (column->image != NULL) Tk_FreeImage(column->image); if (column->textLayout != NULL) TextLayout_Free(column->textLayout); TreeDisplay_FreeColumnDInfo(tree, column); Tk_FreeConfigOptions((char *) column, column->optionTable, tree->tkwin); WFREE(column, TreeColumn_); tree->columnCount--; if (tree->columnCount == 0) tree->nextColumnId = 0; return next; } /* *---------------------------------------------------------------------- * * TreeColumn_SetDInfo -- * * Store a display-info token in a column. Called by the display * code. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeColumn_SetDInfo( TreeColumn column, /* Column record. */ TreeColumnDInfo dInfo /* Display info token. */ ) { column->dInfo = dInfo; } /* *---------------------------------------------------------------------- * * TreeColumn_GetDInfo -- * * Return the display-info token of a column. Called by the display * code. * * Results: * The display-info token or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeColumnDInfo TreeColumn_GetDInfo( TreeColumn column /* Column record. */ ) { return column->dInfo; } /* *---------------------------------------------------------------------- * * TreeColumn_FixedWidth -- * * Return the value of the -width option. * * Results: * The pixel width or -1 if the -width option is unspecified. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_FixedWidth( TreeColumn column /* Column token. */ ) { return column->widthObj ? column->width : -1; } /* *---------------------------------------------------------------------- * * TreeColumn_MinWidth -- * * Return the value of the -minwidth option. * * Results: * The pixel width or -1 if the -minwidth option is unspecified. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_MinWidth( TreeColumn column /* Column token. */ ) { return column->minWidthObj ? column->minWidth : -1; } /* *---------------------------------------------------------------------- * * TreeColumn_MaxWidth -- * * Return the value of the -maxwidth option. * * Results: * The pixel width or -1 if the -maxwidth option is unspecified. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_MaxWidth( TreeColumn column /* Column token. */ ) { return column->maxWidthObj ? column->maxWidth : -1; } #ifdef DEPRECATED /* *---------------------------------------------------------------------- * * TreeColumn_StepWidth -- * * Return the value of the -stepwidth option. * NOTE: -stepwidth is deprecated. * * Results: * The pixel width or -1 if the -stepwidth option is unspecified. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_StepWidth( TreeColumn column /* Column token. */ ) { return column->stepWidthObj ? column->stepWidth : -1; } #endif /* DEPRECATED */ /* *---------------------------------------------------------------------- * * Column_UpdateTextLayout -- * * Recalculate the TextLayout for the text displayed in the * column header. The old TextLayout (if any) is freed. If * there is no text or if it is only one line then no TextLayout * is created. * * Results: * None. * * Side effects: * Memory may be allocated/deallocated. * *---------------------------------------------------------------------- */ static void Column_UpdateTextLayout( TreeColumn column, /* Column record. */ int width /* Maximum line length. Zero means there * is no limit. */ ) { Tk_Font tkfont; char *text = column->text; int textLen = column->textLen; int justify = column->justify; int maxLines = MAX(column->textLines, 0); /* -textlines */ int wrap = TEXT_WRAP_WORD; /* -textwrap */ int flags = 0; int i, multiLine = FALSE; if (column->textLayout != NULL) { TextLayout_Free(column->textLayout); column->textLayout = NULL; } if ((text == NULL) || (textLen == 0)) return; for (i = 0; i < textLen; i++) { if ((text[i] == '\n') || (text[i] == '\r')) { multiLine = TRUE; break; } } #ifdef MAC_OSX_TK /* The height of the header is fixed on Aqua. There is only room for * a single line of text. */ if (column->tree->useTheme) maxLines = 1; #endif if (!multiLine && ((maxLines == 1) || (!width || (width >= column->textWidth)))) return; tkfont = column->tkfont ? column->tkfont : column->tree->tkfont; if (wrap == TEXT_WRAP_WORD) flags |= TK_WHOLE_WORDS; column->textLayout = TextLayout_Compute(tkfont, text, Tcl_NumUtfChars(text, textLen), width, justify, maxLines, flags); } /* *---------------------------------------------------------------------- * * Column_GetArrowSize -- * * Return the size of the sort arrow displayed in the column header * for the column's current state. * * Results: * Height and width of the arrow. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Column_GetArrowSize( TreeColumn column, /* Column record. */ int *widthPtr, /* Returned width. */ int *heightPtr /* Returned height. */ ) { TreeCtrl *tree = column->tree; int state = Column_MakeState(column); int arrowWidth = -1, arrowHeight; Tk_Image image; Pixmap bitmap; /* image > bitmap > theme > draw */ image = PerStateImage_ForState(tree, &column->arrowImage, state, NULL); if (image != NULL) { Tk_SizeOfImage(image, &arrowWidth, &arrowHeight); } if (arrowWidth == -1) { bitmap = PerStateBitmap_ForState(tree, &column->arrowBitmap, state, NULL); if (bitmap != None) { Tk_SizeOfBitmap(tree->display, bitmap, &arrowWidth, &arrowHeight); } } if ((arrowWidth == -1) && tree->useTheme && TreeTheme_GetArrowSize(tree, Tk_WindowId(tree->tkwin), column->arrow == ARROW_UP, &arrowWidth, &arrowHeight) == TCL_OK) { } if (arrowWidth == -1) { Tk_Font tkfont = column->tkfont ? column->tkfont : tree->tkfont; Tk_FontMetrics fm; Tk_GetFontMetrics(tkfont, &fm); arrowWidth = (fm.linespace + column->textPadY[PAD_TOP_LEFT] + column->textPadY[PAD_BOTTOM_RIGHT] + column->borderWidth * 2) / 2; if (!(arrowWidth & 1)) arrowWidth--; arrowHeight = arrowWidth; } (*widthPtr) = arrowWidth; (*heightPtr) = arrowHeight; } /* * The following structure holds size/position info for all the graphical * elements of a column header. */ struct Layout { Tk_Font tkfont; Tk_FontMetrics fm; int width; /* Provided by caller */ int height; /* Provided by caller */ int textLeft; int textWidth; int bytesThatFit; int imageLeft; int imageWidth; int arrowLeft; int arrowWidth; int arrowHeight; }; /* * The following structure is used by the Column_DoLayout() procedure to * hold size/position info for each graphical element displayed in the * header. */ struct LayoutPart { int padX[2]; int padY[2]; int width; int height; int left; int top; }; /* *---------------------------------------------------------------------- * * Column_DoLayout -- * * Arrange all the graphical elements making up a column header. * * Results: * Layout info is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Column_DoLayout( TreeColumn column, /* Column record. */ struct Layout *layout /* Returned layout info. The width and * height fields must be initialized. */ ) { #if defined(MAC_OSX_TK) TreeCtrl *tree = column->tree; #endif struct LayoutPart *parts[3]; struct LayoutPart partArrow, partImage, partText; int i, padList[4], widthList[3], n = 0; int iArrow = -1, iImage = -1, iText = -1; int left, right; int widthForText = 0; #if defined(MAC_OSX_TK) int margins[4]; int arrow = column->arrow; int arrowSide = column->arrowSide; int arrowGravity = column->arrowGravity; #endif #if defined(MAC_OSX_TK) /* Under Aqua, we let the Appearance Manager draw the sort arrow */ if (tree->useTheme) { column->arrow = ARROW_NONE; column->arrowSide = SIDE_RIGHT; column->arrowGravity = SIDE_RIGHT; } #endif padList[0] = 0; if (column->arrow != ARROW_NONE) { Column_GetArrowSize(column, &partArrow.width, &partArrow.height); partArrow.padX[PAD_TOP_LEFT] = column->arrowPadX[PAD_TOP_LEFT]; partArrow.padX[PAD_BOTTOM_RIGHT] = column->arrowPadX[PAD_BOTTOM_RIGHT]; partArrow.padY[PAD_TOP_LEFT] = column->arrowPadY[PAD_TOP_LEFT]; partArrow.padY[PAD_BOTTOM_RIGHT] = column->arrowPadY[PAD_BOTTOM_RIGHT]; } if ((column->arrow != ARROW_NONE) && (column->arrowSide == SIDE_LEFT)) { parts[n] = &partArrow; padList[n] = partArrow.padX[PAD_TOP_LEFT]; padList[n + 1] = partArrow.padX[PAD_BOTTOM_RIGHT]; iArrow = n++; } if ((column->image != NULL) || (column->bitmap != None)) { if (column->image != NULL) Tk_SizeOfImage(column->image, &partImage.width, &partImage.height); else Tk_SizeOfBitmap(column->tree->display, column->bitmap, &partImage.width, &partImage.height); partImage.padX[PAD_TOP_LEFT] = column->imagePadX[PAD_TOP_LEFT]; partImage.padX[PAD_BOTTOM_RIGHT] = column->imagePadX[PAD_BOTTOM_RIGHT]; partImage.padY[PAD_TOP_LEFT] = column->imagePadY[PAD_TOP_LEFT]; partImage.padY[PAD_BOTTOM_RIGHT] = column->imagePadY[PAD_BOTTOM_RIGHT]; parts[n] = &partImage; padList[n] = MAX(partImage.padX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = partImage.padX[PAD_BOTTOM_RIGHT]; iImage = n++; } if (column->textLen > 0) { struct LayoutPart *parts2[3]; int n2 = 0; partText.padX[PAD_TOP_LEFT] = column->textPadX[PAD_TOP_LEFT]; partText.padX[PAD_BOTTOM_RIGHT] = column->textPadX[PAD_BOTTOM_RIGHT]; partText.padY[PAD_TOP_LEFT] = column->textPadY[PAD_TOP_LEFT]; partText.padY[PAD_BOTTOM_RIGHT] = column->textPadY[PAD_BOTTOM_RIGHT]; /* Calculate space for the text */ if (iArrow != -1) parts2[n2++] = &partArrow; if (iImage != -1) parts2[n2++] = &partImage; parts2[n2++] = &partText; if ((column->arrow != ARROW_NONE) && (column->arrowSide == SIDE_RIGHT)) parts2[n2++] = &partArrow; widthForText = layout->width; for (i = 0; i < n2; i++) { if (i) widthForText -= MAX(parts2[i]->padX[0], parts2[i-1]->padX[1]); else widthForText -= parts2[i]->padX[0]; if (parts2[i] != &partText) widthForText -= parts2[i]->width; } widthForText -= parts2[n2-1]->padX[1]; } layout->bytesThatFit = 0; if (widthForText > 0) { if (column->textLayoutInvalid || (column->textLayoutWidth != widthForText)) { Column_UpdateTextLayout(column, widthForText); column->textLayoutInvalid = FALSE; column->textLayoutWidth = widthForText; } if (column->textLayout != NULL) { TextLayout_Size(column->textLayout, &partText.width, &partText.height); parts[n] = &partText; padList[n] = MAX(partText.padX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = partText.padX[PAD_BOTTOM_RIGHT]; iText = n++; } else { layout->tkfont = column->tkfont ? column->tkfont : column->tree->tkfont; Tk_GetFontMetrics(layout->tkfont, &layout->fm); if (widthForText >= column->textWidth) { partText.width = column->textWidth; partText.height = layout->fm.linespace; layout->bytesThatFit = column->textLen; } else { partText.width = widthForText; partText.height = layout->fm.linespace; layout->bytesThatFit = Tree_Ellipsis(layout->tkfont, column->text, column->textLen, &partText.width, "...", FALSE); } parts[n] = &partText; padList[n] = MAX(partText.padX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = partText.padX[PAD_BOTTOM_RIGHT]; iText = n++; } } if ((column->arrow != ARROW_NONE) && (column->arrowSide == SIDE_RIGHT)) { parts[n] = &partArrow; padList[n] = MAX(partArrow.padX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = partArrow.padX[PAD_BOTTOM_RIGHT]; iArrow = n++; } #if defined(MAC_OSX_TK) /* Under Aqua, we let the Appearance Manager draw the sort arrow */ /* This code assumes the arrow is on the right */ if (tree->useTheme && (arrow != ARROW_NONE)) { if (TreeTheme_GetHeaderContentMargins(tree, column->state, arrow, margins) == TCL_OK) { parts[n] = &partArrow; partArrow.width = margins[2]; padList[n] = MAX(0, padList[n]); /* ignore -arrowpadx */ padList[n + 1] = 0; iArrow = n++; } } if (n == 0) { column->arrow = arrow; column->arrowSide = arrowSide; column->arrowGravity = arrowGravity; } #endif if (n == 0) return; for (i = 0; i < n; i++) { padList[i] = parts[i]->padX[0]; if (i) padList[i] = MAX(padList[i], parts[i-1]->padX[1]); padList[i + 1] = parts[i]->padX[1]; widthList[i] = parts[i]->width; } if (iText != -1) { switch (column->justify) { case TK_JUSTIFY_LEFT: partText.left = 0; break; case TK_JUSTIFY_RIGHT: partText.left = layout->width; break; case TK_JUSTIFY_CENTER: if (iImage == -1) partText.left = (layout->width - partText.width) / 2; else partText.left = (layout->width - partImage.width - padList[iText] - partText.width) / 2 + partImage.width + padList[iText]; break; } } if (iImage != -1) { switch (column->justify) { case TK_JUSTIFY_LEFT: partImage.left = 0; break; case TK_JUSTIFY_RIGHT: partImage.left = layout->width; break; case TK_JUSTIFY_CENTER: if (iText == -1) partImage.left = (layout->width - partImage.width) / 2; else partImage.left = (layout->width - partImage.width - padList[iText] - partText.width) / 2; break; } } if (iArrow == -1) goto finish; switch (column->justify) { case TK_JUSTIFY_LEFT: switch (column->arrowSide) { case SIDE_LEFT: partArrow.left = 0; break; case SIDE_RIGHT: switch (column->arrowGravity) { case SIDE_LEFT: partArrow.left = 0; break; case SIDE_RIGHT: partArrow.left = layout->width; break; } break; } break; case TK_JUSTIFY_RIGHT: switch (column->arrowSide) { case SIDE_LEFT: switch (column->arrowGravity) { case SIDE_LEFT: partArrow.left = 0; break; case SIDE_RIGHT: partArrow.left = layout->width; break; } break; case SIDE_RIGHT: partArrow.left = layout->width; break; } break; case TK_JUSTIFY_CENTER: switch (column->arrowSide) { case SIDE_LEFT: switch (column->arrowGravity) { case SIDE_LEFT: partArrow.left = 0; break; case SIDE_RIGHT: if (n == 3) partArrow.left = (layout->width - widthList[1] - padList[2] - widthList[2]) / 2 - padList[1] - widthList[0]; else if (n == 2) partArrow.left = (layout->width - widthList[1]) / 2 - padList[1] - widthList[0]; else partArrow.left = layout->width; break; } break; case SIDE_RIGHT: switch (column->arrowGravity) { case SIDE_LEFT: if (n == 3) partArrow.left = (layout->width - widthList[0] - padList[1] - widthList[1]) / 2 + widthList[0] + padList[1] + widthList[1] + padList[2]; else if (n == 2) partArrow.left = (layout->width - widthList[0]) / 2 + widthList[0] + padList[1]; else partArrow.left = 0; break; case SIDE_RIGHT: partArrow.left = layout->width; break; } break; } break; } finish: right = layout->width - padList[n]; for (i = n - 1; i >= 0; i--) { if (parts[i]->left + parts[i]->width > right) parts[i]->left = right - parts[i]->width; right -= parts[i]->width + padList[i]; } left = padList[0]; for (i = 0; i < n; i++) { if (parts[i]->left < left) parts[i]->left = left; left += parts[i]->width + padList[i + 1]; } if (iArrow != -1) { layout->arrowLeft = partArrow.left; layout->arrowWidth = partArrow.width; layout->arrowHeight = partArrow.height; } if (iImage != -1) { layout->imageLeft = partImage.left; layout->imageWidth = partImage.width; } if (iText != -1) { layout->textLeft = partText.left; layout->textWidth = partText.width; } #if defined(MAC_OSX_TK) /* Under Aqua, we let the Appearance Manager draw the sort arrow */ column->arrow = arrow; column->arrowSide = arrowSide; column->arrowGravity = arrowGravity; #endif } /* *---------------------------------------------------------------------- * * TreeColumn_NeededWidth -- * * Return the total width requested by all the graphical elements * that make up a column header. The width is recalculated if it * is marked out-of-date. * * Results: * The width needed by the current arrangement of the * bitmap/image/text/arrow. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_NeededWidth( TreeColumn column /* Column token. */ ) { TreeCtrl *tree = column->tree; int i, widthList[3], padList[4], n = 0; int arrowWidth, arrowHeight; #if defined(MAC_OSX_TK) int margins[4]; int arrow = column->arrow; #endif if (!tree->showHeader) return 0; if (column->neededWidth >= 0) return column->neededWidth; for (i = 0; i < 3; i++) widthList[i] = 0; for (i = 0; i < 4; i++) padList[i] = 0; #if defined(MAC_OSX_TK) /* Under OSX we let the Appearance Manager draw the sort arrow. */ if (tree->useTheme) column->arrow = ARROW_NONE; #endif if (column->arrow != ARROW_NONE) Column_GetArrowSize(column, &arrowWidth, &arrowHeight); if ((column->arrow != ARROW_NONE) && (column->arrowSide == SIDE_LEFT)) { widthList[n] = arrowWidth; padList[n] = column->arrowPadX[PAD_TOP_LEFT]; padList[n + 1] = column->arrowPadX[PAD_BOTTOM_RIGHT]; n++; } if ((column->image != NULL) || (column->bitmap != None)) { int imgWidth, imgHeight; if (column->image != NULL) Tk_SizeOfImage(column->image, &imgWidth, &imgHeight); else Tk_SizeOfBitmap(tree->display, column->bitmap, &imgWidth, &imgHeight); padList[n] = MAX(column->imagePadX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = column->imagePadX[PAD_BOTTOM_RIGHT]; widthList[n] = imgWidth; n++; } if (column->textLen > 0) { padList[n] = MAX(column->textPadX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = column->textPadX[PAD_BOTTOM_RIGHT]; if (column->textLayoutInvalid || (column->textLayoutWidth != 0)) { Column_UpdateTextLayout(column, 0); column->textLayoutInvalid = FALSE; column->textLayoutWidth = 0; } if (column->textLayout != NULL) TextLayout_Size(column->textLayout, &widthList[n], NULL); else widthList[n] = column->textWidth; n++; } if ((column->arrow != ARROW_NONE) && (column->arrowSide == SIDE_RIGHT)) { widthList[n] = arrowWidth; padList[n] = MAX(column->arrowPadX[PAD_TOP_LEFT], padList[n]); padList[n + 1] = column->arrowPadX[PAD_BOTTOM_RIGHT]; n++; } column->neededWidth = 0; for (i = 0; i < n; i++) column->neededWidth += widthList[i] + padList[i]; column->neededWidth += padList[n]; #if defined(MAC_OSX_TK) if (tree->useTheme) column->arrow = arrow; /* Under OSX we let the Appearance Manager draw the sort arrow. This code * assumes the arrow is on the right. */ if (tree->useTheme && (TreeTheme_GetHeaderContentMargins(tree, column->state, column->arrow, margins) == TCL_OK)) { column->neededWidth += margins[2]; } #endif /* Notice I'm not considering column->borderWidth. */ return column->neededWidth; } /* *---------------------------------------------------------------------- * * TreeColumn_NeededHeight -- * * Return the total height requested by all the graphical elements * that make up a column header. The height is recalculated if it * is marked out-of-date. * * Results: * The height needed by the current arrangement of the * bitmap/image/text/arrow. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_NeededHeight( TreeColumn column /* Column token. */ ) { TreeCtrl *tree = column->tree; int margins[4]; if (column->neededHeight >= 0) return column->neededHeight; #if defined(MAC_OSX_TK) /* List headers are a fixed height on Aqua */ if (tree->useTheme) { (void) TreeTheme_GetHeaderFixedHeight(tree, &column->neededHeight); return column->neededHeight; } #endif column->neededHeight = 0; if (column->arrow != ARROW_NONE) { int arrowWidth, arrowHeight; Column_GetArrowSize(column, &arrowWidth, &arrowHeight); arrowHeight += column->arrowPadY[PAD_TOP_LEFT] + column->arrowPadY[PAD_BOTTOM_RIGHT]; column->neededHeight = MAX(column->neededHeight, arrowHeight); } if ((column->image != NULL) || (column->bitmap != None)) { int imgWidth, imgHeight; if (column->image != NULL) Tk_SizeOfImage(column->image, &imgWidth, &imgHeight); else Tk_SizeOfBitmap(tree->display, column->bitmap, &imgWidth, &imgHeight); imgHeight += column->imagePadY[PAD_TOP_LEFT] + column->imagePadY[PAD_BOTTOM_RIGHT]; column->neededHeight = MAX(column->neededHeight, imgHeight); } if (column->text != NULL) { struct Layout layout; layout.width = TreeColumn_UseWidth(column); layout.height = -1; Column_DoLayout(column, &layout); if (column->textLayout != NULL) { int height; TextLayout_Size(column->textLayout, NULL, &height); height += column->textPadY[PAD_TOP_LEFT] + column->textPadY[PAD_BOTTOM_RIGHT]; column->neededHeight = MAX(column->neededHeight, height); } else { Tk_Font tkfont = column->tkfont ? column->tkfont : column->tree->tkfont; Tk_FontMetrics fm; Tk_GetFontMetrics(tkfont, &fm); fm.linespace += column->textPadY[PAD_TOP_LEFT] + column->textPadY[PAD_BOTTOM_RIGHT]; column->neededHeight = MAX(column->neededHeight, fm.linespace); } } if (column->tree->useTheme && (TreeTheme_GetHeaderContentMargins(tree, column->state, column->arrow, margins) == TCL_OK)) { #ifdef WIN32 /* I'm hacking these margins since the default XP theme does not give * reasonable ContentMargins for HP_HEADERITEM */ int bw = MAX(column->borderWidth, 3); margins[1] = MAX(margins[1], bw); margins[3] = MAX(margins[3], bw); #endif /* WIN32 */ column->neededHeight += margins[1] + margins[3]; } else { column->neededHeight += column->borderWidth * 2; } return column->neededHeight; } /* *---------------------------------------------------------------------- * * TreeColumn_UseWidth -- * * Return the actual display width of a column. * * Results: * Pixel width. * * Side effects: * The size of any column that is marked out-of-date is * recalculated. This could involve recalculating the size of * every element and style in the column in all items. * *---------------------------------------------------------------------- */ int TreeColumn_UseWidth( TreeColumn column /* Column token. */ ) { /* Update layout if needed */ (void) Tree_WidthOfColumns(column->tree); return column->useWidth; } /* *---------------------------------------------------------------------- * * TreeColumn_Offset -- * * Return the x-offset of a column. * * Results: * Pixel offset. * * Side effects: * Column layout is updated if needed. * *---------------------------------------------------------------------- */ int TreeColumn_Offset( TreeColumn column /* Column token. */ ) { /* Update layout if needed */ (void) Tree_WidthOfColumns(column->tree); return column->offset; } /* *---------------------------------------------------------------------- * * TreeColumn_ItemJustify -- * * Return the value of the -itemjustify config option for a column. * If -itemjustify is unspecified, then return the value of the * -justify option. * * Results: * TK_JUSTIFY_xxx constant. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tk_Justify TreeColumn_ItemJustify( TreeColumn column /* Column token. */ ) { return (column->itemJustify != -1) ? column->itemJustify : column->justify; } #ifdef DEPRECATED /* *---------------------------------------------------------------------- * * TreeColumn_WidthHack -- * * Return the value of the -widthhack config option for a column. * NOTE: -widthhack is deprecated. * * Results: * Boolean value. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_WidthHack( TreeColumn column /* Column token. */ ) { return column->widthHack; } #endif /* DEPRECATED */ /* *---------------------------------------------------------------------- * * TreeColumn_Squeeze -- * * Return the value of the -squeeze config option for a column. * * Results: * Boolean value. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_Squeeze( TreeColumn column /* Column token. */ ) { return column->squeeze; } /* *---------------------------------------------------------------------- * * TreeColumn_BackgroundCount -- * * Return the number of -itembackground colors for a column. * * Results: * column->itemBgCount. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_BackgroundCount( TreeColumn column /* Column token. */ ) { return column->itemBgCount; } /* *---------------------------------------------------------------------- * * TreeColumn_BackgroundGC -- * * Return a graphics context for one color of the -itembackground * config option for a column. * * Results: * A graphics context, or None. * * Side effects: * Might allocate a new graphics context? But the GC is freed * when the last reference to the color is lost, so the caller * need not worry about it. * *---------------------------------------------------------------------- */ GC TreeColumn_BackgroundGC( TreeColumn column, /* Column token. */ int index /* This number is determined by the display * code. */ ) { XColor *color; if ((index < 0) || (column->itemBgCount == 0)) return None; color = column->itemBgColor[index % column->itemBgCount]; if (color == NULL) return None; return Tk_GCForColor(color, Tk_WindowId(column->tree->tkwin)); } /* *---------------------------------------------------------------------- * * TreeColumn_ItemStyle -- * * Return the value of the -itemstyle config option for a column. * * Results: * TreeStyle or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeStyle TreeColumn_ItemStyle( TreeColumn column /* Column token. */ ) { return column->itemStyle; } /* *---------------------------------------------------------------------- * * TreeColumn_StyleDeleted -- * * Called when a master style is deleted. * * Results: * Clear the column's -itemstyle option if it is the style being * deleted. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeColumn_StyleDeleted( TreeColumn column, /* Column token. */ TreeStyle style /* Style that was deleted. */ ) { if (column->itemStyle == style) column->itemStyle = NULL; } /* *---------------------------------------------------------------------- * * TreeColumn_Visible -- * * Return the value of the -visible config option for a column. * * Results: * Boolean value. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_Visible( TreeColumn column /* Column token. */ ) { return column->visible; } /* *---------------------------------------------------------------------- * * TreeColumn_GetID -- * * Return the unique identifier for a column. * * Results: * Unique integer id. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_GetID( TreeColumn column /* Column token. */ ) { return column->id; } /* *---------------------------------------------------------------------- * * TreeColumn_Lock -- * * Return the value of the -lock option for a column. * * Results: * One of the COLUMN_LOCK_xxx constants. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_Lock( TreeColumn column /* Column token. */ ) { return column->lock; } /* *---------------------------------------------------------------------- * * TreeColumn_Index -- * * Return the 0-based index for a column. * * Results: * Position of the column in the list of columns. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeColumn_Index( TreeColumn column /* Column token. */ ) { return column->index; } /* *---------------------------------------------------------------------- * * ColumnTagCmd -- * * This procedure is invoked to process the [column tag] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ColumnTagCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; static CONST char *commandNames[] = { "add", "expr", "names", "remove", (char *) NULL }; enum { COMMAND_ADD, COMMAND_EXPR, COMMAND_NAMES, COMMAND_REMOVE }; int index; ColumnForEach iter; TreeColumnList columns; TreeColumn column; int result = TCL_OK; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { /* T column tag add C tagList */ case COMMAND_ADD: { int i, numTags; Tcl_Obj **listObjv; Tk_Uid staticTags[STATIC_SIZE], *tags = staticTags; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "column tagList"); return TCL_ERROR; } if (TreeColumnList_FromObj(tree, objv[4], &columns, 0) != TCL_OK) { return TCL_ERROR; } if (Tcl_ListObjGetElements(interp, objv[5], &numTags, &listObjv) != TCL_OK) { result = TCL_ERROR; break; } STATIC_ALLOC(tags, Tk_Uid, numTags); for (i = 0; i < numTags; i++) { tags[i] = Tk_GetUid(Tcl_GetString(listObjv[i])); } COLUMN_FOR_EACH(column, &columns, NULL, &iter) { column->tagInfo = TagInfo_Add(tree, column->tagInfo, tags, numTags); } STATIC_FREE(tags, Tk_Uid, numTags); break; } /* T column tag expr C tagExpr */ case COMMAND_EXPR: { TagExpr expr; int ok = TRUE; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "column tagExpr"); return TCL_ERROR; } if (TreeColumnList_FromObj(tree, objv[4], &columns, 0) != TCL_OK) { return TCL_ERROR; } if (TagExpr_Init(tree, objv[5], &expr) != TCL_OK) { result = TCL_ERROR; break; } COLUMN_FOR_EACH(column, &columns, NULL, &iter) { if (!TagExpr_Eval(&expr, column->tagInfo)) { ok = FALSE; break; } } TagExpr_Free(&expr); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ok)); break; } /* T column tag names C */ case COMMAND_NAMES: { Tcl_Obj *listObj; Tk_Uid *tags = NULL; int i, tagSpace, numTags = 0; if (objc != 5) { Tcl_WrongNumArgs(interp, 4, objv, "column"); return TCL_ERROR; } if (TreeColumnList_FromObj(tree, objv[4], &columns, 0) != TCL_OK) { return TCL_ERROR; } COLUMN_FOR_EACH(column, &columns, NULL, &iter) { tags = TagInfo_Names(tree, column->tagInfo, tags, &numTags, &tagSpace); } if (numTags) { listObj = Tcl_NewListObj(0, NULL); for (i = 0; i < numTags; i++) { Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewStringObj((char *) tags[i], -1)); } Tcl_SetObjResult(interp, listObj); ckfree((char *) tags); } break; } /* T column tag remove C tagList */ case COMMAND_REMOVE: { int i, numTags; Tcl_Obj **listObjv; Tk_Uid staticTags[STATIC_SIZE], *tags = staticTags; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "column tagList"); return TCL_ERROR; } if (TreeColumnList_FromObj(tree, objv[4], &columns, 0) != TCL_OK) { return TCL_ERROR; } if (Tcl_ListObjGetElements(interp, objv[5], &numTags, &listObjv) != TCL_OK) { result = TCL_ERROR; break; } STATIC_ALLOC(tags, Tk_Uid, numTags); for (i = 0; i < numTags; i++) { tags[i] = Tk_GetUid(Tcl_GetString(listObjv[i])); } COLUMN_FOR_EACH(column, &columns, NULL, &iter) { column->tagInfo = TagInfo_Remove(tree, column->tagInfo, tags, numTags); } STATIC_FREE(tags, Tk_Uid, numTags); break; } } TreeColumnList_Free(&columns); return result; } /* *---------------------------------------------------------------------- * * TreeColumnCmd -- * * This procedure is invoked to process the [column] widget * command. See the user documentation for details on what it * does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeColumnCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; static CONST char *commandNames[] = { "bbox", "cget", "compare", "configure", "count", "create", "delete", "dragcget", "dragconfigure", "id", #ifdef DEPRECATED "index", #endif "list", "move", "neededwidth", "order", "tag", "width", (char *) NULL }; enum { COMMAND_BBOX, COMMAND_CGET, COMMAND_COMPARE, COMMAND_CONFIGURE, COMMAND_COUNT, COMMAND_CREATE, COMMAND_DELETE, COMMAND_DRAGCGET, COMMAND_DRAGCONF, COMMAND_ID, #ifdef DEPRECATED COMMAND_INDEX, #endif COMMAND_LIST, COMMAND_MOVE, COMMAND_NEEDEDWIDTH, COMMAND_ORDER, COMMAND_TAG, COMMAND_WIDTH }; int index; TreeColumnList columns; TreeColumn column; ColumnForEach citer; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } TreeColumnList_Init(tree, &columns, 0); switch (index) { case COMMAND_BBOX: { int left, top, width, height; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "column"); return TCL_ERROR; } if (TreeColumn_FromObj(tree, objv[3], &column, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) return TCL_ERROR; if (TreeColumn_Bbox(column, &left, &top, &width, &height) < 0) break; FormatResult(interp, "%d %d %d %d", left, top, left + width, top + height); break; } case COMMAND_CGET: { TreeColumn column; Tcl_Obj *resultObjPtr; if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "column option"); return TCL_ERROR; } if (TreeColumn_FromObj(tree, objv[3], &column, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; resultObjPtr = Tk_GetOptionValue(interp, (char *) column, column->optionTable, objv[4], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } /* T column compare C op C */ case COMMAND_COMPARE: { TreeColumn column1, column2; static CONST char *opName[] = { "<", "<=", "==", ">=", ">", "!=", NULL }; int op, compare = 0, index1, index2; if (objc != 6) { Tcl_WrongNumArgs(interp, 3, objv, "column1 op column2"); return TCL_ERROR; } if (TreeColumn_FromObj(tree, objv[3], &column1, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if (Tcl_GetIndexFromObj(interp, objv[4], opName, "comparison operator", 0, &op) != TCL_OK) return TCL_ERROR; if (TreeColumn_FromObj(tree, objv[5], &column2, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; index1 = TreeColumn_Index(column1); index2 = TreeColumn_Index(column2); switch (op) { case 0: compare = index1 < index2; break; case 1: compare = index1 <= index2; break; case 2: compare = index1 == index2; break; case 3: compare = index1 >= index2; break; case 4: compare = index1 > index2; break; case 5: compare = index1 != index2; break; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(compare)); break; } case COMMAND_CONFIGURE: { if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "column ?option? ?value? ?option value ...?"); return TCL_ERROR; } if (objc <= 5) { Tcl_Obj *resultObjPtr; if (TreeColumn_FromObj(tree, objv[3], &column, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; resultObjPtr = Tk_GetOptionInfo(interp, (char *) column, column->optionTable, (objc == 4) ? (Tcl_Obj *) NULL : objv[4], tree->tkwin); if (resultObjPtr == NULL) goto errorExit; Tcl_SetObjResult(interp, resultObjPtr); break; } /* If "all" is specified, get a list of columns instead of * COLUMN_ALL, since changing the -lock option of a column * may reorder columns. */ if (TreeColumnList_FromObj(tree, objv[3], &columns, CFO_LIST_ALL | CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; COLUMN_FOR_EACH(column, &columns, NULL, &citer) { if (Column_Config(column, objc - 4, objv + 4, FALSE) != TCL_OK) goto errorExit; } break; } case COMMAND_CREATE: { TreeColumn column, last = tree->columnLast; /* FIXME: -count N -tags $tags */ column = Column_Alloc(tree); if (Column_Config(column, objc - 3, objv + 3, TRUE) != TCL_OK) { Column_Free(column); return TCL_ERROR; } if (tree->columns == NULL) { column->index = 0; tree->columns = column; } else { last->next = column; column->prev = last; column->index = last->index + 1; } tree->columnLast = column; tree->columnTail->index++; { TreeColumn before = NULL; switch (column->lock) { case COLUMN_LOCK_LEFT: before = tree->columnLockNone; if (before == NULL) before = tree->columnLockRight; break; case COLUMN_LOCK_NONE: before = tree->columnLockRight; break; case COLUMN_LOCK_RIGHT: before = NULL; break; } if (before == NULL) before = tree->columnTail; Column_Move(column, before); } /* Indicate that all items must recalculate their list of spans. */ TreeItem_SpansInvalidate(tree, NULL); Tree_DInfoChanged(tree, DINFO_REDO_COLUMN_WIDTH); Tcl_SetObjResult(interp, TreeColumn_ToObj(tree, column)); break; } /* T column delete first ?last? */ case COMMAND_DELETE: { TreeColumnList column2s; TreeColumn prev, next; int flags = CFO_NOT_NULL | CFO_NOT_TAIL; TreeItem item; Tcl_HashEntry *hPtr; Tcl_HashSearch search; int index; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "first ?last?"); return TCL_ERROR; } if (objc == 5) flags |= CFO_NOT_MANY; if (TreeColumnList_FromObj(tree, objv[3], &columns, flags) != TCL_OK) goto errorExit; if (objc == 5) { if (TreeColumnList_FromObj(tree, objv[4], &column2s, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) goto errorExit; } COLUMN_FOR_EACH(column, &columns, (objc == 5) ? &column2s : NULL, &citer) { /* T column delete "all" */ if (citer.all) { column = tree->columns; while (column != NULL) { TreeDisplay_ColumnDeleted(tree, column); column = Column_Free(column); } tree->columnTail->index = 0; tree->columns = NULL; tree->columnLast = NULL; tree->columnLockLeft = NULL; tree->columnLockNone = NULL; tree->columnLockRight = NULL; /* Delete all TreeItemColumns */ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); TreeItem_RemoveAllColumns(tree, item); hPtr = Tcl_NextHashEntry(&search); } tree->columnTree = NULL; tree->columnDrag.column = tree->columnDrag.indColumn = NULL; tree->widthOfColumns = tree->headerHeight = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_DInfoChanged(tree, DINFO_REDO_COLUMN_WIDTH); goto doneDELETE; } /* Delete all TreeItemColumns */ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); TreeItem_RemoveColumns(tree, item, column->index, column->index); hPtr = Tcl_NextHashEntry(&search); } TreeDisplay_ColumnDeleted(tree, column); /* Unlink. */ prev = column->prev; next = column->next; if (prev == NULL) tree->columns = next; else prev->next = next; if (next == NULL) tree->columnLast = prev; else next->prev = prev; if (column == tree->columnTree) tree->columnTree = NULL; if (column == tree->columnDrag.column) tree->columnDrag.column = NULL; if (column == tree->columnDrag.indColumn) tree->columnDrag.indColumn = NULL; (void) Column_Free(column); /* Renumber trailing columns */ column = next; while (column != NULL) { column->index--; column = column->next; } } tree->columnLockLeft = NULL; tree->columnLockNone = NULL; tree->columnLockRight = NULL; index = 0; column = tree->columns; while (column != NULL) { column->index = index++; if (column->lock == COLUMN_LOCK_LEFT && tree->columnLockLeft == NULL) tree->columnLockLeft = column; if (column->lock == COLUMN_LOCK_NONE && tree->columnLockNone == NULL) tree->columnLockNone = column; if (column->lock == COLUMN_LOCK_RIGHT && tree->columnLockRight == NULL) tree->columnLockRight = column; column = column->next; } tree->columnTail->index = index; tree->widthOfColumns = tree->headerHeight = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_DInfoChanged(tree, DINFO_REDO_COLUMN_WIDTH); doneDELETE: /* Indicate that all items must recalculate their list of spans. */ TreeItem_SpansInvalidate(tree, NULL); if (objc == 5) TreeColumnList_Free(&column2s); break; } /* T column dragcget option */ case COMMAND_DRAGCGET: { Tcl_Obj *resultObjPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "option"); return TCL_ERROR; } resultObjPtr = Tk_GetOptionValue(interp, (char *) tree, tree->columnDrag.optionTable, objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } /* T column dragconfigure ?option? ?value? ?option value ...? */ case COMMAND_DRAGCONF: { Tcl_Obj *resultObjPtr; Tk_SavedOptions savedOptions; int mask, result; if (objc < 3) { Tcl_WrongNumArgs(interp, 3, objv, "?option? ?value?"); return TCL_ERROR; } if (objc <= 4) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) tree, tree->columnDrag.optionTable, (objc == 3) ? (Tcl_Obj *) NULL : objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } result = Tk_SetOptions(interp, (char *) tree, tree->columnDrag.optionTable, objc - 3, objv + 3, tree->tkwin, &savedOptions, &mask); if (result != TCL_OK) { Tk_RestoreSavedOptions(&savedOptions); return TCL_ERROR; } Tk_FreeSavedOptions(&savedOptions); if (tree->columnDrag.alpha < 0) tree->columnDrag.alpha = 0; if (tree->columnDrag.alpha > 255) tree->columnDrag.alpha = 255; Tree_DInfoChanged(tree, DINFO_DRAW_HEADER); break; } case COMMAND_COUNT: { int count = tree->columnCount; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 3, objv, "?columnDesc?"); return TCL_ERROR; } if (objc == 4) { if (TreeColumnList_FromObj(tree, objv[3], &columns, 0) != TCL_OK) return TCL_ERROR; count = 0; COLUMN_FOR_EACH(column, &columns, NULL, &citer) { count++; } } Tcl_SetObjResult(interp, Tcl_NewIntObj(count)); break; } case COMMAND_WIDTH: { if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "column"); return TCL_ERROR; } if (TreeColumn_FromObj(tree, objv[3], &column, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; /* Update layout if needed */ (void) Tree_WidthOfColumns(tree); Tcl_SetObjResult(interp, Tcl_NewIntObj(column->useWidth)); break; } case COMMAND_ID: #ifdef DEPRECATED case COMMAND_INDEX: #endif { Tcl_Obj *listObj; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "column"); return TCL_ERROR; } if (TreeColumnList_FromObj(tree, objv[3], &columns, 0) != TCL_OK) return TCL_ERROR; listObj = Tcl_NewListObj(0, NULL); COLUMN_FOR_EACH(column, &columns, NULL, &citer) { Tcl_ListObjAppendElement(interp, listObj, TreeColumn_ToObj(tree, column)); } Tcl_SetObjResult(interp, listObj); break; } /* T column list ?-visible? */ case COMMAND_LIST: { TreeColumn column = tree->columns; Tcl_Obj *listObj; int visible = FALSE; if (objc > 4) { Tcl_WrongNumArgs(interp, 3, objv, "?-visible?"); return TCL_ERROR; } if (objc == 4) { int len; char *s = Tcl_GetStringFromObj(objv[3], &len); if ((s[0] == '-') && (strncmp(s, "-visible", len) == 0)) visible = TRUE; else { FormatResult(interp, "bad switch \"%s\": must be -visible", s); return TCL_ERROR; } } listObj = Tcl_NewListObj(0, NULL); while (column != NULL) { if (!visible || column->visible) Tcl_ListObjAppendElement(interp, listObj, TreeColumn_ToObj(tree, column)); column = column->next; } Tcl_SetObjResult(interp, listObj); break; } /* T column move C before */ case COMMAND_MOVE: { TreeColumn move, before; TreeColumn first = NULL, last = tree->columnTail; if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "column before"); return TCL_ERROR; } if (TreeColumn_FromObj(tree, objv[3], &move, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) return TCL_ERROR; if (TreeColumn_FromObj(tree, objv[4], &before, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if ((move == before) || (move->index == before->index - 1)) break; switch (move->lock) { case COLUMN_LOCK_LEFT: first = tree->columnLockLeft; if (tree->columnLockNone != NULL) last = tree->columnLockNone; else if (tree->columnLockRight != NULL) last = tree->columnLockRight; break; case COLUMN_LOCK_NONE: first = tree->columnLockNone; if (tree->columnLockRight != NULL) last = tree->columnLockRight; break; case COLUMN_LOCK_RIGHT: first = tree->columnLockRight; break; } if (before->index < first->index || before->index > last->index) { FormatResult(tree->interp, "column %s%d and column %s%d -lock options conflict", tree->columnPrefix, move->id, tree->columnPrefix, before->id); return TCL_ERROR; } Column_Move(move, before); /* Indicate that all items must recalculate their list of spans. */ TreeItem_SpansInvalidate(tree, NULL); break; } case COMMAND_NEEDEDWIDTH: { TreeColumn column; int width; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "column"); return TCL_ERROR; } if (TreeColumn_FromObj(tree, objv[3], &column, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; /* Update layout if needed */ (void) Tree_TotalWidth(tree); width = TreeColumn_WidthOfItems(column); width = MAX(width, TreeColumn_NeededWidth(column)); Tcl_SetObjResult(interp, Tcl_NewIntObj(width)); break; } /* T column order C ?-visible? */ case COMMAND_ORDER: { TreeColumn column; int visible = FALSE; int index = 0; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "column ?-visible?"); return TCL_ERROR; } if (objc == 5) { int len; char *s = Tcl_GetStringFromObj(objv[4], &len); if ((s[0] == '-') && (strncmp(s, "-visible", len) == 0)) visible = TRUE; else { FormatResult(interp, "bad switch \"%s\": must be -visible", s); return TCL_ERROR; } } if (TreeColumn_FromObj(tree, objv[3], &column, CFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if (visible) { TreeColumn walk = tree->columns; while (walk != NULL) { if (walk == column) break; if (walk->visible) index++; walk = walk->next; } if (!column->visible) index = -1; } else { index = column->index; } Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); break; } case COMMAND_TAG: { return ColumnTagCmd(clientData, interp, objc, objv); } } TreeColumnList_Free(&columns); return TCL_OK; errorExit: TreeColumnList_Free(&columns); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Column_DrawArrow -- * * Draw the sort arrow for a column. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ static void Column_DrawArrow( TreeColumn column, /* Column record. */ TreeDrawable td, /* Where to draw. */ int x, int y, /* Top-left corner of the column's header. */ struct Layout layout /* Size/position info. */ ) { TreeCtrl *tree = column->tree; int height = tree->headerHeight; int sunken = column->state == COLUMN_STATE_PRESSED; Tk_Image image = NULL; Pixmap bitmap; Tk_3DBorder border; int state = Column_MakeState(column); int arrowPadY = column->arrowPadY[PAD_TOP_LEFT] + column->arrowPadY[PAD_BOTTOM_RIGHT]; if (column->arrow == ARROW_NONE) return; image = PerStateImage_ForState(tree, &column->arrowImage, state, NULL); if (image != NULL) { Tree_RedrawImage(image, 0, 0, layout.arrowWidth, layout.arrowHeight, td, x + layout.arrowLeft + sunken, y + (height - (layout.arrowHeight + arrowPadY)) / 2 + sunken); return; } bitmap = PerStateBitmap_ForState(tree, &column->arrowBitmap, state, NULL); if (bitmap != None) { int bx, by; bx = x + layout.arrowLeft + sunken; by = y + (height - (layout.arrowHeight + arrowPadY)) / 2 + sunken; Tree_DrawBitmap(tree, bitmap, td.drawable, NULL, NULL, 0, 0, (unsigned int) layout.arrowWidth, (unsigned int) layout.arrowHeight, bx, by); return; } if (tree->useTheme) { if (TreeTheme_DrawHeaderArrow(tree, td.drawable, column->arrow == ARROW_UP, x + layout.arrowLeft + sunken, y + (height - (layout.arrowHeight + arrowPadY)) / 2 + sunken, layout.arrowWidth, layout.arrowHeight) == TCL_OK) return; } if (1) { int arrowWidth = layout.arrowWidth; int arrowHeight = layout.arrowHeight; int arrowTop = y + (height - (layout.arrowHeight + arrowPadY)) / 2 + column->arrowPadY[PAD_TOP_LEFT]; int arrowBottom = arrowTop + arrowHeight; XPoint points[5]; int color1 = 0, color2 = 0; int i; switch (column->arrow) { case ARROW_UP: points[0].x = x + layout.arrowLeft; points[0].y = arrowBottom - 1; points[1].x = x + layout.arrowLeft + arrowWidth / 2; points[1].y = arrowTop - 1; color1 = TK_3D_DARK_GC; points[4].x = x + layout.arrowLeft + arrowWidth / 2; points[4].y = arrowTop - 1; points[3].x = x + layout.arrowLeft + arrowWidth - 1; points[3].y = arrowBottom - 1; points[2].x = x + layout.arrowLeft; points[2].y = arrowBottom - 1; color2 = TK_3D_LIGHT_GC; break; case ARROW_DOWN: points[0].x = x + layout.arrowLeft + arrowWidth - 1; points[0].y = arrowTop; points[1].x = x + layout.arrowLeft + arrowWidth / 2; points[1].y = arrowBottom; color1 = TK_3D_LIGHT_GC; points[2].x = x + layout.arrowLeft + arrowWidth - 1; points[2].y = arrowTop; points[3].x = x + layout.arrowLeft; points[3].y = arrowTop; points[4].x = x + layout.arrowLeft + arrowWidth / 2; points[4].y = arrowBottom; color2 = TK_3D_DARK_GC; break; } for (i = 0; i < 5; i++) { points[i].x += sunken; points[i].y += sunken; } border = PerStateBorder_ForState(tree, &column->border, state, NULL); if (border == NULL) border = tree->border; XDrawLines(tree->display, td.drawable, Tk_3DBorderGC(tree->tkwin, border, color2), points + 2, 3, CoordModeOrigin); XDrawLines(tree->display, td.drawable, Tk_3DBorderGC(tree->tkwin, border, color1), points, 2, CoordModeOrigin); } } /* *---------------------------------------------------------------------- * * Column_Draw -- * * Draw the header for a column. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ static void Column_Draw( TreeColumn column, /* Column record. */ TreeDrawable td, /* Where to draw. */ int x, int y, /* Top-left corner of the column's header. */ int dragImage /* TRUE if we are creating a transparent * drag image for this header. */ ) { TreeCtrl *tree = column->tree; int height = tree->headerHeight; struct Layout layout; int width = column->useWidth; int sunken = column->state == COLUMN_STATE_PRESSED; int relief = sunken ? TK_RELIEF_SUNKEN : TK_RELIEF_RAISED; Tk_3DBorder border; int theme = TCL_ERROR; layout.width = width; layout.height = height; Column_DoLayout(column, &layout); border = PerStateBorder_ForState(tree, &column->border, Column_MakeState(column), NULL); if (border == NULL) border = tree->border; if (dragImage) { GC gc = Tk_GCForColor(tree->columnDrag.color, Tk_WindowId(tree->tkwin)); XFillRectangle(tree->display, td.drawable, gc, x, y, width, height); } else { if (tree->useTheme) { theme = TreeTheme_DrawHeaderItem(tree, td.drawable, column->state, column->arrow, x, y, width, height); } if (theme != TCL_OK) Tk_Fill3DRectangle(tree->tkwin, td.drawable, border, x, y, width, height, 0, TK_RELIEF_FLAT); } if (column->image != NULL) { int imgW, imgH, ix, iy, h; Tk_SizeOfImage(column->image, &imgW, &imgH); ix = x + layout.imageLeft + sunken; h = column->imagePadY[PAD_TOP_LEFT] + imgH + column->imagePadY[PAD_BOTTOM_RIGHT]; iy = y + (height - h) / 2 + sunken; iy += column->imagePadY[PAD_TOP_LEFT]; Tree_RedrawImage(column->image, 0, 0, imgW, imgH, td, ix, iy); } else if (column->bitmap != None) { int imgW, imgH, bx, by, h; Tk_SizeOfBitmap(tree->display, column->bitmap, &imgW, &imgH); bx = x + layout.imageLeft + sunken; h = column->imagePadY[PAD_TOP_LEFT] + imgH + column->imagePadY[PAD_BOTTOM_RIGHT]; by = y + (height - h) / 2 + sunken; by += column->imagePadY[PAD_TOP_LEFT]; Tree_DrawBitmapWithGC(tree, column->bitmap, td.drawable, column->bitmapGC, 0, 0, (unsigned int) imgW, (unsigned int) imgH, bx, by); } if ((column->text != NULL) && (column->textLayout != NULL)) { int h; XGCValues gcValues; GC gc; unsigned long mask; TextLayout_Size(column->textLayout, NULL, &h); h += column->textPadY[PAD_TOP_LEFT] + column->textPadY[PAD_BOTTOM_RIGHT]; gcValues.font = Tk_FontId(column->tkfont ? column->tkfont : tree->tkfont); gcValues.foreground = column->textColor->pixel; gcValues.graphics_exposures = False; mask = GCFont | GCForeground | GCGraphicsExposures; gc = Tree_GetGC(tree, mask, &gcValues); TextLayout_Draw(tree->display, td.drawable, gc, column->textLayout, x + layout.textLeft + sunken, y + (height - h) / 2 + column->textPadY[PAD_TOP_LEFT] + sunken, 0, -1, -1); } else if ((column->text != NULL) && (layout.bytesThatFit != 0)) { XGCValues gcValues; GC gc; unsigned long mask; char staticStr[256], *text = staticStr; int textLen = column->textLen; char *ellipsis = "..."; int ellipsisLen = strlen(ellipsis); int tx, ty, h; if (textLen + ellipsisLen > sizeof(staticStr)) text = ckalloc(textLen + ellipsisLen); memcpy(text, column->text, textLen); if (layout.bytesThatFit != textLen) { textLen = abs(layout.bytesThatFit); if (layout.bytesThatFit > 0) { memcpy(text + layout.bytesThatFit, ellipsis, ellipsisLen); textLen += ellipsisLen; } } gcValues.font = Tk_FontId(layout.tkfont); gcValues.foreground = column->textColor->pixel; gcValues.graphics_exposures = False; mask = GCFont | GCForeground | GCGraphicsExposures; gc = Tree_GetGC(tree, mask, &gcValues); tx = x + layout.textLeft + sunken; h = column->textPadY[PAD_TOP_LEFT] + layout.fm.linespace + column->textPadY[PAD_BOTTOM_RIGHT]; ty = y + (height - h) / 2 + layout.fm.ascent + sunken; ty += column->textPadY[PAD_TOP_LEFT]; Tk_DrawChars(tree->display, td.drawable, gc, layout.tkfont, text, textLen, tx, ty); if (text != staticStr) ckfree(text); } if (dragImage) return; #if defined(MAC_OSX_TK) /* Under Aqua, we let the Appearance Manager draw the sort arrow */ if (theme != TCL_OK) #endif Column_DrawArrow(column, td, x, y, layout); if (theme != TCL_OK) Tk_Draw3DRectangle(tree->tkwin, td.drawable, border, x, y, width, height, column->borderWidth, relief); } /* *---------------------------------------------------------------------- * * SetImageForColumn -- * * Set a photo image containing a simplified picture of the header * of a column. This image is used when dragging and dropping a column * header. * * Results: * Token for a photo image, or NULL if the image could not be * created. * * Side effects: * A photo image called "::TreeCtrl::ImageColumn" will be created if * it doesn't exist. The image is set to contain a picture of the * column header. * *---------------------------------------------------------------------- */ static Tk_Image SetImageForColumn( TreeCtrl *tree, /* Widget info. */ TreeColumn column /* Column record. */ ) { Tk_PhotoHandle photoH; TreeDrawable td; int width = column->useWidth; /* the entire column, not just what is visible */ int height = tree->headerHeight; XImage *ximage; photoH = Tk_FindPhoto(tree->interp, "::TreeCtrl::ImageColumn"); if (photoH == NULL) { Tcl_GlobalEval(tree->interp, "image create photo ::TreeCtrl::ImageColumn"); photoH = Tk_FindPhoto(tree->interp, "::TreeCtrl::ImageColumn"); if (photoH == NULL) return NULL; } td.width = width; td.height = height; td.drawable = Tk_GetPixmap(tree->display, Tk_WindowId(tree->tkwin), width, height, Tk_Depth(tree->tkwin)); Column_Draw(column, td, 0, 0, TRUE); /* Pixmap -> XImage */ ximage = XGetImage(tree->display, td.drawable, 0, 0, (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap); if (ximage == NULL) panic("tkTreeColumn.c:SetImageForColumn() ximage is NULL"); /* XImage -> Tk_Image */ Tree_XImage2Photo(tree->interp, photoH, ximage, tree->columnDrag.alpha); XDestroyImage(ximage); Tk_FreePixmap(tree->display, td.drawable); return Tk_GetImage(tree->interp, tree->tkwin, "::TreeCtrl::ImageColumn", NULL, (ClientData) NULL); } static void DrawDragIndicator( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ int lock ) { TreeColumn column = tree->columnDrag.indColumn; int x, y, w, h; int minX = 0, maxX = 0; GC gc; if ((column == NULL) || (column->lock != lock)) return; switch (lock) { case COLUMN_LOCK_LEFT: minX = Tree_HeaderLeft(tree); maxX = Tree_ContentLeft(tree); break; case COLUMN_LOCK_NONE: minX = Tree_ContentLeft(tree); maxX = Tree_ContentRight(tree); break; case COLUMN_LOCK_RIGHT: minX = Tree_ContentRight(tree); maxX = Tree_HeaderRight(tree); break; } if (TreeColumn_Bbox(column, &x, &y, &w, &h) == 0) { if (tree->columnDrag.indSide == SIDE_LEFT) { x -= 1; if (x == minX - 1) x += 1; } else { x += w - 1; if (x == maxX - 1) x -= 1; } gc = Tk_GCForColor(tree->columnDrag.indColor, Tk_WindowId(tree->tkwin)); XFillRectangle(tree->display, drawable, gc, x, y, 2, tree->headerHeight); } } static void DrawHeaderLeft( TreeCtrl *tree, /* Widget info. */ TreeDrawable td /* Where to draw. */ ) { TreeColumn column = tree->columnLockLeft; Tk_Window tkwin = tree->tkwin; int x = Tree_HeaderLeft(tree), y = Tree_HeaderTop(tree); TreeDrawable td2; td2.width = Tk_Width(tkwin); td2.height = Tree_HeaderBottom(tree); td2.drawable = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), td2.width, td2.height, Tk_Depth(tkwin)); while (column != NULL && column->lock == COLUMN_LOCK_LEFT) { if (column->visible) { Column_Draw(column, td2, x, y, FALSE); x += column->useWidth; } column = column->next; } DrawDragIndicator(tree, td2.drawable, COLUMN_LOCK_LEFT); XCopyArea(tree->display, td2.drawable, td.drawable, tree->copyGC, Tree_HeaderLeft(tree), y, x - Tree_HeaderLeft(tree), tree->headerHeight, Tree_HeaderLeft(tree), y); Tk_FreePixmap(tree->display, td2.drawable); } static void DrawHeaderRight( TreeCtrl *tree, /* Widget info. */ TreeDrawable td /* Where to draw. */ ) { TreeColumn column = tree->columnLockRight; Tk_Window tkwin = tree->tkwin; int x = Tree_ContentRight(tree), y = Tree_HeaderTop(tree); TreeDrawable td2; td2.width = Tk_Width(tkwin); td2.height = Tree_HeaderBottom(tree); td2.drawable = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), td2.width, td2.height, Tk_Depth(tkwin)); while (column != NULL && column->lock == COLUMN_LOCK_RIGHT) { if (column->visible) { Column_Draw(column, td2, x, y, FALSE); x += column->useWidth; } column = column->next; } DrawDragIndicator(tree, td2.drawable, COLUMN_LOCK_RIGHT); XCopyArea(tree->display, td2.drawable, td.drawable, tree->copyGC, Tree_ContentRight(tree), y, x - Tree_ContentRight(tree), tree->headerHeight, Tree_ContentRight(tree), y); Tk_FreePixmap(tree->display, td2.drawable); } /* *---------------------------------------------------------------------- * * Tree_DrawHeader -- * * Draw the header of every column. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ void Tree_DrawHeader( TreeCtrl *tree, /* Widget info. */ TreeDrawable td, /* Where to draw. */ int x, int y /* Top-left corner of the header. */ ) { TreeColumn column = tree->columns; Tk_Window tkwin = tree->tkwin; int minX, maxX, width, height; Drawable drawable = td.drawable; TreeDrawable tp; Drawable pixmap; /* Update layout if needed */ (void) Tree_HeaderHeight(tree); (void) Tree_WidthOfColumns(tree); minX = Tree_ContentLeft(tree); maxX = Tree_ContentRight(tree); if (tree->doubleBuffer == DOUBLEBUFFER_ITEM) { tp.width = Tk_Width(tkwin); tp.height = Tree_HeaderBottom(tree); tp.drawable = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), tp.width, tp.height, Tk_Depth(tkwin)); } else { tp = td; } pixmap = tp.drawable; column = tree->columnLockNone; while (column != NULL && column->lock == COLUMN_LOCK_NONE) { if (column->visible) { if ((x < maxX) && (x + column->useWidth > minX)) Column_Draw(column, tp, x, y, FALSE); x += column->useWidth; } column = column->next; } /* Draw "tail" column */ if (x < maxX) { column = tree->columnTail; width = maxX - x + column->borderWidth; height = tree->headerHeight; if (!column->visible) { Tk_Fill3DRectangle(tkwin, pixmap, tree->border, x, y, width, height, 0, TK_RELIEF_FLAT); } else if (tree->useTheme && (TreeTheme_DrawHeaderItem(tree, pixmap, 0, 0, x, y, width, height) == TCL_OK)) { } else { Tk_3DBorder border; border = PerStateBorder_ForState(tree, &column->border, Column_MakeState(column), NULL); if (border == NULL) border = tree->border; Tk_Fill3DRectangle(tkwin, pixmap, border, x, y, width, height, column->borderWidth, TK_RELIEF_RAISED); } } if (minX < maxX) DrawDragIndicator(tree, pixmap, COLUMN_LOCK_NONE); if (Tree_WidthOfLeftColumns(tree) > 0) DrawHeaderLeft(tree, tp); if (Tree_WidthOfRightColumns(tree) > 0) DrawHeaderRight(tree, tp); if (tree->columnDrag.column != NULL) { Tk_Image image; int x, y, w, h; if (TreeColumn_Bbox(tree->columnDrag.column, &x, &y, &w, &h) == 0) { int ix = 0, iy = 0, iw = w, ih = tree->headerHeight; image = SetImageForColumn(tree, tree->columnDrag.column); x += tree->columnDrag.offset; Tree_RedrawImage(image, ix, iy, iw, ih, tp, x, y); Tk_FreeImage(image); } } if (tree->doubleBuffer == DOUBLEBUFFER_ITEM) { XCopyArea(tree->display, pixmap, drawable, tree->copyGC, Tree_HeaderLeft(tree), y, Tree_HeaderWidth(tree), tree->headerHeight, Tree_HeaderLeft(tree), y); Tk_FreePixmap(tree->display, pixmap); } } /* *---------------------------------------------------------------------- * * TreeColumn_WidthOfItems -- * * Calculate the maximum needed width of the styles in every * ReallyVisible() item for a particular column. The width will * only be recalculated if it is marked out-of-date. * * Results: * Pixel width. * * Side effects: * The size of elements and styles will be updated if they are * marked out-of-date. * *---------------------------------------------------------------------- */ int TreeColumn_WidthOfItems( TreeColumn column /* Column token. */ ) { TreeCtrl *tree = column->tree; TreeItem item; TreeItemColumn itemColumn; int width; if (column->widthOfItems >= 0) return column->widthOfItems; column->widthOfItems = 0; item = tree->root; if (!TreeItem_ReallyVisible(tree, item)) item = TreeItem_NextVisible(tree, item); while (item != NULL) { #ifdef EXPENSIVE_SPAN_WIDTH /* NOT USED */ width = TreeItem_NeededWidthOfColumn(tree, item, column->index); if (column == tree->columnTree) width += TreeItem_Indent(tree, item); column->widthOfItems = MAX(column->widthOfItems, width); #else itemColumn = TreeItem_FindColumn(tree, item, column->index); if (itemColumn != NULL) { width = TreeItemColumn_NeededWidth(tree, item, itemColumn); if (column == tree->columnTree) width += TreeItem_Indent(tree, item); column->widthOfItems = MAX(column->widthOfItems, width); } #endif item = TreeItem_NextVisible(tree, item); } return column->widthOfItems; } /* *---------------------------------------------------------------------- * * Tree_InvalidateColumnWidth -- * * Marks the width of zero or more columns as out-of-date. * Schedules a redisplay to check the widths of columns which * will perform any relayout necessary. * * Results: * None. * * Side effects: * Idle task may be scheduled. * *---------------------------------------------------------------------- */ void Tree_InvalidateColumnWidth( TreeCtrl *tree, /* Widget info. */ TreeColumn column /* Column to modify. NULL means * modify every column. */ ) { #ifdef COLUMN_SPANxxx /* It may be necessary to recalculate the width of other columns as * well when column-spanning is in effect. */ column = NULL; #endif if (column == NULL) { column = tree->columns; while (column != NULL) { column->widthOfItems = -1; column = column->next; } } else { column->widthOfItems = -1; } tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_DInfoChanged(tree, DINFO_CHECK_COLUMN_WIDTH); } /* *---------------------------------------------------------------------- * * Tree_InvalidateColumnHeight -- * * Marks the height of zero or more column headers as out-of-date. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tree_InvalidateColumnHeight( TreeCtrl *tree, /* Widget info. */ TreeColumn column /* Column to modify. NULL means * modify every column. */ ) { if (column == NULL) { column = tree->columns; while (column != NULL) { column->neededHeight = -1; column = column->next; } } else { column->neededHeight = -1; } tree->headerHeight = -1; } /* *---------------------------------------------------------------------- * * TreeColumn_TreeChanged -- * * Called when a TreeCtrl is configured. Performs any relayout * necessary on column headers. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeColumn_TreeChanged( TreeCtrl *tree, /* Widget info. */ int flagT /* TREE_CONF_xxx flags. */ ) { TreeColumn column; /* Column widths are invalidated elsewhere */ if (flagT & TREE_CONF_FONT) { column = tree->columns; while (column != NULL) { if ((column->tkfont == NULL) && (column->textLen > 0)) { column->textWidth = Tk_TextWidth(tree->tkfont, column->text, column->textLen); column->neededWidth = column->neededHeight = -1; column->textLayoutInvalid = TRUE; } column = column->next; } tree->headerHeight = -1; } } /* *---------------------------------------------------------------------- * * Tree_HeaderHeight -- * * Return the total height of the column header area. The height * is only recalculated if it is marked out-of-date. * * Results: * Pixel height. Will be zero if the -showheader option is FALSE. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tree_HeaderHeight( TreeCtrl *tree /* Widget info. */ ) { TreeColumn column; int height; if (!tree->showHeader) return 0; if (tree->headerHeight >= 0) return tree->headerHeight; height = 0; column = tree->columns; while (column != NULL) { if (column->visible) height = MAX(height, TreeColumn_NeededHeight(column)); column = column->next; } return tree->headerHeight = height; } /* *-------------------------------------------------------------- * * TreeColumn_Bbox -- * * Return the bounding box for a column header. * * Results: * Return value is -1 if the item is not visible. * * Side effects: * Column layout will be updated if needed. * *-------------------------------------------------------------- */ int TreeColumn_Bbox( TreeColumn column, /* Column token. */ int *x, int *y, /* Out: window coordinates. */ int *w, int *h /* Out: width and height. */ ) { TreeCtrl *tree = column->tree; int left = 0 - tree->xOrigin; if (!tree->showHeader || !TreeColumn_Visible(column)) return -1; *y = Tree_HeaderTop(tree); *h = Tree_HeaderHeight(tree); if (column == tree->columnTail) { *x = Tree_WidthOfColumns(tree) - tree->xOrigin; *w = 1; /* xxx */ return 0; } /* Get width (and update column layout) */ *w = TreeColumn_UseWidth(column); switch (TreeColumn_Lock(column)) { case COLUMN_LOCK_LEFT: left = Tree_BorderLeft(tree); break; case COLUMN_LOCK_NONE: break; case COLUMN_LOCK_RIGHT: left = Tree_ContentRight(tree); break; } *x = left + TreeColumn_Offset(column); return 0; } /* *-------------------------------------------------------------- * * Tree_HeaderUnderPoint -- * * Return a TreeColumn whose header contains the given coordinates. * * Results: * TreeColumn token or NULL if no column contains the point. * * Side effects: * Column layout will be updated if needed. * *-------------------------------------------------------------- */ TreeColumn Tree_HeaderUnderPoint( TreeCtrl *tree, /* Widget info. */ int *x_, int *y_, /* In: window coordinates. * Out: coordinates relative to top-left * corner of the returned column. */ int *w, int *h, /* Returned width and height. */ int nearest /* TRUE if the column nearest the coordinates * should be returned. */ ) { Tk_Window tkwin = tree->tkwin; int x = *x_, y = *y_; int left, top, width, height; TreeColumn column = tree->columns; int hit; hit = Tree_HitTest(tree, x, y); if (!nearest && (hit != TREE_AREA_HEADER)) return NULL; if (nearest) { if (x < Tree_BorderLeft(tree)) x = Tree_BorderLeft(tree); if (x >= Tree_BorderRight(tree)) x = Tree_BorderRight(tree) - 1; if (y < Tree_BorderTop(tree)) y = Tree_BorderTop(tree); if (y >= Tree_ContentTop(tree)) y = Tree_ContentTop(tree) - 1; } /* Test the columns in reverse of drawing order. */ column = tree->columnLockRight; while ((column != NULL) && (TreeColumn_Lock(column) == COLUMN_LOCK_RIGHT)) { if (TreeColumn_Bbox(column, &left, &top, &width, &height) == 0) { if ((x >= left) && (x < left + width)) { goto done; } } column = TreeColumn_Next(column); } column = tree->columnLockLeft; while ((column != NULL) && (TreeColumn_Lock(column) == COLUMN_LOCK_LEFT)) { if (TreeColumn_Bbox(column, &left, &top, &width, &height) == 0) { if ((x >= left) && (x < left + width)) { goto done; } } column = TreeColumn_Next(column); } column = tree->columnLockNone; while ((column != NULL) && (TreeColumn_Lock(column) == COLUMN_LOCK_NONE)) { if (TreeColumn_Bbox(column, &left, &top, &width, &height) == 0) { if ((x >= left) && (x < left + width)) { goto done; } } column = TreeColumn_Next(column); } column = tree->columnTail; left = Tree_WidthOfColumns(tree) - tree->xOrigin; width = Tk_Width(tkwin) - left; done: (*x_) = x - left; (*y_) = y - Tree_HeaderTop(tree); (*w) = width; (*h) = Tree_HeaderHeight(tree); return column; } /* *---------------------------------------------------------------------- * * LayoutColumns -- * * Calculates the display width and horizontal offset of a range * of columns. * * Results: * The .useWidth and .offset fields of every column in the range * are updated. * The result is the sum of the widths of all visible columns in the * range. * * Side effects: * The size of elements and styles may be updated if they are * marked out-of-date. * *---------------------------------------------------------------------- */ static int LayoutColumns( TreeColumn first, /* First column to update. All columns * with the same -lock value are updated. */ TreeColumn *visPtr, /* Out: first visible column. */ int *countVisPtr /* Out: number of visible columns. */ ) { TreeCtrl *tree; TreeColumn column; int width, visWidth, totalWidth = 0; int numExpand = 0, numSqueeze = 0; #ifdef UNIFORM_GROUP Tcl_HashEntry *hPtr; Tcl_HashSearch search; UniformGroup *uniform; int uniformCount = 0; #endif if (visPtr != NULL) (*visPtr) = NULL; (*countVisPtr) = 0; if (first == NULL) return 0; tree = first->tree; #ifdef UNIFORM_GROUP /* Initialize the .minSize field of every uniform group. */ hPtr = Tcl_FirstHashEntry(&tree->uniformGroupHash, &search); while (hPtr != NULL) { uniform = (UniformGroup *) Tcl_GetHashValue(hPtr); uniform->minSize = 0; hPtr = Tcl_NextHashEntry(&search); } #endif /* * Determine the initial display width of each column. This will be: * a) the column's -width option (a fixed width), or * b) the maximum of: * 1) the width requested by the column's header * 2) the width requested by each item style in that column * For b) the width is clipped to -minwidth and -maxwidth. */ column = first; while (column != NULL && column->lock == first->lock) { if (column->visible) { if (column->widthObj != NULL) width = column->width; else { width = TreeColumn_WidthOfItems(column); width = MAX(width, TreeColumn_NeededWidth(column)); width = MAX(width, TreeColumn_MinWidth(column)); if (TreeColumn_MaxWidth(column) != -1) width = MIN(width, TreeColumn_MaxWidth(column)); #ifdef UNIFORM_GROUP /* Track the maximum requested width of every column in this * column's uniform group considering -weight. */ if (column->uniform != NULL) { int weight = MAX(column->weight, 1); int minSize = (width + weight - 1) / weight; if (minSize > column->uniform->minSize) column->uniform->minSize = minSize; uniformCount++; } if (column->expand) numExpand += MAX(column->weight, 0); if (column->squeeze) numSqueeze += MAX(column->weight, 0); #else if (column->expand) numExpand++; if (column->squeeze) numSqueeze++; #endif } if (visPtr != NULL && (*visPtr) == NULL) (*visPtr) = column; (*countVisPtr)++; } else width = 0; column->useWidth = width; totalWidth += width; column = column->next; } #ifdef UNIFORM_GROUP /* Apply the -uniform and -weight options. */ if (uniformCount > 0) { column = first; while (column != NULL && column->lock == first->lock) { if (column->visible && column->widthObj == NULL && column->uniform != NULL) { int weight = MAX(column->weight, 1); width = column->uniform->minSize * weight; if (column->maxWidthObj != NULL) width = MIN(width, column->maxWidth); totalWidth -= column->useWidth; column->useWidth = width; totalWidth += width; } column = column->next; } } #endif /* UNIFORM_GROUP */ /* Locked columns don't squeeze or expand. */ if (first->lock != COLUMN_LOCK_NONE) goto doOffsets; visWidth = Tree_ContentWidth(tree); if (visWidth <= 0) goto doOffsets; /* Squeeze columns */ if ((visWidth < totalWidth) && (numSqueeze > 0)) { int spaceRemaining = totalWidth - visWidth; while ((spaceRemaining > 0) && (numSqueeze > 0)) { int each = (spaceRemaining >= numSqueeze) ? spaceRemaining / numSqueeze : 1; numSqueeze = 0; column = first; while (column != NULL && column->lock == first->lock) { if (column->visible && column->squeeze && (column->widthObj == NULL)) { int min = MAX(0, TreeColumn_MinWidth(column)); if (column->useWidth > min) { int sub = MIN(each, column->useWidth - min); column->useWidth -= sub; spaceRemaining -= sub; if (!spaceRemaining) break; if (column->useWidth > min) numSqueeze++; } } column = column->next; } } } /* Expand columns */ if ((visWidth > totalWidth) && (numExpand > 0)) { int spaceRemaining = visWidth - totalWidth; while ((spaceRemaining > 0) && (numExpand > 0)) { int each = (spaceRemaining >= numExpand) ? spaceRemaining / numExpand : 1; numExpand = 0; column = first; while (column != NULL && column->lock == first->lock) { #ifdef UNIFORM_GROUP int weight = MAX(column->weight, 0); if (column->visible && column->expand && weight && (column->widthObj == NULL)) { int max = TreeColumn_MaxWidth(column); if ((max == -1) || (column->useWidth < max)) { int eachW = MIN(each * weight, spaceRemaining); int add = (max == -1) ? eachW : MIN(eachW, max - column->useWidth); column->useWidth += add; spaceRemaining -= add; if (!spaceRemaining) break; if ((max == -1) || (column->useWidth < max)) numExpand += weight; #else if (column->visible && column->expand && (column->widthObj == NULL)) { int max = TreeColumn_MaxWidth(column); if ((max == -1) || (column->useWidth < max)) { int add = (max == -1) ? each : MIN(each, max - column->useWidth); column->useWidth += add; spaceRemaining -= add; if (!spaceRemaining) break; if ((max == -1) || (column->useWidth < max)) numExpand++; #endif } } column = column->next; } } } doOffsets: /* Calculate the horizontal offset of each column in the range. * The total width is recalculated as well (needed anyway if any * columns were expanded or squeezed). */ totalWidth = 0; column = first; while (column != NULL && column->lock == first->lock) { column->offset = totalWidth; totalWidth += column->useWidth; column = column->next; } return totalWidth; } /* *---------------------------------------------------------------------- * * Tree_WidthOfColumns -- * * Return the total display width of all non-locked columns (except * the tail). * The width is only recalculated if it is marked out-of-date. * Other fields of the TreeCtrl are updated to reflect the current * arrangement of columns. * * Results: * Pixel width. * * Side effects: * The size of elements and styles may be updated if they are * marked out-of-date. * *---------------------------------------------------------------------- */ int Tree_WidthOfColumns( TreeCtrl *tree /* Widget info. */ ) { /* This gets called when the layout of all columns needs to be current. * So update the layout of the left- and right-locked columns too. */ (void) Tree_WidthOfLeftColumns(tree); (void) Tree_WidthOfRightColumns(tree); if (tree->widthOfColumns >= 0) return tree->widthOfColumns; tree->widthOfColumns = LayoutColumns( tree->columnLockNone, &tree->columnVis, &tree->columnCountVis); if (tree->columnTree != NULL && TreeColumn_Visible(tree->columnTree)) { tree->columnTreeLeft = tree->columnTree->offset; tree->columnTreeVis = TRUE; } else { tree->columnTreeLeft = 0; tree->columnTreeVis = FALSE; } return tree->widthOfColumns; } /* *---------------------------------------------------------------------- * * Tree_WidthOfLeftColumns -- * * Return the total display width of all left-locked columns. * The width is only recalculated if it is marked out-of-date. * Other fields of the TreeCtrl are updated to reflect the current * arrangement of columns. * * Results: * Pixel width. * * Side effects: * The size of elements and styles may be updated if they are * marked out-of-date. * *---------------------------------------------------------------------- */ int Tree_WidthOfLeftColumns( TreeCtrl *tree /* Widget info. */ ) { int showLocked = tree->vertical && (tree->wrapMode == TREE_WRAP_NONE); if (!showLocked) { tree->columnCountVisLeft = 0; return tree->widthOfColumnsLeft = 0; } if (tree->widthOfColumnsLeft < 0) { tree->widthOfColumnsLeft = LayoutColumns( tree->columnLockLeft, NULL, &tree->columnCountVisLeft); } return tree->widthOfColumnsLeft; } /* *---------------------------------------------------------------------- * * Tree_WidthOfRightColumns -- * * Return the total display width of all right-locked columns. * The width is only recalculated if it is marked out-of-date. * Other fields of the TreeCtrl are updated to reflect the current * arrangement of columns. * * Results: * Pixel width. * * Side effects: * The size of elements and styles may be updated if they are * marked out-of-date. * *---------------------------------------------------------------------- */ int Tree_WidthOfRightColumns( TreeCtrl *tree /* Widget info. */ ) { int showLocked = tree->vertical && (tree->wrapMode == TREE_WRAP_NONE); if (!showLocked) { tree->columnCountVisRight = 0; return tree->widthOfColumnsRight = 0; } if (tree->widthOfColumnsRight < 0) { tree->widthOfColumnsRight = LayoutColumns( tree->columnLockRight, NULL, &tree->columnCountVisRight); } return tree->widthOfColumnsRight; } /* *---------------------------------------------------------------------- * * Tree_InitColumns -- * * Perform column-related initialization when a new TreeCtrl is * created. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ void Tree_InitColumns( TreeCtrl *tree /* Widget info. */ ) { TreeColumn column; column = Column_Alloc(tree); column->id = -1; tree->columnTail = column; tree->nextColumnId = 0; tree->columnCount = 0; Column_Config(column, 0, NULL, TRUE); tree->columnDrag.optionTable = Tk_CreateOptionTable(tree->interp, dragSpecs); (void) Tk_InitOptions(tree->interp, (char *) tree, tree->columnDrag.optionTable, tree->tkwin); #ifdef UNIFORM_GROUP Tcl_InitHashTable(&tree->uniformGroupHash, TCL_STRING_KEYS); #endif } /* *---------------------------------------------------------------------- * * Tree_FreeColumns -- * * Free column-related resources for a deleted TreeCtrl. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void Tree_FreeColumns( TreeCtrl *tree /* Widget info. */ ) { TreeColumn column = tree->columns; while (column != NULL) { column = Column_Free(column); } Column_Free(tree->columnTail); tree->columnCount = 0; #ifdef UNIFORM_GROUP Tcl_DeleteHashTable(&tree->uniformGroupHash); #endif } int TreeColumn_InitInterp( Tcl_Interp *interp /* Current interpreter. */ ) { Tk_OptionSpec *specPtr; Tcl_DString dString; specPtr = Tree_FindOptionSpec(columnSpecs, "-background"); if (specPtr->defValue == NULL) { Tcl_DStringInit(&dString); Tcl_DStringAppendElement(&dString, DEF_BUTTON_BG_COLOR); Tcl_DStringAppendElement(&dString, "normal"); Tcl_DStringAppendElement(&dString, DEF_BUTTON_ACTIVE_BG_COLOR); Tcl_DStringAppendElement(&dString, ""); specPtr->defValue = ckalloc(Tcl_DStringLength(&dString) + 1); strcpy((char *)specPtr->defValue, Tcl_DStringValue(&dString)); Tcl_DStringFree(&dString); } PerStateCO_Init(columnSpecs, "-arrowbitmap", &pstBitmap, ColumnStateFromObj); PerStateCO_Init(columnSpecs, "-arrowimage", &pstImage, ColumnStateFromObj); PerStateCO_Init(columnSpecs, "-background", &pstBorder, ColumnStateFromObj); StringTableCO_Init(columnSpecs, "-itemjustify", justifyStrings); return TCL_OK; } tktreectrl-2.2.8/generic/tkTreeCtrl.c0000700000175600010010000035456311041155074015765 0ustar TimNone/* * tkTreeCtrl.c -- * * This module implements treectrl widgets for the Tk toolkit. * * Copyright (c) 2002-2008 Tim Baker * Copyright (c) 2002-2003 Christian Krone * Copyright (c) 2003-2005 ActiveState, a division of Sophos * * RCS: @(#) $Id: tkTreeCtrl.c,v 1.108 2008/07/21 18:49:32 treectrl Exp $ */ #include "tkTreeCtrl.h" #ifdef WIN32 #include #endif #if defined(MAC_TCL) || defined(MAC_OSX_TK) #include #endif /* * TIP #116 altered Tk_PhotoPutBlock API to add interp arg. * We need to remove that for compiling with 8.4. */ #if (TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION < 5) #define TK_PHOTOPUTBLOCK(interp, hdl, blk, x, y, w, h, cr) \ Tk_PhotoPutBlock(hdl, blk, x, y, w, h, cr) #define TK_PHOTOPUTZOOMEDBLOCK(interp, hdl, blk, x, y, w, h, \ zx, zy, sx, sy, cr) \ Tk_PhotoPutZoomedBlock(hdl, blk, x, y, w, h, \ zx, zy, sx, sy, cr) #else #define TK_PHOTOPUTBLOCK Tk_PhotoPutBlock #define TK_PHOTOPUTZOOMEDBLOCK Tk_PhotoPutZoomedBlock #endif /* This structure is used for reference-counted images. */ typedef struct TreeImageRef { int count; /* Reference count. */ Tk_Image image; /* Image token. */ Tcl_HashEntry *hPtr; /* Entry in tree->imageNameHash. */ } TreeImageRef; static CONST char *bgModeST[] = { "column", "order", "ordervisible", "row", #ifdef DEPRECATED "index", "visindex", #endif (char *) NULL }; static CONST char *columnResizeModeST[] = { "proxy", "realtime", (char *) NULL }; static CONST char *doubleBufferST[] = { "none", "item", "window", (char *) NULL }; static CONST char *lineStyleST[] = { "dot", "solid", (char *) NULL }; static CONST char *orientStringTable[] = { "horizontal", "vertical", (char *) NULL }; extern Tk_ObjCustomOption TreeCtrlCO_column_NOT_TAIL; static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", "white", -1, Tk_Offset(TreeCtrl, border), 0, (ClientData) "white", TREE_CONF_REDISPLAY}, {TK_OPTION_STRING, "-backgroundimage", "backgroundImage", "BackgroundImage", (char *) NULL, -1, Tk_Offset(TreeCtrl, backgroundImageString), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_BG_IMAGE | TREE_CONF_REDISPLAY}, {TK_OPTION_STRING_TABLE, "-backgroundmode", "backgroundMode", "BackgroundMode", "row", -1, Tk_Offset(TreeCtrl, backgroundMode), 0, (ClientData) bgModeST, TREE_CONF_REDISPLAY}, {TK_OPTION_STRING_TABLE, "-columnresizemode", "columnResizeMode", "ColumnResizeMode", "proxy", -1, Tk_Offset(TreeCtrl, columnResizeMode), 0, (ClientData) columnResizeModeST, 0}, {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth"}, {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) "-background"}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_LISTBOX_BORDER_WIDTH, Tk_Offset(TreeCtrl, borderWidthObj), Tk_Offset(TreeCtrl, borderWidth), 0, (ClientData) NULL, TREE_CONF_BORDERS | TREE_CONF_RELAYOUT}, {TK_OPTION_COLOR, "-buttoncolor", "buttonColor", "ButtonColor", "#808080", -1, Tk_Offset(TreeCtrl, buttonColor), 0, (ClientData) NULL, TREE_CONF_BUTTON | TREE_CONF_REDISPLAY}, {TK_OPTION_CUSTOM, "-buttonbitmap", "buttonBitmap", "ButtonBitmap", (char *) NULL, Tk_Offset(TreeCtrl, buttonBitmap.obj), Tk_Offset(TreeCtrl, buttonBitmap), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_BUTTON | TREE_CONF_BUTBMP | TREE_CONF_RELAYOUT}, {TK_OPTION_CUSTOM, "-buttonimage", "buttonImage", "ButtonImage", (char *) NULL, Tk_Offset(TreeCtrl, buttonImage.obj), Tk_Offset(TreeCtrl, buttonImage), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_BUTTON | TREE_CONF_BUTIMG | TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-buttonsize", "buttonSize", "ButtonSize", "9", Tk_Offset(TreeCtrl, buttonSizeObj), Tk_Offset(TreeCtrl, buttonSize), 0, (ClientData) NULL, TREE_CONF_BUTTON | TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-buttonthickness", "buttonThickness", "ButtonThickness", "1", Tk_Offset(TreeCtrl, buttonThicknessObj), Tk_Offset(TreeCtrl, buttonThickness), 0, (ClientData) NULL, TREE_CONF_BUTTON | TREE_CONF_REDISPLAY}, {TK_OPTION_STRING, "-columnprefix", "columnPrefix", "ColumnPrefix", "", -1, Tk_Offset(TreeCtrl, columnPrefix), 0, (ClientData) NULL, 0}, {TK_OPTION_PIXELS, "-columnproxy", "columnProxy", "ColumnProxy", (char *) NULL, Tk_Offset(TreeCtrl, columnProxy.xObj), Tk_Offset(TreeCtrl, columnProxy.x), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_PROXY}, {TK_OPTION_BOOLEAN, "-columntagexpr", "columnTagExpr", "ColumnTagExpr", "1", -1, Tk_Offset(TreeCtrl, columnTagExpr), 0, (ClientData) NULL, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", (char *) NULL, -1, Tk_Offset(TreeCtrl, cursor), TK_OPTION_NULL_OK, (ClientData) NULL, 0}, #ifdef DEPRECATED {TK_OPTION_STRING, "-defaultstyle", "defaultStyle", "DefaultStyle", (char *) NULL, Tk_Offset(TreeCtrl, defaultStyle.stylesObj), -1, TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_DEFSTYLE}, #endif /* DEPRECATED */ {TK_OPTION_STRING_TABLE, "-doublebuffer", "doubleBuffer", "DoubleBuffer", "item", -1, Tk_Offset(TreeCtrl, doubleBuffer), 0, (ClientData) doubleBufferST, TREE_CONF_REDISPLAY}, {TK_OPTION_SYNONYM, "-fg", (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) "-foreground"}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_LISTBOX_FONT, Tk_Offset(TreeCtrl, fontObj), Tk_Offset(TreeCtrl, tkfont), 0, (ClientData) NULL, TREE_CONF_FONT | TREE_CONF_RELAYOUT}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", DEF_LISTBOX_FG, Tk_Offset(TreeCtrl, fgObj), Tk_Offset(TreeCtrl, fgColorPtr), 0, (ClientData) NULL, TREE_CONF_FG | TREE_CONF_REDISPLAY}, {TK_OPTION_PIXELS, "-height", "height", "Height", "200", Tk_Offset(TreeCtrl, heightObj), Tk_Offset(TreeCtrl, height), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_LISTBOX_HIGHLIGHT_BG, -1, Tk_Offset(TreeCtrl, highlightBgColorPtr), 0, (ClientData) NULL, TREE_CONF_REDISPLAY}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", DEF_LISTBOX_HIGHLIGHT, -1, Tk_Offset(TreeCtrl, highlightColorPtr), 0, (ClientData) NULL, TREE_CONF_REDISPLAY}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_LISTBOX_HIGHLIGHT_WIDTH, Tk_Offset(TreeCtrl, highlightWidthObj), Tk_Offset(TreeCtrl, highlightWidth), 0, (ClientData) NULL, TREE_CONF_BORDERS | TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-indent", "indent", "Indent", "19", Tk_Offset(TreeCtrl, indentObj), Tk_Offset(TreeCtrl, indent), 0, (ClientData) NULL, TREE_CONF_INDENT | TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-itemheight", "itemHeight", "ItemHeight", "0", Tk_Offset(TreeCtrl, itemHeightObj), Tk_Offset(TreeCtrl, itemHeight), 0, (ClientData) NULL, TREE_CONF_ITEMSIZE | TREE_CONF_RELAYOUT}, #if 0 {TK_OPTION_CUSTOM, "-itempadx", (char *) NULL, (char *) NULL, "0", Tk_Offset(TreeCtrl, itemPadXObj), Tk_Offset(TreeCtrl, itemPadX), 0, (ClientData) &TreeCtrlCO_pad, 0}, {TK_OPTION_CUSTOM, "-itempady", (char *) NULL, (char *) NULL, "0", Tk_Offset(TreeCtrl, itemPadYObj), Tk_Offset(TreeCtrl, itemPadY), 0, (ClientData) &TreeCtrlCO_pad, 0}, #endif {TK_OPTION_STRING, "-itemprefix", "itemPrefix", "ItemPrefix", "", -1, Tk_Offset(TreeCtrl, itemPrefix), 0, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-itemtagexpr", "itemTagExpr", "ItemTagExpr", "1", -1, Tk_Offset(TreeCtrl, itemTagExpr), 0, (ClientData) NULL, 0}, {TK_OPTION_PIXELS, "-itemwidth", "itemWidth", "ItemWidth", "", Tk_Offset(TreeCtrl, itemWidthObj), Tk_Offset(TreeCtrl, itemWidth), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_ITEMSIZE | TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-itemwidthequal", "itemWidthEqual", "ItemWidthEqual", "0", -1, Tk_Offset(TreeCtrl, itemWidthEqual), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_ITEMSIZE | TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-itemwidthmultiple", "itemWidthMultiple", "ItemWidthMultiple", "", Tk_Offset(TreeCtrl, itemWidMultObj), Tk_Offset(TreeCtrl, itemWidMult), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_ITEMSIZE | TREE_CONF_RELAYOUT}, {TK_OPTION_COLOR, "-linecolor", "lineColor", "LineColor", "#808080", -1, Tk_Offset(TreeCtrl, lineColor), 0, (ClientData) NULL, TREE_CONF_LINE | TREE_CONF_REDISPLAY}, {TK_OPTION_STRING_TABLE, "-linestyle", "lineStyle", "LineStyle", "dot", -1, Tk_Offset(TreeCtrl, lineStyle), 0, (ClientData) lineStyleST, TREE_CONF_LINE | TREE_CONF_REDISPLAY}, {TK_OPTION_PIXELS, "-linethickness", "lineThickness", "LineThickness", "1", Tk_Offset(TreeCtrl, lineThicknessObj), Tk_Offset(TreeCtrl, lineThickness), 0, (ClientData) NULL, TREE_CONF_LINE | TREE_CONF_REDISPLAY}, {TK_OPTION_PIXELS, "-minitemheight", "minItemHeight", "MinItemHeight", "0", Tk_Offset(TreeCtrl, minItemHeightObj), Tk_Offset(TreeCtrl, minItemHeight), 0, (ClientData) NULL, TREE_CONF_ITEMSIZE | TREE_CONF_RELAYOUT}, {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "vertical", -1, Tk_Offset(TreeCtrl, vertical), 0, (ClientData) orientStringTable, TREE_CONF_RELAYOUT}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", "sunken", -1, Tk_Offset(TreeCtrl, relief), 0, (ClientData) NULL, TREE_CONF_REDISPLAY}, {TK_OPTION_PIXELS, "-rowproxy", "rowProxy", "RowProxy", (char *) NULL, Tk_Offset(TreeCtrl, rowProxy.yObj), Tk_Offset(TreeCtrl, rowProxy.y), TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_PROXY}, {TK_OPTION_STRING, "-scrollmargin", "scrollMargin", "ScrollMargin", "0", Tk_Offset(TreeCtrl, scrollMargin), -1, 0, (ClientData) NULL, 0}, {TK_OPTION_STRING, "-selectmode", "selectMode", "SelectMode", DEF_LISTBOX_SELECT_MODE, -1, Tk_Offset(TreeCtrl, selectMode), TK_OPTION_NULL_OK, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-showbuttons", "showButtons", "ShowButtons", "1", -1, Tk_Offset(TreeCtrl, showButtons), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-showheader", "showHeader", "ShowHeader", "1", -1, Tk_Offset(TreeCtrl, showHeader), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-showlines", "showLines", "ShowLines", "1", -1, Tk_Offset(TreeCtrl, showLines), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-showrootlines", "showRootLines", "ShowRootLines", "1", -1, Tk_Offset(TreeCtrl, showRootLines), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-showroot", "showRoot", "ShowRoot", "1", -1, Tk_Offset(TreeCtrl, showRoot), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-showrootbutton", "showRootButton", "ShowRootButton", "0", -1, Tk_Offset(TreeCtrl, showRootButton), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-showrootchildbuttons", "showRootChildButtons", "ShowRootChildButtons", "1", -1, Tk_Offset(TreeCtrl, showRootChildButtons), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", DEF_LISTBOX_TAKE_FOCUS, -1, Tk_Offset(TreeCtrl, takeFocus), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_CUSTOM, "-treecolumn", "treeColumn", "TreeColumn", (char *) NULL, -1, Tk_Offset(TreeCtrl, columnTree), TK_OPTION_NULL_OK, (ClientData) &TreeCtrlCO_column_NOT_TAIL, TREE_CONF_RELAYOUT}, {TK_OPTION_BOOLEAN, "-usetheme", "useTheme", "UseTheme", "0", -1, Tk_Offset(TreeCtrl, useTheme), 0, (ClientData) NULL, TREE_CONF_THEME | TREE_CONF_RELAYOUT}, {TK_OPTION_PIXELS, "-width", "width", "Width", "200", Tk_Offset(TreeCtrl, widthObj), Tk_Offset(TreeCtrl, width), 0, (ClientData) NULL, TREE_CONF_RELAYOUT}, {TK_OPTION_STRING, "-wrap", "wrap", "Wrap", (char *) NULL, Tk_Offset(TreeCtrl, wrapObj), -1, TK_OPTION_NULL_OK, (ClientData) NULL, TREE_CONF_WRAP | TREE_CONF_RELAYOUT}, {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", (char *) NULL, -1, Tk_Offset(TreeCtrl, xScrollCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-xscrolldelay", "xScrollDelay", "ScrollDelay", "50", Tk_Offset(TreeCtrl, xScrollDelay), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-xscrollincrement", "xScrollIncrement", "ScrollIncrement", "0", -1, Tk_Offset(TreeCtrl, xScrollIncrement), 0, (ClientData) NULL, TREE_CONF_REDISPLAY}, {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", (char *) NULL, -1, Tk_Offset(TreeCtrl, yScrollCmd), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-yscrolldelay", "yScrollDelay", "ScrollDelay", "50", Tk_Offset(TreeCtrl, yScrollDelay), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-yscrollincrement", "yScrollIncrement", "ScrollIncrement", "0", -1, Tk_Offset(TreeCtrl, yScrollIncrement), 0, (ClientData) NULL, TREE_CONF_REDISPLAY}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, -1, -1, 0, (ClientData) NULL, 0} }; static Tk_OptionSpec debugSpecs[] = { {TK_OPTION_INT, "-displaydelay", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeCtrl, debug.displayDelay), 0, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-data", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeCtrl, debug.data), 0, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-display", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeCtrl, debug.display), 0, (ClientData) NULL, 0}, {TK_OPTION_COLOR, "-drawcolor", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeCtrl, debug.drawColor), TK_OPTION_NULL_OK, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-enable", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeCtrl, debug.enable), 0, (ClientData) NULL, 0}, {TK_OPTION_COLOR, "-erasecolor", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeCtrl, debug.eraseColor), TK_OPTION_NULL_OK, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-span", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeCtrl, debug.span), 0, (ClientData) NULL, 0}, {TK_OPTION_BOOLEAN, "-textlayout", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeCtrl, debug.textLayout), 0, (ClientData) NULL, 0}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, -1, -1, 0, (ClientData) NULL, 0} }; static int TreeWidgetCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); static int TreeConfigure(Tcl_Interp *interp, TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[], int createFlag); static void TreeEventProc(ClientData clientData, XEvent * eventPtr); static void TreeDestroy(char *memPtr); static void TreeCmdDeletedProc(ClientData clientData); static void TreeWorldChanged(ClientData instanceData); static void TreeComputeGeometry(TreeCtrl *tree); static int TreeStateCmd(TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); static int TreeSelectionCmd(Tcl_Interp *interp, TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); static int TreeXviewCmd(Tcl_Interp *interp, TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); static int TreeYviewCmd(Tcl_Interp *interp, TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); static int TreeDebugCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); static Tk_ClassProcs treectrlClass = { sizeof(Tk_ClassProcs), /* size */ TreeWorldChanged, /* worldChangedProc. */ NULL, /* createProc. */ NULL /* modalProc. */ }; /* *-------------------------------------------------------------- * * TreeObjCmd -- * * This procedure is invoked to process the [treectrl] 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 TreeObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree; Tk_Window tkwin; Tk_OptionTable optionTable; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?"); return TCL_ERROR; } tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), Tcl_GetStringFromObj(objv[1], NULL), (char *) NULL); if (tkwin == NULL) { return TCL_ERROR; } optionTable = Tk_CreateOptionTable(interp, optionSpecs); tree = (TreeCtrl *) ckalloc(sizeof(TreeCtrl)); memset(tree, '\0', sizeof(TreeCtrl)); tree->tkwin = tkwin; tree->display = Tk_Display(tkwin); tree->interp = interp; tree->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(tree->tkwin), TreeWidgetCmd, (ClientData) tree, TreeCmdDeletedProc); tree->optionTable = optionTable; tree->relief = TK_RELIEF_SUNKEN; tree->prevWidth = Tk_Width(tkwin); tree->prevHeight = Tk_Height(tkwin); tree->updateIndex = 1; tree->stateNames[0] = "open"; tree->stateNames[1] = "selected"; tree->stateNames[2] = "enabled"; tree->stateNames[3] = "active"; tree->stateNames[4] = "focus"; Tcl_InitHashTable(&tree->selection, TCL_ONE_WORD_KEYS); /* Do this before Tree_InitColumns() which does Tk_InitOptions(), which * calls Tk_GetOption() which relies on the window class */ Tk_SetClass(tkwin, "TreeCtrl"); Tk_SetClassProcs(tkwin, &treectrlClass, (ClientData) tree); tree->debug.optionTable = Tk_CreateOptionTable(interp, debugSpecs); (void) Tk_InitOptions(interp, (char *) tree, tree->debug.optionTable, tkwin); Tcl_InitHashTable(&tree->itemHash, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&tree->itemSpansHash, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&tree->elementHash, TCL_STRING_KEYS); Tcl_InitHashTable(&tree->styleHash, TCL_STRING_KEYS); Tcl_InitHashTable(&tree->imageNameHash, TCL_STRING_KEYS); Tcl_InitHashTable(&tree->imageTokenHash, TCL_ONE_WORD_KEYS); TreeItemList_Init(tree, &tree->preserveItemList, 0); #ifdef ALLOC_HAX tree->allocData = TreeAlloc_Init(); #endif Tree_InitColumns(tree); TreeItem_Init(tree); TreeNotify_Init(tree); (void) TreeStyle_Init(tree); TreeMarquee_Init(tree); TreeDragImage_Init(tree); TreeDInfo_Init(tree); Tk_CreateEventHandler(tree->tkwin, #ifdef USE_TTK ExposureMask|StructureNotifyMask|FocusChangeMask|ActivateMask|VirtualEventMask, #else ExposureMask|StructureNotifyMask|FocusChangeMask|ActivateMask, #endif TreeEventProc, (ClientData) tree); /* Must do this on Unix because Tk_GCForColor() uses * Tk_WindowId(tree->tkwin) */ Tk_MakeWindowExist(tree->tkwin); /* Window must exist on Win32. */ TreeTheme_Init(tree); /* * Keep a hold of the associated tkwin until we destroy the listbox, * otherwise Tk might free it while we still need it. */ Tcl_Preserve((ClientData) tkwin); if (Tk_InitOptions(interp, (char *) tree, optionTable, tkwin) != TCL_OK) { Tk_DestroyWindow(tree->tkwin); return TCL_ERROR; } if (TreeConfigure(interp, tree, objc - 2, objv + 2, TRUE) != TCL_OK) { Tk_DestroyWindow(tree->tkwin); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tree->tkwin), -1)); return TCL_OK; } #define W2Cx(x) ((x) + tree->xOrigin) #define C2Wx(x) ((x) - tree->xOrigin) #define C2Ox(x) ((x) - Tree_ContentLeft(tree)) #define W2Cy(y) ((y) + tree->yOrigin) #define C2Wy(y) ((y) - tree->yOrigin) #define C2Oy(y) ((y) - Tree_ContentTop(tree)) /* *-------------------------------------------------------------- * * TreeWidgetCmd -- * * 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 TreeWidgetCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; int result = TCL_OK; static CONST char *commandName[] = { "activate", "bbox", "canvasx", "canvasy", "cget", #ifdef DEPRECATED "collapse", #endif "column", #ifdef DEPRECATED "compare", #endif "configure", "contentbox", "debug", "depth", "dragimage", "element", #ifdef DEPRECATED "expand", #endif "identify", "index", "item", "marquee", "notify", #ifdef DEPRECATED "numcolumns", "numitems", #endif "orphans", #ifdef DEPRECATED "range", #endif "scan", "see", "selection", "state", "style", #ifdef DEPRECATED "toggle", #endif "xview", "yview", (char *) NULL }; enum { COMMAND_ACTIVATE, COMMAND_BBOX, COMMAND_CANVASX, COMMAND_CANVASY, COMMAND_CGET, #ifdef DEPRECATED COMMAND_COLLAPSE, #endif COMMAND_COLUMN, #ifdef DEPRECATED COMMAND_COMPARE, #endif COMMAND_CONFIGURE, COMMAND_CONTENTBOX, COMMAND_DEBUG, COMMAND_DEPTH, COMMAND_DRAGIMAGE, COMMAND_ELEMENT, #ifdef DEPRECATED COMMAND_EXPAND, #endif COMMAND_IDENTIFY, COMMAND_INDEX, COMMAND_ITEM, COMMAND_MARQUEE, COMMAND_NOTIFY, #ifdef DEPRECATED COMMAND_NUMCOLUMNS, COMMAND_NUMITEMS, #endif COMMAND_ORPHANS, #ifdef DEPRECATED COMMAND_RANGE, #endif COMMAND_SCAN, COMMAND_SEE, COMMAND_SELECTION, COMMAND_STATE, COMMAND_STYLE, #ifdef DEPRECATED COMMAND_TOGGLE, #endif COMMAND_XVIEW, COMMAND_YVIEW }; Tcl_Obj *resultObjPtr; int index; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], commandName, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } Tcl_Preserve((ClientData) tree); Tree_PreserveItems(tree); switch (index) { case COMMAND_ACTIVATE: { TreeItem active, item; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "item"); goto error; } if (TreeItem_FromObj(tree, objv[2], &item, IFO_NOT_NULL) != TCL_OK) { goto error; } if (item != tree->activeItem) { int x, y, w, h; active = tree->activeItem; TreeItem_ChangeState(tree, active, STATE_ACTIVE, 0); tree->activeItem = item; TreeItem_ChangeState(tree, tree->activeItem, 0, STATE_ACTIVE); /* FIXME: is it onscreen? */ /* FIXME: what if only lock columns displayed? */ if (Tree_ItemBbox(tree, item, COLUMN_LOCK_NONE, &x, &y, &w, &h) >= 0) { Tk_SetCaretPos(tree->tkwin, x - tree->xOrigin, y - tree->yOrigin, h); } TreeNotify_ActiveItem(tree, active, item); } break; } /* .t bbox ?area? */ case COMMAND_BBOX: { static CONST char *areaName[] = { "content", "header", "left", "right", (char *) NULL }; int x1, y1, x2, y2; if (objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?area?"); goto error; } if (objc == 3) { int area[4] = { TREE_AREA_CONTENT, TREE_AREA_HEADER, TREE_AREA_LEFT, TREE_AREA_RIGHT }; if (Tcl_GetIndexFromObj(interp, objv[2], areaName, "area", 0, &index) != TCL_OK) { goto error; } if (!Tree_AreaBbox(tree, area[index], &x1, &y1, &x2, &y2)) break; } else { x1 = 0; y1 = 0; x2 = Tk_Width(tree->tkwin); y2 = Tk_Height(tree->tkwin); } FormatResult(interp, "%d %d %d %d", x1, y1, x2, y2); break; } case COMMAND_CANVASX: { int x; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "x"); goto error; } if (Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) goto error; Tcl_SetObjResult(interp, Tcl_NewIntObj(x + tree->xOrigin)); break; } case COMMAND_CANVASY: { int y; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "y"); goto error; } if (Tcl_GetIntFromObj(interp, objv[2], &y) != TCL_OK) goto error; Tcl_SetObjResult(interp, Tcl_NewIntObj(y + tree->yOrigin)); break; } case COMMAND_CGET: { if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); goto error; } resultObjPtr = Tk_GetOptionValue(interp, (char *) tree, tree->optionTable, objv[2], tree->tkwin); if (resultObjPtr == NULL) { result = TCL_ERROR; } else { Tcl_SetObjResult(interp, resultObjPtr); } break; } case COMMAND_CONFIGURE: { resultObjPtr = NULL; if (objc <= 3) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) tree, tree->optionTable, (objc == 2) ? (Tcl_Obj *) NULL : objv[2], tree->tkwin); if (resultObjPtr == NULL) { result = TCL_ERROR; } else { Tcl_SetObjResult(interp, resultObjPtr); } } else { result = TreeConfigure(interp, tree, objc - 2, objv + 2, FALSE); } break; } case COMMAND_CONTENTBOX: { int x1, y1, x2, y2; if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); goto error; } if (Tree_AreaBbox(tree, TREE_AREA_CONTENT, &x1, &y1, &x2, &y2)) { FormatResult(interp, "%d %d %d %d", x1, y1, x2, y2); } break; } #ifdef DEPRECATED /* T expand ?-recurse? I ... */ case COMMAND_COLLAPSE: case COMMAND_EXPAND: case COMMAND_TOGGLE: { char *s; int recurse = 0; int mode = 0; /* lint */ int i, j, count, len; TreeItemList items, item2s; TreeItem _item; ItemForEach iter; if (objc == 2) break; s = Tcl_GetStringFromObj(objv[2], &len); if (s[0] == '-') { if (strncmp(s, "-recurse", len)) { FormatResult(interp, "bad option \"%s\": must be -recurse", s); goto error; } if (objc == 3) break; recurse = 1; } switch (index) { case COMMAND_COLLAPSE: mode = 0; break; case COMMAND_EXPAND: mode = 1; break; case COMMAND_TOGGLE: mode = -1; break; } for (i = 2 + recurse; i < objc; i++) { if (TreeItemList_FromObj(tree, objv[i], &items, IFO_NOT_NULL) != TCL_OK) { goto error; } TreeItemList_Init(tree, &item2s, 0); ITEM_FOR_EACH(_item, &items, NULL, &iter) { TreeItemList_Append(&item2s, _item); if (!iter.all && recurse) { TreeItem_ListDescendants(tree, _item, &item2s); } } count = TreeItemList_Count(&item2s); for (j = 0; j < count; j++) { _item = TreeItemList_Nth(&item2s, j); TreeItem_OpenClose(tree, _item, mode); } TreeItemList_Free(&items); TreeItemList_Free(&item2s); } #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif break; } #endif /* DEPRECATED */ case COMMAND_COLUMN: { result = TreeColumnCmd(clientData, interp, objc, objv); break; } #ifdef DEPRECATED case COMMAND_COMPARE: { TreeItem item1, item2; static CONST char *opName[] = { "<", "<=", "==", ">=", ">", "!=", NULL }; int op, compare = 0, index1, index2; if (objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "item1 op item2"); goto error; } if (TreeItem_FromObj(tree, objv[2], &item1, IFO_NOT_NULL) != TCL_OK) goto error; if (Tcl_GetIndexFromObj(interp, objv[3], opName, "comparison operator", 0, &op) != TCL_OK) goto error; if (TreeItem_FromObj(tree, objv[4], &item2, IFO_NOT_NULL) != TCL_OK) goto error; if (TreeItem_RootAncestor(tree, item1) != TreeItem_RootAncestor(tree, item2)) { FormatResult(interp, "item %s%d and item %s%d don't share a common ancestor", tree->itemPrefix, TreeItem_GetID(tree, item1), tree->itemPrefix, TreeItem_GetID(tree, item2)); goto error; } TreeItem_ToIndex(tree, item1, &index1, NULL); TreeItem_ToIndex(tree, item2, &index2, NULL); switch (op) { case 0: compare = index1 < index2; break; case 1: compare = index1 <= index2; break; case 2: compare = index1 == index2; break; case 3: compare = index1 >= index2; break; case 4: compare = index1 > index2; break; case 5: compare = index1 != index2; break; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(compare)); break; } #endif /* DEPRECATED */ case COMMAND_DEBUG: { result = TreeDebugCmd(clientData, interp, objc, objv); break; } case COMMAND_DEPTH: { TreeItem item; int depth; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?item?"); goto error; } if (objc == 3) { if (TreeItem_FromObj(tree, objv[2], &item, IFO_NOT_NULL) != TCL_OK) goto error; depth = TreeItem_GetDepth(tree, item); if (TreeItem_RootAncestor(tree, item) == tree->root) depth++; Tcl_SetObjResult(interp, Tcl_NewIntObj(depth)); break; } Tree_UpdateItemIndex(tree); Tcl_SetObjResult(interp, Tcl_NewIntObj(tree->depth + 1)); break; } case COMMAND_DRAGIMAGE: { result = TreeDragImageCmd(clientData, interp, objc, objv); break; } case COMMAND_ELEMENT: { result = TreeElementCmd(clientData, interp, objc, objv); break; } case COMMAND_IDENTIFY: { int x, y, width, height, depth; TreeColumn treeColumn; TreeItem item; char buf[64]; int hit; int lock; /* set id [$tree identify $x $y] "item I column C" : mouse is in column C of item I "item I column C elem E" : mouse is in element E in column C of item I "item I button" : mouse is in button-area of item I "item I line J" : mouse is near line coming from item J "header C ?left|right?" : mouse is in header column C "" : mouse is not in any item */ if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "x y"); goto error; } if (Tk_GetPixelsFromObj(interp, tree->tkwin, objv[2], &x) != TCL_OK) goto error; if (Tk_GetPixelsFromObj(interp, tree->tkwin, objv[3], &y) != TCL_OK) goto error; hit = Tree_HitTest(tree, x, y); /* Require point inside borders */ if (hit == TREE_AREA_NONE) break; if (hit == TREE_AREA_HEADER) { treeColumn = Tree_HeaderUnderPoint(tree, &x, &y, &width, &height, FALSE); if (treeColumn == tree->columnTail) { strcpy(buf, "header tail"); if (x < 4) sprintf(buf + strlen(buf), " left"); Tcl_SetResult(interp, buf, TCL_VOLATILE); break; } else if (treeColumn != NULL) { sprintf(buf, "header %s%d", tree->columnPrefix, TreeColumn_GetID(treeColumn)); if (x < 4) sprintf(buf + strlen(buf), " left"); else if (x >= width - 4) sprintf(buf + strlen(buf), " right"); Tcl_SetResult(interp, buf, TCL_VOLATILE); break; } } item = Tree_ItemUnderPoint(tree, &x, &y, FALSE); if (item == NULL) break; sprintf(buf, "item %s%d", tree->itemPrefix, TreeItem_GetID(tree, item)); /* TreeItem_ToObj() */ depth = TreeItem_GetDepth(tree, item); if (item == tree->root) depth = (tree->showButtons && tree->showRootButton) ? 1 : 0; else if (tree->showRoot) { depth++; if (tree->showButtons && tree->showRootButton) depth++; } else if (tree->showButtons && tree->showRootChildButtons) depth += 1; else if (tree->showLines && tree->showRootLines) depth += 1; lock = (hit == TREE_AREA_LEFT) ? COLUMN_LOCK_LEFT : (hit == TREE_AREA_RIGHT) ? COLUMN_LOCK_RIGHT : COLUMN_LOCK_NONE; /* Point is in a line or button */ if (tree->columnTreeVis && (TreeColumn_Lock(tree->columnTree) == lock) && (x >= tree->columnTreeLeft) && (x < tree->columnTreeLeft + TreeColumn_UseWidth(tree->columnTree)) && (x < tree->columnTreeLeft + depth * tree->useIndent)) { int column = (x - tree->columnTreeLeft) / tree->useIndent + 1; if (column == depth) { if (TreeItem_HasButton(tree, item)) sprintf(buf + strlen(buf), " button"); } else if (tree->showLines) { TreeItem sibling; do { item = TreeItem_GetParent(tree, item); } while (++column < depth); sibling = TreeItem_NextSiblingVisible(tree, item); if ((sibling != NULL) && ((TreeItem_GetParent(tree, sibling) != tree->root) || tree->showRootLines)) sprintf(buf + strlen(buf), " line %s%d", tree->itemPrefix, TreeItem_GetID(tree, item)); /* TreeItem_ToObj() */ } } else { TreeItem_Identify(tree, item, lock, x, y, buf); } Tcl_SetResult(interp, buf, TCL_VOLATILE); break; } #ifdef DEPRECATED case COMMAND_INDEX: { TreeItem item; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "item"); goto error; } if (TreeItem_FromObj(tree, objv[2], &item, 0) != TCL_OK) { goto error; } if (item != NULL) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item)); break; } #endif /* DEPRECATED */ case COMMAND_ITEM: { result = TreeItemCmd(clientData, interp, objc, objv); break; } case COMMAND_MARQUEE: { result = TreeMarqueeCmd(clientData, interp, objc, objv); break; } case COMMAND_NOTIFY: { result = TreeNotifyCmd(clientData, interp, objc, objv); break; } #ifdef DEPRECATED case COMMAND_NUMCOLUMNS: { if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); goto error; } Tcl_SetObjResult(interp, Tcl_NewIntObj(tree->columnCount)); break; } case COMMAND_NUMITEMS: { if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); goto error; } Tcl_SetObjResult(interp, Tcl_NewIntObj(tree->itemCount)); break; } #endif /* DEPRECATED */ case COMMAND_ORPHANS: { Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_Obj *listObj; TreeItem item; if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); goto error; } /* Pretty slow. Could keep a hash table of orphans */ listObj = Tcl_NewListObj(0, NULL); hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); if ((item != tree->root) && (TreeItem_GetParent(tree, item) == NULL)) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); } hPtr = Tcl_NextHashEntry(&search); } Tcl_SetObjResult(interp, listObj); break; } #ifdef DEPRECATED case COMMAND_RANGE: { TreeItem item, itemFirst, itemLast; Tcl_Obj *listObj; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "first last"); goto error; } if (TreeItem_FromObj(tree, objv[2], &itemFirst, IFO_NOT_NULL) != TCL_OK) goto error; if (TreeItem_FromObj(tree, objv[3], &itemLast, IFO_NOT_NULL) != TCL_OK) goto error; if (TreeItem_FirstAndLast(tree, &itemFirst, &itemLast) == 0) goto error; listObj = Tcl_NewListObj(0, NULL); item = itemFirst; while (item != NULL) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); if (item == itemLast) break; item = TreeItem_Next(tree, item); } Tcl_SetObjResult(interp, listObj); break; } #endif /* DEPRECATED */ case COMMAND_SCAN: { static CONST char *optionName[] = { "dragto", "mark", (char *) NULL }; int x, y, gain = 10, xOrigin, yOrigin; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?"); goto error; } if (Tcl_GetIndexFromObj(interp, objv[2], optionName, "option", 2, &index) != TCL_OK) goto error; switch (index) { /* T scan dragto x y ?gain? */ case 0: if ((objc < 5) || (objc > 6)) { Tcl_WrongNumArgs(interp, 3, objv, "x y ?gain?"); goto error; } if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) goto error; if (objc == 6) { if (Tcl_GetIntFromObj(interp, objv[5], &gain) != TCL_OK) goto error; } xOrigin = tree->scanXOrigin - gain * (x - tree->scanX); yOrigin = tree->scanYOrigin - gain * (y - tree->scanY); Tree_SetOriginX(tree, xOrigin); Tree_SetOriginY(tree, yOrigin); break; /* T scan mark x y ?gain? */ case 1: if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "x y"); goto error; } if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) goto error; tree->scanX = x; tree->scanY = y; tree->scanXOrigin = tree->xOrigin; tree->scanYOrigin = tree->yOrigin; break; } break; } case COMMAND_SEE: { TreeItem item; int x, y, w, h; int visWidth = Tree_ContentWidth(tree); int visHeight = Tree_ContentHeight(tree); int xOrigin = tree->xOrigin; int yOrigin = tree->yOrigin; int minX = Tree_ContentLeft(tree); int minY = Tree_ContentTop(tree); int maxX = Tree_ContentRight(tree); int maxY = Tree_ContentBottom(tree); int index, offset; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "item"); goto error; } if (TreeItem_FromObj(tree, objv[2], &item, IFO_NOT_NULL) != TCL_OK) goto error; /* Canvas coords */ if (Tree_ItemBbox(tree, item, COLUMN_LOCK_NONE, &x, &y, &w, &h) < 0) break; if ((C2Wx(x) > maxX) || (C2Wx(x + w) <= minX) || (w <= visWidth)) { if ((C2Wx(x) < minX) || (w > visWidth)) { index = Increment_FindX(tree, x); offset = Increment_ToOffsetX(tree, index); xOrigin = C2Ox(offset); } else if (C2Wx(x + w) > maxX) { index = Increment_FindX(tree, x + w - visWidth); offset = Increment_ToOffsetX(tree, index); if (offset < x + w - visWidth) { index++; offset = Increment_ToOffsetX(tree, index); } xOrigin = C2Ox(offset); } } if ((C2Wy(y) > maxY) || (C2Wy(y + h) <= minY) || (h <= visHeight)) { if ((C2Wy(y) < minY) || (h > visHeight)) { index = Increment_FindY(tree, y); offset = Increment_ToOffsetY(tree, index); yOrigin = C2Oy(offset); } else if (C2Wy(y + h) > maxY) { index = Increment_FindY(tree, y + h - visHeight); offset = Increment_ToOffsetY(tree, index); if (offset < y + h - visHeight) { index++; offset = Increment_ToOffsetY(tree, index); } yOrigin = C2Oy(offset); } } Tree_SetOriginX(tree, xOrigin); Tree_SetOriginY(tree, yOrigin); break; } case COMMAND_SELECTION: { result = TreeSelectionCmd(interp, tree, objc, objv); break; } case COMMAND_STATE: { result = TreeStateCmd(tree, objc, objv); break; } case COMMAND_STYLE: { result = TreeStyleCmd(clientData, interp, objc, objv); break; } case COMMAND_XVIEW: { result = TreeXviewCmd(interp, tree, objc, objv); break; } case COMMAND_YVIEW: { result = TreeYviewCmd(interp, tree, objc, objv); break; } } Tree_ReleaseItems(tree); Tcl_Release((ClientData) tree); return result; error: Tree_ReleaseItems(tree); Tcl_Release((ClientData) tree); return TCL_ERROR; } /* *-------------------------------------------------------------- * * TreeConfigure -- * * This procedure is called to process an argv/argc list, plus * the Tk option database, in order to configure (or reconfigure) * a treectrl widget. * * 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, such as colors, border width, * etc. get set for tree; old resources get freed, * if there were any. * *-------------------------------------------------------------- */ static int TreeConfigure( Tcl_Interp *interp, /* Current interpreter. */ TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[], /* Argument values. */ int createFlag /* TRUE if the widget is being created. */ ) { int error; Tcl_Obj *errorResult = NULL; TreeCtrl saved; Tk_SavedOptions savedOptions; int oldShowRoot = tree->showRoot; int mask, maskFree = 0; XGCValues gcValues; unsigned long gcMask; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(interp, (char *) tree, tree->optionTable, objc, objv, tree->tkwin, &savedOptions, &mask) != TCL_OK) { mask = 0; continue; } /* Wouldn't have to do this if Tk_InitOptions() would return * a mask of configured options like Tk_SetOptions() does. */ if (createFlag) { if (tree->backgroundImageString != NULL) mask |= TREE_CONF_BG_IMAGE; if (tree->buttonBitmap.obj != NULL) mask |= TREE_CONF_BUTBMP; if (tree->buttonImage.obj != NULL) mask |= TREE_CONF_BUTIMG; #ifdef DEPRECATED if (tree->defaultStyle.stylesObj != NULL) mask |= TREE_CONF_DEFSTYLE; #endif if (tree->wrapObj != NULL) mask |= TREE_CONF_WRAP; if (!ObjectIsEmpty(tree->itemWidthObj)) mask |= TREE_CONF_ITEMSIZE; if (!ObjectIsEmpty(tree->itemWidMultObj)) mask |= TREE_CONF_ITEMSIZE; } /* * Step 1: Save old values */ if (mask & TREE_CONF_BG_IMAGE) saved.backgroundImage = tree->backgroundImage; #ifdef DEPRECATED if (mask & TREE_CONF_DEFSTYLE) { saved.defaultStyle.styles = tree->defaultStyle.styles; saved.defaultStyle.numStyles = tree->defaultStyle.numStyles; } #endif if (mask & TREE_CONF_WRAP) { saved.wrapMode = tree->wrapMode; saved.wrapArg = tree->wrapArg; } /* * Step 2: Process new values */ if (mask & TREE_CONF_BG_IMAGE) { if (tree->backgroundImageString == NULL) { tree->backgroundImage = NULL; } else { Tk_Image image = Tree_GetImage(tree, tree->backgroundImageString); if (image == NULL) continue; tree->backgroundImage = image; maskFree |= TREE_CONF_BG_IMAGE; } } #ifdef DEPRECATED if (mask & TREE_CONF_DEFSTYLE) { if (tree->defaultStyle.stylesObj == NULL) { tree->defaultStyle.styles = NULL; tree->defaultStyle.numStyles = 0; } else { int i, listObjc; Tcl_Obj **listObjv; TreeStyle style; if ((Tcl_ListObjGetElements(interp, tree->defaultStyle.stylesObj, &listObjc, &listObjv) != TCL_OK)) continue; tree->defaultStyle.styles = (TreeStyle *) ckalloc(sizeof(TreeStyle) * listObjc); tree->defaultStyle.numStyles = listObjc; for (i = 0; i < listObjc; i++) { if (ObjectIsEmpty(listObjv[i])) { style = NULL; } else { if (TreeStyle_FromObj(tree, listObjv[i], &style) != TCL_OK) { ckfree((char *) tree->defaultStyle.styles); break; } } tree->defaultStyle.styles[i] = style; } if (i < listObjc) continue; maskFree |= TREE_CONF_DEFSTYLE; } } #endif /* DEPRECATED */ /* Parse -wrap string into wrapMode and wrapArg */ if (mask & TREE_CONF_WRAP) { int listObjc; Tcl_Obj **listObjv; if (tree->wrapObj == NULL) { tree->wrapMode = TREE_WRAP_NONE; tree->wrapArg = 0; } else { int len0, len1; char *s0, *s1, ch0, ch1; if ((Tcl_ListObjGetElements(interp, tree->wrapObj, &listObjc, &listObjv) != TCL_OK) || (listObjc > 2)) { badWrap: FormatResult(interp, "bad wrap \"%s\"", Tcl_GetString(tree->wrapObj)); continue; } if (listObjc == 1) { s0 = Tcl_GetStringFromObj(listObjv[0], &len0); ch0 = s0[0]; if ((ch0 == 'w') && !strncmp(s0, "window", len0)) { tree->wrapMode = TREE_WRAP_WINDOW; tree->wrapArg = 0; } else goto badWrap; } else { s1 = Tcl_GetStringFromObj(listObjv[1], &len1); ch1 = s1[0]; if ((ch1 == 'i') && !strncmp(s1, "items", len1)) { int n; if ((Tcl_GetIntFromObj(interp, listObjv[0], &n) != TCL_OK) || (n < 0)) { goto badWrap; } tree->wrapMode = TREE_WRAP_ITEMS; tree->wrapArg = n; } else if ((ch1 == 'p') && !strncmp(s1, "pixels", len1)) { int n; if (Tk_GetPixelsFromObj(interp, tree->tkwin, listObjv[0], &n) != TCL_OK) { goto badWrap; } tree->wrapMode = TREE_WRAP_PIXELS; tree->wrapArg = n; } else goto badWrap; } } } /* * Step 3: Free saved values */ if (mask & TREE_CONF_BG_IMAGE) { if (saved.backgroundImage != NULL) Tree_FreeImage(tree, saved.backgroundImage); } #ifdef DEPRECATED if (mask & TREE_CONF_DEFSTYLE) { if (saved.defaultStyle.styles != NULL) ckfree((char *) saved.defaultStyle.styles); } #endif Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); /* * Free new values. */ if (maskFree & TREE_CONF_BG_IMAGE) Tree_FreeImage(tree, tree->backgroundImage); #ifdef DEPRECATED if (maskFree & TREE_CONF_DEFSTYLE) ckfree((char *) tree->defaultStyle.styles); #endif /* * Restore old values. */ if (mask & TREE_CONF_BG_IMAGE) { tree->backgroundImage = saved.backgroundImage; } #ifdef DEPRECATED if (mask & TREE_CONF_DEFSTYLE) { tree->defaultStyle.styles = saved.defaultStyle.styles; tree->defaultStyle.numStyles = saved.defaultStyle.numStyles; } #endif if (mask & TREE_CONF_WRAP) { tree->wrapMode = saved.wrapMode; tree->wrapArg = saved.wrapArg; } Tcl_SetObjResult(interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } tree->itemPrefixLen = strlen(tree->itemPrefix); tree->columnPrefixLen = strlen(tree->columnPrefix); Tk_SetWindowBackground(tree->tkwin, Tk_3DBorderColor(tree->border)->pixel); if (createFlag) mask |= TREE_CONF_FONT | TREE_CONF_RELAYOUT; if (mask & (TREE_CONF_FONT | TREE_CONF_FG)) { /* * Should be blended into TreeWorldChanged. */ gcValues.font = Tk_FontId(tree->tkfont); gcValues.foreground = tree->fgColorPtr->pixel; gcValues.graphics_exposures = False; gcMask = GCForeground | GCFont | GCGraphicsExposures; if (tree->textGC != None) Tk_FreeGC(tree->display, tree->textGC); tree->textGC = Tk_GetGC(tree->tkwin, gcMask, &gcValues); } if (tree->copyGC == None) { gcValues.function = GXcopy; gcValues.graphics_exposures = False; gcMask = GCFunction | GCGraphicsExposures; tree->copyGC = Tk_GetGC(tree->tkwin, gcMask, &gcValues); } if (createFlag) mask |= TREE_CONF_BUTTON; if (mask & TREE_CONF_BUTTON) { if (tree->buttonGC != None) Tk_FreeGC(tree->display, tree->buttonGC); gcValues.foreground = tree->buttonColor->pixel; gcValues.line_width = tree->buttonThickness; gcMask = GCForeground | GCLineWidth; tree->buttonGC = Tk_GetGC(tree->tkwin, gcMask, &gcValues); } if (createFlag) mask |= TREE_CONF_LINE; if (mask & TREE_CONF_LINE) { if (tree->lineGC != None) Tk_FreeGC(tree->display, tree->lineGC); gcValues.foreground = tree->lineColor->pixel; gcValues.line_width = tree->lineThickness; gcMask = GCForeground | GCLineWidth; tree->lineGC = Tk_GetGC(tree->tkwin, gcMask, &gcValues); } if (mask & TREE_CONF_PROXY) { TreeColumnProxy_Undisplay(tree); TreeColumnProxy_Display(tree); TreeRowProxy_Undisplay(tree); TreeRowProxy_Display(tree); } tree->useIndent = MAX(tree->indent, Tree_ButtonMaxWidth(tree)); if (createFlag) mask |= TREE_CONF_BORDERS; if (mask & TREE_CONF_BORDERS) { if (tree->highlightWidth < 0) tree->highlightWidth = 0; if (tree->useTheme && TreeTheme_SetBorders(tree) == TCL_OK) { /* nothing */ } else { tree->inset.left = tree->inset.top = tree->inset.right = tree->inset.bottom = tree->highlightWidth + tree->borderWidth; } } if (oldShowRoot != tree->showRoot) { TreeItem_InvalidateHeight(tree, tree->root); tree->updateIndex = 1; } TreeStyle_TreeChanged(tree, mask); TreeColumn_TreeChanged(tree, mask); if (mask & TREE_CONF_RELAYOUT) { TreeComputeGeometry(tree); Tree_InvalidateColumnWidth(tree, NULL); Tree_InvalidateColumnHeight(tree, NULL); /* In case -usetheme changes */ Tree_RelayoutWindow(tree); } else if (mask & TREE_CONF_REDISPLAY) { Tree_RelayoutWindow(tree); } return TCL_OK; } /* *--------------------------------------------------------------------------- * * TreeWorldChanged -- * * 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: * Widget will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ static void TreeWorldChanged( ClientData instanceData /* Widget info. */ ) { TreeCtrl *tree = (TreeCtrl *) instanceData; XGCValues gcValues; unsigned long gcMask; gcValues.font = Tk_FontId(tree->tkfont); gcValues.foreground = tree->fgColorPtr->pixel; gcValues.graphics_exposures = False; gcMask = GCForeground | GCFont | GCGraphicsExposures; if (tree->textGC != None) Tk_FreeGC(tree->display, tree->textGC); tree->textGC = Tk_GetGC(tree->tkwin, gcMask, &gcValues); TreeStyle_TreeChanged(tree, TREE_CONF_FONT | TREE_CONF_RELAYOUT); TreeColumn_TreeChanged(tree, TREE_CONF_FONT | TREE_CONF_RELAYOUT); TreeComputeGeometry(tree); Tree_InvalidateColumnWidth(tree, NULL); Tree_RelayoutWindow(tree); } /* *-------------------------------------------------------------- * * TreeEventProc -- * * This procedure is invoked by the Tk dispatcher for various * events on the widget. * * Results: * None. * * Side effects: * When the window gets deleted, internal structures get * cleaned up. When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void TreeEventProc( ClientData clientData, /* Widget info. */ XEvent *eventPtr /* Event info. */ ) { TreeCtrl *tree = clientData; switch (eventPtr->type) { case Expose: { int x = eventPtr->xexpose.x; int y = eventPtr->xexpose.y; Tree_ExposeArea(tree, x, y, x + eventPtr->xexpose.width, y + eventPtr->xexpose.height); break; } case ConfigureNotify: { if ((tree->prevWidth != Tk_Width(tree->tkwin)) || (tree->prevHeight != Tk_Height(tree->tkwin))) { tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_RelayoutWindow(tree); tree->prevWidth = Tk_Width(tree->tkwin); tree->prevHeight = Tk_Height(tree->tkwin); } break; } case FocusIn: /* Handle focus as Tile does */ if ( eventPtr->xfocus.detail == NotifyInferior || eventPtr->xfocus.detail == NotifyAncestor || eventPtr->xfocus.detail == NotifyNonlinear) { Tree_FocusChanged(tree, 1); } break; case FocusOut: /* Handle focus as Tile does */ if ( eventPtr->xfocus.detail == NotifyInferior || eventPtr->xfocus.detail == NotifyAncestor || eventPtr->xfocus.detail == NotifyNonlinear) { Tree_FocusChanged(tree, 0); } break; case ActivateNotify: Tree_Activate(tree, 1); break; case DeactivateNotify: Tree_Activate(tree, 0); break; case DestroyNotify: if (!tree->deleted) { tree->deleted = 1; Tcl_DeleteCommandFromToken(tree->interp, tree->widgetCmd); Tcl_EventuallyFree((ClientData) tree, TreeDestroy); } break; #ifdef USE_TTK case VirtualEvent: if (!strcmp("ThemeChanged", ((XVirtualEvent *)(eventPtr))->name)) { TreeTheme_ThemeChanged(tree); tree->widthOfColumns = -1; tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1; Tree_RelayoutWindow(tree); } break; #endif } } /* *---------------------------------------------------------------------- * * TreeCmdDeletedProc -- * * 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 TreeCmdDeletedProc( ClientData clientData /* Widget info. */ ) { TreeCtrl *tree = clientData; if (!tree->deleted) { Tk_DestroyWindow(tree->tkwin); } } /* *---------------------------------------------------------------------- * * TreeDestroy -- * * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release * to clean up the internal structure of a widget at a safe time * (when no-one is using it anymore). * * Results: * None. * * Side effects: * Everything associated with the widget is freed up. * *---------------------------------------------------------------------- */ static void TreeDestroy( char *memPtr /* Widget info. */ ) { TreeCtrl *tree = (TreeCtrl *) memPtr; TreeItem item; Tcl_HashEntry *hPtr; Tcl_HashSearch search; int i, count; hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); TreeItem_FreeResources(tree, item); hPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&tree->itemHash); Tcl_DeleteHashTable(&tree->itemSpansHash); count = TreeItemList_Count(&tree->preserveItemList); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&tree->preserveItemList, i); TreeItem_Release(tree, item); } TreeItemList_Free(&tree->preserveItemList); TreeStyle_Free(tree); TreeDragImage_Free(tree->dragImage); TreeMarquee_Free(tree->marquee); TreeDInfo_Free(tree); TreeTheme_Free(tree); if (tree->copyGC != None) Tk_FreeGC(tree->display, tree->copyGC); if (tree->textGC != None) Tk_FreeGC(tree->display, tree->textGC); if (tree->buttonGC != None) Tk_FreeGC(tree->display, tree->buttonGC); if (tree->lineGC != None) Tk_FreeGC(tree->display, tree->lineGC); Tree_FreeAllGC(tree); Tree_FreeColumns(tree); while (tree->regionStackLen > 0) TkDestroyRegion(tree->regionStack[--tree->regionStackLen]); QE_DeleteBindingTable(tree->bindingTable); for (i = STATE_USER - 1; i < 32; i++) if (tree->stateNames[i] != NULL) ckfree(tree->stateNames[i]); Tk_FreeConfigOptions((char *) tree, tree->debug.optionTable, tree->tkwin); Tk_FreeConfigOptions((char *) tree, tree->optionTable, tree->tkwin); hPtr = Tcl_FirstHashEntry(&tree->imageNameHash, &search); while (hPtr != NULL) { TreeImageRef *ref = (TreeImageRef *) Tcl_GetHashValue(hPtr); Tk_FreeImage(ref->image); ckfree((char *) ref); hPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&tree->imageNameHash); Tcl_DeleteHashTable(&tree->imageTokenHash); Tcl_DeleteHashTable(&tree->selection); #ifdef DEPRECATED if (tree->defaultStyle.styles != NULL) ckfree((char *) tree->defaultStyle.styles); #endif #ifdef ALLOC_HAX TreeAlloc_Finalize(tree->allocData); #endif Tcl_Release(tree->tkwin); WFREE(tree, TreeCtrl); } /* *---------------------------------------------------------------------- * * Tree_UpdateScrollbarX -- * * This procedure is invoked whenever information has changed in * a widget in a way that would invalidate a scrollbar display. * * A event is generated. * * If there is an associated scrollbar, then this procedure updates * it by invoking a Tcl command. * * Results: * None. * * Side effects: * A Tcl command is invoked, and an additional command may be * invoked to process errors in the command. * *---------------------------------------------------------------------- */ void Tree_UpdateScrollbarX( TreeCtrl *tree /* Widget info. */ ) { Tcl_Interp *interp = tree->interp; int result; double fractions[2]; char buffer[TCL_DOUBLE_SPACE * 2]; char *xScrollCmd; Tree_GetScrollFractionsX(tree, fractions); TreeNotify_Scroll(tree, fractions, FALSE); if (tree->xScrollCmd == NULL) return; Tcl_Preserve((ClientData) interp); Tcl_Preserve((ClientData) tree); xScrollCmd = tree->xScrollCmd; Tcl_Preserve((ClientData) xScrollCmd); sprintf(buffer, "%g %g", fractions[0], fractions[1]); result = Tcl_VarEval(interp, xScrollCmd, " ", buffer, (char *) NULL); if (result != TCL_OK) Tcl_BackgroundError(interp); Tcl_ResetResult(interp); Tcl_Release((ClientData) xScrollCmd); Tcl_Release((ClientData) tree); Tcl_Release((ClientData) interp); } /* *---------------------------------------------------------------------- * * Tree_UpdateScrollbarY -- * * This procedure is invoked whenever information has changed in * a widget in a way that would invalidate a scrollbar display. * * A event is generated. * * If there is an associated scrollbar, then this procedure updates * it by invoking a Tcl command. * * Results: * None. * * Side effects: * A Tcl command is invoked, and an additional command may be * invoked to process errors in the command. * *---------------------------------------------------------------------- */ void Tree_UpdateScrollbarY( TreeCtrl *tree /* Widget info. */ ) { Tcl_Interp *interp = tree->interp; int result; double fractions[2]; char buffer[TCL_DOUBLE_SPACE * 2]; char *yScrollCmd; Tree_GetScrollFractionsY(tree, fractions); TreeNotify_Scroll(tree, fractions, TRUE); if (tree->yScrollCmd == NULL) return; Tcl_Preserve((ClientData) interp); Tcl_Preserve((ClientData) tree); yScrollCmd = tree->yScrollCmd; Tcl_Preserve((ClientData) yScrollCmd); sprintf(buffer, "%g %g", fractions[0], fractions[1]); result = Tcl_VarEval(interp, yScrollCmd, " ", buffer, (char *) NULL); if (result != TCL_OK) Tcl_BackgroundError(interp); Tcl_ResetResult(interp); Tcl_Release((ClientData) yScrollCmd); Tcl_Release((ClientData) tree); Tcl_Release((ClientData) interp); } /* *---------------------------------------------------------------------- * * TreeComputeGeometry -- * * This procedure is invoked to compute the requested size for the * window. * * Results: * None. * * Side effects: * Tk_GeometryRequest is called to register the desired dimensions * for the window. * *---------------------------------------------------------------------- */ static void TreeComputeGeometry( TreeCtrl *tree /* Widget info. */ ) { Tk_SetInternalBorderEx(tree->tkwin, tree->inset.left, tree->inset.right, tree->inset.top, tree->inset.bottom); Tk_GeometryRequest(tree->tkwin, tree->width + tree->inset.left + tree->inset.right, tree->height + tree->inset.top + tree->inset.bottom); } /* *---------------------------------------------------------------------- * * Tree_AddItem -- * * Add an item to the hash table of items. Also set the unique item * id and increment the number of items. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tree_AddItem( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item that was created. */ ) { Tcl_HashEntry *hPtr; int id, isNew; id = TreeItem_SetID(tree, item, tree->nextItemId++); hPtr = Tcl_CreateHashEntry(&tree->itemHash, (char *) id, &isNew); Tcl_SetHashValue(hPtr, item); tree->itemCount++; } /* *---------------------------------------------------------------------- * * Tree_RemoveItem -- * * Remove an item from the selection, if selected. * Remove an item from the hash table of items. * Decrement the number of items. * Reset the unique item id allocator if the last item is removed. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tree_RemoveItem( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item to remove. */ ) { Tcl_HashEntry *hPtr; if (TreeItem_GetSelected(tree, item)) Tree_RemoveFromSelection(tree, item); hPtr = Tcl_FindHashEntry(&tree->itemSpansHash, (char *) item); if (hPtr != NULL) Tcl_DeleteHashEntry(hPtr); hPtr = Tcl_FindHashEntry(&tree->itemHash, (char *) TreeItem_GetID(tree, item)); Tcl_DeleteHashEntry(hPtr); tree->itemCount--; if (tree->itemCount == 1) tree->nextItemId = TreeItem_GetID(tree, tree->root) + 1; } /* *---------------------------------------------------------------------- * * ImageChangedProc -- * * This procedure is invoked by the image code whenever the manager * for an image does something that affects the image's size or * how it is displayed. * * Results: * None. * * Side effects: * Arranges for the widget to get redisplayed. * *---------------------------------------------------------------------- */ static void ImageChangedProc( ClientData clientData, /* Widget info. */ int x, int y, /* Upper left pixel (within image) * that must be redisplayed. */ int width, int height, /* Dimensions of area to redisplay * (may be <= 0). */ int imageWidth, int imageHeight /* New dimensions of image. */ ) { /* I would like to know the image was deleted... */ TreeCtrl *tree = clientData; /* FIXME: any image elements need to have their size invalidated * and items relayout'd accordingly. */ /* FIXME: this is used for the background image, but whitespace * is not redrawn if the background image is modified. */ Tree_DInfoChanged(tree, DINFO_INVALIDATE | DINFO_OUT_OF_DATE); } /* *---------------------------------------------------------------------- * * Tree_GetImage -- * * Wrapper around Tk_GetImage(). If the requested image does not yet * exist it is created. Otherwise an existing instance is returned. * * The purpose of this procedure is to save memory. We may expect * the same image to be used hundreds of times (a folder image for * example) and want to avoid allocating an instance for every usage. * * For each call to this function, there must be a matching call * to Tree_FreeImage. * * Results: * Token for the image instance. If an error occurs the result is * NULL and a message is left in the interpreter's result. * * Side effects: * A new image instance may be created. * *---------------------------------------------------------------------- */ Tk_Image Tree_GetImage( TreeCtrl *tree, /* Widget info. */ char *imageName /* Name of an existing image. */ ) { Tcl_HashEntry *hPtr, *h2Ptr; TreeImageRef *ref; Tk_Image image; int isNew; hPtr = Tcl_CreateHashEntry(&tree->imageNameHash, imageName, &isNew); if (isNew) { image = Tk_GetImage(tree->interp, tree->tkwin, imageName, ImageChangedProc, (ClientData) tree); if (image == NULL) { Tcl_DeleteHashEntry(hPtr); return NULL; } ref = (TreeImageRef *) ckalloc(sizeof(TreeImageRef)); ref->count = 0; ref->image = image; ref->hPtr = hPtr; Tcl_SetHashValue(hPtr, ref); h2Ptr = Tcl_CreateHashEntry(&tree->imageTokenHash, (char *) image, &isNew); Tcl_SetHashValue(h2Ptr, ref); } ref = (TreeImageRef *) Tcl_GetHashValue(hPtr); ref->count++; return ref->image; } /* *---------------------------------------------------------------------- * * Tree_FreeImage -- * * Decrement the reference count on an image. * * Results: * If the reference count hits zero, frees the image instance and * hash table entries. * * Side effects: * Memory may be freed. * *---------------------------------------------------------------------- */ void Tree_FreeImage( TreeCtrl *tree, /* Widget info. */ Tk_Image image /* Image token. */ ) { Tcl_HashEntry *hPtr; TreeImageRef *ref; hPtr = Tcl_FindHashEntry(&tree->imageTokenHash, (char *) image); if (hPtr != NULL) { ref = (TreeImageRef *) Tcl_GetHashValue(hPtr); if (--ref->count == 0) { Tcl_DeleteHashEntry(ref->hPtr); /* imageNameHash */ Tcl_DeleteHashEntry(hPtr); Tk_FreeImage(ref->image); ckfree((char *) ref); } } } /* *---------------------------------------------------------------------- * * Tree_StateFromObj -- * * Parse a Tcl_Obj containing a state name (with optional modifers) * into a STATE_xxx flag, and modify an existing array of state * flags accordingly. * * If the object contains "foo", then the state "foo" is set on. * If the object contains "!foo", then the state "foo" is set off. * If the object contains "^foo", then the state "foo" is toggled. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tree_StateFromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *obj, /* String rep of the state. */ int states[3], /* Initialized state flags, indexed by the * STATE_OP_xxx contants. A single flag * may be turned on or off in each value. */ int *indexPtr, /* Returned index of the STATE_xxx flag. * May be NULL. */ int flags /* SFO_xxx flags. */ ) { Tcl_Interp *interp = tree->interp; int i, op = STATE_OP_ON, op2, op3, length, state = 0; char ch0, *string; string = Tcl_GetStringFromObj(obj, &length); if (length == 0) goto unknown; ch0 = string[0]; if (ch0 == '!') { if (flags & SFO_NOT_OFF) { FormatResult(interp, "can't specify '!' for this command"); return TCL_ERROR; } op = STATE_OP_OFF; ++string; ch0 = string[0]; } else if (ch0 == '~') { if (flags & SFO_NOT_TOGGLE) { FormatResult(interp, "can't specify '~' for this command"); return TCL_ERROR; } op = STATE_OP_TOGGLE; ++string; ch0 = string[0]; } for (i = 0; i < 32; i++) { if (tree->stateNames[i] == NULL) continue; if ((ch0 == tree->stateNames[i][0]) && (strcmp(string, tree->stateNames[i]) == 0)) { if ((i < STATE_USER - 1) && (flags & SFO_NOT_STATIC)) { FormatResult(interp, "can't specify state \"%s\" for this command", tree->stateNames[i]); return TCL_ERROR; } state = 1L << i; break; } } if (state == 0) goto unknown; if (states != NULL) { if (op == STATE_OP_ON) { op2 = STATE_OP_OFF; op3 = STATE_OP_TOGGLE; } else if (op == STATE_OP_OFF) { op2 = STATE_OP_ON; op3 = STATE_OP_TOGGLE; } else { op2 = STATE_OP_ON; op3 = STATE_OP_OFF; } states[op2] &= ~state; states[op3] &= ~state; states[op] |= state; } if (indexPtr != NULL) (*indexPtr) = i; return TCL_OK; unknown: FormatResult(interp, "unknown state \"%s\"", string); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tree_StateFromListObj -- * * Call Tree_StateFromObj for a Tcl_Obj list object. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tree_StateFromListObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *obj, /* List of states. */ int states[3], /* Uninitialized state flags, indexed by the * STATE_OP_xxx contants. A single flag * may be turned on or off in each value. */ int flags /* SFO_xxx flags. */ ) { Tcl_Interp *interp = tree->interp; int i, listObjc; Tcl_Obj **listObjv; states[0] = states[1] = states[2] = 0; if (Tcl_ListObjGetElements(interp, obj, &listObjc, &listObjv) != TCL_OK) return TCL_ERROR; for (i = 0; i < listObjc; i++) { if (Tree_StateFromObj(tree, listObjv[i], states, NULL, flags) != TCL_OK) return TCL_ERROR; } return TCL_OK; } /* *-------------------------------------------------------------- * * TreeStateCmd -- * * This procedure is invoked to process the [state] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int TreeStateCmd( TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tcl_Interp *interp = tree->interp; static CONST char *commandName[] = { "define", "linkage", "names", "undefine", (char *) NULL }; enum { COMMAND_DEFINE, COMMAND_LINKAGE, COMMAND_NAMES, COMMAND_UNDEFINE }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandName, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case COMMAND_DEFINE: { char *string; int i, length, slot = -1; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "stateName"); return TCL_ERROR; } string = Tcl_GetStringFromObj(objv[3], &length); if (!length || (*string == '~') || (*string == '!')) { FormatResult(interp, "invalid state name \"%s\"", string); return TCL_ERROR; } for (i = 0; i < 32; i++) { if (tree->stateNames[i] == NULL) { if (slot == -1) slot = i; continue; } if (strcmp(tree->stateNames[i], string) == 0) { FormatResult(interp, "state \"%s\" already defined", string); return TCL_ERROR; } } if (slot == -1) { FormatResult(interp, "cannot define any more states"); return TCL_ERROR; } tree->stateNames[slot] = ckalloc(length + 1); strcpy(tree->stateNames[slot], string); break; } case COMMAND_LINKAGE: { int index; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "state"); return TCL_ERROR; } if (Tree_StateFromObj(tree, objv[3], NULL, &index, SFO_NOT_OFF | SFO_NOT_TOGGLE) != TCL_OK) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewStringObj( (index < STATE_USER - 1) ? "static" : "dynamic", -1)); break; } case COMMAND_NAMES: { Tcl_Obj *listObj; int i; if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); return TCL_ERROR; } listObj = Tcl_NewListObj(0, NULL); for (i = STATE_USER - 1; i < 32; i++) { if (tree->stateNames[i] != NULL) Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj(tree->stateNames[i], -1)); } Tcl_SetObjResult(interp, listObj); break; } case COMMAND_UNDEFINE: { int i, index; for (i = 3; i < objc; i++) { if (Tree_StateFromObj(tree, objv[i], NULL, &index, SFO_NOT_STATIC | SFO_NOT_OFF | SFO_NOT_TOGGLE) != TCL_OK) return TCL_ERROR; Tree_UndefineState(tree, 1L << index); PerStateInfo_Undefine(tree, &pstBitmap, &tree->buttonBitmap, 1L << index); PerStateInfo_Undefine(tree, &pstImage, &tree->buttonImage, 1L << index); ckfree(tree->stateNames[index]); tree->stateNames[index] = NULL; } break; } } return TCL_OK; } /* *-------------------------------------------------------------- * * Tree_AddToSelection -- * * Add an item to the hash table of selected items. Turn on the * STATE_SELECTED state for the item. * * Results: * None. * * Side effects: * The widget may be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_AddToSelection( TreeCtrl *tree, /* Widget info */ TreeItem item /* Item to add to the selection. */ ) { Tcl_HashEntry *hPtr; int isNew; #ifdef SELECTION_VISIBLE if (!TreeItem_ReallyVisible(tree, item)) panic("Tree_AddToSelection: item %d not ReallyVisible", TreeItem_GetID(tree, item)); #endif if (TreeItem_GetSelected(tree, item)) panic("Tree_AddToSelection: item %d already selected", TreeItem_GetID(tree, item)); if (!TreeItem_GetEnabled(tree, item)) panic("Tree_AddToSelection: item %d not enabled", TreeItem_GetID(tree, item)); TreeItem_ChangeState(tree, item, 0, STATE_SELECTED); hPtr = Tcl_CreateHashEntry(&tree->selection, (char *) item, &isNew); if (!isNew) panic("Tree_AddToSelection: item %d already in selection hash table", TreeItem_GetID(tree, item)); tree->selectCount++; } /* *-------------------------------------------------------------- * * Tree_RemoveFromSelection -- * * Remove an item from the hash table of selected items. Turn off the * STATE_SELECTED state for the item. * * Results: * None. * * Side effects: * The widget may be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_RemoveFromSelection( TreeCtrl *tree, /* Widget info */ TreeItem item /* Item to remove from the selection. */ ) { Tcl_HashEntry *hPtr; if (!TreeItem_GetSelected(tree, item)) panic("Tree_RemoveFromSelection: item %d isn't selected", TreeItem_GetID(tree, item)); TreeItem_ChangeState(tree, item, STATE_SELECTED, 0); hPtr = Tcl_FindHashEntry(&tree->selection, (char *) item); if (hPtr == NULL) panic("Tree_RemoveFromSelection: item %d not found in selection hash table", TreeItem_GetID(tree, item)); Tcl_DeleteHashEntry(hPtr); tree->selectCount--; } /* *-------------------------------------------------------------- * * TreeSelectionCmd -- * * This procedure is invoked to process the [selection] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int TreeSelectionCmd( Tcl_Interp *interp, /* Current interpreter. */ TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { static CONST char *commandName[] = { "add", "anchor", "clear", "count", "get", "includes", "modify", NULL }; enum { COMMAND_ADD, COMMAND_ANCHOR, COMMAND_CLEAR, COMMAND_COUNT, COMMAND_GET, COMMAND_INCLUDES, COMMAND_MODIFY }; int index; TreeItemList itemsFirst, itemsLast; TreeItem item, itemFirst, itemLast; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandName, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case COMMAND_ADD: { int i, count; TreeItemList items; Tcl_HashEntry *hPtr; Tcl_HashSearch search; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "first ?last?"); return TCL_ERROR; } if (TreeItemList_FromObj(tree, objv[3], &itemsFirst, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; itemFirst = TreeItemList_Nth(&itemsFirst, 0); itemLast = NULL; if (objc == 5) { if (TreeItemList_FromObj(tree, objv[4], &itemsLast, IFO_NOT_NULL) != TCL_OK) { TreeItemList_Free(&itemsFirst); return TCL_ERROR; } itemLast = TreeItemList_Nth(&itemsLast, 0); } if ((itemFirst == ITEM_ALL) || (itemLast == ITEM_ALL)) { if (objc == 5) TreeItemList_Free(&itemsLast); TreeItemList_Init(tree, &items, tree->itemCount - tree->selectCount); /* Include orphans. */ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); #ifdef SELECTION_VISIBLE if (!TreeItem_GetSelected(tree, item) && TreeItem_GetEnabled(tree, item) && TreeItem_ReallyVisible(tree, item)) { #else if (!TreeItem_GetSelected(tree, item) && TreeItem_GetEnabled(tree, item)) { #endif Tree_AddToSelection(tree, item); TreeItemList_Append(&items, item); } hPtr = Tcl_NextHashEntry(&search); } goto doneADD; } if (objc == 5) { TreeItemList_Free(&itemsFirst); TreeItemList_Free(&itemsLast); count = TreeItem_FirstAndLast(tree, &itemFirst, &itemLast); if (count == 0) return TCL_ERROR; TreeItemList_Init(tree, &items, count); while (1) { #ifdef SELECTION_VISIBLE if (!TreeItem_GetSelected(tree, itemFirst) && TreeItem_GetEnabled(tree, itemFirst) && TreeItem_ReallyVisible(tree, itemFirst)) { #else if (!TreeItem_GetSelected(tree, itemFirst) && TreeItem_GetEnabled(tree, itemFirst)) { #endif Tree_AddToSelection(tree, itemFirst); TreeItemList_Append(&items, itemFirst); } if (itemFirst == itemLast) break; itemFirst = TreeItem_Next(tree, itemFirst); } goto doneADD; } count = TreeItemList_Count(&itemsFirst); TreeItemList_Init(tree, &items, count); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&itemsFirst, i); #ifdef SELECTION_VISIBLE if (!TreeItem_GetSelected(tree, item) && TreeItem_GetEnabled(tree, item) && TreeItem_ReallyVisible(tree, item)) { #else if (!TreeItem_GetSelected(tree, item) && TreeItem_GetEnabled(tree, item)) { #endif Tree_AddToSelection(tree, item); TreeItemList_Append(&items, item); } } doneADD: if (TreeItemList_Count(&items)) { TreeNotify_Selection(tree, &items, NULL); } TreeItemList_Free(&items); TreeItemList_Free(&itemsFirst); break; } case COMMAND_ANCHOR: { if (objc != 3 && objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "?item?"); return TCL_ERROR; } if (objc == 4) { if (TreeItem_FromObj(tree, objv[3], &item, IFO_NOT_NULL) != TCL_OK) { return TCL_ERROR; } tree->anchorItem = item; } Tcl_SetObjResult(interp, TreeItem_ToObj(tree, tree->anchorItem)); break; } case COMMAND_CLEAR: { int i, count; TreeItemList items; Tcl_HashEntry *hPtr; Tcl_HashSearch search; if (objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "?first? ?last?"); return TCL_ERROR; } itemFirst = itemLast = NULL; if (objc >= 4) { if (TreeItemList_FromObj(tree, objv[3], &itemsFirst, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; itemFirst = TreeItemList_Nth(&itemsFirst, 0); } if (objc == 5) { if (TreeItemList_FromObj(tree, objv[4], &itemsLast, IFO_NOT_NULL) != TCL_OK) { TreeItemList_Free(&itemsFirst); return TCL_ERROR; } itemLast = TreeItemList_Nth(&itemsLast, 0); } if (tree->selectCount < 1) { if (objc >= 4) TreeItemList_Free(&itemsFirst); if (objc == 5) TreeItemList_Free(&itemsLast); break; } if ((objc == 3) || (itemFirst == ITEM_ALL) || (itemLast == ITEM_ALL)) { if (objc >= 4) TreeItemList_Free(&itemsFirst); if (objc == 5) TreeItemList_Free(&itemsLast); TreeItemList_Init(tree, &items, tree->selectCount); hPtr = Tcl_FirstHashEntry(&tree->selection, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&tree->selection, hPtr); TreeItemList_Append(&items, item); hPtr = Tcl_NextHashEntry(&search); } count = TreeItemList_Count(&items); for (i = 0; i < count; i++) Tree_RemoveFromSelection(tree, TreeItemList_Nth(&items, i)); goto doneCLEAR; } if (objc == 5) { TreeItemList_Free(&itemsFirst); TreeItemList_Free(&itemsLast); count = TreeItem_FirstAndLast(tree, &itemFirst, &itemLast); if (count == 0) return TCL_ERROR; TreeItemList_Init(tree, &items, count); while (1) { if (TreeItem_GetSelected(tree, itemFirst)) { Tree_RemoveFromSelection(tree, itemFirst); TreeItemList_Append(&items, itemFirst); } if (itemFirst == itemLast) break; itemFirst = TreeItem_Next(tree, itemFirst); } goto doneCLEAR; } count = TreeItemList_Count(&itemsFirst); TreeItemList_Init(tree, &items, count); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&itemsFirst, i); if (TreeItem_GetSelected(tree, item)) { Tree_RemoveFromSelection(tree, item); TreeItemList_Append(&items, item); } } TreeItemList_Free(&itemsFirst); doneCLEAR: if (TreeItemList_Count(&items)) { TreeNotify_Selection(tree, NULL, &items); } TreeItemList_Free(&items); break; } case COMMAND_COUNT: { if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(tree->selectCount)); break; } case COMMAND_GET: { TreeItem item; Tcl_Obj *listObj; Tcl_HashEntry *hPtr; Tcl_HashSearch search; #ifdef SELECTION_VISIBLE if (objc < 3 || objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "?first? ?last?"); return TCL_ERROR; } if (objc > 3) { int first, last; TreeItemList items; if (TclGetIntForIndex(interp, objv[3], tree->selectCount - 1, &first) != TCL_OK) { return TCL_ERROR; } if (first < 0) first = 0; last = first; if (objc == 5) { if (TclGetIntForIndex(interp, objv[4], tree->selectCount - 1, &last) != TCL_OK) { return TCL_ERROR; } } if (last >= tree->selectCount) last = tree->selectCount - 1; if (first > last) break; /* Build a list of selected items. */ TreeItemList_Init(tree, &items, tree->selectCount); hPtr = Tcl_FirstHashEntry(&tree->selection, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&tree->selection, hPtr); TreeItemList_Append(&items, item); hPtr = Tcl_NextHashEntry(&search); } /* Sort it. */ TreeItemList_Sort(&items); if (first == last) { item = TreeItemList_Nth(&items, first); Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item)); } else { listObj = Tcl_NewListObj(0, NULL); for (index = first; index <= last; index++) { item = TreeItemList_Nth(&items, index); Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); } Tcl_SetObjResult(interp, listObj); } TreeItemList_Free(&items); break; } #else /* SELECTION_VISIBLE */ /* If any item may be selected, including orphans, then getting * a sorted list of selected items is impossible. */ if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); return TCL_ERROR; } #endif /* SELECTION_VISIBLE */ if (tree->selectCount < 1) break; listObj = Tcl_NewListObj(0, NULL); hPtr = Tcl_FirstHashEntry(&tree->selection, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&tree->selection, hPtr); Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); hPtr = Tcl_NextHashEntry(&search); } Tcl_SetObjResult(interp, listObj); break; } case COMMAND_INCLUDES: { if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "item"); return TCL_ERROR; } if (TreeItem_FromObj(tree, objv[3], &item, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewBooleanObj( TreeItem_GetSelected(tree, item))); break; } case COMMAND_MODIFY: { int i, j, k, objcS, objcD; Tcl_Obj **objvS, **objvD; Tcl_HashEntry *hPtr; Tcl_HashSearch search; TreeItem item; TreeItemList items; TreeItemList itemS, itemD, newS, newD; int allS = FALSE, allD = FALSE; if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "select deselect"); return TCL_ERROR; } if (Tcl_ListObjGetElements(interp, objv[3], &objcS, &objvS) != TCL_OK) return TCL_ERROR; if (Tcl_ListObjGetElements(interp, objv[4], &objcD, &objvD) != TCL_OK) return TCL_ERROR; /* No change */ if (!objcS && !objcD) break; /* Some of these may get double-initialized. */ TreeItemList_Init(tree, &itemS, 0); TreeItemList_Init(tree, &itemD, 0); TreeItemList_Init(tree, &newS, 0); TreeItemList_Init(tree, &newD, 0); /* List of items to select */ for (i = 0; i < objcS; i++) { if (TreeItemList_FromObj(tree, objvS[i], &items, IFO_NOT_NULL) != TCL_OK) { TreeItemList_Free(&itemS); return TCL_ERROR; } /* Add unique items to itemS */ for (k = 0; k < TreeItemList_Count(&items); k++) { item = TreeItemList_Nth(&items, k); if (item == ITEM_ALL) { allS = TRUE; break; } for (j = 0; j < TreeItemList_Count(&itemS); j++) { if (TreeItemList_Nth(&itemS, j) == item) break; } if (j == TreeItemList_Count(&itemS)) { TreeItemList_Append(&itemS, item); } } TreeItemList_Free(&items); if (allS) break; } /* List of items to deselect */ for (i = 0; i < objcD; i++) { if (TreeItemList_FromObj(tree, objvD[i], &items, IFO_NOT_NULL) != TCL_OK) { TreeItemList_Free(&itemS); TreeItemList_Free(&itemD); return TCL_ERROR; } /* Add unique items to itemD */ for (k = 0; k < TreeItemList_Count(&items); k++) { item = TreeItemList_Nth(&items, k); if (item == ITEM_ALL) { allD = TRUE; break; } for (j = 0; j < TreeItemList_Count(&itemD); j++) { if (TreeItemList_Nth(&itemD, j) == item) break; } if (j == TreeItemList_Count(&itemD)) { TreeItemList_Append(&itemD, item); } } TreeItemList_Free(&items); if (allD) break; } /* Select all */ if (allS) { TreeItemList_Init(tree, &newS, tree->itemCount - tree->selectCount); #ifdef SELECTION_VISIBLE item = tree->root; if (!TreeItem_ReallyVisible(tree, item)) item = TreeItem_NextVisible(tree, item); while (item != NULL) { if (!TreeItem_GetSelected(tree, item) && TreeItem_GetEnabled(tree, item)) { TreeItemList_Append(&newS, item); } item = TreeItem_NextVisible(tree, item); } #else /* Include detached items */ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); if (!TreeItem_GetSelected(tree, item) && TreeItem_GetEnabled(tree, item)) { TreeItemList_Append(&newS, item); } hPtr = Tcl_NextHashEntry(&search); } #endif /* Ignore the deselect list. */ goto modifyDONE; } /* Select some */ if (objcS > 0) { TreeItemList_Init(tree, &newS, objcS); for (i = 0; i < TreeItemList_Count(&itemS); i++) { item = TreeItemList_Nth(&itemS, i); if (TreeItem_GetSelected(tree, item)) continue; if (!TreeItem_GetEnabled(tree, item)) continue; #ifdef SELECTION_VISIBLE if (!TreeItem_ReallyVisible(tree, item)) continue; #endif TreeItemList_Append(&newS, item); } } /* Deselect all */ if (allD) { TreeItemList_Init(tree, &newD, tree->selectCount); hPtr = Tcl_FirstHashEntry(&tree->selection, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&tree->selection, hPtr); /* Don't deselect an item in the select list */ for (j = 0; j < TreeItemList_Count(&itemS); j++) { if (item == TreeItemList_Nth(&itemS, j)) break; } if (j == TreeItemList_Count(&itemS)) { TreeItemList_Append(&newD, item); } hPtr = Tcl_NextHashEntry(&search); } } /* Deselect some */ if ((objcD > 0) && !allD) { TreeItemList_Init(tree, &newD, objcD); for (i = 0; i < TreeItemList_Count(&itemD); i++) { item = TreeItemList_Nth(&itemD, i); if (!TreeItem_GetSelected(tree, item)) continue; /* Don't deselect an item in the select list */ for (j = 0; j < TreeItemList_Count(&itemS); j++) { if (item == TreeItemList_Nth(&itemS, j)) break; } if (j == TreeItemList_Count(&itemS)) { TreeItemList_Append(&newD, item); } } } modifyDONE: for (i = 0; i < TreeItemList_Count(&newS); i++) Tree_AddToSelection(tree, TreeItemList_Nth(&newS, i)); for (i = 0; i < TreeItemList_Count(&newD); i++) Tree_RemoveFromSelection(tree, TreeItemList_Nth(&newD, i)); if (TreeItemList_Count(&newS) || TreeItemList_Count(&newD)) { TreeNotify_Selection(tree, &newS, &newD); } TreeItemList_Free(&newS); TreeItemList_Free(&itemS); TreeItemList_Free(&newD); TreeItemList_Free(&itemD); break; } } return TCL_OK; } /* *-------------------------------------------------------------- * * A_XviewCmd -- * * This procedure is invoked to process the "xview" option for * the widget command for a TreeCtrl. See the user documentation * for details on what it does. * * NOTE: This procedure is called when the -xscrollincrement option * is specified. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int A_XviewCmd( TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tcl_Interp *interp = tree->interp; if (objc == 2) { double fractions[2]; Tree_GetScrollFractionsX(tree, fractions); FormatResult(interp, "%g %g", fractions[0], fractions[1]); } else { int count, index = 0, indexMax, offset, type; double fraction; int visWidth = Tree_ContentWidth(tree); int totWidth = Tree_TotalWidth(tree); int xIncr = tree->xScrollIncrement; if (visWidth < 0) visWidth = 0; if (totWidth <= visWidth) return TCL_OK; if (visWidth > 1) { /* Find incrementLeft when scrolled to extreme right */ indexMax = Increment_FindX(tree, totWidth - visWidth); offset = Increment_ToOffsetX(tree, indexMax); if (offset < totWidth - visWidth) { indexMax++; offset = Increment_ToOffsetX(tree, indexMax); } /* Add some fake content to right */ if (offset + visWidth > totWidth) totWidth = offset + visWidth; } else { indexMax = Increment_FindX(tree, totWidth); visWidth = 1; } type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count); switch (type) { case TK_SCROLL_ERROR: return TCL_ERROR; case TK_SCROLL_MOVETO: offset = (int) (fraction * totWidth + 0.5); index = Increment_FindX(tree, offset); break; case TK_SCROLL_PAGES: offset = Tree_ContentLeft(tree) + tree->xOrigin; offset += (int) (count * visWidth * 0.9); index = Increment_FindX(tree, offset); if ((count > 0) && (index == Increment_FindX(tree, Tree_ContentLeft(tree) + tree->xOrigin))) index++; break; case TK_SCROLL_UNITS: offset = Tree_ContentLeft(tree) + tree->xOrigin; index = offset / xIncr; index += count; break; } /* Don't scroll too far left */ if (index < 0) index = 0; /* Don't scroll too far right */ if (index > indexMax) index = indexMax; offset = Increment_ToOffsetX(tree, index); if (offset - Tree_ContentLeft(tree) != tree->xOrigin) { tree->xOrigin = offset - Tree_ContentLeft(tree); Tree_EventuallyRedraw(tree); } } return TCL_OK; } /* *-------------------------------------------------------------- * * A_YviewCmd -- * * This procedure is invoked to process the "yview" option for * the widget command for a TreeCtrl. See the user documentation * for details on what it does. * * NOTE: This procedure is called when the -yscrollincrement option * is specified. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int A_YviewCmd( TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tcl_Interp *interp = tree->interp; if (objc == 2) { double fractions[2]; Tree_GetScrollFractionsY(tree, fractions); FormatResult(interp, "%g %g", fractions[0], fractions[1]); } else { int count, index = 0, indexMax, offset, type; double fraction; int visHeight = Tree_ContentHeight(tree); int totHeight = Tree_TotalHeight(tree); int yIncr = tree->yScrollIncrement; if (visHeight < 0) visHeight = 0; if (totHeight <= visHeight) return TCL_OK; if (visHeight > 1) { /* Find incrementTop when scrolled to bottom */ indexMax = Increment_FindY(tree, totHeight - visHeight); offset = Increment_ToOffsetY(tree, indexMax); if (offset < totHeight - visHeight) { indexMax++; offset = Increment_ToOffsetY(tree, indexMax); } /* Add some fake content to bottom */ if (offset + visHeight > totHeight) totHeight = offset + visHeight; } else { indexMax = Increment_FindY(tree, totHeight); visHeight = 1; } type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count); switch (type) { case TK_SCROLL_ERROR: return TCL_ERROR; case TK_SCROLL_MOVETO: offset = (int) (fraction * totHeight + 0.5); index = Increment_FindY(tree, offset); break; case TK_SCROLL_PAGES: offset = Tree_ContentTop(tree) + tree->yOrigin; offset += (int) (count * visHeight * 0.9); index = Increment_FindY(tree, offset); if ((count > 0) && (index == Increment_FindY(tree, Tree_ContentTop(tree) + tree->yOrigin))) index++; break; case TK_SCROLL_UNITS: offset = Tree_ContentTop(tree) + tree->yOrigin; index = offset / yIncr; index += count; break; } /* Don't scroll too far up */ if (index < 0) index = 0; /* Don't scroll too far down */ if (index > indexMax) index = indexMax; offset = Increment_ToOffsetY(tree, index); if (offset - Tree_ContentTop(tree) != tree->yOrigin) { tree->yOrigin = offset - Tree_ContentTop(tree); Tree_EventuallyRedraw(tree); } } return TCL_OK; } /* *-------------------------------------------------------------- * * TreeXviewCmd -- * * This procedure is invoked to process the "xview" option for * the widget command for a TreeCtrl. See the user documentation * for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int TreeXviewCmd( Tcl_Interp *interp, /* Current interpreter. */ TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { if (tree->xScrollIncrement <= 0) return B_XviewCmd(tree, objc, objv); return A_XviewCmd(tree, objc, objv); } /* *-------------------------------------------------------------- * * TreeYviewCmd -- * * This procedure is invoked to process the "yview" option for * the widget command for a TreeCtrl. See the user documentation * for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int TreeYviewCmd( Tcl_Interp *interp, /* Current interpreter. */ TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { if (tree->yScrollIncrement <= 0) return B_YviewCmd(tree, objc, objv); return A_YviewCmd(tree, objc, objv); } void Tree_Debug( TreeCtrl *tree /* Widget info. */ ) { if (TreeItem_Debug(tree, tree->root) != TCL_OK) { dbwin("Tree_Debug: %s\n", Tcl_GetStringResult(tree->interp)); Tcl_BackgroundError(tree->interp); } } /* *-------------------------------------------------------------- * * TreeDebugCmd -- * * This procedure is invoked to process the [debug] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int TreeDebugCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; static CONST char *commandNames[] = { "alloc", "cget", "configure", "dinfo", "expose", "scroll", (char *) NULL }; enum { COMMAND_ALLOC, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DINFO, COMMAND_EXPOSE, COMMAND_SCROLL }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { /* T debug alloc */ case COMMAND_ALLOC: { #ifdef ALLOC_HAX #ifdef TREECTRL_DEBUG TreeAlloc_Stats(interp, tree->allocData); #else FormatResult(interp, "TREECTRL_DEBUG is not defined"); #endif #else FormatResult(interp, "ALLOC_HAX is not defined"); #endif break; } /* T debug cget option */ case COMMAND_CGET: { Tcl_Obj *resultObjPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "option"); return TCL_ERROR; } resultObjPtr = Tk_GetOptionValue(interp, (char *) tree, tree->debug.optionTable, objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } /* T debug configure ?option? ?value? ?option value ...? */ case COMMAND_CONFIGURE: { Tcl_Obj *resultObjPtr; Tk_SavedOptions savedOptions; int mask, result; if (objc < 3) { Tcl_WrongNumArgs(interp, 3, objv, "?option? ?value?"); return TCL_ERROR; } if (objc <= 4) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) tree, tree->debug.optionTable, (objc == 3) ? (Tcl_Obj *) NULL : objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } result = Tk_SetOptions(interp, (char *) tree, tree->debug.optionTable, objc - 3, objv + 3, tree->tkwin, &savedOptions, &mask); if (result != TCL_OK) { Tk_RestoreSavedOptions(&savedOptions); return TCL_ERROR; } Tk_FreeSavedOptions(&savedOptions); if (tree->debug.eraseColor != NULL) { tree->debug.gcErase = Tk_GCForColor(tree->debug.eraseColor, Tk_WindowId(tree->tkwin)); } if (tree->debug.drawColor != NULL) { tree->debug.gcDraw = Tk_GCForColor(tree->debug.drawColor, Tk_WindowId(tree->tkwin)); } break; } case COMMAND_DINFO: { extern int Tree_DumpDInfo(TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); return Tree_DumpDInfo(tree, objc, objv); } /* T debug expose x1 y1 x2 y2 */ case COMMAND_EXPOSE: { int x1, y1, x2, y2; if (objc != 7) { Tcl_WrongNumArgs(interp, 3, objv, "x1 y1 x2 y2"); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[3], &x1) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[4], &y1) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[5], &x2) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[6], &y2) != TCL_OK) return TCL_ERROR; Tree_RedrawArea(tree, MIN(x1, x2), MIN(y1, y2), MAX(x1, x2), MAX(y1, y2)); break; } case COMMAND_SCROLL: { int visHeight = Tree_ContentHeight(tree); int totHeight = Tree_TotalHeight(tree); int yIncr = tree->yScrollIncrement; if (yIncr <= 0) yIncr = tree->itemHeight; if (yIncr <= 0) yIncr = 1; FormatResult(interp, "visHeight %d totHeight %d visHeight %% yIncr %d totHeight %% yIncr %d", visHeight, totHeight, visHeight % yIncr, totHeight % yIncr ); break; } } return TCL_OK; } /* *-------------------------------------------------------------- * * Tree_PreserveItems -- * * Increment tree->preserveItemRefCnt. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_PreserveItems( TreeCtrl *tree ) { tree->preserveItemRefCnt++; } /* *-------------------------------------------------------------- * * Tree_ReleaseItems -- * * Decrement tree->preserveItemRefCnt. If it reaches zero, * release the storage of items marked as deleted. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_ReleaseItems( TreeCtrl *tree ) { int i, count; TreeItem item; if (tree->preserveItemRefCnt == 0) panic("mismatched calls to Tree_PreserveItems/Tree_ReleaseItems"); if (--tree->preserveItemRefCnt > 0) return; count = TreeItemList_Count(&tree->preserveItemList); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&tree->preserveItemList, i); TreeItem_Release(tree, item); } TreeItemList_Free(&tree->preserveItemList); } /* *-------------------------------------------------------------- * * TextLayoutCmd -- * * This procedure is invoked to process the [textlayout] Tcl * command. The command is used by the library scripts to place * the text-edit Entry or Text widget. * * Results: * A standard Tcl result. * * Side effects: * None. * *-------------------------------------------------------------- */ /* textlayout $font $text -width pixels -wrap word|char -justify left|center|right -ignoretabs boolean -ignorenewlines boolean */ static int TextLayoutCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tk_Font tkfont; Tk_Window tkwin = Tk_MainWindow(interp); char *text; int flags = 0; Tk_Justify justify = TK_JUSTIFY_LEFT; Tk_TextLayout layout; int width = 0, height; int result = TCL_OK; int i; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "font text ?options ...?"); return TCL_ERROR; } tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[1]); if (tkfont == NULL) return TCL_ERROR; text = Tcl_GetString(objv[2]); for (i = 3; i < objc; i += 2) { static CONST char *optionNames[] = { "-ignoretabs", "-ignorenewlines", "-justify", "-width", (char *) NULL }; enum { OPT_IGNORETABS, OPT_IGNORENEWLINES, OPT_JUSTIFY, OPT_WIDTH }; int index; if (Tcl_GetIndexFromObj(interp, objv[i], optionNames, "option", 0, &index) != TCL_OK) { result = TCL_ERROR; goto done; } if (i + 1 == objc) { FormatResult(interp, "missing value for \"%s\" option", optionNames[index]); goto done; } switch (index) { case OPT_IGNORENEWLINES: { int v; if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &v) != TCL_OK) { result = TCL_ERROR; goto done; } if (v) flags |= TK_IGNORE_NEWLINES; else flags &= ~TK_IGNORE_NEWLINES; break; } case OPT_IGNORETABS: { int v; if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &v) != TCL_OK) { result = TCL_ERROR; goto done; } if (v) flags |= TK_IGNORE_TABS; else flags &= ~TK_IGNORE_TABS; break; } case OPT_JUSTIFY: { if (Tk_GetJustifyFromObj(interp, objv[i + 1], &justify) != TCL_OK) { result = TCL_ERROR; goto done; } break; } case OPT_WIDTH: { if (Tk_GetPixelsFromObj(interp, tkwin, objv[i + 1], &width) != TCL_OK) { result = TCL_ERROR; goto done; } break; } } } layout = Tk_ComputeTextLayout(tkfont, text, -1, width, justify, flags, &width, &height); FormatResult(interp, "%d %d", width, height); Tk_FreeTextLayout(layout); done: Tk_FreeFont(tkfont); return result; } /* *-------------------------------------------------------------- * * ImageTintCmd -- * * This procedure is invoked to process the [imagetint] Tcl * command. The command may be used to apply a highlight to an * existing photo image. It is used by the demos to produce a * selected version of an image. * * Results: * A standard Tcl result. * * Side effects: * A photo image is modified. * *-------------------------------------------------------------- */ static int ImageTintCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { char *imageName; Tk_PhotoHandle photoH; Tk_PhotoImageBlock photoBlock; XColor *xColor; unsigned char *pixelPtr, *photoPix; int x, y, alpha, imgW, imgH, pitch; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "imageName color alpha"); return TCL_ERROR; } imageName = Tcl_GetStringFromObj(objv[1], NULL); photoH = Tk_FindPhoto(interp, imageName); if (photoH == NULL) { Tcl_AppendResult(interp, "image \"", imageName, "\" doesn't exist or is not a photo image", (char *) NULL); return TCL_ERROR; } xColor = Tk_AllocColorFromObj(interp, Tk_MainWindow(interp), objv[2]); if (xColor == NULL) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[3], &alpha) != TCL_OK) return TCL_ERROR; if (alpha < 0) alpha = 0; if (alpha > 255) alpha = 255; Tk_PhotoGetImage(photoH, &photoBlock); photoPix = photoBlock.pixelPtr; imgW = photoBlock.width; imgH = photoBlock.height; pitch = photoBlock.pitch; pixelPtr = (unsigned char *) Tcl_Alloc(imgW * 4); photoBlock.pixelPtr = pixelPtr; photoBlock.width = imgW; photoBlock.height = 1; photoBlock.pitch = imgW * 4; photoBlock.pixelSize = 4; photoBlock.offset[0] = 0; photoBlock.offset[1] = 1; photoBlock.offset[2] = 2; photoBlock.offset[3] = 3; for (x = 0; x < imgW; x++) { pixelPtr[x*4 + 0] = UCHAR(((double) xColor->red / USHRT_MAX) * 255); pixelPtr[x*4 + 1] = UCHAR(((double) xColor->green / USHRT_MAX) * 255); pixelPtr[x*4 + 2] = UCHAR(((double) xColor->blue / USHRT_MAX) * 255); } for (y = 0; y < imgH; y++) { for (x = 0; x < imgW; x++) { if (photoPix[x * 4 + 3]) { pixelPtr[x * 4 + 3] = alpha; } else { pixelPtr[x * 4 + 3] = 0; } } TK_PHOTOPUTBLOCK(interp, photoH, &photoBlock, 0, y, imgW, 1, TK_PHOTO_COMPOSITE_OVERLAY); photoPix += pitch; } Tcl_Free((char *) photoBlock.pixelPtr); return TCL_OK; } /* *-------------------------------------------------------------- * * LoupeCmd -- * * This procedure is invoked to process the [loupe] Tcl * command. The command is used to perform a screen grab on the * root window and place a magnified version of the screen grab * into an existing photo image. The command is used to check those * dotted lines and make sure they line up properly. * * Results: * A standard Tcl result. * * Side effects: * A photo image is modified. * *-------------------------------------------------------------- */ static int LoupeCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tk_Window tkwin = Tk_MainWindow(interp); Display *display = Tk_Display(tkwin); int screenNum = Tk_ScreenNumber(tkwin); int displayW = DisplayWidth(display, screenNum); int displayH = DisplayHeight(display, screenNum); char *imageName; Tk_PhotoHandle photoH; Tk_PhotoImageBlock photoBlock; unsigned char *pixelPtr; int x, y, w, h, zoom; int grabX, grabY, grabW, grabH; int minx = 0, miny = 0; #ifdef WIN32 int xx, yy; HWND hwnd; HDC hdc; #elif defined(MAC_TCL) || defined(MAC_OSX_TK) #else Visual *visual = Tk_Visual(tkwin); Window rootWindow = RootWindow(display, screenNum); XImage *ximage; XColor *xcolors; unsigned long red_shift, green_shift, blue_shift; int i, ncolors; int separated = 0; #endif /* * x && y are points on screen to snap from * w && h are size of image to grab (default to image size) * zoom is the integer zoom factor to grab */ if ((objc != 4) && (objc != 6) && (objc != 7)) { Tcl_WrongNumArgs(interp, 1, objv, "imageName x y ?w h? ?zoom?"); return TCL_ERROR; } imageName = Tcl_GetStringFromObj(objv[1], NULL); photoH = Tk_FindPhoto(interp, imageName); if (photoH == NULL) { Tcl_AppendResult(interp, "image \"", imageName, "\" doesn't exist or is not a photo image", (char *) NULL); return TCL_ERROR; } if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { return TCL_ERROR; } if (objc >= 6) { if ((Tcl_GetIntFromObj(interp, objv[4], &w) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[5], &h) != TCL_OK)) { return TCL_ERROR; } } else { /* * Get dimensions from image */ Tk_PhotoGetSize(photoH, &w, &h); } if (objc == 7) { if (Tcl_GetIntFromObj(interp, objv[6], &zoom) != TCL_OK) { return TCL_ERROR; } } else { zoom = 1; } #ifdef WIN32 /* * Windows multiple monitors can have negative coords */ minx = GetSystemMetrics(SM_XVIRTUALSCREEN); miny = GetSystemMetrics(SM_YVIRTUALSCREEN); displayW = GetSystemMetrics(SM_CXVIRTUALSCREEN); displayH = GetSystemMetrics(SM_CYVIRTUALSCREEN); #elif defined(MAC_TCL) || defined(MAC_OSX_TK) /* * OS X multiple monitors can have negative coords * FIX: must be implemented * Probably with CGDisplayPixelsWide & CGDisplayPixelsHigh, * may need to iterate existing displays */ #else /* * Does X11 allow for negative screen coords? */ #endif grabX = x - (w / zoom / 2); grabY = y - (h / zoom / 2); grabW = w / zoom; grabH = h / zoom; if (grabW > displayW) grabW = displayW; if (grabH > displayH) grabH = displayH; if (grabX < minx) grabX = minx; if (grabY < miny) grabY = miny; if (grabX + grabW > displayW) grabX = displayW - grabW; if (grabY + grabH > displayH) grabY = displayH - grabH; if ((grabW <= 0) || (grabH <= 0)) { return TCL_OK; } #ifdef WIN32 hwnd = GetDesktopWindow(); hdc = GetWindowDC(hwnd); /* XImage -> Tk_Image */ pixelPtr = (unsigned char *) Tcl_Alloc(grabW * grabH * 4); memset(pixelPtr, 0, (grabW * grabH * 4)); photoBlock.pixelPtr = pixelPtr; photoBlock.width = grabW; photoBlock.height = grabH; photoBlock.pitch = grabW * 4; photoBlock.pixelSize = 4; photoBlock.offset[0] = 0; photoBlock.offset[1] = 1; photoBlock.offset[2] = 2; photoBlock.offset[3] = 3; /* * We could do a BitBlt for bulk copying, but then we'd have to * do screen size consistency checks and possibly pixel conversion. */ for (yy = 0; yy < grabH; yy++) { COLORREF pixel; unsigned long stepDest = yy * photoBlock.pitch; for (xx = 0; xx < grabW; xx++) { pixel = GetPixel(hdc, grabX + xx, grabY + yy); if (pixel == CLR_INVALID) { /* * Skip just this pixel, as others will be valid depending on * what corner we are in. */ continue; } pixelPtr[stepDest + xx * 4 + 0] = GetRValue(pixel); pixelPtr[stepDest + xx * 4 + 1] = GetGValue(pixel); pixelPtr[stepDest + xx * 4 + 2] = GetBValue(pixel); pixelPtr[stepDest + xx * 4 + 3] = 255; } } ReleaseDC(hwnd, hdc); #elif defined(MAC_TCL) || defined(MAC_OSX_TK) /* * Adapted from John Anon's ScreenController demo code. */ { int xx, yy; unsigned char *screenBytes; int bPerPixel, byPerRow, byPerPixel; // Gets all the screen info: CGDisplayHideCursor(kCGDirectMainDisplay); bPerPixel = CGDisplayBitsPerPixel(kCGDirectMainDisplay); byPerRow = CGDisplayBytesPerRow(kCGDirectMainDisplay); byPerPixel = bPerPixel / 8; screenBytes = (unsigned char *)CGDisplayBaseAddress(kCGDirectMainDisplay); pixelPtr = (unsigned char *) Tcl_Alloc(grabW * grabH * 4); memset(pixelPtr, 0, (grabW * grabH * 4)); photoBlock.pixelPtr = pixelPtr; photoBlock.width = grabW; photoBlock.height = grabH; photoBlock.pitch = grabW * 4; photoBlock.pixelSize = 4; photoBlock.offset[0] = 0; photoBlock.offset[1] = 1; photoBlock.offset[2] = 2; photoBlock.offset[3] = 3; for (yy = 0; yy < grabH; yy++) { unsigned long newPixel = 0; unsigned long stepSrc = (grabY + yy) * byPerRow; unsigned long stepDest = yy * photoBlock.pitch; for (xx = 0; xx < grabW; xx++) { if (bPerPixel == 16) { unsigned short thisPixel; thisPixel = *((unsigned short*)(screenBytes + stepSrc + ((grabX + xx) * byPerPixel))); #ifdef WORDS_BIGENDIAN /* Transform from 0xARGB (1555) to 0xR0G0B0A0 (4444) */ newPixel = (((thisPixel & 0x8000) >> 15) * 0xF8) | /* A */ ((thisPixel & 0x7C00) << 17) | /* R */ ((thisPixel & 0x03E0) << 14) | /* G */ ((thisPixel & 0x001F) << 11); /* B */ #else /* Transform from 0xARGB (1555) to 0xB0G0R0A0 (4444) */ newPixel = (((thisPixel & 0x8000) >> 15) * 0xF8) | /* A */ ((thisPixel & 0x7C00) << 11) | /* R */ ((thisPixel & 0x03E0) << 14) | /* G */ ((thisPixel & 0x001F) << 17); /* B */ #endif } else if (bPerPixel == 32) { unsigned long thisPixel; thisPixel = *((unsigned long*)(screenBytes + stepSrc + ((grabX + xx) * byPerPixel))); #ifdef WORDS_BIGENDIAN /* Transformation is from 0xAARRGGBB to 0xRRGGBBAA */ newPixel = ((thisPixel & 0xFF000000) >> 24) | ((thisPixel & 0x00FFFFFF) << 8); #else /* Transformation is from 0xAARRGGBB to 0xBBGGRRAA */ newPixel = (thisPixel & 0xFF00FF00) | ((thisPixel & 0x00FF0000) >> 16) | ((thisPixel & 0x000000FF) << 16); #endif } *((unsigned int *)(pixelPtr + stepDest + xx * 4)) = newPixel; } } CGDisplayShowCursor(kCGDirectMainDisplay); } #else ximage = XGetImage(display, rootWindow, grabX, grabY, grabW, grabH, AllPlanes, ZPixmap); if (ximage == NULL) { FormatResult(interp, "XGetImage() failed"); return TCL_ERROR; } /* See TkPostscriptImage */ ncolors = visual->map_entries; xcolors = (XColor *) ckalloc(sizeof(XColor) * ncolors); if ((visual->class == DirectColor) || (visual->class == TrueColor)) { separated = 1; red_shift = green_shift = blue_shift = 0; while ((0x0001 & (ximage->red_mask >> red_shift)) == 0) red_shift++; while ((0x0001 & (ximage->green_mask >> green_shift)) == 0) green_shift++; while ((0x0001 & (ximage->blue_mask >> blue_shift)) == 0) blue_shift++; for (i = 0; i < ncolors; i++) { xcolors[i].pixel = ((i << red_shift) & ximage->red_mask) | ((i << green_shift) & ximage->green_mask) | ((i << blue_shift) & ximage->blue_mask); } } else { for (i = 0; i < ncolors; i++) xcolors[i].pixel = i; } XQueryColors(display, Tk_Colormap(tkwin), xcolors, ncolors); /* XImage -> Tk_Image */ pixelPtr = (unsigned char *) Tcl_Alloc(ximage->width * ximage->height * 4); photoBlock.pixelPtr = pixelPtr; photoBlock.width = ximage->width; photoBlock.height = ximage->height; photoBlock.pitch = ximage->width * 4; photoBlock.pixelSize = 4; photoBlock.offset[0] = 0; photoBlock.offset[1] = 1; photoBlock.offset[2] = 2; photoBlock.offset[3] = 3; for (y = 0; y < ximage->height; y++) { for (x = 0; x < ximage->width; x++) { int r, g, b; unsigned long pixel; pixel = XGetPixel(ximage, x, y); if (separated) { r = (pixel & ximage->red_mask) >> red_shift; g = (pixel & ximage->green_mask) >> green_shift; b = (pixel & ximage->blue_mask) >> blue_shift; r = ((double) xcolors[r].red / USHRT_MAX) * 255; g = ((double) xcolors[g].green / USHRT_MAX) * 255; b = ((double) xcolors[b].blue / USHRT_MAX) * 255; } else { r = ((double) xcolors[pixel].red / USHRT_MAX) * 255; g = ((double) xcolors[pixel].green / USHRT_MAX) * 255; b = ((double) xcolors[pixel].blue / USHRT_MAX) * 255; } pixelPtr[y * photoBlock.pitch + x * 4 + 0] = r; pixelPtr[y * photoBlock.pitch + x * 4 + 1] = g; pixelPtr[y * photoBlock.pitch + x * 4 + 2] = b; pixelPtr[y * photoBlock.pitch + x * 4 + 3] = 255; } } #endif TK_PHOTOPUTZOOMEDBLOCK(interp, photoH, &photoBlock, 0, 0, w, h, zoom, zoom, 1, 1, TK_PHOTO_COMPOSITE_SET); Tcl_Free((char *) pixelPtr); #if !defined(WIN32) && !defined(MAC_TCL) && !defined(MAC_OSX_TK) ckfree((char *) xcolors); XDestroyImage(ximage); #endif return TCL_OK; } #ifndef USE_TTK /* *-------------------------------------------------------------- * * RecomputeWidgets -- * * This procedure is called when the system theme changes on platforms * that support theming. The worldChangedProc of all treectrl widgets * is called to relayout and redisplay the widgets. * * Taken from tkFont.c. * * Results: * None. * * Side effects: * All treectrl widgets will be redisplayed at idle time. * *-------------------------------------------------------------- */ static void RecomputeWidgets( TkWindow *winPtr /* Window info. */ ) { Tk_ClassWorldChangedProc *proc; /* Clomp! Stomp! All over the internals */ proc = Tk_GetClassProc(winPtr->classProcsPtr, worldChangedProc); if (proc == TreeWorldChanged) { TreeTheme_ThemeChanged((TreeCtrl *) winPtr->instanceData); TreeWorldChanged(winPtr->instanceData); } for (winPtr = winPtr->childList; winPtr != NULL; winPtr = winPtr->nextPtr) { RecomputeWidgets(winPtr); } } /* *-------------------------------------------------------------- * * Tree_TheWorldHasChanged -- * * This procedure is called when the system theme changes on platforms * that support theming. The worldChangedProc of all treectrl widgets * is called to relayout and redisplay the widgets. * * Results: * None. * * Side effects: * All treectrl widgets will be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_TheWorldHasChanged( Tcl_Interp *interp /* Current interpreter. */ ) { /* Could send a <> event to every window like Tile does. */ /* Could keep a list of treectrl widgets. */ TkWindow *winPtr = (TkWindow *) Tk_MainWindow(interp); RecomputeWidgets(winPtr); } #endif /* !USE_TTK */ /* * In order to find treectrl.tcl during initialization, the following script * is invoked. */ static char initScript[] = "if {![llength [info proc ::TreeCtrl::Init]]} {\n\ namespace eval ::TreeCtrl {}\n\ proc ::TreeCtrl::Init {} {\n\ global treectrl_library\n\ tcl_findLibrary treectrl " PACKAGE_PATCHLEVEL " " PACKAGE_PATCHLEVEL " treectrl.tcl TREECTRL_LIBRARY treectrl_library\n\ }\n\ }\n\ ::TreeCtrl::Init"; /* *-------------------------------------------------------------- * * Treectrl_Init -- * * This procedure initializes the TreeCtrl package and related * commands. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated. New Tcl commands are created. * *-------------------------------------------------------------- */ DLLEXPORT int Treectrl_Init( Tcl_Interp *interp /* Interpreter the package is loading into. */ ) { #ifdef USE_TTK static CONST char *tcl_version = "8.5"; #else static CONST char *tcl_version = "8.4"; #endif #ifdef USE_TCL_STUBS if (Tcl_InitStubs(interp, tcl_version, 0) == NULL) { return TCL_ERROR; } #endif #ifdef USE_TK_STUBS #if (TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION < 5) if (Tk_InitStubs(interp, (char*)tcl_version, 0) == NULL) { #else if (Tk_InitStubs(interp, tcl_version, 0) == NULL) { #endif return TCL_ERROR; } #endif dbwin_add_interp(interp); PerStateCO_Init(optionSpecs, "-buttonbitmap", &pstBitmap, TreeStateFromObj); PerStateCO_Init(optionSpecs, "-buttonimage", &pstImage, TreeStateFromObj); if (TreeElement_Init(interp) != TCL_OK) { return TCL_ERROR; } /* We don't care if this fails. */ (void) TreeTheme_InitInterp(interp); if (TreeColumn_InitInterp(interp) != TCL_OK) return TCL_ERROR; /* Hack for editing a text Element. */ Tcl_CreateObjCommand(interp, "textlayout", TextLayoutCmd, NULL, NULL); /* Hack for colorizing an image (like Win98 explorer). */ Tcl_CreateObjCommand(interp, "imagetint", ImageTintCmd, NULL, NULL); /* Screen magnifier to check those dotted lines. */ Tcl_CreateObjCommand(interp, "loupe", LoupeCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "treectrl", TreeObjCmd, NULL, NULL); if (Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_PATCHLEVEL) != TCL_OK) { return TCL_ERROR; } return Tcl_EvalEx(interp, initScript, -1, TCL_EVAL_GLOBAL); } /* *-------------------------------------------------------------- * * Treectrl_SafeInit -- * * This procedure initializes the TreeCtrl package and related * commands. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated. New Tcl commands are created. * *-------------------------------------------------------------- */ DLLEXPORT int Treectrl_SafeInit( Tcl_Interp *interp /* Interpreter the package is loading into. */ ) { return Treectrl_Init(interp); } tktreectrl-2.2.8/generic/tkTreeCtrl.h0000700000175600010010000013535111041155074015762 0ustar TimNone/* * tkTreeCtrl.h -- * * This module is the header for treectrl widgets for the Tk toolkit. * * Copyright (c) 2002-2008 Tim Baker * Copyright (c) 2002-2003 Christian Krone * Copyright (c) 2003 ActiveState Corporation * * RCS: @(#) $Id: tkTreeCtrl.h,v 1.95 2008/07/21 18:49:32 treectrl Exp $ */ #include "tkPort.h" #include "default.h" #include "tclInt.h" #include "tkInt.h" #include "qebind.h" #define dbwin TreeCtrl_dbwin #define dbwin_add_interp TreeCtrl_dbwin_add_interp extern void dbwin(char *fmt, ...); extern void dbwin_add_interp(Tcl_Interp *interp); #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifdef WIN32 #define vsnprintf _vsnprintf #endif #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif #define SELECTION_VISIBLE #define ALLOC_HAX #define DEPRECATED typedef struct TreeCtrl TreeCtrl; typedef struct TreeColumn_ *TreeColumn; typedef struct TreeColumnDInfo_ *TreeColumnDInfo; typedef struct TreeDInfo_ *TreeDInfo; typedef struct TreeDragImage_ *TreeDragImage; typedef struct TreeItem_ *TreeItem; typedef struct TreeItemColumn_ *TreeItemColumn; typedef struct TreeItemDInfo_ *TreeItemDInfo; typedef struct TreeMarquee_ *TreeMarquee; typedef struct TreeItemRInfo_ *TreeItemRInfo; typedef struct TreeStyle_ *TreeStyle; typedef struct TreeElement_ *TreeElement; typedef struct TreeThemeData_ *TreeThemeData; /*****/ typedef struct PerStateInfo PerStateInfo; typedef struct PerStateData PerStateData; typedef struct PerStateType PerStateType; /* There is one of these for each XColor, Tk_Font, Tk_Image etc */ struct PerStateData { int stateOff; int stateOn; /* Type-specific fields go here */ }; struct PerStateInfo { #ifdef TREECTRL_DEBUG PerStateType *type; #endif Tcl_Obj *obj; int count; PerStateData *data; }; typedef int (*PerStateType_FromObjProc)(TreeCtrl *, Tcl_Obj *, PerStateData *); typedef void (*PerStateType_FreeProc)(TreeCtrl *, PerStateData *); struct PerStateType { CONST char *name; int size; PerStateType_FromObjProc fromObjProc; PerStateType_FreeProc freeProc; }; /*****/ typedef struct { Drawable drawable; int width; int height; } TreeDrawable; typedef struct { int x, y; int width, height; } TreeRectangle; typedef struct GCCache GCCache; struct GCCache { unsigned long mask; XGCValues gcValues; GC gc; GCCache *next; }; /* * A TreePtrList is used for dynamically-growing lists of ClientData pointers. * A TreePtrList is NULL-terminated. * Based on Tcl_DString code. */ #define TIL_STATIC_SPACE 128 typedef struct TreePtrList TreePtrList; typedef TreePtrList TreeItemList; typedef TreePtrList TreeColumnList; struct TreePtrList { #ifdef TREECTRL_DEBUG char magic[4]; #endif TreeCtrl *tree; ClientData *pointers; /* NULL-terminated list of pointers. */ int count; /* Number of items. */ int space; /* Number of slots pointed to by pointers[]. */ ClientData pointerSpace[TIL_STATIC_SPACE]; /* Space to use in common case * where the list is small. */ }; enum { LEFT, TOP, RIGHT, BOTTOM }; struct TreeCtrlDebug { Tk_OptionTable optionTable; int enable; /* Turn all debugging on/off */ int data; /* Debug data structures */ int display; /* Debug display routines */ int span; /* Debug column spanning */ int textLayout; /* Debug text layout */ int displayDelay; /* Delay between copy/draw operations */ XColor *eraseColor; /* Erase "invalidated" areas */ GC gcErase; /* for eraseColor */ XColor *drawColor; /* Erase about-to-be-drawn areas */ GC gcDraw; /* for eraseColor */ }; struct TreeCtrlColumnDrag { Tk_OptionTable optionTable; int enable; /* -enable */ TreeColumn column; /* -imagecolumn */ Tcl_Obj *offsetObj; /* -imageoffset */ int offset; /* -imageoffset */ XColor *color; /* -imagecolor */ int alpha; /* -imagealpha */ TreeColumn indColumn; /* -indicatorcolumn */ XColor *indColor; /* -indicatorcolor */ int indSide; /* -indicatorside */ }; struct TreeCtrl { /* Standard stuff */ Tk_Window tkwin; Display *display; Tcl_Interp *interp; Tcl_Command widgetCmd; Tk_OptionTable optionTable; /* Configuration options */ Tcl_Obj *fgObj; /* -foreground */ XColor *fgColorPtr; /* -foreground */ Tcl_Obj *borderWidthObj; /* -borderwidth */ int borderWidth; /* -borderwidth */ Tk_3DBorder border; /* -background */ Tk_Cursor cursor; /* Current cursor for window, or None. */ int relief; /* -relief */ Tcl_Obj *highlightWidthObj; /* -highlightthickness */ int highlightWidth; /* -highlightthickness */ XColor *highlightBgColorPtr; /* -highlightbackground */ XColor *highlightColorPtr; /* -highlightcolor */ char *xScrollCmd; /* -xscrollcommand */ char *yScrollCmd; /* -yscrollcommand */ Tcl_Obj *xScrollDelay; /* -xscrolldelay: used by scripts */ Tcl_Obj *yScrollDelay; /* -yscrolldelay: used by scripts */ int xScrollIncrement; /* -xscrollincrement */ int yScrollIncrement; /* -yscrollincrement */ Tcl_Obj *scrollMargin; /* -scrollmargin: used by scripts */ char *takeFocus; /* -takfocus */ Tcl_Obj *fontObj; /* -font */ Tk_Font tkfont; /* -font */ int showButtons; /* boolean: Draw expand/collapse buttons */ int showLines; /* boolean: Draw lines connecting parent to * child */ int showRootLines; /* boolean: Draw lines connecting children * of the root item */ int showRoot; /* boolean: Draw the unique root item */ int showRootButton; /* boolean: Draw expand/collapse button for * root item */ int showRootChildButtons; /* boolean: Draw expand/collapse buttons for * children of the root item */ int showHeader; /* boolean: show column titles */ Tcl_Obj *indentObj; /* pixels: offset of child relative to * parent */ int indent; /* pixels: offset of child relative to * parent */ char *selectMode; /* -selectmode: used by scripts only */ Tcl_Obj *itemHeightObj; /* -itemheight: Fixed height for all items (unless overridden) */ int itemHeight; /* -itemheight */ Tcl_Obj *minItemHeightObj; /* -minitemheight: Minimum height for all items */ int minItemHeight; /* -minitemheight */ Tcl_Obj *itemWidthObj; /* -itemwidth */ int itemWidth; /* -itemwidth */ int itemWidthEqual; /* -itemwidthequal */ Tcl_Obj *itemWidMultObj; /* -itemwidthmultiple */ int itemWidMult; /* -itemwidthmultiple */ Tcl_Obj *widthObj; /* -width */ int width; /* -width */ Tcl_Obj *heightObj; /* -height */ int height; /* -height */ TreeColumn columnTree; /* column where buttons/lines are drawn */ #define DOUBLEBUFFER_NONE 0 #define DOUBLEBUFFER_ITEM 1 #define DOUBLEBUFFER_WINDOW 2 int doubleBuffer; /* -doublebuffer */ XColor *buttonColor; /* -buttoncolor */ Tcl_Obj *buttonSizeObj; /* -buttonSize */ int buttonSize; /* -buttonsize */ Tcl_Obj *buttonThicknessObj;/* -buttonthickness */ int buttonThickness; /* -buttonthickness */ XColor *lineColor; /* -linecolor */ Tcl_Obj *lineThicknessObj; /* -linethickness */ int lineThickness; /* -linethickness */ #define LINE_STYLE_DOT 0 #define LINE_STYLE_SOLID 1 int lineStyle; /* -linestyle */ int vertical; /* -orient */ Tcl_Obj *wrapObj; /* -wrap */ PerStateInfo buttonImage; /* -buttonimage */ PerStateInfo buttonBitmap; /* -buttonbitmap */ char *backgroundImageString; /* -backgroundimage */ int useIndent; /* MAX of open/closed button width and * indent */ #define BG_MODE_COLUMN 0 #define BG_MODE_ORDER 1 #define BG_MODE_ORDERVIS 2 #define BG_MODE_ROW 3 #ifdef DEPRECATED #define BG_MODE_INDEX 4 /* compatibility */ #define BG_MODE_VISINDEX 5 /* compatibility */ #endif /* DEPRECATED */ int backgroundMode; /* -backgroundmode */ int columnResizeMode; /* -columnresizemode */ int *itemPadX; /* -itempadx */ Tcl_Obj *itemPadXObj; /* -itempadx */ int *itemPadY; /* -itempady */ Tcl_Obj *itemPadYObj; /* -itempady */ struct TreeCtrlDebug debug; struct TreeCtrlColumnDrag columnDrag; /* Other stuff */ int gotFocus; /* flag */ int deleted; /* flag */ int updateIndex; /* flag */ int isActive; /* flag: mac & win "active" toplevel */ struct { int left; int top; int right; int bottom; } inset; /* borderWidth + highlightWidth */ int xOrigin; /* offset from content x=0 to window x=0 */ int yOrigin; /* offset from content y=0 to window y=0 */ GC copyGC; GC textGC; GC buttonGC; GC lineGC; Tk_Image backgroundImage; /* -backgroundimage */ int useTheme; /* -usetheme */ char *itemPrefix; /* -itemprefix */ char *columnPrefix; /* -columnprefix */ int prevWidth; int prevHeight; int drawableXOrigin; int drawableYOrigin; TreeColumn columns; /* List of columns */ TreeColumn columnLast; /* Last in list of columns */ TreeColumn columnTail; /* Last infinitely-wide column */ TreeColumn columnVis; /* First visible column */ int columnCount; /* Number of columns */ int columnCountVis; /* Number of visible columns */ int headerHeight; /* Height of column titles */ int widthOfColumns; /* Sum of column widths */ int columnTreeLeft; /* left of column where buttons/lines are * drawn */ int columnTreeVis; /* TRUE if columnTree is visible */ int columnBgCnt; /* Max -itembackground colors */ #define COLUMN_LOCK_LEFT 0 #define COLUMN_LOCK_NONE 1 #define COLUMN_LOCK_RIGHT 2 TreeColumn columnLockLeft; /* First left-locked column */ TreeColumn columnLockNone; /* First unlocked column */ TreeColumn columnLockRight; /* First right-locked column */ int widthOfColumnsLeft; /* Sum of left-locked column widths */ int widthOfColumnsRight; /* Sum of right-locked column widths */ int columnCountVisLeft; /* Number of visible left-locked columns */ int columnCountVisRight; /* Number of visible right-locked columns */ #define UNIFORM_GROUP #ifdef UNIFORM_GROUP Tcl_HashTable uniformGroupHash; /* -uniform -> UniformGroup */ #endif TreeItem root; TreeItem activeItem; TreeItem anchorItem; int nextItemId; int nextColumnId; Tcl_HashTable itemHash; /* TreeItem.id -> TreeItem */ Tcl_HashTable itemSpansHash; /* TreeItem -> nothing */ Tcl_HashTable elementHash; /* Element.name -> Element */ Tcl_HashTable styleHash; /* Style.name -> Style */ Tcl_HashTable imageNameHash; /* image name -> TreeImageRef */ Tcl_HashTable imageTokenHash; /* Tk_Image -> TreeImageRef */ int depth; /* max depth of items under root */ int itemCount; /* Total number of items */ int itemVisCount; /* Total number of ReallyVisible() items */ QE_BindingTable bindingTable; TreeDragImage dragImage; TreeMarquee marquee; TreeDInfo dInfo; int selectCount; /* Number of selected items */ Tcl_HashTable selection; /* Selected items */ #define TREE_WRAP_NONE 0 #define TREE_WRAP_ITEMS 1 #define TREE_WRAP_PIXELS 2 #define TREE_WRAP_WINDOW 3 int wrapMode; /* TREE_WRAP_xxx */ int wrapArg; /* Number of items, number of pixels */ int totalWidth; /* Max/Sum of all TreeRanges */ int totalHeight; /* Max/Sum of all TreeRanges */ struct { Tcl_Obj *xObj; int x; /* Window coords */ int sx; /* Window coords */ int onScreen; } columnProxy; char *stateNames[32]; /* Names of static and dynamic item states */ int scanX; /* [scan mark] and [scan dragto] */ int scanY; int scanXOrigin; int scanYOrigin; Tk_OptionTable styleOptionTable; #ifdef DEPRECATED struct { Tcl_Obj *stylesObj; TreeStyle *styles; int numStyles; } defaultStyle; #endif /* DEPRECATED */ Tk_OptionTable itemOptionTable; int itemPrefixLen; /* -itemprefix */ int columnPrefixLen; /* -columnprefix */ #ifdef ALLOC_HAX ClientData allocData; #endif int preserveItemRefCnt; /* Ref count so items-in-use aren't freed. */ TreeItemList preserveItemList; /* List of items to be deleted when * preserveItemRefCnt==0. */ struct { Tcl_Obj *yObj; int y; /* Window coords */ int sy; /* Window coords */ int onScreen; } rowProxy; char *optionHax[64]; /* Used by OptionHax_xxx */ int optionHaxCnt; /* Used by OptionHax_xxx */ TreeThemeData themeData; GCCache *gcCache; /* Graphics contexts for elements. */ TkRegion regionStack[8]; /* Temp region stack. */ int regionStackLen; /* Number of unused regions in regionStack. */ int itemTagExpr; /* Enable/disable operators in item tags */ int columnTagExpr; /* Enable/disable operators in column tags */ }; #define TREE_CONF_FONT 0x0001 #define TREE_CONF_ITEMSIZE 0x0002 #define TREE_CONF_INDENT 0x0004 #define TREE_CONF_WRAP 0x0008 #define TREE_CONF_BUTIMG 0x0010 #define TREE_CONF_BUTBMP 0x0020 #define TREE_CONF_BORDERS 0x0040 /* xxx */ #define TREE_CONF_RELAYOUT 0x0100 #define TREE_CONF_REDISPLAY 0x0200 #define TREE_CONF_FG 0x0400 #define TREE_CONF_PROXY 0x0800 #define TREE_CONF_BUTTON 0x1000 #define TREE_CONF_LINE 0x2000 #define TREE_CONF_DEFSTYLE 0x4000 #define TREE_CONF_BG_IMAGE 0x8000 #define TREE_CONF_THEME 0x00010000 extern void Tree_AddItem(TreeCtrl *tree, TreeItem item); extern void Tree_RemoveItem(TreeCtrl *tree, TreeItem item); extern Tk_Image Tree_GetImage(TreeCtrl *tree, char *imageName); extern void Tree_FreeImage(TreeCtrl *tree, Tk_Image image); extern void Tree_UpdateScrollbarX(TreeCtrl *tree); extern void Tree_UpdateScrollbarY(TreeCtrl *tree); extern void Tree_AddToSelection(TreeCtrl *tree, TreeItem item); extern void Tree_RemoveFromSelection(TreeCtrl *tree, TreeItem item); extern void Tree_PreserveItems(TreeCtrl *tree); extern void Tree_ReleaseItems(TreeCtrl *tree); #define STATE_OP_ON 0 #define STATE_OP_OFF 1 #define STATE_OP_TOGGLE 2 #define SFO_NOT_OFF 0x0001 #define SFO_NOT_TOGGLE 0x0002 #define SFO_NOT_STATIC 0x0004 extern int Tree_StateFromObj(TreeCtrl *tree, Tcl_Obj *obj, int states[3], int *indexPtr, int flags); extern int Tree_StateFromListObj(TreeCtrl *tree, Tcl_Obj *obj, int states[3], int flags); #define Tree_BorderLeft(tree) \ tree->inset.left #define Tree_BorderTop(tree) \ tree->inset.top #define Tree_BorderRight(tree) \ (Tk_Width(tree->tkwin) - tree->inset.right) #define Tree_BorderBottom(tree) \ (Tk_Height(tree->tkwin) - tree->inset.bottom) #define Tree_HeaderLeft(tree) \ Tree_BorderLeft(tree) #define Tree_HeaderTop(tree) \ Tree_BorderTop(tree) #define Tree_HeaderRight(tree) \ Tree_BorderRight(tree) #define Tree_HeaderBottom(tree) \ (Tree_BorderTop(tree) + Tree_HeaderHeight(tree)) #define Tree_HeaderWidth(tree) \ (Tree_HeaderRight(tree) - Tree_HeaderLeft(tree)) #define Tree_ContentLeft(tree) \ (Tree_BorderLeft(tree) + Tree_WidthOfLeftColumns(tree)) #define Tree_ContentTop(tree) \ (Tree_BorderTop(tree) + Tree_HeaderHeight(tree)) #define Tree_ContentRight(tree) \ (Tree_BorderRight(tree) - Tree_WidthOfRightColumns(tree)) #define Tree_ContentBottom(tree) \ Tree_BorderBottom(tree) #define Tree_ContentWidth(tree) \ (Tree_ContentRight(tree) - Tree_ContentLeft(tree)) #define Tree_ContentHeight(tree) \ (Tree_ContentBottom(tree) - Tree_ContentTop(tree)) /* tkTreeItem.c */ #define ITEM_ALL ((TreeItem) -1) #define IFO_NOT_MANY 0x0001 /* ItemFromObj flag: > 1 item is not ok */ #define IFO_NOT_NULL 0x0002 /* ItemFromObj flag: can't be NULL */ #define IFO_NOT_ROOT 0x0004 /* ItemFromObj flag: "root" is forbidden */ #define IFO_NOT_ORPHAN 0x0008 /* ItemFromObj flag: item must have a parent */ #define IFO_LIST_ALL 0x0010 /* ItemFromObj flag: return "all" as list */ extern int TreeItemList_FromObj(TreeCtrl *tree, Tcl_Obj *objPtr, TreeItemList *items, int flags); extern int TreeItem_FromObj(TreeCtrl *tree, Tcl_Obj *objPtr, TreeItem *itemPtr, int flags); typedef struct ItemForEach ItemForEach; struct ItemForEach { TreeCtrl *tree; int error; int all; Tcl_HashSearch search; TreeItem last; TreeItem item; TreeItemList *items; int index; }; extern TreeItem TreeItemForEach_Start(TreeItemList *items, TreeItemList *item2s, ItemForEach *iter); extern TreeItem TreeItemForEach_Next(ItemForEach *iter); #define ITEM_FOR_EACH(item, items, item2s, iter) \ for (item = TreeItemForEach_Start(items, item2s, iter); \ item != NULL; \ item = TreeItemForEach_Next(iter)) #define FormatResult TreeCtrl_FormatResult extern void FormatResult(Tcl_Interp *interp, char *fmt, ...); #define DStringAppendf TreeCtrl_DStringAppendf extern void DStringAppendf(Tcl_DString *dString, char *fmt, ...); extern void Tree_Debug(TreeCtrl *tree); extern int TreeItem_Init(TreeCtrl *tree); extern int TreeItem_Debug(TreeCtrl *tree, TreeItem item); extern void TreeItem_OpenClose(TreeCtrl *tree, TreeItem item, int mode); extern void TreeItem_Delete(TreeCtrl *tree, TreeItem item); extern int TreeItem_Deleted(TreeCtrl *tree, TreeItem item); #define STATE_OPEN 0x0001 #define STATE_SELECTED 0x0002 #define STATE_ENABLED 0x0004 #define STATE_ACTIVE 0x0008 #define STATE_FOCUS 0x0010 #define STATE_USER 6 /* first user bit */ extern int TreeItem_GetState(TreeCtrl *tree, TreeItem item_); #define CS_DISPLAY 0x01 #define CS_LAYOUT 0x02 extern int TreeItem_ChangeState(TreeCtrl *tree, TreeItem item_, int stateOff, int stateOn); extern void TreeItem_UndefineState(TreeCtrl *tree, TreeItem item_, int state); extern int TreeItem_HasButton(TreeCtrl *tree, TreeItem item_); extern int TreeItem_GetDepth(TreeCtrl *tree, TreeItem item_); extern int TreeItem_GetID(TreeCtrl *tree, TreeItem item_); extern int TreeItem_SetID(TreeCtrl *tree, TreeItem item_, int id); extern int TreeItem_GetEnabled(TreeCtrl *tree, TreeItem item_); extern int TreeItem_GetSelected(TreeCtrl *tree, TreeItem item_); extern TreeItem TreeItem_GetParent(TreeCtrl *tree, TreeItem item); extern TreeItem TreeItem_GetNextSibling(TreeCtrl *tree, TreeItem item); extern TreeItem TreeItem_NextSiblingVisible(TreeCtrl *tree, TreeItem item); extern void TreeItem_SetDInfo(TreeCtrl *tree, TreeItem item, TreeItemDInfo dInfo); extern TreeItemDInfo TreeItem_GetDInfo(TreeCtrl *tree, TreeItem item); extern void TreeItem_SetRInfo(TreeCtrl *tree, TreeItem item, TreeItemRInfo rInfo); extern TreeItemRInfo TreeItem_GetRInfo(TreeCtrl *tree, TreeItem item); extern void TreeItem_AppendChild(TreeCtrl *tree, TreeItem self, TreeItem child); extern void TreeItem_RemoveFromParent(TreeCtrl *tree, TreeItem self); extern int TreeItem_FirstAndLast(TreeCtrl *tree, TreeItem *first, TreeItem *last); extern void TreeItem_ListDescendants(TreeCtrl *tree, TreeItem item_, TreeItemList *items); extern int TreeItem_Height(TreeCtrl *tree, TreeItem self); extern int TreeItem_TotalHeight(TreeCtrl *tree, TreeItem self); extern void TreeItem_InvalidateHeight(TreeCtrl *tree, TreeItem self); extern void TreeItem_SpansInvalidate(TreeCtrl *tree, TreeItem item_); extern int *TreeItem_GetSpans(TreeCtrl *tree, TreeItem item_); extern void TreeItem_Draw(TreeCtrl *tree, TreeItem self, int lock, int x, int y, int width, int height, TreeDrawable td, int minX, int maxX, int index); extern void TreeItem_DrawLines(TreeCtrl *tree, TreeItem self, int x, int y, int width, int height, TreeDrawable td); extern void TreeItem_DrawButton(TreeCtrl *tree, TreeItem self, int x, int y, int width, int height, TreeDrawable td); extern int TreeItem_ReallyVisible(TreeCtrl *tree, TreeItem self); extern void TreeItem_FreeResources(TreeCtrl *tree, TreeItem self); extern void TreeItem_Release(TreeCtrl *tree, TreeItem item); extern TreeItem TreeItem_RootAncestor(TreeCtrl *tree, TreeItem item_); extern int TreeItem_IsAncestor(TreeCtrl *tree, TreeItem item1, TreeItem item2); extern Tcl_Obj *TreeItem_ToObj(TreeCtrl *tree, TreeItem item); extern void TreeItem_ToIndex(TreeCtrl *tree, TreeItem item, int *absolute, int *visible); extern TreeItem TreeItem_Next(TreeCtrl *tree, TreeItem item); extern TreeItem TreeItem_NextVisible(TreeCtrl *tree, TreeItem item); extern TreeItem TreeItem_Prev(TreeCtrl *tree, TreeItem item); extern TreeItem TreeItem_PrevVisible(TreeCtrl *tree, TreeItem item); extern void TreeItem_Identify(TreeCtrl *tree, TreeItem item_, int lock, int x, int y, char *buf); extern void TreeItem_Identify2(TreeCtrl *tree, TreeItem item_, int x1, int y1, int x2, int y2, Tcl_Obj *listObj); extern int TreeItem_GetRects(TreeCtrl *tree, TreeItem item_, TreeColumn treeColumn, int objc, Tcl_Obj *CONST objv[], TreeRectangle rects[]); extern int TreeItem_Indent(TreeCtrl *tree, TreeItem item_); extern void Tree_UpdateItemIndex(TreeCtrl *tree); extern void Tree_DeselectHidden(TreeCtrl *tree); extern int TreeItemCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); extern void TreeItem_UpdateWindowPositions(TreeCtrl *tree, TreeItem item_, int lock, int x, int y, int width, int height); extern void TreeItem_OnScreen(TreeCtrl *tree, TreeItem item_, int onScreen); extern TreeItemColumn TreeItem_GetFirstColumn(TreeCtrl *tree, TreeItem item); extern TreeItemColumn TreeItemColumn_GetNext(TreeCtrl *tree, TreeItemColumn column); extern void TreeItemColumn_InvalidateSize(TreeCtrl *tree, TreeItemColumn column); extern TreeStyle TreeItemColumn_GetStyle(TreeCtrl *tree, TreeItemColumn column); extern int TreeItemColumn_Index(TreeCtrl *tree, TreeItem item_, TreeItemColumn column_); extern void TreeItemColumn_ForgetStyle(TreeCtrl *tree, TreeItemColumn column_); extern int TreeItemColumn_NeededWidth(TreeCtrl *tree, TreeItem item_, TreeItemColumn column_); extern TreeItemColumn TreeItem_FindColumn(TreeCtrl *tree, TreeItem item, int columnIndex); extern int TreeItem_ColumnFromObj(TreeCtrl *tree, TreeItem item, Tcl_Obj *obj, TreeItemColumn *columnPtr, int *indexPtr); extern void TreeItem_RemoveColumns(TreeCtrl *tree, TreeItem item_, int first, int last); extern void TreeItem_RemoveAllColumns(TreeCtrl *tree, TreeItem item_); extern void TreeItem_MoveColumn(TreeCtrl *tree, TreeItem item_, int columnIndex, int beforeIndex); /* tkTreeElem.c */ extern int TreeElement_Init(Tcl_Interp *interp); extern int TreeStateFromObj(TreeCtrl *tree, Tcl_Obj *obj, int *stateOff, int *stateOn); extern int StringTableCO_Init(Tk_OptionSpec *optionTable, CONST char *optionName, CONST char **tablePtr); typedef struct StyleDrawArgs StyleDrawArgs; struct StyleDrawArgs { TreeCtrl *tree; TreeStyle style; int indent; int x; int y; int width; int height; TreeDrawable td; int state; /* STATE_xxx */ Tk_Justify justify; int bounds[4]; }; /* tkTreeStyle.c */ extern int TreeStyle_Init(TreeCtrl *tree); extern int TreeStyle_NeededWidth(TreeCtrl *tree, TreeStyle style_, int state); extern int TreeStyle_NeededHeight(TreeCtrl *tree, TreeStyle style_, int state); extern int TreeStyle_UseHeight(StyleDrawArgs *drawArgs); extern void TreeStyle_Draw(StyleDrawArgs *args); extern void TreeStyle_FreeResources(TreeCtrl *tree, TreeStyle style_); extern void TreeStyle_Free(TreeCtrl *tree); extern int TreeElement_FromObj(TreeCtrl *tree, Tcl_Obj *obj, TreeElement *elemPtr); extern int TreeElement_IsType(TreeCtrl *tree, TreeElement elem, CONST char *type); extern int TreeStyle_FromObj(TreeCtrl *tree, Tcl_Obj *obj, TreeStyle *stylePtr); extern Tcl_Obj *TreeStyle_ToObj(TreeStyle style_); extern Tcl_Obj *TreeStyle_GetImage(TreeCtrl *tree, TreeStyle style_); extern Tcl_Obj *TreeStyle_GetText(TreeCtrl *tree, TreeStyle style_); extern int TreeStyle_SetImage(TreeCtrl *tree, TreeItem item, TreeItemColumn column, TreeStyle style_, Tcl_Obj *textObj); extern int TreeStyle_SetText(TreeCtrl *tree, TreeItem item, TreeItemColumn column, TreeStyle style_, Tcl_Obj *textObj); extern int TreeStyle_FindElement(TreeCtrl *tree, TreeStyle style_, TreeElement elem, int *index); extern TreeStyle TreeStyle_NewInstance(TreeCtrl *tree, TreeStyle master); extern int TreeStyle_ElementActual(TreeCtrl *tree, TreeStyle style_, int state, Tcl_Obj *elemObj, Tcl_Obj *obj); extern int TreeStyle_ElementCget(TreeCtrl *tree, TreeItem item, TreeItemColumn column, TreeStyle style_, Tcl_Obj *elemObj, Tcl_Obj *obj); extern int TreeStyle_ElementConfigure(TreeCtrl *tree, TreeItem item, TreeItemColumn column, TreeStyle style_, Tcl_Obj *elemObj, int objc, Tcl_Obj **objv, int *eMask); extern void TreeStyle_ListElements(TreeCtrl *tree, TreeStyle style_); extern TreeStyle TreeStyle_GetMaster(TreeCtrl *tree, TreeStyle style_); extern char *TreeStyle_Identify(StyleDrawArgs *drawArgs, int x, int y); extern void TreeStyle_Identify2(StyleDrawArgs *drawArgs, int x1, int y1, int x2, int y2, Tcl_Obj *listObj); extern int TreeStyle_Remap(TreeCtrl *tree, TreeStyle styleFrom_, TreeStyle styleTo_, int objc, Tcl_Obj *CONST objv[]); extern void TreeStyle_TreeChanged(TreeCtrl *tree, int flagT); #define SORT_ASCII 0 #define SORT_DICT 1 #define SORT_DOUBLE 2 #define SORT_LONG 3 #define SORT_COMMAND 4 extern int TreeStyle_GetSortData(TreeCtrl *tree, TreeStyle style_, int elemIndex, int type, long *lv, double *dv, char **sv); #if 0 extern int TreeStyle_ValidateElements(TreeCtrl *tree, TreeStyle style_, int objc, Tcl_Obj *CONST objv[]); #endif extern int TreeStyle_GetElemRects(StyleDrawArgs *drawArgs, int objc, Tcl_Obj *CONST objv[], TreeRectangle rects[]); extern int TreeElementCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); extern int TreeStyleCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); extern int TreeStyle_ChangeState(TreeCtrl *tree, TreeStyle style_, int state1, int state2); extern void Tree_UndefineState(TreeCtrl *tree, int state); extern int TreeStyle_NumElements(TreeCtrl *tree, TreeStyle style_); extern void TreeStyle_UpdateWindowPositions(StyleDrawArgs *drawArgs); extern void TreeStyle_OnScreen(TreeCtrl *tree, TreeStyle style_, int onScreen); extern int Tree_ButtonMaxWidth(TreeCtrl *tree); extern int Tree_ButtonHeight(TreeCtrl *tree, int state); /* tkTreeNotify.c */ extern int TreeNotify_Init(TreeCtrl *tree); extern void TreeNotify_OpenClose(TreeCtrl *tree, TreeItem item, int isOpen, int before); extern void TreeNotify_Selection(TreeCtrl *tree, TreeItemList *select, TreeItemList *deselect); extern int TreeNotifyCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); extern void TreeNotify_ActiveItem(TreeCtrl *tree, TreeItem itemOld, TreeItem itemNew); extern void TreeNotify_Scroll(TreeCtrl *tree, double fractions[2], int vertical); extern void TreeNotify_ItemDeleted(TreeCtrl *tree, TreeItemList *items); extern void TreeNotify_ItemVisibility(TreeCtrl *tree, TreeItemList *v, TreeItemList *h); /* tkTreeColumn.c */ extern int TreeColumn_InitInterp(Tcl_Interp *interp); extern void Tree_InitColumns(TreeCtrl *tree); extern TreeColumn Tree_FindColumn(TreeCtrl *tree, int columnIndex); #define COLUMN_ALL ((TreeColumn) -1) /* Every column. */ #define COLUMN_NTAIL ((TreeColumn) -2) /* Every column but the tail. */ #define CFO_NOT_MANY 0x01 #define CFO_NOT_NULL 0x02 #define CFO_NOT_TAIL 0x04 #define CFO_LIST_ALL 0x08 extern int TreeColumnList_FromObj(TreeCtrl *tree, Tcl_Obj *objPtr, TreeColumnList *columns, int flags); extern int TreeColumn_FromObj(TreeCtrl *tree, Tcl_Obj *objPtr, TreeColumn *columnPtr, int flags); typedef struct ColumnForEach ColumnForEach; struct ColumnForEach { TreeCtrl *tree; int error; int all; int ntail; TreeColumn current; TreeColumn next; TreeColumn last; TreeColumnList *list; int index; }; extern TreeColumn TreeColumnForEach_Start(TreeColumnList *columns, TreeColumnList *column2s, ColumnForEach *iter); extern TreeColumn TreeColumnForEach_Next(ColumnForEach *iter); #define COLUMN_FOR_EACH(column, columns, column2s, iter) \ for (column = TreeColumnForEach_Start(columns, column2s, iter); \ column != NULL; \ column = TreeColumnForEach_Next(iter)) extern Tcl_Obj *TreeColumn_ToObj(TreeCtrl *tree, TreeColumn column_); extern int TreeColumnCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); extern int TreeColumn_GetID(TreeColumn column_); extern int TreeColumn_Index(TreeColumn column_); extern TreeColumn TreeColumn_Next(TreeColumn column_); extern TreeColumn TreeColumn_Prev(TreeColumn column_); extern int TreeColumn_FixedWidth(TreeColumn column_); extern int TreeColumn_MinWidth(TreeColumn column_); extern int TreeColumn_MaxWidth(TreeColumn column_); extern int TreeColumn_NeededWidth(TreeColumn column_); extern int TreeColumn_UseWidth(TreeColumn column_); extern int TreeColumn_Offset(TreeColumn column_); extern Tk_Justify TreeColumn_ItemJustify(TreeColumn column_); #ifdef DEPRECATED extern int TreeColumn_WidthHack(TreeColumn column_); extern int TreeColumn_StepWidth(TreeColumn column_); #endif extern TreeStyle TreeColumn_ItemStyle(TreeColumn column_); extern void TreeColumn_StyleDeleted(TreeColumn column_, TreeStyle style); extern int TreeColumn_Visible(TreeColumn column_); extern int TreeColumn_Squeeze(TreeColumn column_); extern int TreeColumn_BackgroundCount(TreeColumn column_); extern GC TreeColumn_BackgroundGC(TreeColumn column_, int which); extern void Tree_DrawHeader(TreeCtrl *tree, TreeDrawable td, int x, int y); extern int TreeColumn_WidthOfItems(TreeColumn column_); extern void TreeColumn_InvalidateWidth(TreeColumn column_); extern void TreeColumn_Init(TreeCtrl *tree); extern void Tree_FreeColumns(TreeCtrl *tree); extern void Tree_InvalidateColumnWidth(TreeCtrl *tree, TreeColumn column); extern void Tree_InvalidateColumnHeight(TreeCtrl *tree, TreeColumn column); extern int Tree_HeaderHeight(TreeCtrl *tree); extern int TreeColumn_Bbox(TreeColumn column, int *x, int *y, int *w, int *h); extern TreeColumn Tree_HeaderUnderPoint(TreeCtrl *tree, int *x_, int *y_, int *w, int *h, int nearest); extern int TreeColumn_Lock(TreeColumn column_); extern int Tree_WidthOfColumns(TreeCtrl *tree); extern int Tree_WidthOfLeftColumns(TreeCtrl *tree); extern int Tree_WidthOfRightColumns(TreeCtrl *tree); extern void TreeColumn_TreeChanged(TreeCtrl *tree, int flagT); extern void TreeColumn_SetDInfo(TreeColumn column, TreeColumnDInfo dInfo); extern TreeColumnDInfo TreeColumn_GetDInfo(TreeColumn column); /* tkTreeDrag.c */ extern int TreeDragImage_Init(TreeCtrl *tree); extern void TreeDragImage_Free(TreeDragImage dragImage_); extern void TreeDragImage_Display(TreeDragImage dragImage_); extern void TreeDragImage_Undisplay(TreeDragImage dragImage_); extern void TreeDragImage_Draw(TreeDragImage dragImage_, Drawable drawable, int x, int y); extern int TreeDragImageCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); /* tkTreeMarquee.c */ extern int TreeMarquee_Init(TreeCtrl *tree); extern void TreeMarquee_Free(TreeMarquee marquee_); extern void TreeMarquee_Draw(TreeMarquee marquee_, Drawable drawable, int x, int y); extern void TreeMarquee_Display(TreeMarquee marquee_); extern void TreeMarquee_Undisplay(TreeMarquee marquee_); extern int TreeMarqueeCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); /* tkTreeDisplay.c */ extern int Tree_TotalWidth(TreeCtrl *tree); extern int Tree_TotalHeight(TreeCtrl *tree); extern TreeItem Tree_ItemUnderPoint(TreeCtrl *tree, int *x, int *y, int nearest); extern void Tree_FreeItemRInfo(TreeCtrl *tree, TreeItem item); extern int Tree_ItemBbox(TreeCtrl *tree, TreeItem item, int lock, int *x, int *y, int *w, int *h); extern TreeItem Tree_ItemAbove(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemBelow(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemLeft(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemRight(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemTop(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemBottom(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemLeftMost(TreeCtrl *tree, TreeItem item); extern TreeItem Tree_ItemRightMost(TreeCtrl *tree, TreeItem item); extern int Tree_ItemToRNC(TreeCtrl *tree, TreeItem item, int *row, int *col); extern TreeItem Tree_RNCToItem(TreeCtrl *tree, int row, int col); extern int Tree_AreaBbox(TreeCtrl *tree, int area, int *x1_, int *y1_, int *x2_, int *y2_); enum { TREE_AREA_NONE = 0, TREE_AREA_HEADER, TREE_AREA_CONTENT, TREE_AREA_LEFT, TREE_AREA_RIGHT }; extern int Tree_HitTest(TreeCtrl *tree, int x, int y); extern void TreeDInfo_Init(TreeCtrl *tree); extern void TreeDInfo_Free(TreeCtrl *tree); extern void Tree_EventuallyRedraw(TreeCtrl *tree); extern void Tree_GetScrollFractionsX(TreeCtrl *tree, double fractions[2]); extern void Tree_GetScrollFractionsY(TreeCtrl *tree, double fractions[2]); extern int Increment_FindX(TreeCtrl *tree, int offset); extern int Increment_FindY(TreeCtrl *tree, int offset); extern int Increment_ToOffsetX(TreeCtrl *tree, int index); extern int Increment_ToOffsetY(TreeCtrl *tree, int index); extern int B_XviewCmd(TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); extern int B_YviewCmd(TreeCtrl *tree, int objc, Tcl_Obj *CONST objv[]); extern void Tree_SetOriginX(TreeCtrl *tree, int xOrigin); extern void Tree_SetOriginY(TreeCtrl *tree, int yOrigin); extern void Tree_RelayoutWindow(TreeCtrl *tree); extern void Tree_FreeItemDInfo(TreeCtrl *tree, TreeItem item1, TreeItem item2); extern void Tree_InvalidateItemDInfo(TreeCtrl *tree, TreeColumn column, TreeItem item1, TreeItem item2); extern void TreeDisplay_ItemDeleted(TreeCtrl *tree, TreeItem item); extern void TreeDisplay_ColumnDeleted(TreeCtrl *tree, TreeColumn column); extern void TreeDisplay_FreeColumnDInfo(TreeCtrl *tree, TreeColumn column); extern void TreeDisplay_GetReadyForTrouble(TreeCtrl *tree, int *requestsPtr); extern int TreeDisplay_WasThereTrouble(TreeCtrl *tree, int requests); extern void Tree_InvalidateArea(TreeCtrl *tree, int x1, int y1, int x2, int y2); extern void Tree_InvalidateItemArea(TreeCtrl *tree, int x1, int y1, int x2, int y2); extern void Tree_InvalidateRegion(TreeCtrl *tree, TkRegion region); extern void Tree_RedrawArea(TreeCtrl *tree, int x1, int y1, int x2, int y2); extern void Tree_ExposeArea(TreeCtrl *tree, int x1, int y1, int x2, int y2); extern void Tree_FocusChanged(TreeCtrl *tree, int gotFocus); extern void Tree_Activate(TreeCtrl *tree, int isActive); extern void Tree_ItemsInArea(TreeCtrl *tree, TreeItemList *items, int minX, int minY, int maxX, int maxY); extern void TreeColumnProxy_Undisplay(TreeCtrl *tree); extern void TreeColumnProxy_Display(TreeCtrl *tree); extern void TreeRowProxy_Undisplay(TreeCtrl *tree); extern void TreeRowProxy_Display(TreeCtrl *tree); extern void Tree_DrawTiledImage(TreeCtrl *tree, Drawable drawable, Tk_Image image, int x1, int y1, int x2, int y2, int xOffset, int yOffset); #define DINFO_OUT_OF_DATE 0x0001 #define DINFO_CHECK_COLUMN_WIDTH 0x0002 #define DINFO_DRAW_HEADER 0x0004 #define DINFO_SET_ORIGIN_X 0x0008 #define DINFO_UPDATE_SCROLLBAR_X 0x0010 #define DINFO_REDRAW_PENDING 0x00020 #define DINFO_INVALIDATE 0x0040 #define DINFO_DRAW_HIGHLIGHT 0x0080 #define DINFO_DRAW_BORDER 0x0100 #define DINFO_REDO_RANGES 0x0200 #define DINFO_SET_ORIGIN_Y 0x0400 #define DINFO_UPDATE_SCROLLBAR_Y 0x0800 #define DINFO_REDO_INCREMENTS 0x1000 #define DINFO_REDO_COLUMN_WIDTH 0x2000 #define DINFO_REDO_SELECTION 0x4000 #define DINFO_DRAW_WHITESPACE 0x8000 extern void Tree_DInfoChanged(TreeCtrl *tree, int flags); extern void Tree_TheWorldHasChanged(Tcl_Interp *interp); /* tkTreeTheme.c */ extern int TreeTheme_InitInterp(Tcl_Interp *interp); extern void TreeTheme_ThemeChanged(TreeCtrl *tree); extern int TreeTheme_Init(TreeCtrl *tree); extern int TreeTheme_Free(TreeCtrl *tree); extern int TreeTheme_DrawHeaderItem(TreeCtrl *tree, Drawable drawable, int state, int arrow, int x, int y, int width, int height); extern int TreeTheme_GetHeaderFixedHeight(TreeCtrl *tree, int *heightPtr); extern int TreeTheme_GetHeaderContentMargins(TreeCtrl *tree, int state, int arrow, int bounds[4]); extern int TreeTheme_DrawHeaderArrow(TreeCtrl *tree, Drawable drawable, int up, int x, int y, int width, int height); extern int TreeTheme_DrawButton(TreeCtrl *tree, Drawable drawable, int open, int x, int y, int width, int height); extern int TreeTheme_GetButtonSize(TreeCtrl *tree, Drawable drawable, int open, int *widthPtr, int *heightPtr); extern int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *widthPtr, int *heightPtr); extern int TreeTheme_SetBorders(TreeCtrl *tree); extern int TreeTheme_DrawBorders(TreeCtrl *tree, Drawable drawable); extern void TreeTheme_Relayout(TreeCtrl *tree); /* tkTreeUtils.c */ #ifdef TREECTRL_DEBUG #define WIPE(p,s) memset((char *) p, 0xAA, s) #else #define WIPE(p,s) #endif #define CWIPE(p,t,c) WIPE(p, sizeof(t) * (c)) #define WIPEFREE(p,s) { WIPE(p, s); ckfree((char *) p); } #define WFREE(p,t) WIPEFREE(p, sizeof(t)) #define WCFREE(p,t,c) WIPEFREE(p, sizeof(t) * (c)) extern int Tree_Ellipsis(Tk_Font tkfont, char *string, int numBytes, int *maxPixels, char *ellipsis, int force); extern void Tree_HDotLine(TreeCtrl *tree, Drawable drawable, GC gc, int x1, int y1, int x2); extern void Tree_VDotLine(TreeCtrl *tree, Drawable drawable, GC gc, int x1, int y1, int y2); extern void Tree_DrawActiveOutline(TreeCtrl *tree, Drawable drawable, int x, int y, int width, int height, int open); typedef struct DotState { void *stuff[10]; } DotState; extern void TreeDotRect_Setup(TreeCtrl *tree, Drawable drawable, DotState *dotState); extern void TreeDotRect_Draw(DotState *dotState, int x, int y, int width, int height); extern void TreeDotRect_Restore(DotState *dotState); typedef struct TextLayout_ *TextLayout; extern TextLayout TextLayout_Compute(Tk_Font tkfont, CONST char *string, int numChars, int wrapLength, Tk_Justify justify, int maxLines, int flags); extern void TextLayout_Free(TextLayout textLayout); extern void TextLayout_Size(TextLayout textLayout, int *widthPtr, int *heightPtr); extern int TextLayout_TotalWidth(TextLayout textLayout); extern void TextLayout_Draw(Display *display, Drawable drawable, GC gc, TextLayout layout, int x, int y, int firstChar, int lastChar, int underline); #ifdef MAC_OSX_TK extern void DrawXORLine(Display *display, Drawable drawable, int x1, int y1, int x2, int y2); #endif extern void Tree_RedrawImage(Tk_Image image, int imageX, int imageY, int width, int height, TreeDrawable td, int drawableX, int drawableY); extern void Tree_DrawBitmapWithGC(TreeCtrl *tree, Pixmap bitmap, Drawable drawable, GC gc, int src_x, int src_y, int width, int height, int dest_x, int dest_y); extern void Tree_DrawBitmap(TreeCtrl *tree, Pixmap bitmap, Drawable drawable, XColor *fg, XColor *bg, int src_x, int src_y, int width, int height, int dest_x, int dest_y); extern TkRegion Tree_GetRegion(TreeCtrl *tree); extern void Tree_FreeRegion(TreeCtrl *tree, TkRegion region); extern void Tree_FillRegion(Display *display, Drawable drawable, GC gc, TkRegion rgn); extern void Tree_OffsetRegion(TkRegion region, int xOffset, int yOffset); extern int Tree_ScrollWindow(TreeCtrl *tree, GC gc, int x, int y, int width, int height, int dx, int dy, TkRegion damageRgn); extern void Tree_UnsetClipMask(TreeCtrl *tree, Drawable drawable, GC gc); extern void Tree_XImage2Photo(Tcl_Interp *interp, Tk_PhotoHandle photoH, XImage *ximage, int alpha); #define PAD_TOP_LEFT 0 #define PAD_BOTTOM_RIGHT 1 extern Tk_ObjCustomOption TreeCtrlCO_pad; extern int TreeCtrl_GetPadAmountFromObj(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *padObj, int *topLeftPtr, int *bottomRightPtr); extern Tcl_Obj * TreeCtrl_NewPadAmountObj(int *padAmounts); /*****/ #define ObjectIsEmpty TreeCtrl_ObjectIsEmpty extern int ObjectIsEmpty(Tcl_Obj *obj); #define pstBitmap TreeCtrl_pstBitmap #define pstBoolean TreeCtrl_pstBoolean #define pstBorder TreeCtrl_pstBorder #define pstColor TreeCtrl_pstColor #define pstFont TreeCtrl_pstFont #define pstImage TreeCtrl_pstImage #define pstRelief TreeCtrl_pstRelief extern PerStateType pstBitmap; extern PerStateType pstBoolean; extern PerStateType pstBorder; extern PerStateType pstColor; extern PerStateType pstFont; extern PerStateType pstImage; extern PerStateType pstRelief; #define MATCH_NONE 0 #define MATCH_ANY 1 #define MATCH_PARTIAL 2 #define MATCH_EXACT 3 extern void PerStateInfo_Free(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo); typedef int (*StateFromObjProc)(TreeCtrl *tree, Tcl_Obj *obj, int *stateOff, int *stateOn); extern int PerStateInfo_FromObj(TreeCtrl *tree, StateFromObjProc proc, PerStateType *typePtr, PerStateInfo *pInfo); extern PerStateData *PerStateInfo_ForState(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, int state, int *match); extern Tcl_Obj *PerStateInfo_ObjForState(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, int state, int *match); extern int PerStateInfo_Undefine(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, int state); extern GC Tree_GetGC(TreeCtrl *tree, unsigned long mask, XGCValues *gcValues); extern void Tree_FreeAllGC(TreeCtrl *tree); extern Pixmap PerStateBitmap_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern void PerStateBitmap_MaxSize(TreeCtrl *tree, PerStateInfo *pInfo, int *widthPtr, int *heightPtr); extern int PerStateBoolean_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern Tk_3DBorder PerStateBorder_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern XColor *PerStateColor_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern Tk_Font PerStateFont_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern Tk_Image PerStateImage_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern void PerStateImage_MaxSize(TreeCtrl *tree, PerStateInfo *pInfo, int *widthPtr, int *heightPtr); extern int PerStateRelief_ForState(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); extern void PSTSave(PerStateInfo *pInfo, PerStateInfo *pSave); extern void PSTRestore(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, PerStateInfo *pSave); #ifdef ALLOC_HAX extern ClientData TreeAlloc_Init(void); extern void TreeAlloc_Finalize(ClientData data); extern char *TreeAlloc_Alloc(ClientData data, Tk_Uid id, int size); extern char *TreeAlloc_CAlloc(ClientData data, Tk_Uid id, int size, int count, int roundUp); extern char *TreeAlloc_Realloc(ClientData data, Tk_Uid id, char *ptr, int size1, int size2); extern void TreeAlloc_Free(ClientData data, Tk_Uid id, char *ptr, int size); extern void TreeAlloc_CFree(ClientData data, Tk_Uid id, char *ptr, int size, int count, int roundUp); extern void TreeAlloc_Stats(Tcl_Interp *interp, ClientData data); #endif /*****/ extern void TreePtrList_Init(TreeCtrl *tree, TreePtrList *tilPtr, int count); extern ClientData *TreePtrList_Append(TreePtrList *tilPtr, ClientData ptr); extern ClientData *TreePtrList_Concat(TreePtrList *tilPtr, TreePtrList *til2Ptr); extern void TreePtrList_Free(TreePtrList *tilPtr); #define TreeItemList_Init TreePtrList_Init #define TreeItemList_Append TreePtrList_Append #define TreeItemList_Concat TreePtrList_Concat #define TreeItemList_Free TreePtrList_Free #define TreeItemList_Items(L) ((TreeItem *) (L)->pointers) #define TreeItemList_Nth(L,n) ((TreeItem) (L)->pointers[n]) #define TreeItemList_Count(L) ((L)->count) extern void TreeItemList_Sort(TreeItemList *items); #define TreeColumnList_Init TreePtrList_Init #define TreeColumnList_Append TreePtrList_Append #define TreeColumnList_Concat TreePtrList_Concat #define TreeColumnList_Free TreePtrList_Free #define TreeColumnList_Nth(L,n) ((TreeColumn) (L)->pointers[n]) #define TreeColumnList_Count(L) ((L)->count) /*****/ /* * This structure holds a list of tags. */ typedef struct TagInfo TagInfo; struct TagInfo { int numTags; /* Number of tag slots actually used * at tagPtr. */ int tagSpace; /* Total amount of tag space available * at tagPtr. */ #define TREE_TAG_SPACE 3 Tk_Uid tagPtr[TREE_TAG_SPACE]; /* Array of tags. The actual size will * be tagSpace. THIS FIELD MUST BE THE * LAST IN THE STRUCTURE. */ }; extern TagInfo *TagInfo_Add(TreeCtrl *tree, TagInfo *tagInfo, Tk_Uid tags[], int numTags); extern TagInfo *TagInfo_Remove(TreeCtrl *tree, TagInfo *tagInfo, Tk_Uid tags[], int numTags); extern Tk_Uid *TagInfo_Names(TreeCtrl *tree, TagInfo *tagInfo, Tk_Uid *tags, int *numTagsPtr, int *tagSpacePtr); extern TagInfo *TagInfo_Copy(TreeCtrl *tree, TagInfo *tagInfo); extern void TagInfo_Free(TreeCtrl *tree, TagInfo *tagInfo); extern int TagInfo_FromObj(TreeCtrl *tree, Tcl_Obj *objPtr, TagInfo **tagInfoPtr); extern Tk_ObjCustomOption TreeCtrlCO_tagInfo; /* * This struct holds information about a tag expression. */ typedef struct TagExpr { TreeCtrl *tree; Tk_Uid *uids; /* expresion compiled to an array of uids */ Tk_Uid staticUids[15]; int allocated; /* available space for array of uids */ int length; /* number of uids */ int index; /* current position in expression evaluation */ int simple; /* TRUE if expr is single tag */ Tk_Uid uid; /* single tag if 'simple' is TRUE */ char *string; /* tag expression string */ int stringIndex; /* current position in string scan */ int stringLength; /* length of tag expression string */ char *rewritebuffer; /* tag string (after removing escapes) */ char staticRWB[100]; } TagExpr; extern int TagExpr_Init(TreeCtrl *tree, Tcl_Obj *exprObj, TagExpr *expr); extern int TagExpr_Scan(TagExpr *expr); extern int TagExpr_Eval(TagExpr *expr, TagInfo *tags); extern void TagExpr_Free(TagExpr *expr); extern Tk_OptionSpec *Tree_FindOptionSpec(Tk_OptionSpec *optionTable, CONST char *optionName); extern Tk_ObjCustomOption *PerStateCO_Alloc(CONST char *optionName, PerStateType *typePtr, StateFromObjProc proc); extern int PerStateCO_Init(Tk_OptionSpec *optionTable, CONST char *optionName, PerStateType *typePtr, StateFromObjProc proc); /*****/ typedef struct DynamicOptionSpec DynamicOptionSpec; typedef struct DynamicOption DynamicOption; struct DynamicOption { int id; /* Unique id. */ DynamicOption *next; /* Linked list. */ char data[1]; /* Actual size will be > 1 */ }; typedef void (DynamicOptionInitProc)(void *data); extern DynamicOption *DynamicOption_AllocIfNeeded(TreeCtrl *tree, DynamicOption **firstPtr, int id, int size, DynamicOptionInitProc *init); extern void *DynamicOption_FindData(DynamicOption *first, int id); extern void DynamicOption_Free(TreeCtrl *tree, DynamicOption *first, Tk_OptionSpec *optionTable); extern void DynamicOption_Free1(TreeCtrl *tree, DynamicOption **firstPtr, int id, int size); extern int DynamicCO_Init(Tk_OptionSpec *optionTable, CONST char *optionName, int id, int size, int objOffset, int internalOffset, Tk_ObjCustomOption *custom, DynamicOptionInitProc *init); extern int BooleanFlagCO_Init(Tk_OptionSpec *optionTable, CONST char *optionName, int theFlag); extern int ItemButtonCO_Init(Tk_OptionSpec *optionTable, CONST char *optionName, int flag1, int flag2); extern int Tree_GetIntForIndex(TreeCtrl *tree, Tcl_Obj *objPtr, int *indexPtr, int *endRelativePtr); extern Tk_ObjCustomOption TreeCtrlCO_pixels; extern Tk_ObjCustomOption TreeCtrlCO_string; extern Tk_ObjCustomOption TreeCtrlCO_style; /*****/ #define STATIC_SIZE 20 #define STATIC_ALLOC(P,T,C) \ if (C > STATIC_SIZE) \ P = (T *) ckalloc(sizeof(T) * (C)) #define STATIC_FREE(P,T,C) \ CWIPE(P, T, C); \ if (C > STATIC_SIZE) \ ckfree((char *) P) #define STATIC_FREE2(P,P2) \ if (P != P2) \ ckfree((char *) P) tktreectrl-2.2.8/generic/tkTreeDisplay.c0000700000175600010010000057604111073204143016460 0ustar TimNone/* * tkTreeDisplay.c -- * * This module implements treectrl widget's main display code. * * Copyright (c) 2002-2008 Tim Baker * * RCS: @(#) $Id: tkTreeDisplay.c,v 1.87 2008/10/08 19:22:11 treectrl Exp $ */ #include "tkTreeCtrl.h" /* Window -> Canvas */ #define W2Cy(y) ((y) + tree->yOrigin) #define DW2Cy(y) ((y) + dInfo->yOrigin) #define COMPLEX_WHITESPACE typedef struct TreeColumnDInfo_ TreeColumnDInfo_; typedef struct TreeDInfo_ TreeDInfo_; typedef struct RItem RItem; typedef struct Range Range; typedef struct DItem DItem; static void Range_RedoIfNeeded(TreeCtrl *tree); static int Range_TotalWidth(TreeCtrl *tree, Range *range_); static int Range_TotalHeight(TreeCtrl *tree, Range *range_); static void Range_Redo(TreeCtrl *tree); static Range *Range_UnderPoint(TreeCtrl *tree, int *x_, int *y_, int nearest); static RItem *Range_ItemUnderPoint(TreeCtrl *tree, Range *range, int *x_, int *y_); /* One of these per TreeItem that is ReallyVisible(). */ struct RItem { TreeItem item; /* The item. */ Range *range; /* Range the item is in. */ int size; /* Height or width consumed in Range. */ int offset; /* Vertical or horizontal offset in Range. */ int index; /* 0-based index in Range. */ }; /* A collection of visible TreeItems. */ struct Range { RItem *first; RItem *last; int totalWidth; int totalHeight; int index; /* 0-based index in list of Ranges. */ int offset; /* vertical/horizontal offset from canvas * top/left. */ Range *prev; Range *next; }; typedef struct DItemArea { int x; /* Where it should be drawn, window coords. */ int width; /* Current width. */ int dirty[4]; /* Dirty area in item coords. */ #define DITEM_DIRTY 0x0001 #define DITEM_ALL_DIRTY 0x0002 int flags; } DItemArea; /* Display information for a TreeItem that is onscreen. */ struct DItem { #ifdef TREECTRL_DEBUG char magic[4]; #endif TreeItem item; int y; /* Where it should be drawn, window coords. */ int height; /* Current height. */ DItemArea area; DItemArea left, right; int oldX, oldY; /* Where it was last drawn, window coords. */ Range *range; /* Range the TreeItem is in. */ int index; /* Used for alternating background colors. */ int oldIndex; /* Used for alternating background colors. */ int *spans; /* span[n] is the column index of the item * column displayed at the n'th tree column. */ DItem *next; }; /* Display information for a TreeColumn. */ struct TreeColumnDInfo_ { int offset; /* Last seen x-offset */ int width; /* Last seen column width */ }; /* Display information for a TreeCtrl. */ struct TreeDInfo_ { GC scrollGC; int xOrigin; /* Last seen TreeCtrl.xOrigin */ int yOrigin; /* Last seen TreeCtrl.yOrigin */ int totalWidth; /* Last seen Tree_TotalWidth() */ int totalHeight; /* Last seen Tree_TotalHeight() */ int headerHeight; /* Last seen TreeCtrl.headerHeight */ DItem *dItem; /* Head of list for each displayed item */ DItem *dItemLast; /* Temp for UpdateDInfo() */ DItem *dItemFree; /* List of unused DItems */ Range *rangeFirst; /* Head of Ranges */ Range *rangeLast; /* Tail of Ranges */ Range *rangeFirstD; /* First range with valid display info */ Range *rangeLastD; /* Last range with valid display info */ RItem *rItem; /* Block of RItems for all Ranges */ int rItemMax; /* size of rItem[] */ int itemHeight; /* Observed max TreeItem height */ int itemWidth; /* Observed max TreeItem width */ TreeDrawable pixmapW; /* Pixmap as big as the window */ TreeDrawable pixmapI; /* Pixmap as big as the largest item */ TkRegion dirtyRgn; /* DOUBLEBUFFER_WINDOW */ int flags; /* DINFO_XXX */ int xScrollIncrement; /* Last seen TreeCtr.xScrollIncrement */ int yScrollIncrement; /* Last seen TreeCtr.yScrollIncrement */ int *xScrollIncrements; /* When tree->xScrollIncrement is zero */ int *yScrollIncrements; /* When tree->yScrollIncrement is zero */ int xScrollIncrementCount; /* Size of xScrollIncrements. */ int yScrollIncrementCount; /* Size of yScrollIncrements. */ int incrementTop; /* yScrollIncrement[] index of item at top */ int incrementLeft; /* xScrollIncrement[] index of item at left */ TkRegion wsRgn; /* Region containing whitespace */ #ifdef COMPLEX_WHITESPACE int complexWhitespace; #endif Tcl_HashTable itemVisHash; /* Table of visible items */ int requests; /* Incremented for every call to Tree_EventuallyRedraw */ int bounds[4], empty; /* Bounds of TREE_AREA_CONTENT */ int boundsL[4], emptyL; /* Bounds of TREE_AREA_LEFT */ int boundsR[4], emptyR; /* Bounds of TREE_AREA_RIGHT */ int widthOfColumnsLeft; /* Last seen Tree_WidthOfLeftColumns() */ int widthOfColumnsRight; /* Last seen Tree_WidthOfRightColumns() */ Range *rangeLock; /* If there is no Range for non-locked * columns, this range holds the vertical * offset and height of each ReallyVisible * item for displaying locked columns. */ }; #ifdef COMPLEX_WHITESPACE static int ComplexWhitespace(TreeCtrl *tree); #endif /*========*/ void Tree_FreeItemRInfo(TreeCtrl *tree, TreeItem item) { TreeItem_SetRInfo(tree, item, NULL); } static Range * Range_Free(TreeCtrl *tree, Range *range) { Range *next = range->next; WFREE(range, Range); return next; } /* *---------------------------------------------------------------------- * * Range_Redo -- * * This procedure puts all ReallyVisible() TreeItems into a list of * Ranges. If tree->wrapMode is TREE_WRAP_NONE there will only be a * single Range. * * Results: * None. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Range_Redo( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *rangeList = dInfo->rangeFirst; Range *range; RItem *rItem; TreeItem item = tree->root; int fixedWidth = -1, stepWidth = -1; int wrapCount = 0, wrapPixels = 0; int count, pixels, rItemCount = 0; int rangeIndex = 0, itemIndex; if (tree->debug.enable && tree->debug.display) dbwin("Range_Redo %s\n", Tk_PathName(tree->tkwin)); /* Update column variables */ (void) Tree_WidthOfColumns(tree); dInfo->rangeFirst = NULL; dInfo->rangeLast = NULL; if (tree->columnCountVis < 1) goto freeRanges; switch (tree->wrapMode) { case TREE_WRAP_NONE: break; case TREE_WRAP_ITEMS: wrapCount = tree->wrapArg; break; case TREE_WRAP_PIXELS: wrapPixels = tree->wrapArg; break; case TREE_WRAP_WINDOW: wrapPixels = tree->vertical ? Tree_ContentHeight(tree) : Tree_ContentWidth(tree); if (wrapPixels < 0) wrapPixels = 0; break; } /* For horizontal layout with wrapping I need to know how wide each item * is. This is the same block of code as in Range_TotalWidth */ if ((wrapPixels > 0) && !tree->vertical) { /* More than one item column, so all items have the same width */ if (tree->columnCountVis > 1) fixedWidth = Tree_WidthOfColumns(tree); /* Single item column, fixed width for all items */ else if (tree->itemWidth > 0) fixedWidth = tree->itemWidth; /* Single item column, fixed width for all items */ /* THIS IS FOR COMPATIBILITY ONLY */ else if (TreeColumn_FixedWidth(tree->columnVis) != -1) fixedWidth = TreeColumn_FixedWidth(tree->columns); /* Single item column, want all items same width */ else if (tree->itemWidthEqual #ifdef DEPRECATED || TreeColumn_WidthHack(tree->columnVis) #endif /* DEPRECATED */ ) { fixedWidth = TreeColumn_WidthOfItems(tree->columnVis); /* Each item is a multiple of this width */ if (tree->itemWidMult > 0) stepWidth = tree->itemWidMult; #ifdef DEPRECATED else stepWidth = TreeColumn_StepWidth(tree->columnVis); #endif /* DEPRECATED */ if ((stepWidth != -1) && (fixedWidth % stepWidth)) fixedWidth += stepWidth - fixedWidth % stepWidth; /* Single item column, variable item width */ } else { /* Each item is a multiple of this width */ if (tree->itemWidMult > 0) stepWidth = tree->itemWidMult; #ifdef DEPRECATED else stepWidth = TreeColumn_StepWidth(tree->columnVis); #endif /* DEPRECATED */ } } /* Speed up ReallyVisible() and get itemVisCount */ Tree_UpdateItemIndex(tree); if (dInfo->rItemMax < tree->itemVisCount) { dInfo->rItem = (RItem *) ckrealloc((char *) dInfo->rItem, tree->itemVisCount * sizeof(RItem)); dInfo->rItemMax = tree->itemVisCount; } if (!TreeItem_ReallyVisible(tree, item)) item = TreeItem_NextVisible(tree, item); while (item != NULL) { if (rangeList == NULL) range = (Range *) ckalloc(sizeof(Range)); else { range = rangeList; rangeList = rangeList->next; } memset(range, '\0', sizeof(Range)); range->totalWidth = -1; range->totalHeight = -1; range->index = rangeIndex++; count = 0; pixels = 0; itemIndex = 0; while (1) { rItem = dInfo->rItem + rItemCount; if (rItemCount >= dInfo->rItemMax) panic("rItemCount > dInfo->rItemMax"); if (range->first == NULL) range->first = range->last = rItem; TreeItem_SetRInfo(tree, item, (TreeItemRInfo) rItem); rItem->item = item; rItem->range = range; rItem->index = itemIndex; /* Range must be <= this number of pixels */ if (wrapPixels > 0) { rItem->offset = pixels; if (tree->vertical) { rItem->size = TreeItem_Height(tree, item); } else { if (fixedWidth != -1) { rItem->size = fixedWidth; } else { TreeItemColumn itemColumn = TreeItem_FindColumn(tree, item, TreeColumn_Index(tree->columnVis)); if (itemColumn != NULL) { int columnWidth = TreeItemColumn_NeededWidth(tree, item, itemColumn); if (tree->columnTreeVis) columnWidth += TreeItem_Indent(tree, item); rItem->size = columnWidth; } else rItem->size = 0; if ((stepWidth != -1) && (rItem->size % stepWidth)) rItem->size += stepWidth - rItem->size % stepWidth; } } /* Too big */ if (pixels + rItem->size > wrapPixels) { /* Ensure at least one item is in this Range */ if (itemIndex == 0) { pixels += rItem->size; rItemCount++; } break; } pixels += rItem->size; } range->last = rItem; itemIndex++; rItemCount++; if (++count == wrapCount) break; item = TreeItem_NextVisible(tree, item); if (item == NULL) break; } /* Since we needed to calculate the height or width of this range, * we don't need to do it later in Range_TotalWidth/Height() */ if (wrapPixels > 0) { if (tree->vertical) range->totalHeight = pixels; else range->totalWidth = pixels; } if (dInfo->rangeFirst == NULL) dInfo->rangeFirst = range; else { range->prev = dInfo->rangeLast; dInfo->rangeLast->next = range; } dInfo->rangeLast = range; item = TreeItem_NextVisible(tree, range->last->item); } freeRanges: while (rangeList != NULL) rangeList = Range_Free(tree, rangeList); /* If there are no visible non-locked columns, we won't have a Range. * But we need to know the offset/size of each item for drawing any * locked columns (and for vertical scrolling... and hit testing). */ if (dInfo->rangeLock != NULL) { (void) Range_Free(tree, dInfo->rangeLock); dInfo->rangeLock = NULL; } (void) Tree_WidthOfColumns(tree); /* update columnCountVisLeft etc */ if ((dInfo->rangeFirst == NULL) && (tree->columnCountVisLeft || tree->columnCountVisRight)) { /* Speed up ReallyVisible() and get itemVisCount */ Tree_UpdateItemIndex(tree); if (tree->itemVisCount == 0) return; if (dInfo->rItemMax < tree->itemVisCount) { dInfo->rItem = (RItem *) ckrealloc((char *) dInfo->rItem, tree->itemVisCount * sizeof(RItem)); dInfo->rItemMax = tree->itemVisCount; } dInfo->rangeLock = (Range *) ckalloc(sizeof(Range)); range = dInfo->rangeLock; pixels = 0; itemIndex = 0; rItem = dInfo->rItem; item = tree->root; if (!TreeItem_ReallyVisible(tree, item)) item = TreeItem_NextVisible(tree, item); while (item != NULL) { rItem->item = item; rItem->range = range; rItem->size = TreeItem_Height(tree, item); rItem->offset = pixels; rItem->index = itemIndex++; TreeItem_SetRInfo(tree, item, (TreeItemRInfo) rItem); pixels += rItem->size; rItem++; item = TreeItem_NextVisible(tree, item); } range->offset = 0; range->first = dInfo->rItem; range->last = dInfo->rItem + tree->itemVisCount - 1; range->totalWidth = 1; range->totalHeight = pixels; range->prev = range->next = NULL; } } /* *---------------------------------------------------------------------- * * Range_TotalWidth -- * * Return the width of a Range. The width is only calculated if * it hasn't been done yet by Range_Redo(). * * Results: * Pixel width of the Range. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Range_TotalWidth( TreeCtrl *tree, /* Widget info. */ Range *range /* Range to return the width of. */ ) { TreeItem item; TreeItemColumn itemColumn; RItem *rItem; int fixedWidth = -1, stepWidth = -1; int itemWidth; if (range->totalWidth >= 0) return range->totalWidth; if (tree->vertical) { /* More than one item column, so all ranges have the same width */ if (tree->columnCountVis > 1) return range->totalWidth = Tree_WidthOfColumns(tree); /* If wrapping is disabled, then use the column width, * since it may expand to fill the window */ if (tree->wrapMode == TREE_WRAP_NONE) return range->totalWidth = TreeColumn_UseWidth(tree->columnVis); /* Single item column, fixed width for all ranges */ if (tree->itemWidth > 0) return range->totalWidth = tree->itemWidth; /* Single item column, fixed width for all ranges */ /* THIS IS FOR COMPATIBILITY ONLY */ if (TreeColumn_FixedWidth(tree->columnVis) != -1) return range->totalWidth = TreeColumn_FixedWidth(tree->columnVis); /* Single item column, each item is a multiple of this width */ if (tree->itemWidMult > 0) stepWidth = tree->itemWidMult; #ifdef DEPRECATED else stepWidth = TreeColumn_StepWidth(tree->columnVis); #endif /* DEPRECATED */ /* Single item column, want all items same width */ if (tree->itemWidthEqual #ifdef DEPRECATED || TreeColumn_WidthHack(tree->columnVis) #endif /* DEPRECATED */ ) { range->totalWidth = TreeColumn_WidthOfItems(tree->columnVis); if ((stepWidth != -1) && (range->totalWidth % stepWidth)) range->totalWidth += stepWidth - range->totalWidth % stepWidth; return range->totalWidth; } /* Max needed width of items in this range */ range->totalWidth = 0; rItem = range->first; while (1) { item = rItem->item; itemColumn = TreeItem_FindColumn(tree, item, TreeColumn_Index(tree->columnVis)); if (itemColumn != NULL) itemWidth = TreeItemColumn_NeededWidth(tree, item, itemColumn); else itemWidth = 0; if (tree->columnTreeVis) itemWidth += TreeItem_Indent(tree, item); if (itemWidth > range->totalWidth) range->totalWidth = itemWidth; if (rItem == range->last) break; rItem++; } if ((stepWidth != -1) && (range->totalWidth % stepWidth)) range->totalWidth += stepWidth - range->totalWidth % stepWidth; return range->totalWidth; } else { /* More than one item column, so all items have the same width */ if (tree->columnCountVis > 1) fixedWidth = Tree_WidthOfColumns(tree); /* Single item column, fixed width for all items */ else if (tree->itemWidth > 0) fixedWidth = tree->itemWidth; /* Single item column, fixed width for all items */ /* THIS IS FOR COMPATIBILITY ONLY */ else if (TreeColumn_FixedWidth(tree->columnVis) != -1) fixedWidth = TreeColumn_FixedWidth(tree->columnVis); /* Single item column, want all items same width */ else if (tree->itemWidthEqual #ifdef DEPRECATED || TreeColumn_WidthHack(tree->columnVis) #endif /* DEPRECATED */ ) { fixedWidth = TreeColumn_WidthOfItems(tree->columnVis); /* Each item is a multiple of this width */ if (tree->itemWidMult > 0) stepWidth = tree->itemWidMult; #ifdef DEPRECATED else stepWidth = TreeColumn_StepWidth(tree->columnVis); #endif /* DEPRECATED */ if ((stepWidth != -1) && (fixedWidth % stepWidth)) fixedWidth += stepWidth - fixedWidth % stepWidth; } /* Single item column, variable item width */ else { /* Each item is a multiple of this width */ if (tree->itemWidMult > 0) stepWidth = tree->itemWidMult; #ifdef DEPRECATED else stepWidth = TreeColumn_StepWidth(tree->columnVis); #endif /* DEPRECATED */ } /* Sum of widths of items in this range */ range->totalWidth = 0; rItem = range->first; while (1) { item = rItem->item; if (fixedWidth != -1) itemWidth = fixedWidth; else { itemColumn = TreeItem_FindColumn(tree, item, TreeColumn_Index(tree->columnVis)); if (itemColumn != NULL) itemWidth = TreeItemColumn_NeededWidth(tree, item, itemColumn); else itemWidth = 0; if (tree->columnTreeVis) itemWidth += TreeItem_Indent(tree, item); if ((stepWidth != -1) && (itemWidth % stepWidth)) itemWidth += stepWidth - itemWidth % stepWidth; } rItem = (RItem *) TreeItem_GetRInfo(tree, item); rItem->offset = range->totalWidth; rItem->size = itemWidth; range->totalWidth += itemWidth; if (rItem == range->last) break; rItem++; } return range->totalWidth; } } /* *---------------------------------------------------------------------- * * Range_TotalHeight -- * * Return the height of a Range. The height is only calculated if * it hasn't been done yet by Range_Redo(). * * Results: * Pixel height of the Range. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Range_TotalHeight( TreeCtrl *tree, /* Widget info. */ Range *range /* Range to return the height of. */ ) { TreeItem item; RItem *rItem; int itemHeight; if (range->totalHeight >= 0) return range->totalHeight; range->totalHeight = 0; rItem = range->first; while (1) { item = rItem->item; itemHeight = TreeItem_Height(tree, item); if (tree->vertical) { rItem->offset = range->totalHeight; rItem->size = itemHeight; range->totalHeight += itemHeight; } else { if (itemHeight > range->totalHeight) range->totalHeight = itemHeight; } if (rItem == range->last) break; rItem++; } return range->totalHeight; } /* *---------------------------------------------------------------------- * * Tree_TotalWidth -- * * Return the width needed by all the Ranges. The width is only * recalculated if it was marked out-of-date. * * Results: * Pixel width of the "canvas". * * Side effects: * The list of Ranges will be recalculated if needed. * *---------------------------------------------------------------------- */ int Tree_TotalWidth( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range; int rangeWidth; Range_RedoIfNeeded(tree); if (tree->totalWidth >= 0) return tree->totalWidth; if (dInfo->rangeFirst == NULL) return tree->totalWidth = Tree_WidthOfColumns(tree); tree->totalWidth = 0; range = dInfo->rangeFirst; while (range != NULL) { rangeWidth = Range_TotalWidth(tree, range); if (tree->vertical) { range->offset = tree->totalWidth; tree->totalWidth += rangeWidth; } else { if (rangeWidth > tree->totalWidth) tree->totalWidth = rangeWidth; } range = range->next; } return tree->totalWidth; } /* *---------------------------------------------------------------------- * * Tree_TotalHeight -- * * Return the height needed by all the Ranges. The height is only * recalculated if it was marked out-of-date. * * Results: * Pixel height of the "canvas". * * Side effects: * The list of Ranges will be recalculated if needed. * *---------------------------------------------------------------------- */ int Tree_TotalHeight( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range; int rangeHeight; Range_RedoIfNeeded(tree); if (tree->totalHeight >= 0) return tree->totalHeight; tree->totalHeight = 0; range = dInfo->rangeFirst; while (range != NULL) { rangeHeight = Range_TotalHeight(tree, range); if (tree->vertical) { if (rangeHeight > tree->totalHeight) tree->totalHeight = rangeHeight; } else { range->offset = tree->totalHeight; tree->totalHeight += rangeHeight; } range = range->next; } /* If dInfo->rangeLock is not NULL, then we are displaying some items * in locked columns but no non-locked columns. */ if (dInfo->rangeLock != NULL) { if (dInfo->rangeLock->totalHeight > tree->totalHeight) tree->totalHeight = dInfo->rangeLock->totalHeight; } return tree->totalHeight; } /* *---------------------------------------------------------------------- * * Range_UnderPoint -- * * Return the Range containing the given coordinates. * * Results: * Range containing the coordinates or NULL if the point is * outside any Range. * * Side effects: * The list of Ranges will be recalculated if needed. * *---------------------------------------------------------------------- */ static Range * Range_UnderPoint( TreeCtrl *tree, /* Widget info. */ int *x_, /* In: window x coordinate. * Out: x coordinate relative to the top-left * of the Range. */ int *y_, /* In: window y coordinate. * Out: y coordinate relative to the top-left * of the Range. */ int nearest /* TRUE if the Range nearest the coordinates * should be returned. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range; int x = *x_, y = *y_; Range_RedoIfNeeded(tree); if ((Tree_TotalWidth(tree) <= 0) || (Tree_TotalHeight(tree) <= 0)) return NULL; range = dInfo->rangeFirst; if (nearest) { int minX, minY, maxX, maxY; if (!Tree_AreaBbox(tree, TREE_AREA_CONTENT, &minX, &minY, &maxX, &maxY)) return NULL; /* Keep inside borders and header. Perhaps another flag needed. */ if (x < minX) x = minX; if (x >= maxX) x = maxX - 1; if (y < minY) y = minY; if (y >= maxY) y = maxY - 1; } /* Window -> canvas */ x += tree->xOrigin; y += tree->yOrigin; if (nearest) { if (x < 0) x = 0; if (x >= Tree_TotalWidth(tree)) x = Tree_TotalWidth(tree) - 1; if (y < 0) y = 0; if (y >= Tree_TotalHeight(tree)) y = Tree_TotalHeight(tree) - 1; } else { if (x < 0) return NULL; if (x >= Tree_TotalWidth(tree)) return NULL; if (y < 0) return NULL; if (y >= Tree_TotalHeight(tree)) return NULL; } if (tree->vertical) { while (range != NULL) { if ((x >= range->offset) && (x < range->offset + range->totalWidth)) { if (nearest || (y < range->totalHeight)) { (*x_) = x - range->offset; (*y_) = MIN(y, range->totalHeight - 1); return range; } return NULL; } range = range->next; } return NULL; } else { while (range != NULL) { if ((y >= range->offset) && (y < range->offset + range->totalHeight)) { if (nearest || (x < range->totalWidth)) { (*x_) = MIN(x, range->totalWidth - 1); (*y_) = y - range->offset; return range; } return NULL; } range = range->next; } return NULL; } } /* *---------------------------------------------------------------------- * * Range_ItemUnderPoint -- * * Return the RItem containing the given x and/or y coordinates. * * Results: * RItem containing the coordinates. Panics() if no RItem is found. * * Side effects: * None. * *---------------------------------------------------------------------- */ static RItem * Range_ItemUnderPoint( TreeCtrl *tree, /* Widget info. */ Range *range, /* Range to search. */ int *x_, /* In: x coordinate relative to top-left of * the Range. * Out: x coordinate relative to top-left of * the returned RItem. * May be NULL if y_ is not NULL. */ int *y_ /* In: y coordinate relative to top-left of * the Range. * Out: y coordinate relative to top-left of * the returned RItem. * May be NULL if x_ is not NULL. */ ) { RItem *rItem; int x = -666, y = -666; int i, l, u; if (x_ != NULL) { x = (*x_); if (x < 0 || x >= range->totalWidth) goto panicNow; } if (y_ != NULL) { y = (*y_); if (y < 0 || y >= range->totalHeight) goto panicNow; } if (tree->vertical) { /* Binary search */ l = 0; u = range->last->index; while (l <= u) { i = (l + u) / 2; rItem = range->first + i; if ((y >= rItem->offset) && (y < rItem->offset + rItem->size)) { /* Range -> item coords */ if (x_ != NULL) (*x_) = x; if (y_ != NULL) (*y_) = y - rItem->offset; return rItem; } if (y < rItem->offset) u = i - 1; else l = i + 1; } } else { /* Binary search */ l = 0; u = range->last->index; while (l <= u) { i = (l + u) / 2; rItem = range->first + i; if ((x >= rItem->offset) && (x < rItem->offset + rItem->size)) { /* Range -> item coords */ if (x_ != NULL) (*x_) = x - rItem->offset; if (y_ != NULL) (*y_) = y; return rItem; } if (x < rItem->offset) u = i - 1; else l = i + 1; } } panicNow: panic("Range_ItemUnderPoint: can't find TreeItem in Range: x %d y %d W %d H %d", x, y, range->totalWidth, range->totalHeight); return NULL; } /* *---------------------------------------------------------------------- * * Increment_AddX -- * * Appends one or more values to the list of horizontal scroll * increments. * * Results: * New size of DInfo.xScrollIncrements. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static int Increment_AddX( TreeCtrl *tree, /* Widget info. */ int offset, /* Offset to add. */ int size /* Current size of DInfo.xScrollIncrements. */ ) { TreeDInfo dInfo = tree->dInfo; int visWidth = Tree_ContentWidth(tree); while ((visWidth > 1) && (dInfo->xScrollIncrementCount > 0) && (offset - dInfo->xScrollIncrements[dInfo->xScrollIncrementCount - 1] > visWidth)) { size = Increment_AddX(tree, dInfo->xScrollIncrements[dInfo->xScrollIncrementCount - 1] + visWidth, size); } if (dInfo->xScrollIncrementCount + 1 > size) { size *= 2; dInfo->xScrollIncrements = (int *) ckrealloc( (char *) dInfo->xScrollIncrements, size * sizeof(int)); } dInfo->xScrollIncrements[dInfo->xScrollIncrementCount++] = offset; return size; } /* *---------------------------------------------------------------------- * * Increment_AddY -- * * Appends one or more values to the list of vertical scroll * increments. * * Results: * New size of DInfo.yScrollIncrements. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static int Increment_AddY( TreeCtrl *tree, /* Widget info. */ int offset, /* Offset to add. */ int size /* Current size of DInfo.yScrollIncrements. */ ) { TreeDInfo dInfo = tree->dInfo; int visHeight = Tree_ContentHeight(tree); while ((visHeight > 1) && (dInfo->yScrollIncrementCount > 0) && (offset - dInfo->yScrollIncrements[dInfo->yScrollIncrementCount - 1] > visHeight)) { size = Increment_AddY(tree, dInfo->yScrollIncrements[dInfo->yScrollIncrementCount - 1] + visHeight, size); } if (dInfo->yScrollIncrementCount + 1 > size) { size *= 2; dInfo->yScrollIncrements = (int *) ckrealloc( (char *) dInfo->yScrollIncrements, size * sizeof(int)); } dInfo->yScrollIncrements[dInfo->yScrollIncrementCount++] = offset; return size; } /* *---------------------------------------------------------------------- * * RItemsToIncrementsX -- * * Recalculate the list of horizontal scroll increments. This gets * called when the TreeCtrl -orient option is "horizontal" and * -xscrollincrement option is "". * * Results: * DInfo.xScrollIncrements is updated if the canvas width is > 0. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void RItemsToIncrementsX( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range, *rangeFirst = dInfo->rangeFirst; RItem *rItem; int visWidth = Tree_ContentWidth(tree); int totalWidth = Tree_TotalWidth(tree); int x1, x2, x; int size; if (totalWidth <= 0 /* dInfo->rangeFirst == NULL */) return; size = 10; dInfo->xScrollIncrements = (int *) ckalloc(size * sizeof(int)); if (rangeFirst == NULL) { /* Only the column headers are shown. */ } else if (rangeFirst->next == NULL) { /* A single horizontal range is easy. Add one increment for the * left edge of each item. */ rItem = rangeFirst->first; while (1) { size = Increment_AddX(tree, rItem->offset, size); if (rItem == rangeFirst->last) break; rItem++; } } else { /* First increment is zero */ dInfo->xScrollIncrements[dInfo->xScrollIncrementCount++] = 0; x1 = 0; while (1) { x2 = totalWidth; for (range = rangeFirst; range != NULL; range = range->next) { if (x1 >= range->totalWidth) continue; /* Find RItem whose right side is >= x1 by smallest amount */ x = x1; rItem = Range_ItemUnderPoint(tree, range, &x, NULL); if (rItem->offset + rItem->size < x2) x2 = rItem->offset + rItem->size; } if (x2 == totalWidth) break; size = Increment_AddX(tree, x2, size); x1 = x2; } } if ((visWidth > 1) && (totalWidth - dInfo->xScrollIncrements[dInfo->xScrollIncrementCount - 1] > visWidth)) { Increment_AddX(tree, totalWidth, size); dInfo->xScrollIncrementCount--; dInfo->xScrollIncrements[dInfo->xScrollIncrementCount - 1] = totalWidth - visWidth; } } /* *---------------------------------------------------------------------- * * RItemsToIncrementsY -- * * Recalculate the list of vertical scroll increments. This gets * called when the TreeCtrl -orient option is "vertical" and * -yscrollincrement option is "". * * Results: * DInfo.yScrollIncrements is updated if the canvas height is > 0. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void RItemsToIncrementsY( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range, *rangeFirst; RItem *rItem; int visHeight = Tree_ContentHeight(tree); int totalHeight = Tree_TotalHeight(tree); int y1, y2, y; int size; if (totalHeight <= 0 /* dInfo->rangeFirst == NULL */) return; size = 10; dInfo->yScrollIncrements = (int *) ckalloc(size * sizeof(int)); /* If only locked columns are visible, we still scroll vertically. */ rangeFirst = dInfo->rangeFirst; if (rangeFirst == NULL) rangeFirst = dInfo->rangeLock; if (rangeFirst->next == NULL) { /* A single vertical range is easy. Add one increment for the * top edge of each item. */ rItem = rangeFirst->first; while (1) { size = Increment_AddY(tree, rItem->offset, size); if (rItem == rangeFirst->last) break; rItem++; } } else { /* First increment is zero */ dInfo->yScrollIncrements[dInfo->yScrollIncrementCount++] = 0; y1 = 0; while (1) { y2 = totalHeight; for (range = rangeFirst; range != NULL; range = range->next) { if (y1 >= range->totalHeight) continue; /* Find RItem whose bottom edge is >= y1 by smallest amount */ y = y1; rItem = Range_ItemUnderPoint(tree, range, NULL, &y); if (rItem->offset + rItem->size < y2) y2 = rItem->offset + rItem->size; } if (y2 == totalHeight) break; size = Increment_AddY(tree, y2, size); y1 = y2; } } if ((visHeight > 1) && (totalHeight - dInfo->yScrollIncrements[dInfo->yScrollIncrementCount - 1] > visHeight)) { size = Increment_AddY(tree, totalHeight, size); dInfo->yScrollIncrementCount--; dInfo->yScrollIncrements[dInfo->yScrollIncrementCount - 1] = totalHeight - visHeight; } } /* *---------------------------------------------------------------------- * * RangesToIncrementsX -- * * Recalculate the list of horizontal scroll increments. This gets * called when the TreeCtrl -orient option is "vertical" and * -xscrollincrement option is "". * * Results: * DInfo.xScrollIncrements is updated if there are any Ranges. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void RangesToIncrementsX( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range = dInfo->rangeFirst; int visWidth = Tree_ContentWidth(tree); int totalWidth = Tree_TotalWidth(tree); int size; if (totalWidth <= visWidth) return; /* First increment is zero */ size = 10; dInfo->xScrollIncrements = (int *) ckalloc(size * sizeof(int)); dInfo->xScrollIncrements[dInfo->xScrollIncrementCount++] = 0; if (dInfo->rangeFirst != NULL) { range = dInfo->rangeFirst->next; while (range != NULL) { size = Increment_AddX(tree, range->offset, size); range = range->next; } } if ((visWidth > 1) && (totalWidth - dInfo->xScrollIncrements[dInfo->xScrollIncrementCount - 1] > visWidth)) { size = Increment_AddX(tree, totalWidth, size); dInfo->xScrollIncrementCount--; dInfo->xScrollIncrements[dInfo->xScrollIncrementCount - 1] = totalWidth - visWidth; } } /* *---------------------------------------------------------------------- * * RangesToIncrementsY -- * * Recalculate the list of vertical scroll increments. This gets * called when the TreeCtrl -orient option is "horizontal" and * -yscrollincrement option is "". * * Results: * DInfo.yScrollIncrements is updated if there are any Ranges. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void RangesToIncrementsY( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range = dInfo->rangeFirst; int visHeight = Tree_ContentHeight(tree); int totalHeight = Tree_TotalHeight(tree); int size; if (dInfo->rangeFirst == NULL) return; /* First increment is zero */ size = 10; dInfo->yScrollIncrements = (int *) ckalloc(size * sizeof(int)); dInfo->yScrollIncrements[dInfo->yScrollIncrementCount++] = 0; range = dInfo->rangeFirst->next; while (range != NULL) { size = Increment_AddY(tree, range->offset, size); range = range->next; } if ((visHeight > 1) && (totalHeight - dInfo->yScrollIncrements[dInfo->yScrollIncrementCount - 1] > visHeight)) { size = Increment_AddY(tree, totalHeight, size); dInfo->yScrollIncrementCount--; dInfo->yScrollIncrements[dInfo->yScrollIncrementCount - 1] = totalHeight - visHeight; } } /* *---------------------------------------------------------------------- * * Increment_Redo -- * * Recalculate the lists of scroll increments. * * Results: * DInfo.xScrollIncrements and DInfo.xScrollIncrements are updated. * Either may be set to NULL. The old values are freed, if any. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Increment_Redo( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; /* Free x */ if (dInfo->xScrollIncrements != NULL) ckfree((char *) dInfo->xScrollIncrements); dInfo->xScrollIncrements = NULL; dInfo->xScrollIncrementCount = 0; /* Free y */ if (dInfo->yScrollIncrements != NULL) ckfree((char *) dInfo->yScrollIncrements); dInfo->yScrollIncrements = NULL; dInfo->yScrollIncrementCount = 0; if (tree->vertical) { /* No xScrollIncrement is given. Snap to left edge of a Range */ if (tree->xScrollIncrement <= 0) RangesToIncrementsX(tree); /* No yScrollIncrement is given. Snap to top edge of a TreeItem */ if (tree->yScrollIncrement <= 0) RItemsToIncrementsY(tree); } else { /* No xScrollIncrement is given. Snap to left edge of a TreeItem */ if (tree->xScrollIncrement <= 0) RItemsToIncrementsX(tree); /* No yScrollIncrement is given. Snap to top edge of a Range */ if (tree->yScrollIncrement <= 0) RangesToIncrementsY(tree); } } /* *---------------------------------------------------------------------- * * Increment_RedoIfNeeded -- * * Recalculate the lists of scroll increments if needed. * * Results: * DInfo.xScrollIncrements and DInfo.xScrollIncrements may be * updated. * * Side effects: * Memory may be allocated. The list of Ranges will be recalculated * if needed. * *---------------------------------------------------------------------- */ static void Increment_RedoIfNeeded( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range_RedoIfNeeded(tree); /* Check for x|yScrollIncrement >0 changing to <=0 */ if (((dInfo->yScrollIncrement > 0) != (tree->yScrollIncrement > 0)) || ((dInfo->xScrollIncrement > 0) != (tree->xScrollIncrement > 0))) { dInfo->yScrollIncrement = tree->yScrollIncrement; dInfo->xScrollIncrement = tree->xScrollIncrement; dInfo->flags |= DINFO_REDO_INCREMENTS; } if (dInfo->flags & DINFO_REDO_INCREMENTS) { Increment_Redo(tree); dInfo->flags &= ~DINFO_REDO_INCREMENTS; } } /* *---------------------------------------------------------------------- * * B_IncrementFind -- * * Search a list of increments and return one nearest to the * given offset. * * Results: * Index of the nearest increment <= the given offset. * Panic() if no appropriate offset if found. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int B_IncrementFind( int *increments, /* DInfo.x|yScrollIncrements. */ int count, /* Length of increments[]. */ int offset /* Offset to search with. */ ) { int i, l, u, v; if (offset < 0) offset = 0; /* Binary search */ l = 0; u = count - 1; while (l <= u) { i = (l + u) / 2; v = increments[i]; if ((offset >= v) && ((i == count - 1) || (offset < increments[i + 1]))) return i; if (offset < v) u = i - 1; else l = i + 1; } panic("B_IncrementFind failed (count %d offset %d)", count, offset); return -1; } /* *---------------------------------------------------------------------- * * B_IncrementFindX -- * * Search DInfo.xScrollIncrements and return one nearest to the * given offset. * * Results: * Index of the nearest increment <= the given offset. * Panic() if no appropriate offset if found. * * Side effects: * None. * *---------------------------------------------------------------------- */ int B_IncrementFindX( TreeCtrl *tree, /* Widget info. */ int offset /* Offset to search with. */ ) { TreeDInfo dInfo = tree->dInfo; return B_IncrementFind( dInfo->xScrollIncrements, dInfo->xScrollIncrementCount, offset); } /* *---------------------------------------------------------------------- * * B_IncrementFindY -- * * Search DInfo.yScrollIncrements and return one nearest to the * given offset. * * Results: * Index of the nearest increment <= the given offset. * Panic() if no appropriate offset if found. * * Side effects: * None. * *---------------------------------------------------------------------- */ int B_IncrementFindY( TreeCtrl *tree, /* Widget info. */ int offset /* Offset to search with. */ ) { TreeDInfo dInfo = tree->dInfo; return B_IncrementFind( dInfo->yScrollIncrements, dInfo->yScrollIncrementCount, offset); } /* *-------------------------------------------------------------- * * B_XviewCmd -- * * This procedure is invoked to process the "xview" option for * the widget command for a TreeCtrl. See the user documentation * for details on what it does. * * NOTE: This procedure is called when the -xscrollincrement option * is unspecified. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ int B_XviewCmd( TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tcl_Interp *interp = tree->interp; TreeDInfo dInfo = tree->dInfo; if (objc == 2) { double fractions[2]; Tree_GetScrollFractionsX(tree, fractions); FormatResult(interp, "%g %g", fractions[0], fractions[1]); } else { int count, index = 0, indexMax, offset, type; double fraction; int visWidth = Tree_ContentWidth(tree); int totWidth = Tree_TotalWidth(tree); if (visWidth < 0) visWidth = 0; if (totWidth <= visWidth) return TCL_OK; if (visWidth > 1) { /* Find incrementLeft when scrolled to right */ indexMax = Increment_FindX(tree, totWidth - visWidth); offset = Increment_ToOffsetX(tree, indexMax); if (offset < totWidth - visWidth) { indexMax++; offset = Increment_ToOffsetX(tree, indexMax); } /* Add some fake content to right */ if (offset + visWidth > totWidth) totWidth = offset + visWidth; } else { indexMax = Increment_FindX(tree, totWidth); visWidth = 1; } type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count); switch (type) { case TK_SCROLL_ERROR: return TCL_ERROR; case TK_SCROLL_MOVETO: offset = (int) (fraction * totWidth + 0.5); index = Increment_FindX(tree, offset); break; case TK_SCROLL_PAGES: offset = Tree_ContentLeft(tree) + tree->xOrigin; offset += (int) (count * visWidth * 0.9); index = Increment_FindX(tree, offset); if ((count > 0) && (index == Increment_FindX(tree, Tree_ContentLeft(tree) + tree->xOrigin))) index++; break; case TK_SCROLL_UNITS: index = dInfo->incrementLeft + count; break; } /* Don't scroll too far left */ if (index < 0) index = 0; /* Don't scroll too far right */ if (index > indexMax) index = indexMax; offset = Increment_ToOffsetX(tree, index); if ((index != dInfo->incrementLeft) || (tree->xOrigin != offset - Tree_ContentLeft(tree))) { dInfo->incrementLeft = index; tree->xOrigin = offset - Tree_ContentLeft(tree); Tree_EventuallyRedraw(tree); } } return TCL_OK; } /* *-------------------------------------------------------------- * * B_YviewCmd -- * * This procedure is invoked to process the "yview" option for * the widget command for a TreeCtrl. See the user documentation * for details on what it does. * * NOTE: This procedure is called when the -yscrollincrement option * is unspecified. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ int B_YviewCmd( TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tcl_Interp *interp = tree->interp; TreeDInfo dInfo = tree->dInfo; if (objc == 2) { double fractions[2]; Tree_GetScrollFractionsY(tree, fractions); FormatResult(interp, "%g %g", fractions[0], fractions[1]); } else { int count, index = 0, indexMax, offset, type; double fraction; int visHeight = Tree_ContentHeight(tree); int totHeight = Tree_TotalHeight(tree); if (visHeight < 0) visHeight = 0; if (totHeight <= visHeight) return TCL_OK; if (visHeight > 1) { /* Find incrementTop when scrolled to bottom */ indexMax = Increment_FindY(tree, totHeight - visHeight); offset = Increment_ToOffsetY(tree, indexMax); if (offset < totHeight - visHeight) { indexMax++; offset = Increment_ToOffsetY(tree, indexMax); } /* Add some fake content to bottom */ if (offset + visHeight > totHeight) totHeight = offset + visHeight; } else { indexMax = Increment_FindY(tree, totHeight); visHeight = 1; } type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count); switch (type) { case TK_SCROLL_ERROR: return TCL_ERROR; case TK_SCROLL_MOVETO: offset = (int) (fraction * totHeight + 0.5); index = Increment_FindY(tree, offset); break; case TK_SCROLL_PAGES: offset = Tree_ContentTop(tree) + tree->yOrigin; offset += (int) (count * visHeight * 0.9); index = Increment_FindY(tree, offset); if ((count > 0) && (index == Increment_FindY(tree, Tree_ContentTop(tree) + tree->yOrigin))) index++; break; case TK_SCROLL_UNITS: index = dInfo->incrementTop + count; break; } /* Don't scroll too far up */ if (index < 0) index = 0; /* Don't scroll too far down */ if (index > indexMax) index = indexMax; offset = Increment_ToOffsetY(tree, index); if ((index != dInfo->incrementTop) || (tree->yOrigin != offset - Tree_ContentTop(tree))) { dInfo->incrementTop = index; tree->yOrigin = offset - Tree_ContentTop(tree); Tree_EventuallyRedraw(tree); } } return TCL_OK; } /* *-------------------------------------------------------------- * * Tree_ItemUnderPoint -- * * Return a TreeItem containing the given coordinates. * * Results: * TreeItem token or NULL if no item contains the point. * * Side effects: * The list of Ranges will be recalculated if needed. * *-------------------------------------------------------------- */ TreeItem Tree_ItemUnderPoint( TreeCtrl *tree, /* Widget info. */ int *x_, int *y_, /* In: window coordinates. * Out: coordinates relative to top-left * corner of the returned item. */ int nearest /* TRUE if the item nearest the coordinates * should be returned. */ ) { Range *range; RItem *rItem; int hit; hit = Tree_HitTest(tree, *x_, *y_); if (!nearest && ((hit == TREE_AREA_LEFT) || (hit == TREE_AREA_RIGHT))) { TreeDInfo dInfo = tree->dInfo; Range_RedoIfNeeded(tree); range = dInfo->rangeFirst; /* If range is NULL use dInfo->rangeLock. */ if (range == NULL) { if (dInfo->rangeLock == NULL) return NULL; range = dInfo->rangeLock; } if (*y_ + tree->yOrigin < range->totalHeight) { int x = *x_; int y = *y_; if (hit == TREE_AREA_RIGHT) { x -= Tree_ContentRight(tree); } else { x -= Tree_BorderLeft(tree); } /* Window -> canvas */ y += tree->yOrigin; rItem = Range_ItemUnderPoint(tree, range, NULL, &y); *x_ = x; *y_ = y; return rItem->item; } return NULL; } range = Range_UnderPoint(tree, x_, y_, nearest); if (range == NULL) return NULL; rItem = Range_ItemUnderPoint(tree, range, x_, y_); if (rItem != NULL) return rItem->item; return NULL; } /* *-------------------------------------------------------------- * * Tree_AreaBbox -- * * Return the bounding box of a visible area. * * Results: * Return value is TRUE if the area is non-empty. * * Side effects: * Column and item layout will be updated if needed. * *-------------------------------------------------------------- */ int Tree_AreaBbox( TreeCtrl *tree, int area, int *x1_, int *y1_, int *x2_, int *y2_ ) { int x1 = 0, y1 = 0, x2 = 0, y2 = 0; switch (area) { case TREE_AREA_HEADER: x1 = Tree_BorderLeft(tree); y1 = Tree_BorderTop(tree); x2 = Tree_BorderRight(tree); y2 = Tree_ContentTop(tree); break; case TREE_AREA_CONTENT: x1 = Tree_ContentLeft(tree); y1 = Tree_ContentTop(tree); x2 = Tree_ContentRight(tree); y2 = Tree_ContentBottom(tree); break; case TREE_AREA_LEFT: x1 = Tree_BorderLeft(tree); y1 = Tree_ContentTop(tree); x2 = Tree_ContentLeft(tree); y2 = Tree_ContentBottom(tree); /* Don't overlap right-locked columns. */ if (x2 > Tree_ContentRight(tree)) x2 = Tree_ContentRight(tree); break; case TREE_AREA_RIGHT: x1 = Tree_ContentRight(tree); y1 = Tree_ContentTop(tree); x2 = Tree_BorderRight(tree); y2 = Tree_ContentBottom(tree); break; } if (x2 <= x1 || y2 <= y1) return FALSE; if (x1 < Tree_BorderLeft(tree)) x1 = Tree_BorderLeft(tree); if (x2 > Tree_BorderRight(tree)) x2 = Tree_BorderRight(tree); if (y1 < Tree_BorderTop(tree)) y1 = Tree_BorderTop(tree); if (y2 > Tree_BorderBottom(tree)) y2 = Tree_BorderBottom(tree); *x1_ = x1; *y1_ = y1; *x2_ = x2; *y2_ = y2; return (x2 > x1) && (y2 > y1); } /* *-------------------------------------------------------------- * * Tree_HitTest -- * * Determine which are of the window contains the given point. * * Results: * Return value is one of the TREE_AREA_xxx constants. * * Side effects: * Column layout will be updated if needed. * *-------------------------------------------------------------- */ int Tree_HitTest( TreeCtrl *tree, int x, int y ) { if ((x < Tree_BorderLeft(tree)) || (x >= Tree_BorderRight(tree))) return TREE_AREA_NONE; if ((y < Tree_BorderTop(tree)) || (y >= Tree_BorderBottom(tree))) return TREE_AREA_NONE; if (y < Tree_HeaderBottom(tree)) { return TREE_AREA_HEADER; } /* Right-locked columns are drawn over the left. */ if (x >= Tree_ContentRight(tree)) { return TREE_AREA_RIGHT; } if (x < Tree_ContentLeft(tree)) { return TREE_AREA_LEFT; } if (Tree_ContentLeft(tree) >= Tree_ContentRight(tree)) { return TREE_AREA_NONE; } return TREE_AREA_CONTENT; } /* *-------------------------------------------------------------- * * Tree_ItemBbox -- * * Return the bounding box for an item. * * Results: * Return value is -1 if the item is not ReallyVisible() * or if there are no visible columns. The coordinates * are relative to the top-left corner of the canvas. * * Side effects: * Column layout will be updated if needed. * The list of Ranges will be recalculated if needed. * *-------------------------------------------------------------- */ int Tree_ItemBbox( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item whose bbox is needed. */ int lock, int *x, int *y, /* Returned left and top. */ int *w, int *h /* Returned width and height. */ ) { Range *range; RItem *rItem; if (!TreeItem_ReallyVisible(tree, item)) return -1; /* Update columnCountVisXXX if needed */ (void) Tree_WidthOfColumns(tree); Range_RedoIfNeeded(tree); rItem = (RItem *) TreeItem_GetRInfo(tree, item); switch (lock) { case COLUMN_LOCK_LEFT: if (tree->columnCountVisLeft == 0) return -1; *x = Tree_BorderLeft(tree) + tree->xOrigin; /* window -> canvas */ *y = rItem->offset; *w = Tree_WidthOfLeftColumns(tree); *h = rItem->size; return 0; case COLUMN_LOCK_NONE: break; case COLUMN_LOCK_RIGHT: if (tree->columnCountVisRight == 0) return -1; *x = Tree_ContentRight(tree) + tree->xOrigin; /* window -> canvas */ *y = rItem->offset; *w = Tree_WidthOfRightColumns(tree); *h = rItem->size; return 0; } if (tree->columnCountVis < 1) return -1; range = rItem->range; if (tree->vertical) { (*x) = range->offset; (*w) = range->totalWidth; (*y) = rItem->offset; (*h) = rItem->size; } else { (*x) = rItem->offset; (*w) = rItem->size; (*y) = range->offset; (*h) = range->totalHeight; } return 0; } /* *-------------------------------------------------------------- * * Tree_ItemLARB -- * * Return an adjacent item above, below, to the left or to the * right of the given item. * * Results: * An adjacent item or NULL if there is no such item. * * Side effects: * The list of Ranges will be recalculated if needed. * *-------------------------------------------------------------- */ TreeItem Tree_ItemLARB( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item to use as a reference. */ int vertical, /* TRUE if items are arranged * from top-to-bottom in each Range. */ int prev /* TRUE for above/left, * FALSE for below/right. */ ) { RItem *rItem, *rItem2; Range *range; int i, l, u; if (!TreeItem_ReallyVisible(tree, item) || (tree->columnCountVis < 1)) return NULL; Range_RedoIfNeeded(tree); rItem = (RItem *) TreeItem_GetRInfo(tree, item); if (vertical) { if (prev) { if (rItem == rItem->range->first) return NULL; rItem--; } else { if (rItem == rItem->range->last) return NULL; rItem++; } return rItem->item; } else { /* Find the previous range */ range = prev ? rItem->range->prev : rItem->range->next; if (range == NULL) return NULL; /* Find item with same index */ /* Binary search */ l = 0; u = range->last->index; while (l <= u) { i = (l + u) / 2; rItem2 = range->first + i; if (rItem2->index == rItem->index) return rItem2->item; if (rItem->index < rItem2->index) u = i - 1; else l = i + 1; } } return NULL; } TreeItem Tree_ItemLeft( TreeCtrl *tree, TreeItem item) { return Tree_ItemLARB(tree, item, !tree->vertical, TRUE); } TreeItem Tree_ItemAbove( TreeCtrl *tree, TreeItem item) { return Tree_ItemLARB(tree, item, tree->vertical, TRUE); } TreeItem Tree_ItemRight( TreeCtrl *tree, TreeItem item) { return Tree_ItemLARB(tree, item, !tree->vertical, FALSE); } TreeItem Tree_ItemBelow( TreeCtrl *tree, TreeItem item) { return Tree_ItemLARB(tree, item, tree->vertical, FALSE); } /* *-------------------------------------------------------------- * * Tree_ItemFL -- * * Return the first or last item in the same row or column * as the given item. * * Results: * First/last item or NULL if there is no such item. * * Side effects: * The list of Ranges will be recalculated if needed. * *-------------------------------------------------------------- */ TreeItem Tree_ItemFL( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item to use as a reference. */ int vertical, /* TRUE if items are arranged * from top-to-bottom in each Range. */ int first /* TRUE for top/left, * FALSE for bottom/right. */ ) { TreeDInfo dInfo = tree->dInfo; RItem *rItem, *rItem2; Range *range; int i, l, u; if (!TreeItem_ReallyVisible(tree, item) || (tree->columnCountVis < 1)) { return NULL; } Range_RedoIfNeeded(tree); rItem = (RItem *) TreeItem_GetRInfo(tree, item); if (vertical) { return (first ? rItem->range->first->item : rItem->range->last->item); } else { /* Find the first/last range */ range = first ? dInfo->rangeFirst : dInfo->rangeLast; /* Check next/prev range until happy */ while (1) { if (range == rItem->range) return item; /* Find item with same index */ /* Binary search */ l = 0; u = range->last->index; while (l <= u) { i = (l + u) / 2; rItem2 = range->first + i; if (rItem2->index == rItem->index) return rItem2->item; if (rItem->index < rItem2->index) u = i - 1; else l = i + 1; } range = first ? range->next : range->prev; } } return NULL; } TreeItem Tree_ItemTop( TreeCtrl *tree, TreeItem item) { return Tree_ItemFL(tree, item, tree->vertical, TRUE); } TreeItem Tree_ItemBottom( TreeCtrl *tree, TreeItem item) { return Tree_ItemFL(tree, item, tree->vertical, FALSE); } TreeItem Tree_ItemLeftMost( TreeCtrl *tree, TreeItem item) { return Tree_ItemFL(tree, item, !tree->vertical, TRUE); } TreeItem Tree_ItemRightMost( TreeCtrl *tree, TreeItem item) { return Tree_ItemFL(tree, item, !tree->vertical, FALSE); } /* *-------------------------------------------------------------- * * Tree_ItemToRNC -- * * Return the row and column for the given item. * * Results: * A standard Tcl result. * * Side effects: * The list of Ranges will be recalculated if needed. * *-------------------------------------------------------------- */ int Tree_ItemToRNC( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item to get row n' column of. */ int *row, int *col /* Returned row and column. */ ) { RItem *rItem; if (!TreeItem_ReallyVisible(tree, item) || (tree->columnCountVis < 1)) return TCL_ERROR; Range_RedoIfNeeded(tree); rItem = (RItem *) TreeItem_GetRInfo(tree, item); if (tree->vertical) { (*row) = rItem->index; (*col) = rItem->range->index; } else { (*row) = rItem->range->index; (*col) = rItem->index; } return TCL_OK; } /* *-------------------------------------------------------------- * * Tree_RNCToItem -- * * Return the item at a given row and column. * * Results: * Token for the item. Never returns NULL unless there are no * Ranges. * * Side effects: * The list of Ranges will be recalculated if needed. * *-------------------------------------------------------------- */ TreeItem Tree_RNCToItem( TreeCtrl *tree, /* Widget info. */ int row, int col /* Row and column. These values are * clipped to valid values. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range; RItem *rItem; int i, l, u; Range_RedoIfNeeded(tree); range = dInfo->rangeFirst; if (range == NULL) return NULL; if (row < 0) row = 0; if (col < 0) col = 0; if (tree->vertical) { if (col > dInfo->rangeLast->index) col = dInfo->rangeLast->index; while (range->index != col) range = range->next; rItem = range->last; if (row > rItem->index) row = rItem->index; /* Binary search */ l = 0; u = range->last->index; while (l <= u) { i = (l + u) / 2; rItem = range->first + i; if (rItem->index == row) break; if (row < rItem->index) u = i - 1; else l = i + 1; } } else { if (row > dInfo->rangeLast->index) row = dInfo->rangeLast->index; while (range->index != row) range = range->next; rItem = range->last; if (col > rItem->index) col = rItem->index; /* Binary search */ l = 0; u = range->last->index; while (l <= u) { i = (l + u) / 2; rItem = range->first + i; if (rItem->index == col) break; if (col < rItem->index) u = i - 1; else l = i + 1; } } return rItem->item; } /*=============*/ static void DisplayDelay(TreeCtrl *tree) { if (tree->debug.enable && tree->debug.display && tree->debug.displayDelay > 0) { #if !defined(WIN32) && !defined(MAC_TCL) && !defined(MAC_OSX_TK) XSync(tree->display, False); #endif Tcl_Sleep(tree->debug.displayDelay); } } /* *-------------------------------------------------------------- * * DItem_Alloc -- * * Allocate and initialize a new DItem, and store a pointer to it * in the given item. * * Results: * Pointer to the DItem which may come from an existing pool of * unused DItems. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ static DItem * DItem_Alloc( TreeCtrl *tree, /* Widget info. */ RItem *rItem /* Range info for the item. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; dItem = (DItem *) TreeItem_GetDInfo(tree, rItem->item); if (dItem != NULL) panic("tried to allocate duplicate DItem"); /* Pop unused DItem from stack */ if (dInfo->dItemFree != NULL) { dItem = dInfo->dItemFree; dInfo->dItemFree = dItem->next; /* No free DItems, alloc a new one */ } else { dItem = (DItem *) ckalloc(sizeof(DItem)); } memset(dItem, '\0', sizeof(DItem)); #ifdef TREECTRL_DEBUG strncpy(dItem->magic, "MAGC", 4); #endif dItem->item = rItem->item; dItem->area.flags = DITEM_DIRTY | DITEM_ALL_DIRTY; dItem->left.flags = DITEM_DIRTY | DITEM_ALL_DIRTY; dItem->right.flags = DITEM_DIRTY | DITEM_ALL_DIRTY; TreeItem_SetDInfo(tree, rItem->item, (TreeItemDInfo) dItem); return dItem; } /* *-------------------------------------------------------------- * * DItem_Unlink -- * * Remove a DItem from a linked list of DItems. * * Results: * Pointer to the given list of DItems. * * Side effects: * None. * *-------------------------------------------------------------- */ static DItem * DItem_Unlink( DItem *head, /* First in linked list. */ DItem *dItem /* DItem to remove from list. */ ) { DItem *prev; if (head == dItem) head = dItem->next; else { for (prev = head; prev->next != dItem; prev = prev->next) { /* nothing */ } prev->next = dItem->next; } dItem->next = NULL; return head; } /* *-------------------------------------------------------------- * * DItem_Free -- * * Add a DItem to the pool of unused DItems. If the DItem belongs * to a TreeItem the pointer to the DItem is set to NULL in that * TreeItem. * * Results: * Pointer to the next DItem. * * Side effects: * None. * *-------------------------------------------------------------- */ static DItem * DItem_Free( TreeCtrl *tree, /* Widget info. */ DItem *dItem /* DItem to free. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *next = dItem->next; #ifdef TREECTRL_DEBUG if (strncmp(dItem->magic, "MAGC", 4) != 0) panic("DItem_Free: dItem.magic != MAGC"); #endif if (dItem->item != NULL) { TreeItem_SetDInfo(tree, dItem->item, (TreeItemDInfo) NULL); dItem->item = NULL; } /* Push unused DItem on the stack */ dItem->next = dInfo->dItemFree; dInfo->dItemFree = dItem; return next; } /* *-------------------------------------------------------------- * * FreeDItems -- * * Add a list of DItems to the pool of unused DItems, * optionally removing the DItems from the DInfo.dItem list. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static void FreeDItems( TreeCtrl *tree, /* Widget info. */ DItem *first, /* First DItem to free. */ DItem *last, /* DItem after the last one to free. */ int unlink /* TRUE if the DItems should be removed * from the DInfo.dItem list. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *prev; if (unlink) { if (dInfo->dItem == first) dInfo->dItem = last; else { for (prev = dInfo->dItem; prev->next != first; prev = prev->next) { /* nothing */ } prev->next = last; } } while (first != last) first = DItem_Free(tree, first); } /* *-------------------------------------------------------------- * * Tree_ItemsInArea -- * * Return a list of items overlapping the given area. * * Results: * Initializes the given TreeItemList and appends any items * in the given area. * * Side effects: * The list of Ranges will be recalculated if needed. Memory may * be allocated. * *-------------------------------------------------------------- */ void Tree_ItemsInArea( TreeCtrl *tree, /* Widget info. */ TreeItemList *items, /* Uninitialized list. The caller must free * it with TreeItemList_Free. */ int minX, int minY, /* Left, top in canvas coordinates. */ int maxX, int maxY /* Right, bottom in canvas coordinates. * Points on the right/bottom edge are not * included in the area. */ ) { TreeDInfo dInfo = tree->dInfo; int x, y, rx = 0, ry = 0, ix, iy, dx, dy; Range *range; RItem *rItem; TreeItemList_Init(tree, items, 0); Range_RedoIfNeeded(tree); range = dInfo->rangeFirst; if (tree->vertical) { /* Find the first range which could be in the area horizontally */ while (range != NULL) { if ((range->offset < maxX) && (range->offset + range->totalWidth >= minX)) { rx = range->offset; ry = 0; break; } range = range->next; } } else { /* Find the first range which could be in the area vertically */ while (range != NULL) { if ((range->offset < maxY) && (range->offset + range->totalHeight >= minY)) { rx = 0; ry = range->offset; break; } range = range->next; } } if (range == NULL) return; while (range != NULL) { if ((rx + range->totalWidth > minX) && (ry + range->totalHeight > minY)) { if (tree->vertical) { /* Range coords */ dx = MAX(minX - rx, 0); dy = minY; } else { dx = minX; dy = MAX(minY - ry, 0); } ix = dx; iy = dy; rItem = Range_ItemUnderPoint(tree, range, &ix, &iy); /* Canvas coords of top-left of item */ x = rx + dx - ix; y = ry + dy - iy; while (1) { TreeItemList_Append(items, rItem->item); if (tree->vertical) { y += rItem->size; if (y >= maxY) break; } else { x += rItem->size; if (x >= maxX) break; } if (rItem == range->last) break; rItem++; } } if (tree->vertical) { if (rx + range->totalWidth >= maxX) break; rx += range->totalWidth; } else { if (ry + range->totalHeight >= maxY) break; ry += range->totalHeight; } range = range->next; } } #define DCOLUMN #ifdef DCOLUMN /* *-------------------------------------------------------------- * * GetOnScreenColumnsForItemAux -- * * Determine which columns of an item are onscreen. * * Results: * Sets the column list. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ static void GetOnScreenColumnsForItemAux( TreeCtrl *tree, /* Widget info. */ DItem *dItem, /* Display info for an item. */ DItemArea *area, /* Layout info. */ int bounds[4], /* TREE_AREA_xxx bounds. */ int lock, /* Set of columns we care about. */ TreeColumnList *columns /* Initialized list to append to. */ ) { int minX, maxX, columnIndex = 0, x = 0, i, width; TreeColumn column = NULL, column2; minX = MAX(area->x, bounds[0]); maxX = MIN(area->x + area->width, bounds[2]); minX -= area->x; maxX -= area->x; switch (lock) { case COLUMN_LOCK_LEFT: column = tree->columnLockLeft; break; case COLUMN_LOCK_NONE: column = tree->columnLockNone; break; case COLUMN_LOCK_RIGHT: column = tree->columnLockRight; break; } for (columnIndex = TreeColumn_Index(column); columnIndex < tree->columnCount; columnIndex++) { if (TreeColumn_Lock(column) != lock) break; column2 = TreeColumn_Next(column); width = TreeColumn_GetDInfo(column)->width; if (width == 0) /* also handles hidden columns */ goto next; if (dItem->spans != NULL) { /* FIXME: not possible since I skip over the entire span. */ if (dItem->spans[columnIndex] != columnIndex) goto next; /* Calculate the width of the span. */ for (i = columnIndex + 1; i < tree->columnCount && dItem->spans[i] == columnIndex; i++) { width += TreeColumn_GetDInfo(column2)->width; column2 = TreeColumn_Next(column2); } columnIndex = i - 1; } if (x < maxX && x + width > minX) { TreeColumnList_Append(columns, column); } next: x += width; if (x >= maxX) break; column = column2; } } /* *-------------------------------------------------------------- * * GetOnScreenColumnsForItem -- * * Determine which columns of an item are onscreen. * * Results: * Sets the column list. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ static int GetOnScreenColumnsForItem( TreeCtrl *tree, /* Widget info. */ DItem *dItem, /* Display info for an item. */ TreeColumnList *columns /* Initialized list to append to. */ ) { TreeDInfo dInfo = tree->dInfo; if (!dInfo->emptyL) { GetOnScreenColumnsForItemAux(tree, dItem, &dItem->left, dInfo->boundsL, COLUMN_LOCK_LEFT, columns); } if (!dInfo->empty && dInfo->rangeFirst != NULL) { GetOnScreenColumnsForItemAux(tree, dItem, &dItem->area, dInfo->bounds, COLUMN_LOCK_NONE, columns); } if (!dInfo->emptyR) { GetOnScreenColumnsForItemAux(tree, dItem, &dItem->right, dInfo->boundsR, COLUMN_LOCK_RIGHT, columns); } return TreeColumnList_Count(columns); } /* *-------------------------------------------------------------- * * TrackOnScreenColumnsForItem -- * * Compares the list of onscreen columns for an item to the * list of previously-onscreen columns for the item. * * Results: * Hides window elements for columns that are no longer * onscreen. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ static void TrackOnScreenColumnsForItem( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ Tcl_HashEntry *hPtr /* DInfo.itemVisHash entry. */ ) { TreeColumnList columns; TreeColumn column, *value; DItem *dItem; int i, j, count = 0, n = 0; Tcl_DString dString; TreeColumnList_Init(tree, &columns, 0); Tcl_DStringInit(&dString); /* dItem is NULL if the item just went offscreen. */ dItem = (DItem *) TreeItem_GetDInfo(tree, item); if (dItem != NULL) count = GetOnScreenColumnsForItem(tree, dItem, &columns); if (tree->debug.enable && tree->debug.span) DStringAppendf(&dString, "onscreen columns for item %d:", TreeItem_GetID(tree, item)); /* value is NULL if the item just came onscreen. */ value = (TreeColumn *) Tcl_GetHashValue(hPtr); if (value == NULL) { value = (TreeColumn *) ckalloc(sizeof(TreeColumn) * (count + 1)); value[0] = NULL; } /* Track newly-visible columns */ for (i = 0; i < count; i++) { column = TreeColumnList_Nth(&columns, i); for (j = 0; value[j] != NULL; j++) { if (column == value[j]) break; } if (value[j] == NULL) { if (tree->debug.enable && tree->debug.span) DStringAppendf(&dString, " +%d", TreeColumn_GetID(column)); n++; } } /* Track newly-hidden columns */ for (j = 0; value[j] != NULL; j++) { column = value[j]; for (i = 0; i < count; i++) { if (TreeColumnList_Nth(&columns, i) == column) break; } if (i == count) { TreeItemColumn itemColumn = TreeItem_FindColumn(tree, item, TreeColumn_Index(column)); if (itemColumn != NULL) { TreeStyle style = TreeItemColumn_GetStyle(tree, itemColumn); if (style != NULL) TreeStyle_OnScreen(tree, style, FALSE); } if (tree->debug.enable && tree->debug.span) DStringAppendf(&dString, " -%d", TreeColumn_GetID(column)); n++; } } if (n && tree->debug.enable && tree->debug.span) dbwin("%s\n", Tcl_DStringValue(&dString)); /* Set the list of onscreen columns unless it is the same or the item * is hidden. */ if (n > 0 && dItem != NULL) { value = (TreeColumn *) ckrealloc((char *) value, sizeof(TreeColumn) * (count + 1)); memcpy(value, (TreeColumn *) columns.pointers, sizeof(TreeColumn) * count); value[count] = NULL; Tcl_SetHashValue(hPtr, (ClientData) value); } Tcl_DStringFree(&dString); TreeColumnList_Free(&columns); } #endif /* DCOLUMN */ /* *-------------------------------------------------------------- * * UpdateDInfoForRange -- * * Allocates or updates a DItem for every on-screen item in a Range. * If an item already has a DItem (because the item was previously * displayed), then the DItem may be marked dirty if there were * changes to the item's on-screen size or position. * * Results: * The return value is the possibly-updated dItemHead. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ static DItem * UpdateDInfoForRange( TreeCtrl *tree, /* Widget info. */ DItem *dItemHead, /* Linked list of used DItems. */ Range *range, /* Range to update DItems for. */ RItem *rItem, /* First item in the Range we care about. */ int x, int y /* Left & top window coordinates of rItem. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; DItemArea *area; TreeItem item; int maxX, maxY; int index, indexVis; int bgImgWidth, bgImgHeight; if (tree->backgroundImage != NULL) Tk_SizeOfImage(tree->backgroundImage, &bgImgWidth, &bgImgHeight); maxX = Tree_ContentRight(tree); maxY = Tree_ContentBottom(tree); /* Top-to-bottom */ if (tree->vertical) { while (1) { item = rItem->item; /* Update item/style layout. This can be needed when using fixed * column widths. */ (void) TreeItem_Height(tree, item); TreeItem_ToIndex(tree, item, &index, &indexVis); switch (tree->backgroundMode) { #ifdef DEPRECATED case BG_MODE_INDEX: #endif case BG_MODE_ORDER: break; #ifdef DEPRECATED case BG_MODE_VISINDEX: #endif case BG_MODE_ORDERVIS: index = indexVis; break; case BG_MODE_COLUMN: index = range->index; break; case BG_MODE_ROW: index = rItem->index; break; } dItem = (DItem *) TreeItem_GetDInfo(tree, item); /* Re-use a previously allocated DItem */ if (dItem != NULL) { dItemHead = DItem_Unlink(dItemHead, dItem); area = &dItem->area; /* This item is already marked for total redraw */ if (area->flags & DITEM_ALL_DIRTY) ; /* nothing */ /* All display info is marked as invalid */ else if (dInfo->flags & DINFO_INVALIDATE) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* The range may have changed size */ else if ((area->width != range->totalWidth) || (dItem->height != rItem->size)) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* Items may have alternating background colors. */ else if ((tree->columnBgCnt > 1) && ((index % tree->columnBgCnt) != (dItem->index % tree->columnBgCnt))) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* We don't copy items horizontally to their new position, * except for horizontal scrolling which moves the whole * range */ else if (x != dItem->oldX + (dInfo->xOrigin - tree->xOrigin)) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* If we are displaying dotted lines and the item has moved * from odd-top to non-odd-top or vice versa, must redraw * the lines for this item. */ else if (tree->showLines && (tree->lineStyle == LINE_STYLE_DOT) && tree->columnTreeVis && (TreeColumn_Lock(tree->columnTree) == COLUMN_LOCK_NONE) && ((DW2Cy(dItem->oldY) & 1) != (W2Cy(y) & 1))) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* We can't copy the item to its new position unless it * has the same part of the background image behind it */ else if ((tree->backgroundImage != NULL) && (((dItem->oldY + dInfo->yOrigin) % bgImgHeight) != ((y + tree->yOrigin) % bgImgHeight))) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; } /* Make a new DItem */ else { dItem = DItem_Alloc(tree, rItem); area = &dItem->area; } area->x = x; dItem->y = y; area->width = Range_TotalWidth(tree, range); dItem->height = rItem->size; dItem->range = range; dItem->index = index; dItem->spans = TreeItem_GetSpans(tree, dItem->item); /* Keep track of the maximum item size */ if (area->width > dInfo->itemWidth) dInfo->itemWidth = area->width; if (dItem->height > dInfo->itemHeight) dInfo->itemHeight = dItem->height; /* Linked list of DItems */ if (dInfo->dItem == NULL) dInfo->dItem = dItem; else dInfo->dItemLast->next = dItem; dInfo->dItemLast = dItem; if (rItem == range->last) break; /* Advance to next TreeItem */ rItem++; /* Stop when out of bounds */ y += dItem->height; if (y >= maxY) break; } } /* Left-to-right */ else { while (1) { item = rItem->item; /* Update item/style layout. This can be needed when using fixed * column widths. */ (void) TreeItem_Height(tree, item); TreeItem_ToIndex(tree, item, &index, &indexVis); switch (tree->backgroundMode) { #ifdef DEPRECATED case BG_MODE_INDEX: #endif case BG_MODE_ORDER: break; #ifdef DEPRECATED case BG_MODE_VISINDEX: #endif case BG_MODE_ORDERVIS: index = indexVis; break; case BG_MODE_COLUMN: index = rItem->index; break; case BG_MODE_ROW: index = range->index; break; } dItem = (DItem *) TreeItem_GetDInfo(tree, item); /* Re-use a previously allocated DItem */ if (dItem != NULL) { dItemHead = DItem_Unlink(dItemHead, dItem); area = &dItem->area; /* This item is already marked for total redraw */ if (area->flags & DITEM_ALL_DIRTY) ; /* nothing */ /* All display info is marked as invalid */ else if (dInfo->flags & DINFO_INVALIDATE) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* The range may have changed size */ else if ((area->width != rItem->size) || (dItem->height != range->totalHeight)) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* Items may have alternating background colors. */ else if ((tree->columnBgCnt > 1) && ((index % tree->columnBgCnt) != (dItem->index % tree->columnBgCnt))) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* We don't copy items vertically to their new position, * except for vertical scrolling which moves the whole range */ else if (y != dItem->oldY + (dInfo->yOrigin - tree->yOrigin)) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* If we are displaying dotted lines and the item has moved * from odd-top to non-odd-top or vice versa, must redraw * the lines for this item. */ else if (tree->showLines && (tree->lineStyle == LINE_STYLE_DOT) && tree->columnTreeVis && ((DW2Cy(dItem->oldY) & 1) != (W2Cy(y) & 1))) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* We can't copy the item to its new position unless it * has the same part of the background image behind it */ else if ((tree->backgroundImage != NULL) && (((dItem->oldX + dInfo->xOrigin) % bgImgWidth) != ((x + tree->xOrigin) % bgImgWidth))) area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; } /* Make a new DItem */ else { dItem = DItem_Alloc(tree, rItem); area = &dItem->area; } area->x = x; dItem->y = y; area->width = rItem->size; dItem->height = Range_TotalHeight(tree, range); dItem->range = range; dItem->index = index; dItem->spans = TreeItem_GetSpans(tree, dItem->item); /* Keep track of the maximum item size */ if (area->width > dInfo->itemWidth) dInfo->itemWidth = area->width; if (dItem->height > dInfo->itemHeight) dInfo->itemHeight = dItem->height; /* Linked list of DItems */ if (dInfo->dItem == NULL) dInfo->dItem = dItem; else dInfo->dItemLast->next = dItem; dInfo->dItemLast = dItem; if (rItem == range->last) break; /* Advance to next TreeItem */ rItem++; /* Stop when out of bounds */ x += area->width; if (x >= maxX) break; } } return dItemHead; } /* *-------------------------------------------------------------- * * Tree_UpdateDInfo -- * * At the finish of this procedure every on-screen item will have * a DItem associated with it and no off-screen item will have * a DItem. * * Results: * None. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ void Tree_UpdateDInfo( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItemHead = dInfo->dItem; int x, y, rx = 0, ry = 0, ix, iy, dx, dy; int minX, minY, maxX, maxY; Range *range; RItem *rItem; DItem *dItem; if (tree->debug.enable && tree->debug.display) dbwin("Tree_UpdateDInfo %s\n", Tk_PathName(tree->tkwin)); dInfo->dItem = dInfo->dItemLast = NULL; dInfo->rangeFirstD = dInfo->rangeLastD = NULL; dInfo->itemWidth = dInfo->itemHeight = 0; dInfo->empty = !Tree_AreaBbox(tree, TREE_AREA_CONTENT, &dInfo->bounds[0], &dInfo->bounds[1], &dInfo->bounds[2], &dInfo->bounds[3]); dInfo->emptyL = !Tree_AreaBbox(tree, TREE_AREA_LEFT, &dInfo->boundsL[0], &dInfo->boundsL[1], &dInfo->boundsL[2], &dInfo->boundsL[3]); dInfo->emptyR = !Tree_AreaBbox(tree, TREE_AREA_RIGHT, &dInfo->boundsR[0], &dInfo->boundsR[1], &dInfo->boundsR[2], &dInfo->boundsR[3]); if (dInfo->empty) goto done; minX = dInfo->bounds[0]; minY = dInfo->bounds[1]; maxX = dInfo->bounds[2]; maxY = dInfo->bounds[3]; range = dInfo->rangeFirst; if (tree->vertical) { /* Find the first range which could be onscreen horizontally. * It may not be onscreen if it has less height than other ranges. */ while (range != NULL) { if ((range->offset < maxX + tree->xOrigin) && (range->offset + range->totalWidth >= minX + tree->xOrigin)) { rx = range->offset; ry = 0; break; } range = range->next; } } else { /* Find the first range which could be onscreen vertically. * It may not be onscreen if it has less width than other ranges. */ while (range != NULL) { if ((range->offset < maxY + tree->yOrigin) && (range->offset + range->totalHeight >= minY + tree->yOrigin)) { rx = 0; ry = range->offset; break; } range = range->next; } } while (range != NULL) { if ((rx + range->totalWidth > minX + tree->xOrigin) && (ry + range->totalHeight > minY + tree->yOrigin)) { if (tree->vertical) { /* Range coords */ dx = MAX(minX + tree->xOrigin - rx, 0); dy = minY + tree->yOrigin; } else { dx = minX + tree->xOrigin; dy = MAX(minY + tree->yOrigin - ry, 0); } ix = dx; iy = dy; rItem = Range_ItemUnderPoint(tree, range, &ix, &iy); /* Window coords of top-left of item */ x = (rx - tree->xOrigin) + dx - ix; y = (ry - tree->yOrigin) + dy - iy; dItemHead = UpdateDInfoForRange(tree, dItemHead, range, rItem, x, y); } /* Track this range even if it has no DItems, so whitespace is * erased */ if (dInfo->rangeFirstD == NULL) dInfo->rangeFirstD = range; dInfo->rangeLastD = range; if (tree->vertical) { rx += range->totalWidth; if (rx >= maxX + tree->xOrigin) break; } else { ry += range->totalHeight; if (ry >= maxY + tree->yOrigin) break; } range = range->next; } if (dInfo->dItemLast != NULL) dInfo->dItemLast->next = NULL; done: if (dInfo->dItem != NULL) goto skipLock; if (!tree->itemVisCount) goto skipLock; if (dInfo->emptyL && dInfo->emptyR) goto skipLock; range = dInfo->rangeFirst; if ((range != NULL) && !range->totalHeight) goto skipLock; { int y = Tree_ContentTop(tree) + tree->yOrigin; /* Window -> Canvas */ int index, indexVis; /* If no non-locked columns are displayed, we have no Range and * must use dInfo->rangeLock. */ if (range == NULL) { range = dInfo->rangeLock; } /* Find the first item on-screen vertically. */ rItem = Range_ItemUnderPoint(tree, range, NULL, &y); y = rItem->offset; /* Top of the item */ y -= tree->yOrigin; /* Canvas -> Window */ while (1) { DItem *dItem = (DItem *) TreeItem_GetDInfo(tree, rItem->item); /* Re-use a previously allocated DItem */ if (dItem != NULL) { dItemHead = DItem_Unlink(dItemHead, dItem); } else { dItem = DItem_Alloc(tree, rItem); } TreeItem_ToIndex(tree, rItem->item, &index, &indexVis); switch (tree->backgroundMode) { #ifdef DEPRECATED case BG_MODE_INDEX: #endif case BG_MODE_ORDER: break; #ifdef DEPRECATED case BG_MODE_VISINDEX: #endif case BG_MODE_ORDERVIS: index = indexVis; break; case BG_MODE_COLUMN: index = range->index; break; case BG_MODE_ROW: index = rItem->index; break; } dItem->y = y; dItem->height = rItem->size; dItem->range = range; dItem->index = index; dItem->spans = TreeItem_GetSpans(tree, dItem->item); /* Keep track of the maximum item size */ if (dItem->height > dInfo->itemHeight) dInfo->itemHeight = dItem->height; /* Linked list of DItems */ if (dInfo->dItem == NULL) dInfo->dItem = dItem; else dInfo->dItemLast->next = dItem; dInfo->dItemLast = dItem; if (rItem == range->last) break; y += rItem->size; if (y >= Tree_ContentBottom(tree)) break; rItem++; } } skipLock: if (!dInfo->emptyL || !dInfo->emptyR) { int bgImgWidth, bgImgHeight; DItemArea *area; if (!dInfo->emptyL) { /* Keep track of the maximum item size */ if (dInfo->widthOfColumnsLeft > dInfo->itemWidth) dInfo->itemWidth = dInfo->widthOfColumnsLeft; } if (!dInfo->emptyR) { /* Keep track of the maximum item size */ if (dInfo->widthOfColumnsRight > dInfo->itemWidth) dInfo->itemWidth = dInfo->widthOfColumnsRight; } if (tree->backgroundImage != NULL) Tk_SizeOfImage(tree->backgroundImage, &bgImgWidth, &bgImgHeight); for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { if (!dInfo->emptyL) { area = &dItem->left; area->x = Tree_BorderLeft(tree); area->width = dInfo->widthOfColumnsLeft; /* This item is already marked for total redraw */ if (area->flags & DITEM_ALL_DIRTY) { ; /* nothing */ /* All display info is marked as invalid */ } else if (dInfo->flags & DINFO_INVALIDATE) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* Items may have alternating background colors. */ } else if ((tree->columnBgCnt > 1) && ((dItem->oldIndex % tree->columnBgCnt) != (dItem->index % tree->columnBgCnt))) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* If we are displaying dotted lines and the item has moved * from odd-top to non-odd-top or vice versa, must redraw * the lines for this item. */ } else if (tree->showLines && (tree->lineStyle == LINE_STYLE_DOT) && tree->columnTreeVis && (TreeColumn_Lock(tree->columnTree) == COLUMN_LOCK_LEFT) && ((DW2Cy(dItem->oldY) & 1) != (W2Cy(dItem->y) & 1))) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* We can't copy the item to its new position unless it * has the same part of the background image behind it */ } else if ((tree->backgroundImage != NULL) && ((dInfo->xOrigin % bgImgWidth) != (tree->xOrigin % bgImgWidth))) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; } } if (!dInfo->emptyR) { area = &dItem->right; area->x = Tree_ContentRight(tree); area->width = dInfo->widthOfColumnsRight; /* This item is already marked for total redraw */ if (area->flags & DITEM_ALL_DIRTY) { ; /* nothing */ /* All display info is marked as invalid */ } else if (dInfo->flags & DINFO_INVALIDATE) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* Items may have alternating background colors. */ } else if ((tree->columnBgCnt > 1) && ((dItem->oldIndex % tree->columnBgCnt) != (dItem->index % tree->columnBgCnt))) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* If we are displaying dotted lines and the item has moved * from odd-top to non-odd-top or vice versa, must redraw * the lines for this item. */ } else if (tree->showLines && (tree->lineStyle == LINE_STYLE_DOT) && tree->columnTreeVis && (TreeColumn_Lock(tree->columnTree) == COLUMN_LOCK_RIGHT) && ((DW2Cy(dItem->oldY) & 1) != (W2Cy(dItem->y) & 1))) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; /* We can't copy the item to its new position unless it * has the same part of the background image behind it */ } else if ((tree->backgroundImage != NULL) && ((dInfo->xOrigin % bgImgWidth) != (tree->xOrigin % bgImgWidth))) { area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; } } } } while (dItemHead != NULL) dItemHead = DItem_Free(tree, dItemHead); dInfo->flags &= ~DINFO_INVALIDATE; } /* *-------------------------------------------------------------- * * InvalidateDItemX -- * * Mark a horizontal span of a DItem as dirty (needing to be * redrawn). The caller must set the DITEM_DIRTY flag afterwards. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static void InvalidateDItemX( DItem *dItem, /* Item to mark dirty. */ DItemArea *area, int itemX, /* x-coordinate of item. */ int dirtyX, /* Left edge of area to mark as dirty. */ int dirtyWidth /* Width of area to mark as dirty. */ ) { int x1, x2; if (dirtyX <= itemX) area->dirty[LEFT] = 0; else { x1 = dirtyX - itemX; if (!(area->flags & DITEM_DIRTY) || (x1 < area->dirty[LEFT])) area->dirty[LEFT] = x1; } if (dirtyX + dirtyWidth >= itemX + area->width) area->dirty[RIGHT] = area->width; else { x2 = dirtyX + dirtyWidth - itemX; if (!(area->flags & DITEM_DIRTY) || (x2 > area->dirty[RIGHT])) area->dirty[RIGHT] = x2; } } /* *-------------------------------------------------------------- * * InvalidateDItemY -- * * Mark a vertical span of a DItem as dirty (needing to be * redrawn). The caller must set the DITEM_DIRTY flag afterwards. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static void InvalidateDItemY( DItem *dItem, /* Item to mark dirty. */ DItemArea *area, int itemY, /* y-coordinate of item. */ int dirtyY, /* Top edge of area to mark as dirty. */ int dirtyHeight /* Height of area to mark as dirty. */ ) { int y1, y2; if (dirtyY <= itemY) area->dirty[TOP] = 0; else { y1 = dirtyY - itemY; if (!(area->flags & DITEM_DIRTY) || (y1 < area->dirty[TOP])) area->dirty[TOP] = y1; } if (dirtyY + dirtyHeight >= itemY + dItem->height) area->dirty[BOTTOM] = dItem->height; else { y2 = dirtyY + dirtyHeight - itemY; if (!(area->flags & DITEM_DIRTY) || (y2 > area->dirty[BOTTOM])) area->dirty[BOTTOM] = y2; } } /* *-------------------------------------------------------------- * * Range_RedoIfNeeded -- * * Recalculate the list of Ranges if they are marked out-of-date. * Also calculate the height and width of the canvas based on the * list of Ranges. * * Results: * None. * * Side effects: * Memory may be allocated. * *-------------------------------------------------------------- */ static void Range_RedoIfNeeded( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; if (dInfo->flags & DINFO_REDO_RANGES) { dInfo->rangeFirstD = dInfo->rangeLastD = NULL; dInfo->flags |= DINFO_OUT_OF_DATE; Range_Redo(tree); dInfo->flags &= ~DINFO_REDO_RANGES; #ifdef COMPLEX_WHITESPACE if (ComplexWhitespace(tree)) { dInfo->flags |= DINFO_DRAW_WHITESPACE; } #endif /* Do this after clearing REDO_RANGES to prevent infinite loop */ tree->totalWidth = tree->totalHeight = -1; (void) Tree_TotalWidth(tree); (void) Tree_TotalHeight(tree); dInfo->flags |= DINFO_REDO_INCREMENTS; } } /* *-------------------------------------------------------------- * * DblBufWinDirty -- * * Add a rectangle to the dirty region of the "-doublebuffer window" * pixmap. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static void DblBufWinDirty( TreeCtrl *tree, int x1, int y1, int x2, int y2 ) { TreeDInfo dInfo = tree->dInfo; XRectangle rect; rect.x = x1; rect.y = y1; rect.width = x2 - x1; rect.height = y2 - y1; TkUnionRectWithRegion(&rect, dInfo->dirtyRgn, dInfo->dirtyRgn); } /* *-------------------------------------------------------------- * * DItemAllDirty -- * * Determine if a DItem will be entirely redrawn in all columns. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static int DItemAllDirty( TreeCtrl *tree, DItem *dItem ) { TreeDInfo dInfo = tree->dInfo; if ((!dInfo->empty && dInfo->rangeFirst != NULL) && !(dItem->area.flags & DITEM_ALL_DIRTY)) return 0; if (!dInfo->emptyL && !(dItem->left.flags & DITEM_ALL_DIRTY)) return 0; if (!dInfo->emptyR && !(dItem->right.flags & DITEM_ALL_DIRTY)) return 0; return 1; } /* *-------------------------------------------------------------- * * ScrollVerticalComplex -- * * Perform scrolling by copying the pixels of items from the * previous display position to the current position. Any areas * of items copied over by the moved items are marked dirty. * * Results: * The number of items whose pixels were copied. * * Side effects: * Pixels are copied in the TreeCtrl window or in the * offscreen pixmap (if double-buffering is used). * *-------------------------------------------------------------- */ static int ScrollVerticalComplex( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem, *dItem2; Range *range; TkRegion damageRgn; int minX, minY, maxX, maxY; int oldX, oldY, width, height, offset; int y; int numCopy = 0; if (dInfo->empty && dInfo->emptyL && dInfo->emptyR) return 0; minX = Tree_BorderLeft(tree); minY = Tree_ContentTop(tree); maxX = Tree_BorderRight(tree); maxY = Tree_ContentBottom(tree); /* Try updating the display by copying items on the screen to their * new location */ for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { /* Copy an item to its new location unless: * (a) item display info is invalid * (b) item is in same location as last draw */ if (DItemAllDirty(tree, dItem) || (dItem->oldY == dItem->y)) continue; numCopy++; range = dItem->range; /* This item was previously displayed so it only needs to be * copied to the new location. Copy all such items as one */ offset = dItem->y - dItem->oldY; height = dItem->height; for (dItem2 = dItem->next; dItem2 != NULL; dItem2 = dItem2->next) { if ((dItem2->range != range) || DItemAllDirty(tree, dItem2) || (dItem2->oldY + offset != dItem2->y)) break; numCopy++; height += dItem2->height; } y = dItem->y; oldY = dItem->oldY; /* Don't copy part of the window border */ if (oldY < minY) { height -= minY - oldY; oldY = minY; } if (oldY + height > maxY) height = maxY - oldY; /* Don't copy over the window border */ if (oldY + offset < minY) { height -= minY - (oldY + offset); oldY += minY - (oldY + offset); } if (oldY + offset + height > maxY) height = maxY - (oldY + offset); if (!dInfo->emptyL || !dInfo->emptyR) { oldX = minX; width = maxX - minX; } else { oldX = dItem->oldX; width = dItem->area.width; } if (oldX < minX) { width -= minX - oldX; oldX = minX; } if (oldX + width > maxX) width = maxX - oldX; /* Update oldY of copied items */ while (1) { /* If an item was partially visible, invalidate the exposed area */ if ((dItem->oldY < minY) && (offset > 0)) { if (!dInfo->empty && dInfo->rangeFirst != NULL) { InvalidateDItemX(dItem, &dItem->area, dItem->oldX, oldX, width); InvalidateDItemY(dItem, &dItem->area, dItem->oldY, dItem->oldY, minY - dItem->oldY); dItem->area.flags |= DITEM_DIRTY; } if (!dInfo->emptyL) { InvalidateDItemX(dItem, &dItem->left, dItem->left.x, oldX, width); InvalidateDItemY(dItem, &dItem->left, dItem->oldY, dItem->oldY, minY - dItem->oldY); dItem->left.flags |= DITEM_DIRTY; } if (!dInfo->emptyR) { InvalidateDItemX(dItem, &dItem->right, dItem->right.x, oldX, width); InvalidateDItemY(dItem, &dItem->right, dItem->oldY, dItem->oldY, minY - dItem->oldY); dItem->right.flags |= DITEM_DIRTY; } } if ((dItem->oldY + dItem->height > maxY) && (offset < 0)) { if (!dInfo->empty && dInfo->rangeFirst != NULL) { InvalidateDItemX(dItem, &dItem->area, dItem->oldX, oldX, width); InvalidateDItemY(dItem, &dItem->area, dItem->oldY, maxY, maxY - dItem->oldY + dItem->height); dItem->area.flags |= DITEM_DIRTY; } if (!dInfo->emptyL) { InvalidateDItemX(dItem, &dItem->left, dItem->left.x, oldX, width); InvalidateDItemY(dItem, &dItem->left, dItem->oldY, maxY, maxY - dItem->oldY + dItem->height); dItem->left.flags |= DITEM_DIRTY; } if (!dInfo->emptyR) { InvalidateDItemX(dItem, &dItem->right, dItem->right.x, oldX, width); InvalidateDItemY(dItem, &dItem->right, dItem->oldY, maxY, maxY - dItem->oldY + dItem->height); dItem->right.flags |= DITEM_DIRTY; } } dItem->oldY = dItem->y; if (dItem->next == dItem2) break; dItem = dItem->next; } /* Invalidate parts of items being copied over */ for ( ; dItem2 != NULL; dItem2 = dItem2->next) { if (dItem2->range != range) break; if (!DItemAllDirty(tree, dItem2) && (dItem2->oldY + dItem2->height > y) && (dItem2->oldY < y + height)) { if (!dInfo->empty && dInfo->rangeFirst != NULL) { InvalidateDItemX(dItem2, &dItem2->area, dItem2->oldX, oldX, width); InvalidateDItemY(dItem2, &dItem2->area, dItem2->oldY, y, height); dItem2->area.flags |= DITEM_DIRTY; } if (!dInfo->emptyL) { InvalidateDItemX(dItem2, &dItem2->left, dItem2->left.x, oldX, width); InvalidateDItemY(dItem2, &dItem2->left, dItem2->oldY, y, height); dItem2->left.flags |= DITEM_DIRTY; } if (!dInfo->emptyR) { InvalidateDItemX(dItem2, &dItem2->right, dItem2->right.x, oldX, width); InvalidateDItemY(dItem2, &dItem2->right, dItem2->oldY, y, height); dItem2->right.flags |= DITEM_DIRTY; } } } if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { int dirtyMin, dirtyMax; XCopyArea(tree->display, dInfo->pixmapW.drawable, dInfo->pixmapW.drawable, tree->copyGC, oldX, oldY, width, height, oldX, oldY + offset); if (offset < 0) { dirtyMin = oldY + offset + height; dirtyMax = oldY + height; } else { dirtyMin = oldY; dirtyMax = oldY + offset; } Tree_InvalidateArea(tree, oldX, dirtyMin, oldX + width, dirtyMax); DblBufWinDirty(tree, oldX, oldY + offset, oldX + width, oldY + offset + height); continue; } /* Copy */ damageRgn = Tree_GetRegion(tree); if (Tree_ScrollWindow(tree, dInfo->scrollGC, oldX, oldY, width, height, 0, offset, damageRgn)) { DisplayDelay(tree); Tree_InvalidateRegion(tree, damageRgn); } Tree_FreeRegion(tree, damageRgn); } return numCopy; } /* *-------------------------------------------------------------- * * ScrollHorizontalSimple -- * * Perform scrolling by shifting the pixels in the content area of * the list to the left or right. * * Results: * None. * * Side effects: * Stuff is copied/scrolled in the TreeCtrl window or in the * offscreen pixmap (if double-buffering is used). * *-------------------------------------------------------------- */ static void ScrollHorizontalSimple( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; TkRegion damageRgn; int minX, minY, maxX, maxY; int width, offset; int x, y; int dirtyMin, dirtyMax; if (dInfo->xOrigin == tree->xOrigin) return; /* Only column headers are visible. */ if (dInfo->rangeFirst == NULL) return; if (dInfo->empty) return; minX = dInfo->bounds[0]; minY = dInfo->bounds[1]; maxX = dInfo->bounds[2]; maxY = dInfo->bounds[3]; /* Update oldX */ for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { dItem->oldX = dItem->area.x; } offset = dInfo->xOrigin - tree->xOrigin; /* We only scroll the content, not the whitespace */ y = 0 - tree->yOrigin + Tree_TotalHeight(tree); if (y < maxY) maxY = y; /* Simplify if a whole screen was scrolled. */ if (abs(offset) >= maxX - minX) { Tree_InvalidateArea(tree, minX, minY, maxX, maxY); return; } /* We only scroll the content, not the whitespace */ x = 0 - tree->xOrigin + Tree_TotalWidth(tree); if (x < maxX) maxX = x; width = maxX - minX - abs(offset); /* Move pixels right */ if (offset > 0) { x = minX; dirtyMin = minX; dirtyMax = maxX - width; /* Move pixels left */ } else { x = maxX - width; dirtyMin = minX + width; dirtyMax = maxX; } damageRgn = Tree_GetRegion(tree); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { XCopyArea(tree->display, dInfo->pixmapW.drawable, dInfo->pixmapW.drawable, tree->copyGC, x, minY, width, maxY - minY, x + offset, minY); Tree_InvalidateArea(tree, dirtyMin, minY, dirtyMax, maxY); Tree_FreeRegion(tree, damageRgn); return; } if (Tree_ScrollWindow(tree, dInfo->scrollGC, x, minY, width, maxY - minY, offset, 0, damageRgn)) { DisplayDelay(tree); Tree_InvalidateRegion(tree, damageRgn); } Tree_FreeRegion(tree, damageRgn); Tree_InvalidateArea(tree, dirtyMin, minY, dirtyMax, maxY); } /* *-------------------------------------------------------------- * * ScrollVerticalSimple -- * * Perform scrolling by shifting the pixels in the content area of * the list up or down. * * Results: * None. * * Side effects: * Stuff is copied/scrolled in the TreeCtrl window or in the * offscreen pixmap (if double-buffering is used). * *-------------------------------------------------------------- */ static void ScrollVerticalSimple( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; TkRegion damageRgn; int minX, minY, maxX, maxY; int height, offset; int x, y; int dirtyMin, dirtyMax; if (dInfo->yOrigin == tree->yOrigin) return; /* Update oldY */ for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { dItem->oldY = dItem->y; } if (dInfo->empty) return; minX = dInfo->bounds[0]; minY = dInfo->bounds[1]; maxX = dInfo->bounds[2]; maxY = dInfo->bounds[3]; offset = dInfo->yOrigin - tree->yOrigin; /* We only scroll the content, not the whitespace */ x = 0 - tree->xOrigin + Tree_TotalWidth(tree); if (x < maxX) maxX = x; /* Simplify if a whole screen was scrolled. */ if (abs(offset) > maxY - minY) { Tree_InvalidateArea(tree, minX, minY, maxX, maxY); return; } height = maxY - minY - abs(offset); /* Move pixels down */ if (offset > 0) { y = minY; dirtyMin = minY; dirtyMax = maxY - height; /* Move pixels up */ } else { y = maxY - height; dirtyMin = minY + height; dirtyMax = maxY; } damageRgn = Tree_GetRegion(tree); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { XCopyArea(tree->display, dInfo->pixmapW.drawable, dInfo->pixmapW.drawable, tree->copyGC, minX, y, maxX - minX, height, minX, y + offset); Tree_InvalidateArea(tree, minX, dirtyMin, maxX, dirtyMax); Tree_FreeRegion(tree, damageRgn); return; } if (Tree_ScrollWindow(tree, dInfo->scrollGC, minX, y, maxX - minX, height, 0, offset, damageRgn)) { DisplayDelay(tree); Tree_InvalidateRegion(tree, damageRgn); } Tree_FreeRegion(tree, damageRgn); Tree_InvalidateArea(tree, minX, dirtyMin, maxX, dirtyMax); } /* *-------------------------------------------------------------- * * ScrollHorizontalComplex -- * * Perform scrolling by copying the pixels of items from the * previous display position to the current position. Any areas * of items copied over by the moved items are marked dirty. * * Results: * The number of items whose pixels were copied. * * Side effects: * Pixels are copied in the TreeCtrl window or in the * offscreen pixmap (if double-buffering is used). * *-------------------------------------------------------------- */ static int ScrollHorizontalComplex( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem, *dItem2; Range *range; TkRegion damageRgn; int minX, minY, maxX, maxY; int oldX, oldY, width, height, offset; int x; int numCopy = 0; if (!Tree_AreaBbox(tree, TREE_AREA_CONTENT, &minX, &minY, &maxX, &maxY)) return 0; /* Try updating the display by copying items on the screen to their * new location */ for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { /* Copy an item to its new location unless: * (a) item display info is invalid * (b) item is in same location as last draw */ if ((dItem->area.flags & DITEM_ALL_DIRTY) || (dItem->oldX == dItem->area.x)) continue; numCopy++; range = dItem->range; /* This item was previously displayed so it only needs to be * copied to the new location. Copy all such items as one */ offset = dItem->area.x - dItem->oldX; width = dItem->area.width; for (dItem2 = dItem->next; dItem2 != NULL; dItem2 = dItem2->next) { if ((dItem2->range != range) || (dItem2->area.flags & DITEM_ALL_DIRTY) || (dItem2->oldX + offset != dItem2->area.x)) break; numCopy++; width += dItem2->area.width; } x = dItem->area.x; oldX = dItem->oldX; /* Don't copy part of the window border */ if (oldX < minX) { width -= minX - oldX; oldX = minX; } if (oldX + width > maxX) width = maxX - oldX; /* Don't copy over the window border */ if (oldX + offset < minX) { width -= minX - (oldX + offset); oldX += minX - (oldX + offset); } if (oldX + offset + width > maxX) width = maxX - (oldX + offset); oldY = dItem->oldY; height = dItem->height; /* range->totalHeight */ if (oldY < minY) { height -= minY - oldY; oldY = minY; } if (oldY + height > maxY) height = maxY - oldY; /* Update oldX of copied items */ while (1) { /* If an item was partially visible, invalidate the exposed area */ if ((dItem->oldX < minX) && (offset > 0)) { InvalidateDItemX(dItem, &dItem->area, dItem->oldX, dItem->oldX, minX - dItem->oldX); InvalidateDItemY(dItem, &dItem->area, oldY, oldY, height); dItem->area.flags |= DITEM_DIRTY; } if ((dItem->oldX + dItem->area.width > maxX) && (offset < 0)) { InvalidateDItemX(dItem, &dItem->area, dItem->oldX, maxX, maxX - dItem->oldX + dItem->area.width); InvalidateDItemY(dItem, &dItem->area, oldY, oldY, height); dItem->area.flags |= DITEM_DIRTY; } dItem->oldX = dItem->area.x; if (dItem->next == dItem2) break; dItem = dItem->next; } /* Invalidate parts of items being copied over */ for ( ; dItem2 != NULL; dItem2 = dItem2->next) { if (dItem2->range != range) break; if (!(dItem2->area.flags & DITEM_ALL_DIRTY) && (dItem2->oldX + dItem2->area.width > x) && (dItem2->oldX < x + width)) { InvalidateDItemX(dItem2, &dItem2->area, dItem2->oldX, x, width); InvalidateDItemY(dItem2, &dItem2->area, oldY, oldY, height); dItem2->area.flags |= DITEM_DIRTY; } } if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { int dirtyMin, dirtyMax; XCopyArea(tree->display, dInfo->pixmapW.drawable, dInfo->pixmapW.drawable, tree->copyGC, oldX, oldY, width, height, oldX + offset, oldY); if (offset < 0) { dirtyMin = oldX + offset + width; dirtyMax = oldX + width; } else { dirtyMin = oldX; dirtyMax = oldX + offset; } Tree_InvalidateArea(tree, dirtyMin, oldY, dirtyMax, oldY + height); DblBufWinDirty(tree, oldX + offset, oldY, oldX + offset + width, oldY + height); continue; } /* Copy */ damageRgn = Tree_GetRegion(tree); if (Tree_ScrollWindow(tree, dInfo->scrollGC, oldX, oldY, width, height, offset, 0, damageRgn)) { DisplayDelay(tree); Tree_InvalidateRegion(tree, damageRgn); } Tree_FreeRegion(tree, damageRgn); } return numCopy; } /* *-------------------------------------------------------------- * * Proxy_Draw -- * * Draw (or erase) the visual indicator used when the user is * resizing a column or row (and -columnresizemode is "proxy"). * * Results: * None. * * Side effects: * Stuff is drawn in the TreeCtrl window (or erased, since this * is XOR drawing). * *-------------------------------------------------------------- */ static void Proxy_Draw( TreeCtrl *tree, /* Widget info. */ int x1, /* Vertical or horizontal line window coords. */ int y1, int x2, int y2 ) { #if defined(MAC_OSX_TK) DrawXORLine(tree->display, Tk_WindowId(tree->tkwin), x1, y1, x2, y2); #else XGCValues gcValues; unsigned long gcMask; GC gc; #if defined(MAC_TCL) gcValues.function = GXxor; #else gcValues.function = GXinvert; #endif gcValues.graphics_exposures = False; gcMask = GCFunction | GCGraphicsExposures; gc = Tree_GetGC(tree, gcMask, &gcValues); /* GXinvert doesn't work with XFillRectangle() on Win32 or Mac */ #if defined(WIN32) || defined(MAC_TCL) XDrawLine(tree->display, Tk_WindowId(tree->tkwin), gc, x1, y1, x2, y2); #else XFillRectangle(tree->display, Tk_WindowId(tree->tkwin), gc, x1, y1, MAX(x2 - x1, 1), MAX(y2 - y1, 1)); #endif #endif /* !MAC_OSX_TK */ } /* *-------------------------------------------------------------- * * TreeColumnProxy_Undisplay -- * * Hide the visual indicator used when the user is * resizing a column (if it is displayed). * * Results: * None. * * Side effects: * Stuff is erased in the TreeCtrl window. * *-------------------------------------------------------------- */ void TreeColumnProxy_Undisplay( TreeCtrl *tree /* Widget info. */ ) { if (tree->columnProxy.onScreen) { Proxy_Draw(tree, tree->columnProxy.sx, Tree_BorderTop(tree), tree->columnProxy.sx, Tree_BorderBottom(tree)); tree->columnProxy.onScreen = FALSE; } } /* *-------------------------------------------------------------- * * TreeColumnProxy_Display -- * * Display the visual indicator used when the user is * resizing a column (if it isn't displayed and should be * displayed). * * Results: * None. * * Side effects: * Stuff is drawn in the TreeCtrl window. * *-------------------------------------------------------------- */ void TreeColumnProxy_Display( TreeCtrl *tree /* Widget info. */ ) { if (!tree->columnProxy.onScreen && (tree->columnProxy.xObj != NULL)) { tree->columnProxy.sx = tree->columnProxy.x; Proxy_Draw(tree, tree->columnProxy.x, Tree_BorderTop(tree), tree->columnProxy.x, Tree_BorderBottom(tree)); tree->columnProxy.onScreen = TRUE; } } /* *-------------------------------------------------------------- * * TreeRowProxy_Display -- * * Display the visual indicator used when the user is * resizing a row (if it isn't displayed and should be * displayed). * * Results: * None. * * Side effects: * Stuff is drawn in the TreeCtrl window. * *-------------------------------------------------------------- */ void TreeRowProxy_Display( TreeCtrl *tree /* Widget info. */ ) { if (!tree->rowProxy.onScreen && (tree->rowProxy.yObj != NULL)) { tree->rowProxy.sy = tree->rowProxy.y; Proxy_Draw(tree, Tree_BorderLeft(tree), tree->rowProxy.y, Tree_BorderRight(tree), tree->rowProxy.y); tree->rowProxy.onScreen = TRUE; } } /* *-------------------------------------------------------------- * * TreeRowProxy_Undisplay -- * * Hide the visual indicator used when the user is * resizing a row (if it is displayed). * * Results: * None. * * Side effects: * Stuff is erased in the TreeCtrl window. * *-------------------------------------------------------------- */ void TreeRowProxy_Undisplay( TreeCtrl *tree /* Widget info. */ ) { if (tree->rowProxy.onScreen) { Proxy_Draw(tree, Tree_BorderLeft(tree), tree->rowProxy.sy, Tree_BorderRight(tree), tree->rowProxy.sy); tree->rowProxy.onScreen = FALSE; } } /* *-------------------------------------------------------------- * * CalcWhiteSpaceRegion -- * * Create a new region containing all the whitespace of the list * The whitespace is the area inside the borders/header where items * are not displayed. * * Results: * The new whitespace region, which may be empty. * * Side effects: * A new region is allocated. * *-------------------------------------------------------------- */ static TkRegion CalcWhiteSpaceRegion( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; int x, y, minX, minY, maxX, maxY; int left, right, top, bottom; TkRegion wsRgn; XRectangle rect; Range *range; x = 0 - tree->xOrigin; y = 0 - tree->yOrigin; wsRgn = Tree_GetRegion(tree); /* Erase area below left columns */ if (!dInfo->emptyL) { minX = dInfo->boundsL[0]; minY = dInfo->boundsL[1]; maxX = dInfo->boundsL[2]; maxY = dInfo->boundsL[3]; if (y + Tree_TotalHeight(tree) < maxY) { rect.x = minX; rect.y = y + Tree_TotalHeight(tree); rect.width = maxX - minX; rect.height = maxY - (y + Tree_TotalHeight(tree)); TkUnionRectWithRegion(&rect, wsRgn, wsRgn); } } /* Erase area below right columns */ if (!dInfo->emptyR) { minX = dInfo->boundsR[0]; minY = dInfo->boundsR[1]; maxX = dInfo->boundsR[2]; maxY = dInfo->boundsR[3]; if (y + Tree_TotalHeight(tree) < maxY) { rect.x = minX; rect.y = y + Tree_TotalHeight(tree); rect.width = maxX - minX; rect.height = maxY - (y + Tree_TotalHeight(tree)); TkUnionRectWithRegion(&rect, wsRgn, wsRgn); } } if (dInfo->empty) return wsRgn; minX = dInfo->bounds[0]; minY = dInfo->bounds[1]; maxX = dInfo->bounds[2]; maxY = dInfo->bounds[3]; /* Only the header is visible. */ if (dInfo->rangeFirst == NULL) { rect.x = minX; rect.y = minY; rect.width = maxX - rect.x; rect.height = maxY - rect.y; TkUnionRectWithRegion(&rect, wsRgn, wsRgn); return wsRgn; } if (tree->vertical) { /* Erase area to right of last Range */ if (x + Tree_TotalWidth(tree) < maxX) { rect.x = x + Tree_TotalWidth(tree); rect.y = minY; rect.width = maxX - rect.x; rect.height = maxY - rect.y; TkUnionRectWithRegion(&rect, wsRgn, wsRgn); } } else { /* Erase area below last Range */ if (y + Tree_TotalHeight(tree) < maxY) { rect.x = minX; rect.y = y + Tree_TotalHeight(tree); rect.width = maxX - rect.x; rect.height = maxY - rect.y; TkUnionRectWithRegion(&rect, wsRgn, wsRgn); } } for (range = dInfo->rangeFirstD; range != NULL; range = range->next) { if (tree->vertical) { left = MAX(x + range->offset, minX); right = MIN(x + range->offset + range->totalWidth, maxX); top = MAX(y + range->totalHeight, minY); bottom = maxY; /* Erase area below Range */ if (top < bottom) { rect.x = left; rect.y = top; rect.width = right - left; rect.height = bottom - top; TkUnionRectWithRegion(&rect, wsRgn, wsRgn); } } else { left = MAX(x + range->totalWidth, minX); right = maxX; top = MAX(y + range->offset, minY); bottom = MIN(y + range->offset + range->totalHeight, maxY); /* Erase area to right of Range */ if (left < right) { rect.x = left; rect.y = top; rect.width = right - left; rect.height = bottom - top; TkUnionRectWithRegion(&rect, wsRgn, wsRgn); } } if (range == dInfo->rangeLastD) break; } return wsRgn; } #ifdef COMPLEX_WHITESPACE /* *-------------------------------------------------------------- * * Tree_IntersectRect -- * * Determine the area of overlap between two rectangles. * * Results: * If the rectangles have non-zero size and overlap, resultPtr * holds the area of overlap, and the return value is 1. * Otherwise 0 is returned and resultPtr is untouched. * * Side effects: * None. * *-------------------------------------------------------------- */ static int Tree_IntersectRect( XRectangle *resultPtr, /* Out: area of overlap. May be the same * as r1 or r2. */ CONST XRectangle *r1, /* First rectangle. */ CONST XRectangle *r2 /* Second rectangle. */ ) { XRectangle result; if (r1->width == 0 || r1->height == 0) return 0; if (r2->width == 0 || r2->height == 0) return 0; if (r1->x >= r2->x + r2->width) return 0; if (r2->x >= r1->x + r1->width) return 0; if (r1->y >= r2->y + r2->height) return 0; if (r2->y >= r1->y + r1->height) return 0; result.x = MAX(r1->x, r2->x); result.width = MIN(r1->x + r1->width, r2->x + r2->width) - result.x; result.y = MAX(r1->y, r2->y); result.height = MIN(r1->y + r1->height, r2->y + r2->height) - result.y; *resultPtr = result; return 1; }; /* *-------------------------------------------------------------- * * GetItemBgIndex -- * * Determine the index used to pick an -itembackground color * for a displayed item. * This is only valid for tree->vertical=1. * * Results: * Integer index. * * Side effects: * None. * *-------------------------------------------------------------- */ static int GetItemBgIndex( TreeCtrl *tree, /* Widget info. */ RItem *rItem /* Range info for an item. */ ) { Range *range = rItem->range; int index, indexVis; TreeItem_ToIndex(tree, rItem->item, &index, &indexVis); switch (tree->backgroundMode) { #ifdef DEPRECATED case BG_MODE_INDEX: #endif case BG_MODE_ORDER: break; #ifdef DEPRECATED case BG_MODE_VISINDEX: #endif case BG_MODE_ORDERVIS: index = indexVis; break; case BG_MODE_COLUMN: index = range->index; /* always zero */ break; case BG_MODE_ROW: index = rItem->index; break; } return index; } /* *-------------------------------------------------------------- * * DrawColumnBackground -- * * Draws rows of -itembackground colors in a column in the * whitespace region. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static void DrawColumnBackground( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ TreeColumn treeColumn, /* Column to get background colors from. */ TkRegion dirtyRgn, /* Area that needs painting. Will be * inside 'bounds' and inside borders. */ XRectangle *bounds, /* Window coords of column to paint. */ RItem *rItem, /* Item(s) to get row heights from when drawing * in the tail column, otherwise NULL. */ int height, /* Height of each row below actual items. */ int index /* Used for alternating background colors. */ ) { int bgCount = TreeColumn_BackgroundCount(treeColumn); GC gc = None, backgroundGC; XRectangle dirtyBox, drawBox, rowBox; int top, bottom; TkClipBox(dirtyRgn, &dirtyBox); if (!dirtyBox.width || !dirtyBox.height) return; backgroundGC = Tk_3DBorderGC(tree->tkwin, tree->border, TK_3D_FLAT_GC); /* If the column has zero -itembackground colors, paint with the * treectrl's -background color. If a single -itembackground color * is specified, then paint with it. */ if (bgCount < 2) { if (bgCount == 1) gc = TreeColumn_BackgroundGC(treeColumn, 0); if (gc == None) gc = backgroundGC; Tree_FillRegion(tree->display, drawable, gc, dirtyRgn); return; } top = bounds->y; bottom = dirtyBox.y + dirtyBox.height; while (top < bottom) { /* Can't use clipping regions with XFillRectangle * because the clip region is ignored on Win32. */ rowBox.x = bounds->x; rowBox.y = top; rowBox.width = bounds->width; rowBox.height = rItem ? rItem->size : height; if (Tree_IntersectRect(&drawBox, &rowBox, &dirtyBox)) { if (rItem != NULL) { index = GetItemBgIndex(tree, rItem); } gc = TreeColumn_BackgroundGC(treeColumn, index); if (gc == None) gc = backgroundGC; XFillRectangle(tree->display, drawable, gc, drawBox.x, drawBox.y, drawBox.width, drawBox.height); } if (rItem != NULL && rItem == rItem->range->last) { index = GetItemBgIndex(tree, rItem); rItem = NULL; } if (rItem != NULL) { rItem++; } index++; top += rowBox.height; } } /* *-------------------------------------------------------------- * * DrawWhitespaceBelowItem -- * * Draws rows of -itembackground colors in each column in the * whitespace region. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static void DrawWhitespaceBelowItem( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ int lock, /* Which columns to draw. */ int bounds[4], /* TREE_AREA_xxx bounds. */ int left, /* Window coord of first column's left edge. */ int top, /* Window coord just below the last item. */ TkRegion dirtyRgn, /* Area of whitespace that needs painting. */ TkRegion columnRgn, /* Existing region to set and use. */ int height, /* Height of each row. */ int index /* Used for alternating background colors. */ ) { int i = 0, width; TreeColumn treeColumn = NULL; XRectangle boundsBox, columnBox; switch (lock) { case COLUMN_LOCK_LEFT: treeColumn = tree->columnLockLeft; break; case COLUMN_LOCK_NONE: treeColumn = tree->columnLockNone; break; case COLUMN_LOCK_RIGHT: treeColumn = tree->columnLockRight; break; } boundsBox.x = bounds[0]; boundsBox.y = bounds[1]; boundsBox.width = bounds[2] - bounds[0]; boundsBox.height = bounds[3] - bounds[1]; for (i = TreeColumn_Index(treeColumn); i < tree->columnCount; i++) { if (TreeColumn_Lock(treeColumn) != lock) break; width = TreeColumn_GetDInfo(treeColumn)->width; if (width == 0) /* also handles hidden columns */ goto next; columnBox.x = left; columnBox.y = top; columnBox.width = width; columnBox.height = bounds[3] - top; if (Tree_IntersectRect(&columnBox, &boundsBox, &columnBox)) { TkSubtractRegion(columnRgn, columnRgn, columnRgn); TkUnionRectWithRegion(&columnBox, columnRgn, columnRgn); TkIntersectRegion(dirtyRgn, columnRgn, columnRgn); DrawColumnBackground(tree, drawable, treeColumn, columnRgn, &columnBox, (RItem *) NULL, height, index); } left += width; next: treeColumn = TreeColumn_Next(treeColumn); } } /* *-------------------------------------------------------------- * * ComplexWhitespace -- * * Return 1 if -itembackground colors should be drawn into the * whitespace region. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ static int ComplexWhitespace( TreeCtrl *tree ) { if (tree->columnBgCnt == 0 && TreeColumn_BackgroundCount(tree->columnTail) == 0) return 0; if (!tree->vertical || tree->wrapMode != TREE_WRAP_NONE) return 0; if (tree->itemHeight <= 0 && tree->minItemHeight <= 0) return 0; return 1; } /* *-------------------------------------------------------------- * * DrawWhitespace -- * * Paints part of the whitespace region. * * Results: * If -itembackground colors are not being drawn into the * whitespace region, the dirtyRgn is filled with the treectrl's * -background color. Otherwise rows of color are drawn below * the last item and in the tail column if those columns have * any -itembackground colors specified. * * Side effects: * None. * *-------------------------------------------------------------- */ static void DrawWhitespace( TreeCtrl *tree, Drawable drawable, TkRegion dirtyRgn ) { TreeDInfo dInfo = tree->dInfo; int x, y, minX, minY, maxX, maxY; int top, bottom; int height, index; XRectangle columnBox; TkRegion columnRgn; Range *range; RItem *rItem; /* If we aren't drawing -itembackground colors in the whitespace region, * then just paint the entire dirty area with the treectrl's -background * color. */ if (!ComplexWhitespace(tree)) { GC gc = Tk_3DBorderGC(tree->tkwin, tree->border, TK_3D_FLAT_GC); Tree_FillRegion(tree->display, drawable, gc, dirtyRgn); return; } x = 0 - tree->xOrigin; y = 0 - tree->yOrigin; top = MAX(y + Tree_TotalHeight(tree), Tree_ContentTop(tree)); bottom = Tree_ContentBottom(tree); /* Figure out the height of each row of color below the items. */ if (tree->backgroundMode == BG_MODE_COLUMN) height = bottom - top; /* solid block of color */ else if (tree->itemHeight > 0) height = tree->itemHeight; else height = tree->minItemHeight; columnRgn = Tree_GetRegion(tree); range = dInfo->rangeFirst; if (range == NULL) range = dInfo->rangeLock; if (!dInfo->empty) { minX = dInfo->bounds[0]; minY = dInfo->bounds[1]; maxX = dInfo->bounds[2]; maxY = dInfo->bounds[3]; /* Draw to the right of the items using the tail * column's -itembackground colors. The height of each row matches * the height of the adjacent item. */ if (x + Tree_TotalWidth(tree) < maxX) { columnBox.y = Tree_ContentTop(tree); if (range == NULL) { rItem = NULL; index = 0; } else { /* Get the item at the top of the screen. */ if (range->totalHeight == 0) { rItem = range->last; /* all items have zero height */ } else { int y2 = minY + tree->yOrigin; /* Window -> canvas */ rItem = Range_ItemUnderPoint(tree, range, NULL, &y2); columnBox.y -= y2; } index = GetItemBgIndex(tree, rItem); } columnBox.x = x + Tree_TotalWidth(tree); columnBox.width = maxX - columnBox.x; columnBox.height = maxY - columnBox.y; TkSubtractRegion(columnRgn, columnRgn, columnRgn); TkUnionRectWithRegion(&columnBox, columnRgn, columnRgn); TkIntersectRegion(dirtyRgn, columnRgn, columnRgn); DrawColumnBackground(tree, drawable, tree->columnTail, columnRgn, &columnBox, rItem, height, index); } } if (top < bottom) { /* Get the display index of the last visible item. */ if (range == NULL) { index = 0; } else { rItem = range->last; index = GetItemBgIndex(tree, rItem); if (tree->backgroundMode != BG_MODE_COLUMN) { index++; } } /* Draw below non-locked columns. */ if (!dInfo->empty && Tree_TotalWidth(tree)/* && dInfo->rangeFirst != NULL */) { DrawWhitespaceBelowItem(tree, drawable, COLUMN_LOCK_NONE, dInfo->bounds, x, top, dirtyRgn, columnRgn, height, index); } /* Draw below the left columns. */ if (!dInfo->emptyL) { minX = dInfo->boundsL[0]; DrawWhitespaceBelowItem(tree, drawable, COLUMN_LOCK_LEFT, dInfo->boundsL, minX, top, dirtyRgn, columnRgn, height, index); } /* Draw below the right columns. */ if (!dInfo->emptyR) { minX = dInfo->boundsR[0]; DrawWhitespaceBelowItem(tree, drawable, COLUMN_LOCK_RIGHT, dInfo->boundsR, minX, top, dirtyRgn, columnRgn, height, index); } } Tree_FreeRegion(tree, columnRgn); } #endif /* COMPLEX_WHITESPACE */ /* *---------------------------------------------------------------------- * * Tree_DrawTiledImage -- * * This procedure draws a tiled image in the indicated box. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void Tree_DrawTiledImage( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ Tk_Image image, /* The image to draw. */ int x1, int y1, /* Left & top of area to fill with the image. */ int x2, int y2, /* Right & bottom, of area to fill with the * image. */ int xOffset, int yOffset /* Used to keep the image aligned with an * origin. */ ) { int imgWidth, imgHeight; int srcX, srcY; int srcW, srcH; int dstX, dstY; Tk_SizeOfImage(image, &imgWidth, &imgHeight); /* xOffset can be < 0 for left-locked columns. */ if (xOffset < 0) xOffset = imgWidth + xOffset % imgWidth; srcX = (x1 + xOffset) % imgWidth; dstX = x1; while (dstX < x2) { srcW = imgWidth - srcX; if (dstX + srcW > x2) { srcW = x2 - dstX; } srcY = (y1 + yOffset) % imgHeight; dstY = y1; while (dstY < y2) { srcH = imgHeight - srcY; if (dstY + srcH > y2) { srcH = y2 - dstY; } Tk_RedrawImage(image, srcX, srcY, srcW, srcH, drawable, dstX, dstY); srcY = 0; dstY += srcH; } srcX = 0; /* the last tile gives dstX == x2 which ends the while loop; same * for dstY above */ dstX += srcW; }; } /* *---------------------------------------------------------------------- * * DisplayDItem -- * * Draw a single item. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ static int DisplayDItem( TreeCtrl *tree, /* Widget info. */ DItem *dItem, DItemArea *area, int lock, /* Which set of columns. */ int bounds[4], /* TREE_AREA_xxx bounds of drawing. */ TreeDrawable pixmap, /* Where to draw. */ TreeDrawable drawable /* Where to copy to. */ ) { Tk_Window tkwin = tree->tkwin; int left, top, right, bottom; left = area->x; right = left + area->width; top = dItem->y; bottom = top + dItem->height; if (!(area->flags & DITEM_ALL_DIRTY)) { left += area->dirty[LEFT]; right = area->x + area->dirty[RIGHT]; top += area->dirty[TOP]; bottom = dItem->y + area->dirty[BOTTOM]; } area->flags &= ~(DITEM_DIRTY | DITEM_ALL_DIRTY); if (left < bounds[0]) left = bounds[0]; if (right > bounds[2]) right = bounds[2]; if (top < bounds[1]) top = bounds[1]; if (bottom > bounds[3]) bottom = bounds[3]; if (right <= left || bottom <= top) return 0; if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) { XFillRectangle(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, left, top, right - left, bottom - top); DisplayDelay(tree); } if (tree->doubleBuffer != DOUBLEBUFFER_NONE) { if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { DblBufWinDirty(tree, left, top, right, bottom); } /* The top-left corner of the drawable is at this * point in the canvas */ tree->drawableXOrigin = left + tree->xOrigin; tree->drawableYOrigin = top + tree->yOrigin; TreeItem_Draw(tree, dItem->item, lock, area->x - left, dItem->y - top, area->width, dItem->height, pixmap, 0, right - left, dItem->index); XCopyArea(tree->display, pixmap.drawable, drawable.drawable, tree->copyGC, 0, 0, right - left, bottom - top, left, top); } else { /* The top-left corner of the drawable is at this * point in the canvas */ tree->drawableXOrigin = tree->xOrigin; tree->drawableYOrigin = tree->yOrigin; TreeItem_Draw(tree, dItem->item, lock, area->x, dItem->y, area->width, dItem->height, drawable, left, right, dItem->index); } return 1; } void DebugDrawBorder( TreeCtrl *tree, int inset, int left, int top, int right, int bottom ) { Tk_Window tkwin = tree->tkwin; if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) { if (left > 0) { XFillRectangle(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, inset, inset, left, Tk_Height(tkwin) - inset * 2); } if (top > 0) { XFillRectangle(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, inset, inset, Tk_Width(tkwin) - inset * 2, top); } if (right > 0) { XFillRectangle(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, Tk_Width(tkwin) - inset - right, inset, right, Tk_Height(tkwin) - inset * 2); } if (bottom > 0) { XFillRectangle(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, inset, Tk_Height(tkwin) - inset - bottom, Tk_Width(tkwin) - inset * 2, bottom); } DisplayDelay(tree); } } /* *-------------------------------------------------------------- * * TreeDisplay_GetReadyForTrouble -- * TreeDisplay_WasThereTrouble -- * * These 2 procedures are used to detect when something happens * during a display update that requests another display update. * If that happens, then the current display is aborted and we * try again (unless the window was destroyed). * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void TreeDisplay_GetReadyForTrouble( TreeCtrl *tree, int *requestsPtr ) { TreeDInfo dInfo = tree->dInfo; *requestsPtr = dInfo->requests; } int TreeDisplay_WasThereTrouble( TreeCtrl *tree, int requests ) { TreeDInfo dInfo = tree->dInfo; if (tree->deleted || (requests != dInfo->requests)) { if (tree->debug.enable) dbwin("TreeDisplay_WasThereTrouble: %p\n", tree); return 1; } return 0; } /* *---------------------------------------------------------------------- * * DisplayGetPixmap -- * * Allocate or reallocate a pixmap of needed size. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Pixmap DisplayGetPixmap( TreeCtrl *tree, TreeDrawable *dPixmap, int width, int height ) { Tk_Window tkwin = tree->tkwin; if (dPixmap->drawable == None) { dPixmap->drawable = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), width, height, Tk_Depth(tkwin)); dPixmap->width = width; dPixmap->height = height; } else if ((dPixmap->width < width) || (dPixmap->height < height)) { Tk_FreePixmap(tree->display, dPixmap->drawable); dPixmap->drawable = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), width, height, Tk_Depth(tkwin)); dPixmap->width = width; dPixmap->height = height; } return dPixmap->drawable; } /* *-------------------------------------------------------------- * * Tree_Display -- * * This procedure is called at idle time when something has happened * that might require the list to be redisplayed. An effort is made * to only redraw what is needed. * * Results: * None. * * Side effects: * Stuff is drawn in the TreeCtrl window. * *-------------------------------------------------------------- */ void Tree_Display( ClientData clientData /* Widget info. */ ) { TreeCtrl *tree = clientData; TreeDInfo dInfo = tree->dInfo; DItem *dItem; Tk_Window tkwin = tree->tkwin; Drawable drawable; TreeDrawable tdrawable; int minX, minY, maxX, maxY; int count; int numCopy = 0, numDraw = 0; TkRegion wsRgnNew, wsRgnDif; #ifdef COMPLEX_WHITESPACE int complexWhitespace; #endif XRectangle wsBox; int requests; if (tree->debug.enable && tree->debug.display && 0) dbwin("Tree_Display %s\n", Tk_PathName(tkwin)); if (tree->deleted) { dInfo->flags &= ~(DINFO_REDRAW_PENDING); return; } /* */ Tcl_Preserve((ClientData) tree); Tree_PreserveItems(tree); displayRetry: /* Some change requires selection changes */ if (dInfo->flags & DINFO_REDO_SELECTION) { #ifdef SELECTION_VISIBLE /* Possible event. */ Tree_DeselectHidden(tree); if (tree->deleted) goto displayExit; #endif dInfo->flags &= ~(DINFO_REDO_SELECTION); } /* DINFO_REDO_COLUMN_WIDTH - A column was created or deleted. */ /* DINFO_CHECK_COLUMN_WIDTH - The width, offset or visibility of one or * more columns *might* have changed. */ if (dInfo->flags & (DINFO_REDO_COLUMN_WIDTH | DINFO_CHECK_COLUMN_WIDTH)) { TreeColumn treeColumn = tree->columns; TreeColumnDInfo dColumn; int force = (dInfo->flags & DINFO_REDO_COLUMN_WIDTH) != 0; int redoRanges = force, drawItems = force, drawHeader = force; int offset, width; /* Set max -itembackground as well. */ tree->columnBgCnt = 0; while (treeColumn != NULL) { offset = TreeColumn_Offset(treeColumn); width = TreeColumn_UseWidth(treeColumn); dColumn = TreeColumn_GetDInfo(treeColumn); /* Haven't seen this column before. */ if (dColumn == NULL) { dColumn = (TreeColumnDInfo) ckalloc(sizeof(TreeColumnDInfo_)); TreeColumn_SetDInfo(treeColumn, dColumn); if (width > 0) redoRanges = drawItems = drawHeader = TRUE; } else { /* Changes to observed width also detects column visibililty * changing. */ if (dColumn->width != width) { redoRanges = drawItems = drawHeader = TRUE; } else if ((dColumn->offset != offset) && (width > 0)) { drawItems = drawHeader = TRUE; } } dColumn->offset = offset; dColumn->width = width; if (TreeColumn_Visible(treeColumn) && (TreeColumn_BackgroundCount(treeColumn) > tree->columnBgCnt)) tree->columnBgCnt = TreeColumn_BackgroundCount(treeColumn); treeColumn = TreeColumn_Next(treeColumn); } if (redoRanges) dInfo->flags |= DINFO_REDO_RANGES | DINFO_OUT_OF_DATE; if (drawHeader) dInfo->flags |= DINFO_DRAW_HEADER; if (drawItems) dInfo->flags |= DINFO_INVALIDATE; dInfo->flags &= ~(DINFO_REDO_COLUMN_WIDTH | DINFO_CHECK_COLUMN_WIDTH); } if (dInfo->headerHeight != Tree_HeaderHeight(tree)) { dInfo->headerHeight = Tree_HeaderHeight(tree); dInfo->flags |= DINFO_OUT_OF_DATE | DINFO_SET_ORIGIN_Y | DINFO_UPDATE_SCROLLBAR_Y | DINFO_DRAW_HEADER; if (tree->vertical && (tree->wrapMode == TREE_WRAP_WINDOW)) dInfo->flags |= DINFO_REDO_RANGES; } if (dInfo->widthOfColumnsLeft != Tree_WidthOfLeftColumns(tree) || dInfo->widthOfColumnsRight != Tree_WidthOfRightColumns(tree)) { dInfo->widthOfColumnsLeft = Tree_WidthOfLeftColumns(tree); dInfo->widthOfColumnsRight = Tree_WidthOfRightColumns(tree); dInfo->flags |= DINFO_SET_ORIGIN_X | DINFO_UPDATE_SCROLLBAR_X/* | DINFO_OUT_OF_DATE | DINFO_REDO_RANGES | DINFO_DRAW_HEADER*/; } Range_RedoIfNeeded(tree); Increment_RedoIfNeeded(tree); if (dInfo->xOrigin != tree->xOrigin) { dInfo->flags |= DINFO_UPDATE_SCROLLBAR_X | DINFO_OUT_OF_DATE | DINFO_DRAW_HEADER; } if (dInfo->yOrigin != tree->yOrigin) { dInfo->flags |= DINFO_UPDATE_SCROLLBAR_Y | DINFO_OUT_OF_DATE; } if (dInfo->totalWidth != Tree_TotalWidth(tree)) { dInfo->totalWidth = Tree_TotalWidth(tree); dInfo->flags |= DINFO_SET_ORIGIN_X | DINFO_UPDATE_SCROLLBAR_X | DINFO_OUT_OF_DATE; } if (dInfo->totalHeight != Tree_TotalHeight(tree)) { dInfo->totalHeight = Tree_TotalHeight(tree); dInfo->flags |= DINFO_SET_ORIGIN_Y | DINFO_UPDATE_SCROLLBAR_Y | DINFO_OUT_OF_DATE; } if (dInfo->flags & DINFO_SET_ORIGIN_X) { Tree_SetOriginX(tree, tree->xOrigin); dInfo->flags &= ~DINFO_SET_ORIGIN_X; } if (dInfo->flags & DINFO_SET_ORIGIN_Y) { Tree_SetOriginY(tree, tree->yOrigin); dInfo->flags &= ~DINFO_SET_ORIGIN_Y; } #ifdef COMPLEX_WHITESPACE /* If -itembackground colors are being drawn in the whitespace region, * then redraw all the whitespace if: * a) scrolling occurs, or * b) all the display info was marked as invalid (such as when * -itembackground colors change, or a column moves), or * c) item/column sizes change (handled by Range_RedoIfNeeded). */ complexWhitespace = ComplexWhitespace(tree); if (complexWhitespace) { if ((dInfo->xOrigin != tree->xOrigin) || (dInfo->yOrigin != tree->yOrigin) || (dInfo->flags & DINFO_INVALIDATE)) { dInfo->flags |= DINFO_DRAW_WHITESPACE; } } /* If tree->columnBgCnt was > 0 but is now 0, redraw whitespace. */ if (complexWhitespace != dInfo->complexWhitespace) { dInfo->complexWhitespace = complexWhitespace; dInfo->flags |= DINFO_DRAW_WHITESPACE; } #endif /* * dInfo->requests counts the number of calls to Tree_EventuallyRedraw(). * If binding scripts do something that causes a redraw to be requested, * then we abort the current draw and start again. */ TreeDisplay_GetReadyForTrouble(tree, &requests); if (dInfo->flags & DINFO_UPDATE_SCROLLBAR_X) { /* Possible event. */ Tree_UpdateScrollbarX(tree); dInfo->flags &= ~DINFO_UPDATE_SCROLLBAR_X; } if (dInfo->flags & DINFO_UPDATE_SCROLLBAR_Y) { /* Possible event. */ Tree_UpdateScrollbarY(tree); dInfo->flags &= ~DINFO_UPDATE_SCROLLBAR_Y; } if (tree->deleted || !Tk_IsMapped(tkwin)) goto displayExit; if (TreeDisplay_WasThereTrouble(tree, requests)) { goto displayRetry; } if (dInfo->flags & DINFO_OUT_OF_DATE) { Tree_UpdateDInfo(tree); dInfo->flags &= ~DINFO_OUT_OF_DATE; } if (dInfo->flags & DINFO_INVALIDATE) { for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { dItem->area.flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; dItem->left.flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; dItem->right.flags |= DITEM_DIRTY | DITEM_ALL_DIRTY; } dInfo->flags &= ~DINFO_INVALIDATE; } /* * When an item goes from visible to hidden, "window" elements in the * item must be hidden. An item may become hidden because of scrolling, * or because an ancestor was collapsed, or because the -visible option * of the item changed. */ { Tcl_HashEntry *hPtr; Tcl_HashSearch search; TreeItemList newV, newH; TreeItem item; int isNew, i, count; TreeItemList_Init(tree, &newV, 0); TreeItemList_Init(tree, &newH, 0); for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { hPtr = Tcl_FindHashEntry(&dInfo->itemVisHash, (char *) dItem->item); if (hPtr == NULL) { /* This item is now visible, wasn't before */ TreeItemList_Append(&newV, dItem->item); TreeItem_OnScreen(tree, dItem->item, TRUE); } #ifdef DCOLUMN /* The item was onscreen and still is. Figure out which * item-columns have become visible or hidden. */ else { TrackOnScreenColumnsForItem(tree, dItem->item, hPtr); } #endif /* DCOLUMN */ } hPtr = Tcl_FirstHashEntry(&dInfo->itemVisHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&dInfo->itemVisHash, hPtr); if (TreeItem_GetDInfo(tree, item) == NULL) { /* This item was visible but isn't now */ TreeItemList_Append(&newH, item); TreeItem_OnScreen(tree, item, FALSE); } hPtr = Tcl_NextHashEntry(&search); } /* Remove newly-hidden items from itemVisHash */ count = TreeItemList_Count(&newH); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&newH, i); hPtr = Tcl_FindHashEntry(&dInfo->itemVisHash, (char *) item); #ifdef DCOLUMN TrackOnScreenColumnsForItem(tree, item, hPtr); ckfree((char *) Tcl_GetHashValue(hPtr)); #endif Tcl_DeleteHashEntry(hPtr); } /* Add newly-visible items to itemVisHash */ count = TreeItemList_Count(&newV); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&newV, i); hPtr = Tcl_CreateHashEntry(&dInfo->itemVisHash, (char *) item, &isNew); #ifdef DCOLUMN TrackOnScreenColumnsForItem(tree, item, hPtr); #endif /* DCOLUMN */ } /* * Generate an event here. This can be used to set * an item's styles when the item is about to be displayed, and to * clear an item's styles when the item is no longer displayed. */ if (TreeItemList_Count(&newV) || TreeItemList_Count(&newH)) { TreeNotify_ItemVisibility(tree, &newV, &newH); } TreeItemList_Free(&newV); TreeItemList_Free(&newH); if (tree->deleted || !Tk_IsMapped(tkwin)) goto displayExit; if (TreeDisplay_WasThereTrouble(tree, requests)) goto displayRetry; } tdrawable.width = Tk_Width(tkwin); tdrawable.height = Tk_Height(tkwin); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { tdrawable.drawable = DisplayGetPixmap(tree, &dInfo->pixmapW, tdrawable.width, tdrawable.height); } else { tdrawable.drawable = Tk_WindowId(tkwin); } drawable = tdrawable.drawable; /* XOR off */ TreeColumnProxy_Undisplay(tree); TreeRowProxy_Undisplay(tree); TreeDragImage_Undisplay(tree->dragImage); TreeMarquee_Undisplay(tree->marquee); if (dInfo->flags & DINFO_DRAW_HEADER) { if (Tree_AreaBbox(tree, TREE_AREA_HEADER, &minX, &minY, &maxX, &maxY)) { if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) { XFillRectangle(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, minX, minY, maxX - minX, maxY - minY); DisplayDelay(tree); } Tree_DrawHeader(tree, tdrawable, 0 - tree->xOrigin, Tree_HeaderTop(tree)); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { DblBufWinDirty(tree, minX, minY, maxX, maxY); } } dInfo->flags &= ~DINFO_DRAW_HEADER; } if (tree->vertical) { numCopy = ScrollVerticalComplex(tree); ScrollHorizontalSimple(tree); } else { ScrollVerticalSimple(tree); numCopy = ScrollHorizontalComplex(tree); } /* If we scrolled, then copy the entire pixmap, plus the header * if needed. */ if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { if ((dInfo->xOrigin != tree->xOrigin) || (dInfo->yOrigin != tree->yOrigin)) { DblBufWinDirty(tree, Tree_BorderLeft(tree), Tree_ContentTop(tree), Tree_BorderRight(tree), Tree_ContentBottom(tree)); } } if (dInfo->flags & DINFO_DRAW_WHITESPACE) { TkSubtractRegion(dInfo->wsRgn, dInfo->wsRgn, dInfo->wsRgn); dInfo->flags &= ~DINFO_DRAW_WHITESPACE; } if (tree->backgroundImage != NULL) { wsRgnNew = CalcWhiteSpaceRegion(tree); /* If we scrolled, redraw entire whitespace area */ if (dInfo->xOrigin != tree->xOrigin || dInfo->yOrigin != tree->yOrigin) { wsRgnDif = wsRgnNew; } else { wsRgnDif = Tree_GetRegion(tree); TkSubtractRegion(wsRgnNew, dInfo->wsRgn, wsRgnDif); } TkClipBox(wsRgnDif, &wsBox); if ((wsBox.width > 0) && (wsBox.height > 0)) { Drawable pixmap = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), wsBox.width, wsBox.height, Tk_Depth(tkwin)); GC gc = Tk_3DBorderGC(tkwin, tree->border, TK_3D_FLAT_GC); if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) { Tree_FillRegion(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, wsRgnDif); DisplayDelay(tree); } /* FIXME: only if backgroundImage is transparent */ Tree_OffsetRegion(wsRgnDif, -wsBox.x, -wsBox.y); Tree_FillRegion(tree->display, pixmap, gc, wsRgnDif); Tree_OffsetRegion(wsRgnDif, wsBox.x, wsBox.y); /* tree->drawableXOrigin = tree->xOrigin + wsBox.x; tree->drawableYOrigin = tree->yOrigin + wsBox.y;*/ Tree_DrawTiledImage(tree, pixmap, tree->backgroundImage, 0, 0, wsBox.width, wsBox.height, tree->xOrigin + wsBox.x, tree->yOrigin + wsBox.y); TkSetRegion(tree->display, tree->copyGC, wsRgnNew); /* XSetClipOrigin(tree->display, tree->copyGC, 0, 0);*/ XCopyArea(tree->display, pixmap, drawable, tree->copyGC, 0, 0, wsBox.width, wsBox.height, wsBox.x, wsBox.y); XSetClipMask(tree->display, tree->copyGC, None); /* XSetClipOrigin(tree->display, tree->copyGC, 0, 0);*/ Tk_FreePixmap(tree->display, pixmap); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { DblBufWinDirty(tree, wsBox.x, wsBox.y, wsBox.x + wsBox.width, wsBox.y + wsBox.height); } } if (wsRgnDif != wsRgnNew) Tree_FreeRegion(tree, wsRgnDif); Tree_FreeRegion(tree, dInfo->wsRgn); dInfo->wsRgn = wsRgnNew; } dInfo->xOrigin = tree->xOrigin; dInfo->yOrigin = tree->yOrigin; /* Does this need to be here? */ dInfo->flags &= ~(DINFO_REDRAW_PENDING); if (tree->backgroundImage == NULL) { /* Calculate the current whitespace region, subtract the old whitespace * region, and fill the difference with the background color. */ wsRgnNew = CalcWhiteSpaceRegion(tree); wsRgnDif = Tree_GetRegion(tree); TkSubtractRegion(wsRgnNew, dInfo->wsRgn, wsRgnDif); TkClipBox(wsRgnDif, &wsBox); if ((wsBox.width > 0) && (wsBox.height > 0)) { #ifndef COMPLEX_WHITESPACE GC gc = Tk_3DBorderGC(tkwin, tree->border, TK_3D_FLAT_GC); #endif if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) { Tree_FillRegion(tree->display, Tk_WindowId(tkwin), tree->debug.gcDraw, wsRgnDif); DisplayDelay(tree); } #ifdef COMPLEX_WHITESPACE DrawWhitespace(tree, drawable, wsRgnDif); #else Tree_FillRegion(tree->display, drawable, gc, wsRgnDif); #endif if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { DblBufWinDirty(tree, wsBox.x, wsBox.y, wsBox.x + wsBox.width, wsBox.y + wsBox.height); } } Tree_FreeRegion(tree, wsRgnDif); Tree_FreeRegion(tree, dInfo->wsRgn); dInfo->wsRgn = wsRgnNew; } /* See if there are any dirty items */ count = 0; for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { if ((!dInfo->empty && dInfo->rangeFirst != NULL) && (dItem->area.flags & DITEM_DIRTY)) { count++; break; } if (!dInfo->emptyL && (dItem->left.flags & DITEM_DIRTY)) { count++; break; } if (!dInfo->emptyR && (dItem->right.flags & DITEM_DIRTY)) { count++; break; } } /* Display dirty items */ if (count > 0) { TreeDrawable tpixmap = tdrawable; if (tree->doubleBuffer != DOUBLEBUFFER_NONE) { /* Allocate pixmap for largest item */ tpixmap.width = MIN(Tk_Width(tkwin), dInfo->itemWidth); tpixmap.height = MIN(Tk_Height(tkwin), dInfo->itemHeight); tpixmap.drawable = DisplayGetPixmap(tree, &dInfo->pixmapI, tpixmap.width, tpixmap.height); } for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { int drawn = 0; if (!dInfo->empty && dInfo->rangeFirst != NULL) { tree->drawableXOrigin = tree->xOrigin; tree->drawableYOrigin = tree->yOrigin; TreeItem_UpdateWindowPositions(tree, dItem->item, COLUMN_LOCK_NONE, dItem->area.x, dItem->y, dItem->area.width, dItem->height); if (TreeDisplay_WasThereTrouble(tree, requests)) { if (tree->deleted || !Tk_IsMapped(tree->tkwin)) goto displayExit; goto displayRetry; } if (dItem->area.flags & DITEM_DIRTY) { drawn += DisplayDItem(tree, dItem, &dItem->area, COLUMN_LOCK_NONE, dInfo->bounds, tpixmap, tdrawable); } } if (!dInfo->emptyL) { tree->drawableXOrigin = tree->xOrigin; tree->drawableYOrigin = tree->yOrigin; TreeItem_UpdateWindowPositions(tree, dItem->item, COLUMN_LOCK_LEFT, dItem->left.x, dItem->y, dItem->left.width, dItem->height); if (TreeDisplay_WasThereTrouble(tree, requests)) { if (tree->deleted || !Tk_IsMapped(tree->tkwin)) goto displayExit; goto displayRetry; } if (dItem->left.flags & DITEM_DIRTY) { drawn += DisplayDItem(tree, dItem, &dItem->left, COLUMN_LOCK_LEFT, dInfo->boundsL, tpixmap, tdrawable); } } if (!dInfo->emptyR) { tree->drawableXOrigin = tree->xOrigin; tree->drawableYOrigin = tree->yOrigin; TreeItem_UpdateWindowPositions(tree, dItem->item, COLUMN_LOCK_RIGHT, dItem->right.x, dItem->y, dItem->right.width, dItem->height); if (TreeDisplay_WasThereTrouble(tree, requests)) { if (tree->deleted || !Tk_IsMapped(tree->tkwin)) goto displayExit; goto displayRetry; } if (dItem->right.flags & DITEM_DIRTY) { drawn += DisplayDItem(tree, dItem, &dItem->right, COLUMN_LOCK_RIGHT, dInfo->boundsR, tpixmap, tdrawable); } } numDraw += drawn ? 1 : 0; dItem->oldX = dItem->area.x; /* FIXME: could have dInfo->empty */ dItem->oldY = dItem->y; dItem->oldIndex = dItem->index; } } if (tree->debug.enable && tree->debug.display) dbwin("copy %d draw %d %s\n", numCopy, numDraw, Tk_PathName(tkwin)); if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { XRectangle box; drawable = Tk_WindowId(tkwin); TkClipBox(dInfo->dirtyRgn, &box); if (box.width > 0 && box.height > 0) { TkSetRegion(tree->display, tree->copyGC, dInfo->dirtyRgn); XCopyArea(tree->display, dInfo->pixmapW.drawable, drawable, tree->copyGC, box.x, box.y, box.width, box.height, box.x, box.y); XSetClipMask(tree->display, tree->copyGC, None); } TkSubtractRegion(dInfo->dirtyRgn, dInfo->dirtyRgn, dInfo->dirtyRgn); DisplayDelay(tree); } /* XOR on */ TreeMarquee_Display(tree->marquee); TreeDragImage_Display(tree->dragImage); TreeRowProxy_Display(tree); TreeColumnProxy_Display(tree); if (tree->doubleBuffer == DOUBLEBUFFER_NONE) dInfo->flags |= DINFO_DRAW_HIGHLIGHT | DINFO_DRAW_BORDER; if (dInfo->flags & (DINFO_DRAW_BORDER | DINFO_DRAW_HIGHLIGHT)) { if (tree->useTheme && TreeTheme_DrawBorders(tree, drawable) == TCL_OK) { /* nothing */ } else { /* Draw focus rectangle (outside of 3D-border) */ if ((dInfo->flags & DINFO_DRAW_HIGHLIGHT) && (tree->highlightWidth > 0)) { GC fgGC, bgGC; DebugDrawBorder(tree, 0, tree->highlightWidth, tree->highlightWidth, tree->highlightWidth, tree->highlightWidth); bgGC = Tk_GCForColor(tree->highlightBgColorPtr, drawable); if (tree->gotFocus) fgGC = Tk_GCForColor(tree->highlightColorPtr, drawable); else fgGC = bgGC; TkpDrawHighlightBorder(tkwin, fgGC, bgGC, tree->highlightWidth, drawable); dInfo->flags &= ~DINFO_DRAW_HIGHLIGHT; } /* Draw 3D-border (inside of focus rectangle) */ if ((dInfo->flags & DINFO_DRAW_BORDER) && (tree->borderWidth > 0)) { DebugDrawBorder(tree, tree->highlightWidth, tree->borderWidth, tree->borderWidth, tree->borderWidth, tree->borderWidth); Tk_Draw3DRectangle(tkwin, drawable, tree->border, tree->highlightWidth, tree->highlightWidth, Tk_Width(tkwin) - tree->highlightWidth * 2, Tk_Height(tkwin) - tree->highlightWidth * 2, tree->borderWidth, tree->relief); dInfo->flags &= ~DINFO_DRAW_BORDER; } } dInfo->flags &= ~(DINFO_DRAW_BORDER | DINFO_DRAW_HIGHLIGHT); } displayExit: dInfo->flags &= ~(DINFO_REDRAW_PENDING); Tree_ReleaseItems(tree); Tcl_Release((ClientData) tree); } /* *-------------------------------------------------------------- * * A_IncrementFindX -- * * Return a horizontal scroll position nearest to the given * offset. * * Results: * Index of the nearest increment <= the given offset. * * Side effects: * None. * *-------------------------------------------------------------- */ static int A_IncrementFindX( TreeCtrl *tree, /* Widget info. */ int offset /* Canvas x-coordinate. */ ) { int totWidth = Tree_TotalWidth(tree); int xIncr = tree->xScrollIncrement; int index, indexMax; indexMax = totWidth / xIncr; if (totWidth % xIncr == 0) indexMax--; if (offset < 0) offset = 0; index = offset / xIncr; if (index > indexMax) index = indexMax; return index; } /* *-------------------------------------------------------------- * * A_IncrementFindY -- * * Return a vertical scroll position nearest to the given * offset. * * Results: * Index of the nearest increment <= the given offset. * * Side effects: * None. * *-------------------------------------------------------------- */ static int A_IncrementFindY( TreeCtrl *tree, /* Widget info. */ int offset /* Canvas y-coordinate. */ ) { int totHeight = Tree_TotalHeight(tree); int yIncr = tree->yScrollIncrement; int index, indexMax; indexMax = totHeight / yIncr; if (totHeight % yIncr == 0) indexMax--; if (offset < 0) offset = 0; index = offset / yIncr; if (index > indexMax) index = indexMax; return index; } /* *-------------------------------------------------------------- * * Increment_FindX -- * * Return a horizontal scroll position nearest to the given * offset. * * Results: * Index of the nearest increment <= the given offset. * * Side effects: * None. * *-------------------------------------------------------------- */ int Increment_FindX( TreeCtrl *tree, /* Widget info. */ int offset /* Canvas x-coordinate. */ ) { if (tree->xScrollIncrement <= 0) { Increment_RedoIfNeeded(tree); return B_IncrementFindX(tree, offset); } return A_IncrementFindX(tree, offset); } /* *-------------------------------------------------------------- * * Increment_FindY -- * * Return a vertical scroll position nearest to the given * offset. * * Results: * Index of the nearest increment <= the given offset. * * Side effects: * None. * *-------------------------------------------------------------- */ int Increment_FindY( TreeCtrl *tree, /* Widget info. */ int offset /* Canvas y-coordinate. */ ) { if (tree->yScrollIncrement <= 0) { Increment_RedoIfNeeded(tree); return B_IncrementFindY(tree, offset); } return A_IncrementFindY(tree, offset); } /* *-------------------------------------------------------------- * * Increment_ToOffsetX -- * * Return the canvas coordinate for a scroll position. * * Results: * Pixel distance. * * Side effects: * None. * *-------------------------------------------------------------- */ int Increment_ToOffsetX( TreeCtrl *tree, /* Widget info. */ int index /* Index of the increment. */ ) { TreeDInfo dInfo = tree->dInfo; if (tree->xScrollIncrement <= 0) { if (index < 0 || index >= dInfo->xScrollIncrementCount) panic("Increment_ToOffsetX: bad index %d (must be 0-%d)", index, dInfo->xScrollIncrementCount-1); return dInfo->xScrollIncrements[index]; } return index * tree->xScrollIncrement; } /* *-------------------------------------------------------------- * * Increment_ToOffsetY -- * * Return the canvas coordinate for a scroll position. * * Results: * Pixel distance. * * Side effects: * None. * *-------------------------------------------------------------- */ int Increment_ToOffsetY( TreeCtrl *tree, /* Widget info. */ int index /* Index of the increment. */ ) { TreeDInfo dInfo = tree->dInfo; if (tree->yScrollIncrement <= 0) { if (index < 0 || index >= dInfo->yScrollIncrementCount) { panic("Increment_ToOffsetY: bad index %d (must be 0-%d)\ntotHeight %d visHeight %d", index, dInfo->yScrollIncrementCount - 1, Tree_TotalHeight(tree), Tree_ContentHeight(tree)); } return dInfo->yScrollIncrements[index]; } return index * tree->yScrollIncrement; } /* *-------------------------------------------------------------- * * GetScrollFractions -- * * Return the fractions that may be passed to a scrollbar "set" * command. * * Results: * Two fractions from 0.0 to 1.0. * * Side effects: * None. * *-------------------------------------------------------------- */ static void GetScrollFractions( int screen1, int screen2, /* Min/max coordinates that are visible in * the window. */ int object1, int object2, /* Min/max coordinates of the scrollable * content (usually 0 to N where N is the * total width or height of the canvas). */ double fractions[2] /* Returned values. */ ) { double range, f1, f2; range = object2 - object1; if (range <= 0) { f1 = 0; f2 = 1.0; } else { f1 = (screen1 - object1) / range; if (f1 < 0) f1 = 0.0; f2 = (screen2 - object1) / range; if (f2 > 1.0) f2 = 1.0; if (f2 < f1) f2 = f1; } fractions[0] = f1; fractions[1] = f2; } /* *-------------------------------------------------------------- * * Tree_GetScrollFractionsX -- * * Return the fractions that may be passed to a scrollbar "set" * command for a horizontal scrollbar. * * Results: * Two fractions from 0 to 1.0. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_GetScrollFractionsX( TreeCtrl *tree, /* Widget info. */ double fractions[2] /* Returned values. */ ) { int left = tree->xOrigin + Tree_ContentLeft(tree); int visWidth = Tree_ContentWidth(tree); int totWidth = Tree_TotalWidth(tree); int index, offset; /* The tree is empty, or everything fits in the window */ if (visWidth < 0) visWidth = 0; if (totWidth <= visWidth) { fractions[0] = 0.0; fractions[1] = 1.0; return; } if (visWidth <= 1) { GetScrollFractions(left, left + 1, 0, totWidth, fractions); return; } /* Find incrementLeft when scrolled to extreme right */ index = Increment_FindX(tree, totWidth - visWidth); offset = Increment_ToOffsetX(tree, index); if (offset < totWidth - visWidth) { index++; offset = Increment_ToOffsetX(tree, index); } /* Add some fake content to right */ if (offset + visWidth > totWidth) totWidth = offset + visWidth; GetScrollFractions(left, left + visWidth, 0, totWidth, fractions); } /* *-------------------------------------------------------------- * * Tree_GetScrollFractionsY -- * * Return the fractions that may be passed to a scrollbar "set" * command for a vertical scrollbar. * * Results: * Two fractions from 0 to 1.0. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_GetScrollFractionsY( TreeCtrl *tree, /* Widget info. */ double fractions[2] /* Returned values. */ ) { int top = Tree_ContentTop(tree) + tree->yOrigin; /* canvas coords */ int visHeight = Tree_ContentHeight(tree); int totHeight = Tree_TotalHeight(tree); int index, offset; /* The tree is empty, or everything fits in the window */ if (visHeight < 0) visHeight = 0; if (totHeight <= visHeight) { fractions[0] = 0.0; fractions[1] = 1.0; return; } if (visHeight <= 1) { GetScrollFractions(top, top + 1, 0, totHeight, fractions); return; } /* Find incrementTop when scrolled to bottom */ index = Increment_FindY(tree, totHeight - visHeight); offset = Increment_ToOffsetY(tree, index); if (offset < totHeight - visHeight) { index++; offset = Increment_ToOffsetY(tree, index); } /* Add some fake content to bottom */ if (offset + visHeight > totHeight) totHeight = offset + visHeight; GetScrollFractions(top, top + visHeight, 0, totHeight, fractions); } /* *-------------------------------------------------------------- * * Tree_SetOriginX -- * * Change the horizontal scroll position. * * Results: * None. * * Side effects: * If the horizontal scroll position changes, then the widget is * redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_SetOriginX( TreeCtrl *tree, /* Widget info. */ int xOrigin /* The desired offset from the left edge * of the window to the left edge of the * canvas. The actual value will be clipped * to the nearest scroll increment. */ ) { TreeDInfo dInfo = tree->dInfo; int totWidth = Tree_TotalWidth(tree); int visWidth = Tree_ContentWidth(tree); int index, indexMax, offset; /* The tree is empty, or everything fits in the window */ if (visWidth < 0) visWidth = 0; if (totWidth <= visWidth) { xOrigin = 0 - Tree_ContentLeft(tree); if (xOrigin != tree->xOrigin) { tree->xOrigin = xOrigin; dInfo->incrementLeft = 0; Tree_EventuallyRedraw(tree); } return; } if (visWidth > 1) { /* Find incrementLeft when scrolled to extreme right */ indexMax = Increment_FindX(tree, totWidth - visWidth); offset = Increment_ToOffsetX(tree, indexMax); if (offset < totWidth - visWidth) { indexMax++; offset = Increment_ToOffsetX(tree, indexMax); } /* Add some fake content to right */ if (offset + visWidth > totWidth) totWidth = offset + visWidth; } else indexMax = Increment_FindX(tree, totWidth); xOrigin += Tree_ContentLeft(tree); /* origin -> canvas */ index = Increment_FindX(tree, xOrigin); /* Don't scroll too far left */ if (index < 0) index = 0; /* Don't scroll too far right */ if (index > indexMax) index = indexMax; offset = Increment_ToOffsetX(tree, index); xOrigin = offset - Tree_ContentLeft(tree); if (xOrigin == tree->xOrigin) return; tree->xOrigin = xOrigin; dInfo->incrementLeft = index; Tree_EventuallyRedraw(tree); } /* *-------------------------------------------------------------- * * Tree_SetOriginY -- * * Change the vertical scroll position. * * Results: * None. * * Side effects: * If the vertical scroll position changes, then the widget is * redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_SetOriginY( TreeCtrl *tree, /* Widget info. */ int yOrigin /* The desired offset from the top edge * of the window to the top edge of the * canvas. The actual value will be clipped * to the nearest scroll increment. */ ) { TreeDInfo dInfo = tree->dInfo; int visHeight = Tree_ContentHeight(tree); int totHeight = Tree_TotalHeight(tree); int index, indexMax, offset; /* The tree is empty, or everything fits in the window */ if (visHeight < 0) visHeight = 0; if (totHeight <= visHeight) { yOrigin = 0 - Tree_ContentTop(tree); if (yOrigin != tree->yOrigin) { tree->yOrigin = yOrigin; dInfo->incrementTop = 0; Tree_EventuallyRedraw(tree); } return; } if (visHeight > 1) { /* Find incrementTop when scrolled to bottom */ indexMax = Increment_FindY(tree, totHeight - visHeight); offset = Increment_ToOffsetY(tree, indexMax); if (offset < totHeight - visHeight) { indexMax++; offset = Increment_ToOffsetY(tree, indexMax); } /* Add some fake content to bottom */ if (offset + visHeight > totHeight) totHeight = offset + visHeight; } else indexMax = Increment_FindY(tree, totHeight); yOrigin += Tree_ContentTop(tree); /* origin -> canvas */ index = Increment_FindY(tree, yOrigin); /* Don't scroll too far up */ if (index < 0) index = 0; /* Don't scroll too far down */ if (index > indexMax) index = indexMax; offset = Increment_ToOffsetY(tree, index); yOrigin = offset - Tree_ContentTop(tree); if (yOrigin == tree->yOrigin) return; tree->yOrigin = yOrigin; dInfo->incrementTop = index; Tree_EventuallyRedraw(tree); } /* *-------------------------------------------------------------- * * Tree_EventuallyRedraw -- * * Schedule an idle task to redisplay the widget, if one is not * already scheduled and the widget is mapped and the widget * hasn't been deleted. * * Results: * None. * * Side effects: * The widget may be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_EventuallyRedraw( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; dInfo->requests++; if ((dInfo->flags & DINFO_REDRAW_PENDING) || tree->deleted || !Tk_IsMapped(tree->tkwin)) { return; } dInfo->flags |= DINFO_REDRAW_PENDING; Tcl_DoWhenIdle(Tree_Display, (ClientData) tree); } /* *-------------------------------------------------------------- * * Tree_RelayoutWindow -- * * Invalidate all the layout info for the widget and schedule a * redisplay at idle time. This gets called when certain config * options change and when the size of the widget changes. * * Results: * None. * * Side effects: * The widget will be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_RelayoutWindow( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; FreeDItems(tree, dInfo->dItem, NULL, 0); dInfo->dItem = NULL; dInfo->flags |= DINFO_REDO_RANGES | DINFO_OUT_OF_DATE | DINFO_CHECK_COLUMN_WIDTH | DINFO_DRAW_HEADER | DINFO_DRAW_HIGHLIGHT | DINFO_DRAW_BORDER | DINFO_SET_ORIGIN_X | DINFO_SET_ORIGIN_Y | DINFO_UPDATE_SCROLLBAR_X | DINFO_UPDATE_SCROLLBAR_Y; dInfo->xOrigin = tree->xOrigin; dInfo->yOrigin = tree->yOrigin; /* Needed if -background color changes. */ dInfo->flags |= DINFO_DRAW_WHITESPACE; if (tree->doubleBuffer != DOUBLEBUFFER_WINDOW) { if (dInfo->pixmapW.drawable != None) { Tk_FreePixmap(tree->display, dInfo->pixmapW.drawable); dInfo->pixmapW.drawable = None; } } if (tree->doubleBuffer == DOUBLEBUFFER_NONE) { if (dInfo->pixmapI.drawable != None) { Tk_FreePixmap(tree->display, dInfo->pixmapI.drawable); dInfo->pixmapI.drawable = None; } } if (tree->useTheme) { TreeTheme_Relayout(tree); TreeTheme_SetBorders(tree); } Tree_EventuallyRedraw(tree); } /* *-------------------------------------------------------------- * * Tree_FocusChanged -- * * This procedure handles the widget gaining or losing the input * focus. The state of every item has STATE_FOCUS toggled on or * off. * * Results: * None. * * Side effects: * The widget may be redisplayed at idle time if -highlightthickness * is > 0, or if any Elements change appearance because of the * state change. * *-------------------------------------------------------------- */ void Tree_FocusChanged( TreeCtrl *tree, /* Widget info. */ int gotFocus /* TRUE if the widget has the focus, * otherwise FALSE. */ ) { TreeDInfo dInfo = tree->dInfo; TreeItem item; Tcl_HashEntry *hPtr; Tcl_HashSearch search; int stateOn, stateOff; tree->gotFocus = gotFocus; if (gotFocus) stateOff = 0, stateOn = STATE_FOCUS; else stateOff = STATE_FOCUS, stateOn = 0; /* Slow. Change state of every item */ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); TreeItem_ChangeState(tree, item, stateOff, stateOn); hPtr = Tcl_NextHashEntry(&search); } #ifdef USE_TTK dInfo->flags |= DINFO_DRAW_HIGHLIGHT; Tree_EventuallyRedraw(tree); #else if (tree->highlightWidth > 0) { dInfo->flags |= DINFO_DRAW_HIGHLIGHT; Tree_EventuallyRedraw(tree); } #endif } /* *-------------------------------------------------------------- * * Tree_Activate -- * * This procedure handles the widget's toplevel being the "active" * foreground window (on Macintosh and Windows). Currently it just * redraws the header if -usetheme is TRUE and the header is * visible. * * Results: * None. * * Side effects: * The widget may be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_Activate( TreeCtrl *tree, /* Widget info. */ int isActive /* TRUE if the widget's toplevel is the * active window, otherwise FALSE. */ ) { TreeDInfo dInfo = tree->dInfo; tree->isActive = isActive; /* TODO: Like Tree_FocusChanged, change state of every item. */ /* Would need a new item state STATE_ACTIVEWINDOW or something. */ /* Would want to merge this with Tree_FocusChanged code to avoid * double-iteration of items. */ /* Aqua column header looks different when window is not active */ if (tree->useTheme && tree->showHeader) { dInfo->flags |= DINFO_DRAW_HEADER; Tree_EventuallyRedraw(tree); } } /* *-------------------------------------------------------------- * * Tree_FreeItemDInfo -- * * Free any DItem associated with each item in a range of items. * This is called when the size of an item changed or an item is * deleted. * * Results: * None. * * Side effects: * The widget will be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_FreeItemDInfo( TreeCtrl *tree, /* Widget info. */ TreeItem item1, /* First item in the range. */ TreeItem item2 /* Last item in the range, or NULL. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; TreeItem item = item1; int changed = 0; while (item != NULL) { dItem = (DItem *) TreeItem_GetDInfo(tree, item); if (dItem != NULL) { FreeDItems(tree, dItem, dItem->next, 1); changed = 1; } if (item == item2 || item2 == NULL) break; item = TreeItem_Next(tree, item); } changed = 1; if (changed) { dInfo->flags |= DINFO_OUT_OF_DATE; Tree_EventuallyRedraw(tree); } } /* *-------------------------------------------------------------- * * Tree_InvalidateItemDInfo -- * * Mark as dirty any DItem associated with each item in a range * of items. This is called when the appearance of an item changed * (but not its size). * * Results: * None. * * Side effects: * The widget will be redisplayed at idle time if any of the items * had a DItem. * *-------------------------------------------------------------- */ void Tree_InvalidateItemDInfo( TreeCtrl *tree, /* Widget info. */ TreeColumn column, /* Column to invalidate, or NULL for all. */ TreeItem item1, /* First item in the range. */ TreeItem item2 /* Last item in the range, or NULL. */ ) { TreeDInfo dInfo = tree->dInfo; TreeColumn column2; DItem *dItem; TreeItem item = item1; int changed = 0; if (dInfo->flags & (DINFO_INVALIDATE | DINFO_REDO_COLUMN_WIDTH)) return; while (item != NULL) { dItem = (DItem *) TreeItem_GetDInfo(tree, item); if ((dItem == NULL) || DItemAllDirty(tree, dItem)) goto next; if (column == NULL) { dItem->area.flags |= (DITEM_DIRTY | DITEM_ALL_DIRTY); dItem->left.flags |= (DITEM_DIRTY | DITEM_ALL_DIRTY); dItem->right.flags |= (DITEM_DIRTY | DITEM_ALL_DIRTY); changed = 1; } else { TreeColumnDInfo dColumn = TreeColumn_GetDInfo(column); int columnIndex, left, width, i; DItemArea *area = NULL; switch (TreeColumn_Lock(column)) { case COLUMN_LOCK_NONE: area = &dItem->area; break; case COLUMN_LOCK_LEFT: area = &dItem->left; break; case COLUMN_LOCK_RIGHT: area = &dItem->right; break; } if (area->flags & DITEM_ALL_DIRTY) goto next; columnIndex = TreeColumn_Index(column); left = dColumn->offset; /* If only one column is visible, the width may be * different than the column width. */ if ((TreeColumn_Lock(column) == COLUMN_LOCK_NONE) && (tree->columnCountVis == 1)) { width = area->width; /* All spans are 1. */ } else if (dItem->spans == NULL) { width = dColumn->width; /* If the column being redrawn is not the first in the span, * then do nothing. */ } else if (columnIndex != dItem->spans[columnIndex]) { goto next; /* Calculate the width of the entire span. */ /* Do NOT call TreeColumn_UseWidth() or another routine * that calls Tree_WidthOfColumns() because that may end * up recalculating the size of items whose display info * is currently being invalidated. */ } else { width = 0; column2 = column; i = columnIndex; while (dItem->spans[i] == columnIndex) { width += TreeColumn_GetDInfo(column2)->width; if (++i == tree->columnCount) break; column2 = TreeColumn_Next(column2); } } if (width > 0) { InvalidateDItemX(dItem, area, 0, left, width); InvalidateDItemY(dItem, area, 0, 0, dItem->height); area->flags |= DITEM_DIRTY; changed = 1; } } next: if (item == item2 || item2 == NULL) break; item = TreeItem_Next(tree, item); } if (changed) { Tree_EventuallyRedraw(tree); } } /* *-------------------------------------------------------------- * * TreeDisplay_ItemDeleted -- * * Removes an item from the hash table of on-screen items. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void TreeDisplay_ItemDeleted( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item to remove. */ ) { TreeDInfo dInfo = tree->dInfo; Tcl_HashEntry *hPtr; hPtr = Tcl_FindHashEntry(&dInfo->itemVisHash, (char *) item); if (hPtr != NULL) { #ifdef DCOLUMN ckfree((char *) Tcl_GetHashValue(hPtr)); #endif Tcl_DeleteHashEntry(hPtr); } } /* *-------------------------------------------------------------- * * TreeDisplay_ColumnDeleted -- * * Removes a column from the list of on-screen columns for * all on-screen items. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void TreeDisplay_ColumnDeleted( TreeCtrl *tree, /* Widget info. */ TreeColumn column /* Column to remove. */ ) { #ifdef DCOLUMN TreeDInfo dInfo = tree->dInfo; Tcl_HashSearch search; Tcl_HashEntry *hPtr; TreeColumn *value; int i; hPtr = Tcl_FirstHashEntry(&dInfo->itemVisHash, &search); while (hPtr != NULL) { value = (TreeColumn *) Tcl_GetHashValue(hPtr); for (i = 0; value[i] != NULL; i++) { if (value[i] == column) { while (value[i] != NULL) { value[i] = value[i + 1]; ++i; } if (tree->debug.enable && tree->debug.span) dbwin("TreeDisplay_ColumnDeleted item %d column %d\n", TreeItem_GetID(tree, (TreeItem) Tcl_GetHashKey( &dInfo->itemVisHash, hPtr)), TreeColumn_GetID(column)); break; } } hPtr = Tcl_NextHashEntry(&search); } #endif } /* *-------------------------------------------------------------- * * TreeDisplay_FreeColumnDInfo -- * * Free any display info associated with a column when it is * deleted. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void TreeDisplay_FreeColumnDInfo( TreeCtrl *tree, /* Widget info. */ TreeColumn column /* Column info. */ ) { TreeColumnDInfo dColumn = TreeColumn_GetDInfo(column); if (dColumn != NULL) ckfree((char *) dColumn); } /* *-------------------------------------------------------------- * * Tree_DInfoChanged -- * * Set some DINFO_xxx flags and schedule a redisplay. * * Results: * None. * * Side effects: * The widget will be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_DInfoChanged( TreeCtrl *tree, /* Widget info. */ int flags /* DINFO_xxx flags. */ ) { TreeDInfo dInfo = tree->dInfo; dInfo->flags |= flags; Tree_EventuallyRedraw(tree); } /* *-------------------------------------------------------------- * * Tree_InvalidateArea -- * * Mark as dirty parts of any DItems in the given area. If the given * area overlaps the borders they are marked as needing to be * redrawn. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_InvalidateArea( TreeCtrl *tree, /* Widget info. */ int x1, int y1, /* Left & top of dirty area in window * coordinates. */ int x2, int y2 /* Right & bottom of dirty area in window * coordinates. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; if (x1 >= x2 || y1 >= y2) return; if ((y2 > Tree_HeaderTop(tree)) && (y1 < Tree_HeaderBottom(tree))) dInfo->flags |= DINFO_DRAW_HEADER; dItem = dInfo->dItem; while (dItem != NULL) { if ((!dInfo->empty && dInfo->rangeFirst != NULL) && !(dItem->area.flags & DITEM_ALL_DIRTY) && (x2 > dItem->area.x) && (x1 < dItem->area.x + dItem->area.width) && (y2 > dItem->y) && (y1 < dItem->y + dItem->height)) { InvalidateDItemX(dItem, &dItem->area, dItem->area.x, x1, x2 - x1); InvalidateDItemY(dItem, &dItem->area, dItem->y, y1, y2 - y1); dItem->area.flags |= DITEM_DIRTY; } if (!dInfo->emptyL && !(dItem->left.flags & DITEM_ALL_DIRTY) && (x2 > dInfo->boundsL[0]) && (x1 < dInfo->boundsL[2]) && (y2 > dItem->y) && (y1 < dItem->y + dItem->height)) { InvalidateDItemX(dItem, &dItem->left, dItem->left.x, x1, x2 - x1); InvalidateDItemY(dItem, &dItem->left, dItem->y, y1, y2 - y1); dItem->left.flags |= DITEM_DIRTY; } if (!dInfo->emptyR && !(dItem->right.flags & DITEM_ALL_DIRTY) && (x2 > dInfo->boundsR[0]) && (x1 < dInfo->boundsR[2]) && (y2 > dItem->y) && (y1 < dItem->y + dItem->height)) { InvalidateDItemX(dItem, &dItem->right, dItem->right.x, x1, x2 - x1); InvalidateDItemY(dItem, &dItem->right, dItem->y, y1, y2 - y1); dItem->right.flags |= DITEM_DIRTY; } dItem = dItem->next; } if ((x1 < Tree_BorderLeft(tree)) || (y1 < Tree_BorderTop(tree)) || (x2 > Tree_BorderRight(tree)) || (y2 > Tree_BorderBottom(tree))) { dInfo->flags |= DINFO_DRAW_HIGHLIGHT; dInfo->flags |= DINFO_DRAW_BORDER; } /* Invalidate part of the whitespace */ if ((x1 < x2 && y1 < y2) && TkRectInRegion(dInfo->wsRgn, x1, y1, x2 - x1, y2 - y1)) { XRectangle rect; TkRegion rgn = Tree_GetRegion(tree); rect.x = x1; rect.y = y1; rect.width = x2 - x1; rect.height = y2 - y1; TkUnionRectWithRegion(&rect, rgn, rgn); TkSubtractRegion(dInfo->wsRgn, rgn, dInfo->wsRgn); Tree_FreeRegion(tree, rgn); } if (tree->debug.enable && tree->debug.display && tree->debug.eraseColor) { XFillRectangle(tree->display, Tk_WindowId(tree->tkwin), tree->debug.gcErase, x1, y1, x2 - x1, y2 - y1); DisplayDelay(tree); } } /* *-------------------------------------------------------------- * * Tree_InvalidateRegion -- * * Mark as dirty parts of any DItems in the given area. If the given * area overlaps the borders they are marked as needing to be * redrawn. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_InvalidateRegion( TreeCtrl *tree, /* Widget info. */ TkRegion region /* Region to mark as dirty, in window * coordinates. */ ) { TreeDInfo dInfo = tree->dInfo; DItem *dItem; int minX, minY, maxX, maxY; XRectangle rect; int x1, x2, y1, y2; TkRegion rgn; TkClipBox(region, &rect); if (!rect.width || !rect.height) return; if (Tree_AreaBbox(tree, TREE_AREA_HEADER, &minX, &minY, &maxX, &maxY) && TkRectInRegion(region, minX, minY, maxX - minX, maxY - minY) != RectangleOut) dInfo->flags |= DINFO_DRAW_HEADER; rgn = Tree_GetRegion(tree); dItem = dInfo->dItem; while (dItem != NULL) { if ((!dInfo->empty && dInfo->rangeFirst != NULL) && !(dItem->area.flags & DITEM_ALL_DIRTY)) { rect.x = dItem->area.x; rect.y = dItem->y; rect.width = dItem->area.width; rect.height = dItem->height; TkSubtractRegion(rgn, rgn, rgn); TkUnionRectWithRegion(&rect, rgn, rgn); TkIntersectRegion(region, rgn, rgn); TkClipBox(rgn, &rect); if (rect.width > 0 && rect.height > 0) { InvalidateDItemX(dItem, &dItem->area, dItem->area.x, rect.x, rect.width); InvalidateDItemY(dItem, &dItem->area, dItem->y, rect.y, rect.height); dItem->area.flags |= DITEM_DIRTY; } } if (!dInfo->emptyL && !(dItem->left.flags & DITEM_ALL_DIRTY)) { rect.x = dItem->left.x; rect.y = dItem->y; rect.width = dItem->left.width; rect.height = dItem->height; TkSubtractRegion(rgn, rgn, rgn); TkUnionRectWithRegion(&rect, rgn, rgn); TkIntersectRegion(region, rgn, rgn); TkClipBox(rgn, &rect); if (rect.width > 0 && rect.height > 0) { InvalidateDItemX(dItem, &dItem->left, dItem->left.x, rect.x, rect.width); InvalidateDItemY(dItem, &dItem->left, dItem->y, rect.y, rect.height); dItem->left.flags |= DITEM_DIRTY; } } if (!dInfo->emptyR && !(dItem->right.flags & DITEM_ALL_DIRTY)) { rect.x = dItem->right.x; rect.y = dItem->y; rect.width = dItem->right.width; rect.height = dItem->height; TkSubtractRegion(rgn, rgn, rgn); TkUnionRectWithRegion(&rect, rgn, rgn); TkIntersectRegion(region, rgn, rgn); TkClipBox(rgn, &rect); if (rect.width > 0 && rect.height > 0) { InvalidateDItemX(dItem, &dItem->right, dItem->right.x, rect.x, rect.width); InvalidateDItemY(dItem, &dItem->right, dItem->y, rect.y, rect.height); dItem->right.flags |= DITEM_DIRTY; } } dItem = dItem->next; } TkClipBox(region, &rect); x1 = rect.x, x2 = rect.x + rect.width; y1 = rect.y, y2 = rect.y + rect.height; if ((x1 < Tree_BorderLeft(tree)) || (y1 < Tree_BorderTop(tree)) || (x2 > Tree_BorderRight(tree)) || (y2 > Tree_BorderBottom(tree))) { dInfo->flags |= DINFO_DRAW_HIGHLIGHT; dInfo->flags |= DINFO_DRAW_BORDER; } /* Invalidate part of the whitespace */ TkSubtractRegion(dInfo->wsRgn, region, dInfo->wsRgn); Tree_FreeRegion(tree, rgn); if (tree->debug.enable && tree->debug.display && tree->debug.eraseColor) { Tree_FillRegion(tree->display, Tk_WindowId(tree->tkwin), tree->debug.gcErase, region); DisplayDelay(tree); } } /* *-------------------------------------------------------------- * * Tree_InvalidateItemArea -- * * Mark as dirty parts of any DItems in the given area. This is * like Tree_InvalidateArea() but the given area is clipped inside * the borders/header. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void Tree_InvalidateItemArea( TreeCtrl *tree, /* Widget info. */ int x1, int y1, /* Left & top of dirty area in window * coordinates. */ int x2, int y2 /* Right & bottom of dirty area in window * coordinates. */ ) { if (x1 < Tree_ContentLeft(tree)) x1 = Tree_ContentLeft(tree); if (y1 < Tree_ContentTop(tree)) y1 = Tree_ContentTop(tree); if (x2 > Tree_ContentRight(tree)) x2 = Tree_ContentRight(tree); if (y2 > Tree_ContentBottom(tree)) y2 = Tree_ContentBottom(tree); Tree_InvalidateArea(tree, x1, y1, x2, y2); } /* *-------------------------------------------------------------- * * Tree_RedrawArea -- * * Mark as dirty parts of any DItems in the given area. If the given * area overlaps the borders they are marked as needing to be * redrawn. The given area is subtracted from the whitespace region * so that that part of the whitespace region will be redrawn. * * Results: * None. * * Side effects: * The widget will be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_RedrawArea( TreeCtrl *tree, /* Widget info. */ int x1, int y1, /* Left & top of dirty area in window * coordinates. */ int x2, int y2 /* Right & bottom of dirty area in window * coordinates. */ ) { Tree_InvalidateArea(tree, x1, y1, x2, y2); Tree_EventuallyRedraw(tree); } /* *-------------------------------------------------------------- * * Tree_ExposeArea -- * * Called in response to events. Causes part of the window * to be redisplayed. With "-doublebuffer window", part of the * offscreen pixmap is marked as needing to be copied but no redrawing * of items is done. Without "-doublebuffer window", items will be * redrawn. * * Results: * None. * * Side effects: * The widget will be redisplayed at idle time. * *-------------------------------------------------------------- */ void Tree_ExposeArea( TreeCtrl *tree, /* Widget info. */ int x1, int y1, /* Left & top of dirty area in window * coordinates. */ int x2, int y2 /* Right & bottom of dirty area in window * coordinates. */ ) { TreeDInfo dInfo = tree->dInfo; if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) { if ((x1 < Tree_BorderLeft(tree)) || (y1 < Tree_BorderTop(tree)) || (x2 > Tree_BorderRight(tree)) || (y2 > Tree_BorderBottom(tree))) { dInfo->flags |= DINFO_DRAW_HIGHLIGHT; dInfo->flags |= DINFO_DRAW_BORDER; } if (x1 < Tree_BorderLeft(tree)) x1 = Tree_BorderLeft(tree); if (x2 > Tree_BorderRight(tree)) x2 = Tree_BorderRight(tree); if (y1 < Tree_BorderTop(tree)) y1 = Tree_BorderTop(tree); if (y2 > Tree_BorderBottom(tree)) y2 = Tree_BorderBottom(tree); DblBufWinDirty(tree, x1, y1, x2, y2); } else { Tree_InvalidateArea(tree, x1, y1, x2, y2); } Tree_EventuallyRedraw(tree); } /* *-------------------------------------------------------------- * * TreeDInfo_Init -- * * Perform display-related initialization when a new TreeCtrl is * created. * * Results: * None. * * Side effects: * Memory is allocated. * *-------------------------------------------------------------- */ void TreeDInfo_Init( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo; XGCValues gcValues; dInfo = (TreeDInfo) ckalloc(sizeof(TreeDInfo_)); memset(dInfo, '\0', sizeof(TreeDInfo_)); gcValues.graphics_exposures = True; dInfo->scrollGC = Tk_GetGC(tree->tkwin, GCGraphicsExposures, &gcValues); dInfo->flags = DINFO_OUT_OF_DATE; dInfo->wsRgn = Tree_GetRegion(tree); dInfo->dirtyRgn = TkCreateRegion(); Tcl_InitHashTable(&dInfo->itemVisHash, TCL_ONE_WORD_KEYS); tree->dInfo = dInfo; } /* *-------------------------------------------------------------- * * TreeDInfo_Free -- * * Free display-related resources for a deleted TreeCtrl. * * Results: * None. * * Side effects: * Memory is allocated. * *-------------------------------------------------------------- */ void TreeDInfo_Free( TreeCtrl *tree /* Widget info. */ ) { TreeDInfo dInfo = tree->dInfo; Range *range = dInfo->rangeFirst; Tcl_HashEntry *hPtr; Tcl_HashSearch search; if (dInfo->rItem != NULL) ckfree((char *) dInfo->rItem); if (dInfo->rangeLock != NULL) ckfree((char *) dInfo->rangeLock); while (dInfo->dItem != NULL) { DItem *next = dInfo->dItem->next; WFREE(dInfo->dItem, DItem); dInfo->dItem = next; } while (dInfo->dItemFree != NULL) { DItem *next = dInfo->dItemFree->next; WFREE(dInfo->dItemFree, DItem); dInfo->dItemFree = next; } while (range != NULL) range = Range_Free(tree, range); Tk_FreeGC(tree->display, dInfo->scrollGC); if (dInfo->flags & DINFO_REDRAW_PENDING) Tcl_CancelIdleCall(Tree_Display, (ClientData) tree); if (dInfo->pixmapW.drawable != None) Tk_FreePixmap(tree->display, dInfo->pixmapW.drawable); if (dInfo->pixmapI.drawable != None) Tk_FreePixmap(tree->display, dInfo->pixmapI.drawable); if (dInfo->xScrollIncrements != NULL) ckfree((char *) dInfo->xScrollIncrements); if (dInfo->yScrollIncrements != NULL) ckfree((char *) dInfo->yScrollIncrements); Tree_FreeRegion(tree, dInfo->wsRgn); TkDestroyRegion(dInfo->dirtyRgn); #ifdef DCOLUMN hPtr = Tcl_FirstHashEntry(&dInfo->itemVisHash, &search); while (hPtr != NULL) { ckfree((char *) Tcl_GetHashValue(hPtr)); hPtr = Tcl_NextHashEntry(&search); } #endif Tcl_DeleteHashTable(&dInfo->itemVisHash); WFREE(dInfo, TreeDInfo_); } int Tree_DumpDInfo( TreeCtrl *tree, /* Widget info. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { Tcl_Interp *interp = tree->interp; TreeDInfo dInfo = tree->dInfo; Tcl_DString dString; DItem *dItem; Range *range; RItem *rItem; int index; static CONST char *optionNames[] = { "alloc", "ditem", "onscreen", "range", (char *) NULL }; enum { DUMP_ALLOC, DUMP_DITEM, DUMP_ONSCREEN, DUMP_RANGE }; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "option"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], optionNames, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } Tcl_DStringInit(&dString); if (index == DUMP_ALLOC) { int count = 0, size = 0; for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) { count += 1; } for (dItem = dInfo->dItemFree; dItem != NULL; dItem = dItem->next) { count += 1; } size = count * sizeof(DItem); DStringAppendf(&dString, "%-20s: %8d : %8d B %5d KB\n", "DItem", count, size, (size + 1023) / 1024); count = dInfo->rItemMax; size = count * sizeof(RItem); DStringAppendf(&dString, "%-20s: %8d : %8d B %5d KB\n", "RItem", count, size, (size + 1023) / 1024); } if (index == DUMP_DITEM) { DStringAppendf(&dString, "DumpDInfo: itemW,H %d,%d totalW,H %d,%d flags 0x%0x vertical %d itemVisCount %d\n", dInfo->itemWidth, dInfo->itemHeight, dInfo->totalWidth, dInfo->totalHeight, dInfo->flags, tree->vertical, tree->itemVisCount); DStringAppendf(&dString, " empty=%d bounds=%d,%d,%d,%d\n", dInfo->empty, dInfo->bounds[0], dInfo->bounds[1], dInfo->bounds[2], dInfo->bounds[3]); DStringAppendf(&dString, " emptyL=%d boundsL=%d,%d,%d,%d\n", dInfo->emptyL, dInfo->boundsL[0], dInfo->boundsL[1], dInfo->boundsL[2], dInfo->boundsL[3]); DStringAppendf(&dString, " emptyR=%d boundsR=%d,%d,%d,%d\n", dInfo->emptyR, dInfo->boundsR[0], dInfo->boundsR[1], dInfo->boundsR[2], dInfo->boundsR[3]); dItem = dInfo->dItem; while (dItem != NULL) { if (dItem->item == NULL) { DStringAppendf(&dString, " item NULL\n"); } else { DStringAppendf(&dString, " item %d x,y,w,h %d,%d,%d,%d dirty %d,%d,%d,%d flags %0X\n", TreeItem_GetID(tree, dItem->item), dItem->area.x, dItem->y, dItem->area.width, dItem->height, dItem->area.dirty[LEFT], dItem->area.dirty[TOP], dItem->area.dirty[RIGHT], dItem->area.dirty[BOTTOM], dItem->area.flags); DStringAppendf(&dString, " left: dirty %d,%d,%d,%d flags %0X\n", dItem->left.dirty[LEFT], dItem->left.dirty[TOP], dItem->left.dirty[RIGHT], dItem->left.dirty[BOTTOM], dItem->left.flags); DStringAppendf(&dString, " right: dirty %d,%d,%d,%d flags %0X\n", dItem->right.dirty[LEFT], dItem->right.dirty[TOP], dItem->right.dirty[RIGHT], dItem->right.dirty[BOTTOM], dItem->right.flags); } dItem = dItem->next; } } if (index == DUMP_ONSCREEN) { dItem = dInfo->dItem; while (dItem != NULL) { Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&dInfo->itemVisHash, (char *) dItem->item); TreeColumn *value = (TreeColumn *) Tcl_GetHashValue(hPtr); DStringAppendf(&dString, "item %d:", TreeItem_GetID(tree, dItem->item)); while (*value != NULL) { DStringAppendf(&dString, " %d", TreeColumn_GetID(*value)); ++value; } DStringAppendf(&dString, "\n"); dItem = dItem->next; } } if (index == DUMP_RANGE) { DStringAppendf(&dString, " dInfo.rangeFirstD %p dInfo.rangeLastD %p\n", dInfo->rangeFirstD, dInfo->rangeLastD); for (range = dInfo->rangeFirstD; range != NULL; range = range->next) { DStringAppendf(&dString, " Range: totalW,H %d,%d offset %d\n", range->totalWidth, range->totalHeight, range->offset); if (range == dInfo->rangeLastD) break; } DStringAppendf(&dString, " dInfo.rangeFirst %p dInfo.rangeLast %p\n", dInfo->rangeFirst, dInfo->rangeLast); for (range = dInfo->rangeFirst; range != NULL; range = range->next) { DStringAppendf(&dString, " Range: first %p last %p totalW,H %d,%d offset %d\n", range->first, range->last, range->totalWidth, range->totalHeight, range->offset); rItem = range->first; while (1) { DStringAppendf(&dString, " RItem: item %d index %d offset %d size %d\n", TreeItem_GetID(tree, rItem->item), rItem->index, rItem->offset, rItem->size); if (rItem == range->last) break; rItem++; } } } Tcl_DStringResult(tree->interp, &dString); return TCL_OK; } tktreectrl-2.2.8/generic/tkTreeDrag.c0000700000175600010010000003306110762067722015734 0ustar TimNone/* * tkTreeDrag.c -- * * This module implements outline dragging for treectrl widgets. * * Copyright (c) 2002-2008 Tim Baker * * RCS: @(#) $Id: tkTreeDrag.c,v 1.28 2008/02/29 20:49:22 treectrl Exp $ */ #include "tkTreeCtrl.h" typedef struct TreeDragImage_ TreeDragImage_; typedef struct DragElem DragElem; /* * The following structure holds info about a single element of the drag * image. */ struct DragElem { int x, y, width, height; DragElem *next; }; /* * The following structure holds info about the drag image. There is one of * these per TreeCtrl. */ struct TreeDragImage_ { TreeCtrl *tree; Tk_OptionTable optionTable; int visible; int x, y; /* offset to draw at in canvas coords */ int bounds[4]; /* bounds of all DragElems */ DragElem *elem; int onScreen; /* TRUE if is displayed */ int sx, sy; /* Window coords where displayed */ }; #define DRAG_CONF_VISIBLE 0x0001 static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BOOLEAN, "-visible", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeDragImage_, visible), 0, (ClientData) NULL, DRAG_CONF_VISIBLE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, 0, 0} }; /* *---------------------------------------------------------------------- * * DragElem_Alloc -- * * Allocate and initialize a new DragElem record. Add the record * to the list of records for the drag image. * * Results: * Pointer to allocated DragElem. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static DragElem * DragElem_Alloc( TreeDragImage dragImage /* Drag image record. */ ) { DragElem *elem = (DragElem *) ckalloc(sizeof(DragElem)); DragElem *walk = dragImage->elem; memset(elem, '\0', sizeof(DragElem)); if (dragImage->elem == NULL) dragImage->elem = elem; else { while (walk->next != NULL) walk = walk->next; walk->next = elem; } return elem; } /* *---------------------------------------------------------------------- * * DragElem_Free -- * * Free a DragElem. * * Results: * Pointer to the next DragElem. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ static DragElem * DragElem_Free( TreeDragImage dragImage, /* Drag image record. */ DragElem *elem /* Drag element to free. */ ) { DragElem *next = elem->next; WFREE(elem, DragElem); return next; } /* *---------------------------------------------------------------------- * * TreeDragImage_Init -- * * Perform drag-image-related initialization when a new TreeCtrl is * created. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ int TreeDragImage_Init( TreeCtrl *tree /* Widget info. */ ) { TreeDragImage dragImage; dragImage = (TreeDragImage) ckalloc(sizeof(TreeDragImage_)); memset(dragImage, '\0', sizeof(TreeDragImage_)); dragImage->tree = tree; dragImage->optionTable = Tk_CreateOptionTable(tree->interp, optionSpecs); if (Tk_InitOptions(tree->interp, (char *) dragImage, dragImage->optionTable, tree->tkwin) != TCL_OK) { WFREE(dragImage, TreeDragImage_); return TCL_ERROR; } tree->dragImage = (TreeDragImage) dragImage; return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeDragImage_Free -- * * Free drag-image-related resources when a TreeCtrl is deleted. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeDragImage_Free( TreeDragImage dragImage /* Drag image token. */ ) { DragElem *elem = dragImage->elem; while (elem != NULL) elem = DragElem_Free(dragImage, elem); Tk_FreeConfigOptions((char *) dragImage, dragImage->optionTable, dragImage->tree->tkwin); WFREE(dragImage, TreeDragImage_); } /* *---------------------------------------------------------------------- * * TreeDragImage_Display -- * * Draw the drag image if it is not already displayed and if * it's -visible option is TRUE. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void TreeDragImage_Display( TreeDragImage dragImage /* Drag image token. */ ) { TreeCtrl *tree = dragImage->tree; if (!dragImage->onScreen && dragImage->visible) { dragImage->sx = 0 - tree->xOrigin; dragImage->sy = 0 - tree->yOrigin; TreeDragImage_Draw(dragImage, Tk_WindowId(tree->tkwin), dragImage->sx, dragImage->sy); dragImage->onScreen = TRUE; } } /* *---------------------------------------------------------------------- * * TreeDragImage_Undisplay -- * * Erase the drag image if it is displayed. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void TreeDragImage_Undisplay( TreeDragImage dragImage /* Drag image token. */ ) { TreeCtrl *tree = dragImage->tree; if (dragImage->onScreen) { TreeDragImage_Draw(dragImage, Tk_WindowId(tree->tkwin), dragImage->sx, dragImage->sy); dragImage->onScreen = FALSE; } } /* *---------------------------------------------------------------------- * * DragImage_Config -- * * This procedure is called to process an objc/objv list to set * configuration options for a DragImage. * * Results: * The return value is a standard Tcl result. If TCL_ERROR is * returned, then an error message is left in interp's result. * * Side effects: * Configuration information, such as text string, colors, font, * etc. get set for dragImage; old resources get freed, if there * were any. Display changes may occur. * *---------------------------------------------------------------------- */ static int DragImage_Config( TreeDragImage dragImage, /* Drag image record. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = dragImage->tree; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; int mask; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) dragImage, dragImage->optionTable, objc, objv, tree->tkwin, &savedOptions, &mask) != TCL_OK) { mask = 0; continue; } /* xxx */ Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); /* xxx */ Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } if (mask & DRAG_CONF_VISIBLE) { TreeDragImage_Undisplay((TreeDragImage) dragImage); TreeDragImage_Display((TreeDragImage) dragImage); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeDragImage_Draw -- * * Draw (or erase) the elements that make up the drag image. * * Results: * None. * * Side effects: * Stuff is drawn (or erased, since this is XOR drawing). * *---------------------------------------------------------------------- */ void TreeDragImage_Draw(TreeDragImage dragImage, Drawable drawable, int x, int y) { TreeCtrl *tree = dragImage->tree; DragElem *elem = dragImage->elem; DotState dotState; /* if (!dragImage->visible) return; */ if (elem == NULL) return; TreeDotRect_Setup(tree, drawable, &dotState); while (elem != NULL) { TreeDotRect_Draw(&dotState, x + dragImage->x + elem->x, y + dragImage->y + elem->y, elem->width, elem->height); elem = elem->next; } TreeDotRect_Restore(&dotState); } /* *---------------------------------------------------------------------- * * TreeDragImageCmd -- * * This procedure is invoked to process the [dragimage] widget * command. See the user documentation for details on what it * does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeDragImageCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; TreeDragImage dragImage = tree->dragImage; static CONST char *commandNames[] = { "add", "cget", "clear", "configure", "offset", (char *) NULL }; enum { COMMAND_ADD, COMMAND_CGET, COMMAND_CLEAR, COMMAND_CONFIGURE, COMMAND_OFFSET }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { /* T dragimage add I ?C? ?E ...? */ case COMMAND_ADD: { TreeItem item; TreeItemColumn itemColumn; TreeColumn treeColumn; TreeRectangle rects[128]; DragElem *elem; int i, count, result = TCL_OK; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "item ?column? ?element ...?"); return TCL_ERROR; } if (TreeItem_FromObj(tree, objv[3], &item, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; TreeDragImage_Undisplay(tree->dragImage); /* Every element in every column. */ if (objc == 4) { treeColumn = tree->columns; itemColumn = TreeItem_GetFirstColumn(tree, item); while (itemColumn != NULL) { if (TreeItemColumn_GetStyle(tree, itemColumn) != NULL) { count = TreeItem_GetRects(tree, item, treeColumn, -1, NULL, rects); if (count == -1) { result = TCL_ERROR; goto doneADD; } for (i = 0; i < count; i++) { elem = DragElem_Alloc(dragImage); elem->x = rects[i].x; elem->y = rects[i].y; elem->width = rects[i].width; elem->height = rects[i].height; } } treeColumn = TreeColumn_Next(treeColumn); itemColumn = TreeItemColumn_GetNext(tree, itemColumn); } } else { if (TreeColumn_FromObj(tree, objv[4], &treeColumn, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; goto doneADD; } /* Every element in a column. */ if (objc == 5) { objc = -1; objv = NULL; /* List of elements in a column. */ } else { objc -= 5; objv += 5; } count = TreeItem_GetRects(tree, item, treeColumn, objc, objv, rects); if (count == -1) { result = TCL_ERROR; goto doneADD; } for (i = 0; i < count; i++) { elem = DragElem_Alloc(dragImage); elem->x = rects[i].x; elem->y = rects[i].y; elem->width = rects[i].width; elem->height = rects[i].height; } } doneADD: dragImage->bounds[0] = 100000; dragImage->bounds[1] = 100000; dragImage->bounds[2] = -100000; dragImage->bounds[3] = -100000; for (elem = dragImage->elem; elem != NULL; elem = elem->next) { if (elem->x < dragImage->bounds[0]) dragImage->bounds[0] = elem->x; if (elem->y < dragImage->bounds[1]) dragImage->bounds[1] = elem->y; if (elem->x + elem->width > dragImage->bounds[2]) dragImage->bounds[2] = elem->x + elem->width; if (elem->y + elem->height > dragImage->bounds[3]) dragImage->bounds[3] = elem->y + elem->height; } TreeDragImage_Display(tree->dragImage); return result; } /* T dragimage cget option */ case COMMAND_CGET: { Tcl_Obj *resultObjPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "option"); return TCL_ERROR; } resultObjPtr = Tk_GetOptionValue(interp, (char *) dragImage, dragImage->optionTable, objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } /* T dragimage clear */ case COMMAND_CLEAR: { if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); return TCL_ERROR; } if (dragImage->elem != NULL) { DragElem *elem = dragImage->elem; TreeDragImage_Undisplay(tree->dragImage); /* if (dragImage->visible) DragImage_Redraw(dragImage); */ while (elem != NULL) elem = DragElem_Free(dragImage, elem); dragImage->elem = NULL; } break; } /* T dragimage configure ?option? ?value? ?option value ...? */ case COMMAND_CONFIGURE: { Tcl_Obj *resultObjPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 3, objv, "?option? ?value?"); return TCL_ERROR; } if (objc <= 4) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) dragImage, dragImage->optionTable, (objc == 3) ? (Tcl_Obj *) NULL : objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } return DragImage_Config(dragImage, objc - 3, objv + 3); } /* T dragimage offset ?x y? */ case COMMAND_OFFSET: { int x, y; if (objc != 3 && objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "?x y?"); return TCL_ERROR; } if (objc == 3) { FormatResult(interp, "%d %d", dragImage->x, dragImage->y); break; } if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) return TCL_ERROR; TreeDragImage_Undisplay(tree->dragImage); /* if (dragImage->visible) DragImage_Redraw(dragImage); */ dragImage->x = x; dragImage->y = y; TreeDragImage_Display(tree->dragImage); break; } } return TCL_OK; } tktreectrl-2.2.8/generic/tkTreeElem.c0000700000175600010010000036457510745240306015752 0ustar TimNone/* * tkTreeElem.c -- * * This module implements elements for treectrl widgets. * * Copyright (c) 2002-2008 Tim Baker * * RCS: @(#) $Id: tkTreeElem.c,v 1.67 2008/01/22 01:03:02 treectrl Exp $ */ #include "tkTreeCtrl.h" #include "tkTreeElem.h" /* *---------------------------------------------------------------------- * * DO_BooleanForState -- * DO_ColorForState -- * DO_FontForState -- * * Returns the value of a per-state option for an element. * * Results: * If the element has the dynamic option allocated, then the * per-state info is checked for a match. If an exact match for * the given state is not found, and if the element is an instance * (not a master), then the master element is checked. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int DO_BooleanForState( TreeCtrl *tree, /* Widget info. */ TreeElement elem, /* Element to examine. */ int id, /* Unique id of dynamic option. */ int state /* STATE_xxx flags. */ ) { int result = -1; PerStateInfo *psi; int match = MATCH_NONE; psi = DynamicOption_FindData(elem->options, id); if (psi != NULL) result = PerStateBoolean_ForState(tree, psi, state, &match); if ((match != MATCH_EXACT) && (elem->master != NULL)) { PerStateInfo *psi = DynamicOption_FindData(elem->master->options, id); if (psi != NULL) { int matchM; int resultM = PerStateBoolean_ForState(tree, psi, state, &matchM); if (matchM > match) result = resultM; } } return result; } static XColor * DO_ColorForState( TreeCtrl *tree, TreeElement elem, int id, int state ) { XColor *result = NULL; PerStateInfo *psi; int match = MATCH_NONE; psi = DynamicOption_FindData(elem->options, id); if (psi != NULL) result = PerStateColor_ForState(tree, psi, state, &match); if ((match != MATCH_EXACT) && (elem->master != NULL)) { PerStateInfo *psi = DynamicOption_FindData(elem->master->options, id); if (psi != NULL) { int matchM; XColor *resultM = PerStateColor_ForState(tree, psi, state, &matchM); if (matchM > match) result = resultM; } } return result; } static Tk_Font DO_FontForState( TreeCtrl *tree, TreeElement elem, int id, int state ) { Tk_Font result = NULL; PerStateInfo *psi; int match = MATCH_NONE; psi = DynamicOption_FindData(elem->options, id); if (psi != NULL) result = PerStateFont_ForState(tree, psi, state, &match); if ((match != MATCH_EXACT) && (elem->master != NULL)) { PerStateInfo *psi = DynamicOption_FindData(elem->master->options, id); if (psi != NULL) { int matchM; Tk_Font resultM = PerStateFont_ForState(tree, psi, state, &matchM); if (matchM > match) result = resultM; } } return result; } /* *---------------------------------------------------------------------- * * DO_ObjectForState -- * * Returns the object representation of a per-state option * for an element. * * Results: * If the element has the dynamic option allocated, then the * per-state info is checked for a match. If an exact match for * the given state is not found, and if the element is an instance * (not a master), then the master element is checked. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Tcl_Obj * DO_ObjectForState( TreeCtrl *tree, /* Widget info. */ PerStateType *typePtr, /* Type-specific functions and values. */ TreeElement elem, /* Element to examine. */ int id, /* Unique id of dynamic option. */ int state /* STATE_xxx flags. */ ) { Tcl_Obj *result = NULL; PerStateInfo *psi; int match = MATCH_NONE; psi = DynamicOption_FindData(elem->options, id); if (psi != NULL) result = PerStateInfo_ObjForState(tree, typePtr, psi, state, &match); if ((match != MATCH_EXACT) && (elem->master != NULL)) { PerStateInfo *psi = DynamicOption_FindData(elem->master->options, id); if (psi != NULL) { int matchM; Tcl_Obj *resultM = PerStateInfo_ObjForState(tree, typePtr, psi, state, &matchM); if (matchM > match) result = resultM; } } return result; } /* BEGIN custom "boolean" option */ /* Just like TK_OPTION_BOOLEAN but supports TK_OPTION_NULL_OK */ /* Internal value is -1 for no-such-value */ static int BooleanSet( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags) { int objEmpty; int new, *internalPtr; if (internalOffset >= 0) internalPtr = (int *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*value)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*value) = NULL; else { if (Tcl_GetBooleanFromObj(interp, (*value), &new) != TCL_OK) return TCL_ERROR; } if (internalPtr != NULL) { if ((*value) == NULL) new = -1; *((int *) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj *BooleanGet( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset) { int value = *(int *) (recordPtr + internalOffset); if (value == -1) return NULL; return Tcl_NewBooleanObj(value); } static void BooleanRestore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr) { *(int *) internalPtr = *(int *) saveInternalPtr; } static Tk_ObjCustomOption booleanCO = { "boolean", BooleanSet, BooleanGet, BooleanRestore, NULL, (ClientData) NULL }; static void DynamicOptionInitBoolean( void *data ) { *((int *) data) = -1; } /* END custom "boolean" option */ /* BEGIN custom "integer" option */ /* Just like TK_OPTION_INT but supports TK_OPTION_NULL_OK and bounds checking */ typedef struct IntegerClientData { int min; int max; int empty; /* internal form if empty */ int flags; /* 0x01 - use min, 0x02 - use max */ } IntegerClientData; static int IntegerSet( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags) { IntegerClientData *cd = clientData; int objEmpty; int new, *internalPtr; if (internalOffset >= 0) internalPtr = (int *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*value)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*value) = NULL; else { if (Tcl_GetIntFromObj(interp, (*value), &new) != TCL_OK) return TCL_ERROR; if ((cd->flags & 0x01) && (new < cd->min)) { FormatResult(interp, "bad integer value \"%d\": must be >= %d", new, cd->min); return TCL_ERROR; } if ((cd->flags & 0x02) && (new > cd->max)) { FormatResult(interp, "bad integer value \"%d\": must be <= %d", new, cd->max); return TCL_ERROR; } } if (internalPtr != NULL) { if ((*value) == NULL) new = cd->empty; *((int *) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj *IntegerGet( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset) { IntegerClientData *cd = clientData; int value = *(int *) (recordPtr + internalOffset); if (value == cd->empty) return NULL; return Tcl_NewIntObj(value); } static void IntegerRestore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr) { *(int *) internalPtr = *(int *) saveInternalPtr; } /* END custom "integer" option */ /*****/ /* BEGIN custom "stringtable" option */ /* Just like TK_OPTION_STRING_TABLE but supports TK_OPTION_NULL_OK */ /* The integer rep is -1 if empty string specified */ typedef struct StringTableClientData { CONST char **tablePtr; /* NULL-termintated list of strings */ CONST char *msg; /* Tcl_GetIndexFromObj() message */ } StringTableClientData; static int StringTableSet( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags) { StringTableClientData *cd = clientData; int objEmpty; int new, *internalPtr; if (internalOffset >= 0) internalPtr = (int *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*value)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*value) = NULL; else { if (Tcl_GetIndexFromObj(interp, (*value), cd->tablePtr, cd->msg, 0, &new) != TCL_OK) return TCL_ERROR; } if (internalPtr != NULL) { if ((*value) == NULL) new = -1; *((int *) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj *StringTableGet( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset) { StringTableClientData *cd = clientData; int index = *(int *) (recordPtr + internalOffset); if (index == -1) return NULL; return Tcl_NewStringObj(cd->tablePtr[index], -1); } static void StringTableRestore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr) { *(int *) internalPtr = *(int *) saveInternalPtr; } /* END custom "stringtable" option */ static int BooleanCO_Init( Tk_OptionSpec *optionTable, CONST char *optionName) { Tk_OptionSpec *specPtr; specPtr = Tree_FindOptionSpec(optionTable, optionName); specPtr->clientData = &booleanCO; return TCL_OK; } static Tk_ObjCustomOption * IntegerCO_Alloc( CONST char *optionName, int min, int max, int empty, int flags ) { IntegerClientData *cd; Tk_ObjCustomOption *co; /* ClientData for the Tk custom option record */ cd = (IntegerClientData *) ckalloc(sizeof(IntegerClientData)); cd->min = min; cd->max = max; cd->empty = empty; cd->flags = flags; /* The Tk custom option record */ co = (Tk_ObjCustomOption *) ckalloc(sizeof(Tk_ObjCustomOption)); co->name = (char *) optionName + 1; co->setProc = IntegerSet; co->getProc = IntegerGet; co->restoreProc = IntegerRestore; co->freeProc = NULL; co->clientData = (ClientData) cd; return co; } static int IntegerCO_Init( Tk_OptionSpec *optionTable, CONST char *optionName, int min, int max, int empty, int flags ) { Tk_OptionSpec *specPtr; specPtr = Tree_FindOptionSpec(optionTable, optionName); if (specPtr->type != TK_OPTION_CUSTOM) panic("IntegerCO_Init: %s is not TK_OPTION_CUSTOM", optionName); if (specPtr->clientData != NULL) return TCL_OK; specPtr->clientData = IntegerCO_Alloc(optionName, min, max, empty, flags); return TCL_OK; } Tk_ObjCustomOption * StringTableCO_Alloc( CONST char *optionName, CONST char **tablePtr ) { StringTableClientData *cd; Tk_ObjCustomOption *co; /* ClientData for the Tk custom option record */ cd = (StringTableClientData *) ckalloc(sizeof(StringTableClientData)); cd->tablePtr = tablePtr; cd->msg = optionName + 1; /* The Tk custom option record */ co = (Tk_ObjCustomOption *) ckalloc(sizeof(Tk_ObjCustomOption)); co->name = (char *) optionName + 1; co->setProc = StringTableSet; co->getProc = StringTableGet; co->restoreProc = StringTableRestore; co->freeProc = NULL; co->clientData = (ClientData) cd; return co; } int StringTableCO_Init(Tk_OptionSpec *optionTable, CONST char *optionName, CONST char **tablePtr) { Tk_OptionSpec *specPtr; specPtr = Tree_FindOptionSpec(optionTable, optionName); if (specPtr->type != TK_OPTION_CUSTOM) panic("StringTableCO_Init: %s is not TK_OPTION_CUSTOM", optionName); if (specPtr->clientData != NULL) return TCL_OK; specPtr->clientData = StringTableCO_Alloc(optionName, tablePtr); return TCL_OK; } /*****/ int TreeStateFromObj(TreeCtrl *tree, Tcl_Obj *obj, int *stateOff, int *stateOn) { int states[3]; states[STATE_OP_ON] = states[STATE_OP_OFF] = states[STATE_OP_TOGGLE] = 0; if (Tree_StateFromObj(tree, obj, states, NULL, SFO_NOT_TOGGLE) != TCL_OK) return TCL_ERROR; (*stateOn) |= states[STATE_OP_ON]; (*stateOff) |= states[STATE_OP_OFF]; return TCL_OK; } static void AdjustForSticky(int sticky, int cavityWidth, int cavityHeight, int expandX, int expandY, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr) { int dx = 0; int dy = 0; if (cavityWidth > *widthPtr) { dx = cavityWidth - *widthPtr; } if (cavityHeight > *heightPtr) { dy = cavityHeight - *heightPtr; } if ((sticky & STICKY_W) && (sticky & STICKY_E)) { if (expandX) *widthPtr += dx; else sticky &= ~(STICKY_W | STICKY_E); } if ((sticky & STICKY_N) && (sticky & STICKY_S)) { if (expandY) *heightPtr += dy; else sticky &= ~(STICKY_N | STICKY_S); } if (!(sticky & STICKY_W)) { *xPtr += (sticky & STICKY_E) ? dx : dx / 2; } if (!(sticky & STICKY_N)) { *yPtr += (sticky & STICKY_S) ? dy : dy / 2; } } /* This macro gets the value of a per-state option for an element, then * looks for a better match from the master element if it exists */ #define OPTION_FOR_STATE(xFUNC,xTYPE,xVAR,xFIELD,xSTATE) \ xVAR = xFUNC(tree, &elemX->xFIELD, xSTATE, &match); \ if ((match != MATCH_EXACT) && (masterX != NULL)) { \ xTYPE varM = xFUNC(tree, &masterX->xFIELD, xSTATE, &match2); \ if (match2 > match) \ xVAR = varM; \ } #define BITMAP_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateBitmap_ForState,Pixmap,xVAR,xFIELD,xSTATE) #define BOOLEAN_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateBoolean_ForState,int,xVAR,xFIELD,xSTATE) #define BORDER_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateBorder_ForState,Tk_3DBorder,xVAR,xFIELD,xSTATE) #define COLOR_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateColor_ForState,XColor*,xVAR,xFIELD,xSTATE) #define FONT_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateFont_ForState,Tk_Font,xVAR,xFIELD,xSTATE) #define IMAGE_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateImage_ForState,Tk_Image,xVAR,xFIELD,xSTATE) #define RELIEF_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateRelief_ForState,int,xVAR,xFIELD,xSTATE) /* This macro gets the object for a per-state option for an element, then * looks for a better match from the master element if it exists */ #define OBJECT_FOR_STATE(xVAR,xTYPE,xFIELD,xSTATE) \ xVAR = PerStateInfo_ObjForState(tree, &xTYPE, &elemX->xFIELD, xSTATE, &match); \ if ((match != MATCH_EXACT) && (masterX != NULL)) { \ Tcl_Obj *objM = PerStateInfo_ObjForState(tree, &xTYPE, &masterX->xFIELD, xSTATE, &matchM); \ if (matchM > match) \ xVAR = objM; \ } /*****/ typedef struct ElementBitmap ElementBitmap; struct ElementBitmap { TreeElement_ header; #ifdef DEPRECATED PerStateInfo draw; #endif PerStateInfo bitmap; PerStateInfo fg; PerStateInfo bg; }; #define BITMAP_CONF_BITMAP 0x0001 #define BITMAP_CONF_FG 0x0002 #define BITMAP_CONF_BG 0x0004 #ifdef DEPRECATED #define BITMAP_CONF_DRAW 0x0008 #endif static Tk_OptionSpec bitmapOptionSpecs[] = { {TK_OPTION_CUSTOM, "-background", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBitmap, bg.obj), Tk_Offset(ElementBitmap, bg), TK_OPTION_NULL_OK, (ClientData) NULL, BITMAP_CONF_BG}, {TK_OPTION_CUSTOM, "-bitmap", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBitmap, bitmap.obj), Tk_Offset(ElementBitmap, bitmap), TK_OPTION_NULL_OK, (ClientData) NULL, BITMAP_CONF_BITMAP}, #ifdef DEPRECATED {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBitmap, draw.obj), Tk_Offset(ElementBitmap, draw), TK_OPTION_NULL_OK, (ClientData) NULL, BITMAP_CONF_DRAW}, #endif {TK_OPTION_CUSTOM, "-foreground", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBitmap, fg.obj), Tk_Offset(ElementBitmap, fg), TK_OPTION_NULL_OK, (ClientData) NULL, BITMAP_CONF_FG}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void DeleteProcBitmap(TreeElementArgs *args) { /* TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementBitmap *elemX = (ElementBitmap *) elem;*/ } static int WorldChangedProcBitmap(TreeElementArgs *args) { int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & BITMAP_CONF_BITMAP) mask |= CS_DISPLAY | CS_LAYOUT; if ((flagS | flagM) & ( #ifdef DEPRECATED BITMAP_CONF_DRAW | #endif BITMAP_CONF_FG | BITMAP_CONF_BG)) mask |= CS_DISPLAY; return mask; } static int ConfigProcBitmap(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementBitmap *elemX = (ElementBitmap *) elem; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } return TCL_OK; } static int CreateProcBitmap(TreeElementArgs *args) { return TCL_OK; } static void DisplayProcBitmap(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementBitmap *elemX = (ElementBitmap *) elem; ElementBitmap *masterX = (ElementBitmap *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int width, height; int match, match2; #ifdef DEPRECATED int draw; #endif Pixmap bitmap; XColor *fg, *bg; int imgW, imgH; #ifdef DEPRECATED BOOLEAN_FOR_STATE(draw, draw, state) if (!draw) return; #endif BITMAP_FOR_STATE(bitmap, bitmap, state) if (bitmap == None) return; COLOR_FOR_STATE(fg, fg, state) COLOR_FOR_STATE(bg, bg, state) Tk_SizeOfBitmap(tree->display, bitmap, &imgW, &imgH); width = imgW, height = imgH; AdjustForSticky(args->display.sticky, args->display.width, args->display.height, FALSE, FALSE, &x, &y, &width, &height); if (imgW > args->display.width) imgW = args->display.width; if (imgH > args->display.height) imgH = args->display.height; Tree_DrawBitmap(tree, bitmap, args->display.drawable, fg, bg, 0, 0, (unsigned int) imgW, (unsigned int) imgH, x, y); } static void NeededProcBitmap(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementBitmap *elemX = (ElementBitmap *) elem; ElementBitmap *masterX = (ElementBitmap *) elem->master; int state = args->state; int width = 0, height = 0; int match, match2; Pixmap bitmap; BITMAP_FOR_STATE(bitmap, bitmap, state) if (bitmap != None) Tk_SizeOfBitmap(tree->display, bitmap, &width, &height); args->needed.width = width; args->needed.height = height; } static int StateProcBitmap(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementBitmap *elemX = (ElementBitmap *) elem; ElementBitmap *masterX = (ElementBitmap *) elem->master; int match, match2; #ifdef DEPRECATED int draw1, draw2; #endif Pixmap bitmap1, bitmap2; XColor *fg1, *fg2; XColor *bg1, *bg2; if (!args->states.visible2) return 0; BITMAP_FOR_STATE(bitmap1, bitmap, args->states.state1) BITMAP_FOR_STATE(bitmap2, bitmap, args->states.state2) if (bitmap1 != bitmap2) { if ((bitmap1 != None) && (bitmap2 != None)) { int w1, h1, w2, h2; Tk_SizeOfBitmap(tree->display, bitmap1, &w1, &h1); Tk_SizeOfBitmap(tree->display, bitmap2, &w2, &h2); if ((w1 != w2) || (h1 != h2)) return CS_DISPLAY | CS_LAYOUT; return CS_DISPLAY; } return CS_DISPLAY | CS_LAYOUT; } /* Layout hasn't changed, and -draw layout option is false. */ if (!args->states.draw2) return 0; #ifdef DEPRECATED BOOLEAN_FOR_STATE(draw1, draw, args->states.state1) BOOLEAN_FOR_STATE(draw2, draw, args->states.state2) if ((draw1 != 0) != (draw2 != 0)) return CS_DISPLAY; if (draw2 == 0) return 0; #endif COLOR_FOR_STATE(fg1, fg, args->states.state1) COLOR_FOR_STATE(fg2, fg, args->states.state2) if (fg1 != fg2) return CS_DISPLAY; COLOR_FOR_STATE(bg1, bg, args->states.state1) COLOR_FOR_STATE(bg2, bg, args->states.state2) if (bg1 != bg2) return CS_DISPLAY; return 0; } static int UndefProcBitmap(TreeElementArgs *args) { TreeCtrl *tree = args->tree; ElementBitmap *elemX = (ElementBitmap *) args->elem; int modified = 0; #ifdef DEPRECATED modified |= PerStateInfo_Undefine(tree, &pstBoolean, &elemX->draw, args->state); #endif modified |= PerStateInfo_Undefine(tree, &pstColor, &elemX->fg, args->state); modified |= PerStateInfo_Undefine(tree, &pstColor, &elemX->bg, args->state); modified |= PerStateInfo_Undefine(tree, &pstBitmap, &elemX->bitmap, args->state); return modified; } static int ActualProcBitmap(TreeElementArgs *args) { TreeCtrl *tree = args->tree; ElementBitmap *elemX = (ElementBitmap *) args->elem; ElementBitmap *masterX = (ElementBitmap *) args->elem->master; static CONST char *optionName[] = { "-background", "-bitmap", #ifdef DEPRECATED "-draw", #endif "-foreground", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { OBJECT_FOR_STATE(obj, pstColor, bg, args->state) break; } case 1: { OBJECT_FOR_STATE(obj, pstBitmap, bitmap, args->state) break; } #ifdef DEPRECATED case 2: { OBJECT_FOR_STATE(obj, pstBoolean, draw, args->state) break; } case 3: { OBJECT_FOR_STATE(obj, pstColor, fg, args->state) break; } #else case 2: { OBJECT_FOR_STATE(obj, pstColor, fg, args->state) break; } #endif } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } TreeElementType treeElemTypeBitmap = { "bitmap", sizeof(ElementBitmap), bitmapOptionSpecs, NULL, CreateProcBitmap, DeleteProcBitmap, ConfigProcBitmap, DisplayProcBitmap, NeededProcBitmap, NULL, /* heightProc */ WorldChangedProcBitmap, StateProcBitmap, UndefProcBitmap, ActualProcBitmap, NULL /* onScreenProc */ }; /*****/ typedef struct ElementBorder ElementBorder; struct ElementBorder { TreeElement_ header; /* Must be first */ #ifdef DEPRECATED PerStateInfo draw; #endif PerStateInfo border; PerStateInfo relief; int thickness; Tcl_Obj *thicknessObj; int width; Tcl_Obj *widthObj; int height; Tcl_Obj *heightObj; int filled; }; #define BORDER_CONF_BG 0x0001 #define BORDER_CONF_RELIEF 0x0002 #define BORDER_CONF_SIZE 0x0004 #define BORDER_CONF_THICKNESS 0x0008 #define BORDER_CONF_FILLED 0x0010 #ifdef DEPRECATED #define BORDER_CONF_DRAW 0x0020 #endif static Tk_OptionSpec borderOptionSpecs[] = { {TK_OPTION_CUSTOM, "-background", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBorder, border.obj), Tk_Offset(ElementBorder, border), TK_OPTION_NULL_OK, (ClientData) NULL, BORDER_CONF_BG}, #ifdef DEPRECATED {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBorder, draw.obj), Tk_Offset(ElementBorder, draw), TK_OPTION_NULL_OK, (ClientData) NULL, BORDER_CONF_DRAW}, #endif {TK_OPTION_CUSTOM, "-filled", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementBorder, filled), TK_OPTION_NULL_OK, (ClientData) &booleanCO, BORDER_CONF_FILLED}, {TK_OPTION_PIXELS, "-height", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBorder, heightObj), Tk_Offset(ElementBorder, height), TK_OPTION_NULL_OK, (ClientData) NULL, BORDER_CONF_SIZE}, {TK_OPTION_CUSTOM, "-relief", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBorder, relief.obj), Tk_Offset(ElementBorder, relief), TK_OPTION_NULL_OK, (ClientData) NULL, BORDER_CONF_RELIEF}, {TK_OPTION_PIXELS, "-thickness", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBorder, thicknessObj), Tk_Offset(ElementBorder, thickness), TK_OPTION_NULL_OK, (ClientData) NULL, BORDER_CONF_THICKNESS}, {TK_OPTION_PIXELS, "-width", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementBorder, widthObj), Tk_Offset(ElementBorder, width), TK_OPTION_NULL_OK, (ClientData) NULL, BORDER_CONF_SIZE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void DeleteProcBorder(TreeElementArgs *args) { /* TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementBorder *elemX = (ElementBorder *) elem;*/ } static int WorldChangedProcBorder(TreeElementArgs *args) { int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & BORDER_CONF_SIZE) mask |= CS_DISPLAY | CS_LAYOUT; if ((flagS | flagM) & ( #ifdef DEPRECATED BORDER_CONF_DRAW | #endif BORDER_CONF_BG | BORDER_CONF_RELIEF | BORDER_CONF_THICKNESS | BORDER_CONF_FILLED)) mask |= CS_DISPLAY; return mask; } static int ConfigProcBorder(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementBorder *elemX = (ElementBorder *) elem; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } return TCL_OK; } static int CreateProcBorder(TreeElementArgs *args) { TreeElement elem = args->elem; ElementBorder *elemX = (ElementBorder *) elem; elemX->filled = -1; return TCL_OK; } static void DisplayProcBorder(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementBorder *elemX = (ElementBorder *) elem; ElementBorder *masterX = (ElementBorder *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int width = args->display.width, height = args->display.height; int match, match2; #ifdef DEPRECATED int draw; #endif Tk_3DBorder border; int relief, filled = FALSE; int thickness = 0; #ifdef DEPRECATED BOOLEAN_FOR_STATE(draw, draw, state) if (!draw) return; #endif BORDER_FOR_STATE(border, border, state) if (border == NULL) return; RELIEF_FOR_STATE(relief, relief, state) if (relief == TK_RELIEF_NULL) relief = TK_RELIEF_FLAT; if (elemX->thicknessObj) thickness = elemX->thickness; else if ((masterX != NULL) && (masterX->thicknessObj != NULL)) thickness = masterX->thickness; if (elemX->filled != -1) filled = elemX->filled; else if ((masterX != NULL) && (masterX->filled != -1)) filled = masterX->filled; if (elemX->widthObj != NULL) width = elemX->width; else if ((masterX != NULL) && (masterX->widthObj != NULL)) width = masterX->width; if (elemX->heightObj != NULL) height = elemX->height; else if ((masterX != NULL) && (masterX->heightObj != NULL)) height = masterX->height; AdjustForSticky(args->display.sticky, args->display.width, args->display.height, TRUE, TRUE, &x, &y, &width, &height); if (filled) { Tk_Fill3DRectangle(tree->tkwin, args->display.drawable, border, x, y, width, height, thickness, relief); } else if (thickness > 0) { Tk_Draw3DRectangle(tree->tkwin, args->display.drawable, border, x, y, width, height, thickness, relief); } } static void NeededProcBorder(TreeElementArgs *args) { TreeElement elem = args->elem; ElementBorder *elemX = (ElementBorder *) elem; ElementBorder *masterX = (ElementBorder *) elem->master; int width = 0, height = 0; if (elemX->widthObj != NULL) width = elemX->width; else if ((masterX != NULL) && (masterX->widthObj != NULL)) width = masterX->width; if (elemX->heightObj != NULL) height = elemX->height; else if ((masterX != NULL) && (masterX->heightObj != NULL)) height = masterX->height; args->needed.width = width; args->needed.height = height; } static int StateProcBorder(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementBorder *elemX = (ElementBorder *) elem; ElementBorder *masterX = (ElementBorder *) elem->master; int match, match2; #ifdef DEPRECATED int draw1, draw2; #endif Tk_3DBorder border1, border2; int relief1, relief2; if (!args->states.visible2 || !args->states.draw2) return 0; #ifdef DEPRECATED BOOLEAN_FOR_STATE(draw1, draw, args->states.state1) BOOLEAN_FOR_STATE(draw2, draw, args->states.state2) if ((draw1 != 0) != (draw2 != 0)) return CS_DISPLAY; if (draw2 == 0) return 0; #endif BORDER_FOR_STATE(border1, border, args->states.state1) BORDER_FOR_STATE(border2, border, args->states.state2) if (border1 != border2) return CS_DISPLAY; RELIEF_FOR_STATE(relief1, relief, args->states.state1) RELIEF_FOR_STATE(relief2, relief, args->states.state2) if (relief1 != relief2) return CS_DISPLAY; return 0; } static int UndefProcBorder(TreeElementArgs *args) { TreeCtrl *tree = args->tree; ElementBorder *elemX = (ElementBorder *) args->elem; int modified = 0; #ifdef DEPRECATED modified |= PerStateInfo_Undefine(tree, &pstBoolean, &elemX->draw, args->state); #endif modified |= PerStateInfo_Undefine(tree, &pstBorder, &elemX->border, args->state); modified |= PerStateInfo_Undefine(tree, &pstRelief, &elemX->relief, args->state); return modified; } static int ActualProcBorder(TreeElementArgs *args) { TreeCtrl *tree = args->tree; ElementBorder *elemX = (ElementBorder *) args->elem; ElementBorder *masterX = (ElementBorder *) args->elem->master; static CONST char *optionName[] = { "-background", #ifdef DEPRECATED "-draw", #endif "-relief", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { OBJECT_FOR_STATE(obj, pstBorder, border, args->state) break; } #ifdef DEPRECATED case 1: { OBJECT_FOR_STATE(obj, pstBoolean, draw, args->state) break; } case 2: { OBJECT_FOR_STATE(obj, pstRelief, relief, args->state) break; } #else case 1: { OBJECT_FOR_STATE(obj, pstRelief, relief, args->state) break; } #endif } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } TreeElementType treeElemTypeBorder = { "border", sizeof(ElementBorder), borderOptionSpecs, NULL, CreateProcBorder, DeleteProcBorder, ConfigProcBorder, DisplayProcBorder, NeededProcBorder, NULL, /* heightProc */ WorldChangedProcBorder, StateProcBorder, UndefProcBorder, ActualProcBorder, NULL /* onScreenProc */ }; /*****/ #if 0 static CONST char *chkbutStateST[] = { "checked", "mixed", "normal", "active", "pressed", "disabled", (char *) NULL }; typedef struct ElementCheckButton ElementCheckButton; struct ElementCheckButton { TreeElement_ header; PerStateInfo image; int state; }; #define CHKBUT_CONF_IMAGE 0x0001 #define CHKBUT_CONF_STATE 0x0002 static Tk_OptionSpec chkbutOptionSpecs[] = { {TK_OPTION_STRING, "-image", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementCheckButton, image.obj), -1, TK_OPTION_NULL_OK, (ClientData) NULL, CHKBUT_CONF_IMAGE}, {TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL, "normal", -1, Tk_Offset(ElementCheckButton, state), 0, (ClientData) chkbutStateST, CHKBUT_CONF_STATE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void DeleteProcCheckButton(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementCheckButton *elemX = (ElementCheckButton *) elem; PerStateInfo_Free(tree, &pstImage, &elemX->image); } static int WorldChangedProcCheckButton(TreeElementArgs *args) { int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & (CHKBUT_CONF_IMAGE | CHKBUT_CONF_STATE)) mask |= CS_DISPLAY | CS_LAYOUT; return mask; } static int ChkButStateFromObj(TreeCtrl *tree, Tcl_Obj *obj, int *stateOff, int *stateOn) { Tcl_Interp *interp = tree->interp; int i, op = STATE_OP_ON, op2, op3, length, state = 0; char ch0, *string; int states[3]; states[STATE_OP_ON] = 0; states[STATE_OP_OFF] = 0; states[STATE_OP_TOGGLE] = 0; string = Tcl_GetStringFromObj(obj, &length); if (length == 0) goto unknown; ch0 = string[0]; if (ch0 == '!') { op = STATE_OP_OFF; ++string; ch0 = string[0]; } else if (ch0 == '~') { if (1) { FormatResult(interp, "can't specify '~' for this command"); return TCL_ERROR; } op = STATE_OP_TOGGLE; ++string; ch0 = string[0]; } for (i = 0; chkbutStateST[i] != NULL; i++) { if ((ch0 == chkbutStateST[i][0]) && !strcmp(string, chkbutStateST[i])) { state = 1L << i; break; } } if (state == 0) goto unknown; if (op == STATE_OP_ON) { op2 = STATE_OP_OFF; op3 = STATE_OP_TOGGLE; } else if (op == STATE_OP_OFF) { op2 = STATE_OP_ON; op3 = STATE_OP_TOGGLE; } else { op2 = STATE_OP_ON; op3 = STATE_OP_OFF; } states[op2] &= ~state; states[op3] &= ~state; states[op] |= state; *stateOn |= states[STATE_OP_ON]; *stateOff |= states[STATE_OP_OFF]; return TCL_OK; unknown: FormatResult(interp, "unknown state \"%s\"", string); return TCL_ERROR; } static int ConfigProcCheckButton(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementCheckButton *elemX = (ElementCheckButton *) elem; ElementCheckButton savedX; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } if (args->config.flagSelf & CHKBUT_CONF_IMAGE) PSTSave(&elemX->image, &savedX.image); if (args->config.flagSelf & CHKBUT_CONF_IMAGE) { if (PerStateInfo_FromObj(tree, ChkButStateFromObj, &pstImage, &elemX->image) != TCL_OK) continue; } if (args->config.flagSelf & CHKBUT_CONF_IMAGE) PerStateInfo_Free(tree, &pstImage, &savedX.image); Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); if (args->config.flagSelf & CHKBUT_CONF_IMAGE) PSTRestore(tree, &pstImage, &elemX->image, &savedX.image); Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } return TCL_OK; } static int CreateProcCheckButton(TreeElementArgs *args) { return TCL_OK; } static void DisplayProcCheckButton(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementCheckButton *elemX = (ElementCheckButton *) elem; ElementCheckButton *masterX = (ElementCheckButton *) elem->master; int state = args->state; int match, matchM; Tk_Image image; int imgW, imgH; int dx = 0, dy = 0; image = PerStateImage_ForState(tree, &elemX->image, state, &match); if ((match != MATCH_EXACT) && (masterX != NULL)) { Tk_Image imageM = PerStateImage_ForState(tree, &masterX->image, state, &matchM); if (matchM > match) image = imageM; } if (image != NULL) { Tk_SizeOfImage(image, &imgW, &imgH); if (imgW < args->display.width) dx = (args->display.width - imgW) / 2; else if (imgW > args->display.width) imgW = args->display.width; if (imgH < args->display.height) dy = (args->display.height - imgH) / 2; else if (imgH > args->display.height) imgH = args->display.height; Tk_RedrawImage(image, 0, 0, imgW, imgH, args->display.drawable, args->display.x + dx, args->display.y + dy); } } static void NeededProcCheckButton(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementCheckButton *elemX = (ElementCheckButton *) elem; ElementCheckButton *masterX = (ElementCheckButton *) elem->master; int state = args->state; int match, match2; Tk_Image image; int width = 0, height = 0; image = PerStateImage_ForState(tree, &elemX->image, state, &match); if ((match != MATCH_EXACT) && (masterX != NULL)) { Tk_Image image2 = PerStateImage_ForState(tree, &masterX->image, state, &match2); if (match2 > match) image = image2; } if (image != NULL) Tk_SizeOfImage(image, &width, &height); args->layout.width = width; args->layout.height = height; } static int StateProcCheckButton(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementCheckButton *elemX = (ElementCheckButton *) elem; ElementCheckButton *masterX = (ElementCheckButton *) elem->master; int match, match2; Tk_Image image1, image2; int mask = 0; image1 = PerStateImage_ForState(tree, &elemX->image, args->states.state1, &match); if ((match != MATCH_EXACT) && (masterX != NULL)) { Tk_Image image = PerStateImage_ForState(tree, &masterX->image, args->states.state1, &match2); if (match2 > match) image1 = image; } image2 = PerStateImage_ForState(tree, &elemX->image, args->states.state2, &match); if ((match != MATCH_EXACT) && (masterX != NULL)) { Tk_Image image = PerStateImage_ForState(tree, &masterX->image, args->states.state2, &match2); if (match2 > match) image2 = image; } if (image1 != image2) { mask |= CS_DISPLAY; if ((image1 != NULL) && (image2 != NULL)) { int w1, h1, w2, h2; Tk_SizeOfImage(image1, &w1, &h1); Tk_SizeOfImage(image2, &w2, &h2); if ((w1 != w2) || (h1 != h2)) mask |= CS_LAYOUT; } else mask |= CS_LAYOUT; } return mask; } static int UndefProcCheckButton(TreeElementArgs *args) { TreeCtrl *tree = args->tree; ElementCheckButton *elemX = (ElementCheckButton *) args->elem; return PerStateInfo_Undefine(tree, &pstImage, &elemX->image, args->state); } static int ActualProcCheckButton(TreeElementArgs *args) { TreeCtrl *tree = args->tree; ElementCheckButton *elemX = (ElementCheckButton *) args->elem; ElementCheckButton *masterX = (ElementCheckButton *) args->elem->master; static CONST char *optionName[] = { "-image", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { obj = PerStateInfo_ObjForState(tree, &pstImage, &elemX->image, args->state, &match); if ((match != MATCH_EXACT) && (masterX != NULL)) { objM = PerStateInfo_ObjForState(tree, &pstImage, &masterX->image, args->state, &matchM); if (matchM > match) obj = objM; } break; } } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } TreeElementType treeElemTypeCheckButton = { "checkbutton", sizeof(ElementCheckButton), chkbutOptionSpecs, NULL, CreateProcCheckButton, DeleteProcCheckButton, ConfigProcCheckButton, DisplayProcCheckButton, NeededProcCheckButton, NULL, /* heightProc */ WorldChangedProcCheckButton, StateProcCheckButton, UndefProcCheckButton, ActualProcCheckButton, NULL /* onScreenProc */ }; #endif /*****/ typedef struct ElementImage ElementImage; struct ElementImage { TreeElement_ header; PerStateInfo image; }; typedef struct ElementImageSize { int width; Tcl_Obj *widthObj; int height; Tcl_Obj *heightObj; } ElementImageSize; #define IMAGE_CONF_IMAGE 0x0001 #define IMAGE_CONF_SIZE 0x0002 #define IMAGE_CONF_DISPLAY 0x0004 #ifdef DEPRECATED #define IMAGE_CONF_DRAW 0x0008 #endif static Tk_OptionSpec imageOptionSpecs[] = { #ifdef DEPRECATED {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, IMAGE_CONF_DRAW}, #endif {TK_OPTION_CUSTOM, "-height", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, IMAGE_CONF_SIZE}, {TK_OPTION_CUSTOM, "-image", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementImage, image.obj), Tk_Offset(ElementImage, image), TK_OPTION_NULL_OK, (ClientData) NULL, IMAGE_CONF_IMAGE}, {TK_OPTION_CUSTOM, "-tiled", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, IMAGE_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-width", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, IMAGE_CONF_SIZE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void DeleteProcImage(TreeElementArgs *args) { /* TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementImage *elemX = (ElementImage *) elem;*/ } static int WorldChangedProcImage(TreeElementArgs *args) { int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & ( #ifdef DEPRECATED IMAGE_CONF_DRAW | #endif IMAGE_CONF_IMAGE | IMAGE_CONF_SIZE)) mask |= CS_DISPLAY | CS_LAYOUT; if ((flagS | flagM) & IMAGE_CONF_DISPLAY) mask |= CS_DISPLAY; return mask; } static int ConfigProcImage(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementImage *elemX = (ElementImage *) elem; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } return TCL_OK; } static int CreateProcImage(TreeElementArgs *args) { /* ElementImage *elemX = (ElementImage *) args->elem;*/ return TCL_OK; } static void DisplayProcImage(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementImage *elemX = (ElementImage *) elem; ElementImage *masterX = (ElementImage *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int width, height; int match, match2; #ifdef DEPRECATED int draw; #endif Tk_Image image; int imgW, imgH; int tiled = 0, *eit, *eitM = NULL; #ifdef DEPRECATED draw = DO_BooleanForState(tree, elem, 1002, state); if (!draw) return; #endif IMAGE_FOR_STATE(image, image, state) if (image == NULL) return; eit = DynamicOption_FindData(elem->options, 1003); if (masterX != NULL) eitM = DynamicOption_FindData(elem->master->options, 1003); if (eit != NULL && *eit != -1) tiled = *eit; else if ((eitM != NULL) && (*eitM != -1)) tiled = *eitM; if (tiled) { Tree_DrawTiledImage(tree, args->display.drawable, image, x, y, x + args->display.width, y + args->display.height, -x, -y); return; } Tk_SizeOfImage(image, &imgW, &imgH); width = imgW, height = imgH; AdjustForSticky(args->display.sticky, args->display.width, args->display.height, FALSE, FALSE, &x, &y, &width, &height); if (imgW > args->display.width) imgW = args->display.width; if (imgH > args->display.height) imgH = args->display.height; Tree_RedrawImage(image, 0, 0, imgW, imgH, args->display.td, x, y); } static void NeededProcImage(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementImage *elemX = (ElementImage *) elem; ElementImage *masterX = (ElementImage *) elem->master; int state = args->state; int width = 0, height = 0; int match, match2; Tk_Image image; ElementImageSize *eis, *eisM = NULL; IMAGE_FOR_STATE(image, image, state) if (image != NULL) Tk_SizeOfImage(image, &width, &height); eis = DynamicOption_FindData(elem->options, 1001); if (masterX != NULL) eisM = DynamicOption_FindData(elem->master->options, 1001); if (eis != NULL && eis->widthObj != NULL) width = eis->width; else if ((eisM != NULL) && (eisM->widthObj != NULL)) width = eisM->width; if (eis != NULL && eis->heightObj != NULL) height = eis->height; else if ((eisM != NULL) && (eisM->heightObj != NULL)) height = eisM->height; args->needed.width = width; args->needed.height = height; } static int StateProcImage(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementImage *elemX = (ElementImage *) elem; ElementImage *masterX = (ElementImage *) elem->master; int match, match2; #ifdef DEPRECATED int draw1, draw2; #endif Tk_Image image1, image2; if (!args->states.visible2) return 0; IMAGE_FOR_STATE(image1, image, args->states.state1) IMAGE_FOR_STATE(image2, image, args->states.state2) if (image1 != image2) { if ((image1 != NULL) && (image2 != NULL)) { int w1, h1, w2, h2; Tk_SizeOfImage(image1, &w1, &h1); Tk_SizeOfImage(image2, &w2, &h2); if ((w1 != w2) || (h1 != h2)) return CS_DISPLAY | CS_LAYOUT; return CS_DISPLAY; } return CS_DISPLAY | CS_LAYOUT; } if (!args->states.draw2) return 0; #ifdef DEPRECATED draw1 = DO_BooleanForState(tree, elem, 1002, args->states.state1); draw2 = DO_BooleanForState(tree, elem, 1002, args->states.state2); if ((draw1 != 0) != (draw2 != 0)) return CS_DISPLAY; #endif return 0; } static int UndefProcImage(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementImage *elemX = (ElementImage *) elem; int modified = 0; #ifdef DEPRECATED PerStateInfo *psi; #endif #ifdef DEPRECATED if ((psi = DynamicOption_FindData(elem->options, 1002)) != NULL) modified |= PerStateInfo_Undefine(tree, &pstBoolean, psi, args->state); #endif modified |= PerStateInfo_Undefine(tree, &pstImage, &elemX->image, args->state); return modified; } static int ActualProcImage(TreeElementArgs *args) { TreeCtrl *tree = args->tree; ElementImage *elemX = (ElementImage *) args->elem; ElementImage *masterX = (ElementImage *) args->elem->master; static CONST char *optionName[] = { #ifdef DEPRECATED "-draw", #endif "-image", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { #ifdef DEPRECATED case 0: { obj = DO_ObjectForState(tree, &pstBoolean, args->elem, 1002, args->state); break; } case 1: { OBJECT_FOR_STATE(obj, pstImage, image, args->state) break; } #else case 0: { OBJECT_FOR_STATE(obj, pstImage, image, args->state) break; } #endif } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } TreeElementType treeElemTypeImage = { "image", sizeof(ElementImage), imageOptionSpecs, NULL, CreateProcImage, DeleteProcImage, ConfigProcImage, DisplayProcImage, NeededProcImage, NULL, /* heightProc */ WorldChangedProcImage, StateProcImage, UndefProcImage, ActualProcImage, NULL /* onScreenProc */ }; /*****/ typedef struct ElementRect ElementRect; struct ElementRect { TreeElement_ header; #ifdef DEPRECATED PerStateInfo draw; #endif int width; Tcl_Obj *widthObj; int height; Tcl_Obj *heightObj; PerStateInfo fill; PerStateInfo outline; int outlineWidth; Tcl_Obj *outlineWidthObj; int open; char *openString; int showFocus; }; #define RECT_CONF_FILL 0x0001 #define RECT_CONF_OUTLINE 0x0002 #define RECT_CONF_OUTWIDTH 0x0004 #define RECT_CONF_OPEN 0x0008 #define RECT_CONF_SIZE 0x0010 #define RECT_CONF_FOCUS 0x0020 #ifdef DEPRECATED #define RECT_CONF_DRAW 0x0040 #endif static Tk_OptionSpec rectOptionSpecs[] = { #ifdef DEPRECATED {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementRect, draw.obj), Tk_Offset(ElementRect, draw), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_DRAW}, #endif {TK_OPTION_CUSTOM, "-fill", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementRect, fill.obj), Tk_Offset(ElementRect, fill), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_FILL}, {TK_OPTION_PIXELS, "-height", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementRect, heightObj), Tk_Offset(ElementRect, height), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_SIZE}, {TK_OPTION_STRING, "-open", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementRect, openString), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_OPEN}, {TK_OPTION_CUSTOM, "-outline", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementRect, outline.obj), Tk_Offset(ElementRect, outline), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_OUTLINE}, {TK_OPTION_PIXELS, "-outlinewidth", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementRect, outlineWidthObj), Tk_Offset(ElementRect, outlineWidth), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_OUTWIDTH}, {TK_OPTION_CUSTOM, "-showfocus", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementRect, showFocus), TK_OPTION_NULL_OK, (ClientData) &booleanCO, RECT_CONF_FOCUS}, {TK_OPTION_PIXELS, "-width", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementRect, widthObj), Tk_Offset(ElementRect, width), TK_OPTION_NULL_OK, (ClientData) NULL, RECT_CONF_SIZE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void DeleteProcRect(TreeElementArgs *args) { /* TreeCtrl *tree = args->tree; ElementRect *elemX = (ElementRect *) args->elem;*/ } static int WorldChangedProcRect(TreeElementArgs *args) { int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & (RECT_CONF_SIZE | RECT_CONF_OUTWIDTH)) mask |= CS_DISPLAY | CS_LAYOUT; if ((flagS | flagM) & ( #ifdef DEPRECATED RECT_CONF_DRAW | #endif RECT_CONF_FILL | RECT_CONF_OUTLINE | RECT_CONF_OPEN | RECT_CONF_FOCUS)) mask |= CS_DISPLAY; return mask; } static int ConfigProcRect(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementRect *elemX = (ElementRect *) elem; ElementRect savedX; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; int i; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } if (args->config.flagSelf & RECT_CONF_OPEN) savedX.open = elemX->open; if (args->config.flagSelf & RECT_CONF_OPEN) { elemX->open = 0; if (elemX->openString != NULL) { int badChar = 0; for (i = 0; elemX->openString[i]; i++) { switch (elemX->openString[i]) { case 'w': case 'W': elemX->open |= 0x01; break; case 'n': case 'N': elemX->open |= 0x02; break; case 'e': case 'E': elemX->open |= 0x04; break; case 's': case 'S': elemX->open |= 0x08; break; default: { Tcl_ResetResult(tree->interp); Tcl_AppendResult(tree->interp, "bad open value \"", elemX->openString, "\": must be a string ", "containing zero or more of n, e, s, and w", (char *) NULL); badChar = 1; break; } } if (badChar) break; } if (badChar) continue; } } Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); if (args->config.flagSelf & RECT_CONF_OPEN) elemX->open = savedX.open; Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } return TCL_OK; } static int CreateProcRect(TreeElementArgs *args) { ElementRect *elemX = (ElementRect *) args->elem; elemX->showFocus = -1; return TCL_OK; } static void DisplayProcRect(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementRect *elemX = (ElementRect *) elem; ElementRect *masterX = (ElementRect *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int width = args->display.width, height = args->display.height; int match, match2; #ifdef DEPRECATED int draw; #endif XColor *color; int open = 0; int outlineWidth = 0; int showFocus = 0; #ifdef DEPRECATED BOOLEAN_FOR_STATE(draw, draw, state) if (!draw) return; #endif if (elemX->outlineWidthObj != NULL) outlineWidth = elemX->outlineWidth; else if ((masterX != NULL) && (masterX->outlineWidthObj != NULL)) outlineWidth = masterX->outlineWidth; if (elemX->openString != NULL) open = elemX->open; else if ((masterX != NULL) && (masterX->openString != NULL)) open = masterX->open; if (elemX->showFocus != -1) showFocus = elemX->showFocus; else if ((masterX != NULL) && (masterX->showFocus != -1)) showFocus = masterX->showFocus; if (elemX->widthObj != NULL) width = elemX->width; else if ((masterX != NULL) && (masterX->widthObj != NULL)) width = masterX->width; if (elemX->heightObj != NULL) height = elemX->height; else if ((masterX != NULL) && (masterX->heightObj != NULL)) height = masterX->height; AdjustForSticky(args->display.sticky, args->display.width, args->display.height, TRUE, TRUE, &x, &y, &width, &height); COLOR_FOR_STATE(color, fill, state) if (color != NULL) { GC gc = Tk_GCForColor(color, Tk_WindowId(tree->tkwin)); XFillRectangle(tree->display, args->display.drawable, gc, x, y, width, height); } COLOR_FOR_STATE(color, outline, state) if ((color != NULL) && (outlineWidth > 0)) { GC gc = Tk_GCForColor(color, Tk_WindowId(tree->tkwin)); if (!(open & 0x01)) XFillRectangle(tree->display, args->display.drawable, gc, x, y, outlineWidth, height); if (!(open & 0x02)) XFillRectangle(tree->display, args->display.drawable, gc, x, y, width, outlineWidth); if (!(open & 0x04)) XFillRectangle(tree->display, args->display.drawable, gc, x + width - outlineWidth, y, outlineWidth, height); if (!(open & 0x08)) XFillRectangle(tree->display, args->display.drawable, gc, x, y + height - outlineWidth, width, outlineWidth); } if (showFocus && (state & STATE_FOCUS) && (state & STATE_ACTIVE)) { Tree_DrawActiveOutline(tree, args->display.drawable, args->display.x, args->display.y, args->display.width, args->display.height, open); } } static void NeededProcRect(TreeElementArgs *args) { TreeElement elem = args->elem; ElementRect *elemX = (ElementRect *) elem; ElementRect *masterX = (ElementRect *) elem->master; int width = 0, height = 0; int outlineWidth = 0; if (elemX->outlineWidthObj != NULL) outlineWidth = elemX->outlineWidth; else if ((masterX != NULL) && (masterX->outlineWidthObj != NULL)) outlineWidth = masterX->outlineWidth; if (elemX->widthObj != NULL) width = elemX->width; else if ((masterX != NULL) && (masterX->widthObj != NULL)) width = masterX->width; if (elemX->heightObj != NULL) height = elemX->height; else if ((masterX != NULL) && (masterX->heightObj != NULL)) height = masterX->height; args->needed.width = MAX(width, outlineWidth * 2); args->needed.height = MAX(height, outlineWidth * 2); } static int StateProcRect(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementRect *elemX = (ElementRect *) elem; ElementRect *masterX = (ElementRect *) elem->master; int match, match2; #ifdef DEPRECATED int draw1, draw2; #endif XColor *f1, *f2; XColor *o1, *o2; int s1, s2; int showFocus = 0; /* If either the -draw or -visible layout option is false for the * current state, then changes to colors etc don't warrant a redisplay. */ if (!args->states.visible2 || !args->states.draw2) return 0; #ifdef DEPRECATED BOOLEAN_FOR_STATE(draw1, draw, args->states.state1) BOOLEAN_FOR_STATE(draw2, draw, args->states.state2) if ((draw1 != 0) != (draw2 != 0)) return CS_DISPLAY; /* If the element isn't drawn, then changes to colors etc don't * warrant a redisplay. */ if (draw2 == 0) return 0; #endif if (elemX->showFocus != -1) showFocus = elemX->showFocus; else if ((masterX != NULL) && (masterX->showFocus != -1)) showFocus = masterX->showFocus; s1 = showFocus && (args->states.state1 & STATE_FOCUS) && (args->states.state1 & STATE_ACTIVE); s2 = showFocus && (args->states.state2 & STATE_FOCUS) && (args->states.state2 & STATE_ACTIVE); if (s1 != s2) return CS_DISPLAY; COLOR_FOR_STATE(f1, fill, args->states.state1) COLOR_FOR_STATE(f2, fill, args->states.state2) if (f1 != f2) return CS_DISPLAY; COLOR_FOR_STATE(o1, outline, args->states.state1) COLOR_FOR_STATE(o2, outline, args->states.state2) if (o1 != o2) return CS_DISPLAY; return 0; } static int UndefProcRect(TreeElementArgs *args) { TreeCtrl *tree = args->tree; ElementRect *elemX = (ElementRect *) args->elem; int modified = 0; #ifdef DEPRECATED modified |= PerStateInfo_Undefine(tree, &pstBoolean, &elemX->draw, args->state); #endif modified |= PerStateInfo_Undefine(tree, &pstColor, &elemX->fill, args->state); modified |= PerStateInfo_Undefine(tree, &pstColor, &elemX->outline, args->state); return modified; } static int ActualProcRect(TreeElementArgs *args) { TreeCtrl *tree = args->tree; ElementRect *elemX = (ElementRect *) args->elem; ElementRect *masterX = (ElementRect *) args->elem->master; static CONST char *optionName[] = { #ifdef DEPRECATED "-draw", #endif "-fill", "-outline", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { #ifdef DEPRECATED case 0: { OBJECT_FOR_STATE(obj, pstBoolean, draw, args->state) break; } case 1: { OBJECT_FOR_STATE(obj, pstColor, fill, args->state) break; } case 2: { OBJECT_FOR_STATE(obj, pstColor, outline, args->state) break; } #else case 0: { OBJECT_FOR_STATE(obj, pstColor, fill, args->state) break; } case 1: { OBJECT_FOR_STATE(obj, pstColor, outline, args->state) break; } #endif } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } TreeElementType treeElemTypeRect = { "rect", sizeof(ElementRect), rectOptionSpecs, NULL, CreateProcRect, DeleteProcRect, ConfigProcRect, DisplayProcRect, NeededProcRect, NULL, /* heightProc */ WorldChangedProcRect, StateProcRect, UndefProcRect, ActualProcRect, NULL /* onScreenProc */ }; /*****/ typedef struct ElementText ElementText; struct ElementText { TreeElement_ header; char *textCfg; /* -text */ char *text; /* This will be the same as textCfg, or it * will be a dynamically allocated string * from any -data or -textvariable. */ #define STRINGREP_INVALID -1 int textLen; /* Number of bytes (not characters) in the * UTF-8 string. If -1, it means the string * representation is invalid. */ }; #define TEXTVAR /* for Tk_SetOptions() */ #define TEXT_CONF_LAYOUT 0x0001 #define TEXT_CONF_DISPLAY 0x0002 #define TEXT_CONF_STRINGREP 0x0040 #ifdef TEXTVAR #define TEXT_CONF_TEXTVAR 0x0080 #endif typedef struct ElementTextData { Tcl_Obj *dataObj; /* -data */ #define TDT_NULL -1 #define TDT_DOUBLE 0 #define TDT_INTEGER 1 #define TDT_LONG 2 #define TDT_STRING 3 #define TDT_TIME 4 int dataType; /* -datatype */ Tcl_Obj *formatObj; /* -format */ } ElementTextData; typedef struct ElementTextLayout { #define TK_JUSTIFY_NULL -1 int justify; /* -justify */ int lines; /* -lines */ Tcl_Obj *widthObj; /* -width */ int width; /* -width */ #define TEXT_WRAP_NULL -1 #define TEXT_WRAP_CHAR 0 #define TEXT_WRAP_NONE 1 #define TEXT_WRAP_WORD 2 int wrap; /* -wrap */ } ElementTextLayout; /* This structure doesn't hold any option values, but it is managed by * the dynamic-option code. */ typedef struct ElementTextLayout2 { TextLayout layout; int layoutWidth; int neededWidth; int totalWidth; } ElementTextLayout2; #define TEXT_STYLE #ifdef TEXT_STYLE typedef struct ElementTextStyle { int underline; /* -underline */ } ElementTextStyle; /* Called by the dynamic-option code when an ElementTextData is allocated. */ static void ElementTextStyleInit( void *data ) { ElementTextStyle *ets = data; #define TEXT_UNDERLINE_EMPTYVAL -100000 ets->underline = TEXT_UNDERLINE_EMPTYVAL; } #endif #ifdef TEXTVAR typedef struct ElementTextVar { Tcl_Obj *varNameObj; /* -textvariable */ TreeCtrl *tree; /* needed to redisplay */ TreeItem item; /* needed to redisplay */ TreeItemColumn column; /* needed to redisplay */ } ElementTextVar; #endif /* Called by the dynamic-option code when an ElementTextData is allocated. */ static void ElementTextDataInit( void *data ) { ElementTextData *etd = data; etd->dataType = TDT_NULL; } /* Called by the dynamic-option code when an ElementTextLayout is allocated. */ static void ElementTextLayoutInit( void *data ) { ElementTextLayout *etl = data; etl->justify = TK_JUSTIFY_NULL; etl->lines = -1; etl->wrap = TEXT_WRAP_NULL; } static CONST char *textDataTypeST[] = { "double", "integer", "long", "string", "time", (char *) NULL }; static CONST char *textJustifyST[] = { "left", "right", "center", (char *) NULL }; static CONST char *textWrapST[] = { "char", "none", "word", (char *) NULL }; static Tk_OptionSpec textOptionSpecs[] = { {TK_OPTION_CUSTOM, "-data", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_STRINGREP}, {TK_OPTION_CUSTOM, "-datatype", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_STRINGREP}, #ifdef DEPRECATED {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_DISPLAY}, #endif {TK_OPTION_CUSTOM, "-fill", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_DISPLAY}, {TK_OPTION_CUSTOM, "-font", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_LAYOUT}, {TK_OPTION_CUSTOM, "-format", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_STRINGREP}, {TK_OPTION_CUSTOM, "-justify", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_LAYOUT}, {TK_OPTION_CUSTOM, "-lines", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_LAYOUT}, {TK_OPTION_STRING, "-text", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementText, textCfg), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_STRINGREP}, #ifdef TEXTVAR {TK_OPTION_CUSTOM, "-textvariable", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_STRINGREP | TEXT_CONF_TEXTVAR}, #endif #ifdef TEXT_STYLE {TK_OPTION_CUSTOM, "-underline", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_DISPLAY}, #endif {TK_OPTION_CUSTOM, "-width", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_LAYOUT}, {TK_OPTION_CUSTOM, "-wrap", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeElement_, options), TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_LAYOUT}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, 0, 0} }; static int WorldChangedProcText(TreeElementArgs *args) { /* TreeCtrl *tree = args->tree;*/ TreeElement elem = args->elem; ElementText *elemX = (ElementText *) elem; /* ElementText *masterX = (ElementText *) elem->master;*/ int flagT = args->change.flagTree; int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & TEXT_CONF_STRINGREP) { elemX->textLen = STRINGREP_INVALID; } if ((elemX->textLen == STRINGREP_INVALID) || ((flagS | flagM) & TEXT_CONF_LAYOUT) || /* Not needed if this element has its own font. */ (flagT & TREE_CONF_FONT)) { mask |= CS_DISPLAY | CS_LAYOUT; } if ((flagS | flagM) & TEXT_CONF_DISPLAY) mask |= CS_DISPLAY; return mask; } static void TextUpdateStringRep(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master; Tcl_Obj *dataObj, *formatObj; char *text; ElementTextData *etd, *etdM = NULL; #ifdef TEXTVAR ElementTextVar *etv; Tcl_Obj *varNameObj; #endif int dataType; /* Free any string allocated as a result of -data or -textvariable. */ if ((elemX->text != NULL) && (elemX->text != elemX->textCfg)) { ckfree(elemX->text); } /* Forget any string, and mark the string rep as no-longer invalid. */ elemX->text = NULL; elemX->textLen = 0; /* If -text is specified, then -data and -textvariable are ignored. */ if (elemX->textCfg != NULL) { elemX->text = elemX->textCfg; elemX->textLen = strlen(elemX->textCfg); return; } #ifdef TEXTVAR etv = DynamicOption_FindData(elem->options, 1001); varNameObj = etv ? etv->varNameObj : NULL; if (varNameObj != NULL) { Tcl_Obj *valueObj = Tcl_ObjGetVar2(tree->interp, varNameObj, NULL, TCL_GLOBAL_ONLY); if (valueObj == NULL) { /* not possible I think */ } else { /* FIXME: do I need to allocate a copy, or can I just point * to the internal rep of the string object? */ text = Tcl_GetStringFromObj(valueObj, &elemX->textLen); if (elemX->textLen > 0) { elemX->text = ckalloc(elemX->textLen); memcpy(elemX->text, text, elemX->textLen); } } return; } #endif etd = DynamicOption_FindData(elem->options, 1006); if (masterX != NULL) etdM = DynamicOption_FindData(elem->master->options, 1006); dataObj = etd ? etd->dataObj : NULL; if ((dataObj == NULL) && (etdM != NULL)) dataObj = etdM->dataObj; dataType = etd ? etd->dataType : TDT_NULL; if ((dataType == TDT_NULL) && (etdM != NULL)) dataType = etdM->dataType; formatObj = etd ? etd->formatObj : NULL; if ((formatObj == NULL) && (etdM != NULL)) formatObj = etdM->formatObj; /* Only create a string rep if elemX (not masterX) has dataObj, dataType or formatObj. */ if ((dataObj != NULL) && (dataType != TDT_NULL) && ((etd != NULL) && ((etd->dataObj != NULL) || (etd->dataType != TDT_NULL) || (etd->formatObj != NULL)))) { int i, objc = 0; Tcl_Obj *objv[5], *resultObj = NULL; static Tcl_Obj *staticObj[3] = { NULL }; static Tcl_Obj *staticFormat[4] = { NULL }; Tcl_ObjCmdProc *clockObjCmd = NULL, *formatObjCmd = NULL; ClientData clockClientData = NULL, formatClientData = NULL; Tcl_CmdInfo cmdInfo; if (staticFormat[0] == NULL) { staticFormat[0] = Tcl_NewStringObj("%g", -1); staticFormat[1] = Tcl_NewStringObj("%d", -1); staticFormat[2] = Tcl_NewStringObj("%ld", -1); staticFormat[3] = Tcl_NewStringObj("%s", -1); for (i = 0; i < 4; i++) Tcl_IncrRefCount(staticFormat[i]); } if (staticObj[0] == NULL) { staticObj[0] = Tcl_NewStringObj("clock", -1); staticObj[1] = Tcl_NewStringObj("format", -1); staticObj[2] = Tcl_NewStringObj("-format", -1); for (i = 0; i < 3; i++) Tcl_IncrRefCount(staticObj[i]); } if (Tcl_GetCommandInfo(tree->interp, "::clock", &cmdInfo) == 1) { clockObjCmd = cmdInfo.objProc; clockClientData = cmdInfo.objClientData; } if (Tcl_GetCommandInfo(tree->interp, "::format", &cmdInfo) == 1) { formatObjCmd = cmdInfo.objProc; formatClientData = cmdInfo.objClientData; } /* Important to remove any shared result object, otherwise * calls like Tcl_SetStringObj(Tcl_GetObjResult()) fail. */ Tcl_ResetResult(tree->interp); switch (dataType) { case TDT_DOUBLE: if (formatObjCmd == NULL) break; if (formatObj == NULL) formatObj = staticFormat[0]; objv[objc++] = staticObj[1]; /* format */ objv[objc++] = formatObj; objv[objc++] = dataObj; if (formatObjCmd(formatClientData, tree->interp, objc, objv) == TCL_OK) resultObj = Tcl_GetObjResult(tree->interp); break; case TDT_INTEGER: if (formatObjCmd == NULL) break; if (formatObj == NULL) formatObj = staticFormat[1]; objv[objc++] = staticObj[1]; /* format */ objv[objc++] = formatObj; objv[objc++] = dataObj; if (formatObjCmd(formatClientData, tree->interp, objc, objv) == TCL_OK) resultObj = Tcl_GetObjResult(tree->interp); break; case TDT_LONG: if (formatObjCmd == NULL) break; if (formatObj == NULL) formatObj = staticFormat[2]; objv[objc++] = staticObj[1]; /* format */ objv[objc++] = formatObj; objv[objc++] = dataObj; if (formatObjCmd(formatClientData, tree->interp, objc, objv) == TCL_OK) resultObj = Tcl_GetObjResult(tree->interp); break; case TDT_STRING: if (formatObjCmd == NULL) break; if (formatObj == NULL) formatObj = staticFormat[3]; objv[objc++] = staticObj[1]; /* format */ objv[objc++] = formatObj; objv[objc++] = dataObj; if (formatObjCmd(formatClientData, tree->interp, objc, objv) == TCL_OK) resultObj = Tcl_GetObjResult(tree->interp); break; case TDT_TIME: if (clockObjCmd == NULL) break; objv[objc++] = staticObj[0]; objv[objc++] = staticObj[1]; objv[objc++] = dataObj; if (formatObj != NULL) { objv[objc++] = staticObj[2]; objv[objc++] = formatObj; } if (clockObjCmd(clockClientData, tree->interp, objc, objv) == TCL_OK) resultObj = Tcl_GetObjResult(tree->interp); break; default: panic("unknown ElementText dataType"); break; } if (resultObj != NULL) { text = Tcl_GetStringFromObj(resultObj, &elemX->textLen); if (elemX->textLen > 0) { elemX->text = ckalloc(elemX->textLen); memcpy(elemX->text, text, elemX->textLen); } } } } static ElementTextLayout2 * TextUpdateLayout( char *func, TreeElementArgs *args, int fixedWidth, int maxWidth ) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master; int state = args->state; Tk_Font tkfont; char *text = NULL; int textLen = 0; int justify = TK_JUSTIFY_LEFT; int lines = 0; int wrap = TEXT_WRAP_WORD; int width = 0; int flags = 0; int i, multiLine = FALSE; int textWidth; ElementTextLayout *etl, *etlM = NULL; ElementTextLayout2 *etl2; DynamicOption *opt; if (tree->debug.enable && tree->debug.textLayout) dbwin("TextUpdateLayout: %s %p (%s) %s\n fixedWidth %d maxWidth %d\n", Tk_PathName(tree->tkwin), elemX, masterX ? "instance" : "master", func, fixedWidth, maxWidth); etl2 = DynamicOption_FindData(elem->options, 1007); if (etl2 != NULL && etl2->layout != NULL) { if (tree->debug.enable && tree->debug.textLayout) dbwin(" FREE\n"); TextLayout_Free(etl2->layout); etl2->layout = NULL; } if (elemX->text != NULL) { text = elemX->text; textLen = elemX->textLen; } else if ((masterX != NULL) && (masterX->text != NULL)) { text = masterX->text; textLen = masterX->textLen; } if ((text == NULL) || (textLen == 0)) return etl2; etl = DynamicOption_FindData(elem->options, 1005); if (masterX != NULL) etlM = DynamicOption_FindData(elem->master->options, 1005); if (etl != NULL && etl->lines != -1) lines = etl->lines; else if (etlM != NULL && etlM->lines != -1) lines = etlM->lines; if (lines == 1) return etl2; tkfont = DO_FontForState(tree, elem, 1004, state); if (tkfont == NULL) tkfont = tree->tkfont; if (etl != NULL && etl->wrap != TEXT_WRAP_NULL) wrap = etl->wrap; else if (etlM != NULL && etlM->wrap != TEXT_WRAP_NULL) wrap = etlM->wrap; if (wrap != TEXT_WRAP_NONE) { if (fixedWidth >= 0) width = fixedWidth; else if (maxWidth >= 0) width = maxWidth; if (etl != NULL && etl->widthObj != NULL) { if (!width || (etl->width < width)) width = etl->width; } else if ((etlM != NULL) && (etlM->widthObj != NULL)) { if (!width || (etlM->width < width)) width = etlM->width; } } for (i = 0; i < textLen; i++) { if ((text[i] == '\n') || (text[i] == '\r')) { multiLine = TRUE; break; } } if (tree->debug.enable && tree->debug.textLayout) dbwin(" lines %d multiLine %d width %d wrap %s\n", lines, multiLine, width, textWrapST[wrap]); if (!multiLine) { if (width == 0) return etl2; textWidth = Tk_TextWidth(tkfont, text, textLen); if (tree->debug.enable && tree->debug.textLayout) dbwin(" available width %d textWidth %d\n", width, textWidth); if (width >= textWidth) return etl2; } if (etl != NULL && etl->justify != TK_JUSTIFY_NULL) justify = etl->justify; else if (etlM != NULL && etlM->justify != TK_JUSTIFY_NULL) justify = etlM->justify; if (wrap == TEXT_WRAP_WORD) flags |= TK_WHOLE_WORDS; if (etl2 == NULL) { opt = (DynamicOption *) DynamicOption_AllocIfNeeded(tree, &elem->options, 1007, sizeof(ElementTextLayout2), NULL); etl2 = (ElementTextLayout2 *) opt->data; /* It is possible that the needed size of this element does not * require a TextLayout, in which case neededWidth never gets * set. */ etl2->neededWidth = -1; } etl2->layout = TextLayout_Compute(tkfont, text, Tcl_NumUtfChars(text, textLen), width, justify, lines, flags); if (tree->debug.enable && tree->debug.textLayout) dbwin(" ALLOC\n"); return etl2; } #ifdef TEXTVAR static Tcl_VarTraceProc VarTraceProc_Text; static void TextTraceSet(Tcl_Interp *interp, ElementText *elemX) { ElementTextVar *etv = DynamicOption_FindData(elemX->header.options, 1001); Tcl_Obj *varNameObj = etv ? etv->varNameObj : NULL; if (varNameObj != NULL) { Tcl_TraceVar2(interp, Tcl_GetString(varNameObj), NULL, TCL_GLOBAL_ONLY | TCL_TRACE_WRITES | TCL_TRACE_UNSETS, VarTraceProc_Text, (ClientData) elemX); } } static void TextTraceUnset(Tcl_Interp *interp, ElementText *elemX) { ElementTextVar *etv = DynamicOption_FindData(elemX->header.options, 1001); Tcl_Obj *varNameObj = etv ? etv->varNameObj : NULL; if (varNameObj != NULL) { Tcl_UntraceVar2(interp, Tcl_GetString(varNameObj), NULL, TCL_GLOBAL_ONLY | TCL_TRACE_WRITES | TCL_TRACE_UNSETS, VarTraceProc_Text, (ClientData) elemX); } } static char *VarTraceProc_Text(ClientData clientData, Tcl_Interp *interp, CONST char *name1, CONST char *name2, int flags) { ElementText *elemX = (ElementText *) clientData; ElementTextVar *etv = DynamicOption_FindData(elemX->header.options, 1001); Tcl_Obj *varNameObj = etv ? etv->varNameObj : NULL; Tcl_Obj *valueObj; /* * If the variable is unset, then immediately recreate it unless * the whole interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { /* Use the current string if it is valid. */ if (elemX->textLen > 0) { valueObj = Tcl_NewStringObj(elemX->text, elemX->textLen); } else { valueObj = Tcl_NewStringObj("", 0); } Tcl_IncrRefCount(valueObj); Tcl_ObjSetVar2(interp, varNameObj, NULL, valueObj, TCL_GLOBAL_ONLY); Tcl_DecrRefCount(valueObj); TextTraceSet(interp, elemX); } return (char *) NULL; } elemX->textLen = STRINGREP_INVALID; Tree_ElementChangedItself(etv->tree, etv->item, etv->column, (TreeElement) elemX, TEXT_CONF_TEXTVAR, CS_LAYOUT | CS_DISPLAY); return (char *) NULL; } #endif /* TEXTVAR */ static void DeleteProcText(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementText *elemX = (ElementText *) elem; ElementTextLayout2 *etl2; if ((elemX->textCfg == NULL) && (elemX->text != NULL)) { ckfree(elemX->text); elemX->text = NULL; } etl2 = DynamicOption_FindData(elem->options, 1007); if (etl2 != NULL && etl2->layout != NULL) TextLayout_Free(etl2->layout); DynamicOption_Free1(tree, &elem->options, 1007, sizeof(ElementTextLayout2)); #ifdef TEXTVAR TextTraceUnset(tree->interp, elemX); #endif } static int ConfigProcText(TreeElementArgs *args) { TreeCtrl *tree = args->tree; Tcl_Interp *interp = tree->interp; TreeElement elem = args->elem; ElementText *elemX = (ElementText *) elem; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; char *textCfg = elemX->textCfg; #ifdef TEXTVAR ElementTextVar *etv; Tcl_Obj *varNameObj; #endif #ifdef TEXTVAR TextTraceUnset(interp, elemX); #endif for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } #ifdef TEXTVAR etv = DynamicOption_FindData(elem->options, 1001); if (etv != NULL) { etv->tree = tree; etv->item = args->config.item; etv->column = args->config.column; varNameObj = etv->varNameObj; } else varNameObj = NULL; if (varNameObj != NULL) { Tcl_Obj *valueObj; valueObj = Tcl_ObjGetVar2(interp, varNameObj, NULL, TCL_GLOBAL_ONLY); if (valueObj == NULL) { valueObj = Tcl_NewStringObj("", 0); Tcl_IncrRefCount(valueObj); /* This validates the variable name. We get an error * if it is the name of an array */ if (Tcl_ObjSetVar2(interp, varNameObj, NULL, valueObj, TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) == NULL) { Tcl_DecrRefCount(valueObj); continue; } Tcl_DecrRefCount(valueObj); } } #endif Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); } } /* If -text was specified, then do not try to free the old value in * TextUpdateStringRep. */ if (textCfg != elemX->textCfg && elemX->text == textCfg) elemX->text = NULL; #ifdef TEXTVAR TextTraceSet(interp, elemX); #endif if (error) { Tcl_SetObjResult(interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } return TCL_OK; } static int CreateProcText(TreeElementArgs *args) { /* ElementText *elemX = (ElementText *) args->elem;*/ return TCL_OK; } static ElementTextLayout2 * TextRedoLayoutIfNeeded( char *func, TreeElementArgs *args, int fixedWidth ) { TreeElement elem = args->elem; /* ElementText *elemX = (ElementText *) elem;*/ ElementText *masterX = (ElementText *) elem->master; int doLayout = 0; int wrap = TEXT_WRAP_WORD; ElementTextLayout *etl, *etlM = NULL; ElementTextLayout2 *etl2; etl = DynamicOption_FindData(elem->options, 1005); if (masterX != NULL) etlM = DynamicOption_FindData(elem->master->options, 1005); etl2 = DynamicOption_FindData(elem->options, 1007); /* If text wrapping is disabled, the layout doesn't change */ if (etl != NULL && etl->wrap != TEXT_WRAP_NULL) wrap = etl->wrap; else if ((etlM != NULL) && (etlM->wrap != TEXT_WRAP_NULL)) wrap = etlM->wrap; if (wrap == TEXT_WRAP_NONE) return etl2; if (etl2 != NULL && etl2->layout != NULL) { /* See comment in NeededProc about totalWidth */ if ((etl2->neededWidth != -1) && (fixedWidth >= etl2->neededWidth)) fixedWidth = etl2->totalWidth; /* Already layed out at this width */ if (fixedWidth == etl2->layoutWidth) return etl2; } /* May switch from layout -> no layout or vice versa */ if (etl2 == NULL || etl2->layout == NULL) doLayout = 1; /* Width was constrained and we have more space now */ else if ((etl2->layoutWidth != -1) && (fixedWidth > etl2->layoutWidth)) doLayout = 1; /* Width was unconstrained or we have less space now */ else { int width; TextLayout_Size(etl2->layout, &width, NULL); /* Redo if we are narrower than the layout */ if (fixedWidth < width) doLayout = 1; } if (doLayout) etl2 = TextUpdateLayout(func, args, fixedWidth, -1); if (etl2 != NULL) etl2->layoutWidth = (etl2->layout != NULL) ? fixedWidth : -1; return etl2; } static void DisplayProcText(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int width, height; #ifdef DEPRECATED int draw; #endif XColor *color; char *text = elemX->text; int textLen = elemX->textLen; Tk_Font tkfont; TextLayout layout = NULL; Tk_FontMetrics fm; GC gc; int bytesThatFit, pixelsForText; char *ellipsis = "..."; TkRegion clipRgn = NULL; ElementTextLayout2 *etl2; #ifdef TEXT_STYLE ElementTextStyle *ets, *etsM = NULL; int underline = TEXT_UNDERLINE_EMPTYVAL; #endif #ifdef DEPRECATED draw = DO_BooleanForState(tree, elem, 1002, state); if (!draw) return; #endif if ((text == NULL) && (masterX != NULL)) { text = masterX->text; textLen = masterX->textLen; } if (text == NULL) /* always false (or layout sets height/width to zero) */ return; color = DO_ColorForState(tree, elem, 1003, state); tkfont = DO_FontForState(tree, elem, 1004, state); /* FIXME: -font {"" {state...}}*/ if ((color != NULL) || (tkfont != NULL)) { XGCValues gcValues; unsigned long gcMask = 0; if (color == NULL) color = tree->fgColorPtr; gcValues.foreground = color->pixel; gcMask |= GCForeground; if (tkfont == NULL) tkfont = tree->tkfont; gcValues.font = Tk_FontId(tkfont); gcMask |= GCFont; gcValues.graphics_exposures = False; gcMask |= GCGraphicsExposures; gc = Tree_GetGC(tree, gcMask, &gcValues); } else { tkfont = tree->tkfont; gc = tree->textGC; } #ifdef TEXT_STYLE ets = DynamicOption_FindData(elem->options, 1008); if (ets != NULL && ets->underline != TEXT_UNDERLINE_EMPTYVAL) underline = ets->underline; else if (masterX != NULL) { etsM = DynamicOption_FindData(elem->master->options, 1008); if (etsM != NULL && etsM->underline != TEXT_UNDERLINE_EMPTYVAL) underline = etsM->underline; } #endif etl2 = TextRedoLayoutIfNeeded("DisplayProcText", args, args->display.width); if (etl2 != NULL && etl2->layout != NULL) layout = etl2->layout; if (layout != NULL) { TextLayout_Size(layout, &width, &height); pixelsForText = width; /* Hack -- The actual size of the text may be slightly smaller than * the available space when squeezed. If so we don't want to center * the text horizontally */ if ((etl2->neededWidth == -1) || (etl2->neededWidth > width)) width = args->display.width; AdjustForSticky(args->display.sticky, args->display.width, args->display.height, FALSE, FALSE, &x, &y, &width, &height); /* Use clipping if text is larger than the display area. */ if (pixelsForText > args->display.width || height > args->display.height) { XRectangle rect; clipRgn = Tree_GetRegion(tree); rect.x = x; rect.y = y; rect.width = args->display.width; rect.height = args->display.height; TkUnionRectWithRegion(&rect, clipRgn, clipRgn); TkSetRegion(tree->display, gc, clipRgn); } TextLayout_Draw(tree->display, args->display.drawable, gc, layout, x, y, 0, -1, underline); if (clipRgn != NULL) { Tree_UnsetClipMask(tree, args->display.drawable, gc); Tree_FreeRegion(tree, clipRgn); } return; } Tk_GetFontMetrics(tkfont, &fm); pixelsForText = args->display.width; bytesThatFit = Tree_Ellipsis(tkfont, text, textLen, &pixelsForText, ellipsis, FALSE); width = pixelsForText, height = fm.linespace; /* Hack -- The actual size of the text may be slightly smaller than * the available space when squeezed. If so we don't want to center * the text horizontally */ if (bytesThatFit != textLen) width = args->display.width; AdjustForSticky(args->display.sticky, args->display.width, args->display.height, FALSE, FALSE, &x, &y, &width, &height); /* Use clipping if text is larger than the display area. */ if (pixelsForText > args->display.width || height > args->display.height) { XRectangle rect; clipRgn = Tree_GetRegion(tree); rect.x = x; rect.y = y; rect.width = args->display.width; rect.height = args->display.height; TkUnionRectWithRegion(&rect, clipRgn, clipRgn); TkSetRegion(tree->display, gc, clipRgn); } if (bytesThatFit != textLen) { char staticStr[256], *buf = staticStr; int bufLen = abs(bytesThatFit); int ellipsisLen = strlen(ellipsis); if (bufLen + ellipsisLen > sizeof(staticStr)) buf = ckalloc(bufLen + ellipsisLen); memcpy(buf, text, bufLen); if (bytesThatFit > 0) { memcpy(buf + bufLen, ellipsis, ellipsisLen); bufLen += ellipsisLen; } Tk_DrawChars(tree->display, args->display.drawable, gc, tkfont, buf, bufLen, x, y + fm.ascent); #ifdef TEXT_STYLE if (underline >= 0 && underline < Tcl_NumUtfChars(buf, abs(bytesThatFit))) { CONST char *fstBytePtr = Tcl_UtfAtIndex(buf, underline); CONST char *sndBytePtr = Tcl_UtfNext(fstBytePtr); Tk_UnderlineChars(tree->display, args->display.drawable, gc, tkfont, buf, x, y + fm.ascent, fstBytePtr - buf, sndBytePtr - buf); } #endif if (buf != staticStr) ckfree(buf); } else { Tk_DrawChars(tree->display, args->display.drawable, gc, tkfont, text, textLen, x, y + fm.ascent); #ifdef TEXT_STYLE if (underline >= 0 && underline < Tcl_NumUtfChars(text, textLen)) { CONST char *fstBytePtr = Tcl_UtfAtIndex(text, underline); CONST char *sndBytePtr = Tcl_UtfNext(fstBytePtr); Tk_UnderlineChars(tree->display, args->display.drawable, gc, tkfont, text, x, y + fm.ascent, fstBytePtr - text, sndBytePtr - text); } #endif } if (clipRgn != NULL) { Tree_UnsetClipMask(tree, args->display.drawable, gc); Tree_FreeRegion(tree, clipRgn); } } static void NeededProcText(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master; int state = args->state; char *text = NULL; int textLen = 0; Tk_Font tkfont; Tk_FontMetrics fm; int width = 0, height = 0; ElementTextLayout *etl, *etlM = NULL; ElementTextLayout2 *etl2; etl = DynamicOption_FindData(args->elem->options, 1005); if (masterX != NULL) etlM = DynamicOption_FindData(args->elem->master->options, 1005); if ((masterX != NULL) && (masterX->textLen == STRINGREP_INVALID)) { args->elem = (TreeElement) masterX; TextUpdateStringRep(args); args->elem = elem; } if (elemX->textLen == STRINGREP_INVALID) { TextUpdateStringRep(args); } etl2 = TextUpdateLayout("NeededProcText", args, args->needed.fixedWidth, args->needed.maxWidth); if (etl2 != NULL) { etl2->layoutWidth = -1; etl2->neededWidth = -1; } if (etl2 != NULL && etl2->layout != NULL) { TextLayout_Size(etl2->layout, &width, &height); if (args->needed.fixedWidth >= 0) etl2->layoutWidth = args->needed.fixedWidth; else if (args->needed.maxWidth >= 0) etl2->layoutWidth = args->needed.maxWidth; etl2->neededWidth = width; /* * Hack -- If we call TextLayout_Compute() with the same width * returned by TextLayout_Size(), we may get a different layout. * I think this has to do with whitespace at the end of lines. * So if HeightProc or DisplayProc is given neededWidth, I do the * layout at totalWidth, not neededWidth. */ etl2->totalWidth = TextLayout_TotalWidth(etl2->layout); } else { if (elemX->text != NULL) { text = elemX->text; textLen = elemX->textLen; } else if ((masterX != NULL) && (masterX->text != NULL)) { text = masterX->text; textLen = masterX->textLen; } if (textLen > 0) { int maxWidth = -1; tkfont = DO_FontForState(tree, elem, 1004, state); if (tkfont == NULL) tkfont = tree->tkfont; width = Tk_TextWidth(tkfont, text, textLen); if (etl != NULL && etl->widthObj != NULL) maxWidth = etl->width; else if ((etlM != NULL) && (etlM->widthObj != NULL)) maxWidth = etlM->width; if ((maxWidth >= 0) && (maxWidth < width)) width = maxWidth; Tk_GetFontMetrics(tkfont, &fm); height = fm.linespace; } } args->needed.width = width; args->needed.height = height; } static void HeightProcText(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master; int state = args->state; int height = 0; char *text = NULL; int textLen = 0; Tk_Font tkfont; Tk_FontMetrics fm; ElementTextLayout2 *etl2; etl2 = TextRedoLayoutIfNeeded("HeightProcText", args, args->height.fixedWidth); if (etl2 != NULL && etl2->layout != NULL) { TextLayout_Size(etl2->layout, NULL, &height); } else { if (elemX->text != NULL) { text = elemX->text; textLen = elemX->textLen; } else if ((masterX != NULL) && (masterX->text != NULL)) { text = masterX->text; textLen = masterX->textLen; } if (textLen > 0) { tkfont = DO_FontForState(tree, elem, 1004, state); if (tkfont == NULL) tkfont = tree->tkfont; Tk_GetFontMetrics(tkfont, &fm); height = fm.linespace; } } args->height.height = height; } int TreeElement_GetSortData( TreeCtrl *tree, TreeElement elem, int type, long *lv, double *dv, char **sv) { ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master; ElementTextData *etd, *etdM = NULL; Tcl_Obj *dataObj = NULL; int dataType = TDT_NULL; etd = DynamicOption_FindData(elem->options, 1006); if (etd != NULL) { dataObj = etd->dataObj; dataType = etd->dataType; } if (dataType == TDT_NULL && masterX != NULL) { etdM = DynamicOption_FindData(elem->master->options, 1006); /* FIXME: get dataObj from master? */ if (etdM != NULL) dataType = etdM->dataType; } switch (type) { case SORT_ASCII: case SORT_DICT: if (dataObj != NULL && dataType != TDT_NULL) (*sv) = Tcl_GetString(dataObj); else (*sv) = elemX->textCfg; break; case SORT_DOUBLE: if (dataObj != NULL && dataType == TDT_DOUBLE) { if (Tcl_GetDoubleFromObj(tree->interp, dataObj, dv) != TCL_OK) return TCL_ERROR; break; } if (elemX->textCfg != NULL) { if (Tcl_GetDouble(tree->interp, elemX->textCfg, dv) != TCL_OK) return TCL_ERROR; break; } FormatResult(tree->interp, "can't get a double from an empty -text value"); return TCL_ERROR; case SORT_LONG: if (dataObj != NULL && dataType != TDT_NULL) { if (dataType == TDT_LONG || dataType == TDT_TIME) { if (Tcl_GetLongFromObj(tree->interp, dataObj, lv) != TCL_OK) return TCL_ERROR; break; } if (dataType == TDT_INTEGER) { int iv; if (Tcl_GetIntFromObj(tree->interp, dataObj, &iv) != TCL_OK) return TCL_ERROR; (*lv) = iv; break; } } if (elemX->textCfg != NULL) { if (TclGetLong(tree->interp, elemX->textCfg, lv) != TCL_OK) return TCL_ERROR; break; } FormatResult(tree->interp, "can't get a long from an empty -text value"); return TCL_ERROR; } return TCL_OK; } static int StateProcText(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; /* ElementText *elemX = (ElementText *) elem; ElementText *masterX = (ElementText *) elem->master;*/ #ifdef DEPRECATED int draw1, draw2; #endif XColor *f1, *f2; Tk_Font tkfont1, tkfont2; if (!args->states.visible2) return 0; tkfont1 = DO_FontForState(tree, elem, 1004, args->states.state1); tkfont2 = DO_FontForState(tree, elem, 1004, args->states.state2); if (tkfont1 != tkfont2) return CS_DISPLAY | CS_LAYOUT; if (!args->states.draw2) return 0; #ifdef DEPRECATED draw1 = DO_BooleanForState(tree, elem, 1002, args->states.state1); draw2 = DO_BooleanForState(tree, elem, 1002, args->states.state2); if ((draw1 != 0) != (draw2 != 0)) return CS_DISPLAY; if (draw2 == 0) return 0; #endif f1 = DO_ColorForState(tree, elem, 1003, args->states.state1); f2 = DO_ColorForState(tree, elem, 1003, args->states.state2); if (f1 != f2) return CS_DISPLAY; return 0; } static int UndefProcText(TreeElementArgs *args) { TreeCtrl *tree = args->tree; /* ElementText *elemX = (ElementText *) args->elem;*/ int modified = 0; PerStateInfo *psi; if ((psi = DynamicOption_FindData(args->elem->options, 1002)) != NULL) modified |= PerStateInfo_Undefine(tree, &pstBoolean, psi, args->state); if ((psi = DynamicOption_FindData(args->elem->options, 1003)) != NULL) modified |= PerStateInfo_Undefine(tree, &pstColor, psi, args->state); if ((psi = DynamicOption_FindData(args->elem->options, 1004)) != NULL) modified |= PerStateInfo_Undefine(tree, &pstFont, psi, args->state); return modified; } static int ActualProcText(TreeElementArgs *args) { TreeCtrl *tree = args->tree; /* ElementText *elemX = (ElementText *) args->elem; ElementText *masterX = (ElementText *) args->elem->master;*/ static CONST char *optionName[] = { #ifdef DEPRECATED "-draw", #endif "-fill", "-font", (char *) NULL }; int index; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { #ifdef DEPRECATED case 0: { obj = DO_ObjectForState(tree, &pstBoolean, args->elem, 1002, args->state); break; } case 1: { obj = DO_ObjectForState(tree, &pstColor, args->elem, 1003, args->state); break; } case 2: { obj = DO_ObjectForState(tree, &pstFont, args->elem, 1004, args->state); break; } #else case 0: { obj = DO_ObjectForState(tree, &pstColor, args->elem, 1003, args->state); break; } case 1: { obj = DO_ObjectForState(tree, &pstFont, args->elem, 1004, args->state); break; } #endif } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } TreeElementType treeElemTypeText = { "text", sizeof(ElementText), textOptionSpecs, NULL, CreateProcText, DeleteProcText, ConfigProcText, DisplayProcText, NeededProcText, HeightProcText, WorldChangedProcText, StateProcText, UndefProcText, ActualProcText, NULL /* onScreenProc */ }; /*****/ typedef struct ElementWindow ElementWindow; struct ElementWindow { TreeElement_ header; #ifdef DEPRECATED PerStateInfo draw; /* -draw */ #endif TreeCtrl *tree; TreeItem item; /* Needed if window changes size */ TreeItemColumn column; /* Needed if window changes size */ Tk_Window tkwin; /* Window associated with item. NULL means * window has been destroyed. */ int destroy; /* Destroy window when element * is deleted */ #define CLIP_WINDOW 1 #ifdef CLIP_WINDOW int clip; /* TRUE if tkwin is a borderless frame * widget whose first child is the actual * window we want displayed. */ Tk_Window child; /* The first child of tkwin. tkwin is resized * so that it is never out-of-bounds, and * the child is positioned within tkwin to * provide clipping of the child. */ #endif }; #define EWIN_CONF_WINDOW 0x0001 #ifdef DEPRECATED #define EWIN_CONF_DRAW 0x0002 #endif static Tk_OptionSpec windowOptionSpecs[] = { #ifdef CLIP_WINDOW {TK_OPTION_CUSTOM, "-clip", (char *) NULL, (char *) NULL, (char) NULL, -1, Tk_Offset(ElementWindow, clip), TK_OPTION_NULL_OK, (ClientData) &booleanCO, 0}, #endif {TK_OPTION_CUSTOM, "-destroy", (char *) NULL, (char *) NULL, (char) NULL, -1, Tk_Offset(ElementWindow, destroy), TK_OPTION_NULL_OK, (ClientData) &booleanCO, 0}, #ifdef DEPRECATED {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementWindow, draw.obj), Tk_Offset(ElementWindow, draw), TK_OPTION_NULL_OK, (ClientData) NULL, EWIN_CONF_DRAW}, #endif {TK_OPTION_WINDOW, "-window", (char *) NULL, (char *) NULL, (char) NULL, -1, Tk_Offset(ElementWindow, tkwin), TK_OPTION_NULL_OK, (ClientData) NULL, EWIN_CONF_WINDOW}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void WinItemStructureProc( ClientData clientData, /* Pointer to record describing window elem. */ XEvent *eventPtr) /* Describes what just happened. */ { ElementWindow *elemX = clientData; if (eventPtr->type == DestroyNotify) { elemX->tkwin = elemX->child = NULL; Tree_ElementChangedItself(elemX->tree, elemX->item, elemX->column, (TreeElement) elemX, EWIN_CONF_WINDOW, CS_LAYOUT | CS_DISPLAY); } } static void WinItemRequestProc( ClientData clientData, /* Pointer to record for window item. */ Tk_Window tkwin) /* Window that changed its desired * size. */ { ElementWindow *elemX = clientData; #ifdef CLIP_WINDOW /* We don't care about size changes for the clip window. */ if (elemX->child != NULL && tkwin != elemX->child) return; #endif Tree_ElementChangedItself(elemX->tree, elemX->item, elemX->column, (TreeElement) elemX, EWIN_CONF_WINDOW, CS_LAYOUT | CS_DISPLAY); } static void WinItemLostSlaveProc( ClientData clientData, /* WindowItem structure for slave window that * was stolen away. */ Tk_Window tkwin) /* Tk's handle for the slave window. */ { ElementWindow *elemX = clientData; TreeCtrl *tree = elemX->tree; #ifdef CLIP_WINDOW /* If either window is lost to another geometry manager, forget * about both windows. */ if (elemX->child != NULL) { Tk_DeleteEventHandler(elemX->child, StructureNotifyMask, WinItemStructureProc, (ClientData) elemX); if (tkwin != elemX->child) { Tk_ManageGeometry(elemX->child, (Tk_GeomMgr *) NULL, (ClientData) NULL); Tk_UnmapWindow(elemX->child); } elemX->child = NULL; } if (elemX->tkwin != NULL) { Tk_DeleteEventHandler(elemX->tkwin, StructureNotifyMask, WinItemStructureProc, (ClientData) elemX); if (tkwin != elemX->tkwin) { Tk_ManageGeometry(elemX->tkwin, (Tk_GeomMgr *) NULL, (ClientData) NULL); if (tree->tkwin != Tk_Parent(elemX->tkwin)) { Tk_UnmaintainGeometry(elemX->tkwin, tree->tkwin); } Tk_UnmapWindow(elemX->tkwin); } elemX->tkwin = NULL; } #else Tk_DeleteEventHandler(elemX->tkwin, StructureNotifyMask, WinItemStructureProc, (ClientData) elemX); if (tree->tkwin != Tk_Parent(elemX->tkwin)) { Tk_UnmaintainGeometry(elemX->tkwin, tree->tkwin); } Tk_UnmapWindow(elemX->tkwin); elemX->tkwin = NULL; #endif Tree_ElementChangedItself(elemX->tree, elemX->item, elemX->column, (TreeElement) elemX, EWIN_CONF_WINDOW, CS_LAYOUT | CS_DISPLAY); } static Tk_GeomMgr winElemGeomType = { "treectrl", /* name */ WinItemRequestProc, /* requestProc */ WinItemLostSlaveProc, /* lostSlaveProc */ }; static void DeleteProcWindow(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; ElementWindow *masterX = (ElementWindow *) elem->master; if (elemX->tkwin != NULL) { #ifdef CLIP_WINDOW if (elemX->child != NULL) { Tk_DeleteEventHandler(elemX->child, StructureNotifyMask, WinItemStructureProc, (ClientData) elemX); Tk_ManageGeometry(elemX->child, (Tk_GeomMgr *) NULL, (ClientData) NULL); Tk_UnmapWindow(elemX->child); elemX->child = NULL; } #endif Tk_DeleteEventHandler(elemX->tkwin, StructureNotifyMask, WinItemStructureProc, (ClientData) elemX); Tk_ManageGeometry(elemX->tkwin, (Tk_GeomMgr *) NULL, (ClientData) NULL); if (tree->tkwin != Tk_Parent(elemX->tkwin)) { Tk_UnmaintainGeometry(elemX->tkwin, tree->tkwin); } Tk_UnmapWindow(elemX->tkwin); if ((elemX->destroy == 1) || ((masterX != NULL) && (masterX->destroy == 1))) { Tk_DestroyWindow(elemX->tkwin); } elemX->tkwin = NULL; } } static int WorldChangedProcWindow(TreeElementArgs *args) { int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; #ifdef DEPRECATED if ((flagS | flagM) & (EWIN_CONF_DRAW)) mask |= CS_DISPLAY; #endif if ((flagS | flagM) & (EWIN_CONF_WINDOW)) mask |= CS_DISPLAY | CS_LAYOUT; return mask; } static int ConfigProcWindow(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; ElementWindow *masterX = (ElementWindow *) elem->master; ElementWindow savedX; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; savedX.tkwin = elemX->tkwin; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } if (args->config.flagSelf & EWIN_CONF_WINDOW) { if ((elem->master == NULL) && (elemX->tkwin != NULL)){ FormatResult(tree->interp, "can't specify -window for a master element"); continue; } } Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } if (savedX.tkwin != elemX->tkwin) { if (savedX.tkwin != NULL) { #ifdef CLIP_WINDOW if (elemX->child != NULL) { Tk_DeleteEventHandler(elemX->child, StructureNotifyMask, WinItemStructureProc, (ClientData) elemX); Tk_ManageGeometry(elemX->child, (Tk_GeomMgr *) NULL, (ClientData) NULL); Tk_UnmapWindow(elemX->child); elemX->child = NULL; } #endif Tk_DeleteEventHandler(savedX.tkwin, StructureNotifyMask, WinItemStructureProc, (ClientData) elemX); Tk_ManageGeometry(savedX.tkwin, (Tk_GeomMgr *) NULL, (ClientData) NULL); Tk_UnmaintainGeometry(savedX.tkwin, tree->tkwin); Tk_UnmapWindow(savedX.tkwin); } if (elemX->tkwin != NULL) { Tk_Window ancestor, parent; /* * Make sure that the treectrl is either the parent of the * window associated with the element or a descendant of that * parent. Also, don't allow a top-of-hierarchy window to be * managed inside a treectrl. */ parent = Tk_Parent(elemX->tkwin); for (ancestor = tree->tkwin; ; ancestor = Tk_Parent(ancestor)) { if (ancestor == parent) { break; } if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_HIERARCHY) { badWindow: FormatResult(tree->interp, "can't use %s in a window element of %s", Tk_PathName(elemX->tkwin), Tk_PathName(tree->tkwin)); elemX->tkwin = NULL; return TCL_ERROR; } } if (((Tk_FakeWin *) (elemX->tkwin))->flags & TK_TOP_HIERARCHY) { goto badWindow; } if (elemX->tkwin == tree->tkwin) { goto badWindow; } #ifdef CLIP_WINDOW if ((elemX->clip == 1) || ((masterX != NULL) && (masterX->clip == 1))) { elemX->child = (Tk_Window) ((TkWindow *) elemX->tkwin)->childList; if (elemX->child != NULL) { Tk_CreateEventHandler(elemX->child, StructureNotifyMask, WinItemStructureProc, (ClientData) elemX); Tk_ManageGeometry(elemX->child, &winElemGeomType, (ClientData) elemX); } } #endif Tk_CreateEventHandler(elemX->tkwin, StructureNotifyMask, WinItemStructureProc, (ClientData) elemX); Tk_ManageGeometry(elemX->tkwin, &winElemGeomType, (ClientData) elemX); } } #if 0 if ((elemX->tkwin != NULL) && (itemPtr->state == TK_STATE_HIDDEN)) { if (tree->tkwin == Tk_Parent(elemX->tkwin)) { Tk_UnmapWindow(elemX->tkwin); } else { Tk_UnmaintainGeometry(elemX->tkwin, tree->tkwin); } } #endif return TCL_OK; } static int CreateProcWindow(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; elemX->tree = tree; elemX->item = args->create.item; elemX->column = args->create.column; elemX->destroy = -1; #ifdef CLIP_WINDOW elemX->clip = -1; #endif return TCL_OK; } static void DisplayProcWindow(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; ElementWindow *masterX = (ElementWindow *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int minX, maxX, minY, maxY; int width, height; int match, match2; #ifdef DEPRECATED int draw; #endif int requests; #ifdef DEPRECATED BOOLEAN_FOR_STATE(draw, draw, state); if (!draw) goto hideIt; #endif if (elemX->tkwin == NULL) return; #ifdef CLIP_WINDOW if (elemX->child != NULL) { width = Tk_ReqWidth(elemX->child); height = Tk_ReqHeight(elemX->child); } else { width = Tk_ReqWidth(elemX->tkwin); height = Tk_ReqHeight(elemX->tkwin); } if (width < 1 || height < 1) goto hideIt; #else width = Tk_ReqWidth(elemX->tkwin); height = Tk_ReqHeight(elemX->tkwin); #endif AdjustForSticky(args->display.sticky, args->display.width, args->display.height, TRUE, TRUE, &x, &y, &width, &height); x += tree->drawableXOrigin - tree->xOrigin; y += tree->drawableYOrigin - tree->yOrigin; /* -squeeze layout may give the element less space than requested. */ if (width > args->display.width) width = args->display.width; if (height > args->display.height) height = args->display.height; minX = args->display.bounds[0]; minY = args->display.bounds[1]; maxX = args->display.bounds[2]; maxY = args->display.bounds[3]; /* * If the window is completely out of the visible area of the treectrl * then unmap it. The window could suddenly reappear if the treectrl * window gets resized. */ if (((x + width) <= minX) || ((y + height) <= minY) || (x >= maxX) || (y >= maxY)) { hideIt: if (tree->tkwin == Tk_Parent(elemX->tkwin)) { Tk_UnmapWindow(elemX->tkwin); } else { Tk_UnmaintainGeometry(elemX->tkwin, tree->tkwin); } return; } TreeDisplay_GetReadyForTrouble(tree, &requests); #ifdef CLIP_WINDOW if (elemX->child != NULL) { int cx = x, cy = y, cw = width, ch = height; /* clip win coords */ if (cx < minX) { cw -= minX - cx; cx = minX; } if (cy < minY) { ch -= minY - cy; cy = minY; } if (cx + cw > maxX) cw = maxX - cx; if (cy + ch > maxY) ch = maxY - cy; /* * Reposition and map the window (but in different ways depending * on whether the treectrl is the window's parent). */ if (tree->tkwin == Tk_Parent(elemX->tkwin)) { if ((cx != Tk_X(elemX->tkwin)) || (cy != Tk_Y(elemX->tkwin)) || (cw != Tk_Width(elemX->tkwin)) || (ch != Tk_Height(elemX->tkwin))) { Tk_MoveResizeWindow(elemX->tkwin, cx, cy, cw, ch); if (TreeDisplay_WasThereTrouble(tree, requests)) return; } Tk_MapWindow(elemX->tkwin); } else { Tk_MaintainGeometry(elemX->tkwin, tree->tkwin, cx, cy, cw, ch); } if (TreeDisplay_WasThereTrouble(tree, requests)) return; /* * Position the child window within the clip window. */ x -= cx; y -= cy; if ((x != Tk_X(elemX->child)) || (y != Tk_Y(elemX->child)) || (width != Tk_Width(elemX->child)) || (height != Tk_Height(elemX->child))) { Tk_MoveResizeWindow(elemX->child, x, y, width, height); if (TreeDisplay_WasThereTrouble(tree, requests)) return; } Tk_MapWindow(elemX->child); return; } #endif /* CLIP_WINDOW */ /* * Reposition and map the window (but in different ways depending * on whether the treectrl is the window's parent). */ if (tree->tkwin == Tk_Parent(elemX->tkwin)) { if ((x != Tk_X(elemX->tkwin)) || (y != Tk_Y(elemX->tkwin)) || (width != Tk_Width(elemX->tkwin)) || (height != Tk_Height(elemX->tkwin))) { Tk_MoveResizeWindow(elemX->tkwin, x, y, width, height); if (TreeDisplay_WasThereTrouble(tree, requests)) return; } Tk_MapWindow(elemX->tkwin); } else { Tk_MaintainGeometry(elemX->tkwin, tree->tkwin, x, y, width, height); } } static void NeededProcWindow(TreeElementArgs *args) { /* TreeCtrl *tree = args->tree;*/ TreeElement elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; /* ElementWindow *masterX = (ElementWindow *) elem->master; int state = args->state;*/ int width = 0, height = 0; #ifdef CLIP_WINDOW if (elemX->child != NULL) { width = Tk_ReqWidth(elemX->child); if (width <= 0) { width = 1; } height = Tk_ReqHeight(elemX->child); if (height <= 0) { height = 1; } } else #endif if (elemX->tkwin) { width = Tk_ReqWidth(elemX->tkwin); if (width <= 0) { width = 1; } height = Tk_ReqHeight(elemX->tkwin); if (height <= 0) { height = 1; } } args->needed.width = width; args->needed.height = height; } static int StateProcWindow(TreeElementArgs *args) { #ifdef DEPRECATED TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementBitmap *elemX = (ElementBitmap *) elem; ElementBitmap *masterX = (ElementBitmap *) elem->master; int match, match2; int draw1, draw2; if (!args->states.visible2 || !args->states.draw2) return 0; BOOLEAN_FOR_STATE(draw1, draw, args->states.state1) BOOLEAN_FOR_STATE(draw2, draw, args->states.state2) if ((draw1 != 0) != (draw2 != 0)) return CS_DISPLAY; #endif return 0; } static int UndefProcWindow(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; int modified = 0; #ifdef DEPRECATED modified |= PerStateInfo_Undefine(tree, &pstBoolean, &elemX->draw, args->state); #endif return modified; } static int ActualProcWindow(TreeElementArgs *args) { #ifdef DEPRECATED TreeCtrl *tree = args->tree; ElementWindow *elemX = (ElementWindow *) args->elem; ElementWindow *masterX = (ElementWindow *) args->elem->master; static CONST char *optionName[] = { "-draw", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { OBJECT_FOR_STATE(obj, pstBoolean, draw, args->state) break; } } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); #endif return TCL_OK; } static void OnScreenProcWindow(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementWindow *elemX = (ElementWindow *) elem; if (!args->screen.visible && (elemX->tkwin != NULL)) { if (tree->tkwin == Tk_Parent(elemX->tkwin)) { Tk_UnmapWindow(elemX->tkwin); } else { Tk_UnmaintainGeometry(elemX->tkwin, tree->tkwin); } } } TreeElementType treeElemTypeWindow = { "window", sizeof(ElementWindow), windowOptionSpecs, NULL, CreateProcWindow, DeleteProcWindow, ConfigProcWindow, DisplayProcWindow, NeededProcWindow, NULL, /* heightProc */ WorldChangedProcWindow, StateProcWindow, UndefProcWindow, ActualProcWindow, OnScreenProcWindow }; /*****/ typedef struct ElementAssocData ElementAssocData; struct ElementAssocData { TreeElementType *typeList; }; int TreeElement_TypeFromObj(TreeCtrl *tree, Tcl_Obj *objPtr, TreeElementType **typePtrPtr) { Tcl_Interp *interp = tree->interp; ElementAssocData *assocData; char *typeStr; int length; TreeElementType *typeList; TreeElementType *typePtr, *matchPtr = NULL; assocData = Tcl_GetAssocData(interp, "TreeCtrlElementTypes", NULL); typeList = assocData->typeList; typeStr = Tcl_GetStringFromObj(objPtr, &length); if (!length) { FormatResult(interp, "invalid element type \"\""); return TCL_ERROR; } for (typePtr = typeList; typePtr != NULL; typePtr = typePtr->next) { if ((typeStr[0] == typePtr->name[0]) && !strncmp(typeStr, typePtr->name, length)) { if (matchPtr != NULL) { FormatResult(interp, "ambiguous element type \"%s\"", typeStr); return TCL_ERROR; } matchPtr = typePtr; } } if (matchPtr == NULL) { FormatResult(interp, "unknown element type \"%s\"", typeStr); return TCL_ERROR; } *typePtrPtr = matchPtr; return TCL_OK; } int TreeCtrl_RegisterElementType(Tcl_Interp *interp, TreeElementType *newTypePtr) { ElementAssocData *assocData; TreeElementType *typeList; TreeElementType *prevPtr, *typePtr, *nextPtr; assocData = Tcl_GetAssocData(interp, "TreeCtrlElementTypes", NULL); typeList = assocData->typeList; for (typePtr = typeList, prevPtr = NULL; typePtr != NULL; prevPtr = typePtr, typePtr = nextPtr) { nextPtr = typePtr->next; /* Remove duplicate type */ if (!strcmp(typePtr->name, newTypePtr->name)) { if (prevPtr == NULL) typeList = typePtr->next; else prevPtr->next = typePtr->next; ckfree((char *) typePtr); } } typePtr = (TreeElementType *) ckalloc(sizeof(TreeElementType)); memcpy(typePtr, newTypePtr, sizeof(TreeElementType)); typePtr->next = typeList; typeList = typePtr; typePtr->optionTable = Tk_CreateOptionTable(interp, newTypePtr->optionSpecs); assocData->typeList = typeList; return TCL_OK; } static TreeCtrlStubs stubs = { TreeCtrl_RegisterElementType, Tree_RedrawElement, Tree_ElementIterateBegin, Tree_ElementIterateNext, Tree_ElementIterateGet, Tree_ElementIterateChanged, PerStateInfo_Free, PerStateInfo_FromObj, PerStateInfo_ForState, PerStateInfo_ObjForState, PerStateInfo_Undefine, &pstBoolean, PerStateBoolean_ForState, PSTSave, PSTRestore, TreeStateFromObj, BooleanCO_Init, StringTableCO_Init, PerStateCO_Init }; static void FreeAssocData(ClientData clientData, Tcl_Interp *interp) { ElementAssocData *assocData = clientData; TreeElementType *typeList = assocData->typeList; TreeElementType *next; while (typeList != NULL) { next = typeList->next; /* The ElementType.optionTables are freed when the interp is deleted */ ckfree((char *) typeList); typeList = next; } ckfree((char *) assocData); } int TreeElement_Init(Tcl_Interp *interp) { ElementAssocData *assocData; /* FIXME: memory leak with dynamically-allocated ClientData. */ /* * bitmap */ PerStateCO_Init(treeElemTypeBitmap.optionSpecs, "-background", &pstColor, TreeStateFromObj); PerStateCO_Init(treeElemTypeBitmap.optionSpecs, "-bitmap", &pstBitmap, TreeStateFromObj); #ifdef DEPRECATED PerStateCO_Init(treeElemTypeBitmap.optionSpecs, "-draw", &pstBoolean, TreeStateFromObj); #endif PerStateCO_Init(treeElemTypeBitmap.optionSpecs, "-foreground", &pstColor, TreeStateFromObj); /* * border */ #ifdef DEPRECATED PerStateCO_Init(treeElemTypeBorder.optionSpecs, "-draw", &pstBoolean, TreeStateFromObj); #endif PerStateCO_Init(treeElemTypeBorder.optionSpecs, "-background", &pstBorder, TreeStateFromObj); PerStateCO_Init(treeElemTypeBorder.optionSpecs, "-relief", &pstRelief, TreeStateFromObj); /* * image */ #ifdef DEPRECATED DynamicCO_Init(treeElemTypeImage.optionSpecs, "-draw", 1002, sizeof(PerStateInfo), Tk_Offset(PerStateInfo, obj), 0, PerStateCO_Alloc("-draw", &pstBoolean, TreeStateFromObj), (DynamicOptionInitProc *) NULL); #endif PerStateCO_Init(treeElemTypeImage.optionSpecs, "-image", &pstImage, TreeStateFromObj); /* 2 options in the same structure. */ DynamicCO_Init(treeElemTypeImage.optionSpecs, "-height", 1001, sizeof(ElementImageSize), Tk_Offset(ElementImageSize, heightObj), Tk_Offset(ElementImageSize, height), &TreeCtrlCO_pixels, (DynamicOptionInitProc *) NULL); DynamicCO_Init(treeElemTypeImage.optionSpecs, "-width", 1001, sizeof(ElementImageSize), Tk_Offset(ElementImageSize, widthObj), Tk_Offset(ElementImageSize, width), &TreeCtrlCO_pixels, (DynamicOptionInitProc *) NULL); DynamicCO_Init(treeElemTypeImage.optionSpecs, "-tiled", 1003, sizeof(int), -1, 0, &booleanCO, DynamicOptionInitBoolean); /* * rect */ #ifdef DEPRECATED PerStateCO_Init(treeElemTypeRect.optionSpecs, "-draw", &pstBoolean, TreeStateFromObj); #endif PerStateCO_Init(treeElemTypeRect.optionSpecs, "-fill", &pstColor, TreeStateFromObj); PerStateCO_Init(treeElemTypeRect.optionSpecs, "-outline", &pstColor, TreeStateFromObj); /* * text */ /* 3 options in the same structure. */ DynamicCO_Init(treeElemTypeText.optionSpecs, "-data", 1006, sizeof(ElementTextData), Tk_Offset(ElementTextData, dataObj), -1, &TreeCtrlCO_string, ElementTextDataInit); DynamicCO_Init(treeElemTypeText.optionSpecs, "-datatype", 1006, sizeof(ElementTextData), -1, Tk_Offset(ElementTextData, dataType), StringTableCO_Alloc("-datatype", textDataTypeST), ElementTextDataInit); DynamicCO_Init(treeElemTypeText.optionSpecs, "-format", 1006, sizeof(ElementTextData), Tk_Offset(ElementTextData, formatObj), -1, &TreeCtrlCO_string, ElementTextDataInit); /* 4 options in the same structure. */ DynamicCO_Init(treeElemTypeText.optionSpecs, "-justify", 1005, sizeof(ElementTextLayout), -1, Tk_Offset(ElementTextLayout, justify), StringTableCO_Alloc("-justify", textJustifyST), ElementTextLayoutInit); DynamicCO_Init(treeElemTypeText.optionSpecs, "-lines", 1005, sizeof(ElementTextLayout), -1, Tk_Offset(ElementTextLayout, lines), IntegerCO_Alloc("-lines", 0, /* min */ 0, /* max (ignored) */ -1, /* empty */ 0x01), /* flags: min */ ElementTextLayoutInit); DynamicCO_Init(treeElemTypeText.optionSpecs, "-width", 1005, sizeof(ElementTextLayout), Tk_Offset(ElementTextLayout, widthObj), Tk_Offset(ElementTextLayout, width), &TreeCtrlCO_pixels, ElementTextLayoutInit); DynamicCO_Init(treeElemTypeText.optionSpecs, "-wrap", 1005, sizeof(ElementTextLayout), -1, Tk_Offset(ElementTextLayout, wrap), StringTableCO_Alloc("-wrap", textWrapST), ElementTextLayoutInit); #ifdef DEPRECATED DynamicCO_Init(treeElemTypeText.optionSpecs, "-draw", 1002, sizeof(PerStateInfo), Tk_Offset(PerStateInfo, obj), 0, PerStateCO_Alloc("-draw", &pstBoolean, TreeStateFromObj), (DynamicOptionInitProc *) NULL); #endif DynamicCO_Init(treeElemTypeText.optionSpecs, "-fill", 1003, sizeof(PerStateInfo), Tk_Offset(PerStateInfo, obj), 0, PerStateCO_Alloc("-fill", &pstColor, TreeStateFromObj), (DynamicOptionInitProc *) NULL); DynamicCO_Init(treeElemTypeText.optionSpecs, "-font", 1004, sizeof(PerStateInfo), Tk_Offset(PerStateInfo, obj), 0, PerStateCO_Alloc("-font", &pstFont, TreeStateFromObj), (DynamicOptionInitProc *) NULL); DynamicCO_Init(treeElemTypeText.optionSpecs, "-textvariable", 1001, sizeof(ElementTextVar), Tk_Offset(struct ElementTextVar, varNameObj), -1, &TreeCtrlCO_string, (DynamicOptionInitProc *) NULL); #ifdef TEXT_STYLE DynamicCO_Init(treeElemTypeText.optionSpecs, "-underline", 1008, sizeof(ElementTextStyle), -1, Tk_Offset(ElementTextStyle, underline), IntegerCO_Alloc("-underline", 0, /* min (ignored) */ 0, /* max (ignored) */ TEXT_UNDERLINE_EMPTYVAL, /* empty */ 0x00), /* flags */ ElementTextStyleInit); #endif /* * window */ #ifdef DEPRECATED PerStateCO_Init(treeElemTypeWindow.optionSpecs, "-draw", &pstBoolean, TreeStateFromObj); #endif assocData = (ElementAssocData *) ckalloc(sizeof(ElementAssocData)); assocData->typeList = NULL; Tcl_SetAssocData(interp, "TreeCtrlElementTypes", FreeAssocData, assocData); TreeCtrl_RegisterElementType(interp, &treeElemTypeBitmap); TreeCtrl_RegisterElementType(interp, &treeElemTypeBorder); /* TreeCtrl_RegisterElementType(interp, &treeElemTypeCheckButton);*/ TreeCtrl_RegisterElementType(interp, &treeElemTypeImage); TreeCtrl_RegisterElementType(interp, &treeElemTypeRect); TreeCtrl_RegisterElementType(interp, &treeElemTypeText); TreeCtrl_RegisterElementType(interp, &treeElemTypeWindow); Tcl_SetAssocData(interp, "TreeCtrlStubs", NULL, &stubs); return TCL_OK; } tktreectrl-2.2.8/generic/tkTreeElem.h0000700000175600010010000001232010745240306015731 0ustar TimNone/* * tkTreeElem.h -- * * This module is the header for elements in treectrl widgets. * * Copyright (c) 2002-2008 Tim Baker * * RCS: @(#) $Id: tkTreeElem.h,v 1.28 2008/01/22 01:03:02 treectrl Exp $ */ typedef struct TreeElementType TreeElementType; typedef struct TreeElement_ TreeElement_; typedef struct TreeElementArgs TreeElementArgs; struct TreeElementArgs { TreeCtrl *tree; TreeElement elem; int state; struct { TreeItem item; TreeItemColumn column; } create; struct { int noop; } delete; struct { int objc; Tcl_Obj *CONST *objv; int flagSelf; TreeItem item; TreeItemColumn column; } config; struct { int x; int y; int width; int height; #define STICKY_W 0x1000 /* These values must match ELF_STICKY_xxx */ #define STICKY_N 0x2000 #define STICKY_E 0x4000 #define STICKY_S 0x8000 int sticky; TreeDrawable td; Drawable drawable; int bounds[4]; } display; struct { int fixedWidth; int fixedHeight; int maxWidth; int maxHeight; int width; int height; } needed; struct { int fixedWidth; int height; } height; struct { int flagTree; int flagMaster; int flagSelf; } change; struct { int state1; int state2; int draw1; int draw2; int visible1; int visible2; } states; struct { Tcl_Obj *obj; } actual; struct { int visible; } screen; }; struct TreeElementType { char *name; /* "image", "text" */ int size; /* size of an TreeElement */ Tk_OptionSpec *optionSpecs; Tk_OptionTable optionTable; int (*createProc)(TreeElementArgs *args); void (*deleteProc)(TreeElementArgs *args); int (*configProc)(TreeElementArgs *args); void (*displayProc)(TreeElementArgs *args); void (*neededProc)(TreeElementArgs *args); void (*heightProc)(TreeElementArgs *args); int (*changeProc)(TreeElementArgs *args); int (*stateProc)(TreeElementArgs *args); int (*undefProc)(TreeElementArgs *args); int (*actualProc)(TreeElementArgs *args); void (*onScreenProc)(TreeElementArgs *args); TreeElementType *next; }; /* list of these for each style */ struct TreeElement_ { Tk_Uid name; /* "elem2", "eText" etc */ TreeElementType *typePtr; TreeElement master; /* NULL if this is master */ DynamicOption *options; /* Dynamically-allocated options. */ /* type-specific data here */ }; extern TreeElementType treeElemTypeBitmap; extern TreeElementType treeElemTypeBorder; extern TreeElementType treeElemTypeCheckButton; extern TreeElementType treeElemTypeImage; extern TreeElementType treeElemTypeRect; extern TreeElementType treeElemTypeText; extern TreeElementType treeElemTypeWindow; #define ELEMENT_TYPE_MATCHES(t1,t2) ((t1)->name == (t2)->name) /***** ***** *****/ extern int TreeElement_GetSortData(TreeCtrl *tree, TreeElement elem, int type, long *lv, double *dv, char **sv); typedef struct TreeIterate_ *TreeIterate; extern int TreeElement_TypeFromObj(TreeCtrl *tree, Tcl_Obj *objPtr, TreeElementType **typePtrPtr); extern void Tree_RedrawElement(TreeCtrl *tree, TreeItem item, TreeElement elem); extern TreeIterate Tree_ElementIterateBegin(TreeCtrl *tree, TreeElementType *elemTypePtr); extern TreeIterate Tree_ElementIterateNext(TreeIterate iter_); extern TreeElement Tree_ElementIterateGet(TreeIterate iter_); extern void Tree_ElementIterateChanged(TreeIterate iter_, int mask); extern void Tree_ElementChangedItself(TreeCtrl *tree, TreeItem item, TreeItemColumn column, TreeElement elem, int flags, int mask); typedef struct TreeCtrlStubs TreeCtrlStubs; struct TreeCtrlStubs { int (*TreeCtrl_RegisterElementType)(Tcl_Interp *interp, TreeElementType *typePtr); void (*Tree_RedrawElement)(TreeCtrl *tree, TreeItem item, TreeElement elem); TreeIterate (*Tree_ElementIterateBegin)(TreeCtrl *tree, TreeElementType *elemTypePtr); TreeIterate (*Tree_ElementIterateNext)(TreeIterate iter_); TreeElement (*Tree_ElementIterateGet)(TreeIterate iter_); void (*Tree_ElementIterateChanged)(TreeIterate iter_, int mask); void (*PerStateInfo_Free)(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo); int (*PerStateInfo_FromObj)(TreeCtrl *tree, StateFromObjProc proc, PerStateType *typePtr, PerStateInfo *pInfo); PerStateData *(*PerStateInfo_ForState)(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, int state, int *match); Tcl_Obj *(*PerStateInfo_ObjForState)(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, int state, int *match); int (*PerStateInfo_Undefine)(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, int state); PerStateType *pstBoolean; int (*PerStateBoolean_ForState)(TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match); void (*PSTSave)(PerStateInfo *pInfo, PerStateInfo *pSave); void (*PSTRestore)(TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, PerStateInfo *pSave); int (*TreeStateFromObj)(TreeCtrl *tree, Tcl_Obj *obj, int *stateOff, int *stateOn); int (*BooleanCO_Init)(Tk_OptionSpec *optionTable, CONST char *optionName); int (*StringTableCO_Init)(Tk_OptionSpec *optionTable, CONST char *optionName, CONST char **tablePtr); int (*PerStateCO_Init)(Tk_OptionSpec *optionTable, CONST char *optionName, PerStateType *typePtr, StateFromObjProc proc); }; tktreectrl-2.2.8/generic/tkTreeItem.c0000700000175600010010000066265111041155075015760 0ustar TimNone/* * tkTreeItem.c -- * * This module implements items for treectrl widgets. * * Copyright (c) 2002-2008 Tim Baker * * RCS: @(#) $Id: tkTreeItem.c,v 1.106 2008/07/21 18:49:33 treectrl Exp $ */ #include "tkTreeCtrl.h" typedef struct TreeItem_ TreeItem_; typedef struct Column Column; /* * A data structure of the following type is kept for a single column in a * single item. */ struct Column { int cstate; /* STATE_xxx flags manipulated with the * [item state forcolumn] command */ int span; /* Number of tree-columns this column covers */ TreeStyle style; /* Instance style. */ Column *next; /* Column to the right of this one */ }; /* * A data structure of the following type is kept for each item. */ struct TreeItem_ { int id; /* unique id */ int depth; /* tree depth (-1 for the unique root item) */ int fixedHeight; /* -height: desired height of this item (0 for * no-such-value) */ int numChildren; int index; /* "row" in flattened tree */ int indexVis; /* visible "row" in flattened tree, -1 if hidden */ int state; /* STATE_xxx flags */ TreeItem parent; TreeItem firstChild; TreeItem lastChild; TreeItem prevSibling; TreeItem nextSibling; TreeItemDInfo dInfo; /* display info, or NULL */ TreeItemRInfo rInfo; /* range info, or NULL */ Column *columns; int *spans; /* 1 per tree-column. spans[N] is the column index of * the item-column displayed in column N. If this * item's columns all have a span of 1, this field * is NULL (unless it was previously allocated * because some spans were > 1). */ int spanAlloc; /* Size of spans[]. */ #define ITEM_FLAG_DELETED 0x0001 /* Item is being deleted */ #define ITEM_FLAG_SPANS_SIMPLE 0x0002 /* All spans are 1 */ #define ITEM_FLAG_SPANS_VALID 0x0004 /* Some spans are > 1, but we don't * need to redo them. Also indicates * we have an entry in * TreeCtrl.itemSpansHash. */ #define ITEM_FLAG_BUTTON 0x0008 /* -button true */ #define ITEM_FLAG_BUTTON_AUTO 0x0010 /* -button auto */ #define ITEM_FLAG_VISIBLE 0x0020 /* -visible */ int flags; TagInfo *tagInfo; /* Tags. May be NULL. */ }; static CONST char *ItemUid = "Item", *ItemColumnUid = "ItemColumn"; /* * Macro to test whether an item is the unique root item */ #define IS_ROOT(i) ((i)->depth == -1) #define IS_ALL(i) ((i) == ITEM_ALL) #define IS_DELETED(i) (((i)->flags & ITEM_FLAG_DELETED) != 0) #define IS_VISIBLE(i) (((i)->flags & ITEM_FLAG_VISIBLE) != 0) /* * Flags returned by Tk_SetOptions() (see itemOptionSpecs below). */ #define ITEM_CONF_BUTTON 0x0001 #define ITEM_CONF_SIZE 0x0002 #define ITEM_CONF_VISIBLE 0x0004 /* * Information used for Item objv parsing. */ static Tk_OptionSpec itemOptionSpecs[] = { {TK_OPTION_CUSTOM, "-button", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeItem_, flags), 0, (ClientData) NULL, ITEM_CONF_BUTTON}, {TK_OPTION_PIXELS, "-height", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeItem_, fixedHeight), TK_OPTION_NULL_OK, (ClientData) NULL, ITEM_CONF_SIZE}, {TK_OPTION_CUSTOM, "-tags", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(TreeItem_, tagInfo), TK_OPTION_NULL_OK, (ClientData) &TreeCtrlCO_tagInfo, 0}, {TK_OPTION_CUSTOM, "-visible", (char *) NULL, (char *) NULL, "1", -1, Tk_Offset(TreeItem_, flags), 0, (ClientData) NULL, ITEM_CONF_VISIBLE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, 0, 0} }; /* *---------------------------------------------------------------------- * * Column_Alloc -- * * Allocate and initialize a new Column record. * * Results: * Pointer to allocated Column. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static Column * Column_Alloc( TreeCtrl *tree /* Widget info. */ ) { #ifdef ALLOC_HAX Column *column = (Column *) TreeAlloc_Alloc(tree->allocData, ItemColumnUid, sizeof(Column)); #else Column *column = (Column *) ckalloc(sizeof(Column)); #endif memset(column, '\0', sizeof(Column)); column->span = 1; return column; } /* *---------------------------------------------------------------------- * * TreeItemColumn_InvalidateSize -- * * Marks the needed height and width of the column as out-of-date. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItemColumn_InvalidateSize( TreeCtrl *tree, /* Widget info. */ TreeItemColumn column_ /* Column token. */ ) { } /* *---------------------------------------------------------------------- * * TreeItemColumn_NeededWidth -- * * Returns the requested width of a Column. * * Results: * If the Column has a style, the requested width of the style * is returned (a positive pixel value). Otherwise 0 is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItemColumn_NeededWidth( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeItemColumn column_ /* Column token. */ ) { Column *self = (Column *) column_; if (self->style != NULL) return TreeStyle_NeededWidth(tree, self->style, item->state | self->cstate); return 0; } #ifdef EXPENSIVE_SPAN_WIDTH /* NOT USED */ /* * When a style spans 2 or more columns, all of the requested width goes * to the first column in the span. Ideally the width needed by the style * would be distributed over each column in the span. To be done properly, * the visibility and fixed-width of each column needs to be considered. * * This routine does an okay job of calculating the requested width of a * column in an item when spans are involved; however there is a lot of * processing involved, and this routine is called for each column in * a span separately (it would be better to calculate the width of all * the columns in a span at the same time). */ int TreeItem_NeededWidthOfColumn( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int _columnIndex /* Column index. */ ) { TreeColumn treeColumn = tree->columns; Column *column = item->columns; int columnIndex = 0, itemColumnIndex = 0, span = 1; int selfIndex = _columnIndex, fixedWidth = 0, width = 0; int spanStart, spanEnd; struct span { Column *itemColumn; int itemColumnIndex; int fixedWidth; int spanWidth; int visible; } staticSpans[STATIC_SIZE], *spans = staticSpans; STATIC_ALLOC(spans, struct span, tree->columnCount); while (treeColumn != NULL) { spans[columnIndex].visible = TreeColumn_Visible(treeColumn); if (--span == 0) { if (spans[columnIndex].visible) span = column ? column->span : 1; else span = 1; itemColumnIndex = columnIndex; } spans[columnIndex].itemColumn = column; spans[columnIndex].itemColumnIndex = itemColumnIndex; spans[columnIndex].spanWidth = 0; spans[columnIndex].fixedWidth = TreeColumn_FixedWidth(treeColumn); ++columnIndex; treeColumn = TreeColumn_Next(treeColumn); if (column != NULL) column = column->next; } span = 0; columnIndex = spanStart = spanEnd = spans[selfIndex].itemColumnIndex; while (spans[columnIndex].itemColumnIndex == spanStart) { if (spans[columnIndex].visible) { if (spans[columnIndex].fixedWidth >= 0) { fixedWidth += spans[columnIndex].fixedWidth; spans[columnIndex].spanWidth = spans[columnIndex].fixedWidth; } else ++span; /* number of visible columns in the span with no * fixed width */ } spanEnd = columnIndex; ++columnIndex; if (columnIndex == tree->columnCount) break; } column = spans[spanStart].itemColumn; if (column != NULL && column->style != NULL) { width = TreeStyle_NeededWidth(tree, column->style, item->state | column->cstate); if (width > fixedWidth && span > 0) { width -= fixedWidth; while (width > 0) { int each = (width > span) ? width / span : 1; columnIndex = spanStart; while (columnIndex <= spanEnd) { if (spans[columnIndex].visible) { if (spans[columnIndex].fixedWidth < 0) { spans[columnIndex].spanWidth += each; width -= each; if (width <= 0) break; } } ++columnIndex; } } }; } if (0) { int i; for (i = 0; i < tree->columnCount; i++) { dbwin("%d,%d: itemColumn %p itemColumnIndex %d fixedWidth %d spanWidth %d\n", item->id, i, spans[i].itemColumn, spans[i].itemColumnIndex, spans[i].fixedWidth, spans[i].spanWidth); } } width = spans[selfIndex].spanWidth; STATIC_FREE(spans, struct span, tree->columnCount); return width; } #endif /* EXPENSIVE_SPAN_WIDTH */ /* *---------------------------------------------------------------------- * * TreeItemColumn_GetStyle -- * * Returns the style assigned to a Column. * * Results: * Returns the style, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeStyle TreeItemColumn_GetStyle( TreeCtrl *tree, /* Widget info. */ TreeItemColumn column /* Column token. */ ) { return ((Column *) column)->style; } /* *---------------------------------------------------------------------- * * TreeItemColumn_Index -- * * Return the 0-based index of a Column in an Item's linked list of * Columns. * * Results: * Integer index of the Column. * * Side effects: * Tcl_Panic() if the Column isn't found. * *---------------------------------------------------------------------- */ int TreeItemColumn_Index( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeItemColumn column_ /* Column token. */ ) { Column *column; int i = 0; column = item->columns; while ((column != NULL) && (column != (Column *) column_)) { i++; column = column->next; } if (column == NULL) panic("TreeItemColumn_Index: couldn't find the column\n"); return i; } /* *---------------------------------------------------------------------- * * TreeItemColumn_ForgetStyle -- * * Free the style assigned to a Column. * * Results: * Column has no style assigned anymore. * * Side effects: * Memory is freed. * *---------------------------------------------------------------------- */ void TreeItemColumn_ForgetStyle( TreeCtrl *tree, /* Widget info. */ TreeItemColumn column_ /* Column token. */ ) { Column *self = (Column *) column_; if (self->style != NULL) { TreeStyle_FreeResources(tree, self->style); self->style = NULL; } } /* *---------------------------------------------------------------------- * * TreeItemColumn_GetNext -- * * Return the Column to the right of this one. * * Results: * The next Column in the linked list, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItemColumn TreeItemColumn_GetNext( TreeCtrl *tree, /* Widget info. */ TreeItemColumn column /* Column token. */ ) { return (TreeItemColumn) ((Column *) column)->next; } /* *---------------------------------------------------------------------- * * Column_FreeResources -- * * Free the style and memory associated with the given Column. * * Results: * The next Column in the linked list, or NULL. * * Side effects: * Memory is freed. * *---------------------------------------------------------------------- */ static Column * Column_FreeResources( TreeCtrl *tree, /* Widget info. */ Column *self /* Column to free. */ ) { Column *next = self->next; if (self->style != NULL) TreeStyle_FreeResources(tree, self->style); #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, ItemColumnUid, (char *) self, sizeof(Column)); #else WFREE(self, Column); #endif return next; } /* *---------------------------------------------------------------------- * * Item_UpdateIndex -- * * Set the Item.depth, Item.index and Item.indexVis fields of the * given Item and all its descendants. * * Results: * None. * * Side effects: * The TreeCtrl.depth field may be updated to track the maximum * depth of all items. * *---------------------------------------------------------------------- */ static void Item_UpdateIndex(TreeCtrl *tree, TreeItem item, /* Item to update. */ int *index, /* New Item.index value for the item. * Value is incremented. */ int *indexVis /* New Item.indexVis value for the item if * the item is ReallyVisible(). * Value is incremented if the item is * ReallyVisible(). */ ) { TreeItem child, parent = item->parent; int parentVis, parentOpen; /* Also track max depth */ if (parent != NULL) item->depth = parent->depth + 1; else item->depth = 0; if (item->depth > tree->depth) tree->depth = item->depth; item->index = (*index)++; item->indexVis = -1; if (parent != NULL) { parentOpen = (parent->state & STATE_OPEN) != 0; parentVis = parent->indexVis != -1; if (IS_ROOT(parent) && !tree->showRoot) { parentOpen = TRUE; parentVis = IS_VISIBLE(parent); } if (parentVis && parentOpen && IS_VISIBLE(item)) item->indexVis = (*indexVis)++; } child = item->firstChild; while (child != NULL) { Item_UpdateIndex(tree, child, index, indexVis); child = child->nextSibling; } } /* *---------------------------------------------------------------------- * * Tree_UpdateItemIndex -- * * Set the Item.depth, Item.index and Item.indexVis fields of the * every Item. Set TreeCtrl.depth to the maximum depth of all * Items. Set TreeCtrl.itemVisCount to the count of all visible * items. * * Because this is slow we try not to do it until necessary. * The tree->updateIndex flags indicates when this is needed. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tree_UpdateItemIndex( TreeCtrl *tree /* Widget info. */ ) { TreeItem item = tree->root; int index = 1, indexVis = 0; if (!tree->updateIndex) return; if (tree->debug.enable && tree->debug.data) dbwin("Tree_UpdateItemIndex %s\n", Tk_PathName(tree->tkwin)); /* Also track max depth */ tree->depth = -1; item->index = 0; item->indexVis = -1; if (tree->showRoot && IS_VISIBLE(item)) item->indexVis = indexVis++; item = item->firstChild; while (item != NULL) { Item_UpdateIndex(tree, item, &index, &indexVis); item = item->nextSibling; } tree->itemVisCount = indexVis; tree->updateIndex = 0; } /* *---------------------------------------------------------------------- * * Item_Alloc -- * * Allocate an initialize a new Item record. * * Results: * Pointer to the allocated Item record. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static TreeItem Item_Alloc( TreeCtrl *tree /* Widget info. */ ) { #ifdef ALLOC_HAX TreeItem item = (TreeItem) TreeAlloc_Alloc(tree->allocData, ItemUid, sizeof(TreeItem_)); #else TreeItem item = (TreeItem) ckalloc(sizeof(TreeItem_)); #endif memset(item, '\0', sizeof(TreeItem_)); if (Tk_InitOptions(tree->interp, (char *) item, tree->itemOptionTable, tree->tkwin) != TCL_OK) panic("Tk_InitOptions() failed in Item_Alloc()"); item->state = STATE_OPEN | STATE_ENABLED; if (tree->gotFocus) item->state |= STATE_FOCUS; item->indexVis = -1; /* In the typical case all spans are 1. */ item->flags |= ITEM_FLAG_SPANS_SIMPLE; Tree_AddItem(tree, item); return item; } /* *---------------------------------------------------------------------- * * Item_AllocRoot -- * * Allocate an initialize a new Item record for the root item. * * Results: * Pointer to the allocated Item record. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static TreeItem Item_AllocRoot( TreeCtrl *tree /* Widget info. */ ) { TreeItem item; item = Item_Alloc(tree); item->depth = -1; item->state |= STATE_ACTIVE; return item; } /* *---------------------------------------------------------------------- * * TreeItem_GetFirstColumn -- * * Return the first Column record for an Item. * * Results: * Token for the column, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItemColumn TreeItem_GetFirstColumn( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return (TreeItemColumn) item->columns; } /* *---------------------------------------------------------------------- * * TreeItem_GetState -- * * Return the state flags for an Item. * * Results: * Bit mask of STATE_xxx flags. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetState( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return item->state; } /* *---------------------------------------------------------------------- * * Column_ChangeState -- * * Toggles zero or more STATE_xxx flags for a Column. If the * Column has a style assigned, its state may be changed. * * Results: * Bit mask of CS_LAYOUT and CS_DISPLAY flags, or zero if no * changes occurred. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static int Column_ChangeState( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the column. */ Column *column, /* Column to modify the state of. */ TreeColumn treeColumn, /* Tree column. */ int stateOff, /* STATE_xxx flags to turn off. */ int stateOn /* STATE_xxx flags to turn on. */ ) { int cstate, state; int sMask, iMask = 0; cstate = column->cstate; cstate &= ~stateOff; cstate |= stateOn; if (cstate == column->cstate) return 0; state = item->state | column->cstate; state &= ~stateOff; state |= stateOn; if (column->style != NULL) { sMask = TreeStyle_ChangeState(tree, column->style, item->state | column->cstate, state); if (sMask) { if (sMask & CS_LAYOUT) Tree_InvalidateColumnWidth(tree, treeColumn); iMask |= sMask; } if (iMask & CS_LAYOUT) { TreeItem_InvalidateHeight(tree, item); TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); Tree_FreeItemDInfo(tree, item, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } else if (iMask & CS_DISPLAY) { Tree_InvalidateItemDInfo(tree, treeColumn, item, NULL); } } column->cstate = cstate; return iMask; } /* *---------------------------------------------------------------------- * * TreeItem_ChangeState -- * * Toggles zero or more STATE_xxx flags for an Item. If the * Column has a style assigned, its state may be changed. * * Results: * Bit mask of CS_LAYOUT and CS_DISPLAY flags, or zero if no * changes occurred. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ int TreeItem_ChangeState( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int stateOff, /* STATE_xxx flags to turn off. */ int stateOn /* STATE_xxx flags to turn on. */ ) { Column *column; TreeColumn treeColumn; int columnIndex = 0, state, cstate; int sMask, iMask = 0; state = item->state; state &= ~stateOff; state |= stateOn; if (state == item->state) return 0; treeColumn = tree->columns; column = item->columns; while (column != NULL) { if (column->style != NULL) { cstate = item->state | column->cstate; cstate &= ~stateOff; cstate |= stateOn; sMask = TreeStyle_ChangeState(tree, column->style, item->state | column->cstate, cstate); if (sMask) { if (sMask & CS_LAYOUT) { Tree_InvalidateColumnWidth(tree, treeColumn); TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); } else if (sMask & CS_DISPLAY) { Tree_InvalidateItemDInfo(tree, treeColumn, item, NULL); } iMask |= sMask; } } columnIndex++; column = column->next; treeColumn = TreeColumn_Next(treeColumn); } /* This item has a button */ if (TreeItem_HasButton(tree, item)) { Tk_Image image1, image2; Pixmap bitmap1, bitmap2; /* NOTE: These next 2 lines must have 'static' to work around a * Microsoft compiler optimization bug. */ static int butOpen, butClosed; static int themeOpen, themeClosed; int w1, h1, w2, h2; void *ptr1 = NULL, *ptr2 = NULL; /* * Compare the image/bitmap/theme/xlib button for the old state * to the image/bitmap/theme/xlib button for the new state. Figure * out if the size or appearance has changed. */ /* image > bitmap > theme > draw */ image1 = PerStateImage_ForState(tree, &tree->buttonImage, item->state, NULL); if (image1 != NULL) { Tk_SizeOfImage(image1, &w1, &h1); ptr1 = image1; } if (ptr1 == NULL) { bitmap1 = PerStateBitmap_ForState(tree, &tree->buttonBitmap, item->state, NULL); if (bitmap1 != None) { Tk_SizeOfBitmap(tree->display, bitmap1, &w1, &h1); ptr1 = (void *) bitmap1; } } if (ptr1 == NULL) { if (tree->useTheme && TreeTheme_GetButtonSize(tree, Tk_WindowId(tree->tkwin), (item->state & STATE_OPEN) != 0, &w1, &h1) == TCL_OK) { ptr1 = (item->state & STATE_OPEN) ? &themeOpen : &themeClosed; } } if (ptr1 == NULL) { w1 = h1 = tree->buttonSize; ptr1 = (item->state & STATE_OPEN) ? &butOpen : &butClosed; } /* image > bitmap > theme > draw */ image2 = PerStateImage_ForState(tree, &tree->buttonImage, state, NULL); if (image2 != NULL) { Tk_SizeOfImage(image2, &w2, &h2); ptr2 = image2; } if (ptr2 == NULL) { bitmap2 = PerStateBitmap_ForState(tree, &tree->buttonBitmap, state, NULL); if (bitmap2 != None) { Tk_SizeOfBitmap(tree->display, bitmap2, &w2, &h2); ptr2 = (void *) bitmap2; } } if (ptr2 == NULL) { if (tree->useTheme && TreeTheme_GetButtonSize(tree, Tk_WindowId(tree->tkwin), (state & STATE_OPEN) != 0, &w2, &h2) == TCL_OK) { ptr2 = (state & STATE_OPEN) ? &themeOpen : &themeClosed; } } if (ptr2 == NULL) { w2 = h2 = tree->buttonSize; ptr2 = (state & STATE_OPEN) ? &butOpen : &butClosed; } if ((w1 != w2) || (h1 != h2)) { iMask |= CS_LAYOUT | CS_DISPLAY; } else if (ptr1 != ptr2) { iMask |= CS_DISPLAY; if (tree->columnTree != NULL) Tree_InvalidateItemDInfo(tree, tree->columnTree, item, NULL); } } if (iMask & CS_LAYOUT) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } item->state = state; return iMask; } /* *---------------------------------------------------------------------- * * TreeItem_UndefineState -- * * Clear a STATE_xxx flag in an Item and its Columns. This is * called when a user-defined state is undefined via the * [state undefine] widget command. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_UndefineState( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int state /* STATE_xxx flag that is undefined. */ ) { Column *column = item->columns; while (column != NULL) { column->cstate &= ~state; column = column->next; } item->state &= ~state; } /* *---------------------------------------------------------------------- * * TreeItem_HasButton -- * * Determine whether an item should have a button displayed next to * it. This considers the value of the item option -button as well * as the treectrl options -showbuttons, -showrootchildbuttons and * -showrootbutton. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_HasButton( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { if (!tree->showButtons || (IS_ROOT(item) && !tree->showRootButton)) return 0; if (item->parent == tree->root && !tree->showRootChildButtons) return 0; if (item->flags & ITEM_FLAG_BUTTON) return 1; if (item->flags & ITEM_FLAG_BUTTON_AUTO) { TreeItem child = item->firstChild; while (child != NULL) { if (IS_VISIBLE(child)) return 1; child = child->nextSibling; } } return 0; } /* *---------------------------------------------------------------------- * * TreeItem_GetDepth -- * * Return the depth of an Item. * * Results: * Integer >= -1. (-1 for the root) * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetDepth( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { #if 0 Tree_UpdateItemIndex(tree); #endif return item->depth; } /* *---------------------------------------------------------------------- * * TreeItem_GetID -- * * Return the unique ID of an Item. * * Results: * Integer >= 0. (0 for the root) * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetID( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return item->id; } /* *---------------------------------------------------------------------- * * TreeItem_SetID -- * * Set the unique ID of an Item. This is called when the item * is created. * * Results: * The given ID. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_SetID( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int id /* Unique ID for the item. */ ) { return item->id = id; } /* *---------------------------------------------------------------------- * * TreeItem_GetEnabled -- * * Return whether an Item is enabled or not. * * Results: * TRUE if the item is enabled, FALSE otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetEnabled( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return (item->state & STATE_ENABLED) != 0; } /* *---------------------------------------------------------------------- * * TreeItem_GetSelected -- * * Return whether an Item is selected or not. * * Results: * TRUE if the item is part of the selection, FALSE otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetSelected( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return (item->state & STATE_SELECTED) != 0; } /* *---------------------------------------------------------------------- * * TreeItem_GetParent -- * * Return the parent of an Item. * * Results: * Token for parent Item, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_GetParent( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return item->parent; } /* *---------------------------------------------------------------------- * * TreeItem_GetNextSibling -- * * Return the next sibling of an Item. * * Results: * Token for next sibling Item, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_GetNextSibling( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return item->nextSibling; } /* *---------------------------------------------------------------------- * * TreeItem_NextSiblingVisible -- * * Find a following sibling that is ReallyVisible(). * * Results: * Token for a sibling Item, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_NextSiblingVisible( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { item = TreeItem_GetNextSibling(tree, item); while (item != NULL) { if (TreeItem_ReallyVisible(tree, item)) return item; item = TreeItem_GetNextSibling(tree, item); } return NULL; } /* *---------------------------------------------------------------------- * * TreeItem_SetDInfo -- * * Store a display-info token in an Item. Called by the display * code. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_SetDInfo( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeItemDInfo dInfo /* Display-info token. */ ) { item->dInfo = dInfo; } /* *---------------------------------------------------------------------- * * TreeItem_GetDInfo -- * * Return the display-info token of an Item. Called by the display * code. * * Results: * The display-info token or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItemDInfo TreeItem_GetDInfo( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return item->dInfo; } /* *---------------------------------------------------------------------- * * TreeItem_SetRInfo -- * * Store a range-info token in an Item. Called by the display * code. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_SetRInfo( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeItemRInfo rInfo /* Range-info token */ ) { item->rInfo = rInfo; } /* *---------------------------------------------------------------------- * * TreeItem_GetRInfo -- * * Return the range-info token of an Item. Called by the display * code. * * Results: * The range-info token or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItemRInfo TreeItem_GetRInfo( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return item->rInfo; } /* *---------------------------------------------------------------------- * * TreeItem_Next -- * * Return the Item after the given one. * * Results: * Result will be: * a) the first child, or * b) the next sibling, or * c) the next sibling of an ancestor, or * d) NULL if no item follows this one * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_Next( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { if (item->firstChild != NULL) return item->firstChild; if (item->nextSibling != NULL) return item->nextSibling; while (1) { item = item->parent; if (item == NULL) break; if (item->nextSibling != NULL) return item->nextSibling; } return NULL; } /* *---------------------------------------------------------------------- * * TreeItem_NextVisible -- * * Return the ReallyVisible() Item after the given one. * * Results: * Result will be: * a) the first ReallyVisible() child, or * b) the next ReallyVisible() sibling, or * c) the next ReallyVisible() sibling of an ancestor, or * d) NULL if no ReallyVisible() item follows this one * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_NextVisible( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { item = TreeItem_Next(tree, item); while (item != NULL) { if (TreeItem_ReallyVisible(tree, item)) return item; item = TreeItem_Next(tree, item); } return NULL; } /* *---------------------------------------------------------------------- * * TreeItem_Prev -- * * Return the Item before the given one. * * Results: * Result will be: * a) the last descendant of the previous sibling, or * b) the parent, or * c) NULL if the given Item is the root * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_Prev( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeItem walk; if (item->parent == NULL) /* root */ return NULL; walk = item->parent; if (item->prevSibling) { walk = item->prevSibling; while (walk->lastChild != NULL) walk = walk->lastChild; } return walk; } /* *---------------------------------------------------------------------- * * TreeItem_PrevVisible -- * * Return the ReallyVisible() Item before the given one. * * Results: * Result will be: * a) the last descendant of the previous sibling, or * b) the parent, or * c) NULL if the given Item is the root * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_PrevVisible( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { item = TreeItem_Prev(tree, item); while (item != NULL) { if (TreeItem_ReallyVisible(tree, item)) return item; item = TreeItem_Prev(tree, item); } return NULL; } /* *---------------------------------------------------------------------- * * TreeItem_ToIndex -- * * Return Item.index and Item.indexVis. * * Results: * The zero-based indexes of the Item. * * Side effects: * Will recalculate the indexes of every item if needed. * *---------------------------------------------------------------------- */ void TreeItem_ToIndex( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int *index, /* Returned Item.index, may be NULL */ int *indexVis /* Returned Item.indexVis, may be NULL */ ) { Tree_UpdateItemIndex(tree); if (index != NULL) (*index) = item->index; if (indexVis != NULL) (*indexVis) = item->indexVis; } /* *---------------------------------------------------------------------- * * ItemHasTag -- * * Checks whether an item has a certain tag. * * Results: * Returns TRUE if the item has the given tag. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int ItemHasTag( TreeItem item, /* The item to test. */ Tk_Uid tag /* Tag to look for. */ ) { TagInfo *tagInfo = item->tagInfo; Tk_Uid *tagPtr; int count; if (tagInfo == NULL) return 0; for (tagPtr = tagInfo->tagPtr, count = tagInfo->numTags; count > 0; tagPtr++, count--) { if (*tagPtr == tag) { return 1; } } return 0; } typedef struct Qualifiers { TreeCtrl *tree; int visible; /* 1 if the item must be ReallyVisible(), 0 if the item must not be ReallyVisible(), -1 for unspecified. */ int states[3]; /* Item states that must be on or off. */ TagExpr expr; /* Tag expression. */ int exprOK; /* TRUE if expr is valid. */ int depth; /* >= 0 for depth, -1 for unspecified */ Tk_Uid tag; /* Tag (without operators) or NULL. */ } Qualifiers; /* *---------------------------------------------------------------------- * * Qualifiers_Init -- * * Helper routine for TreeItem_FromObj. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Qualifiers_Init( TreeCtrl *tree, /* Widget info. */ Qualifiers *q /* Out: Initialized qualifiers. */ ) { q->tree = tree; q->visible = -1; q->states[0] = q->states[1] = q->states[2] = 0; q->exprOK = FALSE; q->depth = -1; q->tag = NULL; } /* *---------------------------------------------------------------------- * * Qualifiers_Scan -- * * Helper routine for TreeItem_FromObj. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Qualifiers_Scan( Qualifiers *q, /* Must call Qualifiers_Init first, * and Qualifiers_Free if result is TCL_OK. */ int objc, /* Number of arguments. */ Tcl_Obj **objv, /* Argument values. */ int startIndex, /* First objv[] index to look at. */ int *argsUsed /* Out: number of objv[] used. */ ) { TreeCtrl *tree = q->tree; Tcl_Interp *interp = tree->interp; int qual, j = startIndex; static CONST char *qualifiers[] = { "depth", "state", "tag", "visible", "!visible", NULL }; enum qualEnum { QUAL_DEPTH, QUAL_STATE, QUAL_TAG, QUAL_VISIBLE, QUAL_NOT_VISIBLE }; /* Number of arguments used by qualifiers[]. */ static int qualArgs[] = { 2, 2, 2, 1, 1 }; *argsUsed = 0; for (; j < objc; ) { if (Tcl_GetIndexFromObj(NULL, objv[j], qualifiers, NULL, 0, &qual) != TCL_OK) break; if (objc - j < qualArgs[qual]) { Tcl_AppendResult(interp, "missing arguments to \"", Tcl_GetString(objv[j]), "\" qualifier", NULL); goto errorExit; } switch ((enum qualEnum) qual) { case QUAL_DEPTH: { if (Tcl_GetIntFromObj(interp, objv[j + 1], &q->depth) != TCL_OK) goto errorExit; break; } case QUAL_STATE: { if (Tree_StateFromListObj(tree, objv[j + 1], q->states, SFO_NOT_TOGGLE) != TCL_OK) goto errorExit; break; } case QUAL_TAG: { if (tree->itemTagExpr) { if (q->exprOK) TagExpr_Free(&q->expr); if (TagExpr_Init(tree, objv[j + 1], &q->expr) != TCL_OK) return TCL_ERROR; q->exprOK = TRUE; } else { q->tag = Tk_GetUid(Tcl_GetString(objv[j + 1])); } break; } case QUAL_VISIBLE: { q->visible = 1; break; } case QUAL_NOT_VISIBLE: { q->visible = 0; break; } } *argsUsed += qualArgs[qual]; j += qualArgs[qual]; } return TCL_OK; errorExit: if (q->exprOK) TagExpr_Free(&q->expr); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Qualifies -- * * Helper routine for TreeItem_FromObj. * * Results: * Returns TRUE if the item meets the given criteria. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Qualifies( Qualifiers *q, /* Qualifiers to check. */ TreeItem item /* The item to test. May be NULL. */ ) { TreeCtrl *tree = q->tree; /* Note: if the item is NULL it is a "match" because we have run * out of items to check. */ if (item == NULL) return 1; if ((q->visible == 1) && !TreeItem_ReallyVisible(tree, item)) return 0; else if ((q->visible == 0) && TreeItem_ReallyVisible(tree, (TreeItem) item)) return 0; if (q->states[STATE_OP_OFF] & item->state) return 0; if ((q->states[STATE_OP_ON] & item->state) != q->states[STATE_OP_ON]) return 0; if (q->exprOK && !TagExpr_Eval(&q->expr, item->tagInfo)) return 0; if ((q->depth >= 0) && (item->depth + 1 != q->depth)) return 0; if ((q->tag != NULL) && !ItemHasTag(item, q->tag)) return 0; return 1; } /* *---------------------------------------------------------------------- * * Qualifiers_Free -- * * Helper routine for TreeItem_FromObj. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Qualifiers_Free( Qualifiers *q /* Out: Initialized qualifiers. */ ) { if (q->exprOK) TagExpr_Free(&q->expr); } /* *---------------------------------------------------------------------- * * TreeItemList_FromObj -- * * Parse a Tcl_Obj item description to get a list of items. * * -- returning a single item -- * "active MODIFIERS" * "anchor MODIFIERS" * "nearest x y MODIFIERS" * "root MODIFIERS" * "first QUALIFIERS MODIFIERS" * "last QUALIFIERS MODIFIERS" * "end QUALIFIERS MODIFIERS" * "rnc row col MODIFIERS" * "ID MODIFIERS" * -- returning multiple items -- * all QUALIFIERS * QUALIFIERS (like "all QUALIFIERS") * list listOfItemDescs * range QUALIFIERS * tag tagExpr QUALIFIERS * "TAG-EXPR QUALFIERS" * * MODIFIERS: * -- returning a single item -- * above * below * left * right * top * bottom * leftmost * rightmost * next QUALIFIERS * prev QUALIFIERS * parent * firstchild QUALIFIERS * lastchild QUALIFIERS * child N|end?-offset? QUALIFIERS * nextsibling QUALIFIERS * prevsibling QUALIFIERS * sibling N|end?-offset? QUALIFIERS * -- returning multiple items -- * ancestors QUALIFIERS * children QUALIFIERS * descendants QUALIFIERS * * QUALIFIERS: * depth integer * state stateList * tag tagExpr * visible * !visible * * Examples: * $T item id "first visible firstchild" * $T item id "first visible firstchild visible" * $T item id "nearest x y nextsibling visible" * $T item id "last visible state enabled" * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItemList_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *objPtr, /* Object to parse to a list of items. */ TreeItemList *items, /* Uninitialized item list. Caller must free * it with TreeItemList_Free unless the * result of this function is TCL_ERROR. */ int flags /* IFO_xxx flags */ ) { Tcl_Interp *interp = tree->interp; int i, objc, index, listIndex, id; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_Obj **objv, *elemPtr; TreeItem item = NULL; Qualifiers q; int qualArgsTotal; static CONST char *indexName[] = { "active", "all", "anchor", "end", "first", "last", "list", "nearest", "range", "rnc", "root", (char *) NULL }; enum indexEnum { INDEX_ACTIVE, INDEX_ALL, INDEX_ANCHOR, INDEX_END, INDEX_FIRST, INDEX_LAST, INDEX_LIST, INDEX_NEAREST, INDEX_RANGE, INDEX_RNC, INDEX_ROOT }; /* Number of arguments used by indexName[]. */ static int indexArgs[] = { 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 1 }; /* Boolean: can indexName[] be followed by 1 or more qualifiers. */ static int indexQual[] = { 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1 }; static CONST char *modifiers[] = { "above", "ancestors", "below", "bottom", "child", "children", "descendants", "firstchild", "lastchild", "left", "leftmost", "next", "nextsibling", "parent", "prev", "prevsibling", "right", "rightmost", "sibling", "top", (char *) NULL }; enum modEnum { TMOD_ABOVE, TMOD_ANCESTORS, TMOD_BELOW, TMOD_BOTTOM, TMOD_CHILD, TMOD_CHILDREN, TMOD_DESCENDANTS, TMOD_FIRSTCHILD, TMOD_LASTCHILD, TMOD_LEFT, TMOD_LEFTMOST, TMOD_NEXT, TMOD_NEXTSIBLING, TMOD_PARENT, TMOD_PREV, TMOD_PREVSIBLING, TMOD_RIGHT, TMOD_RIGHTMOST, TMOD_SIBLING, TMOD_TOP }; /* Number of arguments used by modifiers[]. */ static int modArgs[] = { 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1 }; /* Boolean: can modifiers[] be followed by 1 or more qualifiers. */ static int modQual[] = { 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0 }; TreeItemList_Init(tree, items, 0); Qualifiers_Init(tree, &q); if (Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK) goto baditem; if (objc == 0) goto baditem; listIndex = 0; elemPtr = objv[listIndex]; if (Tcl_GetIndexFromObj(NULL, elemPtr, indexName, NULL, 0, &index) == TCL_OK) { if (objc - listIndex < indexArgs[index]) { Tcl_AppendResult(interp, "missing arguments to \"", Tcl_GetString(elemPtr), "\" keyword", NULL); goto errorExit; } qualArgsTotal = 0; if (indexQual[index]) { if (Qualifiers_Scan(&q, objc, objv, listIndex + indexArgs[index], &qualArgsTotal) != TCL_OK) { goto errorExit; } } switch ((enum indexEnum) index) { case INDEX_ACTIVE: { item = tree->activeItem; break; } case INDEX_ALL: { if (qualArgsTotal) { hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); if (Qualifies(&q, item)) { TreeItemList_Append(items, (TreeItem) item); } hPtr = Tcl_NextHashEntry(&search); } item = NULL; } else if (flags & IFO_LIST_ALL) { hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); TreeItemList_Append(items, item); hPtr = Tcl_NextHashEntry(&search); } item = NULL; } else { item = ITEM_ALL; } break; } case INDEX_ANCHOR: { item = tree->anchorItem; break; } case INDEX_FIRST: { item = tree->root; while (!Qualifies(&q, item)) item = TreeItem_Next(tree, item); break; } case INDEX_END: case INDEX_LAST: { item = tree->root; while (item->lastChild) { item = item->lastChild; } while (!Qualifies(&q, item)) item = TreeItem_Prev(tree, item); break; } case INDEX_LIST: { int listObjc; Tcl_Obj **listObjv; int count; if (Tcl_ListObjGetElements(interp, objv[listIndex + 1], &listObjc, &listObjv) != TCL_OK) { goto errorExit; } for (i = 0; i < listObjc; i++) { TreeItemList item2s; if (TreeItemList_FromObj(tree, listObjv[i], &item2s, flags) != TCL_OK) goto errorExit; TreeItemList_Concat(items, &item2s); TreeItemList_Free(&item2s); } /* If any of the item descriptions in the list is "all", then * clear the list of items and use "all". */ count = TreeItemList_Count(items); for (i = 0; i < count; i++) { TreeItem item2 = TreeItemList_Nth(items, i); if (IS_ALL(item2)) break; } if (i < count) { TreeItemList_Free(items); item = ITEM_ALL; } else item = NULL; break; } case INDEX_NEAREST: { int x, y; if (Tk_GetPixelsFromObj(interp, tree->tkwin, objv[listIndex + 1], &x) != TCL_OK) { goto errorExit; } if (Tk_GetPixelsFromObj(interp, tree->tkwin, objv[listIndex + 2], &y) != TCL_OK) { goto errorExit; } item = Tree_ItemUnderPoint(tree, &x, &y, TRUE); break; } case INDEX_RANGE: { TreeItem itemFirst, itemLast; if (TreeItem_FromObj(tree, objv[listIndex + 1], &itemFirst, IFO_NOT_NULL) != TCL_OK) goto errorExit; if (TreeItem_FromObj(tree, objv[listIndex + 2], &itemLast, IFO_NOT_NULL) != TCL_OK) goto errorExit; if (TreeItem_FirstAndLast(tree, &itemFirst, &itemLast) == 0) goto errorExit; while (1) { if (Qualifies(&q, itemFirst)) { TreeItemList_Append(items, itemFirst); } if (itemFirst == itemLast) break; itemFirst = TreeItem_Next(tree, itemFirst); } item = NULL; break; } case INDEX_RNC: { int row, col; if (Tcl_GetIntFromObj(interp, objv[listIndex + 1], &row) != TCL_OK) goto errorExit; if (Tcl_GetIntFromObj(interp, objv[listIndex + 2], &col) != TCL_OK) goto errorExit; item = Tree_RNCToItem(tree, row, col); break; } case INDEX_ROOT: { item = tree->root; break; } } listIndex += indexArgs[index] + qualArgsTotal; /* No indexName[] was found. */ } else { int gotId = FALSE; TagExpr expr; /* Try an itemPrefix + item ID. */ if (tree->itemPrefixLen) { char *end, *t = Tcl_GetString(elemPtr); if (strncmp(t, tree->itemPrefix, tree->itemPrefixLen) == 0) { t += tree->itemPrefixLen; id = strtoul(t, &end, 10); if ((end != t) && (*end == '\0')) gotId = TRUE; } /* Try an item ID. */ } else if (Tcl_GetIntFromObj(NULL, elemPtr, &id) == TCL_OK) { gotId = TRUE; } if (gotId) { hPtr = Tcl_FindHashEntry(&tree->itemHash, (char *) id); if (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); } else { item = NULL; } listIndex++; goto gotFirstPart; } /* Try a list of qualifiers. This has the same effect as * "all QUALIFIERS". */ if (Qualifiers_Scan(&q, objc, objv, listIndex, &qualArgsTotal) != TCL_OK) { goto errorExit; } if (qualArgsTotal) { hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); if (Qualifies(&q, item)) { TreeItemList_Append(items, item); } hPtr = Tcl_NextHashEntry(&search); } item = NULL; listIndex += qualArgsTotal; goto gotFirstPart; } /* Try a tag or tag expression followed by qualifiers. */ if (objc > 1) { if (Qualifiers_Scan(&q, objc, objv, listIndex + 1, &qualArgsTotal) != TCL_OK) { goto errorExit; } } if (tree->itemTagExpr) { if (TagExpr_Init(tree, elemPtr, &expr) != TCL_OK) goto errorExit; hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); if (TagExpr_Eval(&expr, item->tagInfo) && Qualifies(&q, item)) { TreeItemList_Append(items, item); } hPtr = Tcl_NextHashEntry(&search); } TagExpr_Free(&expr); } else { Tk_Uid tag = Tk_GetUid(Tcl_GetString(elemPtr)); hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); if (ItemHasTag(item, tag) && Qualifies(&q, item)) { TreeItemList_Append(items, item); } hPtr = Tcl_NextHashEntry(&search); } } item = NULL; listIndex += 1 + qualArgsTotal; } gotFirstPart: /* If 1 item, use it and clear the list. */ if (TreeItemList_Count(items) == 1) { item = TreeItemList_Nth(items, 0); items->count = 0; } /* If "all" but only root exists, use it. */ if (IS_ALL(item) && (tree->itemCount == 1) && !(flags & IFO_NOT_ROOT)) { item = tree->root; } /* If > 1 item, no modifiers may follow. */ if ((TreeItemList_Count(items) > 1) || IS_ALL(item)) { if (listIndex < objc) { Tcl_AppendResult(interp, "unexpected arguments after \"", (char *) NULL); for (i = 0; i < listIndex; i++) { Tcl_AppendResult(interp, Tcl_GetString(objv[i]), (char *) NULL); if (i != listIndex - 1) Tcl_AppendResult(interp, " ", (char *) NULL); } Tcl_AppendResult(interp, "\"", (char *) NULL); goto errorExit; } } /* This means a valid specification was given, but there is no such item */ if ((TreeItemList_Count(items) == 0) && (item == NULL)) { if (flags & IFO_NOT_NULL) goto noitem; /* Empty list returned */ goto goodExit; } /* Process any modifiers following the item we matched above. */ for (; listIndex < objc; /* nothing */) { elemPtr = objv[listIndex]; if (Tcl_GetIndexFromObj(interp, elemPtr, modifiers, "modifier", 0, &index) != TCL_OK) { goto errorExit; } if (objc - listIndex < modArgs[index]) { Tcl_AppendResult(interp, "missing arguments to \"", Tcl_GetString(elemPtr), "\" modifier", NULL); goto errorExit; } qualArgsTotal = 0; if (modQual[index]) { Qualifiers_Free(&q); Qualifiers_Init(tree, &q); if (Qualifiers_Scan(&q, objc, objv, listIndex + modArgs[index], &qualArgsTotal) != TCL_OK) { goto errorExit; } } switch ((enum modEnum) index) { case TMOD_ABOVE: { item = Tree_ItemAbove(tree, item); break; } case TMOD_ANCESTORS: { item = item->parent; while (item != NULL) { if (Qualifies(&q, item)) { TreeItemList_Append(items, item); } item = item->parent; } item = NULL; break; } case TMOD_BELOW: { item = Tree_ItemBelow(tree, item); break; } case TMOD_BOTTOM: { item = Tree_ItemBottom(tree, item); break; } case TMOD_CHILD: { int n, endRelative; if (Tree_GetIntForIndex(tree, objv[listIndex + 1], &n, &endRelative) != TCL_OK) { goto errorExit; } if (endRelative) { item = item->lastChild; while (item != NULL) { if (Qualifies(&q, item)) if (n-- <= 0) break; item = item->prevSibling; } } else { item = item->firstChild; while (item != NULL) { if (Qualifies(&q, item)) if (n-- <= 0) break; item = item->nextSibling; } } break; } case TMOD_CHILDREN: { item = item->firstChild; while (item != NULL) { if (Qualifies(&q, item)) { TreeItemList_Append(items, item); } item = item->nextSibling; } item = NULL; break; } case TMOD_DESCENDANTS: { TreeItem last = item; while (last->lastChild != NULL) last = last->lastChild; item = item->firstChild; while (item != NULL) { if (Qualifies(&q, item)) { TreeItemList_Append(items, item); } if (item == last) break; item = TreeItem_Next(tree, item); } item = NULL; break; } case TMOD_FIRSTCHILD: { item = item->firstChild; while (!Qualifies(&q, item)) item = item->nextSibling; break; } case TMOD_LASTCHILD: { item = item->lastChild; while (!Qualifies(&q, item)) item = item->prevSibling; break; } case TMOD_LEFT: { item = Tree_ItemLeft(tree, item); break; } case TMOD_LEFTMOST: { item = Tree_ItemLeftMost(tree, item); break; } case TMOD_NEXT: { item = TreeItem_Next(tree, item); while (!Qualifies(&q, item)) item = TreeItem_Next(tree, item); break; } case TMOD_NEXTSIBLING: { item = item->nextSibling; while (!Qualifies(&q, item)) item = item->nextSibling; break; } case TMOD_PARENT: { item = item->parent; break; } case TMOD_PREV: { item = TreeItem_Prev(tree, item); while (!Qualifies(&q, item)) item = TreeItem_Prev(tree, item); break; } case TMOD_PREVSIBLING: { item = item->prevSibling; while (!Qualifies(&q, item)) item = item->prevSibling; break; } case TMOD_RIGHT: { item = Tree_ItemRight(tree, item); break; } case TMOD_RIGHTMOST: { item = Tree_ItemRightMost(tree, item); break; } case TMOD_SIBLING: { int n, endRelative; if (Tree_GetIntForIndex(tree, objv[listIndex + 1], &n, &endRelative) != TCL_OK) { goto errorExit; } item = item->parent; if (item == NULL) break; if (endRelative) { item = item->lastChild; while (item != NULL) { if (Qualifies(&q, item)) if (n-- <= 0) break; item = item->prevSibling; } } else { item = item->firstChild; while (item != NULL) { if (Qualifies(&q, item)) if (n-- <= 0) break; item = item->nextSibling; } } break; } case TMOD_TOP: { item = Tree_ItemTop(tree, item); break; } } if ((TreeItemList_Count(items) > 1) || IS_ALL(item)) { int end = listIndex + modArgs[index] + qualArgsTotal; if (end < objc) { Tcl_AppendResult(interp, "unexpected arguments after \"", (char *) NULL); for (i = 0; i < end; i++) { Tcl_AppendResult(interp, Tcl_GetString(objv[i]), (char *) NULL); if (i != end - 1) Tcl_AppendResult(interp, " ", (char *) NULL); } Tcl_AppendResult(interp, "\"", (char *) NULL); goto errorExit; } } if ((TreeItemList_Count(items) == 0) && (item == NULL)) { if (flags & IFO_NOT_NULL) goto noitem; /* Empty list returned. */ goto goodExit; } listIndex += modArgs[index] + qualArgsTotal; } if ((flags & IFO_NOT_MANY) && (IS_ALL(item) || (TreeItemList_Count(items) > 1))) { FormatResult(interp, "can't specify > 1 item for this command"); goto errorExit; } if (TreeItemList_Count(items)) { if (flags & (IFO_NOT_ROOT | IFO_NOT_ORPHAN)) { int i; for (i = 0; i < TreeItemList_Count(items); i++) { item = TreeItemList_Nth(items, i); if (IS_ROOT(item) && (flags & IFO_NOT_ROOT)) goto notRoot; if ((item->parent == NULL) && (flags & IFO_NOT_ORPHAN)) goto notOrphan; } } } else if (IS_ALL(item)) { TreeItemList_Append(items, ITEM_ALL); } else { if (IS_ROOT(item) && (flags & IFO_NOT_ROOT)) { notRoot: FormatResult(interp, "can't specify \"root\" for this command"); goto errorExit; } if ((item->parent == NULL) && (flags & IFO_NOT_ORPHAN)) { notOrphan: FormatResult(interp, "item \"%s\" has no parent", Tcl_GetString(objPtr)); goto errorExit; } TreeItemList_Append(items, item); } goodExit: Qualifiers_Free(&q); return TCL_OK; baditem: Tcl_AppendResult(interp, "bad item description \"", Tcl_GetString(objPtr), "\"", NULL); goto errorExit; noitem: Tcl_AppendResult(interp, "item \"", Tcl_GetString(objPtr), "\" doesn't exist", NULL); errorExit: Qualifiers_Free(&q); TreeItemList_Free(items); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TreeItem_FromObj -- * * Parse a Tcl_Obj item description to get a single item. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *objPtr, /* Object to parse to an item. */ TreeItem *itemPtr, /* Returned item. */ int flags /* IFO_xxx flags */ ) { TreeItemList items; if (TreeItemList_FromObj(tree, objPtr, &items, flags | IFO_NOT_MANY) != TCL_OK) return TCL_ERROR; /* May be NULL. */ (*itemPtr) = TreeItemList_Nth(&items, 0); TreeItemList_Free(&items); return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeItemForEach_Start -- * * Begin iterating over items. A command might accept two item * descriptions for a range of items, or a single item description * which may itself refer to multiple items. Either item * description could be ITEM_ALL. * * Results: * Returns the first item to iterate over. If an error occurs * then ItemForEach.error is set to 1. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItemForEach_Start( TreeItemList *items, /* List of items. */ TreeItemList *item2s, /* List of items or NULL. */ ItemForEach *iter /* Returned info, pass to TreeItemForEach_Next. */ ) { TreeCtrl *tree = items->tree; TreeItem item, item2 = NULL; item = TreeItemList_Nth(items, 0); if (item2s) item2 = TreeItemList_Nth(item2s, 0); iter->tree = tree; iter->all = FALSE; iter->error = 0; iter->items = NULL; if (IS_ALL(item) || IS_ALL(item2)) { Tcl_HashEntry *hPtr = Tcl_FirstHashEntry(&tree->itemHash, &iter->search); iter->all = TRUE; return iter->item = (TreeItem) Tcl_GetHashValue(hPtr); } if (item2 != NULL) { if (TreeItem_FirstAndLast(tree, &item, &item2) == 0) { iter->error = 1; return NULL; } iter->last = item2; return iter->item = item; } iter->items = items; iter->index = 0; return iter->item = item; } /* *---------------------------------------------------------------------- * * TreeItemForEach_Next -- * * Returns the next item to iterate over. Keep calling this until * the result is NULL. * * Results: * Returns the next item to iterate over or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItemForEach_Next( ItemForEach *iter /* Initialized by TreeItemForEach_Start. */ ) { TreeCtrl *tree = iter->tree; if (iter->all) { Tcl_HashEntry *hPtr = Tcl_NextHashEntry(&iter->search); if (hPtr == NULL) return iter->item = NULL; return iter->item = (TreeItem) Tcl_GetHashValue(hPtr); } if (iter->items != NULL) { if (iter->index >= TreeItemList_Count(iter->items)) return iter->item = NULL; return iter->item = TreeItemList_Nth(iter->items, ++iter->index); } if (iter->item == iter->last) return iter->item = NULL; return iter->item = TreeItem_Next(tree, iter->item); } /* *---------------------------------------------------------------------- * * Item_ToggleOpen -- * * Inverts the STATE_OPEN flag of an Item. * * Results: * Items may be displayed/undisplayed. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void Item_ToggleOpen( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item record. */ int stateOff, /* STATE_OPEN or 0 */ int stateOn /* STATE_OPEN or 0 */ ) { int mask; mask = TreeItem_ChangeState(tree, item, stateOff, stateOn); if (IS_ROOT(item) && !tree->showRoot) return; #if 0 /* Don't affect display if we weren't visible */ if (!TreeItem_ReallyVisible(tree, item)) return; /* Invalidate display info for this item, so it is redrawn later. */ Tree_InvalidateItemDInfo(tree, item, NULL); #endif if (item->numChildren > 0) { /* indexVis needs updating for all items after this one, if we * have any visible children */ tree->updateIndex = 1; Tree_DInfoChanged(tree, DINFO_REDO_RANGES); /* Hiding/showing children may change the width of any column */ Tree_InvalidateColumnWidth(tree, NULL); } /* If this item was previously onscreen, this call is repetitive. */ Tree_EventuallyRedraw(tree); } /* *---------------------------------------------------------------------- * * TreeItem_OpenClose -- * * Inverts the STATE_OPEN flag of an Item. * * Results: * Items may be displayed/undisplayed. * * Side effects: * Display changes. and events may be * generated. * *---------------------------------------------------------------------- */ void TreeItem_OpenClose( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int mode /* -1: toggle * 0: close * 1: open */ ) { int stateOff = 0, stateOn = 0; /* When processing a list of items, any or event * may result in items being deleted. */ if (IS_DELETED(item)) return; if (mode == -1) { if (item->state & STATE_OPEN) stateOff = STATE_OPEN; else stateOn = STATE_OPEN; } else if (!mode && (item->state & STATE_OPEN)) stateOff = STATE_OPEN; else if (mode && !(item->state & STATE_OPEN)) stateOn = STATE_OPEN; if (stateOff != stateOn) { TreeNotify_OpenClose(tree, item, stateOn, TRUE); if (IS_DELETED(item)) return; Item_ToggleOpen(tree, item, stateOff, stateOn); TreeNotify_OpenClose(tree, item, stateOn, FALSE); } } /* *---------------------------------------------------------------------- * * TreeItem_Delete -- * * Recursively frees resources associated with an Item and its * descendants. * * Results: * Items are removed from their parent and freed. * * Side effects: * Memory is freed. If the active item or selection-anchor item * is deleted, the root becomes the active/anchor item. * Display changes may occur. * *---------------------------------------------------------------------- */ void TreeItem_Delete( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { if (TreeItem_ReallyVisible(tree, item)) Tree_InvalidateColumnWidth(tree, NULL); while (item->numChildren > 0) TreeItem_Delete(tree, item->firstChild); TreeItem_RemoveFromParent(tree, item); TreeDisplay_ItemDeleted(tree, item); Tree_RemoveItem(tree, item); TreeItem_FreeResources(tree, item); if (tree->activeItem == item) { tree->activeItem = tree->root; TreeItem_ChangeState(tree, tree->activeItem, 0, STATE_ACTIVE); } if (tree->anchorItem == item) tree->anchorItem = tree->root; if (tree->debug.enable && tree->debug.data) Tree_Debug(tree); } /* *---------------------------------------------------------------------- * * TreeItem_Deleted -- * * Return 1 if the given item is deleted. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_Deleted( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { return IS_DELETED(item); } /* *---------------------------------------------------------------------- * * TreeItem_FirstAndLast -- * * Determine the order of two items and swap them if needed. * * Results: * If the items do not share a common ancestor, 0 is returned and * an error message is left in the interpreter result. * Otherwise the return value is the number of items in the * range between first and last. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_FirstAndLast( TreeCtrl *tree, /* Widget info. */ TreeItem *first, /* Item token. */ TreeItem *last /* Item token. */ ) { int indexFirst, indexLast, index; if (TreeItem_RootAncestor(tree, *first) != TreeItem_RootAncestor(tree, *last)) { FormatResult(tree->interp, "item %s%d and item %s%d don't share a common ancestor", tree->itemPrefix, TreeItem_GetID(tree, *first), tree->itemPrefix, TreeItem_GetID(tree, *last)); return 0; } TreeItem_ToIndex(tree, *first, &indexFirst, NULL); TreeItem_ToIndex(tree, *last, &indexLast, NULL); if (indexFirst > indexLast) { TreeItem item = *first; *first = *last; *last = item; index = indexFirst; indexFirst = indexLast; indexLast = index; } return indexLast - indexFirst + 1; } /* *---------------------------------------------------------------------- * * TreeItem_ListDescendants -- * * Appends descendants of an item to a list of items. * * Results: * List of items may grow. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_ListDescendants( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeItemList *items /* List of items to append descendants to. */ ) { TreeItem last; if (item->firstChild == NULL) return; last = item; while (last->lastChild != NULL) last = last->lastChild; item = item->firstChild; while (1) { TreeItemList_Append(items, item); if (item == last) break; item = TreeItem_Next(tree, item); } } /* *---------------------------------------------------------------------- * * TreeItem_UpdateDepth -- * * Recursively updates Item.depth of an Item and its * descendants. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_UpdateDepth( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeItem child; if (IS_ROOT(item)) return; if (item->parent != NULL) item->depth = item->parent->depth + 1; else item->depth = 0; child = item->firstChild; while (child != NULL) { TreeItem_UpdateDepth(tree, child); child = child->nextSibling; } } /* *---------------------------------------------------------------------- * * TreeItem_AddToParent -- * * Called *after* an Item is added as a child to another Item. * * Results: * None. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ void TreeItem_AddToParent( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeItem last, parent = item->parent; /* If this is the new last child, redraw the lines of the previous * sibling and all of its descendants so the line from the previous * sibling reaches this item */ if ((item->prevSibling != NULL) && (item->nextSibling == NULL) && tree->showLines && (tree->columnTree != NULL)) { last = item->prevSibling; while (last->lastChild != NULL) last = last->lastChild; Tree_InvalidateItemDInfo(tree, tree->columnTree, item->prevSibling, last); } /* Redraw the parent if the parent has "-button auto". */ if (IS_VISIBLE(item) && (parent->flags & ITEM_FLAG_BUTTON_AUTO) && tree->showButtons && (tree->columnTree != NULL)) { Tree_InvalidateItemDInfo(tree, tree->columnTree, parent, NULL); } tree->updateIndex = 1; Tree_DInfoChanged(tree, DINFO_REDO_RANGES); /* Tree_UpdateItemIndex() also recalcs depth, but in one of my demos * I retrieve item depth during list creation. Since Tree_UpdateItemIndex() * is slow I will keep depth up-to-date here. */ TreeItem_UpdateDepth(tree, item); Tree_InvalidateColumnWidth(tree, NULL); if (tree->debug.enable && tree->debug.data) Tree_Debug(tree); } /* *---------------------------------------------------------------------- * * RemoveFromParentAux -- * * Recursively update Item.depth, Item.index and Item.indexVis. * * Results: * None. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void RemoveFromParentAux( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item being removed. */ int *index /* New value of Item.index. Is incremented. */ ) { TreeItem child; /* Invalidate display info. Don't free it because we may just be * moving the item to a new parent. FIXME: if it is being moved, * it might not actually need to be redrawn (just copied) */ if (item->dInfo != NULL) Tree_InvalidateItemDInfo(tree, NULL, item, NULL); if (item->parent != NULL) item->depth = item->parent->depth + 1; else item->depth = 0; item->index = (*index)++; item->indexVis = -1; child = item->firstChild; while (child != NULL) { RemoveFromParentAux(tree, child, index); child = child->nextSibling; } } /* *---------------------------------------------------------------------- * * TreeItem_RemoveFromParent -- * * Remove an Item from its parent (if any). * * Results: * None. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ void TreeItem_RemoveFromParent( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeItem parent = item->parent; TreeItem last; int index = 0; if (parent == NULL) return; /* If this is the last child, redraw the lines of the previous * sibling and all of its descendants because the line from * the previous sibling to us is now gone */ if ((item->prevSibling != NULL) && (item->nextSibling == NULL) && tree->showLines && (tree->columnTree != NULL)) { last = item->prevSibling; while (last->lastChild != NULL) last = last->lastChild; Tree_InvalidateItemDInfo(tree, tree->columnTree, item->prevSibling, last); } /* Redraw the parent if the parent has "-button auto". */ if (IS_VISIBLE(item) && (parent->flags & ITEM_FLAG_BUTTON_AUTO) && tree->showButtons && (tree->columnTree != NULL)) { Tree_InvalidateItemDInfo(tree, tree->columnTree, parent, NULL); } /* * Set a flag indicating that item indexes are out-of-date. This doesn't * cover the current item being removed. */ tree->updateIndex = 1; Tree_DInfoChanged(tree, DINFO_REDO_RANGES); if (item->prevSibling) item->prevSibling->nextSibling = item->nextSibling; if (item->nextSibling) item->nextSibling->prevSibling = item->prevSibling; if (parent->firstChild == item) { parent->firstChild = item->nextSibling; if (!parent->firstChild) parent->lastChild = NULL; } if (parent->lastChild == item) parent->lastChild = item->prevSibling; item->prevSibling = item->nextSibling = NULL; item->parent = NULL; parent->numChildren--; /* * Update Item.depth, Item.index and Item.indexVis for the item and its * descendants. An up-to-date Item.index is needed for some operations that * use a range of items, such as [item delete]. */ RemoveFromParentAux(tree, item, &index); } /* *---------------------------------------------------------------------- * * TreeItem_RemoveColumns -- * * Free a range of Columns in an Item. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeItem_RemoveColumns( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int first, /* 0-based column index at start of * the range. Must be <= last */ int last /* 0-based column index at end of * the range. Must be >= first */ ) { Column *column = item->columns; Column *prev = NULL, *next = NULL; int i = 0; while (column != NULL) { next = column->next; if (i == first - 1) prev = column; else if (i >= first) Column_FreeResources(tree, column); if (i == last) break; ++i; column = next; } if (prev != NULL) prev->next = next; else item->columns = next; } /* *---------------------------------------------------------------------- * * TreeItem_RemoveAllColumns -- * * Free all the Columns in an Item. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeItem_RemoveAllColumns( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { Column *column = item->columns; while (column != NULL) { Column *next = column->next; Column_FreeResources(tree, column); column = next; } item->columns = NULL; } /* *---------------------------------------------------------------------- * * Item_CreateColumn -- * * Allocate a Column record for an Item if it doesn't already * exist. * * Results: * Pointer to new or existing Column record. * * Side effects: * Any column records preceding the desired one are allocated * if they weren't already. Memory is allocated. * *---------------------------------------------------------------------- */ static Column * Item_CreateColumn( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item to contain the column. */ int columnIndex, /* 0-based index of new column. */ int *isNew /* May be NULL. Set to TRUE if the * column record was created. */ ) { Column *column; int i; if (isNew != NULL) (*isNew) = FALSE; column = item->columns; if (column == NULL) { column = Column_Alloc(tree); item->columns = column; if (isNew != NULL) (*isNew) = TRUE; } for (i = 0; i < columnIndex; i++) { if (column->next == NULL) { column->next = Column_Alloc(tree); if (isNew != NULL) (*isNew) = TRUE; } column = column->next; } return column; } /* *---------------------------------------------------------------------- * * TreeItem_MoveColumn -- * * Rearranges an Item's list of Column records by moving one * in front of another. * * Results: * If the Column to be moved does not exist and the Column to place it * in front of does not exist, then nothing happens. If the Column is * to be moved past all currently allocated Columns, then new * Column records are allocated. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ void TreeItem_MoveColumn( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int columnIndex, /* 0-based index of the column to move. */ int beforeIndex /* 0-based index of the second column to move * the first column to the left of. */ ) { Column *before = NULL, *move = NULL; Column *prevM = NULL, *prevB = NULL; Column *last = NULL, *prev, *walk; int index = 0; prev = NULL; walk = item->columns; while (walk != NULL) { if (index == columnIndex) { prevM = prev; move = walk; } if (index == beforeIndex) { prevB = prev; before = walk; } prev = walk; if (walk->next == NULL) last = walk; index++; walk = walk->next; } if (move == NULL && before == NULL) return; if (move == NULL) move = Column_Alloc(tree); else { if (before == NULL) { prevB = Item_CreateColumn(tree, item, beforeIndex - 1, NULL); last = prevB; } if (prevM == NULL) item->columns = move->next; else prevM->next = move->next; } if (before == NULL) { last->next = move; move->next = NULL; } else { if (prevB == NULL) item->columns = move; else prevB->next = move; move->next = before; } } /* *---------------------------------------------------------------------- * * TreeItem_FreeResources -- * * Free memory etc assocated with an Item. * * Results: * None. * * Side effects: * Memory is deallocated. Display changes. * *---------------------------------------------------------------------- */ void TreeItem_FreeResources( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { Column *column; column = item->columns; while (column != NULL) column = Column_FreeResources(tree, column); if (item->dInfo != NULL) Tree_FreeItemDInfo(tree, item, NULL); if (item->rInfo != NULL) Tree_FreeItemRInfo(tree, item); if (item->spans != NULL) ckfree((char *) item->spans); Tk_FreeConfigOptions((char *) item, tree->itemOptionTable, tree->tkwin); /* Add the item record to the "preserved" list. It will be freed later. */ TreeItemList_Append(&tree->preserveItemList, item); } /* *---------------------------------------------------------------------- * * TreeItem_Release -- * * Finally free an item record when it is no longer needed. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeItem_Release( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, ItemUid, (char *) item, sizeof(TreeItem_)); #else WFREE(item, TreeItem_); #endif } /* *---------------------------------------------------------------------- * * Item_UseHeight -- * * Return the height used by styles in an Item. * * Results: * Maximum height in pixels of the style in each visible Column. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Item_HeightOfStyles( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item record. */ ) { Column *column = item->columns; TreeColumn treeColumn = tree->columns; StyleDrawArgs drawArgs; int height = 0; drawArgs.tree = tree; while (column != NULL) { if (TreeColumn_Visible(treeColumn) && (column->style != NULL)) { drawArgs.state = item->state | column->cstate; drawArgs.style = column->style; drawArgs.indent = (treeColumn == tree->columnTree) ? TreeItem_Indent(tree, item) : 0; if ((TreeColumn_FixedWidth(treeColumn) != -1) || TreeColumn_Squeeze(treeColumn)) { drawArgs.width = TreeColumn_UseWidth(treeColumn); } else drawArgs.width = -1; height = MAX(height, TreeStyle_UseHeight(&drawArgs)); } treeColumn = TreeColumn_Next(treeColumn); column = column->next; } return height; } /* *---------------------------------------------------------------------- * * TreeItem_Height -- * * Return the height of an Item. * * Results: * If the Item -height option is > 0, the result is the maximum * of the button height (if a button is displayed) and the -height * option. * If the TreeCtrl -itemheight option is > 0, the result is the maximum * of the button height (if a button is displayed) and the -itemheight * option. * Otherwise the result is the maximum of the button height (if a button * is displayed) AND the TreeCtrl -minitemheight AND the height of * the style in each visible Column. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_Height( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { int buttonHeight = 0; int useHeight; if (!IS_VISIBLE(item) || (IS_ROOT(item) && !tree->showRoot)) return 0; /* Get requested height of the style in each column */ useHeight = Item_HeightOfStyles(tree, item); /* Can't have less height than our button */ if (TreeItem_HasButton(tree, item)) { buttonHeight = Tree_ButtonHeight(tree, item->state); } /* User specified a fixed height for this item */ if (item->fixedHeight > 0) return MAX(item->fixedHeight, buttonHeight); /* Fixed height of all items */ if (tree->itemHeight > 0) return MAX(tree->itemHeight, buttonHeight); /* Minimum height of all items */ if (tree->minItemHeight > 0) useHeight = MAX(useHeight, tree->minItemHeight); /* No fixed height specified */ return MAX(useHeight, buttonHeight); } /* *---------------------------------------------------------------------- * * TreeItem_InvalidateHeight -- * * Marks Item.neededHeight out-of-date. * NOTE: Item.neededHeight is unused. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_InvalidateHeight( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { } /* *---------------------------------------------------------------------- * * Item_FindColumn -- * * Return a Column record given a zero-based index. * * Results: * The Column record or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Column * Item_FindColumn( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item record. */ int columnIndex /* 0-based index of column to find. */ ) { Column *column; int i = 0; column = item->columns; if (!column) return NULL; while (column != NULL && i < columnIndex) { column = column->next; i++; } return column; } /* *---------------------------------------------------------------------- * * Item_FindColumnFromObj -- * * Return a Column record given a Tcl_Obj column description. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Item_FindColumnFromObj( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item record. */ Tcl_Obj *obj, /* Column description. */ Column **columnPtr, /* Returned column, or NULL. */ int *indexPtr /* May be NULL. Returned 0-based index of * the column. */ ) { TreeColumn treeColumn; int columnIndex; if (TreeColumn_FromObj(tree, obj, &treeColumn, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) return TCL_ERROR; columnIndex = TreeColumn_Index(treeColumn); (*columnPtr) = Item_FindColumn(tree, item, columnIndex); if (indexPtr != NULL) (*indexPtr) = columnIndex; return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeItem_FindColumn -- * * Return an item-column token given a zero-based index. * * Results: * The item-column token or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItemColumn TreeItem_FindColumn( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int columnIndex /* 0-based index of column to find. */ ) { return (TreeItemColumn) Item_FindColumn(tree, item, columnIndex); } /* *---------------------------------------------------------------------- * * TreeItem_ColumnFromObj -- * * Return an item-column token given a Tcl_Obj column description. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_ColumnFromObj( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ Tcl_Obj *obj, /* Column description. */ TreeItemColumn *columnPtr, /* Returned column, or NULL. */ int *indexPtr /* May be NULL. Returned 0-based index of * the column. */ ) { return Item_FindColumnFromObj(tree, item, obj, (Column **) columnPtr, indexPtr); } #if 0 /* *---------------------------------------------------------------------- * * Item_CreateColumnFromObj -- * * Return a Column record given a Tcl_Obj column description. * The Column record is allocated if it doesn't exist. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static int Item_CreateColumnFromObj( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item record. */ Tcl_Obj *obj, /* Column description. */ Column **column, /* Returned column. */ int *indexPtr, /* May be NULL. Returned 0-based index of * the column. */ int *isNew /* May be NULL. Set to TRUE if the * column record was created. */ ) { TreeColumn treeColumn; int columnIndex; if (TreeColumn_FromObj(tree, obj, &treeColumn, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) return TCL_ERROR; columnIndex = TreeColumn_Index(treeColumn); (*column) = Item_CreateColumn(tree, item, columnIndex, isNew); if (indexPtr != NULL) (*indexPtr) = columnIndex; return TCL_OK; } #endif /* *---------------------------------------------------------------------- * * TreeItem_Indent -- * * Return the amount of indentation for the given item. This is * the width of the buttons/lines. * * Results: * Pixel value >= 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_Indent( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { int depth; if (IS_ROOT(item)) return (tree->showRoot && tree->showButtons && tree->showRootButton) ? tree->useIndent : 0; Tree_UpdateItemIndex(tree); depth = item->depth; if (tree->showRoot) { depth += 1; if (tree->showButtons && tree->showRootButton) depth += 1; } else if (tree->showButtons && tree->showRootChildButtons) depth += 1; else if (tree->showLines && tree->showRootLines) depth += 1; return tree->useIndent * depth; } /* *---------------------------------------------------------------------- * * ItemDrawBackground -- * * Draws part of the background area of an Item. The area is * erased to the -itembackground color of the tree column or the * TreeCtrl -background color. If the TreeCtrl -backgroundimage * option is specified then that image is tiled over the given area. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ static void ItemDrawBackground( TreeCtrl *tree, /* Widget info. */ TreeColumn treeColumn, /* Tree-column token. */ TreeItem item, /* Item record. */ Column *column, /* First column. */ TreeDrawable drawable, /* Where to draw. */ int x, int y, /* Area of the item to draw. */ int width, int height, /* ^ */ int index /* Used to select a color from the * tree-column's -itembackground option. */ ) { GC gc = None; gc = TreeColumn_BackgroundGC(treeColumn, index); if (gc == None) gc = Tk_3DBorderGC(tree->tkwin, tree->border, TK_3D_FLAT_GC); /* * FIXME: If the background image is non-transparent, there is no * need to erase first. */ XFillRectangle(tree->display, drawable.drawable, gc, x, y, width, height); if (tree->backgroundImage != NULL) { Tree_DrawTiledImage(tree, drawable.drawable, tree->backgroundImage, x, y, x + width, y + height, tree->drawableXOrigin, tree->drawableYOrigin); } } /* *---------------------------------------------------------------------- * * TreeItem_SpansInvalidate -- * * Invalidates the Item.spans field of one or all items. * * Results: * The item(s) are removed from the TreeCtrl.itemSpansHash to * indicate that the list of spans must be recalculated. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_SpansInvalidate( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. NULL for all items. */ ) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; int count = 0; if (item == NULL) { hPtr = Tcl_FirstHashEntry(&tree->itemSpansHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&tree->itemSpansHash, hPtr); item->flags &= ~ITEM_FLAG_SPANS_VALID; count++; hPtr = Tcl_NextHashEntry(&search); } if (count) { Tcl_DeleteHashTable(&tree->itemSpansHash); Tcl_InitHashTable(&tree->itemSpansHash, TCL_ONE_WORD_KEYS); } } else if (item->flags & ITEM_FLAG_SPANS_VALID) { hPtr = Tcl_FindHashEntry(&tree->itemSpansHash, (char *) item); Tcl_DeleteHashEntry(hPtr); item->flags &= ~ITEM_FLAG_SPANS_VALID; count++; } if (count && tree->debug.enable && tree->debug.span) dbwin("TreeItem_SpansInvalidate forgot %d items\n", count); } /* *---------------------------------------------------------------------- * * TreeItem_SpansRedo -- * * Updates the Item.spans field of an item. * * Results: * Item.spans is resized if needed to (at least) the current number * of tree columns. For tree column N, the index of the item * column displayed there is written to spans[N]. * * The return value is 1 if every span is 1, otherwise 0. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ int TreeItem_SpansRedo( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeColumn treeColumn = tree->columns; Column *itemColumn = item->columns; int columnIndex = 0, spanner = 0, span = 1, simple = TRUE; int lock = TreeColumn_Lock(treeColumn); if (tree->debug.enable && tree->debug.span) dbwin("TreeItem_SpansRedo item %d\n", item->id); if (item->spans == NULL) { item->spans = (int *) ckalloc(sizeof(int) * tree->columnCount); item->spanAlloc = tree->columnCount; } else if (item->spanAlloc < tree->columnCount) { item->spans = (int *) ckrealloc((char *) item->spans, sizeof(int) * tree->columnCount); item->spanAlloc = tree->columnCount; } while (treeColumn != NULL) { /* End current span if column lock changes. */ if (TreeColumn_Lock(treeColumn) != lock) { lock = TreeColumn_Lock(treeColumn); span = 1; } if (--span == 0) { if (TreeColumn_Visible(treeColumn)) span = itemColumn ? itemColumn->span : 1; else span = 1; if (span > 1) simple = FALSE; spanner = columnIndex; } item->spans[columnIndex] = spanner; columnIndex++; treeColumn = TreeColumn_Next(treeColumn); if (itemColumn != NULL) itemColumn = itemColumn->next; } return simple; } /* *---------------------------------------------------------------------- * * TreeItem_SpansRedoIfNeeded -- * * Updates the Item.spans field of an item if needed. * * Results: * If all spans are known to be 1, nothing is done. If the list of * spans is marked valid, nothing is done. Otherwise the list of * spans is recalculated; if any span is > 1 the item is added * to TreeCtrl.itemSpansHash. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ void TreeItem_SpansRedoIfNeeded( TreeCtrl *tree, TreeItem item ) { /* All the spans are 1. */ if (item->flags & ITEM_FLAG_SPANS_SIMPLE) return; /* Some spans > 1, but we calculated them already. */ if (item->flags & ITEM_FLAG_SPANS_VALID) return; if (TreeItem_SpansRedo(tree, item)) { /* Reverted to all spans=1. */ item->flags |= ITEM_FLAG_SPANS_SIMPLE; } else { int isNew; Tcl_HashEntry *hPtr; hPtr = Tcl_CreateHashEntry(&tree->itemSpansHash, (char *) item, &isNew); Tcl_SetHashValue(hPtr, (ClientData) item); item->flags |= ITEM_FLAG_SPANS_VALID; } } /* *---------------------------------------------------------------------- * * TreeItem_GetSpans -- * * Returns the spans[] array for an item. * * Results: * If all spans are known to be 1, the result is NULL. Otherwise the * list of spans is returned. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ int * TreeItem_GetSpans( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeItem_SpansRedoIfNeeded(tree, item); if (item->flags & ITEM_FLAG_SPANS_SIMPLE) return NULL; return item->spans; } /* * The following structure holds information about which item column * is displayed at a given tree column. */ typedef struct SpanInfo { TreeColumn treeColumn; /* Always non-null. */ TreeItemColumn itemColumn; /* May be null. */ int span; /* Number of tree-columns spanned. */ int width; /* Width of the span. */ } SpanInfo; /* *---------------------------------------------------------------------- * * Item_GetSpans -- * * Fills an array of SpanInfo records, one per visible span. * * Results: * The return value is the number of SpanInfo records written. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Item_GetSpans( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeColumn firstColumn, /* Which columns. */ SpanInfo spans[] /* Returned span records. */ ) { TreeColumn treeColumn = firstColumn; int columnIndex = TreeColumn_Index(firstColumn); Column *column = Item_FindColumn(tree, item, columnIndex); int spanCount = 0, span = 1; SpanInfo *spanPtr = NULL; while (treeColumn != NULL) { if (TreeColumn_Lock(treeColumn) != TreeColumn_Lock(firstColumn)) break; if (--span == 0) { if (TreeColumn_Visible(treeColumn)) { span = column ? column->span : 1; if (spanPtr == NULL) spanPtr = spans; else spanPtr++; spanPtr->treeColumn = treeColumn; spanPtr->itemColumn = (TreeItemColumn) column; spanPtr->span = 0; spanPtr->width = 0; spanCount++; } else { span = 1; goto next; } } spanPtr->span++; spanPtr->width += TreeColumn_UseWidth(treeColumn); next: ++columnIndex; treeColumn = TreeColumn_Next(treeColumn); if (column != NULL) column = column->next; } return spanCount; } typedef int (*TreeItemWalkSpansProc)( TreeCtrl *tree, TreeItem item, SpanInfo *spanPtr, StyleDrawArgs *drawArgs, ClientData clientData ); /* *---------------------------------------------------------------------- * * TreeItem_WalkSpans -- * * Iterates over the spans of an item and calls a callback routine * for each span of non-zero width. This is used for drawing, * hit-testing and other purposes. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_WalkSpans( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int lock, /* Which columns. */ int x, int y, /* Drawable coordinates of the item. */ int width, int height, /* Total size of the item. */ TreeItemWalkSpansProc proc, /* Callback routine. */ ClientData clientData /* Data passed to callback routine. */ ) { int columnWidth, totalWidth; Column *itemColumn; StyleDrawArgs drawArgs; TreeColumn treeColumn = tree->columnLockNone; int spanCount, spanIndex, columnCount = tree->columnCountVis; SpanInfo staticSpans[STATIC_SIZE], *spans = staticSpans; int area = TREE_AREA_CONTENT; switch (lock) { case COLUMN_LOCK_LEFT: treeColumn = tree->columnLockLeft; columnCount = tree->columnCountVisLeft; area = TREE_AREA_LEFT; break; case COLUMN_LOCK_NONE: break; case COLUMN_LOCK_RIGHT: treeColumn = tree->columnLockRight; columnCount = tree->columnCountVisRight; area = TREE_AREA_RIGHT; break; } if (!Tree_AreaBbox(tree, area, &drawArgs.bounds[0], &drawArgs.bounds[1], &drawArgs.bounds[2], &drawArgs.bounds[3])) { drawArgs.bounds[0] = drawArgs.bounds[1] = drawArgs.bounds[2] = drawArgs.bounds[3] = 0; } STATIC_ALLOC(spans, SpanInfo, columnCount); spanCount = Item_GetSpans(tree, item, treeColumn, spans); drawArgs.tree = tree; drawArgs.td.drawable = None; totalWidth = 0; for (spanIndex = 0; spanIndex < spanCount; spanIndex++) { treeColumn = spans[spanIndex].treeColumn; itemColumn = (Column *) spans[spanIndex].itemColumn; /* If this is the single visible column, use the provided width which * may be different than the column's width. */ if ((tree->columnCountVis == 1) && (treeColumn == tree->columnVis)) { columnWidth = width; /* More than one column is visible, or this is not the visible * column. */ } else { columnWidth = spans[spanIndex].width; } if (columnWidth <= 0) continue; if (itemColumn != NULL) { drawArgs.state = item->state | itemColumn->cstate; drawArgs.style = itemColumn->style; /* may be NULL */ } else { drawArgs.state = item->state; drawArgs.style = NULL; } if (treeColumn == tree->columnTree) drawArgs.indent = TreeItem_Indent(tree, item); else drawArgs.indent = 0; drawArgs.x = x + totalWidth; drawArgs.y = y; drawArgs.width = columnWidth; drawArgs.height = height; drawArgs.justify = TreeColumn_ItemJustify(treeColumn); if ((*proc)(tree, item, &spans[spanIndex], &drawArgs, clientData)) break; totalWidth += columnWidth; } STATIC_FREE(spans, SpanInfo, columnCount); } /* *---------------------------------------------------------------------- * * SpanWalkProc_Draw -- * * Callback routine to TreeItem_WalkSpans for TreeItem_Draw. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ static int SpanWalkProc_Draw( TreeCtrl *tree, TreeItem item, SpanInfo *spanPtr, StyleDrawArgs *drawArgs, ClientData clientData ) { TreeColumn treeColumn = spanPtr->treeColumn; Column *itemColumn = (Column *) spanPtr->itemColumn; int i, x; struct { TreeDrawable td; int minX; int maxX; int index; } *data = clientData; /* Draw nothing if the entire span is out-of-bounds. */ if ((drawArgs->x >= data->maxX) || (drawArgs->x + drawArgs->width <= data->minX)) return 0; drawArgs->td = data->td; /* Draw background colors. */ if (spanPtr->span == 1) { /* Important point: use drawArgs->width since an item's width may * be totally different than tree->columnVis' width. */ ItemDrawBackground(tree, treeColumn, item, itemColumn, drawArgs->td, drawArgs->x, drawArgs->y, drawArgs->width, drawArgs->height, data->index); } else { x = drawArgs->x; for (i = 0; i < spanPtr->span; i++) { int columnWidth = TreeColumn_UseWidth(treeColumn); if ((columnWidth > 0) && (x < data->maxX) && (x + columnWidth > data->minX)) { ItemDrawBackground(tree, treeColumn, item, itemColumn, drawArgs->td, x, drawArgs->y, columnWidth, drawArgs->height, data->index); } x += columnWidth; treeColumn = TreeColumn_Next(treeColumn); } } if (drawArgs->style != NULL) { StyleDrawArgs drawArgsCopy = *drawArgs; TreeStyle_Draw(&drawArgsCopy); } if (spanPtr->treeColumn == tree->columnTree) { if (tree->showLines) TreeItem_DrawLines(tree, item, drawArgs->x, drawArgs->y, drawArgs->width, drawArgs->height, data->td); if (tree->showButtons) TreeItem_DrawButton(tree, item, drawArgs->x, drawArgs->y, drawArgs->width, drawArgs->height, data->td); } /* Stop walking if we went past the right edge of the dirty area. */ return drawArgs->x + drawArgs->width >= data->maxX; } /* *---------------------------------------------------------------------- * * TreeItem_Draw -- * * Draws part of an Item. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ void TreeItem_Draw( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int lock, /* Which columns. */ int x, int y, /* Drawable coordinates of the item. */ int width, int height, /* Total size of the item. */ TreeDrawable td, /* Where to draw. */ int minX, int maxX, /* Left/right edge that needs to be drawn. */ int index /* Used to select a color from a * tree-column's -itembackground option. */ ) { struct { TreeDrawable td; int minX; int maxX; int index; } clientData; clientData.td = td; clientData.minX = minX; clientData.maxX = maxX; clientData.index = index; TreeItem_WalkSpans(tree, item, lock, x, y, width, height, SpanWalkProc_Draw, (ClientData) &clientData); } /* *---------------------------------------------------------------------- * * TreeItem_DrawLines -- * * Draws horizontal and vertical lines indicating parent-child * relationship in an item. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ void TreeItem_DrawLines( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int x, int y, /* Drawable coordinates of columnTree. */ int width, int height, /* Total size of columnTree. */ TreeDrawable td /* Where to draw. */ ) { TreeItem parent, walk; int indent, left, lineLeft, lineTop; int hasPrev, hasNext; int i, vert = 0; indent = TreeItem_Indent(tree, item); /* Left edge of button/line area */ left = x /* + tree->columnTreeLeft */ + indent - tree->useIndent; /* Left edge of vertical line */ lineLeft = left + (tree->useIndent - tree->lineThickness) / 2; /* Top edge of horizontal line */ lineTop = y + (height - tree->lineThickness) / 2; /* NOTE: The next three checks do not call TreeItem_ReallyVisible() * since 'item' is ReallyVisible */ /* Check for ReallyVisible previous sibling */ walk = item->prevSibling; while ((walk != NULL) && !IS_VISIBLE(walk)) walk = walk->prevSibling; hasPrev = (walk != NULL); /* Check for ReallyVisible parent */ if ((item->parent != NULL) && (!IS_ROOT(item->parent) || tree->showRoot)) hasPrev = TRUE; /* Check for ReallyVisible next sibling */ walk = item->nextSibling; while ((walk != NULL) && !IS_VISIBLE(walk)) walk = walk->nextSibling; hasNext = (walk != NULL); /* Option: Don't connect children of root item */ if ((item->parent != NULL) && IS_ROOT(item->parent) && !tree->showRootLines) hasPrev = hasNext = FALSE; /* Vertical line to parent and/or previous/next sibling */ if (hasPrev || hasNext) { int top = y, bottom = y + height; if (!hasPrev) top = lineTop; if (!hasNext) bottom = lineTop + tree->lineThickness; if (tree->lineStyle == LINE_STYLE_DOT) { for (i = 0; i < tree->lineThickness; i++) Tree_VDotLine(tree, td.drawable, tree->lineGC, lineLeft + i, top, bottom); } else XFillRectangle(tree->display, td.drawable, tree->lineGC, lineLeft, top, tree->lineThickness, bottom - top); /* Don't overlap horizontal line */ vert = tree->lineThickness; } /* Horizontal line to self */ if (hasPrev || hasNext) { if (tree->lineStyle == LINE_STYLE_DOT) { for (i = 0; i < tree->lineThickness; i++) Tree_HDotLine(tree, td.drawable, tree->lineGC, lineLeft + vert, lineTop + i, x /* + tree->columnTreeLeft */ + indent); } else XFillRectangle(tree->display, td.drawable, tree->lineGC, lineLeft + vert, lineTop, left + tree->useIndent - (lineLeft + vert), tree->lineThickness); } /* Vertical lines from ancestors to their next siblings */ for (parent = item->parent; parent != NULL; parent = parent->parent) { lineLeft -= tree->useIndent; /* Option: Don't connect children of root item */ if ((parent->parent != NULL) && IS_ROOT(parent->parent) && !tree->showRootLines) continue; /* Check for ReallyVisible next sibling */ item = parent->nextSibling; while ((item != NULL) && !IS_VISIBLE(item)) item = item->nextSibling; if (item != NULL) { if (tree->lineStyle == LINE_STYLE_DOT) { for (i = 0; i < tree->lineThickness; i++) Tree_VDotLine(tree, td.drawable, tree->lineGC, lineLeft + i, y, y + height); } else XFillRectangle(tree->display, td.drawable, tree->lineGC, lineLeft, y, tree->lineThickness, height); } } } /* *---------------------------------------------------------------------- * * TreeItem_DrawButton -- * * Draws the button (if any) in an item. * * Results: * None. * * Side effects: * Stuff is drawn in a drawable. * *---------------------------------------------------------------------- */ void TreeItem_DrawButton( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int x, int y, /* Drawable coordinates of columnTree. */ int width, int height, /* Total size of columnTree. */ TreeDrawable td /* Where to draw. */ ) { int indent, left, lineLeft, lineTop; int buttonLeft, buttonTop, w1; int macoffset = 0; Tk_Image image; Pixmap bitmap; if (!TreeItem_HasButton(tree, item)) return; #if defined(MAC_TCL) || defined(MAC_OSX_TK) /* QuickDraw on Mac is offset by one pixel in both x and y. */ macoffset = 1; #endif indent = TreeItem_Indent(tree, item); /* Left edge of button/line area */ left = x /* + tree->columnTreeLeft */ + indent - tree->useIndent; image = PerStateImage_ForState(tree, &tree->buttonImage, item->state, NULL); if (image != NULL) { int imgW, imgH; Tk_SizeOfImage(image, &imgW, &imgH); Tree_RedrawImage(image, 0, 0, imgW, imgH, td, left + (tree->useIndent - imgW) / 2, y + (height - imgH) / 2); return; } bitmap = PerStateBitmap_ForState(tree, &tree->buttonBitmap, item->state, NULL); if (bitmap != None) { int bmpW, bmpH; int bx, by; Tk_SizeOfBitmap(tree->display, bitmap, &bmpW, &bmpH); bx = left + (tree->useIndent - bmpW) / 2; by = y + (height - bmpH) / 2; Tree_DrawBitmap(tree, bitmap, td.drawable, NULL, NULL, 0, 0, (unsigned int) bmpW, (unsigned int) bmpH, bx, by); return; } if (tree->useTheme) { int bw, bh; if (TreeTheme_GetButtonSize(tree, td.drawable, item->state & STATE_OPEN, &bw, &bh) == TCL_OK) { if (TreeTheme_DrawButton(tree, td.drawable, item->state & STATE_OPEN, left + (tree->useIndent - bw) / 2, y + (height - bh) / 2, bw, bh) == TCL_OK) { return; } } } w1 = tree->buttonThickness / 2; /* Left edge of vertical line */ /* Make sure this matches TreeItem_DrawLines() */ lineLeft = left + (tree->useIndent - tree->buttonThickness) / 2; /* Top edge of horizontal line */ /* Make sure this matches TreeItem_DrawLines() */ lineTop = y + (height - tree->buttonThickness) / 2; buttonLeft = left + (tree->useIndent - tree->buttonSize) / 2; buttonTop = y + (height - tree->buttonSize) / 2; /* Erase button background */ XFillRectangle(tree->display, td.drawable, Tk_3DBorderGC(tree->tkwin, tree->border, TK_3D_FLAT_GC), buttonLeft + tree->buttonThickness, buttonTop + tree->buttonThickness, tree->buttonSize - tree->buttonThickness, tree->buttonSize - tree->buttonThickness); /* Draw button outline */ XDrawRectangle(tree->display, td.drawable, tree->buttonGC, buttonLeft + w1, buttonTop + w1, tree->buttonSize - tree->buttonThickness + macoffset, tree->buttonSize - tree->buttonThickness + macoffset); /* Horizontal '-' */ XFillRectangle(tree->display, td.drawable, tree->buttonGC, buttonLeft + tree->buttonThickness * 2, lineTop, tree->buttonSize - tree->buttonThickness * 4, tree->buttonThickness); if (!(item->state & STATE_OPEN)) { /* Finish '+' */ XFillRectangle(tree->display, td.drawable, tree->buttonGC, lineLeft, buttonTop + tree->buttonThickness * 2, tree->buttonThickness, tree->buttonSize - tree->buttonThickness * 4); } } /* *---------------------------------------------------------------------- * * SpanWalkProc_UpdateWindowPositions -- * * Callback routine to TreeItem_WalkSpans for * TreeItem_UpdateWindowPositions. * * Results: * None. * * Side effects: * Windows in window elements may be resized/repositioned. * *---------------------------------------------------------------------- */ static int SpanWalkProc_UpdateWindowPositions( TreeCtrl *tree, TreeItem item, SpanInfo *spanPtr, StyleDrawArgs *drawArgs, ClientData clientData ) { StyleDrawArgs drawArgsCopy; int requests; if ((drawArgs->x >= drawArgs->bounds[2]) || (drawArgs->x + drawArgs->width <= drawArgs->bounds[0]) || (drawArgs->style == NULL)) return 0; TreeDisplay_GetReadyForTrouble(tree, &requests); drawArgsCopy = *drawArgs; TreeStyle_UpdateWindowPositions(&drawArgsCopy); if (TreeDisplay_WasThereTrouble(tree, requests)) return 1; /* Stop walking if we went past the right edge of the display area. */ return drawArgs->x + drawArgs->width >= drawArgs->bounds[2]; } /* *---------------------------------------------------------------------- * * TreeItem_UpdateWindowPositions -- * * Updates the geometry of any on-screen window elements. Called * by the display code when an item was possibly scrolled. * * Results: * None. * * Side effects: * Windows in window elements may be resized/repositioned. * *---------------------------------------------------------------------- */ void TreeItem_UpdateWindowPositions( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int lock, /* Columns we care about. */ int x, int y, /* Window coordinates of the item. */ int width, int height /* Total size of the item. */ ) { TreeItem_WalkSpans(tree, item, lock, x, y, width, height, SpanWalkProc_UpdateWindowPositions, (ClientData) NULL); } /* *---------------------------------------------------------------------- * * TreeItem_OnScreen -- * * Called by the display code when the item becomes visible * (i.e., actually displayed) or hidden. * * Results: * None. * * Side effects: * Windows in window elements may be mapped/unmapped. * *---------------------------------------------------------------------- */ void TreeItem_OnScreen( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int onScreen /* TRUE if item is displayed. */ ) { #if 0 Column *column = item->columns; while (column != NULL) { if (column->style != NULL) { TreeStyle_OnScreen(tree, column->style, onScreen); } column = column->next; } #endif } /* *---------------------------------------------------------------------- * * TreeItem_ReallyVisible -- * * Return whether the given Item could be displayed. * * Results: * TRUE if the item's -visible is TRUE, all of its ancestors' * -visible options are TRUE, and all of its ancestors are open. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_ReallyVisible( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { #if 0 Tree_UpdateItemIndex(tree); return item->indexVis != -1; #else TreeItem parent = item->parent; if (!tree->updateIndex) return item->indexVis != -1; if (!IS_VISIBLE(item)) return 0; if (parent == NULL) return IS_ROOT(item) ? tree->showRoot : 0; if (IS_ROOT(parent)) { if (!IS_VISIBLE(parent)) return 0; if (!tree->showRoot) return 1; if (!(parent->state & STATE_OPEN)) return 0; } if (!IS_VISIBLE(parent) || !(parent->state & STATE_OPEN)) return 0; return TreeItem_ReallyVisible(tree, parent); #endif } /* *---------------------------------------------------------------------- * * TreeItem_RootAncestor -- * * Return the toplevel ancestor of an Item. * * Results: * Returns the root, or an orphan ancestor, or the given Item. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeItem TreeItem_RootAncestor( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { while (item->parent != NULL) item = item->parent; return item; } /* *---------------------------------------------------------------------- * * TreeItem_IsAncestor -- * * Determine if one Item is the ancestor of another. * * Results: * TRUE if item1 is an ancestor of item2. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_IsAncestor( TreeCtrl *tree, /* Widget info. */ TreeItem item1, /* Possible ancestor. */ TreeItem item2 /* Item to check ancestry of. */ ) { if (item1 == item2) return 0; while (item2 && item2 != item1) item2 = item2->parent; return item2 != NULL; } /* *---------------------------------------------------------------------- * * TreeItem_ToObj -- * * Convert an Item to a Tcl_Obj. * * Results: * A new Tcl_Obj representing the Item. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ Tcl_Obj *TreeItem_ToObj( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { if (tree->itemPrefixLen) { char buf[100 + TCL_INTEGER_SPACE]; (void) sprintf(buf, "%s%d", tree->itemPrefix, item->id); return Tcl_NewStringObj(buf, -1); } return Tcl_NewIntObj(item->id); } /* *---------------------------------------------------------------------- * * Item_Configure -- * * This procedure is called to process an objc/objv list, plus * the Tk option database, in order to configure (or reconfigure) * an Item. * * 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 gets set for item; old resources get * freed, if there were any. * *---------------------------------------------------------------------- */ static int Item_Configure( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item to configure. */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Array of arguments */ ) { Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; int mask; int lastVisible = IS_VISIBLE(item); for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) item, tree->itemOptionTable, objc, objv, tree->tkwin, &savedOptions, &mask) != TCL_OK) { mask = 0; continue; } /* xxx */ Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); /* xxx */ Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } if (mask & ITEM_CONF_SIZE) { Tree_FreeItemDInfo(tree, item, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } if (mask & ITEM_CONF_BUTTON) { if (tree->columnTree != NULL) Tree_InvalidateItemDInfo(tree, tree->columnTree, item, NULL); } if ((mask & ITEM_CONF_VISIBLE) && (IS_VISIBLE(item) != lastVisible)) { /* Changing the visibility of an item can change the width of * any column. This is due to column expansion (this item may * be the widest item in the column) and spans > 1. */ Tree_InvalidateColumnWidth(tree, NULL); /* If this is the last child, redraw the lines of the previous * sibling and all of its descendants because the line from * the previous sibling to us is appearing/disappearing. */ if ((item->prevSibling != NULL) && (item->nextSibling == NULL) && tree->showLines && (tree->columnTree != NULL)) { TreeItem last = item->prevSibling; while (last->lastChild != NULL) last = last->lastChild; Tree_InvalidateItemDInfo(tree, tree->columnTree, item->prevSibling, last); } /* Redraw the parent if the parent has "-button auto". */ if ((item->parent != NULL) && (item->parent->flags & ITEM_FLAG_BUTTON_AUTO) && tree->showButtons && (tree->columnTree != NULL)) { Tree_InvalidateItemDInfo(tree, tree->columnTree, item->parent, NULL); } tree->updateIndex = 1; Tree_DInfoChanged(tree, DINFO_REDO_RANGES | DINFO_REDO_SELECTION); } return TCL_OK; } /* *---------------------------------------------------------------------- * * ItemCreateCmd -- * * This procedure is invoked to process the [item create] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ItemCreateCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; static CONST char *optionNames[] = { "-button", "-count", "-height", "-nextsibling", "-open", "-parent", "-prevsibling", "-returnid", "-tags", "-visible", (char *) NULL }; enum { OPT_BUTTON, OPT_COUNT, OPT_HEIGHT, OPT_NEXTSIBLING, OPT_OPEN, OPT_PARENT, OPT_PREVSIBLING, OPT_RETURNID, OPT_TAGS, OPT_VISIBLE }; int index, i, count = 1, button = 0, returnId = 1, open = 1, visible = 1; int height = 0; TreeItem item, parent = NULL, prevSibling = NULL, nextSibling = NULL; TreeItem head = NULL, tail = NULL; Tcl_Obj *listObj = NULL, *tagsObj = NULL; TagInfo *tagInfo = NULL; TreeColumn treeColumn; for (i = 3; i < objc; i += 2) { if (Tcl_GetIndexFromObj(interp, objv[i], optionNames, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } if (i + 1 == objc) { FormatResult(interp, "missing value for \"%s\" option", optionNames[index]); return TCL_ERROR; } switch (index) { case OPT_BUTTON: { int length; char *s = Tcl_GetStringFromObj(objv[i + 1], &length); if (s[0] == 'a' && strncmp(s, "auto", length) == 0) { button = ITEM_FLAG_BUTTON_AUTO; } else { if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &button) != TCL_OK) { FormatResult(interp, "expected boolean or auto but got \"%s\"", s); return TCL_ERROR; } if (button) { button = ITEM_FLAG_BUTTON; } } break; } case OPT_COUNT: if (Tcl_GetIntFromObj(interp, objv[i + 1], &count) != TCL_OK) return TCL_ERROR; if (count <= 0) { FormatResult(interp, "bad count \"%d\": must be > 0", count); } break; case OPT_HEIGHT: if (Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &height) != TCL_OK) return TCL_ERROR; if (height < 0) { FormatResult(interp, "bad screen distance \"%s\": must be > 0", Tcl_GetString(objv[i + 1])); } break; case OPT_NEXTSIBLING: if (TreeItem_FromObj(tree, objv[i + 1], &nextSibling, IFO_NOT_NULL | IFO_NOT_ROOT | IFO_NOT_ORPHAN) != TCL_OK) { return TCL_ERROR; } parent = prevSibling = NULL; break; case OPT_OPEN: if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &open) != TCL_OK) { return TCL_ERROR; } break; case OPT_PARENT: if (TreeItem_FromObj(tree, objv[i + 1], &parent, IFO_NOT_NULL) != TCL_OK) { return TCL_ERROR; } prevSibling = nextSibling = NULL; break; case OPT_PREVSIBLING: if (TreeItem_FromObj(tree, objv[i + 1], &prevSibling, IFO_NOT_NULL | IFO_NOT_ROOT | IFO_NOT_ORPHAN) != TCL_OK) { return TCL_ERROR; } parent = nextSibling = NULL; break; case OPT_RETURNID: if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &returnId) != TCL_OK) { return TCL_ERROR; } break; case OPT_TAGS: tagsObj = objv[i + 1]; break; case OPT_VISIBLE: if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &visible) != TCL_OK) { return TCL_ERROR; } break; } } /* Do it here so I don't have to free it above if an error occurs. */ if (tagsObj != NULL) { if (TagInfo_FromObj(tree, tagsObj, &tagInfo) != TCL_OK) return TCL_ERROR; } if (returnId) listObj = Tcl_NewListObj(0, NULL); /* Don't allow non-deleted items to become children of a * deleted item. */ if ((parent && IS_DELETED(parent)) || (prevSibling && IS_DELETED(prevSibling->parent)) || (nextSibling && IS_DELETED(nextSibling->parent))) parent = prevSibling = nextSibling = NULL; for (i = 0; i < count; i++) { item = Item_Alloc(tree); item->flags &= ~(ITEM_FLAG_BUTTON | ITEM_FLAG_BUTTON_AUTO); item->flags |= button; if (visible) item->flags |= ITEM_FLAG_VISIBLE; else item->flags &= ~ITEM_FLAG_VISIBLE; if (open) item->state |= STATE_OPEN; else item->state &= ~STATE_OPEN; item->fixedHeight = height; /* Apply each column's -itemstyle option. */ for (treeColumn = tree->columns; treeColumn != NULL; treeColumn = TreeColumn_Next(treeColumn)) { TreeStyle style = TreeColumn_ItemStyle(treeColumn); if (style != NULL) { Column *column = Item_CreateColumn(tree, item, TreeColumn_Index(treeColumn), NULL); column->style = TreeStyle_NewInstance(tree, style); } } #ifdef DEPRECATED /* Apply default styles */ if (tree->defaultStyle.numStyles) { int i, n = MIN(tree->columnCount, tree->defaultStyle.numStyles); for (i = 0; i < n; i++) { Column *column = Item_CreateColumn(tree, item, i, NULL); if (column->style != NULL) continue; if (tree->defaultStyle.styles[i] != NULL) { column->style = TreeStyle_NewInstance(tree, tree->defaultStyle.styles[i]); } } } #endif /* DEPRECATED */ if (tagInfo != NULL) { if (count == 1) { item->tagInfo = tagInfo; tagInfo = NULL; } else { item->tagInfo = TagInfo_Copy(tree, tagInfo); } } /* Link the new items together as siblings */ if (parent || prevSibling || nextSibling) { if (head == NULL) head = item; if (tail != NULL) { tail->nextSibling = item; item->prevSibling = tail; } tail = item; } if (returnId) Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); } if (parent != NULL) { head->prevSibling = parent->lastChild; if (parent->lastChild != NULL) parent->lastChild->nextSibling = head; else parent->firstChild = head; parent->lastChild = tail; } else if (prevSibling != NULL) { parent = prevSibling->parent; if (prevSibling->nextSibling != NULL) prevSibling->nextSibling->prevSibling = tail; else parent->lastChild = tail; head->prevSibling = prevSibling; tail->nextSibling = prevSibling->nextSibling; prevSibling->nextSibling = head; } else if (nextSibling != NULL) { parent = nextSibling->parent; if (nextSibling->prevSibling != NULL) nextSibling->prevSibling->nextSibling = head; else parent->firstChild = head; head->prevSibling = nextSibling->prevSibling; tail->nextSibling = nextSibling; nextSibling->prevSibling = tail; } if (parent != NULL) { for (item = head; item != NULL; item = item->nextSibling) { item->parent = parent; item->depth = parent->depth + 1; } parent->numChildren += count; TreeItem_AddToParent(tree, head); } TagInfo_Free(tree, tagInfo); if (returnId) Tcl_SetObjResult(interp, listObj); return TCL_OK; } /* *---------------------------------------------------------------------- * * NoStyleMsg -- * * Utility to set the interpreter result with a message indicating * a Column has no assigned style. * * Results: * None. * * Side effects: * Interpreter result is changed. * *---------------------------------------------------------------------- */ static void NoStyleMsg( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item record. */ int columnIndex /* 0-based index of the column that * has no style. */ ) { FormatResult(tree->interp, "item %s%d column %s%d has no style", tree->itemPrefix, item->id, tree->columnPrefix, TreeColumn_GetID(Tree_FindColumn(tree, columnIndex))); } /* *---------------------------------------------------------------------- * * ItemElementCmd -- * * This procedure is invoked to process the [item element] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ItemElementCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; static CONST char *commandNames[] = { #ifdef DEPRECATED "actual", #endif "cget", "configure", "perstate", (char *) NULL }; enum { #ifdef DEPRECATED COMMAND_ACTUAL, #endif COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_PERSTATE }; int index; int columnIndex; Column *column; TreeItemList itemList; TreeItem item; int flags = IFO_NOT_NULL; int result = TCL_OK; if (objc < 7) { Tcl_WrongNumArgs(interp, 3, objv, "command item column element ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], commandNames, "command", 0, &index) != TCL_OK) return TCL_ERROR; /* * [configure] without an option-value pair can operate on a single item * only. [cget] and [perstate] only operate on a single item. */ if ((index != COMMAND_CONFIGURE) || (objc < 9)) flags |= IFO_NOT_MANY; if (TreeItemList_FromObj(tree, objv[4], &itemList, flags) != TCL_OK) return TCL_ERROR; item = TreeItemList_Nth(&itemList, 0); switch (index) { /* T item element perstate I C E option ?stateList? */ #ifdef DEPRECATED case COMMAND_ACTUAL: #endif case COMMAND_PERSTATE: { int state; if (objc < 8 || objc > 9) { Tcl_WrongNumArgs(tree->interp, 4, objv, "item column element option ?stateList?"); result = TCL_ERROR; break; } if (Item_FindColumnFromObj(tree, item, objv[5], &column, &columnIndex) != TCL_OK) { result = TCL_ERROR; break; } if ((column == NULL) || (column->style == NULL)) { NoStyleMsg(tree, item, columnIndex); result = TCL_ERROR; break; } state = item->state | column->cstate; if (objc == 9) { int states[3]; if (Tree_StateFromListObj(tree, objv[8], states, SFO_NOT_OFF | SFO_NOT_TOGGLE) != TCL_OK) { result = TCL_ERROR; break; } state = states[STATE_OP_ON]; } result = TreeStyle_ElementActual(tree, column->style, state, objv[6], objv[7]); break; } /* T item element cget I C E option */ case COMMAND_CGET: { if (objc != 8) { Tcl_WrongNumArgs(tree->interp, 4, objv, "item column element option"); result = TCL_ERROR; break; } if (Item_FindColumnFromObj(tree, item, objv[5], &column, &columnIndex) != TCL_OK) { result = TCL_ERROR; break; } if ((column == NULL) || (column->style == NULL)) { NoStyleMsg(tree, item, columnIndex); result = TCL_ERROR; break; } result = TreeStyle_ElementCget(tree, item, (TreeItemColumn) column, column->style, objv[6], objv[7]); break; } /* T item element configure I C E ... */ case COMMAND_CONFIGURE: { struct columnObj { TreeColumnList columns; int isColumn; int numArgs; } staticCO[STATIC_SIZE], *co = staticCO; int i, index, indexElem, prevColumn; ItemForEach iter; /* If no option-value pair is given, we can't specify more than * one column. */ flags = CFO_NOT_NULL | CFO_NOT_TAIL; if (objc < 9) flags |= CFO_NOT_MANY; STATIC_ALLOC(co, struct columnObj, objc); for (i = 5; i < objc; i++) { co[i].isColumn = FALSE; co[i].numArgs = -1; } indexElem = 6; /* Get the first column(s) */ i = indexElem - 1; if (TreeColumnList_FromObj(tree, objv[i], &co[i].columns, flags) != TCL_OK) { result = TCL_ERROR; break; } co[i].isColumn = TRUE; prevColumn = i; while (1) { int numArgs = 0; char breakChar = '\0'; /* Look for a + or , */ for (index = indexElem + 1; index < objc; index++) { if (numArgs % 2 == 0) { int length; char *s = Tcl_GetStringFromObj(objv[index], &length); if ((length == 1) && ((s[0] == '+') || (s[0] == ','))) { breakChar = s[0]; break; } } numArgs++; } /* Require at least one option-value pair if more than one * element is specified. */ if ((breakChar || indexElem != 6) && (numArgs < 2)) { FormatResult(interp, "missing option-value pair after element \"%s\"", Tcl_GetString(objv[indexElem])); result = TCL_ERROR; goto doneCONF; } co[indexElem].numArgs = numArgs; if (!breakChar) break; if (index == objc - 1) { FormatResult(interp, "missing %s after \"%c\"", (breakChar == '+') ? "element name" : "column", breakChar); result = TCL_ERROR; goto doneCONF; } /* + indicates start of another element */ if (breakChar == '+') { indexElem = index + 1; } /* , indicates start of another column */ else if (breakChar == ',') { co[prevColumn].numArgs = index - prevColumn; if (TreeColumnList_FromObj(tree, objv[index + 1], &co[index + 1].columns, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; goto doneCONF; } co[index + 1].isColumn = TRUE; prevColumn = index + 1; indexElem = index + 2; if (indexElem == objc) { FormatResult(interp, "missing element name after column \"%s\"", Tcl_GetString(objv[index + 1])); result = TCL_ERROR; goto doneCONF; } } } co[prevColumn].numArgs = index - prevColumn; ITEM_FOR_EACH(item, &itemList, NULL, &iter) { /* T item element configure I C E option value \ * + E option value , C E option value */ int iMask = 0; /* co[index].numArgs is the number of arguments from the C * to the next separator (but not including that separator). */ for (index = 5; index < objc; index += co[index].numArgs + 1) { ColumnForEach citer; TreeColumn treeColumn; if (!co[index].isColumn) panic("isColumn == FALSE"); COLUMN_FOR_EACH(treeColumn, &co[index].columns, NULL, &citer) { int columnIndex, cMask = 0; columnIndex = TreeColumn_Index(treeColumn); column = Item_FindColumn(tree, item, columnIndex); if ((column == NULL) || (column->style == NULL)) { NoStyleMsg(tree, item, columnIndex); result = TCL_ERROR; break; } indexElem = index + 1; /* Do each element in this column */ while (1) { int eMask, index2; if (co[indexElem].numArgs == -1) panic("indexElem=%d (%s) objc=%d numArgs == -1", indexElem, Tcl_GetString(objv[indexElem]), objc); result = TreeStyle_ElementConfigure(tree, item, (TreeItemColumn) column, column->style, objv[indexElem], co[indexElem].numArgs, (Tcl_Obj **) objv + indexElem + 1, &eMask); if (result != TCL_OK) break; cMask |= eMask; /* co[indexElem].numArgs is the number of * option-value arguments after the element. */ index2 = indexElem + co[indexElem].numArgs; if (index2 == objc - 1) break; /* Skip the '+' or ',' */ index2 += 2; if (co[index2].isColumn) break; indexElem = index2; } if (cMask & CS_LAYOUT) { TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); Tree_InvalidateColumnWidth(tree, treeColumn); } else if (cMask & CS_DISPLAY) { Tree_InvalidateItemDInfo(tree, treeColumn, item, NULL); } iMask |= cMask; if (result != TCL_OK) break; } if (result != TCL_OK) break; } if (iMask & CS_LAYOUT) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } else if (iMask & CS_DISPLAY) { } if (result != TCL_OK) break; } doneCONF: for (i = 5; i < objc; i++) { if (co[i].isColumn) TreeColumnList_Free(&co[i].columns); } STATIC_FREE(co, struct columnObj, objc); break; } } TreeItemList_Free(&itemList); return result; } /* *---------------------------------------------------------------------- * * ItemStyleCmd -- * * This procedure is invoked to process the [item style] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ItemStyleCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; static CONST char *commandNames[] = { "elements", "map", "set", (char *) NULL }; enum { COMMAND_ELEMENTS, COMMAND_MAP, COMMAND_SET }; int index; TreeItemList itemList; TreeItem item; int flags = IFO_NOT_NULL; int result = TCL_OK; if (objc < 5) { Tcl_WrongNumArgs(interp, 3, objv, "command item ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } /* [style elements] only works on a single item. * [style set] only works on a single item without a column-style pair. */ if ((index == COMMAND_ELEMENTS) || (index == COMMAND_SET && objc < 7)) flags |= IFO_NOT_MANY; if (TreeItemList_FromObj(tree, objv[4], &itemList, flags) != TCL_OK) { return TCL_ERROR; } item = TreeItemList_Nth(&itemList, 0); switch (index) { /* T item style elements I C */ case COMMAND_ELEMENTS: { Column *column; int columnIndex; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "item column"); result = TCL_ERROR; break; } if (Item_FindColumnFromObj(tree, item, objv[5], &column, &columnIndex) != TCL_OK) { result = TCL_ERROR; break; } if ((column == NULL) || (column->style == NULL)) { NoStyleMsg(tree, item, columnIndex); result = TCL_ERROR; break; } TreeStyle_ListElements(tree, column->style); break; } /* T item style map I C S map */ case COMMAND_MAP: { TreeStyle style; TreeColumnList columns; TreeColumn treeColumn; Column *column; int columnIndex; int objcM; Tcl_Obj **objvM; ItemForEach iter; ColumnForEach citer; if (objc != 8) { Tcl_WrongNumArgs(interp, 4, objv, "item column style map"); return TCL_ERROR; } if (TreeColumnList_FromObj(tree, objv[5], &columns, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; break; } if (TreeStyle_FromObj(tree, objv[6], &style) != TCL_OK) { result = TCL_ERROR; goto doneMAP; } if (Tcl_ListObjGetElements(interp, objv[7], &objcM, &objvM) != TCL_OK) { result = TCL_ERROR; goto doneMAP; } if (objcM & 1) { FormatResult(interp, "list must contain even number of elements"); result = TCL_ERROR; goto doneMAP; } ITEM_FOR_EACH(item, &itemList, NULL, &iter) { COLUMN_FOR_EACH(treeColumn, &columns, NULL, &citer) { columnIndex = TreeColumn_Index(treeColumn); column = Item_CreateColumn(tree, item, columnIndex, NULL); if (column->style != NULL) { if (TreeStyle_Remap(tree, column->style, style, objcM, objvM) != TCL_OK) { result = TCL_ERROR; break; } } else { column->style = TreeStyle_NewInstance(tree, style); } TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); Tree_InvalidateColumnWidth(tree, treeColumn); } TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); if (result != TCL_OK) break; } Tree_DInfoChanged(tree, DINFO_REDO_RANGES); doneMAP: TreeColumnList_Free(&columns); break; } /* T item style set I ?C? ?S? ?C S ...?*/ case COMMAND_SET: { struct columnStyle { TreeColumnList columns; TreeStyle style; }; struct columnStyle staticCS[STATIC_SIZE], *cs = staticCS; TreeColumn treeColumn; Column *column; int i, count = 0, length, changed = FALSE, changedI; ItemForEach iter; ColumnForEach citer; if (objc < 5) { Tcl_WrongNumArgs(interp, 4, objv, "item ?column? ?style? ?column style ...?"); return TCL_ERROR; } /* Return list of styles. */ if (objc == 5) { Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); treeColumn = tree->columns; column = item->columns; while (treeColumn != NULL) { if ((column != NULL) && (column->style != NULL)) Tcl_ListObjAppendElement(interp, listObj, TreeStyle_ToObj(TreeStyle_GetMaster( tree, column->style))); else Tcl_ListObjAppendElement(interp, listObj, Tcl_NewObj()); treeColumn = TreeColumn_Next(treeColumn); if (column != NULL) column = column->next; } Tcl_SetObjResult(interp, listObj); break; } /* Return style in one column. */ if (objc == 6) { if (Item_FindColumnFromObj(tree, item, objv[5], &column, NULL) != TCL_OK) return TCL_ERROR; if ((column != NULL) && (column->style != NULL)) Tcl_SetObjResult(interp, TreeStyle_ToObj( TreeStyle_GetMaster(tree, column->style))); break; } /* Get column/style pairs. */ STATIC_ALLOC(cs, struct columnStyle, objc / 2); for (i = 5; i < objc; i += 2) { if (TreeColumnList_FromObj(tree, objv[i], &cs[count].columns, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; goto doneSET; } if (i + 1 == objc) { FormatResult(interp, "missing style for column \"%s\"", Tcl_GetString(objv[i])); result = TCL_ERROR; goto doneSET; } (void) Tcl_GetStringFromObj(objv[i + 1], &length); if (length == 0) { cs[count].style = NULL; } else { if (TreeStyle_FromObj(tree, objv[i + 1], &cs[count].style) != TCL_OK) { result = TCL_ERROR; goto doneSET; } } count++; } ITEM_FOR_EACH(item, &itemList, NULL, &iter) { changedI = FALSE; for (i = 0; i < count; i++) { COLUMN_FOR_EACH(treeColumn, &cs[i].columns, NULL, &citer) { if (cs[i].style == NULL) { column = Item_FindColumn(tree, item, TreeColumn_Index(treeColumn)); if (column == NULL || column->style == NULL) continue; TreeItemColumn_ForgetStyle(tree, (TreeItemColumn) column); } else { column = Item_CreateColumn(tree, item, TreeColumn_Index(treeColumn), NULL); if (column->style != NULL) { if (TreeStyle_GetMaster(tree, column->style) == cs[i].style) continue; TreeItemColumn_ForgetStyle(tree, (TreeItemColumn) column); } column->style = TreeStyle_NewInstance(tree, cs[i].style); } TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); Tree_InvalidateColumnWidth(tree, treeColumn); changedI = TRUE; } if (changedI) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); changed = TRUE; } } } if (changed) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); doneSET: for (i = 0; i < count; i++) { TreeColumnList_Free(&cs[i].columns); } STATIC_FREE(cs, struct columnStyle, objc / 2); break; } } TreeItemList_Free(&itemList); return result; } /* Quicksort is not a "stable" sorting algorithm, but it can become a * stable sort by using the pre-sort order of two items as a tie-breaker * for items that would otherwise be considered equal. */ #define STABLE_SORT /* one per column per SortItem */ struct SortItem1 { long longValue; double doubleValue; char *string; }; /* one per Item */ struct SortItem { TreeItem item; struct SortItem1 *item1; Tcl_Obj *obj; /* TreeItem_ToObj() */ #ifdef STABLE_SORT int index; /* The pre-sort order of the item */ #endif }; typedef struct SortData SortData; /* Used to process -element option */ struct SortElement { TreeStyle style; TreeElement elem; int elemIndex; }; /* One per TreeColumn */ struct SortColumn { int (*proc)(SortData *, struct SortItem *, struct SortItem *, int); int sortBy; int column; int order; Tcl_Obj *command; struct SortElement elems[20]; int elemCount; }; /* Data for sort as a whole */ struct SortData { TreeCtrl *tree; struct SortItem *items; struct SortItem1 *item1s; /* SortItem.item1 points in here */ #define MAX_SORT_COLUMNS 40 struct SortColumn columns[MAX_SORT_COLUMNS]; int columnCount; /* max number of columns to compare */ int result; }; /* from Tcl 8.4.0 */ static int DictionaryCompare( char *left, char *right ) { Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower; int diff, zeros; int secondaryDiff = 0; while (1) { if (isdigit(UCHAR(*right)) && isdigit(UCHAR(*left))) { /* INTL: digit */ /* * 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))) { /* INTL: digit */ if (isdigit(UCHAR(*left))) { /* INTL: digit */ 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))) { /* INTL: digit */ return -1; } } continue; } /* * Convert character to Unicode for comparison purposes. If either * string is at the terminating null, do a byte-wise comparison and * bail out immediately. */ if ((*left != '\0') && (*right != '\0')) { left += Tcl_UtfToUniChar(left, &uniLeft); right += Tcl_UtfToUniChar(right, &uniRight); /* * Convert both chars to lower for the comparison, because * dictionary sorts are case insensitve. Covert to lower, not * upper, so chars between Z and a will sort before A (where most * other interesting punctuations occur) */ uniLeftLower = Tcl_UniCharToLower(uniLeft); uniRightLower = Tcl_UniCharToLower(uniRight); } else { diff = UCHAR(*left) - UCHAR(*right); break; } diff = uniLeftLower - uniRightLower; if (diff) { return diff; } else if (secondaryDiff == 0) { if (Tcl_UniCharIsUpper(uniLeft) && Tcl_UniCharIsLower(uniRight)) { secondaryDiff = -1; } else if (Tcl_UniCharIsUpper(uniRight) && Tcl_UniCharIsLower(uniLeft)) { secondaryDiff = 1; } } } if (diff == 0) { diff = secondaryDiff; } return diff; } static int CompareAscii( SortData *sortData, struct SortItem *a, struct SortItem *b, int n /* Column index. */ ) { char *left = a->item1[n].string; char *right = b->item1[n].string; /* make sure to handle case where no string value has been set */ if (left == NULL) { return ((right == NULL) ? 0 : (0 - UCHAR(*right))); } else if (right == NULL) { return UCHAR(*left); } else { return strcmp(left, right); } } static int CompareDict( SortData *sortData, struct SortItem *a, struct SortItem *b, int n /* Column index. */ ) { char *left = a->item1[n].string; char *right = b->item1[n].string; /* make sure to handle case where no string value has been set */ if (left == NULL) { return ((right == NULL) ? 0 : (0 - UCHAR(*right))); } else if (right == NULL) { return UCHAR(*left); } else { return DictionaryCompare(left, right); } } static int CompareDouble( SortData *sortData, struct SortItem *a, struct SortItem *b, int n /* Column index. */ ) { return (a->item1[n].doubleValue < b->item1[n].doubleValue) ? -1 : ((a->item1[n].doubleValue == b->item1[n].doubleValue) ? 0 : 1); } static int CompareLong( SortData *sortData, struct SortItem *a, struct SortItem *b, int n /* Column index. */ ) { return (a->item1[n].longValue < b->item1[n].longValue) ? -1 : ((a->item1[n].longValue == b->item1[n].longValue) ? 0 : 1); } static int CompareCmd( SortData *sortData, struct SortItem *a, struct SortItem *b, int n /* Column index. */ ) { Tcl_Interp *interp = sortData->tree->interp; Tcl_Obj **objv, *paramObjv[2]; int objc, v; paramObjv[0] = a->obj; paramObjv[1] = b->obj; Tcl_ListObjLength(interp, sortData->columns[n].command, &objc); Tcl_ListObjReplace(interp, sortData->columns[n].command, objc - 2, 2, 2, paramObjv); Tcl_ListObjGetElements(interp, sortData->columns[n].command, &objc, &objv); sortData->result = Tcl_EvalObjv(interp, objc, objv, 0); if (sortData->result != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (evaluating item sort -command)"); return 0; } sortData->result = Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &v); if (sortData->result != TCL_OK) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "-command returned non-numeric result", -1); return 0; } return v; } static int CompareProc( SortData *sortData, struct SortItem *a, struct SortItem *b ) { int i, v; if (a->item == b->item) return 0; for (i = 0; i < sortData->columnCount; i++) { v = (*sortData->columns[i].proc)(sortData, a, b, i); /* -command returned error */ if (sortData->result != TCL_OK) return 0; if (v != 0) { if (i && (sortData->columns[i].order != sortData->columns[0].order)) v *= -1; return v; } } #ifdef STABLE_SORT return (a->index < b->index) ? -1 : 1; #else return 0; #endif } /* BEGIN custom quicksort() */ static int find_pivot( SortData *sortData, struct SortItem *left, struct SortItem *right, struct SortItem *pivot ) { struct SortItem *a, *b, *c, *p, *tmp; int v; a = left; b = (left + (right - left) / 2); c = right; /* Arrange a <= b <= c. */ v = CompareProc(sortData, a, b); if (sortData->result != TCL_OK) return 0; if (v > 0) { tmp = a; a = b; b = tmp; } v = CompareProc(sortData, a, c); if (sortData->result != TCL_OK) return 0; if (v > 0) { tmp = a; a = c; c = tmp; } v = CompareProc(sortData, b, c); if (sortData->result != TCL_OK) return 0; if (v > 0) { tmp = b; b = c; c = tmp; } /* if (a < b) pivot = b */ v = CompareProc(sortData, a, b); if (sortData->result != TCL_OK) return 0; if (v < 0) { (*pivot) = *b; return 1; } /* if (b < c) pivot = c */ v = CompareProc(sortData, b, c); if (sortData->result != TCL_OK) return 0; if (v < 0) { (*pivot) = *c; return 1; } for (p = left + 1; p <= right; p++) { int v = CompareProc(sortData, p, left); if (sortData->result != TCL_OK) return 0; if (v != 0) { (*pivot) = (v < 0) ? *left : *p; return 1; } } return 0; } /* If the user provides a -command which does not properly compare two * elements, quicksort may go into an infinite loop or access illegal memory. * This #define indicates parts of the code which are not part of a normal * quicksort, but are present to detect the aforementioned bugs. */ #define BUGGY_COMMAND static struct SortItem * partition( SortData *sortData, struct SortItem *left, struct SortItem *right, struct SortItem *pivot ) { int v; #ifdef BUGGY_COMMAND struct SortItem *min = left, *max = right; #endif while (left <= right) { /* while (*left < *pivot) ++left; */ while (1) { v = CompareProc(sortData, left, pivot); if (sortData->result != TCL_OK) return NULL; if (v >= 0) break; #ifdef BUGGY_COMMAND /* If -command always returns < 0, 'left' becomes invalid */ if (left == max) goto buggy; #endif left++; } /* while (*right >= *pivot) --right; */ while (1) { v = CompareProc(sortData, right, pivot); if (sortData->result != TCL_OK) return NULL; if (v < 0) break; #ifdef BUGGY_COMMAND /* If -command always returns >= 0, 'right' becomes invalid */ if (right == min) goto buggy; #endif right--; } if (left < right) { struct SortItem tmp = *left; *left = *right; *right = tmp; left++; right--; } } return left; #ifdef BUGGY_COMMAND buggy: FormatResult(sortData->tree->interp, "buggy item sort -command detected"); sortData->result = TCL_ERROR; return NULL; #endif } static void quicksort( SortData *sortData, struct SortItem *left, struct SortItem *right ) { struct SortItem *p, pivot; if (sortData->result != TCL_OK) return; if (left == right) return; /* FIXME: switch to insertion sort or similar when the number of * elements is small. */ if (find_pivot(sortData, left, right, &pivot) == 1) { p = partition(sortData, left, right, &pivot); quicksort(sortData, left, p - 1); quicksort(sortData, p, right); } } /* END custom quicksort() */ /* *---------------------------------------------------------------------- * * ItemSortCmd -- * * This procedure is invoked to process the [item sort] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ItemSortCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; TreeItem item, first, last, walk, lastChild; Column *column; int i, j, count, elemIndex, index, indexF = 0, indexL = 0; int sawColumn = FALSE, sawCmd = FALSE; static int (*sortProc[5])(SortData *, struct SortItem *, struct SortItem *, int) = { CompareAscii, CompareDict, CompareDouble, CompareLong, CompareCmd }; SortData sortData; TreeColumn treeColumn; struct SortElement *elemPtr; int notReally = FALSE; int result = TCL_OK; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "item ?option ...?"); return TCL_ERROR; } if (TreeItem_FromObj(tree, objv[3], &item, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; /* If the item has no children, then nothing is done and no error * is generated. */ if (item->numChildren < 1) return TCL_OK; /* Defaults: sort ascii strings in column 0 only */ sortData.tree = tree; sortData.columnCount = 1; sortData.columns[0].column = 0; sortData.columns[0].sortBy = SORT_ASCII; sortData.columns[0].order = 1; sortData.columns[0].elemCount = 0; sortData.result = TCL_OK; first = item->firstChild; last = item->lastChild; for (i = 4; i < objc; ) { static CONST char *optionName[] = { "-ascii", "-column", "-command", "-decreasing", "-dictionary", "-element", "-first", "-increasing", "-integer", "-last", "-notreally", "-real", NULL }; int numArgs[] = { 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1 }; enum { OPT_ASCII, OPT_COLUMN, OPT_COMMAND, OPT_DECREASING, OPT_DICT, OPT_ELEMENT, OPT_FIRST, OPT_INCREASING, OPT_INTEGER, OPT_LAST, OPT_NOT_REALLY, OPT_REAL }; if (Tcl_GetIndexFromObj(interp, objv[i], optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; if (objc - i < numArgs[index]) { FormatResult(interp, "missing value for \"%s\" option", optionName[index]); return TCL_ERROR; } switch (index) { case OPT_ASCII: sortData.columns[sortData.columnCount - 1].sortBy = SORT_ASCII; break; case OPT_COLUMN: if (TreeColumn_FromObj(tree, objv[i + 1], &treeColumn, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) return TCL_ERROR; /* The first -column we see is the first column we compare */ if (sawColumn) { if (sortData.columnCount + 1 > MAX_SORT_COLUMNS) { FormatResult(interp, "can't compare more than %d columns", MAX_SORT_COLUMNS); return TCL_ERROR; } sortData.columnCount++; /* Defaults for this column */ sortData.columns[sortData.columnCount - 1].sortBy = SORT_ASCII; sortData.columns[sortData.columnCount - 1].order = 1; sortData.columns[sortData.columnCount - 1].elemCount = 0; } sortData.columns[sortData.columnCount - 1].column = TreeColumn_Index(treeColumn); sawColumn = TRUE; break; case OPT_COMMAND: sortData.columns[sortData.columnCount - 1].command = objv[i + 1]; sortData.columns[sortData.columnCount - 1].sortBy = SORT_COMMAND; sawCmd = TRUE; break; case OPT_DECREASING: sortData.columns[sortData.columnCount - 1].order = 0; break; case OPT_DICT: sortData.columns[sortData.columnCount - 1].sortBy = SORT_DICT; break; case OPT_ELEMENT: { int listObjc; Tcl_Obj **listObjv; if (Tcl_ListObjGetElements(interp, objv[i + 1], &listObjc, &listObjv) != TCL_OK) return TCL_ERROR; elemPtr = sortData.columns[sortData.columnCount - 1].elems; sortData.columns[sortData.columnCount - 1].elemCount = 0; if (listObjc == 0) { } else if (listObjc == 1) { if (TreeElement_FromObj(tree, listObjv[0], &elemPtr->elem) != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (processing -element option)"); return TCL_ERROR; } if (!TreeElement_IsType(tree, elemPtr->elem, "text")) { FormatResult(interp, "element %s is not of type \"text\"", Tcl_GetString(listObjv[0])); Tcl_AddErrorInfo(interp, "\n (processing -element option)"); return TCL_ERROR; } elemPtr->style = NULL; elemPtr->elemIndex = -1; sortData.columns[sortData.columnCount - 1].elemCount++; } else { if (listObjc & 1) { FormatResult(interp, "list must have even number of elements"); Tcl_AddErrorInfo(interp, "\n (processing -element option)"); return TCL_ERROR; } for (j = 0; j < listObjc; j += 2) { if ((TreeStyle_FromObj(tree, listObjv[j], &elemPtr->style) != TCL_OK) || (TreeElement_FromObj(tree, listObjv[j + 1], &elemPtr->elem) != TCL_OK) || (TreeStyle_FindElement(tree, elemPtr->style, elemPtr->elem, &elemPtr->elemIndex) != TCL_OK)) { Tcl_AddErrorInfo(interp, "\n (processing -element option)"); return TCL_ERROR; } if (!TreeElement_IsType(tree, elemPtr->elem, "text")) { FormatResult(interp, "element %s is not of type \"text\"", Tcl_GetString(listObjv[j + 1])); Tcl_AddErrorInfo(interp, "\n (processing -element option)"); return TCL_ERROR; } sortData.columns[sortData.columnCount - 1].elemCount++; elemPtr++; } } break; } case OPT_FIRST: if (TreeItem_FromObj(tree, objv[i + 1], &first, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if (first->parent != item) { FormatResult(interp, "item %s%d is not a child of item %s%d", tree->itemPrefix, first->id, tree->itemPrefix, item->id); return TCL_ERROR; } break; case OPT_INCREASING: sortData.columns[sortData.columnCount - 1].order = 1; break; case OPT_INTEGER: sortData.columns[sortData.columnCount - 1].sortBy = SORT_LONG; break; case OPT_LAST: if (TreeItem_FromObj(tree, objv[i + 1], &last, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if (last->parent != item) { FormatResult(interp, "item %s%d is not a child of item %s%d", tree->itemPrefix, last->id, tree->itemPrefix, item->id); return TCL_ERROR; } break; case OPT_NOT_REALLY: notReally = TRUE; break; case OPT_REAL: sortData.columns[sortData.columnCount - 1].sortBy = SORT_DOUBLE; break; } i += numArgs[index]; } /* If there are no columns, we cannot perform a sort unless -command * is specified. */ if ((tree->columnCount < 1) && (sortData.columns[0].sortBy != SORT_COMMAND)) { FormatResult(interp, "there are no columns"); return TCL_ERROR; } /* If there is only one item to sort, then return early. */ if (first == last) { if (notReally) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, first)); return TCL_OK; } for (i = 0; i < sortData.columnCount; i++) { /* Initialize the sort procedure for this column. */ sortData.columns[i].proc = sortProc[sortData.columns[i].sortBy]; /* Append two dummy args to the -command argument. These two dummy * args are replaced by the 2 item ids being compared. See * CompareCmd(). */ if (sortData.columns[i].sortBy == SORT_COMMAND) { Tcl_Obj *obj = Tcl_DuplicateObj(sortData.columns[i].command); Tcl_Obj *obj2 = Tcl_NewObj(); Tcl_IncrRefCount(obj); if (Tcl_ListObjAppendElement(interp, obj, obj2) != TCL_OK) { Tcl_DecrRefCount(obj); Tcl_IncrRefCount(obj2); Tcl_DecrRefCount(obj2); for (j = 0; j < i; j++) { if (sortData.columns[j].sortBy == SORT_COMMAND) { Tcl_DecrRefCount(sortData.columns[j].command); } } return TCL_ERROR; } (void) Tcl_ListObjAppendElement(interp, obj, obj2); sortData.columns[i].command = obj; } } index = 0; walk = item->firstChild; while (walk != NULL) { if (walk == first) indexF = index; if (walk == last) indexL = index; index++; walk = walk->nextSibling; } if (indexF > indexL) { walk = last; last = first; first = walk; index = indexL; indexL = indexF; indexF = index; } count = indexL - indexF + 1; sortData.item1s = (struct SortItem1 *) ckalloc(sizeof(struct SortItem1) * count * sortData.columnCount); sortData.items = (struct SortItem *) ckalloc(sizeof(struct SortItem) * count); for (i = 0; i < count; i++) { sortData.items[i].item1 = sortData.item1s + i * sortData.columnCount; sortData.items[i].obj = NULL; } index = 0; walk = first; while (walk != last->nextSibling) { struct SortItem *sortItem = &sortData.items[index]; sortItem->item = walk; #ifdef STABLE_SORT sortItem->index = index; #endif if (sawCmd) { Tcl_Obj *obj = TreeItem_ToObj(tree, walk); Tcl_IncrRefCount(obj); sortData.items[index].obj = obj; } for (i = 0; i < sortData.columnCount; i++) { struct SortItem1 *sortItem1 = sortItem->item1 + i; if (sortData.columns[i].sortBy == SORT_COMMAND) continue; column = Item_FindColumn(tree, walk, sortData.columns[i].column); if ((column == NULL) || (column->style == NULL)) { NoStyleMsg(tree, walk, sortData.columns[i].column); result = TCL_ERROR; goto done; } /* -element was empty. Find the first text element in the style */ if (sortData.columns[i].elemCount == 0) elemIndex = -1; /* -element was element name. Find the element in the style */ else if ((sortData.columns[i].elemCount == 1) && (sortData.columns[i].elems[0].style == NULL)) { if (TreeStyle_FindElement(tree, column->style, sortData.columns[i].elems[0].elem, &elemIndex) != TCL_OK) { result = TCL_ERROR; goto done; } } /* -element was style/element pair list */ else { TreeStyle masterStyle = TreeStyle_GetMaster(tree, column->style); /* If the item style does not match any in the -element list, * we will use the first text element in the item style. */ elemIndex = -1; /* Match a style from the -element list. Look in reverse order * to handle duplicates. */ for (j = sortData.columns[i].elemCount - 1; j >= 0; j--) { if (sortData.columns[i].elems[j].style == masterStyle) { elemIndex = sortData.columns[i].elems[j].elemIndex; break; } } } if (TreeStyle_GetSortData(tree, column->style, elemIndex, sortData.columns[i].sortBy, &sortItem1->longValue, &sortItem1->doubleValue, &sortItem1->string) != TCL_OK) { char msg[128]; sprintf(msg, "\n (preparing to sort item %s%d column %s%d)", tree->itemPrefix, walk->id, tree->columnPrefix, TreeColumn_GetID( Tree_FindColumn(tree, sortData.columns[i].column))); Tcl_AddErrorInfo(interp, msg); result = TCL_ERROR; goto done; } } index++; walk = walk->nextSibling; } quicksort(&sortData, sortData.items, sortData.items + count - 1); if (sortData.result != TCL_OK) { result = sortData.result; goto done; } if (sawCmd) Tcl_ResetResult(interp); if (notReally) { Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); Tcl_Obj *itemObj; /* Smallest to largest */ if (sortData.columns[0].order == 1) { for (i = 0; i < count; i++) { itemObj = sortData.items[i].obj; if (itemObj == NULL) itemObj = TreeItem_ToObj(tree, sortData.items[i].item); Tcl_ListObjAppendElement(interp, listObj, itemObj); } } /* Largest to smallest */ else { for (i = count - 1; i >= 0; i--) { itemObj = sortData.items[i].obj; if (itemObj == NULL) itemObj = TreeItem_ToObj(tree, sortData.items[i].item); Tcl_ListObjAppendElement(interp, listObj, itemObj); } } Tcl_SetObjResult(interp, listObj); goto done; } first = first->prevSibling; last = last->nextSibling; /* Smallest to largest */ if (sortData.columns[0].order == 1) { for (i = 0; i < count - 1; i++) { sortData.items[i].item->nextSibling = sortData.items[i + 1].item; sortData.items[i + 1].item->prevSibling = sortData.items[i].item; } indexF = 0; indexL = count - 1; } /* Largest to smallest */ else { for (i = count - 1; i > 0; i--) { sortData.items[i].item->nextSibling = sortData.items[i - 1].item; sortData.items[i - 1].item->prevSibling = sortData.items[i].item; } indexF = count - 1; indexL = 0; } lastChild = item->lastChild; sortData.items[indexF].item->prevSibling = first; if (first) first->nextSibling = sortData.items[indexF].item; else item->firstChild = sortData.items[indexF].item; sortData.items[indexL].item->nextSibling = last; if (last) last->prevSibling = sortData.items[indexL].item; else item->lastChild = sortData.items[indexL].item; /* Redraw the lines of the old/new lastchild */ if ((item->lastChild != lastChild) && tree->showLines && (tree->columnTree != NULL)) { if (lastChild->dInfo != NULL) Tree_InvalidateItemDInfo(tree, tree->columnTree, lastChild, NULL); if (item->lastChild->dInfo != NULL) Tree_InvalidateItemDInfo(tree, tree->columnTree, item->lastChild, NULL); } tree->updateIndex = 1; Tree_DInfoChanged(tree, DINFO_REDO_RANGES); done: for (i = 0; i < count; i++) { if (sortData.items[i].obj != NULL) { Tcl_DecrRefCount(sortData.items[i].obj); } } for (i = 0; i < sortData.columnCount; i++) { if (sortData.columns[i].sortBy == SORT_COMMAND) { Tcl_DecrRefCount(sortData.columns[i].command); } } ckfree((char *) sortData.item1s); ckfree((char *) sortData.items); if (tree->debug.enable && tree->debug.data) { Tree_Debug(tree); } return result; } /* *---------------------------------------------------------------------- * * TreeItemList_Sort -- * * Sorts a list of items. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TILSCompare( CONST VOID *first_, CONST VOID *second_ ) { TreeItem first = *(TreeItem *) first_; TreeItem second = *(TreeItem *) second_; return first->index - second->index; } void TreeItemList_Sort( TreeItemList *items ) { Tree_UpdateItemIndex(items->tree); /* TkTable uses this, but mentions possible lack of thread-safety. */ qsort((VOID *) TreeItemList_Items(items), (size_t) TreeItemList_Count(items), sizeof(TreeItem), TILSCompare); } /* *---------------------------------------------------------------------- * * ItemStateCmd -- * * This procedure is invoked to process the [item state] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ItemStateCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; static CONST char *commandNames[] = { "forcolumn", "get", "set", (char *) NULL }; enum { COMMAND_FORCOLUMN, COMMAND_GET, COMMAND_SET }; int index; TreeItem item; if (objc < 5) { Tcl_WrongNumArgs(interp, 3, objv, "command item ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], commandNames, "command", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { /* T item state forcolumn I C ?stateList? */ case COMMAND_FORCOLUMN: { TreeItemList itemList; TreeColumnList columns; TreeColumn treeColumn; Tcl_Obj *listObj; Column *column; int columnIndex; int i, states[3], stateOn, stateOff; ItemForEach iter; ColumnForEach citer; int flags = IFO_NOT_NULL; int result = TCL_OK; if (objc < 6 || objc > 7) { Tcl_WrongNumArgs(interp, 4, objv, "item column ?stateList?"); return TCL_ERROR; } /* Without a stateList only one item is accepted. */ if (objc == 6) flags |= IFO_NOT_MANY; if (TreeItemList_FromObj(tree, objv[4], &itemList, flags) != TCL_OK) return TCL_ERROR; TreeColumnList_Init(tree, &columns, 0); if (objc == 6) { item = TreeItemList_Nth(&itemList, 0); if (Item_FindColumnFromObj(tree, item, objv[5], &column, &columnIndex) != TCL_OK) { result = TCL_ERROR; goto doneFORC; } if ((column == NULL) || !column->cstate) goto doneFORC; listObj = Tcl_NewListObj(0, NULL); for (i = 0; i < 32; i++) { if (tree->stateNames[i] == NULL) continue; if (column->cstate & (1L << i)) { Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj(tree->stateNames[i], -1)); } } Tcl_SetObjResult(interp, listObj); goto doneFORC; } if (TreeColumnList_FromObj(tree, objv[5], &columns, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; goto doneFORC; } if (Tree_StateFromListObj(tree, objv[6], states, SFO_NOT_STATIC) != TCL_OK) { result = TCL_ERROR; goto doneFORC; } if ((states[0] | states[1] | states[2]) == 0) goto doneFORC; ITEM_FOR_EACH(item, &itemList, NULL, &iter) { COLUMN_FOR_EACH(treeColumn, &columns, NULL, &citer) { columnIndex = TreeColumn_Index(treeColumn); column = Item_CreateColumn(tree, item, columnIndex, NULL); stateOn = states[STATE_OP_ON]; stateOff = states[STATE_OP_OFF]; stateOn |= ~column->cstate & states[STATE_OP_TOGGLE]; stateOff |= column->cstate & states[STATE_OP_TOGGLE]; Column_ChangeState(tree, item, column, treeColumn, stateOff, stateOn); } } doneFORC: TreeColumnList_Free(&columns); TreeItemList_Free(&itemList); return result; } /* T item state get I ?state? */ case COMMAND_GET: { Tcl_Obj *listObj; int i, states[3]; if (objc > 6) { Tcl_WrongNumArgs(interp, 5, objv, "?state?"); return TCL_ERROR; } if (TreeItem_FromObj(tree, objv[4], &item, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if (objc == 6) { states[STATE_OP_ON] = 0; if (Tree_StateFromObj(tree, objv[5], states, NULL, SFO_NOT_OFF | SFO_NOT_TOGGLE) != TCL_OK) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewBooleanObj((item->state & states[STATE_OP_ON]) != 0)); break; } listObj = Tcl_NewListObj(0, NULL); for (i = 0; i < 32; i++) { if (tree->stateNames[i] == NULL) continue; if (item->state & (1L << i)) { Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj(tree->stateNames[i], -1)); } } Tcl_SetObjResult(interp, listObj); break; } /* T item state set I ?I? {state ...} */ case COMMAND_SET: { TreeItemList itemList, item2List; int states[3], stateOn, stateOff; ItemForEach iter; int result = TCL_OK; if (objc < 6 || objc > 7) { Tcl_WrongNumArgs(interp, 5, objv, "?last? stateList"); return TCL_ERROR; } if (TreeItemList_FromObj(tree, objv[4], &itemList, IFO_NOT_NULL) != TCL_OK) return TCL_ERROR; if (objc == 6) { TreeItemList_Init(tree, &item2List, 0); } if (objc == 7) { if (TreeItemList_FromObj(tree, objv[5], &item2List, IFO_NOT_NULL) != TCL_OK) { result = TCL_ERROR; goto doneSET; } } if (Tree_StateFromListObj(tree, objv[objc - 1], states, SFO_NOT_STATIC) != TCL_OK) { result = TCL_ERROR; goto doneSET; } if ((states[0] | states[1] | states[2]) == 0) goto doneSET; ITEM_FOR_EACH(item, &itemList, &item2List, &iter) { stateOn = states[STATE_OP_ON]; stateOff = states[STATE_OP_OFF]; stateOn |= ~item->state & states[STATE_OP_TOGGLE]; stateOff |= item->state & states[STATE_OP_TOGGLE]; TreeItem_ChangeState(tree, item, stateOff, stateOn); } if (iter.error) result = TCL_ERROR; doneSET: TreeItemList_Free(&itemList); TreeItemList_Free(&item2List); return result; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * ItemTagCmd -- * * This procedure is invoked to process the [item tag] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int ItemTagCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; static CONST char *commandNames[] = { "add", "expr", "names", "remove", (char *) NULL }; enum { COMMAND_ADD, COMMAND_EXPR, COMMAND_NAMES, COMMAND_REMOVE }; int index; ItemForEach iter; TreeItemList items; TreeItem item; int result = TCL_OK; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { /* T item tag add I tagList */ case COMMAND_ADD: { int i, numTags; Tcl_Obj **listObjv; Tk_Uid staticTags[STATIC_SIZE], *tags = staticTags; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "item tagList"); return TCL_ERROR; } if (TreeItemList_FromObj(tree, objv[4], &items, IFO_NOT_NULL) != TCL_OK) { return TCL_ERROR; } if (Tcl_ListObjGetElements(interp, objv[5], &numTags, &listObjv) != TCL_OK) { result = TCL_ERROR; break; } STATIC_ALLOC(tags, Tk_Uid, numTags); for (i = 0; i < numTags; i++) { tags[i] = Tk_GetUid(Tcl_GetString(listObjv[i])); } ITEM_FOR_EACH(item, &items, NULL, &iter) { item->tagInfo = TagInfo_Add(tree, item->tagInfo, tags, numTags); } STATIC_FREE(tags, Tk_Uid, numTags); break; } /* T item tag expr I tagExpr */ case COMMAND_EXPR: { TagExpr expr; int ok = TRUE; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "item tagExpr"); return TCL_ERROR; } if (TreeItemList_FromObj(tree, objv[4], &items, IFO_NOT_NULL) != TCL_OK) { return TCL_ERROR; } if (TagExpr_Init(tree, objv[5], &expr) != TCL_OK) { result = TCL_ERROR; break; } ITEM_FOR_EACH(item, &items, NULL, &iter) { if (!TagExpr_Eval(&expr, item->tagInfo)) { ok = FALSE; break; } } TagExpr_Free(&expr); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ok)); break; } /* T item tag names I */ case COMMAND_NAMES: { Tcl_Obj *listObj; Tk_Uid *tags = NULL; int i, tagSpace, numTags = 0; if (objc != 5) { Tcl_WrongNumArgs(interp, 4, objv, "item"); return TCL_ERROR; } if (TreeItemList_FromObj(tree, objv[4], &items, IFO_NOT_NULL) != TCL_OK) { return TCL_ERROR; } ITEM_FOR_EACH(item, &items, NULL, &iter) { tags = TagInfo_Names(tree, item->tagInfo, tags, &numTags, &tagSpace); } if (numTags) { listObj = Tcl_NewListObj(0, NULL); for (i = 0; i < numTags; i++) { Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewStringObj((char *) tags[i], -1)); } Tcl_SetObjResult(interp, listObj); ckfree((char *) tags); } break; } /* T item tag remove I tagList */ case COMMAND_REMOVE: { int i, numTags; Tcl_Obj **listObjv; Tk_Uid staticTags[STATIC_SIZE], *tags = staticTags; if (objc != 6) { Tcl_WrongNumArgs(interp, 4, objv, "item tagList"); return TCL_ERROR; } if (TreeItemList_FromObj(tree, objv[4], &items, IFO_NOT_NULL) != TCL_OK) { return TCL_ERROR; } if (Tcl_ListObjGetElements(interp, objv[5], &numTags, &listObjv) != TCL_OK) { result = TCL_ERROR; break; } STATIC_ALLOC(tags, Tk_Uid, numTags); for (i = 0; i < numTags; i++) { tags[i] = Tk_GetUid(Tcl_GetString(listObjv[i])); } ITEM_FOR_EACH(item, &items, NULL, &iter) { item->tagInfo = TagInfo_Remove(tree, item->tagInfo, tags, numTags); } STATIC_FREE(tags, Tk_Uid, numTags); break; } } TreeItemList_Free(&items); return result; } #ifdef SELECTION_VISIBLE /* *---------------------------------------------------------------------- * * Tree_DeselectHidden -- * * Removes any selected items which are no longer ReallyVisible() * from the selection. * * Results: * None. * * Side effects: * event may be generated. * *---------------------------------------------------------------------- */ /* * FIXME: optimize all calls to this routine. * Optionally call Tree_DInfoChanged(tree, DINFO_REDO_SELECTION) instead. */ void Tree_DeselectHidden( TreeCtrl *tree /* Widget info. */ ) { TreeItemList items; Tcl_HashEntry *hPtr; Tcl_HashSearch search; TreeItem item; int i; if (tree->selectCount < 1) return; /* This call is slow for large lists. */ Tree_UpdateItemIndex(tree); TreeItemList_Init(tree, &items, tree->selectCount); hPtr = Tcl_FirstHashEntry(&tree->selection, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashKey(&tree->selection, hPtr); if (!TreeItem_ReallyVisible(tree, item)) TreeItemList_Append(&items, item); hPtr = Tcl_NextHashEntry(&search); } for (i = 0; i < TreeItemList_Count(&items); i++) Tree_RemoveFromSelection(tree, TreeItemList_Nth(&items, i)); if (TreeItemList_Count(&items)) { TreeNotify_Selection(tree, NULL, &items); } TreeItemList_Free(&items); } #endif /* SELECTION_VISIBLE */ /* *---------------------------------------------------------------------- * * TreeItemCmd -- * * This procedure is invoked to process the [item] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeItemCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; enum { COMMAND_ANCESTORS, COMMAND_BBOX, COMMAND_CGET, COMMAND_CHILDREN, COMMAND_COLLAPSE, COMMAND_COMPARE, #ifdef DEPRECATED COMMAND_COMPLEX, #endif COMMAND_CONFIGURE, COMMAND_COUNT, COMMAND_CREATE, COMMAND_DELETE, COMMAND_DESCENDANTS, COMMAND_DUMP, COMMAND_ELEMENT, COMMAND_ENABLED, COMMAND_EXPAND, COMMAND_FIRSTCHILD, COMMAND_ID, COMMAND_IMAGE, COMMAND_ISANCESTOR, COMMAND_ISOPEN, COMMAND_LASTCHILD, COMMAND_NEXTSIBLING, COMMAND_NUMCHILDREN, COMMAND_ORDER, COMMAND_PARENT, COMMAND_PREVSIBLING, COMMAND_RANGE, COMMAND_REMOVE, COMMAND_RNC, COMMAND_SORT, COMMAND_SPAN, COMMAND_STATE, COMMAND_STYLE, COMMAND_TAG, COMMAND_TEXT, COMMAND_TOGGLE }; /* AF_xxx must not conflict with IFO_xxx. */ #define AF_NOT_ANCESTOR 0x00010000 /* item can't be ancestor of other item */ #define AF_NOT_EQUAL 0x00020000 /* second item can't be same as first */ #define AF_SAMEROOT 0x00040000 /* both items must be descendants of a * common ancestor */ #define AF_NOT_ITEM 0x00080000 /* arg is not an Item */ #define AF_NOT_DELETED 0x00100000 /* item can't be deleted */ struct { char *cmdName; int minArgs; int maxArgs; int flags; /* AF_xxx | IFO_xxx for 1st arg. */ int flags2; /* AF_xxx | IFO_xxx for 2nd arg. */ int flags3; /* AF_xxx | IFO_xxx for 3rd arg. */ char *argString; Tcl_ObjCmdProc *proc; } argInfo[] = { { "ancestors", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "bbox", 1, 3, IFO_NOT_MANY | IFO_NOT_NULL, AF_NOT_ITEM, AF_NOT_ITEM, "item ?column? ?element?", NULL }, { "cget", 2, 2, IFO_NOT_MANY | IFO_NOT_NULL, AF_NOT_ITEM, 0, "item option", NULL }, { "children", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "collapse", 1, 2, IFO_NOT_NULL, AF_NOT_ITEM, 0, "item ?-recurse?", NULL}, { "compare", 3, 3, IFO_NOT_MANY | IFO_NOT_NULL, AF_NOT_ITEM, IFO_NOT_MANY | IFO_NOT_NULL | AF_SAMEROOT, "item1 op item2", NULL }, #ifdef DEPRECATED { "complex", 2, 100000, IFO_NOT_MANY | IFO_NOT_NULL, AF_NOT_ITEM, AF_NOT_ITEM, "item list ...", NULL }, #endif { "configure", 1, 100000, IFO_NOT_NULL, AF_NOT_ITEM, AF_NOT_ITEM, "item ?option? ?value? ?option value ...?", NULL }, { "count", 0, 1, 0, 0, 0, "?itemDesc?" , NULL}, { "create", 0, 0, 0, 0, 0, NULL, ItemCreateCmd }, { "delete", 1, 2, IFO_NOT_NULL, IFO_NOT_NULL | AF_SAMEROOT, 0, "first ?last?", NULL }, { "descendants", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "dump", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "element", 0, 0, 0, 0, 0, NULL, ItemElementCmd }, { "enabled", 1, 2, IFO_NOT_NULL, AF_NOT_ITEM, 0, "item ?boolean?", NULL }, { "expand", 1, 2, IFO_NOT_NULL, AF_NOT_ITEM, 0, "item ?-recurse?", NULL}, { "firstchild", 1, 2, IFO_NOT_MANY | IFO_NOT_NULL | AF_NOT_DELETED, IFO_NOT_MANY | IFO_NOT_NULL | IFO_NOT_ROOT | AF_NOT_ANCESTOR | AF_NOT_EQUAL | AF_NOT_DELETED, 0, "item ?newFirstChild?", NULL }, { "id", 1, 1, 0, 0, 0, "item", NULL }, { "image", 1, 100000, IFO_NOT_NULL, AF_NOT_ITEM, AF_NOT_ITEM, "item ?column? ?image? ?column image ...?", NULL }, { "isancestor", 2, 2, IFO_NOT_MANY | IFO_NOT_NULL, IFO_NOT_MANY | IFO_NOT_NULL, 0, "item item2", NULL }, { "isopen", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "lastchild", 1, 2, IFO_NOT_MANY | IFO_NOT_NULL | AF_NOT_DELETED, IFO_NOT_MANY | IFO_NOT_NULL | IFO_NOT_ROOT | AF_NOT_ANCESTOR | AF_NOT_EQUAL | AF_NOT_DELETED, 0, "item ?newLastChild?", NULL }, { "nextsibling", 1, 2, IFO_NOT_MANY | IFO_NOT_NULL | IFO_NOT_ROOT | IFO_NOT_ORPHAN, IFO_NOT_MANY | IFO_NOT_NULL | IFO_NOT_ROOT | AF_NOT_ANCESTOR | AF_NOT_EQUAL, 0, "item ?newNextSibling?", NULL }, { "numchildren", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "order", 1, 2, IFO_NOT_MANY | IFO_NOT_NULL, AF_NOT_ITEM, 0, "item ?-visible?", NULL }, { "parent", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "prevsibling", 1, 2, IFO_NOT_MANY | IFO_NOT_NULL | IFO_NOT_ROOT | IFO_NOT_ORPHAN, IFO_NOT_MANY | IFO_NOT_NULL | IFO_NOT_ROOT | AF_NOT_ANCESTOR | AF_NOT_EQUAL, 0, "item ?newPrevSibling?", NULL }, { "range", 2, 2, IFO_NOT_MANY | IFO_NOT_NULL, IFO_NOT_MANY | IFO_NOT_NULL | AF_SAMEROOT, 0, "first last", NULL }, { "remove", 1, 1, IFO_NOT_NULL | IFO_NOT_ROOT, 0, 0, "item", NULL }, { "rnc", 1, 1, IFO_NOT_MANY | IFO_NOT_NULL, 0, 0, "item", NULL }, { "sort", 0, 0, 0, 0, 0, NULL, ItemSortCmd }, { "span", 1, 100000, IFO_NOT_NULL, AF_NOT_ITEM, AF_NOT_ITEM, "item ?column? ?span? ?column span ...?", NULL }, { "state", 0, 0, 0, 0, 0, NULL, ItemStateCmd }, { "style", 0, 0, 0, 0, 0, NULL, ItemStyleCmd }, { "tag", 0, 0, 0, 0, 0, NULL, ItemTagCmd }, { "text", 1, 100000, IFO_NOT_NULL, AF_NOT_ITEM, AF_NOT_ITEM, "item ?column? ?text? ?column text ...?", NULL }, { "toggle", 1, 2, IFO_NOT_NULL, AF_NOT_ITEM, 0, "item ?-recurse?", NULL}, { NULL } }; int index; int numArgs = objc - 3; TreeItemList itemList, item2List; TreeItem item = NULL, item2 = NULL, child; ItemForEach iter; int result = TCL_OK; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObjStruct(interp, objv[2], argInfo, sizeof(argInfo[0]), "command", 0, &index) != TCL_OK) { return TCL_ERROR; } if (argInfo[index].proc != NULL) return argInfo[index].proc(clientData, interp, objc, objv); if ((numArgs < argInfo[index].minArgs) || (numArgs > argInfo[index].maxArgs)) { Tcl_WrongNumArgs(interp, 3, objv, argInfo[index].argString); return TCL_ERROR; } TreeItemList_Init(tree, &itemList, 0); TreeItemList_Init(tree, &item2List, 0); if ((numArgs >= 1) && !(argInfo[index].flags & AF_NOT_ITEM)) { if (TreeItemList_FromObj(tree, objv[3], &itemList, argInfo[index].flags & 0xFFFF) != TCL_OK) { goto errorExit; } item = TreeItemList_Nth(&itemList, 0); /* May be NULL. */ if ((argInfo[index].flags & AF_NOT_DELETED) && IS_DELETED(item)) { FormatResult(interp, "item %s%d is being deleted", tree->itemPrefix, item->id); goto errorExit; } } if (((numArgs >= 2) && !(argInfo[index].flags2 & AF_NOT_ITEM)) || ((numArgs >= 3) && !(argInfo[index].flags3 & AF_NOT_ITEM))) { int flags, obji; if (argInfo[index].flags2 & AF_NOT_ITEM) { obji = 5; flags = argInfo[index].flags3; } else { obji = 4; flags = argInfo[index].flags2; } if (TreeItemList_FromObj(tree, objv[obji], &item2List, flags & 0xFFFF) != TCL_OK) { goto errorExit; } ITEM_FOR_EACH(item2, &item2List, NULL, &iter) { if ((flags & AF_NOT_DELETED) && IS_DELETED(item2)) { FormatResult(interp, "item %s%d is being deleted", tree->itemPrefix, item2->id); goto errorExit; } if ((flags & AF_NOT_EQUAL) && (item == item2)) { FormatResult(interp, "item %s%d same as second item", tree->itemPrefix, item->id); goto errorExit; } if ((argInfo[index].flags & AF_NOT_ANCESTOR) && TreeItem_IsAncestor(tree, item, item2)) { FormatResult(interp, "item %s%d is ancestor of item %s%d", tree->itemPrefix, item->id, tree->itemPrefix, item2->id); goto errorExit; } if ((flags & AF_NOT_ANCESTOR) && TreeItem_IsAncestor(tree, item2, item)) { FormatResult(interp, "item %s%d is ancestor of item %s%d", tree->itemPrefix, item2->id, tree->itemPrefix, item->id); goto errorExit; } if ((flags & AF_SAMEROOT) && TreeItem_RootAncestor(tree, item) != TreeItem_RootAncestor(tree, item2)) { FormatResult(interp, "item %s%d and item %s%d don't share a common ancestor", tree->itemPrefix, item->id, tree->itemPrefix, item2->id); goto errorExit; } } item2 = TreeItemList_Nth(&item2List, 0); /* May be NULL. */ } switch (index) { case COMMAND_ANCESTORS: { Tcl_Obj *listObj; TreeItem parent = item->parent; if (parent == NULL) break; /* empty list */ listObj = Tcl_NewListObj(0, NULL); while (parent != NULL) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, parent)); parent = parent->parent; } Tcl_SetObjResult(interp, listObj); break; } /* T item bbox I ?C? ?E? */ case COMMAND_BBOX: { int x, y, w, h; int count; TreeColumn treeColumn; TreeRectangle rect; if (objc == 4) { if (Tree_ItemBbox(tree, item, COLUMN_LOCK_NONE, &x, &y, &w, &h) < 0) break; } else { if (TreeColumn_FromObj(tree, objv[4], &treeColumn, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) goto errorExit; /* Bounds of a column. */ if (objc == 5) { objc = 0; objv = NULL; /* Single element in a column. */ } else { objc -= 5; objv += 5; } count = TreeItem_GetRects(tree, item, treeColumn, objc, objv, &rect); if (count == 0) break; if (count == -1) goto errorExit; x = rect.x; y = rect.y; w = rect.width; h = rect.height; } FormatResult(interp, "%d %d %d %d", x - tree->xOrigin, y - tree->yOrigin, x - tree->xOrigin + w, y - tree->yOrigin + h); break; } case COMMAND_CGET: { Tcl_Obj *resultObjPtr; resultObjPtr = Tk_GetOptionValue(interp, (char *) item, tree->itemOptionTable, objv[4], tree->tkwin); if (resultObjPtr == NULL) goto errorExit; Tcl_SetObjResult(interp, resultObjPtr); break; } case COMMAND_CHILDREN: { if (item->numChildren != 0) { Tcl_Obj *listObj; listObj = Tcl_NewListObj(0, NULL); child = item->firstChild; while (child != NULL) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, child)); child = child->nextSibling; } Tcl_SetObjResult(interp, listObj); } break; } case COMMAND_COLLAPSE: case COMMAND_EXPAND: case COMMAND_TOGGLE: { int recurse = 0; int mode = 0; /* lint */ int i, count; TreeItemList items; if (numArgs == 2) { int len; char *s = Tcl_GetStringFromObj(objv[4], &len); if (strncmp(s, "-recurse", len)) { FormatResult(interp, "bad option \"%s\": must be -recurse", s); goto errorExit; } recurse = 1; } switch (index) { case COMMAND_COLLAPSE: mode = 0; break; case COMMAND_EXPAND: mode = 1; break; case COMMAND_TOGGLE: mode = -1; break; } TreeItemList_Init(tree, &items, 0); ITEM_FOR_EACH(item, &itemList, NULL, &iter) { TreeItemList_Append(&items, item); if (!iter.all && recurse) { TreeItem_ListDescendants(tree, item, &items); } } count = TreeItemList_Count(&items); for (i = 0; i < count; i++) { item = TreeItemList_Nth(&items, i); TreeItem_OpenClose(tree, item, mode); } TreeItemList_Free(&items); #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif break; } /* T item compare I op I */ case COMMAND_COMPARE: { static CONST char *opName[] = { "<", "<=", "==", ">=", ">", "!=", NULL }; int op, compare = 0, index1, index2; if (Tcl_GetIndexFromObj(interp, objv[4], opName, "comparison operator", 0, &op) != TCL_OK) goto errorExit; TreeItem_ToIndex(tree, item, &index1, NULL); TreeItem_ToIndex(tree, item2, &index2, NULL); switch (op) { case 0: compare = index1 < index2; break; case 1: compare = index1 <= index2; break; case 2: compare = index1 == index2; break; case 3: compare = index1 >= index2; break; case 4: compare = index1 > index2; break; case 5: compare = index1 != index2; break; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(compare)); break; } #ifdef DEPRECATED case COMMAND_COMPLEX: { int i, j, columnIndex; int objc1, objc2; Tcl_Obj **objv1, **objv2; TreeColumn treeColumn = tree->columns; Column *column; int eMask, cMask, iMask = 0; if (objc <= 4) break; columnIndex = 0; for (i = 4; i < objc; i++, columnIndex++, treeColumn = TreeColumn_Next(treeColumn)) { if (treeColumn == NULL) { FormatResult(interp, "column #%d doesn't exist", columnIndex); result = TCL_ERROR; goto doneComplex; } column = Item_FindColumn(tree, item, columnIndex); if (column == NULL) { FormatResult(interp, "item %s%d doesn't have column %s%d", tree->itemPrefix, item->id, tree->columnPrefix, TreeColumn_GetID(treeColumn)); result = TCL_ERROR; goto doneComplex; } /* List of element-configs per column */ if (Tcl_ListObjGetElements(interp, objv[i], &objc1, &objv1) != TCL_OK) { result = TCL_ERROR; goto doneComplex; } if (objc1 == 0) continue; if (column->style == NULL) { FormatResult(interp, "item %s%d column %s%d has no style", tree->itemPrefix, item->id, tree->columnPrefix, TreeColumn_GetID(treeColumn)); result = TCL_ERROR; goto doneComplex; } cMask = 0; for (j = 0; j < objc1; j++) { /* elem option value... */ if (Tcl_ListObjGetElements(interp, objv1[j], &objc2, &objv2) != TCL_OK) { result = TCL_ERROR; goto doneComplex; } if (objc2 < 3) { FormatResult(interp, "wrong # args: should be \"element option value ...\""); result = TCL_ERROR; goto doneComplex; } if (TreeStyle_ElementConfigure(tree, item, (TreeItemColumn) column, column->style, objv2[0], objc2 - 1, objv2 + 1, &eMask) != TCL_OK) { result = TCL_ERROR; goto doneComplex; } cMask |= eMask; iMask |= eMask; } if (cMask & CS_LAYOUT) TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); } doneComplex: if (iMask & CS_DISPLAY) Tree_InvalidateItemDInfo(tree, NULL, item, NULL); if (iMask & CS_LAYOUT) { Tree_InvalidateColumnWidth(tree, NULL); TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } break; } #endif /* DEPRECATED*/ /* T item configure I ?option? ?value? ?option value ...? */ case COMMAND_CONFIGURE: { if (objc <= 5) { Tcl_Obj *resultObjPtr; if (IS_ALL(item) || (TreeItemList_Count(&itemList) > 1)) { FormatResult(interp, "can't specify > 1 item for this command"); goto errorExit; } resultObjPtr = Tk_GetOptionInfo(interp, (char *) item, tree->itemOptionTable, (objc == 4) ? (Tcl_Obj *) NULL : objv[4], tree->tkwin); if (resultObjPtr == NULL) goto errorExit; Tcl_SetObjResult(interp, resultObjPtr); break; } ITEM_FOR_EACH(item, &itemList, NULL, &iter) { result = Item_Configure(tree, item, objc - 4, objv + 4); if (result != TCL_OK) break; } break; } case COMMAND_COUNT: { int count = tree->itemCount; if (objc == 4) { count = 0; ITEM_FOR_EACH(item, &itemList, &item2List, &iter) { count++; } } Tcl_SetObjResult(interp, Tcl_NewIntObj(count)); break; } case COMMAND_DELETE: { TreeItemList deleted, selected; int i, count; /* The root is never deleted */ if (tree->itemCount == 1) break; if (objc == 5) { if (item == NULL || item2 == NULL) { FormatResult(interp, "invalid range \"%s\" to \"%s\"", Tcl_GetString(objv[3]), Tcl_GetString(objv[4])); goto errorExit; } } /* * ITEM_FLAG_DELETED prevents us from adding the same item * twice to the 'deleted' list. It also prevents nested * calls to this command (through binding scripts) deleting * the same item twice. */ TreeItemList_Init(tree, &deleted, tree->itemCount - 1); TreeItemList_Init(tree, &selected, tree->selectCount); ITEM_FOR_EACH(item, &itemList, &item2List, &iter) { if (IS_ROOT(item)) continue; if (IS_DELETED(item)) continue; item->flags |= ITEM_FLAG_DELETED; TreeItemList_Append(&deleted, item); if (TreeItem_GetSelected(tree, item)) TreeItemList_Append(&selected, item); if (iter.all) continue; /* Check every descendant. */ if (item->firstChild == NULL) continue; item2 = item; while (item2->lastChild != NULL) item2 = item2->lastChild; item = item->firstChild; while (1) { if (IS_DELETED(item)) { /* Skip all descendants (they are already flagged). */ while (item->lastChild != NULL) item = item->lastChild; } else { item->flags |= ITEM_FLAG_DELETED; TreeItemList_Append(&deleted, item); if (TreeItem_GetSelected(tree, item)) TreeItemList_Append(&selected, item); } if (item == item2) break; item = TreeItem_Next(tree, item); } } count = TreeItemList_Count(&selected); if (count) { for (i = 0; i < count; i++) { item = TreeItemList_Nth(&selected, i); Tree_RemoveFromSelection(tree, item); } /* Generate event for selected items being deleted. */ TreeNotify_Selection(tree, NULL, &selected); } count = TreeItemList_Count(&deleted); if (count) { /* Generate event for items being deleted. */ TreeNotify_ItemDeleted(tree, &deleted); /* Remove every item from its parent. Needed because items * are deleted recursively. */ for (i = 0; i < count; i++) { item = TreeItemList_Nth(&deleted, i); TreeItem_RemoveFromParent(tree, item); } /* Delete the items. The item record will be freed when no * longer in use; however, the item cannot be referred to * by commands from this point on. */ for (i = 0; i < count; i++) { item = TreeItemList_Nth(&deleted, i); TreeItem_Delete(tree, item); } } TreeItemList_Free(&selected); TreeItemList_Free(&deleted); break; } case COMMAND_DESCENDANTS: { Tcl_Obj *listObj; if (item->firstChild == NULL) break; item2 = item; while (item2->lastChild != NULL) item2 = item2->lastChild; item = item->firstChild; listObj = Tcl_NewListObj(0, NULL); while (1) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); if (item == item2) break; item = TreeItem_Next(tree, item); } Tcl_SetObjResult(interp, listObj); break; } case COMMAND_DUMP: { Tree_UpdateItemIndex(tree); FormatResult(interp, "index %d indexVis %d", item->index, item->indexVis); break; } /* T item enabled I ?boolean? */ case COMMAND_ENABLED: { int enabled; TreeItemList newD; int stateOff, stateOn; if (objc == 4) { if (IS_ALL(item) || (TreeItemList_Count(&itemList) > 1)) { FormatResult(interp, "can't specify > 1 item for this command"); goto errorExit; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(item->state & STATE_ENABLED)); break; } if (Tcl_GetBooleanFromObj(interp, objv[4], &enabled) != TCL_OK) goto errorExit; stateOff = enabled ? 0 : STATE_ENABLED; stateOn = enabled ? STATE_ENABLED : 0; TreeItemList_Init(tree, &newD, tree->selectCount); ITEM_FOR_EACH(item, &itemList, NULL, &iter) { if (enabled != TreeItem_GetEnabled(tree, item)) { TreeItem_ChangeState(tree, item, stateOff, stateOn); /* Disabled items cannot be selected. */ if (!enabled && TreeItem_GetSelected(tree, item)) { Tree_RemoveFromSelection(tree, item); TreeItemList_Append(&newD, item); } } } if (TreeItemList_Count(&newD)) TreeNotify_Selection(tree, NULL, &newD); TreeItemList_Free(&newD); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(enabled)); break; } case COMMAND_FIRSTCHILD: { if (item2 != NULL && item2 != item->firstChild) { TreeItem_RemoveFromParent(tree, item2); item2->nextSibling = item->firstChild; if (item->firstChild != NULL) item->firstChild->prevSibling = item2; else item->lastChild = item2; item->firstChild = item2; item2->parent = item; item->numChildren++; TreeItem_AddToParent(tree, item2); #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif } if (item->firstChild != NULL) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item->firstChild)); break; } /* T item id I */ case COMMAND_ID: { Tcl_Obj *listObj; listObj = Tcl_NewListObj(0, NULL); ITEM_FOR_EACH(item, &itemList, NULL, &iter) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, item)); } Tcl_SetObjResult(interp, listObj); break; } case COMMAND_ISANCESTOR: { Tcl_SetObjResult(interp, Tcl_NewBooleanObj( TreeItem_IsAncestor(tree, item, item2))); break; } case COMMAND_ISOPEN: { Tcl_SetObjResult(interp, Tcl_NewBooleanObj(item->state & STATE_OPEN)); break; } case COMMAND_LASTCHILD: { /* Don't allow non-deleted items to become children of a * deleted item. */ if (item2 != NULL && item2 != item->lastChild) { TreeItem_RemoveFromParent(tree, item2); item2->prevSibling = item->lastChild; if (item->lastChild != NULL) item->lastChild->nextSibling = item2; else item->firstChild = item2; item->lastChild = item2; item2->parent = item; item->numChildren++; TreeItem_AddToParent(tree, item2); #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif } if (item->lastChild != NULL) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item->lastChild)); break; } case COMMAND_NEXTSIBLING: { if (item2 != NULL && item2 != item->nextSibling) { TreeItem_RemoveFromParent(tree, item2); item2->prevSibling = item; if (item->nextSibling != NULL) { item->nextSibling->prevSibling = item2; item2->nextSibling = item->nextSibling; } else item->parent->lastChild = item2; item->nextSibling = item2; item2->parent = item->parent; item->parent->numChildren++; TreeItem_AddToParent(tree, item2); #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif } if (item->nextSibling != NULL) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item->nextSibling)); break; } case COMMAND_NUMCHILDREN: { Tcl_SetObjResult(interp, Tcl_NewIntObj(item->numChildren)); break; } /* T item order I ?-visible? */ case COMMAND_ORDER: { int visible = FALSE; if (objc == 5) { int len; char *s = Tcl_GetStringFromObj(objv[4], &len); if ((s[0] == '-') && (strncmp(s, "-visible", len) == 0)) visible = TRUE; else { FormatResult(interp, "bad switch \"%s\": must be -visible", s); goto errorExit; } } Tree_UpdateItemIndex(tree); Tcl_SetObjResult(interp, Tcl_NewIntObj(visible ? item->indexVis : item->index)); break; } /* T item range I I */ case COMMAND_RANGE: { TreeItem itemFirst = item; TreeItem itemLast = item2; Tcl_Obj *listObj; if (itemFirst == itemLast) { Tcl_SetObjResult(interp, TreeItem_ToObj(tree, itemFirst)); break; } (void) TreeItem_FirstAndLast(tree, &itemFirst, &itemLast); listObj = Tcl_NewListObj(0, NULL); while (itemFirst != NULL) { Tcl_ListObjAppendElement(interp, listObj, TreeItem_ToObj(tree, itemFirst)); if (itemFirst == itemLast) break; itemFirst = TreeItem_Next(tree, itemFirst); } Tcl_SetObjResult(interp, listObj); break; } case COMMAND_PARENT: { if (item->parent != NULL) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item->parent)); break; } case COMMAND_PREVSIBLING: { if (item2 != NULL && item2 != item->prevSibling) { TreeItem_RemoveFromParent(tree, item2); item2->nextSibling = item; if (item->prevSibling != NULL) { item->prevSibling->nextSibling = item2; item2->prevSibling = item->prevSibling; } else item->parent->firstChild = item2; item->prevSibling = item2; item2->parent = item->parent; item->parent->numChildren++; TreeItem_AddToParent(tree, item2); #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif } if (item->prevSibling != NULL) Tcl_SetObjResult(interp, TreeItem_ToObj(tree, item->prevSibling)); break; } case COMMAND_REMOVE: { int removed = FALSE; ITEM_FOR_EACH(item, &itemList, NULL, &iter) { if (item->parent != NULL) { TreeItem_RemoveFromParent(tree, item); Tree_FreeItemDInfo(tree, item, NULL); removed = TRUE; } } if (!removed) break; if (tree->debug.enable && tree->debug.data) Tree_Debug(tree); Tree_InvalidateColumnWidth(tree, NULL); #ifdef SELECTION_VISIBLE Tree_DeselectHidden(tree); #endif break; } case COMMAND_RNC: { int row,col; if (Tree_ItemToRNC(tree, item, &row, &col) == TCL_OK) FormatResult(interp, "%d %d", row, col); break; } /* T item span I ?C? ?span? ?C span ...? */ case COMMAND_SPAN: { TreeColumn treeColumn = tree->columns; Column *column = item->columns; Tcl_Obj *listObj; struct columnSpan { TreeColumnList columns; int span; } staticCS[STATIC_SIZE], *cs = staticCS; int i, count = 0, span, changed = FALSE; ColumnForEach citer; if ((objc < 6) && (IS_ALL(item) || (TreeItemList_Count(&itemList) > 1))) { FormatResult(interp, "can't specify > 1 item for this command"); goto errorExit; } if (objc == 4) { listObj = Tcl_NewListObj(0, NULL); while (treeColumn != NULL) { Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(column ? column->span : 1)); treeColumn = TreeColumn_Next(treeColumn); if (column != NULL) column = column->next; } Tcl_SetObjResult(interp, listObj); break; } if (objc == 5) { if (Item_FindColumnFromObj(tree, item, objv[4], &column, NULL) != TCL_OK) { goto errorExit; } Tcl_SetObjResult(interp, Tcl_NewIntObj(column ? column->span : 1)); break; } if ((objc - 4) & 1) { FormatResult(interp, "missing argument after column \"%s\"", Tcl_GetString(objv[objc - 1])); goto errorExit; } /* Gather column/span pairs. */ STATIC_ALLOC(cs, struct columnSpan, objc / 2); for (i = 4; i < objc; i += 2) { if (TreeColumnList_FromObj(tree, objv[i], &cs[count].columns, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; goto doneSPAN; } if (Tcl_GetIntFromObj(interp, objv[i + 1], &span) != TCL_OK) { result = TCL_ERROR; goto doneSPAN; } if (span <= 0) { FormatResult(interp, "bad span \"%d\": must be > 0", span); result = TCL_ERROR; goto doneSPAN; } cs[count].span = span; count++; } ITEM_FOR_EACH(item, &itemList, NULL, &iter) { int changedI = FALSE; for (i = 0; i < count; i++) { COLUMN_FOR_EACH(treeColumn, &cs[i].columns, NULL, &citer) { column = Item_CreateColumn(tree, item, TreeColumn_Index(treeColumn), NULL); if (column->span != cs[i].span) { if (cs[i].span > 1) { item->flags &= ~ITEM_FLAG_SPANS_SIMPLE; } TreeItem_SpansInvalidate(tree, item); column->span = cs[i].span; TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); changedI = TRUE; Tree_InvalidateColumnWidth(tree, treeColumn); } } } if (changedI) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); changed = TRUE; } } if (changed) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); doneSPAN: for (i = 0; i < count; i++) { TreeColumnList_Free(&cs[i].columns); } STATIC_FREE(cs, struct columnSpan, objc / 2); break; } /* T item image I ?C? ?image? ?C image ...? */ case COMMAND_IMAGE: /* T item text I ?C? ?text? ?C text ...? */ case COMMAND_TEXT: { TreeColumn treeColumn = tree->columns; Column *column; Tcl_Obj *objPtr; int isImage = (index == COMMAND_IMAGE); struct columnObj { TreeColumnList columns; Tcl_Obj *obj; } staticCO[STATIC_SIZE], *co = staticCO; int i, count = 0, changed = FALSE, columnIndex; ColumnForEach citer; if ((objc < 6) && (IS_ALL(item) || (TreeItemList_Count(&itemList) > 1))) { FormatResult(interp, "can't specify > 1 item for this command"); goto errorExit; } if (objc == 4) { Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); column = item->columns; while (treeColumn != NULL) { if ((column != NULL) && (column->style != NULL)) objPtr = isImage ? TreeStyle_GetImage(tree, column->style) : TreeStyle_GetText(tree, column->style); else objPtr = NULL; if (objPtr == NULL) objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(interp, listObj, objPtr); treeColumn = TreeColumn_Next(treeColumn); if (column != NULL) column = column->next; } Tcl_SetObjResult(interp, listObj); break; } if (objc == 5) { if (Item_FindColumnFromObj(tree, item, objv[4], &column, NULL) != TCL_OK) { goto errorExit; } if ((column != NULL) && (column->style != NULL)) { objPtr = isImage ? TreeStyle_GetImage(tree, column->style) : TreeStyle_GetText(tree, column->style); if (objPtr != NULL) Tcl_SetObjResult(interp, objPtr); } break; } if ((objc - 4) & 1) { FormatResult(interp, "missing argument after column \"%s\"", Tcl_GetString(objv[objc - 1])); goto errorExit; } /* Gather column/obj pairs. */ STATIC_ALLOC(co, struct columnObj, objc / 2); for (i = 4; i < objc; i += 2) { if (TreeColumnList_FromObj(tree, objv[i], &co[count].columns, CFO_NOT_NULL | CFO_NOT_TAIL) != TCL_OK) { result = TCL_ERROR; goto doneTEXT; } co[count].obj = objv[i + 1]; count++; } ITEM_FOR_EACH(item, &itemList, NULL, &iter) { int changedI = FALSE; for (i = 0; i < count; i++) { COLUMN_FOR_EACH(treeColumn, &co[i].columns, NULL, &citer) { columnIndex = TreeColumn_Index(treeColumn); column = Item_FindColumn(tree, item, columnIndex); if ((column == NULL) || (column->style == NULL)) { NoStyleMsg(tree, item, columnIndex); result = TCL_ERROR; goto doneTEXT; } result = isImage ? TreeStyle_SetImage(tree, item, (TreeItemColumn) column, column->style, co[i].obj) : TreeStyle_SetText(tree, item, (TreeItemColumn) column, column->style, co[i].obj); if (result != TCL_OK) goto doneTEXT; TreeItemColumn_InvalidateSize(tree, (TreeItemColumn) column); Tree_InvalidateColumnWidth(tree, treeColumn); changedI = TRUE; } } if (changedI) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); changed = TRUE; } } if (changed) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); doneTEXT: for (i = 0; i < count; i++) { TreeColumnList_Free(&co[i].columns); } STATIC_FREE(co, struct columnObj, objc / 2); break; } } TreeItemList_Free(&itemList); TreeItemList_Free(&item2List); return result; errorExit: TreeItemList_Free(&itemList); TreeItemList_Free(&item2List); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TreeItem_Debug -- * * Perform some sanity checks on an Item and its descendants. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_Debug( TreeCtrl *tree, /* Widget info. */ TreeItem item /* Item token. */ ) { TreeItem child; Tcl_Interp *interp = tree->interp; int count; if (item->parent == item) { FormatResult(interp, "parent of %d is itself", item->id); return TCL_ERROR; } if (item->parent == NULL) { if (item->prevSibling != NULL) { FormatResult(interp, "parent of %d is nil, prevSibling is not nil", item->id); return TCL_ERROR; } if (item->nextSibling != NULL) { FormatResult(interp, "parent of %d is nil, nextSibling is not nil", item->id); return TCL_ERROR; } } if (item->prevSibling != NULL) { if (item->prevSibling == item) { FormatResult(interp, "prevSibling of %d is itself", item->id); return TCL_ERROR; } if (item->prevSibling->nextSibling != item) { FormatResult(interp, "item%d.prevSibling.nextSibling is not it", item->id); return TCL_ERROR; } } if (item->nextSibling != NULL) { if (item->nextSibling == item) { FormatResult(interp, "nextSibling of %d is itself", item->id); return TCL_ERROR; } if (item->nextSibling->prevSibling != item) { FormatResult(interp, "item%d.nextSibling->prevSibling is not it", item->id); return TCL_ERROR; } } if (item->numChildren < 0) { FormatResult(interp, "numChildren of %d is %d", item->id, item->numChildren); return TCL_ERROR; } if (item->numChildren == 0) { if (item->firstChild != NULL) { FormatResult(interp, "item%d.numChildren is zero, firstChild is not nil", item->id); return TCL_ERROR; } if (item->lastChild != NULL) { FormatResult(interp, "item%d.numChildren is zero, lastChild is not nil", item->id); return TCL_ERROR; } } if (item->numChildren > 0) { if (item->firstChild == NULL) { FormatResult(interp, "item%d.firstChild is nil", item->id); return TCL_ERROR; } if (item->firstChild == item) { FormatResult(interp, "item%d.firstChild is itself", item->id); return TCL_ERROR; } if (item->firstChild->parent != item) { FormatResult(interp, "item%d.firstChild.parent is not it", item->id); return TCL_ERROR; } if (item->firstChild->prevSibling != NULL) { FormatResult(interp, "item%d.firstChild.prevSibling is not nil", item->id); return TCL_ERROR; } if (item->lastChild == NULL) { FormatResult(interp, "item%d.lastChild is nil", item->id); return TCL_ERROR; } if (item->lastChild == item) { FormatResult(interp, "item%d.lastChild is itself", item->id); return TCL_ERROR; } if (item->lastChild->parent != item) { FormatResult(interp, "item%d.lastChild.parent is not it", item->id); return TCL_ERROR; } if (item->lastChild->nextSibling != NULL) { FormatResult(interp, "item%d.lastChild.nextSibling is not nil", item->id); return TCL_ERROR; } /* Count number of children */ count = 0; child = item->firstChild; while (child != NULL) { count++; child = child->nextSibling; } if (count != item->numChildren) { FormatResult(interp, "item%d.numChildren is %d, but counted %d", item->id, item->numChildren, count); return TCL_ERROR; } /* Debug each child recursively */ child = item->firstChild; while (child != NULL) { if (child->parent != item) { FormatResult(interp, "child->parent of %d is not it", item->id); return TCL_ERROR; } if (TreeItem_Debug(tree, child) != TCL_OK) return TCL_ERROR; child = child->nextSibling; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * SpanWalkProc_Identify -- * * Callback routine to TreeItem_WalkSpans for TreeItem_Identify. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int SpanWalkProc_Identify( TreeCtrl *tree, TreeItem item, SpanInfo *spanPtr, StyleDrawArgs *drawArgs, ClientData clientData ) { struct { int x; int y; char *buf; } *data = clientData; if ((data->x < drawArgs->x + drawArgs->indent) || (data->x >= drawArgs->x + drawArgs->width)) return 0; sprintf(data->buf + strlen(data->buf), " column %s%d", tree->columnPrefix, TreeColumn_GetID(spanPtr->treeColumn)); if (drawArgs->style != NULL) { char *elem = TreeStyle_Identify(drawArgs, data->x, data->y); if (elem != NULL) sprintf(data->buf + strlen(data->buf), " elem %s", elem); } return 1; /* stop */ } /* *---------------------------------------------------------------------- * * TreeItem_Identify -- * * Determine which column and element the given point is in. * This is used by the [identify] widget command. * * Results: * If the Item is not ReallyVisible() or no columns are visible * then buf[] is untouched. Otherwise the given string may be * appended with "column C" followed by "elem E" although both * are optional. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_Identify( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int lock, /* Columns to hit-test. */ int x, int y, /* Item coords to hit-test with. */ char *buf /* NULL-terminated string which may be * appended. */ ) { int left, top, width, height; struct { int x; int y; char *buf; } clientData; if (Tree_ItemBbox(tree, item, lock, &left, &top, &width, &height) < 0) return; /* Tree_ItemBbox returns canvas coords. x/y are item coords. */ clientData.x = x; clientData.y = y; clientData.buf = buf; TreeItem_WalkSpans(tree, item, lock, 0, 0, width, height, SpanWalkProc_Identify, (ClientData) &clientData); } /* *---------------------------------------------------------------------- * * SpanWalkProc_Identify2 -- * * Callback routine to TreeItem_WalkSpans for TreeItem_Identify2. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int SpanWalkProc_Identify2( TreeCtrl *tree, TreeItem item, SpanInfo *spanPtr, StyleDrawArgs *drawArgs, ClientData clientData ) { Tcl_Obj *subListObj; struct { int x1; int y1; int x2; int y2; Tcl_Obj *listObj; } *data = clientData; if ((data->x2 < drawArgs->x + drawArgs->indent) || (data->x1 >= drawArgs->x + drawArgs->width)) return 0; subListObj = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(tree->interp, subListObj, TreeColumn_ToObj(tree, spanPtr->treeColumn)); if (drawArgs->style != NULL) { StyleDrawArgs drawArgsCopy = *drawArgs; TreeStyle_Identify2(&drawArgsCopy, data->x1, data->y1, data->x2, data->y2, subListObj); } Tcl_ListObjAppendElement(tree->interp, data->listObj, subListObj); return drawArgs->x + drawArgs->width >= data->x2; } /* *---------------------------------------------------------------------- * * TreeItem_Identify2 -- * * Determine which columns and elements intersect the given * area. This is used by the [marquee identify] widget command. * * Results: * If the Item is not ReallyVisible() or no columns are visible * then listObj is untouched. Otherwise the list is appended * with C {E ...} C {E...}. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeItem_Identify2( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int x1, int y1, /* Top-left of area to hit-test. */ int x2, int y2, /* Bottom-right of area to hit-test. */ Tcl_Obj *listObj /* Initialized list object. */ ) { int left, top, width, height; struct { int x1; int y1; int x2; int y2; Tcl_Obj *listObj; } clientData; if (Tree_ItemBbox(tree, item, COLUMN_LOCK_NONE, &left, &top, &width, &height) < 0) return; /* Tree_ItemBbox returns canvas coords. x1 etc are canvas coords. */ clientData.x1 = x1; clientData.y1 = y1; clientData.x2 = x2; clientData.y2 = y2; clientData.listObj = listObj; TreeItem_WalkSpans(tree, item, COLUMN_LOCK_NONE, left, top, width, height, SpanWalkProc_Identify2, (ClientData) &clientData); } /* *---------------------------------------------------------------------- * * SpanWalkProc_GetRects -- * * Callback routine to TreeItem_WalkSpans for TreeItem_GetRects. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int SpanWalkProc_GetRects( TreeCtrl *tree, TreeItem item, SpanInfo *spanPtr, StyleDrawArgs *drawArgs, ClientData clientData ) { int objc; Tcl_Obj *CONST *objv; struct { TreeColumn treeColumn; int count; Tcl_Obj *CONST *objv; TreeRectangle *rects; int result; } *data = clientData; if (spanPtr->treeColumn != data->treeColumn) return 0; /* Bounds of span. */ if (data->count == 0) { /* Not sure why I add 'indent' but for compatibility I will leave * it in. */ data->rects[0].x = drawArgs->x + drawArgs->indent; data->rects[0].y = drawArgs->y; data->rects[0].width = drawArgs->width - drawArgs->indent; data->rects[0].height = drawArgs->height; data->result = 1; /* # of rects */ return 1; /* stop */ } if (drawArgs->style == NULL) { NoStyleMsg(tree, item, TreeColumn_Index(spanPtr->treeColumn)); data->result = -1; /* error */ return 1; /* stop */ } if (data->count == -1) { /* All the elements. */ objc = 0; objv = NULL; } else { objc = data->count; objv = data->objv; } data->result = TreeStyle_GetElemRects(drawArgs, objc, objv, data->rects); return 1; /* stop */ } /* *---------------------------------------------------------------------- * * TreeItem_GetRects -- * * Returns zero or more bounding boxes for an item-column or * element(s) in an item-column. * * Results: * If the item is not visible, or has zero height/width, or the given * column is obscurred by a preceding span, or the column has zero * width or is not visible, the return value is zero. * * If count==0, the bounding box of the span is returned and the * return value is 1 (for a single rect). * * If count!=0, and the item-column does not have a style assigned, an * error is left in the interpreter result and the return value is -1. * * If count==-1, the bounding box of each element in the style is * returned and the return value is the number of elements in the style. * * If count>0, the bounding box of each element specified by the objv[] * array is returned and the return value is equal to count. If any of * the objv[] elements in not in the style, an error is left in the * interpreter result and the return value is -1. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeItem_GetRects( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ TreeColumn treeColumn, /* The column to get rects for. */ int count, /* -1 means get rects for all elements. * 0 means get bounds of the span. * 1+ means objv[] contains names of elements * to get rects for. */ Tcl_Obj *CONST objv[], /* Array of element names or NULL. */ TreeRectangle rects[] /* Out: returned bounding boxes. */ ) { int left, top, width, height; int lock = TreeColumn_Lock(treeColumn); struct { TreeColumn treeColumn; int count; Tcl_Obj *CONST *objv; TreeRectangle *rects; int result; } clientData; if (Tree_ItemBbox(tree, item, lock, &left, &top, &width, &height) < 0) return 0; clientData.treeColumn = treeColumn; clientData.count = count; clientData.objv = objv; clientData.rects = rects; clientData.result = 0; /* -1 error, 0 no rects, 1+ success */ TreeItem_WalkSpans(tree, item, lock, left, top, width, height, SpanWalkProc_GetRects, (ClientData) &clientData); return clientData.result; } /* *---------------------------------------------------------------------- * * TreeItem_Init -- * * Perform item-related initialization when a new TreeCtrl is * created. * * Results: * TCL_OK. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ int TreeItem_Init( TreeCtrl *tree /* Widget info. */ ) { ItemButtonCO_Init(itemOptionSpecs, "-button", ITEM_FLAG_BUTTON, ITEM_FLAG_BUTTON_AUTO); BooleanFlagCO_Init(itemOptionSpecs, "-visible", ITEM_FLAG_VISIBLE); tree->itemOptionTable = Tk_CreateOptionTable(tree->interp, itemOptionSpecs); tree->root = Item_AllocRoot(tree); tree->activeItem = tree->root; /* always non-null */ tree->anchorItem = tree->root; /* always non-null */ return TCL_OK; } tktreectrl-2.2.8/generic/tkTreeMarquee.c0000700000175600010010000002751110745240306016451 0ustar TimNone/* * tkTreeMarquee.c -- * * This module implements the selection rectangle for treectrl widgets. * * Copyright (c) 2002-2008 Tim Baker * * RCS: @(#) $Id: tkTreeMarquee.c,v 1.16 2008/01/22 01:03:02 treectrl Exp $ */ #include "tkTreeCtrl.h" typedef struct TreeMarquee_ TreeMarquee_; /* * The following structure holds info about the selection rectangle. * There is one of these per TreeCtrl. */ struct TreeMarquee_ { TreeCtrl *tree; Tk_OptionTable optionTable; int visible; /* -visible option. */ int x1, y1, x2, y2; /* Opposing corners. */ int onScreen; /* TRUE if it was drawn. */ int sx, sy; /* Offset of canvas from top-left * corner of the window when we * were drawn. */ }; #define MARQ_CONF_VISIBLE 0x0001 static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BOOLEAN, "-visible", (char *) NULL, (char *) NULL, "0", -1, Tk_Offset(TreeMarquee_, visible), 0, (ClientData) NULL, MARQ_CONF_VISIBLE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, 0, 0} }; /* *---------------------------------------------------------------------- * * TreeMarquee_Init -- * * Perform marquee-related initialization when a new TreeCtrl is * created. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ int TreeMarquee_Init( TreeCtrl *tree /* Widget info. */ ) { TreeMarquee marquee; marquee = (TreeMarquee) ckalloc(sizeof(TreeMarquee_)); memset(marquee, '\0', sizeof(TreeMarquee_)); marquee->tree = tree; marquee->optionTable = Tk_CreateOptionTable(tree->interp, optionSpecs); if (Tk_InitOptions(tree->interp, (char *) marquee, marquee->optionTable, tree->tkwin) != TCL_OK) { WFREE(marquee, TreeMarquee_); return TCL_ERROR; } tree->marquee = marquee; return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeMarquee_Free -- * * Free marquee-related resources when a TreeCtrl is deleted. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeMarquee_Free( TreeMarquee marquee /* Marquee token. */ ) { Tk_FreeConfigOptions((char *) marquee, marquee->optionTable, marquee->tree->tkwin); WFREE(marquee, TreeMarquee_); } /* *---------------------------------------------------------------------- * * TreeMarquee_Display -- * * Draw the selection rectangle if it is not already displayed and if * it's -visible option is TRUE. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void TreeMarquee_Display( TreeMarquee marquee /* Marquee token. */ ) { TreeCtrl *tree = marquee->tree; if (!marquee->onScreen && marquee->visible) { marquee->sx = 0 - tree->xOrigin; marquee->sy = 0 - tree->yOrigin; TreeMarquee_Draw(marquee, Tk_WindowId(tree->tkwin), marquee->sx, marquee->sy); marquee->onScreen = TRUE; } } /* *---------------------------------------------------------------------- * * TreeMarquee_Undisplay -- * * Erase the selection rectangle if it is displayed. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void TreeMarquee_Undisplay( TreeMarquee marquee /* Marquee token. */ ) { TreeCtrl *tree = marquee->tree; if (marquee->onScreen) { TreeMarquee_Draw(marquee, Tk_WindowId(tree->tkwin), marquee->sx, marquee->sy); marquee->onScreen = FALSE; } } /* *---------------------------------------------------------------------- * * TreeMarquee_Draw -- * * Draw (or erase) the selection rectangle. * * Results: * None. * * Side effects: * Stuff is drawn (or erased, since this is XOR drawing). * *---------------------------------------------------------------------- */ void TreeMarquee_Draw( TreeMarquee marquee, /* Marquee token. */ Drawable drawable, /* Where to draw. */ int x1, int y1 /* Offset of canvas from top-left corner * of the window. */ ) { TreeCtrl *tree = marquee->tree; int x, y, w, h; DotState dotState; x = MIN(marquee->x1, marquee->x2); w = abs(marquee->x1 - marquee->x2) + 1; y = MIN(marquee->y1, marquee->y2); h = abs(marquee->y1 - marquee->y2) + 1; TreeDotRect_Setup(tree, drawable, &dotState); TreeDotRect_Draw(&dotState, x1 + x, y1 + y, w, h); TreeDotRect_Restore(&dotState); } /* *---------------------------------------------------------------------- * * Marquee_Config -- * * This procedure is called to process an objc/objv list to set * configuration options for a Marquee. * * Results: * The return value is a standard Tcl result. If TCL_ERROR is * returned, then an error message is left in interp's result. * * Side effects: * Configuration information, such as text string, colors, font, * etc. get set for marquee; old resources get freed, if there * were any. Display changes may occur. * *---------------------------------------------------------------------- */ static int Marquee_Config( TreeMarquee marquee, /* Marquee record. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = marquee->tree; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; int mask; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) marquee, marquee->optionTable, objc, objv, tree->tkwin, &savedOptions, &mask) != TCL_OK) { mask = 0; continue; } /* xxx */ Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); /* xxx */ Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } if (mask & MARQ_CONF_VISIBLE) { TreeMarquee_Undisplay(marquee); TreeMarquee_Display(marquee); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeMarqueeCmd -- * * This procedure is invoked to process the [marquee] widget * command. See the user documentation for details on what it * does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeMarqueeCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; TreeMarquee marquee = tree->marquee; static CONST char *commandNames[] = { "anchor", "cget", "configure", "coords", "corner", "identify", (char *) NULL }; enum { COMMAND_ANCHOR, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_COORDS, COMMAND_CORNER, COMMAND_IDENTIFY }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { /* T marquee anchor ?x y?*/ case COMMAND_ANCHOR: { int x, y; if (objc != 3 && objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "?x y?"); return TCL_ERROR; } if (objc == 3) { FormatResult(interp, "%d %d", marquee->x1, marquee->y1); break; } if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) return TCL_ERROR; if ((x == marquee->x1) && (y == marquee->y1)) break; TreeMarquee_Undisplay(tree->marquee); marquee->x1 = x; marquee->y1 = y; TreeMarquee_Display(tree->marquee); break; } /* T marquee cget option */ case COMMAND_CGET: { Tcl_Obj *resultObjPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "option"); return TCL_ERROR; } resultObjPtr = Tk_GetOptionValue(interp, (char *) marquee, marquee->optionTable, objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } /* T marquee configure ?option? ?value? ?option value ...? */ case COMMAND_CONFIGURE: { Tcl_Obj *resultObjPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 3, objv, "?option? ?value?"); return TCL_ERROR; } if (objc <= 4) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) marquee, marquee->optionTable, (objc == 3) ? (Tcl_Obj *) NULL : objv[3], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } return Marquee_Config(marquee, objc - 3, objv + 3); } /* T marquee coords ?x y x y? */ case COMMAND_COORDS: { int x1, y1, x2, y2; if (objc != 3 && objc != 7) { Tcl_WrongNumArgs(interp, 3, objv, "?x y x y?"); return TCL_ERROR; } if (objc == 3) { FormatResult(interp, "%d %d %d %d", marquee->x1, marquee->y1, marquee->x2, marquee->y2); break; } if (Tcl_GetIntFromObj(interp, objv[3], &x1) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[4], &y1) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[5], &x2) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[6], &y2) != TCL_OK) return TCL_ERROR; if (x1 == marquee->x1 && y1 == marquee->y1 && x2 == marquee->x2 && y2 == marquee->y2) break; TreeMarquee_Undisplay(tree->marquee); marquee->x1 = x1; marquee->y1 = y1; marquee->x2 = x2; marquee->y2 = y2; TreeMarquee_Display(tree->marquee); break; } /* T marquee corner ?x y?*/ case COMMAND_CORNER: { int x, y; if (objc != 3 && objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "?x y?"); return TCL_ERROR; } if (objc == 3) { FormatResult(interp, "%d %d", marquee->x2, marquee->y2); break; } if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) return TCL_ERROR; if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) return TCL_ERROR; if (x == marquee->x2 && y == marquee->y2) break; TreeMarquee_Undisplay(tree->marquee); marquee->x2 = x; marquee->y2 = y; TreeMarquee_Display(tree->marquee); break; } /* T marquee identify */ case COMMAND_IDENTIFY: { int x1, y1, x2, y2, n = 0; int totalWidth = Tree_TotalWidth(tree); int totalHeight = Tree_TotalHeight(tree); TreeItemList items; Tcl_Obj *listObj; if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); return TCL_ERROR; } x1 = MIN(marquee->x1, marquee->x2); x2 = MAX(marquee->x1, marquee->x2); y1 = MIN(marquee->y1, marquee->y2); y2 = MAX(marquee->y1, marquee->y2); if (x2 <= 0) break; if (x1 >= totalWidth) break; if (y2 <= 0) break; if (y1 >= totalHeight) break; if (x1 < 0) x1 = 0; if (x2 > totalWidth) x2 = totalWidth; if (y1 < 0) y1 = 0; if (y2 > totalHeight) y2 = totalHeight; Tree_ItemsInArea(tree, &items, x1, y1, x2, y2); if (TreeItemList_Count(&items) == 0) { TreeItemList_Free(&items); break; } listObj = Tcl_NewListObj(0, NULL); for (n = 0; n < TreeItemList_Count(&items); n++) { Tcl_Obj *subListObj = Tcl_NewListObj(0, NULL); TreeItem item = TreeItemList_Nth(&items, n); Tcl_ListObjAppendElement(interp, subListObj, TreeItem_ToObj(tree, item)); TreeItem_Identify2(tree, item, x1, y1, x2, y2, subListObj); Tcl_ListObjAppendElement(interp, listObj, subListObj); } TreeItemList_Free(&items); Tcl_SetObjResult(interp, listObj); break; } } return TCL_OK; } tktreectrl-2.2.8/generic/tkTreeNotify.c0000700000175600010010000004577110760347544016343 0ustar TimNone/* * tkTreeNotify.c -- * * This module implements "qebind.c" events for treectrl widgets. * * Copyright (c) 2002-2008 Tim Baker * * RCS: @(#) $Id: tkTreeNotify.c,v 1.24 2008/02/22 20:02:26 hobbs2 Exp $ */ #include "tkTreeCtrl.h" static int EVENT_EXPAND, DETAIL_EXPAND_BEFORE, DETAIL_EXPAND_AFTER; static int EVENT_COLLAPSE, DETAIL_COLLAPSE_BEFORE, DETAIL_COLLAPSE_AFTER; static int EVENT_SELECTION; static int EVENT_ACTIVEITEM; static int EVENT_SCROLL, DETAIL_SCROLL_X, DETAIL_SCROLL_Y; static int EVENT_ITEM_DELETE; static int EVENT_ITEM_VISIBILITY; /* *---------------------------------------------------------------------- * * ExpandItem -- * * Append an item ID to a dynamic string. * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void ExpandItem( TreeCtrl *tree, /* Widget info. */ int id, /* Item ID. */ Tcl_DString *result /* Gets appended. Caller must initialize. */ ) { char buf[10 + TCL_INTEGER_SPACE]; (void) sprintf(buf, "%s%d", (tree->itemPrefixLen ? tree->itemPrefix : ""), id); Tcl_DStringAppend(result, buf, -1); } /* *---------------------------------------------------------------------- * * ExpandItemList -- * * Append a list of item IDs to a dynamic string. * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void ExpandItemList( TreeCtrl *tree, /* Widget info. */ TreeItemList *itemList, /* list of item IDs */ Tcl_DString *result /* Gets appended. Caller must initialize. */ ) { if (itemList == NULL) { Tcl_DStringAppend(result, "{}", 2); } else { int i, count; char buf[10 + TCL_INTEGER_SPACE]; Tcl_DStringStartSublist(result); count = TreeItemList_Count(itemList); for (i = 0; i < count; i++) { (void) sprintf(buf, "%s%d", (tree->itemPrefixLen ? tree->itemPrefix : ""), TreeItem_GetID(tree, TreeItemList_Nth(itemList, i))); Tcl_DStringAppendElement(result, buf); } Tcl_DStringEndSublist(result); } } /* *---------------------------------------------------------------------- * * DumpPercents -- * * Appends a sublist to a dynamic string. The sublist contains * %-char,value pairs. This is to handle the %? substitution. * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void DumpPercents( QE_ExpandArgs *args, /* %-substitution args. */ QE_ExpandProc proc, /* Function to return value for a given * %-char. */ CONST char *chars /* NULL-terminated list of %-chars. */ ) { char which = args->which; char buf[2]; int i; buf[1] = '\0'; Tcl_DStringStartSublist(args->result); for (i = 0; chars[i]; i++) { args->which = chars[i]; buf[0] = chars[i]; Tcl_DStringAppendElement(args->result, buf); Tcl_DStringAppend(args->result, " ", 1); (*proc)(args); } Tcl_DStringEndSublist(args->result); args->which = which; } /* *---------------------------------------------------------------------- * * Percents_Any -- * * Append a value for a single %-char to a dynamic string. This * function handles the default %-chars (d,e,P,W,T, and ?) and * calls QE_ExpandUnknown() for any unrecognized %-char. * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_Any( QE_ExpandArgs *args, /* %-substitution args. */ QE_ExpandProc proc, /* Function to return value for a given * %-char. */ CONST char *chars /* NULL-terminated list of %-chars. */ ) { struct { TreeCtrl *tree; } *data = args->clientData; char chars2[64]; switch (args->which) { case 'd': /* detail */ QE_ExpandDetail(args->bindingTable, args->event, args->detail, args->result); break; case 'e': /* event */ QE_ExpandEvent(args->bindingTable, args->event, args->result); break; case 'P': /* pattern */ QE_ExpandPattern(args->bindingTable, args->event, args->detail, args->result); break; case 'W': /* object */ QE_ExpandString((char *) args->object, args->result); break; case 'T': /* tree */ QE_ExpandString(Tk_PathName(data->tree->tkwin), args->result); break; case '?': strcpy(chars2, "TWPed"); strcat(chars2, chars); DumpPercents(args, proc, chars2); break; default: QE_ExpandUnknown(args->which, args->result); break; } } /* *---------------------------------------------------------------------- * * Percents_Expand -- * * %-substitution callback for . * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_Expand( QE_ExpandArgs *args /* %-substitution args. */ ) { struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ int id; } *data = args->clientData; switch (args->which) { case 'I': ExpandItem(data->tree, data->id, args->result); break; default: Percents_Any(args, Percents_Expand, "I"); break; } } /* *---------------------------------------------------------------------- * * Percents_ItemVisibility -- * * %-substitution callback for . * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_ItemVisibility( QE_ExpandArgs *args /* %-substitution args. */ ) { struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ TreeItemList *v; TreeItemList *h; } *data = args->clientData; TreeItemList *table; switch (args->which) { case 'v': case 'h': table = (args->which == 'v') ? data->v : data->h; ExpandItemList(data->tree, table, args->result); break; default: Percents_Any(args, Percents_ItemVisibility, "vh"); break; } } /* *---------------------------------------------------------------------- * * Percents_Selection -- * * %-substitution callback for . * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_Selection( QE_ExpandArgs *args /* %-substitution args. */ ) { struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ TreeItemList *select; TreeItemList *deselect; int count; } *data = args->clientData; TreeItemList *itemList; switch (args->which) { case 'c': QE_ExpandNumber(data->count, args->result); break; case 'D': case 'S': itemList = (args->which == 'D') ? data->deselect : data->select; ExpandItemList(data->tree, itemList, args->result); break; default: Percents_Any(args, Percents_Selection, "cSD"); break; } } /* *---------------------------------------------------------------------- * * Percents_ActiveItem -- * * %-substitution callback for . * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_ActiveItem( QE_ExpandArgs *args /* %-substitution args. */ ) { struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ int prev; int current; } *data = args->clientData; switch (args->which) { case 'c': ExpandItem(data->tree, data->current, args->result); break; case 'p': ExpandItem(data->tree, data->prev, args->result); break; default: Percents_Any(args, Percents_ActiveItem, "cp"); break; } } /* *---------------------------------------------------------------------- * * Percents_Scroll -- * * %-substitution callback for . * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_Scroll( QE_ExpandArgs *args /* %-substitution args. */ ) { struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ double lower; double upper; } *data = args->clientData; switch (args->which) { case 'l': QE_ExpandDouble(data->lower, args->result); break; case 'u': QE_ExpandDouble(data->upper, args->result); break; default: Percents_Any(args, Percents_Scroll, "lu"); break; } } /* *---------------------------------------------------------------------- * * TreeNotifyCmd -- * * This procedure is invoked to process the [notify] widget * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeNotifyCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; static CONST char *commandName[] = { "bind", "configure", "detailnames", "eventnames", "generate", "install", "linkage", "unbind", "uninstall", (char *) NULL }; enum { COMMAND_BIND, COMMAND_CONFIGURE, COMMAND_DETAILNAMES, COMMAND_EVENTNAMES, COMMAND_GENERATE, COMMAND_INSTALL, COMMAND_LINKAGE, COMMAND_UNBIND, COMMAND_UNINSTALL }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandName, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case COMMAND_BIND: { return QE_BindCmd(tree->bindingTable, 2, objc, objv); } case COMMAND_CONFIGURE: { return QE_ConfigureCmd(tree->bindingTable, 2, objc, objv); } /* T notify detailnames $eventName */ case COMMAND_DETAILNAMES: { char *eventName; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "eventName"); return TCL_ERROR; } eventName = Tcl_GetString(objv[3]); return QE_GetDetailNames(tree->bindingTable, eventName); } /* T notify eventnames */ case COMMAND_EVENTNAMES: { if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); return TCL_ERROR; } return QE_GetEventNames(tree->bindingTable); } case COMMAND_GENERATE: { return QE_GenerateCmd(tree->bindingTable, 2, objc, objv); } case COMMAND_INSTALL: { return QE_InstallCmd(tree->bindingTable, 2, objc, objv); } case COMMAND_LINKAGE: { return QE_LinkageCmd(tree->bindingTable, 2, objc, objv); } case COMMAND_UNBIND: { return QE_UnbindCmd(tree->bindingTable, 2, objc, objv); } case COMMAND_UNINSTALL: { return QE_UninstallCmd(tree->bindingTable, 2, objc, objv); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeNotify_OpenClose -- * * Generate an or event. * * Results: * Any scripts bound to the event are evaluated. * * Side effects: * Whatever binding scripts do. * *---------------------------------------------------------------------- */ void TreeNotify_OpenClose( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item token. */ int state, /* STATE_OPEN or 0 */ int before /* TRUE for event, FALSE for * event. */ ) { QE_Event event; struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ int id; } data; data.tree = tree; data.id = TreeItem_GetID(tree, item); if (state & STATE_OPEN) { event.type = EVENT_EXPAND; event.detail = before ? DETAIL_EXPAND_BEFORE : DETAIL_EXPAND_AFTER; } else { event.type = EVENT_COLLAPSE; event.detail = before ? DETAIL_COLLAPSE_BEFORE : DETAIL_COLLAPSE_AFTER; } event.clientData = (ClientData) &data; (void) QE_BindEvent(tree->bindingTable, &event); } /* *---------------------------------------------------------------------- * * TreeNotify_Selection -- * * Generate a event. * * Results: * Any scripts bound to the event are evaluated. * * Side effects: * Whatever binding scripts do. * *---------------------------------------------------------------------- */ void TreeNotify_Selection( TreeCtrl *tree, /* Widget info. */ TreeItemList *select, /* List of items or NULL. */ TreeItemList *deselect /* List of items or NULL. */ ) { QE_Event event; struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ TreeItemList *select; TreeItemList *deselect; int count; } data; data.tree = tree; data.select = select; data.deselect = deselect; data.count = tree->selectCount; event.type = EVENT_SELECTION; event.detail = 0; event.clientData = (ClientData) &data; (void) QE_BindEvent(tree->bindingTable, &event); } /* *---------------------------------------------------------------------- * * TreeNotify_ActiveItem -- * * Generate an event. * * Results: * Any scripts bound to the event are evaluated. * * Side effects: * Whatever binding scripts do. * *---------------------------------------------------------------------- */ void TreeNotify_ActiveItem( TreeCtrl *tree, /* Widget info. */ TreeItem itemPrev, /* Previous active item. */ TreeItem itemCur /* Current active item. */ ) { QE_Event event; struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ int prev; int current; } data; data.tree = tree; data.prev = TreeItem_GetID(tree, itemPrev); data.current = TreeItem_GetID(tree, itemCur); event.type = EVENT_ACTIVEITEM; event.detail = 0; event.clientData = (ClientData) &data; (void) QE_BindEvent(tree->bindingTable, &event); } /* *---------------------------------------------------------------------- * * TreeNotify_Scroll -- * * Generate a event. * * Results: * Any scripts bound to the event are evaluated. * * Side effects: * Whatever binding scripts do. * *---------------------------------------------------------------------- */ void TreeNotify_Scroll( TreeCtrl *tree, /* Widget info. */ double fractions[2], /* Fractions suitable for a scrollbar's * [set] command. */ int vertical /* TRUE for , FALSE for * . */ ) { QE_Event event; struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ double lower; double upper; } data; data.tree = tree; data.lower = fractions[0]; data.upper = fractions[1]; event.type = EVENT_SCROLL; event.detail = vertical ? DETAIL_SCROLL_Y : DETAIL_SCROLL_X; event.clientData = (ClientData) &data; (void) QE_BindEvent(tree->bindingTable, &event); } /* *---------------------------------------------------------------------- * * Percents_ItemDelete -- * * %-substitution callback for . * * Results: * DString gets longer. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ static void Percents_ItemDelete( QE_ExpandArgs *args /* %-substitution args. */ ) { struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ TreeItemList *items; } *data = args->clientData; switch (args->which) { case 'i': ExpandItemList(data->tree, data->items, args->result); break; default: Percents_Any(args, Percents_ItemDelete, "i"); break; } } /* *---------------------------------------------------------------------- * * TreeNotify_ItemDeleted -- * * Generate an event. * * Results: * Any scripts bound to the event are evaluated. * * Side effects: * Whatever binding scripts do. * *---------------------------------------------------------------------- */ void TreeNotify_ItemDeleted( TreeCtrl *tree, /* Widget info. */ TreeItemList *items /* List of items. */ ) { QE_Event event; struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ TreeItemList *items; } data; data.tree = tree; data.items = items; event.type = EVENT_ITEM_DELETE; event.detail = 0; event.clientData = (ClientData) &data; (void) QE_BindEvent(tree->bindingTable, &event); } /* *---------------------------------------------------------------------- * * TreeNotify_ItemVisibility -- * * Generate an event. * * Results: * Any scripts bound to the event are evaluated. * * Side effects: * Whatever binding scripts do. * *---------------------------------------------------------------------- */ void TreeNotify_ItemVisibility( TreeCtrl *tree, /* Widget info. */ TreeItemList *v, /* List of newly-visible items. */ TreeItemList *h /* List of newly-hidden items. */ ) { QE_Event event; struct { TreeCtrl *tree; /* Must be first. See Percents_Any(). */ TreeItemList *v; TreeItemList *h; } data; data.tree = tree; data.v = v; data.h = h; event.type = EVENT_ITEM_VISIBILITY; event.detail = 0; event.clientData = (ClientData) &data; (void) QE_BindEvent(tree->bindingTable, &event); } /* *---------------------------------------------------------------------- * * TreeNotify_Init -- * * Perform event-related initialization when a new TreeCtrl is * created. * * Results: * Installs all the static events and details. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ int TreeNotify_Init( TreeCtrl *tree /* Widget info. */ ) { tree->bindingTable = QE_CreateBindingTable(tree->interp); EVENT_EXPAND = QE_InstallEvent(tree->bindingTable, "Expand", Percents_Expand); DETAIL_EXPAND_BEFORE = QE_InstallDetail(tree->bindingTable, "before", EVENT_EXPAND, NULL); DETAIL_EXPAND_AFTER = QE_InstallDetail(tree->bindingTable, "after", EVENT_EXPAND, NULL); EVENT_COLLAPSE = QE_InstallEvent(tree->bindingTable, "Collapse", Percents_Expand); DETAIL_COLLAPSE_BEFORE = QE_InstallDetail(tree->bindingTable, "before", EVENT_COLLAPSE, NULL); DETAIL_COLLAPSE_AFTER = QE_InstallDetail(tree->bindingTable, "after", EVENT_COLLAPSE, NULL); EVENT_SELECTION = QE_InstallEvent(tree->bindingTable, "Selection", Percents_Selection); EVENT_ACTIVEITEM = QE_InstallEvent(tree->bindingTable, "ActiveItem", Percents_ActiveItem); EVENT_SCROLL = QE_InstallEvent(tree->bindingTable, "Scroll", Percents_Scroll); DETAIL_SCROLL_X = QE_InstallDetail(tree->bindingTable, "x", EVENT_SCROLL, NULL); DETAIL_SCROLL_Y = QE_InstallDetail(tree->bindingTable, "y", EVENT_SCROLL, NULL); EVENT_ITEM_DELETE = QE_InstallEvent(tree->bindingTable, "ItemDelete", Percents_ItemDelete); EVENT_ITEM_VISIBILITY = QE_InstallEvent(tree->bindingTable, "ItemVisibility", Percents_ItemVisibility); return TCL_OK; } tktreectrl-2.2.8/generic/tkTreeStyle.c0000700000175600010010000055260610762067722016172 0ustar TimNone/* * tkTreeStyle.c -- * * This module implements styles for treectrl widgets. * * Copyright (c) 2002-2008 Tim Baker * * RCS: @(#) $Id: tkTreeStyle.c,v 1.78 2008/02/29 20:49:22 treectrl Exp $ */ #include "tkTreeCtrl.h" #include "tkTreeElem.h" /* This is the roundUp argument to TreeAlloc_CAlloc. */ #define ELEMENT_LINK_ROUND 1 /* Define this for performance gain and increased memory usage. */ /* When undefined, there is quite a performance hit when elements are * squeezable and a style has less than its needed width. The memory * savings are not too great when undefined. */ #define CACHE_STYLE_SIZE /* Define this for performance gain and increased memory usage. */ #define CACHE_ELEM_SIZE typedef struct MStyle MStyle; typedef struct IStyle IStyle; typedef struct MElementLink MElementLink; typedef struct IElementLink IElementLink; /* * A data structure of the following type is kept for each master style. * Master styles are created by the [style create] widget command. */ struct MStyle { MStyle *master; /* Always NULL. Needed to distinguish between * an MStyle and IStyle. */ Tk_Uid name; /* Unique identifier. */ int numElements; /* Size of elements[]. */ MElementLink *elements; /* Array of master elements. */ int vertical; /* -orient */ }; /* * A data structure of the following type is kept for each instance style. * Instance styles are created when a style is assigned to an item-column. */ struct IStyle { MStyle *master; /* Always non-NULL. */ IElementLink *elements; /* Array of master or instance elements. */ int neededWidth; /* Requested size of this style based on */ int neededHeight; /* layout of the elements. */ #ifdef TREECTRL_DEBUG int neededState; #endif #ifdef CACHE_STYLE_SIZE int minWidth; int minHeight; int layoutWidth; int layoutHeight; #endif }; #define ELF_eEXPAND_W 0x0001 /* expand Layout.ePadX[0] */ #define ELF_eEXPAND_N 0x0002 #define ELF_eEXPAND_E 0x0004 #define ELF_eEXPAND_S 0x0008 #define ELF_iEXPAND_W 0x0010 /* expand Layout.iPadX[0] */ #define ELF_iEXPAND_N 0x0020 #define ELF_iEXPAND_E 0x0040 #define ELF_iEXPAND_S 0x0080 #define ELF_SQUEEZE_X 0x0100 /* shrink Layout.useWidth if needed */ #define ELF_SQUEEZE_Y 0x0200 #define ELF_DETACH 0x0400 #define ELF_INDENT 0x0800 /* don't layout under button&line area */ #define ELF_STICKY_W 0x1000 #define ELF_STICKY_N 0x2000 #define ELF_STICKY_E 0x4000 #define ELF_STICKY_S 0x8000 #define ELF_iEXPAND_X 0x00010000 /* expand Layout.useWidth */ #define ELF_iEXPAND_Y 0x00020000 #define ELF_eEXPAND_WE (ELF_eEXPAND_W | ELF_eEXPAND_E) #define ELF_eEXPAND_NS (ELF_eEXPAND_N | ELF_eEXPAND_S) #define ELF_eEXPAND (ELF_eEXPAND_WE | ELF_eEXPAND_NS) #define ELF_iEXPAND_WE (ELF_iEXPAND_W | ELF_iEXPAND_E) #define ELF_iEXPAND_NS (ELF_iEXPAND_N | ELF_iEXPAND_S) #define ELF_iEXPAND (ELF_iEXPAND_WE | ELF_iEXPAND_NS) #define ELF_EXPAND_WE (ELF_eEXPAND_WE | ELF_iEXPAND_WE) #define ELF_EXPAND_NS (ELF_eEXPAND_NS | ELF_iEXPAND_NS) #define ELF_EXPAND_W (ELF_eEXPAND_W | ELF_iEXPAND_W) #define ELF_EXPAND_N (ELF_eEXPAND_N | ELF_iEXPAND_N) #define ELF_EXPAND_E (ELF_eEXPAND_E | ELF_iEXPAND_E) #define ELF_EXPAND_S (ELF_eEXPAND_S | ELF_iEXPAND_S) #define ELF_STICKY (ELF_STICKY_W | ELF_STICKY_N | ELF_STICKY_E | ELF_STICKY_S) #define DETACH_OR_UNION(e) (((e)->onion != NULL) || ((e)->flags & ELF_DETACH)) /* * An array of these is kept for each master style, one per element. * Most of the fields are set by the [style layout] widget command. */ struct MElementLink { TreeElement elem; /* Master element. */ int ePadX[2]; /* external horizontal padding */ int ePadY[2]; /* external vertical padding */ int iPadX[2]; /* internal horizontal padding */ int iPadY[2]; /* internal vertical padding */ int flags; /* ELF_xxx */ int *onion, onionCount; /* -union option info */ int minWidth, fixedWidth, maxWidth; int minHeight, fixedHeight, maxHeight; PerStateInfo draw; /* -draw */ PerStateInfo visible; /* -visible */ }; /* * An array of these is kept for each instance style, one per element. */ struct IElementLink { TreeElement elem; /* Master or instance element. */ #ifdef CACHE_ELEM_SIZE int neededWidth; int neededHeight; int layoutWidth; int layoutHeight; #endif }; static CONST char *MStyleUid = "MStyle", *IStyleUid = "IStyle", *MElementLinkUid = "MElementLink", *IElementLinkUid = "IElementLink"; static char *orientStringTable[] = { "horizontal", "vertical", (char *) NULL }; static Tk_OptionSpec styleOptionSpecs[] = { {TK_OPTION_STRING_TABLE, "-orient", (char *) NULL, (char *) NULL, "horizontal", -1, Tk_Offset(MStyle, vertical), 0, (ClientData) orientStringTable, 0}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; /* * The following structure is used to hold layout information about a * single element. This information is not cached anywhere. */ struct Layout { MElementLink *master; IElementLink *eLink; int useWidth; int useHeight; #ifndef CACHE_ELEM_SIZE int neededWidth; int neededHeight; #endif int x; /* left of ePad */ int y; /* above ePad */ int eWidth; /* ePad + iPad + useWidth + iPad + ePad */ int eHeight; /* ePad + iPad + useHeight + iPad + ePad */ int iWidth; /* iPad + useWidth + iPad */ int iHeight; /* iPad + useHeight + iPad */ int ePadX[2]; /* external horizontal padding */ int ePadY[2]; /* external vertical padding */ int iPadX[2]; /* internal horizontal padding */ int iPadY[2]; /* internal vertical padding */ int uPadX[2]; /* padding due to -union */ int uPadY[2]; /* padding due to -union */ int temp; int visible; /* TRUE if the element should be displayed. */ }; #define IS_HIDDEN(L) ((L)->visible == 0) /* *---------------------------------------------------------------------- * * Style_DoExpandH -- * * Add extra horizontal space to an element. The space is * distributed from right to left until all available space * is used or expansion is not possible. * * Results: * Layout.ePadX, Layout.iPadX, and Layout.useWidth may be * updated. The amount of available space that was used is * returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Style_DoExpandH( struct Layout *layout, /* Layout to be adjusted. */ int right /* Limit of expansion. */ ) { MElementLink *eLink1 = layout->master; int flags = eLink1->flags; int numExpand = 0, spaceRemaining, spaceUsed = 0; int *ePadX, *iPadX, *uPadX; if (!(flags & (ELF_EXPAND_WE | ELF_iEXPAND_X))) return 0; ePadX = layout->ePadX; iPadX = layout->iPadX; uPadX = layout->uPadX; spaceRemaining = right - (layout->x + ePadX[PAD_TOP_LEFT] + layout->iWidth + MAX(ePadX[PAD_BOTTOM_RIGHT], uPadX[PAD_BOTTOM_RIGHT])); if (spaceRemaining <= 0) return 0; if (layout->temp) numExpand = layout->temp; /* For -detach or vertical layout, just set layout->temp to zero */ else { if (flags & ELF_eEXPAND_W) numExpand++; if (flags & ELF_iEXPAND_W) numExpand++; if (flags & ELF_iEXPAND_X) { if ((eLink1->maxWidth < 0) || (eLink1->maxWidth > layout->useWidth)) numExpand++; } if (flags & ELF_iEXPAND_E) numExpand++; if (flags & ELF_eEXPAND_E) numExpand++; } while ((spaceRemaining > 0) && (numExpand > 0)) { int each = (spaceRemaining >= numExpand) ? (spaceRemaining / numExpand) : 1; numExpand = 0; /* Allocate extra space to the *right* padding first so that any * extra single pixel is given to the right. */ if (flags & ELF_eEXPAND_E) { int add = each; ePadX[PAD_BOTTOM_RIGHT] += add; layout->eWidth += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } if (flags & ELF_iEXPAND_E) { int add = each; iPadX[PAD_BOTTOM_RIGHT] += add; layout->iWidth += add; layout->eWidth += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } if (flags & ELF_iEXPAND_X) { int max = eLink1->maxWidth; if ((max < 0) || (layout->useWidth < max)) { int add = (max < 0) ? each : MIN(each, max - layout->useWidth); layout->useWidth += add; layout->iWidth += add; layout->eWidth += add; spaceRemaining -= add; spaceUsed += add; if ((max >= 0) && (max == layout->useWidth)) layout->temp--; if (!spaceRemaining) break; if ((max < 0) || (max > layout->useWidth)) numExpand++; } } if (flags & ELF_iEXPAND_W) { int add = each; iPadX[PAD_TOP_LEFT] += add; layout->iWidth += add; layout->eWidth += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } if (flags & ELF_eEXPAND_W) { int add = each; ePadX[PAD_TOP_LEFT] += add; layout->eWidth += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } } return spaceUsed; } /* *---------------------------------------------------------------------- * * Style_DoExpandV -- * * Add extra vertical space to an element. The space is * distributed from bottom to top until all available space * is used or expansion is not possible. * * Results: * Layout.ePadY, Layout.iPadY, and Layout.useHeight may be * updated. The amount of available space that was used is * returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Style_DoExpandV( struct Layout *layout, /* Layout to be adjusted. */ int bottom /* Limit of expansion. */ ) { MElementLink *eLink1 = layout->master; int flags = eLink1->flags; int numExpand = 0, spaceRemaining, spaceUsed = 0; int *ePadY, *iPadY, *uPadY; if (!(flags & (ELF_EXPAND_NS | ELF_iEXPAND_Y))) return 0; ePadY = layout->ePadY; iPadY = layout->iPadY; uPadY = layout->uPadY; spaceRemaining = bottom - (layout->y + ePadY[PAD_TOP_LEFT] + layout->iHeight + MAX(ePadY[PAD_BOTTOM_RIGHT], uPadY[PAD_BOTTOM_RIGHT])); if (spaceRemaining <= 0) return 0; if (layout->temp) numExpand = layout->temp; /* For -detach or vertical layout, just set layout->temp to zero */ else { if (flags & ELF_eEXPAND_N) numExpand++; if (flags & ELF_iEXPAND_N) numExpand++; if (flags & ELF_iEXPAND_Y) { if ((eLink1->maxHeight < 0) || (eLink1->maxHeight > layout->useHeight)) numExpand++; } if (flags & ELF_iEXPAND_S) numExpand++; if (flags & ELF_eEXPAND_S) numExpand++; } while ((spaceRemaining > 0) && (numExpand > 0)) { int each = (spaceRemaining >= numExpand) ? (spaceRemaining / numExpand) : 1; numExpand = 0; /* Allocate extra space to the *bottom* padding first so that any * extra single pixel is given to the bottom. */ if (flags & ELF_eEXPAND_S) { int add = each; ePadY[PAD_BOTTOM_RIGHT] += add; layout->eHeight += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } if (flags & ELF_iEXPAND_S) { int add = each; iPadY[PAD_BOTTOM_RIGHT] += add; layout->iHeight += add; layout->eHeight += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } if (flags & ELF_iEXPAND_Y) { int max = eLink1->maxHeight; if ((max < 0) || (layout->useHeight < max)) { int add = (max < 0) ? each : MIN(each, max - layout->useHeight); layout->useHeight += add; layout->iHeight += add; layout->eHeight += add; spaceRemaining -= add; spaceUsed += add; if ((max >= 0) && (max == layout->useHeight)) layout->temp--; if (!spaceRemaining) break; if ((max < 0) || (max > layout->useHeight)) numExpand++; } } if (flags & ELF_iEXPAND_N) { int add = each; iPadY[PAD_TOP_LEFT] += add; layout->iHeight += add; layout->eHeight += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } if (flags & ELF_eEXPAND_N) { int add = each; ePadY[PAD_TOP_LEFT] += add; layout->eHeight += add; spaceRemaining -= add; spaceUsed += add; if (!spaceRemaining) break; numExpand++; } } return spaceUsed; } /* *---------------------------------------------------------------------- * * ElementLink_NeededSize -- * * Calculate the needed width and height of an element. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Element_NeededSize( TreeCtrl *tree, /* Widget info. */ MElementLink *eLink1, /* Master style layout info. */ TreeElement elem, /* Master/Instance element. */ int state, /* STATE_xxx flags. */ int *widthPtr, /* Out: width */ int *heightPtr /* Out: height */ ) { TreeElementArgs args; int width, height; if ((eLink1->fixedWidth >= 0) && (eLink1->fixedHeight >= 0)) { width = eLink1->fixedWidth; height = eLink1->fixedHeight; } else { args.tree = tree; args.state = state; args.elem = elem; args.needed.fixedWidth = eLink1->fixedWidth; args.needed.fixedHeight = eLink1->fixedHeight; if (eLink1->maxWidth > eLink1->minWidth) args.needed.maxWidth = eLink1->maxWidth; else args.needed.maxWidth = -1; if (eLink1->maxHeight > eLink1->minHeight) args.needed.maxHeight = eLink1->maxHeight; else args.needed.maxHeight = -1; (*args.elem->typePtr->neededProc)(&args); width = args.needed.width; height = args.needed.height; if (eLink1->fixedWidth >= 0) width = eLink1->fixedWidth; else if ((eLink1->minWidth >= 0) && (width < eLink1->minWidth)) width = eLink1->minWidth; else if ((eLink1->maxWidth >= 0) && (width > eLink1->maxWidth)) width = eLink1->maxWidth; if (eLink1->fixedHeight >= 0) height = eLink1->fixedHeight; else if ((eLink1->minHeight >= 0) && (height < eLink1->minHeight)) height = eLink1->minHeight; else if ((eLink1->maxHeight >= 0) && (height > eLink1->maxHeight)) height = eLink1->maxHeight; } *widthPtr = width; *heightPtr = height; } /* *---------------------------------------------------------------------- * * Style_DoLayoutH -- * * Calculate the horizontal size and position of each element. * This gets called if the style -orient option is horizontal or * vertical. * * Results: * layouts[] is updated. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Style_DoLayoutH( StyleDrawArgs *drawArgs, /* Various args. */ struct Layout layouts[] /* Array of layout records to be * filled in, one per element. Should be * uninitialized. */ ) { IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; MElementLink *eLinks1, *eLink1; IElementLink *eLinks2, *eLink2; int x = drawArgs->indent; int w, e; int *ePadX, *iPadX, *uPadX, *ePadY, *iPadY, *uPadY; int numExpandWE = 0; int numSqueezeX = 0; int i, j, eLinkCount = 0; int rightEdge = 0; eLinks1 = masterStyle->elements; eLinks2 = style->elements; eLinkCount = masterStyle->numElements; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; layout->visible = PerStateBoolean_ForState(drawArgs->tree, &eLink1->visible, drawArgs->state, NULL) != 0; if (IS_HIDDEN(layout)) continue; layout->eLink = eLink2; layout->master = eLink1; /* Width before squeezing/expanding */ if (eLink1->onion != NULL) { layout->useWidth = 0; } else { #ifdef CACHE_ELEM_SIZE layout->useWidth = eLink2->neededWidth; #else Element_NeededSize(drawArgs->tree, eLink1, eLink2->elem, drawArgs->state, &layout->neededWidth, &layout->neededHeight); layout->useWidth = layout->neededWidth; #endif } for (j = 0; j < 2; j++) { /* Pad values before expansion */ layout->ePadX[j] = eLink1->ePadX[j]; layout->ePadY[j] = eLink1->ePadY[j]; layout->iPadX[j] = eLink1->iPadX[j]; layout->iPadY[j] = eLink1->iPadY[j]; /* No -union padding yet */ layout->uPadX[j] = 0; layout->uPadY[j] = 0; } /* Count all non-union, non-detach squeezeable elements */ if (DETACH_OR_UNION(eLink1)) continue; if (eLink1->flags & ELF_SQUEEZE_X) numSqueezeX++; } /* Calculate the padding around elements surrounded by -union elements */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int first = -1, last = -1; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if (eLink1->onion == NULL) continue; for (j = 0; j < eLink1->onionCount; j++) { struct Layout *layout = &layouts[eLink1->onion[j]]; if (IS_HIDDEN(layout)) continue; /* Remember the first and last visible elements surrounded by * this -union element. */ if (first == -1) first = j; last = j; } /* If there are no visible elements surrounded by this -union * element, then hide it. */ if (first == -1) { layout->visible = 0; continue; } ePadX = eLink1->ePadX; ePadY = eLink1->ePadY; iPadX = eLink1->iPadX; iPadY = eLink1->iPadY; for (j = 0; j < eLink1->onionCount; j++) { struct Layout *layout = &layouts[eLink1->onion[j]]; if (IS_HIDDEN(layout)) continue; uPadX = layout->uPadX; uPadY = layout->uPadY; if (masterStyle->vertical) { uPadX[PAD_TOP_LEFT] = MAX(uPadX[PAD_TOP_LEFT], iPadX[PAD_TOP_LEFT] + ePadX[PAD_TOP_LEFT]); uPadX[PAD_BOTTOM_RIGHT] = MAX(uPadX[PAD_BOTTOM_RIGHT], iPadX[PAD_BOTTOM_RIGHT] + ePadX[PAD_BOTTOM_RIGHT]); if (j == first) /* topmost */ uPadY[PAD_TOP_LEFT] = MAX(uPadY[PAD_TOP_LEFT], iPadY[PAD_TOP_LEFT] + ePadY[PAD_TOP_LEFT]); if (j == last) /* bottommost */ uPadY[PAD_BOTTOM_RIGHT] = MAX(uPadY[PAD_BOTTOM_RIGHT], iPadY[PAD_BOTTOM_RIGHT] + ePadY[PAD_BOTTOM_RIGHT]); } else { if (j == first) /* leftmost */ uPadX[PAD_TOP_LEFT] = MAX(uPadX[PAD_TOP_LEFT], iPadX[PAD_TOP_LEFT] + ePadX[PAD_TOP_LEFT]); if (j == last) /* rightmost */ uPadX[PAD_BOTTOM_RIGHT] = MAX(uPadX[PAD_BOTTOM_RIGHT], iPadX[PAD_BOTTOM_RIGHT] + ePadX[PAD_BOTTOM_RIGHT]); uPadY[PAD_TOP_LEFT] = MAX(uPadY[PAD_TOP_LEFT], iPadY[PAD_TOP_LEFT] + ePadY[PAD_TOP_LEFT]); uPadY[PAD_BOTTOM_RIGHT] = MAX(uPadY[PAD_BOTTOM_RIGHT], iPadY[PAD_BOTTOM_RIGHT] + ePadY[PAD_BOTTOM_RIGHT]); } } } /* Left-to-right layout. Make the width of some elements less than they * need */ if (!masterStyle->vertical && (drawArgs->width < style->neededWidth + drawArgs->indent) && (numSqueezeX > 0)) { int numSqueeze = numSqueezeX; int spaceRemaining = (style->neededWidth + drawArgs->indent) - drawArgs->width; while ((spaceRemaining > 0) && (numSqueeze > 0)) { int each = (spaceRemaining >= numSqueeze) ? (spaceRemaining / numSqueeze) : 1; numSqueeze = 0; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int min = 0; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if (DETACH_OR_UNION(eLink1)) continue; if (!(eLink1->flags & ELF_SQUEEZE_X)) continue; if (eLink1->minWidth >= 0) min = eLink1->minWidth; if (layout->useWidth > min) { int sub = MIN(each, layout->useWidth - min); layout->useWidth -= sub; spaceRemaining -= sub; if (!spaceRemaining) break; if (layout->useWidth > min) numSqueeze++; } } } } /* Reduce the width of all non-union elements, except for the * cases handled above. */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int width, subtract; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if (eLink1->onion != NULL) continue; if (!(eLink1->flags & ELF_SQUEEZE_X)) continue; if (!(eLink1->flags & ELF_DETACH) && !masterStyle->vertical) continue; ePadX = eLink1->ePadX; iPadX = eLink1->iPadX; uPadX = layout->uPadX; width = MAX(ePadX[PAD_TOP_LEFT], uPadX[PAD_TOP_LEFT]) + iPadX[PAD_TOP_LEFT] + layout->useWidth + iPadX[PAD_BOTTOM_RIGHT] + MAX(ePadX[PAD_BOTTOM_RIGHT], uPadX[PAD_BOTTOM_RIGHT]); subtract = width - drawArgs->width; if (!(eLink1->flags & ELF_DETACH) || (eLink1->flags & ELF_INDENT)) subtract += drawArgs->indent; if (subtract > 0) { if ((eLink1->minWidth >= 0) && (eLink1->minWidth <= layout->useWidth) && (layout->useWidth - subtract < eLink1->minWidth)) layout->useWidth = eLink1->minWidth; else layout->useWidth -= subtract; } } /* Layout elements left-to-right */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int right; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (DETACH_OR_UNION(eLink1)) continue; ePadX = eLink1->ePadX; iPadX = eLink1->iPadX; uPadX = layout->uPadX; layout->x = x + abs(ePadX[PAD_TOP_LEFT] - MAX(ePadX[PAD_TOP_LEFT], uPadX[PAD_TOP_LEFT])); layout->iWidth = iPadX[PAD_TOP_LEFT] + layout->useWidth + iPadX[PAD_BOTTOM_RIGHT]; layout->eWidth = ePadX[PAD_TOP_LEFT] + layout->iWidth + ePadX[PAD_BOTTOM_RIGHT]; right = layout->x + layout->ePadX[PAD_TOP_LEFT] + layout->iWidth + MAX(ePadX[PAD_BOTTOM_RIGHT], uPadX[PAD_BOTTOM_RIGHT]); if (masterStyle->vertical) rightEdge = MAX(rightEdge, right); else { rightEdge = right; x = layout->x + layout->eWidth; } /* Count number that want to expand */ if (eLink1->flags & (ELF_EXPAND_WE | ELF_iEXPAND_X)) numExpandWE++; } /* Left-to-right layout. Expand some elements horizontally if we have * more space available horizontally than is needed by the Style. */ if (!masterStyle->vertical && (drawArgs->width > rightEdge) && (numExpandWE > 0)) { int numExpand = 0; int spaceRemaining = drawArgs->width - rightEdge; /* Each element has 5 areas that can optionally expand. */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; layout->temp = 0; if (DETACH_OR_UNION(eLink1)) continue; if (eLink1->flags & ELF_eEXPAND_W) layout->temp++; if (eLink1->flags & ELF_iEXPAND_W) layout->temp++; if (eLink1->flags & ELF_iEXPAND_X) { if ((eLink1->maxWidth < 0) || (eLink1->maxWidth > layout->useWidth)) layout->temp++; } if (eLink1->flags & ELF_iEXPAND_E) layout->temp++; if (eLink1->flags & ELF_eEXPAND_E) layout->temp++; numExpand += layout->temp; } while ((spaceRemaining > 0) && (numExpand > 0)) { int each = (spaceRemaining >= numExpand) ? spaceRemaining / numExpand : 1; numExpand = 0; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int spaceUsed; if (IS_HIDDEN(layout)) continue; if (!layout->temp) continue; eLink1 = &eLinks1[i]; spaceUsed = Style_DoExpandH(layout, layout->x + layout->ePadX[PAD_TOP_LEFT] + layout->iWidth + MAX(layout->ePadX[PAD_BOTTOM_RIGHT], layout->uPadX[PAD_BOTTOM_RIGHT]) + MIN(each * layout->temp, spaceRemaining)); if (spaceUsed) { /* Shift following elements to the right */ for (j = i + 1; j < eLinkCount; j++) if (!DETACH_OR_UNION(&eLinks1[j])) layouts[j].x += spaceUsed; rightEdge += spaceUsed; spaceRemaining -= spaceUsed; if (!spaceRemaining) break; numExpand += layout->temp; } else layout->temp = 0; } } } /* Top-to-bottom layout. Expand some elements horizontally */ if (masterStyle->vertical && (numExpandWE > 0)) { for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int right; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if (DETACH_OR_UNION(eLink1)) continue; layout->temp = 0; Style_DoExpandH(layout, drawArgs->width); right = layout->x + layout->ePadX[PAD_TOP_LEFT] + layout->iWidth + MAX(layout->ePadX[PAD_BOTTOM_RIGHT], layout->uPadX[PAD_BOTTOM_RIGHT]); rightEdge = MAX(rightEdge, right); } } /* Now handle column justification */ /* All the non-union, non-detach elements are moved as a group */ if (drawArgs->width > rightEdge) { int dx = drawArgs->width - rightEdge; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if (DETACH_OR_UNION(eLink1)) continue; switch (drawArgs->justify) { case TK_JUSTIFY_LEFT: break; case TK_JUSTIFY_RIGHT: layout->x += dx; break; case TK_JUSTIFY_CENTER: layout->x += dx / 2; break; } } } /* Position and expand -detach elements */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (!(eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; ePadX = eLink1->ePadX; iPadX = eLink1->iPadX; uPadX = layout->uPadX; layout->x = abs(ePadX[PAD_TOP_LEFT] - MAX(ePadX[PAD_TOP_LEFT], uPadX[PAD_TOP_LEFT])); if (eLink1->flags & ELF_INDENT) layout->x += drawArgs->indent; layout->iWidth = iPadX[PAD_TOP_LEFT] + layout->useWidth + iPadX[PAD_BOTTOM_RIGHT]; layout->eWidth = ePadX[PAD_TOP_LEFT] + layout->iWidth + ePadX[PAD_BOTTOM_RIGHT]; layout->temp = 0; Style_DoExpandH(layout, drawArgs->width); } /* Now calculate layout of -union elements. */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (IS_HIDDEN(layout)) continue; if (eLink1->onion == NULL) continue; ePadX = eLink1->ePadX; iPadX = eLink1->iPadX; w = 1000000, e = -1000000; for (j = 0; j < eLink1->onionCount; j++) { struct Layout *layout2 = &layouts[eLink1->onion[j]]; if (IS_HIDDEN(layout2)) continue; w = MIN(w, layout2->x + layout2->ePadX[PAD_TOP_LEFT]); e = MAX(e, layout2->x + layout2->ePadX[PAD_TOP_LEFT] + layout2->iWidth); } layout->x = w - iPadX[PAD_TOP_LEFT] - ePadX[PAD_TOP_LEFT]; layout->useWidth = (e - w); layout->iWidth = iPadX[PAD_TOP_LEFT] + layout->useWidth + iPadX[PAD_BOTTOM_RIGHT]; layout->eWidth = ePadX[PAD_TOP_LEFT] + layout->iWidth + ePadX[PAD_BOTTOM_RIGHT]; } /* Expand -union elements if needed: horizontal */ /* Expansion of "-union" elements is different than non-"-union" elements */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int extraWidth; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if ((eLink1->onion == NULL) || !(eLink1->flags & ELF_EXPAND_WE)) continue; if (drawArgs->width - (layout->eWidth + drawArgs->indent) <= 0) continue; /* External and internal expansion: W */ extraWidth = layout->x - drawArgs->indent; if ((extraWidth > 0) && (eLink1->flags & ELF_EXPAND_W)) { if ((eLink1->flags & ELF_EXPAND_W) == ELF_EXPAND_W) { int eExtra = extraWidth / 2; int iExtra = extraWidth - extraWidth / 2; layout->x = drawArgs->indent; /* External expansion */ layout->ePadX[PAD_TOP_LEFT] += eExtra; layout->eWidth += extraWidth; /* Internal expansion */ layout->iPadX[PAD_TOP_LEFT] += iExtra; layout->iWidth += iExtra; } /* External expansion only: W */ else if (eLink1->flags & ELF_eEXPAND_W) { layout->ePadX[PAD_TOP_LEFT] += extraWidth; layout->x = drawArgs->indent; layout->eWidth += extraWidth; } /* Internal expansion only: W */ else { layout->iPadX[PAD_TOP_LEFT] += extraWidth; layout->x = drawArgs->indent; layout->iWidth += extraWidth; layout->eWidth += extraWidth; } } /* External and internal expansion: E */ extraWidth = drawArgs->width - (layout->x + layout->eWidth); if ((extraWidth > 0) && (eLink1->flags & ELF_EXPAND_E)) { if ((eLink1->flags & ELF_EXPAND_E) == ELF_EXPAND_E) { int eExtra = extraWidth / 2; int iExtra = extraWidth - extraWidth / 2; /* External expansion */ layout->ePadX[PAD_BOTTOM_RIGHT] += eExtra; layout->eWidth += extraWidth; /* all the space */ /* Internal expansion */ layout->iPadX[PAD_BOTTOM_RIGHT] += iExtra; layout->iWidth += iExtra; } /* External expansion only: E */ else if (eLink1->flags & ELF_eEXPAND_E) { layout->ePadX[PAD_BOTTOM_RIGHT] += extraWidth; layout->eWidth += extraWidth; } /* Internal expansion only: E */ else { layout->iPadX[PAD_BOTTOM_RIGHT] += extraWidth; layout->iWidth += extraWidth; layout->eWidth += extraWidth; } } } /* Add internal padding to display area for -union elements */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if (eLink1->onion == NULL) continue; iPadX = layout->iPadX; layout->useWidth += iPadX[PAD_TOP_LEFT] + iPadX[PAD_BOTTOM_RIGHT]; iPadX[PAD_TOP_LEFT] = iPadX[PAD_BOTTOM_RIGHT] = 0; } } /* *---------------------------------------------------------------------- * * Style_DoLayoutV -- * * Calculate the vertical size and position of each element. * This gets called if the style -orient option is horizontal or * vertical. * * Results: * layouts[] is updated. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Style_DoLayoutV( StyleDrawArgs *drawArgs, /* Various args. */ struct Layout layouts[] /* Array of layout records to be updated, * one per element. Should be initialized * by Style_DoLayoutH(). */ ) { IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; MElementLink *eLinks1, *eLink1; IElementLink *eLinks2, *eLink2; int y = 0; int n, s; int *ePadY, *iPadY, *uPadY; int numExpandNS = 0; int numSqueezeY = 0; int i, j, eLinkCount = 0; int bottomEdge = 0; eLinks1 = masterStyle->elements; eLinks2 = style->elements; eLinkCount = masterStyle->numElements; for (i = 0; i < eLinkCount; i++) { if (IS_HIDDEN(&layouts[i])) continue; eLink1 = &eLinks1[i]; /* Count all non-union, non-detach squeezeable elements */ if (DETACH_OR_UNION(eLink1)) continue; if (eLink1->flags & ELF_SQUEEZE_Y) numSqueezeY++; } /* Top-top-bottom layout. Make the height of some elements less than they * need */ if (masterStyle->vertical && (drawArgs->height < style->neededHeight) && (numSqueezeY > 0)) { int numSqueeze = numSqueezeY; int spaceRemaining = style->neededHeight - drawArgs->height; while ((spaceRemaining > 0) && (numSqueeze > 0)) { int each = (spaceRemaining >= numSqueeze) ? (spaceRemaining / numSqueeze) : 1; numSqueeze = 0; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int min = 0; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if (DETACH_OR_UNION(eLink1)) continue; if (!(eLink1->flags & ELF_SQUEEZE_Y)) continue; if (eLink1->minHeight >= 0) min = eLink1->minHeight; if (layout->useHeight > min) { int sub = MIN(each, layout->useHeight - min); layout->useHeight -= sub; spaceRemaining -= sub; if (!spaceRemaining) break; if (layout->useHeight > min) numSqueeze++; } } } } /* Reduce the height of all non-union elements, except for the * cases handled above. */ if (drawArgs->height < style->neededHeight) { for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int height, subtract; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if (eLink1->onion != NULL) continue; if (!(eLink1->flags & ELF_SQUEEZE_Y)) continue; if (!(eLink1->flags & ELF_DETACH) && masterStyle->vertical) continue; ePadY = eLink1->ePadY; iPadY = eLink1->iPadY; uPadY = layout->uPadY; height = MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT]) + iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT] + MAX(ePadY[PAD_BOTTOM_RIGHT], uPadY[PAD_BOTTOM_RIGHT]); subtract = height - drawArgs->height; if (subtract > 0) { if ((eLink1->minHeight >= 0) && (eLink1->minHeight <= layout->useHeight) && (layout->useHeight - subtract < eLink1->minHeight)) layout->useHeight = eLink1->minHeight; else layout->useHeight -= subtract; } } } /* Layout elements top-to-bottom */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (DETACH_OR_UNION(eLink1)) continue; ePadY = eLink1->ePadY; iPadY = eLink1->iPadY; uPadY = layout->uPadY; layout->y = y + abs(ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT])); layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; if (masterStyle->vertical) y = layout->y + layout->eHeight; if (masterStyle->vertical) { bottomEdge = layout->y + layout->ePadY[PAD_TOP_LEFT] + layout->iHeight + MAX(ePadY[PAD_BOTTOM_RIGHT], uPadY[PAD_BOTTOM_RIGHT]); } /* Count number that want to expand */ if (eLink1->flags & (ELF_EXPAND_NS | ELF_iEXPAND_Y)) numExpandNS++; } /* Top-to-bottom layout. Expand some elements vertically if we have * more space available vertically than is needed by the Style. */ if (masterStyle->vertical && (drawArgs->height > bottomEdge) && (numExpandNS > 0)) { int numExpand = 0; int spaceRemaining = drawArgs->height - bottomEdge; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; layout->temp = 0; if (DETACH_OR_UNION(eLink1)) continue; if (eLink1->flags & ELF_eEXPAND_N) layout->temp++; if (eLink1->flags & ELF_iEXPAND_N) layout->temp++; if (eLink1->flags & ELF_iEXPAND_Y) { if ((eLink1->maxHeight < 0) || (eLink1->maxHeight > layout->useHeight)) layout->temp++; } if (eLink1->flags & ELF_iEXPAND_S) layout->temp++; if (eLink1->flags & ELF_eEXPAND_S) layout->temp++; numExpand += layout->temp; } while ((spaceRemaining > 0) && (numExpand > 0)) { int each = (spaceRemaining >= numExpand) ? spaceRemaining / numExpand : 1; numExpand = 0; for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int spaceUsed; if (IS_HIDDEN(layout)) continue; if (!layout->temp) continue; eLink1 = &eLinks1[i]; spaceUsed = Style_DoExpandV(layout, layout->y + layout->ePadY[PAD_TOP_LEFT] + layout->iHeight + MAX(layout->ePadY[PAD_BOTTOM_RIGHT], layout->uPadY[PAD_BOTTOM_RIGHT]) + MIN(each * layout->temp, spaceRemaining)); if (spaceUsed) { /* Shift following elements down */ for (j = i + 1; j < eLinkCount; j++) if (!DETACH_OR_UNION(&eLinks1[j])) layouts[j].y += spaceUsed; spaceRemaining -= spaceUsed; if (!spaceRemaining) break; numExpand += layout->temp; } else layout->temp = 0; } } } /* Left-to-right layout. Expand some elements vertically */ if (!masterStyle->vertical && (numExpandNS > 0)) { for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if (DETACH_OR_UNION(eLink1)) continue; layout->temp = 0; Style_DoExpandV(layout, drawArgs->height); } } /* Position and expand -detach elements */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (!(eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; ePadY = eLink1->ePadY; iPadY = eLink1->iPadY; uPadY = layout->uPadY; layout->y = abs(ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT])); layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; layout->temp = 0; Style_DoExpandV(layout, drawArgs->height); } /* Now calculate layout of -union elements. */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (eLink1->onion == NULL) continue; ePadY = eLink1->ePadY; iPadY = eLink1->iPadY; n = 1000000, s = -1000000; for (j = 0; j < eLink1->onionCount; j++) { struct Layout *layout2 = &layouts[eLink1->onion[j]]; if (IS_HIDDEN(layout2)) continue; n = MIN(n, layout2->y + layout2->ePadY[PAD_TOP_LEFT]); s = MAX(s, layout2->y + layout2->ePadY[PAD_TOP_LEFT] + layout2->iHeight); } layout->y = n - iPadY[PAD_TOP_LEFT] - ePadY[PAD_TOP_LEFT]; layout->useHeight = (s - n); layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; } /* Expand -union elements if needed: vertical */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; int extraHeight; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if ((eLink1->onion == NULL) || !(eLink1->flags & ELF_EXPAND_NS)) continue; if (drawArgs->height - layout->eHeight <= 0) continue; /* External and internal expansion: N */ extraHeight = layout->y; if ((extraHeight > 0) && (eLink1->flags & ELF_EXPAND_N)) { if ((eLink1->flags & ELF_EXPAND_N) == ELF_EXPAND_N) { int eExtra = extraHeight / 2; int iExtra = extraHeight - extraHeight / 2; /* External expansion */ layout->ePadY[PAD_TOP_LEFT] += eExtra; layout->y = 0; layout->eHeight += extraHeight; /* Internal expansion */ layout->iPadY[PAD_TOP_LEFT] += iExtra; layout->iHeight += iExtra; } /* External expansion only: N */ else if (eLink1->flags & ELF_eEXPAND_N) { layout->ePadY[PAD_TOP_LEFT] += extraHeight; layout->y = 0; layout->eHeight += extraHeight; } /* Internal expansion only: N */ else { layout->iPadY[PAD_TOP_LEFT] += extraHeight; layout->y = 0; layout->iHeight += extraHeight; layout->eHeight += extraHeight; } } /* External and internal expansion: S */ extraHeight = drawArgs->height - (layout->y + layout->eHeight); if ((extraHeight > 0) && (eLink1->flags & ELF_EXPAND_S)) { if ((eLink1->flags & ELF_EXPAND_S) == ELF_EXPAND_S) { int eExtra = extraHeight / 2; int iExtra = extraHeight - extraHeight / 2; /* External expansion */ layout->ePadY[PAD_BOTTOM_RIGHT] += eExtra; layout->eHeight += extraHeight; /* all the space */ /* Internal expansion */ layout->iPadY[PAD_BOTTOM_RIGHT] += iExtra; layout->iHeight += iExtra; } /* External expansion only: S */ else if (eLink1->flags & ELF_eEXPAND_S) { layout->ePadY[PAD_BOTTOM_RIGHT] += extraHeight; layout->eHeight += extraHeight; } /* Internal expansion only */ else { layout->iPadY[PAD_BOTTOM_RIGHT] += extraHeight; layout->iHeight += extraHeight; layout->eHeight += extraHeight; } } } /* Add internal padding to display area for -union elements */ for (i = 0; i < eLinkCount; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if (eLink1->onion == NULL) continue; iPadY = layout->iPadY; layout->useHeight += iPadY[PAD_TOP_LEFT] + iPadY[PAD_BOTTOM_RIGHT]; iPadY[PAD_TOP_LEFT] = iPadY[PAD_BOTTOM_RIGHT] = 0; } } /* *---------------------------------------------------------------------- * * Layout_Size -- * * Calculate the height and width of a style after all the * elements have been arranged. * * Results: * The height and width of the style. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Layout_Size( int vertical, /* TRUE if elements are arranged from top * to bottom. */ int numLayouts, /* Number of layout records. */ struct Layout layouts[], /* Initialized layout records. */ int *widthPtr, /* Returned width. */ int *heightPtr /* Returned height. */ ) { int i, W, N, E, S; int width = 0, height = 0; W = 1000000, N = 1000000, E = -1000000, S = -1000000; for (i = 0; i < numLayouts; i++) { struct Layout *layout = &layouts[i]; int w, n, e, s; int *ePadX, *iPadX, *uPadX, *ePadY, *iPadY, *uPadY; if (IS_HIDDEN(layout)) continue; ePadX = layout->ePadX, iPadX = layout->iPadX, uPadX = layout->uPadX; ePadY = layout->ePadY, iPadY = layout->iPadY, uPadY = layout->uPadY; w = layout->x + ePadX[PAD_TOP_LEFT] - MAX(ePadX[PAD_TOP_LEFT], uPadX[PAD_TOP_LEFT]); n = layout->y + ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT]); e = layout->x + layout->eWidth - ePadX[PAD_BOTTOM_RIGHT] + MAX(ePadX[PAD_BOTTOM_RIGHT], uPadX[PAD_BOTTOM_RIGHT]); s = layout->y + layout->eHeight - ePadY[PAD_BOTTOM_RIGHT] + MAX(ePadY[PAD_BOTTOM_RIGHT], uPadY[PAD_BOTTOM_RIGHT]); if (vertical) { N = MIN(N, n); S = MAX(S, s); width = MAX(width, e - w); } else { W = MIN(W, w); E = MAX(E, e); height = MAX(height, s - n); } } if (vertical) height = MAX(height, S - N); else width = MAX(width, E - W); (*widthPtr) = width; (*heightPtr) = height; } /* *---------------------------------------------------------------------- * * Style_DoLayoutNeededV -- * * Calculate the vertical size and position of each element. * This is similar to Style_DoLayoutV but without expansion or * squeezing. Also, the size and position of -union elements * is not calculated. * * Results: * layouts[] is updated. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Style_DoLayoutNeededV( StyleDrawArgs *drawArgs, /* Various args. */ struct Layout layouts[] /* Array of layout records to be updated, * one per element. Should be initialized * by Style_DoLayoutH(). */ ) { IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; MElementLink *eLinks1, *eLink1; IElementLink *eLinks2, *eLink2; int *ePadY, *iPadY, *uPadY; int i; int y = 0; eLinks1 = masterStyle->elements; eLinks2 = style->elements; /* Layout elements left-to-right, or top-to-bottom */ for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; /* The size of a -union element is determined by the elements * it surrounds */ if (eLink1->onion != NULL) { /* I don't need good values because I'm only calculating the * needed height */ layout->y = layout->iHeight = layout->eHeight = 0; continue; } /* -detach elements are positioned by themselves */ if (eLink1->flags & ELF_DETACH) continue; ePadY = eLink1->ePadY; iPadY = eLink1->iPadY; uPadY = layout->uPadY; layout->y = y + abs(ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT])); layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; if (masterStyle->vertical) y = layout->y + layout->eHeight; } /* -detach elements */ for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (!(eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; ePadY = eLink1->ePadY; iPadY = eLink1->iPadY; uPadY = layout->uPadY; layout->y = abs(ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT])); layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; } } /* *---------------------------------------------------------------------- * * Style_DoLayout -- * * Calculate the size and position of each element. * * Results: * layouts[] is updated. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* Arrange all the Elements considering drawArgs.width and maybe drawArgs.height */ static void Style_DoLayout( StyleDrawArgs *drawArgs, /* Various args. */ struct Layout layouts[], /* Uninitialized records to be filled in. */ int neededV, /* TRUE if drawArgs.height should be ignored. */ char *file, /* debug */ int line /* debug */ ) { TreeCtrl *tree = drawArgs->tree; IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; int state = drawArgs->state; int i; if (style->neededWidth == -1) panic("Style_DoLayout(file %s line %d): style.neededWidth == -1", file, line); #ifdef CACHE_STYLE_STYLE if (style->minWidth + drawArgs->indent > drawArgs->width) panic("Style_DoLayout(file %s line %d): style.minWidth + drawArgs->indent %d > drawArgs.width %d", file, line, style->minWidth + drawArgs->indent, drawArgs->width); #endif Style_DoLayoutH(drawArgs, layouts); for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; MElementLink *eLink1 = layout->master; IElementLink *eLink2 = layout->eLink; TreeElementArgs args; if (IS_HIDDEN(layout)) continue; /* The size of a -union element is determined by the elements * it surrounds */ if (eLink1->onion != NULL) { layout->useHeight = 0; continue; } #ifdef CACHE_ELEM_SIZE layout->useHeight = eLink2->neededHeight; #else layout->useHeight = layout->neededHeight; #endif /* If a Text Element is given less width than it needs (due to * -squeeze x layout), then it may wrap lines. This means * the height can vary depending on the width. */ if (eLink2->elem->typePtr->heightProc == NULL) continue; if (eLink1->fixedHeight >= 0) continue; #ifdef CACHE_ELEM_SIZE /* Not squeezed */ if (layout->useWidth >= eLink2->neededWidth) continue; /* Already calculated the height at this width */ if (layout->useWidth == eLink2->layoutWidth) { layout->useHeight = eLink2->layoutHeight; continue; } #if 0 /* */ if ((eLink2->layoutWidth == -1) && (layout->useWidth >= eLink2->neededWidth)) continue; #endif #else /* Not squeezed */ if (layout->useWidth >= layout->neededWidth) continue; #endif args.tree = tree; args.state = state; args.elem = eLink2->elem; args.height.fixedWidth = layout->useWidth; (*args.elem->typePtr->heightProc)(&args); if (eLink1->fixedHeight >= 0) layout->useHeight = eLink1->fixedHeight; else if ((eLink1->minHeight >= 0) && (args.height.height < eLink1->minHeight)) layout->useHeight = eLink1->minHeight; else if ((eLink1->maxHeight >= 0) && (args.height.height > eLink1->maxHeight)) layout->useHeight = eLink1->maxHeight; else layout->useHeight = args.height.height; #ifdef CACHE_ELEM_SIZE eLink2->layoutWidth = layout->useWidth; eLink2->layoutHeight = layout->useHeight; #endif } if (neededV) { Style_DoLayoutNeededV(drawArgs, layouts); } else { Style_DoLayoutV(drawArgs, layouts); } } /* *---------------------------------------------------------------------- * * Style_NeededSize -- * * Calculate the width and height of a style based only on * the requested size of each element. * * Results: * The width and height. The minimum width and height is equal to * the requested width and height minus any squeezing. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Style_NeededSize( TreeCtrl *tree, /* Widget info. */ IStyle *style, /* Style to calculate size of. */ int state, /* STATE_xxx flags. */ int *widthPtr, /* Returned width. */ int *heightPtr, /* Returned height. */ int *minWidthPtr, /* Returned minimum width. */ int *minHeightPtr /* Returned minimum height. */ ) { MStyle *masterStyle = style->master; MElementLink *eLinks1, *eLink1; IElementLink *eLinks2, *eLink2; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; int *ePadX, *iPadX, *uPadX, *ePadY, *iPadY, *uPadY; int i, j; int x = 0, y = 0; int squeezeX = 0, squeezeY = 0; STATIC_ALLOC(layouts, struct Layout, masterStyle->numElements); eLinks1 = masterStyle->elements; eLinks2 = style->elements; for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; layout->visible = PerStateBoolean_ForState(tree, &eLink1->visible, state, NULL) != 0; if (IS_HIDDEN(layout)) continue; layout->master = eLink1; layout->eLink = eLink2; if (eLink1->onion == NULL) { #ifdef CACHE_ELEM_SIZE if ((eLink2->neededWidth == -1) || (eLink2->neededHeight == -1)) { Element_NeededSize(tree, eLink1, eLink2->elem, state, &eLink2->neededWidth, &eLink2->neededHeight); eLink2->layoutWidth = -1; } layout->useWidth = eLink2->neededWidth; layout->useHeight = eLink2->neededHeight; #else Element_NeededSize(tree, eLink1, eLink2->elem, state, &layout->neededWidth, &layout->neededHeight); layout->useWidth = layout->neededWidth; #endif } /* No -union padding yet */ layout->uPadX[PAD_TOP_LEFT] = 0; layout->uPadX[PAD_BOTTOM_RIGHT] = 0; layout->uPadY[PAD_TOP_LEFT] = 0; layout->uPadY[PAD_BOTTOM_RIGHT] = 0; } /* Figure out the padding around elements surrounded by -union elements */ for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; int first = -1, last = -1; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; if (eLink1->onion == NULL) continue; for (j = 0; j < eLink1->onionCount; j++) { struct Layout *layout = &layouts[eLink1->onion[j]]; if (IS_HIDDEN(layout)) continue; /* Remember the first and last visible elements surrounded by * this -union element. */ if (first == -1) first = j; last = j; } /* If there are no visible elements surrounded by this -union * element, then hide it. */ if (first == -1) { layout->visible = 0; continue; } ePadX = eLink1->ePadX; ePadY = eLink1->ePadY; iPadX = eLink1->iPadX; iPadY = eLink1->iPadY; for (j = 0; j < eLink1->onionCount; j++) { struct Layout *layout = &layouts[eLink1->onion[j]]; if (IS_HIDDEN(layout)) continue; uPadX = layout->uPadX; uPadY = layout->uPadY; if (masterStyle->vertical) { uPadX[PAD_TOP_LEFT] = MAX(uPadX[PAD_TOP_LEFT], iPadX[PAD_TOP_LEFT] + ePadX[PAD_TOP_LEFT]); uPadX[PAD_BOTTOM_RIGHT] = MAX(uPadX[PAD_BOTTOM_RIGHT], iPadX[PAD_BOTTOM_RIGHT] + ePadX[PAD_BOTTOM_RIGHT]); if (j == first) /* topmost */ uPadY[PAD_TOP_LEFT] = MAX(uPadY[PAD_TOP_LEFT], iPadY[PAD_TOP_LEFT] + ePadY[PAD_TOP_LEFT]); if (j == last) /* bottommost */ uPadY[PAD_BOTTOM_RIGHT] = MAX(uPadY[PAD_BOTTOM_RIGHT], iPadY[PAD_BOTTOM_RIGHT] + ePadY[PAD_BOTTOM_RIGHT]); } else { if (j == first) /* leftmost */ uPadX[PAD_TOP_LEFT] = MAX(uPadX[PAD_TOP_LEFT], iPadX[PAD_TOP_LEFT] + ePadX[PAD_TOP_LEFT]); if (j == last) /* rightmost */ uPadX[PAD_BOTTOM_RIGHT] = MAX(uPadX[PAD_BOTTOM_RIGHT], iPadX[PAD_BOTTOM_RIGHT] + ePadX[PAD_BOTTOM_RIGHT]); uPadY[PAD_TOP_LEFT] = MAX(uPadY[PAD_TOP_LEFT], iPadY[PAD_TOP_LEFT] + ePadY[PAD_TOP_LEFT]); uPadY[PAD_BOTTOM_RIGHT] = MAX(uPadY[PAD_BOTTOM_RIGHT], iPadY[PAD_BOTTOM_RIGHT] + ePadY[PAD_BOTTOM_RIGHT]); } } } /* Layout elements left-to-right, or top-to-bottom */ for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; ePadX = eLink1->ePadX; ePadY = eLink1->ePadY; iPadX = eLink1->iPadX; iPadY = eLink1->iPadY; uPadX = layout->uPadX; uPadY = layout->uPadY; /* The size of a -union element is determined by the elements * it surrounds */ if (eLink1->onion != NULL) { layout->x = layout->y = layout->eWidth = layout->eHeight = 0; layout->ePadX[PAD_TOP_LEFT] = 0; layout->ePadX[PAD_BOTTOM_RIGHT] = 0; layout->ePadY[PAD_TOP_LEFT] = 0; layout->ePadY[PAD_BOTTOM_RIGHT] = 0; layout->iPadX[PAD_TOP_LEFT] = 0; layout->iPadX[PAD_BOTTOM_RIGHT] = 0; layout->iPadY[PAD_TOP_LEFT] = 0; layout->iPadY[PAD_BOTTOM_RIGHT] = 0; continue; } if (eLink1->flags & ELF_SQUEEZE_X) { if ((eLink1->minWidth >= 0) && (eLink1->minWidth <= layout->useWidth)) { squeezeX += layout->useWidth - eLink1->minWidth; } else { squeezeX += layout->useWidth; } } if (eLink1->flags & ELF_SQUEEZE_Y) { if ((eLink1->minHeight >= 0) && (eLink1->minHeight <= layout->useHeight)) { squeezeY += layout->useHeight - eLink1->minHeight; } else { squeezeY += layout->useHeight; } } /* -detach elements are positioned by themselves */ if (eLink1->flags & ELF_DETACH) continue; layout->eLink = eLink2; layout->x = x + abs(ePadX[PAD_TOP_LEFT] - MAX(ePadX[PAD_TOP_LEFT], uPadX[PAD_TOP_LEFT])); layout->y = y + abs(ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT])); layout->iWidth = iPadX[PAD_TOP_LEFT] + layout->useWidth + iPadX[PAD_BOTTOM_RIGHT]; layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eWidth = ePadX[PAD_TOP_LEFT] + layout->iWidth + ePadX[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; for (j = 0; j < 2; j++) { layout->ePadX[j] = eLink1->ePadX[j]; layout->ePadY[j] = eLink1->ePadY[j]; layout->iPadX[j] = eLink1->iPadX[j]; layout->iPadY[j] = eLink1->iPadY[j]; } if (masterStyle->vertical) y = layout->y + layout->eHeight; else x = layout->x + layout->eWidth; } /* -detach elements */ for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink1 = &eLinks1[i]; eLink2 = &eLinks2[i]; if (!(eLink1->flags & ELF_DETACH) || (eLink1->onion != NULL)) continue; ePadX = eLink1->ePadX; ePadY = eLink1->ePadY; iPadX = eLink1->iPadX; iPadY = eLink1->iPadY; uPadX = layout->uPadX; uPadY = layout->uPadY; layout->eLink = eLink2; layout->master = eLink1; layout->x = abs(ePadX[PAD_TOP_LEFT] - MAX(ePadX[PAD_TOP_LEFT], uPadX[PAD_TOP_LEFT])); layout->y = abs(ePadY[PAD_TOP_LEFT] - MAX(ePadY[PAD_TOP_LEFT], uPadY[PAD_TOP_LEFT])); layout->iWidth = iPadX[PAD_TOP_LEFT] + layout->useWidth + iPadX[PAD_BOTTOM_RIGHT]; layout->iHeight = iPadY[PAD_TOP_LEFT] + layout->useHeight + iPadY[PAD_BOTTOM_RIGHT]; layout->eWidth = ePadX[PAD_TOP_LEFT] + layout->iWidth + ePadX[PAD_BOTTOM_RIGHT]; layout->eHeight = ePadY[PAD_TOP_LEFT] + layout->iHeight + ePadY[PAD_BOTTOM_RIGHT]; for (j = 0; j < 2; j++) { layout->ePadX[j] = eLink1->ePadX[j]; layout->ePadY[j] = eLink1->ePadY[j]; layout->iPadX[j] = eLink1->iPadX[j]; layout->iPadY[j] = eLink1->iPadY[j]; } } Layout_Size(masterStyle->vertical, masterStyle->numElements, layouts, widthPtr, heightPtr); *minWidthPtr = *widthPtr - squeezeX; *minHeightPtr = *heightPtr - squeezeY; STATIC_FREE(layouts, struct Layout, masterStyle->numElements); } /* *---------------------------------------------------------------------- * * Style_CheckNeededSize -- * * If the style's requested size is out-of-date then recalculate * Style.neededWidth, Style.neededHeight, Style.minWidth, and * Style.minHeight. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Style_CheckNeededSize( TreeCtrl *tree, /* Widget info. */ IStyle *style, /* Style info. */ int state /* STATE_xxx flags. */ ) { if (style->neededWidth == -1) { int minWidth, minHeight; Style_NeededSize(tree, style, state, &style->neededWidth, &style->neededHeight, &minWidth, &minHeight); #ifdef CACHE_STYLE_SIZE style->minWidth = minWidth; style->minHeight = minHeight; style->layoutWidth = -1; #endif /* CACHE_STYLE_SIZE */ #ifdef TREECTRL_DEBUG style->neededState = state; #endif } #ifdef TREECTRL_DEBUG if (style->neededState != state) panic("Style_CheckNeededSize: neededState %d != state %d\n", style->neededState, state); #endif } #ifndef CACHE_STYLE_SIZE static void Style_MinSize( TreeCtrl *tree, /* Widget info. */ IStyle *style, /* Style info. */ int state, /* STATE_xxx flags. */ int *minWidthPtr, int *minHeightPtr ) { int i, hasSqueeze = FALSE; for (i = 0; i < style->master->numElements; i++) { MElementLink *eLink1 = &style->master->elements[i]; if ((eLink1->onion == NULL) && (eLink1->flags & (ELF_SQUEEZE_X | ELF_SQUEEZE_Y))) { hasSqueeze = TRUE; break; } } if (hasSqueeze) { int width, height; Style_NeededSize(tree, style, state, &width, &height, minWidthPtr, minHeightPtr); } else { *minWidthPtr = style->neededWidth; *minHeightPtr = style->neededHeight; } } #endif /* !CACHE_STYLE_SIZE */ /* *---------------------------------------------------------------------- * * TreeStyle_NeededWidth -- * * Return the requested width of a style. * * Results: * The requested width. If the requested size is out-of-date * then it is recalculated. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_NeededWidth( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* Style token. */ int state /* STATE_xxx flags. */ ) { IStyle *style = (IStyle *) style_; Style_CheckNeededSize(tree, style, state); return style->neededWidth; } /* *---------------------------------------------------------------------- * * TreeStyle_NeededHeight -- * * Return the requested height of a style. * * Results: * The requested height. If the requested size is out-of-date * then it is recalculated. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_NeededHeight( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* Style token. */ int state /* STATE_xxx flags. */ ) { IStyle *style = (IStyle *) style_; Style_CheckNeededSize(tree, style, state); return style->neededHeight; } /* *---------------------------------------------------------------------- * * TreeStyle_UseHeight -- * * Return the height of a style for a given state and width. * * Results: * The height of the style. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* Calculate height of Style considering drawArgs.width */ int TreeStyle_UseHeight( StyleDrawArgs *drawArgs /* Various args. */ ) { TreeCtrl *tree = drawArgs->tree; IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; int state = drawArgs->state; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; int width, height, minWidth; #ifndef CACHE_STYLE_SIZE int minHeight; #endif Style_CheckNeededSize(tree, style, state); #ifdef CACHE_STYLE_SIZE minWidth = style->minWidth; #else if (drawArgs->width < style->neededWidth + drawArgs->indent) Style_MinSize(tree, style, state, &minWidth, &minHeight); else minWidth = style->neededWidth; #endif /* * If we have: * a) infinite space available, or * b) more width than the style needs, or * c) less width than the style needs, but it has no -squeeze x elements * then return the needed height of the style. This is safe since no * text elements will be growing vertically when lines wrap. */ if ((drawArgs->width == -1) || (drawArgs->width >= style->neededWidth + drawArgs->indent) || (style->neededWidth == minWidth)) { return style->neededHeight; } /* We never lay out the style at less than the minimum width */ if (drawArgs->width < minWidth + drawArgs->indent) drawArgs->width = minWidth + drawArgs->indent; #ifdef CACHE_STYLE_SIZE /* We have less space than the style needs, and have already calculated * the height of the style at this width. (The height may change because * of text elements wrapping lines). */ if (drawArgs->width == style->layoutWidth) return style->layoutHeight; #endif STATIC_ALLOC(layouts, struct Layout, masterStyle->numElements); Style_DoLayout(drawArgs, layouts, TRUE, __FILE__, __LINE__); Layout_Size(style->master->vertical, masterStyle->numElements, layouts, &width, &height); STATIC_FREE(layouts, struct Layout, masterStyle->numElements); #ifdef CACHE_STYLE_SIZE style->layoutWidth = drawArgs->width; style->layoutHeight = height; #endif return height; } /* *---------------------------------------------------------------------- * * TreeStyle_Draw -- * * Draw all the elements in a style. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void TreeStyle_Draw( StyleDrawArgs *drawArgs /* Various args. */ ) { IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; TreeCtrl *tree = drawArgs->tree; int *bounds = drawArgs->bounds; TreeElementArgs args; int i, x, y, minWidth, minHeight; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; #undef DEBUG_DRAW #ifdef DEBUG_DRAW int debugDraw = FALSE; #endif Style_CheckNeededSize(tree, style, drawArgs->state); #ifdef CACHE_STYLE_SIZE minWidth = style->minWidth; minHeight = style->minHeight; #else if ((drawArgs->width < style->neededWidth + drawArgs->indent) || (drawArgs->height < style->neededHeight)) { Style_MinSize(tree, style, drawArgs->state, &minWidth, &minHeight); } else { minWidth = style->neededWidth; minHeight = style->neededHeight; } #endif /* Get the bounds allowed for drawing (in window coordinates), inside * the item-column(s) and inside the header/borders. */ x = drawArgs->x + tree->drawableXOrigin - tree->xOrigin; y = drawArgs->y + tree->drawableYOrigin - tree->yOrigin; args.display.bounds[0] = MAX(bounds[0], x); args.display.bounds[1] = MAX(bounds[1], y); args.display.bounds[2] = MIN(bounds[2], x + drawArgs->width); args.display.bounds[3] = MIN(bounds[3], y + drawArgs->height); /* We never lay out the style at less than the minimum size */ if (drawArgs->width < minWidth + drawArgs->indent) drawArgs->width = minWidth + drawArgs->indent; if (drawArgs->height < minHeight) drawArgs->height = minHeight; STATIC_ALLOC(layouts, struct Layout, masterStyle->numElements); Style_DoLayout(drawArgs, layouts, FALSE, __FILE__, __LINE__); args.tree = tree; args.state = drawArgs->state; args.display.td = drawArgs->td; args.display.drawable = drawArgs->td.drawable; for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; /* Don't "draw" window elements. TreeStyle_UpdateWindowPositions() * does that for us. */ if (ELEMENT_TYPE_MATCHES(layout->eLink->elem->typePtr, &treeElemTypeWindow)) continue; if (PerStateBoolean_ForState(tree, &layout->master->draw, drawArgs->state, NULL) == 0) continue; #ifdef DEBUG_DRAW if (debugDraw && layout->master->onion != NULL) continue; #endif if ((layout->useWidth > 0) && (layout->useHeight > 0)) { args.elem = layout->eLink->elem; args.display.x = drawArgs->x + layout->x + layout->ePadX[PAD_TOP_LEFT]; args.display.y = drawArgs->y + layout->y + layout->ePadY[PAD_TOP_LEFT]; args.display.x += layout->iPadX[PAD_TOP_LEFT]; args.display.y += layout->iPadY[PAD_TOP_LEFT]; args.display.width = layout->useWidth; args.display.height = layout->useHeight; args.display.sticky = layout->master->flags & ELF_STICKY; #ifdef DEBUG_DRAW if (debugDraw) { XColor *color[3]; GC gc[3]; if (layout->master->onion != NULL) { color[0] = Tk_GetColor(tree->interp, tree->tkwin, "blue2"); gc[0] = Tk_GCForColor(color[0], Tk_WindowId(tree->tkwin)); color[1] = Tk_GetColor(tree->interp, tree->tkwin, "blue3"); gc[1] = Tk_GCForColor(color[1], Tk_WindowId(tree->tkwin)); } else { color[0] = Tk_GetColor(tree->interp, tree->tkwin, "gray50"); gc[0] = Tk_GCForColor(color[0], Tk_WindowId(tree->tkwin)); color[1] = Tk_GetColor(tree->interp, tree->tkwin, "gray60"); gc[1] = Tk_GCForColor(color[1], Tk_WindowId(tree->tkwin)); color[2] = Tk_GetColor(tree->interp, tree->tkwin, "gray70"); gc[2] = Tk_GCForColor(color[2], Tk_WindowId(args.tree->tkwin)); } /* external */ XFillRectangle(tree->display, args.display.drawable, gc[2], args.display.x - layout->ePadX[PAD_TOP_LEFT], args.display.y - layout->ePadY[PAD_TOP_LEFT], layout->eWidth, layout->eHeight); /* internal */ XFillRectangle(tree->display, args.display.drawable, gc[1], args.display.x, args.display.y, args.display.width, args.display.height); /* needed */ if (!layout->master->onion && !(layout->master->flags & ELF_DETACH)) XFillRectangle(tree->display, args.display.drawable, gc[0], args.display.x + layout->iPadX[PAD_TOP_LEFT], args.display.y + layout->iPadY[PAD_TOP_LEFT], layout->eLink->neededWidth, layout->eLink->neededHeight); } else #endif /* DEBUG_DRAW */ (*args.elem->typePtr->displayProc)(&args); } } #ifdef DEBUG_DRAW if (debugDraw) for (i = 0; i < masterStyle->numElements; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; if (layout->master->onion == NULL) continue; if (layout->useWidth > 0 && layout->useHeight > 0) { args.elem = layout->eLink->elem; args.display.x = drawArgs->x + layout->x + layout->ePadX[PAD_TOP_LEFT]; args.display.y = drawArgs->y + layout->y + layout->ePadY[PAD_TOP_LEFT]; args.display.width = layout->iWidth; args.display.height = layout->iHeight; { XColor *color[3]; GC gc[3]; color[0] = Tk_GetColor(tree->interp, tree->tkwin, "blue2"); gc[0] = Tk_GCForColor(color[0], Tk_WindowId(tree->tkwin)); color[1] = Tk_GetColor(tree->interp, tree->tkwin, "blue3"); gc[1] = Tk_GCForColor(color[1], Tk_WindowId(tree->tkwin)); /* external */ XDrawRectangle(tree->display, args.display.drawable, gc[0], args.display.x - layout->ePadX[PAD_TOP_LEFT], args.display.y - layout->ePadY[PAD_TOP_LEFT], layout->eWidth - 1, layout->eHeight - 1); /* internal */ XDrawRectangle(tree->display, args.display.drawable, gc[1], args.display.x, args.display.y, args.display.width - 1, args.display.height - 1); } } } #endif /* DEBUG_DRAW */ STATIC_FREE(layouts, struct Layout, masterStyle->numElements); } /* *---------------------------------------------------------------------- * * TreeStyle_UpdateWindowPositions -- * * Call the displayProc on each window element so it can update * its geometry. This is needed if an item was scrolled and its * displayProc wasn't otherwise called. * * Results: * None. * * Side effects: * Possible window geometry changes. * *---------------------------------------------------------------------- */ void TreeStyle_UpdateWindowPositions( StyleDrawArgs *drawArgs /* Various args. */ ) { IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; TreeCtrl *tree = drawArgs->tree; int *bounds = drawArgs->bounds; TreeElementArgs args; int i, x, y, minWidth, minHeight; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; int numElements = masterStyle->numElements; /* FIXME: Perhaps remember whether this style has any window * elements */ for (i = 0; i < numElements; i++) { if (ELEMENT_TYPE_MATCHES(masterStyle->elements[i].elem->typePtr, &treeElemTypeWindow)) break; } if (i == numElements) return; Style_CheckNeededSize(tree, style, drawArgs->state); #ifdef CACHE_STYLE_SIZE minWidth = style->minWidth; minHeight = style->minHeight; #else if ((drawArgs->width < style->neededWidth + drawArgs->indent) || (drawArgs->height < style->neededHeight)) { Style_MinSize(tree, style, drawArgs->state, &minWidth, &minHeight); } else { minWidth = style->neededWidth; minHeight = style->neededHeight; } #endif /* Get the bounds allowed for drawing (in window coordinates), inside * the item-column(s) and inside the header/borders. */ x = drawArgs->x + tree->drawableXOrigin - tree->xOrigin; y = drawArgs->y + tree->drawableYOrigin - tree->yOrigin; args.display.bounds[0] = MAX(bounds[0], x); args.display.bounds[1] = MAX(bounds[1], y); args.display.bounds[2] = MIN(bounds[2], x + drawArgs->width); args.display.bounds[3] = MIN(bounds[3], y + drawArgs->height); /* We never lay out the style at less than the minimum size */ if (drawArgs->width < minWidth + drawArgs->indent) drawArgs->width = minWidth + drawArgs->indent; if (drawArgs->height < minHeight) drawArgs->height = minHeight; STATIC_ALLOC(layouts, struct Layout, numElements); Style_DoLayout(drawArgs, layouts, FALSE, __FILE__, __LINE__); args.tree = tree; args.state = drawArgs->state; args.display.td = drawArgs->td; args.display.drawable = drawArgs->td.drawable; for (i = 0; i < numElements; i++) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; if (!ELEMENT_TYPE_MATCHES(layout->eLink->elem->typePtr, &treeElemTypeWindow)) continue; if (PerStateBoolean_ForState(tree, &layout->master->draw, drawArgs->state, NULL) == 0) continue; if ((layout->useWidth > 0) && (layout->useHeight > 0)) { int requests; TreeDisplay_GetReadyForTrouble(tree, &requests); args.elem = layout->eLink->elem; args.display.x = drawArgs->x + layout->x + layout->ePadX[PAD_TOP_LEFT]; args.display.y = drawArgs->y + layout->y + layout->ePadY[PAD_TOP_LEFT]; args.display.x += layout->iPadX[PAD_TOP_LEFT]; args.display.y += layout->iPadY[PAD_TOP_LEFT]; args.display.width = layout->useWidth; args.display.height = layout->useHeight; args.display.sticky = layout->master->flags & ELF_STICKY; (*args.elem->typePtr->displayProc)(&args); /* Updating the position of a window may generate a * or event on that window. Binding scripts on those * events could do anything, including deleting items and * thus the style we are drawing. In other cases (such as when * using Tile widgets I notice), the Tk_GeomMgr.requestProc * may get called which calls Tree_ElementChangedItself which * calls FreeDItemInfo which frees a DItem we are in the middle * of displaying. So if anything was done that caused a display * request, then abort abort abort. */ if (TreeDisplay_WasThereTrouble(tree, requests)) break; } } STATIC_FREE(layouts, struct Layout, numElements); } /* *---------------------------------------------------------------------- * * TreeStyle_OnScreen -- * * Call the onScreenProc (if non-NULL) on each element so it can * update its visibility when an item's visibility changes. * * Results: * None. * * Side effects: * Possible window visibility changes. * *---------------------------------------------------------------------- */ void TreeStyle_OnScreen( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* Style token. */ int onScreen /* Boolean indicating whether the item * using the style is on screen anymore. */ ) { IStyle *style = (IStyle *) style_; TreeElementArgs args; int i; args.tree = tree; args.screen.visible = onScreen; for (i = 0; i < style->master->numElements; i++) { IElementLink *eLink = &style->elements[i]; if (eLink->elem->typePtr->onScreenProc == NULL) continue; args.elem = eLink->elem; (*args.elem->typePtr->onScreenProc)(&args); } } /* *---------------------------------------------------------------------- * * Element_FreeResources -- * * Free memory etc associated with an Element. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ static void Element_FreeResources( TreeCtrl *tree, /* Widget info. */ TreeElement elem /* Record to free. */ ) { TreeElementType *typePtr = elem->typePtr; TreeElementArgs args; Tcl_HashEntry *hPtr; if (elem->master == NULL) { hPtr = Tcl_FindHashEntry(&tree->elementHash, elem->name); Tcl_DeleteHashEntry(hPtr); } args.tree = tree; args.elem = elem; (*typePtr->deleteProc)(&args); Tk_FreeConfigOptions((char *) elem, typePtr->optionTable, tree->tkwin); DynamicOption_Free(tree, elem->options, typePtr->optionSpecs); #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, typePtr->name, (char *) elem, typePtr->size); #else WFREE(elem, TreeElement_); #endif } /* *---------------------------------------------------------------------- * * MElementLink_Init -- * * Initialize (don't allocate) a MElementLink. * * Results: * eLink is filled with default values. * * Side effects: * None. * *---------------------------------------------------------------------- */ static MElementLink * MElementLink_Init( MElementLink *eLink, /* Existing record to initialize. */ TreeElement elem /* Existing element to point to. */ ) { memset(eLink, '\0', sizeof(MElementLink)); eLink->elem = elem; eLink->flags |= ELF_INDENT; eLink->minWidth = eLink->fixedWidth = eLink->maxWidth = -1; eLink->minHeight = eLink->fixedHeight = eLink->maxHeight = -1; eLink->flags |= ELF_STICKY; return eLink; } /* *---------------------------------------------------------------------- * * MElementLink_FreeResources -- * * Free memory etc associated with an MElementLink. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ static void MElementLink_FreeResources( TreeCtrl *tree, /* Widget info. */ MElementLink *eLink /* Record to free. */ ) { if (eLink->onion != NULL) WCFREE(eLink->onion, int, eLink->onionCount); PerStateInfo_Free(tree, &pstBoolean, &eLink->draw); if (eLink->draw.obj != NULL) { Tcl_DecrRefCount(eLink->draw.obj); } PerStateInfo_Free(tree, &pstBoolean, &eLink->visible); if (eLink->visible.obj != NULL) { Tcl_DecrRefCount(eLink->visible.obj); } } /* *---------------------------------------------------------------------- * * IElementLink_FreeResources -- * * Free memory etc associated with an ElementLink. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ static void IElementLink_FreeResources( TreeCtrl *tree, /* Widget info. */ IElementLink *eLink /* Record to free. */ ) { if (eLink->elem->master != NULL) Element_FreeResources(tree, eLink->elem); } /* *---------------------------------------------------------------------- * * MStyle_FreeResources -- * * Free memory etc associated with a Style. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ static void MStyle_FreeResources( TreeCtrl *tree, /* Widget info. */ MStyle *style /* Style to free. */ ) { Tcl_HashEntry *hPtr; int i; hPtr = Tcl_FindHashEntry(&tree->styleHash, style->name); Tcl_DeleteHashEntry(hPtr); if (style->numElements > 0) { for (i = 0; i < style->numElements; i++) MElementLink_FreeResources(tree, &style->elements[i]); #ifdef ALLOC_HAX TreeAlloc_CFree(tree->allocData, MElementLinkUid, (char *) style->elements, sizeof(MElementLink), style->numElements, ELEMENT_LINK_ROUND); #else WCFREE(style->elements, MElementLink, style->numElements); #endif } #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, MStyleUid, (char *) style, sizeof(MStyle)); #else WFREE(style, MStyle); #endif } /* *---------------------------------------------------------------------- * * IStyle_FreeResources -- * * Free memory etc associated with a Style. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ static void IStyle_FreeResources( TreeCtrl *tree, /* Widget info. */ IStyle *style /* Style to free. */ ) { MStyle *masterStyle = style->master; int i; if (masterStyle->numElements > 0) { for (i = 0; i < masterStyle->numElements; i++) IElementLink_FreeResources(tree, &style->elements[i]); #ifdef ALLOC_HAX TreeAlloc_CFree(tree->allocData, IElementLinkUid, (char *) style->elements, sizeof(IElementLink), masterStyle->numElements, ELEMENT_LINK_ROUND); #else WCFREE(style->elements, IElementLink, masterStyle->numElements); #endif } #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, IStyleUid, (char *) style, sizeof(IStyle)); #else WFREE(style, IStyle); #endif } /* *---------------------------------------------------------------------- * * TreeStyle_FreeResources -- * * Free memory etc associated with a Style. * * Results: * None. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeStyle_FreeResources( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* Token of style to free. */ ) { MStyle *masterStyle = (MStyle *) style_; IStyle *style = (IStyle *) style_; if (style->master == NULL) MStyle_FreeResources(tree, masterStyle); else IStyle_FreeResources(tree, style); } /* *---------------------------------------------------------------------- * * MStyle_FindElem -- * * Find an ElementLink in a style. * * Results: * If found, a pointer to the ElementLink and index in the * style's array of ElementLinks is returned; otherwise NULL * is returned. * * Side effects: * World peace. * *---------------------------------------------------------------------- */ static MElementLink * MStyle_FindElem( TreeCtrl *tree, /* Widget info. */ MStyle *style, /* Style to search. */ TreeElement master, /* Master element to find. */ int *index /* Returned index, may be NULL. */ ) { int i; for (i = 0; i < style->numElements; i++) { MElementLink *eLink = &style->elements[i]; if (eLink->elem->name == master->name) { if (index != NULL) (*index) = i; return eLink; } } return NULL; } /* *---------------------------------------------------------------------- * * IStyle_FindElem -- * * Find an ElementLink in a style. * * Results: * If found, a pointer to the ElementLink and index in the * style's array of ElementLinks is returned; otherwise NULL * is returned. * * Side effects: * World peace. * *---------------------------------------------------------------------- */ static IElementLink * IStyle_FindElem( TreeCtrl *tree, /* Widget info. */ IStyle *style, /* Style to search. */ TreeElement master, /* Master element to find. */ int *index /* Returned index, may be NULL. */ ) { MStyle *masterStyle = style->master; int i; for (i = 0; i < masterStyle->numElements; i++) { IElementLink *eLink = &style->elements[i]; if (eLink->elem->name == master->name) { if (index != NULL) (*index) = i; return eLink; } } return NULL; } /* *---------------------------------------------------------------------- * * TreeStyle_FindElement -- * * Find an ElementLink in a style. * * Results: * If found, the index in the style's array of ElementLinks is * returned with TCL_OK. Otherwise TCL_ERROR is returned and an * error message is placed in the interpreter result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_FindElement( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* Token of style to search. */ TreeElement elem, /* Master element to find. */ int *index /* Returned index, may be NULL. */ ) { MStyle *masterStyle = (MStyle *) style_; IStyle *style = (IStyle *) style_; if (((style->master == NULL) && (MStyle_FindElem(tree, masterStyle, elem, index) == NULL)) || ((style->master != NULL) && (IStyle_FindElem(tree, style, elem, index) == NULL))) { FormatResult(tree->interp, "style %s does not use element %s", style->master ? style->master->name : masterStyle->name, elem->name); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Element_CreateAndConfig -- * * Allocate and initialize a new Element (master or instance). * * Results: * An Element is allocated, its createProc is called, default * configuration options are set, then the configProc and changeProc * are called to handle any given configurations options. If an * error occurs NULL is returned. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static TreeElement Element_CreateAndConfig( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the element. Should * be NULL for a master element. */ TreeItemColumn column, /* Item-column containing the element. * Should be NULL for a master element. */ TreeElement masterElem, /* Master element if creating an instance. */ TreeElementType *type, /* Element type. Should be NULL when * creating an instance. */ CONST char *name, /* Name of master element, NULL for an * instance. */ int objc, /* Array of intialial configuration. */ Tcl_Obj *CONST objv[] /* options. */ ) { TreeElement elem; TreeElementArgs args; if (masterElem != NULL) { type = masterElem->typePtr; name = masterElem->name; } #ifdef ALLOC_HAX elem = (TreeElement) TreeAlloc_Alloc(tree->allocData, type->name, type->size); #else elem = (TreeElement) ckalloc(type->size); #endif memset(elem, '\0', type->size); elem->name = Tk_GetUid(name); elem->typePtr = type; elem->master = masterElem; args.tree = tree; args.elem = elem; args.create.item = item; args.create.column = column; if ((*type->createProc)(&args) != TCL_OK) { #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, type->name, (char *) elem, type->size); #else WFREE(elem, TreeElement_); #endif return NULL; } if (Tk_InitOptions(tree->interp, (char *) elem, type->optionTable, tree->tkwin) != TCL_OK) { #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, type->name, (char *) elem, type->size); #else WFREE(elem, TreeElement_); #endif return NULL; } args.config.objc = objc; args.config.objv = objv; args.config.flagSelf = 0; args.config.item = item; args.config.column = column; if ((*type->configProc)(&args) != TCL_OK) { (*type->deleteProc)(&args); Tk_FreeConfigOptions((char *) elem, type->optionTable, tree->tkwin); DynamicOption_Free(tree, elem->options, type->optionSpecs); #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, type->name, (char *) elem, type->size); #else WFREE(elem, TreeElement_); #endif return NULL; } args.change.flagSelf = args.config.flagSelf; args.change.flagTree = 0; args.change.flagMaster = 0; (*type->changeProc)(&args); return elem; } /* *---------------------------------------------------------------------- * * Style_CreateElem -- * * Allocate and initialize a new instance Element in a IStyle * (if it doesn't already exist) and return its associated * IElementLink. * * Results: * If the style already has a matching instance element, then a * pointer to an existing IElementLink is returned. * If the style does not already have a matching instance element, * then a new one is created and a pointer to an existing * IElementLink is returned. * If an error occurs creating the new element the result is * NULL. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static IElementLink * Style_CreateElem( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the element. */ TreeItemColumn column, /* Item-column containing the element. */ IStyle *style, /* Style to search/add the element to. */ TreeElement masterElem, /* Element to find or create and instance of. */ int *isNew) /* If non-NULL, set to TRUE if a new instance * element was created. */ { MStyle *masterStyle = style->master; IElementLink *eLink = NULL; TreeElement elem; int i; if (masterElem->master != NULL) panic("Style_CreateElem called with instance Element"); if (isNew != NULL) (*isNew) = FALSE; for (i = 0; i < masterStyle->numElements; i++) { eLink = &style->elements[i]; if (eLink->elem == masterElem) { /* Allocate instance Element here */ break; } /* Instance Style already has instance Element */ if (eLink->elem->name == masterElem->name) return eLink; } /* Error: Element isn't in the master Style */ if (i == masterStyle->numElements) return NULL; elem = Element_CreateAndConfig(tree, item, column, masterElem, NULL, NULL, 0, NULL); if (elem == NULL) return NULL; eLink->elem = elem; if (isNew != NULL) (*isNew) = TRUE; return eLink; } /* *---------------------------------------------------------------------- * * TreeStyle_NewInstance -- * * Create and initialize a new instance of a master style. * * Results: * A new instance Style. The new array of ElementLinks is * initialized to contain pointers to master elements; instance * elements are created the first time they are configured. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ TreeStyle TreeStyle_NewInstance( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* Master style to create instance of. */ ) { MStyle *style = (MStyle *) style_; IStyle *copy; IElementLink *eLink; int i; #ifdef ALLOC_HAX copy = (IStyle *) TreeAlloc_Alloc(tree->allocData, IStyleUid, sizeof(IStyle)); #else copy = (IStyle *) ckalloc(sizeof(IStyle)); #endif memset(copy, '\0', sizeof(IStyle)); copy->master = style; copy->neededWidth = -1; copy->neededHeight = -1; if (style->numElements > 0) { #ifdef ALLOC_HAX copy->elements = (IElementLink *) TreeAlloc_CAlloc(tree->allocData, IElementLinkUid, sizeof(IElementLink), style->numElements, ELEMENT_LINK_ROUND); #else copy->elements = (IElementLink *) ckalloc(sizeof(IElementLink) * style->numElements); #endif memset(copy->elements, '\0', sizeof(IElementLink) * style->numElements); for (i = 0; i < style->numElements; i++) { eLink = ©->elements[i]; eLink->elem = style->elements[i].elem; #ifdef CACHE_ELEM_SIZE eLink->neededWidth = -1; eLink->neededHeight = -1; #endif } } return (TreeStyle) copy; } /* *---------------------------------------------------------------------- * * Element_FromObj -- * * Convert a Tcl_Obj to a master element. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int Element_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *obj, /* Object to convert from. */ TreeElement *elemPtr /* Returned record. */ ) { char *name; Tcl_HashEntry *hPtr; name = Tcl_GetString(obj); hPtr = Tcl_FindHashEntry(&tree->elementHash, name); if (hPtr == NULL) { Tcl_AppendResult(tree->interp, "element \"", name, "\" doesn't exist", NULL); return TCL_ERROR; } (*elemPtr) = (TreeElement) Tcl_GetHashValue(hPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeElement_FromObj -- * * Convert a Tcl_Obj to a master element. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeElement_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *obj, /* Object to convert from. */ TreeElement *elemPtr /* Returned master element token. */ ) { return Element_FromObj(tree, obj, elemPtr); } /* *---------------------------------------------------------------------- * * TreeElement_IsType -- * * Determine if an element is of a certain type. * * Results: * TRUE if the type matches, otherwise FALSE. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeElement_IsType( TreeCtrl *tree, /* Widget info. */ TreeElement elem, /* Element to check. */ CONST char *type /* NULL-terminated element type name. */ ) { return strcmp(elem->typePtr->name, type) == 0; } /* *---------------------------------------------------------------------- * * TreeStyle_FromObj -- * * Convert a Tcl_Obj to a master style. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *obj, /* Object to convert from. */ TreeStyle *stylePtr) /* Returned master style token. */ { char *name; Tcl_HashEntry *hPtr; name = Tcl_GetString(obj); hPtr = Tcl_FindHashEntry(&tree->styleHash, name); if (hPtr == NULL) { Tcl_AppendResult(tree->interp, "style \"", name, "\" doesn't exist", NULL); return TCL_ERROR; } (*stylePtr) = (TreeStyle) Tcl_GetHashValue(hPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Element_ToObj -- * * Create a new Tcl_Obj representing an element. * * Results: * A Tcl_Obj. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static Tcl_Obj * Element_ToObj( TreeElement elem /* Element to create Tcl_Obj from. */ ) { return Tcl_NewStringObj(elem->name, -1); } /* *---------------------------------------------------------------------- * * TreeStyle_ToObj -- * * Create a new Tcl_Obj representing a style. * * Results: * A Tcl_Obj. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ Tcl_Obj * TreeStyle_ToObj( TreeStyle style_ /* Style token to create Tcl_Obj from. */ ) { MStyle *masterStyle = (MStyle *) style_; IStyle *style = (IStyle *) style_; if (style->master != NULL) masterStyle = style->master; return Tcl_NewStringObj(masterStyle->name, -1); } /* *---------------------------------------------------------------------- * * Style_Changed -- * * Called when a master style is configured or the layout of one * of its elements changes. * * Results: * For each item-column using an instance of the given master * style, size and display info is marked out-of-date. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void Style_Changed( TreeCtrl *tree, /* Widget info. */ MStyle *masterStyle /* Style that changed. */ ) { TreeItem item; TreeItemColumn column; TreeColumn treeColumn; Tcl_HashEntry *hPtr; Tcl_HashSearch search; int columnIndex, layout; int updateDInfo = FALSE; IStyle *style; hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); treeColumn = tree->columns; column = TreeItem_GetFirstColumn(tree, item); columnIndex = 0; layout = FALSE; while (column != NULL) { style = (IStyle *) TreeItemColumn_GetStyle(tree, column); if ((style != NULL) && (style->master == masterStyle)) { #ifdef CACHE_ELEM_SIZE int i; for (i = 0; i < masterStyle->numElements; i++) { IElementLink *eLink = &style->elements[i]; /* This is needed if the -width/-height layout options change */ eLink->neededWidth = eLink->neededHeight = -1; } #endif style->neededWidth = style->neededHeight = -1; Tree_InvalidateColumnWidth(tree, treeColumn); TreeItemColumn_InvalidateSize(tree, column); layout = TRUE; } columnIndex++; column = TreeItemColumn_GetNext(tree, column); treeColumn = TreeColumn_Next(treeColumn); } if (layout) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); updateDInfo = TRUE; } hPtr = Tcl_NextHashEntry(&search); } if (updateDInfo) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } /* *---------------------------------------------------------------------- * * MStyle_ChangeElementsAux -- * * Update the list of elements used by a style. Elements * may be inserted or deleted. * * Results: * The list of elements in the style is updated. * * Side effects: * Memory may be allocated/deallocated. * *---------------------------------------------------------------------- */ static void MStyle_ChangeElementsAux( TreeCtrl *tree, /* Widget info. */ MStyle *style, /* Master style to be updated. */ int count, /* The number of elements in the style after * this routine finishes. */ TreeElement *elemList, /* List of master elements the style uses. */ int *map /* Array of indexes into the list of elements * currently used by the style. */ ) { MElementLink *eLink, *eLinks = NULL; int i, staticKeep[STATIC_SIZE], *keep = staticKeep; STATIC_ALLOC(keep, int, style->numElements); if (count > 0) { #ifdef ALLOC_HAX eLinks = (MElementLink *) TreeAlloc_CAlloc(tree->allocData, MElementLinkUid, sizeof(MElementLink), count, ELEMENT_LINK_ROUND); #else eLinks = (MElementLink *) ckalloc(sizeof(MElementLink) * count); #endif } /* Assume we are discarding all the old ElementLinks */ for (i = 0; i < style->numElements; i++) keep[i] = 0; for (i = 0; i < count; i++) { if (map[i] != -1) { eLinks[i] = style->elements[map[i]]; keep[map[i]] = 1; } else { eLink = MElementLink_Init(&eLinks[i], elemList[i]); } } if (style->numElements > 0) { /* Free unused ElementLinks */ for (i = 0; i < style->numElements; i++) { if (!keep[i]) { MElementLink_FreeResources(tree, &style->elements[i]); } } #ifdef ALLOC_HAX TreeAlloc_CFree(tree->allocData, MElementLinkUid, (char *) style->elements, sizeof(MElementLink), style->numElements, ELEMENT_LINK_ROUND); #else WCFREE(style->elements, MElementLink, style->numElements); #endif } STATIC_FREE(keep, int, style->numElements); style->elements = eLinks; style->numElements = count; } /* *---------------------------------------------------------------------- * * IStyle_ChangeElementsAux -- * * Update the list of elements used by a style. Elements * may be inserted or deleted. * * Results: * The list of elements in the style is updated. * * Side effects: * Memory may be allocated/deallocated. * *---------------------------------------------------------------------- */ static void IStyle_ChangeElementsAux( TreeCtrl *tree, /* Widget info. */ IStyle *style, /* Instance style to be updated. */ int oldCount, /* The previous number of elements. */ int count, /* The number of elements in the style after * this routine finishes. */ TreeElement *elemList, /* List of master elements the style uses. */ int *map /* Array of indexes into the list of elements * currently used by the style. */ ) { IElementLink *eLink, *eLinks = NULL; int i, staticKeep[STATIC_SIZE], *keep = staticKeep; STATIC_ALLOC(keep, int, oldCount); if (count > 0) { #ifdef ALLOC_HAX eLinks = (IElementLink *) TreeAlloc_CAlloc(tree->allocData, IElementLinkUid, sizeof(IElementLink), count, ELEMENT_LINK_ROUND); #else eLinks = (IElementLink *) ckalloc(sizeof(IElementLink) * count); #endif } /* Assume we are discarding all the old ElementLinks */ for (i = 0; i < oldCount; i++) keep[i] = 0; for (i = 0; i < count; i++) { if (map[i] != -1) { eLinks[i] = style->elements[map[i]]; keep[map[i]] = 1; } else { eLink = &eLinks[i]; eLink->elem = elemList[i]; #ifdef CACHE_ELEM_SIZE eLink->neededWidth = eLink->neededHeight = -1; #endif } } if (oldCount > 0) { /* Free unused ElementLinks */ for (i = 0; i < oldCount; i++) { if (!keep[i]) { IElementLink_FreeResources(tree, &style->elements[i]); } } #ifdef ALLOC_HAX TreeAlloc_CFree(tree->allocData, IElementLinkUid, (char *) style->elements, sizeof(IElementLink), oldCount, ELEMENT_LINK_ROUND); #else WCFREE(style->elements, IElementLink, oldCount); #endif } STATIC_FREE(keep, int, oldCount); style->elements = eLinks; } /* *---------------------------------------------------------------------- * * Style_ChangeElements -- * * Update the list of elements used by a style. Elements * may be inserted or deleted. * * Results: * The list of elements in the master style is updated. For * each item-column using an instance of the master style, * the list of elements is updated. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void Style_ChangeElements( TreeCtrl *tree, /* Widget info. */ MStyle *masterStyle, /* Master style to be updated. */ int count, /* The number of elements in the style after * this routine finishes. */ TreeElement *elemList, /* List of master elements the style uses. */ int *map /* Array of indexes into the list of elements * currently used by the style. */ ) { TreeItem item; TreeItemColumn column; TreeColumn treeColumn; Tcl_HashEntry *hPtr; Tcl_HashSearch search; int columnIndex, layout; int updateDInfo = FALSE; IStyle *style; int i, j, k, oldCount; /* Update -union lists */ for (i = 0; i < masterStyle->numElements; i++) { MElementLink *eLink = &masterStyle->elements[i]; int staticKeep[STATIC_SIZE], *keep = staticKeep; int onionCnt = 0, *onion = NULL; if (eLink->onion == NULL) continue; STATIC_ALLOC(keep, int, eLink->onionCount); /* Check every Element in this -union */ for (j = 0; j < eLink->onionCount; j++) { MElementLink *eLink2 = &masterStyle->elements[eLink->onion[j]]; /* Check the new list of Elements */ keep[j] = -1; for (k = 0; k < count; k++) { /* This new Element is in the -union */ if (elemList[k] == eLink2->elem) { keep[j] = k; onionCnt++; break; } } } if (onionCnt > 0) { if (onionCnt != eLink->onionCount) onion = (int *) ckalloc(sizeof(int) * onionCnt); else onion = eLink->onion; k = 0; for (j = 0; j < eLink->onionCount; j++) { if (keep[j] != -1) onion[k++] = keep[j]; } } STATIC_FREE(keep, int, eLink->onionCount); if (onionCnt != eLink->onionCount) { WCFREE(eLink->onion, int, eLink->onionCount); eLink->onion = onion; eLink->onionCount = onionCnt; } } oldCount = masterStyle->numElements; MStyle_ChangeElementsAux(tree, masterStyle, count, elemList, map); hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); treeColumn = tree->columns; column = TreeItem_GetFirstColumn(tree, item); columnIndex = 0; layout = FALSE; while (column != NULL) { style = (IStyle *) TreeItemColumn_GetStyle(tree, column); if ((style != NULL) && (style->master == masterStyle)) { IStyle_ChangeElementsAux(tree, style, oldCount, count, elemList, map); style->neededWidth = style->neededHeight = -1; Tree_InvalidateColumnWidth(tree, treeColumn); TreeItemColumn_InvalidateSize(tree, column); layout = TRUE; } columnIndex++; column = TreeItemColumn_GetNext(tree, column); treeColumn = TreeColumn_Next(treeColumn); } if (layout) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); updateDInfo = TRUE; } hPtr = Tcl_NextHashEntry(&search); } if (updateDInfo) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } /* *---------------------------------------------------------------------- * * Style_ElemChanged -- * * Called when a master element or TreeCtrl is configured. * * Results: * A check is made on each item-column to see if it is using * the element. The size of any element/column/item affected * is marked out-of-date. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void Style_ElemChanged( TreeCtrl *tree, /* Widget info. */ MStyle *masterStyle, /* Master style that uses the element. */ TreeElement masterElem, /* Master element affected by the change. */ int masterElemIndex, /* Index of masterElem in masterStyle. */ int flagM, /* Flags returned by TreeElementType.configProc() * if the master element was configured, * zero if the TreeCtrl was configured. */ int flagT, /* TREE_CONF_xxx flags if the TreeCtrl was * configured, zero if the master element * was configured. */ int csM /* CS_xxx flags returned by * TreeElementType.changeProc(). */ ) { TreeItem item; TreeItemColumn column; TreeColumn treeColumn; Tcl_HashEntry *hPtr; Tcl_HashSearch search; IElementLink *eLink; int columnIndex; TreeElementArgs args; IStyle *style; int eMask, cMask, iMask; int updateDInfo = FALSE; args.tree = tree; args.change.flagTree = flagT; args.change.flagMaster = flagM; args.change.flagSelf = 0; hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); treeColumn = tree->columns; column = TreeItem_GetFirstColumn(tree, item); columnIndex = 0; iMask = 0; while (column != NULL) { cMask = 0; style = (IStyle *) TreeItemColumn_GetStyle(tree, column); if ((style != NULL) && (style->master == masterStyle)) { eLink = &style->elements[masterElemIndex]; if (eLink->elem == masterElem) { #ifdef CACHE_ELEM_SIZE if (csM & CS_LAYOUT) eLink->neededWidth = eLink->neededHeight = -1; #endif cMask |= csM; } /* Instance element */ else { args.elem = eLink->elem; eMask = (*masterElem->typePtr->changeProc)(&args); #ifdef CACHE_ELEM_SIZE if (eMask & CS_LAYOUT) eLink->neededWidth = eLink->neededHeight = -1; #endif cMask |= eMask; } iMask |= cMask; if (cMask & CS_LAYOUT) { style->neededWidth = style->neededHeight = -1; Tree_InvalidateColumnWidth(tree, treeColumn); TreeItemColumn_InvalidateSize(tree, column); } else if (cMask & CS_DISPLAY) { Tree_InvalidateItemDInfo(tree, treeColumn, item, NULL); } } columnIndex++; column = TreeItemColumn_GetNext(tree, column); treeColumn = TreeColumn_Next(treeColumn); } if (iMask & CS_LAYOUT) { TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); updateDInfo = TRUE; } else if (iMask & CS_DISPLAY) { } hPtr = Tcl_NextHashEntry(&search); } if (updateDInfo) Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } /* *---------------------------------------------------------------------- * * TreeStyle_GetMaster -- * * Return the master style for an instance style. * * Results: * Token for the master style. * * Side effects: * None. * *---------------------------------------------------------------------- */ TreeStyle TreeStyle_GetMaster( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* Instance style token. */ ) { return (TreeStyle) ((IStyle *) style_)->master; } static Tcl_Obj *confImageObj = NULL; static Tcl_Obj *confTextObj = NULL; /* *---------------------------------------------------------------------- * * Style_GetImageOrText -- * * Return the value of a configuration option for an element. * * Results: * The result of Tk_GetOptionValue for an option of the first * element of the proper type (if any), otherwise NULL. * * Side effects: * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ static Tcl_Obj * Style_GetImageOrText( TreeCtrl *tree, /* Widget info. */ IStyle *style, /* Style. */ TreeElementType *typePtr, /* Type of element to look for. */ CONST char *optionName, /* Name of config option to query. */ Tcl_Obj **optionNameObj /* Pointer to a Tcl_Obj to hold the * option name. Initialized * on the first call. */ ) { IElementLink *eLink; int i; if (*optionNameObj == NULL) { *optionNameObj = Tcl_NewStringObj(optionName, -1); Tcl_IncrRefCount(*optionNameObj); } for (i = 0; i < style->master->numElements; i++) { eLink = &style->elements[i]; if (ELEMENT_TYPE_MATCHES(eLink->elem->typePtr, typePtr)) { Tcl_Obj *resultObjPtr; resultObjPtr = Tk_GetOptionValue(tree->interp, (char *) eLink->elem, eLink->elem->typePtr->optionTable, *optionNameObj, tree->tkwin); return resultObjPtr; } } return NULL; } /* *---------------------------------------------------------------------- * * TreeStyle_GetImage -- * * Return the value of the -image option for the first * image element in a style (if any). * * Results: * The result of Tk_GetOptionValue if the element was found, * otherwise NULL. * * Side effects: * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ Tcl_Obj * TreeStyle_GetImage( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* Token for style to examine. */ ) { return Style_GetImageOrText(tree, (IStyle *) style_, &treeElemTypeImage, "-image", &confImageObj); } /* *---------------------------------------------------------------------- * * TreeStyle_GetText -- * * Return the value of the -text option for the first * text element in a style (if any). * * Results: * The result of Tk_GetOptionValue if the element was found, * otherwise NULL. * * Side effects: * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ Tcl_Obj * TreeStyle_GetText( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* Token for style to examine. */ ) { return Style_GetImageOrText(tree, (IStyle *) style_, &treeElemTypeText, "-text", &confTextObj); } /* *---------------------------------------------------------------------- * * Style_SetImageOrText -- * * Set the value of a configuration option for the first * element of the proper type in a style (if any). * * Results: * A standard Tcl result. * * Side effects: * Size of the element and style will be marked out-of-date. * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ static int Style_SetImageOrText( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the style. Needed if * a new instance Element is created. */ TreeItemColumn column, /* Item-column containing the style */ IStyle *style, /* The style */ TreeElementType *typePtr, /* Element type to look for. */ CONST char *optionName, /* NULL-terminated config option name. */ Tcl_Obj **optionNameObj, /* Pointer to Tcl_Obj to hold the option * name; initialized on the first call. */ Tcl_Obj *valueObj /* New value for the config option. */ ) { MStyle *masterStyle = style->master; IElementLink *eLink; int i; if (*optionNameObj == NULL) { *optionNameObj = Tcl_NewStringObj(optionName, -1); Tcl_IncrRefCount(*optionNameObj); } for (i = 0; i < masterStyle->numElements; i++) { TreeElement masterElem = masterStyle->elements[i].elem; if (ELEMENT_TYPE_MATCHES(masterElem->typePtr, typePtr)) { Tcl_Obj *objv[2]; TreeElementArgs args; eLink = Style_CreateElem(tree, item, column, style, masterElem, NULL); objv[0] = *optionNameObj; objv[1] = valueObj; args.tree = tree; args.elem = eLink->elem; args.config.objc = 2; args.config.objv = objv; args.config.flagSelf = 0; args.config.item = item; args.config.column = column; if ((*eLink->elem->typePtr->configProc)(&args) != TCL_OK) return TCL_ERROR; args.change.flagSelf = args.config.flagSelf; args.change.flagTree = 0; args.change.flagMaster = 0; (void) (*eLink->elem->typePtr->changeProc)(&args); #ifdef CACHE_ELEM_SIZE eLink->neededWidth = eLink->neededHeight = -1; #endif style->neededWidth = style->neededHeight = -1; break; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeStyle_SetImage -- * * Set the value of the -image option for the first image * element in a style (if any). * * Results: * A standard Tcl result. * * Side effects: * Size of the element and style will be marked out-of-date. * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ int TreeStyle_SetImage( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the style. */ TreeItemColumn column, /* Item-column containing the style. */ TreeStyle style_, /* The instance style. */ Tcl_Obj *valueObj /* New value for -image option. */ ) { return Style_SetImageOrText(tree, item, column, (IStyle *) style_, &treeElemTypeImage, "-image", &confImageObj, valueObj); } /* *---------------------------------------------------------------------- * * TreeStyle_SetText -- * * Set the value of the -text option for the first text * element in a style (if any). * * Results: * A standard Tcl result. * * Side effects: * Size of the element and style will be marked out-of-date. * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ int TreeStyle_SetText( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the style. */ TreeItemColumn column, /* Item-column containing the style. */ TreeStyle style_, /* The instance style. */ Tcl_Obj *valueObj /* New value for -text option. */ ) { return Style_SetImageOrText(tree, item, column, (IStyle *) style_, &treeElemTypeText, "-text", &confTextObj, valueObj); } /* *---------------------------------------------------------------------- * * Style_Deleted -- * * Called when a master style is about to be deleted. Any * item-columns using an instance of the style have their style * freed. * * Results: * The TreeCtrl -defaultstyle option is updated if the deleted * style was specified in the value of the option. * * Side effects: * Display changes. Memory is deallocated. * *---------------------------------------------------------------------- */ static void Style_Deleted( TreeCtrl *tree, /* Widget info. */ MStyle *masterStyle /* The master style being deleted. */ ) { TreeItem item; TreeItemColumn column; TreeColumn treeColumn; Tcl_HashEntry *hPtr; Tcl_HashSearch search; IStyle *style; int columnIndex; hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); treeColumn = tree->columns; column = TreeItem_GetFirstColumn(tree, item); columnIndex = 0; while (column != NULL) { style = (IStyle *) TreeItemColumn_GetStyle(tree, column); if ((style != NULL) && (style->master == masterStyle)) { Tree_InvalidateColumnWidth(tree, treeColumn); TreeItemColumn_ForgetStyle(tree, column); TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); } columnIndex++; column = TreeItemColumn_GetNext(tree, column); treeColumn = TreeColumn_Next(treeColumn); } hPtr = Tcl_NextHashEntry(&search); } /* Update each column's -itemstyle option */ treeColumn = tree->columns; while (treeColumn != NULL) { TreeColumn_StyleDeleted(treeColumn, (TreeStyle) masterStyle); treeColumn = TreeColumn_Next(treeColumn); } #ifdef DEPRECATED /* Update -defaultstyle option */ if (tree->defaultStyle.stylesObj != NULL) { Tcl_Obj *stylesObj = tree->defaultStyle.stylesObj; if (Tcl_IsShared(stylesObj)) { stylesObj = Tcl_DuplicateObj(stylesObj); Tcl_DecrRefCount(tree->defaultStyle.stylesObj); Tcl_IncrRefCount(stylesObj); tree->defaultStyle.stylesObj = stylesObj; } for (columnIndex = 0; columnIndex < tree->defaultStyle.numStyles; columnIndex++) { Tcl_Obj *emptyObj; if (tree->defaultStyle.styles[columnIndex] != (TreeStyle) masterStyle) continue; tree->defaultStyle.styles[columnIndex] = NULL; emptyObj = Tcl_NewObj(); Tcl_ListObjReplace(tree->interp, stylesObj, columnIndex, 1, 1, &emptyObj); } } #endif /* DEPRECATED */ } /* *---------------------------------------------------------------------- * * Element_Changed -- * * Called when a master element or TreeCtrl has been configured. * * Results: * Every master and instance style using the element is updated. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void Element_Changed( TreeCtrl *tree, /* Widget info. */ TreeElement masterElem, /* Master element that may have changed. */ int flagM, /* Flags returned by TreeElementType.configProc() * if the master element was configured, * zero if the TreeCtrl was configured. */ int flagT, /* TREE_CONF_xxx flags if the TreeCtrl was * configured, zero if the master element * was configured. */ int csM /* CS_xxx flags returned by * TreeElementType.changeProc(). */ ) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; MStyle *masterStyle; MElementLink *eLink; int i; hPtr = Tcl_FirstHashEntry(&tree->styleHash, &search); while (hPtr != NULL) { masterStyle = (MStyle *) Tcl_GetHashValue(hPtr); for (i = 0; i < masterStyle->numElements; i++) { eLink = &masterStyle->elements[i]; if (eLink->elem == masterElem) { Style_ElemChanged(tree, masterStyle, masterElem, i, flagM, flagT, csM); break; } } hPtr = Tcl_NextHashEntry(&search); } } /* *---------------------------------------------------------------------- * * Element_Deleted -- * * Called when a master element is about to be deleted. * * Results: * The list of elements in any master styles using the element is * updated. Ditto for instance styles. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ static void Element_Deleted( TreeCtrl *tree, /* Widget info. */ TreeElement masterElem /* Master element being deleted. */ ) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; MStyle *masterStyle; MElementLink *eLink; int i, j; hPtr = Tcl_FirstHashEntry(&tree->styleHash, &search); while (hPtr != NULL) { masterStyle = (MStyle *) Tcl_GetHashValue(hPtr); for (i = 0; i < masterStyle->numElements; i++) { eLink = &masterStyle->elements[i]; if (eLink->elem == masterElem) { TreeElement staticElemList[STATIC_SIZE], *elemList = staticElemList; int staticElemMap[STATIC_SIZE], *elemMap = staticElemMap; STATIC_ALLOC(elemList, TreeElement, masterStyle->numElements); STATIC_ALLOC(elemMap, int, masterStyle->numElements); for (j = 0; j < masterStyle->numElements; j++) { if (j == i) continue; elemList[(j < i) ? j : (j - 1)] = masterStyle->elements[j].elem; elemMap[(j < i) ? j : (j - 1)] = j; } Style_ChangeElements(tree, masterStyle, masterStyle->numElements - 1, elemList, elemMap); STATIC_FREE(elemList, TreeElement, masterStyle->numElements + 1); STATIC_FREE(elemMap, int, masterStyle->numElements + 1); break; } } hPtr = Tcl_NextHashEntry(&search); } } /* *---------------------------------------------------------------------- * * Tree_RedrawElement -- * * A STUB export. Schedules a redraw of the given item. * * Results: * None. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ void Tree_RedrawElement( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the element. */ TreeElement elem /* The element that changed. */ ) { /* Master element */ if (elem->master == NULL) { } /* Instance element */ else { Tree_InvalidateItemDInfo(tree, NULL, item, NULL); } } typedef struct Iterate { TreeCtrl *tree; TreeItem item; TreeItemColumn column; int columnIndex; IStyle *style; TreeElementType *elemTypePtr; IElementLink *eLink; Tcl_HashSearch search; Tcl_HashEntry *hPtr; } Iterate; static int IterateItem(Iterate *iter) { int i; while (iter->column != NULL) { iter->style = (IStyle *) TreeItemColumn_GetStyle(iter->tree, iter->column); if (iter->style != NULL) { for (i = 0; i < iter->style->master->numElements; i++) { iter->eLink = &iter->style->elements[i]; if (ELEMENT_TYPE_MATCHES(iter->eLink->elem->typePtr, iter->elemTypePtr)) return 1; } } iter->column = TreeItemColumn_GetNext(iter->tree, iter->column); iter->columnIndex++; } return 0; } TreeIterate Tree_ElementIterateBegin( TreeCtrl *tree, TreeElementType *elemTypePtr) { Iterate *iter; iter = (Iterate *) ckalloc(sizeof(Iterate)); iter->tree = tree; iter->elemTypePtr = elemTypePtr; iter->hPtr = Tcl_FirstHashEntry(&tree->itemHash, &iter->search); while (iter->hPtr != NULL) { iter->item = (TreeItem) Tcl_GetHashValue(iter->hPtr); iter->column = TreeItem_GetFirstColumn(tree, iter->item); iter->columnIndex = 0; if (IterateItem(iter)) return (TreeIterate) iter; iter->hPtr = Tcl_NextHashEntry(&iter->search); } ckfree((char *) iter); return NULL; } TreeIterate Tree_ElementIterateNext( TreeIterate iter_) { Iterate *iter = (Iterate *) iter_; iter->column = TreeItemColumn_GetNext(iter->tree, iter->column); iter->columnIndex++; if (IterateItem(iter)) return iter_; iter->hPtr = Tcl_NextHashEntry(&iter->search); while (iter->hPtr != NULL) { iter->item = (TreeItem) Tcl_GetHashValue(iter->hPtr); iter->column = TreeItem_GetFirstColumn(iter->tree, iter->item); iter->columnIndex = 0; if (IterateItem(iter)) return iter_; iter->hPtr = Tcl_NextHashEntry(&iter->search); } ckfree((char *) iter); return NULL; } /* *---------------------------------------------------------------------- * * Tree_ElementChangedItself -- * * Called when an element has reconfigured itself outside of * any API calls. For example, when a window associated with a * window element is resized, or a text element's -textvariable * is set. * * Results: * None. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ void Tree_ElementChangedItself( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the element. */ TreeItemColumn column, /* Item-column containing the element. */ TreeElement elem, /* The element that changed. */ int flags, /* Element-specific configuration flags. */ int csM /* CS_xxx flags detailing the effects of * the change. */ ) { /* Master element. */ if (item == NULL) { Element_Changed(tree, elem, flags, 0, csM); return; } if (csM & CS_LAYOUT) { IStyle *style = (IStyle *) TreeItemColumn_GetStyle(tree, column); int i; IElementLink *eLink = NULL; int columnIndex; if (style == NULL) panic("Tree_ElementChangedItself but style is NULL\n"); for (i = 0; i < style->master->numElements; i++) { eLink = &style->elements[i]; if (eLink->elem == elem) break; } if (eLink == NULL) panic("Tree_ElementChangedItself but eLink is NULL\n"); columnIndex = TreeItemColumn_Index(tree, item, column); #ifdef CACHE_ELEM_SIZE eLink->neededWidth = eLink->neededHeight = -1; #endif style->neededWidth = style->neededHeight = -1; Tree_InvalidateColumnWidth(tree, Tree_FindColumn(tree, columnIndex)); TreeItemColumn_InvalidateSize(tree, column); TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); } else if (csM & CS_DISPLAY) { int columnIndex; columnIndex = TreeItemColumn_Index(tree, item, column); Tree_InvalidateItemDInfo(tree, Tree_FindColumn(tree, columnIndex), item, NULL); } } void Tree_ElementIterateChanged(TreeIterate iter_, int mask) { Iterate *iter = (Iterate *) iter_; if (mask & CS_LAYOUT) { #ifdef CACHE_ELEM_SIZE iter->eLink->neededWidth = iter->eLink->neededHeight = -1; #endif iter->style->neededWidth = iter->style->neededHeight = -1; Tree_InvalidateColumnWidth(iter->tree, Tree_FindColumn(iter->tree, iter->columnIndex)); TreeItemColumn_InvalidateSize(iter->tree, iter->column); TreeItem_InvalidateHeight(iter->tree, iter->item); Tree_FreeItemDInfo(iter->tree, iter->item, NULL); Tree_DInfoChanged(iter->tree, DINFO_REDO_RANGES); } if (mask & CS_DISPLAY) Tree_InvalidateItemDInfo(iter->tree, NULL, iter->item, NULL); } TreeElement Tree_ElementIterateGet(TreeIterate iter_) { Iterate *iter = (Iterate *) iter_; return iter->eLink->elem; } /* *---------------------------------------------------------------------- * * TreeStyle_TreeChanged -- * * Called when a TreeCtrl is configured. This handles changes to * the -font option affecting text elements for example. * * Results: * Calls the changeProc on every master element. Any elements * affected by the change are eventually redisplayed. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ void TreeStyle_TreeChanged( TreeCtrl *tree, /* Widget info. */ int flagT /* TREE_CONF_xxx flags. */ ) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; TreeElement masterElem; TreeElementArgs args; int eMask; if (flagT == 0) return; args.tree = tree; args.change.flagTree = flagT; args.change.flagMaster = 0; args.change.flagSelf = 0; hPtr = Tcl_FirstHashEntry(&tree->elementHash, &search); while (hPtr != NULL) { masterElem = (TreeElement) Tcl_GetHashValue(hPtr); args.elem = masterElem; eMask = (*masterElem->typePtr->changeProc)(&args); Element_Changed(tree, masterElem, 0, flagT, eMask); hPtr = Tcl_NextHashEntry(&search); } } /* *---------------------------------------------------------------------- * * TreeStyle_ElementCget -- * * This procedure is invoked to process the [item element cget] * widget command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeStyle_ElementCget( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the element. */ TreeItemColumn column, /* Item-column containing the element. */ TreeStyle style_, /* Style containing the element. */ Tcl_Obj *elemObj, /* Name of the element. */ Tcl_Obj *optionNameObj /* Name of the config option. */ ) { IStyle *style = (IStyle *) style_; Tcl_Obj *resultObjPtr = NULL; TreeElement elem; IElementLink *eLink; if (Element_FromObj(tree, elemObj, &elem) != TCL_OK) return TCL_ERROR; eLink = IStyle_FindElem(tree, style, elem, NULL); if ((eLink != NULL) && (eLink->elem == elem)) { int index = TreeItemColumn_Index(tree, item, column); TreeColumn treeColumn = Tree_FindColumn(tree, index); FormatResult(tree->interp, "element %s is not configured in item %s%d column %s%d", elem->name, tree->itemPrefix, TreeItem_GetID(tree, item), tree->columnPrefix, TreeColumn_GetID(treeColumn)); return TCL_ERROR; } if (eLink == NULL) { FormatResult(tree->interp, "style %s does not use element %s", style->master->name, elem->name); return TCL_ERROR; } resultObjPtr = Tk_GetOptionValue(tree->interp, (char *) eLink->elem, eLink->elem->typePtr->optionTable, optionNameObj, tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(tree->interp, resultObjPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeStyle_ElementConfigure -- * * This procedure is invoked to process the [item element configure] * widget command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeStyle_ElementConfigure( TreeCtrl *tree, /* Widget info. */ TreeItem item, /* Item containing the element. */ TreeItemColumn column, /* Item-column containing the element. */ TreeStyle style_, /* Style containing the element. */ Tcl_Obj *elemObj, /* Name of the element. */ int objc, /* Number of arguments. */ Tcl_Obj **objv, /* Argument values. */ int *eMask /* Returned CS_xxx flags. */ ) { IStyle *style = (IStyle *) style_; TreeElement elem; IElementLink *eLink; TreeElementArgs args; (*eMask) = 0; if (Element_FromObj(tree, elemObj, &elem) != TCL_OK) return TCL_ERROR; if (objc <= 1) { Tcl_Obj *resultObjPtr; eLink = IStyle_FindElem(tree, style, elem, NULL); if ((eLink != NULL) && (eLink->elem == elem)) { int index = TreeItemColumn_Index(tree, item, column); TreeColumn treeColumn = Tree_FindColumn(tree, index); FormatResult(tree->interp, "element %s is not configured in item %s%d column %s%d", elem->name, tree->itemPrefix, TreeItem_GetID(tree, item), tree->columnPrefix, TreeColumn_GetID(treeColumn)); return TCL_ERROR; } if (eLink == NULL) { FormatResult(tree->interp, "style %s does not use element %s", style->master->name, elem->name); return TCL_ERROR; } resultObjPtr = Tk_GetOptionInfo(tree->interp, (char *) eLink->elem, eLink->elem->typePtr->optionTable, (objc == 0) ? (Tcl_Obj *) NULL : objv[0], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(tree->interp, resultObjPtr); } else { int isNew; eLink = Style_CreateElem(tree, item, column, style, elem, &isNew); if (eLink == NULL) { FormatResult(tree->interp, "style %s does not use element %s", style->master->name, elem->name); return TCL_ERROR; } /* Do this before configProc(). If eLink was just allocated and an * error occurs in configProc() it won't be done */ (*eMask) = 0; if (isNew) { #ifdef CACHE_ELEM_SIZE eLink->neededWidth = eLink->neededHeight = -1; #endif style->neededWidth = style->neededHeight = -1; (*eMask) = CS_DISPLAY | CS_LAYOUT; } args.tree = tree; args.elem = eLink->elem; args.config.objc = objc; args.config.objv = objv; args.config.flagSelf = 0; args.config.item = item; args.config.column = column; if ((*args.elem->typePtr->configProc)(&args) != TCL_OK) return TCL_ERROR; args.change.flagSelf = args.config.flagSelf; args.change.flagTree = 0; args.change.flagMaster = 0; (*eMask) |= (*elem->typePtr->changeProc)(&args); if (!isNew && ((*eMask) & CS_LAYOUT)) { #ifdef CACHE_ELEM_SIZE eLink->neededWidth = eLink->neededHeight = -1; #endif style->neededWidth = style->neededHeight = -1; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeStyle_ElementActual -- * * This procedure is invoked to process the [item element perstate] * widget command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeStyle_ElementActual( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* The style. */ int state, /* STATE_xxx flags. */ Tcl_Obj *elemObj, /* Name of the element. */ Tcl_Obj *optionNameObj /* Name of the config option. */ ) { IStyle *style = (IStyle *) style_; TreeElement masterElem; IElementLink *eLink; TreeElementArgs args; if (Element_FromObj(tree, elemObj, &masterElem) != TCL_OK) return TCL_ERROR; eLink = IStyle_FindElem(tree, style, masterElem, NULL); if (eLink == NULL) { FormatResult(tree->interp, "style %s does not use element %s", style->master->name, masterElem->name); return TCL_ERROR; } args.tree = tree; args.elem = eLink->elem; args.state = state; args.actual.obj = optionNameObj; return (*masterElem->typePtr->actualProc)(&args); } /* *---------------------------------------------------------------------- * * TreeElementCmd -- * * This procedure is invoked to process the [element] * widget command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeElementCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; static CONST char *commandNames[] = { "cget", "configure", "create", "delete", "names", "perstate", "type", (char *) NULL }; enum { COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_CREATE, COMMAND_DELETE, COMMAND_NAMES, COMMAND_PERSTATE, COMMAND_TYPE }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case COMMAND_CGET: { Tcl_Obj *resultObjPtr = NULL; TreeElement elem; if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "name option"); return TCL_ERROR; } if (Element_FromObj(tree, objv[3], &elem) != TCL_OK) return TCL_ERROR; resultObjPtr = Tk_GetOptionValue(interp, (char *) elem, elem->typePtr->optionTable, objv[4], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } case COMMAND_CONFIGURE: { Tcl_Obj *resultObjPtr = NULL; TreeElement elem; int eMask; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "name ?option? ?value option value ...?"); return TCL_ERROR; } if (Element_FromObj(tree, objv[3], &elem) != TCL_OK) return TCL_ERROR; if (objc <= 5) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) elem, elem->typePtr->optionTable, (objc == 4) ? (Tcl_Obj *) NULL : objv[4], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); } else { TreeElementArgs args; args.tree = tree; args.elem = elem; args.config.objc = objc - 4; args.config.objv = objv + 4; args.config.flagSelf = 0; args.config.item = NULL; args.config.column = NULL; if ((*elem->typePtr->configProc)(&args) != TCL_OK) return TCL_ERROR; args.change.flagSelf = args.config.flagSelf; args.change.flagTree = 0; args.change.flagMaster = 0; eMask = (*elem->typePtr->changeProc)(&args); Element_Changed(tree, elem, args.change.flagSelf, 0, eMask); } break; } case COMMAND_CREATE: { char *name; int length; int isNew; TreeElement elem; TreeElementType *typePtr; Tcl_HashEntry *hPtr; if (objc < 5) { Tcl_WrongNumArgs(interp, 3, objv, "name type ?option value ...?"); return TCL_ERROR; } name = Tcl_GetStringFromObj(objv[3], &length); if (!length) return TCL_ERROR; hPtr = Tcl_FindHashEntry(&tree->elementHash, name); if (hPtr != NULL) { FormatResult(interp, "element \"%s\" already exists", name); return TCL_ERROR; } if (TreeElement_TypeFromObj(tree, objv[4], &typePtr) != TCL_OK) return TCL_ERROR; elem = Element_CreateAndConfig(tree, NULL, NULL, NULL, typePtr, name, objc - 5, objv + 5); if (elem == NULL) return TCL_ERROR; hPtr = Tcl_CreateHashEntry(&tree->elementHash, name, &isNew); Tcl_SetHashValue(hPtr, elem); Tcl_SetObjResult(interp, Element_ToObj(elem)); break; } case COMMAND_DELETE: { TreeElement elem; int i; for (i = 3; i < objc; i++) { if (Element_FromObj(tree, objv[i], &elem) != TCL_OK) return TCL_ERROR; Element_Deleted(tree, elem); Element_FreeResources(tree, elem); } break; } case COMMAND_NAMES: { Tcl_Obj *listObj; Tcl_HashSearch search; Tcl_HashEntry *hPtr; TreeElement elem; if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } listObj = Tcl_NewListObj(0, NULL); hPtr = Tcl_FirstHashEntry(&tree->elementHash, &search); while (hPtr != NULL) { elem = (TreeElement) Tcl_GetHashValue(hPtr); Tcl_ListObjAppendElement(interp, listObj, Element_ToObj(elem)); hPtr = Tcl_NextHashEntry(&search); } Tcl_SetObjResult(interp, listObj); break; } /* T element perstate E option stateList */ case COMMAND_PERSTATE: { TreeElement elem; int states[3]; TreeElementArgs args; if (objc != 6) { Tcl_WrongNumArgs(tree->interp, 3, objv, "element option stateList"); return TCL_ERROR; } if (Element_FromObj(tree, objv[3], &elem) != TCL_OK) return TCL_ERROR; if (Tree_StateFromListObj(tree, objv[5], states, SFO_NOT_OFF | SFO_NOT_TOGGLE) != TCL_OK) return TCL_ERROR; args.tree = tree; args.elem = elem; args.state = states[STATE_OP_ON]; args.actual.obj = objv[4]; return (*elem->typePtr->actualProc)(&args); } case COMMAND_TYPE: { TreeElement elem; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "name"); return TCL_ERROR; } if (Element_FromObj(tree, objv[3], &elem) != TCL_OK) return TCL_ERROR; Tcl_SetResult(interp, elem->typePtr->name, TCL_STATIC); /* Tk_Uid */ break; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * Style_CreateAndConfig -- * * Allocate and initialize a master style. * * Results: * Pointer to the new Style, or NULL if an error occurs. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ static MStyle * Style_CreateAndConfig( TreeCtrl *tree, /* Widget info. */ char *name, /* Name of new style. */ int objc, /* Number of config-option arg-value pairs. */ Tcl_Obj *CONST objv[] /* Config-option arg-value pairs. */ ) { MStyle *style; #ifdef ALLOC_HAX style = (MStyle *) TreeAlloc_Alloc(tree->allocData, MStyleUid, sizeof(MStyle)); #else style = (MStyle *) ckalloc(sizeof(MStyle)); #endif memset(style, '\0', sizeof(MStyle)); style->name = Tk_GetUid(name); if (Tk_InitOptions(tree->interp, (char *) style, tree->styleOptionTable, tree->tkwin) != TCL_OK) { #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, MStyleUid, (char *) style, sizeof(MStyle)); #else WFREE(style, MStyle); #endif return NULL; } if (Tk_SetOptions(tree->interp, (char *) style, tree->styleOptionTable, objc, objv, tree->tkwin, NULL, NULL) != TCL_OK) { Tk_FreeConfigOptions((char *) style, tree->styleOptionTable, tree->tkwin); #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, MStyleUid, (char *) style, sizeof(MStyle)); #else WFREE(style, MStyle); #endif return NULL; } return style; } /* *---------------------------------------------------------------------- * * TreeStyle_ListElements -- * * Creates a Tcl list with the names of elements in a style. * * Results: * If the style is a master style, the interpreter result holds * a list of each element in the style. If the style is an * instance style, the interpreter result holds a list of those * elements configured for the style (i.e., instance elements). * * Side effects: * Memory is allocated, interpreter result changed. * *---------------------------------------------------------------------- */ void TreeStyle_ListElements( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* The style. */ ) { MStyle *masterStyle = (MStyle *) style_; IStyle *style = (IStyle *) style_; Tcl_Obj *listObj; TreeElement elem; int i, numElements = TreeStyle_NumElements(tree, style_); if (numElements <= 0) return; listObj = Tcl_NewListObj(0, NULL); for (i = 0; i < numElements; i++) { if (style->master != NULL) { elem = style->elements[i].elem; if (elem->master == NULL) continue; } else { elem = masterStyle->elements[i].elem; } Tcl_ListObjAppendElement(tree->interp, listObj, Element_ToObj(elem)); } Tcl_SetObjResult(tree->interp, listObj); } enum { OPTION_DETACH, OPTION_DRAW, OPTION_EXPAND, OPTION_HEIGHT, OPTION_iEXPAND, OPTION_INDENT, OPTION_iPADX, OPTION_iPADY, OPTION_MAXHEIGHT, OPTION_MAXWIDTH, OPTION_MINHEIGHT, OPTION_MINWIDTH, OPTION_PADX, OPTION_PADY, OPTION_SQUEEZE, OPTION_STICKY, OPTION_UNION, OPTION_WIDTH, OPTION_VISIBLE }; /* *---------------------------------------------------------------------- * * LayoutOptionToObj -- * * Return a Tcl_Obj holding the value of a style layout option * for an element. * * Results: * Pointer to a new Tcl_Obj or NULL if the option has no value. * * Side effects: * A Tcl_Obj may be allocated. * *---------------------------------------------------------------------- */ static Tcl_Obj * LayoutOptionToObj( TreeCtrl *tree, /* Widget info. */ MStyle *style, /* Master style using the element. */ MElementLink *eLink, /* Layout info for the element. */ int option /* OPTION_xxx constant. */ ) { Tcl_Interp *interp = tree->interp; switch (option) { case OPTION_PADX: return TreeCtrl_NewPadAmountObj(eLink->ePadX); case OPTION_PADY: return TreeCtrl_NewPadAmountObj(eLink->ePadY); case OPTION_iPADX: return TreeCtrl_NewPadAmountObj(eLink->iPadX); case OPTION_iPADY: return TreeCtrl_NewPadAmountObj(eLink->iPadY); case OPTION_DETACH: return Tcl_NewStringObj((eLink->flags & ELF_DETACH) ? "yes" : "no", -1); case OPTION_EXPAND: { char flags[4]; int n = 0; if (eLink->flags & ELF_eEXPAND_W) flags[n++] = 'w'; if (eLink->flags & ELF_eEXPAND_N) flags[n++] = 'n'; if (eLink->flags & ELF_eEXPAND_E) flags[n++] = 'e'; if (eLink->flags & ELF_eEXPAND_S) flags[n++] = 's'; if (n) return Tcl_NewStringObj(flags, n); break; } case OPTION_iEXPAND: { char flags[6]; int n = 0; if (eLink->flags & ELF_iEXPAND_X) flags[n++] = 'x'; if (eLink->flags & ELF_iEXPAND_Y) flags[n++] = 'y'; if (eLink->flags & ELF_iEXPAND_W) flags[n++] = 'w'; if (eLink->flags & ELF_iEXPAND_N) flags[n++] = 'n'; if (eLink->flags & ELF_iEXPAND_E) flags[n++] = 'e'; if (eLink->flags & ELF_iEXPAND_S) flags[n++] = 's'; if (n) return Tcl_NewStringObj(flags, n); break; } case OPTION_INDENT: return Tcl_NewStringObj((eLink->flags & ELF_INDENT) ? "yes" : "no", -1); case OPTION_SQUEEZE: { char flags[2]; int n = 0; if (eLink->flags & ELF_SQUEEZE_X) flags[n++] = 'x'; if (eLink->flags & ELF_SQUEEZE_Y) flags[n++] = 'y'; if (n) return Tcl_NewStringObj(flags, n); break; } case OPTION_UNION: { int i; Tcl_Obj *objPtr; if (eLink->onionCount == 0) break; objPtr = Tcl_NewListObj(0, NULL); for (i = 0; i < eLink->onionCount; i++) Tcl_ListObjAppendElement(interp, objPtr, Element_ToObj(style->elements[eLink->onion[i]].elem)); return objPtr; } case OPTION_MAXHEIGHT: { if (eLink->maxHeight >= 0) return Tcl_NewIntObj(eLink->maxHeight); break; } case OPTION_MINHEIGHT: { if (eLink->minHeight >= 0) return Tcl_NewIntObj(eLink->minHeight); break; } case OPTION_HEIGHT: { if (eLink->fixedHeight >= 0) return Tcl_NewIntObj(eLink->fixedHeight); break; } case OPTION_MAXWIDTH: { if (eLink->maxWidth >= 0) return Tcl_NewIntObj(eLink->maxWidth); break; } case OPTION_MINWIDTH: { if (eLink->minWidth >= 0) return Tcl_NewIntObj(eLink->minWidth); break; } case OPTION_WIDTH: { if (eLink->fixedWidth >= 0) return Tcl_NewIntObj(eLink->fixedWidth); break; } case OPTION_STICKY: { char flags[4]; int n = 0; if (eLink->flags & ELF_STICKY_W) flags[n++] = 'w'; if (eLink->flags & ELF_STICKY_N) flags[n++] = 'n'; if (eLink->flags & ELF_STICKY_E) flags[n++] = 'e'; if (eLink->flags & ELF_STICKY_S) flags[n++] = 's'; if (n) return Tcl_NewStringObj(flags, n); break; } case OPTION_DRAW: { return eLink->draw.obj; } case OPTION_VISIBLE: { return eLink->visible.obj; } } return NULL; } /* *---------------------------------------------------------------------- * * StyleLayoutCmd -- * * This procedure is invoked to process the [style layout] * widget command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StyleLayoutCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* The current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; TreeStyle _style; MStyle *style; TreeElement elem; MElementLink saved, *eLink; int i, index; static CONST char *optionNames[] = { "-detach", "-draw", "-expand", "-height", "-iexpand", "-indent", "-ipadx", "-ipady", "-maxheight", "-maxwidth", "-minheight", "-minwidth", "-padx", "-pady", "-squeeze", "-sticky", "-union", "-width", "-visible", (char *) NULL }; if (objc < 5) { Tcl_WrongNumArgs(interp, 3, objv, "name element ?option? ?value? ?option value ...?"); return TCL_ERROR; } if (TreeStyle_FromObj(tree, objv[3], &_style) != TCL_OK) return TCL_ERROR; style = (MStyle *) _style; if (Element_FromObj(tree, objv[4], &elem) != TCL_OK) return TCL_ERROR; eLink = MStyle_FindElem(tree, style, elem, NULL); if (eLink == NULL) { FormatResult(interp, "style %s does not use element %s", style->name, elem->name); return TCL_ERROR; } /* T style layout S E */ if (objc == 5) { Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); Tcl_Obj *objPtr; for (i = 0; optionNames[i] != NULL; i++) { Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj(optionNames[i], -1)); objPtr = LayoutOptionToObj(tree, style, eLink, i); Tcl_ListObjAppendElement(interp, listObj, objPtr ? objPtr : Tcl_NewObj()); } Tcl_SetObjResult(interp, listObj); return TCL_OK; } /* T style layout S E option */ if (objc == 6) { Tcl_Obj *objPtr; if (Tcl_GetIndexFromObj(interp, objv[5], optionNames, "option", 0, &index) != TCL_OK) return TCL_ERROR; objPtr = LayoutOptionToObj(tree, style, eLink, index); if (objPtr != NULL) Tcl_SetObjResult(interp, objPtr); return TCL_OK; } saved = *eLink; for (i = 5; i < objc; i += 2) { if (i + 2 > objc) { FormatResult(interp, "value for \"%s\" missing", Tcl_GetString(objv[i])); goto badConfig; } if (Tcl_GetIndexFromObj(interp, objv[i], optionNames, "option", 0, &index) != TCL_OK) { goto badConfig; } switch (index) { case OPTION_PADX: { if (TreeCtrl_GetPadAmountFromObj(interp, tree->tkwin, objv[i + 1], &eLink->ePadX[PAD_TOP_LEFT], &eLink->ePadX[PAD_BOTTOM_RIGHT]) != TCL_OK) goto badConfig; break; } case OPTION_PADY: { if (TreeCtrl_GetPadAmountFromObj(interp, tree->tkwin, objv[i + 1], &eLink->ePadY[PAD_TOP_LEFT], &eLink->ePadY[PAD_BOTTOM_RIGHT]) != TCL_OK) goto badConfig; break; } case OPTION_iPADX: { if (TreeCtrl_GetPadAmountFromObj(interp, tree->tkwin, objv[i + 1], &eLink->iPadX[PAD_TOP_LEFT], &eLink->iPadX[PAD_BOTTOM_RIGHT]) != TCL_OK) goto badConfig; break; } case OPTION_iPADY: { if (TreeCtrl_GetPadAmountFromObj(interp, tree->tkwin, objv[i + 1], &eLink->iPadY[PAD_TOP_LEFT], &eLink->iPadY[PAD_BOTTOM_RIGHT]) != TCL_OK) goto badConfig; break; } case OPTION_DETACH: { int detach; if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &detach) != TCL_OK) goto badConfig; if (detach) eLink->flags |= ELF_DETACH; else eLink->flags &= ~ELF_DETACH; break; } case OPTION_EXPAND: { char *expand; int len, k; expand = Tcl_GetStringFromObj(objv[i + 1], &len); eLink->flags &= ~ELF_eEXPAND; for (k = 0; k < len; k++) { switch (expand[k]) { case 'w': case 'W': eLink->flags |= ELF_eEXPAND_W; break; case 'n': case 'N': eLink->flags |= ELF_eEXPAND_N; break; case 'e': case 'E': eLink->flags |= ELF_eEXPAND_E; break; case 's': case 'S': eLink->flags |= ELF_eEXPAND_S; break; default: { Tcl_ResetResult(tree->interp); Tcl_AppendResult(tree->interp, "bad expand value \"", expand, "\": must be a string ", "containing zero or more of n, e, s, and w", (char *) NULL); goto badConfig; } } } break; } case OPTION_iEXPAND: { char *expand; int len, k; expand = Tcl_GetStringFromObj(objv[i + 1], &len); eLink->flags &= ~(ELF_iEXPAND | ELF_iEXPAND_X | ELF_iEXPAND_Y); for (k = 0; k < len; k++) { switch (expand[k]) { case 'x': case 'X': eLink->flags |= ELF_iEXPAND_X; break; case 'y': case 'Y': eLink->flags |= ELF_iEXPAND_Y; break; case 'w': case 'W': eLink->flags |= ELF_iEXPAND_W; break; case 'n': case 'N': eLink->flags |= ELF_iEXPAND_N; break; case 'e': case 'E': eLink->flags |= ELF_iEXPAND_E; break; case 's': case 'S': eLink->flags |= ELF_iEXPAND_S; break; default: { Tcl_ResetResult(tree->interp); Tcl_AppendResult(tree->interp, "bad iexpand value \"", expand, "\": must be a string ", "containing zero or more of x, y, n, e, s, and w", (char *) NULL); goto badConfig; } } } break; } case OPTION_INDENT: { int indent; if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &indent) != TCL_OK) goto badConfig; if (indent) eLink->flags |= ELF_INDENT; else eLink->flags &= ~ELF_INDENT; break; } case OPTION_SQUEEZE: { char *string; int len, k; string = Tcl_GetStringFromObj(objv[i + 1], &len); eLink->flags &= ~(ELF_SQUEEZE_X | ELF_SQUEEZE_Y); for (k = 0; k < len; k++) { switch (string[k]) { case 'x': case 'X': eLink->flags |= ELF_SQUEEZE_X; break; case 'y': case 'Y': eLink->flags |= ELF_SQUEEZE_Y; break; default: { Tcl_ResetResult(tree->interp); Tcl_AppendResult(tree->interp, "bad squeeze value \"", string, "\": must be a string ", "containing zero or more of x and y", (char *) NULL); goto badConfig; } } } break; } case OPTION_UNION: { int objc1; Tcl_Obj **objv1; int j, k, n, *onion, count = 0; if (Tcl_ListObjGetElements(interp, objv[i + 1], &objc1, &objv1) != TCL_OK) goto badConfig; if (objc1 == 0) { if (eLink->onion != NULL) { if (eLink->onion != saved.onion) WCFREE(eLink->onion, int, eLink->onionCount); eLink->onionCount = 0; eLink->onion = NULL; } break; } onion = (int *) ckalloc(sizeof(int) * objc1); for (j = 0; j < objc1; j++) { TreeElement elem2; MElementLink *eLink2; if (Element_FromObj(tree, objv1[j], &elem2) != TCL_OK) { ckfree((char *) onion); goto badConfig; } eLink2 = MStyle_FindElem(tree, style, elem2, &n); if (eLink2 == NULL) { ckfree((char *) onion); FormatResult(interp, "style %s does not use element %s", style->name, elem2->name); goto badConfig; } if (eLink == eLink2) { ckfree((char *) onion); FormatResult(interp, "element %s can't form union with itself", elem2->name); goto badConfig; } /* Silently ignore duplicates */ for (k = 0; k < count; k++) { if (onion[k] == n) break; } if (k < count) continue; onion[count++] = n; } if ((eLink->onion != NULL) && (eLink->onion != saved.onion)) WCFREE(eLink->onion, int, eLink->onionCount); if (count == objc1) eLink->onion = onion; else { eLink->onion = (int *) ckalloc(sizeof(int) * count); for (k = 0; k < count; k++) eLink->onion[k] = onion[k]; ckfree((char *) onion); } eLink->onionCount = count; break; } case OPTION_MAXHEIGHT: { int height; if (ObjectIsEmpty(objv[i + 1])) { eLink->maxHeight = -1; break; } if ((Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &height) != TCL_OK) || (height < 0)) { FormatResult(interp, "bad screen distance \"%s\"", Tcl_GetString(objv[i + 1])); goto badConfig; } eLink->maxHeight = height; break; } case OPTION_MINHEIGHT: { int height; if (ObjectIsEmpty(objv[i + 1])) { eLink->minHeight = -1; break; } if ((Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &height) != TCL_OK) || (height < 0)) { FormatResult(interp, "bad screen distance \"%s\"", Tcl_GetString(objv[i + 1])); goto badConfig; } eLink->minHeight = height; break; } case OPTION_HEIGHT: { int height; if (ObjectIsEmpty(objv[i + 1])) { eLink->fixedHeight = -1; break; } if ((Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &height) != TCL_OK) || (height < 0)) { FormatResult(interp, "bad screen distance \"%s\"", Tcl_GetString(objv[i + 1])); goto badConfig; } eLink->fixedHeight = height; break; } case OPTION_MAXWIDTH: { int width; if (ObjectIsEmpty(objv[i + 1])) { eLink->maxWidth = -1; break; } if ((Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &width) != TCL_OK) || (width < 0)) { FormatResult(interp, "bad screen distance \"%s\"", Tcl_GetString(objv[i + 1])); goto badConfig; } eLink->maxWidth = width; break; } case OPTION_MINWIDTH: { int width; if (ObjectIsEmpty(objv[i + 1])) { eLink->minWidth = -1; break; } if ((Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &width) != TCL_OK) || (width < 0)) { FormatResult(interp, "bad screen distance \"%s\"", Tcl_GetString(objv[i + 1])); goto badConfig; } eLink->minWidth = width; break; } case OPTION_WIDTH: { int width; if (ObjectIsEmpty(objv[i + 1])) { eLink->fixedWidth = -1; break; } if ((Tk_GetPixelsFromObj(interp, tree->tkwin, objv[i + 1], &width) != TCL_OK) || (width < 0)) { FormatResult(interp, "bad screen distance \"%s\"", Tcl_GetString(objv[i + 1])); goto badConfig; } eLink->fixedWidth = width; break; } case OPTION_STICKY: { char *sticky; int len, k; sticky = Tcl_GetStringFromObj(objv[i + 1], &len); eLink->flags &= ~ELF_STICKY; for (k = 0; k < len; k++) { switch (sticky[k]) { case 'w': case 'W': eLink->flags |= ELF_STICKY_W; break; case 'n': case 'N': eLink->flags |= ELF_STICKY_N; break; case 'e': case 'E': eLink->flags |= ELF_STICKY_E; break; case 's': case 'S': eLink->flags |= ELF_STICKY_S; break; default: { Tcl_ResetResult(tree->interp); Tcl_AppendResult(tree->interp, "bad sticky value \"", sticky, "\": must be a string ", "containing zero or more of n, e, s, and w", (char *) NULL); goto badConfig; } } } break; } case OPTION_DRAW: case OPTION_VISIBLE: { PerStateInfo *psi, *psiSaved; if (index == OPTION_DRAW) { psi = &eLink->draw; psiSaved = &saved.draw; } else { psi = &eLink->visible; psiSaved = &saved.visible; } /* Already configured this once. */ if (psi->obj != NULL && psi->obj != psiSaved->obj) { PerStateInfo_Free(tree, &pstBoolean, psi); Tcl_DecrRefCount(psi->obj); /* First configure. Don't free the saved data. */ } else { psi->data = NULL; psi->count = 0; } psi->obj = objv[i + 1]; Tcl_IncrRefCount(psi->obj); if (PerStateInfo_FromObj(tree, TreeStateFromObj, &pstBoolean, psi) != TCL_OK) { goto badConfig; } break; } } } if (saved.onion && (eLink->onion != saved.onion)) WCFREE(saved.onion, int, saved.onionCount); if (saved.draw.obj != NULL && saved.draw.obj != eLink->draw.obj) { PerStateInfo_Free(tree, &pstBoolean, &saved.draw); Tcl_DecrRefCount(saved.draw.obj); } if (saved.visible.obj != NULL && saved.visible.obj != eLink->visible.obj) { PerStateInfo_Free(tree, &pstBoolean, &saved.visible); Tcl_DecrRefCount(saved.visible.obj); } Style_Changed(tree, style); return TCL_OK; badConfig: if (eLink->onion && (eLink->onion != saved.onion)) WCFREE(eLink->onion, int, eLink->onionCount); if (eLink->draw.obj != NULL && eLink->draw.obj != saved.draw.obj) { PerStateInfo_Free(tree, &pstBoolean, &eLink->draw); Tcl_DecrRefCount(eLink->draw.obj); } if (eLink->visible.obj != NULL && eLink->visible.obj != saved.visible.obj) { PerStateInfo_Free(tree, &pstBoolean, &eLink->visible); Tcl_DecrRefCount(eLink->visible.obj); } *eLink = saved; return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TreeStyleCmd -- * * This procedure is invoked to process the [style] widget * command. See the user documentation for details on what it * does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeStyleCmd( ClientData clientData, /* Widget info. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[] /* Argument values. */ ) { TreeCtrl *tree = clientData; static CONST char *commandNames[] = { "cget", "configure", "create", "delete", "elements", "layout", "names", (char *) NULL }; enum { COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_CREATE, COMMAND_DELETE, COMMAND_ELEMENTS, COMMAND_LAYOUT, COMMAND_NAMES }; int index; TreeStyle _style; MStyle *style; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "command ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], commandNames, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case COMMAND_CGET: { Tcl_Obj *resultObjPtr; if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "name option"); return TCL_ERROR; } if (TreeStyle_FromObj(tree, objv[3], &_style) != TCL_OK) return TCL_ERROR; style = (MStyle *) _style; resultObjPtr = Tk_GetOptionValue(interp, (char *) style, tree->styleOptionTable, objv[4], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); break; } case COMMAND_CONFIGURE: { Tcl_Obj *resultObjPtr = NULL; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "name ?option? ?value option value ...?"); return TCL_ERROR; } if (TreeStyle_FromObj(tree, objv[3], &_style) != TCL_OK) return TCL_ERROR; style = (MStyle *) _style; if (objc <= 5) { resultObjPtr = Tk_GetOptionInfo(interp, (char *) style, tree->styleOptionTable, (objc == 4) ? (Tcl_Obj *) NULL : objv[4], tree->tkwin); if (resultObjPtr == NULL) return TCL_ERROR; Tcl_SetObjResult(interp, resultObjPtr); } else { if (Tk_SetOptions(tree->interp, (char *) style, tree->styleOptionTable, objc - 4, objv + 4, tree->tkwin, NULL, NULL) != TCL_OK) return TCL_ERROR; Style_Changed(tree, style); } break; } case COMMAND_CREATE: { char *name; int len; Tcl_HashEntry *hPtr; int isNew; if (objc < 4) { Tcl_WrongNumArgs(interp, 3, objv, "name ?option value ...?"); return TCL_ERROR; } name = Tcl_GetStringFromObj(objv[3], &len); if (!len) { FormatResult(interp, "invalid style name \"\""); return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&tree->styleHash, name); if (hPtr != NULL) { FormatResult(interp, "style \"%s\" already exists", name); return TCL_ERROR; } style = Style_CreateAndConfig(tree, name, objc - 4, objv + 4); if (style == NULL) return TCL_ERROR; hPtr = Tcl_CreateHashEntry(&tree->styleHash, name, &isNew); Tcl_SetHashValue(hPtr, style); Tcl_SetObjResult(interp, TreeStyle_ToObj((TreeStyle) style)); break; } case COMMAND_DELETE: { int i; if (objc < 3) { Tcl_WrongNumArgs(interp, 3, objv, "?name ...?"); return TCL_ERROR; } for (i = 3; i < objc; i++) { if (TreeStyle_FromObj(tree, objv[i], &_style) != TCL_OK) return TCL_ERROR; Style_Deleted(tree, (MStyle *) _style); TreeStyle_FreeResources(tree, _style); } break; } /* T style elements S ?{E ...}? */ case COMMAND_ELEMENTS: { TreeElement elem, *elemList = NULL; int i, j, count = 0; int staticMap[STATIC_SIZE], *map = staticMap; int listObjc; Tcl_Obj **listObjv; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "name ?elementList?"); return TCL_ERROR; } if (TreeStyle_FromObj(tree, objv[3], &_style) != TCL_OK) return TCL_ERROR; style = (MStyle *) _style; if (objc == 5) { if (Tcl_ListObjGetElements(interp, objv[4], &listObjc, &listObjv) != TCL_OK) return TCL_ERROR; if (listObjc > 0) elemList = (TreeElement *) ckalloc(sizeof(TreeElement_) * listObjc); for (i = 0; i < listObjc; i++) { if (Element_FromObj(tree, listObjv[i], &elem) != TCL_OK) { ckfree((char *) elemList); return TCL_ERROR; } /* Ignore duplicate elements */ for (j = 0; j < count; j++) { if (elemList[j] == elem) break; } if (j < count) continue; elemList[count++] = elem; } STATIC_ALLOC(map, int, count); for (i = 0; i < count; i++) map[i] = -1; /* Reassigning Elements to a Style */ if (style->numElements > 0) { /* Check each Element */ for (i = 0; i < count; i++) { /* See if this Element is already used by the Style */ for (j = 0; j < style->numElements; j++) { if (elemList[i] == style->elements[j].elem) { /* Preserve it */ map[i] = j; break; } } } } Style_ChangeElements(tree, style, count, elemList, map); if (elemList != NULL) ckfree((char *) elemList); STATIC_FREE(map, int, count); break; } TreeStyle_ListElements(tree, (TreeStyle) style); break; } /* T style layout S E ?option? ?value? ?option value ...? */ case COMMAND_LAYOUT: { return StyleLayoutCmd(clientData, interp, objc, objv); } case COMMAND_NAMES: { Tcl_Obj *listObj; Tcl_HashSearch search; Tcl_HashEntry *hPtr; listObj = Tcl_NewListObj(0, NULL); hPtr = Tcl_FirstHashEntry(&tree->styleHash, &search); while (hPtr != NULL) { _style = (TreeStyle) Tcl_GetHashValue(hPtr); Tcl_ListObjAppendElement(interp, listObj, TreeStyle_ToObj(_style)); hPtr = Tcl_NextHashEntry(&search); } Tcl_SetObjResult(interp, listObj); break; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tree_ButtonMaxWidth -- * * Return the maximum possible size of a button in any state. This * includes the size of the -buttonimage and -buttonbitmap options, * as well as the theme button and default +/- button. * * Results: * Pixel size >= 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tree_ButtonMaxWidth( TreeCtrl *tree /* Widget info. */ ) { int w, h, width = 0; PerStateImage_MaxSize(tree, &tree->buttonImage, &w, &h); width = MAX(width, w); PerStateBitmap_MaxSize(tree, &tree->buttonBitmap, &w, &h); width = MAX(width, w); if (tree->useTheme) { if (TreeTheme_GetButtonSize(tree, Tk_WindowId(tree->tkwin), TRUE, &w, &h) == TCL_OK) width = MAX(width, w); if (TreeTheme_GetButtonSize(tree, Tk_WindowId(tree->tkwin), FALSE, &w, &h) == TCL_OK) width = MAX(width, w); } return MAX(width, tree->buttonSize); } /* *---------------------------------------------------------------------- * * Tree_ButtonHeight -- * * Return the size of a button for a certain state. * * Results: * Pixel size >= 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tree_ButtonHeight( TreeCtrl *tree, /* Widget info. */ int state /* STATE_xxx flags. */ ) { Tk_Image image; Pixmap bitmap; int w, h; image = PerStateImage_ForState(tree, &tree->buttonImage, state, NULL); if (image != NULL) { Tk_SizeOfImage(image, &w, &h); return h; } bitmap = PerStateBitmap_ForState(tree, &tree->buttonBitmap, state, NULL); if (bitmap != None) { Tk_SizeOfBitmap(tree->display, bitmap, &w, &h); return h; } if (tree->useTheme && TreeTheme_GetButtonSize(tree, Tk_WindowId(tree->tkwin), (state & STATE_OPEN) != 0, &w, &h) == TCL_OK) return h; return tree->buttonSize; } /* *---------------------------------------------------------------------- * * TreeStyle_Identify -- * * Perform hit-testing on a style. * * Results: * The name of the element containing the given point, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * TreeStyle_Identify( StyleDrawArgs *drawArgs, /* Various args. */ int x, /* Window x-coord to hit-test against. */ int y /* Window y-coord to hit-test against. */ ) { TreeCtrl *tree = drawArgs->tree; IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; int state = drawArgs->state; IElementLink *eLink = NULL; int i, minWidth, minHeight; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; Style_CheckNeededSize(tree, style, state); #ifdef CACHE_STYLE_SIZE minWidth = style->minWidth; minHeight = style->minHeight; #else Style_MinSize(tree, style, state, &minWidth, &minHeight); #endif if (drawArgs->width < minWidth + drawArgs->indent) drawArgs->width = minWidth + drawArgs->indent; if (drawArgs->height < minHeight) drawArgs->height = minHeight; x -= drawArgs->x; STATIC_ALLOC(layouts, struct Layout, masterStyle->numElements); Style_DoLayout(drawArgs, layouts, FALSE, __FILE__, __LINE__); for (i = style->master->numElements - 1; i >= 0; i--) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink = layout->eLink; if ((x >= layout->x + layout->ePadX[PAD_TOP_LEFT]) && (x < layout->x + layout->ePadX[PAD_TOP_LEFT] + layout->iWidth) && (y >= layout->y + layout->ePadY[PAD_TOP_LEFT]) && (y < layout->y + layout->ePadY[PAD_TOP_LEFT] + layout->iHeight)) { goto done; } } eLink = NULL; done: STATIC_FREE(layouts, struct Layout, masterStyle->numElements); if (eLink != NULL) return (char *) eLink->elem->name; return NULL; } /* *---------------------------------------------------------------------- * * TreeStyle_Identify2 -- * * Return a list of elements overlapping the given area. * * Results: * The names of any elements overlapping the given area are * appended to the supplied list. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ void TreeStyle_Identify2( StyleDrawArgs *drawArgs, /* Various args. */ int x1, int y1, /* Top-left of area to hit-test. */ int x2, int y2, /* Bottom-right of area to hit-test. */ Tcl_Obj *listObj /* Initialized list object to hold * the result. */ ) { TreeCtrl *tree = drawArgs->tree; IStyle *style = (IStyle *) drawArgs->style; MStyle *masterStyle = style->master; int state = drawArgs->state; IElementLink *eLink; int i, minWidth, minHeight; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; Style_CheckNeededSize(tree, style, state); #ifdef CACHE_STYLE_SIZE minWidth = style->minWidth; minHeight = style->minHeight; #else Style_MinSize(tree, style, state, &minWidth, &minHeight); #endif if (drawArgs->width < minWidth + drawArgs->indent) drawArgs->width = minWidth + drawArgs->indent; if (drawArgs->height < minHeight) drawArgs->height = minHeight; STATIC_ALLOC(layouts, struct Layout, masterStyle->numElements); Style_DoLayout(drawArgs, layouts, FALSE, __FILE__, __LINE__); for (i = style->master->numElements - 1; i >= 0; i--) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; eLink = layout->eLink; if ((drawArgs->x + layout->x + layout->ePadX[PAD_TOP_LEFT] < x2) && (drawArgs->x + layout->x + layout->ePadX[PAD_TOP_LEFT] + layout->iWidth > x1) && (drawArgs->y + layout->y + layout->ePadY[PAD_TOP_LEFT] < y2) && (drawArgs->y + layout->y + layout->ePadY[PAD_TOP_LEFT] + layout->iHeight > y1)) { Tcl_ListObjAppendElement(drawArgs->tree->interp, listObj, Tcl_NewStringObj(eLink->elem->name, -1)); } } STATIC_FREE(layouts, struct Layout, masterStyle->numElements); } /* *---------------------------------------------------------------------- * * TreeStyle_Remap -- * * The guts of the [item style map] command. See the user * documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TreeStyle_Remap( TreeCtrl *tree, /* Widget info. */ TreeStyle styleFrom_, /* Current instance style. */ TreeStyle styleTo_, /* Master style to "convert" the current * style to. */ int objc, /* Must be even number. */ Tcl_Obj *CONST objv[] /* Array of old-new element names. */ ) { IStyle *styleFrom = (IStyle *) styleFrom_; MStyle *styleTo = (MStyle *) styleTo_; int i, indexFrom, indexTo; int staticMap[STATIC_SIZE], *map = staticMap; IElementLink *eLink; TreeElement elemFrom, elemTo; TreeElement staticElemMap[STATIC_SIZE], *elemMap = staticElemMap; int styleFromNumElements = styleFrom->master->numElements; int result = TCL_OK; /* Must be instance */ if ((styleFrom == NULL) || (styleFrom->master == NULL)) return TCL_ERROR; /* Must be master */ if ((styleTo == NULL) || (styleTo->master != NULL)) return TCL_ERROR; /* Nothing to do */ if (styleFrom->master == styleTo) return TCL_OK; if (objc & 1) return TCL_ERROR; STATIC_ALLOC(map, int, styleFromNumElements); STATIC_ALLOC(elemMap, TreeElement, styleFromNumElements); for (i = 0; i < styleFromNumElements; i++) map[i] = -1; for (i = 0; i < objc; i += 2) { /* Get the old-style element */ if (Element_FromObj(tree, objv[i], &elemFrom) != TCL_OK) { result = TCL_ERROR; goto done; } /* Verify the old style uses the element */ if (MStyle_FindElem(tree, styleFrom->master, elemFrom, &indexFrom) == NULL) { FormatResult(tree->interp, "style %s does not use element %s", styleFrom->master->name, elemFrom->name); result = TCL_ERROR; goto done; } /* Get the new-style element */ if (Element_FromObj(tree, objv[i + 1], &elemTo) != TCL_OK) { result = TCL_ERROR; goto done; } /* Verify the new style uses the element */ if (MStyle_FindElem(tree, styleTo, elemTo, &indexTo) == NULL) { FormatResult(tree->interp, "style %s does not use element %s", styleTo->name, elemTo->name); result = TCL_ERROR; goto done; } /* Must be the same type */ if (elemFrom->typePtr != elemTo->typePtr) { FormatResult(tree->interp, "can't map element type %s to %s", elemFrom->typePtr->name, elemTo->typePtr->name); result = TCL_ERROR; goto done; } /* See if the instance style has any info for this element */ eLink = &styleFrom->elements[indexFrom]; if (eLink->elem->master != NULL) { map[indexFrom] = indexTo; elemMap[indexFrom] = eLink->elem; } } for (i = 0; i < styleFromNumElements; i++) { eLink = &styleFrom->elements[i]; indexTo = map[i]; /* Free info for any Elements not being remapped */ if ((indexTo == -1) && (eLink->elem->master != NULL)) { elemFrom = eLink->elem->master; Element_FreeResources(tree, eLink->elem); eLink->elem = elemFrom; } /* Remap this Element */ if (indexTo != -1) { elemMap[i]->master = styleTo->elements[indexTo].elem; elemMap[i]->name = styleTo->elements[indexTo].elem->name; } } if (styleFromNumElements != styleTo->numElements) { #ifdef ALLOC_HAX if (styleFromNumElements > 0) TreeAlloc_CFree(tree->allocData, IElementLinkUid, (char *) styleFrom->elements, sizeof(IElementLink), styleFromNumElements, ELEMENT_LINK_ROUND); styleFrom->elements = (IElementLink *) TreeAlloc_CAlloc(tree->allocData, IElementLinkUid, sizeof(IElementLink), styleTo->numElements, ELEMENT_LINK_ROUND); #else if (styleFromNumElements > 0) WCFREE(styleFrom->elements, IElementLink, styleFromNumElements); styleFrom->elements = (IElementLink *) ckalloc(sizeof(IElementLink) * styleTo->numElements); #endif memset(styleFrom->elements, '\0', sizeof(IElementLink) * styleTo->numElements); } for (i = 0; i < styleTo->numElements; i++) { styleFrom->elements[i].elem = styleTo->elements[i].elem; #ifdef CACHE_ELEM_SIZE styleFrom->elements[i].neededWidth = -1; styleFrom->elements[i].neededHeight = -1; #endif } for (i = 0; i < styleFromNumElements; i++) { indexTo = map[i]; if (indexTo != -1) styleFrom->elements[indexTo].elem = elemMap[i]; } styleFrom->master = styleTo; styleFrom->neededWidth = styleFrom->neededHeight = -1; done: STATIC_FREE(map, int, styleFromNumElements); STATIC_FREE(elemMap, TreeElement, styleFromNumElements); return result; } /* *---------------------------------------------------------------------- * * TreeStyle_GetSortData -- * * Called by the [item sort] code. Returns a long, double or * string value from a text element. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_GetSortData( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* The style. */ int elemIndex, /* Index of a text element, or -1 to use * the first text element. */ int type, /* SORT_xxx constant. */ long *lv, /* Returned for SORT_LONG. */ double *dv, /* Returned for SORT_DOUBLE. */ char **sv /* Returned for SORT_ASCII or SORT_DICT. */ ) { IStyle *style = (IStyle *) style_; IElementLink *eLink = style->elements; int i; if (elemIndex == -1) { for (i = 0; i < style->master->numElements; i++) { if (ELEMENT_TYPE_MATCHES(eLink->elem->typePtr, &treeElemTypeText)) return TreeElement_GetSortData(tree, eLink->elem, type, lv, dv, sv); eLink++; } } else { if ((elemIndex < 0) || (elemIndex >= style->master->numElements)) panic("bad elemIndex %d to TreeStyle_GetSortData", elemIndex); eLink = &style->elements[elemIndex]; if (ELEMENT_TYPE_MATCHES(eLink->elem->typePtr, &treeElemTypeText)) return TreeElement_GetSortData(tree, eLink->elem, type, lv, dv, sv); } FormatResult(tree->interp, "can't find text element in style %s", style->master->name); return TCL_ERROR; } #if 0 /* *---------------------------------------------------------------------- * * TreeStyle_ValidateElements -- * * Verify that each object in an objv[] array refers to a * master element. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_ValidateElements( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* Instance style. */ int objc, /* Number of element names. */ Tcl_Obj *CONST objv[] /* Array of element names. */ ) { IStyle *style = (IStyle *) style_; MStyle *master = style->master; TreeElement elem; MElementLink *eLink; int i; for (i = 0; i < objc; i++) { if (Element_FromObj(tree, objv[i], &elem) != TCL_OK) return TCL_ERROR; eLink = MStyle_FindElem(tree, master, elem, NULL); if (eLink == NULL) { FormatResult(tree->interp, "style %s does not use element %s", master->name, elem->name); return TCL_ERROR; } } return TCL_OK; } #endif /* 0 */ /* *---------------------------------------------------------------------- * * TreeStyle_GetElemRects -- * * Return a list of rectangles for specified elements in a style. * * Results: * The number of rects[] written. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_GetElemRects( StyleDrawArgs *drawArgs, /* Various args. */ int objc, /* Number of element names. */ Tcl_Obj *CONST objv[], /* Array of element names. */ TreeRectangle rects[] /* Returned rectangles. */ ) { IStyle *style = (IStyle *) drawArgs->style; MStyle *master = style->master; int i, j, count = 0, minWidth, minHeight; struct Layout staticLayouts[STATIC_SIZE], *layouts = staticLayouts; TreeElement staticElems[STATIC_SIZE], *elems = staticElems; MElementLink *eLink; STATIC_ALLOC(elems, TreeElement, objc); for (j = 0; j < objc; j++) { if (Element_FromObj(drawArgs->tree, objv[j], &elems[j]) != TCL_OK) { count = -1; goto done; } eLink = MStyle_FindElem(drawArgs->tree, master, elems[j], NULL); if (eLink == NULL) { FormatResult(drawArgs->tree->interp, "style %s does not use element %s", master->name, elems[j]->name); count = -1; goto done; } } #ifdef CACHE_STYLE_SIZE minWidth = style->minWidth; minHeight = style->minHeight; #else Style_MinSize(drawArgs->tree, style, drawArgs->state, &minWidth, &minHeight); #endif if (drawArgs->width < minWidth + drawArgs->indent) drawArgs->width = minWidth + drawArgs->indent; if (drawArgs->height < minHeight) drawArgs->height = minHeight; STATIC_ALLOC(layouts, struct Layout, master->numElements); Style_DoLayout(drawArgs, layouts, FALSE, __FILE__, __LINE__); for (i = master->numElements - 1; i >= 0; i--) { struct Layout *layout = &layouts[i]; if (IS_HIDDEN(layout)) continue; if (objc > 0) { for (j = 0; j < objc; j++) if (elems[j] == layout->eLink->elem || elems[j] == layout->master->elem) break; if (j == objc) continue; } rects[count].x = drawArgs->x + layout->x + layout->ePadX[PAD_TOP_LEFT]; rects[count].y = drawArgs->y + layout->y + layout->ePadY[PAD_TOP_LEFT]; if (layout->master->onion == NULL) { rects[count].x += layout->iPadX[PAD_TOP_LEFT]; rects[count].y += layout->iPadY[PAD_TOP_LEFT]; rects[count].width = layout->useWidth; rects[count].height = layout->useHeight; } else { rects[count].width = layout->iWidth; rects[count].height = layout->iHeight; } count++; } STATIC_FREE(layouts, struct Layout, master->numElements); done: STATIC_FREE(elems, TreeElement, objc); return count; } /* *---------------------------------------------------------------------- * * TreeStyle_ChangeState -- * * Called when the state of an item or item-column changes. * * Results: * A bitmask of CS_DISPLAY and CS_LAYOUT values. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_ChangeState( TreeCtrl *tree, /* Widget info. */ TreeStyle style_, /* The instance style. */ int state1, /* The previous state. */ int state2 /* The current state. */ ) { IStyle *style = (IStyle *) style_; MStyle *masterStyle = style->master; MElementLink *eLink1; IElementLink *eLink2; TreeElementArgs args; int i, eMask, mask = 0; int undisplay; if (state1 == state2) return 0; args.tree = tree; for (i = 0; i < masterStyle->numElements; i++) { eLink2 = &style->elements[i]; args.elem = eLink2->elem; args.states.state1 = state1; args.states.state2 = state2; args.states.draw1 = args.states.draw2 = TRUE; args.states.visible1 = args.states.visible2 = TRUE; eLink1 = &masterStyle->elements[i]; undisplay = FALSE; eMask = 0; /* Check for the style layout option -draw changing. */ if (eLink1->draw.count > 0) { args.states.draw1 = PerStateBoolean_ForState(tree, &eLink1->draw, state1, NULL) != 0; args.states.draw2 = PerStateBoolean_ForState(tree, &eLink1->draw, state2, NULL) != 0; if (args.states.draw1 != args.states.draw2) { eMask |= CS_DISPLAY; if (!args.states.draw2) undisplay = TRUE; } } /* Check for the style layout option -visible changing. */ if (eLink1->visible.count > 0) { args.states.visible1 = PerStateBoolean_ForState(tree, &eLink1->visible, state1, NULL) != 0; args.states.visible2 = PerStateBoolean_ForState(tree, &eLink1->visible, state2, NULL) != 0; /* FIXME: Changing visibility might not change the layout. */ if (args.states.visible1 != args.states.visible2) { eMask |= CS_DISPLAY | CS_LAYOUT; if (!args.states.visible2) undisplay = TRUE; } } /* Tell the element about the state change. */ eMask |= (*args.elem->typePtr->stateProc)(&args); /* Hack: If a window element becomes hidden, then tell it it is * not onscreen, otherwise it will never be "drawn" in the * hidden state. */ if (undisplay && ELEMENT_TYPE_MATCHES(args.elem->typePtr, &treeElemTypeWindow)) { args.screen.visible = FALSE; (*args.elem->typePtr->onScreenProc)(&args); } if (eMask) { #ifdef CACHE_ELEM_SIZE if (eMask & CS_LAYOUT) eLink2->neededWidth = eLink2->neededHeight = -1; #endif mask |= eMask; } } if (mask & CS_LAYOUT) style->neededWidth = style->neededHeight = -1; #ifdef TREECTRL_DEBUG if (style->neededWidth != -1) style->neededState = state2; #endif return mask; } /* *---------------------------------------------------------------------- * * Tree_UndefineState -- * * The guts of the [state undefine] widget command. * * Results: * The undefProc of every element is called to respond to the * undefined state flag. The size of every element/column/item is * marked out-of-date regardless of whether the state change * affected the element. * * Side effects: * Display changes. * *---------------------------------------------------------------------- */ void Tree_UndefineState( TreeCtrl *tree, /* Widget info. */ int state /* STATE_xxx flag. */ ) { TreeItem item; TreeItemColumn column; Tcl_HashEntry *hPtr; Tcl_HashSearch search; IElementLink *eLink; int i, columnIndex; TreeElementArgs args; /* Undefine the state for the -draw and -visible style layout * options for each element of this style. */ hPtr = Tcl_FirstHashEntry(&tree->styleHash, &search); while (hPtr != NULL) { MStyle *masterStyle = (MStyle *) Tcl_GetHashValue(hPtr); for (i = 0; i < masterStyle->numElements; i++) { MElementLink *eLink1 = &masterStyle->elements[i]; PerStateInfo_Undefine(tree, &pstBoolean, &eLink1->draw, state); PerStateInfo_Undefine(tree, &pstBoolean, &eLink1->visible, state); } hPtr = Tcl_NextHashEntry(&search); } args.tree = tree; args.state = state; hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search); while (hPtr != NULL) { item = (TreeItem) Tcl_GetHashValue(hPtr); column = TreeItem_GetFirstColumn(tree, item); columnIndex = 0; while (column != NULL) { IStyle *style = (IStyle *) TreeItemColumn_GetStyle(tree, column); if (style != NULL) { for (i = 0; i < style->master->numElements; i++) { eLink = &style->elements[i]; /* Instance element */ if (eLink->elem->master != NULL) { args.elem = eLink->elem; (*args.elem->typePtr->undefProc)(&args); } #ifdef CACHE_ELEM_SIZE eLink->neededWidth = eLink->neededHeight = -1; #endif } style->neededWidth = style->neededHeight = -1; TreeItemColumn_InvalidateSize(tree, column); } columnIndex++; column = TreeItemColumn_GetNext(tree, column); } TreeItem_InvalidateHeight(tree, item); Tree_FreeItemDInfo(tree, item, NULL); TreeItem_UndefineState(tree, item, state); hPtr = Tcl_NextHashEntry(&search); } Tree_InvalidateColumnWidth(tree, NULL); Tree_DInfoChanged(tree, DINFO_REDO_RANGES); hPtr = Tcl_FirstHashEntry(&tree->elementHash, &search); while (hPtr != NULL) { args.elem = (TreeElement) Tcl_GetHashValue(hPtr); (*args.elem->typePtr->undefProc)(&args); hPtr = Tcl_NextHashEntry(&search); } } /* *---------------------------------------------------------------------- * * TreeStyle_NumElements -- * * Return the number of elements in a style. * * Results: * The number of... oh nevermind. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_NumElements( TreeCtrl *tree, /* Widget info. */ TreeStyle style_ /* The style. */ ) { MStyle *masterStyle = ((MStyle *) style_); IStyle *style = ((IStyle *) style_); return (style->master == NULL) ? masterStyle->numElements : style->master->numElements; } /* *---------------------------------------------------------------------- * * TreeStyle_Init -- * * Style-related package initialization. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TreeStyle_Init( TreeCtrl *tree /* Widget info. */ ) { tree->styleOptionTable = Tk_CreateOptionTable(tree->interp, styleOptionSpecs); return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeStyle_Free -- * * Free style-related resources for a deleted TreeCtrl. * * Results: * None. * * Side effects: * Memory is freed. * *---------------------------------------------------------------------- */ void TreeStyle_Free( TreeCtrl *tree /* Widget info. */ ) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; TreeElement elem; TreeStyle style; while (1) { hPtr = Tcl_FirstHashEntry(&tree->styleHash, &search); if (hPtr == NULL) break; style = (TreeStyle) Tcl_GetHashValue(hPtr); TreeStyle_FreeResources(tree, style); } while (1) { hPtr = Tcl_FirstHashEntry(&tree->elementHash, &search); if (hPtr == NULL) break; elem = (TreeElement) Tcl_GetHashValue(hPtr); Element_FreeResources(tree, elem); } Tcl_DeleteHashTable(&tree->elementHash); Tcl_DeleteHashTable(&tree->styleHash); } tktreectrl-2.2.8/generic/tkTreeTheme.c0000700000175600010010000013322410762067114016116 0ustar TimNone/* * tkTreeTheme.c -- * * This module implements platform-specific visual themes. * * Copyright (c) 2006-2008 Tim Baker * * RCS: @(#) $Id: tkTreeTheme.c,v 1.25 2008/02/28 00:25:07 hobbs2 Exp $ */ #if defined(WIN32) || defined(_WIN32) #define WINVER 0x0501 /* Cygwin */ #define _WIN32_WINNT 0x0501 /* ACTCTX stuff */ #endif #include "tkTreeCtrl.h" #ifdef USE_TTK #include "ttk/ttkTheme.h" #include "ttk/ttk-extra.h" #endif /* These must agree with tkTreeColumn.c */ #define COLUMN_STATE_NORMAL 0 #define COLUMN_STATE_ACTIVE 1 #define COLUMN_STATE_PRESSED 2 #ifndef USE_TTK #ifdef WIN32 #include "tkWinInt.h" #include #include #include #include /* Cygwin */ #ifndef TMT_CONTENTMARGINS #define TMT_CONTENTMARGINS 3602 #endif typedef HTHEME (STDAPICALLTYPE OpenThemeDataProc)(HWND hwnd, LPCWSTR pszClassList); typedef HRESULT (STDAPICALLTYPE CloseThemeDataProc)(HTHEME hTheme); typedef HRESULT (STDAPICALLTYPE DrawThemeBackgroundProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); typedef HRESULT (STDAPICALLTYPE DrawThemeBackgroundExProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, DTBGOPTS *PDTBGOPTS); typedef HRESULT (STDAPICALLTYPE DrawThemeParentBackgroundProc)(HWND hwnd, HDC hdc, OPTIONAL const RECT *prc); typedef HRESULT (STDAPICALLTYPE DrawThemeEdgeProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pDestRect, UINT uEdge, UINT uFlags, RECT *pContentRect); typedef HRESULT (STDAPICALLTYPE DrawThemeTextProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect); typedef HRESULT (STDAPICALLTYPE GetThemeBackgroundContentRectProc)( HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, RECT *pContentRect); typedef HRESULT (STDAPICALLTYPE GetThemeBackgroundExtentProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pContentRect, RECT *pExtentRect); typedef HRESULT (STDAPICALLTYPE GetThemeMarginsProc)(HTHEME, HDC, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, MARGINS *pMargins); typedef HRESULT (STDAPICALLTYPE GetThemePartSizeProc)(HTHEME, HDC, int iPartId, int iStateId, RECT *prc, enum THEMESIZE eSize, SIZE *psz); typedef HRESULT (STDAPICALLTYPE GetThemeTextExtentProc)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, const RECT *pBoundingRect, RECT *pExtentRect); typedef BOOL (STDAPICALLTYPE IsThemeActiveProc)(VOID); typedef BOOL (STDAPICALLTYPE IsAppThemedProc)(VOID); typedef BOOL (STDAPICALLTYPE IsThemePartDefinedProc)(HTHEME, int, int); typedef HRESULT (STDAPICALLTYPE IsThemeBackgroundPartiallyTransparentProc)( HTHEME, int, int); typedef struct { OpenThemeDataProc *OpenThemeData; CloseThemeDataProc *CloseThemeData; DrawThemeBackgroundProc *DrawThemeBackground; DrawThemeBackgroundExProc *DrawThemeBackgroundEx; DrawThemeParentBackgroundProc *DrawThemeParentBackground; DrawThemeEdgeProc *DrawThemeEdge; DrawThemeTextProc *DrawThemeText; GetThemeBackgroundContentRectProc *GetThemeBackgroundContentRect; GetThemeBackgroundExtentProc *GetThemeBackgroundExtent; GetThemeMarginsProc *GetThemeMargins; GetThemePartSizeProc *GetThemePartSize; GetThemeTextExtentProc *GetThemeTextExtent; IsThemeActiveProc *IsThemeActive; IsAppThemedProc *IsAppThemed; IsThemePartDefinedProc *IsThemePartDefined; IsThemeBackgroundPartiallyTransparentProc *IsThemeBackgroundPartiallyTransparent; } XPThemeProcs; typedef struct { HINSTANCE hlibrary; XPThemeProcs *procs; int registered; int themeEnabled; SIZE buttonOpen; SIZE buttonClosed; } XPThemeData; typedef struct TreeThemeData_ { HTHEME hThemeHEADER; HTHEME hThemeTREEVIEW; } TreeThemeData_; static XPThemeProcs *procs = NULL; static XPThemeData *appThemeData = NULL; TCL_DECLARE_MUTEX(themeMutex) /* Functions imported from kernel32.dll requiring windows XP or greater. */ /* But I already link to GetVersionEx so is this importing needed? */ typedef HANDLE (STDAPICALLTYPE CreateActCtxAProc)(PCACTCTXA pActCtx); typedef BOOL (STDAPICALLTYPE ActivateActCtxProc)(HANDLE hActCtx, ULONG_PTR *lpCookie); typedef BOOL (STDAPICALLTYPE DeactivateActCtxProc)(DWORD dwFlags, ULONG_PTR ulCookie); typedef VOID (STDAPICALLTYPE ReleaseActCtxProc)(HANDLE hActCtx); typedef struct { CreateActCtxAProc *CreateActCtxA; ActivateActCtxProc *ActivateActCtx; DeactivateActCtxProc *DeactivateActCtx; ReleaseActCtxProc *ReleaseActCtx; } ActCtxProcs; static ActCtxProcs * GetActCtxProcs(void) { HINSTANCE hInst; ActCtxProcs *procs = (ActCtxProcs *) ckalloc(sizeof(ActCtxProcs)); hInst = LoadLibrary("kernel32.dll"); // FIXME: leak? if (hInst != 0) { #define LOADPROC(name) \ (0 != (procs->name = (name ## Proc *)GetProcAddress(hInst, #name) )) if (LOADPROC(CreateActCtxA) && LOADPROC(ActivateActCtx) && LOADPROC(DeactivateActCtx) && LOADPROC(ReleaseActCtx)) { return procs; } #undef LOADPROC } ckfree((char*)procs); return NULL; } static HMODULE thisModule = NULL; /* Return the HMODULE for this treectrl.dll. */ static HMODULE GetMyHandle(void) { #if 1 return thisModule; #else HMODULE hModule = NULL; /* FIXME: Only >=NT so I shouldn't link to it? But I already linked to * GetVersionEx so will it run on 95/98? */ GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)&appThemeData, &hModule); return hModule; #endif } BOOL WINAPI DllMain(hInst, reason, reserved) HINSTANCE hInst; /* Library instance handle. */ DWORD reason; /* Reason this function is being called. */ LPVOID reserved; /* Not used. */ { if (reason == DLL_PROCESS_ATTACH) { thisModule = (HMODULE) hInst; } return TRUE; } static HANDLE ActivateManifestContext(ActCtxProcs *procs, ULONG_PTR *ulpCookie) { ACTCTXA actctx; HANDLE hCtx; #if 1 char myPath[1024]; DWORD len; if (procs == NULL) return INVALID_HANDLE_VALUE; len = GetModuleFileName(GetMyHandle(),myPath,1024); myPath[len] = 0; ZeroMemory(&actctx, sizeof(actctx)); actctx.cbSize = sizeof(actctx); actctx.lpSource = myPath; actctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; #else if (procs == NULL) return INVALID_HANDLE_VALUE; ZeroMemory(&actctx, sizeof(actctx)); actctx.cbSize = sizeof(actctx); actctx.dwFlags = ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID; actctx.hModule = GetMyHandle(); #endif actctx.lpResourceName = MAKEINTRESOURCE(2); hCtx = procs->CreateActCtxA(&actctx); if (hCtx == INVALID_HANDLE_VALUE) { char msg[1024]; DWORD err = GetLastError(); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)msg, sizeof(msg), 0); return INVALID_HANDLE_VALUE; } if (procs->ActivateActCtx(hCtx, ulpCookie)) return hCtx; return INVALID_HANDLE_VALUE; } static void DeactivateManifestContext(ActCtxProcs *procs, HANDLE hCtx, ULONG_PTR ulpCookie) { if (procs == NULL) return; if (hCtx != INVALID_HANDLE_VALUE) { procs->DeactivateActCtx(0, ulpCookie); procs->ReleaseActCtx(hCtx); } ckfree((char*)procs); } /* http://www.manbu.net/Lib/En/Class5/Sub16/1/29.asp */ static int ComCtlVersionOK(void) { HINSTANCE handle; typedef HRESULT (STDAPICALLTYPE DllGetVersionProc)(DLLVERSIONINFO *); DllGetVersionProc *pDllGetVersion; int result = FALSE; ActCtxProcs *procs; HANDLE hCtx; ULONG_PTR ulpCookie; procs = GetActCtxProcs(); hCtx = ActivateManifestContext(procs, &ulpCookie); handle = LoadLibrary("comctl32.dll"); DeactivateManifestContext(procs, hCtx, ulpCookie); if (handle == NULL) return FALSE; pDllGetVersion = (DllGetVersionProc *) GetProcAddress(handle, "DllGetVersion"); if (pDllGetVersion != NULL) { DLLVERSIONINFO dvi; memset(&dvi, '\0', sizeof(dvi)); dvi.cbSize = sizeof(dvi); if ((*pDllGetVersion)(&dvi) == NOERROR) result = dvi.dwMajorVersion >= 6; } FreeLibrary(handle); return result; } /* *---------------------------------------------------------------------- * * LoadXPThemeProcs -- * Initialize XP theming support. * * XP theme support is included in UXTHEME.DLL * We dynamically load this DLL at runtime instead of linking * to it at build-time. * * Returns: * A pointer to an XPThemeProcs table if successful, NULL otherwise. *---------------------------------------------------------------------- */ static XPThemeProcs * LoadXPThemeProcs(HINSTANCE *phlib) { OSVERSIONINFO os; /* * We have to check whether we are running at least on Windows XP. * In order to determine this we call GetVersionEx directly, although * it would be a good idea to wrap it inside a function similar to * TkWinGetPlatformId... */ ZeroMemory(&os, sizeof(os)); os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&os); if ((os.dwMajorVersion >= 5 && os.dwMinorVersion >= 1) || (os.dwMajorVersion > 5)) { /* * We are running under Windows XP or a newer version. * Load the library "uxtheme.dll", where the native widget * drawing routines are implemented. */ HINSTANCE handle; *phlib = handle = LoadLibrary("uxtheme.dll"); if (handle != 0) { /* * We have successfully loaded the library. Proceed in storing the * addresses of the functions we want to use. */ XPThemeProcs *procs = (XPThemeProcs*)ckalloc(sizeof(XPThemeProcs)); #define LOADPROC(name) \ (0 != (procs->name = (name ## Proc *)GetProcAddress(handle, #name) )) if ( LOADPROC(OpenThemeData) && LOADPROC(CloseThemeData) && LOADPROC(DrawThemeBackground) && LOADPROC(DrawThemeBackgroundEx) && LOADPROC(DrawThemeParentBackground) && LOADPROC(DrawThemeEdge) && LOADPROC(DrawThemeText) && LOADPROC(GetThemeBackgroundContentRect) && LOADPROC(GetThemeBackgroundExtent) && LOADPROC(GetThemeMargins) && LOADPROC(GetThemePartSize) && LOADPROC(GetThemeTextExtent) && LOADPROC(IsThemeActive) && LOADPROC(IsAppThemed) && LOADPROC(IsThemePartDefined) && LOADPROC(IsThemeBackgroundPartiallyTransparent) && ComCtlVersionOK() ) { return procs; } #undef LOADPROC ckfree((char*)procs); } } return 0; } int TreeTheme_DrawHeaderItem(TreeCtrl *tree, Drawable drawable, int state, int arrow, int x, int y, int width, int height) { HTHEME hTheme; HDC hDC; TkWinDCState dcState; RECT rc; HRESULT hr; int iPartId = HP_HEADERITEM; int iStateId = HIS_NORMAL; switch (state) { case COLUMN_STATE_ACTIVE: iStateId = HIS_HOT; break; case COLUMN_STATE_PRESSED: iStateId = HIS_PRESSED; break; } if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; hTheme = tree->themeData->hThemeHEADER; if (!hTheme) return TCL_ERROR; #if 0 /* Always returns FALSE */ if (!procs->IsThemePartDefined( hTheme, iPartId, iStateId)) { return TCL_ERROR; } #endif rc.left = x; rc.top = y; rc.right = x + width; rc.bottom = y + height; /* Is transparent for the default XP style. */ if (procs->IsThemeBackgroundPartiallyTransparent( hTheme, iPartId, iStateId)) { #if 1 /* What color should I use? */ Tk_Fill3DRectangle(tree->tkwin, drawable, tree->border, x, y, width, height, 0, TK_RELIEF_FLAT); #else /* This draws nothing, maybe because the parent window is not * themed */ procs->DrawThemeParentBackground( hwnd, hDC, &rc); #endif } hDC = TkWinGetDrawableDC(tree->display, drawable, &dcState); #if 0 { /* Default XP theme gives rect 3 pixels narrower than rc */ RECT contentRect, extentRect; hr = procs->GetThemeBackgroundContentRect( hTheme, hDC, iPartId, iStateId, &rc, &contentRect ); dbwin("GetThemeBackgroundContentRect width=%d height=%d\n", contentRect.right - contentRect.left, contentRect.bottom - contentRect.top); /* Gives rc */ hr = procs->GetThemeBackgroundExtent( hTheme, hDC, iPartId, iStateId, &contentRect, &extentRect ); dbwin("GetThemeBackgroundExtent width=%d height=%d\n", extentRect.right - extentRect.left, extentRect.bottom - extentRect.top); } #endif hr = procs->DrawThemeBackground( hTheme, hDC, iPartId, iStateId, &rc, NULL); TkWinReleaseDrawableDC(drawable, hDC, &dcState); if (hr != S_OK) return TCL_ERROR; return TCL_OK; } int TreeTheme_GetHeaderContentMargins(TreeCtrl *tree, int state, int arrow, int bounds[4]) { Window win = Tk_WindowId(tree->tkwin); HTHEME hTheme; HDC hDC; TkWinDCState dcState; HRESULT hr; MARGINS margins; int iPartId = HP_HEADERITEM; int iStateId = HIS_NORMAL; switch (state) { case COLUMN_STATE_ACTIVE: iStateId = HIS_HOT; break; case COLUMN_STATE_PRESSED: iStateId = HIS_PRESSED; break; } if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; hTheme = tree->themeData->hThemeHEADER; if (!hTheme) return TCL_ERROR; hDC = TkWinGetDrawableDC(tree->display, win, &dcState); /* The default XP themes give 3,0,0,0 which makes little sense since * it is the *right* side that should not be drawn over by text; the * 2-pixel wide header divider is on the right */ hr = procs->GetThemeMargins( hTheme, hDC, iPartId, iStateId, TMT_CONTENTMARGINS, NULL, &margins); TkWinReleaseDrawableDC(win, hDC, &dcState); if (hr != S_OK) return TCL_ERROR; bounds[0] = margins.cxLeftWidth; bounds[1] = margins.cyTopHeight; bounds[2] = margins.cxRightWidth; bounds[3] = margins.cyBottomHeight; /* dbwin("margins %d %d %d %d\n", bounds[0], bounds[1], bounds[2], bounds[3]); */ return TCL_OK; } int TreeTheme_DrawHeaderArrow(TreeCtrl *tree, Drawable drawable, int up, int x, int y, int width, int height) { #if 1 XColor *color; GC gc; int i; if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; color = Tk_GetColor(tree->interp, tree->tkwin, "#ACA899"); gc = Tk_GCForColor(color, drawable); if (up) { for (i = 0; i < height; i++) { XDrawLine(tree->display, drawable, gc, x + width / 2 - i, y + i, x + width / 2 + i + 1, y + i); } } else { for (i = 0; i < height; i++) { XDrawLine(tree->display, drawable, gc, x + width / 2 - i, y + (height - 1) - i, x + width / 2 + i + 1, y + (height - 1) - i); } } Tk_FreeColor(color); return TCL_OK; #else /* Doesn't seem that Microsoft actually implemented this */ Window win = Tk_WindowId(tree->tkwin); HWND hwnd = Tk_GetHWND(win); HTHEME hTheme; HDC hDC; TkWinDCState dcState; RECT rc; HRESULT hr; int iPartId = HP_HEADERSORTARROW; int iStateId = up ? HSAS_SORTEDUP : HSAS_SORTEDDOWN; if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; hTheme = tree->themeData->hThemeHEADER; if (!hTheme) return TCL_ERROR; if (!procs->IsThemePartDefined( hTheme, iPartId, iStateId)) { return TCL_ERROR; } hDC = TkWinGetDrawableDC(tree->display, drawable, &dcState); rc.left = x; rc.top = y; rc.right = x + width; rc.bottom = y + height; hr = procs->DrawThemeBackground( hTheme, hDC, iPartId, iStateId, &rc, NULL); TkWinReleaseDrawableDC(drawable, hDC, &dcState); return TCL_OK; #endif /* 0 */ } int TreeTheme_DrawButton(TreeCtrl *tree, Drawable drawable, int open, int x, int y, int width, int height) { HTHEME hTheme; HDC hDC; TkWinDCState dcState; RECT rc; HRESULT hr; int iPartId, iStateId; if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; iPartId = TVP_GLYPH; iStateId = open ? GLPS_OPENED : GLPS_CLOSED; hTheme = tree->themeData->hThemeTREEVIEW; if (!hTheme) return TCL_ERROR; #if 0 /* Always returns FALSE */ if (!procs->IsThemePartDefined( hTheme, iPartId, iStateId)) { return TCL_ERROR; } #endif hDC = TkWinGetDrawableDC(tree->display, drawable, &dcState); rc.left = x; rc.top = y; rc.right = x + width; rc.bottom = y + height; hr = procs->DrawThemeBackground( hTheme, hDC, iPartId, iStateId, &rc, NULL); TkWinReleaseDrawableDC(drawable, hDC, &dcState); if (hr != S_OK) return TCL_ERROR; return TCL_OK; } int TreeTheme_GetButtonSize(TreeCtrl *tree, Drawable drawable, int open, int *widthPtr, int *heightPtr) { HTHEME hTheme; HDC hDC; TkWinDCState dcState; HRESULT hr; SIZE size; int iPartId, iStateId; if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; /* Use cached values */ size = open ? appThemeData->buttonOpen : appThemeData->buttonClosed; if (size.cx > 1) { *widthPtr = size.cx; *heightPtr = size.cy; return TCL_OK; } iPartId = TVP_GLYPH; iStateId = open ? GLPS_OPENED : GLPS_CLOSED; hTheme = tree->themeData->hThemeTREEVIEW; if (!hTheme) return TCL_ERROR; #if 0 /* Always returns FALSE */ if (!procs->IsThemePartDefined( hTheme, iPartId, iStateId)) { return TCL_ERROR; } #endif hDC = TkWinGetDrawableDC(tree->display, drawable, &dcState); /* Returns 9x9 for default XP style */ hr = procs->GetThemePartSize( hTheme, hDC, iPartId, iStateId, NULL, TS_DRAW, &size ); TkWinReleaseDrawableDC(drawable, hDC, &dcState); /* With RandomN of 10000, I eventually get hr=E_HANDLE, invalid handle */ /* Not any longer since I don't call OpenThemeData/CloseThemeData for * every call. */ if (hr != S_OK) return TCL_ERROR; /* Gave me 0,0 for a non-default theme, even though glyph existed */ if ((size.cx <= 1) && (size.cy <= 1)) return TCL_ERROR; /* Cache the values */ if (open) appThemeData->buttonOpen = size; else appThemeData->buttonClosed = size; *widthPtr = size.cx; *heightPtr = size.cy; return TCL_OK; } int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *widthPtr, int *heightPtr) { if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; *widthPtr = 9; *heightPtr = 5; return TCL_OK; } int TreeTheme_SetBorders(TreeCtrl *tree) { return TCL_ERROR; } int TreeTheme_DrawBorders( TreeCtrl *tree, Drawable drawable ) { return TCL_ERROR; } void TreeTheme_Relayout( TreeCtrl *tree ) { } #if !defined(WM_THEMECHANGED) #define WM_THEMECHANGED 0x031A #endif static LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { Tcl_Interp *interp = (Tcl_Interp *)GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (msg) { case WM_THEMECHANGED: Tcl_MutexLock(&themeMutex); appThemeData->themeEnabled = procs->IsThemeActive() && procs->IsAppThemed(); appThemeData->buttonClosed.cx = appThemeData->buttonOpen.cx = -1; Tcl_MutexUnlock(&themeMutex); Tree_TheWorldHasChanged(interp); break; } return DefWindowProc(hwnd, msg, wp, lp); } static CHAR windowClassName[32] = "TreeCtrlMonitorClass"; static BOOL RegisterThemeMonitorWindowClass(HINSTANCE hinst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hinst; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.lpszMenuName = windowClassName; wc.lpszClassName = windowClassName; return RegisterClassEx(&wc); } static HWND CreateThemeMonitorWindow(HINSTANCE hinst, Tcl_Interp *interp) { CHAR title[32] = "TreeCtrlMonitorWindow"; HWND hwnd; hwnd = CreateWindow(windowClassName, title, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinst, NULL); if (!hwnd) return NULL; SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG)interp); ShowWindow(hwnd, SW_HIDE); UpdateWindow(hwnd); return hwnd; } typedef struct PerInterpData PerInterpData; struct PerInterpData { HWND hwnd; }; static void FreeAssocData(ClientData clientData, Tcl_Interp *interp) { PerInterpData *data = (PerInterpData *) clientData; DestroyWindow(data->hwnd); ckfree((char *) data); } void TreeTheme_ThemeChanged(TreeCtrl *tree) { Window win = Tk_WindowId(tree->tkwin); HWND hwnd = Tk_GetHWND(win); if (tree->themeData != NULL) { if (tree->themeData->hThemeHEADER != NULL) { procs->CloseThemeData(tree->themeData->hThemeHEADER); tree->themeData->hThemeHEADER = NULL; } if (tree->themeData->hThemeTREEVIEW != NULL) { procs->CloseThemeData(tree->themeData->hThemeTREEVIEW); tree->themeData->hThemeTREEVIEW = NULL; } } if (!appThemeData->themeEnabled || !procs) return; if (tree->themeData == NULL) tree->themeData = (TreeThemeData) ckalloc(sizeof(TreeThemeData_)); tree->themeData->hThemeHEADER = procs->OpenThemeData(hwnd, L"HEADER"); tree->themeData->hThemeTREEVIEW = procs->OpenThemeData(hwnd, L"TREEVIEW"); } int TreeTheme_Init(TreeCtrl *tree) { Window win = Tk_WindowId(tree->tkwin); HWND hwnd = Tk_GetHWND(win); if (!appThemeData->themeEnabled || !procs) return TCL_ERROR; tree->themeData = (TreeThemeData) ckalloc(sizeof(TreeThemeData_)); /* http://www.codeproject.com/cs/miscctrl/themedtabpage.asp?msg=1445385#xx1445385xx */ /* http://msdn2.microsoft.com/en-us/library/ms649781.aspx */ tree->themeData->hThemeHEADER = procs->OpenThemeData(hwnd, L"HEADER"); tree->themeData->hThemeTREEVIEW = procs->OpenThemeData(hwnd, L"TREEVIEW"); return TCL_OK; } int TreeTheme_Free(TreeCtrl *tree) { if (tree->themeData != NULL) { if (tree->themeData->hThemeHEADER != NULL) procs->CloseThemeData(tree->themeData->hThemeHEADER); if (tree->themeData->hThemeTREEVIEW != NULL) procs->CloseThemeData(tree->themeData->hThemeTREEVIEW); ckfree((char *) tree->themeData); } return TCL_OK; } int TreeTheme_InitInterp(Tcl_Interp *interp) { HWND hwnd; PerInterpData *data; Tcl_MutexLock(&themeMutex); /* This is done once per-application */ if (appThemeData == NULL) { appThemeData = (XPThemeData *) ckalloc(sizeof(XPThemeData)); appThemeData->procs = LoadXPThemeProcs(&appThemeData->hlibrary); appThemeData->registered = FALSE; appThemeData->themeEnabled = FALSE; appThemeData->buttonClosed.cx = appThemeData->buttonOpen.cx = -1; procs = appThemeData->procs; if (appThemeData->procs) { /* Check this again if WM_THEMECHANGED arrives */ appThemeData->themeEnabled = procs->IsThemeActive() && procs->IsAppThemed(); appThemeData->registered = RegisterThemeMonitorWindowClass(Tk_GetHINSTANCE()); } } Tcl_MutexUnlock(&themeMutex); if (!procs || !appThemeData->registered) return TCL_ERROR; /* Per-interp */ hwnd = CreateThemeMonitorWindow(Tk_GetHINSTANCE(), interp); if (!hwnd) return TCL_ERROR; data = (PerInterpData *) ckalloc(sizeof(PerInterpData)); data->hwnd = hwnd; Tcl_SetAssocData(interp, "TreeCtrlTheme", FreeAssocData, (ClientData) data); return TCL_OK; } #elif defined(MAC_OSX_TK) #include #include "tkMacOSXInt.h" static RgnHandle oldClip = NULL, boundsRgn = NULL; int TreeTheme_DrawHeaderItem(TreeCtrl *tree, Drawable drawable, int state, int arrow, int x, int y, int width, int height) { MacDrawable *macWin = (MacDrawable *) drawable; Rect bounds; ThemeButtonDrawInfo info; CGrafPtr saveWorld; GDHandle saveDevice; GWorldPtr destPort; bounds.left = macWin->xOff + x; bounds.top = macWin->yOff + y; bounds.right = bounds.left + width; bounds.bottom = bounds.top + height; switch (state) { case COLUMN_STATE_ACTIVE: info.state = kThemeStateActive /* kThemeStateRollover */; break; case COLUMN_STATE_PRESSED: info.state = kThemeStatePressed; break; default: info.state = kThemeStateActive; break; } /* Background window */ if (!tree->isActive) info.state = kThemeStateInactive; info.value = (arrow != 0) ? kThemeButtonOn : kThemeButtonOff; info.adornment = (arrow == 1) ? kThemeAdornmentHeaderButtonSortUp : kThemeAdornmentNone; destPort = TkMacOSXGetDrawablePort(drawable); GetGWorld(&saveWorld, &saveDevice); SetGWorld(destPort, 0); TkMacOSXSetUpClippingRgn(drawable); /* Save the old clipping region because we are going to modify it. */ if (oldClip == NULL) oldClip = NewRgn(); GetClip(oldClip); /* Create a clipping region as big as the header. */ if (boundsRgn == NULL) boundsRgn = NewRgn(); RectRgn(boundsRgn, &bounds); /* Set the clipping region to the intersection of the two regions. */ SectRgn(oldClip, boundsRgn, boundsRgn); SetClip(boundsRgn); /* Draw the left edge outside of the clipping region. */ bounds.left -= 1; (void) DrawThemeButton(&bounds, kThemeListHeaderButton, &info, NULL, /*prevInfo*/ NULL, /*eraseProc*/ NULL, /*labelProc*/ NULL); /*userData*/ SetClip(oldClip); SetGWorld(saveWorld,saveDevice); return TCL_OK; } /* List headers are a fixed height on Aqua */ int TreeTheme_GetHeaderFixedHeight(TreeCtrl *tree, int *heightPtr) { SInt32 metric; GetThemeMetric(kThemeMetricListHeaderHeight, &metric); *heightPtr = metric; return TCL_OK; } int TreeTheme_GetHeaderContentMargins(TreeCtrl *tree, int state, int arrow, int bounds[4]) { Rect inBounds, outBounds; ThemeButtonDrawInfo info; SInt32 metric; inBounds.left = 0; inBounds.top = 0; inBounds.right = 100; GetThemeMetric(kThemeMetricListHeaderHeight, &metric); inBounds.bottom = metric; switch (state) { case COLUMN_STATE_ACTIVE: info.state = kThemeStateActive /* kThemeStateRollover */; break; case COLUMN_STATE_PRESSED: info.state = kThemeStatePressed; break; default: info.state = kThemeStateActive; break; } /* Background window */ if (!tree->isActive) info.state = kThemeStateInactive; info.value = (arrow != 0) ? kThemeButtonOn : kThemeButtonOff; info.adornment = (arrow == 1) ? kThemeAdornmentHeaderButtonSortUp : kThemeAdornmentNone; (void) GetThemeButtonContentBounds( &inBounds, kThemeListHeaderButton, &info, &outBounds); bounds[0] = outBounds.left - inBounds.left; bounds[1] = outBounds.top - inBounds.top; bounds[2] = inBounds.right - outBounds.right; bounds[3] = inBounds.bottom - outBounds.bottom; return TCL_OK; } int TreeTheme_DrawHeaderArrow(TreeCtrl *tree, Drawable drawable, int up, int x, int y, int width, int height) { return TCL_ERROR; } int TreeTheme_DrawButton(TreeCtrl *tree, Drawable drawable, int open, int x, int y, int width, int height) { MacDrawable *macWin = (MacDrawable *) drawable; Rect bounds; ThemeButtonDrawInfo info; CGrafPtr saveWorld; GDHandle saveDevice; GWorldPtr destPort; bounds.left = macWin->xOff + x; bounds.top = macWin->yOff + y; bounds.right = bounds.left + width; bounds.bottom = bounds.top + height; info.state = kThemeStateActive; info.value = open ? kThemeDisclosureDown : kThemeDisclosureRight; info.adornment = kThemeAdornmentNone; destPort = TkMacOSXGetDrawablePort(drawable); GetGWorld(&saveWorld, &saveDevice); SetGWorld(destPort, 0); TkMacOSXSetUpClippingRgn(drawable); /* Drawing the disclosure triangles produces a white background. * To avoid this, set the clipping region to the exact area where * pixels are drawn. */ /* Save the old clipping region because we are going to modify it. */ if (oldClip == NULL) oldClip = NewRgn(); GetClip(oldClip); /* Create a clipping region containing the pixels of the button. */ if (boundsRgn == NULL) boundsRgn = NewRgn(); (void) GetThemeButtonRegion(&bounds, kThemeDisclosureButton, &info, boundsRgn); /* Set the clipping region to the intersection of the two regions. */ SectRgn(oldClip, boundsRgn, boundsRgn); SetClip(boundsRgn); (void) DrawThemeButton(&bounds, kThemeDisclosureButton, &info, NULL, /*prevInfo*/ NULL, /*eraseProc*/ NULL, /*labelProc*/ NULL); /*userData*/ /* Restore the original clipping region. */ SetClip(oldClip); SetGWorld(saveWorld,saveDevice); return TCL_OK; } int TreeTheme_GetButtonSize(TreeCtrl *tree, Drawable drawable, int open, int *widthPtr, int *heightPtr) { SInt32 metric; (void) GetThemeMetric( kThemeMetricDisclosureTriangleWidth, &metric); *widthPtr = metric; (void) GetThemeMetric( kThemeMetricDisclosureTriangleHeight, &metric); *heightPtr = metric; return TCL_OK; } int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *widthPtr, int *heightPtr) { return TCL_ERROR; } int TreeTheme_SetBorders(TreeCtrl *tree) { return TCL_ERROR; } int TreeTheme_DrawBorders( TreeCtrl *tree, Drawable drawable ) { return TCL_ERROR; } void TreeTheme_Relayout( TreeCtrl *tree ) { } void TreeTheme_ThemeChanged(TreeCtrl *tree) { } int TreeTheme_Init(TreeCtrl *tree) { return TCL_OK; } int TreeTheme_Free(TreeCtrl *tree) { return TCL_OK; } int TreeTheme_InitInterp(Tcl_Interp *interp) { return TCL_OK; } #else /* MAC_OSX_TK */ int TreeTheme_DrawHeaderItem(TreeCtrl *tree, Drawable drawable, int state, int arrow, int x, int y, int width, int height) { return TCL_ERROR; } int TreeTheme_GetHeaderContentMargins(TreeCtrl *tree, int state, int arrow, int bounds[4]) { return TCL_ERROR; } int TreeTheme_DrawHeaderArrow(TreeCtrl *tree, Drawable drawable, int up, int x, int y, int width, int height) { return TCL_ERROR; } int TreeTheme_DrawButton(TreeCtrl *tree, Drawable drawable, int open, int x, int y, int width, int height) { return TCL_ERROR; } int TreeTheme_GetButtonSize(TreeCtrl *tree, Drawable drawable, int open, int *widthPtr, int *heightPtr) { return TCL_ERROR; } int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *widthPtr, int *heightPtr) { return TCL_ERROR; } int TreeTheme_SetBorders(TreeCtrl *tree) { return TCL_ERROR; } int TreeTheme_DrawBorders( TreeCtrl *tree, Drawable drawable ) { return TCL_ERROR; } void TreeTheme_Relayout( TreeCtrl *tree ) { } void TreeTheme_ThemeChanged(TreeCtrl *tree) { } int TreeTheme_Init(TreeCtrl *tree) { return TCL_OK; } int TreeTheme_Free(TreeCtrl *tree) { return TCL_OK; } int TreeTheme_InitInterp(Tcl_Interp *interp) { return TCL_OK; } #endif /* !WIN32 && !MAC_OSX_TK */ #else /* !USE_TTK */ typedef struct TreeThemeData_ { Ttk_Layout layout; Ttk_Layout buttonLayout; Ttk_Layout headingLayout; Tk_OptionTable buttonOptionTable; Tk_OptionTable headingOptionTable; Ttk_Box clientBox; int buttonWidth[2], buttonHeight[2]; Ttk_Padding buttonPadding[2]; } TreeThemeData_; int TreeTheme_DrawHeaderItem(TreeCtrl *tree, Drawable drawable, int state, int arrow, int x, int y, int width, int height) { TreeThemeData themeData = tree->themeData; Ttk_Layout layout = themeData->headingLayout; Ttk_State ttk_state = 0; Ttk_Box box; if (layout == NULL) return TCL_ERROR; box = Ttk_MakeBox(x, y, width, height); switch (state) { case COLUMN_STATE_ACTIVE: ttk_state = TTK_STATE_ACTIVE; break; case COLUMN_STATE_PRESSED: ttk_state = TTK_STATE_PRESSED; break; } eTtk_RebindSublayout(layout, NULL); /* !!! rebind to column */ eTtk_PlaceLayout(layout, ttk_state, box); eTtk_DrawLayout(layout, ttk_state, drawable); return TCL_OK; } int TreeTheme_GetHeaderContentMargins(TreeCtrl *tree, int state, int arrow, int bounds[4]) { return TCL_ERROR; } int TreeTheme_DrawHeaderArrow(TreeCtrl *tree, Drawable drawable, int up, int x, int y, int width, int height) { return TCL_ERROR; } /* From ttkTreeview.c */ #define TTK_STATE_OPEN TTK_STATE_USER1 int TreeTheme_DrawButton(TreeCtrl *tree, Drawable drawable, int open, int x, int y, int width, int height) { TreeThemeData themeData = tree->themeData; Ttk_Layout layout = themeData->buttonLayout; Ttk_State ttk_state = 0; Ttk_Box box; Ttk_Padding padding; if (layout == NULL) return TCL_ERROR; open = open ? 1 : 0; padding = themeData->buttonPadding[open]; x -= padding.left; y -= padding.top; width = themeData->buttonWidth[open]; height = themeData->buttonHeight[open]; box = Ttk_MakeBox(x, y, width, height); ttk_state = open ? TTK_STATE_OPEN : 0; eTtk_RebindSublayout(layout, NULL); /* !!! rebind to item */ eTtk_PlaceLayout(layout, ttk_state, box); eTtk_DrawLayout(layout, ttk_state, drawable); return TCL_OK; } int TreeTheme_GetButtonSize(TreeCtrl *tree, Drawable drawable, int open, int *widthPtr, int *heightPtr) { TreeThemeData themeData = tree->themeData; Ttk_Padding padding; if (themeData->buttonLayout == NULL) return TCL_ERROR; open = open ? 1 : 0; padding = themeData->buttonPadding[open]; *widthPtr = themeData->buttonWidth[open] - padding.left - padding.right; *heightPtr = themeData->buttonHeight[open] - padding.top - padding.bottom; return TCL_OK; } int TreeTheme_GetArrowSize(TreeCtrl *tree, Drawable drawable, int up, int *widthPtr, int *heightPtr) { return TCL_ERROR; } int TreeTheme_SetBorders(TreeCtrl *tree) { TreeThemeData themeData = tree->themeData; Tk_Window tkwin = tree->tkwin; Ttk_Box clientBox = themeData->clientBox; tree->inset.left = clientBox.x; tree->inset.top = clientBox.y; tree->inset.right = Tk_Width(tkwin) - (clientBox.x + clientBox.width); tree->inset.bottom = Tk_Height(tkwin) - (clientBox.y + clientBox.height); return TCL_OK; } /* * This routine is a big hack so that the "field" element (of the TreeCtrl * layout) doesn't erase the entire background of the window. This routine * draws each edge of the layout into a pixmap and copies the pixmap to the * window. */ int TreeTheme_DrawBorders( TreeCtrl *tree, Drawable drawable ) { TreeThemeData themeData = tree->themeData; Tk_Window tkwin = tree->tkwin; Ttk_Box winBox = Ttk_WinBox(tree->tkwin); Ttk_State state = 0; /* ??? */ int left, top, right, bottom; Drawable pixmapLR = None, pixmapTB = None; left = tree->inset.left; top = tree->inset.top; right = tree->inset.right; bottom = tree->inset.bottom; /* If the Ttk layout doesn't specify any borders or padding, then * draw nothing. */ if (left < 1 && top < 1 && right < 1 && bottom < 1) return TCL_OK; if (left > 0 || top > 0) eTtk_PlaceLayout(themeData->layout, state, winBox); if (left > 0 || right > 0) { pixmapLR = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), MAX(left, right), Tk_Height(tkwin), Tk_Depth(tkwin)); } if (top > 0 || bottom > 0) { pixmapTB = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin), Tk_Width(tkwin), MAX(top, bottom), Tk_Depth(tkwin)); } DebugDrawBorder(tree, 0, left, top, right, bottom); if (left > 0) { eTtk_DrawLayout(themeData->layout, state, pixmapLR); XCopyArea(tree->display, pixmapLR, drawable, tree->copyGC, 0, 0, left, Tk_Height(tkwin), 0, 0); } if (top > 0) { eTtk_DrawLayout(themeData->layout, state, pixmapTB); XCopyArea(tree->display, pixmapTB, drawable, tree->copyGC, 0, 0, Tk_Width(tkwin), top, 0, 0); } if (right > 0) { winBox.x -= winBox.width - right; eTtk_PlaceLayout(themeData->layout, state, winBox); eTtk_DrawLayout(themeData->layout, state, pixmapLR); XCopyArea(tree->display, pixmapLR, drawable, tree->copyGC, 0, 0, right, Tk_Height(tkwin), Tree_BorderRight(tree), 0); } if (bottom > 0) { winBox.x = 0; winBox.y -= winBox.height - bottom; eTtk_PlaceLayout(themeData->layout, state, winBox); eTtk_DrawLayout(themeData->layout, state, pixmapTB); XCopyArea(tree->display, pixmapTB, drawable, tree->copyGC, 0, 0, Tk_Width(tkwin), bottom, 0, Tree_BorderBottom(tree)); } if (pixmapLR != None) Tk_FreePixmap(tree->display, pixmapLR); if (pixmapTB != None) Tk_FreePixmap(tree->display, pixmapTB); return TCL_OK; } static Tk_OptionSpec NullOptionSpecs[] = { {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} }; /* from ttkTreeview.c */ static Ttk_Layout GetSublayout( Tcl_Interp *interp, Ttk_Theme themePtr, Ttk_Layout parentLayout, const char *layoutName, Tk_OptionTable optionTable, Ttk_Layout *layoutPtr) { Ttk_Layout newLayout = eTtk_CreateSublayout( interp, themePtr, parentLayout, layoutName, optionTable); if (newLayout) { if (*layoutPtr) eTtk_FreeLayout(*layoutPtr); *layoutPtr = newLayout; } return newLayout; } Ttk_Layout TreeCtrlGetLayout( Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr ) { TreeCtrl *tree = recordPtr; TreeThemeData themeData = tree->themeData; Ttk_Layout treeLayout, newLayout; if (themeData->headingOptionTable == NULL) themeData->headingOptionTable = Tk_CreateOptionTable(interp, NullOptionSpecs); if (themeData->buttonOptionTable == NULL) themeData->buttonOptionTable = Tk_CreateOptionTable(interp, NullOptionSpecs); /* Create a new layout record based on widget -style or class */ treeLayout = eTtk_CreateLayout(interp, themePtr, "TreeCtrl", tree, tree->optionTable, tree->tkwin); /* Create a sublayout for drawing the column headers. The sublayout is * called "TreeCtrl.TreeCtrlHeading" by default. The actual layout specification * was defined by Ttk_RegisterLayout("TreeCtrlHeading") below. */ newLayout = GetSublayout(interp, themePtr, treeLayout, ".TreeCtrlHeading", themeData->headingOptionTable, &themeData->headingLayout); if (newLayout == NULL) return NULL; newLayout = GetSublayout(interp, themePtr, treeLayout, ".TreeCtrlButton", themeData->buttonOptionTable, &themeData->buttonLayout); if (newLayout == NULL) return NULL; return treeLayout; } void TreeCtrlDoLayout( void *recordPtr ) { TreeCtrl *tree = recordPtr; TreeThemeData themeData = tree->themeData; Ttk_LayoutNode *node; Ttk_Box winBox = Ttk_WinBox(tree->tkwin); Ttk_State state = 0; /* ??? */ eTtk_PlaceLayout(themeData->layout, state, winBox); node = eTtk_LayoutFindNode(themeData->layout, "client"); if (node != NULL) themeData->clientBox = eTtk_LayoutNodeInternalParcel(themeData->layout, node); else themeData->clientBox = winBox; /* Size of opened and closed buttons. */ eTtk_LayoutSize(themeData->buttonLayout, TTK_STATE_OPEN, &themeData->buttonWidth[1], &themeData->buttonHeight[1]); eTtk_LayoutSize(themeData->buttonLayout, 0, &themeData->buttonWidth[0], &themeData->buttonHeight[0]); node = eTtk_LayoutFindNode(themeData->buttonLayout, "indicator"); if (node != NULL) { Ttk_Box box1, box2; box1 = Ttk_MakeBox(0, 0, themeData->buttonWidth[1], themeData->buttonHeight[1]); eTtk_PlaceLayout(themeData->buttonLayout, TTK_STATE_OPEN, box1); box2 = eTtk_LayoutNodeInternalParcel(themeData->buttonLayout, node); themeData->buttonPadding[1] = Ttk_MakePadding(box2.x, box2.y, (box1.x + box1.width) - (box2.x + box2.width), (box1.y + box1.height) - (box2.y + box2.height)); box1 = Ttk_MakeBox(0, 0, themeData->buttonWidth[0], themeData->buttonHeight[0]); eTtk_PlaceLayout(themeData->buttonLayout, 0, box1); box2 = eTtk_LayoutNodeInternalParcel(themeData->buttonLayout, node); themeData->buttonPadding[0] = Ttk_MakePadding(box2.x, box2.y, (box1.x + box1.width) - (box2.x + box2.width), (box1.y + box1.height) - (box2.y + box2.height)); } else { themeData->buttonPadding[1] = Ttk_MakePadding(0,0,0,0); themeData->buttonPadding[0] = Ttk_MakePadding(0,0,0,0); } } void TreeTheme_Relayout( TreeCtrl *tree ) { TreeThemeData themeData = tree->themeData; Ttk_Theme themePtr = Ttk_GetCurrentTheme(tree->interp); Ttk_Layout newLayout = TreeCtrlGetLayout(tree->interp, themePtr, tree); if (newLayout) { if (themeData->layout) { eTtk_FreeLayout(themeData->layout); } themeData->layout = newLayout; TreeCtrlDoLayout(tree); } } /* HeaderElement is used for Treeheading.cell. The platform-specific code * will draw the native heading. */ typedef struct { Tcl_Obj *backgroundObj; } HeaderElement; static Ttk_ElementOptionSpec HeaderElementOptions[] = { { "-background", TK_OPTION_COLOR, Tk_Offset(HeaderElement, backgroundObj), DEFAULT_BACKGROUND }, {NULL} }; static void HeaderElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { HeaderElement *e = elementRecord; XColor *color = Tk_GetColorFromObj(tkwin, e->backgroundObj); GC gc = Tk_GCForColor(color, d); XFillRectangle(Tk_Display(tkwin), d, gc, b.x, b.y, b.width, b.height); } static Ttk_ElementSpec HeaderElementSpec = { TK_STYLE_VERSION_2, sizeof(HeaderElement), HeaderElementOptions, Ttk_NullElementGeometry, HeaderElementDraw }; /* Default button element (aka Treeitem.indicator). */ typedef struct { Tcl_Obj *backgroundObj; Tcl_Obj *colorObj; Tcl_Obj *sizeObj; Tcl_Obj *thicknessObj; } TreeitemIndicator; static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = { { "-buttonbackground", TK_OPTION_COLOR, Tk_Offset(TreeitemIndicator, backgroundObj), "white" }, { "-buttoncolor", TK_OPTION_COLOR, Tk_Offset(TreeitemIndicator, colorObj), "#808080" }, { "-buttonsize", TK_OPTION_PIXELS, Tk_Offset(TreeitemIndicator, sizeObj), "9" }, { "-buttonthickness", TK_OPTION_PIXELS, Tk_Offset(TreeitemIndicator, thicknessObj), "1" }, {NULL} }; static void TreeitemIndicatorSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { TreeitemIndicator *indicator = elementRecord; int size = 0; Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size); *widthPtr = *heightPtr = size; *paddingPtr = Ttk_MakePadding(0,0,0,0); } static void TreeitemIndicatorDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { TreeitemIndicator *indicator = elementRecord; int w1, lineLeft, lineTop, buttonLeft, buttonTop, buttonThickness, buttonSize; XColor *bgColor = Tk_GetColorFromObj(tkwin, indicator->backgroundObj); XColor *buttonColor = Tk_GetColorFromObj(tkwin, indicator->colorObj); XGCValues gcValues; unsigned long gcMask; GC buttonGC; Ttk_Padding padding = Ttk_MakePadding(0,0,0,0); b = Ttk_PadBox(b, padding); Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &buttonSize); Tk_GetPixelsFromObj(NULL, tkwin, indicator->thicknessObj, &buttonThickness); w1 = buttonThickness / 2; /* Left edge of vertical line */ /* Make sure this matches TreeItem_DrawLines() */ lineLeft = b.x + (b.width - buttonThickness) / 2; /* Top edge of horizontal line */ /* Make sure this matches TreeItem_DrawLines() */ lineTop = b.y + (b.height - buttonThickness) / 2; buttonLeft = b.x; buttonTop = b.y; /* Erase button background */ XFillRectangle(Tk_Display(tkwin), d, Tk_GCForColor(bgColor, d), buttonLeft + buttonThickness, buttonTop + buttonThickness, buttonSize - buttonThickness, buttonSize - buttonThickness); gcValues.foreground = buttonColor->pixel; gcValues.line_width = buttonThickness; gcMask = GCForeground | GCLineWidth; buttonGC = Tk_GetGC(tkwin, gcMask, &gcValues); /* Draw button outline */ XDrawRectangle(Tk_Display(tkwin), d, buttonGC, buttonLeft + w1, buttonTop + w1, buttonSize - buttonThickness, buttonSize - buttonThickness); /* Horizontal '-' */ XFillRectangle(Tk_Display(tkwin), d, buttonGC, buttonLeft + buttonThickness * 2, lineTop, buttonSize - buttonThickness * 4, buttonThickness); if (!(state & TTK_STATE_OPEN)) { /* Finish '+' */ XFillRectangle(Tk_Display(tkwin), d, buttonGC, lineLeft, buttonTop + buttonThickness * 2, buttonThickness, buttonSize - buttonThickness * 4); } Tk_FreeGC(Tk_Display(tkwin), buttonGC); } static Ttk_ElementSpec TreeitemIndicatorElementSpec = { TK_STYLE_VERSION_2, sizeof(TreeitemIndicator), TreeitemIndicatorOptions, TreeitemIndicatorSize, TreeitemIndicatorDraw }; TTK_BEGIN_LAYOUT(HeadingLayout) TTK_NODE("Treeheading.cell", TTK_FILL_BOTH) TTK_NODE("Treeheading.border", TTK_FILL_BOTH) TTK_END_LAYOUT TTK_BEGIN_LAYOUT(ButtonLayout) TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT) TTK_END_LAYOUT TTK_BEGIN_LAYOUT(TreeCtrlLayout) TTK_GROUP("TreeCtrl.field", TTK_FILL_BOTH|TTK_BORDER, TTK_GROUP("TreeCtrl.padding", TTK_FILL_BOTH, TTK_NODE("TreeCtrl.client", TTK_FILL_BOTH))) TTK_END_LAYOUT void TreeTheme_ThemeChanged(TreeCtrl *tree) { } int TreeTheme_Init(TreeCtrl *tree) { tree->themeData = (TreeThemeData) ckalloc(sizeof(TreeThemeData_)); memset(tree->themeData, '\0', sizeof(TreeThemeData_)); return TCL_OK; } int TreeTheme_Free(TreeCtrl *tree) { TreeThemeData themeData = tree->themeData; if (themeData != NULL) { if (themeData->layout != NULL) eTtk_FreeLayout(themeData->layout); if (themeData->buttonLayout != NULL) eTtk_FreeLayout(themeData->buttonLayout); if (themeData->headingLayout != NULL) eTtk_FreeLayout(themeData->headingLayout); ckfree((char *) themeData); } return TCL_OK; } int TreeTheme_InitInterp(Tcl_Interp *interp) { Ttk_Theme theme = Ttk_GetDefaultTheme(interp); Ttk_RegisterLayout(theme, "TreeCtrl", TreeCtrlLayout); /* Problem: what if Treeview also defines this? */ Ttk_RegisterElement(interp, theme, "Treeheading.cell", &HeaderElementSpec, 0); /* Problem: what if Treeview also defines this? */ Ttk_RegisterElement(interp, theme, "Treeitem.indicator", &TreeitemIndicatorElementSpec, 0); Ttk_RegisterLayout(theme, "TreeCtrlHeading", HeadingLayout); Ttk_RegisterLayout(theme, "TreeCtrlButton", ButtonLayout); return TCL_OK; } #endif /* USE_TTK */ tktreectrl-2.2.8/generic/tkTreeUtils.c0000700000175600010010000047552211041153372016157 0ustar TimNone/* * tkTreeUtils.c -- * * This module implements misc routines for treectrl widgets. * * Copyright (c) 2002-2008 Tim Baker * * RCS: @(#) $Id: tkTreeUtils.c,v 1.75 2008/07/21 18:35:38 treectrl Exp $ */ #include "tkTreeCtrl.h" #ifdef WIN32 #include "tkWinInt.h" #endif /* OffsetRgn() on Mac */ #if defined(MAC_OSX_TK) #include #include "tkMacOSXInt.h" static PixPatHandle gPenPat = NULL; /* TkRegion changed from RgnHandle to HIShapeRef in 8.4.17/8.5.0 */ #if (TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION >= 5) #define MAC_OSX_HISHAPE 1 #elif (TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION == 4) && (TK_RELEASE_SERIAL >= 17) #define MAC_OSX_HISHAPE 1 #endif #endif struct dbwinterps { int count; #define DBWIN_MAX_INTERPS 16 Tcl_Interp *interps[DBWIN_MAX_INTERPS]; }; static Tcl_ThreadDataKey dbwinTDK; static CONST char *DBWIN_VAR_NAME = "dbwin"; static void dbwin_forget_interp(ClientData clientData, Tcl_Interp *interp) { struct dbwinterps *dbwinterps = Tcl_GetThreadData(&dbwinTDK, sizeof(struct dbwinterps)); int i; for (i = 0; i < dbwinterps->count; i++) { if (dbwinterps->interps[i] == interp) { for (; i < dbwinterps->count - 1; i++) { dbwinterps->interps[i] = dbwinterps->interps[i + 1]; } dbwinterps->count--; break; } } } void dbwin_add_interp(Tcl_Interp *interp) { struct dbwinterps *dbwinterps = Tcl_GetThreadData(&dbwinTDK, sizeof(struct dbwinterps)); if (dbwinterps->count < DBWIN_MAX_INTERPS) { dbwinterps->interps[dbwinterps->count++] = interp; Tcl_SetAssocData(interp, DBWIN_VAR_NAME, dbwin_forget_interp, NULL); } } void dbwin(char *fmt, ...) { struct dbwinterps *dbwinterps = Tcl_GetThreadData(&dbwinTDK, sizeof(struct dbwinterps)); char buf[512]; va_list args; int i; if (dbwinterps->count <= 0) return; va_start(args, fmt); vsnprintf(buf, 512, fmt, args); va_end(args); buf[511] = '\0'; for (i = 0; i < dbwinterps->count; i++) { /* All sorts of nasty stuff could happen here. */ Tcl_SetVar2(dbwinterps->interps[i], DBWIN_VAR_NAME, NULL, buf, TCL_GLOBAL_ONLY); } } /* * Forward declarations for procedures defined later in this file: */ static int PadAmountOptionSet _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags)); static Tcl_Obj *PadAmountOptionGet _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset)); static void PadAmountOptionRestore _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr)); static void PadAmountOptionFree _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin, char *internalPtr)); /* * The following Tk_ObjCustomOption structure can be used as clientData entry * of a Tk_OptionSpec record with a TK_OPTION_CUSTOM type in the form * "(ClientData) &TreeCtrlCO_pad"; the option will then parse list with * one or two screen distances. */ Tk_ObjCustomOption TreeCtrlCO_pad = { "pad amount", PadAmountOptionSet, PadAmountOptionGet, PadAmountOptionRestore, PadAmountOptionFree }; /* *---------------------------------------------------------------------- * * FormatResult -- * * Set the interpreter's result to a formatted string. * * Results: * None. * * Side effects: * Interpreter's result is modified. * *---------------------------------------------------------------------- */ void FormatResult( Tcl_Interp *interp, /* Current interpreter. */ char *fmt, ... /* Format string and varargs. */ ) { va_list ap; char buf[256]; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); Tcl_SetResult(interp, buf, TCL_VOLATILE); } /* *---------------------------------------------------------------------- * * DStringAppendf -- * * Format a string and append it to a Tcl_DString. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void DStringAppendf( Tcl_DString *dString, /* Initialized dynamic string. */ char *fmt, ... /* Format string and varargs. */ ) { va_list ap; char buf[256]; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); Tcl_DStringAppend(dString, buf, -1); } /* *---------------------------------------------------------------------- * * Tree_Ellipsis -- * * Determine the number of bytes from the string that will fit * in the given horizontal span. If the entire string does not * fit then determine the largest number of bytes of a substring * with an ellipsis "..." appended that will fit. * * Results: * When the return value is equal to numBytes the caller should * not add the ellipsis to the string (unless force is TRUE). In * this case maxPixels contains the number of pixels for the entire * string (plus ellipsis if force is TRUE). * * When the return value is less than numBytes the caller should add * the ellipsis because only a substring fits. In this case * maxPixels contains the number of pixels for the substring * plus ellipsis. The substring has a minimum of one character. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tree_Ellipsis( Tk_Font tkfont, /* The font used to display the string. */ char *string, /* UTF-8 string, need not be NULL-terminated. */ int numBytes, /* Number of bytes to consider. */ int *maxPixels, /* In: maximum line length allowed. * Out: length of string that fits (with * ellipsis added if needed). */ char *ellipsis, /* NULL-terminated "..." */ int force /* TRUE if ellipsis should always be added * even if the whole string fits in * maxPixels. */ ) { char staticStr[256], *tmpStr = staticStr; int pixels, pixelsTest, bytesThatFit, bytesTest; int ellipsisNumBytes = strlen(ellipsis); int bytesInFirstCh; Tcl_UniChar uniCh; bytesThatFit = Tk_MeasureChars(tkfont, string, numBytes, *maxPixels, 0, &pixels); /* The whole string fits. No ellipsis needed (unless forced) */ if ((bytesThatFit == numBytes) && !force) { (*maxPixels) = pixels; return numBytes; } bytesInFirstCh = Tcl_UtfToUniChar(string, &uniCh); if (bytesThatFit <= bytesInFirstCh) { goto singleChar; } /* Strip off one character at a time, adding ellipsis, until it fits */ if (force) bytesTest = bytesThatFit; else bytesTest = Tcl_UtfPrev(string + bytesThatFit, string) - string; if (bytesTest + ellipsisNumBytes > sizeof(staticStr)) tmpStr = ckalloc(bytesTest + ellipsisNumBytes); memcpy(tmpStr, string, bytesTest); while (bytesTest > 0) { memcpy(tmpStr + bytesTest, ellipsis, ellipsisNumBytes); numBytes = Tk_MeasureChars(tkfont, tmpStr, bytesTest + ellipsisNumBytes, *maxPixels, 0, &pixelsTest); if (numBytes == bytesTest + ellipsisNumBytes) { (*maxPixels) = pixelsTest; if (tmpStr != staticStr) ckfree(tmpStr); return bytesTest; } bytesTest = Tcl_UtfPrev(string + bytesTest, string) - string; } singleChar: /* No single char + ellipsis fits. Return the number of bytes for * the first character. The returned pixel width is the width of the * first character plus ellipsis. */ bytesThatFit = bytesInFirstCh; memcpy(tmpStr, string, bytesThatFit); memcpy(tmpStr + bytesThatFit, ellipsis, ellipsisNumBytes); (void) Tk_MeasureChars(tkfont, tmpStr, bytesThatFit + ellipsisNumBytes, -1, 0, &pixels); (*maxPixels) = pixels; if (tmpStr != staticStr) ckfree(tmpStr); return bytesThatFit; } /* *---------------------------------------------------------------------- * * Tree_HDotLine -- * * Draws a horizontal 1-pixel-tall dotted line. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void Tree_HDotLine( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ GC gc, /* Graphics context. */ int x1, int y1, int x2 /* Left, top and right coordinates. */ ) { #ifdef WIN32 TkWinDCState state; HDC dc; HPEN pen, oldPen; int nw; int wx = x1 + tree->drawableXOrigin; int wy = y1 + tree->drawableYOrigin; dc = TkWinGetDrawableDC(tree->display, drawable, &state); SetROP2(dc, R2_COPYPEN); pen = CreatePen(PS_SOLID, 1, gc->foreground); oldPen = SelectObject(dc, pen); nw = !(wx & 1) == !(wy & 1); for (x1 += !nw; x1 < x2; x1 += 2) { MoveToEx(dc, x1, y1, NULL); LineTo(dc, x1 + 1, y1); } SelectObject(dc, oldPen); DeleteObject(pen); TkWinReleaseDrawableDC(drawable, dc, &state); #else int nw; int wx = x1 + tree->drawableXOrigin; int wy = y1 + tree->drawableYOrigin; nw = !(wx & 1) == !(wy & 1); for (x1 += !nw; x1 < x2; x1 += 2) { XDrawPoint(tree->display, drawable, gc, x1, y1); } #endif } /* *---------------------------------------------------------------------- * * Tree_VDotLine -- * * Draws a vertical 1-pixel-wide dotted line. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void Tree_VDotLine( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ GC gc, /* Graphics context. */ int x1, int y1, int y2) /* Left, top, and bottom coordinates. */ { #ifdef WIN32 TkWinDCState state; HDC dc; HPEN pen, oldPen; int nw; int wx = x1 + tree->drawableXOrigin; int wy = y1 + tree->drawableYOrigin; dc = TkWinGetDrawableDC(tree->display, drawable, &state); SetROP2(dc, R2_COPYPEN); pen = CreatePen(PS_SOLID, 1, gc->foreground); oldPen = SelectObject(dc, pen); nw = !(wx & 1) == !(wy & 1); for (y1 += !nw; y1 < y2; y1 += 2) { MoveToEx(dc, x1, y1, NULL); LineTo(dc, x1 + 1, y1); } SelectObject(dc, oldPen); DeleteObject(pen); TkWinReleaseDrawableDC(drawable, dc, &state); #else int nw; int wx = x1 + tree->drawableXOrigin; int wy = y1 + tree->drawableYOrigin; nw = !(wx & 1) == !(wy & 1); for (y1 += !nw; y1 < y2; y1 += 2) { XDrawPoint(tree->display, drawable, gc, x1, y1); } #endif } /* *---------------------------------------------------------------------- * * Tree_DrawActiveOutline -- * * Draws 0 or more sides of a rectangle, dot-on dot-off, XOR style. * This is used by rectangle Elements to indicate the "active" * item. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void Tree_DrawActiveOutline( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ int x, int y, /* Left and top coordinates. */ int width, int height, /* Size of rectangle. */ int open /* Bitmask of edges not to draw: * 0x01: left * 0x02: top * 0x04: right * 0x08: bottom */ ) { #ifdef WIN32 int wx = x + tree->drawableXOrigin; int wy = y + tree->drawableYOrigin; int w = !(open & 0x01); int n = !(open & 0x02); int e = !(open & 0x04); int s = !(open & 0x08); int nw, ne, sw, se; int i; TkWinDCState state; HDC dc; /* Dots on even pixels only */ nw = !(wx & 1) == !(wy & 1); ne = !((wx + width - 1) & 1) == !(wy & 1); sw = !(wx & 1) == !((wy + height - 1) & 1); se = !((wx + width - 1) & 1) == !((wy + height - 1) & 1); dc = TkWinGetDrawableDC(tree->display, drawable, &state); SetROP2(dc, R2_NOT); if (w) /* left */ { for (i = !nw; i < height; i += 2) { MoveToEx(dc, x, y + i, NULL); LineTo(dc, x + 1, y + i); } } if (n) /* top */ { for (i = nw ? w * 2 : 1; i < width; i += 2) { MoveToEx(dc, x + i, y, NULL); LineTo(dc, x + i + 1, y); } } if (e) /* right */ { for (i = ne ? n * 2 : 1; i < height; i += 2) { MoveToEx(dc, x + width - 1, y + i, NULL); LineTo(dc, x + width, y + i); } } if (s) /* bottom */ { for (i = sw ? w * 2 : 1; i < width - (se && e); i += 2) { MoveToEx(dc, x + i, y + height - 1, NULL); LineTo(dc, x + i + 1, y + height - 1); } } TkWinReleaseDrawableDC(drawable, dc, &state); #else /* WIN32 */ int wx = x + tree->drawableXOrigin; int wy = y + tree->drawableYOrigin; int w = !(open & 0x01); int n = !(open & 0x02); int e = !(open & 0x04); int s = !(open & 0x08); int nw, ne, sw, se; int i; XGCValues gcValues; unsigned long gcMask; GC gc; /* Dots on even pixels only */ nw = !(wx & 1) == !(wy & 1); ne = !((wx + width - 1) & 1) == !(wy & 1); sw = !(wx & 1) == !((wy + height - 1) & 1); se = !((wx + width - 1) & 1) == !((wy + height - 1) & 1); #if defined(MAC_TCL) || defined(MAC_OSX_TK) gcValues.function = GXxor; #else gcValues.function = GXinvert; #endif gcMask = GCFunction; gc = Tree_GetGC(tree, gcMask, &gcValues); if (w) /* left */ { for (i = !nw; i < height; i += 2) { XDrawPoint(tree->display, drawable, gc, x, y + i); } } if (n) /* top */ { for (i = nw ? w * 2 : 1; i < width; i += 2) { XDrawPoint(tree->display, drawable, gc, x + i, y); } } if (e) /* right */ { for (i = ne ? n * 2 : 1; i < height; i += 2) { XDrawPoint(tree->display, drawable, gc, x + width - 1, y + i); } } if (s) /* bottom */ { for (i = sw ? w * 2 : 1; i < width - (se && e); i += 2) { XDrawPoint(tree->display, drawable, gc, x + i, y + height - 1); } } #endif } /* * The following structure is used when drawing a number of dotted XOR * rectangles. */ struct DotStatePriv { TreeCtrl *tree; Drawable drawable; #ifdef WIN32 HDC dc; TkWinDCState dcState; HRGN rgn; #elif defined(MAC_OSX_TK) CGrafPtr saveWorld; GDHandle saveDevice; RgnHandle rgn; #else GC gc; TkRegion rgn; #endif }; /* *---------------------------------------------------------------------- * * TreeDotRect_Setup -- * * Prepare a drawable for drawing a series of dotted XOR rectangles. * * Results: * State info is returned to be used by the other TreeDotRect_xxx() * procedures. * * Side effects: * On Win32 and OSX the device context/graphics port is altered * in preparation for drawing. On X11 a new graphics context is * created. * *---------------------------------------------------------------------- */ void TreeDotRect_Setup( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ DotState *p /* Where to save state info. */ ) { struct DotStatePriv *dotState = (struct DotStatePriv *) p; #ifdef WIN32 #elif defined(MAC_OSX_TK) MacDrawable *macWin = (MacDrawable *) drawable; GWorldPtr destPort; Rect bounds; RgnHandle clipRgn; #else XGCValues gcValues; unsigned long mask; XRectangle xrect; #endif if (sizeof(*dotState) > sizeof(*p)) panic("TreeDotRect_Setup: DotState hack is too small"); dotState->tree = tree; dotState->drawable = drawable; #ifdef WIN32 dotState->dc = TkWinGetDrawableDC(tree->display, drawable, &dotState->dcState); /* XOR drawing */ SetROP2(dotState->dc, R2_NOT); /* Keep drawing inside the contentbox. */ dotState->rgn = CreateRectRgn( Tree_ContentLeft(tree), Tree_ContentTop(tree), Tree_ContentRight(tree), Tree_ContentBottom(tree)); SelectClipRgn(dotState->dc, dotState->rgn); #elif defined(MAC_OSX_TK) /* NOTE: OSX doesn't support XOR drawing except in Quickdraw. That is * why the X11 wrapper isn't used here. */ tree->display->request++; destPort = TkMacOSXGetDrawablePort(drawable); GetGWorld(&dotState->saveWorld, &dotState->saveDevice); SetGWorld(destPort, NULL); TkMacOSXSetUpClippingRgn(drawable); /* Save the old clip region. */ #ifdef MAC_OSX_HISHAPE /* NOTE: Tree_GetRegion returns a HIShapeRef which isn't wanted. */ dotState->rgn = NewRgn(); // FIXME: want to cache these regions. #else dotState->rgn = (RgnHandle) Tree_GetRegion(tree); #endif GetClip(dotState->rgn); /* Keep drawing inside the contentbox. */ #ifdef MAC_OSX_HISHAPE clipRgn = NewRgn(); // FIXME: want to cache these regions. #else clipRgn = (RgnHandle) Tree_GetRegion(tree); #endif bounds.left = macWin->xOff + Tree_ContentLeft(tree); bounds.top = macWin->yOff + Tree_ContentTop(tree); bounds.right = bounds.left + Tree_ContentWidth(tree); bounds.bottom = bounds.top + Tree_ContentHeight(tree); RectRgn(clipRgn, &bounds); /* Set the clipping region to the intersection of the two regions. */ SectRgn(dotState->rgn, clipRgn, clipRgn); SetClip(clipRgn); #ifdef MAC_OSX_HISHAPE DisposeRgn(clipRgn); #else Tree_FreeRegion(tree, (TkRegion) clipRgn); #endif PenNormal(); PenMode(patXor); ShowPen(); #else gcValues.line_style = LineOnOffDash; gcValues.line_width = 1; gcValues.dash_offset = 0; gcValues.dashes = 1; #if defined(MAC_TCL) gcValues.function = GXxor; #else gcValues.function = GXinvert; #endif mask = GCLineWidth | GCLineStyle | GCDashList | GCDashOffset | GCFunction; dotState->gc = Tk_GetGC(tree->tkwin, mask, &gcValues); /* Keep drawing inside the contentbox. */ dotState->rgn = Tree_GetRegion(tree); xrect.x = Tree_ContentLeft(tree); xrect.y = Tree_ContentTop(tree); xrect.width = Tree_ContentRight(tree) - xrect.x; xrect.height = Tree_ContentBottom(tree) - xrect.y; TkUnionRectWithRegion(&xrect, dotState->rgn, dotState->rgn); TkSetRegion(tree->display, dotState->gc, dotState->rgn); #endif } /* *---------------------------------------------------------------------- * * TreeDotRect_Draw -- * * Draw a dotted XOR rectangle. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void TreeDotRect_Draw( DotState *p, /* Info returned by TreeDotRect_Setup(). */ int x, int y, /* Left and top coordinates. */ int width, int height /* Size of rectangle. */ ) { struct DotStatePriv *dotState = (struct DotStatePriv *) p; #ifdef WIN32 #if 1 RECT rect; rect.left = x; rect.right = x + width; rect.top = y; rect.bottom = y + height; DrawFocusRect(dotState->dc, &rect); #else HDC dc = dotState->dc; int i; int wx = x + dotState->tree->drawableXOrigin; int wy = y + dotState->tree->drawableYOrigin; int nw, ne, sw, se; /* Dots on even pixels only */ nw = !(wx & 1) == !(wy & 1); ne = !((wx + width - 1) & 1) == !(wy & 1); sw = !(wx & 1) == !((wy + height - 1) & 1); se = !((wx + width - 1) & 1) == !((wy + height - 1) & 1); for (i = !nw; i < height; i += 2) { MoveToEx(dc, x, y + i, NULL); LineTo(dc, x + 1, y + i); } for (i = nw ? 2 : 1; i < width; i += 2) { MoveToEx(dc, x + i, y, NULL); LineTo(dc, x + i + 1, y); } for (i = ne ? 2 : 1; i < height; i += 2) { MoveToEx(dc, x + width - 1, y + i, NULL); LineTo(dc, x + width, y + i); } for (i = sw ? 2 : 1; i < width - se; i += 2) { MoveToEx(dc, x + i, y + height - 1, NULL); LineTo(dc, x + i + 1, y + height - 1); } #endif #elif defined(MAC_OSX_TK) MacDrawable *macWin = (MacDrawable *) dotState->drawable; int i; int wx = x + dotState->tree->drawableXOrigin; int wy = y + dotState->tree->drawableYOrigin; int nw, ne, sw, se; /* Dots on even pixels only */ nw = !(wx & 1) == !(wy & 1); ne = !((wx + width - 1) & 1) == !(wy & 1); sw = !(wx & 1) == !((wy + height - 1) & 1); se = !((wx + width - 1) & 1) == !((wy + height - 1) & 1); x += macWin->xOff; y += macWin->yOff; for (i = !nw; i < height; i += 2) { MoveTo(x, y + i); LineTo(x, y + i); } for (i = nw ? 2 : 1; i < width; i += 2) { MoveTo(x + i, y); LineTo(x + i, y); } for (i = ne ? 2 : 1; i < height; i += 2) { MoveTo(x + width, y + i); LineTo(x + width, y + i); } for (i = sw ? 2 : 1; i < width - se; i += 2) { MoveTo(x + i, y + height - 1); LineTo(x + i, y + height - 1); } #else /* MAC_OSX_TK */ XDrawRectangle(dotState->tree->display, dotState->drawable, dotState->gc, x, y, width - 1, height - 1); #endif } /* *---------------------------------------------------------------------- * * TreeDotRect_Restore -- * * Restore the drawing environment. * * Results: * None. * * Side effects: * On Win32 and OSX the device context/graphics port is restored. * On X11 a new graphics context is freed. * *---------------------------------------------------------------------- */ void TreeDotRect_Restore( DotState *p /* Info returned by TreeDotRect_Setup(). */ ) { struct DotStatePriv *dotState = (struct DotStatePriv *) p; #ifdef WIN32 SelectClipRgn(dotState->dc, NULL); DeleteObject(dotState->rgn); TkWinReleaseDrawableDC(dotState->drawable, dotState->dc, &dotState->dcState); #elif defined(MAC_OSX_TK) HidePen(); SetClip(dotState->rgn); #ifdef MAC_OSX_HISHAPE DisposeRgn(dotState->rgn); #else Tree_FreeRegion(dotState->tree, (TkRegion) dotState->rgn); #endif SetGWorld(dotState->saveWorld, dotState->saveDevice); #else XSetClipMask(dotState->tree->display, dotState->gc, None); Tree_FreeRegion(dotState->tree, dotState->rgn); Tk_FreeGC(dotState->tree->display, dotState->gc); #endif } #ifdef MAC_OSX_TK /* *---------------------------------------------------------------------- * * DrawXORLine -- * * Draw a 1-pixel thick XOR line (not dotted). This is used * to draw the vertical column proxy when resizing columns. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void DrawXORLine( Display *display, /* Display. */ Drawable drawable, /* Where to draw. */ int x1, int y1, /* Left, top. */ int x2, int y2 /* Bottom, right. */ ) { MacDrawable *macWin = (MacDrawable *) drawable; CGrafPtr saveWorld; GDHandle saveDevice; GWorldPtr destPort; destPort = TkMacOSXGetDrawablePort(drawable); display->request++; GetGWorld(&saveWorld, &saveDevice); SetGWorld(destPort, NULL); TkMacOSXSetUpClippingRgn(drawable); #if 1 PenNormal(); #else TkMacOSXSetUpGraphicsPort(gc, destPort); #endif PenMode(patXor); ShowPen(); MoveTo(macWin->xOff + x1, macWin->yOff + y1); LineTo(macWin->xOff + x2, macWin->yOff + y2); HidePen(); SetGWorld(saveWorld, saveDevice); } #endif /* MAC_OSX_TK */ /* *---------------------------------------------------------------------- * * Tree_GetRegion -- * * Return a pre-allocated TkRegion or create a new one. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ TkRegion Tree_GetRegion( TreeCtrl *tree /* Widget info. */ ) { TkRegion region; if (tree->regionStackLen == 0) { return TkCreateRegion(); } region = tree->regionStack[--tree->regionStackLen]; TkSubtractRegion(region, region, region); return region; } /* *---------------------------------------------------------------------- * * Tree_FreeRegion -- * * Push a region onto the free stack. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tree_FreeRegion( TreeCtrl *tree, /* Widget info. */ TkRegion region /* Region being released. */ ) { if (tree->regionStackLen == sizeof(tree->regionStack) / sizeof(TkRegion)) panic("Tree_FreeRegion: the stack is full"); tree->regionStack[tree->regionStackLen++] = region; } /* *---------------------------------------------------------------------- * * Tree_FillRegion -- * * Paint a region with the foreground color of a graphics context. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void Tree_FillRegion( Display *display, /* Display. */ Drawable drawable, /* Where to draw. */ GC gc, /* Foreground color. */ TkRegion rgn /* Region to paint. */ ) { #ifdef WIN32 HDC dc; TkWinDCState dcState; HBRUSH brush; dc = TkWinGetDrawableDC(display, drawable, &dcState); SetROP2(dc, R2_COPYPEN); brush = CreateSolidBrush(gc->foreground); FillRgn(dc, (HRGN) rgn, brush); DeleteObject(brush); TkWinReleaseDrawableDC(drawable, dc, &dcState); #elif defined(MAC_OSX_TK) && (TK_MINOR_VERSION == 4) && (TK_RELEASE_SERIAL < 15) /* Not needed as of 8.4.15 / 8.5a7 */ MacDrawable *macWin = (MacDrawable *) drawable; CGrafPtr saveWorld; GDHandle saveDevice; GWorldPtr destPort; RGBColor macColor; destPort = TkMacOSXGetDrawablePort(drawable); if (gPenPat == NULL) gPenPat = NewPixPat(); if (TkSetMacColor(gc->foreground, &macColor) == true) MakeRGBPat(gPenPat, &macColor); display->request++; GetGWorld(&saveWorld, &saveDevice); SetGWorld(destPort, NULL); TkMacOSXSetUpClippingRgn(drawable); TkMacOSXSetUpGraphicsPort(gc, destPort); OffsetRgn((RgnHandle) rgn, macWin->xOff, macWin->yOff); ShowPen(); /* seemed to work without this */ FillCRgn((RgnHandle) rgn, gPenPat); HidePen(); /* seemed to work without this */ OffsetRgn((RgnHandle) rgn, -macWin->xOff, -macWin->yOff); SetGWorld(saveWorld, saveDevice); #else XRectangle box; TkClipBox(rgn, &box); TkSetRegion(display, gc, rgn); XFillRectangle(display, drawable, gc, box.x, box.y, box.width, box.height); XSetClipMask(display, gc, None); #endif } /* *---------------------------------------------------------------------- * * Tree_OffsetRegion -- * * Offset a region. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tree_OffsetRegion( TkRegion region, /* Region to modify. */ int xOffset, int yOffset /* Horizontal and vertical offsets. */ ) { #ifdef WIN32 OffsetRgn((HRGN) region, xOffset, yOffset); #elif defined(MAC_OSX_HISHAPE) HIShapeOffset((HIMutableShapeRef) region, xOffset, yOffset); #elif defined(MAC_TCL) || defined(MAC_OSX_TK) OffsetRgn((RgnHandle) region, (short) xOffset, (short) yOffset); #else XOffsetRegion((Region) region, xOffset, yOffset); #endif } /* *---------------------------------------------------------------------- * * Tree_ScrollWindow -- * * Wrapper around TkScrollWindow() to fix an apparent bug with the * Mac/OSX versions. * * Results: * None. * * Side effects: * Stuff is scrolled in a drawable. * *---------------------------------------------------------------------- */ int Tree_ScrollWindow( TreeCtrl *tree, /* Widget info. */ GC gc, /* Arg to TkScrollWindow(). */ int x, int y, /* Arg to TkScrollWindow(). */ int width, int height, /* Arg to TkScrollWindow(). */ int dx, int dy, /* Arg to TkScrollWindow(). */ TkRegion damageRgn /* Arg to TkScrollWindow(). */ ) { #ifdef WIN32xxx /* It would be best to call ScrollWindowEx with SW_SCROLLCHILDREN so * that windows in window elements scroll smoothly with a minimum of * redrawing. */ HWND hwnd = TkWinGetHWND(Tk_WindowId(tree->tkwin)); HWND hwndChild; RECT scrollRect, childRect; struct { int x; int y; TkWindow *winPtr; } winInfo[128], *winInfoPtr; TkWindow *winPtr = (TkWindow *) tree->tkwin; int winCount = 0; int result; winInfoPtr = winInfo; for (winPtr = winPtr->childList; winPtr != NULL; winPtr = winPtr->nextPtr) { if (winPtr->window != None) { hwndChild = TkWinGetHWND(winPtr->window); GetWindowRect(hwndChild, &childRect); winInfoPtr->x = childRect.left; winInfoPtr->y = childRect.top; winInfoPtr->winPtr = winPtr; winInfoPtr++; winCount++; } } scrollRect.left = x; scrollRect.top = y; scrollRect.right = x + width; scrollRect.bottom = y + height; result = (ScrollWindowEx(hwnd, dx, dy, &scrollRect, NULL, (HRGN) damageRgn, NULL, SW_SCROLLCHILDREN) == NULLREGION) ? 0 : 1; winInfoPtr = winInfo; while (winCount--) { winPtr = winInfoPtr->winPtr; hwndChild = TkWinGetHWND(winPtr->window); GetWindowRect(hwndChild, &childRect); if (childRect.left != winInfoPtr->x || childRect.top != winInfoPtr->y) { dbwin("moved window %s %d,%d\n", winPtr->pathName, childRect.left - winInfoPtr->x, childRect.top - winInfoPtr->y); winPtr->changes.x += childRect.left - winInfoPtr->x; winPtr->changes.y += childRect.top - winInfoPtr->y; /* TkDoConfigureNotify(winPtr); */ } winInfoPtr++; } #else /* WIN32 */ int result = TkScrollWindow(tree->tkwin, gc, x, y, width, height, dx, dy, damageRgn); #endif /* WIN32 */ #if defined(MAC_TCL) || defined(MAC_OSX_TK) { MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tree->tkwin); /* BUG IN TK? */ Tree_OffsetRegion(damageRgn, -macWin->xOff, -macWin->yOff); } #endif return result; } /* *---------------------------------------------------------------------- * * Tree_UnsetClipMask -- * * Wrapper around XSetClipMask(). On Win32 Tk_DrawChars() does * not clear the clipping region. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tree_UnsetClipMask( TreeCtrl *tree, /* Widget info. */ Drawable drawable, /* Where to draw. */ GC gc /* Graphics context to modify. */ ) { XSetClipMask(tree->display, gc, None); #ifdef WIN32 /* Tk_DrawChars does not clear the clip region */ if (drawable == Tk_WindowId(tree->tkwin)) { HDC dc; TkWinDCState dcState; dc = TkWinGetDrawableDC(tree->display, drawable, &dcState); SelectClipRgn(dc, NULL); TkWinReleaseDrawableDC(drawable, dc, &dcState); } #endif } /* *---------------------------------------------------------------------- * * Tree_RedrawImage -- * * Wrapper around Tk_RedrawImage to clip the drawing to the actual * area of the drawable. If you try to draw a transparent photo * image outside the bounds of a drawable, X11 will silently fail * and nothing will be drawn. See tkImgPhoto.c:ImgPhotoDisplay. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void Tree_RedrawImage( Tk_Image image, int imageX, int imageY, int width, int height, TreeDrawable td, int drawableX, int drawableY ) { #if 0 int ix = imageX, iy = imageY, iw = width, ih = height; #endif if (drawableX < 0) { imageX = 0 - drawableX; width -= imageX; drawableX = 0; } if (drawableX + width > td.width) { width -= (drawableX + width) - td.width; } if (drawableY < 0) { imageY = 0 - drawableY; height -= imageY; drawableY = 0; } if (drawableY + height > td.height) { height -= (drawableY + height) - td.height; } #if 0 if (ix != imageX || iy != imageY || iw != width || ih != height) dbwin("Tree_RedrawImage clipped %d,%d,%d,%d -> %d,%d,%d,%d\n", ix,iy,iw,ih, imageX, imageY, width, height); #endif if (width > 0 && height > 0) { Tk_RedrawImage(image, imageX, imageY, width, height, td.drawable, drawableX, drawableY); } } /* *---------------------------------------------------------------------- * * Tree_DrawBitmapWithGC -- * * Draw part of a bitmap. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void Tree_DrawBitmapWithGC( TreeCtrl *tree, /* Widget info. */ Pixmap bitmap, /* Bitmap to draw. */ Drawable drawable, /* Where to draw. */ GC gc, /* Graphics context. */ int src_x, int src_y, /* Left and top of part of bitmap to copy. */ int width, int height, /* Width and height of part of bitmap to * copy. */ int dest_x, int dest_y /* Left and top coordinates to copy part of * the bitmap to. */ ) { #ifdef WIN32 TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask; #endif XSetClipOrigin(tree->display, gc, dest_x, dest_y); #ifdef WIN32 /* * It seems as though the device context is not set up properly * when drawing a transparent bitmap into a window. Normally Tk draws * into an offscreen pixmap which gets a temporary device context. * This fixes a bug with -doublebuffer none in the demo "Bitmaps". */ if (drawable == Tk_WindowId(tree->tkwin)) { if ((clipPtr != NULL) && (clipPtr->type == TKP_CLIP_PIXMAP) && (clipPtr->value.pixmap == bitmap)) { HDC dc; TkWinDCState dcState; dc = TkWinGetDrawableDC(tree->display, drawable, &dcState); SetTextColor(dc, RGB(0,0,0)); SetBkColor(dc, RGB(255,255,255)); TkWinReleaseDrawableDC(drawable, dc, &dcState); } } #endif XCopyPlane(tree->display, bitmap, drawable, gc, src_x, src_y, (unsigned int) width, (unsigned int) height, dest_x, dest_y, 1); XSetClipOrigin(tree->display, gc, 0, 0); } /* *---------------------------------------------------------------------- * * Tree_DrawBitmap -- * * Draw part of a bitmap. * * Results: * None. * * Side effects: * Stuff is drawn. * *---------------------------------------------------------------------- */ void Tree_DrawBitmap( TreeCtrl *tree, /* Widget info. */ Pixmap bitmap, /* Bitmap to draw. */ Drawable drawable, /* Where to draw. */ XColor *fg, XColor *bg, /* Foreground and background colors. * May be NULL. */ int src_x, int src_y, /* Left and top of part of bitmap to copy. */ int width, int height, /* Width and height of part of bitmap to * copy. */ int dest_x, int dest_y /* Left and top coordinates to copy part of * the bitmap to. */ ) { XGCValues gcValues; GC gc; unsigned long mask = 0; if (fg != NULL) { gcValues.foreground = fg->pixel; mask |= GCForeground; } if (bg != NULL) { gcValues.background = bg->pixel; mask |= GCBackground; } else { gcValues.clip_mask = bitmap; mask |= GCClipMask; } gcValues.graphics_exposures = False; mask |= GCGraphicsExposures; gc = Tk_GetGC(tree->tkwin, mask, &gcValues); Tree_DrawBitmapWithGC(tree, bitmap, drawable, gc, src_x, src_y, width, height, dest_x, dest_y); Tk_FreeGC(tree->display, gc); } /* * TIP #116 altered Tk_PhotoPutBlock API to add interp arg. * We need to remove that for compiling with 8.4. */ #if (TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION < 5) #define TK_PHOTOPUTBLOCK(interp, hdl, blk, x, y, w, h, cr) \ Tk_PhotoPutBlock(hdl, blk, x, y, w, h, cr) #define TK_PHOTOPUTZOOMEDBLOCK(interp, hdl, blk, x, y, w, h, \ zx, zy, sx, sy, cr) \ Tk_PhotoPutZoomedBlock(hdl, blk, x, y, w, h, \ zx, zy, sx, sy, cr) #else #define TK_PHOTOPUTBLOCK Tk_PhotoPutBlock #define TK_PHOTOPUTZOOMEDBLOCK Tk_PhotoPutZoomedBlock #endif /* *---------------------------------------------------------------------- * * Tree_XImage2Photo -- * * Copy pixels from an XImage to a Tk photo image. * * Results: * None. * * Side effects: * The given photo image is blanked and all the pixels from the * XImage are put into the photo image. * *---------------------------------------------------------------------- */ #if defined(WIN32) || defined(MAC_TCL) || defined(MAC_OSX_TK) void Tree_XImage2Photo( Tcl_Interp *interp, /* Current interpreter. */ Tk_PhotoHandle photoH, /* Existing photo image. */ XImage *ximage, /* XImage to copy pixels from. */ int alpha /* Desired transparency of photo image.*/ ) { Tk_PhotoImageBlock photoBlock; unsigned char *pixelPtr; int x, y, w = ximage->width, h = ximage->height; #if defined(MAC_TCL) || defined(MAC_OSX_TK) unsigned long red_shift, green_shift, blue_shift; #endif Tk_PhotoBlank(photoH); /* See TkPoscriptImage */ #if defined(MAC_TCL) || defined(MAC_OSX_TK) red_shift = green_shift = blue_shift = 0; while ((0x0001 & (ximage->red_mask >> red_shift)) == 0) red_shift++; while ((0x0001 & (ximage->green_mask >> green_shift)) == 0) green_shift++; while ((0x0001 & (ximage->blue_mask >> blue_shift)) == 0) blue_shift++; #endif pixelPtr = (unsigned char *) Tcl_Alloc(ximage->width * ximage->height * 4); photoBlock.pixelPtr = pixelPtr; photoBlock.width = ximage->width; photoBlock.height = ximage->height; photoBlock.pitch = ximage->width * 4; photoBlock.pixelSize = 4; photoBlock.offset[0] = 0; photoBlock.offset[1] = 1; photoBlock.offset[2] = 2; photoBlock.offset[3] = 3; for (y = 0; y < ximage->height; y++) { for (x = 0; x < ximage->width; x++) { int r, g, b; unsigned long pixel; /* FIXME: I think this blows up on classic Mac??? */ pixel = XGetPixel(ximage, x, y); #ifdef WIN32 r = GetRValue(pixel); g = GetGValue(pixel); b = GetBValue(pixel); #endif #if defined(MAC_TCL) || defined(MAC_OSX_TK) r = (pixel & ximage->red_mask) >> red_shift; g = (pixel & ximage->green_mask) >> green_shift; b = (pixel & ximage->blue_mask) >> blue_shift; #endif pixelPtr[y * photoBlock.pitch + x * 4 + 0] = r; pixelPtr[y * photoBlock.pitch + x * 4 + 1] = g; pixelPtr[y * photoBlock.pitch + x * 4 + 2] = b; pixelPtr[y * photoBlock.pitch + x * 4 + 3] = alpha; } } TK_PHOTOPUTBLOCK(interp, photoH, &photoBlock, 0, 0, w, h, TK_PHOTO_COMPOSITE_SET); Tcl_Free((char *) pixelPtr); } #else /* not X11 */ void Tree_XImage2Photo( Tcl_Interp *interp, /* Current interpreter. */ Tk_PhotoHandle photoH, /* Existing photo image. */ XImage *ximage, /* XImage to copy pixels from. */ int alpha /* Desired transparency of photo image.*/ ) { Tk_Window tkwin = Tk_MainWindow(interp); Display *display = Tk_Display(tkwin); Visual *visual = Tk_Visual(tkwin); Tk_PhotoImageBlock photoBlock; unsigned char *pixelPtr; int x, y, w = ximage->width, h = ximage->height; int i, ncolors; XColor *xcolors; unsigned long red_shift, green_shift, blue_shift; int separated = 0; Tk_PhotoBlank(photoH); /* See TkPoscriptImage */ ncolors = visual->map_entries; xcolors = (XColor *) ckalloc(sizeof(XColor) * ncolors); if ((visual->class == DirectColor) || (visual->class == TrueColor)) { separated = 1; red_shift = green_shift = blue_shift = 0; /* ximage->red_mask etc are zero */ while ((0x0001 & (visual->red_mask >> red_shift)) == 0) red_shift++; while ((0x0001 & (visual->green_mask >> green_shift)) == 0) green_shift++; while ((0x0001 & (visual->blue_mask >> blue_shift)) == 0) blue_shift++; for (i = 0; i < ncolors; i++) { xcolors[i].pixel = ((i << red_shift) & visual->red_mask) | ((i << green_shift) & visual->green_mask) | ((i << blue_shift) & visual->blue_mask); } } else { red_shift = green_shift = blue_shift = 0; for (i = 0; i < ncolors; i++) xcolors[i].pixel = i; } XQueryColors(display, Tk_Colormap(tkwin), xcolors, ncolors); pixelPtr = (unsigned char *) Tcl_Alloc(ximage->width * ximage->height * 4); photoBlock.pixelPtr = pixelPtr; photoBlock.width = ximage->width; photoBlock.height = ximage->height; photoBlock.pitch = ximage->width * 4; photoBlock.pixelSize = 4; photoBlock.offset[0] = 0; photoBlock.offset[1] = 1; photoBlock.offset[2] = 2; photoBlock.offset[3] = 3; for (y = 0; y < ximage->height; y++) { for (x = 0; x < ximage->width; x++) { int r, g, b; unsigned long pixel; pixel = XGetPixel(ximage, x, y); if (separated) { r = (pixel & visual->red_mask) >> red_shift; g = (pixel & visual->green_mask) >> green_shift; b = (pixel & visual->blue_mask) >> blue_shift; r = ((double) xcolors[r].red / USHRT_MAX) * 255; g = ((double) xcolors[g].green / USHRT_MAX) * 255; b = ((double) xcolors[b].blue / USHRT_MAX) * 255; } else { r = ((double) xcolors[pixel].red / USHRT_MAX) * 255; g = ((double) xcolors[pixel].green / USHRT_MAX) * 255; b = ((double) xcolors[pixel].blue / USHRT_MAX) * 255; } pixelPtr[y * photoBlock.pitch + x * 4 + 0] = r; pixelPtr[y * photoBlock.pitch + x * 4 + 1] = g; pixelPtr[y * photoBlock.pitch + x * 4 + 2] = b; pixelPtr[y * photoBlock.pitch + x * 4 + 3] = alpha; } } TK_PHOTOPUTBLOCK(interp, photoH, &photoBlock, 0, 0, w, h, TK_PHOTO_COMPOSITE_SET); Tcl_Free((char *) pixelPtr); ckfree((char *) xcolors); } #endif /* X11 */ /* * Replacement for Tk_TextLayout stuff. Allows the caller to break lines * on character boundaries (as well as word boundaries). Allows the caller * to specify the maximum number of lines to display. Will add ellipsis "..." * to the end of text that is too long to fit (when max lines specified). */ #define TEXTLAYOUT_ELLIPSIS typedef struct LayoutChunk { CONST char *start; /* Pointer to simple string to be displayed. * * This is a pointer into the TkTextLayout's * * string. */ int numBytes; /* The number of bytes in this chunk. */ int numChars; /* The number of characters in this chunk. */ int numDisplayChars; /* The number of characters to display when * * this chunk is displayed. Can be less than * * numChars if extra space characters were * * absorbed by the end of the chunk. This * * will be < 0 if this is a chunk that is * * holding a tab or newline. */ int x, y; /* The origin of the first character in this * * chunk with respect to the upper-left hand * * corner of the TextLayout. */ int totalWidth; /* Width in pixels of this chunk. Used * * when hit testing the invisible spaces at * * the end of a chunk. */ int displayWidth; /* Width in pixels of the displayable * * characters in this chunk. Can be less than * * width if extra space characters were * * absorbed by the end of the chunk. */ #ifdef TEXTLAYOUT_ELLIPSIS int ellipsis; /* TRUE if adding "..." */ #endif } LayoutChunk; typedef struct LayoutInfo { Tk_Font tkfont; /* The font used when laying out the text. */ CONST char *string; /* The string that was layed out. */ int numLines; /* Number of lines */ int width; /* The maximum width of all lines in the * * text layout. */ int height; int numChunks; /* Number of chunks actually used in * * following array. */ int totalWidth; #define TEXTLAYOUT_ALLOCHAX #ifdef TEXTLAYOUT_ALLOCHAX int maxChunks; struct LayoutInfo *nextFree; #endif LayoutChunk chunks[1]; /* Array of chunks. The actual size will * * be maxChunks. THIS FIELD MUST BE THE LAST * * IN THE STRUCTURE. */ } LayoutInfo; #ifdef TEXTLAYOUT_ALLOCHAX TCL_DECLARE_MUTEX(textLayoutMutex) /* FIXME: memory leak, list is never freed. */ static LayoutInfo *freeLayoutInfo = NULL; #endif #ifdef TEXTLAYOUT_ALLOCHAX static LayoutChunk *NewChunk(LayoutInfo **layoutPtrPtr, #else static LayoutChunk *NewChunk(LayoutInfo **layoutPtrPtr, int *maxPtr, #endif CONST char *start, int numBytes, int curX, int newX, int y) { LayoutInfo *layoutPtr; LayoutChunk *chunkPtr; #ifdef TEXTLAYOUT_ALLOCHAX int numChars; #else int maxChunks, numChars; #endif size_t s; layoutPtr = *layoutPtrPtr; #ifdef TEXTLAYOUT_ALLOCHAX if (layoutPtr->numChunks == layoutPtr->maxChunks) { layoutPtr->maxChunks *= 2; s = sizeof(LayoutInfo) + ((layoutPtr->maxChunks - 1) * sizeof(LayoutChunk)); layoutPtr = (LayoutInfo *) ckrealloc((char *) layoutPtr, s); *layoutPtrPtr = layoutPtr; } #else maxChunks = *maxPtr; if (layoutPtr->numChunks == maxChunks) { maxChunks *= 2; s = sizeof(LayoutInfo) + ((maxChunks - 1) * sizeof(LayoutChunk)); layoutPtr = (LayoutInfo *) ckrealloc((char *) layoutPtr, s); *layoutPtrPtr = layoutPtr; *maxPtr = maxChunks; } #endif numChars = Tcl_NumUtfChars(start, numBytes); chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks]; chunkPtr->start = start; chunkPtr->numBytes = numBytes; chunkPtr->numChars = numChars; chunkPtr->numDisplayChars = numChars; chunkPtr->x = curX; chunkPtr->y = y; chunkPtr->totalWidth = newX - curX; chunkPtr->displayWidth = newX - curX; chunkPtr->ellipsis = FALSE; layoutPtr->numChunks++; return chunkPtr; } TextLayout TextLayout_Compute( Tk_Font tkfont, /* Font that will be used to display text. */ CONST char *string, /* String whose dimensions are to be ** computed. */ int numChars, /* Number of characters to consider from ** string, or < 0 for strlen(). */ int wrapLength, /* Longest permissible line length, in ** pixels. <= 0 means no automatic wrapping: ** just let lines get as long as needed. */ Tk_Justify justify, /* How to justify lines. */ int maxLines, int flags /* Flag bits OR-ed together. ** TK_IGNORE_TABS means that tab characters ** should not be expanded. TK_IGNORE_NEWLINES ** means that newline characters should not ** cause a line break. */ ) { CONST char *start, *end, *special; int n, y, bytesThisChunk, maxChunks; int baseline, height, curX, newX, maxWidth; LayoutInfo *layoutPtr; LayoutChunk *chunkPtr; Tk_FontMetrics fm; Tcl_DString lineBuffer; int *lineLengths; int curLine; int tabWidth = 20; /* FIXME */ Tcl_DStringInit(&lineBuffer); Tk_GetFontMetrics(tkfont, &fm); height = fm.ascent + fm.descent; if (numChars < 0) numChars = Tcl_NumUtfChars(string, -1); if (wrapLength == 0) wrapLength = -1; #ifdef TEXTLAYOUT_ALLOCHAX Tcl_MutexLock(&textLayoutMutex); if (freeLayoutInfo != NULL) { layoutPtr = freeLayoutInfo; freeLayoutInfo = layoutPtr->nextFree; } else { maxChunks = 1; layoutPtr = (LayoutInfo *) ckalloc(sizeof(LayoutInfo) + (maxChunks - 1) * sizeof(LayoutChunk)); layoutPtr->maxChunks = maxChunks; } Tcl_MutexUnlock(&textLayoutMutex); #else maxChunks = 1; layoutPtr = (LayoutInfo *) ckalloc(sizeof(LayoutInfo) + (maxChunks - 1) * sizeof(LayoutChunk)); #endif layoutPtr->tkfont = tkfont; layoutPtr->string = string; layoutPtr->numChunks = 0; layoutPtr->numLines = 0; baseline = fm.ascent; maxWidth = 0; curX = 0; end = Tcl_UtfAtIndex(string, numChars); special = string; flags &= TK_WHOLE_WORDS | TK_IGNORE_TABS | TK_IGNORE_NEWLINES; flags |= TK_AT_LEAST_ONE; for (start = string; start < end;) { if (start >= special) { for (special = start; special < end; special++) { if (!(flags & TK_IGNORE_NEWLINES)) { if ((*special == '\n') || (*special == '\r')) break; } if (!(flags & TK_IGNORE_TABS)) { if (*special == '\t') break; } } } chunkPtr = NULL; if (start < special) { bytesThisChunk = Tk_MeasureChars(tkfont, start, special - start, wrapLength - curX, flags, &newX); newX += curX; flags &= ~TK_AT_LEAST_ONE; if (bytesThisChunk > 0) { #ifdef TEXTLAYOUT_ALLOCHAX chunkPtr = NewChunk(&layoutPtr, start, #else chunkPtr = NewChunk(&layoutPtr, &maxChunks, start, #endif bytesThisChunk, curX, newX, baseline); start += bytesThisChunk; curX = newX; } } if ((start == special) && (special < end)) { chunkPtr = NULL; if (*special == '\t') { newX = curX + tabWidth; newX -= newX % tabWidth; #ifdef TEXTLAYOUT_ALLOCHAX NewChunk(&layoutPtr, start, 1, curX, newX, #else NewChunk(&layoutPtr, &maxChunks, start, 1, curX, newX, #endif baseline)->numDisplayChars = -1; start++; if ((start < end) && ((wrapLength <= 0) || (newX <= wrapLength))) { curX = newX; flags &= ~TK_AT_LEAST_ONE; continue; } } else { #ifdef TEXTLAYOUT_ALLOCHAX NewChunk(&layoutPtr, start, 1, curX, curX, #else NewChunk(&layoutPtr, &maxChunks, start, 1, curX, curX, #endif baseline)->numDisplayChars = -1; start++; goto wrapLine; } } while ((start < end) && isspace(UCHAR(*start))) { if (!(flags & TK_IGNORE_NEWLINES)) { if ((*start == '\n') || (*start == '\r')) break; } if (!(flags & TK_IGNORE_TABS)) { if (*start == '\t') break; } start++; } if (chunkPtr != NULL) { CONST char *end; end = chunkPtr->start + chunkPtr->numBytes; bytesThisChunk = start - end; if (bytesThisChunk > 0) { bytesThisChunk = Tk_MeasureChars(tkfont, end, bytesThisChunk, -1, 0, &chunkPtr->totalWidth); chunkPtr->numBytes += bytesThisChunk; chunkPtr->numChars += Tcl_NumUtfChars(end, bytesThisChunk); chunkPtr->totalWidth += curX; } } wrapLine: flags |= TK_AT_LEAST_ONE; if (curX > maxWidth) maxWidth = curX; Tcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX)); curX = 0; baseline += height; layoutPtr->numLines++; if ((maxLines > 0) && (layoutPtr->numLines >= maxLines)) break; } if (start >= end) if ((layoutPtr->numChunks > 0) && !(flags & TK_IGNORE_NEWLINES)) { if (layoutPtr->chunks[layoutPtr->numChunks - 1].start[0] == '\n') { chunkPtr = #ifdef TEXTLAYOUT_ALLOCHAX NewChunk(&layoutPtr, start, 0, curX, curX, #else NewChunk(&layoutPtr, &maxChunks, start, 0, curX, curX, #endif baseline); chunkPtr->numDisplayChars = -1; Tcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX)); baseline += height; } } #ifdef TEXTLAYOUT_ELLIPSIS /* Fiddle with chunks on the last line to add ellipsis if there is some * text remaining */ if ((start < end) && (layoutPtr->numChunks > 0)) { char *ellipsis = "..."; int ellipsisLen = strlen(ellipsis); char staticStr[256], *buf = staticStr; int pixelsForText; chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks - 1]; if (wrapLength > 0) { y = chunkPtr->y; for (n = layoutPtr->numChunks - 1; n >= 0; n--) { chunkPtr = &layoutPtr->chunks[n]; /* Only consider the last line */ if (chunkPtr->y != y) break; if (chunkPtr->start[0] == '\n') continue; if (chunkPtr->x + chunkPtr->totalWidth < wrapLength) pixelsForText = wrapLength - chunkPtr->x; else pixelsForText = chunkPtr->totalWidth - 1; bytesThisChunk = Tree_Ellipsis(tkfont, (char *) chunkPtr->start, chunkPtr->numBytes, &pixelsForText, ellipsis, TRUE); if (pixelsForText > wrapLength - chunkPtr->x) pixelsForText = wrapLength - chunkPtr->x; if (bytesThisChunk > 0) { chunkPtr->numBytes = bytesThisChunk; chunkPtr->numChars = Tcl_NumUtfChars(chunkPtr->start, bytesThisChunk); chunkPtr->numDisplayChars = chunkPtr->numChars; chunkPtr->ellipsis = TRUE; chunkPtr->displayWidth = pixelsForText; chunkPtr->totalWidth = pixelsForText; lineLengths = (int *) Tcl_DStringValue(&lineBuffer); lineLengths[layoutPtr->numLines - 1] = chunkPtr->x + pixelsForText; if (chunkPtr->x + pixelsForText > maxWidth) maxWidth = chunkPtr->x + pixelsForText; break; } } } else { if (chunkPtr->start[0] == '\n') { if (layoutPtr->numChunks == 1) goto finish; if (layoutPtr->chunks[layoutPtr->numChunks - 2].y != chunkPtr->y) goto finish; chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks - 2]; } if (chunkPtr->numBytes + ellipsisLen > sizeof(staticStr)) buf = ckalloc(chunkPtr->numBytes + ellipsisLen); memcpy(buf, chunkPtr->start, chunkPtr->numBytes); memcpy(buf + chunkPtr->numBytes, ellipsis, ellipsisLen); Tk_MeasureChars(tkfont, buf, chunkPtr->numBytes + ellipsisLen, -1, 0, &chunkPtr->displayWidth); chunkPtr->totalWidth = chunkPtr->displayWidth; chunkPtr->ellipsis = TRUE; lineLengths = (int *) Tcl_DStringValue(&lineBuffer); lineLengths[layoutPtr->numLines - 1] = chunkPtr->x + chunkPtr->displayWidth; if (chunkPtr->x + chunkPtr->displayWidth > maxWidth) maxWidth = chunkPtr->x + chunkPtr->displayWidth; if (buf != staticStr) ckfree(buf); } } finish: #endif layoutPtr->width = maxWidth; layoutPtr->height = baseline - fm.ascent; layoutPtr->totalWidth = 0; if (layoutPtr->numChunks == 0) { layoutPtr->height = height; layoutPtr->numChunks = 1; layoutPtr->chunks[0].start = string; layoutPtr->chunks[0].numBytes = 0; layoutPtr->chunks[0].numChars = 0; layoutPtr->chunks[0].numDisplayChars = -1; layoutPtr->chunks[0].x = 0; layoutPtr->chunks[0].y = fm.ascent; layoutPtr->chunks[0].totalWidth = 0; layoutPtr->chunks[0].displayWidth = 0; } else { curLine = 0; chunkPtr = layoutPtr->chunks; y = chunkPtr->y; lineLengths = (int *) Tcl_DStringValue(&lineBuffer); for (n = 0; n < layoutPtr->numChunks; n++) { int extra; if (chunkPtr->y != y) { curLine++; y = chunkPtr->y; } extra = maxWidth - lineLengths[curLine]; if (justify == TK_JUSTIFY_CENTER) { chunkPtr->x += extra / 2; } else if (justify == TK_JUSTIFY_RIGHT) { chunkPtr->x += extra; } if (chunkPtr->x + chunkPtr->totalWidth > layoutPtr->totalWidth) layoutPtr->totalWidth = chunkPtr->x + chunkPtr->totalWidth; chunkPtr++; } /* dbwin("totalWidth %d displayWidth %d\n", layoutPtr->totalWidth, maxWidth); */ Tcl_DStringFree(&lineBuffer); } /* We don't want single-line text layouts for text elements, but it happens for column titles */ /* if (layoutPtr->numLines == 1) dbwin("WARNING: single-line TextLayout created\n"); */ return (TextLayout) layoutPtr; } void TextLayout_Free(TextLayout textLayout) { LayoutInfo *layoutPtr = (LayoutInfo *) textLayout; #ifdef TEXTLAYOUT_ALLOCHAX Tcl_MutexLock(&textLayoutMutex); layoutPtr->nextFree = freeLayoutInfo; freeLayoutInfo = layoutPtr; Tcl_MutexUnlock(&textLayoutMutex); #else ckfree((char *) layoutPtr); #endif } void TextLayout_Size(TextLayout textLayout, int *widthPtr, int *heightPtr) { LayoutInfo *layoutPtr = (LayoutInfo *) textLayout; if (widthPtr != NULL) (*widthPtr) = layoutPtr->width; if (heightPtr != NULL) (*heightPtr) = layoutPtr->height; } int TextLayout_TotalWidth(TextLayout textLayout) { LayoutInfo *layoutPtr = (LayoutInfo *) textLayout; return layoutPtr->totalWidth; } void TextLayout_Draw( Display *display, /* Display on which to draw. */ Drawable drawable, /* Window or pixmap in which to draw. */ GC gc, /* Graphics context to use for drawing text. */ TextLayout layout, /* Layout information, from a previous call * * to Tk_ComputeTextLayout(). */ int x, int y, /* Upper-left hand corner of rectangle in * * which to draw (pixels). */ int firstChar, /* The index of the first character to draw * * from the given text item. 0 specfies the * * beginning. */ int lastChar, /* The index just after the last character * * to draw from the given text item. A number * * < 0 means to draw all characters. */ int underline /* Character index to underline, or < 0 for * no underline. */ ) { LayoutInfo *layoutPtr = (LayoutInfo *) layout; int i, numDisplayChars, drawX; CONST char *firstByte; CONST char *lastByte; LayoutChunk *chunkPtr; if (lastChar < 0) lastChar = 100000000; chunkPtr = layoutPtr->chunks; for (i = 0; i < layoutPtr->numChunks; i++) { numDisplayChars = chunkPtr->numDisplayChars; if ((numDisplayChars > 0) && (firstChar < numDisplayChars)) { if (firstChar <= 0) { drawX = 0; firstChar = 0; firstByte = chunkPtr->start; } else { firstByte = Tcl_UtfAtIndex(chunkPtr->start, firstChar); Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start, firstByte - chunkPtr->start, -1, 0, &drawX); } if (lastChar < numDisplayChars) numDisplayChars = lastChar; lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars); #ifdef TEXTLAYOUT_ELLIPSIS if (chunkPtr->ellipsis) { char staticStr[256], *buf = staticStr; char *ellipsis = "..."; int ellipsisLen = strlen(ellipsis); if ((lastByte - firstByte) + ellipsisLen > sizeof(staticStr)) buf = ckalloc((lastByte - firstByte) + ellipsisLen); memcpy(buf, firstByte, (lastByte - firstByte)); memcpy(buf + (lastByte - firstByte), ellipsis, ellipsisLen); Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont, buf, (lastByte - firstByte) + ellipsisLen, x + chunkPtr->x + drawX, y + chunkPtr->y); if (buf != staticStr) ckfree(buf); } else #endif Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont, firstByte, lastByte - firstByte, x + chunkPtr->x + drawX, y + chunkPtr->y); #if 1 if (underline >= firstChar && underline < numDisplayChars) { CONST char *fstBytePtr = Tcl_UtfAtIndex(chunkPtr->start, underline); CONST char *sndBytePtr = Tcl_UtfNext(fstBytePtr); Tk_UnderlineChars(display, drawable, gc, layoutPtr->tkfont, firstByte, x + chunkPtr->x + drawX, y + chunkPtr->y, fstBytePtr - chunkPtr->start, sndBytePtr - chunkPtr->start); } #endif } firstChar -= chunkPtr->numChars; lastChar -= chunkPtr->numChars; #if 1 underline -= chunkPtr->numChars; #endif if (lastChar <= 0) break; chunkPtr++; } } /* *---------------------------------------------------------------------- * * TreeCtrl_GetPadAmountFromObj -- * * Parse a pad amount configuration option. * A pad amount (typically the value of an option -XXXpadx or * -XXXpady, where XXX may be a possibly empty string) can * be either a single pixel width, or a list of two pixel widths. * If a single pixel width, the amount specified is used for * padding on both sides. If two amounts are specified, then * they specify the left/right or top/bottom padding. * * Results: * Standard Tcl Result. * * Side effects: * Sets internal representation of the object. In case of an error * the result of the interpreter is modified. * *---------------------------------------------------------------------- */ int TreeCtrl_GetPadAmountFromObj(interp, tkwin, padObj, topLeftPtr, bottomRightPtr) Tcl_Interp *interp; /* Interpreter for error reporting, or NULL, * if no error message is wanted. */ Tk_Window tkwin; /* A window. Needed by Tk_GetPixels() */ Tcl_Obj *padObj; /* Object containing a pad amount. */ int *topLeftPtr; /* Pointer to the location, where to store the first component of the padding. */ int *bottomRightPtr; /* Pointer to the location, where to store the second component of the padding. */ { int padc; /* Number of element objects in padv. */ Tcl_Obj **padv; /* Pointer to the element objects of the * parsed pad amount value. */ int topLeft, bottomRight; if (Tcl_ListObjGetElements(interp, padObj, &padc, &padv) != TCL_OK) { return TCL_ERROR; } /* * The value specifies a non empty string. * Check that this string is indeed a valid pad amount. */ if (padc < 1 || padc > 2) { if (interp != NULL) { error: Tcl_ResetResult(interp); Tcl_AppendResult(interp, "bad pad amount \"", Tcl_GetString(padObj), "\": must be a list of ", "1 or 2 positive screen distances", (char *) NULL); } return TCL_ERROR; } if ((Tk_GetPixelsFromObj(interp, tkwin, padv[0], &topLeft) != TCL_OK) || (topLeft < 0)) { goto error; } if (padc == 2) { if ((Tk_GetPixelsFromObj(interp, tkwin, padv[1], &bottomRight) != TCL_OK) || (bottomRight < 0)) { goto error; } } else { bottomRight = topLeft; } (*topLeftPtr) = topLeft; (*bottomRightPtr) = bottomRight; return TCL_OK; } /* *---------------------------------------------------------------------- * * TreeCtrl_NewPadAmountObj -- * * Create a Tcl object with an internal representation, that * corresponds to a pad amount, i.e. an integer Tcl_Obj or a * list Tcl_Obj with 2 elements. * * Results: * The created object. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * TreeCtrl_NewPadAmountObj(padAmounts) int *padAmounts; /* Internal form of a pad amount. */ { Tcl_Obj *newObj; /* * If both values are the same, create a list with one value, * otherwise create a two element list with the top/left value * first followed by the bottom/right value. */ if (padAmounts[PAD_TOP_LEFT] == padAmounts[PAD_BOTTOM_RIGHT]) { newObj = Tcl_NewIntObj(padAmounts[PAD_TOP_LEFT]); } else { newObj = Tcl_NewObj(); Tcl_ListObjAppendElement((Tcl_Interp *) NULL, newObj, Tcl_NewIntObj(padAmounts[PAD_TOP_LEFT])); Tcl_ListObjAppendElement((Tcl_Interp *) NULL, newObj, Tcl_NewIntObj(padAmounts[PAD_BOTTOM_RIGHT])); } return newObj; } /* *---------------------------------------------------------------------- * * PadAmountOptionSet -- * PadAmountOptionGet -- * PadAmountOptionRestore -- * PadAmountOptionFree -- * * Handlers for object-based pad amount configuration options. * A pad amount (typically the value of an option -XXXpadx or * -XXXpady, where XXX may be a possibly empty string) can * be either a single pixel width, or a list of two pixel widths. * If a single pixel width, the amount specified is used for * padding on both sides. If two amounts are specified, then * they specify the left/right or top/bottom padding. * * Results: * See user documentation for expected results from these functions. * PadAmountOptionSet Standard Tcl Result. * PadAmountOptionGet Tcl_Obj * containing a valid internal * representation of the pad amount. * PadAmountOptionRestore None. * PadAmountOptionFree None. * * Side effects: * Depends on the function. * PadAmountOptionSet Sets option value to new setting, * allocating a new integer array. * PadAmountOptionGet Creates a new Tcl_Obj. * PadAmountOptionRestore Resets option value to original value. * PadAmountOptionFree Free storage for internal rep. * *---------------------------------------------------------------------- */ static int PadAmountOptionSet(clientData, interp, tkwin, valuePtr, recordPtr, internalOffset, saveInternalPtr, flags) ClientData clientData; /* unused. */ Tcl_Interp *interp; /* Interpreter for error reporting, or NULL, * if no error message is wanted. */ Tk_Window tkwin; /* A window. Needed by Tk_GetPixels() */ Tcl_Obj **valuePtr; /* The argument to "-padx", "-pady", "-ipadx", * or "-ipady". The thing to be parsed. */ char *recordPtr; /* Pointer to start of widget record. */ int internalOffset; /* Offset of internal representation or * -1, if no internal repr is wanted. */ char *saveInternalPtr; /* Pointer to the place, where the saved * internal form (of type "int *") resides. */ int flags; /* Flags as specified in Tk_OptionSpec. */ { int topLeft, bottomRight; /* The two components of the padding. */ int *new; /* Pointer to the allocated array of integers * containing the parsed pad amounts. */ int **internalPtr; /* Pointer to the place, where the internal * form (of type "int *") resides. */ /* * Check that the given object indeed specifies a valid pad amount. */ if (TreeCtrl_GetPadAmountFromObj(interp, tkwin, *valuePtr, &topLeft, &bottomRight) != TCL_OK) { return TCL_ERROR; } /* * Store a pointer to an allocated array of the two padding values * into the widget record at the specified offset. */ if (internalOffset >= 0) { internalPtr = (int **) (recordPtr + internalOffset); *(int **) saveInternalPtr = *internalPtr; new = (int *) ckalloc(2 * sizeof(int)); new[PAD_TOP_LEFT] = topLeft; new[PAD_BOTTOM_RIGHT] = bottomRight; *internalPtr = new; } return TCL_OK; } static Tcl_Obj * PadAmountOptionGet(clientData, tkwin, recordPtr, internalOffset) ClientData clientData; /* unused. */ Tk_Window tkwin; /* A window; unused. */ char *recordPtr; /* Pointer to start of widget record. */ int internalOffset; /* Offset of internal representation. */ { int *padAmounts = *(int **)(recordPtr + internalOffset); return TreeCtrl_NewPadAmountObj(padAmounts); } static void PadAmountOptionRestore(clientData, tkwin, internalPtr, saveInternalPtr) ClientData clientData; /* unused. */ Tk_Window tkwin; /* A window; unused. */ char *internalPtr; /* Pointer to the place, where the internal * form (of type "int *") resides. */ char *saveInternalPtr; /* Pointer to the place, where the saved * internal form (of type "int *") resides. */ { *(int **) internalPtr = *(int **) saveInternalPtr; } static void PadAmountOptionFree(clientData, tkwin, internalPtr) ClientData clientData; /* unused. */ Tk_Window tkwin; /* A window; unused */ char *internalPtr; /* Pointer to the place, where the internal * form (of type "int *") resides. */ { if (*(int **)internalPtr != NULL) { ckfree((char *) *(int **)internalPtr); } } /* *---------------------------------------------------------------------- * * ObjectIsEmpty -- * * This procedure tests whether the string value of an object is * empty. * * Results: * The return value is 1 if the string value of objPtr has length * zero, and 0 otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int ObjectIsEmpty( Tcl_Obj *obj /* Object to test. May be NULL. */ ) { int length; if (obj == NULL) return 1; if (obj->bytes != NULL) return (obj->length == 0); Tcl_GetStringFromObj(obj, &length); return (length == 0); } #define PERSTATE_ROUNDUP 5 /* *---------------------------------------------------------------------- * * PerStateInfo_Free -- * * Frees memory and resources associated with a single per-state * option. pInfo is set to an empty state ready to be used again. * * Results: * None. * * Side effects: * Memory is deallocated. Colors, etc are freed. * *---------------------------------------------------------------------- */ void PerStateInfo_Free( TreeCtrl *tree, /* Widget info. */ PerStateType *typePtr, /* Type-specific functions and values. */ PerStateInfo *pInfo /* Per-state info to free. */ ) { PerStateData *pData = pInfo->data; int i; if (pInfo->data == NULL) return; #ifdef TREECTRL_DEBUG if (pInfo->type != typePtr) panic("PerStateInfo_Free type mismatch: got %s expected %s", pInfo->type ? pInfo->type->name : "NULL", typePtr->name); #endif for (i = 0; i < pInfo->count; i++) { (*typePtr->freeProc)(tree, pData); pData = (PerStateData *) (((char *) pData) + typePtr->size); } #ifdef ALLOC_HAX TreeAlloc_CFree(tree->allocData, typePtr->name, (char *) pInfo->data, typePtr->size, pInfo->count, PERSTATE_ROUNDUP); #else WIPEFREE(pInfo->data, typePtr->size * pInfo->count); #endif pInfo->data = NULL; pInfo->count = 0; } /* *---------------------------------------------------------------------- * * PerStateInfo_FromObj -- * * Parse a Tcl_Obj to an array of PerStateData. The current data * is freed (if any). If the Tcl_Obj is NULL then pInfo is left in * an empty state ready to be used again. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated/deallocated. * *---------------------------------------------------------------------- */ int PerStateInfo_FromObj( TreeCtrl *tree, /* Widget info. */ StateFromObjProc proc, /* Procedure used to turn a Tcl_Obj into * a state bit-flag. */ PerStateType *typePtr, /* Type-specific functions and values. */ PerStateInfo *pInfo /* Per-state info to return. pInfo->obj * must be NULL or point to a valid Tcl_Obj. */ ) { int i, j; int objc, objc2; Tcl_Obj **objv, **objv2; PerStateData *pData; #ifdef TREECTRL_DEBUG pInfo->type = typePtr; #endif PerStateInfo_Free(tree, typePtr, pInfo); if (pInfo->obj == NULL) return TCL_OK; if (Tcl_ListObjGetElements(tree->interp, pInfo->obj, &objc, &objv) != TCL_OK) return TCL_ERROR; if (objc == 0) return TCL_OK; if (objc == 1) { #ifdef ALLOC_HAX pData = (PerStateData *) TreeAlloc_CAlloc(tree->allocData, typePtr->name, typePtr->size, 1, PERSTATE_ROUNDUP); #else pData = (PerStateData *) ckalloc(typePtr->size); #endif pData->stateOff = pData->stateOn = 0; /* all states */ if ((*typePtr->fromObjProc)(tree, objv[0], pData) != TCL_OK) { #ifdef ALLOC_HAX TreeAlloc_CFree(tree->allocData, typePtr->name, (char *) pData, typePtr->size, 1, PERSTATE_ROUNDUP); #else WIPEFREE(pData, typePtr->size); #endif return TCL_ERROR; } pInfo->data = pData; pInfo->count = 1; return TCL_OK; } if (objc & 1) { FormatResult(tree->interp, "list must have even number of elements"); return TCL_ERROR; } #ifdef ALLOC_HAX pData = (PerStateData *) TreeAlloc_CAlloc(tree->allocData, typePtr->name, typePtr->size, objc / 2, PERSTATE_ROUNDUP); #else pData = (PerStateData *) ckalloc(typePtr->size * (objc / 2)); #endif pInfo->data = pData; for (i = 0; i < objc; i += 2) { if ((*typePtr->fromObjProc)(tree, objv[i], pData) != TCL_OK) { goto freeIt; } pInfo->count++; if (Tcl_ListObjGetElements(tree->interp, objv[i + 1], &objc2, &objv2) != TCL_OK) { goto freeIt; } pData->stateOff = pData->stateOn = 0; /* all states */ for (j = 0; j < objc2; j++) { if (proc(tree, objv2[j], &pData->stateOff, &pData->stateOn) != TCL_OK) { goto freeIt; } } pData = (PerStateData *) (((char *) pData) + typePtr->size); } return TCL_OK; freeIt: pData = pInfo->data; for (i = 0; i < pInfo->count; i++) { (*typePtr->freeProc)(tree, pData); pData = (PerStateData *) (((char *) pData) + typePtr->size); } #ifdef ALLOC_HAX TreeAlloc_CFree(tree->allocData, typePtr->name, (char *) pInfo->data, typePtr->size, objc / 2, PERSTATE_ROUNDUP); #else WIPEFREE(pInfo->data, typePtr->size * (objc / 2)); #endif pInfo->data = NULL; pInfo->count = 0; return TCL_ERROR; } /* *---------------------------------------------------------------------- * * PerStateInfo_ForState -- * * Return the best-matching PerStateData for a given state. * * Results: * The return value is a pointer to the best-matching PerStateData. * *match is set to a MATCH_xxx constant. NULL is returned if * no appropriate PerStateData was found. * * Side effects: * None. * *---------------------------------------------------------------------- */ PerStateData * PerStateInfo_ForState( TreeCtrl *tree, /* Widget info. */ PerStateType *typePtr, /* Type-specific functions and values. */ PerStateInfo *pInfo, /* Per-state info to search. */ int state, /* State bit-flags to compare. */ int *match /* Returned MATCH_xxx constant. */ ) { PerStateData *pData = pInfo->data; int stateOff = ~state, stateOn = state; int i; #ifdef TREECTRL_DEBUG if ((pInfo->data != NULL) && (pInfo->type != typePtr)) { panic("PerStateInfo_ForState type mismatch: got %s expected %s", pInfo->type ? pInfo->type->name : "NULL", typePtr->name); } #endif for (i = 0; i < pInfo->count; i++) { /* Any state */ if ((pData->stateOff == 0) && (pData->stateOn == 0)) { if (match) (*match) = MATCH_ANY; return pData; } /* Exact match */ if ((pData->stateOff == stateOff) && (pData->stateOn == stateOn)) { if (match) (*match) = MATCH_EXACT; return pData; } /* Partial match */ if (((pData->stateOff & stateOff) == pData->stateOff) && ((pData->stateOn & stateOn) == pData->stateOn)) { if (match) (*match) = MATCH_PARTIAL; return pData; } pData = (PerStateData *) (((char *) pData) + typePtr->size); } if (match) (*match) = MATCH_NONE; return NULL; } /* *---------------------------------------------------------------------- * * PerStateInfo_ObjForState -- * * Return a Tcl_Obj from the list object that was parsed by * PerStateInfo_FromObj(). pInfo is searched for the best-matching * PerStateData for the given state and the object used to * create that PerStateData is returned. * * Results: * *match is set to a MATCH_xxx constant. NULL is returned if * no appropriate PerStateData was found. The object should not * be modified by the caller. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * PerStateInfo_ObjForState( TreeCtrl *tree, /* Widget info. */ PerStateType *typePtr, /* Type-specific functions and values. */ PerStateInfo *pInfo, /* Per-state info to search. */ int state, /* State bit-flags to compare. */ int *match /* Returned MATCH_xxx constant. */ ) { PerStateData *pData; Tcl_Obj *obj; int i; #ifdef TREECTRL_DEBUG if ((pInfo->data != NULL) && (pInfo->type != typePtr)) panic("PerStateInfo_ObjForState type mismatch: got %s expected %s", pInfo->type ? pInfo->type->name : "NULL", typePtr->name); #endif pData = PerStateInfo_ForState(tree, typePtr, pInfo, state, match); if (pData != NULL) { i = ((char *) pData - (char *) pInfo->data) / typePtr->size; Tcl_ListObjIndex(tree->interp, pInfo->obj, i * 2, &obj); return obj; } return NULL; } static Tcl_Obj * DuplicateListObj( Tcl_Obj *objPtr ) { int objc; Tcl_Obj **objv; int result; /* * Comment from TclLsetFlat: * ... A plain Tcl_DuplicateObj * will just increase the intrep's refCount without upping the sublists' * refCount, so that their true shared status cannot be determined from * their refCount. */ result = Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv); return Tcl_NewListObj(objc, objv); } /* *---------------------------------------------------------------------- * * PerStateInfo_Undefine -- * * Called when a user-defined state flag is undefined. The state * flag is cleared from every PerStateData using that flag. The * list object that was parsed by PerStateInfo_FromObj() is modified * by removing any reference to the undefined state. * * Results: * The return value is a boolean indicating whether or not pInfo * was modified. * * Side effects: * The list object pointed to by pInfo->obj may be recreated. * *---------------------------------------------------------------------- */ int PerStateInfo_Undefine( TreeCtrl *tree, /* Widget info. */ PerStateType *typePtr, /* Type-specific functions and values. */ PerStateInfo *pInfo, /* Per-state info to modify. */ int state /* State bit-flag that was undefined. */ ) { PerStateData *pData = pInfo->data; int i, j, numStates, stateOff, stateOn; Tcl_Obj *configObj = pInfo->obj, *listObj, *stateObj; int modified = 0; #ifdef TREECTRL_DEBUG if ((pInfo->data != NULL) && (pInfo->type != typePtr)) panic("PerStateInfo_Undefine type mismatch: got %s expected %s", pInfo->type ? pInfo->type->name : "NULL", typePtr->name); #endif for (i = 0; i < pInfo->count; i++) { if ((pData->stateOff | pData->stateOn) & state) { pData->stateOff &= ~state; pData->stateOn &= ~state; if (Tcl_IsShared(configObj)) { configObj = DuplicateListObj(configObj); Tcl_DecrRefCount(pInfo->obj); Tcl_IncrRefCount(configObj); pInfo->obj = configObj; } Tcl_ListObjIndex(tree->interp, configObj, i * 2 + 1, &listObj); if (Tcl_IsShared(listObj)) { listObj = DuplicateListObj(listObj); Tcl_ListObjReplace(tree->interp, configObj, i * 2 + 1, 1, 1, &listObj); } Tcl_ListObjLength(tree->interp, listObj, &numStates); for (j = 0; j < numStates; ) { Tcl_ListObjIndex(tree->interp, listObj, j, &stateObj); stateOff = stateOn = 0; TreeStateFromObj(tree, stateObj, &stateOff, &stateOn); if ((stateOff | stateOn) & state) { Tcl_ListObjReplace(tree->interp, listObj, j, 1, 0, NULL); numStates--; } else j++; } /* Given {bitmap {state1 state2 state3}}, we just invalidated * the string rep of the sublist {state1 state2 state3}, but not * the parent list. */ Tcl_InvalidateStringRep(configObj); modified = 1; } pData = (PerStateData *) (((char *) pData) + typePtr->size); } return modified; } /*****/ GC Tree_GetGC( TreeCtrl *tree, unsigned long mask, XGCValues *gcValues) { GCCache *pGC; unsigned long valid = GCFont | GCForeground | GCFunction | GCBackground | GCGraphicsExposures; if ((mask | valid) != valid) panic("GCCache_Get: unsupported mask"); for (pGC = tree->gcCache; pGC != NULL; pGC = pGC->next) { if (mask != pGC->mask) continue; if ((mask & GCFont) && (pGC->gcValues.font != gcValues->font)) continue; if ((mask & GCForeground) && (pGC->gcValues.foreground != gcValues->foreground)) continue; if ((mask & GCFunction) && (pGC->gcValues.function != gcValues->function)) continue; if ((mask & GCBackground) && (pGC->gcValues.background != gcValues->background)) continue; if ((mask & GCGraphicsExposures) && (pGC->gcValues.graphics_exposures != gcValues->graphics_exposures)) continue; return pGC->gc; } pGC = (GCCache *) ckalloc(sizeof(*pGC)); pGC->gcValues = (*gcValues); pGC->mask = mask; pGC->gc = Tk_GetGC(tree->tkwin, mask, gcValues); pGC->next = tree->gcCache; tree->gcCache = pGC; return pGC->gc; } void Tree_FreeAllGC( TreeCtrl *tree) { GCCache *pGC = tree->gcCache, *next; while (pGC != NULL) { next = pGC->next; Tk_FreeGC(tree->display, pGC->gc); WFREE(pGC, GCCache); pGC = next; } tree->gcCache = NULL; } /*****/ typedef struct PerStateDataBitmap PerStateDataBitmap; struct PerStateDataBitmap { PerStateData header; Pixmap bitmap; }; static int PSDBitmapFromObj( TreeCtrl *tree, Tcl_Obj *obj, PerStateDataBitmap *pBitmap) { if (ObjectIsEmpty(obj)) { /* Specify empty string to override masterX */ pBitmap->bitmap = None; } else { pBitmap->bitmap = Tk_AllocBitmapFromObj(tree->interp, tree->tkwin, obj); if (pBitmap->bitmap == None) return TCL_ERROR; } return TCL_OK; } static void PSDBitmapFree( TreeCtrl *tree, PerStateDataBitmap *pBitmap) { if (pBitmap->bitmap != None) Tk_FreeBitmap(tree->display, pBitmap->bitmap); } PerStateType pstBitmap = { "pstBitmap", sizeof(PerStateDataBitmap), (PerStateType_FromObjProc) PSDBitmapFromObj, (PerStateType_FreeProc) PSDBitmapFree }; Pixmap PerStateBitmap_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataBitmap *pData; pData = (PerStateDataBitmap *) PerStateInfo_ForState(tree, &pstBitmap, pInfo, state, match); if (pData != NULL) return pData->bitmap; return None; } void PerStateBitmap_MaxSize( TreeCtrl *tree, PerStateInfo *pInfo, int *widthPtr, int *heightPtr) { PerStateDataBitmap *pData = (PerStateDataBitmap *) pInfo->data; int i, width, height, w, h; width = height = 0; for (i = 0; i < pInfo->count; i++, ++pData) { if (pData->bitmap == None) continue; Tk_SizeOfBitmap(tree->display, pData->bitmap, &w, &h); width = MAX(width, w); height = MAX(height, h); } (*widthPtr) = width; (*heightPtr) = height; } /*****/ typedef struct PerStateDataBoolean PerStateDataBoolean; struct PerStateDataBoolean { PerStateData header; int value; }; static int PSDBooleanFromObj( TreeCtrl *tree, Tcl_Obj *obj, PerStateDataBoolean *pBoolean) { if (ObjectIsEmpty(obj)) { pBoolean->value = -1; } else { if (Tcl_GetBooleanFromObj(tree->interp, obj, &pBoolean->value) != TCL_OK) return TCL_ERROR; } return TCL_OK; } static void PSDBooleanFree( TreeCtrl *tree, PerStateDataBoolean *pBoolean) { } PerStateType pstBoolean = { "pstBoolean", sizeof(PerStateDataBoolean), (PerStateType_FromObjProc) PSDBooleanFromObj, (PerStateType_FreeProc) PSDBooleanFree }; int PerStateBoolean_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataBoolean *pData; pData = (PerStateDataBoolean *) PerStateInfo_ForState(tree, &pstBoolean, pInfo, state, match); if (pData != NULL) return pData->value; return -1; } /*****/ typedef struct PerStateDataBorder PerStateDataBorder; struct PerStateDataBorder { PerStateData header; Tk_3DBorder border; }; static int PSDBorderFromObj( TreeCtrl *tree, Tcl_Obj *obj, PerStateDataBorder *pBorder) { if (ObjectIsEmpty(obj)) { /* Specify empty string to override masterX */ pBorder->border = NULL; } else { pBorder->border = Tk_Alloc3DBorderFromObj(tree->interp, tree->tkwin, obj); if (pBorder->border == NULL) return TCL_ERROR; } return TCL_OK; } static void PSDBorderFree( TreeCtrl *tree, PerStateDataBorder *pBorder) { if (pBorder->border != NULL) Tk_Free3DBorder(pBorder->border); } PerStateType pstBorder = { "pstBorder", sizeof(PerStateDataBorder), (PerStateType_FromObjProc) PSDBorderFromObj, (PerStateType_FreeProc) PSDBorderFree }; Tk_3DBorder PerStateBorder_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataBorder *pData; pData = (PerStateDataBorder *) PerStateInfo_ForState(tree, &pstBorder, pInfo, state, match); if (pData != NULL) return pData->border; return NULL; } /*****/ typedef struct PerStateDataColor PerStateDataColor; struct PerStateDataColor { PerStateData header; XColor *color; }; static int PSDColorFromObj( TreeCtrl *tree, Tcl_Obj *obj, PerStateDataColor *pColor) { if (ObjectIsEmpty(obj)) { /* Specify empty string to override masterX */ pColor->color = NULL; } else { pColor->color = Tk_AllocColorFromObj(tree->interp, tree->tkwin, obj); if (pColor->color == NULL) return TCL_ERROR; } return TCL_OK; } static void PSDColorFree( TreeCtrl *tree, PerStateDataColor *pColor) { if (pColor->color != NULL) Tk_FreeColor(pColor->color); } PerStateType pstColor = { "pstColor", sizeof(PerStateDataColor), (PerStateType_FromObjProc) PSDColorFromObj, (PerStateType_FreeProc) PSDColorFree }; XColor * PerStateColor_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataColor *pData; pData = (PerStateDataColor *) PerStateInfo_ForState(tree, &pstColor, pInfo, state, match); if (pData != NULL) return pData->color; return NULL; } /*****/ typedef struct PerStateDataFont PerStateDataFont; struct PerStateDataFont { PerStateData header; Tk_Font tkfont; }; static int PSDFontFromObj( TreeCtrl *tree, Tcl_Obj *obj, PerStateDataFont *pFont) { if (ObjectIsEmpty(obj)) { /* Specify empty string to override masterX */ pFont->tkfont = NULL; } else { pFont->tkfont = Tk_AllocFontFromObj(tree->interp, tree->tkwin, obj); if (pFont->tkfont == NULL) return TCL_ERROR; } return TCL_OK; } static void PSDFontFree( TreeCtrl *tree, PerStateDataFont *pFont) { if (pFont->tkfont != NULL) Tk_FreeFont(pFont->tkfont); } PerStateType pstFont = { "pstFont", sizeof(PerStateDataFont), (PerStateType_FromObjProc) PSDFontFromObj, (PerStateType_FreeProc) PSDFontFree }; Tk_Font PerStateFont_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataFont *pData; pData = (PerStateDataFont *) PerStateInfo_ForState(tree, &pstFont, pInfo, state, match); if (pData != NULL) return pData->tkfont; return NULL; } /*****/ typedef struct PerStateDataImage PerStateDataImage; struct PerStateDataImage { PerStateData header; Tk_Image image; char *string; }; static int PSDImageFromObj( TreeCtrl *tree, Tcl_Obj *obj, PerStateDataImage *pImage) { int length; char *string; if (ObjectIsEmpty(obj)) { /* Specify empty string to override masterX */ pImage->image = NULL; pImage->string = NULL; } else { string = Tcl_GetStringFromObj(obj, &length); pImage->image = Tree_GetImage(tree, string); if (pImage->image == NULL) return TCL_ERROR; pImage->string = ckalloc(length + 1); strcpy(pImage->string, string); } return TCL_OK; } static void PSDImageFree( TreeCtrl *tree, PerStateDataImage *pImage) { if (pImage->string != NULL) ckfree(pImage->string); if (pImage->image != NULL) Tree_FreeImage(tree, pImage->image); } PerStateType pstImage = { "pstImage", sizeof(PerStateDataImage), (PerStateType_FromObjProc) PSDImageFromObj, (PerStateType_FreeProc) PSDImageFree }; Tk_Image PerStateImage_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataImage *pData; pData = (PerStateDataImage *) PerStateInfo_ForState(tree, &pstImage, pInfo, state, match); if (pData != NULL) return pData->image; return NULL; } void PerStateImage_MaxSize( TreeCtrl *tree, PerStateInfo *pInfo, int *widthPtr, int *heightPtr) { PerStateDataImage *pData = (PerStateDataImage *) pInfo->data; int i, width, height, w, h; width = height = 0; for (i = 0; i < pInfo->count; i++, ++pData) { if (pData->image == None) continue; Tk_SizeOfImage(pData->image, &w, &h); width = MAX(width, w); height = MAX(height, h); } (*widthPtr) = width; (*heightPtr) = height; } /*****/ typedef struct PerStateDataRelief PerStateDataRelief; struct PerStateDataRelief { PerStateData header; int relief; }; static int PSDReliefFromObj( TreeCtrl *tree, Tcl_Obj *obj, PerStateDataRelief *pRelief) { if (ObjectIsEmpty(obj)) { /* Specify empty string to override masterX */ pRelief->relief = TK_RELIEF_NULL; } else { if (Tk_GetReliefFromObj(tree->interp, obj, &pRelief->relief) != TCL_OK) return TCL_ERROR; } return TCL_OK; } static void PSDReliefFree( TreeCtrl *tree, PerStateDataRelief *pRelief) { } PerStateType pstRelief = { "pstRelief", sizeof(PerStateDataRelief), (PerStateType_FromObjProc) PSDReliefFromObj, (PerStateType_FreeProc) PSDReliefFree }; int PerStateRelief_ForState( TreeCtrl *tree, PerStateInfo *pInfo, int state, int *match) { PerStateDataRelief *pData; pData = (PerStateDataRelief *) PerStateInfo_ForState(tree, &pstRelief, pInfo, state, match); if (pData != NULL) return pData->relief; return TK_RELIEF_NULL; } /*****/ void PSTSave( PerStateInfo *pInfo, PerStateInfo *pSave) { #ifdef TREECTRL_DEBUG pSave->type = pInfo->type; /* could be NULL */ #endif pSave->data = pInfo->data; pSave->count = pInfo->count; pInfo->data = NULL; pInfo->count = 0; } void PSTRestore( TreeCtrl *tree, PerStateType *typePtr, PerStateInfo *pInfo, PerStateInfo *pSave) { PerStateInfo_Free(tree, typePtr, pInfo); pInfo->data = pSave->data; pInfo->count = pSave->count; } #ifdef ALLOC_HAX /* * The following TreeAlloc_xxx calls implement a mini memory allocator that * allocates blocks of same-sized chunks, and holds on to those chunks when * they are freed so they can be reused quickly. If you don't want to use it * just comment out #define ALLOC_HAX in tkTreeCtrl.h. */ typedef struct AllocElem AllocElem; typedef struct AllocBlock AllocBlock; typedef struct AllocList AllocList; typedef struct AllocData AllocData; #ifdef TREECTRL_DEBUG #define ALLOC_STATS #endif #ifdef ALLOC_STATS typedef struct AllocStats AllocStats; #endif /* * One of the following structures exists for each client piece of memory. * These structures are allocated in arrays (blocks). */ struct AllocElem { AllocElem *next; #ifdef TREECTRL_DEBUG int free; int size; #endif char body[1]; /* First byte of client's space. Actual * size of this field will be larger than * one. */ }; struct AllocBlock { int count; /* Size of .elem[] */ AllocBlock *next; /* Next block with same-sized elems. */ AllocElem elem[1]; /* Actual size will be larger than one. */ }; /* * One of the following structures maintains an array of blocks of AllocElems * of the same size. */ struct AllocList { int size; /* Size of every AllocElem.body[] */ AllocElem *head; /* Top of stack of unused pieces of memory. */ AllocBlock *blocks; /* Linked list of allocated blocks. The blocks * may contain a different number of elements. */ int blockSize; /* The number of AllocElems per block to allocate. * Starts at 16 and gets doubled up to 1024. */ AllocList *next; /* Points to an AllocList with a different .size */ }; /* * A pointer to one of the following structures is stored in each TreeCtrl. */ struct AllocData { AllocList *freeLists; /* Linked list. */ #ifdef ALLOC_STATS AllocStats *stats; /* For memory-usage reporting. */ #endif }; #ifdef ALLOC_STATS struct AllocStats { Tk_Uid id; /* Name for reporting results. */ unsigned count; /* Number of allocations. */ unsigned size; /* Total allocated bytes. */ AllocStats *next; /* Linked list. */ }; #endif /* * The following macro computes the offset of the "body" field within * AllocElem. It is used to get back to the header pointer from the * body pointer that's used by clients. */ #define BODY_OFFSET \ ((unsigned long) (&((AllocElem *) 0)->body)) #ifdef ALLOC_STATS static AllocStats * AllocStats_Get( ClientData _data, Tk_Uid id ) { AllocData *data = (AllocData *) _data; AllocStats *stats = data->stats; while (stats != NULL) { if (stats->id == id) break; stats = stats->next; } if (stats == NULL) { stats = (AllocStats *) ckalloc(sizeof(AllocStats)); stats->id = id; stats->count = 0; stats->size = 0; stats->next = data->stats; data->stats = stats; } return stats; } void TreeAlloc_Stats( Tcl_Interp *interp, ClientData _data ) { AllocData *data = (AllocData *) _data; AllocStats *stats = data->stats; int numElems = 0; Tcl_DString dString; Tcl_DStringInit(&dString); while (stats != NULL) { DStringAppendf(&dString, "%-20s: %8d : %8d B %5d KB\n", stats->id, stats->count, stats->size, (stats->size + 1023) / 1024); numElems += stats->count; stats = stats->next; } DStringAppendf(&dString, "%-31s: %8d B %5d KB\n", "AllocElem overhead", numElems * BODY_OFFSET, (numElems * BODY_OFFSET) / 1024); Tcl_DStringResult(interp, &dString); } #endif /* ALLOC_STATS */ /* *---------------------------------------------------------------------- * * TreeAlloc_Alloc -- * * Return storage for a piece of data of the given size. * * Results: * The return value is a pointer to memory for the caller's * use. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ char * TreeAlloc_Alloc( ClientData _data, /* Token returned by TreeAlloc_Init(). */ Tk_Uid id, /* ID for memory-usage reporting. */ int size /* Number of bytes needed. */ ) { AllocData *data = (AllocData *) _data; AllocList *freeLists = data->freeLists; AllocList *freeList = freeLists; AllocBlock *block; AllocElem *elem, *result; #ifdef ALLOC_STATS AllocStats *stats = AllocStats_Get(_data, id); #endif int i; #ifdef ALLOC_STATS stats->count++; stats->size += size; #endif while ((freeList != NULL) && (freeList->size != size)) freeList = freeList->next; if (freeList == NULL) { freeList = (AllocList *) ckalloc(sizeof(AllocList)); freeList->size = size; freeList->head = NULL; freeList->next = freeLists; freeList->blocks = NULL; freeList->blockSize = 16; freeLists = freeList; ((AllocData *) data)->freeLists = freeLists; } if (freeList->head == NULL) { unsigned elemSize = TCL_ALIGN(BODY_OFFSET + size); block = (AllocBlock *) ckalloc(Tk_Offset(AllocBlock, elem) + elemSize * freeList->blockSize); block->count = freeList->blockSize; block->next = freeList->blocks; /* dbwin("TreeAlloc_Alloc alloc %d of size %d\n", freeList->blockSize, size); */ freeList->blocks = block; if (freeList->blockSize < 1024) freeList->blockSize *= 2; freeList->head = block->elem; elem = freeList->head; for (i = 1; i < block->count - 1; i++) { #ifdef TREECTRL_DEBUG elem->free = 1; elem->size = size; #endif elem->next = (AllocElem *) (((char *) freeList->head) + elemSize * i); elem = elem->next; } elem->next = NULL; #ifdef TREECTRL_DEBUG elem->free = 1; elem->size = size; #endif } result = freeList->head; freeList->head = result->next; #ifdef TREECTRL_DEBUG if (!result->free) panic("TreeAlloc_Alloc: element not marked free"); result->free = 0; #endif return result->body; } /* *---------------------------------------------------------------------- * * TreeAlloc_Realloc -- * * Realloc. * * Results: * The return value is a pointer to memory for the caller's * use. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ char * TreeAlloc_Realloc( ClientData data, /* Token returned by TreeAlloc_Init(). */ Tk_Uid id, /* ID for memory-usage reporting. */ char *ptr, int size1, /* Number of bytes in ptr. */ int size2 /* Number of bytes needed. */ ) { char *ptr2; ptr2 = TreeAlloc_Alloc(data, id, size2); memcpy(ptr2, ptr, MIN(size1, size2)); TreeAlloc_Free(data, id, ptr, size1); return ptr2; } /* *---------------------------------------------------------------------- * * TreeAlloc_Free -- * * Mark a piece of memory as free for reuse. * * Results: * The piece of memory is added to a list of free pieces of the * same size. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeAlloc_Free( ClientData _data, /* Token returned by TreeAlloc_Init(). */ Tk_Uid id, /* ID for memory-usage reporting. */ char *ptr, /* Memory to mark for reuse. Must have * been allocated by TreeAlloc_Alloc(). */ int size /* Number of bytes. Must match the size * passed to TreeAlloc_CAlloc(). */ ) { AllocData *data = (AllocData *) _data; AllocList *freeLists = data->freeLists; AllocList *freeList = freeLists; AllocElem *elem; #ifdef ALLOC_STATS AllocStats *stats = AllocStats_Get(_data, id); #endif #ifdef ALLOC_STATS stats->count--; stats->size -= size; #endif /* * Comment from Tcl_DbCkfree: * The following cast is *very* tricky. Must convert the pointer * to an integer before doing arithmetic on it, because otherwise * the arithmetic will be done differently (and incorrectly) on * word-addressed machines such as Crays (will subtract only bytes, * even though BODY_OFFSET is in words on these machines). */ elem = (AllocElem *) (((unsigned long) ptr) - BODY_OFFSET); #ifdef TREECTRL_DEBUG if (elem->free) panic("TreeAlloc_Free: element already marked free"); if (elem->size != size) panic("TreeAlloc_Free: element size %d != size %d", elem->size, size); #endif while (freeList != NULL && freeList->size != size) freeList = freeList->next; if (freeList == NULL) panic("TreeAlloc_Free: can't find free list for size %d", size); WIPE(elem->body, size); elem->next = freeList->head; #ifdef TREECTRL_DEBUG elem->free = 1; #endif freeList->head = elem; } /* *---------------------------------------------------------------------- * * TreeAlloc_CAlloc -- * * Return storage for an array of pieces of memory. * * Results: * Pointer to the available memory. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ char * TreeAlloc_CAlloc( ClientData data, /* Token returned by TreeAlloc_Init(). */ Tk_Uid id, /* ID for memory-usage reporting. */ int size, /* Number of bytes needed for each piece * of memory. */ int count, /* Number of pieces of memory needed. */ int roundUp /* Positive number used to reduce the number * of lists of memory pieces of different * size. */ ) { int n = (count / roundUp) * roundUp + ((count % roundUp) ? roundUp : 0); #ifdef ALLOC_STATS AllocStats *stats = AllocStats_Get(data, id); #endif #ifdef ALLOC_STATS stats->count += count - 1; #endif return TreeAlloc_Alloc(data, id, size * n); } /* *---------------------------------------------------------------------- * * TreeAlloc_CFree -- * * Mark a piece of memory as free for reuse. * * Results: * The piece of memory is added to a list of free pieces of the * same size. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TreeAlloc_CFree( ClientData data, /* Token returned by TreeAlloc_Init(). */ Tk_Uid id, /* ID for memory-usage reporting. */ char *ptr, /* Memory to mark for reuse. Must have * been allocated by TreeAlloc_CAlloc(). */ int size, /* Same arg to TreeAlloc_CAlloc(). */ int count, /* Same arg to TreeAlloc_CAlloc(). */ int roundUp /* Same arg to TreeAlloc_CAlloc(). */ ) { int n = (count / roundUp) * roundUp + ((count % roundUp) ? roundUp : 0); #ifdef ALLOC_STATS AllocStats *stats = AllocStats_Get(data, id); #endif TreeAlloc_Free(data, id, ptr, size * n); #ifdef ALLOC_STATS stats->count -= count - 1; #endif } /* *---------------------------------------------------------------------- * * TreeAlloc_Init -- * * Allocate and initialize a new memory-manager record. * * Results: * Pointer to memory-manager record. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ ClientData TreeAlloc_Init(void) { AllocData *data = (AllocData *) ckalloc(sizeof(AllocData)); data->freeLists = NULL; #ifdef ALLOC_STATS data->stats = NULL; #endif return data; } /* *---------------------------------------------------------------------- * * TreeAlloc_Finalize -- * * Free all the memory associated with a memory-manager record. * * Results: * Pointer to memory-manager record. * * Side effects: * Memory is deallocated. * *---------------------------------------------------------------------- */ void TreeAlloc_Finalize( ClientData _data /* Pointer to AllocData created by * TreeAlloc_Init(). */ ) { AllocData *data = (AllocData *) _data; AllocList *freeList = data->freeLists; #ifdef ALLOC_STATS AllocStats *stats = data->stats; #endif while (freeList != NULL) { AllocList *nextList = freeList->next; AllocBlock *block = freeList->blocks; while (block != NULL) { AllocBlock *nextBlock = block->next; ckfree((char *) block); block = nextBlock; } ckfree((char *) freeList); freeList = nextList; } #ifdef ALLOC_STATS while (stats != NULL) { AllocStats *next = stats->next; ckfree((char *) stats); stats = next; } #endif ckfree((char *) data); } #endif /* ALLOC_HAX */ /* *---------------------------------------------------------------------- * * TreePtrList_Init -- * * Initializes an pointer list, discarding any previous contents * of the pointer list (TreePtrList_Free should have been called already * if the pointer list was previously in use). * * Results: * None. * * Side effects: * The pointer list is initialized to be empty. * *---------------------------------------------------------------------- */ void TreePtrList_Init( TreeCtrl *tree, /* Widget info. */ TreePtrList *tplPtr, /* Structure describing pointer list. */ int count /* Number of pointers the list should hold. * 0 for default. */ ) { #ifdef TREECTRL_DEBUG strncpy(tplPtr->magic, "MAGC", 4); #endif tplPtr->tree = tree; tplPtr->pointers = tplPtr->pointerSpace; tplPtr->count = 0; tplPtr->space = TIL_STATIC_SPACE; if (count + 1 > TIL_STATIC_SPACE) { tplPtr->space = count + 1; tplPtr->pointers = (ClientData *) ckalloc(tplPtr->space * sizeof(ClientData)); } tplPtr->pointers[0] = NULL; } /* *---------------------------------------------------------------------- * * TreePtrList_Grow -- * * Increase the available space in an pointer list. * * Results: * The pointers[] array is resized if needed. * * Side effects: * Memory gets reallocated if needed. * *---------------------------------------------------------------------- */ void TreePtrList_Grow( TreePtrList *tplPtr, /* Structure describing pointer list. */ int count /* Number of pointers the list should hold. */ ) { #ifdef TREECTRL_DEBUG if (strncmp(tplPtr->magic, "MAGC", 4) != 0) panic("TreePtrList_Grow: using uninitialized list"); #endif if (tplPtr->space >= count + 1) return; while (tplPtr->space < count + 1) tplPtr->space *= 2; if (tplPtr->pointers == tplPtr->pointerSpace) { ClientData *pointers; pointers = (ClientData *) ckalloc(tplPtr->space * sizeof(ClientData)); memcpy(pointers, tplPtr->pointers, (tplPtr->count + 1) * sizeof(ClientData)); tplPtr->pointers = pointers; } else { tplPtr->pointers = (ClientData *) ckrealloc((char *) tplPtr->pointers, tplPtr->space * sizeof(ClientData)); } } /* *---------------------------------------------------------------------- * * TreePtrList_Append -- * * Append an pointer to an pointer list. * * Results: * The return value is a pointer to the list of pointers. * * Side effects: * Memory gets reallocated if needed. * *---------------------------------------------------------------------- */ ClientData * TreePtrList_Append( TreePtrList *tplPtr, /* Structure describing pointer list. */ ClientData pointer /* Item to append. */ ) { #ifdef TREECTRL_DEBUG if (strncmp(tplPtr->magic, "MAGC", 4) != 0) panic("TreePtrList_Append: using uninitialized list"); #endif TreePtrList_Grow(tplPtr, tplPtr->count + 1); tplPtr->pointers[tplPtr->count] = pointer; tplPtr->count++; tplPtr->pointers[tplPtr->count] = NULL; return tplPtr->pointers; } /* *---------------------------------------------------------------------- * * TreePtrList_Concat -- * * Join two pointer lists. * * Results: * The return value is a pointer to the list of pointers. * * Side effects: * Memory gets reallocated if needed. * *---------------------------------------------------------------------- */ ClientData * TreePtrList_Concat( TreePtrList *tplPtr, /* Structure describing pointer list. */ TreePtrList *tpl2Ptr /* Item list to append. */ ) { #ifdef TREECTRL_DEBUG if (strncmp(tplPtr->magic, "MAGC", 4) != 0) panic("TreePtrList_Concat: using uninitialized list"); #endif TreePtrList_Grow(tplPtr, tplPtr->count + tpl2Ptr->count); memcpy(tplPtr->pointers + tplPtr->count, tpl2Ptr->pointers, tpl2Ptr->count * sizeof(ClientData)); tplPtr->count += tpl2Ptr->count; tplPtr->pointers[tplPtr->count] = NULL; return tplPtr->pointers; } /* *---------------------------------------------------------------------- * * TreePtrList_Free -- * * Frees up any memory allocated for the pointer list and * reinitializes the pointer list to an empty state. * * Results: * None. * * Side effects: * The previous contents of the pointer list are lost. * *---------------------------------------------------------------------- */ void TreePtrList_Free( TreePtrList *tplPtr /* Structure describing pointer list. */ ) { #ifdef TREECTRL_DEBUG if (strncmp(tplPtr->magic, "MAGC", 4) != 0) panic("TreePtrList_Free: using uninitialized list"); #endif if (tplPtr->pointers != tplPtr->pointerSpace) { ckfree((char *) tplPtr->pointers); } tplPtr->pointers = tplPtr->pointerSpace; tplPtr->count = 0; tplPtr->space = TIL_STATIC_SPACE; tplPtr->pointers[0] = NULL; } #define TAG_INFO_SIZE(tagSpace) \ (Tk_Offset(TagInfo, tagPtr) + ((tagSpace) * sizeof(Tk_Uid))) static CONST char *TagInfoUid = "TagInfo"; /* *---------------------------------------------------------------------- * * TagInfo_Add -- * * Adds tags to a list of tags. * * Results: * Non-duplicate tags are added. * * Side effects: * Memory may be (re)allocated. * *---------------------------------------------------------------------- */ TagInfo * TagInfo_Add( TreeCtrl *tree, /* Widget info. */ TagInfo *tagInfo, /* Tag list. May be NULL. */ Tk_Uid tags[], int numTags ) { int i, j; if (tagInfo == NULL) { if (numTags <= TREE_TAG_SPACE) { #ifdef ALLOC_HAX tagInfo = (TagInfo *) TreeAlloc_Alloc(tree->allocData, TagInfoUid, sizeof(TagInfo)); #else tagInfo = (TagInfo *) ckalloc(sizeof(TagInfo)); #endif tagInfo->tagSpace = TREE_TAG_SPACE; } else { int tagSpace = (numTags / TREE_TAG_SPACE) * TREE_TAG_SPACE + ((numTags % TREE_TAG_SPACE) ? TREE_TAG_SPACE : 0); if (tagSpace % TREE_TAG_SPACE) panic("TagInfo_Add miscalc"); #ifdef ALLOC_HAX tagInfo = (TagInfo *) TreeAlloc_Alloc(tree->allocData, TagInfoUid, TAG_INFO_SIZE(tagSpace)); #else tagInfo = (TagInfo *) ckalloc(TAG_INFO_SIZE(tagSpace)); #endif tagInfo->tagSpace = tagSpace; } tagInfo->numTags = 0; } for (i = 0; i < numTags; i++) { for (j = 0; j < tagInfo->numTags; j++) { if (tagInfo->tagPtr[j] == tags[i]) break; } if (j >= tagInfo->numTags) { /* Resize existing storage if needed. */ if (tagInfo->tagSpace == tagInfo->numTags) { tagInfo->tagSpace += TREE_TAG_SPACE; #ifdef ALLOC_HAX tagInfo = (TagInfo *) TreeAlloc_Realloc(tree->allocData, TagInfoUid, (char *) tagInfo, TAG_INFO_SIZE(tagInfo->tagSpace - TREE_TAG_SPACE), TAG_INFO_SIZE(tagInfo->tagSpace)); #else tagInfo = (TagInfo *) ckrealloc((char *) tagInfo, TAG_INFO_SIZE(tagInfo->tagSpace)); #endif } tagInfo->tagPtr[tagInfo->numTags++] = tags[i]; } } return tagInfo; } /* *---------------------------------------------------------------------- * * TagInfo_Remove -- * * Removes tags from a list of tags. * * Results: * Existing tags are removed. * * Side effects: * Memory may be reallocated. * *---------------------------------------------------------------------- */ TagInfo * TagInfo_Remove( TreeCtrl *tree, /* Widget info. */ TagInfo *tagInfo, /* Tag list. May be NULL. */ Tk_Uid tags[], int numTags ) { int i, j; if (tagInfo == NULL) return tagInfo; for (i = 0; i < numTags; i++) { for (j = 0; j < tagInfo->numTags; j++) { if (tagInfo->tagPtr[j] == tags[i]) { tagInfo->tagPtr[j] = tagInfo->tagPtr[tagInfo->numTags - 1]; tagInfo->numTags--; break; } } } if (tagInfo->numTags == 0) { TagInfo_Free(tree, tagInfo); tagInfo = NULL; } return tagInfo; } /* *---------------------------------------------------------------------- * * TagInfo_Names -- * * Build a list of unique tag names. * * Results: * Unique tags are added to a dynamically-allocated list. * * Side effects: * Memory may be (re)allocated. * *---------------------------------------------------------------------- */ Tk_Uid * TagInfo_Names( TreeCtrl *tree, /* Widget info. */ TagInfo *tagInfo, /* Tag list. May be NULL. */ Tk_Uid *tags, /* Current list, may be NULL. */ int *numTagsPtr, /* Number of tags in tags[]. */ int *tagSpacePtr /* Size of tags[]. */ ) { int numTags = *numTagsPtr, tagSpace = *tagSpacePtr; int i, j; if (tagInfo == NULL) return tags; for (i = 0; i < tagInfo->numTags; i++) { Tk_Uid tag = tagInfo->tagPtr[i]; for (j = 0; j < numTags; j++) { if (tag == tags[j]) break; } if (j < numTags) continue; if ((tags == NULL) || (numTags == tagSpace)) { if (tags == NULL) { tagSpace = 32; tags = (Tk_Uid *) ckalloc(sizeof(Tk_Uid) * tagSpace); } else { tagSpace *= 2; tags = (Tk_Uid *) ckrealloc((char *) tags, sizeof(Tk_Uid) * tagSpace); } } tags[numTags++] = tag; } *numTagsPtr = numTags; *tagSpacePtr = tagSpace; return tags; } /* *---------------------------------------------------------------------- * * TagInfo_Copy -- * * Copy a list of tags. * * Results: * Allocates a new TagInfo if given one is not NULL. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ TagInfo * TagInfo_Copy( TreeCtrl *tree, /* Widget info. */ TagInfo *tagInfo /* Tag list. May be NULL. */ ) { TagInfo *copy = NULL; if (tagInfo != NULL) { int tagSpace = tagInfo->tagSpace; #ifdef ALLOC_HAX copy = (TagInfo *) TreeAlloc_Alloc(tree->allocData, TagInfoUid, TAG_INFO_SIZE(tagSpace)); #else copy = (TagInfo *) ckalloc(TAG_INFO_SIZE(tagSpace)); #endif memcpy((void *) copy->tagPtr, tagInfo->tagPtr, tagInfo->numTags * sizeof(Tk_Uid)); copy->numTags = tagInfo->numTags; copy->tagSpace = tagSpace; } return copy; } /* *---------------------------------------------------------------------- * * TagInfo_Free -- * * Free a list of tags. * * Results: * TagInfo struct is freed if non-NULL. * * Side effects: * Memory may be freed. * *---------------------------------------------------------------------- */ void TagInfo_Free( TreeCtrl *tree, /* Widget info. */ TagInfo *tagInfo /* Tag list. May be NULL. */ ) { if (tagInfo != NULL) #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, TagInfoUid, (char *) tagInfo, TAG_INFO_SIZE(tagInfo->tagSpace)); #else ckfree((char *) tagInfo); #endif } int TagInfo_FromObj( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *objPtr, TagInfo **tagInfoPtr ) { int i, numTags; Tcl_Obj **listObjv; TagInfo *tagInfo = NULL; if (Tcl_ListObjGetElements(tree->interp, objPtr, &numTags, &listObjv) != TCL_OK) { return TCL_ERROR; } if (numTags == 0) { *tagInfoPtr = NULL; return TCL_OK; } for (i = 0; i < numTags; i++) { Tk_Uid tag = Tk_GetUid(Tcl_GetString(listObjv[i])); tagInfo = TagInfo_Add(tree, tagInfo, &tag, 1); } *tagInfoPtr = tagInfo; return TCL_OK; } Tcl_Obj * TagInfo_ToObj( TreeCtrl *tree, /* Widget info. */ TagInfo *tagInfo ) { Tcl_Obj *listObj; int i; if (tagInfo == NULL) return NULL; listObj = Tcl_NewListObj(0, NULL); for (i = 0; i < tagInfo->numTags; i++) { Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewStringObj((char *) tagInfo->tagPtr[i], -1)); } return listObj; } /* *---------------------------------------------------------------------- * * TagInfoCO_Set -- * TagInfoCO_Get -- * TagInfoCO_Restore -- * TagInfoCO_Free -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a TagInfo record. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TagInfoCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; int objEmpty; TagInfo *new, **internalPtr; if (internalOffset >= 0) internalPtr = (TagInfo **) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*value)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*value) = NULL; else { if (TagInfo_FromObj(tree, (*value), &new) != TCL_OK) return TCL_ERROR; } if (internalPtr != NULL) { if ((*value) == NULL) new = NULL; *((TagInfo **) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj * TagInfoCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; TagInfo *value = *(TagInfo **) (recordPtr + internalOffset); return TagInfo_ToObj(tree, value); } static void TagInfoCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { *(TagInfo **) internalPtr = *(TagInfo **) saveInternalPtr; } static void TagInfoCO_Free( ClientData clientData, /* unused. */ Tk_Window tkwin, /* A window; unused */ char *internalPtr /* Pointer to the place, where the internal * form resides. */ ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; TagInfo_Free(tree, *(TagInfo **)internalPtr); } Tk_ObjCustomOption TreeCtrlCO_tagInfo = { "tag list", TagInfoCO_Set, TagInfoCO_Get, TagInfoCO_Restore, TagInfoCO_Free, (ClientData) NULL }; /* *---------------------------------------------------------------------- * * TagExpr_Init -- * * This procedure initializes a TagExpr struct by parsing a Tcl_Obj * string representation of a tag expression. * * Results: * A standard Tcl result. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ int TagExpr_Init( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *exprObj, /* Tag expression string. */ TagExpr *expr /* Struct to initialize. */ ) { int i; char *tag; expr->tree = tree; expr->index = 0; expr->length = 0; expr->uid = NULL; expr->allocated = sizeof(expr->staticUids) / sizeof(Tk_Uid); expr->uids = expr->staticUids; expr->simple = TRUE; expr->rewritebuffer = expr->staticRWB; tag = Tcl_GetStringFromObj(exprObj, &expr->stringLength); /* short circuit impossible searches for null tags */ if (expr->stringLength == 0) { return TCL_OK; } /* * Pre-scan tag for at least one unquoted "&&" "||" "^" "!" * if not found then use string as simple tag */ for (i = 0; i < expr->stringLength ; i++) { if (tag[i] == '"') { i++; for ( ; i < expr->stringLength; i++) { if (tag[i] == '\\') { i++; continue; } if (tag[i] == '"') { break; } } } else { if ((tag[i] == '&' && tag[i+1] == '&') || (tag[i] == '|' && tag[i+1] == '|') || (tag[i] == '^') || (tag[i] == '!')) { expr->simple = FALSE; break; } } } if (expr->simple) { expr->uid = Tk_GetUid(tag); return TCL_OK; } expr->string = tag; expr->stringIndex = 0; /* Allocate buffer for rewritten tags (after de-escaping) */ if (expr->stringLength >= sizeof(expr->staticRWB)) expr->rewritebuffer = ckalloc(expr->stringLength + 1); if (TagExpr_Scan(expr) != TCL_OK) { TagExpr_Free(expr); return TCL_ERROR; } expr->length = expr->index; return TCL_OK; } /* * Uids for operands in compiled tag expressions. * Initialization is done by GetStaticUids(). */ typedef struct { Tk_Uid andUid; Tk_Uid orUid; Tk_Uid xorUid; Tk_Uid parenUid; Tk_Uid negparenUid; Tk_Uid endparenUid; Tk_Uid tagvalUid; Tk_Uid negtagvalUid; } SearchUids; static Tcl_ThreadDataKey searchUidTDK; /* *---------------------------------------------------------------------- * * GetStaticUids -- * * This procedure is invoked to return a structure filled with * the Uids used when doing tag searching. If it was never before * called in the current thread, it initializes the structure for * that thread (uids are only ever local to one thread [Bug * 1114977]). * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static SearchUids * GetStaticUids() { SearchUids *searchUids = (SearchUids *) Tcl_GetThreadData(&searchUidTDK, sizeof(SearchUids)); if (searchUids->andUid == NULL) { searchUids->andUid = Tk_GetUid("&&"); searchUids->orUid = Tk_GetUid("||"); searchUids->xorUid = Tk_GetUid("^"); searchUids->parenUid = Tk_GetUid("("); searchUids->endparenUid = Tk_GetUid(")"); searchUids->negparenUid = Tk_GetUid("!("); searchUids->tagvalUid = Tk_GetUid("!!"); searchUids->negtagvalUid = Tk_GetUid("!"); } return searchUids; } /* *---------------------------------------------------------------------- * * TagExpr_Scan -- * * This procedure recursively parses a string representation of a * tag expression into an array of Tk_Uids. * * Results: * The return value indicates if the tag expression * was successfully scanned (syntax). * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ int TagExpr_Scan( TagExpr *expr /* Info about a tag expression. */ ) { Tcl_Interp *interp = expr->tree->interp; int looking_for_tag; /* When true, scanner expects * next char(s) to be a tag, * else operand expected */ int found_tag; /* One or more tags found */ int found_endquote; /* For quoted tag string parsing */ int negate_result; /* Pending negation of next tag value */ char *tag; /* tag from tag expression string */ SearchUids *searchUids; /* Collection of uids for basic search * expression terms. */ char c; searchUids = GetStaticUids(); negate_result = 0; found_tag = 0; looking_for_tag = 1; while (expr->stringIndex < expr->stringLength) { c = expr->string[expr->stringIndex++]; if (expr->allocated == expr->index) { expr->allocated += 15; if (expr->uids != expr->staticUids) { expr->uids = (Tk_Uid *) ckrealloc((char *)(expr->uids), (expr->allocated)*sizeof(Tk_Uid)); } else { expr->uids = (Tk_Uid *) ckalloc((expr->allocated)*sizeof(Tk_Uid)); memcpy((void *) expr->uids, expr->staticUids, sizeof(expr->staticUids)); } } if (looking_for_tag) { switch (c) { case ' ' : /* ignore unquoted whitespace */ case '\t' : case '\n' : case '\r' : break; case '!' : /* negate next tag or subexpr */ if (looking_for_tag > 1) { Tcl_AppendResult(interp, "Too many '!' in tag search expression", (char *) NULL); return TCL_ERROR; } looking_for_tag++; negate_result = 1; break; case '(' : /* scan (negated) subexpr recursively */ if (negate_result) { expr->uids[expr->index++] = searchUids->negparenUid; negate_result = 0; } else { expr->uids[expr->index++] = searchUids->parenUid; } if (TagExpr_Scan(expr) != TCL_OK) { /* Result string should be already set * by nested call to tag_expr_scan() */ return TCL_ERROR; } looking_for_tag = 0; found_tag = 1; break; case '"' : /* quoted tag string */ if (negate_result) { expr->uids[expr->index++] = searchUids->negtagvalUid; negate_result = 0; } else { expr->uids[expr->index++] = searchUids->tagvalUid; } tag = expr->rewritebuffer; found_endquote = 0; while (expr->stringIndex < expr->stringLength) { c = expr->string[expr->stringIndex++]; if (c == '\\') { c = expr->string[expr->stringIndex++]; } if (c == '"') { found_endquote = 1; break; } *tag++ = c; } if (! found_endquote) { Tcl_AppendResult(interp, "Missing endquote in tag search expression", (char *) NULL); return TCL_ERROR; } if (! (tag - expr->rewritebuffer)) { Tcl_AppendResult(interp, "Null quoted tag string in tag search expression", (char *) NULL); return TCL_ERROR; } *tag++ = '\0'; expr->uids[expr->index++] = Tk_GetUid(expr->rewritebuffer); looking_for_tag = 0; found_tag = 1; break; case '&' : /* illegal chars when looking for tag */ case '|' : case '^' : case ')' : Tcl_AppendResult(interp, "Unexpected operator in tag search expression", (char *) NULL); return TCL_ERROR; default : /* unquoted tag string */ if (negate_result) { expr->uids[expr->index++] = searchUids->negtagvalUid; negate_result = 0; } else { expr->uids[expr->index++] = searchUids->tagvalUid; } tag = expr->rewritebuffer; *tag++ = c; /* copy rest of tag, including any embedded whitespace */ while (expr->stringIndex < expr->stringLength) { c = expr->string[expr->stringIndex]; if (c == '!' || c == '&' || c == '|' || c == '^' || c == '(' || c == ')' || c == '"') { break; } *tag++ = c; expr->stringIndex++; } /* remove trailing whitespace */ while (1) { c = *--tag; /* there must have been one non-whitespace char, * so this will terminate */ if (c != ' ' && c != '\t' && c != '\n' && c != '\r') { break; } } *++tag = '\0'; expr->uids[expr->index++] = Tk_GetUid(expr->rewritebuffer); looking_for_tag = 0; found_tag = 1; } } else { /* ! looking_for_tag */ switch (c) { case ' ' : /* ignore whitespace */ case '\t' : case '\n' : case '\r' : break; case '&' : /* AND operator */ c = expr->string[expr->stringIndex++]; if (c != '&') { Tcl_AppendResult(interp, "Singleton '&' in tag search expression", (char *) NULL); return TCL_ERROR; } expr->uids[expr->index++] = searchUids->andUid; looking_for_tag = 1; break; case '|' : /* OR operator */ c = expr->string[expr->stringIndex++]; if (c != '|') { Tcl_AppendResult(interp, "Singleton '|' in tag search expression", (char *) NULL); return TCL_ERROR; } expr->uids[expr->index++] = searchUids->orUid; looking_for_tag = 1; break; case '^' : /* XOR operator */ expr->uids[expr->index++] = searchUids->xorUid; looking_for_tag = 1; break; case ')' : /* end subexpression */ expr->uids[expr->index++] = searchUids->endparenUid; goto breakwhile; default : /* syntax error */ Tcl_AppendResult(interp, "Invalid boolean operator in tag search expression", (char *) NULL); return TCL_ERROR; } } } breakwhile: if (found_tag && ! looking_for_tag) { return TCL_OK; } Tcl_AppendResult(interp, "Missing tag in tag search expression", (char *) NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TagExpr_Eval -- * * This procedure recursively evaluates a compiled tag expression. * * Results: * The return value indicates if the tag expression * successfully matched the tags of the given item. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int _TagExpr_Eval( TagExpr *expr, /* Info about a tag expression. */ TagInfo *tagInfo /* Tags to test. */ ) { int looking_for_tag; /* When true, scanner expects * next char(s) to be a tag, * else operand expected */ int negate_result; /* Pending negation of next tag value */ Tk_Uid uid; Tk_Uid *tagPtr; int count; int result; /* Value of expr so far */ int parendepth; SearchUids *searchUids; /* Collection of uids for basic search * expression terms. */ TagInfo dummy; if (expr->stringLength == 0) /* empty expression (an error?) */ return 0; /* No tags given. */ if (tagInfo == NULL) { dummy.numTags = 0; tagInfo = &dummy; } /* A single tag. */ if (expr->simple) { for (tagPtr = tagInfo->tagPtr, count = tagInfo->numTags; count > 0; tagPtr++, count--) { if (*tagPtr == expr->uid) { return 1; } } return 0; } searchUids = GetStaticUids(); result = 0; /* just to keep the compiler quiet */ negate_result = 0; looking_for_tag = 1; while (expr->index < expr->length) { uid = expr->uids[expr->index++]; if (looking_for_tag) { if (uid == searchUids->tagvalUid) { /* * assert(expr->index < expr->length); */ uid = expr->uids[expr->index++]; result = 0; /* * set result 1 if tag is found in item's tags */ for (tagPtr = tagInfo->tagPtr, count = tagInfo->numTags; count > 0; tagPtr++, count--) { if (*tagPtr == uid) { result = 1; break; } } } else if (uid == searchUids->negtagvalUid) { negate_result = ! negate_result; /* * assert(expr->index < expr->length); */ uid = expr->uids[expr->index++]; result = 0; /* * set result 1 if tag is found in item's tags */ for (tagPtr = tagInfo->tagPtr, count = tagInfo->numTags; count > 0; tagPtr++, count--) { if (*tagPtr == uid) { result = 1; break; } } } else if (uid == searchUids->parenUid) { /* * evaluate subexpressions with recursion */ result = _TagExpr_Eval(expr, tagInfo); } else if (uid == searchUids->negparenUid) { negate_result = ! negate_result; /* * evaluate subexpressions with recursion */ result = _TagExpr_Eval(expr, tagInfo); /* * } else { * assert(0); */ } if (negate_result) { result = ! result; negate_result = 0; } looking_for_tag = 0; } else { /* ! looking_for_tag */ if (((uid == searchUids->andUid) && (!result)) || ((uid == searchUids->orUid) && result)) { /* * short circuit expression evaluation * * if result before && is 0, or result before || is 1, * then the expression is decided and no further * evaluation is needed. */ parendepth = 0; while (expr->index < expr->length) { uid = expr->uids[expr->index++]; if (uid == searchUids->tagvalUid || uid == searchUids->negtagvalUid) { expr->index++; continue; } if (uid == searchUids->parenUid || uid == searchUids->negparenUid) { parendepth++; continue; } if (uid == searchUids->endparenUid) { parendepth--; if (parendepth < 0) { break; } } } return result; } else if (uid == searchUids->xorUid) { /* * if the previous result was 1 * then negate the next result */ negate_result = result; } else if (uid == searchUids->endparenUid) { return result; /* * } else { * assert(0); */ } looking_for_tag = 1; } } /* * assert(! looking_for_tag); */ return result; } int TagExpr_Eval( TagExpr *expr, /* Info about a tag expression. */ TagInfo *tagInfo /* Tags to test. */ ) { expr->index = 0; return _TagExpr_Eval(expr, tagInfo); } /* *---------------------------------------------------------------------- * * TagExpr_Free -- * * This procedure frees the given struct. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TagExpr_Free( TagExpr *expr ) { if (expr->rewritebuffer != expr->staticRWB) ckfree(expr->rewritebuffer); if (expr->uids != expr->staticUids) ckfree((char *) expr->uids); } /* *---------------------------------------------------------------------- * * OptionHax_Remember -- * OptionHax_Forget -- * * These procedures are used to work around a limitation in * the Tk_SavedOption structure: the internal form of a configuration * option cannot be larger than a double. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void OptionHax_Remember( TreeCtrl *tree, char *ptr ) { #ifdef TREECTRL_DEBUG int i; for (i = 0; i < tree->optionHaxCnt; i++) { if (ptr == tree->optionHax[i]) { panic("OptionHax_Remember: ptr is not new"); } } if (tree->optionHaxCnt == sizeof(tree->optionHax) / sizeof(tree->optionHax[0])) panic("OptionHax_Remember: too many options"); #endif tree->optionHax[tree->optionHaxCnt++] = ptr; /*dbwin("OptionHax_Remember %p\n", ptr);*/ } static int OptionHax_Forget( TreeCtrl *tree, char *ptr ) { int i; for (i = 0; i < tree->optionHaxCnt; i++) { if (ptr == tree->optionHax[i]) { tree->optionHax[i] = tree->optionHax[--tree->optionHaxCnt]; /*dbwin("OptionHax_Forget %p\n", ptr);*/ return 1; } } return 0; } /* *---------------------------------------------------------------------- * * Tree_FindOptionSpec -- * * Return a pointer to a name Tk_OptionSpec in a table. * * Results: * Returns a pointer or panics. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tk_OptionSpec * Tree_FindOptionSpec( Tk_OptionSpec *optionTable, CONST char *optionName ) { while (optionTable->type != TK_OPTION_END) { if (strcmp(optionTable->optionName, optionName) == 0) return optionTable; optionTable++; } panic("Tree_FindOptionSpec: can't find %s", optionName); return NULL; } /* *---------------------------------------------------------------------- * * PerStateCO_Set -- * PerStateCO_Get -- * PerStateCO_Restore -- * PerStateCO_Free -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a PerStateInfo record. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ typedef struct PerStateCOClientData { PerStateType *typePtr; StateFromObjProc proc; } PerStateCOClientData; static int PerStateCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { PerStateCOClientData *cd = (PerStateCOClientData *) clientData; TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; int objEmpty; PerStateInfo new, *internalPtr, *hax; if (internalOffset >= 0) internalPtr = (PerStateInfo *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*value)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*value) = NULL; else { new.obj = (*value); new.data = NULL; new.count = 0; /* Tcl_IncrRefCount((*value));*/ if (PerStateInfo_FromObj(tree, cd->proc, cd->typePtr, &new) != TCL_OK) { /* Tcl_DecrRefCount((*value));*/ return TCL_ERROR; } } if (internalPtr != NULL) { if ((*value) == NULL) { new.obj = NULL; new.data = NULL; new.count = 0; } OptionHax_Remember(tree, saveInternalPtr); if (internalPtr->obj != NULL) { hax = (PerStateInfo *) ckalloc(sizeof(PerStateInfo)); *hax = *internalPtr; *((PerStateInfo **) saveInternalPtr) = hax; } else { *((PerStateInfo **) saveInternalPtr) = NULL; } *internalPtr = new; /*dbwin("PerStateCO_Set %p %s\n", internalPtr, cd->typePtr->name);*/ } return TCL_OK; } static Tcl_Obj * PerStateCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { PerStateInfo *value = (PerStateInfo *) (recordPtr + internalOffset); return value->obj; /* May be NULL. */ } static void PerStateCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; PerStateInfo *psi = (PerStateInfo *) internalPtr; PerStateInfo *hax = *(PerStateInfo **) saveInternalPtr; /*dbwin("PerStateCO_Restore\n");*/ if (hax != NULL) { #ifdef TREECTRL_DEBUG psi->type = hax->type; #endif psi->data = hax->data; psi->count = hax->count; ckfree((char *) hax); } else { #ifdef TREECTRL_DEBUG psi->type = NULL; #endif /* psi->obj = NULL;*/ psi->data = NULL; psi->count = 0; } OptionHax_Forget(tree, saveInternalPtr); } static void PerStateCO_Free( ClientData clientData, /* unused. */ Tk_Window tkwin, /* A window; unused */ char *internalPtr /* Pointer to the place, where the internal * form resides. */ ) { PerStateCOClientData *cd = (PerStateCOClientData *) clientData; TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; PerStateInfo *hax; Tcl_Obj *objPtr = NULL; if (OptionHax_Forget(tree, internalPtr)) { hax = *(PerStateInfo **) internalPtr; if (hax != NULL) { objPtr = hax->obj; PerStateInfo_Free(tree, cd->typePtr, hax); ckfree((char *) hax); } } else { /*dbwin("PerStateCO_Free %p %s\n", internalPtr, cd->typePtr->name);*/ objPtr = ((PerStateInfo *) internalPtr)->obj; PerStateInfo_Free(tree, cd->typePtr, (PerStateInfo *) internalPtr); } /* if (objPtr != NULL) Tcl_DecrRefCount(objPtr);*/ } /* *---------------------------------------------------------------------- * * PerStateCO_Alloc -- * * Allocates a Tk_ObjCustomOption record and clientData. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tk_ObjCustomOption * PerStateCO_Alloc( CONST char *optionName, PerStateType *typePtr, StateFromObjProc proc ) { PerStateCOClientData *cd; Tk_ObjCustomOption *co; /* ClientData for the Tk custom option record */ cd = (PerStateCOClientData *) ckalloc(sizeof(PerStateCOClientData)); cd->typePtr = typePtr; cd->proc = proc; /* The Tk custom option record */ co = (Tk_ObjCustomOption *) ckalloc(sizeof(Tk_ObjCustomOption)); co->name = (char *) optionName + 1; co->setProc = PerStateCO_Set; co->getProc = PerStateCO_Get; co->restoreProc = PerStateCO_Restore; co->freeProc = PerStateCO_Free; co->clientData = (ClientData) cd; return co; } /* *---------------------------------------------------------------------- * * PerStateCO_Init -- * * Initializes a Tk_OptionSpec.clientData for a custom option. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ int PerStateCO_Init( Tk_OptionSpec *optionTable, CONST char *optionName, PerStateType *typePtr, StateFromObjProc proc ) { Tk_OptionSpec *specPtr; specPtr = Tree_FindOptionSpec(optionTable, optionName); if (specPtr->type != TK_OPTION_CUSTOM) panic("PerStateCO_Init: %s is not TK_OPTION_CUSTOM", optionName); if (specPtr->clientData != NULL) return TCL_OK; specPtr->clientData = PerStateCO_Alloc(optionName, typePtr, proc); return TCL_OK; } #define DEBUG_DYNAMICxxx static CONST char *DynamicOptionUid = "DynamicOption"; /* *---------------------------------------------------------------------- * * DynamicOption_Find -- * * Returns a pointer to a dynamic-option record or NULL. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ DynamicOption * DynamicOption_Find( DynamicOption *first, /* Head of linked list. */ int id /* Unique id. */ ) { DynamicOption *opt = first; while (opt != NULL) { if (opt->id == id) return opt; opt = opt->next; } return NULL; } /* *---------------------------------------------------------------------- * * DynamicOption_FindData -- * * Returns a pointer to the option-specific data for a * dynamic-option record or NULL. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void * DynamicOption_FindData( DynamicOption *first, /* Head of linked list. */ int id /* Unique id. */ ) { DynamicOption *opt = DynamicOption_Find(first, id); if (opt != NULL) return opt->data; return NULL; } /* *---------------------------------------------------------------------- * * DynamicOption_AllocIfNeeded -- * * Returns a pointer to a dynamic-option record. * * Results: * If the dynamic-option record exists, it is returned. Otherwise * a new one is allocated and initialized. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ DynamicOption * DynamicOption_AllocIfNeeded( TreeCtrl *tree, DynamicOption **firstPtr, /* Pointer to the head of linked list. * Will be updated if a new record is * created. */ int id, /* Unique id. */ int size, /* Size of option-specific data. */ DynamicOptionInitProc *init /* Proc to intialize the option-specific * data. May be NULL. */ ) { DynamicOption *opt = *firstPtr; while (opt != NULL) { if (opt->id == id) return opt; opt = opt->next; } #ifdef DEBUG_DYNAMIC dbwin("DynamicOption_AllocIfNeeded allocated id=%d\n", id); #endif #ifdef ALLOC_HAX opt = (DynamicOption *) TreeAlloc_Alloc(tree->allocData, DynamicOptionUid, Tk_Offset(DynamicOption, data) + size); #else opt = (DynamicOption *) ckalloc(Tk_Offset(DynamicOption, data) + size); #endif opt->id = id; memset(opt->data, '\0', size); if (init != NULL) (*init)(opt->data); opt->next = *firstPtr; *firstPtr = opt; return opt; } /* *---------------------------------------------------------------------- * * DynamicCO_Set -- * DynamicCO_Get -- * DynamicCO_Restore -- * DynamicCO_Free -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a DynamicOption record. * * A dynamic option is one for which storage is not allocated until * the option is configured for the first time. Dynamic options are * saved in a linked list. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* This is the Tk_OptionSpec.clientData field for a dynamic option. */ typedef struct DynamicCOClientData { int id; /* Unique id. */ int size; /* Size of client data. */ int objOffset; /* Offset in the client data to store the * object representation of the option. * May be < 0. */ int internalOffset; /* Offset in the client data to store the * internal representation of the option. * May be < 0. */ Tk_ObjCustomOption *custom; /* Table of procedures and clientData for * the actual option. */ DynamicOptionInitProc *init;/* This gets called to initialize the client * data when it is first allocated. May be * NULL. */ } DynamicCOClientData; /* This is used to save the current value of an option when a call to * Tk_SetOptions is in progress. */ typedef struct DynamicCOSave { Tcl_Obj *objPtr; /* The object representation of the option. */ double internalForm; /* The internal form of the option. */ } DynamicCOSave; static int DynamicCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; DynamicCOClientData *cd = clientData; DynamicOption **firstPtr, *opt; DynamicCOSave *save; Tcl_Obj **objPtrPtr = NULL; /* Get pointer to the head of the list of dynamic options. */ firstPtr = (DynamicOption **) (recordPtr + internalOffset); /* Get the dynamic option record. Create it if needed, and update the * linked list of dynamic options. */ opt = DynamicOption_AllocIfNeeded(tree, firstPtr, cd->id, cd->size, cd->init); if (cd->objOffset >= 0) objPtrPtr = (Tcl_Obj **) (opt->data + cd->objOffset); save = (DynamicCOSave *) ckalloc(sizeof(DynamicCOSave)); #ifdef DEBUG_DYNAMIC dbwin("DynamicCO_Set id=%d saveInternalPtr=%p save=%p\n", cd->id, saveInternalPtr, save); #endif if (objPtrPtr != NULL) { save->objPtr = *objPtrPtr; #ifdef DEBUG_DYNAMIC if (save->objPtr) dbwin(" old object '%s' refCount=%d\n", Tcl_GetString(save->objPtr), save->objPtr->refCount); else dbwin(" old object NULL\n"); #endif } if (cd->custom->setProc(cd->custom->clientData, interp, tkwin, value, opt->data, cd->internalOffset, (char *) &save->internalForm, flags) != TCL_OK) { ckfree((char *) save); return TCL_ERROR; } if (objPtrPtr != NULL) { #ifdef DEBUG_DYNAMIC if (*value) dbwin(" new object '%s' refCount=%d\n", Tcl_GetString(*value), (*value)->refCount); else dbwin(" new object NULL\n"); #endif *objPtrPtr = *value; if (*value != NULL) Tcl_IncrRefCount(*value); } *(DynamicCOSave **) saveInternalPtr = save; OptionHax_Remember(tree, saveInternalPtr); return TCL_OK; } static Tcl_Obj * DynamicCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { DynamicCOClientData *cd = clientData; DynamicOption *first = *(DynamicOption **) (recordPtr + internalOffset); DynamicOption *opt = DynamicOption_Find(first, cd->id); #ifdef DEBUG_DYNAMIC dbwin("DynamicCO_Get id=%d opt=%p objOffset=%d\n", cd->id, opt, cd->objOffset); #endif if (opt == NULL) return NULL; if (cd->objOffset >= 0) { #ifdef TREECTRL_DEBUG Tcl_Obj *objPtr = *(Tcl_Obj **) (opt->data + cd->objOffset); if (objPtr && objPtr->refCount == 0) panic("DynamicCO_Get refCount=0"); #endif return *(Tcl_Obj **) (opt->data + cd->objOffset); } if (cd->custom->getProc != NULL) return cd->custom->getProc(cd->custom->clientData, tkwin, opt->data, cd->internalOffset); return NULL; } static void DynamicCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; DynamicCOClientData *cd = clientData; DynamicOption *first = *(DynamicOption **) internalPtr; DynamicOption *opt = DynamicOption_Find(first, cd->id); DynamicCOSave *save = *(DynamicCOSave **)saveInternalPtr; Tcl_Obj **objPtrPtr; if (opt == NULL) panic("DynamicCO_Restore: opt=NULL"); #ifdef DEBUG_DYNAMIC dbwin("DynamicCO_Restore id=%d internalOffset=%d save=%p\n", cd->id, cd->internalOffset, save); #endif if (cd->internalOffset >= 0 && cd->custom->restoreProc != NULL) cd->custom->restoreProc(cd->custom->clientData, tkwin, opt->data + cd->internalOffset, (char *) &save->internalForm); if (cd->objOffset >= 0) { objPtrPtr = (Tcl_Obj **) (opt->data + cd->objOffset); #ifdef DEBUG_DYNAMIC if (*objPtrPtr) dbwin("DynamicCO_Restore replace object '%s' refCount=%d\n", Tcl_GetString(*objPtrPtr), (*objPtrPtr)->refCount); else dbwin("DynamicCO_Restore replace object NULL\n"); if (save->objPtr) dbwin("DynamicCO_Restore restore object '%s' refCount=%d\n", Tcl_GetString(save->objPtr), save->objPtr->refCount); else dbwin("DynamicCO_Restore restore object NULL\n"); #endif /* if (*objPtrPtr != NULL) Tcl_DecrRefCount(*objPtrPtr);*/ *objPtrPtr = save->objPtr; } ckfree((char *) save); OptionHax_Forget(tree, saveInternalPtr); } static void DynamicCO_Free( ClientData clientData, Tk_Window tkwin, char *internalPtr ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; DynamicCOClientData *cd = clientData; Tcl_Obj **objPtrPtr; if (OptionHax_Forget(tree, internalPtr)) { DynamicCOSave *save = *(DynamicCOSave **) internalPtr; #ifdef DEBUG_DYNAMIC dbwin("DynamicCO_Free id=%d internalPtr=%p save=%p\n", cd->id, internalPtr, save); #endif if (cd->internalOffset >= 0 && cd->custom->freeProc != NULL) cd->custom->freeProc(cd->custom->clientData, tkwin, (char *) &save->internalForm); if (cd->objOffset >= 0) { #ifdef DEBUG_DYNAMIC if (save->objPtr) { dbwin("DynamicCO_Free free object '%s' refCount=%d-1\n", Tcl_GetString(save->objPtr), (save->objPtr)->refCount); if (save->objPtr->refCount == 0) panic("DynamicCO_Free refCount=0"); } else dbwin("DynamicCO_Free free object NULL\n"); #endif if (save->objPtr) { Tcl_DecrRefCount(save->objPtr); } } ckfree((char *) save); } else { DynamicOption *first = *(DynamicOption **) internalPtr; DynamicOption *opt = DynamicOption_Find(first, cd->id); #ifdef DEBUG_DYNAMIC dbwin("DynamicCO_Free id=%d internalPtr=%p save=NULL\n", cd->id, internalPtr); #endif if (opt != NULL && cd->internalOffset >= 0 && cd->custom->freeProc != NULL) cd->custom->freeProc(cd->custom->clientData, tkwin, opt->data + cd->internalOffset); if (opt != NULL && cd->objOffset >= 0) { objPtrPtr = (Tcl_Obj **) (opt->data + cd->objOffset); #ifdef DEBUG_DYNAMIC if (*objPtrPtr) { dbwin("DynamicCO_Free free object '%s' refCount=%d-1\n", Tcl_GetString(*objPtrPtr), (*objPtrPtr)->refCount); if ((*objPtrPtr)->refCount == 0) panic("DynamicCO_Free refCount=0"); } else dbwin("DynamicCO_Free free object NULL\n"); #endif if (*objPtrPtr != NULL) { Tcl_DecrRefCount(*objPtrPtr); } } } } /* *---------------------------------------------------------------------- * * DynamicOption_Init -- * * Initialize a Tk_OptionSpec.clientData field before calling * Tk_CreateOptionTable. * * Results: * None. * * Side effects: * Memory may be allocated. * *---------------------------------------------------------------------- */ int DynamicCO_Init( Tk_OptionSpec *optionTable, /* Table to search. */ CONST char *optionName, /* Name of the option. */ int id, /* Unique id. */ int size, /* Size of client data. */ int objOffset, /* Offset in the client data to store the * object representation of the option. * May be < 0. */ int internalOffset, /* Offset in the client data to store the * internal representation of the option. * May be < 0. */ Tk_ObjCustomOption *custom, /* Table of procedures and clientData for * the actual option. */ DynamicOptionInitProc *init /* This gets called to initialize the client * data when it is first allocated. May be * NULL. */ ) { Tk_OptionSpec *specPtr; DynamicCOClientData *cd; Tk_ObjCustomOption *co; if (size <= 0) panic("DynamicCO_Init: option %s size=%d", optionName, size); specPtr = Tree_FindOptionSpec(optionTable, optionName); if (specPtr->type != TK_OPTION_CUSTOM) panic("DynamicCO_Init: %s is not TK_OPTION_CUSTOM", optionName); if (specPtr->clientData != NULL) return TCL_OK; /* ClientData for the Tk custom option record */ cd = (DynamicCOClientData *) ckalloc(sizeof(DynamicCOClientData)); cd->id = id; cd->size = size; cd->objOffset = objOffset; cd->internalOffset = internalOffset; cd->custom = custom; cd->init = init; /* The Tk custom option record */ co = (Tk_ObjCustomOption *) ckalloc(sizeof(Tk_ObjCustomOption)); co->name = (char *) optionName + 1; co->setProc = DynamicCO_Set; co->getProc = DynamicCO_Get; co->restoreProc = DynamicCO_Restore; co->freeProc = DynamicCO_Free; co->clientData = (ClientData) cd; /* Update the option table */ specPtr->clientData = co; #ifdef DEBUG_DYNAMIC dbwin("DynamicCO_Init id=%d size=%d objOffset=%d internalOffset=%d custom->name=%s\n", id, size, objOffset, internalOffset, custom->name); #endif return TCL_OK; } /* *---------------------------------------------------------------------- * * DynamicOption_Free -- * * Free a linked list of dynamic-option records. This gets called * after Tk_FreeConfigOptions. * * Results: * None. * * Side effects: * Memory may be freed. * *---------------------------------------------------------------------- */ void DynamicOption_Free( TreeCtrl *tree, DynamicOption *first, Tk_OptionSpec *optionTable ) { DynamicOption *opt = first; DynamicCOClientData *cd; Tk_ObjCustomOption *co; int i; while (opt != NULL) { DynamicOption *next = opt->next; for (i = 0; optionTable[i].type != TK_OPTION_END; i++) { if (optionTable[i].type != TK_OPTION_CUSTOM) continue; co = (Tk_ObjCustomOption *) optionTable[i].clientData; if (co->setProc != DynamicCO_Set) continue; cd = (DynamicCOClientData *) co->clientData; if (cd->id != opt->id) continue; #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, DynamicOptionUid, (char *) opt, Tk_Offset(DynamicOption, data) + cd->size); #else ckfree((char *) opt); #endif break; } opt = next; } } /* *---------------------------------------------------------------------- * * DynamicOption_Free1 -- * * Free a single dynamic-option record. This is a big hack so that * dynamic-option records that aren't associated with a Tk_OptionSpec * array can be used. * * Results: * None. * * Side effects: * Memory may be freed. * *---------------------------------------------------------------------- */ void DynamicOption_Free1( TreeCtrl *tree, DynamicOption **firstPtr, int id, int size ) { DynamicOption *opt = *firstPtr, *prev = NULL; while (opt != NULL) { if (opt->id == id) { if (prev == NULL) *firstPtr = opt->next; else prev->next = opt->next; #ifdef ALLOC_HAX TreeAlloc_Free(tree->allocData, DynamicOptionUid, (char *) opt, Tk_Offset(DynamicOption, data) + size); #else ckfree((char *) opt); #endif return; } prev = opt; opt = opt->next; } } /* *---------------------------------------------------------------------- * * StringCO_Set -- * StringCO_Get -- * StringCO_Restore -- * StringCO_Free -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is exactly the same as a TK_OPTION_STRING. This is used * when storage for the option is dynamically allocated. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int StringCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **valuePtr, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { int objEmpty; char *internalPtr, *new, *value; int length; if (internalOffset >= 0) internalPtr = (char *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*valuePtr)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) (*valuePtr) = NULL; if (internalPtr != NULL) { if (*valuePtr != NULL) { value = Tcl_GetStringFromObj(*valuePtr, &length); new = ckalloc((unsigned) (length + 1)); strcpy(new, value); } else { new = NULL; } *((char **) saveInternalPtr) = *((char **) internalPtr); *((char **) internalPtr) = new; } return TCL_OK; } static Tcl_Obj * StringCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { char **internalPtr = (char **) (recordPtr + internalOffset); return Tcl_NewStringObj(*internalPtr, -1); } static void StringCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { *(char **) internalPtr = *(char **) saveInternalPtr; } static void StringCO_Free( ClientData clientData, Tk_Window tkwin, char *internalPtr ) { if (*((char **) internalPtr) != NULL) { ckfree(*((char **) internalPtr)); *((char **) internalPtr) = NULL; } } Tk_ObjCustomOption TreeCtrlCO_string = { "string", StringCO_Set, StringCO_Get, StringCO_Restore, StringCO_Free, (ClientData) NULL }; /* *---------------------------------------------------------------------- * * PixelsCO_Set -- * PixelsCO_Get -- * PixelsCO_Restore -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is exactly the same as a TK_OPTION_PIXELS. This is used * when storage for the option is dynamically allocated. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PixelsCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **valuePtr, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { int objEmpty; int *internalPtr, new; if (internalOffset >= 0) internalPtr = (int *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*valuePtr)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) { (*valuePtr) = NULL; new = 0; } else { if (Tk_GetPixelsFromObj(interp, tkwin, *valuePtr, &new) != TCL_OK) return TCL_ERROR; } if (internalPtr != NULL) { *((int *) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj * PixelsCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { int *internalPtr = (int *) (recordPtr + internalOffset); return Tcl_NewIntObj(*internalPtr); } static void PixelsCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { *(int *) internalPtr = *(int *) saveInternalPtr; } Tk_ObjCustomOption TreeCtrlCO_pixels = { "string", PixelsCO_Set, PixelsCO_Get, PixelsCO_Restore, NULL, (ClientData) NULL }; /* *---------------------------------------------------------------------- * * StyleCO_Set -- * StyleCO_Get -- * StyleCO_Restore -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a TreeStyle. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int StyleCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **valuePtr, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { TreeCtrl *tree = (TreeCtrl *) ((TkWindow *) tkwin)->instanceData; int objEmpty; TreeStyle *internalPtr, new; if (internalOffset >= 0) internalPtr = (TreeStyle *) (recordPtr + internalOffset); else internalPtr = NULL; objEmpty = ObjectIsEmpty((*valuePtr)); if ((flags & TK_OPTION_NULL_OK) && objEmpty) { (*valuePtr) = NULL; new = NULL; } else { if (TreeStyle_FromObj(tree, *valuePtr, &new) != TCL_OK) return TCL_ERROR; } if (internalPtr != NULL) { *((TreeStyle *) saveInternalPtr) = *internalPtr; *internalPtr = new; } return TCL_OK; } static Tcl_Obj * StyleCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { TreeStyle *internalPtr = (TreeStyle *) (recordPtr + internalOffset); if (*internalPtr == NULL) return NULL; return TreeStyle_ToObj(*internalPtr); } static void StyleCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { *(TreeStyle *) internalPtr = *(TreeStyle *) saveInternalPtr; } Tk_ObjCustomOption TreeCtrlCO_style = { "style", StyleCO_Set, StyleCO_Get, StyleCO_Restore, NULL, (ClientData) NULL }; /* *---------------------------------------------------------------------- * * BooleanFlagCO_Set -- * BooleanFlagCO_Get -- * BooleanFlagCO_Restore -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a boolean value whose internal rep is a single bit of * an int rather than the entire int. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int BooleanFlagCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { int theFlag = (int) clientData; int new, *internalPtr; if (internalOffset >= 0) internalPtr = (int *) (recordPtr + internalOffset); else internalPtr = NULL; if (Tcl_GetBooleanFromObj(interp, (*value), &new) != TCL_OK) return TCL_ERROR; if (internalPtr != NULL) { *((int *) saveInternalPtr) = *internalPtr; if (new) *internalPtr |= theFlag; else *internalPtr &= ~theFlag; } return TCL_OK; } static Tcl_Obj * BooleanFlagCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { int theFlag = (int) clientData; int value = *(int *) (recordPtr + internalOffset); return Tcl_NewBooleanObj(value & theFlag); } static void BooleanFlagCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { int theFlag = (int) clientData; int value = *(int *) saveInternalPtr; if (value & theFlag) *((int *) internalPtr) |= theFlag; else *((int *) internalPtr) &= ~theFlag; } int BooleanFlagCO_Init( Tk_OptionSpec *optionTable, CONST char *optionName, int theFlag ) { Tk_OptionSpec *specPtr; Tk_ObjCustomOption *co; specPtr = Tree_FindOptionSpec(optionTable, optionName); if (specPtr->type != TK_OPTION_CUSTOM) panic("BooleanFlagCO_Init: %s is not TK_OPTION_CUSTOM", optionName); if (specPtr->clientData != NULL) return TCL_OK; /* The Tk custom option record */ co = (Tk_ObjCustomOption *) ckalloc(sizeof(Tk_ObjCustomOption)); co->name = "boolean"; co->setProc = BooleanFlagCO_Set; co->getProc = BooleanFlagCO_Get; co->restoreProc = BooleanFlagCO_Restore; co->freeProc = NULL; co->clientData = (ClientData) theFlag; specPtr->clientData = co; return TCL_OK; } /* *---------------------------------------------------------------------- * * ItemButtonCO_Set -- * ItemButtonCO_Get -- * ItemButtonCO_Restore -- * * These procedures implement a TK_OPTION_CUSTOM where the custom * option is a boolean value or "auto"; the internal rep is two * bits of an int: one bit for the boolean, and one for "auto". * This is used for the item option -button. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ struct ItemButtonCOClientData { int flag1; /* Bit to set when object is "true". */ int flag2; /* Bit to set when object is "auto". */ }; static int ItemButtonCO_Set( ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, int internalOffset, char *saveInternalPtr, int flags ) { struct ItemButtonCOClientData *cd = clientData; int new, *internalPtr, on, off; char *s; int length; if (internalOffset >= 0) internalPtr = (int *) (recordPtr + internalOffset); else internalPtr = NULL; s = Tcl_GetStringFromObj((*value), &length); if (s[0] == 'a' && strncmp(s, "auto", length) == 0) { on = cd->flag2; off = cd->flag1; } else { if (Tcl_GetBooleanFromObj(interp, (*value), &new) != TCL_OK) { FormatResult(interp, "expected boolean or auto but got \"%s\"", s); return TCL_ERROR; } if (new) { on = cd->flag1; off = cd->flag2; } else { on = 0; off = cd->flag1 | cd->flag2; } } if (internalPtr != NULL) { *((int *) saveInternalPtr) = *internalPtr; *internalPtr |= on; *internalPtr &= ~off; } return TCL_OK; } static Tcl_Obj * ItemButtonCO_Get( ClientData clientData, Tk_Window tkwin, char *recordPtr, int internalOffset ) { struct ItemButtonCOClientData *cd = clientData; int value = *(int *) (recordPtr + internalOffset); if (value & cd->flag2) return Tcl_NewStringObj("auto", -1); return Tcl_NewBooleanObj((value & cd->flag1) != 0); } static void ItemButtonCO_Restore( ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr ) { struct ItemButtonCOClientData *cd = clientData; int value = *(int *) saveInternalPtr; *((int *) internalPtr) &= ~(cd->flag1 | cd->flag2); *((int *) internalPtr) |= value & (cd->flag1 | cd->flag2); } int ItemButtonCO_Init( Tk_OptionSpec *optionTable, CONST char *optionName, int flag1, int flag2 ) { Tk_OptionSpec *specPtr; Tk_ObjCustomOption *co; struct ItemButtonCOClientData *cd; specPtr = Tree_FindOptionSpec(optionTable, optionName); if (specPtr->type != TK_OPTION_CUSTOM) panic("BooleanFlagCO_Init: %s is not TK_OPTION_CUSTOM", optionName); if (specPtr->clientData != NULL) return TCL_OK; /* ClientData for the Tk custom option record. */ cd = (struct ItemButtonCOClientData *)ckalloc( sizeof(struct ItemButtonCOClientData)); cd->flag1 = flag1; cd->flag2 = flag2; /* The Tk custom option record */ co = (Tk_ObjCustomOption *) ckalloc(sizeof(Tk_ObjCustomOption)); co->name = "button option"; co->setProc = ItemButtonCO_Set; co->getProc = ItemButtonCO_Get; co->restoreProc = ItemButtonCO_Restore; co->freeProc = NULL; co->clientData = cd; specPtr->clientData = co; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tree_GetIntForIndex -- * * This is basically a direct copy of TclGetIntForIndex with one * important difference: the caller gets to know whether the index * was of the form "end?-offset?". * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tree_GetIntForIndex( TreeCtrl *tree, /* Widget info. */ Tcl_Obj *objPtr, /* Points to an object containing either "end" * or an integer. */ int *indexPtr, /* Location filled in with an integer * representing an index. */ int *endRelativePtr /* Set to 1 if the returned index is relative * to "end". */ ) { int endValue = 0; char *bytes; if (TclGetIntForIndex(tree->interp, objPtr, endValue, indexPtr) != TCL_OK) return TCL_ERROR; bytes = Tcl_GetString(objPtr); if (*bytes == 'e') { *endRelativePtr = 1; } else { *endRelativePtr = 0; } return TCL_OK; } tktreectrl-2.2.8/library/0000755000175600010010000000000011073207472013562 5ustar TimNonetktreectrl-2.2.8/library/filelist-bindings.tcl0000700000175600010010000005224610527725040017675 0ustar TimNone# RCS: @(#) $Id: filelist-bindings.tcl,v 1.26 2006/11/19 00:49:36 treectrl Exp $ bind TreeCtrlFileList { TreeCtrl::FileListEditCancel %W TreeCtrl::DoubleButton1 %W %x %y break } bind TreeCtrlFileList { set TreeCtrl::Priv(selectMode) toggle TreeCtrl::FileListButton1 %W %x %y break } bind TreeCtrlFileList { set TreeCtrl::Priv(selectMode) add TreeCtrl::FileListButton1 %W %x %y break } bind TreeCtrlFileList { set TreeCtrl::Priv(selectMode) set TreeCtrl::FileListButton1 %W %x %y break } bind TreeCtrlFileList { TreeCtrl::FileListMotion1 %W %x %y break } bind TreeCtrlFileList { TreeCtrl::FileListLeave1 %W %x %y break } bind TreeCtrlFileList { TreeCtrl::FileListRelease1 %W %x %y break } ## Bindings for the Entry widget used for editing # Accept edit when we lose the focus bind TreeCtrlEntry { if {[winfo ismapped %W]} { TreeCtrl::EditClose [winfo parent %W] entry 1 0 } } # Accept edit on bind TreeCtrlEntry { TreeCtrl::EditClose [winfo parent %W] entry 1 1 break } # Cancel edit on , use break as we are doing a "closing" action # and don't want that propagated upwards bind TreeCtrlEntry { TreeCtrl::EditClose [winfo parent %W] entry 0 1 break } ## Bindings for the Text widget used for editing # Accept edit when we lose the focus bind TreeCtrlText { if {[winfo ismapped %W]} { TreeCtrl::EditClose [winfo parent %W] text 1 0 } } # Accept edit on bind TreeCtrlText { TreeCtrl::EditClose [winfo parent %W] text 1 1 break } # Cancel edit on , use break as we are doing a "closing" action # and don't want that propagated upwards bind TreeCtrlText { TreeCtrl::EditClose [winfo parent %W] text 0 1 break } namespace eval TreeCtrl { variable Priv set Priv(edit,delay) 500 } proc ::TreeCtrl::IsSensitive {T x y} { variable Priv set id [$T identify $x $y] if {[lindex $id 0] ne "item" || [llength $id] != 6} { return 0 } lassign $id where item arg1 arg2 arg3 arg4 if {![$T item enabled $item]} { return 0 } foreach list $Priv(sensitive,$T) { set C [lindex $list 0] set S [lindex $list 1] set eList [lrange $list 2 end] if {[$T column compare $arg2 != $C]} continue if {[$T item style set $item $C] ne $S} continue if {[lsearch -exact $eList $arg4] == -1} continue return 1 } return 0 } proc ::TreeCtrl::FileListButton1 {T x y} { variable Priv focus $T set id [$T identify $x $y] set marquee 0 set Priv(buttonMode) "" foreach e {text entry} { if {[winfo exists $T.$e] && [winfo ismapped $T.$e]} { EditClose $T $e 1 0 } } FileListEditCancel $T # Click outside any item if {$id eq ""} { set marquee 1 # Click in header } elseif {[lindex $id 0] eq "header"} { ButtonPress1 $T $x $y # Click in item } else { lassign $id where item arg1 arg2 arg3 arg4 switch $arg1 { button - line { ButtonPress1 $T $x $y } column { if {[IsSensitive $T $x $y]} { set Priv(drag,motion) 0 set Priv(drag,click,x) $x set Priv(drag,click,y) $y set Priv(drag,x) [$T canvasx $x] set Priv(drag,y) [$T canvasy $y] set Priv(drop) "" set Priv(drag,wasSel) [$T selection includes $item] set Priv(drag,C) $arg2 set Priv(drag,E) $arg4 $T activate $item if {$Priv(selectMode) eq "add"} { BeginExtend $T $item } elseif {$Priv(selectMode) eq "toggle"} { BeginToggle $T $item } elseif {![$T selection includes $item]} { BeginSelect $T $item } # Changing the selection might change the list if {[$T item id $item] eq ""} return # Click selected item to drag if {[$T selection includes $item]} { set Priv(buttonMode) drag } } else { set marquee 1 } } } } if {$marquee} { set Priv(buttonMode) marquee if {$Priv(selectMode) ne "set"} { set Priv(selection) [$T selection get] } else { $T selection clear set Priv(selection) {} } MarqueeBegin $T $x $y } return } proc ::TreeCtrl::FileListMotion1 {T x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { "drag" - "marquee" { set Priv(autoscan,command,$T) {FileListMotion %T %x %y} AutoScanCheck $T $x $y FileListMotion $T $x $y } default { Motion1 $T $x $y } } return } proc ::TreeCtrl::FileListMotion {T x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { "marquee" { MarqueeUpdate $T $x $y set select $Priv(selection) set deselect {} # Check items covered by the marquee foreach list [$T marque identify] { set item [lindex $list 0] if {![$T item enabled $item]} continue # Check covered columns in this item foreach sublist [lrange $list 1 end] { set column [lindex $sublist 0] set ok 0 # Check covered elements in this column foreach E [lrange $sublist 1 end] { foreach sList $Priv(sensitive,$T) { set sC [lindex $sList 0] set sS [lindex $sList 1] set sEList [lrange $sList 2 end] if {[$T column compare $column != $sC]} continue if {[$T item style set $item $sC] ne $sS} continue if {[lsearch -exact $sEList $E] == -1} continue set ok 1 break } } # Some sensitive elements in this column are covered if {$ok} { # Toggle selected status if {$Priv(selectMode) eq "toggle"} { set i [lsearch -exact $Priv(selection) $item] if {$i == -1} { lappend select $item } else { set i [lsearch -exact $select $item] set select [lreplace $select $i $i] } } else { lappend select $item } } } } $T selection modify $select all } "drag" { if {!$Priv(drag,motion)} { # Detect initial mouse movement if {(abs($x - $Priv(drag,click,x)) <= 4) && (abs($y - $Priv(drag,click,y)) <= 4)} return set Priv(selection) [$T selection get] set Priv(drop) "" $T dragimage clear # For each selected item, add some elements to the dragimage foreach I $Priv(selection) { foreach list $Priv(dragimage,$T) { set C [lindex $list 0] set S [lindex $list 1] if {[$T item style set $I $C] eq $S} { eval $T dragimage add $I $C [lrange $list 2 end] } } } set Priv(drag,motion) 1 TryEvent $T Drag begin {} } # Find the element under the cursor set drop "" set id [$T identify $x $y] if {[IsSensitive $T $x $y]} { set item [lindex $id 1] # If the item is not in the pre-drag selection # (i.e. not being dragged) and it is a directory, # see if we can drop on it if {[lsearch -exact $Priv(selection) $item] == -1} { if {[$T item order $item -visible] < $Priv(DirCnt,$T)} { set drop $item # We can drop if dragged item isn't an ancestor foreach item2 $Priv(selection) { if {[$T item isancestor $item2 $item]} { set drop "" break } } } } } # Select the directory under the cursor (if any) and deselect # the previous drop-directory (if any) $T selection modify $drop $Priv(drop) set Priv(drop) $drop # Show the dragimage in its new position set x [expr {[$T canvasx $x] - $Priv(drag,x)}] set y [expr {[$T canvasy $y] - $Priv(drag,y)}] $T dragimage offset $x $y $T dragimage configure -visible yes } default { Motion1 $T $x $y } } return } proc ::TreeCtrl::FileListLeave1 {T x y} { variable Priv # This gets called when I click the mouse on Unix, and buttonMode is unset if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { default { Leave1 $T $x $y } } return } proc ::TreeCtrl::FileListRelease1 {T x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { "marquee" { AutoScanCancel $T MarqueeEnd $T $x $y } "drag" { AutoScanCancel $T # Some dragging occurred if {$Priv(drag,motion)} { $T dragimage configure -visible no if {$Priv(drop) ne ""} { $T selection modify {} $Priv(drop) TryEvent $T Drag receive \ [list I $Priv(drop) l $Priv(selection)] } TryEvent $T Drag end {} } elseif {$Priv(selectMode) eq "toggle"} { # don't rename # Clicked/released a selected item, but didn't drag } elseif {$Priv(drag,wasSel)} { set I [$T item id active] set C $Priv(drag,C) set E $Priv(drag,E) set S [$T item style set $I $C] set ok 0 foreach list $Priv(edit,$T) { set eC [lindex $list 0] set eS [lindex $list 1] set eEList [lrange $list 2 end] if {[$T column compare $C != $eC]} continue if {$S ne $eS} continue if {[lsearch -exact $eEList $E] == -1} continue set ok 1 break } if {$ok} { FileListEditCancel $T set Priv(editId,$T) \ [after $Priv(edit,delay) [list ::TreeCtrl::FileListEdit $T $I $C $E]] } } } default { Release1 $T $x $y } } set Priv(buttonMode) "" return } proc ::TreeCtrl::FileListEdit {T I C E} { variable Priv array unset Priv editId,$T set lines [$T item element cget $I $C $E -lines] if {$lines eq ""} { set lines [$T element cget $E -lines] } # Scroll item into view $T see $I ; update # Multi-line edit if {$lines ne "1"} { scan [$T item bbox $I $C] "%d %d %d %d" x1 y1 x2 y2 set S [$T item style set $I $C] set padx [$T style layout $S $E -padx] if {[llength $padx] == 2} { set padw [lindex $padx 0] set pade [lindex $padx 1] } else { set pade [set padw $padx] } foreach E2 [$T style elements $S] { if {[lsearch -exact [$T style layout $S $E2 -union] $E] == -1} continue foreach option {-padx -ipadx} { set pad [$T style layout $S $E2 $option] if {[llength $pad] == 2} { incr padw [lindex $pad 0] incr pade [lindex $pad 1] } else { incr padw $pad incr pade $pad } } } TextExpanderOpen $T $I $C $E [expr {$x2 - $x1 - $padw - $pade}] # Single-line edit } else { EntryExpanderOpen $T $I $C $E } TryEvent $T Edit begin [list I $I C $C E $E] return } proc ::TreeCtrl::FileListEditCancel {T} { variable Priv if {[info exists Priv(editId,$T)]} { after cancel $Priv(editId,$T) array unset Priv editId,$T } return } proc ::TreeCtrl::SetDragImage {T listOfLists} { variable Priv foreach list $listOfLists { set column [lindex $list 0] set style [lindex $list 1] set elements [lrange $list 2 end] if {[$T column id $column] eq ""} { error "column \"$column\" doesn't exist" } if {[lsearch -exact [$T style names] $style] == -1} { error "style \"$style\" doesn't exist" } foreach element $elements { if {[lsearch -exact [$T element names] $element] == -1} { error "element \"$element\" doesn't exist" } } } set Priv(dragimage,$T) $listOfLists return } proc ::TreeCtrl::SetEditable {T listOfLists} { variable Priv foreach list $listOfLists { set column [lindex $list 0] set style [lindex $list 1] set elements [lrange $list 2 end] if {[$T column id $column] eq ""} { error "column \"$column\" doesn't exist" } if {[lsearch -exact [$T style names] $style] == -1} { error "style \"$style\" doesn't exist" } foreach element $elements { if {[lsearch -exact [$T element names] $element] == -1} { error "element \"$element\" doesn't exist" } if {[$T element type $element] ne "text"} { error "element \"$element\" is not of type \"text\"" } } } set Priv(edit,$T) $listOfLists return } proc ::TreeCtrl::SetSensitive {T listOfLists} { variable Priv foreach list $listOfLists { set column [lindex $list 0] set style [lindex $list 1] set elements [lrange $list 2 end] if {[$T column id $column] eq ""} { error "column \"$column\" doesn't exist" } if {[lsearch -exact [$T style names] $style] == -1} { error "style \"$style\" doesn't exist" } foreach element $elements { if {[lsearch -exact [$T element names] $element] == -1} { error "element \"$element\" doesn't exist" } } } set Priv(sensitive,$T) $listOfLists return } proc ::TreeCtrl::EntryOpen {T item column element} { variable Priv set Priv(entry,$T,item) $item set Priv(entry,$T,column) $column set Priv(entry,$T,element) $element set Priv(entry,$T,focus) [focus] # Get window coords of the Element scan [$T item bbox $item $column $element] "%d %d" x y # Get the font used by the Element set font [$T item element perstate $item $column $element -font] if {$font eq ""} { set font [$T cget -font] } # Get the text used by the Element. Could check master Element too. set text [$T item element cget $item $column $element -text] # Create the Entry widget if needed set e $T.entry if {[winfo exists $e]} { $e delete 0 end } else { entry $e -borderwidth 1 -relief solid -highlightthickness 0 bindtags $e [linsert [bindtags $e] 1 TreeCtrlEntry] } # Pesky MouseWheel $T notify bind $e { TreeCtrl::EditClose %T entry 0 1 } $e configure -font $font $e insert end $text $e selection range 0 end set ebw [$e cget -borderwidth] set ex [expr {$x - $ebw - 1}] place $e -x $ex -y [expr {$y - $ebw - 1}] -bordermode outside # Make the Entry as wide as the text plus "W" but keep it within the # TreeCtrl borders set width [font measure $font ${text}W] set width [expr {$width + ($ebw + 1) * 2}] scan [$T contentbox] "%d %d %d %d" left top right bottom if {$ex + $width > $right} { set width [expr {$right - $ex}] } scan [$T item bbox $item $column] "%d %d %d %d" left top right bottom if {$ex + $width > $right} { set width [expr {$right - $ex}] } place configure $e -width $width focus $e return } # Like EntryOpen, but Entry widget expands/shrinks during typing proc ::TreeCtrl::EntryExpanderOpen {T item column element} { variable Priv set Priv(entry,$T,item) $item set Priv(entry,$T,column) $column set Priv(entry,$T,element) $element set Priv(entry,$T,focus) [focus] # Get window coords of the Element scan [$T item bbox $item $column $element] "%d %d" x y # Get the font used by the Element set font [$T item element perstate $item $column $element -font] if {$font eq ""} { set font [$T cget -font] } set Priv(entry,$T,font) $font # Get the text used by the Element. Could check master Element too. set text [$T item element cget $item $column $element -text] # Create the Entry widget if needed set e $T.entry if {[winfo exists $e]} { $e delete 0 end } else { entry $e -borderwidth 1 -highlightthickness 0 \ -selectborderwidth 0 -relief solid bindtags $e [linsert [bindtags $e] 1 TreeCtrlEntry] # Resize as user types bind $e { after idle [list TreeCtrl::EntryExpanderKeypress [winfo parent %W]] } } # Pesky MouseWheel $T notify bind $e { TreeCtrl::EditClose %T entry 0 1 } $e configure -font $font -background [$T cget -background] $e insert end $text $e selection range 0 end set ebw [$e cget -borderwidth] set ex [expr {$x - $ebw - 1}] place $e -x $ex -y [expr {$y - $ebw - 1}] \ -bordermode outside # Make the Entry as wide as the text plus "W" but keep it within the # TreeCtrl borders set width [font measure $font ${text}W] set width [expr {$width + ($ebw + 1) * 2}] scan [$T contentbox] "%d %d %d %d" left top right bottom if {$ex + $width > $right} { set width [expr {$right - $ex}] } place configure $e -width $width focus $e return } proc ::TreeCtrl::EditClose {T type accept {refocus 0}} { variable Priv set w $T.$type # We need the double-idle to get winfo ismapped to report properly # so this don't get the FocusOut following Escape immediately update idletasks place forget $w focus $T update idletasks if {$accept} { if {$type eq "entry"} { set t [$w get] } else { set t [$w get 1.0 end-1c] } TryEvent $T Edit accept \ [list I $Priv($type,$T,item) C $Priv($type,$T,column) \ E $Priv($type,$T,element) t $t] } $T notify unbind $w TryEvent $T Edit end \ [list I $Priv($type,$T,item) C $Priv($type,$T,column) \ E $Priv($type,$T,element)] if {$refocus} { focus $Priv($type,$T,focus) } return } proc ::TreeCtrl::EntryExpanderKeypress {T} { variable Priv set font $Priv(entry,$T,font) set text [$T.entry get] set ebw [$T.entry cget -borderwidth] set ex [winfo x $T.entry] set width [font measure $font ${text}W] set width [expr {$width + ($ebw + 1) * 2}] scan [$T contentbox] "%d %d %d %d" left top right bottom if {$ex + $width > $right} { set width [expr {$right - $ex}] } place configure $T.entry -width $width return } proc ::TreeCtrl::TextOpen {T item column element {width 0} {height 0}} { variable Priv set Priv(text,$T,item) $item set Priv(text,$T,column) $column set Priv(text,$T,element) $element set Priv(text,$T,focus) [focus] # Get window coords of the Element scan [$T item bbox $item $column $element] "%d %d %d %d" x1 y1 x2 y2 # Get the font used by the Element set font [$T item element perstate $item $column $element -font] if {$font eq ""} { set font [$T cget -font] } # Get the text used by the Element. Could check master Element too. set text [$T item element cget $item $column $element -text] set justify [$T element cget $element -justify] if {$justify eq ""} { set justify left } set wrap [$T element cget $element -wrap] if {$wrap eq ""} { set wrap word } # Create the Text widget if needed set w $T.text if {[winfo exists $w]} { $w delete 1.0 end } else { text $w -borderwidth 1 -highlightthickness 0 -relief solid bindtags $w [linsert [bindtags $w] 1 TreeCtrlText] } # Pesky MouseWheel $T notify bind $w { TreeCtrl::EditClose %T text 0 1 } $w tag configure TAG -justify $justify $w configure -font $font -background [$T cget -background] -wrap $wrap $w insert end $text $w tag add sel 1.0 end $w tag add TAG 1.0 end set tbw [$w cget -borderwidth] set tx [expr {$x1 - $tbw - 1}] place $w -x $tx -y [expr {$y1 - $tbw - 1}] \ -width [expr {$x2 - $x1 + ($tbw + 1) * 2}] \ -height [expr {$y2 - $y1 + ($tbw + 1) * 2}] \ -bordermode outside focus $w return } # Like TextOpen, but Text widget expands/shrinks during typing proc ::TreeCtrl::TextExpanderOpen {T item column element width} { variable Priv set Priv(text,$T,item) $item set Priv(text,$T,column) $column set Priv(text,$T,element) $element set Priv(text,$T,focus) [focus] # Get window coords of the Element scan [$T item bbox $item $column $element] "%d %d %d %d" x1 y1 x2 y2 set Priv(text,$T,center) [expr {$x1 + ($x2 - $x1) / 2}] # Get the font used by the Element set font [$T item element perstate $item $column $element -font] if {$font eq ""} { set font [$T cget -font] } # Get the text used by the Element. Could check master Element too. set text [$T item element cget $item $column $element -text] set justify [$T element cget $element -justify] if {$justify eq ""} { set justify left } set wrap [$T element cget $element -wrap] if {$wrap eq ""} { set wrap word } # Create the Text widget if needed set w $T.text if {[winfo exists $w]} { $w delete 1.0 end } else { text $w -borderwidth 1 -highlightthickness 0 \ -selectborderwidth 0 -relief solid bindtags $w [linsert [bindtags $w] 1 TreeCtrlText] # Resize as user types bind $w { after idle TreeCtrl::TextExpanderKeypress [winfo parent %W] } } # Pesky MouseWheel $T notify bind $w { TreeCtrl::EditClose %T text 0 1 } $w tag configure TAG -justify $justify $w configure -font $font -background [$T cget -background] -wrap $wrap $w insert end $text $w tag add sel 1.0 end $w tag add TAG 1.0 end set Priv(text,$T,font) $font set Priv(text,$T,justify) $justify set Priv(text,$T,width) $width scan [textlayout $font $text -justify $justify -width $width] \ "%d %d" width height set tbw [$w cget -borderwidth] incr tbw place $w -x [expr {$x1 - $tbw}] -y [expr {$y1 - $tbw}] \ -width [expr {$width + $tbw * 2}] \ -height [expr {$height + $tbw * 2}] \ -bordermode outside focus $w return } proc ::TreeCtrl::TextExpanderKeypress {T} { variable Priv set font $Priv(text,$T,font) set justify $Priv(text,$T,justify) set width $Priv(text,$T,width) set center $Priv(text,$T,center) set text [$T.text get 1.0 end-1c] scan [textlayout $font $text -justify $justify -width $width] \ "%d %d" width height set tbw [$T.text cget -borderwidth] incr tbw place configure $T.text \ -x [expr {$center - ($width + $tbw * 2) / 2}] \ -width [expr {$width + $tbw * 2}] \ -height [expr {$height + $tbw * 2}] $T.text tag add TAG 1.0 end return } tktreectrl-2.2.8/library/treectrl.tcl0000700000175600010010000011702311041153471016101 0ustar TimNone# RCS: @(#) $Id: treectrl.tcl,v 1.40 2008/07/21 18:36:41 treectrl Exp $ bind TreeCtrl { TreeCtrl::CursorCheck %W %x %y TreeCtrl::MotionInHeader %W %x %y } bind TreeCtrl { TreeCtrl::CursorCancel %W TreeCtrl::MotionInHeader %W } bind TreeCtrl { TreeCtrl::ButtonPress1 %W %x %y } bind TreeCtrl { TreeCtrl::DoubleButton1 %W %x %y } bind TreeCtrl { TreeCtrl::Motion1 %W %x %y } bind TreeCtrl { TreeCtrl::Release1 %W %x %y } bind TreeCtrl { set TreeCtrl::Priv(buttonMode) normal TreeCtrl::BeginExtend %W [%W item id {nearest %x %y}] } # Command-click should provide a discontinuous selection on OSX switch -- [tk windowingsystem] { "aqua" { set modifier Command } default { set modifier Control } } bind TreeCtrl <$modifier-ButtonPress-1> { set TreeCtrl::Priv(buttonMode) normal TreeCtrl::BeginToggle %W [%W item id {nearest %x %y}] } bind TreeCtrl { TreeCtrl::Leave1 %W %x %y } bind TreeCtrl { TreeCtrl::Enter1 %W %x %y } bind TreeCtrl { TreeCtrl::SetActiveItem %W [TreeCtrl::UpDown %W active -1] } bind TreeCtrl { TreeCtrl::Extend %W above } bind TreeCtrl { TreeCtrl::SetActiveItem %W [TreeCtrl::UpDown %W active 1] } bind TreeCtrl { TreeCtrl::Extend %W below } bind TreeCtrl { if {[%W cget -orient] eq "vertical" && [%W cget -wrap] eq ""} { %W item collapse [%W item id active] } else { TreeCtrl::SetActiveItem %W [TreeCtrl::LeftRight %W active -1] } } bind TreeCtrl { TreeCtrl::Extend %W left } bind TreeCtrl { %W xview scroll -1 pages } bind TreeCtrl { if {[%W cget -orient] eq "vertical" && [%W cget -wrap] eq ""} { %W item expand [%W item id active] } else { TreeCtrl::SetActiveItem %W [TreeCtrl::LeftRight %W active 1] } } bind TreeCtrl { TreeCtrl::Extend %W right } bind TreeCtrl { %W xview scroll 1 pages } bind TreeCtrl { %W yview scroll -1 pages if {[%W item id {nearest 0 0}] ne ""} { %W activate {nearest 0 0} } } bind TreeCtrl { %W yview scroll 1 pages if {[%W item id {nearest 0 0}] ne ""} { %W activate {nearest 0 0} } } bind TreeCtrl { %W xview scroll -1 pages } bind TreeCtrl { %W xview scroll 1 pages } bind TreeCtrl { %W xview moveto 0 } bind TreeCtrl { %W xview moveto 1 } bind TreeCtrl { TreeCtrl::SetActiveItem %W [%W item id {first visible state enabled}] } bind TreeCtrl { TreeCtrl::DataExtend %W [%W item id {first visible state enabled}] } bind TreeCtrl { TreeCtrl::SetActiveItem %W [%W item id {last visible state enabled}] } bind TreeCtrl { TreeCtrl::DataExtend %W [%W item id {last visible state enabled}] } bind TreeCtrl <> { if {[string equal [selection own -displayof %W] "%W"]} { clipboard clear -displayof %W clipboard append -displayof %W [selection get -displayof %W] } } bind TreeCtrl { TreeCtrl::BeginSelect %W [%W item id active] } bind TreeCtrl { TreeCtrl::BeginSelect %W [%W item id active] } bind TreeCtrl { TreeCtrl::BeginExtend %W [%W item id active] } bind TreeCtrl { TreeCtrl::BeginExtend %W [%W item id active] } bind TreeCtrl { TreeCtrl::Cancel %W } bind TreeCtrl { TreeCtrl::SelectAll %W } bind TreeCtrl { if {[string compare [%W cget -selectmode] "browse"]} { %W selection clear } } bind TreeCtrl { %W item expand [%W item id active] } bind TreeCtrl { %W item collapse [%W item id active] } bind TreeCtrl { %W item toggle [%W item id active] } # Additional Tk bindings that aren't part of the Motif look and feel: bind TreeCtrl { TreeCtrl::ScanMark %W %x %y } bind TreeCtrl { TreeCtrl::ScanDrag %W %x %y } if {$tcl_platform(platform) eq "windows"} { bind TreeCtrl { TreeCtrl::ScanMark %W %x %y } bind TreeCtrl { TreeCtrl::ScanDrag %W %x %y } } # MouseWheel if {[string equal "x11" [tk windowingsystem]]} { # Support for mousewheels on Linux/Unix commonly comes through mapping # the wheel to the extended buttons. If you have a mousewheel, find # Linux configuration info at: # http://www.inria.fr/koala/colas/mouse-wheel-scroll/ bind TreeCtrl <4> { if {!$tk_strictMotif} { %W yview scroll -5 units } } bind TreeCtrl <5> { if {!$tk_strictMotif} { %W yview scroll 5 units } } } elseif {[string equal [tk windowingsystem] "aqua"]} { bind TreeCtrl { %W yview scroll [expr {- (%D)}] units } } else { bind TreeCtrl { %W yview scroll [expr {- (%D / 120) * 4}] units } } namespace eval ::TreeCtrl { variable Priv array set Priv { prev {} } if {[info procs ::lassign] eq ""} { proc lassign {values args} { uplevel 1 [list foreach $args [linsert $values end {}] break] lrange $values [llength $args] end } } } # Retrieve filelist bindings from this dir source [file join [file dirname [info script]] filelist-bindings.tcl] # ::TreeCtrl::ColumnCanResizeLeft -- # # Return 1 if the given column should be resized by the left edge. # # Arguments: # w The treectrl widget. # column The column. proc ::TreeCtrl::ColumnCanResizeLeft {w column} { if {[$w column cget $column -lock] eq "right"} { if {[$w column compare $column == "first visible lock right"]} { return 1 } if {[$w column compare $column == "last visible lock right"]} { return 1 } } return 0 } # ::TreeCtrl::ColumnCanMoveHere -- # # Return 1 if the given column can be moved before another. # # Arguments: # w The treectrl widget. # column The column. # before The column to place 'column' before. proc ::TreeCtrl::ColumnCanMoveHere {w column before} { if {[$w column compare $column == $before] || ([$w column order $column] == [$w column order $before] - 1)} { return 0 } set lock [$w column cget $column -lock] return [expr {[$w column compare $before >= "first lock $lock"] && [$w column compare $before <= "last lock $lock next"]}] } # ::TreeCtrl::ColumnDragFindBefore -- # # This is called when dragging a column header. The result is 1 if the given # coordinates are near a column header before which the dragged column can # be moved. # # Arguments: # w The treectrl widget. # x Window x-coord. # y Window y-coord. # dragColumn The column being dragged. # indColumn_ Out: what to set -indicatorcolumn to. # indSide_ Out: what to set -indicatorside to. proc ::TreeCtrl::ColumnDragFindBefore {w x y dragColumn indColumn_ indSide_} { upvar $indColumn_ indColumn upvar $indSide_ indSide switch -- [$w column cget $dragColumn -lock] { left {set area left} none {set area content} right {set area right} } scan [$w bbox $area] "%d %d %d %d" minX y1 maxX y2 if {$x < $minX} { set x $minX } if {$x >= $maxX} { set x [expr {$maxX - 1}] } set id [$w identify $x $y] if {[lindex $id 0] ne "header"} { return 0 } set indColumn [lindex $id 1] set before $indColumn set prev [$w column id "$dragColumn prev visible"] set next [$w column id "$dragColumn next visible"] if {[$w column compare $indColumn == "tail"]} { set indSide left } elseif {$prev ne "" && [$w column compare $prev == $indColumn]} { set indSide left } elseif {$next ne "" && [$w column compare $next == $indColumn]} { set before [$w column id "$indColumn next visible"] set indSide right } else { scan [$w column bbox $indColumn] "%d %d %d %d" x1 y1 x2 y2 if {$x < $x1 + ($x2 - $x1) / 2} { set indSide left } else { set before [$w column id "$indColumn next visible"] set indSide right } } return [ColumnCanMoveHere $w $dragColumn $before] } # ::TreeCtrl::CursorAction -- # # If the given point is at the left or right edge of a resizable column, the # result is "column resize C". If the given point is in a header with -button # TRUE, the result is "column button C". # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::CursorAction {w x y} { variable Priv set id [$w identify $x $y] if {[lindex $id 0] eq "header"} { set column [lindex $id 1] set side [lindex $id 2] if {$side eq "left"} { if {[$w column compare $column == tail]} { set column2 [$w column id "last visible lock none"] if {$column2 ne "" && [$w column cget $column2 -resize]} { return "column resize $column2" } # Can't -resize or -button the tail column return "" } if {[ColumnCanResizeLeft $w $column]} { if {[$w column cget $column -resize]} { return "column resize $column" } } else { # Resize the previous column set lock [$w column cget $column -lock] if {[$w column compare $column != "first visible lock $lock"]} { set column2 [$w column id "$column prev visible"] if {[$w column cget $column2 -resize]} { return "column resize $column2" } } } } elseif {$side eq "right"} { if {![ColumnCanResizeLeft $w $column]} { if {[$w column cget $column -resize]} { return "column resize $column" } } } if {[$w column compare $column == "tail"]} { # nothing } elseif {[$w column cget $column -button]} { return "column button $column" } } return "" } # ::TreeCtrl::CursorCheck -- # # Sees if the given pointer coordinates are near the edge of a resizable # column in the header. If so and the treectrl's cursor is not already # set to sb_h_double_arrow, then the current cursor is saved and changed # to sb_h_double_arrow, and an [after] callback to CursorCheckAux is # scheduled. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::CursorCheck {w x y} { variable Priv set action [CursorAction $w $x $y] if {[lindex $action 1] ne "resize"} { CursorCancel $w return } set cursor sb_h_double_arrow if {$cursor ne [$w cget -cursor]} { if {![info exists Priv(cursor,$w)]} { set Priv(cursor,$w) [$w cget -cursor] } $w configure -cursor $cursor } if {[info exists Priv(cursor,afterId,$w)]} { after cancel $Priv(cursor,afterId,$w) } set Priv(cursor,afterId,$w) [after 150 [list TreeCtrl::CursorCheckAux $w]] return } # ::TreeCtrl::CursorCheckAux -- # # Get's the location of the pointer and calls CursorCheck if the treectrl's # cursor was previously set to sb_h_double_arrow. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::CursorCheckAux {w} { variable Priv set x [winfo pointerx $w] set y [winfo pointery $w] if {[info exists Priv(cursor,$w)]} { set x [expr {$x - [winfo rootx $w]}] set y [expr {$y - [winfo rooty $w]}] CursorCheck $w $x $y } return } # ::TreeCtrl::CursorCancel -- # # Restores the treectrl's cursor if it was changed to sb_h_double_arrow. # Cancels any pending [after] callback to CursorCheckAux. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::CursorCancel {w} { variable Priv if {[info exists Priv(cursor,$w)]} { $w configure -cursor $Priv(cursor,$w) unset Priv(cursor,$w) } if {[info exists Priv(cursor,afterId,$w)]} { after cancel $Priv(cursor,afterId,$w) unset Priv(cursor,afterId,$w) } return } # ::TreeCtrl::MotionInHeader -- # # This procedure updates the active/normal states of columns as the pointer # moves in and out of column headers. Typically this results in visual # feedback by changing the appearance of the headers. # # Arguments: # w The treectrl widget. # args x y coords if the pointer is in the window, or an empty list. proc ::TreeCtrl::MotionInHeader {w args} { variable Priv if {[llength $args]} { set x [lindex $args 0] set y [lindex $args 1] set action [CursorAction $w $x $y] } else { set action "" } if {[info exists Priv(inheader,$w)]} { set prevColumn $Priv(inheader,$w) } else { set prevColumn "" } set column "" if {[lindex $action 0] eq "column"} { set column [lindex $action 2] } if {$column ne $prevColumn} { if {$prevColumn ne ""} { $w column configure $prevColumn -state normal } if {$column ne ""} { $w column configure $column -state active set Priv(inheader,$w) $column } else { unset Priv(inheader,$w) } } return } # ::TreeCtrl::ButtonPress1 -- # # Handle event. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::ButtonPress1 {w x y} { variable Priv focus $w set id [$w identify $x $y] if {$id eq ""} { return } if {[lindex $id 0] eq "item"} { lassign $id where item arg1 arg2 if {$arg1 eq "button"} { $w item toggle $item return } elseif {$arg1 eq "line"} { $w item toggle $arg2 return } } set Priv(buttonMode) "" if {[lindex $id 0] eq "header"} { set action [CursorAction $w $x $y] if {[lindex $action 1] eq "resize"} { set column [lindex $action 2] set Priv(buttonMode) resize set Priv(column) $column set Priv(x) $x set Priv(y) $y set Priv(width) [$w column width $column] return } set column [lindex $id 1] if {[lindex $action 1] eq "button"} { set Priv(buttonMode) header $w column configure $column -state pressed } else { if {[$w column compare $column == "tail"]} return if {![$w column dragcget -enable]} return set Priv(buttonMode) dragColumnWait } set Priv(column) $column set Priv(columnDrag,x) $x set Priv(columnDrag,y) $y return } set item [lindex $id 1] if {![$w item enabled $item]} { return } # If the initial mouse-click is in a locked column, restrict scrolling # to the vertical. scan [$w contentbox] "%d %d %d %d" x1 y1 x2 y2 if {$x >= $x1 && $x < $x2} { set Priv(autoscan,direction,$w) xy } else { set Priv(autoscan,direction,$w) y } set Priv(buttonMode) normal BeginSelect $w $item return } # ::TreeCtrl::DoubleButtonPress1 -- # # Handle event. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::DoubleButton1 {w x y} { set id [$w identify $x $y] if {$id eq ""} { return } if {[lindex $id 0] eq "item"} { lassign $id where item arg1 arg2 if {$arg1 eq "button"} { $w item toggle $item return } elseif {$arg1 eq "line"} { $w item toggle $arg2 return } } if {[lindex $id 0] eq "header"} { set action [CursorAction $w $x $y] # Double-click between columns to set default column width if {[lindex $action 1] eq "resize"} { set column [lindex $action 2] $w column configure $column -width "" CursorCheck $w $x $y MotionInHeader $w $x $y } else { ButtonPress1 $w $x $y } } return } # ::TreeCtrl::Motion1 -- # # Handle event. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::Motion1 {w x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { header { set id [$w identify $x $y] if {![string match "header $Priv(column)*" $id]} { if {[$w column cget $Priv(column) -state] eq "pressed"} { $w column configure $Priv(column) -state normal } } else { if {[$w column cget $Priv(column) -state] ne "pressed"} { $w column configure $Priv(column) -state pressed } if {[$w column dragcget -enable] && (abs($Priv(columnDrag,x) - $x) > 4)} { $w column dragconfigure \ -imagecolumn $Priv(column) \ -imageoffset [expr {$x - $Priv(columnDrag,x)}] set Priv(buttonMode) dragColumn TryEvent $w ColumnDrag begin [list C $Priv(column)] } } } dragColumnWait { if {(abs($Priv(columnDrag,x) - $x) > 4)} { $w column dragconfigure \ -imagecolumn $Priv(column) \ -imageoffset [expr {$x - $Priv(columnDrag,x)}] set Priv(buttonMode) dragColumn TryEvent $w ColumnDrag begin [list C $Priv(column)] } } dragColumn { scan [$w bbox header] "%d %d %d %d" x1 y1 x2 y2 if {$y < $y1 - 30 || $y >= $y2 + 30} { set inside 0 } else { set inside 1 } if {$inside && ([$w column dragcget -imagecolumn] eq "")} { $w column dragconfigure -imagecolumn $Priv(column) } elseif {!$inside && ([$w column dragcget -imagecolumn] ne "")} { $w column dragconfigure -imagecolumn "" -indicatorcolumn "" } if {$inside} { $w column dragconfigure -imageoffset [expr {$x - $Priv(columnDrag,x)}] if {[ColumnDragFindBefore $w $x $Priv(columnDrag,y) $Priv(column) indColumn indSide]} { $w column dragconfigure -indicatorcolumn $indColumn \ -indicatorside $indSide } else { $w column dragconfigure -indicatorcolumn "" } } if {[$w column cget $Priv(column) -lock] eq "none"} { ColumnDragScrollCheck $w $x $y } } normal { set Priv(x) $x set Priv(y) $y SelectionMotion $w [$w item id [list nearest $x $y]] set Priv(autoscan,command,$w) {SelectionMotion %T [%T item id "nearest %x %y"]} AutoScanCheck $w $x $y } resize { if {[ColumnCanResizeLeft $w $Priv(column)]} { set width [expr {$Priv(width) + $Priv(x) - $x}] } else { set width [expr {$Priv(width) + $x - $Priv(x)}] } set minWidth [$w column cget $Priv(column) -minwidth] set maxWidth [$w column cget $Priv(column) -maxwidth] if {$minWidth eq ""} { set minWidth 0 } if {$width < $minWidth} { set width $minWidth } if {($maxWidth ne "") && ($width > $maxWidth)} { set width $maxWidth } if {$width == 0} { incr width } switch -- [$w cget -columnresizemode] { proxy { scan [$w column bbox $Priv(column)] "%d %d %d %d" x1 y1 x2 y2 if {[ColumnCanResizeLeft $w $Priv(column)]} { # Use "ne" because -columnproxy could be "" if {$x ne [$w cget -columnproxy]} { $w configure -columnproxy $x } } else { if {($x1 + $width - 1) ne [$w cget -columnproxy]} { $w configure -columnproxy [expr {$x1 + $width - 1}] } } } realtime { if {[$w column cget $Priv(column) -width] != $width} { $w column configure $Priv(column) -width $width } } } } } return } # ::TreeCtrl::Leave1 -- # # Handle event. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::Leave1 {w x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { header { if {[$w column cget $Priv(column) -state] eq "pressed"} { $w column configure $Priv(column) -state normal } } } return } # ::TreeCtrl::Enter1 -- # # Handle event. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::Enter1 {w x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { default {} } return } # ::TreeCtrl::Release1 -- # # Handle event. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::Release1 {w x y} { variable Priv if {![info exists Priv(buttonMode)]} return switch $Priv(buttonMode) { header { if {[$w column cget $Priv(column) -state] eq "pressed"} { $w column configure $Priv(column) -state active TryEvent $w Header invoke [list C $Priv(column)] } } dragColumn { AutoScanCancel $w $w column configure $Priv(column) -state normal if {[$w column dragcget -imagecolumn] ne ""} { set visible 1 } else { set visible 0 } set column [$w column dragcget -indicatorcolumn] $w column dragconfigure -imagecolumn "" -indicatorcolumn "" if {$visible && ($column ne "")} { set side [$w column dragcget -indicatorside] if {$side eq "right"} { set column [$w column id "$column next visible"] } TryEvent $w ColumnDrag receive [list C $Priv(column) b $column] } set id [$w identify $x $y] if {[lindex $id 0] eq "header"} { set column [lindex $id 1] if {($column ne "") && [$w column compare $column != "tail"]} { if {[$w column cget $column -button]} { $w column configure $column -state active } } } TryEvent $w ColumnDrag end [list C $Priv(column)] } normal { AutoScanCancel $w set nearest [$w item id [list nearest $x $y]] if {$nearest ne ""} { $w activate $nearest } set Priv(prev) "" } resize { if {[$w cget -columnproxy] ne ""} { scan [$w column bbox $Priv(column)] "%d %d %d %d" x1 y1 x2 y2 if {[ColumnCanResizeLeft $w $Priv(column)]} { set width [expr {$x2 - [$w cget -columnproxy]}] } else { set width [expr {[$w cget -columnproxy] - $x1 + 1}] } $w configure -columnproxy {} $w column configure $Priv(column) -width $width } CursorCheck $w $x $y } } unset Priv(buttonMode) return } # ::TreeCtrl::BeginSelect -- # # This procedure is typically invoked on button-1 presses. It begins # the process of making a selection in the treectrl. Its exact behavior # depends on the selection mode currently in effect for the treectrl. # # Arguments: # w The treectrl widget. # item The item for the selection operation (typically the # one under the pointer). proc ::TreeCtrl::BeginSelect {w item} { variable Priv if {$item eq ""} return if {[string equal [$w cget -selectmode] "multiple"]} { if {[$w selection includes $item]} { $w selection clear $item } else { $w selection add $item } } else { $w selection anchor $item $w selection modify $item all set Priv(selection) {} set Priv(prev) $item } return } # ::TreeCtrl::SelectionMotion -- # # This procedure is called to process mouse motion events while # button 1 is down. It may move or extend the selection, depending # on the treectrl's selection mode. # # Arguments: # w The treectrl widget. # item- The item under the pointer. proc ::TreeCtrl::SelectionMotion {w item} { variable Priv if {$item eq ""} return if {$item eq $Priv(prev)} return if {![$w item enabled $item]} return switch [$w cget -selectmode] { browse { $w selection modify $item all set Priv(prev) $item } extended { set i $Priv(prev) set select {} set deselect {} if {$i eq ""} { set i $item lappend select $item set hack [$w item compare $item == anchor] } else { set hack 0 } if {[$w selection includes anchor] || $hack} { set deselect [concat $deselect [$w item range $i $item]] set select [concat $select [$w item range anchor $item]] } else { set deselect [concat $deselect [$w item range $i $item]] set deselect [concat $deselect [$w item range anchor $item]] } if {![info exists Priv(selection)]} { set Priv(selection) [$w selection get] } while {[$w item compare $i < $item] && [$w item compare $i < anchor]} { if {[lsearch $Priv(selection) $i] >= 0} { lappend select $i } set i [$w item id "$i next visible"] } while {[$w item compare $i > $item] && [$w item compare $i > anchor]} { if {[lsearch $Priv(selection) $i] >= 0} { lappend select $i } set i [$w item id "$i prev visible"] } set Priv(prev) $item $w selection modify $select $deselect } } return } # ::TreeCtrl::BeginExtend -- # # This procedure is typically invoked on shift-button-1 presses. It # begins the process of extending a selection in the treectrl. Its # exact behavior depends on the selection mode currently in effect # for the treectrl. # # Arguments: # w The treectrl widget. # item- The item for the selection operation (typically the # one under the pointer). proc ::TreeCtrl::BeginExtend {w item} { if {[string equal [$w cget -selectmode] "extended"]} { if {[$w selection includes anchor]} { SelectionMotion $w $item } else { # No selection yet; simulate the begin-select operation. BeginSelect $w $item } } return } # ::TreeCtrl::BeginToggle -- # # This procedure is typically invoked on control-button-1 presses. It # begins the process of toggling a selection in the treectrl. Its # exact behavior depends on the selection mode currently in effect # for the treectrl. # # Arguments: # w The treectrl widget. # item The item for the selection operation (typically the # one under the pointer). proc ::TreeCtrl::BeginToggle {w item} { variable Priv if {$item eq ""} return if {[string equal [$w cget -selectmode] "extended"]} { set Priv(selection) [$w selection get] set Priv(prev) $item $w selection anchor $item if {[$w selection includes $item]} { $w selection clear $item } else { $w selection add $item } } return } # ::TreeCtrl::AutoScanCheck -- # # Sees if the given pointer coords are outside the content area of the # treectrl (ie, not including borders or column headers) or within # -scrollmargin distance of the edges of the content area. If so and # auto-scanning is not already in progress, then the window is scrolled # and an [after] callback to AutoScanCheckAux is scheduled. # # Arguments: # w The treectrl widget. # x Window x coord. # y Window y coord. proc ::TreeCtrl::AutoScanCheck {w x y} { variable Priv scan [$w contentbox] "%d %d %d %d" x1 y1 x2 y2 set margin [winfo pixels $w [$w cget -scrollmargin]] if {![info exists Priv(autoscan,direction,$w)]} { set Priv(autoscan,direction,$w) xy } set scrollX [string match *x* $Priv(autoscan,direction,$w)] set scrollY [string match *y* $Priv(autoscan,direction,$w)] if {($scrollX && (($x < $x1 + $margin) || ($x >= $x2 - $margin))) || ($scrollY && (($y < $y1 + $margin) || ($y >= $y2 - $margin)))} { if {[info exists Priv(autoscan,afterId,$w)]} return if {$scrollY && $y >= $y2 - $margin} { $w yview scroll 1 units set delay [$w cget -yscrolldelay] } elseif {$scrollY && $y < $y1 + $margin} { $w yview scroll -1 units set delay [$w cget -yscrolldelay] } elseif {$scrollX && $x >= $x2 - $margin} { $w xview scroll 1 units set delay [$w cget -xscrolldelay] } elseif {$scrollX && $x < $x1 + $margin} { $w xview scroll -1 units set delay [$w cget -xscrolldelay] } set count [scan $delay "%d %d" d1 d2] if {[info exists Priv(autoscan,scanning,$w)]} { if {$count == 2} { set delay $d2 } } else { if {$count == 2} { set delay $d1 } set Priv(autoscan,scanning,$w) 1 } if {$Priv(autoscan,command,$w) ne ""} { set command [string map [list %T $w %x $x %y $y] $Priv(autoscan,command,$w)] eval $command } set Priv(autoscan,afterId,$w) [after $delay [list TreeCtrl::AutoScanCheckAux $w]] return } AutoScanCancel $w return } # ::TreeCtrl::AutoScanCheckAux -- # # Gets the location of the pointer and calls AutoScanCheck. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::AutoScanCheckAux {w} { variable Priv # Not quite sure how this can happen if {![info exists Priv(autoscan,afterId,$w)]} return unset Priv(autoscan,afterId,$w) set x [winfo pointerx $w] set y [winfo pointery $w] set x [expr {$x - [winfo rootx $w]}] set y [expr {$y - [winfo rooty $w]}] AutoScanCheck $w $x $y return } # ::TreeCtrl::AutoScanCancel -- # # Cancels any pending [after] callback to AutoScanCheckAux. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::AutoScanCancel {w} { variable Priv if {[info exists Priv(autoscan,afterId,$w)]} { after cancel $Priv(autoscan,afterId,$w) unset Priv(autoscan,afterId,$w) } unset -nocomplain Priv(autoscan,scanning,$w) return } # ::TreeCtrl::ColumnDragScrollCheck -- # # Sees if the given pointer coords are outside the left or right edges of # the content area of the treectrl (ie, not including borders). If so and # auto-scanning is not already in progress, then the window is scrolled # horizontally and the column drag-image is repositioned, and an [after] # callback to ColumnDragScrollCheckAux is scheduled. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::ColumnDragScrollCheck {w x y} { variable Priv scan [$w contentbox] "%d %d %d %d" x1 y1 x2 y2 if {($x < $x1) || ($x >= $x2)} { if {![info exists Priv(autoscan,afterId,$w)]} { set bbox1 [$w column bbox $Priv(column)] if {$x >= $x2} { $w xview scroll 1 units } else { $w xview scroll -1 units } set bbox2 [$w column bbox $Priv(column)] if {[lindex $bbox1 0] != [lindex $bbox2 0]} { incr Priv(columnDrag,x) [expr {[lindex $bbox2 0] - [lindex $bbox1 0]}] $w column dragconfigure -imageoffset [expr {$x - $Priv(columnDrag,x)}] if {[ColumnDragFindBefore $w $x $Priv(columnDrag,y) $Priv(column) indColumn indSide]} { $w column dragconfigure -indicatorcolumn $indColumn \ -indicatorside $indSide } else { $w column dragconfigure -indicatorcolumn "" } } set Priv(autoscan,afterId,$w) [after 50 [list TreeCtrl::ColumnDragScrollCheckAux $w]] } return } AutoScanCancel $w return } # ::TreeCtrl::ColumnDragScrollCheckAux -- # # Gets the location of the pointer and calls ColumnDragScrollCheck. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::ColumnDragScrollCheckAux {w} { variable Priv # Not quite sure how this can happen if {![info exists Priv(autoscan,afterId,$w)]} return unset Priv(autoscan,afterId,$w) set x [winfo pointerx $w] set y [winfo pointery $w] set x [expr {$x - [winfo rootx $w]}] set y [expr {$y - [winfo rooty $w]}] ColumnDragScrollCheck $w $x $y return } # ::TreeCtrl::UpDown -- # # Returns the id of an item above or below the given item that the active # item could be set to. If the given item isn't visible, the first visible # enabled item is returned. An attempt is made to choose an item in the # same column over repeat calls; this gives a better result if some rows # have less items than others. Only enabled items are considered. # # Arguments: # w The treectrl widget. # item Item to move from, typically the active item. # n +1 to move down, -1 to move up. proc ::TreeCtrl::UpDown {w item n} { variable Priv set rnc [$w item rnc $item] if {$rnc eq ""} { return [$w item id {first visible state enabled}] } scan $rnc "%d %d" row col set Priv(keyNav,row,$w) [expr {$row + $n}] if {![info exists Priv(keyNav,rnc,$w)] || $rnc ne $Priv(keyNav,rnc,$w)} { set Priv(keyNav,col,$w) $col } set item2 [$w item id "rnc $Priv(keyNav,row,$w) $Priv(keyNav,col,$w)"] if {[$w item compare $item == $item2]} { set Priv(keyNav,row,$w) $row if {![$w item enabled $item2]} { return "" } } else { set Priv(keyNav,rnc,$w) [$w item rnc $item2] if {![$w item enabled $item2]} { return [UpDown $w $item2 $n] } } return $item2 } # ::TreeCtrl::LeftRight -- # # Returns the id of an item left or right of the given item that the active # item could be set to. If the given item isn't visible, the first visible # enabled item is returned. An attempt is made to choose an item in the # same row over repeat calls; this gives a better result if some columns # have less items than others. Only enabled items are considered. # # Arguments: # w The treectrl widget. # item Item to move from, typically the active item. # n +1 to move right, -1 to move left. proc ::TreeCtrl::LeftRight {w item n} { variable Priv set rnc [$w item rnc $item] if {$rnc eq ""} { return [$w item id {first visible state enabled}] } scan $rnc "%d %d" row col set Priv(keyNav,col,$w) [expr {$col + $n}] if {![info exists Priv(keyNav,rnc,$w)] || $rnc ne $Priv(keyNav,rnc,$w)} { set Priv(keyNav,row,$w) $row } set item2 [$w item id "rnc $Priv(keyNav,row,$w) $Priv(keyNav,col,$w)"] if {[$w item compare $item == $item2]} { set Priv(keyNav,col,$w) $col if {![$w item enabled $item2]} { return "" } } else { set Priv(keyNav,rnc,$w) [$w item rnc $item2] if {![$w item enabled $item2]} { return [LeftRight $w $item2 $n] } } return $item2 } # ::TreeCtrl::SetActiveItem -- # # Sets the active item, scrolls it into view, and makes it the only selected # item. If -selectmode is extended, makes the active item the anchor of any # future extended selection. # # Arguments: # w The treectrl widget. # item The new active item, or "". proc ::TreeCtrl::SetActiveItem {w item} { if {$item eq ""} return $w activate $item $w see active $w selection modify active all switch [$w cget -selectmode] { extended { $w selection anchor active set Priv(prev) [$w item id active] set Priv(selection) {} } } return } # ::TreeCtrl::Extend -- # # Does nothing unless we're in extended selection mode; in this # case it moves the location cursor (active item) up, down, left or # right, and extends the selection to that point. # # Arguments: # w The treectrl widget. # dir up, down, left or right proc ::TreeCtrl::Extend {w dir} { variable Priv if {[string compare [$w cget -selectmode] "extended"]} { return } if {![info exists Priv(selection)]} { $w selection add active set Priv(selection) [$w selection get] } switch -- $dir { above { set item [UpDown $w active -1] } below { set item [UpDown $w active 1] } left { set item [LeftRight $w active -1] } right { set item [LeftRight $w active 1] } } if {$item eq ""} return $w activate $item $w see active SelectionMotion $w [$w item id active] return } # ::TreeCtrl::DataExtend # # This procedure is called for key-presses such as Shift-KEndData. # If the selection mode isn't multiple or extended then it does nothing. # Otherwise it moves the active item and, if we're in # extended mode, extends the selection to that point. # # Arguments: # w The treectrl widget. # item Item to become new active item. proc ::TreeCtrl::DataExtend {w item} { if {$item eq ""} return set mode [$w cget -selectmode] if {[string equal $mode "extended"]} { $w activate $item $w see $item if {[$w selection includes anchor]} { SelectionMotion $w $item } } elseif {[string equal $mode "multiple"]} { $w activate $item $w see $item } return } # ::TreeCtrl::Cancel # # This procedure is invoked to cancel an extended selection in # progress. If there is an extended selection in progress, it # restores all of the items between the active one and the anchor # to their previous selection state. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::Cancel w { variable Priv if {[string compare [$w cget -selectmode] "extended"]} { return } set first [$w item id anchor] set last $Priv(prev) if { [string equal $last ""] } { # Not actually doing any selection right now return } if {[$w item compare $first > $last]} { set tmp $first set first $last set last $tmp } $w selection clear $first $last while {[$w item compare $first <= $last]} { if {[lsearch $Priv(selection) $first] >= 0} { $w selection add $first } set first [$w item id "$first next visible"] } return } # ::TreeCtrl::SelectAll # # This procedure is invoked to handle the "select all" operation. # For single and browse mode, it just selects the active item. # Otherwise it selects everything in the widget. # # Arguments: # w The treectrl widget. proc ::TreeCtrl::SelectAll w { set mode [$w cget -selectmode] if {[string equal $mode "single"] || [string equal $mode "browse"]} { $w selection modify active all } else { $w selection add all } return } # ::TreeCtrl::MarqueeBegin -- # # Shows the selection rectangle at the given coords. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::MarqueeBegin {w x y} { set x [$w canvasx $x] set y [$w canvasy $y] $w marquee coords $x $y $x $y $w marquee configure -visible yes return } # ::TreeCtrl::MarqueeUpdate -- # # Resizes the selection rectangle. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::MarqueeUpdate {w x y} { set x [$w canvasx $x] set y [$w canvasy $y] $w marquee corner $x $y return } # ::TreeCtrl::MarqueeEnd -- # # Hides the selection rectangle. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::MarqueeEnd {w x y} { $w marquee configure -visible no return } # ::TreeCtrl::ScanMark -- # # Marks the start of a possible scan drag operation. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::ScanMark {w x y} { variable Priv $w scan mark $x $y set Priv(x) $x set Priv(y) $y set Priv(mouseMoved) 0 return } # ::TreeCtrl::ScanDrag -- # # Performs a scan drag if the mouse moved. # # Arguments: # w The treectrl widget. # x Window coord of pointer. # y Window coord of pointer. proc ::TreeCtrl::ScanDrag {w x y} { variable Priv if {![info exists Priv(x)]} { set Priv(x) $x } if {![info exists Priv(y)]} { set Priv(y) $y } if {($x != $Priv(x)) || ($y != $Priv(y))} { set Priv(mouseMoved) 1 } if {[info exists Priv(mouseMoved)] && $Priv(mouseMoved)} { $w scan dragto $x $y } return } # ::TreeCtrl::TryEvent -- # # This procedure is used to cause a treectrl to generate a dynamic event. # If the treectrl doesn't have the event defined (because you didn't call # the [notify install] command) nothing happens. TreeCtrl::PercentsCmd is # used to perform %-substitution on any scripts bound to the event. # # Arguments: # T The treectrl widget. # event Name of event. # detail Name of detail or "". # charMap %-char substitution list (even number of elements). proc ::TreeCtrl::TryEvent {T event detail charMap} { if {[lsearch -exact [$T notify eventnames] $event] == -1} return if {$detail ne ""} { if {[lsearch -exact [$T notify detailnames $event] $detail] == -1} return $T notify generate <$event-$detail> $charMap "::TreeCtrl::PercentsCmd $T" } else { $T notify generate <$event> $charMap "::TreeCtrl::PercentsCmd $T" } return } # ::TreeCtrl::PercentsCmd -- # # This command is passed to [notify generate] to perform %-substitution on # scripts bound to dynamic events. It supports the same set of substitution # characters as the built-in static events (plus any event-specific chars). # # Arguments: # T The treectrl widget. # char %-char to be replaced in bound scripts. # object Same arg passed to [notify bind]. # event Name of event. # detail Name of detail or "". # charMap %-char substitution list (even number of elements). proc ::TreeCtrl::PercentsCmd {T char object event detail charMap} { if {$detail ne ""} { set pattern <$event-$detail> } else { set pattern <$event> } switch -- $char { d { return $detail } e { return $event } P { return $pattern } W { return $object } T { return $T } ? { array set map $charMap array set map [list T $T W $object P $pattern e $event d $detail] return [array get map] } default { array set map [list $char $char] array set map $charMap return $map($char) } } return } namespace eval TreeCtrl { catch { foreach theme [ttk::style theme names] { ttk::style theme settings $theme { ttk::style configure TreeCtrlHeading -relief raised -font TkHeadingFont ttk::style map TreeCtrlHeading -relief { pressed sunken } } } } } tktreectrl-2.2.8/license.terms0000700000175600010010000000414710233773573014622 0ustar TimNoneThis software is copyrighted by Tim Baker and other parties. 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. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. 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. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. tktreectrl-2.2.8/Makefile.in0000664000175600010010000004627610760367022014204 0ustar TimNone# 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 ActiveState SRL. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: Makefile.in,v 1.15 2008/02/24 22:22:10 treectrl Exp $ #======================================================================== # Edit the following few lines when writing a new extension #======================================================================== #======================================================================== # Nothing of the variables below this line 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_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_EXTRA_FILES = PKG_MAN_PAGES = #======================================================================== # "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 = $(lib_BINARIES) SHELL = @SHELL@ srcdir = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ datadir = @datadir@ datarootdir = @datarootdir@ mandir = @mandir@ includedir = @includedir@ DESTDIR = PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_PATCHLEVEL) pkgdatadir = $(datadir)/$(PKG_DIR) pkglibdir = $(libdir)/$(PKG_DIR) pkgincludedir = $(includedir)/$(PKG_DIR) top_builddir = . INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PACKAGE_PATCHLEVEL = @PACKAGE_PATCHLEVEL@ CC = @CC@ CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ CFLAGS_WARNING = @CFLAGS_WARNING@ CLEANFILES = @CLEANFILES@ 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_SRC_DIR = @TCL_SRC_DIR@ TCL_BIN_DIR = @TCL_BIN_DIR@ TK_SRC_DIR = @TK_SRC_DIR@ TK_BIN_DIR = @TK_BIN_DIR@ # Not used, but retained for reference of what libs Tcl required TCL_LIBS = @TCL_LIBS@ TK_LIBS = @TK_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):$(TK_BIN_DIR) TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \ TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library` \ TREECTRL_LIBRARY=`@CYGPATH@ $(srcdir)/library` \ @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ PATH="$(EXTRA_PATH):$(PATH)" \ TCLLIBPATH="$(top_builddir)" TCLSH_PROG = @TCLSH_PROG@ WISH_PROG = @WISH_PROG@ TCLSH = $(TCLSH_ENV) $(TCLSH_PROG) WISH = $(TCLSH_ENV) $(WISH_PROG) # The local includes must come first, because the TK_XINCLUDES can be # just a comment INCLUDES = @PKG_INCLUDES@ \ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ PKG_CFLAGS = @PKG_CFLAGS@ DEFS = @DEFS@ $(PKG_CFLAGS) CONFIG_CLEAN_FILES = Makefile CPPFLAGS = @CPPFLAGS@ LIBS = @PKG_LIBS@ @LIBS@ AR = @AR@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) #======================================================================== # Start of user-definable TARGETS section #======================================================================== #======================================================================== # TEA TARGETS. Please note that the "libraries:" target refers to platform # independent files, and the "binaries:" target inclues 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) pkgIndex.tcl libraries: doc-x: @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" doc: @echo "No docs to build" install: all install-binaries install-libraries install-doc install-binaries: binaries install-lib-binaries install-bin-binaries @mkdir -p $(DESTDIR)$(pkglibdir) $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir) @list='$(PKG_EXTRA_FILES)'; 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 #======================================================================== # This rule installs platform-independent files, such as header files. #======================================================================== install-libraries: libraries #======================================================================== # Install documentation. Unix manpages should go in the $(mandir) # directory. #======================================================================== install-doc-x: @mkdir -p $(DESTDIR)$(mandir)/mann @echo "Installing documentation in $(DESTDIR)$(mandir)" @for i in $(srcdir)/doc/*.n; do \ echo "Installing $$i"; \ rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \ $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \ done install-doc: install-doc-x mkdir -p $(DESTDIR)$(pkglibdir)/htmldoc cp $(srcdir)/doc/*.html $(DESTDIR)$(pkglibdir)/htmldoc test: binaries libraries $(WISH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) | cat shell: binaries libraries @$(WISH) $(SCRIPT) demo: binaries libraries @$(WISH) `@CYGPATH@ $(srcdir)/demos/demo.tcl` | cat gdb: $(TCLSH_ENV) gdb --silent --args $(WISH_PROG) $(srcdir)/demos/demo.tcl 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. # # NOTE regarding the manifest(s): When building on a non-Windows box the # treectrlNN.dll.manifest file should not exist. When building with # MingW GCC the manifest will also not exist. Only when building with # a Microsoft compiler that auto-generates a manifest (to pick the correct # MSVCRT runtime) will $@.manifest exist; in this case mt.exe should # also exist. If mt.exe is used there is actually no need for treectrl.rc # to include treectrl.dll.manifest since mt.exe will clobber that resource # with the merged manifests. #======================================================================== $(PKG_LIB_FILE): $(PKG_OBJECTS) -rm -f $(PKG_LIB_FILE) ${MAKE_LIB} $(RANLIB) $(PKG_LIB_FILE) if test -f $@.manifest; then \ mt -nologo -manifest $@.manifest treectrl.dll.manifest "-outputresource:$@;#2"; \ fi; #======================================================================== # 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: # # tkpkg.$(OBJEXT): $(srcdir)/src/win/tkpkg.c # $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/tkpkg.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. #======================================================================== # I added leading $(srcdir) because autoconf 2.53 strips it off VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win .c.@OBJEXT@: $(COMPILE) -c `@CYGPATH@ $<` -o $@ .rc.@RES@: @RC@ @RC_OUT@ $@ @RC_INCLUDE@ "`@CYGPATH@ $(srcdir)`" @RC_DEPARG@ #======================================================================== # Create the pkgIndex.tcl file. #======================================================================== pkgIndex.tcl: (\ echo 'if {[catch {package require Tcl @TK_VERSION@}]} return';\ echo 'set script ""';\ echo 'if {![info exists ::env(TREECTRL_LIBRARY)]';\ echo ' && [file exists [file join $$dir treectrl.tcl]]} {';\ echo ' append script "set ::treectrl_library \"$$dir\"\n"';\ echo '}';\ echo 'append script "load \"[file join $$dir $(PKG_LIB_FILE)]\" $(PACKAGE_NAME)"';\ echo 'package ifneeded $(PACKAGE_NAME) $(PACKAGE_PATCHLEVEL) $$script'\ ) > pkgIndex.tcl #======================================================================== # 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 = gtar zcvf $(PKG_DIR).tar.gz $(PKG_DIR) DIST_NAME = tktreectrl-$(PACKAGE_PATCHLEVEL) DIST_ARC = $(DIST_NAME).tar.gz COMPRESS = tar zcvf $(DIST_ARC) $(DIST_NAME) DIST_ROOT = /tmp/dist DIST_DIR = $(DIST_ROOT)/$(DIST_NAME) DIST_DEMOS = biglist bitmaps column-lock demo explorer firefox help \ imovie layout mailwasher mycomputer outlook-folders \ outlook-newgroup random span style-editor textvariable \ www-options DIST_DOCS = man.macros treectrl.html treectrl.man treectrl.n DIST_DOCS2 = "What's New in TkTreeCtrl.html" DIST_LIBRARY = filelist-bindings.tcl treectrl.tcl dist-clean: rm -rf $(DIST_DIR) $(DIST_ROOT)/$(DIST_ARC) dist: dist-clean mkdir -p $(DIST_DIR) mkdir -p $(DIST_DIR)/demos mkdir -p $(DIST_DIR)/demos/pics mkdir -p $(DIST_DIR)/doc mkdir -p $(DIST_DIR)/generic mkdir -p $(DIST_DIR)/library mkdir -p $(DIST_DIR)/shellicon mkdir -p $(DIST_DIR)/shellicon/tclconfig mkdir -p $(DIST_DIR)/tclconfig mkdir -p $(DIST_DIR)/tests list='aclocal.m4 ChangeLog configure configure.ac license.terms Makefile.in README.txt treectrl.dll.manifest.in treectrl.rc winrc.m4'; \ for p in $$list; do \ cp -p $(srcdir)/$$p $(DIST_DIR)/$$p; \ done chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4 chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.ac list='$(DIST_DEMOS)'; for p in $$list; do \ cp -p $(srcdir)/demos/$$p.tcl $(DIST_DIR)/demos/$$p.tcl; \ done cp -p $(srcdir)/demos/pics/*.gif $(DIST_DIR)/demos/pics/ list='$(DIST_DOCS)'; for p in $$list; do \ cp -p $(srcdir)/doc/$$p $(DIST_DIR)/doc/$$p; \ done cp -p $(srcdir)/doc/$(DIST_DOCS2) $(DIST_DIR)/doc/$(DIST_DOCS2) cp -p $(srcdir)/generic/*.[ch] $(DIST_DIR)/generic/ list='$(DIST_LIBRARY)'; for p in $$list; do \ cp -p $(srcdir)/library/$$p $(DIST_DIR)/library/$$p; \ done list='aclocal.m4 configure configure.ac Makefile.in shellicon.c'; \ for p in $$list; do \ cp -p $(srcdir)/shellicon/$$p $(DIST_DIR)/shellicon/$$p; \ done chmod 664 $(DIST_DIR)/shellicon/Makefile.in $(DIST_DIR)/shellicon/aclocal.m4 chmod 775 $(DIST_DIR)/shellicon/configure $(DIST_DIR)/shellicon/configure.ac list='install-sh README.txt tcl.m4'; \ for p in $$list; do \ cp -p $(srcdir)/shellicon/tclconfig/$$p $(DIST_DIR)/shellicon/tclconfig/$$p; \ done chmod 664 $(DIST_DIR)/shellicon/tclconfig/tcl.m4 chmod +x $(DIST_DIR)/shellicon/tclconfig/install-sh cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \ $(DIST_DIR)/tclconfig/ chmod 664 $(DIST_DIR)/tclconfig/tcl.m4 chmod +x $(DIST_DIR)/tclconfig/install-sh cp -p $(srcdir)/tests/all.tcl $(srcdir)/tests/*.test $(DIST_DIR)/tests/ (cd $(DIST_ROOT); $(COMPRESS);) #======================================================================== # Windows binary distribution #======================================================================== DIST_WIN_NAME = treectrl$(PACKAGE_PATCHLEVEL) DIST_WIN_DIR = $(DIST_ROOT)/$(DIST_WIN_NAME) DIST_WIN_ARC = tktreectrl-$(PACKAGE_PATCHLEVEL)-Tk@TK_VERSION@-win32.zip COMPRESS_WIN = zip -r -v -9 $(DIST_WIN_ARC) $(DIST_WIN_NAME) UPX = upx -9 $(DIST_WIN_DIR)/$(PKG_LIB_FILE) dist-win-clean: rm -rf $(DIST_WIN_DIR) $(DIST_ROOT)/$(DIST_WIN_ARC) dist-win: dist-win-clean mkdir -p $(DIST_WIN_DIR) mkdir -p $(DIST_WIN_DIR)/demos mkdir -p $(DIST_WIN_DIR)/demos/pics mkdir -p $(DIST_WIN_DIR)/doc mkdir -p $(DIST_WIN_DIR)/shellicon list='pkgIndex.tcl $(PKG_LIB_FILE)'; \ for p in $$list; do \ cp -p $(top_builddir)/$$p $(DIST_WIN_DIR)/$$p; \ done list='license.terms README.txt'; \ for p in $$list; do \ cp -p $(srcdir)/$$p $(DIST_WIN_DIR)/$$p; \ done strip -s $(DIST_WIN_DIR)/$(PKG_LIB_FILE) $(UPX) list='$(DIST_LIBRARY)'; for p in $$list; do \ cp -p $(srcdir)/library/$$p $(DIST_WIN_DIR)/$$p; \ done list='$(DIST_DEMOS)'; for p in $$list; do \ cp -p $(srcdir)/demos/$$p.tcl $(DIST_WIN_DIR)/demos/$$p.tcl; \ done cp -p $(srcdir)/demos/pics/*.gif $(DIST_WIN_DIR)/demos/pics/ list='$(DIST_DOCS)'; for p in $$list; do \ cp -p $(srcdir)/doc/$$p $(DIST_WIN_DIR)/doc/$$p; \ done cp -p $(srcdir)/doc/$(DIST_DOCS2) $(DIST_WIN_DIR)/doc/$(DIST_DOCS2) TCL_TRIM_DOTS=`echo $(PACKAGE_VERSION) | tr -d .`; \ SHELLICON_DLL="shellicon$$TCL_TRIM_DOTS.dll"; \ cp -p $(top_builddir)/shellicon/$$SHELLICON_DLL $(DIST_WIN_DIR)/shellicon/$$SHELLICON_DLL; \ strip -s $(DIST_WIN_DIR)/shellicon/$$SHELLICON_DLL; cp -p $(top_builddir)/shellicon/pkgIndex.tcl $(DIST_WIN_DIR)/shellicon/pkgIndex.tcl (cd $(DIST_ROOT); $(COMPRESS_WIN);) #======================================================================== # End of user-definable section #======================================================================== #======================================================================== # Don't modify the file to clean here. Instead, set the "CLEANFILES" # variable in configure.in #======================================================================== 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: @mkdir -p $(DESTDIR)$(pkglibdir) @list='$(lib_BINARIES)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p"; \ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \ echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \ $(RANLIB) $(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 #======================================================================== # 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: @mkdir -p $(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 .SUFFIXES: .c .$(OBJEXT) .SUFFIXES: .@RES@ .SUFFIXES: .rc 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 # 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: tktreectrl-2.2.8/README.txt0000700000175600010010000000040410265321014013572 0ustar TimNoneCurrent maintainer: Tim Baker (treectrl@users.sourceforge.net) Website: http://tktreectrl.sourceforge.net/ An extra help document with examples and pictures is available from the main website: http://tktreectrl.sourceforge.net/Understanding%20TkTreeCtrl.html tktreectrl-2.2.8/shellicon/0000755000175600010010000000000011073207472014076 5ustar TimNonetktreectrl-2.2.8/shellicon/aclocal.m40000664000175600010010000000022310557742240015740 0ustar TimNone# # Include the TEA standard macro set # builtin(include,tclconfig/tcl.m4) # # Add here whatever m4 macros you want to define for your package # tktreectrl-2.2.8/shellicon/configure0000775000175600010010000125455311073205364016024 0ustar TimNone#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for shellicon 2.2. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 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=: # Zsh 3.x and 4.x performs 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 # PATH needs CR # 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 # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false 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.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. 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 echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. 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 # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH if test "x$CONFIG_SHELL" = x; then if (eval ":") 2>/dev/null; then as_have_required=yes else as_have_required=no fi if test $as_have_required = yes && (eval ": (as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=\$LINENO as_lineno_2=\$LINENO test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } ") 2> /dev/null; then : else as_candidate_shells= as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. case $as_dir in /*) for as_base in sh bash ksh sh5; do as_candidate_shells="$as_candidate_shells $as_dir/$as_base" done;; esac done IFS=$as_save_IFS for as_shell in $as_candidate_shells $SHELL; do # Try only shells that exist, to save several forks. if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { ("$as_shell") 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs 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 : _ASEOF }; then CONFIG_SHELL=$as_shell as_have_required=yes if { "$as_shell" 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs 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_func_return () { (exit $1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = "$1" ); then : else exitcode=1 echo positional parameters were not saved. fi test $exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } _ASEOF }; then break fi fi done if test "x$CONFIG_SHELL" != x; then for as_var in BASH_ENV ENV do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test $as_have_required = no; then echo This script requires a shell more modern than all the echo shells that I found on your system. Please install a echo modern shell, or manually run the script under such a echo shell if you do have one. { (exit 1); exit 1; } fi fi fi (eval "as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0") || { echo No shell found that supports shell functions. echo Please tell autoconf@gnu.org about your system, echo including any error possibly output before this echo message } as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. 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" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # 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 } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi 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 fi echo >conf$$.file 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 -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' 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=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # 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 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, 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= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='shellicon' PACKAGE_TARNAME='shellicon' PACKAGE_VERSION='2.2' PACKAGE_STRING='shellicon 2.2' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datarootdir datadir sysconfdir sharedstatedir localstatedir includedir oldincludedir docdir infodir htmldir dvidir pdfdir psdir libdir localedir mandir DEFS ECHO_C ECHO_N ECHO_T LIBS build_alias host_alias target_alias PACKAGE_PATCHLEVEL CYGPATH EXEEXT PKG_LIB_FILE PKG_STUB_LIB_FILE PKG_STUB_SOURCES PKG_STUB_OBJECTS PKG_TCL_SOURCES PKG_HEADERS PKG_INCLUDES PKG_LIBS PKG_CFLAGS TCL_VERSION TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_LIBS TCL_DEFS TCL_EXTRA_CFLAGS TCL_LD_FLAGS TCL_SHLIB_LD_LIBS TK_VERSION TK_BIN_DIR TK_SRC_DIR TK_LIB_FILE TK_LIB_FLAG TK_LIB_SPEC TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_STUB_LIB_SPEC TK_LIBS TK_XINCLUDES CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC OBJEXT CPP INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA SET_MAKE RANLIB GREP EGREP MATH_LIBS PKG_SOURCES PKG_OBJECTS TCL_TOP_DIR_NATIVE TCL_GENERIC_DIR_NATIVE TCL_UNIX_DIR_NATIVE TCL_WIN_DIR_NATIVE TCL_BMAP_DIR_NATIVE TCL_TOOL_DIR_NATIVE TCL_PLATFORM_DIR_NATIVE TCL_INCLUDES TK_TOP_DIR_NATIVE TK_UNIX_DIR_NATIVE TK_WIN_DIR_NATIVE TK_GENERIC_DIR_NATIVE TK_XLIB_DIR_NATIVE TK_PLATFORM_DIR_NATIVE TK_INCLUDES XMKMF CLEANFILES TCL_THREADS SHARED_BUILD AR CELIB_DIR LIBOBJS DL_LIBS CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING STLIB_LD SHLIB_LD SHLIB_LD_LIBS SHLIB_CFLAGS LD_LIBRARY_PATH_VAR TCL_DBGX CFLAGS_DEFAULT LDFLAGS_DEFAULT MAKE_LIB MAKE_SHARED_LIB MAKE_STATIC_LIB MAKE_STUB_LIB RANLIB_STUB TCLSH_PROG WISH_PROG LTLIBOBJS' ac_subst_files='' 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 # 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=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_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=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_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=\$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_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=\$ac_optarg ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=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 ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && 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'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute directory names. 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 case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; } 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 echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 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 .` || { echo "$as_me: error: Working directory cannot be determined" >&2 { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || { echo "$as_me: error: pwd does not report name of working directory" >&2 { (exit 1); exit 1; }; } # 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 -- "$0" || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X"$0" | 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 .." { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 { (exit 1); exit 1; }; } 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 shellicon 2.2 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/shellicon] --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 shellicon 2.2:";; esac cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-threads build with threads --enable-shared build and link with shared libraries (default: on) --enable-64bit enable 64bit support (default: off) --enable-64bit-vis enable 64bit Sparc VIS support (default: off) --enable-wince enable Win/CE support (where applicable) --disable-load disallow dynamic loading and "load" command (default: enabled) --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-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 if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory 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. _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" || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`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 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 shellicon configure 2.2 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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 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 shellicon $as_me 2.2, which was generated by GNU Autoconf 2.61. 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=. 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=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$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 ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export 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 cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX 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_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_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 cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" 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'; { (exit 1); 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 # 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 # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then set x "$CONFIG_SITE" elif test "x$prefix" != xNONE; then set x "$prefix/share/config.site" "$prefix/etc/config.site" else set x "$ac_default_prefix/share/config.site" \ "$ac_default_prefix/etc/config.site" fi shift for ac_site_file do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" 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. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 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,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 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 { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`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. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } 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 PACKAGE_PATCHLEVEL=2.2.8 cat >>confdefs.h <<_ACEOF #define PACKAGE_PATCHLEVEL "$PACKAGE_PATCHLEVEL" _ACEOF # TEA extensions pass this us the version of TEA they think they # are compatible with. TEA_VERSION="3.5" { echo "$as_me:$LINENO: checking for correct TEA configuration" >&5 echo $ECHO_N "checking for correct TEA configuration... $ECHO_C" >&6; } if test x"${PACKAGE_NAME}" = x ; then { { echo "$as_me:$LINENO: error: The PACKAGE_NAME variable must be defined by your TEA configure.in" >&5 echo "$as_me: error: The PACKAGE_NAME variable must be defined by your TEA configure.in" >&2;} { (exit 1); exit 1; }; } fi if test x"3.5" = x ; then { { echo "$as_me:$LINENO: error: TEA version not specified." >&5 echo "$as_me: error: TEA version not specified." >&2;} { (exit 1); exit 1; }; } elif test "3.5" != "${TEA_VERSION}" ; then { echo "$as_me:$LINENO: result: warning: requested TEA version \"3.5\", have \"${TEA_VERSION}\"" >&5 echo "${ECHO_T}warning: requested TEA version \"3.5\", have \"${TEA_VERSION}\"" >&6; } else { echo "$as_me:$LINENO: result: ok (TEA ${TEA_VERSION})" >&5 echo "${ECHO_T}ok (TEA ${TEA_VERSION})" >&6; } fi case "`uname -s`" in *win32*|*WIN32*|*CYGWIN_NT*|*CYGWIN_9*|*CYGWIN_ME*|*MINGW32_*) # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CYGPATH+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CYGPATH="cygpath -w" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $CYGPATH" >&5 echo "${ECHO_T}$CYGPATH" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi EXEEXT=".exe" TEA_PLATFORM="windows" ;; *) CYGPATH=echo EXEEXT="" TEA_PLATFORM="unix" ;; 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 # 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_... 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 { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in tclconfig \"$srcdir\"/tclconfig" >&5 echo "$as_me: error: cannot find install-sh or install.sh in tclconfig \"$srcdir\"/tclconfig" >&2;} { (exit 1); exit 1; }; } 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 { echo "$as_me:$LINENO: checking for Tcl configuration" >&5 echo $ECHO_N "checking for Tcl configuration... $ECHO_C" >&6; } if test "${ac_cv_c_tclconfig+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { echo "$as_me:$LINENO: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 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 { { echo "$as_me:$LINENO: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&5 echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&2;} { (exit 1); exit 1; }; } 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 -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` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig=`(cd $i/Tcl.framework; pwd)` break fi done fi # 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/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 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 -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" { echo "$as_me:$LINENO: WARNING: Can't find Tcl configuration definitions" >&5 echo "$as_me: WARNING: Can't find Tcl configuration definitions" >&2;} exit 0 else no_tcl= TCL_BIN_DIR=${ac_cv_c_tclconfig} { echo "$as_me:$LINENO: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 echo "${ECHO_T}found ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi fi { echo "$as_me:$LINENO: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 echo $ECHO_N "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... $ECHO_C" >&6; } if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then { echo "$as_me:$LINENO: result: loading" >&5 echo "${ECHO_T}loading" >&6; } . ${TCL_BIN_DIR}/tclConfig.sh else { echo "$as_me:$LINENO: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 echo "${ECHO_T}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 arbitary 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"` -framework ${TCL_LIB_FILE}" break fi done fi if test -f ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}; then TCL_STUB_LIB_SPEC="-L${TCL_BIN_DIR} ${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}\"" #-------------------------------------------------------------------- # 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 { echo "$as_me:$LINENO: checking for Tk configuration" >&5 echo $ECHO_N "checking for Tk configuration... $ECHO_C" >&6; } if test "${ac_cv_c_tkconfig+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { echo "$as_me:$LINENO: WARNING: --with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself" >&5 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 { { echo "$as_me:$LINENO: error: ${with_tkconfig} directory doesn't contain tkConfig.sh" >&5 echo "$as_me: error: ${with_tkconfig} directory doesn't contain tkConfig.sh" >&2;} { (exit 1); exit 1; }; } 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 -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` \ ; 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/lib 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig=`(cd $i; pwd)` break fi done fi # 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 -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" { echo "$as_me:$LINENO: WARNING: Can't find Tk configuration definitions" >&5 echo "$as_me: WARNING: Can't find Tk configuration definitions" >&2;} exit 0 else no_tk= TK_BIN_DIR=${ac_cv_c_tkconfig} { echo "$as_me:$LINENO: result: found ${TK_BIN_DIR}/tkConfig.sh" >&5 echo "${ECHO_T}found ${TK_BIN_DIR}/tkConfig.sh" >&6; } fi fi { echo "$as_me:$LINENO: checking for existence of ${TK_BIN_DIR}/tkConfig.sh" >&5 echo $ECHO_N "checking for existence of ${TK_BIN_DIR}/tkConfig.sh... $ECHO_C" >&6; } if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then { echo "$as_me:$LINENO: result: loading" >&5 echo "${ECHO_T}loading" >&6; } . ${TK_BIN_DIR}/tkConfig.sh else { echo "$as_me:$LINENO: result: could not find ${TK_BIN_DIR}/tkConfig.sh" >&5 echo "${ECHO_T}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 arbitary 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"` -framework ${TK_LIB_FILE}" break fi done fi if test -f ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}; then TK_STUB_LIB_SPEC="-L${TK_BIN_DIR} ${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}\"" # Ensure windowingsystem is defined if test "${TEA_PLATFORM}" = "unix" ; then case ${TK_DEFS} in *MAC_OSX_TK*) cat >>confdefs.h <<\_ACEOF #define MAC_OSX_TK 1 _ACEOF TEA_WINDOWINGSYSTEM="aqua" ;; *) TEA_WINDOWINGSYSTEM="x11" ;; esac elif test "${TEA_PLATFORM}" = "windows" ; then TEA_WINDOWINGSYSTEM="win32" fi #----------------------------------------------------------------------- # 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 { echo "$as_me:$LINENO: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&5 echo "$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&6;} prefix=${TCL_PREFIX} else { echo "$as_me:$LINENO: --prefix defaulting to /usr/local" >&5 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 { echo "$as_me:$LINENO: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&5 echo "$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&6;} exec_prefix=${TCL_EXEC_PREFIX} else { echo "$as_me:$LINENO: --exec-prefix defaulting to ${prefix}" >&5 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, AC_PROG_INSTALL 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. # If the user did not set CFLAGS, set it now to keep # the AC_PROG_CC macro from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" 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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO: checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out 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. { echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # # List of possible output files, starting from the most likely. # The algorithm is not robust to junk in `.', hence go to wildcards (a.*) # only as a last resort. b.out is created by i960 compilers. ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' # # The IRIX 6 linker writes into existing files which may not be # executable, retaining their permissions. Remove them first so a # subsequent execution test works. ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link_default") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; 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 | *.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 { echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6; } if test -z "$ac_file"; then echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } { echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6; } { echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; 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 | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext { echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT { echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; 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 ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 { echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$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 { echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* 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" 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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) { echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6; } ;; xno) { echo "$as_me:$LINENO: result: unsupported" >&5 echo "${ECHO_T}unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; esac 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 { echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 to if __STDC__ is defined, since # 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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f 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 { echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$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 to if __STDC__ is defined, since # 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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } 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 # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. { echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done IFS=$as_save_IFS fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&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 { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } SET_MAKE= else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 echo "${ECHO_T}$ac_ct_RANLIB" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&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.) #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Extract the first word of "grep ggrep" to use in msg output if test -z "$GREP"; then set dummy grep ggrep; ac_prog_name=$2 if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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" { test -f "$ac_path_GREP" && $as_test_x "$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 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" 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 ac_count=`expr $ac_count + 1` 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 fi GREP="$ac_cv_path_GREP" if test -z "$GREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_GREP=$GREP fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 echo "${ECHO_T}$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else # Extract the first word of "egrep" to use in msg output if test -z "$EGREP"; then set dummy egrep; ac_prog_name=$2 if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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" { test -f "$ac_path_EGREP" && $as_test_x "$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 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" 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 ac_count=`expr $ac_count + 1` 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 fi EGREP="$ac_cv_path_EGREP" if test -z "$EGREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_EGREP=$EGREP fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #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 rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF 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=`echo "ac_cv_header_$ac_header" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `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 { echo "$as_me:$LINENO: checking if the compiler understands -pipe" >&5 echo $ECHO_N "checking if the compiler understands -pipe... $ECHO_C" >&6; } OLDCC="$CC" CC="$CC -pipe" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CC="$OLDCC" { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi #-------------------------------------------------------------------- # Common compiler flag setup #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; } if test "${ac_cv_c_bigendian+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # See if sys/param.h defines the BYTE_ORDER macro. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then # It does; now see whether it defined to BIG_ENDIAN or not. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_c_bigendian=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # It does not; compile a test program. if test "$cross_compiling" = yes; then # try to guess the endianness by grepping values into an object file ac_cv_c_bigendian=unknown cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 }; void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } int main () { _ascii (); _ebcdic (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_bigendian=no else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 echo "${ECHO_T}$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in yes) cat >>confdefs.h <<\_ACEOF #define WORDS_BIGENDIAN 1 _ACEOF ;; no) ;; *) { { echo "$as_me:$LINENO: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&5 echo "$as_me: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} { (exit 1); exit 1; }; } ;; esac if test "${TEA_PLATFORM}" = "unix" ; then #-------------------------------------------------------------------- # On a few very rare systems, all of the libm.a stuff is # already in libc.a. Set compiler flags accordingly. # Also, Linux requires the "ieee" library for math to work # right (and it must appear before "-lm"). #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking for sin" >&5 echo $ECHO_N "checking for sin... $ECHO_C" >&6; } if test "${ac_cv_func_sin+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define sin to an innocuous variant, in case declares sin. For example, HP-UX 11i declares gettimeofday. */ #define sin innocuous_sin /* System header to define __stub macros and hopefully few prototypes, which can conflict with char sin (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef sin /* 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 sin (); /* 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_sin || defined __stub___sin choke me #endif int main () { return sin (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_sin=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_sin=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_sin" >&5 echo "${ECHO_T}$ac_cv_func_sin" >&6; } if test $ac_cv_func_sin = yes; then MATH_LIBS="" else MATH_LIBS="-lm" fi { echo "$as_me:$LINENO: checking for main in -lieee" >&5 echo $ECHO_N "checking for main in -lieee... $ECHO_C" >&6; } if test "${ac_cv_lib_ieee_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lieee $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_ieee_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_ieee_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_ieee_main" >&5 echo "${ECHO_T}$ac_cv_lib_ieee_main" >&6; } if test $ac_cv_lib_ieee_main = yes; then MATH_LIBS="-lieee $MATH_LIBS" fi #-------------------------------------------------------------------- # Interactive UNIX requires -linet instead of -lsocket, plus it # needs net/errno.h to define the socket-related error codes. #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking for main in -linet" >&5 echo $ECHO_N "checking for main in -linet... $ECHO_C" >&6; } if test "${ac_cv_lib_inet_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-linet $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_inet_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_inet_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_inet_main" >&5 echo "${ECHO_T}$ac_cv_lib_inet_main" >&6; } if test $ac_cv_lib_inet_main = yes; then LIBS="$LIBS -linet" fi if test "${ac_cv_header_net_errno_h+set}" = set; then { echo "$as_me:$LINENO: checking for net/errno.h" >&5 echo $ECHO_N "checking for net/errno.h... $ECHO_C" >&6; } if test "${ac_cv_header_net_errno_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_net_errno_h" >&5 echo "${ECHO_T}$ac_cv_header_net_errno_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking net/errno.h usability" >&5 echo $ECHO_N "checking net/errno.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking net/errno.h presence" >&5 echo $ECHO_N "checking net/errno.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: net/errno.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: net/errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: net/errno.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: net/errno.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: net/errno.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: net/errno.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: net/errno.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: net/errno.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: net/errno.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: net/errno.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: net/errno.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: net/errno.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: net/errno.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: net/errno.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: net/errno.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: net/errno.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for net/errno.h" >&5 echo $ECHO_N "checking for net/errno.h... $ECHO_C" >&6; } if test "${ac_cv_header_net_errno_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_net_errno_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_net_errno_h" >&5 echo "${ECHO_T}$ac_cv_header_net_errno_h" >&6; } fi if test $ac_cv_header_net_errno_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_NET_ERRNO_H 1 _ACEOF fi #-------------------------------------------------------------------- # Check for the existence of the -lsocket and -lnsl libraries. # The order here is important, so that they end up in the right # order in the command line generated by make. Here are some # special considerations: # 1. Use "connect" and "accept" to check for -lsocket, and # "gethostbyname" to check for -lnsl. # 2. Use each function name only once: can't redo a check because # autoconf caches the results of the last check and won't redo it. # 3. Use -lnsl and -lsocket only if they supply procedures that # aren't already present in the normal libraries. This is because # IRIX 5.2 has libraries, but they aren't needed and they're # bogus: they goof up name resolution if used. # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. # To get around this problem, check for both libraries together # if -lsocket doesn't work by itself. #-------------------------------------------------------------------- tcl_checkBoth=0 { echo "$as_me:$LINENO: checking for connect" >&5 echo $ECHO_N "checking for connect... $ECHO_C" >&6; } if test "${ac_cv_func_connect+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define connect to an innocuous variant, in case declares connect. For example, HP-UX 11i declares gettimeofday. */ #define connect innocuous_connect /* System header to define __stub macros and hopefully few prototypes, which can conflict with char connect (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef connect /* 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 connect (); /* 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_connect || defined __stub___connect choke me #endif int main () { return connect (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_connect=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_connect=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 echo "${ECHO_T}$ac_cv_func_connect" >&6; } if test $ac_cv_func_connect = yes; then tcl_checkSocket=0 else tcl_checkSocket=1 fi if test "$tcl_checkSocket" = 1; then { echo "$as_me:$LINENO: checking for setsockopt" >&5 echo $ECHO_N "checking for setsockopt... $ECHO_C" >&6; } if test "${ac_cv_func_setsockopt+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define setsockopt to an innocuous variant, in case declares setsockopt. For example, HP-UX 11i declares gettimeofday. */ #define setsockopt innocuous_setsockopt /* System header to define __stub macros and hopefully few prototypes, which can conflict with char setsockopt (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef setsockopt /* 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 setsockopt (); /* 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_setsockopt || defined __stub___setsockopt choke me #endif int main () { return setsockopt (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_setsockopt=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_setsockopt=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_setsockopt" >&5 echo "${ECHO_T}$ac_cv_func_setsockopt" >&6; } if test $ac_cv_func_setsockopt = yes; then : else { echo "$as_me:$LINENO: checking for setsockopt in -lsocket" >&5 echo $ECHO_N "checking for setsockopt in -lsocket... $ECHO_C" >&6; } if test "${ac_cv_lib_socket_setsockopt+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 setsockopt (); int main () { return setsockopt (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_socket_setsockopt=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_socket_setsockopt=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_socket_setsockopt" >&5 echo "${ECHO_T}$ac_cv_lib_socket_setsockopt" >&6; } if test $ac_cv_lib_socket_setsockopt = yes; then LIBS="$LIBS -lsocket" else tcl_checkBoth=1 fi fi fi if test "$tcl_checkBoth" = 1; then tk_oldLibs=$LIBS LIBS="$LIBS -lsocket -lnsl" { echo "$as_me:$LINENO: checking for accept" >&5 echo $ECHO_N "checking for accept... $ECHO_C" >&6; } if test "${ac_cv_func_accept+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define accept to an innocuous variant, in case declares accept. For example, HP-UX 11i declares gettimeofday. */ #define accept innocuous_accept /* System header to define __stub macros and hopefully few prototypes, which can conflict with char accept (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef accept /* 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 accept (); /* 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_accept || defined __stub___accept choke me #endif int main () { return accept (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_accept=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_accept=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_accept" >&5 echo "${ECHO_T}$ac_cv_func_accept" >&6; } if test $ac_cv_func_accept = yes; then tcl_checkNsl=0 else LIBS=$tk_oldLibs fi fi { echo "$as_me:$LINENO: checking for gethostbyname" >&5 echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6; } if test "${ac_cv_func_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define gethostbyname to an innocuous variant, in case declares gethostbyname. For example, HP-UX 11i declares gettimeofday. */ #define gethostbyname innocuous_gethostbyname /* System header to define __stub macros and hopefully few prototypes, which can conflict with char gethostbyname (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef gethostbyname /* 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 gethostbyname (); /* 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_gethostbyname || defined __stub___gethostbyname choke me #endif int main () { return gethostbyname (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6; } if test $ac_cv_func_gethostbyname = yes; then : else { echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6; } if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_nsl_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_nsl_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6; } if test $ac_cv_lib_nsl_gethostbyname = yes; then LIBS="$LIBS -lnsl" fi fi # Don't perform the eval of the libraries here because DL_LIBS # won't be set until we call TEA_CONFIG_CFLAGS TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}' { echo "$as_me:$LINENO: checking dirent.h" >&5 echo $ECHO_N "checking dirent.h... $ECHO_C" >&6; } if test "${tcl_cv_dirent_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { #ifndef _POSIX_SOURCE # ifdef __Lynx__ /* * Generate compilation error to make the test fail: Lynx headers * are only valid if really in the POSIX environment. */ missing_procedure(); # endif #endif DIR *d; struct dirent *entryPtr; char *p; d = opendir("foobar"); entryPtr = readdir(d); p = entryPtr->d_name; closedir(d); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then tcl_cv_dirent_h=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_dirent_h=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $tcl_cv_dirent_h" >&5 echo "${ECHO_T}$tcl_cv_dirent_h" >&6; } if test $tcl_cv_dirent_h = no; then cat >>confdefs.h <<\_ACEOF #define NO_DIRENT_H 1 _ACEOF fi if test "${ac_cv_header_errno_h+set}" = set; then { echo "$as_me:$LINENO: checking for errno.h" >&5 echo $ECHO_N "checking for errno.h... $ECHO_C" >&6; } if test "${ac_cv_header_errno_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5 echo "${ECHO_T}$ac_cv_header_errno_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking errno.h usability" >&5 echo $ECHO_N "checking errno.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking errno.h presence" >&5 echo $ECHO_N "checking errno.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: errno.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: errno.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: errno.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: errno.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: errno.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: errno.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: errno.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: errno.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: errno.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for errno.h" >&5 echo $ECHO_N "checking for errno.h... $ECHO_C" >&6; } if test "${ac_cv_header_errno_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_errno_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5 echo "${ECHO_T}$ac_cv_header_errno_h" >&6; } fi if test $ac_cv_header_errno_h = yes; then : else cat >>confdefs.h <<\_ACEOF #define NO_ERRNO_H 1 _ACEOF fi if test "${ac_cv_header_float_h+set}" = set; then { echo "$as_me:$LINENO: checking for float.h" >&5 echo $ECHO_N "checking for float.h... $ECHO_C" >&6; } if test "${ac_cv_header_float_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_float_h" >&5 echo "${ECHO_T}$ac_cv_header_float_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking float.h usability" >&5 echo $ECHO_N "checking float.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking float.h presence" >&5 echo $ECHO_N "checking float.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: float.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: float.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: float.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: float.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: float.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: float.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: float.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: float.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: float.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: float.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: float.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: float.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: float.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: float.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: float.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: float.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for float.h" >&5 echo $ECHO_N "checking for float.h... $ECHO_C" >&6; } if test "${ac_cv_header_float_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_float_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_float_h" >&5 echo "${ECHO_T}$ac_cv_header_float_h" >&6; } fi if test $ac_cv_header_float_h = yes; then : else cat >>confdefs.h <<\_ACEOF #define NO_FLOAT_H 1 _ACEOF fi if test "${ac_cv_header_values_h+set}" = set; then { echo "$as_me:$LINENO: checking for values.h" >&5 echo $ECHO_N "checking for values.h... $ECHO_C" >&6; } if test "${ac_cv_header_values_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_values_h" >&5 echo "${ECHO_T}$ac_cv_header_values_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking values.h usability" >&5 echo $ECHO_N "checking values.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking values.h presence" >&5 echo $ECHO_N "checking values.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: values.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: values.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: values.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: values.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: values.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: values.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: values.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: values.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: values.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: values.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: values.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: values.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: values.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: values.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: values.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: values.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for values.h" >&5 echo $ECHO_N "checking for values.h... $ECHO_C" >&6; } if test "${ac_cv_header_values_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_values_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_values_h" >&5 echo "${ECHO_T}$ac_cv_header_values_h" >&6; } fi if test $ac_cv_header_values_h = yes; then : else cat >>confdefs.h <<\_ACEOF #define NO_VALUES_H 1 _ACEOF fi if test "${ac_cv_header_limits_h+set}" = set; then { echo "$as_me:$LINENO: checking for limits.h" >&5 echo $ECHO_N "checking for limits.h... $ECHO_C" >&6; } if test "${ac_cv_header_limits_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_limits_h" >&5 echo "${ECHO_T}$ac_cv_header_limits_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking limits.h usability" >&5 echo $ECHO_N "checking limits.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking limits.h presence" >&5 echo $ECHO_N "checking limits.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: limits.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: limits.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: limits.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: limits.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: limits.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: limits.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: limits.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: limits.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: limits.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: limits.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: limits.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for limits.h" >&5 echo $ECHO_N "checking for limits.h... $ECHO_C" >&6; } if test "${ac_cv_header_limits_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_limits_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_limits_h" >&5 echo "${ECHO_T}$ac_cv_header_limits_h" >&6; } fi if test $ac_cv_header_limits_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_LIMITS_H 1 _ACEOF else cat >>confdefs.h <<\_ACEOF #define NO_LIMITS_H 1 _ACEOF fi if test "${ac_cv_header_stdlib_h+set}" = set; then { echo "$as_me:$LINENO: checking for stdlib.h" >&5 echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6; } if test "${ac_cv_header_stdlib_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking stdlib.h usability" >&5 echo $ECHO_N "checking stdlib.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking stdlib.h presence" >&5 echo $ECHO_N "checking stdlib.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: stdlib.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: stdlib.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: stdlib.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: stdlib.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: stdlib.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: stdlib.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: stdlib.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for stdlib.h" >&5 echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6; } if test "${ac_cv_header_stdlib_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_stdlib_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6; } fi if test $ac_cv_header_stdlib_h = yes; then tcl_ok=1 else tcl_ok=0 fi cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strtol" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strtoul" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strtod" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* if test $tcl_ok = 0; then cat >>confdefs.h <<\_ACEOF #define NO_STDLIB_H 1 _ACEOF fi if test "${ac_cv_header_string_h+set}" = set; then { echo "$as_me:$LINENO: checking for string.h" >&5 echo $ECHO_N "checking for string.h... $ECHO_C" >&6; } if test "${ac_cv_header_string_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5 echo "${ECHO_T}$ac_cv_header_string_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking string.h usability" >&5 echo $ECHO_N "checking string.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking string.h presence" >&5 echo $ECHO_N "checking string.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: string.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: string.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: string.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: string.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: string.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: string.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: string.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for string.h" >&5 echo $ECHO_N "checking for string.h... $ECHO_C" >&6; } if test "${ac_cv_header_string_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_string_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5 echo "${ECHO_T}$ac_cv_header_string_h" >&6; } fi if test $ac_cv_header_string_h = yes; then tcl_ok=1 else tcl_ok=0 fi cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strstr" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strerror" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* # See also memmove check below for a place where NO_STRING_H can be # set and why. if test $tcl_ok = 0; then cat >>confdefs.h <<\_ACEOF #define NO_STRING_H 1 _ACEOF fi if test "${ac_cv_header_sys_wait_h+set}" = set; then { echo "$as_me:$LINENO: checking for sys/wait.h" >&5 echo $ECHO_N "checking for sys/wait.h... $ECHO_C" >&6; } if test "${ac_cv_header_sys_wait_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking sys/wait.h usability" >&5 echo $ECHO_N "checking sys/wait.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking sys/wait.h presence" >&5 echo $ECHO_N "checking sys/wait.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: sys/wait.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: sys/wait.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: sys/wait.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: sys/wait.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: sys/wait.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: sys/wait.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: sys/wait.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: sys/wait.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: sys/wait.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: sys/wait.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: sys/wait.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: sys/wait.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: sys/wait.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: sys/wait.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: sys/wait.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: sys/wait.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for sys/wait.h" >&5 echo $ECHO_N "checking for sys/wait.h... $ECHO_C" >&6; } if test "${ac_cv_header_sys_wait_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_sys_wait_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; } fi if test $ac_cv_header_sys_wait_h = yes; then : else cat >>confdefs.h <<\_ACEOF #define NO_SYS_WAIT_H 1 _ACEOF fi if test "${ac_cv_header_dlfcn_h+set}" = set; then { echo "$as_me:$LINENO: checking for dlfcn.h" >&5 echo $ECHO_N "checking for dlfcn.h... $ECHO_C" >&6; } if test "${ac_cv_header_dlfcn_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_dlfcn_h" >&5 echo "${ECHO_T}$ac_cv_header_dlfcn_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking dlfcn.h usability" >&5 echo $ECHO_N "checking dlfcn.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking dlfcn.h presence" >&5 echo $ECHO_N "checking dlfcn.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: dlfcn.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: dlfcn.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: dlfcn.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: dlfcn.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: dlfcn.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: dlfcn.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: dlfcn.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: dlfcn.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: dlfcn.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: dlfcn.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: dlfcn.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: dlfcn.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: dlfcn.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: dlfcn.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: dlfcn.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: dlfcn.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for dlfcn.h" >&5 echo $ECHO_N "checking for dlfcn.h... $ECHO_C" >&6; } if test "${ac_cv_header_dlfcn_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_dlfcn_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_dlfcn_h" >&5 echo "${ECHO_T}$ac_cv_header_dlfcn_h" >&6; } fi if test $ac_cv_header_dlfcn_h = yes; then : else cat >>confdefs.h <<\_ACEOF #define NO_DLFCN_H 1 _ACEOF fi # OS/390 lacks sys/param.h (and doesn't need it, by chance). for ac_header in sys/param.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Let the user call this, because if it triggers, they will # need a compat/strtod.c that is correct. Users can also # use Tcl_GetDouble(FromObj) instead. #TEA_BUGGY_STRTOD fi #----------------------------------------------------------------------- # __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="shellicon.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 if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ ; then { { echo "$as_me:$LINENO: error: could not find source file '$i'" >&5 echo "$as_me: error: could not find source file '$i'" >&2;} { (exit 1); exit 1; }; } 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 { { echo "$as_me:$LINENO: error: could not find header file '${srcdir}/$i'" >&5 echo "$as_me: error: could not find header file '${srcdir}/$i'" >&2;} { (exit 1); exit 1; }; } fi PKG_HEADERS="$PKG_HEADERS $i" done vars="-I\"`${CYGPATH} ${srcdir}/../generic`\"" for i in $vars; do PKG_INCLUDES="$PKG_INCLUDES $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" \ ; then { { echo "$as_me:$LINENO: error: could not find stub source file '$i'" >&5 echo "$as_me: error: could not find stub source file '$i'" >&2;} { (exit 1); exit 1; }; } 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="" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then { { echo "$as_me:$LINENO: error: could not find tcl source file '${srcdir}/$i'" >&5 echo "$as_me: error: could not find tcl source file '${srcdir}/$i'" >&2;} { (exit 1); exit 1; }; } fi PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" done #-------------------------------------------------------------------- # __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 { echo "$as_me:$LINENO: checking for Tcl private include files" >&5 echo $ECHO_N "checking for Tcl private include files... $ECHO_C" >&6; } TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}` TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\" TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" TCL_UNIX_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" TCL_WIN_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" TCL_BMAP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/bitmaps\" TCL_TOOL_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/tools\" TCL_COMPAT_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/compat\" if test "${TEA_PLATFORM}" = "windows"; then TCL_PLATFORM_DIR_NATIVE=${TCL_WIN_DIR_NATIVE} else TCL_PLATFORM_DIR_NATIVE=${TCL_UNIX_DIR_NATIVE} fi # 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 fi { echo "$as_me:$LINENO: result: Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" >&5 echo "${ECHO_T}Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" >&6; } #TEA_PUBLIC_TK_HEADERS { echo "$as_me:$LINENO: checking for Tk private include files" >&5 echo $ECHO_N "checking for Tk private include files... $ECHO_C" >&6; } TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}` TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\" TK_UNIX_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\" TK_WIN_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\" 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_WIN_DIR_NATIVE} else TK_PLATFORM_DIR_NATIVE=${TK_UNIX_DIR_NATIVE} fi # 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}" if test "${TEA_WINDOWINGSYSTEM}" = "win32" \ -o "${TEA_WINDOWINGSYSTEM}" = "aqua"; 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}"; fi ;; esac fi { echo "$as_me:$LINENO: result: Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}" >&5 echo "${ECHO_T}Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}" >&6; } #-------------------------------------------------------------------- # For Unix/Tk builds, make sure that the X libraries/headers are found. #-------------------------------------------------------------------- if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then { echo "$as_me:$LINENO: checking for X" >&5 echo $ECHO_N "checking for X... $ECHO_C" >&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 #( *\'*) { { echo "$as_me:$LINENO: error: Cannot use X directory names containing '" >&5 echo "$as_me: error: Cannot use X directory names containing '" >&2;} { (exit 1); exit 1; }; };; #( *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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; 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 | /lib) ;; *) 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/X11R6/include /usr/X11R5/include /usr/X11R4/include /usr/include/X11 /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 /usr/local/X11/include /usr/local/X11R6/include /usr/local/X11R5/include /usr/local/X11R4/include /usr/local/include/X11 /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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # We can compile using X headers with no special include directory. ac_x_includes= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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.$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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { XrmInitialize () ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then LIBS=$ac_save_LIBS # We can link X programs with no special library path. ac_x_libraries= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS=$ac_save_LIBS for ac_dir in `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; 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_ipa8_conftest.oo \ 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 { echo "$as_me:$LINENO: result: $have_x" >&5 echo "${ECHO_T}$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'" { echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6; } fi not_really_there="" if test "$no_x" = ""; then if test "$x_includes" = ""; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 not_really_there="yes" fi rm -f conftest.err conftest.$ac_ext else if test ! -r $x_includes/X11/Intrinsic.h; then not_really_there="yes" fi fi fi if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then { echo "$as_me:$LINENO: checking for X11 header files" >&5 echo $ECHO_N "checking for X11 header files... $ECHO_C" >&6; } found_xincludes="no" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then found_xincludes="yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 found_xincludes="no" fi rm -f conftest.err 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/Intrinsic.h; then { echo "$as_me:$LINENO: result: $i" >&5 echo "${ECHO_T}$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 { echo "$as_me:$LINENO: result: couldn't find any!" >&5 echo "${ECHO_T}couldn't find any!" >&6; } fi if test "$no_x" = yes; then { echo "$as_me:$LINENO: checking for X11 libraries" >&5 echo $ECHO_N "checking for X11 libraries... $ECHO_C" >&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; then { echo "$as_me:$LINENO: result: $i" >&5 echo "${ECHO_T}$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 { echo "$as_me:$LINENO: checking for XCreateWindow in -lXwindow" >&5 echo $ECHO_N "checking for XCreateWindow in -lXwindow... $ECHO_C" >&6; } if test "${ac_cv_lib_Xwindow_XCreateWindow+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lXwindow $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_Xwindow_XCreateWindow=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_Xwindow_XCreateWindow=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_Xwindow_XCreateWindow" >&5 echo "${ECHO_T}$ac_cv_lib_Xwindow_XCreateWindow" >&6; } if test $ac_cv_lib_Xwindow_XCreateWindow = yes; then XLIBSW=-lXwindow fi fi if test "$XLIBSW" = nope ; then { echo "$as_me:$LINENO: result: could not find any! Using -lX11." >&5 echo "${ECHO_T}could not find any! Using -lX11." >&6; } XLIBSW=-lX11 fi if test x"${XLIBSW}" != x ; then PKG_LIBS="${PKG_LIBS} ${XLIBSW}" fi fi # Needed for OS X ppx/intel image handling { echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; } if test "${ac_cv_c_bigendian+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # See if sys/param.h defines the BYTE_ORDER macro. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then # It does; now see whether it defined to BIG_ENDIAN or not. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_c_bigendian=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # It does not; compile a test program. if test "$cross_compiling" = yes; then # try to guess the endianness by grepping values into an object file ac_cv_c_bigendian=unknown cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 }; void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } int main () { _ascii (); _ebcdic (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_bigendian=no else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 echo "${ECHO_T}$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in yes) cat >>confdefs.h <<\_ACEOF #define WORDS_BIGENDIAN 1 _ACEOF ;; no) ;; *) { { echo "$as_me:$LINENO: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&5 echo "$as_me: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} { (exit 1); exit 1; }; } ;; esac #-------------------------------------------------------------------- # __CHANGE__ # A few miscellaneous platform-specific items: # # Define a special symbol for Windows (BUILD_sample in this case) so # that we create the export library with the dll. See sha1.h on how # to use this. # # Windows creates a few extra files that need to be cleaned up. # You can add more files to clean if your extension creates any extra # files. # # Define any extra compiler flags in the PACKAGE_CFLAGS variable. # These will be appended to the current set of compiler flags for # your system. #-------------------------------------------------------------------- if test "${TEA_PLATFORM}" = "windows" ; then cat >>confdefs.h <<\_ACEOF #define BUILD_shellicon 1 _ACEOF CLEANFILES="pkgIndex.tcl *.lib *.dll *.exp *.ilk *.pdb vc*.pch" vars="gdi32.lib user32.lib comctl32.lib ole32.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 else CLEANFILES="pkgIndex.tcl" fi if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then vars="-framework Carbon" 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 fi #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. #-------------------------------------------------------------------- # 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 cat >>confdefs.h <<\_ACEOF #define USE_THREAD_ALLOC 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define _REENTRANT 1 _ACEOF if test "`uname -s`" = "SunOS" ; then cat >>confdefs.h <<\_ACEOF #define _POSIX_PTHREAD_SEMANTICS 1 _ACEOF fi cat >>confdefs.h <<\_ACEOF #define _THREAD_SAFE 1 _ACEOF { echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthread" >&5 echo $ECHO_N "checking for pthread_mutex_init in -lpthread... $ECHO_C" >&6; } if test "${ac_cv_lib_pthread_pthread_mutex_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_pthread_pthread_mutex_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthread_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 echo "${ECHO_T}$ac_cv_lib_pthread_pthread_mutex_init" >&6; } if test $ac_cv_lib_pthread_pthread_mutex_init = yes; 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] { echo "$as_me:$LINENO: checking for __pthread_mutex_init in -lpthread" >&5 echo $ECHO_N "checking for __pthread_mutex_init in -lpthread... $ECHO_C" >&6; } if test "${ac_cv_lib_pthread___pthread_mutex_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_pthread___pthread_mutex_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthread___pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 echo "${ECHO_T}$ac_cv_lib_pthread___pthread_mutex_init" >&6; } if test $ac_cv_lib_pthread___pthread_mutex_init = yes; then tcl_ok=yes else tcl_ok=no fi fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthread" else { echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthreads" >&5 echo $ECHO_N "checking for pthread_mutex_init in -lpthreads... $ECHO_C" >&6; } if test "${ac_cv_lib_pthreads_pthread_mutex_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthreads $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_pthreads_pthread_mutex_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthreads_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 echo "${ECHO_T}$ac_cv_lib_pthreads_pthread_mutex_init" >&6; } if test $ac_cv_lib_pthreads_pthread_mutex_init = yes; then tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthreads" else { echo "$as_me:$LINENO: checking for pthread_mutex_init in -lc" >&5 echo $ECHO_N "checking for pthread_mutex_init in -lc... $ECHO_C" >&6; } if test "${ac_cv_lib_c_pthread_mutex_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_c_pthread_mutex_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_c_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_c_pthread_mutex_init" >&5 echo "${ECHO_T}$ac_cv_lib_c_pthread_mutex_init" >&6; } if test $ac_cv_lib_c_pthread_mutex_init = yes; then tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "no"; then { echo "$as_me:$LINENO: checking for pthread_mutex_init in -lc_r" >&5 echo $ECHO_N "checking for pthread_mutex_init in -lc_r... $ECHO_C" >&6; } if test "${ac_cv_lib_c_r_pthread_mutex_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc_r $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_c_r_pthread_mutex_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_c_r_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 echo "${ECHO_T}$ac_cv_lib_c_r_pthread_mutex_init" >&6; } if test $ac_cv_lib_c_r_pthread_mutex_init = yes; 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 { echo "$as_me:$LINENO: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&5 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 { echo "$as_me:$LINENO: checking for building with threads" >&5 echo $ECHO_N "checking for building with threads... $ECHO_C" >&6; } if test "${TCL_THREADS}" = 1; then cat >>confdefs.h <<\_ACEOF #define TCL_THREADS 1 _ACEOF { echo "$as_me:$LINENO: result: yes (default)" >&5 echo "${ECHO_T}yes (default)" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}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 { echo "$as_me:$LINENO: WARNING: Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads." >&5 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 ;; *) if test "${TCL_THREADS}" = "1"; then { echo "$as_me:$LINENO: WARNING: --enable-threads requested, but building against a Tcl that is NOT thread-enabled. This is an OK configuration that will also run in a thread-enabled core." >&5 echo "$as_me: WARNING: --enable-threads requested, but building against a Tcl that is NOT thread-enabled. This is an OK configuration that will also run in a thread-enabled core." >&2;} fi ;; esac #-------------------------------------------------------------------- # The statement below defines a collection of symbols related to # building as a shared library instead of a static library. #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking how to build libraries" >&5 echo $ECHO_N "checking how to build libraries... $ECHO_C" >&6; } # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then enableval=$enable_shared; tcl_ok=$enableval else tcl_ok=yes fi if test "${enable_shared+set}" = set; then enableval="$enable_shared" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" ; then { echo "$as_me:$LINENO: result: shared" >&5 echo "${ECHO_T}shared" >&6; } SHARED_BUILD=1 else { echo "$as_me:$LINENO: result: static" >&5 echo "${ECHO_T}static" >&6; } SHARED_BUILD=0 cat >>confdefs.h <<\_ACEOF #define STATIC_BUILD 1 _ACEOF 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. #-------------------------------------------------------------------- # Step 0.a: Enable 64 bit support? { echo "$as_me:$LINENO: checking if 64bit support is requested" >&5 echo $ECHO_N "checking if 64bit support is requested... $ECHO_C" >&6; } # Check whether --enable-64bit was given. if test "${enable_64bit+set}" = set; then enableval=$enable_64bit; do64bit=$enableval else do64bit=no fi { echo "$as_me:$LINENO: result: $do64bit" >&5 echo "${ECHO_T}$do64bit" >&6; } # Step 0.b: Enable Solaris 64 bit VIS support? { echo "$as_me:$LINENO: checking if 64bit Sparc VIS support is requested" >&5 echo $ECHO_N "checking if 64bit Sparc VIS support is requested... $ECHO_C" >&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 { echo "$as_me:$LINENO: result: $do64bitVIS" >&5 echo "${ECHO_T}$do64bitVIS" >&6; } if test "$do64bitVIS" = "yes"; then # Force 64bit on with VIS do64bit=yes fi # Step 0.c: Cross-compiling options for Windows/CE builds? if test "${TEA_PLATFORM}" = "windows" ; then { echo "$as_me:$LINENO: checking if Windows/CE build is requested" >&5 echo $ECHO_N "checking if Windows/CE build is requested... $ECHO_C" >&6; } # Check whether --enable-wince was given. if test "${enable_wince+set}" = set; then enableval=$enable_wince; doWince=$enableval else doWince=no fi { echo "$as_me:$LINENO: result: $doWince" >&5 echo "${ECHO_T}$doWince" >&6; } fi # Step 1: set the variable "system" to hold the name and version number # for the system. { echo "$as_me:$LINENO: checking system version" >&5 echo $ECHO_N "checking system version... $ECHO_C" >&6; } if test "${tcl_cv_sys_version+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows elif test -f /usr/lib/NextStep/software_version; then tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { echo "$as_me:$LINENO: WARNING: can't find uname command" >&5 echo "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else # Special check for weird MP-RAS system (uname returns weird # results, and the version is kept in special file). if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then tcl_cv_sys_version=MP-RAS-`awk '{print }' /etc/.relid` fi if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi fi fi fi { echo "$as_me:$LINENO: result: $tcl_cv_sys_version" >&5 echo "${ECHO_T}$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version # Step 2: check for existence of -ldl library. This is needed because # Linux can use either -ldl or -ldld for dynamic loading. { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_dlopen=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } if test $ac_cv_lib_dl_dlopen = yes; then have_dl=yes else have_dl=no fi # Require ranlib early so we can override it in special cases below. # Step 3: 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. do64bit_ok=no LDFLAGS_ORIG="$LDFLAGS" # 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="" TCL_EXPORT_FILE_SUFFIX="" UNSHARED_LIB_SUFFIX="" TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ECHO_VERSION='`echo ${PACKAGE_VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g CFLAGS_OPTIMIZE=-O if test "$GCC" = "yes" ; then CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall -Wno-implicit-int" else CFLAGS_WARNING="" fi TCL_NEEDS_EXP_FILE=0 TCL_BUILD_EXP_FILE="" TCL_EXP_FILE="" # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_AR+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AR="ar" echo "$as_me:$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 { echo "$as_me:$LINENO: result: $AR" >&5 echo "${ECHO_T}$AR" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" case $system in 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 ! -d "${PATH64}" ; then { echo "$as_me:$LINENO: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&5 echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&2;} { echo "$as_me:$LINENO: WARNING: Ensure latest Platform SDK is installed" >&5 echo "$as_me: WARNING: Ensure latest Platform SDK is installed" >&2;} do64bit="no" else { echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6; } do64bit_ok="yes" fi fi if test "$doWince" != "no" ; then if test "$do64bit" != "no" ; then { { echo "$as_me:$LINENO: error: Windows/CE and 64-bit builds incompatible" >&5 echo "$as_me: error: Windows/CE and 64-bit builds incompatible" >&2;} { (exit 1); exit 1; }; } fi if test "$GCC" = "yes" ; then { { echo "$as_me:$LINENO: error: Windows/CE and GCC builds incompatible" >&5 echo "$as_me: error: Windows/CE and GCC builds incompatible" >&2;} { (exit 1); exit 1; }; } 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 { echo "$as_me:$LINENO: checking for Windows/CE celib directory" >&5 echo $ECHO_N "checking for Windows/CE celib directory... $ECHO_C" >&6; } if test "${ac_cv_c_celibconfig+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&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 { { echo "$as_me:$LINENO: error: ${with_celibconfig} directory doesn't contain inc directory" >&5 echo "$as_me: error: ${with_celibconfig} directory doesn't contain inc directory" >&2;} { (exit 1); exit 1; }; } 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 { { echo "$as_me:$LINENO: error: Cannot find celib support library directory" >&5 echo "$as_me: error: Cannot find celib support library directory" >&2;} { (exit 1); exit 1; }; } else no_celib= CELIB_DIR=${ac_cv_c_celibconfig} CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` { echo "$as_me:$LINENO: result: found $CELIB_DIR" >&5 echo "${ECHO_T}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 { { echo "$as_me:$LINENO: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" >&5 echo "$as_me: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" >&2;} { (exit 1); exit 1; }; } 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 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="-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="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" LINKBIN="\"${CEBINROOT}/link.exe\"" else RC="rc" 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 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}" 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 # This essentially turns it all on. LDFLAGS_DEBUG="-debug:full -debugtype:both -warn:2" 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_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".dll" SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' TCL_LIB_VERSIONS_OK=nodots # Bogus to avoid getting this turned off DL_OBJS="tclLoadNone.obj" ;; 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) # ok ... ;; *) CC=${CC}_r ;; esac { echo "$as_me:$LINENO: result: Using $CC for compiling with threads" >&5 echo "${ECHO_T}Using $CC for compiling with threads" >&6; } fi LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" LD_LIBRARY_PATH_VAR="LIBPATH" # Check to enable 64-bit flags for compiler/linker on AIX 4+ if test "$do64bit" = "yes" -a "`uname -v`" -gt "3" ; then if test "$GCC" = "yes" ; then { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5 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" # AIX-5 has dl* in libc.so DL_LIBS="" 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="gcc -shared" else SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry" fi SHLIB_LD="${TCL_SRC_DIR}/unix/ldAix ${SHLIB_LD} ${SHLIB_LD_FLAGS}" DL_LIBS="-ldl" CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} TCL_NEEDS_EXP_FILE=1 TCL_EXPORT_FILE_SUFFIX='${PACKAGE_VERSION}.exp' fi # AIX v<=4.1 has some different flags than 4.2+ if test "$system" = "AIX-4.1" -o "`uname -v`" -lt "4" ; then case " $LIBOBJS " in *" tclLoadAix.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS tclLoadAix.$ac_objext" ;; esac DL_LIBS="-lld" fi # On AIX <=v4 systems, libbsd.a has to be linked in to support # non-blocking file IO. This library has to be linked in after # the MATH_LIBS or it breaks the pow() function. The way to # insure proper sequencing, is to add it to the tail of MATH_LIBS. # This library also supplies gettimeofday. # # AIX does not have a timezone field in struct tm. When the AIX # bsd library is used, the timezone global and the gettimeofday # methods are to be avoided for timezone deduction instead, we # deduce the timezone by comparing the localtime result on a # known GMT value. { echo "$as_me:$LINENO: checking for gettimeofday in -lbsd" >&5 echo $ECHO_N "checking for gettimeofday in -lbsd... $ECHO_C" >&6; } if test "${ac_cv_lib_bsd_gettimeofday+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 gettimeofday (); int main () { return gettimeofday (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_bsd_gettimeofday=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_bsd_gettimeofday=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gettimeofday" >&5 echo "${ECHO_T}$ac_cv_lib_bsd_gettimeofday" >&6; } if test $ac_cv_lib_bsd_gettimeofday = yes; then libbsd=yes else libbsd=no fi if test $libbsd = yes; then MATH_LIBS="$MATH_LIBS -lbsd" cat >>confdefs.h <<\_ACEOF #define USE_DELTA_FOR_TZ 1 _ACEOF fi ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD="${CC} -nostart" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" #----------------------------------------------------------- # 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. #----------------------------------------------------------- { echo "$as_me:$LINENO: checking for inet_ntoa in -lbind" >&5 echo $ECHO_N "checking for inet_ntoa in -lbind... $ECHO_C" >&6; } if test "${ac_cv_lib_bind_inet_ntoa+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbind $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_bind_inet_ntoa=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_bind_inet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_bind_inet_ntoa" >&5 echo "${ECHO_T}$ac_cv_lib_bind_inet_ntoa" >&6; } if test $ac_cv_lib_bind_inet_ntoa = yes; then LIBS="$LIBS -lbind -lsocket" fi ;; BSD/OS-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD="cc -shared" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; HP-UX-*.11.*) # Use updated header definitions where possible cat >>confdefs.h <<\_ACEOF #define _XOPEN_SOURCE_EXTENDED 1 _ACEOF # 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 SHLIB_SUFFIX=".sl" { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } if test "${ac_cv_lib_dld_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } if test $ac_cv_lib_dld_shl_load = yes; then tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = yes; then SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS='${LIBS}' DL_OBJS="tclLoadShl.o" DL_LIBS="-ldld" 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="gcc -shared" SHLIB_LD_LIBS='${LIBS}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} fi # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc #CFLAGS="$CFLAGS +DAportable" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes" ; then if test "$GCC" = "yes" ; then hpux_arch=`${CC} -dumpmachine` case $hpux_arch in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD="${CC} -shared" SHLIB_LD_LIBS='${LIBS}' CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; *) { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5 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 ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } if test "${ac_cv_lib_dld_shl_load+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* 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 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dld_shl_load=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } if test $ac_cv_lib_dld_shl_load = yes; then tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = yes; then SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" DL_OBJS="tclLoadShl.o" DL_LIBS="-ldld" 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 ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' 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_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes" ; then if test "$GCC" = "yes" ; then { echo "$as_me:$LINENO: WARNING: 64bit mode not supported by gcc" >&5 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*) SHLIB_CFLAGS="-fPIC" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings # when you inline the string and math operations. Turn this off to # get rid of the warnings. #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES" SHLIB_LD="${CC} -shared" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,--export-dynamic" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "`uname -m`" = "alpha" ; then CFLAGS="$CFLAGS -mieee" 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 ;; GNU*) SHLIB_CFLAGS="-fPIC" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" SHLIB_LD="${CC} -shared" DL_OBJS="" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,--export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" if test "`uname -m`" = "alpha" ; then CFLAGS="$CFLAGS -mieee" fi ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD="${CC} -shared " DL_OBJS="tclLoadDl.o" DL_LIBS="-mshared -ldl" LD_FLAGS="-Wl,--export-dynamic" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ;; MP-RAS-02*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; MP-RAS-*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,-Bexport" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; NetBSD-*|FreeBSD-[1-2].*) # NetBSD/SPARC needs -fPIC, -fpic will not do. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' { echo "$as_me:$LINENO: checking for ELF" >&5 echo $ECHO_N "checking for ELF... $ECHO_C" >&6; } if test "${tcl_cv_ld_elf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __ELF__ yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then tcl_cv_ld_elf=yes else tcl_cv_ld_elf=no fi rm -f conftest* fi { echo "$as_me:$LINENO: result: $tcl_cv_ld_elf" >&5 echo "${ECHO_T}$tcl_cv_ld_elf" >&6; } if test $tcl_cv_ld_elf = yes; then SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' else SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0' fi # Ancient FreeBSD doesn't handle version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; OpenBSD-*) # OpenBSD/SPARC[64] needs -fPIC, -fpic will not do. case `machine` in sparc|sparc64) SHLIB_CFLAGS="-fPIC";; *) SHLIB_CFLAGS="-fpic";; esac SHLIB_LD="${CC} -shared ${SHLIB_CFLAGS}" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0' { echo "$as_me:$LINENO: checking for ELF" >&5 echo $ECHO_N "checking for ELF... $ECHO_C" >&6; } if test "${tcl_cv_ld_elf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __ELF__ yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then tcl_cv_ld_elf=yes else tcl_cv_ld_elf=no fi rm -f conftest* fi { echo "$as_me:$LINENO: result: $tcl_cv_ld_elf" >&5 echo "${ECHO_T}$tcl_cv_ld_elf" >&6; } if test $tcl_cv_ld_elf = yes; then LDFLAGS=-Wl,-export-dynamic else LDFLAGS="" fi # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; FreeBSD-*) # FreeBSD 3.* and greater have ELF. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' 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 case $system in FreeBSD-3.*) # FreeBSD-3 doesn't handle version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' TCL_LIB_VERSIONS_OK=nodots ;; esac ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" SHLIB_CFLAGS="-fno-common" if test $do64bit = yes; then do64bit_ok=yes CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" fi # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS here: SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' { echo "$as_me:$LINENO: checking if ld accepts -single_module flag" >&5 echo $ECHO_N "checking if ld accepts -single_module flag... $ECHO_C" >&6; } if test "${tcl_cv_ld_single_module+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then tcl_cv_ld_single_module=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_ld_single_module=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { echo "$as_me:$LINENO: result: $tcl_cv_ld_single_module" >&5 echo "${ECHO_T}$tcl_cv_ld_single_module" >&6; } if test $tcl_cv_ld_single_module = yes; then SHLIB_LD="${SHLIB_LD} -Wl,-single_module" fi SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".dylib" DL_OBJS="tclLoadDyld.o" DL_LIBS="" # Don't use -prebind when building for Mac OS X 10.4 or later only: test -z "${MACOSX_DEPLOYMENT_TARGET}" || \ test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F. '{print $2}'`" -lt 4 && \ LDFLAGS="$LDFLAGS -prebind" LDFLAGS="$LDFLAGS -headerpad_max_install_names" { echo "$as_me:$LINENO: checking if ld accepts -search_paths_first flag" >&5 echo $ECHO_N "checking if ld accepts -search_paths_first flag... $ECHO_C" >&6; } if test "${tcl_cv_ld_search_paths_first+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-search_paths_first" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then tcl_cv_ld_search_paths_first=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_ld_search_paths_first=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { echo "$as_me:$LINENO: result: $tcl_cv_ld_search_paths_first" >&5 echo "${ECHO_T}$tcl_cv_ld_search_paths_first" >&6; } if test $tcl_cv_ld_search_paths_first = yes; then LDFLAGS="$LDFLAGS -Wl,-search_paths_first" fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" # TEA specific: for Tk extensions, remove -arch ppc64 from CFLAGS # for fat builds, as neither TkAqua nor TkX11 can be built for 64bit # at present (no 64bit GUI libraries). test $do64bit_ok = no && test -n "${TK_BIN_DIR}" && \ CFLAGS="`echo "$CFLAGS" | sed -e 's/-arch ppc64/-arch ppc/g'`" ;; NEXTSTEP-*) SHLIB_CFLAGS="" SHLIB_LD="cc -nostdlib -r" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadNext.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OS/390-*) CFLAGS_OPTIMIZE="" # Optimizer is buggy cat >>confdefs.h <<\_ACEOF #define _OE_SOCKETS 1 _ACEOF ;; OSF1-1.0|OSF1-1.1|OSF1-1.2) # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 SHLIB_CFLAGS="" # Hack: make package name same as library name SHLIB_LD='ld -R -export :' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadOSF.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OSF1-1.*) # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 SHLIB_CFLAGS="-fPIC" if test "$SHARED_BUILD" = "1" ; then SHLIB_LD="ld -shared" else SHLIB_LD="ld -non_shared" fi SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; 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_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' 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" DL_OBJS="tclLoadDl.o" # dlopen is in -lc on QNX DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) # Note, dlopen is available only on SCO 3.2.5 and greater. However, # this test works, since "uname -s" was non-standard in 3.2.4 and # below. 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" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SINIX*5.4*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-4*) SHLIB_CFLAGS="-PIC" SHLIB_LD="ld" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # SunOS can't handle version numbers with dots in them in library # specs, like -ltcl7.5, so use -ltcl75 instead. Also, it # requires an extra version number at the end of .so file names. # So, the library has to have a name like libtcl75.so.1.0 SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; 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. cat >>confdefs.h <<\_ACEOF #define _REENTRANT 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define _POSIX_PTHREAD_SEMANTICS 1 _ACEOF SHLIB_CFLAGS="-KPIC" # Note: need the LIBS below, otherwise Tk won't find Tcl's # symbols when dynamically loaded into tclsh. SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" 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. cat >>confdefs.h <<\_ACEOF #define _REENTRANT 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define _POSIX_PTHREAD_SEMANTICS 1 _ACEOF 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 "`gcc -dumpversion | awk -F. '{print $1}'`" -lt "3" ; then { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 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 elif test "$arch" = "amd64 i386" ; then if test "$GCC" = "yes" ; then { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5 echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} else do64bit_ok=yes CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64" fi else { echo "$as_me:$LINENO: WARNING: 64bit mode not supported for $arch" >&5 echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} fi fi # Note: need the LIBS below, otherwise Tk won't find Tcl's # symbols when dynamically loaded into tclsh. SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" 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 # 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" fi else SHLIB_LD="/usr/ccs/bin/ld -G -z text" 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" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers # that don't grok the -Bexport option. Test that it does. { echo "$as_me:$LINENO: checking for ld accepts -Bexport flag" >&5 echo $ECHO_N "checking for ld accepts -Bexport flag... $ECHO_C" >&6; } if test "${tcl_cv_ld_Bexport+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-Bexport" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then tcl_cv_ld_Bexport=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_ld_Bexport=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { echo "$as_me:$LINENO: result: $tcl_cv_ld_Bexport" >&5 echo "${ECHO_T}$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 { echo "$as_me:$LINENO: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} fi # Step 4: disable dynamic loading if requested via a command-line switch. # Check whether --enable-load was given. if test "${enable_load+set}" = set; then enableval=$enable_load; tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "no"; then DL_OBJS="" fi if test "x$DL_OBJS" != "x" ; then BUILD_DLTEST="\$(DLTEST_TARGETS)" else echo "Can't figure out how to do dynamic loading or shared libraries" echo "on this system." SHLIB_CFLAGS="" SHLIB_LD="" SHLIB_SUFFIX="" DL_OBJS="tclLoadNone.o" DL_LIBS="" LDFLAGS="$LDFLAGS_ORIG" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" BUILD_DLTEST="" fi 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 "$DL_OBJS" != "tclLoadNone.o" ; then if test "$GCC" = "yes" ; then case $system in AIX-*) ;; BSD/OS*) ;; IRIX*) ;; NetBSD-*|FreeBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; windows) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac fi fi if test "$SHARED_LIB_SUFFIX" = "" ; then SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}' fi if test "$UNSHARED_LIB_SUFFIX" = "" ; then UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a' fi # These must be called after we do the basic CFLAGS checks and # verify any possible 64-bit or similar switches are necessary { echo "$as_me:$LINENO: checking for required early compiler flags" >&5 echo $ECHO_N "checking for required early compiler flags... $ECHO_C" >&6; } tcl_flags="" if test "${tcl_cv_flag__isoc99_source+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_flag__isoc99_source=no else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _ISOC99_SOURCE 1 #include int main () { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_flag__isoc99_source=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 cat >>confdefs.h <<\_ACEOF #define _ISOC99_SOURCE 1 _ACEOF tcl_flags="$tcl_flags _ISOC99_SOURCE" fi if test "${tcl_cv_flag__largefile64_source+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { struct stat64 buf; int i = stat64("/", &buf); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_flag__largefile64_source=no else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _LARGEFILE64_SOURCE 1 #include int main () { struct stat64 buf; int i = stat64("/", &buf); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_flag__largefile64_source=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 cat >>confdefs.h <<\_ACEOF #define _LARGEFILE64_SOURCE 1 _ACEOF tcl_flags="$tcl_flags _LARGEFILE64_SOURCE" fi if test "${tcl_cv_flag__largefile_source64+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { char *p = (char *)open64; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_flag__largefile_source64=no else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _LARGEFILE_SOURCE64 1 #include int main () { char *p = (char *)open64; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_flag__largefile_source64=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 cat >>confdefs.h <<\_ACEOF #define _LARGEFILE_SOURCE64 1 _ACEOF tcl_flags="$tcl_flags _LARGEFILE_SOURCE64" fi if test "x${tcl_flags}" = "x" ; then { echo "$as_me:$LINENO: result: none" >&5 echo "${ECHO_T}none" >&6; } else { echo "$as_me:$LINENO: result: ${tcl_flags}" >&5 echo "${ECHO_T}${tcl_flags}" >&6; } fi { echo "$as_me:$LINENO: checking for 64-bit integer type" >&5 echo $ECHO_N "checking for 64-bit integer type... $ECHO_C" >&6; } if test "${tcl_cv_type_64bit+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else tcl_cv_type_64bit=none # See if the compiler knows natively about __int64 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { __int64 value = (__int64) 0; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_type_64bit=__int64 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { switch (0) { case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; } ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_type_64bit=${tcl_type_64bit} else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "${tcl_cv_type_64bit}" = none ; then cat >>confdefs.h <<\_ACEOF #define TCL_WIDE_INT_IS_LONG 1 _ACEOF { echo "$as_me:$LINENO: result: using long" >&5 echo "${ECHO_T}using long" >&6; } elif test "${tcl_cv_type_64bit}" = "__int64" \ -a "${TEA_PLATFORM}" = "windows" ; then # We actually want to use the default tcl.h checks in this # case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* { echo "$as_me:$LINENO: result: using Tcl header defaults" >&5 echo "${ECHO_T}using Tcl header defaults" >&6; } else cat >>confdefs.h <<_ACEOF #define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit} _ACEOF { echo "$as_me:$LINENO: result: ${tcl_cv_type_64bit}" >&5 echo "${ECHO_T}${tcl_cv_type_64bit}" >&6; } # Now check for auxiliary declarations { echo "$as_me:$LINENO: checking for struct dirent64" >&5 echo $ECHO_N "checking for struct dirent64... $ECHO_C" >&6; } if test "${tcl_cv_struct_dirent64+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { struct dirent64 p; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_struct_dirent64=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_struct_dirent64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $tcl_cv_struct_dirent64" >&5 echo "${ECHO_T}$tcl_cv_struct_dirent64" >&6; } if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then cat >>confdefs.h <<\_ACEOF #define HAVE_STRUCT_DIRENT64 1 _ACEOF fi { echo "$as_me:$LINENO: checking for struct stat64" >&5 echo $ECHO_N "checking for struct stat64... $ECHO_C" >&6; } if test "${tcl_cv_struct_stat64+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { struct stat64 p; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_struct_stat64=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_struct_stat64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $tcl_cv_struct_stat64" >&5 echo "${ECHO_T}$tcl_cv_struct_stat64" >&6; } if test "x${tcl_cv_struct_stat64}" = "xyes" ; then cat >>confdefs.h <<\_ACEOF #define HAVE_STRUCT_STAT64 1 _ACEOF fi for ac_func in open64 lseek64 do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* 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 $ac_func (); /* 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_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { echo "$as_me:$LINENO: checking for off64_t" >&5 echo $ECHO_N "checking for off64_t... $ECHO_C" >&6; } if test "${tcl_cv_type_off64_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { off64_t offset; ; return 0; } _ACEOF 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then tcl_cv_type_off64_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 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 cat >>confdefs.h <<\_ACEOF #define HAVE_TYPE_OFF64_T 1 _ACEOF { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi #-------------------------------------------------------------------- # Set the default compiler switches based on the --enable-symbols option. #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking for build with symbols" >&5 echo $ECHO_N "checking for build with symbols... $ECHO_C" >&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}" LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } else CFLAGS_DEFAULT="${CFLAGS_DEBUG}" LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" if test "$tcl_ok" = "yes"; then { echo "$as_me:$LINENO: result: yes (standard debugging)" >&5 echo "${ECHO_T}yes (standard debugging)" >&6; } fi fi if test "${TEA_PLATFORM}" != "windows" ; then LDFLAGS_DEFAULT="${LDFLAGS}" fi if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then cat >>confdefs.h <<\_ACEOF #define TCL_MEM_DEBUG 1 _ACEOF fi if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then { echo "$as_me:$LINENO: result: enabled symbols mem debugging" >&5 echo "${ECHO_T}enabled symbols mem debugging" >&6; } else { echo "$as_me:$LINENO: result: enabled $tcl_ok debugging" >&5 echo "${ECHO_T}enabled $tcl_ok debugging" >&6; } fi fi if test "${enable_symbols+set}" = set && test "$enable_symbols" != no; then PKG_CFLAGS="$PKG_CFLAGS -DTREECTRL_DEBUG" fi #-------------------------------------------------------------------- # Everyone should be linking against the Tcl stub library. If you # can't for some reason, remove this definition. If you aren't using # stubs, you also need to modify the SHLIB_LD_LIBS setting below to # link against the non-stubbed Tcl library. Add Tk too if necessary. #-------------------------------------------------------------------- cat >>confdefs.h <<\_ACEOF #define USE_TCL_STUBS 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define USE_TK_STUBS 1 _ACEOF #-------------------------------------------------------------------- # 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)" MAKE_STUB_LIB="\${STLIB_LD} -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. SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" fi eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" else eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries eval eval "PKG_STUB_LIB_FILE=${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_NAME}${SHARED_LIB_SUFFIX}" RANLIB=: else eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries eval eval "PKG_STUB_LIB_FILE=lib${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 #-------------------------------------------------------------------- # Find tclsh so that we can run pkg_mkIndex to generate the pkgIndex.tcl # file during the install process. Don't run the TCLSH_PROG through # ${CYGPATH} because it's being used directly by make. # Require that we use a tclsh shell version 8.2 or later since earlier # versions have bugs in the pkg_mkIndex routine. # Add WISH as well if this is a Tk extension. #-------------------------------------------------------------------- { echo "$as_me:$LINENO: checking for tclsh" >&5 echo $ECHO_N "checking for tclsh... $ECHO_C" >&6; } if test -f "${TCL_BIN_DIR}/Makefile" ; then # tclConfig.sh is in Tcl build directory if test "${TEA_PLATFORM}" = "windows"; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" 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 { echo "$as_me:$LINENO: result: ${TCLSH_PROG}" >&5 echo "${ECHO_T}${TCLSH_PROG}" >&6; } { echo "$as_me:$LINENO: checking for wish" >&5 echo $ECHO_N "checking for wish... $ECHO_C" >&6; } if test -f "${TK_BIN_DIR}/Makefile" ; then # tkConfig.sh is in Tk build directory if test "${TEA_PLATFORM}" = "windows"; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" 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 { echo "$as_me:$LINENO: result: ${WISH_PROG}" >&5 echo "${ECHO_T}${WISH_PROG}" >&6; } #-------------------------------------------------------------------- # Finally, substitute all of the various values into the Makefile. # You may alternatively have a special pkgIndex.tcl.in or other files # which require substituting th AC variables in. Include these here. #-------------------------------------------------------------------- ac_config_files="$ac_config_files Makefile" 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_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_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 test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 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=' 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= 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=`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. ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $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} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## 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=: # Zsh 3.x and 4.x performs 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 # PATH needs CR # 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 # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false 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.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. 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 echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. 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 # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. 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" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # 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 } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi 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 fi echo >conf$$.file 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 -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' 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=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # 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 # 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 shellicon $as_me 2.2, which was generated by GNU Autoconf 2.61. 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 cat >>$CONFIG_STATUS <<_ACEOF # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit -q, --quiet 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 ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ shellicon config.status 2.2 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2006 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' INSTALL='$INSTALL' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. 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=$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 ) echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) 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. -*) { echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *) ac_config_targets="$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 if \$ac_cs_recheck; then echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 CONFIG_SHELL=$SHELL export CONFIG_SHELL exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; 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= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } # # Set up the sed scripts for CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "$CONFIG_FILES"; then _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF SHELL!$SHELL$ac_delim PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim PACKAGE_NAME!$PACKAGE_NAME$ac_delim PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim PACKAGE_STRING!$PACKAGE_STRING$ac_delim PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim exec_prefix!$exec_prefix$ac_delim prefix!$prefix$ac_delim program_transform_name!$program_transform_name$ac_delim bindir!$bindir$ac_delim sbindir!$sbindir$ac_delim libexecdir!$libexecdir$ac_delim datarootdir!$datarootdir$ac_delim datadir!$datadir$ac_delim sysconfdir!$sysconfdir$ac_delim sharedstatedir!$sharedstatedir$ac_delim localstatedir!$localstatedir$ac_delim includedir!$includedir$ac_delim oldincludedir!$oldincludedir$ac_delim docdir!$docdir$ac_delim infodir!$infodir$ac_delim htmldir!$htmldir$ac_delim dvidir!$dvidir$ac_delim pdfdir!$pdfdir$ac_delim psdir!$psdir$ac_delim libdir!$libdir$ac_delim localedir!$localedir$ac_delim mandir!$mandir$ac_delim DEFS!$DEFS$ac_delim ECHO_C!$ECHO_C$ac_delim ECHO_N!$ECHO_N$ac_delim ECHO_T!$ECHO_T$ac_delim LIBS!$LIBS$ac_delim build_alias!$build_alias$ac_delim host_alias!$host_alias$ac_delim target_alias!$target_alias$ac_delim PACKAGE_PATCHLEVEL!$PACKAGE_PATCHLEVEL$ac_delim CYGPATH!$CYGPATH$ac_delim EXEEXT!$EXEEXT$ac_delim PKG_LIB_FILE!$PKG_LIB_FILE$ac_delim PKG_STUB_LIB_FILE!$PKG_STUB_LIB_FILE$ac_delim PKG_STUB_SOURCES!$PKG_STUB_SOURCES$ac_delim PKG_STUB_OBJECTS!$PKG_STUB_OBJECTS$ac_delim PKG_TCL_SOURCES!$PKG_TCL_SOURCES$ac_delim PKG_HEADERS!$PKG_HEADERS$ac_delim PKG_INCLUDES!$PKG_INCLUDES$ac_delim PKG_LIBS!$PKG_LIBS$ac_delim PKG_CFLAGS!$PKG_CFLAGS$ac_delim TCL_VERSION!$TCL_VERSION$ac_delim TCL_BIN_DIR!$TCL_BIN_DIR$ac_delim TCL_SRC_DIR!$TCL_SRC_DIR$ac_delim TCL_LIB_FILE!$TCL_LIB_FILE$ac_delim TCL_LIB_FLAG!$TCL_LIB_FLAG$ac_delim TCL_LIB_SPEC!$TCL_LIB_SPEC$ac_delim TCL_STUB_LIB_FILE!$TCL_STUB_LIB_FILE$ac_delim TCL_STUB_LIB_FLAG!$TCL_STUB_LIB_FLAG$ac_delim TCL_STUB_LIB_SPEC!$TCL_STUB_LIB_SPEC$ac_delim TCL_LIBS!$TCL_LIBS$ac_delim TCL_DEFS!$TCL_DEFS$ac_delim TCL_EXTRA_CFLAGS!$TCL_EXTRA_CFLAGS$ac_delim TCL_LD_FLAGS!$TCL_LD_FLAGS$ac_delim TCL_SHLIB_LD_LIBS!$TCL_SHLIB_LD_LIBS$ac_delim TK_VERSION!$TK_VERSION$ac_delim TK_BIN_DIR!$TK_BIN_DIR$ac_delim TK_SRC_DIR!$TK_SRC_DIR$ac_delim TK_LIB_FILE!$TK_LIB_FILE$ac_delim TK_LIB_FLAG!$TK_LIB_FLAG$ac_delim TK_LIB_SPEC!$TK_LIB_SPEC$ac_delim TK_STUB_LIB_FILE!$TK_STUB_LIB_FILE$ac_delim TK_STUB_LIB_FLAG!$TK_STUB_LIB_FLAG$ac_delim TK_STUB_LIB_SPEC!$TK_STUB_LIB_SPEC$ac_delim TK_LIBS!$TK_LIBS$ac_delim TK_XINCLUDES!$TK_XINCLUDES$ac_delim CC!$CC$ac_delim CFLAGS!$CFLAGS$ac_delim LDFLAGS!$LDFLAGS$ac_delim CPPFLAGS!$CPPFLAGS$ac_delim ac_ct_CC!$ac_ct_CC$ac_delim OBJEXT!$OBJEXT$ac_delim CPP!$CPP$ac_delim INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim INSTALL_DATA!$INSTALL_DATA$ac_delim SET_MAKE!$SET_MAKE$ac_delim RANLIB!$RANLIB$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim MATH_LIBS!$MATH_LIBS$ac_delim PKG_SOURCES!$PKG_SOURCES$ac_delim PKG_OBJECTS!$PKG_OBJECTS$ac_delim TCL_TOP_DIR_NATIVE!$TCL_TOP_DIR_NATIVE$ac_delim TCL_GENERIC_DIR_NATIVE!$TCL_GENERIC_DIR_NATIVE$ac_delim TCL_UNIX_DIR_NATIVE!$TCL_UNIX_DIR_NATIVE$ac_delim TCL_WIN_DIR_NATIVE!$TCL_WIN_DIR_NATIVE$ac_delim TCL_BMAP_DIR_NATIVE!$TCL_BMAP_DIR_NATIVE$ac_delim TCL_TOOL_DIR_NATIVE!$TCL_TOOL_DIR_NATIVE$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF CEOF$ac_eof _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF TCL_PLATFORM_DIR_NATIVE!$TCL_PLATFORM_DIR_NATIVE$ac_delim TCL_INCLUDES!$TCL_INCLUDES$ac_delim TK_TOP_DIR_NATIVE!$TK_TOP_DIR_NATIVE$ac_delim TK_UNIX_DIR_NATIVE!$TK_UNIX_DIR_NATIVE$ac_delim TK_WIN_DIR_NATIVE!$TK_WIN_DIR_NATIVE$ac_delim TK_GENERIC_DIR_NATIVE!$TK_GENERIC_DIR_NATIVE$ac_delim TK_XLIB_DIR_NATIVE!$TK_XLIB_DIR_NATIVE$ac_delim TK_PLATFORM_DIR_NATIVE!$TK_PLATFORM_DIR_NATIVE$ac_delim TK_INCLUDES!$TK_INCLUDES$ac_delim XMKMF!$XMKMF$ac_delim CLEANFILES!$CLEANFILES$ac_delim TCL_THREADS!$TCL_THREADS$ac_delim SHARED_BUILD!$SHARED_BUILD$ac_delim AR!$AR$ac_delim CELIB_DIR!$CELIB_DIR$ac_delim LIBOBJS!$LIBOBJS$ac_delim DL_LIBS!$DL_LIBS$ac_delim CFLAGS_DEBUG!$CFLAGS_DEBUG$ac_delim CFLAGS_OPTIMIZE!$CFLAGS_OPTIMIZE$ac_delim CFLAGS_WARNING!$CFLAGS_WARNING$ac_delim STLIB_LD!$STLIB_LD$ac_delim SHLIB_LD!$SHLIB_LD$ac_delim SHLIB_LD_LIBS!$SHLIB_LD_LIBS$ac_delim SHLIB_CFLAGS!$SHLIB_CFLAGS$ac_delim LD_LIBRARY_PATH_VAR!$LD_LIBRARY_PATH_VAR$ac_delim TCL_DBGX!$TCL_DBGX$ac_delim CFLAGS_DEFAULT!$CFLAGS_DEFAULT$ac_delim LDFLAGS_DEFAULT!$LDFLAGS_DEFAULT$ac_delim MAKE_LIB!$MAKE_LIB$ac_delim MAKE_SHARED_LIB!$MAKE_SHARED_LIB$ac_delim MAKE_STATIC_LIB!$MAKE_STATIC_LIB$ac_delim MAKE_STUB_LIB!$MAKE_STUB_LIB$ac_delim RANLIB_STUB!$RANLIB_STUB$ac_delim TCLSH_PROG!$TCLSH_PROG$ac_delim WISH_PROG!$WISH_PROG$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 36; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b end _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF :end s/|#_!!_#|//g CEOF$ac_eof _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ 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[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF fi # test -n "$CONFIG_FILES" for ac_tag in :F $CONFIG_FILES do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 echo "$as_me: error: Invalid tag $ac_tag." >&2;} { (exit 1); exit 1; }; };; :[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="$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 || { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 echo "$as_me: error: cannot find input file: $ac_f" >&2;} { (exit 1); exit 1; }; };; esac ac_file_inputs="$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 "`IFS=: echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} fi case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin";; 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 || 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" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`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 || 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" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`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 # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # 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= case `sed -n '/datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p ' $ac_file_inputs` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF 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 sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s&@configure_input@&$configure_input&;t t s&@top_builddir@&$ac_top_builddir_sub&;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 s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 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 "$tmp/stdin" case $ac_file in -) cat "$tmp/out"; rm -f "$tmp/out";; *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; esac ;; esac done # for ac_tag { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # 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 || { (exit 1); exit 1; } fi tktreectrl-2.2.8/shellicon/configure.ac0000775000175600010010000001700411073207242016366 0ustar TimNone#!/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. # # RCS: @(#) $Id: configure.ac,v 1.7 2008/10/08 19:48:50 treectrl Exp $ #----------------------------------------------------------------------- # Sample configure.in for Tcl Extensions. # See the TEA sample extension for description of structure and items. #----------------------------------------------------------------------- #----------------------------------------------------------------------- # __CHANGE__ # This very first macro is used to verify that the configure script can # find the sources. The argument to AC_INIT should be a unique filename # for this package, and can be a relative path, such as: # # AC_INIT(generic/tcl.h) #----------------------------------------------------------------------- AC_INIT([shellicon], [2.2]) AC_SUBST([PACKAGE_PATCHLEVEL], [2.2.8]) AC_DEFINE_UNQUOTED(PACKAGE_PATCHLEVEL, "$PACKAGE_PATCHLEVEL") TEA_INIT([3.5]) 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, AC_PROG_INSTALL 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([shellicon.c]) TEA_ADD_HEADERS([]) TEA_ADD_INCLUDES([-I\"`${CYGPATH} ${srcdir}/../generic`\"]) TEA_ADD_CFLAGS([]) TEA_ADD_STUB_SOURCES([]) TEA_ADD_TCL_SOURCES([]) #-------------------------------------------------------------------- # __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 #-------------------------------------------------------------------- # For Unix/Tk builds, make sure that the X libraries/headers are found. #-------------------------------------------------------------------- TEA_PATH_X # Needed for OS X ppx/intel image handling AC_C_BIGENDIAN #-------------------------------------------------------------------- # __CHANGE__ # A few miscellaneous platform-specific items: # # Define a special symbol for Windows (BUILD_sample in this case) so # that we create the export library with the dll. See sha1.h on how # to use this. # # Windows creates a few extra files that need to be cleaned up. # You can add more files to clean if your extension creates any extra # files. # # Define any extra compiler flags in the PACKAGE_CFLAGS variable. # These will be appended to the current set of compiler flags for # your system. #-------------------------------------------------------------------- if test "${TEA_PLATFORM}" = "windows" ; then AC_DEFINE(BUILD_shellicon) CLEANFILES="pkgIndex.tcl *.lib *.dll *.exp *.ilk *.pdb vc*.pch" TEA_ADD_LIBS([gdi32.lib user32.lib comctl32.lib ole32.lib]) else CLEANFILES="pkgIndex.tcl" fi if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then TEA_ADD_LIBS([-framework Carbon]) fi AC_SUBST(CLEANFILES) #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. #-------------------------------------------------------------------- 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 if test "${enable_symbols+set}" = set && test "$enable_symbols" != no; then TEA_ADD_CFLAGS([-DTREECTRL_DEBUG]) fi #-------------------------------------------------------------------- # Everyone should be linking against the Tcl stub library. If you # can't for some reason, remove this definition. If you aren't using # stubs, you also need to modify the SHLIB_LD_LIBS setting below to # link against the non-stubbed Tcl library. Add Tk too if necessary. #-------------------------------------------------------------------- AC_DEFINE(USE_TCL_STUBS) AC_DEFINE(USE_TK_STUBS) #-------------------------------------------------------------------- # 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 #-------------------------------------------------------------------- # Find tclsh so that we can run pkg_mkIndex to generate the pkgIndex.tcl # file during the install process. Don't run the TCLSH_PROG through # ${CYGPATH} because it's being used directly by make. # Require that we use a tclsh shell version 8.2 or later since earlier # versions have bugs in the pkg_mkIndex routine. # Add WISH as well if this is a Tk extension. #-------------------------------------------------------------------- TEA_PROG_TCLSH TEA_PROG_WISH #-------------------------------------------------------------------- # Finally, substitute all of the various values into the Makefile. # You may alternatively have a special pkgIndex.tcl.in or other files # which require substituting th AC variables in. Include these here. #-------------------------------------------------------------------- AC_OUTPUT([Makefile]) tktreectrl-2.2.8/shellicon/Makefile.in0000664000175600010010000003543111041154535016147 0ustar TimNone# 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 ActiveState SRL. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: Makefile.in,v 1.5 2008/07/21 18:45:49 treectrl Exp $ #======================================================================== # Edit the following few lines when writing a new extension #======================================================================== #======================================================================== # Nothing of the variables below this line 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_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_EXTRA_FILES = PKG_MAN_PAGES = #======================================================================== # "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 = $(lib_BINARIES) SHELL = @SHELL@ srcdir = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ datadir = @datadir@ datarootdir = @datarootdir@ mandir = @mandir@ includedir = @includedir@ DESTDIR = TREECTRL_DIR = $(libdir)/treectrl$(PACKAGE_PATCHLEVEL) PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_PATCHLEVEL) pkgdatadir = $(datadir)/$(PKG_DIR) pkglibdir = $(TREECTRL_DIR)/$(PKG_DIR) pkgincludedir = $(includedir)/$(PKG_DIR) top_builddir = . INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PACKAGE_PATCHLEVEL = @PACKAGE_PATCHLEVEL@ CC = @CC@ CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ CFLAGS_WARNING = @CFLAGS_WARNING@ CLEANFILES = @CLEANFILES@ 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_SRC_DIR = @TCL_SRC_DIR@ TCL_BIN_DIR = @TCL_BIN_DIR@ TK_SRC_DIR = @TK_SRC_DIR@ TK_BIN_DIR = @TK_BIN_DIR@ # Not used, but retained for reference of what libs Tcl required TCL_LIBS = @TCL_LIBS@ TK_LIBS = @TK_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):$(TK_BIN_DIR) TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \ TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library` \ TREECTRL_LIBRARY=`@CYGPATH@ $(srcdir)/library` \ @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ PATH="$(EXTRA_PATH):$(PATH)" \ TCLLIBPATH="$(top_builddir)" TCLSH_PROG = @TCLSH_PROG@ WISH_PROG = @WISH_PROG@ TCLSH = $(TCLSH_ENV) $(TCLSH_PROG) WISH = $(TCLSH_ENV) $(WISH_PROG) # The local includes must come first, because the TK_XINCLUDES can be # just a comment INCLUDES = @PKG_INCLUDES@ \ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ PKG_CFLAGS = @PKG_CFLAGS@ DEFS = @DEFS@ $(PKG_CFLAGS) CONFIG_CLEAN_FILES = Makefile CPPFLAGS = @CPPFLAGS@ LIBS = @PKG_LIBS@ @LIBS@ AR = @AR@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) #======================================================================== # Start of user-definable TARGETS section #======================================================================== #======================================================================== # TEA TARGETS. Please note that the "libraries:" target refers to platform # independent files, and the "binaries:" target inclues 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) pkgIndex.tcl libraries: doc-x: @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" doc: @echo "No docs to build" install: all install-binaries install-libraries install-doc install-binaries: binaries install-lib-binaries install-bin-binaries @mkdir -p $(DESTDIR)$(pkglibdir) $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir) @list='$(PKG_EXTRA_FILES)'; 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 #======================================================================== # This rule installs platform-independent files, such as header files. #======================================================================== install-libraries: libraries #======================================================================== # Install documentation. Unix manpages should go in the $(mandir) # directory. #======================================================================== install-doc-x: @mkdir -p $(DESTDIR)$(mandir)/mann @echo "Installing documentation in $(DESTDIR)$(mandir)" @for i in $(srcdir)/doc/*.n; do \ echo "Installing $$i"; \ rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \ $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \ done install-doc: install-doc-x mkdir -p $(DESTDIR)$(pkglibdir)/htmldoc cp $(srcdir)/doc/*.html $(DESTDIR)$(pkglibdir)/htmldoc test: binaries libraries $(WISH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) | cat shell: binaries libraries @$(WISH) $(SCRIPT) demo: binaries libraries @$(WISH) `@CYGPATH@ $(srcdir)/demos/demo.tcl` | cat gdb: $(TCLSH_ENV) gdb --silent --args $(WISH_PROG) $(srcdir)/demos/demo.tcl 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) #======================================================================== # 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: # # tkpkg.$(OBJEXT): $(srcdir)/src/win/tkpkg.c # $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/tkpkg.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. #======================================================================== # I added leading $(srcdir) because autoconf 2.53 strips it off VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win .c.@OBJEXT@: $(COMPILE) -c `@CYGPATH@ $<` -o $@ #======================================================================== # Create the pkgIndex.tcl file. #======================================================================== pkgIndex.tcl: (\ echo 'if {[catch {package require Tcl @TK_VERSION@}]} return';\ echo 'set script "load \"[file join $$dir $(PKG_LIB_FILE)]\" $(PACKAGE_NAME)"';\ echo 'package ifneeded $(PACKAGE_NAME) $(PACKAGE_PATCHLEVEL) $$script'\ ) > pkgIndex.tcl #======================================================================== # 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 = gtar zcvf $(PKG_DIR).tar.gz $(PKG_DIR) DIST_ROOT = /tmp/dist DIST_DIR = $(DIST_ROOT)/$(PKG_DIR) dist-clean: rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.* dist: dist-clean mkdir -p $(DIST_DIR) cp -p $(srcdir)/shellicon.c \ $(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.ac \ $(srcdir)/*.in $(DIST_DIR)/ chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4 chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.ac cp -p $(srcdir)/*.[ch] $(DIST_DIR)/ mkdir $(DIST_DIR)/tclconfig cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \ $(DIST_DIR)/tclconfig/ chmod 664 $(DIST_DIR)/tclconfig/tcl.m4 chmod +x $(DIST_DIR)/tclconfig/install-sh list='demos doc generic library mac tests unix win'; \ for p in $$list; do \ if test -d $(srcdir)/$$p ; then \ mkdir $(DIST_DIR)/$$p; \ cp -p $(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.in #======================================================================== 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: @mkdir -p $(DESTDIR)$(pkglibdir) @list='$(lib_BINARIES)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p"; \ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \ echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \ $(RANLIB) $(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 #======================================================================== # 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: @mkdir -p $(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 .SUFFIXES: .c .$(OBJEXT) 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 # 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: tktreectrl-2.2.8/shellicon/shellicon.c0000700000175600010010000005363310560222057016221 0ustar TimNone/* * shellicon.c -- * * This is a Tk extension that adds a new element type to TkTreeCtrl. * The element type's name is "shellicon". A shellicon element can * display the icon for a file or folder using Win32 Shell API calls. * * Copyright (c) 2005 Tim Baker * * RCS: @(#) $Id: shellicon.c,v 1.4 2007/01/31 23:20:15 treectrl Exp $ */ #include "tkTreeCtrl.h" #include "tkTreeElem.h" #include "tkWinInt.h" #ifndef _WIN32_IE #define _WIN32_IE 0x0501 #endif #include #include #include #include #ifndef SHGFI_ADDOVERLAYS #if (_WIN32_IE >= 0x0500) #define SHGFI_ADDOVERLAYS 0x000000020 #define SHGFI_OVERLAYINDEX 0x000000040 #endif #endif #ifndef SHIL_LARGE #define SHIL_LARGE 0 #define SHIL_SMALL 1 #define SHIL_EXTRALARGE 2 #if 0 const GUID IID_IImageList = {0x2C247F21, 0x8591, 0x11D1,{ 0xB1, 0x6A, 0x00,0xC0, 0xF0, 0x28,0x36, 0x28} }; HRESULT (*SHGetImageListProc)(int iImageList, REFIID riid, void **ppv); #endif #endif HIMAGELIST gImgListSmall = NULL; HIMAGELIST gImgListLarge = NULL; TreeCtrlStubs *stubs; #define TreeCtrl_RegisterElementType(i,t) \ stubs->TreeCtrl_RegisterElementType(i,t) #define Tree_RedrawElement(t,i,e) \ stubs->Tree_RedrawElement(t,i,e) #define Tree_ElementIterateBegin(t,et) \ stubs->Tree_ElementIterateBegin(t,et) #define Tree_ElementIterateNext(i) \ stubs->Tree_ElementIterateNext(i) #define Tree_ElementIterateGet(i) \ stubs->Tree_ElementIterateGet(i) #define Tree_ElementIterateChanged(i,m) \ stubs->Tree_ElementIterateChanged(i,m) #define PerStateInfo_Free(t,ty,in) \ stubs->PerStateInfo_Free(t,ty,in) #define PerStateInfo_FromObj(t,pr,ty,in) \ stubs->PerStateInfo_FromObj(t,pr,ty,in) #define PerStateInfo_ForState(t,ty,in,st,ma) \ stubs->PerStateInfo_ForState(t,ty,in,st,ma) #define PerStateInfo_ObjForState(t,ty,in,st,ma) \ stubs->PerStateInfo_ObjForState(t,ty,in,st,ma) #define PerStateInfo_Undefine(t,ty,in,st) \ stubs->PerStateInfo_Undefine(t,ty,in,st) #undef pstBoolean #define pstBoolean \ (*stubs->TreeCtrl_pstBoolean) #define PerStateBoolean_ForState(t,in,st,ma) \ stubs->PerStateBoolean_ForState(t,in,st,ma) #define PSTSave(in,sa) \ stubs->PSTSave(in,sa) #define PSTRestore(t,ty,in,sa) \ stubs->PSTRestore(t,ty,in,sa) #define TreeStateFromObj \ stubs->TreeStateFromObj #define BooleanCO_Init(ot,on) \ stubs->BooleanCO_Init(ot,on) #define StringTableCO_Init(ot,on,ta) \ stubs->StringTableCO_Init(ot,on,ta) #define PerStateCO_Init(a,b,c,d) \ stubs->PerStateCO_Init(a,b,c,d) static void AdjustForSticky(int sticky, int cavityWidth, int cavityHeight, int expandX, int expandY, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr) { int dx = 0; int dy = 0; if (cavityWidth > *widthPtr) { dx = cavityWidth - *widthPtr; } if (cavityHeight > *heightPtr) { dy = cavityHeight - *heightPtr; } if ((sticky & STICKY_W) && (sticky & STICKY_E)) { if (expandX) *widthPtr += dx; else sticky &= ~(STICKY_W | STICKY_E); } if ((sticky & STICKY_N) && (sticky & STICKY_S)) { if (expandY) *heightPtr += dy; else sticky &= ~(STICKY_N | STICKY_S); } if (!(sticky & STICKY_W)) { *xPtr += (sticky & STICKY_E) ? dx : dx / 2; } if (!(sticky & STICKY_N)) { *yPtr += (sticky & STICKY_S) ? dy : dy / 2; } } /* This macro gets the value of a per-state option for an element, then * looks for a better match from the master element if it exists */ #define OPTION_FOR_STATE(xFUNC,xTYPE,xVAR,xFIELD,xSTATE) \ xVAR = xFUNC(tree, &elemX->xFIELD, xSTATE, &match); \ if ((match != MATCH_EXACT) && (masterX != NULL)) { \ xTYPE varM = xFUNC(tree, &masterX->xFIELD, xSTATE, &match2); \ if (match2 > match) \ xVAR = varM; \ } #define BOOLEAN_FOR_STATE(xVAR,xFIELD,xSTATE) \ OPTION_FOR_STATE(PerStateBoolean_ForState,int,xVAR,xFIELD,xSTATE) /* This macro gets the object for a per-state option for an element, then * looks for a better match from the master element if it exists */ #define OBJECT_FOR_STATE(xVAR,xTYPE,xFIELD,xSTATE) \ xVAR = PerStateInfo_ObjForState(tree, &xTYPE, &elemX->xFIELD, xSTATE, &match); \ if ((match != MATCH_EXACT) && (masterX != NULL)) { \ Tcl_Obj *objM = PerStateInfo_ObjForState(tree, &xTYPE, &masterX->xFIELD, xSTATE, &matchM); \ if (matchM > match) \ xVAR = objM; \ } typedef struct ElementShellIcon ElementShellIcon; struct ElementShellIcon { TreeElement_ header; PerStateInfo draw; Tcl_Obj *pathObj; /* path of file or directory */ char *path; Tcl_Obj *widthObj; int width; Tcl_Obj *heightObj; int height; #define TYPE_DIRECTORY 0 #define TYPE_FILE 1 int type; /* If specified, 'path' is assumed to exist */ #define SIZE_LARGE 0 #define SIZE_SMALL 1 int size; /* SIZE_LARGE if unspecified */ HIMAGELIST hImgList; /* the system image list */ int iIcon; /* index into hImgList */ int addOverlays; /* only when useImgList is FALSE */ int useImgList; /* if false, create icons */ HICON hIcon; /* icon */ HICON hIconSel; /* selected icon */ }; #define SHELLICON_CONF_ICON 0x0001 #define SHELLICON_CONF_SIZE 0x0002 #define SHELLICON_CONF_DRAW 0x0004 static CONST char *sizeST[] = { "large", "small", (char *) NULL }; static CONST char *typeST[] = { "directory", "file", (char *) NULL }; static Tk_OptionSpec shellIconOptionSpecs[] = { {TK_OPTION_CUSTOM, "-addoverlays", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementShellIcon, addOverlays), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON}, {TK_OPTION_CUSTOM, "-draw", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementShellIcon, draw.obj), Tk_Offset(ElementShellIcon, draw), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_DRAW}, {TK_OPTION_PIXELS, "-height", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementShellIcon, heightObj), Tk_Offset(ElementShellIcon, height), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_SIZE}, {TK_OPTION_STRING, "-path", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementShellIcon, pathObj), Tk_Offset(ElementShellIcon, path), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON}, {TK_OPTION_CUSTOM, "-size",(char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementShellIcon, size), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON}, {TK_OPTION_CUSTOM, "-type", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementShellIcon, type), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON}, {TK_OPTION_CUSTOM, "-useimagelist", (char *) NULL, (char *) NULL, (char *) NULL, -1, Tk_Offset(ElementShellIcon, useImgList), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_ICON}, {TK_OPTION_PIXELS, "-width", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(ElementShellIcon, widthObj), Tk_Offset(ElementShellIcon, width), TK_OPTION_NULL_OK, (ClientData) NULL, SHELLICON_CONF_SIZE}, {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, -1, 0, (ClientData) NULL, 0} }; static void LoadIconIfNeeded(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementShellIcon *elemX = (ElementShellIcon *) elem; ElementShellIcon *masterX = (ElementShellIcon *) elem->master; SHFILEINFO sfi; Tcl_DString dString1, dString2; UINT uFlags = SHGFI_SYSICONINDEX; DWORD dwFileAttributes = 0; char *nativePath; int size = SIZE_LARGE; int overlays = 1; int type = -1; int useImgList = TRUE; HRESULT result; /* -useimagelist boolean */ if (elemX->useImgList != -1) useImgList = elemX->useImgList; else if (masterX != NULL && masterX->useImgList != -1) useImgList = masterX->useImgList; /* Not using the system image list. */ if (!useImgList) { /* Already have an icon, or no path is given so no icon used */ if ((elemX->hIcon != NULL) || (elemX->path == NULL)) return; /* Equivalent to "file nativename $path" */ nativePath = Tcl_TranslateFileName(tree->interp, elemX->path, &dString1); if (nativePath == NULL) return; /* This will be passed to system calls, so convert from UTF8 */ nativePath = Tcl_UtfToExternalDString(NULL, nativePath, -1, &dString2); uFlags = SHGFI_ICON; /* -addoverlays boolean */ if (elemX->addOverlays != -1) overlays = elemX->addOverlays; else if (masterX != NULL && masterX->addOverlays != -1) overlays = masterX->addOverlays; if (overlays) uFlags |= SHGFI_ADDOVERLAYS; /* -size small or large */ if (elemX->size != -1) size = elemX->size; else if (masterX != NULL && masterX->size != -1) size = masterX->size; switch (size) { case SIZE_LARGE: uFlags |= SHGFI_LARGEICON | SHGFI_SHELLICONSIZE; break; case SIZE_SMALL: uFlags |= SHGFI_SMALLICON | SHGFI_SHELLICONSIZE; break; } /* -type file or -type directory */ if (elemX->type != -1) type = elemX->type; else if (masterX != NULL && masterX->type != -1) type = masterX->type; /* If SHGFI_USEFILEATTRIBUTES is set, SHGetFileInfo is supposed to * assume that the file is real but not look for it on disk. This * can be used to get the icon for a certain type of file, ex *.exe. * In practice, lots of files get a non-generic icon when a * valid file path is given. */ if (type != -1) { dwFileAttributes = (type == TYPE_FILE) ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_DIRECTORY; uFlags |= SHGFI_USEFILEATTRIBUTES; } /* MSDN says SHGFI_OPENICON returns the image list containing the * small open icon. In practice the large open icon gets returned * for SHGFI_LARGEICON, so we support it. */ if (/*(size == SIZE_SMALL) && */(args->state & STATE_OPEN)) uFlags |= SHGFI_OPENICON; CoInitialize(NULL); result = SHGetFileInfo( nativePath, dwFileAttributes, &sfi, sizeof(sfi), uFlags); if (result) { elemX->hIcon = sfi.hIcon; /* Remember the image list so we can get the icon size */ elemX->hImgList = (size == SIZE_LARGE) ? gImgListLarge : gImgListSmall; } result = SHGetFileInfo( nativePath, dwFileAttributes, &sfi, sizeof(sfi), uFlags | SHGFI_SELECTED); if (result) elemX->hIconSel = sfi.hIcon; CoUninitialize(); Tcl_DStringFree(&dString1); Tcl_DStringFree(&dString2); return; } /* Using the system image list */ if ((elemX->hImgList == NULL) && (elemX->path != NULL)) { /* Equivalent to "file nativename $path" */ nativePath = Tcl_TranslateFileName(tree->interp, elemX->path, &dString1); if (nativePath == NULL) return; /* This will be passed to system calls, so convert from UTF8 */ nativePath = Tcl_UtfToExternalDString(NULL, nativePath, -1, &dString2); /* -size small or large */ if (elemX->size != -1) size = elemX->size; else if (masterX != NULL && masterX->size != -1) size = masterX->size; switch (size) { case SIZE_SMALL: uFlags |= SHGFI_SMALLICON | SHGFI_SHELLICONSIZE; break; case SIZE_LARGE: uFlags |= SHGFI_LARGEICON | SHGFI_SHELLICONSIZE; break; } /* -type file or -type directory */ if (elemX->type != -1) type = elemX->type; else if (masterX != NULL && masterX->type != -1) type = masterX->type; /* If SHGFI_USEFILEATTRIBUTES is set, SHGetFileInfo is supposed to * assume that the file is real but not look for it on disk. This * can be used to get the icon for a certain type of file, ex *.exe. * In practice, lots of files get a non-generic icon when a * valid file path is given. */ if (type != -1) { dwFileAttributes = (type == TYPE_FILE) ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_DIRECTORY; uFlags |= SHGFI_USEFILEATTRIBUTES; } /* MSDN says SHGFI_OPENICON returns the image list containing the * small open icon. In practice the large open icon gets returned * for SHGFI_LARGEICON. */ if (/*(size == SIZE_SMALL) && */(args->state & STATE_OPEN)) uFlags |= SHGFI_OPENICON; CoInitialize(NULL); elemX->hImgList = (HIMAGELIST) SHGetFileInfo( nativePath, dwFileAttributes, &sfi, sizeof(sfi), uFlags); if (elemX->hImgList != NULL) { elemX->iIcon = sfi.iIcon; } CoUninitialize(); Tcl_DStringFree(&dString1); Tcl_DStringFree(&dString2); } } static void ForgetIcon(ElementShellIcon *elemX) { if (elemX->hIcon != NULL) DestroyIcon(elemX->hIcon); if (elemX->hIconSel != NULL) DestroyIcon(elemX->hIconSel); elemX->hImgList = NULL; elemX->hIcon = elemX->hIconSel = NULL; } static void DeleteProcShellIcon(TreeElementArgs *args) { TreeElement elem = args->elem; ElementShellIcon *elemX = (ElementShellIcon *) elem; ForgetIcon(elemX); } static int WorldChangedProcShellIcon(TreeElementArgs *args) { ElementShellIcon *elemX = (ElementShellIcon *) args->elem; int flagM = args->change.flagMaster; int flagS = args->change.flagSelf; int mask = 0; if ((flagS | flagM) & (SHELLICON_CONF_ICON | SHELLICON_CONF_SIZE)) mask |= CS_DISPLAY | CS_LAYOUT; if ((flagS | flagM) & (SHELLICON_CONF_DRAW)) mask |= CS_DISPLAY; if ((flagS | flagM) & SHELLICON_CONF_ICON) { ForgetIcon(elemX); } return mask; } static int ConfigProcShellIcon(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementShellIcon *elemX = (ElementShellIcon *) elem; Tk_SavedOptions savedOptions; int error; Tcl_Obj *errorResult = NULL; for (error = 0; error <= 1; error++) { if (error == 0) { if (Tk_SetOptions(tree->interp, (char *) elemX, elem->typePtr->optionTable, args->config.objc, args->config.objv, tree->tkwin, &savedOptions, &args->config.flagSelf) != TCL_OK) { args->config.flagSelf = 0; continue; } /* xxx */ Tk_FreeSavedOptions(&savedOptions); break; } else { errorResult = Tcl_GetObjResult(tree->interp); Tcl_IncrRefCount(errorResult); Tk_RestoreSavedOptions(&savedOptions); /* xxx */ Tcl_SetObjResult(tree->interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } } return TCL_OK; } static int CreateProcShellIcon(TreeElementArgs *args) { ElementShellIcon *elemX = (ElementShellIcon *) args->elem; elemX->type = -1; elemX->size = -1; elemX->addOverlays = -1; elemX->useImgList = -1; return TCL_OK; } static void DisplayProcShellIcon(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementShellIcon *elemX = (ElementShellIcon *) elem; ElementShellIcon *masterX = (ElementShellIcon *) elem->master; int state = args->state; int x = args->display.x, y = args->display.y; int width, height; int match, match2; int draw; HDC hDC; TkWinDCState dcState; UINT fStyle = ILD_TRANSPARENT; HICON hIcon; BOOLEAN_FOR_STATE(draw, draw, state) if (!draw) return; LoadIconIfNeeded(args); if (elemX->hImgList == NULL) return; (void) ImageList_GetIconSize(elemX->hImgList, &width, &height); AdjustForSticky(args->display.sticky, args->display.width, args->display.height, FALSE, FALSE, &x, &y, &width, &height); hDC = TkWinGetDrawableDC(tree->display, args->display.drawable, &dcState); hIcon = (state & STATE_SELECTED) ? elemX->hIconSel : elemX->hIcon; if (hIcon != NULL) { #if 1 /* If DI_DEFAULTSIZE is used, small icons get stretched */ DrawIconEx(hDC, x, y, hIcon, 0, 0, FALSE, NULL, DI_IMAGE | DI_MASK /*| DI_DEFAULTSIZE*/); #else /* Works fine for large, but not for small (they get stretched) */ DrawIcon(hDC, x, y, hIcon); #endif } else { if (state & STATE_SELECTED) fStyle |= ILD_SELECTED; ImageList_Draw(elemX->hImgList, elemX->iIcon, hDC, x, y, fStyle); } TkWinReleaseDrawableDC(args->display.drawable, hDC, &dcState); /* If this is a master element, forget the icon being used because the * appearance may change between items based on the open state */ if (masterX == NULL) { ForgetIcon(elemX); } } static void NeededProcShellIcon(TreeElementArgs *args) { TreeElement elem = args->elem; ElementShellIcon *elemX = (ElementShellIcon *) elem; ElementShellIcon *masterX = (ElementShellIcon *) elem->master; int width = 0, height = 0; int size = SIZE_LARGE; HIMAGELIST hImgList = NULL; /* The icon is not loaded until it is actually going to be displayed. * This is a good thing since loading the icons can take a while */ /* LoadIconIfNeeded(args);*/ if (elemX->hImgList != NULL) { hImgList = elemX->hImgList; } else if (elemX->path != NULL) { if (elemX->size != -1) size = elemX->size; else if (masterX != NULL && masterX->size != -1) size = masterX->size; switch (size) { case SIZE_SMALL: hImgList = gImgListSmall; break; case SIZE_LARGE: hImgList = gImgListLarge; break; } } if (hImgList != NULL) { (void) ImageList_GetIconSize(hImgList, &width, &height); } if (elemX->widthObj != NULL) width = elemX->width; else if ((masterX != NULL) && (masterX->widthObj != NULL)) width = masterX->width; if (elemX->heightObj != NULL) height = elemX->height; else if ((masterX != NULL) && (masterX->heightObj != NULL)) height = masterX->height; args->needed.width = width; args->needed.height = height; } static int StateProcShellIcon(TreeElementArgs *args) { TreeCtrl *tree = args->tree; TreeElement elem = args->elem; ElementShellIcon *elemX = (ElementShellIcon *) elem; ElementShellIcon *masterX = (ElementShellIcon *) elem->master; int match, match2; int draw1, draw2; int sel1, sel2; int open1, open2; int mask = 0; BOOLEAN_FOR_STATE(draw1, draw, args->states.state1) if (draw1 == -1) draw1 = 1; open1 = (args->states.state1 & STATE_OPEN) != 0; sel1 = (args->states.state1 & STATE_SELECTED) != 0; BOOLEAN_FOR_STATE(draw2, draw, args->states.state2) if (draw2 == -1) draw2 = 1; open2 = (args->states.state2 & STATE_OPEN) != 0; sel2 = (args->states.state2 & STATE_SELECTED) != 0; if (elemX->path == NULL) open1 = open2 = sel1 = sel2 = 0; if ((draw1 != draw2) || (sel1 != sel2) || (open1 != open2)) mask |= CS_DISPLAY; /* Directories may have an open and closed icon. */ if (open1 != open2) { ForgetIcon(elemX); } return mask; } static int UndefProcShellIcon(TreeElementArgs *args) { TreeCtrl *tree = args->tree; ElementShellIcon *elemX = (ElementShellIcon *) args->elem; int modified = 0; modified |= PerStateInfo_Undefine(tree, &pstBoolean, &elemX->draw, args->state); return modified; } static int ActualProcShellIcon(TreeElementArgs *args) { TreeCtrl *tree = args->tree; ElementShellIcon *elemX = (ElementShellIcon *) args->elem; ElementShellIcon *masterX = (ElementShellIcon *) args->elem->master; static CONST char *optionName[] = { "-draw", (char *) NULL }; int index, match, matchM; Tcl_Obj *obj = NULL; if (Tcl_GetIndexFromObj(tree->interp, args->actual.obj, optionName, "option", 0, &index) != TCL_OK) return TCL_ERROR; switch (index) { case 0: { OBJECT_FOR_STATE(obj, pstBoolean, draw, args->state) break; } } if (obj != NULL) Tcl_SetObjResult(tree->interp, obj); return TCL_OK; } TreeElementType elemTypeShellIcon = { "shellicon", sizeof(ElementShellIcon), shellIconOptionSpecs, NULL, CreateProcShellIcon, DeleteProcShellIcon, ConfigProcShellIcon, DisplayProcShellIcon, NeededProcShellIcon, NULL, /* heightProc */ WorldChangedProcShellIcon, StateProcShellIcon, UndefProcShellIcon, ActualProcShellIcon, NULL /* onScreenProc */ }; DLLEXPORT int Shellicon_Init(Tcl_Interp *interp) { #if 1 SHFILEINFO sfi; #else HMODULE hLib; #endif #ifdef USE_TCL_STUBS if (Tcl_InitStubs(interp, "8.4", 0) == NULL) { return TCL_ERROR; } #endif #ifdef USE_TK_STUBS if (Tk_InitStubs(interp, "8.4", 0) == NULL) { return TCL_ERROR; } #endif /* InitCommonControlsEx must be called to use the ImageList functions */ /* This is already done by Tk on NT */ if (TkWinGetPlatformId() != VER_PLATFORM_WIN32_NT) { INITCOMMONCONTROLSEX comctl; ZeroMemory(&comctl, sizeof(comctl)); (void) InitCommonControlsEx(&comctl); } #if 1 /* Get the sytem image lists (small and large) */ CoInitialize(NULL); gImgListSmall = (HIMAGELIST) SHGetFileInfo(".exe", FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_SMALLICON); gImgListLarge = (HIMAGELIST) SHGetFileInfo(".exe", FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_LARGEICON); CoUninitialize(); #else /* FIXME: WinXP only */ /* This is broken somewhere */ hLib = LoadLibraryA("shell32"); SHGetImageListProc = (FARPROC) GetProcAddress(hLib, (LPCSTR) 727); SHGetImageListProc(SHIL_SMALL, &IID_IImageList, &gImgListSmall); SHGetImageListProc(SHIL_LARGE, &IID_IImageList, &gImgListLarge); SHGetImageListProc(SHIL_EXTRALARGE, &IID_IImageList, &gImgListXtraLarge); dbwin("small %p large %p xtralarge %p\n", gImgListSmall, gImgListLarge, gImgListXtraLarge); FreeLibrary(hLib); #endif /* Load TkTreeCtrl */ if (Tcl_PkgRequire(interp, "treectrl", PACKAGE_PATCHLEVEL, TRUE) == NULL) return TCL_ERROR; /* Get the stubs table from TkTreeCtrl */ stubs = Tcl_GetAssocData(interp, "TreeCtrlStubs", NULL); if (stubs == NULL) return TCL_ERROR; /* Initialize the options table */ BooleanCO_Init(shellIconOptionSpecs, "-addoverlays"); BooleanCO_Init(shellIconOptionSpecs, "-useimagelist"); PerStateCO_Init(shellIconOptionSpecs, "-draw", &pstBoolean, TreeStateFromObj); StringTableCO_Init(shellIconOptionSpecs, "-size", sizeST); StringTableCO_Init(shellIconOptionSpecs, "-type", typeST); /* Add the "shellicon" element type */ if (TreeCtrl_RegisterElementType(interp, &elemTypeShellIcon) != TCL_OK) return TCL_ERROR; if (Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_PATCHLEVEL) != TCL_OK) { return TCL_ERROR; } return TCL_OK; } DLLEXPORT int Shellicon_SafeInit(Tcl_Interp *interp) { return Shellicon_Init(interp); } tktreectrl-2.2.8/shellicon/tclconfig/0000755000175600010010000000000011073207472016046 5ustar TimNonetktreectrl-2.2.8/shellicon/tclconfig/install-sh0000711000175600010010000000421207577521126020052 0ustar TimNone#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5; it is not part of GNU. # # $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $ # # This script is compatible with the BSD install script, but was written # from scratch. # # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" instcmd="$mvprog" chmodcmd="" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; *) if [ x"$src" = x ] then src=$1 else dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` fi # Make a temp file name in the proper directory. dstdir=`dirname $dst` dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp # and set any options; do chmod last to preserve setuid bits if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi # Now rename the file to the real destination. $doit $rmcmd $dst $doit $mvcmd $dsttmp $dst exit 0 tktreectrl-2.2.8/shellicon/tclconfig/README.txt0000700000175600010010000000145307577521126017551 0ustar TimNoneThese 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 SC_* macros. tktreectrl-2.2.8/shellicon/tclconfig/tcl.m40000664000175600010010000036211510557763454017121 0ustar TimNone# 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. # # RCS: @(#) $Id: tcl.m4,v 1.1 2007/01/31 00:47:40 treectrl Exp $ AC_PREREQ(2.50) dnl TEA extensions pass this us the version of TEA they think they dnl are compatible with (must be set in TEA_INIT below) dnl TEA_VERSION="3.5" # Possible values for key variables defined: # # TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem') # TEA_PLATFORM - windows unix # #------------------------------------------------------------------------ # 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 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 -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` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig=`(cd $i/Tcl.framework; pwd)` break fi done fi # 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/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 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 -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_WARN([Can't find Tcl configuration definitions]) exit 0 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 -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` \ ; 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/lib 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig=`(cd $i; pwd)` break fi done fi # 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 -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_WARN([Can't find Tk configuration definitions]) exit 0 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: # # Subst the following vars: # TCL_BIN_DIR # TCL_SRC_DIR # TCL_LIB_FILE # #------------------------------------------------------------------------ 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 arbitary 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"` -framework ${TCL_LIB_FILE}" break fi done fi if test -f ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}; then TCL_STUB_LIB_SPEC="-L${TCL_BIN_DIR} ${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_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_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 arbitary 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"` -framework ${TK_LIB_FILE}" break fi done fi if test -f ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}; then TK_STUB_LIB_SPEC="-L${TK_BIN_DIR} ${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}\"" # 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) AC_SUBST(TK_LIBS) AC_SUBST(TK_XINCLUDES) ]) #------------------------------------------------------------------------ # TEA_ENABLE_SHARED -- # # Allows the building of shared libraries # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-shared=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 #------------------------------------------------------------------------ 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)]), [tcl_ok=$enableval], [tcl_ok=yes]) if test "${enable_shared+set}" = set; then enableval="$enable_shared" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" ; then AC_MSG_RESULT([shared]) SHARED_BUILD=1 else AC_MSG_RESULT([static]) SHARED_BUILD=0 AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?]) fi AC_SUBST(SHARED_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]), [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 ;; *) if test "${TCL_THREADS}" = "1"; then AC_MSG_WARN([ --enable-threads requested, but building against a Tcl that is NOT thread-enabled. This is an OK configuration that will also run in a thread-enabled core.]) 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) 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 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}" 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 if test "${TEA_PLATFORM}" != "windows" ; then LDFLAGS_DEFAULT="${LDFLAGS}" fi AC_SUBST(TCL_DBGX) AC_SUBST(CFLAGS_DEFAULT) AC_SUBST(LDFLAGS_DEFAULT) 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 ], [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, but there are a few systems, like Next, where # this doesn't work. # # 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, [ if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows elif test -f /usr/lib/NextStep/software_version; then tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` 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 # Special check for weird MP-RAS system (uname returns weird # results, and the version is kept in special file). if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then tcl_cv_sys_version=MP-RAS-`awk '{print $3}' /etc/.relid` fi 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 - Name of the object file that implements dynamic # loading for Tcl on this system. # DL_LIBS - Library file(s) to include in tclsh and other base # applications in order for the "load" command to work. # 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 is # "${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 $VERSION variable # to put the version in the right place. This is used # by platforms that need non-standard library names. # Examples: ${VERSION}.so.1.1 on NetBSD, since it needs # to have a version after the .so, and ${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 # ${VERSION}${SHLIB_SUFFIX}. # TCL_NEEDS_EXP_FILE - # 1 means that an export file is needed to link to a # shared library. # TCL_EXP_FILE - The name of the installed export / import file which # should be used to link to the Tcl shared library. # Empty if Tcl is unshared. # TCL_BUILD_EXP_FILE - # The name of the built export / import file which # should be used to link to the Tcl shared library. # Empty if Tcl is unshared. # 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 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]) if test "$do64bitVIS" = "yes"; then # Force 64bit on with VIS do64bit=yes fi # Step 0.c: Cross-compiling options for Windows/CE builds? if test "${TEA_PLATFORM}" = "windows" ; then AC_MSG_CHECKING([if Windows/CE build is requested]) AC_ARG_ENABLE(wince,[ --enable-wince enable Win/CE support (where applicable)], [doWince=$enableval], [doWince=no]) AC_MSG_RESULT([$doWince]) fi # Step 1: set the variable "system" to hold the name and version number # for the system. TEA_CONFIG_SYSTEM # Step 2: check for existence of -ldl library. This is needed because # Linux can use either -ldl or -ldld for dynamic loading. AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no) # Require ranlib early so we can override it in special cases below. AC_REQUIRE([AC_PROG_RANLIB]) # Step 3: 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. do64bit_ok=no LDFLAGS_ORIG="$LDFLAGS" # 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="" TCL_EXPORT_FILE_SUFFIX="" UNSHARED_LIB_SUFFIX="" TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ECHO_VERSION='`echo ${PACKAGE_VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g CFLAGS_OPTIMIZE=-O if test "$GCC" = "yes" ; then CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall -Wno-implicit-int" else CFLAGS_WARNING="" fi TCL_NEEDS_EXP_FILE=0 TCL_BUILD_EXP_FILE="" TCL_EXP_FILE="" dnl FIXME: Replace AC_CHECK_PROG with AC_CHECK_TOOL once cross compiling is fixed. dnl AC_CHECK_TOOL(AR, ar) AC_CHECK_PROG(AR, ar, ar) STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" case $system in 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 ! -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 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="-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="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" LINKBIN="\"${CEBINROOT}/link.exe\"" AC_SUBST(CELIB_DIR) else RC="rc" 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 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}" 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 # This essentially turns it all on. LDFLAGS_DEBUG="-debug:full -debugtype:both -warn:2" 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_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".dll" SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' TCL_LIB_VERSIONS_OK=nodots # Bogus to avoid getting this turned off DL_OBJS="tclLoadNone.obj" ;; 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) # ok ... ;; *) CC=${CC}_r ;; esac AC_MSG_RESULT([Using $CC for compiling with threads]) fi LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" LD_LIBRARY_PATH_VAR="LIBPATH" # Check to enable 64-bit flags for compiler/linker on AIX 4+ if test "$do64bit" = "yes" -a "`uname -v`" -gt "3" ; then if test "$GCC" = "yes" ; then AC_MSG_WARN([64bit mode not supported with GCC on $system]) 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" # AIX-5 has dl* in libc.so DL_LIBS="" 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="gcc -shared" else SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry" fi SHLIB_LD="${TCL_SRC_DIR}/unix/ldAix ${SHLIB_LD} ${SHLIB_LD_FLAGS}" DL_LIBS="-ldl" CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} TCL_NEEDS_EXP_FILE=1 TCL_EXPORT_FILE_SUFFIX='${PACKAGE_VERSION}.exp' fi # AIX v<=4.1 has some different flags than 4.2+ if test "$system" = "AIX-4.1" -o "`uname -v`" -lt "4" ; then AC_LIBOBJ([tclLoadAix]) DL_LIBS="-lld" fi # On AIX <=v4 systems, libbsd.a has to be linked in to support # non-blocking file IO. This library has to be linked in after # the MATH_LIBS or it breaks the pow() function. The way to # insure proper sequencing, is to add it to the tail of MATH_LIBS. # This library also supplies gettimeofday. # # AIX does not have a timezone field in struct tm. When the AIX # bsd library is used, the timezone global and the gettimeofday # methods are to be avoided for timezone deduction instead, we # deduce the timezone by comparing the localtime result on a # known GMT value. AC_CHECK_LIB(bsd, gettimeofday, libbsd=yes, libbsd=no) if test $libbsd = yes; then MATH_LIBS="$MATH_LIBS -lbsd" AC_DEFINE(USE_DELTA_FOR_TZ, 1, [Do we need a special AIX hack for timezones?]) fi ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD="${CC} -nostart" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" #----------------------------------------------------------- # 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-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD="cc -shared" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; HP-UX-*.11.*) # Use updated header definitions where possible AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?]) # 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 SHLIB_SUFFIX=".sl" AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = yes; then SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS='${LIBS}' DL_OBJS="tclLoadShl.o" DL_LIBS="-ldld" 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="gcc -shared" SHLIB_LD_LIBS='${LIBS}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} fi # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc #CFLAGS="$CFLAGS +DAportable" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes" ; then if test "$GCC" = "yes" ; then hpux_arch=`${CC} -dumpmachine` case $hpux_arch in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD="${CC} -shared" SHLIB_LD_LIBS='${LIBS}' 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 else do64bit_ok=yes CFLAGS="$CFLAGS +DD64" LDFLAGS_ARCH="+DD64" fi fi ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = yes; then SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" DL_OBJS="tclLoadShl.o" DL_LIBS="-ldld" 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 ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' 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_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes" ; then if test "$GCC" = "yes" ; then AC_MSG_WARN([64bit mode not supported by gcc]) else do64bit_ok=yes SHLIB_LD="ld -64 -shared -rdata_shared" CFLAGS="$CFLAGS -64" LDFLAGS_ARCH="-64" fi fi ;; Linux*) SHLIB_CFLAGS="-fPIC" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings # when you inline the string and math operations. Turn this off to # get rid of the warnings. #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES" SHLIB_LD="${CC} -shared" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,--export-dynamic" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "`uname -m`" = "alpha" ; then CFLAGS="$CFLAGS -mieee" 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 ;; GNU*) SHLIB_CFLAGS="-fPIC" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" SHLIB_LD="${CC} -shared" DL_OBJS="" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,--export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" if test "`uname -m`" = "alpha" ; then CFLAGS="$CFLAGS -mieee" fi ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD="${CC} -shared " DL_OBJS="tclLoadDl.o" DL_LIBS="-mshared -ldl" LD_FLAGS="-Wl,--export-dynamic" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ;; MP-RAS-02*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; MP-RAS-*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,-Bexport" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; NetBSD-*|FreeBSD-[[1-2]].*) # NetBSD/SPARC needs -fPIC, -fpic will not do. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [ AC_EGREP_CPP(yes, [ #ifdef __ELF__ yes #endif ], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)]) if test $tcl_cv_ld_elf = yes; then SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' else SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0' fi # Ancient FreeBSD doesn't handle version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; OpenBSD-*) # OpenBSD/SPARC[64] needs -fPIC, -fpic will not do. case `machine` in sparc|sparc64) SHLIB_CFLAGS="-fPIC";; *) SHLIB_CFLAGS="-fpic";; esac SHLIB_LD="${CC} -shared ${SHLIB_CFLAGS}" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0' AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [ AC_EGREP_CPP(yes, [ #ifdef __ELF__ yes #endif ], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)]) if test $tcl_cv_ld_elf = yes; then LDFLAGS=-Wl,-export-dynamic else LDFLAGS="" fi # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; FreeBSD-*) # FreeBSD 3.* and greater have ELF. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' 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 case $system in FreeBSD-3.*) # FreeBSD-3 doesn't handle version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' TCL_LIB_VERSIONS_OK=nodots ;; esac ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" SHLIB_CFLAGS="-fno-common" if test $do64bit = yes; then do64bit_ok=yes CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" fi # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS here: 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]) if test $tcl_cv_ld_single_module = yes; then SHLIB_LD="${SHLIB_LD} -Wl,-single_module" fi SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".dylib" DL_OBJS="tclLoadDyld.o" DL_LIBS="" # Don't use -prebind when building for Mac OS X 10.4 or later only: test -z "${MACOSX_DEPLOYMENT_TARGET}" || \ test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F. '{print [$]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]) if test $tcl_cv_ld_search_paths_first = yes; then LDFLAGS="$LDFLAGS -Wl,-search_paths_first" fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" # TEA specific: for Tk extensions, remove -arch ppc64 from CFLAGS # for fat builds, as neither TkAqua nor TkX11 can be built for 64bit # at present (no 64bit GUI libraries). test $do64bit_ok = no && test -n "${TK_BIN_DIR}" && \ CFLAGS="`echo "$CFLAGS" | sed -e 's/-arch ppc64/-arch ppc/g'`" ;; NEXTSTEP-*) SHLIB_CFLAGS="" SHLIB_LD="cc -nostdlib -r" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadNext.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; 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-1.0|OSF1-1.1|OSF1-1.2) # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 SHLIB_CFLAGS="" # Hack: make package name same as library name SHLIB_LD='ld -R -export $@:' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadOSF.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OSF1-1.*) # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 SHLIB_CFLAGS="-fPIC" if test "$SHARED_BUILD" = "1" ; then SHLIB_LD="ld -shared" else SHLIB_LD="ld -non_shared" fi SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; 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_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' 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" DL_OBJS="tclLoadDl.o" # dlopen is in -lc on QNX DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) # Note, dlopen is available only on SCO 3.2.5 and greater. However, # this test works, since "uname -s" was non-standard in 3.2.4 and # below. 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" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SINIX*5.4*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-4*) SHLIB_CFLAGS="-PIC" SHLIB_LD="ld" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # SunOS can't handle version numbers with dots in them in library # specs, like -ltcl7.5, so use -ltcl75 instead. Also, it # requires an extra version number at the end of .so file names. # So, the library has to have a name like libtcl75.so.1.0 SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; 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" # Note: need the LIBS below, otherwise Tk won't find Tcl's # symbols when dynamically loaded into tclsh. SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" 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. 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 if test "$do64bit" = "yes" ; then arch=`isainfo` if test "$arch" = "sparcv9 sparc" ; then if test "$GCC" = "yes" ; then if test "`gcc -dumpversion | awk -F. '{print [$]1}'`" -lt "3" ; then AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system]) 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 elif test "$arch" = "amd64 i386" ; then if test "$GCC" = "yes" ; then AC_MSG_WARN([64bit mode not supported with GCC on $system]) else do64bit_ok=yes CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64" fi else AC_MSG_WARN([64bit mode not supported for $arch]) fi fi # Note: need the LIBS below, otherwise Tk won't find Tcl's # symbols when dynamically loaded into tclsh. SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" 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 # 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" fi else SHLIB_LD="/usr/ccs/bin/ld -G -z text" 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" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" # 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]) 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 AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform]) fi # Step 4: disable dynamic loading if requested via a command-line switch. AC_ARG_ENABLE(load, AC_HELP_STRING([--disable-load], [disallow dynamic loading and "load" command (default: enabled)]), [tcl_ok=$enableval], [tcl_ok=yes]) if test "$tcl_ok" = "no"; then DL_OBJS="" fi if test "x$DL_OBJS" != "x" ; then BUILD_DLTEST="\$(DLTEST_TARGETS)" else echo "Can't figure out how to do dynamic loading or shared libraries" echo "on this system." SHLIB_CFLAGS="" SHLIB_LD="" SHLIB_SUFFIX="" DL_OBJS="tclLoadNone.o" DL_LIBS="" LDFLAGS="$LDFLAGS_ORIG" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" BUILD_DLTEST="" fi 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 "$DL_OBJS" != "tclLoadNone.o" ; then if test "$GCC" = "yes" ; then case $system in AIX-*) ;; BSD/OS*) ;; IRIX*) ;; NetBSD-*|FreeBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; windows) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac fi fi if test "$SHARED_LIB_SUFFIX" = "" ; then SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}' fi if test "$UNSHARED_LIB_SUFFIX" = "" ; then UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a' fi AC_SUBST(DL_LIBS) 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 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 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 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 #include 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 #include 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 #include 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_MISSING_POSIX_HEADERS # # Supply substitutes for missing POSIX header files. Special # notes: # - stdlib.h doesn't define strtol, strtoul, or # strtod insome versions of SunOS # - some versions of string.h don't declare procedures such # as strstr # # Arguments: # none # # Results: # # Defines some of the following vars: # NO_DIRENT_H # NO_ERRNO_H # NO_VALUES_H # HAVE_LIMITS_H or NO_LIMITS_H # NO_STDLIB_H # NO_STRING_H # NO_SYS_WAIT_H # NO_DLFCN_H # HAVE_SYS_PARAM_H # # HAVE_STRING_H ? # # tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and # CHECK on limits.h #-------------------------------------------------------------------- AC_DEFUN([TEA_MISSING_POSIX_HEADERS], [ AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, AC_TRY_LINK([#include #include ], [ #ifndef _POSIX_SOURCE # ifdef __Lynx__ /* * Generate compilation error to make the test fail: Lynx headers * are only valid if really in the POSIX environment. */ missing_procedure(); # endif #endif DIR *d; struct dirent *entryPtr; char *p; d = opendir("foobar"); entryPtr = readdir(d); p = entryPtr->d_name; closedir(d); ], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)) if test $tcl_cv_dirent_h = no; then AC_DEFINE(NO_DIRENT_H, 1, [Do we have ?]) fi AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have ?])]) AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have ?])]) AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have ?])]) AC_CHECK_HEADER(limits.h, [AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have ?])], [AC_DEFINE(NO_LIMITS_H, 1, [Do we have ?])]) AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0) AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0) AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0) AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0) if test $tcl_ok = 0; then AC_DEFINE(NO_STDLIB_H, 1, [Do we have ?]) fi AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0) AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0) AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0) # See also memmove check below for a place where NO_STRING_H can be # set and why. if test $tcl_ok = 0; then AC_DEFINE(NO_STRING_H, 1, [Do we have ?]) fi AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have ?])]) AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have ?])]) # OS/390 lacks sys/param.h (and doesn't need it, by chance). AC_HAVE_HEADERS(sys/param.h) ]) #-------------------------------------------------------------------- # 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 ], , not_really_there="yes") else if test ! -r $x_includes/X11/Intrinsic.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 ], 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/Intrinsic.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; 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 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 # There used to be code here to use FIONBIO under AIX. However, it # was reported that FIONBIO doesn't work under AIX 3.2.5. Since # using O_NONBLOCK seems fine under AIX 4.*, I removed the FIONBIO # code (JO, 5/31/97). OSF*) AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) AC_MSG_RESULT([FIONBIO]) ;; SunOS-4*) AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) AC_MSG_RESULT([FIONBIO]) ;; *) AC_MSG_RESULT([O_NONBLOCK]) ;; esac ]) #-------------------------------------------------------------------- # TEA_TIME_HANLDER # # 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 ], [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 ], [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 ], [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 ], [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_LINK_LIBS # # Search for the libraries needed to link the Tcl shell. # Things like the math library (-lm) and socket stuff (-lsocket vs. # -lnsl) are dealt with here. # # Arguments: # Requires the following vars to be set in the Makefile: # DL_LIBS # LIBS # MATH_LIBS # # Results: # # Subst's the following var: # TCL_LIBS # MATH_LIBS # # Might append to the following vars: # LIBS # # Might define the following vars: # HAVE_NET_ERRNO_H # #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_LINK_LIBS], [ #-------------------------------------------------------------------- # On a few very rare systems, all of the libm.a stuff is # already in libc.a. Set compiler flags accordingly. # Also, Linux requires the "ieee" library for math to work # right (and it must appear before "-lm"). #-------------------------------------------------------------------- AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm") AC_CHECK_LIB(ieee, main, [MATH_LIBS="-lieee $MATH_LIBS"]) #-------------------------------------------------------------------- # Interactive UNIX requires -linet instead of -lsocket, plus it # needs net/errno.h to define the socket-related error codes. #-------------------------------------------------------------------- AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"]) AC_CHECK_HEADER(net/errno.h, [ AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have ?])]) #-------------------------------------------------------------------- # Check for the existence of the -lsocket and -lnsl libraries. # The order here is important, so that they end up in the right # order in the command line generated by make. Here are some # special considerations: # 1. Use "connect" and "accept" to check for -lsocket, and # "gethostbyname" to check for -lnsl. # 2. Use each function name only once: can't redo a check because # autoconf caches the results of the last check and won't redo it. # 3. Use -lnsl and -lsocket only if they supply procedures that # aren't already present in the normal libraries. This is because # IRIX 5.2 has libraries, but they aren't needed and they're # bogus: they goof up name resolution if used. # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. # To get around this problem, check for both libraries together # if -lsocket doesn't work by itself. #-------------------------------------------------------------------- tcl_checkBoth=0 AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1) if test "$tcl_checkSocket" = 1; then AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt, LIBS="$LIBS -lsocket", tcl_checkBoth=1)]) fi if test "$tcl_checkBoth" = 1; then tk_oldLibs=$LIBS LIBS="$LIBS -lsocket -lnsl" AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs]) fi AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname, [LIBS="$LIBS -lnsl"])]) # Don't perform the eval of the libraries here because DL_LIBS # won't be set until we call TEA_CONFIG_CFLAGS TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}' AC_SUBST(TCL_LIBS) AC_SUBST(MATH_LIBS) ]) #-------------------------------------------------------------------- # 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 ], [char *p = (char *)strtoll; char *q = (char *)strtoull;]) TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include ], [struct stat64 buf; int i = stat64("/", &buf);]) TEA_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include ], [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 # 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 #include ],[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 ?]) fi AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ AC_TRY_COMPILE([#include ],[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 ?]) fi AC_CHECK_FUNCS(open64 lseek64) AC_MSG_CHECKING([for off64_t]) AC_CACHE_VAL(tcl_cv_type_off64_t,[ AC_TRY_COMPILE([#include ],[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 ?]) 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 extensions pass this us the version of TEA they think they # are compatible with. TEA_VERSION="3.5" AC_MSG_CHECKING([for correct TEA configuration]) if test x"${PACKAGE_NAME}" = x ; then AC_MSG_ERROR([ The PACKAGE_NAME variable must be defined by your TEA configure.in]) fi if test x"$1" = x ; then AC_MSG_ERROR([ TEA version not specified.]) elif test "$1" != "${TEA_VERSION}" ; then AC_MSG_RESULT([warning: requested TEA version "$1", have "${TEA_VERSION}"]) else AC_MSG_RESULT([ok (TEA ${TEA_VERSION})]) fi case "`uname -s`" in *win32*|*WIN32*|*CYGWIN_NT*|*CYGWIN_9*|*CYGWIN_ME*|*MINGW32_*) AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *) CYGPATH=echo EXEEXT="" TEA_PLATFORM="unix" ;; 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_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) ]) #------------------------------------------------------------------------ # 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 if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$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" \ ; 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_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.in 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. # If the user did not set CFLAGS, set it now to keep # the AC_PROG_CC macro from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi AC_PROG_CC AC_PROG_CPP AC_PROG_INSTALL #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- AC_PROG_MAKE_SET #-------------------------------------------------------------------- # Find ranlib #-------------------------------------------------------------------- AC_PROG_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_MSG_CHECKING([if the compiler understands -pipe]) OLDCC="$CC" CC="$CC -pipe" AC_TRY_COMPILE(,, AC_MSG_RESULT([yes]), CC="$OLDCC" AC_MSG_RESULT([no])) fi #-------------------------------------------------------------------- # Common compiler flag setup #-------------------------------------------------------------------- AC_C_BIGENDIAN if test "${TEA_PLATFORM}" = "unix" ; then TEA_TCL_LINK_LIBS TEA_MISSING_POSIX_HEADERS # Let the user call this, because if it triggers, they will # need a compat/strtod.c that is correct. Users can also # use Tcl_GetDouble(FromObj) instead. #TEA_BUGGY_STRTOD fi ]) #------------------------------------------------------------------------ # 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 #------------------------------------------------------------------------ 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)" MAKE_STUB_LIB="\${STLIB_LD} -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. SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" fi eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" else eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries eval eval "PKG_STUB_LIB_FILE=${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_NAME}${SHARED_LIB_SUFFIX}" RANLIB=: else eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries eval eval "PKG_STUB_LIB_FILE=lib${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) ]) #------------------------------------------------------------------------ # 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/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: # # Substs the following vars: # TCL_TOP_DIR_NATIVE # TCL_GENERIC_DIR_NATIVE # TCL_UNIX_DIR_NATIVE # TCL_WIN_DIR_NATIVE # TCL_BMAP_DIR_NATIVE # TCL_TOOL_DIR_NATIVE # TCL_PLATFORM_DIR_NATIVE # TCL_BIN_DIR_NATIVE # TCL_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PRIVATE_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}\" TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" TCL_UNIX_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" TCL_WIN_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" TCL_BMAP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/bitmaps\" TCL_TOOL_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/tools\" TCL_COMPAT_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/compat\" if test "${TEA_PLATFORM}" = "windows"; then TCL_PLATFORM_DIR_NATIVE=${TCL_WIN_DIR_NATIVE} else TCL_PLATFORM_DIR_NATIVE=${TCL_UNIX_DIR_NATIVE} fi # 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 fi AC_SUBST(TCL_TOP_DIR_NATIVE) AC_SUBST(TCL_GENERIC_DIR_NATIVE) AC_SUBST(TCL_UNIX_DIR_NATIVE) AC_SUBST(TCL_WIN_DIR_NATIVE) AC_SUBST(TCL_BMAP_DIR_NATIVE) AC_SUBST(TCL_TOOL_DIR_NATIVE) AC_SUBST(TCL_PLATFORM_DIR_NATIVE) AC_SUBST(TCL_INCLUDES) AC_MSG_RESULT([Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}]) ]) #------------------------------------------------------------------------ # 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. # # Substs 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 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: # # Substs the following vars: # TK_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PRIVATE_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}\" TK_UNIX_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\" TK_WIN_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\" 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_WIN_DIR_NATIVE} else TK_PLATFORM_DIR_NATIVE=${TK_UNIX_DIR_NATIVE} fi # 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}" if test "${TEA_WINDOWINGSYSTEM}" = "win32" \ -o "${TEA_WINDOWINGSYSTEM}" = "aqua"; 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}"; fi ;; esac fi AC_SUBST(TK_TOP_DIR_NATIVE) AC_SUBST(TK_UNIX_DIR_NATIVE) AC_SUBST(TK_WIN_DIR_NATIVE) AC_SUBST(TK_GENERIC_DIR_NATIVE) AC_SUBST(TK_XLIB_DIR_NATIVE) AC_SUBST(TK_PLATFORM_DIR_NATIVE) AC_SUBST(TK_INCLUDES) AC_MSG_RESULT([Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}]) ]) #------------------------------------------------------------------------ # 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. # # Substs 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 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" 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}" = "win32" \ -o "${TEA_WINDOWINGSYSTEM}" = "aqua"; 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_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 # Subst's the following values: # 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 TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" 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 # Subst's the following values: # 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 WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" 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_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/lib 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: # # Subst 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} 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) ]) #------------------------------------------------------------------------ # 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 ]) # Local Variables: # mode: autoconf # End: tktreectrl-2.2.8/tclconfig/0000755000175600010010000000000011073207472014066 5ustar TimNonetktreectrl-2.2.8/tclconfig/install-sh0000711000175600010010000000421211073207472016061 0ustar TimNone#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5; it is not part of GNU. # # $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $ # # This script is compatible with the BSD install script, but was written # from scratch. # # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" instcmd="$mvprog" chmodcmd="" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; *) if [ x"$src" = x ] then src=$1 else dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` fi # Make a temp file name in the proper directory. dstdir=`dirname $dst` dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp # and set any options; do chmod last to preserve setuid bits if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi # Now rename the file to the real destination. $doit $rmcmd $dst $doit $mvcmd $dsttmp $dst exit 0 tktreectrl-2.2.8/tclconfig/tcl.m40000664000175600010010000036211311073207472015122 0ustar TimNone# 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. # # RCS: @(#) $Id: tcl.m4,v 1.8 2006/04/06 00:30:08 hobbs2 Exp $ AC_PREREQ(2.50) dnl TEA extensions pass this us the version of TEA they think they dnl are compatible with (must be set in TEA_INIT below) dnl TEA_VERSION="3.5" # Possible values for key variables defined: # # TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem') # TEA_PLATFORM - windows unix # #------------------------------------------------------------------------ # 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 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 -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` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig=`(cd $i/Tcl.framework; pwd)` break fi done fi # 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/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 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 -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_WARN([Can't find Tcl configuration definitions]) exit 0 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 -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` \ ; 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/lib 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig=`(cd $i; pwd)` break fi done fi # 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 -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_WARN([Can't find Tk configuration definitions]) exit 0 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: # # Subst the following vars: # TCL_BIN_DIR # TCL_SRC_DIR # TCL_LIB_FILE # #------------------------------------------------------------------------ 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 arbitary 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"` -framework ${TCL_LIB_FILE}" break fi done fi if test -f ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}; then TCL_STUB_LIB_SPEC="-L${TCL_BIN_DIR} ${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_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_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 arbitary 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"` -framework ${TK_LIB_FILE}" break fi done fi if test -f ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}; then TK_STUB_LIB_SPEC="-L${TK_BIN_DIR} ${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}\"" # 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) AC_SUBST(TK_LIBS) AC_SUBST(TK_XINCLUDES) ]) #------------------------------------------------------------------------ # TEA_ENABLE_SHARED -- # # Allows the building of shared libraries # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-shared=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 #------------------------------------------------------------------------ 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)]), [tcl_ok=$enableval], [tcl_ok=yes]) if test "${enable_shared+set}" = set; then enableval="$enable_shared" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" ; then AC_MSG_RESULT([shared]) SHARED_BUILD=1 else AC_MSG_RESULT([static]) SHARED_BUILD=0 AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?]) fi AC_SUBST(SHARED_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]), [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 ;; *) if test "${TCL_THREADS}" = "1"; then AC_MSG_WARN([ --enable-threads requested, but building against a Tcl that is NOT thread-enabled. This is an OK configuration that will also run in a thread-enabled core.]) 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) 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 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}" 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 if test "${TEA_PLATFORM}" != "windows" ; then LDFLAGS_DEFAULT="${LDFLAGS}" fi AC_SUBST(TCL_DBGX) AC_SUBST(CFLAGS_DEFAULT) AC_SUBST(LDFLAGS_DEFAULT) 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 ], [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, but there are a few systems, like Next, where # this doesn't work. # # 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, [ if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows elif test -f /usr/lib/NextStep/software_version; then tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` 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 # Special check for weird MP-RAS system (uname returns weird # results, and the version is kept in special file). if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then tcl_cv_sys_version=MP-RAS-`awk '{print $3}' /etc/.relid` fi 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 - Name of the object file that implements dynamic # loading for Tcl on this system. # DL_LIBS - Library file(s) to include in tclsh and other base # applications in order for the "load" command to work. # 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 is # "${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 $VERSION variable # to put the version in the right place. This is used # by platforms that need non-standard library names. # Examples: ${VERSION}.so.1.1 on NetBSD, since it needs # to have a version after the .so, and ${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 # ${VERSION}${SHLIB_SUFFIX}. # TCL_NEEDS_EXP_FILE - # 1 means that an export file is needed to link to a # shared library. # TCL_EXP_FILE - The name of the installed export / import file which # should be used to link to the Tcl shared library. # Empty if Tcl is unshared. # TCL_BUILD_EXP_FILE - # The name of the built export / import file which # should be used to link to the Tcl shared library. # Empty if Tcl is unshared. # 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 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]) if test "$do64bitVIS" = "yes"; then # Force 64bit on with VIS do64bit=yes fi # Step 0.c: Cross-compiling options for Windows/CE builds? if test "${TEA_PLATFORM}" = "windows" ; then AC_MSG_CHECKING([if Windows/CE build is requested]) AC_ARG_ENABLE(wince,[ --enable-wince enable Win/CE support (where applicable)], [doWince=$enableval], [doWince=no]) AC_MSG_RESULT([$doWince]) fi # Step 1: set the variable "system" to hold the name and version number # for the system. TEA_CONFIG_SYSTEM # Step 2: check for existence of -ldl library. This is needed because # Linux can use either -ldl or -ldld for dynamic loading. AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no) # Require ranlib early so we can override it in special cases below. AC_REQUIRE([AC_PROG_RANLIB]) # Step 3: 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. do64bit_ok=no LDFLAGS_ORIG="$LDFLAGS" # 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="" TCL_EXPORT_FILE_SUFFIX="" UNSHARED_LIB_SUFFIX="" TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ECHO_VERSION='`echo ${PACKAGE_VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g CFLAGS_OPTIMIZE=-O if test "$GCC" = "yes" ; then CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall -Wno-implicit-int" else CFLAGS_WARNING="" fi TCL_NEEDS_EXP_FILE=0 TCL_BUILD_EXP_FILE="" TCL_EXP_FILE="" dnl FIXME: Replace AC_CHECK_PROG with AC_CHECK_TOOL once cross compiling is fixed. dnl AC_CHECK_TOOL(AR, ar) AC_CHECK_PROG(AR, ar, ar) STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" case $system in 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 ! -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 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="-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="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" LINKBIN="\"${CEBINROOT}/link.exe\"" AC_SUBST(CELIB_DIR) else RC="rc" 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 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}" 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 # This essentially turns it all on. LDFLAGS_DEBUG="-debug:full -debugtype:both -warn:2" 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_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".dll" SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' TCL_LIB_VERSIONS_OK=nodots # Bogus to avoid getting this turned off DL_OBJS="tclLoadNone.obj" ;; 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) # ok ... ;; *) CC=${CC}_r ;; esac AC_MSG_RESULT([Using $CC for compiling with threads]) fi LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" LD_LIBRARY_PATH_VAR="LIBPATH" # Check to enable 64-bit flags for compiler/linker on AIX 4+ if test "$do64bit" = "yes" -a "`uname -v`" -gt "3" ; then if test "$GCC" = "yes" ; then AC_MSG_WARN([64bit mode not supported with GCC on $system]) 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" # AIX-5 has dl* in libc.so DL_LIBS="" 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="gcc -shared" else SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry" fi SHLIB_LD="${TCL_SRC_DIR}/unix/ldAix ${SHLIB_LD} ${SHLIB_LD_FLAGS}" DL_LIBS="-ldl" CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} TCL_NEEDS_EXP_FILE=1 TCL_EXPORT_FILE_SUFFIX='${PACKAGE_VERSION}.exp' fi # AIX v<=4.1 has some different flags than 4.2+ if test "$system" = "AIX-4.1" -o "`uname -v`" -lt "4" ; then AC_LIBOBJ([tclLoadAix]) DL_LIBS="-lld" fi # On AIX <=v4 systems, libbsd.a has to be linked in to support # non-blocking file IO. This library has to be linked in after # the MATH_LIBS or it breaks the pow() function. The way to # insure proper sequencing, is to add it to the tail of MATH_LIBS. # This library also supplies gettimeofday. # # AIX does not have a timezone field in struct tm. When the AIX # bsd library is used, the timezone global and the gettimeofday # methods are to be avoided for timezone deduction instead, we # deduce the timezone by comparing the localtime result on a # known GMT value. AC_CHECK_LIB(bsd, gettimeofday, libbsd=yes, libbsd=no) if test $libbsd = yes; then MATH_LIBS="$MATH_LIBS -lbsd" AC_DEFINE(USE_DELTA_FOR_TZ, 1, [Do we need a special AIX hack for timezones?]) fi ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD="${CC} -nostart" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" #----------------------------------------------------------- # 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-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD="cc -shared" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; HP-UX-*.11.*) # Use updated header definitions where possible AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?]) # 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 SHLIB_SUFFIX=".sl" AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = yes; then SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS='${LIBS}' DL_OBJS="tclLoadShl.o" DL_LIBS="-ldld" 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="gcc -shared" SHLIB_LD_LIBS='${LIBS}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} fi # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc #CFLAGS="$CFLAGS +DAportable" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes" ; then if test "$GCC" = "yes" ; then hpux_arch=`${CC} -dumpmachine` case $hpux_arch in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD="${CC} -shared" SHLIB_LD_LIBS='${LIBS}' 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 else do64bit_ok=yes CFLAGS="$CFLAGS +DD64" LDFLAGS_ARCH="+DD64" fi fi ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = yes; then SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" DL_OBJS="tclLoadShl.o" DL_LIBS="-ldld" 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 ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' 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_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes" ; then if test "$GCC" = "yes" ; then AC_MSG_WARN([64bit mode not supported by gcc]) else do64bit_ok=yes SHLIB_LD="ld -64 -shared -rdata_shared" CFLAGS="$CFLAGS -64" LDFLAGS_ARCH="-64" fi fi ;; Linux*) SHLIB_CFLAGS="-fPIC" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings # when you inline the string and math operations. Turn this off to # get rid of the warnings. #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES" SHLIB_LD="${CC} -shared" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,--export-dynamic" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "`uname -m`" = "alpha" ; then CFLAGS="$CFLAGS -mieee" 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 ;; GNU*) SHLIB_CFLAGS="-fPIC" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" SHLIB_LD="${CC} -shared" DL_OBJS="" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,--export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" if test "`uname -m`" = "alpha" ; then CFLAGS="$CFLAGS -mieee" fi ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD="${CC} -shared " DL_OBJS="tclLoadDl.o" DL_LIBS="-mshared -ldl" LD_FLAGS="-Wl,--export-dynamic" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ;; MP-RAS-02*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; MP-RAS-*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,-Bexport" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; NetBSD-*|FreeBSD-[[1-2]].*) # NetBSD/SPARC needs -fPIC, -fpic will not do. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [ AC_EGREP_CPP(yes, [ #ifdef __ELF__ yes #endif ], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)]) if test $tcl_cv_ld_elf = yes; then SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' else SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0' fi # Ancient FreeBSD doesn't handle version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; OpenBSD-*) # OpenBSD/SPARC[64] needs -fPIC, -fpic will not do. case `machine` in sparc|sparc64) SHLIB_CFLAGS="-fPIC";; *) SHLIB_CFLAGS="-fpic";; esac SHLIB_LD="${CC} -shared ${SHLIB_CFLAGS}" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0' AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [ AC_EGREP_CPP(yes, [ #ifdef __ELF__ yes #endif ], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)]) if test $tcl_cv_ld_elf = yes; then LDFLAGS=-Wl,-export-dynamic else LDFLAGS="" fi # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; FreeBSD-*) # FreeBSD 3.* and greater have ELF. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' 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 case $system in FreeBSD-3.*) # FreeBSD-3 doesn't handle version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' TCL_LIB_VERSIONS_OK=nodots ;; esac ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" SHLIB_CFLAGS="-fno-common" if test $do64bit = yes; then do64bit_ok=yes CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" fi # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS here: 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]) if test $tcl_cv_ld_single_module = yes; then SHLIB_LD="${SHLIB_LD} -Wl,-single_module" fi SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".dylib" DL_OBJS="tclLoadDyld.o" DL_LIBS="" # Don't use -prebind when building for Mac OS X 10.4 or later only: test -z "${MACOSX_DEPLOYMENT_TARGET}" || \ test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F. '{print [$]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]) if test $tcl_cv_ld_search_paths_first = yes; then LDFLAGS="$LDFLAGS -Wl,-search_paths_first" fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" # TEA specific: for Tk extensions, remove -arch ppc64 from CFLAGS # for fat builds, as neither TkAqua nor TkX11 can be built for 64bit # at present (no 64bit GUI libraries). test $do64bit_ok = no && test -n "${TK_BIN_DIR}" && \ CFLAGS="`echo "$CFLAGS" | sed -e 's/-arch ppc64/-arch ppc/g'`" ;; NEXTSTEP-*) SHLIB_CFLAGS="" SHLIB_LD="cc -nostdlib -r" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadNext.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; 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-1.0|OSF1-1.1|OSF1-1.2) # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 SHLIB_CFLAGS="" # Hack: make package name same as library name SHLIB_LD='ld -R -export $@:' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadOSF.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OSF1-1.*) # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 SHLIB_CFLAGS="-fPIC" if test "$SHARED_BUILD" = "1" ; then SHLIB_LD="ld -shared" else SHLIB_LD="ld -non_shared" fi SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; 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_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' 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" DL_OBJS="tclLoadDl.o" # dlopen is in -lc on QNX DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) # Note, dlopen is available only on SCO 3.2.5 and greater. However, # this test works, since "uname -s" was non-standard in 3.2.4 and # below. 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" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SINIX*5.4*) SHLIB_CFLAGS="-K PIC" SHLIB_LD="cc -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-4*) SHLIB_CFLAGS="-PIC" SHLIB_LD="ld" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # SunOS can't handle version numbers with dots in them in library # specs, like -ltcl7.5, so use -ltcl75 instead. Also, it # requires an extra version number at the end of .so file names. # So, the library has to have a name like libtcl75.so.1.0 SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; 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" # Note: need the LIBS below, otherwise Tk won't find Tcl's # symbols when dynamically loaded into tclsh. SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" 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. 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 if test "$do64bit" = "yes" ; then arch=`isainfo` if test "$arch" = "sparcv9 sparc" ; then if test "$GCC" = "yes" ; then if test "`gcc -dumpversion | awk -F. '{print [$]1}'`" -lt "3" ; then AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system]) 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 elif test "$arch" = "amd64 i386" ; then if test "$GCC" = "yes" ; then AC_MSG_WARN([64bit mode not supported with GCC on $system]) else do64bit_ok=yes CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64" fi else AC_MSG_WARN([64bit mode not supported for $arch]) fi fi # Note: need the LIBS below, otherwise Tk won't find Tcl's # symbols when dynamically loaded into tclsh. SHLIB_LD_LIBS='${LIBS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" 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 # 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" fi else SHLIB_LD="/usr/ccs/bin/ld -G -z text" 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" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" # 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]) 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 AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform]) fi # Step 4: disable dynamic loading if requested via a command-line switch. AC_ARG_ENABLE(load, AC_HELP_STRING([--disable-load], [disallow dynamic loading and "load" command (default: enabled)]), [tcl_ok=$enableval], [tcl_ok=yes]) if test "$tcl_ok" = "no"; then DL_OBJS="" fi if test "x$DL_OBJS" != "x" ; then BUILD_DLTEST="\$(DLTEST_TARGETS)" else echo "Can't figure out how to do dynamic loading or shared libraries" echo "on this system." SHLIB_CFLAGS="" SHLIB_LD="" SHLIB_SUFFIX="" DL_OBJS="tclLoadNone.o" DL_LIBS="" LDFLAGS="$LDFLAGS_ORIG" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" BUILD_DLTEST="" fi 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 "$DL_OBJS" != "tclLoadNone.o" ; then if test "$GCC" = "yes" ; then case $system in AIX-*) ;; BSD/OS*) ;; IRIX*) ;; NetBSD-*|FreeBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; windows) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac fi fi if test "$SHARED_LIB_SUFFIX" = "" ; then SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}' fi if test "$UNSHARED_LIB_SUFFIX" = "" ; then UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a' fi AC_SUBST(DL_LIBS) 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 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 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 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 #include 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 #include 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 #include 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_MISSING_POSIX_HEADERS # # Supply substitutes for missing POSIX header files. Special # notes: # - stdlib.h doesn't define strtol, strtoul, or # strtod insome versions of SunOS # - some versions of string.h don't declare procedures such # as strstr # # Arguments: # none # # Results: # # Defines some of the following vars: # NO_DIRENT_H # NO_ERRNO_H # NO_VALUES_H # HAVE_LIMITS_H or NO_LIMITS_H # NO_STDLIB_H # NO_STRING_H # NO_SYS_WAIT_H # NO_DLFCN_H # HAVE_SYS_PARAM_H # # HAVE_STRING_H ? # # tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and # CHECK on limits.h #-------------------------------------------------------------------- AC_DEFUN([TEA_MISSING_POSIX_HEADERS], [ AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, AC_TRY_LINK([#include #include ], [ #ifndef _POSIX_SOURCE # ifdef __Lynx__ /* * Generate compilation error to make the test fail: Lynx headers * are only valid if really in the POSIX environment. */ missing_procedure(); # endif #endif DIR *d; struct dirent *entryPtr; char *p; d = opendir("foobar"); entryPtr = readdir(d); p = entryPtr->d_name; closedir(d); ], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)) if test $tcl_cv_dirent_h = no; then AC_DEFINE(NO_DIRENT_H, 1, [Do we have ?]) fi AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have ?])]) AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have ?])]) AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have ?])]) AC_CHECK_HEADER(limits.h, [AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have ?])], [AC_DEFINE(NO_LIMITS_H, 1, [Do we have ?])]) AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0) AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0) AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0) AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0) if test $tcl_ok = 0; then AC_DEFINE(NO_STDLIB_H, 1, [Do we have ?]) fi AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0) AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0) AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0) # See also memmove check below for a place where NO_STRING_H can be # set and why. if test $tcl_ok = 0; then AC_DEFINE(NO_STRING_H, 1, [Do we have ?]) fi AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have ?])]) AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have ?])]) # OS/390 lacks sys/param.h (and doesn't need it, by chance). AC_HAVE_HEADERS(sys/param.h) ]) #-------------------------------------------------------------------- # 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 ], , not_really_there="yes") else if test ! -r $x_includes/X11/Intrinsic.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 ], 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/Intrinsic.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; 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 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 # There used to be code here to use FIONBIO under AIX. However, it # was reported that FIONBIO doesn't work under AIX 3.2.5. Since # using O_NONBLOCK seems fine under AIX 4.*, I removed the FIONBIO # code (JO, 5/31/97). OSF*) AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) AC_MSG_RESULT([FIONBIO]) ;; SunOS-4*) AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) AC_MSG_RESULT([FIONBIO]) ;; *) AC_MSG_RESULT([O_NONBLOCK]) ;; esac ]) #-------------------------------------------------------------------- # TEA_TIME_HANLDER # # 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 ], [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 ], [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 ], [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 ], [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_LINK_LIBS # # Search for the libraries needed to link the Tcl shell. # Things like the math library (-lm) and socket stuff (-lsocket vs. # -lnsl) are dealt with here. # # Arguments: # Requires the following vars to be set in the Makefile: # DL_LIBS # LIBS # MATH_LIBS # # Results: # # Subst's the following var: # TCL_LIBS # MATH_LIBS # # Might append to the following vars: # LIBS # # Might define the following vars: # HAVE_NET_ERRNO_H # #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_LINK_LIBS], [ #-------------------------------------------------------------------- # On a few very rare systems, all of the libm.a stuff is # already in libc.a. Set compiler flags accordingly. # Also, Linux requires the "ieee" library for math to work # right (and it must appear before "-lm"). #-------------------------------------------------------------------- AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm") AC_CHECK_LIB(ieee, main, [MATH_LIBS="-lieee $MATH_LIBS"]) #-------------------------------------------------------------------- # Interactive UNIX requires -linet instead of -lsocket, plus it # needs net/errno.h to define the socket-related error codes. #-------------------------------------------------------------------- AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"]) AC_CHECK_HEADER(net/errno.h, [ AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have ?])]) #-------------------------------------------------------------------- # Check for the existence of the -lsocket and -lnsl libraries. # The order here is important, so that they end up in the right # order in the command line generated by make. Here are some # special considerations: # 1. Use "connect" and "accept" to check for -lsocket, and # "gethostbyname" to check for -lnsl. # 2. Use each function name only once: can't redo a check because # autoconf caches the results of the last check and won't redo it. # 3. Use -lnsl and -lsocket only if they supply procedures that # aren't already present in the normal libraries. This is because # IRIX 5.2 has libraries, but they aren't needed and they're # bogus: they goof up name resolution if used. # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. # To get around this problem, check for both libraries together # if -lsocket doesn't work by itself. #-------------------------------------------------------------------- tcl_checkBoth=0 AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1) if test "$tcl_checkSocket" = 1; then AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt, LIBS="$LIBS -lsocket", tcl_checkBoth=1)]) fi if test "$tcl_checkBoth" = 1; then tk_oldLibs=$LIBS LIBS="$LIBS -lsocket -lnsl" AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs]) fi AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname, [LIBS="$LIBS -lnsl"])]) # Don't perform the eval of the libraries here because DL_LIBS # won't be set until we call TEA_CONFIG_CFLAGS TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}' AC_SUBST(TCL_LIBS) AC_SUBST(MATH_LIBS) ]) #-------------------------------------------------------------------- # 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 ], [char *p = (char *)strtoll; char *q = (char *)strtoull;]) TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include ], [struct stat64 buf; int i = stat64("/", &buf);]) TEA_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include ], [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 # 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 #include ],[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 ?]) fi AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ AC_TRY_COMPILE([#include ],[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 ?]) fi AC_CHECK_FUNCS(open64 lseek64) AC_MSG_CHECKING([for off64_t]) AC_CACHE_VAL(tcl_cv_type_off64_t,[ AC_TRY_COMPILE([#include ],[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 ?]) 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 extensions pass this us the version of TEA they think they # are compatible with. TEA_VERSION="3.5" AC_MSG_CHECKING([for correct TEA configuration]) if test x"${PACKAGE_NAME}" = x ; then AC_MSG_ERROR([ The PACKAGE_NAME variable must be defined by your TEA configure.in]) fi if test x"$1" = x ; then AC_MSG_ERROR([ TEA version not specified.]) elif test "$1" != "${TEA_VERSION}" ; then AC_MSG_RESULT([warning: requested TEA version "$1", have "${TEA_VERSION}"]) else AC_MSG_RESULT([ok (TEA ${TEA_VERSION})]) fi case "`uname -s`" in *win32*|*WIN32*|*CYGWIN_NT*|*CYGWIN_9*|*CYGWIN_ME*|*MINGW32_*) AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *) CYGPATH=echo EXEEXT="" TEA_PLATFORM="unix" ;; 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_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) ]) #------------------------------------------------------------------------ # 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 if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$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" \ ; 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_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.in 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. # If the user did not set CFLAGS, set it now to keep # the AC_PROG_CC macro from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi AC_PROG_CC AC_PROG_CPP AC_PROG_INSTALL #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- AC_PROG_MAKE_SET #-------------------------------------------------------------------- # Find ranlib #-------------------------------------------------------------------- AC_PROG_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_MSG_CHECKING([if the compiler understands -pipe]) OLDCC="$CC" CC="$CC -pipe" AC_TRY_COMPILE(,, AC_MSG_RESULT([yes]), CC="$OLDCC" AC_MSG_RESULT([no])) fi #-------------------------------------------------------------------- # Common compiler flag setup #-------------------------------------------------------------------- AC_C_BIGENDIAN if test "${TEA_PLATFORM}" = "unix" ; then TEA_TCL_LINK_LIBS TEA_MISSING_POSIX_HEADERS # Let the user call this, because if it triggers, they will # need a compat/strtod.c that is correct. Users can also # use Tcl_GetDouble(FromObj) instead. #TEA_BUGGY_STRTOD fi ]) #------------------------------------------------------------------------ # 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 #------------------------------------------------------------------------ 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)" MAKE_STUB_LIB="\${STLIB_LD} -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. SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" fi eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" else eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries eval eval "PKG_STUB_LIB_FILE=${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_NAME}${SHARED_LIB_SUFFIX}" RANLIB=: else eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries eval eval "PKG_STUB_LIB_FILE=lib${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) ]) #------------------------------------------------------------------------ # 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/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: # # Substs the following vars: # TCL_TOP_DIR_NATIVE # TCL_GENERIC_DIR_NATIVE # TCL_UNIX_DIR_NATIVE # TCL_WIN_DIR_NATIVE # TCL_BMAP_DIR_NATIVE # TCL_TOOL_DIR_NATIVE # TCL_PLATFORM_DIR_NATIVE # TCL_BIN_DIR_NATIVE # TCL_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PRIVATE_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}\" TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" TCL_UNIX_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" TCL_WIN_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" TCL_BMAP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/bitmaps\" TCL_TOOL_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/tools\" TCL_COMPAT_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/compat\" if test "${TEA_PLATFORM}" = "windows"; then TCL_PLATFORM_DIR_NATIVE=${TCL_WIN_DIR_NATIVE} else TCL_PLATFORM_DIR_NATIVE=${TCL_UNIX_DIR_NATIVE} fi # 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 fi AC_SUBST(TCL_TOP_DIR_NATIVE) AC_SUBST(TCL_GENERIC_DIR_NATIVE) AC_SUBST(TCL_UNIX_DIR_NATIVE) AC_SUBST(TCL_WIN_DIR_NATIVE) AC_SUBST(TCL_BMAP_DIR_NATIVE) AC_SUBST(TCL_TOOL_DIR_NATIVE) AC_SUBST(TCL_PLATFORM_DIR_NATIVE) AC_SUBST(TCL_INCLUDES) AC_MSG_RESULT([Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}]) ]) #------------------------------------------------------------------------ # 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. # # Substs 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 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: # # Substs the following vars: # TK_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PRIVATE_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}\" TK_UNIX_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\" TK_WIN_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\" 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_WIN_DIR_NATIVE} else TK_PLATFORM_DIR_NATIVE=${TK_UNIX_DIR_NATIVE} fi # 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}" if test "${TEA_WINDOWINGSYSTEM}" = "win32" \ -o "${TEA_WINDOWINGSYSTEM}" = "aqua"; 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}"; fi ;; esac fi AC_SUBST(TK_TOP_DIR_NATIVE) AC_SUBST(TK_UNIX_DIR_NATIVE) AC_SUBST(TK_WIN_DIR_NATIVE) AC_SUBST(TK_GENERIC_DIR_NATIVE) AC_SUBST(TK_XLIB_DIR_NATIVE) AC_SUBST(TK_PLATFORM_DIR_NATIVE) AC_SUBST(TK_INCLUDES) AC_MSG_RESULT([Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}]) ]) #------------------------------------------------------------------------ # 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. # # Substs 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 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" 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}" = "win32" \ -o "${TEA_WINDOWINGSYSTEM}" = "aqua"; 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_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 # Subst's the following values: # 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 TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" 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 # Subst's the following values: # 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 WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" 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_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/lib 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: # # Subst 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} 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) ]) #------------------------------------------------------------------------ # 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 ]) # Local Variables: # mode: autoconf # End: tktreectrl-2.2.8/tests/0000755000175600010010000000000011073207473013261 5ustar TimNonetktreectrl-2.2.8/tests/all.tcl0000700000175600010010000000332110222336354014521 0ustar TimNone# all.tcl -- # # This file contains a top-level script to run all of the Tcl # tests. Execute it by invoking "source all.test" when running tcltest # in this directory. # # Copyright (c) 1998-2000 by Scriptics Corporation. # All rights reserved. # # RCS: @(#) $Id: all.tcl,v 1.4 2005/03/29 20:39:08 treectrl Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest namespace import ::tcltest::* } set ::tcltest::testSingleFile false set ::tcltest::testsDirectory [file dir [info script]] # We need to ensure that the testsDirectory is absolute ::tcltest::normalizePath ::tcltest::testsDirectory set chan $::tcltest::outputChannel puts $chan "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]" package require treectrl # 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 return tktreectrl-2.2.8/tests/column.test0000700000175600010010000004431111041154207015442 0ustar TimNone# Commands covered: treectrl's widget command column # # This file contains a collection of tests for the column widget command of # the tktreectrl extension. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 2000 by Scriptics Corporation. # Copyright (c) 2002 by Christian Krone. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # CVS: @(#) $Id: column.test,v 1.16 2008/07/21 18:42:15 treectrl Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import ::tcltest::* } package require Tk package require treectrl test column-0.1 {some needed preparations} -body { pack [treectrl .t] } -result {} test column-0.2 {create an image} -body { image create photo emptyImg } -result {emptyImg} test column-1.1 {missing args} -body { .t column } -returnCodes error -result {wrong # args: should be ".t column command ?arg arg ...?"} test column-1.2 {unknown command} -body { .t column foo } -returnCodes error -result {bad command "foo": must be *} -match glob test column-1.3 {configure: no column exists with numerical index} -body { .t column configure 0 } -returnCodes error -result {column "0" doesn't exist} test column-1.4 {configure: no column exists with tag} -body { .t column configure column0 } -returnCodes error -result {column "column0" doesn't exist} test column-1.5 {configure: create and fill a column} -body { .t column create .t column configure 0 -tags column0 .t element create e rect -width 482 -height 20 .t style create s .t style elements s e set i [.t item create] .t item style set $i 0 s .t item lastchild root $i } -result {1} test column-1.6 {configure: create another column} -body { .t column create .t column configure 1 -tags column1 } -result {} test column-2.1 {column bbox: missing args} -body { .t column bbox } -returnCodes error -result {wrong # args: should be ".t column bbox column"} test column-2.2 {column bbox: invalid column} -body { .t column bbox foo } -returnCodes error -result {column "foo" doesn't exist} test column-2.3 {column bbox: tree doesn't show headers} -body { .t configure -showheader 0 .t column bbox column0 } -result {} test column-2.4 {column bbox} -body { .t configure -showheader 1 .t column bbox 0 } -result {0 3 482 7} test column-2.5 {column bbox: tail column not allowed} -body { .t column bbox tail } -returnCodes error -result {can't specify "tail" for this command} test column-3.1 {column configure: missing args} -body { .t column configure } -returnCodes error -result {wrong # args: should be ".t column configure column ?option? ?value? ?option value ...?"} test column-3.2 {column configure: invalid column} -body { .t column configure foo } -returnCodes error -result {column "foo" doesn't exist} test column-3.3 {column configure: list all options} -body { .t column configure column1 } -result {{-arrow {} {} none none} *} -match glob test column-3.4 {column configure: tail column} -body { .t column configure tail } -result {{-arrow {} {} none none} *} -match glob test column-3.4a {column configure: invalid option} -body { .t column configure tail -foo } -returnCodes error -result {unknown option "-foo"} test column-3.5 {column configure: invalid -arrow} -body { .t column configure column1 -arrow straight } -returnCodes error -result {bad arrow "straight": must be none, up, or down} test column-3.6 {column configure/cget: -arrow} -body { .t column configure column1 -arrow up .t column cget column1 -arrow } -result {up} test column-3.7 {column configure: invalid -arrowside} -body { .t column configure column1 -arrowside up } -returnCodes error -result {bad arrowside "up": must be left or right} test column-3.8 {column configure/cget: -arrowside} -body { .t column configure column1 -arrowside left .t column cget column1 -arrowside } -result {left} test column-3.9 {column configure: invalid -arrowgravity} -body { .t column configure column1 -arrowgravity both } -returnCodes error -result {bad arrowgravity "both": must be left or right} test column-3.10 {column configure/cget: -arrowgravity} -body { .t column configure column1 -arrowgravity right .t column cget column1 -arrowgravity } -result {right} test column-3.11 {column configure: invalid -arrowpadx} -body { .t column configure column1 -arrowpadx x } -returnCodes error -result {bad pad amount "x": must be a list of 1 or 2 positive screen distances} test column-3.11a {column configure: invalid 2 element -arrowpadx} -body { .t column configure column1 -arrowpadx {3 x} } -returnCodes error -result {bad pad amount "3 x": must be a list of 1 or 2 positive screen distances} test column-3.12 {column configure/cget: -arrowpadx} -body { .t column configure column1 -arrowpadx 8 .t column cget column1 -arrowpadx } -result {8} test column-3.12a {column configure/cget: 2 element -arrowpadx} -body { .t column configure column1 -arrowpadx {8 5} .t column cget column1 -arrowpadx } -result {8 5} test column-3.13 {column configure: invalid -bitmap} -body { .t column configure column1 -bitmap foo } -returnCodes error -result {bitmap "foo" not defined} test column-3.14 {column configure/cget: -bitmap} -body { .t column configure column1 -bitmap questhead .t column cget column1 -bitmap } -result {questhead} test column-3.15 {column configure: invalid -background} -body { .t column configure column1 -background foo } -returnCodes error -result {unknown color name "foo"} test column-3.16 {column configure/cget: -background} -body { .t column configure column1 -background magenta .t column cget column1 -background } -result {magenta} test column-3.17 {column configure: invalid -borderwidth} -body { .t column configure column1 -borderwidth x } -returnCodes error -result {bad screen distance "x"} test column-3.18 {column configure/cget: -borderwidth} -body { .t column configure column1 -borderwidth 4 .t column cget column1 -borderwidth } -result {4} test column-3.19 {column configure: invalid -button} -body { .t column configure column1 -button "" } -returnCodes error -result {expected boolean value but got ""} test column-3.20 {column configure/cget: -button} -body { .t column configure column1 -button off .t column cget column1 -button } -result {0} test column-3.21 {column configure: invalid -expand} -body { .t column configure column1 -expand ew } -returnCodes error -result {expected boolean value but got "ew"} test column-3.22 {column configure/cget: -expand} -body { .t column configure column1 -expand true .t column cget column1 -expand } -result {1} test column-3.23 {column configure: invalid -image} -body { .t column configure column1 -image questhead } -returnCodes error -result {image "questhead" doesn't exist} test column-3.24 {column configure/cget: -image} -body { .t column configure column1 -image emptyImg .t column cget column1 -image } -result {emptyImg} test column-3.25 {column configure: invalid -imagepadx} -body { .t column configure column1 -imagepadx y } -returnCodes error -result {bad pad amount "y": must be a list of 1 or 2 positive screen distances} test column-3.25a {column configure: invalid 2 element -imagepadx} -body { .t column configure column1 -imagepadx "y \{" } -returnCodes error -result {unmatched open brace in list} test column-3.26 {column configure/cget: -imagepadx} -body { .t column configure column1 -imagepadx 9 -imagepady 4 list [.t column cget column1 -imagepadx] \ [.t column cget column1 -imagepady] } -result {9 4} test column-3.26a {column configure/cget: 2 element -imagepadx/y} -body { .t column configure column1 -imagepadx {9 0} -imagepady {4 3} list [.t column cget column1 -imagepadx] \ [.t column cget column1 -imagepady] } -result {{9 0} {4 3}} test column-3.27 {column configure: invalid -itembackground} -body { .t column configure column1 -itembackground no } -returnCodes error -result {unknown color name "no"} test column-3.28 {column configure/cget: simple -itembackground} -body { .t column configure column1 -itembackground blue .t column cget column1 -itembackground } -result {blue} test column-3.29 {column configure: invalid -itembackground list} -body { .t column configure column1 -itembackground {blue selected green active} } -returnCodes error -result {unknown color name "selected"} test column-3.30 {column configure/cget: -itembackground list} -body { .t column configure column1 -itembackground {blue green magenta red} .t column cget column1 -itembackground } -result {blue green magenta red} test column-3.31 {column configure: invalid -justify} -body { .t column configure column1 -justify no } -returnCodes error -result {bad justification "no": must be left, right, or center} test column-3.32 {column configure/cget: simple -justify} -body { .t column configure column1 -justify center .t column cget column1 -justify } -result {center} test column-3.33 {column configure: invalid -minwidth} -body { .t column configure column1 -minwidth z } -returnCodes error -result {bad screen distance "z"} test column-3.34 {column configure/cget: -minwidth} -body { .t column configure column1 -minwidth 25 .t column cget column1 -minwidth } -result {25} test column-3.35 {column configure: invalid -state} -body { .t column configure column1 -state yes } -returnCodes error -result {bad state "yes": must be normal, active, or pressed} test column-3.36 {column configure/cget: -state} -body { .t column configure column1 -state pressed .t column cget column1 -state } -result {pressed} test column-3.37 {column configure: invalid -stepwidth} -constraints { deprecated } -body { .t column configure column1 -stepwidth "\t" } -returnCodes error -result {bad screen distance " "} test column-3.38 {column configure/cget: -stepwidth} -constraints { deprecated } -body { .t column configure column1 -stepwidth 125 .t column cget column1 -stepwidth } -result {125} test column-3.41 {column configure: -text} -body { .t column configure column1 -text "Text above Column 1" .t column cget column1 -text } -result {Text above Column 1} test column-3.42 {column configure: invalid -textpadx} -body { .t column configure column1 -textpadx baz } -returnCodes error -result {bad pad amount "baz": must be a list of 1 or 2 positive screen distances} test column-3.42a {column configure: invalid 2 element -textpadx} -body { .t column configure column1 -textpadx {foo bar baz} } -returnCodes error -result {bad pad amount "foo bar baz": must be a list of 1 or 2 positive screen distances} test column-3.43 {column configure/cget: -textpadx/y} -body { .t column configure column1 -textpadx 8 -textpady 5 list [.t column cget column1 -textpadx] \ [.t column cget column1 -textpady] } -result {8 5} test column-3.43a {column configure/cget: 2 element -textpadx/y} -body { .t column configure column1 -textpadx {8 4} -textpady {4 5} list [.t column cget column1 -textpadx] \ [.t column cget column1 -textpady] } -result {{8 4} {4 5}} test column-3.44 {column configure: invalid -width} -body { .t column configure column1 -width all } -returnCodes error -result {bad screen distance "all"} test column-3.45 {column configure/cget: -width} -body { .t column configure column1 -width 250 .t column cget column1 -width } -result {250} test column-3.46 {column configure: invalid -visible} -body { .t column configure column1 -visible never } -returnCodes error -result {expected boolean value but got "never"} test column-3.47 {column configure/cget: -visible} -body { .t column configure column1 -visible no .t column cget column1 -visible } -result {0} test column-3.48 {column configure: invalid -widthhack} -constraints { deprecated } -body { .t column configure column1 -widthhack ok } -returnCodes error -result {expected boolean value but got "ok"} test column-3.49 {column configure/cget: -widthhack} -constraints { deprecated } -body { .t column configure column1 -widthhack yes .t column cget column1 -widthhack } -result {1} test column-4.1 {column configure: -tags} -body { .t column configure column1 -tags column2 .t column cget column1 -tags } -returnCodes error -result {column "column1" doesn't exist} test column-4.2 {column configure: -tags} -body { .t column cget column2 -tags } -result {column2} test column-4.3 {column cget: -tags of tail} -body { .t column cget tail -tags } -result {} test column-4.4 {column configure/cget: -tags of tail} -body { .t column configure tail -tags head } -result {} test column-4.5 {column cget: specify tail by its tag} -body { .t column cget head -tags } -result {head} test column-5.1 {column delete: missing args} -body { .t column delete } -returnCodes error -result {wrong # args: should be ".t column delete first ?last?"} test column-5.2 {column delete: column tail} -body { .t column delete tail } -returnCodes error -result {can't specify "tail" for this command} test column-5.3 {column delete: first column} -body { .t column delete 0 } -result {} test column-5.4 {deleted column doesn't exist} -body { .t column cget 0 -tags } -returnCodes error -result {column "0" doesn't exist} test column-5.5 {column delete: all} -body { .t column delete all .t column list } -result {} test column-5.6 {column delete: range of 1} -body { .t column create -tags column1 .t column create -tags column2 .t column create -tags column3 .t column create -tags column4 .t column delete column1 column1 .t column list } -result {1 2 3} test column-5.7 {column delete: range of 2, reverse order} -body { .t column delete column4 column3 .t column list } -result {1} test column-6.1 {column id: missing args} -body { .t column id } -returnCodes error -result {wrong # args: should be ".t column id column"} test column-6.2 {column id: the easy case} -body { .t column id 1 } -result {1} test column-6.3 {column id} -body { .t column id column2 } -result {1} test column-6.4 {column id: tail column} -body { .t column id tail } -result {tail} test column-6.5 {column id: first column} -body { .t column id first } -result {1} test column-6.6 {column id: last column} -body { .t column id last } -result {1} test column-6.7 {column id: tail prev} -body { .t column id "tail prev" } -result {1} test column-7.1 {column move: missing args} -body { .t column move } -returnCodes error -result {wrong # args: should be ".t column move column before"} test column-7.2 {column move: invalid column} -body { .t column move 0 2 } -returnCodes error -result {column "0" doesn't exist} test column-7.3 {column move: move column2} -body { .t column create -tags column1 .t column create -tags column3 .t column move column2 column3 .t column order column2 } -result {1} test column-7.4 {correct moved?} -body { set res {} for {set x 0} {$x < [.t column count]} {incr x} { lappend res [.t column cget "order $x" -tags] } set res } -result {column1 column2 column3} test column-7.5 {column move: tail to the left} -body { .t column move tail column1 } -returnCodes error -result {can't specify "tail" for this command} test column-7.6 {column move: tail as before is ok} -body { .t column move column1 tail .t column order column1 } -result {2} test column-8.1 {column width: missing args} -body { .t column width } -returnCodes error -result {wrong # args: should be ".t column width column"} test column-8.2 {column width: invalid column} -body { .t column width foo } -returnCodes error -result {column "foo" doesn't exist} test column-8.3 {column width: tail column returns always 0} -body { .t column width tail } -result {0} test column-8.4 {column width} -body { .t element create eText2 text -font {{courier -12}} -text "Hello World" .t style create testStyle3 .t style elements testStyle3 eText2 .t item style set 1 column1 testStyle3 update idletasks list [.t column width column1] [font measure {courier -12} "Hello World"] } -result {77 77} test column-9.1 {column neededwidth: missing args} -body { .t column neededwidth } -returnCodes error -result {wrong # args: should be ".t column neededwidth column"} test column-9.2 {column neededwidth: invalid column} -body { .t column neededwidth foo } -returnCodes error -result {column "foo" doesn't exist} test column-9.3 {column neededwidth: tail column returns always 0} -body { .t column neededwidth tail } -result {0} test column-9.4 {column neededwidth} -body { .t column neededwidth column1 } -result {77} test column-10.1 {-itemstyle: not for tail} -body { .t column configure tail -itemstyle testStyle3 } -returnCodes error -result {can't change the -itemstyle option of the tail column} test column-10.2 {-itemstyle: set} -body { .t column configure column1 -itemstyle testStyle3 .t column cget column1 -itemstyle } -result {testStyle3} test column-10.3 {-itemstyle: unset} -body { .t column configure column1 -itemstyle {} .t column cget column1 -itemstyle } -result {} test column-10.4 {-itemstyle: change} -body { .t style create testStyle2 .t column configure column1 -itemstyle testStyle2 .t column cget column1 -itemstyle } -result {testStyle2} test column-10.5 {-itemstyle: style is deleted} -body { .t style delete testStyle2 .t column cget column1 -itemstyle } -result {} test column-11.1 {column count: too many args} -body { .t column count a b } -returnCodes error -result {wrong # args: should be ".t column count ?columnDesc?"} test column-11.2 {column count: no args} -body { .t column count } -result {3} test column-11.3 {column count: with desc} -body { .t column count "range first last" } -result {3} test column-11.4 {column count: all includes tail} -body { .t column count all } -result {4} test column-11.5 {column count: unknown tag} -body { .t column count {tag foo} } -result {0} test column-99.1 {some needed cleanup} -body { destroy .t } -result {} # cleanup image delete emptyImg ::tcltest::cleanupTests return tktreectrl-2.2.8/tests/display.test0000700000175600010010000001102610532134067015615 0ustar TimNone# Commands covered: display code # # This file contains a collection of tests for the style widget command of # the tktreectrl extension. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 2000 by Scriptics Corporation. # Copyright (c) 2002 by Christian Krone. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # CVS: @(#) $Id: display.test,v 1.1 2006/11/25 21:40:07 treectrl Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import ::tcltest::* } package require Tk package require treectrl test display-0.1 {some needed preparations} -body { # The size of the window is important. pack [treectrl .t -width 500 -height 400] .t element create e1 text -text "Hello," .t element create e2 window -destroy yes .t element create e3 text -text " world!" .t style create S1 .t style elements S1 {e1 e2 e3} .t style layout S1 e2 -iexpand x -squeeze x .t column create -text "Column 0" -tags C0 -itemstyle S1 .t column create -text "Column 1" -tags C1 -itemstyle S1 .t column create -text "Column 2" -tags C2 -itemstyle S1 .t column create -text "Column 3" -tags C3 -itemstyle S1 foreach I [.t item create -count 10 -parent root] { foreach C [.t column list] { .t item element configure $I $C e2 -window [entry .t.w${I}C$C] } } update ; # make sure it is visible } -result {} test display-1.1 {: hide some items} -body { .t notify bind .t { puts -nonewline "%P visible=[list [lsort -integer %v]] hidden=[list [lsort -integer %h]]" } .t item configure {list {2 5 9}} -visible no update idletasks } -output { visible={} hidden={2 5 9}} test display-1.2 {: show some items} -body { .t item configure {list {9 2}} -visible yes update idletasks } -output { visible={2 9} hidden={}} test display-1.3 {: hide & show some items} -body { .t item configure {list {5}} -visible yes .t item configure {list {6 7}} -visible no update idletasks } -output { visible=5 hidden={6 7}} test display-1.4 {: delete an item when it becomes visible} -body { .t notify bind .t { %T item delete {list %v} } .t notify bind .t { puts -nonewline "%P [list [lsort -integer %i]]" } .t item configure 6 -visible yes # Deleting an item that is being displayed should not segfault. update idletasks } -output { 6} test display-2.1 {: resizing a column resizes a window element} -body { set w [.t item element cget 2 C1 e2 -window] bind $w { puts -nonewline " %W" } .t column configure C1 -width 100 update idletasks } -output { .t.w2C1} test display-2.2 {: delete a column when a window in a previous column is resized during a display update} -body { set w [.t item element cget 2 C1 e2 -window] bind $w {+ .t column delete C2 } .t column configure C1 -width 150 # Deleting a column while displaying an item should not segfault. update idletasks } -output { .t.w2C1} test display-2.3 {: delete a column when a window in a previous column is resized during a display update} -body { set w [.t item element cget 2 C1 e2 -window] bind $w { .t item delete 2 } .t column configure C1 -width 100 # Deleting an item while displaying it should not segfault. update idletasks } -output { 2} test display-3.1 {} -body { .t configure -width 200 update idletasks .t notify bind .t { puts -nonewline "%P" } .t xview moveto 1.0 update idletasks } -output {} test display-3.2 {: delete an item while scrolling} -body { .t notify bind .t { .t item delete 8 .t notify unbind .t } .t xview moveto 0.0 # Causing a display update while scrolling (during a display update) should # restart the display update and not operate on deleted items. update idletasks } -output { 8} test display-99.1 {delete the tree during a display update} -body { .t notify bind .t { destroy .t } .t item configure 4 -visible no update idletasks winfo exists .t } -result {0} # cleanup ::tcltest::cleanupTests return tktreectrl-2.2.8/tests/element.test0000700000175600010010000001120610525441672015606 0ustar TimNone# Commands covered: [element] # # This file contains a collection of tests for the style widget command of # the tktreectrl extension. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 2000 by Scriptics Corporation. # Copyright (c) 2002 by Christian Krone. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # CVS: @(#) $Id: element.test,v 1.2 2006/11/11 21:42:18 treectrl Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import ::tcltest::* } package require Tk package require treectrl test element-0.1 {some needed preparations} -body { pack [treectrl .t] } -result {} test element-1.1 {element: missing command} -body { .t element } -returnCodes error -result {wrong # args: should be ".t element command ?arg arg ...?"} test element-1.2 {element: invalid command} -body { .t element foo } -returnCodes error -result {bad command "foo": must be *} -match glob ### test element-2.1 {element cget: missing arg} -body { .t element cget } -returnCodes error -result {wrong # args: should be ".t element cget name option"} test element-2.2 {element cget: too many args} -body { .t element cget a b c d } -returnCodes error -result {wrong # args: should be ".t element cget name option"} test element-2.3 {element cget: unknown elem} -body { .t element cget foo a } -returnCodes error -result {element "foo" doesn't exist} ### test element-3.1 {element configure: missing arg} -body { .t element configure } -returnCodes error -result {wrong # args: should be ".t element configure name ?option? ?value option value ...?"} test element-3.2 {element configure: unknown elem} -body { .t element configure foo } -returnCodes error -result {element "foo" doesn't exist} ### test element-4.1 {element create: missing arg} -body { .t element create } -returnCodes error -result {wrong # args: should be ".t element create name type ?option value ...?"} test element-4.2 {element create: empty type} -body { .t element create foo "" } -returnCodes error -result {invalid element type ""} test element-4.3 {element create: ambiguous type} -body { .t element create foo b ; # bitmap or border } -returnCodes error -result {ambiguous element type "b"} test element-4.4 {element create: unknown type} -body { .t element create foo bar } -returnCodes error -result {unknown element type "bar"} ### test element-5.1 {element delete: no args} -body { .t element delete } -result {} test element-5.2 {element delete: unknown elem} -body { .t element delete foo } -returnCodes error -result {element "foo" doesn't exist} test element-5.3 {element delete: single elem} -setup { .t element create e1 bitmap } -body { .t element delete e1 .t element names } -result {} test element-5.4 {element delete: multiple elems} -setup { foreach type [list bitmap border image rect text window] { .t element create e$type $type } } -body { eval .t element delete [.t element names] .t element names } -result {} ### test element-6.1 {element names: too many args} -body { .t element names a } -returnCodes error -result {wrong # args: should be ".t element names"} ### test element-7.1 {element perstate: missing arg} -body { .t element perstate } -returnCodes error -result {wrong # args: should be ".t element perstate element option stateList"} test element-7.2 {element perstate: too many args} -body { .t element perstate a b c d } -returnCodes error -result {wrong # args: should be ".t element perstate element option stateList"} test element-7.3 {element perstate: empty stateList} -setup { .t element create eText text -fill {red !selected blue {}} } -body { .t element perstate eText -fill {} } -result {red} test element-7.4 {element perstate: non-empty statelist} -body { .t element perstate eText -fill {selected} } -result {blue} ### test element-8.1 {element type: missing arg} -body { .t element type } -returnCodes error -result {wrong # args: should be ".t element type name"} test element-8.2 {element type: too many args} -body { .t element type a b } -returnCodes error -result {wrong # args: should be ".t element type name"} test element-8.3 {element type: unknown elem} -body { .t element type foo } -returnCodes error -result {element "foo" doesn't exist} test element-8.4 {element type: success} -body { .t element type eText } -result {text} test element-99.1 {some needed cleanup} -body { destroy .t } -result {} # cleanup ::tcltest::cleanupTests return tktreectrl-2.2.8/tests/item.test0000700000175600010010000012215310572372620015115 0ustar TimNone# Commands covered: treectrl's widget command item # # This file contains a collection of tests for the item widget command of # the tktreectrl extension. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 2000 by Scriptics Corporation. # Copyright (c) 2002 by Christian Krone. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # CVS: @(#) $Id: item.test,v 1.20 2007/03/03 22:24:16 treectrl Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import ::tcltest::* } package require Tk package require treectrl test item-0.1 {some needed preparations} -body { pack [treectrl .t] } -result {} test item-1.1 {item: missing command} -body { .t item } -returnCodes error -result {wrong # args: should be ".t item command ?arg arg ...?"} test item-2.2 {item: invalid command} -body { .t item foo } -returnCodes error -result {bad command "foo": must be *} -match glob # Before continuing to test the item descriptions and their modifiers, # lets create some items with this hierarchy: # 0 # + 1 # | + 2 # | + 3 # | + 4 # + 5 # | + 6 # | + 7 # + 8 test item-2.4 {create some items} -body { set n1 [.t item create]; .t item lastchild 0 $n1 set n2 [.t item create]; .t item lastchild $n1 $n2 set n3 [.t item create]; .t item lastchild $n1 $n3 set n4 [.t item create]; .t item lastchild $n3 $n4 set n5 [.t item create]; .t item lastchild 0 $n5 set n6 [.t item create]; .t item lastchild $n5 $n6 set n7 [.t item create]; .t item lastchild $n5 $n7 set n8 [.t item create]; .t item lastchild 0 $n8 } -result {8} test item-2.5 {some more preparations} -body { .t state define state0 .t element create eBorder border .t element create eImage image .t element create eRect rect .t element create eText text -fill red .t style create testStyle .t style elements testStyle {eText eBorder} } -result {} test item-2.6 {item create} -body { list [.t item create] [.t item create] [.t item create] } -result {9 10 11} test item-3.1 {item delete: missing itemDesc} -body { .t item delete } -returnCodes error -result {wrong # args: should be ".t item delete first ?last?"} test item-3.2 {item delete: unknown item} -body { .t item delete 999 } -returnCodes error -result {item "999" doesn't exist} test item-3.3 {item delete: one item} -body { .t item delete 9 } -result {} test item-3.4 {item delete: item range without common ancestor} -body { .t item delete 10 11 } -returnCodes error -result {item 10 and item 11 don't share a common ancestor} test item-3.5 {item delete: item range with common ancestor} -body { .t item lastchild 8 10 .t item lastchild 8 11 .t item delete 10 11 } -result {} test item-3.6 {item delete: don't delete "root" itemDesc} -body { .t item delete root .t item id root } -result {0} test item-3.7 {item delete: deleting root should be ignored} -body { .t item delete [.t item id root] update idletasks } -result {} test item-4.1 {item ancestors: no ancestor yet} -body { .t item create .t item ancestors 12 } -result {} test item-4.2 {item ancestors} -body { .t item lastchild 7 12 .t item ancestors 12 } -result {7 5 0} test item-5.1 {item children: no children} -body { .t item children 12 } -result {} test item-5.2 {item children} -body { .t item children 0 } -result {1 5 8} test item-6.1 {item firstchild: missing itemDesc} -body { .t item firstchild } -returnCodes error -result {wrong # args: should be ".t item firstchild item ?newFirstChild?"} test item-6.2 {item firstchild: no children} -body { .t item firstchild 12 } -result {} test item-6.3 {item firstchild} -body { .t item firstchild 1 } -result {2} test item-7.1 {item lastchild: no children} -body { .t item lastchild 1 } -result {3} test item-8.1 {item nextsibling: no sibling} -body { .t item nextsibling 12 } -result {} test item-8.2 {item nextsibling: no sibling} -body { .t item nextsibling 2 } -result {3} test item-9.1 {item numchildren: no children} -body { .t item numchildren 12 } -result {0} test item-9.2 {item numchildren} -body { .t item numchildren 1 } -result {2} test item-10.1 {item parent: no parent} -body { .t item parent root } -result {} test item-10.2 {item parent} -body { .t item parent "root firstchild" } -result {0} test item-11.1 {item prevsibling: missing arg} -body { .t item prevsibling } -returnCodes error -result {wrong # args: should be ".t item prevsibling item ?newPrevSibling?"} test item-11.2 {item prevsibling: no prevsibling} -body { .t item prevsibling 1 } -result {} test item-11.3 {item prevsibling} -body { .t item prevsibling 3 } -result {2} test item-12.1 {item remove: invalid item} -body { .t item remove 999 } -returnCodes error -result {item "999" doesn't exist} test item-12.2 {item remove} -body { .t item remove 12 } -result {} test item-13.1 {item complex: missing args} -constraints { deprecated } -body { .t item complex 8 } -returnCodes error -result {wrong # args: should be ".t item complex item list ..."} test item-13.2 {item complex: only allowed if column style is defined} -constraints { deprecated } -body { .t item complex 8 {{e1 -text Hallo}} } -returnCodes error -result {column #0 doesn't exist} test item-13.3 {item complex: invalid list} -constraints { deprecated } -body { .t column create -tag column0 .t item style set 8 0 testStyle .t item complex 8 {{e1 -text}} } -returnCodes error -result {wrong # args: should be "element option value ..."} test item-13.4 {item complex: element name not defined in style} -constraints { deprecated } -body { .t item complex 8 {{e1 -text Hallo}} } -returnCodes error -result {element "e1" doesn't exist} test item-13.5 {item complex: option not known in element} -constraints { deprecated } -body { .t item complex 8 {{eText -bitmap questhead}} } -returnCodes error -result {unknown option "-bitmap"} test item-13.6 {item complex: invalid option value in element} -constraints { deprecated } -body { .t item complex 8 {{eText -fill foo}} } -cleanup { .t column delete column0 } -returnCodes error -result {unknown color name "foo"} test item-14.1 {item element: missing command} -setup { # in case the deprecated complex command is not run... .t column create -tag column0 .t item style set 8 0 testStyle .t item text 8 0 "" } -body { .t item element } -returnCodes error -result {wrong # args: should be ".t item element command item column element ?arg ...?"} test item-14.2 {item element: invalid command} -body { .t item element foo 8 column0 eText } -returnCodes error -result {bad command "foo": must be *} -match glob test item-14.3 {item element perstate: missing arg} -body { .t item element perstate 8 column0 eText } -returnCodes error -result {wrong # args: should be ".t item element perstate item column element option ?stateList?"} test item-14.4 {item element perstate: without stateList} -body { .t element configure eText -fill {red !selected blue {}} .t item element perstate 8 column0 eText -fill } -result {red} test item-14.5 {item element perstate: without stateList} -body { .t item element perstate 8 column0 eText -fill } -result {red} test item-14.6 {item element perstate: with stateList} -body { .t item element perstate 8 column0 eText -fill {selected} } -result {blue} test item-14.7 {item element perstate: all items} -body { .t item element perstate all column0 eText -fill {selected} } -returnCodes error -result {can't specify > 1 item for this command} test item-14.8 {item element perstate: several items} -body { .t item element perstate {list {8 root}} column0 eText -fill {selected} } -returnCodes error -result {can't specify > 1 item for this command} test item-14.21 {item element cget: missing arg} -body { .t item element cget 8 column0 eText } -returnCodes error -result {wrong # args: should be ".t item element cget item column element option"} test item-14.22 {item element cget: too many args} -body { .t item element cget 8 a b c d } -returnCodes error -result {wrong # args: should be ".t item element cget item column element option"} test item-14.23 {item element cget: single item, get -fill} -body { .t item element cget 8 column0 eText -fill } -result {} test item-14.24 {item element cget: all items, get -fill} -body { .t item element cget all column0 eText -fill } -returnCodes error -result {can't specify > 1 item for this command} test item-14.25 {item element cget: multiple items, get -fill} -body { .t item element cget {list {8 1 3}} column0 eText -fill } -returnCodes error -result {can't specify > 1 item for this command} test item-14.31 {item element configure: get all config info} -body { .t item element configure 8 column0 eText } -result {{-data {} {} {} {}} {-datatype {} {} {} {}} *} -match glob test item-14.32 {item element configure: single item, set -fill} -body { .t item element configure 8 column0 eText -fill yellow .t item element cget 8 0 eText -fill } -result {yellow} test item-14.33 {item element configure: single item, get -fill} -body { .t item element configure 8 column0 eText -fill } -result {-fill {} {} {} yellow} test item-14.34 {item element configure: all items, get -fill} -body { .t item element configure all column0 eText -fill } -returnCodes error -result {can't specify > 1 item for this command} test item-14.35 {item element configure: several items, get -fill} -body { .t item element configure {list {8 3}} column0 eText -fill } -returnCodes error -result {can't specify > 1 item for this command} test item-14.36 {item element configure: all items, set -fill} -body { .t item style set all column0 testStyle .t item element configure all column0 eText -fill orange set res {} foreach I [.t item id {range first last}] { lappend res [.t item element cget $I column0 eText -fill] } set res } -result {orange orange orange orange orange orange orange orange orange} test item-14.37 {item element configure: single item, multiple elements} -body { .t item element configure root column0 eText -fill blue + } -returnCodes error -result {missing element name after "+"} test item-14.38 {item element configure: single item, multiple elements} -body { .t item element configure root column0 eText -fill blue + eBorder } -returnCodes error -result {missing option-value pair after element "eBorder"} test item-14.39 {item element configure: single item, multiple elements} -body { .t item element configure root column0 eText -fill blue + eBorder -draw } -returnCodes error -result {missing option-value pair after element "eBorder"} test item-14.40 {item element configure: single item, multiple elements} -body { .t item element configure root column0 eText -fill blue + eBorder -draw false list [.t item element cget root column0 eText -fill] \ [.t item element cget root column0 eBorder -draw] } -result {blue false} test item-14.41 {item element configure: single item, multiple columns} -body { .t item element configure root column0 eText -fill blue , } -returnCodes error -result {missing column after ","} test item-14.42 {item element configure: single item, multiple columns} -body { .t column create -tag column1 .t item style set all column1 testStyle .t item element configure root column0 eText -fill blue , column1 } -returnCodes error -result {missing element name after column "column1"} test item-14.43 {item element configure: single item, multiple columns} -body { .t item element configure root column0 eText -fill blue , column1 eBorder } -returnCodes error -result {missing option-value pair after element "eBorder"} test item-14.44 {item element configure: single item, multiple columns} -body { .t item element configure root column0 eText -fill blue , column1 eBorder -draw } -returnCodes error -result {missing option-value pair after element "eBorder"} test item-14.45 {item element configure: single item, multiple columns} -body { .t item element configure root column0 eText -fill green , column1 eBorder -draw true list [.t item element cget root column0 eText -fill] \ [.t item element cget root column1 eBorder -draw] } -result {green true} test item-14.46 {item element configure: multiple items, multiple columns/elements} -body { .t item element configure {list {1 3}} column0 eText -fill green -text boo + \ eBorder -background red , column1 eBorder -draw true + eText -font {{times 12}} set res {} foreach I {1 3} { lappend res [.t item element cget $I column0 eText -fill] lappend res [.t item element cget $I column0 eText -text] lappend res [.t item element cget $I column0 eBorder -background] lappend res [.t item element cget $I column1 eBorder -draw] lappend res [.t item element cget $I column1 eText -font] } set res } -result {green boo red true {{times 12}} green boo red true {{times 12}}} test item-14.50 {item element configure: cleanup} -body { .t item style set all 0 "" .t column delete all .t column create .t item style set 8 0 testStyle .t item element configure 8 0 eText -fill yellow } -result {} test item-15.1 {item style: missing args} -body { .t item style } -returnCodes error -result {wrong # args: should be ".t item style command item ?arg ...?"} test item-15.2 {item style: invalid command} -body { .t item style foo bar } -returnCodes error -result {bad command "foo": must be *} -match glob test item-15.3 {item style: invalid command} -body { .t item style foo bar } -returnCodes error -result {bad command "foo": must be *} -match glob test item-15.4 {item style elements: missing args} -body { .t item style elements 8 } -returnCodes error -result {wrong # args: should be ".t item style elements item column"} test item-15.5 {item style elements: invalid item} -body { .t item style elements 999 } -returnCodes error -result {item "999" doesn't exist} test item-15.6 {item style elements: item without style} -body { .t item style elements 1 0 } -returnCodes error -result {item 1 column 0 has no style} test item-15.7 {item style elements} -body { .t item style elements 8 0 } -result {eText} test item-15.8 {item style map: missing args} -body { .t item style map 8 } -returnCodes error -result {wrong # args: should be ".t item style map item column style map"} test item-15.9 {item style map: invalid item} -body { .t item style map 999 } -returnCodes error -result {item "999" doesn't exist} test item-15.10 {item style map: item with unknown style} -body { .t item style map 1 0 noStyle {foo bar} } -returnCodes error -result {style "noStyle" doesn't exist} test item-15.11 {item style map: odd elemented list} -body { .t item style map 8 0 testStyle foo .t item style elements 8 0 } -returnCodes error -result {list must contain even number of elements} test item-15.12 {item style map: unknown element} -body { .t style create testStyle2 .t item style map 8 0 testStyle2 {eText foo} .t item style elements 8 0 } -returnCodes error -result {element "foo" doesn't exist} test item-15.13 {item style map: element not in to-style} -body { .t item style map 8 0 testStyle2 {eText eRect} } -returnCodes error -result {style testStyle2 does not use element eRect} test item-15.14 {item style map: element not in from-style} -body { # .t style elements testStyle2 {eImage eRect} .t item style map 8 0 testStyle2 {eRect eBorder} } -returnCodes error -result {style testStyle does not use element eRect} test item-15.15 {item style map: different element types} -body { .t style elements testStyle2 {eImage eRect} .t item style map 8 0 testStyle2 {eBorder eRect} } -returnCodes error -result {can't map element type border to rect} test item-15.16 {item style set: invalid item} -body { .t item style set foo bar } -returnCodes error -result {item "foo" doesn't exist} test item-15.17 {item style set: without args returns all styles} -body { .t item style set 2 } -result {{}} test item-15.18 {item style set: without args returns style} -body { .t item style set 2 0 } -result {} test item-15.19 {item style set: without args returns style} -body { .t item style set 8 0 } -result {testStyle} test item-15.20 {item style set: single item, single column} -body { .t item style set 8 0 testStyle2 .t item style set 8 } -result {testStyle2} test item-15.21 {item style set: all items, single column} -body { .t item style set all 0 testStyle2 set res {} foreach I [.t item id {range 1 8}] { lappend res [.t item style set $I] } set res } -result {testStyle2 testStyle2 testStyle2 testStyle2 testStyle2 testStyle2 testStyle2 testStyle2} test item-15.22 {item style set: list of items, single column} -body { .t item style set {list {2 4 6 8}} 0 "" set res {} foreach I [.t item id {range 1 8}] { lappend res [.t item style set $I] } set res } -result {testStyle2 {{}} testStyle2 {{}} testStyle2 {{}} testStyle2 {{}}} test item-15.23 {item style set: all items, multiple columns} -body { .t column create .t item style set all 0 testStyle 1 testStyle2 set res {} foreach I [.t item id {range 1 8}] { lappend res [.t item style set $I] } set res } -result {{testStyle testStyle2} {testStyle testStyle2} {testStyle testStyle2} {testStyle testStyle2} {testStyle testStyle2} {testStyle testStyle2} {testStyle testStyle2} {testStyle testStyle2}} test item-15.24 {item style set: list of items, multiple columns} -body { .t item style set {list {2 4 6 8}} 0 testStyle2 1 "" set res {} foreach I [.t item id {range 1 8}] { lappend res [.t item style set $I] } set res } -result {{testStyle testStyle2} {testStyle2 {}} {testStyle testStyle2} {testStyle2 {}} {testStyle testStyle2} {testStyle2 {}} {testStyle testStyle2} {testStyle2 {}}} test item-15.25 {item style set: all items, multiple columns} -body { .t item style set all 1 "" 0 "" set res {} foreach I [.t item id {range 1 8}] { lappend res [.t item style set $I] } .t column delete all .t column create set res } -result {{{} {}} {{} {}} {{} {}} {{} {}} {{} {}} {{} {}} {{} {}} {{} {}}} test item-16.1 {item state: missing args} -body { .t item state } -returnCodes error -result {wrong # args: should be ".t item state command item ?arg ...?"} test item-16.2 {item state: unknown command} -body { .t item state foo bar } -returnCodes error -result {bad command "foo": must be *} -match glob test item-16.3 {item state get: unknown item} -body { .t item state get 999 } -returnCodes error -result {item "999" doesn't exist} test item-16.4 {item state get: too much arg} -body { .t item state get 8 open enabled } -returnCodes error -result {wrong # args: should be ".t item state get 8 ?state?"} test item-16.5 {item state get: invalid arg} -body { .t item state get 8 !open } -returnCodes error -result {can't specify '!' for this command} test item-16.6 {item state get: invalid arg} -body { .t item state get 8 ~open } -returnCodes error -result {can't specify '~' for this command} test item-16.6 {item state get: unknown state} -body { .t item state get 8 foo } -returnCodes error -result {unknown state "foo"} test item-16.7 {item state: list all set states} -body { .t item state get 8 } -result {open enabled} test item-16.8 {item state get: state not set} -body { .t item state get 8 active } -result {0} test item-16.9 {item state get: state set} -body { .t item state get 8 open } -result {1} test item-16.10 {item state get: user defined state not set} -body { .t item state get 8 state0 } -result {0} test item-16.11 {item state set: missing arg} -body { .t item state set 8 } -returnCodes error -result {wrong # args: should be ".t item state set 8 ?last? stateList"} test item-16.12 {item state: try to reset predefined state} -body { .t item state set 8 open } -returnCodes error -result {can't specify state "open" for this command} test item-16.13 {item state: unknown states} -body { .t item state set 8 {foo bar} } -returnCodes error -result {unknown state "foo"} test item-16.14 {item state: unknown state leaded by !} -body { .t item state set 8 !foo } -returnCodes error -result {unknown state "foo"} test item-16.15 {item state: unknown state leaded by ~} -body { .t item state set 8 ~bar } -returnCodes error -result {unknown state "bar"} test item-16.16 {item state: switch on states} -body { .t item state set 8 state0 .t item state get 8 } -result {open enabled state0} test item-16.17 {item state get: user defined state set} -body { .t item state get 8 state0 } -result {1} test item-16.18 {item state: toggle state} -body { .t item state set 8 ~state0 .t item state get 8 } -result {open enabled} test item-16.19 {item state: switch off states} -body { .t item state set 8 !state0 .t item state get 8 state0 } -result {0} test item-16.20 {item state: reset predefined state} -body { .t item collapse 8 .t item state get 8 } -result {enabled} test item-16.21 {item state: reset predefined state} -body { .t item expand 8 .t item state get 8 } -result {open enabled} test item-16.22 {item state: reset predefined state} -body { .t item toggle 8 .t item state get 8 enabled } -result {1} test item-16.23 {item state: set range} -body { .t item state set 1 8 state0 set res {} foreach I [.t item id {range 1 8}] { lappend res [.t item state get $I state0] } set res } -result {1 1 1 1 1 1 1 1} test item-16.24 {item state: set list} -body { .t item state set {list {2 4 6 8}} !state0 set res {} foreach I [.t item id {range 1 8}] { lappend res [.t item state get $I state0] } set res } -result {1 0 1 0 1 0 1 0} test item-16.25 {item state: set all} -body { .t item state set all ~state0 set res {} foreach I [.t item id {range 1 8}] { lappend res [.t item state get $I state0] } set res } -result {0 1 0 1 0 1 0 1} test item-16.26 {item state set: invalid range} -body { set I [.t item create] .t item state set $I 8 state0 } -returnCodes error -result {item 13 and item 8 don't share a common ancestor} test item-16.40 {item state forcolumn: missing arg} -body { .t item state forcolumn } -returnCodes error -result {wrong # args: should be ".t item state command item ?arg ...?"} test item-16.41 {item state forcolumn: missing arg} -body { .t item state forcolumn 8 } -returnCodes error -result {wrong # args: should be ".t item state forcolumn item column ?stateList?"} test item-16.42 {item state forcolumn: too many args} -body { .t item state forcolumn a b c d } -returnCodes error -result {wrong # args: should be ".t item state forcolumn item column ?stateList?"} test item-16.43 {item state forcolumn: get for single item} -body { .t item state forcolumn 8 0 } -result {} test item-16.44 {item state forcolumn: get for all} -body { .t item state forcolumn all 0 } -returnCodes error -result {can't specify > 1 item for this command} test item-16.45 {item state forcolumn: set for single item} -body { .t item state forcolumn 8 0 state0 .t item state forcolumn 8 0 } -result {state0} test item-16.46 {item state forcolumn: set all} -body { .t item state forcolumn all 0 state0 set res {} foreach I [.t item id {range 1 8}] { lappend res [.t item state forcolumn $I 0] } set res } -result {state0 state0 state0 state0 state0 state0 state0 state0} test item-16.47 {item state forcolumn: set list} -body { .t item state forcolumn {list {2 4 6 8}} 0 !state0 set res {} foreach I [.t item id {range 1 8}] { lappend res [.t item state forcolumn $I 0] } set res } -result {state0 {} state0 {} state0 {} state0 {}} test item-17.1 {item sort: missing args} -body { .t item sort } -returnCodes error -result {wrong # args: should be ".t item sort item ?option ...?"} test item-17.2 {item sort: invalid item} -body { .t item sort foo } -returnCodes error -result {item "foo" doesn't exist} test item-17.3 {item sort: is all allowed?} -body { .t item sort all } -returnCodes error -result {can't specify > 1 item for this command} test item-17.4 {item sort: invalid option} -body { .t item sort root -foo } -returnCodes error -result {bad option "-foo": must be *} -match glob test item-17.5 {item sort: missing arg to an option} -body { .t item sort root -first } -returnCodes error -result {missing value for "-first" option} test item-17.6 {item sort: invalid column} -body { .t item sort root -column 3 } -returnCodes error -result {column "3" doesn't exist} test item-17.7 {item sort: invalid column, second try} -body { .t item sort root -column tail } -returnCodes error -result {can't specify "tail" for this command} test item-17.8 {item sort: sort needs style to find text} -body { .t item sort root } -returnCodes error -result {item 1 column 0 has no style} proc listItems {t {i root}} { set res {} foreach c [$t item children $i] { lappend res $c eval lappend res [listItems $t $c] } return $res } test item-17.9 {item sort: set the texts in column 0 for all items} -body { .t column create .t style create textStyle .t style elements textStyle {eRect eBorder eText} .t element create eTime text .t style create timeStyle .t style elements timeStyle eTime foreach i [listItems .t] { .t item style set $i 0 textStyle .t item style set $i 1 timeStyle .t item text $i 0 [expr {$i+5}] } .t item text 8 0 } -result {13} test item-17.10 {item sort: sort all by ascii} -body { .t item sort root listItems .t } -result {5 6 7 8 1 2 3 4} test item-17.11 {item sort: sort all decreasing by ascii} -body { .t item sort root -decreasing listItems .t } -result {1 2 3 4 8 5 6 7} test item-17.12 {item sort: sort all as integer} -body { .t item sort root -integer listItems .t } -result {1 2 3 4 5 6 7 8} test item-17.13 {item sort: for integers -dictionary works also} -body { .t item sort root -dictionary listItems .t } -result {1 2 3 4 5 6 7 8} test item-17.14 {item sort: sort all decreasing as integer} -body { .t item sort root -integer -decreasing listItems .t } -result {8 5 6 7 1 2 3 4} test item-17.15 {item sort: don't sort, only return sorted items} -body { .t item lastchild root 5 list [.t item sort root -notreally] [listItems .t] } -result {{5 8 1} {8 1 2 3 4 5 6 7}} test item-17.16 {item sort: return integer sorted items} -body { .t item sort root -notreally -integer } -result {1 5 8} test item-17.17 {item sort: return integer sorted items} -body { .t item sort root -notreally -dictionary -decreasing } -result {8 5 1} test item-17.18 {item sort: two sort options, last wins (as in lsort)} -body { .t item sort root -integer -ascii listItems .t } -result {5 6 7 8 1 2 3 4} test item-17.19 {item sort: two order options, last wins (as in lsort)} -body { .t item sort root -real -decreasing -increasing listItems .t } -result {1 2 3 4 5 6 7 8} test item-17.20 {item sort: restrict to item of different parent} -body { .t item sort root -first 2 } -returnCodes error -result {item 2 is not a child of item 0} test item-17.21 {item sort: restrict to unknown item} -body { .t item sort root -first foo } -returnCodes error -result {item "foo" doesn't exist} test item-17.22 {item sort: restricted sort} -body { .t item sort root -first 5 -last 8 -decreasing listItems .t } -result {1 2 3 4 8 5 6 7} test item-17.23 {item sort: restricted sort returned} -body { .t item sort root -first 5 -last 8 -notreally } -result {5 8} test item-17.24 {item sort: order of restriction doesn't matter} -body { .t item sort root -first 8 -last 5 -notreally } -result {5 8} test item-17.25 {item sort: very restricted sort returned} -body { .t item sort root -first 5 -last 5 -notreally } -result {5} test item-17.26 {item sort -command: missing arg} -body { .t item sort root -command } -returnCodes error -result {missing value for "-command" option} test item-17.27 {item sort -command: unknown command} -body { .t item sort root -command foo } -returnCodes error -result {invalid command name "foo"} test item-17.28 {item sort -command: unknown command} -body { .t item sort root -command # } -returnCodes error -result {invalid command name "#"} test item-17.29 {item sort -command: invalid return value} -body { .t item sort root -command list } -returnCodes error -result {-command returned non-numeric result} proc myCompare {op item1 item2} { switch -- $op { 1 - 0 - -1 { return $op } timespan-1 { regsub -all : [.t item text $item1 1] "" val1 regsub -all : [.t item text $item2 1] "" val2 return [expr {[string trimleft $val1 0]-[string trimleft $val2 0]}] } ascii { return [string compare [.t item text $item1 0] \ [.t item text $item2 0]] } ascii-1 { return [string compare [.t item text $item1 1] \ [.t item text $item2 1]] } default { return -code $op 0 } } } test item-17.30 {item sort -command: too less arguments to proc call} -body { .t item sort root -command myCompare } -returnCodes error -result {wrong # args: should be "myCompare op item1 item2"} test item-17.31 {item sort -command: always returning 0 is identity} -body { set res [list [listItems .t]] .t item sort root -command {myCompare 0} lappend res [listItems .t] } -result {{1 2 3 4 8 5 6 7} {1 2 3 4 8 5 6 7}} test item-17.32 {item sort -command: returnCode break} -body { list [catch {.t item sort root -command {myCompare break}} msg] $msg \ $errorInfo } -result {3 0 {0 (evaluating item sort -command)}} test item-17.33 {item sort -command: always returning 1 is identity?} -body { set res [list [listItems .t]] .t item sort root -command {myCompare 1} } -returnCodes error -result {buggy item sort -command detected} test item-17.34 {item sort -command: always returning -1 reverts?} -constraints { knownBug } -body { .t item sort root -command {myCompare -1} } -returnCodes error -result {buggy item sort -command detected} test item-17.35 {item sort -command: ascii} -body { .t item sort root -command {myCompare ascii} listItems .t } -result {5 6 7 8 1 2 3 4} test item-17.36 {item sort -command: reverse ascii} -body { .t item sort root -command {myCompare ascii} -decreasing listItems .t } -result {1 2 3 4 8 5 6 7} test item-17.37 {item sort: with timespans column} -body { .t item text 1 1 "01:00" .t item text 5 1 "10:00" .t item text 8 1 "02:09:00" .t item sort root -column 1 listItems .t } -result {1 2 3 4 8 5 6 7} test item-17.38 {item sort -command: ascii with timespans column} -body { .t item sort root -command {myCompare ascii-1} listItems .t } -result {1 2 3 4 8 5 6 7} test item-17.39 {item sort -command: timespan with timespans column} -body { .t item sort root -command {myCompare timespan-1} listItems .t } -result {1 2 3 4 5 6 7 8} test item-17.40 {item sort -command: reverse timespan with timespans} -body { .t item sort root -command {myCompare timespan-1} -decreasing listItems .t } -result {8 5 6 7 1 2 3 4} test item-17.41 {item sort -command: reverse timespan with timespans} -body { .t item sort root -command {myCompare timespan-1} -decreasing -notreally } -result {8 5 1} test item-17.42 {item sort -element: missing arg} -body { .t item sort root -element } -returnCodes error -result {missing value for "-element" option} test item-17.43 {item sort -element: invalid element} -body { .t item sort root -element foo } -returnCodes error -result {element "foo" doesn't exist} test item-17.44 {item sort -element: no text element} -body { .t item sort root -element eBorder } -returnCodes error -result {element eBorder is not of type "text"} test item-17.45 {item sort -element: element in wrong column} -body { .t item sort root -column 1 -element eText -dictionary listItems .t } -returnCodes error -result {style timeStyle does not use element eText} test item-17.46 {item sort -element: -colum defaults to 0} -body { .t item sort root -element eTime listItems .t } -returnCodes error -result {style textStyle does not use element eTime} test item-17.47 {item sort -element: element in columns} -body { .t item sort root -column 1 -element eTime listItems .t } -result {1 2 3 4 8 5 6 7} ;# same result as in 17.37 test item-17.48 {item sort -element: useless for -command} -body { .t item sort root -column 1 -element eTime -command {myCompare timespan-1} listItems .t } -result {1 2 3 4 5 6 7 8} ;# same result as in 17.39 test item-17.49 {item sort -command: no columns} -body { while {![catch {.t column configure "order 0"}]} { .t column delete "order 0" } .t item sort root } -returnCodes error -result {there are no columns} test item-18.1 {item enabled: too few args} -body { .t item enabled } -returnCodes error -result {wrong # args: should be ".t item enabled item ?boolean?"} test item-18.2 {item enabled: too many args} -body { .t item enabled a b c } -returnCodes error -result {wrong # args: should be ".t item enabled item ?boolean?"} test item-18.3 {item enabled: null item} -body { .t item enabled 99 } -returnCodes error -result {item "99" doesn't exist} test item-18.4 {item enabled: single item get} -body { .t item enabled root } -result {1} test item-18.5 {item enabled: single item set} -body { .t item enabled root false set res {} foreach I [.t item id {range first last}] { lappend res [.t item enabled $I] } set res } -result {0 1 1 1 1 1 1 1 1} test item-18.6 {item enabled: all get} -body { .t item enabled all } -returnCodes error -result {can't specify > 1 item for this command} test item-18.7 {item enabled: all set} -body { .t item enabled all false set res {} foreach I [.t item id {range first last}] { lappend res [.t item enabled $I] } set res } -result {0 0 0 0 0 0 0 0 0} test item-18.8 {item enabled: multi get} -body { .t item enabled {list {2 4 7}} } -returnCodes error -result {can't specify > 1 item for this command} test item-18.9 {item enabled: multi set} -body { .t item enabled {list {2 4 7}} true set res {} foreach I [.t item id {range first last}] { lappend res [.t item enabled $I] } set res } -result {0 0 1 0 1 0 0 1 0} test item-19.1 {item text: too few args} -body { .t item text } -returnCodes error -result {wrong # args: should be ".t item text item ?column? ?text? ?column text ...?"} test item-19.2 {item text: all items, get every column} -body { .t item text all } -returnCodes error -result {can't specify > 1 item for this command} test item-19.3 {item text: all items, set first column} -body { .t column create .t item style set all first testStyle .t item text all first abc set res {} foreach I [.t item id {range first last}] { lappend res [.t item text $I first] } set res } -result {abc abc abc abc abc abc abc abc abc} test item-19.4 {item text: all items, get first column} -body { .t item text all first } -returnCodes error -result {can't specify > 1 item for this command} test item-19.5 {item text: several items, set first column} -body { .t item text {list {2 4 6 8}} first def set res {} foreach I [.t item id {range first last}] { lappend res [.t item text $I first] } set res } -result {abc abc def abc def abc def abc def} test item-19.6 {item text: several items, get first column} -body { .t item text {list {2 4 6 8}} first } -returnCodes error -result {can't specify > 1 item for this command} test item-20.1 {item tag: too few args} -body { .t item tag } -returnCodes error -result {wrong # args: should be ".t item tag command ?arg arg ...?"} test item-20.2 {item tag add: too few args} -body { .t item tag add } -returnCodes error -result {wrong # args: should be ".t item tag add item tagList"} test item-20.3 {item tag add: too many args} -body { .t item tag add a b c } -returnCodes error -result {wrong # args: should be ".t item tag add item tagList"} test item-20.4 {item tag names: too few args} -body { .t item tag names } -returnCodes error -result {wrong # args: should be ".t item tag names item"} test item-20.5 {item tag names: too many args} -body { .t item tag names a b } -returnCodes error -result {wrong # args: should be ".t item tag names item"} test item-20.6 {item tag remove: too few args} -body { .t item tag remove } -returnCodes error -result {wrong # args: should be ".t item tag remove item tagList"} test item-20.7 {item tag remove: too many args} -body { .t item tag remove a b c } -returnCodes error -result {wrong # args: should be ".t item tag remove item tagList"} test item-20.11 {item tag: add tags to all} -body { .t item delete all .t item create -count 9999 -parent root .t item tag add all {a b c} .t item tag expr all {c && a && b} } -result {1} test item-20.12 {item tag: add duplicate tags} -body { .t item tag add all {c b a} lsort [.t item tag names all] } -result {a b c} test item-20.13 {item tag: remove 1 tag from several items} -body { .t item tag remove {range 100 5000} b list [lsort [.t item tag names all]] [lsort [.t item tag names {range 100 5000}]] } -result {{a b c} {a c}} test item-20.14 {item tag: remove 1 tag from all items} -body { .t item tag remove all b lsort [.t item tag names all] } -result {a c} test item-20.15 {item tag: add tags to all (some dups)} -body { .t item tag add all {a e f b d h g} lsort [.t item tag names all] } -result {a b c d e f g h} test item-20.16 {item tag: long expr} -body { llength [.t item id "tag {(a && e) && (f && b) && (d && h && g)}"] } -result {10000} test item-20.17 {item tag: remove b from 100 items} -body { .t item tag remove {range 100 199} b llength [.t item id "tag !b"] } -result {100} test item-20.18 {item tag: expr} -body { llength [.t item id "tag b"] } -result {9900} test item-20.19 {item tag: remove e from 100 items, overlapping 50 of !b items} -body { .t item tag remove {range 150 249} e llength [.t item id "tag !e"] } -result {100} test item-20.20 {item tag: expr} -body { llength [.t item id "tag {(!b || !e)}"] } -result {150} test item-20.21 {item tag: expr} -body { llength [.t item id "tag b^e"] } -result {100} test item-20.22 {item tag: expr} -body { .t item tag remove {tag !b||!e} {a c d f g h} llength [.t item id "tag !a"] } -result {150} test item-20.23 {item tag: item create -tags} -body { .t item create -count 50 -tags {orphan50 x y z} llength [.t item id "tag x"] } -result {50} test item-20.24 {item tag: item create -tags with dups} -body { .t item create -count 10 -tags {orphan10 x z x y z y} lsort [.t item tag names "tag orphan10"] } -result {orphan10 x y z} test item-20.40 {item tag: [expr]} -body { .t item tag expr "tag orphan50" x } -result {1} test item-20.41 {item tag: [expr]} -body { .t item tag expr "all tag orphan50" x&&y&&z } -result {1} test item-20.42 {item tag: [expr]} -body { .t item tag expr "tag orphan50" a } -result {0} test item-20.43 {item tag: [expr]} -body { .t item tag expr 100 e^b } -cleanup { .t item delete all } -result {1} test item-21.1 {item count: too many args} -body { .t item count a b } -returnCodes error -result {wrong # args: should be ".t item count ?itemDesc?"} test item-21.2 {item count: no args, only root} -body { .t item count } -result {1} test item-21.2 {item count: no args, many items} -setup { .t item create -count 50 -parent root } -body { .t item count } -result {51} test item-21.3 {item count: double-check with range} -body { expr {[.t item count] == [llength [.t item range first last]]} } -result {1} test item-21.4 {item count: double-check with range} -body { expr {[.t item count] == [.t item count "range first last"]} } -result {1} test item-21.5 {item count: all is same as no args} -body { expr {[.t item count] == [.t item count all]} } -result {1} test item-21.6 {item count: depth test} -body { .t item count "depth 1" } -result {50} test item-21.7 {item count: double-check with selection} -setup { .t selection add "range 10 20" } -body { expr {[.t item count "state selected"] == [.t selection count]} } -result {1} test item-22.1 {-button: default value} -setup { .t item delete all .t item create -tags foo } -body { .t item cget foo -button } -result {0} test item-22.2 {-button: default value} -body { .t item cget foo -button } -result {0} test item-22.3 {-button: set true} -body { .t item conf foo -button true .t item cget foo -button } -result {1} test item-22.4 {-button: set true} -body { .t item conf foo -button ON .t item cget foo -button } -result {1} test item-22.5 {-button: set false} -body { .t item conf foo -button NO .t item cget foo -button } -result {0} test item-22.6 {-button: set auto} -body { .t item conf foo -button auto .t item cget foo -button } -result {auto} test item-22.7 {-button: set auto abbreviation} -body { .t item conf foo -button a .t item cget foo -button } -result {auto} test item-99.1 {some needed cleanup} -body { destroy .t } -result {} # cleanup ::tcltest::cleanupTests return tktreectrl-2.2.8/tests/itemdesc.test0000700000175600010010000003401210715750564015756 0ustar TimNone# Commands covered: item descriptions # # This file contains a collection of tests for the treectrl command of # the tktreectrl extension. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 2000 by Scriptics Corporation. # Copyright (c) 2002 by Christian Krone. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: itemdesc.test,v 1.3 2007/11/12 04:07:16 treectrl Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import ::tcltest::* } package require Tk package require treectrl # For the tests of the item descriptions we use [.t see], # if we want to generate an error on unknown items. # For the positive cases we use [.t item id] since it returns the item id. test itemdesc-0.1 {some needed preparations} -body { treectrl .t -itemheight 20 -showheader no .t column create -width 200 pack .t -expand yes -fill both update idletasks } -result {} test itemdesc-1.1 {bogus itemdesc} -body { .t item id "" } -returnCodes error -result {bad item description ""} test itemdesc-1.1.1 {bogus itemdesc} -body { .t item id "\{all" } -returnCodes error -result "bad item description \"\{all\"" test itemdesc-1.2 {all} -setup { .t item create -count 10 } -body { lsort -integer [.t item id all] } -cleanup { .t item delete all } -result {0 1 2 3 4 5 6 7 8 9 10} test itemdesc-1.3 {unknown id} -body { .t see 999 } -returnCodes error -result {item "999" doesn't exist} test itemdesc-1.4 {id of root} -body { .t item id 0 } -result {0} test itemdesc-1.5 {id of active} -body { .t item id active } -result {0} test itemdesc-1.6 {id of anchor (abbreviated)} -body { .t item id an } -result {0} test itemdesc-1.7 {first} -body { .t item id first } -result {0} test itemdesc-1.8 {first visible} -setup { .t configure -showroot 1 } -body { .t item id "first visible" } -result {0} test itemdesc-1.9 {first visible without any node} -setup { .t configure -showroot 0 } -body { .t see "first visible" } -returnCodes error -result {item "first visible" doesn't exist} test itemdesc-1.10 {last} -body { .t item id last } -result {0} test itemdesc-1.10.1 {end} -body { .t item id end } -result {0} test itemdesc-1.11 {last visible} -setup { .t configure -showroot 1 } -body { .t item id "last visible" } -result {0} test itemdesc-1.12 {last visible without any node} -setup { .t configure -showroot 0 } -body { .t see "last visible" } -returnCodes error -result {item "last visible" doesn't exist} test itemdesc-1.13 {nearest without x/y} -body { .t item id nearest } -returnCodes error -result {missing arguments to "nearest" keyword} test itemdesc-1.14 {nearest with invalid x/y} -body { .t item id "nearest foo bar" } -returnCodes error -result {bad screen distance "foo"} test itemdesc-1.15 {nearest with valid x/y} -setup { .t configure -showroot 1 } -body { .t item id "nearest 10 10" } -result {0} test itemdesc-1.16 {nearest with valid x/y, but no item} -setup { .t configure -showroot 0 } -body { .t item id "nearest 10 10" } -result {} # Before continuing to test the item descriptions and their modifiers, # lets create some items with this hierarchy: # 0 # + 1 # | + 2 # | + 3 # | + 4 # + 5 # | + 6 # | + 7 # + 8 test itemdesc-2.16 {create some items} -body { set n1 [.t item create]; .t item lastchild 0 $n1 set n2 [.t item create]; .t item lastchild $n1 $n2 set n3 [.t item create]; .t item lastchild $n1 $n3 set n4 [.t item create]; .t item lastchild $n3 $n4 set n5 [.t item create]; .t item lastchild 0 $n5 set n6 [.t item create]; .t item lastchild $n5 $n6 set n7 [.t item create]; .t item lastchild $n5 $n7 set n8 [.t item create]; .t item lastchild 0 $n8 } -result {8} test itemdesc-2.18 {rnc without r/c} -body { .t item id rnc } -returnCodes error -result {missing arguments to "rnc" keyword} test itemdesc-2.19 {rnc with invalid r/c} -body { .t item id "rnc foo bar" } -returnCodes error -result {expected integer but got "foo"} test itemdesc-2.20 {rnc with valid r/c} -body { .t item id "rnc 0 0" } -result {1} test itemdesc-2.21 {root} -body { .t configure -showroot 1 -orient vertical .t item id root } -result {0} test itemdesc-2.22 {bogus modifier} -body { .t item id "0 foo" } -returnCodes error -result {bad modifier "foo": must be *} -match glob test itemdesc-2.23 {valid modifier with too few arguments} -body { .t item id "0 child" } -returnCodes error -result {missing arguments to "child" modifier} test itemdesc-2.24 {modifier visible alone generates an error} -body { .t item id "0 visible" } -returnCodes error -result {bad modifier "visible": must be *} -match glob test itemdesc-2.25 {modifier above} -body { set res {} for {set n 0} {$n < 9} {incr n} { lappend res [.t item id "$n above"] } set res } -result {{} 0 1 2 3 4 5 6 7} test itemdesc-2.26 {modifier below} -body { set res {} for {set n 0} {$n < 9} {incr n} { lappend res [.t item id "$n below"] } set res } -result {1 2 3 4 5 6 7 8 {}} test itemdesc-2.27 {modifier bottom} -body { set res {} for {set n 0} {$n < 9} {incr n} { lappend res [.t item id "$n bottom"] } set res } -result {8 8 8 8 8 8 8 8 8} test itemdesc-2.28 {modifier child} -body { set res {} for {set n 0} {$n < 6} {incr n} { for {set c 0} {$c < 3} {incr c} { lappend res [.t item id "$n child $c"] } } set res } -result {1 5 8 2 3 {} {} {} {} 4 {} {} {} {} {} 6 7 {}} test itemdesc-2.29 {modifier firstchild} -body { set res {} for {set n 0} {$n < 9} {incr n} { lappend res [.t item id "$n firstchild"] } set res } -result {1 2 {} 4 {} 6 {} {} {}} test itemdesc-2.30 {modifier lastchild} -body { set res {} for {set n 0} {$n < 9} {incr n} { lappend res [.t item id "$n lastchild"] } set res } -result {8 3 {} 4 {} 7 {} {} {}} test itemdesc-2.30 {modifier left, leftmost, right, and rightmost} -body { list [.t item id "1 left"] [.t item id "1 right"] \ [.t item id "2 leftmost"] [.t item id "3 rightmost"] } -result {{} {} 2 3} test itemdesc-2.31 {modifier next} -body { set res {} for {set n 0} {$n < 9} {incr n} { lappend res [.t item id "$n next"] } set res } -result {1 2 3 4 5 6 7 8 {}} test itemdesc-2.32 {modifier nextsibling} -body { set res {} for {set n 0} {$n < 9} {incr n} { lappend res [.t item id "$n nextsibling"] } set res } -result {{} 5 3 {} {} 8 7 {} {}} test itemdesc-2.33 {modifier parent} -body { set res {} for {set n 0} {$n < 9} {incr n} { lappend res [.t item id "$n parent"] } set res } -result {{} 0 1 1 3 0 5 5 0} test itemdesc-2.34 {modifier prev} -body { set res {} for {set n 0} {$n < 9} {incr n} { lappend res [.t item id "$n prev"] } set res } -result {{} 0 1 2 3 4 5 6 7} test itemdesc-2.34 {modifier prevsibling} -body { set res {} for {set n 0} {$n < 9} {incr n} { lappend res [.t item id "$n prevsibling"] } set res } -result {{} {} {} 2 {} 1 {} 6 5} test itemdesc-2.35 {modifier sibling} -body { set res {} for {set n 0} {$n < 7} {incr n} { for {set c 0} {$c < 3} {incr c} { lappend res [.t item id "$n sibling $c"] } } set res } -result {{} {} {} 1 5 8 2 3 {} 2 3 {} 4 {} {} 1 5 8 6 7 {}} test itemdesc-2.36 {modifier top} -body { set res {} for {set n 0} {$n < 9} {incr n} { lappend res [.t item id "$n top"] } set res } -result {0 0 0 0 0 0 0 0 0} test itemdesc-2.37 {modifier cocktail} -body { set res {} set itemDesc 7 foreach mod { bottom rightmost sibling 0 nextsibling prev parent prevsibling prev nextsibling lastchild next } { lappend itemDesc $mod catch {lappend res [.t item id $itemDesc]} } set res } -result {8 8 1 5 4 3 2 1 5 7 8} test itemdesc-2.38 {multiple items: list} -body { .t item id "list {3 8 8}" } -result {3 8 8} test itemdesc-2.39 {multiple items: range} -body { .t item id "range 1 6" } -result {1 2 3 4 5 6} test itemdesc-2.40 {multiple items: range reversed} -body { .t item id "range 6 1" } -result {1 2 3 4 5 6} test itemdesc-2.41 {multiple items: ancestors} -body { .t item id "4 ancestors" } -result {3 1 0} test itemdesc-2.42 {multiple items: children} -body { .t item id "root children" } -result {1 5 8} test itemdesc-2.43 {multiple items: nested list} -body { .t item id "list {3 {list {1 root}} 4}" } -result {3 1 0 4} test itemdesc-2.44 {multiple items: descendants} -body { .t item id "1 descendants" } -result {2 3 4} # qualifiers in item descriptions test itemdesc-3.1 {where visible is allowed} -body { .t item collapse 3 .t item collapse 5 set res {} foreach index { first last } { lappend res [.t item id "$index visible"] } foreach modifier { next prev firstchild lastchild {child 1} nextsibling prevsibling {sibling 0} } { lappend res [.t item id "5 $modifier visible"] } set res } -result {0 8 8 3 {} {} {} 8 1 1} test itemdesc-3.2 {where state is allowed} -body { set res {} foreach index { first last } { lappend res [.t item id "$index state enabled"] } foreach modifier { next prev firstchild lastchild {child 0} nextsibling prevsibling {sibling 0} } { lappend res [.t item id "5 $modifier state enabled"] } set res } -result {0 8 6 4 6 7 6 8 1 1} test itemdesc-3.3 {qualifier state: missing args} -body { .t item id "first state" } -returnCodes error -result {missing arguments to "state" qualifier} test itemdesc-3.4 {qualifier state: unknown state} -body { .t item id "first state foo" } -returnCodes error -result {unknown state "foo"} test itemdesc-3.5 {qualifier state: toggle not allowed} -body { .t item id "first state ~open" } -returnCodes error -result {can't specify '~' for this command} test itemdesc-3.6 {qualifier state: open ok} -body { .t item id "first state open" } -result {0} test itemdesc-3.7 {qualifier state: !open ok} -body { set res {} lappend res [.t item id "first state !open"] lappend res [.t item id "last state !open"] } -result {3 5} test itemdesc-3.8 {qualifier state: multiple states} -body { .t item id "last state {open enabled active}" } -result {0} test itemdesc-3.9 {qualifier after index and modifier} -body { .t item id "first state !open next state !open" } -result {5} test itemdesc-3.10 {qualifier state: following each modifier} -body { set res {} foreach modifier { firstchild lastchild {child 0} } { lappend res [.t item id "root $modifier state !open"] } foreach modifier { next prev nextsibling prevsibling {sibling 0} } { lappend res [.t item id "1 $modifier state !open"] } .t item expand 3 .t item expand 5 set res } -result {5 5 5 3 {} 5 {} 5} test itemdesc-4.1 {modifiers following multiple items is forbidden} -body { .t item id "all children" } -returnCodes error -result {unexpected arguments after "all"} test itemdesc-4.2 {modifiers following multiple items is forbidden} -body { .t item id "all visible children" } -returnCodes error -result {unexpected arguments after "all visible"} test itemdesc-4.3 {modifiers following multiple items is forbidden} -body { .t item id "range 1 2 next" } -returnCodes error -result {unexpected arguments after "range 1 2"} test itemdesc-4.4 {modifiers following multiple items is forbidden} -body { .t item id "1 descendants next" } -returnCodes error -result {unexpected arguments after "1 descendants"} test itemdesc-4.5 {modifiers following multiple items is forbidden} -setup { .t item tag add "1 descendants" tagA } -body { lsort -integer [.t item id "tagA above"] } -cleanup { .t item tag remove all tagA } -returnCodes error -result {unexpected arguments after "tagA"} test itemdesc-4.10 {modifiers following single item ok} -setup { .t item tag add 3 tagA } -body { lsort -integer [.t item id "tagA above"] } -cleanup { .t item tag remove all tagA } -result {2} test itemdesc-5.1 {qualifiers may be first} -body { lsort -integer [.t item id "depth 1"] } -result {1 5 8} test itemdesc-5.2 {qualifiers may be first} -body { lsort -integer [.t item id "visible"] } -result {0 1 2 3 4 5 6 7 8} test itemdesc-5.3 {qualifiers may be first} -setup { .t item collapse 3 } -body { lsort -integer [.t item id "!visible"] } -cleanup { .t item expand 3 } -result {4} test itemdesc-5.4 {qualifiers may be first} -setup { .t item tag add "1 descendants" a } -body { lsort -integer [.t item id "tag a"] } -cleanup { .t item tag remove all a } -result {2 3 4} test itemdesc-5.5 {qualifiers may be first} -setup { .t item collapse {list {3 5}} } -body { lsort -integer [.t item id "state !open"] } -cleanup { .t item expand {list {3 5}} } -result {3 5} test itemdesc-6.1 {-itemprefix} -setup { .t configure -itemprefix item } -body { lsort -dictionary [.t item id "item1 descendants"] } -cleanup { .t configure -itemprefix "" } -result {item2 item3 item4} test itemdesc-6.2 {-itemprefix same as a tag} -setup { .t configure -itemprefix item .t item tag add all item1 } -body { lsort -dictionary [.t item id "item1 descendants"] } -cleanup { .t configure -itemprefix "" .t item tag remove all item1 } -result {item2 item3 item4} test itemdesc-7.1 {-itemtagexpr, error} -setup { .t item tag add "depth 1" a&&b|| } -body { lsort -dictionary [.t item id "tag a&&b||"] } -returnCodes error -result {Missing tag in tag search expression} test itemdesc-7.2 {-itemtagexpr, tag as first word} -setup { .t configure -itemtagexpr false } -body { lsort -dictionary [.t item id "a&&b||"] } -result {1 5 8} test itemdesc-7.3 {-itemtagexpr, tag as qualifier} -body { lsort -dictionary [.t item id "tag a&&b||"] } -cleanup { .t configure -itemtagexpr true .t item tag remove all a&&b|| } -result {1 5 8} test itemdesc-99.1 {some needed cleanup} -body { destroy .t } -result {} # cleanup ::tcltest::cleanupTests return tktreectrl-2.2.8/tests/notify-old.test0000700000175600010010000003274110265612313016241 0ustar TimNone# Commands covered: treectrl's widget command notify # # This file contains a collection of tests for the notify widget command of # the tktreectrl extension. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 2000 by Scriptics Corporation. # Copyright (c) 2002 by Christian Krone. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # CVS: @(#) $Id: notify-old.test,v 1.3 2005/07/15 01:43:39 treectrl Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import ::tcltest::* } package require Tk package require treectrl test notify-0.1 {some needed preparations} -body { treectrl .t } -result {.t} test notify-1.1 {notify: missing args} -body { .t notify } -returnCodes error -result {wrong # args: should be ".t notify command ?arg arg ...?"} test notify-1.2 {notify: unknown command} -body { .t notify foo } -returnCodes error -result {bad command "foo": must be *} -match glob test notify-2.1 {notify eventnames: too much args} -body { .t notify eventnames Open } -returnCodes error -result {wrong # args: should be ".t notify eventnames"} test notify-2.2 {notify eventnames: nothing own installed yet} -body { lsort [.t notify eventnames] } -result {ActiveItem Collapse Expand ItemDelete ItemVisibility Scroll Selection} test notify-2.3 {notify install: missing args} -body { .t notify install } -returnCodes error -result {wrong # args: should be ".t notify install pattern ?percentsCommand?"} test notify-2.4 {notify install: bad pattern} -body { .t notify install foo } -returnCodes error -result {missing "<" in event pattern "foo"} test notify-2.5 {notify install event: old-style missing args} -body { .t notify install event } -returnCodes error -result {wrong # args: should be ".t notify install event name ?percentsCommand?"} test notify-2.6 {notify install event: old-style too much args} -body { .t notify install event foo bar baz } -returnCodes error -result {wrong # args: should be ".t notify install event name ?percentsCommand?"} test notify-2.7 {notify install event} -body { .t notify install event Greetings .t notify install event GoodBye } -result {} test notify-2.8 {notify eventnames: list Greetings} -body { lsort [.t notify eventnames] } -result {ActiveItem Collapse Expand GoodBye Greetings ItemDelete ItemVisibility Scroll Selection} test notify-2.9 {notify detailnames: missing args} -body { .t notify detailnames } -returnCodes error -result {wrong # args: should be ".t notify detailnames eventName"} test notify-2.10 {notify detailnames: too many args} -body { .t notify detailnames foo bar } -returnCodes error -result {wrong # args: should be ".t notify detailnames eventName"} test notify-2.11 {notify detailnames: unknown event} -body { .t notify detailnames Hello } -returnCodes error -result {unknown event "Hello"} test notify-2.12 {notify detailnames: no details yet} -body { .t notify detailnames Greetings } -result {} test notify-2.13 {notify install detail: old-style missing args} -body { .t notify install detail } -returnCodes error -result {wrong # args: should be ".t notify install detail event detail ?percentsCommand?"} test notify-2.14 {notify install detail: old-style unknown event} -body { .t notify install detail Hello GoodBye } -returnCodes error -result {unknown event "Hello"} test notify-2.15 {notify install detail} -body { .t notify install detail Greetings Wrote .t notify install detail Greetings Sent } -result {} test notify-2.16 {notify detailnames} -body { lsort [.t notify detailnames Greetings] } -result {Sent Wrote} test notify-3.1 {notify linkage: missing args} -body { .t notify linkage } -returnCodes error -result {wrong # args: should be ".t notify linkage pattern"} test notify-3.2 {notify linkage: unknown event} -body { .t notify linkage foo } -returnCodes error -result {unknown event "foo"} test notify-3.3 {notify linkage: standard event} -body { .t notify linkage Scroll } -result {static} test notify-3.4 {notify linkage: self made event} -body { .t notify linkage Greetings } -result {dynamic} test notify-3.5 {notify linkage: unknown detail} -body { .t notify linkage Greetings foo } -returnCodes error -result {unknown detail "foo" for event "Greetings"} test notify-3.6 {notify linkage: standard event} -body { .t notify linkage Scroll x } -result {static} test notify-3.7 {notify linkage: self made event} -body { .t notify linkage Greetings Sent } -result {dynamic} test notify-4.1 {notify bind: too much args} -body { .t notify bind z y z z y } -returnCodes error -result {wrong # args: should be ".t notify bind ?object? ?pattern? ?script?"} test notify-4.2 {notify bind: nothing bound yet} -body { .t notify bind .t } -result {} test notify-4.3 {notify bind: invalid pattern} -body { .t notify bind .t Greetings } -returnCodes error -result {missing "<" in event pattern "Greetings"} test notify-4.4 {notify bind: unknown event} -body { .t notify bind .t } -returnCodes error -result {unknown event "Hello"} test notify-4.5 {notify bind: unknown detail} -body { .t notify bind .t } -returnCodes error -result {unknown detail "Prepare" for event "Greetings"} test notify-4.6 {notify bind: nothing yet for simple event} -body { .t notify bind .t } -result {} test notify-4.7 {notify bind: simple event} -body { .t notify bind .t {puts -nonewline "Bye bye"} } -result {} test notify-4.8 {notify bind: simple event, script added} -body { .t notify bind .t {+puts ""} } -result {} test notify-4.9 {notify bind: simple event defined} -body { .t notify bind .t } -result {puts -nonewline "Bye bye" puts ""} test notify-4.10 {notify bind: nothing yet for event with detail} -body { .t notify bind .t } -result {} test notify-4.11 {notify bind: event with detail} -body { .t notify bind .t {puts -nonewline "Hello World"} .t notify bind .t {puts ""} } -result {} test notify-4.12 {notify bind: event with detail defined} -body { .t notify bind .t } -result {puts ""} test notify-4.13 {notify bind without pattern} -body { lsort [.t notify bind .t] } -result { } test notify-5.1 {notify configure: missing args} -body { .t notify configure } -returnCodes error -result {wrong # args: should be ".t notify configure object pattern ?option? ?value? ?option value ...?"} test notify-5.2 {notify configure: unknown event} -body { .t notify configure .t } -returnCodes error -result {unknown event "Hello"} test notify-5.3 {notify configure: unknown event with detail} -body { .t notify configure .t } -returnCodes error -result {unknown event "Hello"} test notify-5.4 {notify configure: unbound event} -body { .t notify configure .t } -result {} test notify-5.5 {notify configure: unbound event with details} -body { .t notify configure .t } -result {} test notify-5.6 {notify configure: dynamic event} -body { .t notify configure .t } -result {-active 1} test notify-5.7 {notify configure: dynamic event} -body { .t notify configure .t -active 0 .t notify configure .t } -result {-active 0} test notify-6.1 {notify generate: missing args} -body { .t notify generate } -returnCodes error -result {wrong # args: should be ".t notify generate pattern ?charMap? ?percentsCommand?"} test notify-6.2 {notify generate: invalid event} -body { .t notify generate Greetings } -returnCodes error -result {missing "<" in event pattern "Greetings"} test notify-6.3 {notify generate: virtual event} -body { .t notify generate <> } -returnCodes error -result {unknown event ""} test notify-6.4 {notify generate: unknown event} -body { .t notify generate } -returnCodes error -result {unknown event "Hello"} test notify-6.5 {notify generate: unknown detail} -body { .t notify generate } -returnCodes error -result {unknown detail "Prepare" for event "Greetings"} test notify-6.6 {notify generate: missing detail} -body { .t notify generate } -returnCodes error -result {cannot generate "": missing detail} test notify-6.7 {notify generate: NOW!} -body { .t notify generate } -output {Hello World} test notify-6.8 {notify generate: not active} -body { .t notify generate } -result {} test notify-6.9 {notify generate: and AGAIN!} -body { .t notify configure .t -active 1 .t notify generate } -output { } test notify-6.10 {notify generate: invalid percent char} -body { .t notify generate {foo bar} } -returnCodes error -result {invalid percent char "foo"} test notify-6.11 {notify generate: odd number of field args} -body { .t notify generate f } -returnCodes error -result {char map must have even number of elements} test notify-6.12 {notify generate: huge number of field args} -body { for {set x 1} {$x < 2048} {incr x} { lappend map f $x } .t notify generate $map } -output { } test notify-6.13 {notify generate: not so much field args} -body { .t notify generate \ {0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j X x} } -output { } test notify-6.14 {notify install/bind/generate: do some replacements} -body { .t notify install event Percent .t notify install detail Percent Test .t notify bind .t \ {puts -nonewline "%%W: %2 %b %| %~ %2 %b%%"} .t notify generate {2 to b be ~ not | or} } -output {%W: to be or not to be%} proc doMyOwnSubst {field window eventName detail args} { return [string map {2 TO b BE ~ NOT | OR} $field] } test notify-6.15 {notify install/bind/generate: my own replacements} -body { .t notify uninstall detail Percent Test .t notify install detail Percent Test doMyOwnSubst .t notify bind .t \ {puts -nonewline "%%W: %2 %b %| %~ %2 %b%%"} .t notify generate } -output {%W: TO BE OR NOT TO BE%} test notify-6.16 {notify install/bind/generate: standard replacements} -body { .t notify generate {2 to b be ~ not | or} } -output {%W: TO BE OR NOT TO BE%} test notify-6.17 {notify install/bind/generate: my own replacements} -body { .t notify uninstall detail Percent Test .t notify uninstall event Percent .t notify install event Percent doMyOwnSubst .t notify bind .t \ {puts -nonewline "%%W: %2 %b %| %~ %2 %b%%"} .t notify generate } -output {%W: TO BE OR NOT TO BE%} test notify-6.18 {notify install/bind/generate: standard replacements} -body { .t notify generate {2 to b be ~ not | or} } -output {%W: TO BE OR NOT TO BE%} test notify-7.1 {notify uninstall: missing args} -body { .t notify uninstall } -returnCodes error -result {wrong # args: should be ".t notify uninstall pattern"} test notify-7.2 {notify uninstall: unknown command} -body { .t notify uninstall foo } -returnCodes error -result {missing "<" in event pattern "foo"} test notify-7.3 {notify uninstall detail: missing args} -body { .t notify uninstall detail } -returnCodes error -result {wrong # args: should be ".t notify uninstall detail event detail"} test notify-7.4 {notify uninstall detail: too much args} -body { .t notify uninstall detail foo bar baz } -returnCodes error -result {wrong # args: should be ".t notify uninstall detail event detail"} test notify-7.5 {notify uninstall detail: unknown event} -body { .t notify uninstall detail foo bar } -returnCodes error -result {unknown event "foo"} test notify-7.6 {notify uninstall detail: unknown detail} -body { .t notify uninstall detail Greetings GoodBye } -returnCodes error -result {unknown detail "GoodBye" for event "Greetings"} test notify-7.7 {notify uninstall detail} -body { .t notify uninstall detail Greetings Sent } -result {} test notify-7.8 {notify uninstall detail: double check} -body { lsearch -exact [.t notify detailnames Greetings] Sent } -result {-1} test notify-7.9 {notify uninstall detail: delete a static detail} -body { .t notify uninstall detail Scroll x } -returnCodes error -result {can't uninstall static detail "x"} test notify-7.10 {notify uninstall event: missing args} -body { .t notify uninstall event } -returnCodes error -result {wrong # args: should be ".t notify uninstall event name"} test notify-7.11 {notify uninstall event: too much args} -body { .t notify uninstall event foo bar } -returnCodes error -result {wrong # args: should be ".t notify uninstall event name"} test notify-7.12 {notify uninstall event: unknown event} -body { .t notify uninstall event foo } -returnCodes error -result {unknown event "foo"} test notify-7.13 {notify uninstall event} -body { .t notify uninstall event Greetings } -result {} test notify-7.14 {notify uninstall event: double check} -body { lsearch -exact [.t notify eventnames] Greetings } -result {-1} test notify-7.15 {notify uninstall event: delete a static event} -body { .t notify uninstall event Scroll } -returnCodes error -result {can't uninstall static event "Scroll"} test notify-99.1 {some needed cleanup} -body { destroy .t } -result {} # cleanup ::tcltest::cleanupTests return tktreectrl-2.2.8/tests/notify.test0000700000175600010010000003164010536347762015500 0ustar TimNone# Commands covered: treectrl's widget command notify # # This file contains a collection of tests for the notify widget command of # the tktreectrl extension. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 2000 by Scriptics Corporation. # Copyright (c) 2002 by Christian Krone. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # CVS: @(#) $Id: notify.test,v 1.6 2006/12/08 20:49:54 treectrl Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import ::tcltest::* } package require Tk package require treectrl test notify-0.1 {some needed preparations} -body { treectrl .t } -result {.t} test notify-1.1 {notify: missing args} -body { .t notify } -returnCodes error -result {wrong # args: should be ".t notify command ?arg arg ...?"} test notify-1.2 {notify: unknown command} -body { .t notify foo } -returnCodes error -result {bad command "foo": must be *} -match glob test notify-2.1 {notify eventnames: too much args} -body { .t notify eventnames Open } -returnCodes error -result {wrong # args: should be ".t notify eventnames"} test notify-2.2 {notify eventnames: nothing own installed yet} -body { lsort [.t notify eventnames] } -result {ActiveItem Collapse Expand ItemDelete ItemVisibility Scroll Selection} test notify-2.3 {notify install: missing args} -body { .t notify install } -returnCodes error -result {wrong # args: should be ".t notify install pattern ?percentsCommand?"} test notify-2.4 {notify install: bad pattern} -body { .t notify install foo } -returnCodes error -result {missing "<" in event pattern "foo"} test notify-2.6 {notify install event: too much args} -body { .t notify install bar baz } -returnCodes error -result {wrong # args: should be ".t notify install pattern ?percentsCommand?"} test notify-2.7 {notify install event} -body { .t notify install .t notify install } -result {} test notify-2.8 {notify eventnames: list Greetings} -body { lsort [.t notify eventnames] } -result {ActiveItem Collapse Expand GoodBye Greetings ItemDelete ItemVisibility Scroll Selection} test notify-2.9 {notify detailnames: missing args} -body { .t notify detailnames } -returnCodes error -result {wrong # args: should be ".t notify detailnames eventName"} test notify-2.10 {notify detailnames: too many args} -body { .t notify detailnames foo bar } -returnCodes error -result {wrong # args: should be ".t notify detailnames eventName"} test notify-2.11 {notify detailnames: unknown event} -body { .t notify detailnames Hello } -returnCodes error -result {unknown event "Hello"} test notify-2.12 {notify detailnames: no details yet} -body { .t notify detailnames Greetings } -result {} test notify-2.15 {notify install detail} -body { .t notify install .t notify install } -result {} test notify-2.16 {notify detailnames} -body { lsort [.t notify detailnames Greetings] } -result {Sent Wrote} test notify-3.1 {notify linkage: missing args} -body { .t notify linkage } -returnCodes error -result {wrong # args: should be ".t notify linkage pattern"} test notify-3.2 {notify linkage: unknown event} -body { .t notify linkage } -returnCodes error -result {unknown event "foo"} test notify-3.3 {notify linkage: standard event} -body { .t notify linkage } -result {static} test notify-3.4 {notify linkage: self made event} -body { .t notify linkage } -result {dynamic} test notify-3.5 {notify linkage: unknown detail} -body { .t notify linkage } -returnCodes error -result {unknown detail "foo" for event "Greetings"} test notify-3.6 {notify linkage: standard event} -body { .t notify linkage } -result {static} test notify-3.7 {notify linkage: self made event} -body { .t notify linkage } -result {dynamic} test notify-4.1 {notify bind: too much args} -body { .t notify bind z y z z y } -returnCodes error -result {wrong # args: should be ".t notify bind ?object? ?pattern? ?script?"} test notify-4.2 {notify bind: nothing bound yet} -body { .t notify bind .t } -result {} test notify-4.3 {notify bind: invalid pattern} -body { .t notify bind .t Greetings } -returnCodes error -result {missing "<" in event pattern "Greetings"} test notify-4.4 {notify bind: unknown event} -body { .t notify bind .t } -returnCodes error -result {unknown event "Hello"} test notify-4.5 {notify bind: unknown detail} -body { .t notify bind .t } -returnCodes error -result {unknown detail "Prepare" for event "Greetings"} test notify-4.6 {notify bind: nothing yet for simple event} -body { .t notify bind .t } -result {} test notify-4.7 {notify bind: simple event} -body { .t notify bind .t {puts -nonewline "Bye bye"} } -result {} test notify-4.8 {notify bind: simple event, script added} -body { .t notify bind .t {+puts ""} } -result {} test notify-4.9 {notify bind: simple event defined} -body { .t notify bind .t } -result {puts -nonewline "Bye bye" puts ""} test notify-4.10 {notify bind: nothing yet for event with detail} -body { .t notify bind .t } -result {} test notify-4.11 {notify bind: event with detail} -body { .t notify bind .t {puts -nonewline "Hello World"} .t notify bind .t {puts ""} } -result {} test notify-4.12 {notify bind: event with detail defined} -body { .t notify bind .t } -result {puts ""} test notify-4.13 {notify bind without pattern} -body { lsort [.t notify bind .t] } -result { } test notify-5.1 {notify configure: missing args} -body { .t notify configure } -returnCodes error -result {wrong # args: should be ".t notify configure object pattern ?option? ?value? ?option value ...?"} test notify-5.2 {notify configure: unknown event} -body { .t notify configure .t } -returnCodes error -result {unknown event "Hello"} test notify-5.3 {notify configure: unknown event with detail} -body { .t notify configure .t } -returnCodes error -result {unknown event "Hello"} test notify-5.4 {notify configure: unbound event} -body { .t notify configure .t } -result {} test notify-5.5 {notify configure: unbound event with details} -body { .t notify configure .t } -result {} test notify-5.6 {notify configure: dynamic event} -body { .t notify configure .t } -result {-active 1} test notify-5.7 {notify configure: dynamic event} -body { .t notify configure .t -active 0 .t notify configure .t } -result {-active 0} test notify-6.1 {notify generate: missing args} -body { .t notify generate } -returnCodes error -result {wrong # args: should be ".t notify generate pattern ?charMap? ?percentsCommand?"} test notify-6.2 {notify generate: invalid event} -body { .t notify generate Greetings } -returnCodes error -result {missing "<" in event pattern "Greetings"} test notify-6.3 {notify generate: virtual event} -body { .t notify generate <> } -returnCodes error -result {unknown event ""} test notify-6.4 {notify generate: unknown event} -body { .t notify generate } -returnCodes error -result {unknown event "Hello"} test notify-6.5 {notify generate: unknown detail} -body { .t notify generate } -returnCodes error -result {unknown detail "Prepare" for event "Greetings"} test notify-6.6 {notify generate: missing detail} -body { .t notify generate } -returnCodes error -result {cannot generate "": missing detail} test notify-6.7 {notify generate: NOW!} -body { .t notify generate } -output {Hello World} test notify-6.8 {notify generate: not active} -body { .t notify generate } -result {} test notify-6.9 {notify generate: and AGAIN!} -body { .t notify configure .t -active 1 .t notify generate } -output { } test notify-6.10 {notify generate: invalid percent char} -body { .t notify generate {foo bar} } -returnCodes error -result {invalid percent char "foo"} test notify-6.11 {notify generate: odd number of field args} -body { .t notify generate f } -returnCodes error -result {char map must have even number of elements} test notify-6.12 {notify generate: huge number of field args} -body { for {set x 1} {$x < 2048} {incr x} { lappend map f $x } .t notify generate $map } -output { } test notify-6.13 {notify generate: not so much field args} -body { .t notify generate \ {0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j X x} } -output { } test notify-6.14 {notify install/bind/generate: do some replacements} -body { .t notify install .t notify bind .t \ {puts -nonewline "%%W: %2 %b %| %~ %2 %b%%"} .t notify generate {2 to b be ~ not | or} } -output {%W: to be or not to be%} proc doMyOwnSubst {char object eventName detail charMap} { return [string map {2 TO b BE ~ NOT | OR} $char] } test notify-6.15 {notify install/bind/generate: my own replacements} -body { .t notify install doMyOwnSubst .t notify bind .t \ {puts -nonewline "%%W: %2 %b %| %~ %2 %b%%"} .t notify generate } -output {%W: TO BE OR NOT TO BE%} test notify-6.16 {notify install/bind/generate: standard replacements} -body { .t notify generate {2 to b be ~ not | or} } -output {%W: TO BE OR NOT TO BE%} test notify-6.17 {notify install/bind/generate: my own replacements} -body { .t notify uninstall .t notify install doMyOwnSubst .t notify bind .t \ {puts -nonewline "%%W: %2 %b %| %~ %2 %b%%"} .t notify generate } -output {%W: TO BE OR NOT TO BE%} test notify-6.18 {notify install/bind/generate: standard replacements} -body { .t notify generate {2 to b be ~ not | or} } -output {%W: TO BE OR NOT TO BE%} test notify-7.1 {notify uninstall: missing args} -body { .t notify uninstall } -returnCodes error -result {wrong # args: should be ".t notify uninstall pattern"} test notify-7.2 {notify uninstall: unknown command} -body { .t notify uninstall foo } -returnCodes error -result {missing "<" in event pattern "foo"} test notify-7.4 {notify uninstall: too much args} -body { .t notify uninstall foo bar } -returnCodes error -result {wrong # args: should be ".t notify uninstall pattern"} test notify-7.5 {notify uninstall detail: unknown event} -body { .t notify uninstall } -returnCodes error -result {unknown event "foo"} test notify-7.6 {notify uninstall detail: unknown detail} -body { .t notify uninstall } -returnCodes error -result {unknown detail "GoodBye" for event "Greetings"} test notify-7.7 {notify uninstall detail} -body { .t notify uninstall } -result {} test notify-7.8 {notify uninstall detail: double check} -body { lsearch -exact [.t notify detailnames Greetings] Sent } -result {-1} test notify-7.9 {notify uninstall detail: delete a static detail} -body { .t notify uninstall } -returnCodes error -result {can't uninstall static detail "x"} test notify-7.12 {notify uninstall event: unknown event} -body { .t notify uninstall } -returnCodes error -result {unknown event "foo"} test notify-7.13 {notify uninstall event} -body { .t notify uninstall } -result {} test notify-7.14 {notify uninstall event: double check} -body { lsearch -exact [.t notify eventnames] Greetings } -result {-1} test notify-7.15 {notify uninstall event: delete a static event} -body { .t notify uninstall } -returnCodes error -result {can't uninstall static event "Scroll"} test notify-8.1 {: set firstchild of a deleted item} -setup { .t item create -count 3 ; # item ids 1, 2 and 3 .t notify bind notify-8 { .t item firstchild %i 2 } set ::error {} proc bgerror msg {set ::error $msg} } -body { .t item delete 1 update ; # background error during set ::error } -cleanup { rename bgerror {} } -result {item 1 is being deleted} test notify-8.2 {: set firstchild to a deleted item} -setup { .t notify bind notify-8 { .t item firstchild 2 %i } set ::error {} proc bgerror msg {set ::error $msg} } -body { .t item delete 3 update ; # background error during set ::error } -cleanup { rename bgerror {} } -result {item 3 is being deleted} test notify-99.1 {some needed cleanup} -body { destroy .t } -result {} # cleanup ::tcltest::cleanupTests return tktreectrl-2.2.8/tests/style.test0000700000175600010010000002057110554773310015321 0ustar TimNone# Commands covered: treectrl's widget command style # # This file contains a collection of tests for the style widget command of # the tktreectrl extension. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 2000 by Scriptics Corporation. # Copyright (c) 2002 by Christian Krone. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # CVS: @(#) $Id: style.test,v 1.8 2007/01/21 23:27:04 treectrl Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import ::tcltest::* } package require Tk package require treectrl test style-0.1 {some needed preparations} -body { pack [treectrl .t] } -result {} test style-0.1 {some other preparations} -body { .t element create eBorder border .t element create eText text .t element create eImage image .t element create eRect rect list } -result {} test style-1.1 {style: missing args} -body { .t style } -returnCodes error -result {wrong # args: should be ".t style command ?arg arg ...?"} test style-1.2 {style: invalid command} -body { .t style foo } -returnCodes error -result {bad command "foo": must be *} -match glob test style-1.3 {style names: no style exists yet} -body { .t style names } -result {} test style-2.1 {style create: missing args} -body { .t style create } -returnCodes error -result {wrong # args: should be ".t style create name ?option value ...?"} test style-2.2 {style create: invalid option} -body { .t style create testStyle -foo bar } -returnCodes error -result {unknown option "-foo"} test style-2.3 {style create} -body { .t style create testStyle } -result {testStyle} test style-2.4 {style create: already existing style} -body { .t style create testStyle } -returnCodes error -result {style "testStyle" already exists} test style-3.1 {style configure: invalid option} -body { .t style configure testStyle -foo bar } -returnCodes error -result {unknown option "-foo"} test style-3.2 {style configure: all options} -body { .t style configure testStyle } -result {{-orient {} {} horizontal horizontal}} test style-3.3 {style configure: the only option} -body { .t style configure testStyle -orient } -result {-orient {} {} horizontal horizontal} test style-3.4 {style configure: invalid option -orient} -body { .t style configure testStyle -orient diagonal } -returnCodes error -result {bad orient "diagonal": must be horizontal or vertical} test style-3.5 {style configure/cget: option -orient} -body { .t style configure testStyle -orient vertical .t style cget testStyle -orient } -result {vertical} test style-4.1 {style delete: unknown style} -body { .t style delete testStyle2 } -returnCodes error -result {style "testStyle2" doesn't exist} test style-4.2 {style delete: unknown style} -body { .t style names } -result {testStyle} test style-4.3 {style delete} -body { .t style delete testStyle } -result {} test style-4.4 {style names: no style defined} -body { .t style names } -result {} test style-5.1 {style elements: missing args} -body { .t style elements } -returnCodes error -result {wrong # args: should be ".t style elements name ?elementList?"} test style-5.2 {style elements: unknown style} -body { .t style elements testStyle } -returnCodes error -result {style "testStyle" doesn't exist} test style-5.3 {style elements: no element yet} -body { .t style create testStyle .t style elements testStyle } -result {} test style-5.4 {style elements: empty element list} -body { .t style elements testStyle {} } -result {} test style-5.5 {style elements: add some elements} -setup { # Create some items using the style. # FIXME: add test to ensure the item-column styles are updated. .t column create .t item create -count 100 -parent root .t item style set all 0 testStyle } -body { .t style elements testStyle {eBorder eImage eText} .t style elements testStyle } -result {eBorder eImage eText} test style-5.6 {style elements: duplicate elements are ignored} -body { .t style elements testStyle {eBorder eImage eImage eText} .t style elements testStyle } -result {eBorder eImage eText} test style-5.7 {style elements: duplicate elements are ignored} -body { .t style elements testStyle {eBorder eImage eText eImage} .t style elements testStyle } -result {eBorder eImage eText} test style-5.8 {style elements: rearrange elements} -body { .t style elements testStyle {eText eImage eBorder} .t style elements testStyle } -result {eText eImage eBorder} test style-5.9 {style elements: remove elements} -body { .t style elements testStyle {eImage} .t style elements testStyle } -result {eImage} test style-5.10 {style elements: add elements} -body { .t style elements testStyle {eBorder eText eImage} .t style elements testStyle } -result {eBorder eText eImage} test style-6.1 {style layout: missing args} -body { .t style layout } -returnCodes error -result {wrong # args: should be ".t style layout name element ?option? ?value? ?option value ...?"} test style-6.2 {style layout: no options specified} -body { .t style layout testStyle eText } -result {-detach no -draw {} -expand {} -height {} -iexpand {} *} -match glob test style-6.3 {style layout: option -padx} -body { .t style layout testStyle eText -padx 3 .t style layout testStyle eText -padx } -result {3} test style-6.4 {style layout: invalid 2 element -pady} -body { .t style layout testStyle eText -pady {3 ""} } -returnCodes error -result {bad pad amount "3 """: must be a list of 1 or 2 positive screen distances} test style-6.5 {style layout: invalid 2 element -pady} -body { .t style layout testStyle eText -pady "\{" } -returnCodes error -result {unmatched open brace in list} test style-6.6 {style layout: invalid 2 element -pady} -body { .t style layout testStyle eText -pady {3 -7} } -returnCodes error -result {bad pad amount "3 -7": must be a list of 1 or 2 positive screen distances} test style-6.7 {style layout: invalid 2 element -pady} -body { .t style layout testStyle eText -pady {3 7} .t style layout testStyle eText -pady } -result {3 7} test style-6.8 {style layout: option -expand} -body { .t style layout testStyle eText -expand "hello world" } -returnCodes error -result {bad expand value "hello world": must be a string containing zero or more of n, e, s, and w} test style-6.9 {style layout: option -expand} -body { .t style layout testStyle eText -expand ew .t style layout testStyle eText -expand } -result {we} test style-6.10 {style layout: option -squeeze} -body { .t style layout testStyle eText -squeeze xyzzy } -returnCodes error -result {bad squeeze value "xyzzy": must be a string containing zero or more of x and y} test style-6.11 {style layout: option -squeeze} -body { .t style layout testStyle eText -squeeze xy .t style layout testStyle eText -squeeze } -result {xy} test style-6.12 {style layout: option -union invalid list} -body { .t style layout testStyle eText -union "\{" } -returnCodes error -result {unmatched open brace in list} test style-6.13 {style layout: option -union unknown elements} -body { .t style layout testStyle eText -union {foo bar} } -returnCodes error -result {element "foo" doesn't exist} test style-6.14 {style layout: option -union element not in style} -body { .t style layout testStyle eText -union {eBorder eRect} } -returnCodes error -result {style testStyle does not use element eRect} test style-6.15 {style layout: option -union with itself} -body { .t style layout testStyle eText -union {eBorder eText} } -returnCodes error -result {element eText can't form union with itself} test style-6.16 {style layout: option -union} -body { .t style layout testStyle eText -union {eBorder eImage} .t style layout testStyle eText -union } -result {eBorder eImage} test style-6.17 {style layout: option invalid -detach} -body { .t style layout testStyle eText -detach {x y} } -returnCodes error -result {expected boolean value but got "x y"} test style-6.18 {style layout: option -detach} -body { .t style layout testStyle eText -detach true .t style layout testStyle eText -detach } -result {yes} test style-99.1 {some needed cleanup} -body { destroy .t } -result {} # cleanup ::tcltest::cleanupTests return tktreectrl-2.2.8/tests/treectrl.test0000700000175600010010000006533510534414663016015 0ustar TimNone# Commands covered: treectrl # # This file contains a collection of tests for the treectrl command of # the tktreectrl extension. Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 2000 by Scriptics Corporation. # Copyright (c) 2002 by Christian Krone. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: treectrl.test,v 1.34 2006/12/03 00:26:27 treectrl Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 namespace import ::tcltest::* } package require Tk package require treectrl test treectrl-1.1 {Usage} -body { treectrl } -returnCodes error -result {wrong # args: should be "treectrl pathName ?options?"} test treectrl-1.2 {Unknown option} -body { treectrl .t -foo bar } -returnCodes error -result {unknown option "-foo"} test treectrl-1.3 {Create a tree} -body { treectrl .t } -result {.t} test treectrl-1.4 {configure: List all options} -body { .t configure } -result {{-background background Background white *}*} -match glob test treectrl-1.5 {configure -background with totally empty visible tree} -body { pack .t -expand yes -fill both update idletasks .t configure -background white update idletasks } -result {} test treectrl-1.6 {configure: -background option} -body { .t configure -background yellow .t configure -background } -result {-background background Background white yellow} test treectrl-1.7 {configure: invalid -backgroundmode option} -body { .t configure -backgroundmode foo } -returnCodes error -result {bad backgroundmode "foo": must be column, order, ordervisible, row, index, or visindex} test treectrl-1.8 {configure: -backgroundmode option} -body { .t configure -backgroundmode column .t configure -backgroundmode } -result {-backgroundmode backgroundMode BackgroundMode row column} test treectrl-1.9 {configure: invalid -buttonsize option} -body { .t configure -buttonsize foo } -returnCodes error -result {bad screen distance "foo"} test treectrl-1.10 {configure: -buttonsize option} -body { .t configure -buttonsize 1c .t configure -buttonsize } -result {-buttonsize buttonSize ButtonSize 9 1c} test treectrl-1.11 {configure: invalid -buttoncolor option} -body { .t configure -buttoncolor foo } -returnCodes error -result {unknown color name "foo"} test treectrl-1.12 {configure: -buttoncolor option} -body { .t configure -buttoncolor red .t configure -buttoncolor } -result {-buttoncolor buttonColor ButtonColor #808080 red} test treectrl-1.13 {configure: invalid -buttonbitmap option} -body { .t configure -buttonbitmap foo } -returnCodes error -result {bitmap "foo" not defined} test treectrl-1.14 {configure: -buttonbitmap option} -body { .t configure -buttonbitmap hourglass .t configure -buttonbitmap } -result {-buttonbitmap buttonBitmap ButtonBitmap {} hourglass} test treectrl-1.17 {configure: invalid -buttonimage option} -body { .t configure -buttonimage foo } -returnCodes error -result {image "foo" doesn't exist} test treectrl-1.18 {configure: -buttonimage option} -body { image create photo emptyImg .t configure -buttonimage emptyImg .t configure -buttonimage } -result {-buttonimage buttonImage ButtonImage {} emptyImg} test treectrl-1.21 {configure: invalid -doublebuffer option} -body { .t configure -doublebuffer foo } -returnCodes error -result {bad doublebuffer "foo": must be none, item, or window} test treectrl-1.22 {configure: -doublebuffer option} -body { .t configure -doublebuffer window .t configure -doublebuffer } -result {-doublebuffer doubleBuffer DoubleBuffer item window} test treectrl-1.23 {configure: invalid -indent option} -body { .t configure -indent foo } -returnCodes error -result {bad screen distance "foo"} test treectrl-1.24 {configure: -indent option} -body { .t configure -indent 2c .t configure -indent } -result {-indent indent Indent 19 2c} test treectrl-1.25 {configure: invalid -itemheight option} -body { .t configure -itemheight foo } -returnCodes error -result {bad screen distance "foo"} test treectrl-1.26 {configure: -itemheight option} -body { .t configure -itemheight 18m .t configure -itemheight } -result {-itemheight itemHeight ItemHeight 0 18m} test treectrl-1.27 {configure: invalid -linestyle option} -body { .t configure -linestyle foo } -returnCodes error -result {bad linestyle "foo": must be dot or solid} test treectrl-1.28 {configure: -linestyle option} -body { .t configure -linestyle solid .t configure -linestyle } -result {-linestyle lineStyle LineStyle dot solid} test treectrl-1.29 {configure: invalid -linethickness option} -body { .t configure -linethickness foo } -returnCodes error -result {bad screen distance "foo"} test treectrl-1.30 {configure: -linethickness option} -body { .t configure -linethickness 3m .t configure -linethickness } -result {-linethickness lineThickness LineThickness 1 3m} test treectrl-1.31 {configure: invalid -linecolor option} -body { .t configure -linecolor #foo } -returnCodes error -result {invalid color name "#foo"} test treectrl-1.32 {configure: -linethickness option} -body { .t configure -linecolor gray20 .t configure -linecolor } -result {-linecolor lineColor LineColor #808080 gray20} test treectrl-1.33 {configure: invalid -orient option} -body { .t configure -orient foo } -returnCodes error -result {bad orient "foo": must be horizontal or vertical} test treectrl-1.34 {configure: -orient option} -body { .t configure -orient h .t configure -orient } -result {-orient orient Orient vertical horizontal} test treectrl-1.35 {configure: invalid -relief option} -body { .t configure -relief foo } -returnCodes error -result {bad relief "foo": must be flat, groove, raised, ridge, solid, or sunken} test treectrl-1.36 {configure: -relief option} -body { .t configure -relief flat .t configure -relief } -result {-relief relief Relief sunken flat} test treectrl-1.37 {configure: invalid -showbuttons option} -body { .t configure -showbuttons foo } -returnCodes error -result {expected boolean value but got "foo"} test treectrl-1.38 {configure: -showbuttons option} -body { .t configure -showbuttons off .t configure -showbuttons } -result {-showbuttons showButtons ShowButtons 1 0} test treectrl-1.39 {configure: invalid -showheader option} -body { .t configure -showheader foo } -returnCodes error -result {expected boolean value but got "foo"} test treectrl-1.40 {configure: -showheader option} -body { .t configure -showheader off .t configure -showheader } -result {-showheader showHeader ShowHeader 1 0} test treectrl-1.41 {configure: invalid -showlines option} -body { .t configure -showlines foo } -returnCodes error -result {expected boolean value but got "foo"} test treectrl-1.42 {configure: -showlines option} -body { .t configure -showlines false .t configure -showlines } -result {-showlines showLines ShowLines 1 0} test treectrl-1.43 {configure: invalid -showroot option} -body { .t configure -showroot foo } -returnCodes error -result {expected boolean value but got "foo"} test treectrl-1.44 {configure: -showroot option} -body { .t configure -showroot no .t configure -showroot } -result {-showroot showRoot ShowRoot 1 0} test treectrl-1.45 {configure: invalid -showrootbutton option} -body { .t configure -showrootbutton foo } -returnCodes error -result {expected boolean value but got "foo"} test treectrl-1.46 {configure: -showrootbutton option} -body { .t configure -showrootbutton True .t configure -showrootbutton } -result {-showrootbutton showRootButton ShowRootButton 0 1} test treectrl-1.47 {configure: invalid -treecolumn option} -body { .t configure -treecolumn foo } -returnCodes error -result {column "foo" doesn't exist} test treectrl-1.49 {configure: -treecolumn option with known column} -body { .t column create -tag column0 .t column create -tag column2 .t configure -treecolumn 1 .t configure -treecolumn } -result {-treecolumn treeColumn TreeColumn {} 1} test treectrl-1.50 {configure: invalid -wrap mode} -body { .t configure -wrap foo } -returnCodes error -result {bad wrap "foo"} test treectrl-1.51 {configure: invalid -wrap option: bogus width} -body { .t configure -wrap {item bar} } -returnCodes error -result {bad wrap "item bar"} test treectrl-1.52 {configure: invalid -wrap option: superflous width} -body { .t configure -wrap {1 window} } -returnCodes error -result {bad wrap "1 window"} test treectrl-1.53 {configure: -wrap option} -body { .t configure -wrap {7 items} .t configure -wrap } -result {-wrap wrap Wrap {} {7 items}} test treectrl-1.54 {configure: -wrap empty option} -body { .t configure -wrap {} .t configure -wrap } -result {-wrap wrap Wrap {} {}} # Before continuing to test the item descriptions and their modifiers, # lets create some items with this hierarchy: # 0 # + 1 # | + 2 # | + 3 # | + 4 # + 5 # | + 6 # | + 7 # + 8 test treectrl-2.16 {create some items} -body { .t configure -showroot 1 -orient vertical set n1 [.t item create]; .t item lastchild 0 $n1 set n2 [.t item create]; .t item lastchild $n1 $n2 set n3 [.t item create]; .t item lastchild $n1 $n3 set n4 [.t item create]; .t item lastchild $n3 $n4 set n5 [.t item create]; .t item lastchild 0 $n5 set n6 [.t item create]; .t item lastchild $n5 $n6 set n7 [.t item create]; .t item lastchild $n5 $n7 set n8 [.t item create]; .t item lastchild 0 $n8 } -result {8} test treectrl-5.1 {state: missing args} -body { .t state } -returnCodes error -result {wrong # args: should be ".t state command ?arg arg ...?"} test treectrl-5.2 {state: invalid command} -body { .t state foo } -returnCodes error -result {bad command "foo": must be *} -match glob test treectrl-5.3 {state names: too many args} -body { .t state names foo bar } -returnCodes error -result {wrong # args: should be ".t state names"} test treectrl-5.4 {state names: no states defined yet} -body { .t state names } -result {} test treectrl-5.5 {state define: missing args} -body { .t state define } -returnCodes error -result {wrong # args: should be ".t state define stateName"} test treectrl-5.6 {state define: overflow check} -body { set msg "" set ret 0 for {set ix 0} {$ix < 1000} {incr ix} { set ret [catch {.t state define state$ix} msg] if {$ret} {break} } list $ret $ix $msg } -result {1 27 {cannot define any more states}} test treectrl-5.7 {state names} -body { .t state names } -result {state0 state1 state2 state3 state4 state5 state6 state7 state8 state9 state10 state11 state12 state13 state14 state15 state16 state17 state18 state19 state20 state21 state22 state23 state24 state25 state26} test treectrl-5.8 {state undefine: missing args is ok} -body { .t state undefine } -result {} test treectrl-5.9 {state undefine: too many args} -body { eval {.t state undefine} [lrange [.t state names] 3 end] .t state names } -result {state0 state1 state2} test treectrl-5.10 {state undefine} -body { foreach state [lrange [.t state names] 1 end] { .t state undefine $state } .t state names } -result {state0} test treectrl-5.11 {state linkage: missing args} -body { .t state linkage } -returnCodes error -result {wrong # args: should be ".t state linkage state"} test treectrl-5.12 {state linkage: unknown state} -body { .t state linkage foo } -returnCodes error -result {unknown state "foo"} test treectrl-5.13 {state linkage: predefined state} -body { .t state linkage open } -result {static} test treectrl-5.14 {state linkage: user defined state} -body { .t state linkage state0 } -result {dynamic} test treectrl-5.15 {state define: strange state name} -body { .t state define ~user } -returnCodes error -result {invalid state name "~user"} test treectrl-5.17 {state define: strange state name} -body { .t state linkage ~user } -returnCodes error -result {can't specify '~' for this command} test treectrl-5.18 {state undefine: strange state name} -body { .t state undefine ~user } -returnCodes error -result {can't specify '~' for this command} test treectrl-5.19 {state define: strange state name} -body { .t state define !WatchIt! } -returnCodes error -result {invalid state name "!WatchIt!"} test treectrl-5.20 {state define: strange state name} -body { .t state define "" } -returnCodes error -result {invalid state name ""} test treectrl-7.0 {some prerequisites for the marquee test} -body { .t element create eImage image -width 202 -height 18m .t element create eRect rect -width 10c -height 18m .t style create testStyle2 .t style elements testStyle2 {eImage eRect} .t item style set 2 .t item style set 8 0 testStyle2 update idletasks } -result {} test treectrl-7.1 {marquee: missing args} -body { .t marquee } -returnCodes error -result {wrong # args: should be ".t marquee command ?arg arg ...?"} test treectrl-7.2 {marquee: unknown command} -body { .t marquee foo } -returnCodes error -result {bad command "foo": must be *} -match glob test treectrl-7.3 {marquee anchor: not yet modified} -body { .t marquee anchor } -result {0 0} test treectrl-7.4 {marquee anchor: odd arguments} -body { .t marquee anchor 1 } -returnCodes error -result {wrong # args: should be ".t marquee anchor ?x y?"} test treectrl-7.5 {marquee identify: should be empty} -body { .t marquee identify } -result {} test treectrl-7.6 {marquee anchor: set it} -body { .t marquee anchor 5 5 } -result {} test treectrl-7.7 {marquee coords: retrieve them} -body { .t marquee coords } -result {5 5 0 0} test treectrl-7.8 {marquee identify: just the root} -body { .t marquee identify } -result {{0 0}} test treectrl-7.9 {marquee corner: set it} -body { .t marquee corner 600 600 .t marquee coords } -result {5 5 600 600} test treectrl-7.10 {marquee identify} -body { .t marquee identify } -result {{0 0} {1 0} {2 0} {3 0} {4 0} {5 0} {6 0} {7 0} {8 {0 eRect eImage}}} test treectrl-7.11 {marquee identify: after invalid item style map} -body { catch {.t item style map 1 0 noStyle {foo bar}} .t marquee identify } -result {{0 0} {1 0} {2 0} {3 0} {4 0} {5 0} {6 0} {7 0} {8 {0 eRect eImage}}} test treectrl-7.12 {marquee visible} -body { list [.t marquee configure -visible] \ [.t marquee cget -visible] \ [.t marquee configure -visible 1] \ [.t marquee cget -visible] } -result {{-visible {} {} 0 0} 0 {} 1} test treectrl-8.1 {selection: missing args} -body { .t selection } -returnCodes error -result {wrong # args: should be ".t selection command ?arg arg ...?"} test treectrl-8.2 {selection: unknown command} -body { .t selection foo } -returnCodes error -result {bad command "foo": must be *} -match glob test treectrl-8.3 {selection count/get: nothing selected yet} -body { list [.t selection count] [.t selection get] } -result {0 {}} test treectrl-8.4 {selection anchor: always defined} -body { .t selection anchor } -result {0} test treectrl-8.5 {selection anchor: modifies the anchor item} -body { .t selection anchor "root lastchild" .t item id anchor } -result {8} test treectrl-8.6 {selection count/get: still nothing selected} -body { list [.t selection count] [.t selection get] } -result {0 {}} test treectrl-8.7 {selection add: all children of an item} -body { .t selection add "1 firstchild" "1 lastchild" list [.t selection count] [lsort -integer [.t selection get]] } -result {2 {2 3}} test treectrl-8.8 {selection add: all items and then some} -body { .t selection add all "1 lastchild" list [.t selection count] [lsort -integer [.t selection get]] } -result {9 {0 1 2 3 4 5 6 7 8}} test treectrl-8.9 {selection clear} -body { .t selection add all .t selection clear "root firstchild" list [.t selection count] [lsort -integer [.t selection get]] } -result {8 {0 2 3 4 5 6 7 8}} test treectrl-8.10 {selection clear: some items and then all} -body { .t selection clear "root lastchild" all list [.t selection count] [.t selection get] } -result {0 {}} test treectrl-8.11 {selection modify: to be or not to be?} -body { .t selection modify all all list [.t selection count] [lsort -integer [.t selection get]] } -result {9 {0 1 2 3 4 5 6 7 8}} test treectrl-8.12 {selection clear: totally empty} -body { .t selection clear list [.t selection count] [lsort -integer [.t selection get]] } -result {0 {}} test treectrl-8.12 {selection modify: to be or not to be?} -body { .t selection modify {{root firstchild} {root lastchild}} {{root lastchild}} list [.t selection count] [lsort -integer [.t selection get]] } -result {2 {1 8}} test treectrl-8.13 {selection includes: missing args} -body { .t selection includes } -returnCodes error -result {wrong # args: should be ".t selection includes item"} test treectrl-8.14 {selection includes: invalid item} -body { .t selection includes {foo bar} } -returnCodes error -result {item "foo bar" doesn't exist} test treectrl-8.15 {selection includes: item is selected} -body { .t selection includes {root child 2} } -result {1} test treectrl-8.16 {selection includes: item is not selected} -body { .t selection includes {root child 0 firstchild} } -result {0} test treectrl-9.1 {see: missing args} -body { .t see } -returnCodes error -result {wrong # args: should be ".t see item"} test treectrl-9.2 {see: too many args} -body { .t see foo bar } -returnCodes error -result {wrong # args: should be ".t see item"} test treectrl-9.3 {see: invalid item} -body { .t see foo } -returnCodes error -result {item "foo" doesn't exist} test treectrl-9.4 {see: bottom most item} -body { .t see "root bottom" } -result {} test treectrl-10.1 {range: missing args} -body { .t item range } -returnCodes error -result {wrong # args: should be ".t item range first last"} test treectrl-10.2 {range: too many args} -body { .t item range foo bar baz } -returnCodes error -result {wrong # args: should be ".t item range first last"} test treectrl-10.3 {range: select all from top to bottom} -body { .t item range "root top" "root bottom" } -result {0 1 2 3 4 5 6 7 8} test treectrl-10.4 {range: select all from bottom to top} -body { .t item range "root bottom" "root top" } -result {0 1 2 3 4 5 6 7 8} test treectrl-11.1 {orphans: too many args} -body { .t orphans foo } -returnCodes error -result {wrong # args: should be ".t orphans"} test treectrl-11.2 {orphans: lets make one} -body { .t item remove 8 .t orphans } -result {8} test treectrl-11.3 {orphans: no orphans} -body { .t item lastchild 0 8 .t orphans } -result {} test treectrl-12.1 {contentbox: too many args} -body { .t contentbox foo } -returnCodes error -result {wrong # args: should be ".t contentbox"} test treectrl-12.2 {contentbox} -body { .t contentbox } -result {3 3 203 203} test treectrl-12.3 {contentbox: simple double check with borders} -body { expr {[lindex [.t contentbox] 0] \ == ([.t cget -bd]+[.t cget -highlightthickness])} } -result {1} test treectrl-12.4 {element delete while item is still displayed} -body { .t element create elText text -text hallo .t style create stText .t style element stText elText set new [.t item create] .t item style set $new 0 stText .t item lastchild 0 $new .t element delete elText place [frame .obscure] -in .t -relwidth 1.0 -relheight 1.0 update destroy .obscure update } -result {} test treectrl-13.1 {depth: too many args} -body { .t depth foo bar } -returnCodes error -result {wrong # args: should be ".t depth ?item?"} test treectrl-13.2 {depth of the root item} -body { .t depth root } -result {0} test treectrl-13.3 {depth of a deeper item} -body { .t depth "root firstchild lastchild" } -result {2} test treectrl-13.4 {depth of the tree} -body { .t depth } -result {3} test treectrl-13.5 {depth of the tree} -body { .t depth } -setup { set rootKids [.t item children root] foreach i $rootKids {.t item remove $i} } -cleanup { foreach i $rootKids {.t item lastchild root $i} } -result {0} test treectrl-14.1 {rename and change some columns} -body { .t column delete column0 .t column create -tag column1 .t column create -tag column3 .t column move "order 0" "order 2" .t column move "order 0" tail .t element create eRect2 rect -fill blue -height 20 -width 150 .t style create testStyle3 .t style elements testStyle3 eRect2 .t item style set 1 column1 testStyle3 } -result {} test treectrl-15.1 {identify: missing args} -body { wm geometry . 400x200 ; update .t identify } -returnCodes error -result {wrong # args: should be ".t identify x y"} test treectrl-15.2 {identify: negative coords} -body { .t configure -showheader 1 -showlines 1 -showbuttons 1 \ -borderwidth 2 -highlightthickness 1 -treecolumn 2 \ -itemheight 0 -linethickness 1 -indent 40 .t item configure 1 -button true update idletasks .t identify -5 -5 } -result {} test treectrl-15.3 {identify: header left} -body { # column 0 has width 0 # column 1 has width 0 # column 2 has width 40 + 40 + 150 = 230 # borders are 2 + 1 = 3 .t identify 3 4 } -result {header 2 left} test treectrl-15.4 {identify: header} -body { .t identify 40 4 } -result {header 2} test treectrl-15.5 {identify: header right} -body { .t identify 232 4 } -result {header 2 right} test treectrl-15.6 {identify: tail left} -body { .t identify 233 4 } -result {header tail left} test treectrl-15.7 {identify: tail} -body { .t identify 250 4 } -result {header tail} test treectrl-15.8 {identify: item (to the left)} -body { .t identify 4 10 } -result {item 1} test treectrl-15.9 {identify: button} -body { .t identify 60 10 } -result {item 1 button} test treectrl-15.10 {identify: over element} -body { .t identify 150 10 } -result {item 1 column 2 elem eRect2} test treectrl-15.11 {identify: item (to the right)} -body { # first make column wider, otherwise we can't get right of the item .t column configure column1 -width 250 update idletasks .t identify 233 10 } -result {item 1 column 2} test treectrl-16.1 {dragimage: missing args} -body { .t dragimage } -returnCodes error -result {wrong # args: should be ".t dragimage command ?arg arg ...?"} test treectrl-16.2 {dragimage: unknown command} -body { .t dragimage foo } -returnCodes error -result {bad command "foo": must be *} -match glob test treectrl-16.3 {dragimage configure} -body { .t dragimage configure } -result {{-visible {} {} 0 0}} test treectrl-16.4 {dragimage configure -visible} -body { .t dragimage configure -visible } -result {-visible {} {} 0 0} test treectrl-16.5 {dragimage cget -visible} -body { .t dragimage cget -visible } -result {0} test treectrl-16.6 {dragimage offset: without preceding add} -body { .t dragimage offset } -result {0 0} test treectrl-16.7 {dragimage add: invalid item} -body { .t dragimage add foo } -returnCodes error -result {item "foo" doesn't exist} test treectrl-16.8 {dragimage add: invalid column} -body { .t dragimage add 1 foo } -returnCodes error -result {column "foo" doesn't exist} test treectrl-16.9 {dragimage add: invalid element} -body { .t dragimage add 1 2 foo } -returnCodes error -result {element "foo" doesn't exist} test treectrl-16.10 {dragimage add: is still not visible} -body { .t dragimage add 1 2 .t dragimage cget -visible } -result {0} test treectrl-16.11 {dragimage visible} -body { .t dragimage configure -visible 1 .t dragimage cget -visible } -result {1} test treectrl-16.12 {dragimage offset} -body { .t dragimage offset 10 10 .t dragimage offset } -result {10 10} test treectrl-16.13 {dragimage clear: too many args} -body { .t dragimage clear 1 } -returnCodes error -result {wrong # args: should be ".t dragimage clear"} test treectrl-16.14 {dragimage clear: doesn't modify the offset} -body { .t dragimage clear .t dragimage offset } -result {10 10} test treectrl-17.1 {columnproxy: Normally left blank} -body { # BTW: This shouldn't be an option... .t cget -columnproxy } -result {} test treectrl-17.2 {columnproxy: Normally left blank} -body { .t configure -columnproxy foo } -returnCodes error -result {bad screen distance "foo"} test treectrl-17.3 {columnproxy: Negative screen distance} -body { # It is unclear if this should be forbiden... .t configure -columnproxy -1c update idletasks .t cget -columnproxy } -result {-1c} test treectrl-17.4 {columnproxy: screen distance bigger than width} -body { # It is unclear if this should be forbiden... set x [expr {[winfo width .t] + 10}] .t configure -columnproxy $x update idletasks expr {[.t cget -columnproxy] == $x} } -result {1} test treectrl-17.5 {columnproxy} -body { .t configure -columnproxy 100 update idletasks .t cget -columnproxy } -result {100} test treectrl-18.1 {-defaultstyle: setup} -body { .t column delete all .t column create -tags a .t column create -tags b .t column create -tags c .t column create -tags d .t item delete all .t style create a .t style create b .t style create c .t style create d } -result {d} test treectrl-18.2 {-defaultstyle: set} -constraints { deprecated } -body { .t configure -defaultstyle {a b c d} .t cget -defaultstyle } -result {a b c d} test treectrl-18.3 {-defaultstyle: new items get default styles} -constraints { deprecated } -body { set I [.t item create] .t item style set $I } -result {a b c d} test treectrl-18.4 {-defaultstyle: moving column updates -defaultstyle} -constraints { deprecated } -body { .t column move "tag a" "tag c" .t cget -defaultstyle } -result {b a c d} test treectrl-18.5 {-defaultstyle: moving column updates -defaultstyle} -constraints { deprecated } -body { .t column move "tag a" tail .t cget -defaultstyle } -result {b c d a} test treectrl-18.6 {-defaultstyle: moving column updates -defaultstyle} -constraints { deprecated } -body { .t column move "tag a" "tag b" .t cget -defaultstyle } -result {a b c d} test treectrl-18.7 {-defaultstyle: moving column updates -defaultstyle} -constraints { deprecated } -body { .t column create -tags e .t column move "tag e" "tag d" .t cget -defaultstyle } -result {a b c {} d} test treectrl-18.8 {-defaultstyle: moving column updates -defaultstyle} -constraints { deprecated } -body { .t column create -tags f .t column move "tag c" tail .t cget -defaultstyle } -result {a b {} d {} c} test treectrl-18.9 {-defaultstyle: deleting column does not update -defaultstyle} -constraints { deprecated } -body { .t column delete "tag e" .t cget -defaultstyle } -result {a b {} d {} c} # cleanup image delete emptyImg ::tcltest::cleanupTests return tktreectrl-2.2.8/treectrl.dll.manifest.in0000700000175600010010000000060610753133102016634 0ustar TimNone tktreectrl-2.2.8/treectrl.rc0000700000175600010010000000045210753154727014272 0ustar TimNone// // This enables themed headers in XP by trying to use comctl32 v6. // #ifndef RT_MANIFEST #define RT_MANIFEST 24 #endif #ifndef ISOLATIONAWARE_MANIFEST_RESOURCE_ID #define ISOLATIONAWARE_MANIFEST_RESOURCE_ID 2 #endif ISOLATIONAWARE_MANIFEST_RESOURCE_ID RT_MANIFEST "treectrl.dll.manifest" tktreectrl-2.2.8/winrc.m40000700000175600010010000000503310760347537013505 0ustar TimNone# This was taken from Tk's configure.in and tcl.m4. AC_DEFUN([TREECTRL_PROG_RC], [ # AC_MSG_CHECKING([for windows resource compiler]) RC_DEPARG='"$<"' if test "${GCC}" = "yes" ; then AC_CHECK_PROG(RC, windres, windres) if test "${RC}" = "" ; then AC_MSG_ERROR([Required resource tool 'windres' not found on PATH.]) fi RC_OUT=-o RC_TYPE= RC_INCLUDE=--include RC_DEFINE=--define RES=res.o # Check for a bug in gcc's windres that causes the # compile to fail when a Windows native path is # passed into windres. The mingw toolchain requires # Windows native paths while Cygwin should work # with both. Avoid the bug by passing a POSIX # path when using the Cygwin toolchain. if test "$ac_cv_cygwin" != "yes" -a "$CYGPATH" != "echo" ; then conftest=/tmp/conftest.rc echo "STRINGTABLE BEGIN" > $conftest echo "101 \"name\"" >> $conftest echo "END" >> $conftest AC_MSG_CHECKING([for Windows native path bug in windres]) cyg_conftest=`$CYGPATH $conftest` if AC_TRY_COMMAND($RC -o conftest.res.o $cyg_conftest) ; then AC_MSG_RESULT([no]) RC_DEPARG='"$(shell $(CYGPATH) $<)"' else AC_MSG_RESULT([yes]) fi conftest= cyg_conftest= fi else if test "$do64bit" != "no" ; then RC="\"${MSSDK}/bin/rc.exe\"" elif test "$doWince" != "no" ; then RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" else RC="rc" fi RC_OUT=-fo RC_TYPE=-r RC_INCLUDE=-i RC_DEFINE=-d RES=res fi AC_SUBST(RC) AC_SUBST(RC_OUT) AC_SUBST(RC_TYPE) AC_SUBST(RC_INCLUDE) AC_SUBST(RC_DEFINE) AC_SUBST(RC_DEPARG) AC_SUBST(RES) ]) # This is basically TEA_ADD_SOURCES but sets the object file extension to # $RES instead of $OBJ. AC_DEFUN([TREECTRL_ADD_RC], [ 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 if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$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"${RES}" != x ; then j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${RES}" else j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${RES}" fi PKG_OBJECTS="$PKG_OBJECTS $j" ;; esac done AC_SUBST(PKG_SOURCES) AC_SUBST(PKG_OBJECTS) ])