diff options
author | Joe Mistachkin <joe@mistachkin.com> | 2014-11-11 22:23:34 (GMT) |
---|---|---|
committer | Joe Mistachkin <joe@mistachkin.com> | 2014-11-11 22:23:34 (GMT) |
commit | b15c525eedc93a453dfea94482bc1198e27748fc (patch) | |
tree | 49a88f59bc168351fe802d8aa68da6d853b823aa /win | |
parent | 07f85cd3c1b4934fb746ea36516ba2944b4eea11 (diff) | |
parent | ee9722cf78769c35f57383613f570b6e797e74bf (diff) | |
download | tk-b15c525eedc93a453dfea94482bc1198e27748fc.zip tk-b15c525eedc93a453dfea94482bc1198e27748fc.tar.gz tk-b15c525eedc93a453dfea94482bc1198e27748fc.tar.bz2 |
Merge updates from core 8.5 branch.
Diffstat (limited to 'win')
-rw-r--r-- | win/Makefile.in | 13 | ||||
-rwxr-xr-x | win/configure | 161 | ||||
-rw-r--r-- | win/configure.in | 3 | ||||
-rw-r--r-- | win/makefile.bc | 1 | ||||
-rw-r--r-- | win/makefile.vc | 5 | ||||
-rw-r--r-- | win/tcl.m4 | 272 | ||||
-rw-r--r-- | win/tkWin32Dll.c | 36 | ||||
-rw-r--r-- | win/tkWinButton.c | 34 | ||||
-rw-r--r-- | win/tkWinDialog.c | 946 | ||||
-rw-r--r-- | win/tkWinInit.c | 14 | ||||
-rw-r--r-- | win/tkWinMenu.c | 6 | ||||
-rw-r--r-- | win/tkWinPort.h | 4 | ||||
-rw-r--r-- | win/tkWinScrlbr.c | 2 | ||||
-rw-r--r-- | win/tkWinWm.c | 7 | ||||
-rw-r--r-- | win/tkWinX.c | 40 | ||||
-rw-r--r-- | win/ttkWinXPTheme.c | 6 | ||||
-rw-r--r-- | win/winMain.c | 4 | ||||
-rw-r--r-- | win/wish.exe.manifest.in | 24 |
18 files changed, 646 insertions, 932 deletions
diff --git a/win/Makefile.in b/win/Makefile.in index eda2aed..1d18b60 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -4,8 +4,6 @@ # "autoconf" program (constructs like "@foo@" will get replaced in the # actual Makefile. -TCLVERSION = @TCL_VERSION@ -TCLPATCHL = @TCL_PATCH_LEVEL@ VERSION = @TK_VERSION@ PATCH_LEVEL = @TK_PATCH_LEVEL@ @@ -165,7 +163,7 @@ LDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@ # Tk does not used deprecated Tcl constructs so it should # compile fine with -DTCL_NO_DEPRECATED. To remove its own # set of deprecated code uncomment the second line. -NO_DEPRECATED_FLAGS = -DTCL_NO_DEPRECATED +NO_DEPRECATED_FLAGS = #NO_DEPRECATED_FLAGS = -DTCL_NO_DEPRECATED -DTK_NO_DEPRECATED # To change the compiler switches, for example to change from optimization to @@ -352,7 +350,6 @@ TK_OBJS = \ tkUtil.$(OBJEXT) \ tkVisual.$(OBJEXT) \ tkStubInit.$(OBJEXT) \ - tkStubLib.$(OBJEXT) \ tkWindow.$(OBJEXT) \ $(TTK_OBJS) @@ -484,12 +481,12 @@ install-binaries: binaries @echo "Creating package index $(PKG_INDEX)"; @$(RM) $(PKG_INDEX); @(\ - echo "if {[catch {package present Tcl $(TCLVERSION).0}]} return";\ + echo "if {[catch {package present Tcl 8.5.0}]} return";\ echo "if {(\$$::tcl_platform(platform) eq \"unix\") && ([info exists ::env(DISPLAY)]";\ echo " || ([info exists ::argv] && (\"-display\" in \$$::argv)))} {";\ - echo " package ifneeded Tk $(VERSION)$(PATCH_LEVEL) [list load [file join \$$dir .. .. bin libtk$(VERSION).dll] Tk]";\ + echo " package ifneeded Tk $(VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir .. .. bin libtk$(VERSION).dll]] Tk]";\ echo "} else {";\ - echo " package ifneeded Tk $(VERSION)$(PATCH_LEVEL) [list load [file join \$$dir .. .. bin $(TK_DLL_FILE)] Tk]";\ + echo " package ifneeded Tk $(VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir .. .. bin $(TK_DLL_FILE)]] Tk]";\ echo "}";\ ) > $(PKG_INDEX); @for i in tkConfig.sh $(TK_LIB_FILE) $(TK_STUB_LIB_FILE); \ @@ -635,7 +632,7 @@ $(CAT32): cat32.${OBJEXT} ${TK_STUB_LIB_FILE}: ${STUB_OBJS} @$(RM) ${TK_STUB_LIB_FILE} - @MAKE_LIB@ ${STUB_OBJS} + @MAKE_STUB_LIB@ ${STUB_OBJS} @POST_MAKE_LIB@ ${TK_DLL_FILE}: ${TK_OBJS} $(TK_RES) diff --git a/win/configure b/win/configure index 5cc7819..7a009e7 100755 --- a/win/configure +++ b/win/configure @@ -309,7 +309,7 @@ ac_includes_default="\ # include <unistd.h> #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 datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP AR ac_ct_AR RANLIB ac_ct_RANLIB RC ac_ct_RC SET_MAKE TCL_THREADS 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_DEFS CYGPATH CELIB_DIR DL_LIBS CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING MAN2TCLFLAGS CFLAGS_DEFAULT LDFLAGS_DEFAULT VC_MANIFEST_EMBED_DLL VC_MANIFEST_EMBED_EXE BUILD_TCLSH TCLSH_PROG TK_WIN_VERSION MACHINE TK_VERSION TK_MAJOR_VERSION TK_MINOR_VERSION TK_PATCH_LEVEL TK_DBGX TK_LIB_FILE TK_DLL_FILE TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_BUILD_STUB_LIB_SPEC TK_SRC_DIR TK_BIN_DIR TCL_MAJOR_VERSION TCL_MINOR_VERSION TCL_PATCH_LEVEL TCL_DBGX CFG_TK_SHARED_LIB_SUFFIX CFG_TK_UNSHARED_LIB_SUFFIX CFG_TK_EXPORT_FILE_SUFFIX TK_SHARED_BUILD DEPARG EXTRA_CFLAGS STLIB_LD SHLIB_LD SHLIB_LD_LIBS SHLIB_CFLAGS SHLIB_SUFFIX CC_OBJNAME CC_EXENAME LDFLAGS_DEBUG LDFLAGS_OPTIMIZE LDFLAGS_CONSOLE LDFLAGS_WINDOW RC_OUT RC_TYPE RC_INCLUDE RC_DEFINE RC_DEFINES TK_RES RES LIBS_GUI DLLSUFFIX LIBPREFIX LIBSUFFIX EXESUFFIX LIBRARIES MAKE_LIB POST_MAKE_LIB MAKE_DLL MAKE_EXE TK_LIB_FLAG TK_LIB_SPEC TK_BUILD_LIB_SPEC TK_STUB_LIB_SPEC TK_STUB_LIB_PATH TK_BUILD_STUB_LIB_PATH TK_CC_SEARCH_FLAGS TK_LD_SEARCH_FLAGS LIBOBJS LTLIBOBJS' +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 datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP AR ac_ct_AR RANLIB ac_ct_RANLIB RC ac_ct_RC SET_MAKE TCL_THREADS 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_DEFS CYGPATH CELIB_DIR DL_LIBS CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING MAN2TCLFLAGS CFLAGS_DEFAULT LDFLAGS_DEFAULT VC_MANIFEST_EMBED_DLL VC_MANIFEST_EMBED_EXE BUILD_TCLSH TCLSH_PROG TK_WIN_VERSION MACHINE TK_VERSION TK_MAJOR_VERSION TK_MINOR_VERSION TK_PATCH_LEVEL TK_DBGX TK_LIB_FILE TK_DLL_FILE TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_BUILD_STUB_LIB_SPEC TK_SRC_DIR TK_BIN_DIR TCL_MAJOR_VERSION TCL_MINOR_VERSION TCL_PATCH_LEVEL TCL_DBGX CFG_TK_SHARED_LIB_SUFFIX CFG_TK_UNSHARED_LIB_SUFFIX CFG_TK_EXPORT_FILE_SUFFIX TK_SHARED_BUILD DEPARG EXTRA_CFLAGS STLIB_LD SHLIB_LD SHLIB_LD_LIBS SHLIB_CFLAGS SHLIB_SUFFIX CC_OBJNAME CC_EXENAME LDFLAGS_DEBUG LDFLAGS_OPTIMIZE LDFLAGS_CONSOLE LDFLAGS_WINDOW RC_OUT RC_TYPE RC_INCLUDE RC_DEFINE RC_DEFINES TK_RES RES LIBS_GUI DLLSUFFIX LIBPREFIX LIBSUFFIX EXESUFFIX LIBRARIES MAKE_LIB MAKE_STUB_LIB POST_MAKE_LIB MAKE_DLL MAKE_EXE TK_LIB_FLAG TK_LIB_SPEC TK_BUILD_LIB_SPEC TK_STUB_LIB_SPEC TK_STUB_LIB_PATH TK_BUILD_STUB_LIB_PATH TK_CC_SEARCH_FLAGS TK_LD_SEARCH_FLAGS LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -851,7 +851,8 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-tcl=DIR use Tcl 8.5 binaries from DIR + --with-tcl directory containing tcl configuration + (tclConfig.sh) --with-celib=DIR use Windows/CE support library from DIR Some influential environment variables: @@ -1311,7 +1312,7 @@ SHELL=/bin/sh TK_VERSION=8.5 TK_MAJOR_VERSION=8 TK_MINOR_VERSION=5 -TK_PATCH_LEVEL=".13" +TK_PATCH_LEVEL=".17" VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION #------------------------------------------------------------------------ @@ -3103,7 +3104,8 @@ echo "${ECHO_T}shared" >&6 echo "$as_me:$LINENO: result: static" >&5 echo "${ECHO_T}static" >&6 SHARED_BUILD=0 - cat >>confdefs.h <<\_ACEOF + +cat >>confdefs.h <<\_ACEOF #define STATIC_BUILD 1 _ACEOF @@ -3115,52 +3117,129 @@ _ACEOF #-------------------------------------------------------------------- - echo "$as_me:$LINENO: checking the location of tclConfig.sh" >&5 -echo $ECHO_N "checking the location of tclConfig.sh... $ECHO_C" >&6 - - if test -d ../../tcl8.5$TK_PATCH_LEVEL/win; then - TCL_BIN_DIR_DEFAULT=../../tcl8.5$TK_PATCH_LEVEL/win - elif test -d ../../tcl8.5/win; then - TCL_BIN_DIR_DEFAULT=../../tcl8.5/win - else - TCL_BIN_DIR_DEFAULT=../../tcl/win - fi + # + # 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 or --without-tcl was given. if test "${with_tcl+set}" = set; then withval="$with_tcl" - TCL_BIN_DIR=$withval -else - TCL_BIN_DIR=`cd $TCL_BIN_DIR_DEFAULT; pwd` + with_tclconfig="${withval}" fi; - if test ! -d $TCL_BIN_DIR; then - { { echo "$as_me:$LINENO: error: Tcl directory $TCL_BIN_DIR does not exist" >&5 -echo "$as_me: error: Tcl directory $TCL_BIN_DIR does not exist" >&2;} + 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 - if test ! -f $TCL_BIN_DIR/tclConfig.sh; then - if test ! -f $TCL_BIN_DIR/../unix/tclConfig.sh; then - { { echo "$as_me:$LINENO: error: There is no tclConfig.sh in $TCL_BIN_DIR: perhaps you did not specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?" >&5 -echo "$as_me: error: There is no tclConfig.sh in $TCL_BIN_DIR: perhaps you did not specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?" >&2;} + 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/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; 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 /cygdrive/c/Tcl/lib 2>/dev/null` \ + `ls -d /cygdrive/c/Progra~1/Tcl/lib 2>/dev/null` \ + `ls -d /c/Tcl/lib 2>/dev/null` \ + `ls -d /c/Progra~1/Tcl/lib 2>/dev/null` \ + `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 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/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; 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: error: Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" >&5 +echo "$as_me: error: Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" >&2;} { (exit 1); exit 1; }; } + 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 - TCL_BIN_DIR=`cd ${TCL_BIN_DIR}/../unix; pwd` fi - echo "$as_me:$LINENO: result: $TCL_BIN_DIR/tclConfig.sh" >&5 -echo "${ECHO_T}$TCL_BIN_DIR/tclConfig.sh" >&6 - 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 + 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 + 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 + . "${TCL_BIN_DIR}/tclConfig.sh" else - echo "$as_me:$LINENO: result: file not found" >&5 -echo "${ECHO_T}file not found" >&6 + 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 # @@ -3495,6 +3574,8 @@ echo "${ECHO_T}yes" >&6 # set various compiler flags depending on whether we are using gcc or cl if test "${GCC}" = "yes" ; then + extra_cflags="-pipe" + extra_ldflags="-pipe -static-libgcc" echo "$as_me:$LINENO: checking for mingw32 version of gcc" >&5 echo $ECHO_N "checking for mingw32 version of gcc... $ECHO_C" >&6 if test "${ac_cv_win32+set}" = set; then @@ -3575,13 +3656,11 @@ echo $ECHO_N "checking compiler flags... $ECHO_C" >&6 RC_DEFINE=--define RES=res.o MAKE_LIB="\${STLIB_LD} \$@" + MAKE_STUB_LIB="\${STLIB_LD} \$@" POST_MAKE_LIB="\${RANLIB} \$@" MAKE_EXE="\${CC} -o \$@" LIBPREFIX="lib" - extra_cflags="-pipe" - extra_ldflags="-pipe" - if test "${SHARED_BUILD}" = "0" ; then # static echo "$as_me:$LINENO: result: using static flags" >&5 @@ -3608,9 +3687,8 @@ echo "$as_me: error: ${CC} does not support the -shared option. runtime= # Link with gcc since ld does not link to default libs like - # -luser32 and -lmsvcrt by default. Make sure CFLAGS is - # included so -mno-cygwin passed the correct libs to the linker. - SHLIB_LD='${CC} -shared ${CFLAGS}' + # -luser32 and -lmsvcrt by default. + SHLIB_LD='${CC} -shared' SHLIB_LD_LIBS='${LIBS}' # Add SHLIB_LD_LIBS to the Make rule, not here. MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \$@ ${extra_ldflags} \ @@ -3991,6 +4069,7 @@ _ACEOF RC_DEFINE=-d RES=res MAKE_LIB="\${STLIB_LD} -out:\$@" + MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\$@" POST_MAKE_LIB= MAKE_EXE="\${CC} -Fe\$@" LIBPREFIX="" @@ -4928,6 +5007,7 @@ TK_WIN_VERSION="$TK_VERSION.$TK_RELEASE_LEVEL.`echo $TK_PATCH_LEVEL | tr -d ab.` + # undefined at this point for win @@ -5658,6 +5738,7 @@ s,@LIBSUFFIX@,$LIBSUFFIX,;t t s,@EXESUFFIX@,$EXESUFFIX,;t t s,@LIBRARIES@,$LIBRARIES,;t t s,@MAKE_LIB@,$MAKE_LIB,;t t +s,@MAKE_STUB_LIB@,$MAKE_STUB_LIB,;t t s,@POST_MAKE_LIB@,$POST_MAKE_LIB,;t t s,@MAKE_DLL@,$MAKE_DLL,;t t s,@MAKE_EXE@,$MAKE_EXE,;t t diff --git a/win/configure.in b/win/configure.in index ef517e6..78cc2e7 100644 --- a/win/configure.in +++ b/win/configure.in @@ -14,7 +14,7 @@ SHELL=/bin/sh TK_VERSION=8.5 TK_MAJOR_VERSION=8 TK_MINOR_VERSION=5 -TK_PATCH_LEVEL=".13" +TK_PATCH_LEVEL=".17" VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION #------------------------------------------------------------------------ @@ -271,6 +271,7 @@ AC_SUBST(LIBSUFFIX) AC_SUBST(EXESUFFIX) AC_SUBST(LIBRARIES) AC_SUBST(MAKE_LIB) +AC_SUBST(MAKE_STUB_LIB) AC_SUBST(POST_MAKE_LIB) AC_SUBST(MAKE_DLL) AC_SUBST(MAKE_EXE) diff --git a/win/makefile.bc b/win/makefile.bc index 12fd5b8..295ed23 100644 --- a/win/makefile.bc +++ b/win/makefile.bc @@ -225,7 +225,6 @@ TKOBJS = \ $(TMPDIR)\tkUtil.obj \ $(TMPDIR)\tkVisual.obj \ $(TMPDIR)\tkStubInit.obj \ - $(TMPDIR)\tkStubLib.obj \ $(TMPDIR)\tkWindow.obj # Maintenance hint: Please have multiple members of TKSTUBOBJS be separated diff --git a/win/makefile.vc b/win/makefile.vc index 68df470..8fbe917 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -360,7 +360,6 @@ TKOBJS = \ $(TMP_DIR)\tkUtil.obj \ $(TMP_DIR)\tkVisual.obj \ $(TMP_DIR)\tkStubInit.obj \ - $(TMP_DIR)\tkStubLib.obj \ $(TMP_DIR)\tkWindow.obj \ $(TTK_OBJS) \ !if !$(STATIC_BUILD) @@ -649,7 +648,7 @@ $** $(TKSTUBLIB): $(TKSTUBOBJS) - $(lib32) -nologo -out:$@ $** + $(lib32) -nologo -nodefaultlib -out:$@ $** $(WISH): $(WISHOBJS) $(TKIMPLIB) @@ -702,7 +701,7 @@ CHMFILE=$(HTMLDIR)\$(HTMLBASE).chm htmlhelp: chmsetup $(CHMFILE) $(CHMFILE): $(DOCDIR)\* - @$(TCLSH) $(TOOLSDIR)\tcltk-man2html.tcl + @$(TCLSH) $(TCLTOOLSDIR)\tcltk-man2html.tcl @echo Compiling HTML help project @$(HHC) <<$(HHPFILE) >NUL [OPTIONS] @@ -3,50 +3,124 @@ # # Locate the tclConfig.sh file and perform a sanity check on # the Tcl compile flags -# Currently a no-op for Windows # # Arguments: -# PATCH_LEVEL The patch level for Tcl if any. +# none # # Results: # # Adds the following arguments to configure: # --with-tcl=... # -# Sets the following vars: -# TCL_BIN_DIR Full path to the tclConfig.sh file +# Defines the following vars: +# TCL_BIN_DIR Full path to the directory containing +# the tclConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([SC_PATH_TCLCONFIG], [ - AC_MSG_CHECKING([the location of tclConfig.sh]) + # + # Ok, lets find the tcl configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tcl + # - if test -d ../../tcl8.5$1/win; then - TCL_BIN_DIR_DEFAULT=../../tcl8.5$1/win - elif test -d ../../tcl8.5/win; then - TCL_BIN_DIR_DEFAULT=../../tcl8.5/win - else - TCL_BIN_DIR_DEFAULT=../../tcl/win - fi + 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 - AC_ARG_WITH(tcl, [ --with-tcl=DIR use Tcl 8.5 binaries from DIR], - TCL_BIN_DIR=$withval, TCL_BIN_DIR=`cd $TCL_BIN_DIR_DEFAULT; pwd`) - if test ! -d $TCL_BIN_DIR; then - AC_MSG_ERROR(Tcl directory $TCL_BIN_DIR does not exist) - fi - if test ! -f $TCL_BIN_DIR/tclConfig.sh; then - if test ! -f $TCL_BIN_DIR/../unix/tclConfig.sh; then - AC_MSG_ERROR(There is no tclConfig.sh in $TCL_BIN_DIR: perhaps you did not specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?) + # 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/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; 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 /cygdrive/c/Tcl/lib 2>/dev/null` \ + `ls -d /cygdrive/c/Progra~1/Tcl/lib 2>/dev/null` \ + `ls -d /c/Tcl/lib 2>/dev/null` \ + `ls -d /c/Progra~1/Tcl/lib 2>/dev/null` \ + `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 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/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + done + fi + ]) + + if test x"${ac_cv_c_tclconfig}" = x ; then + TCL_BIN_DIR="# no Tcl configs found" + AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh]) + else + no_tcl= + TCL_BIN_DIR="${ac_cv_c_tclconfig}" + AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh]) fi - TCL_BIN_DIR=`cd ${TCL_BIN_DIR}/../unix; pwd` fi - AC_MSG_RESULT($TCL_BIN_DIR/tclConfig.sh) ]) #------------------------------------------------------------------------ # SC_PATH_TKCONFIG -- # # Locate the tkConfig.sh file -# Currently a no-op for Windows # # Arguments: # none @@ -56,31 +130,109 @@ AC_DEFUN([SC_PATH_TCLCONFIG], [ # Adds the following arguments to configure: # --with-tk=... # -# Sets the following vars: -# TK_BIN_DIR Full path to the tkConfig.sh file +# Defines the following vars: +# TK_BIN_DIR Full path to the directory containing +# the tkConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([SC_PATH_TKCONFIG], [ - AC_MSG_CHECKING([the location of tkConfig.sh]) + # + # Ok, lets find the tk configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tk + # - if test -d ../../tk8.5$1/win; then - TK_BIN_DIR_DEFAULT=../../tk8.5$1/win - elif test -d ../../tk8.5/win; then - TK_BIN_DIR_DEFAULT=../../tk8.5/win - else - TK_BIN_DIR_DEFAULT=../../tk/win - fi + 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 - AC_ARG_WITH(tk, [ --with-tk=DIR use Tk 8.5 binaries from DIR], - TK_BIN_DIR=$withval, TK_BIN_DIR=`cd $TK_BIN_DIR_DEFAULT; pwd`) - if test ! -d $TK_BIN_DIR; then - AC_MSG_ERROR(Tk directory $TK_BIN_DIR does not exist) - fi - if test ! -f $TK_BIN_DIR/tkConfig.sh; then - AC_MSG_ERROR(There is no tkConfig.sh in $TK_BIN_DIR: perhaps you did not specify the Tk *build* directory (not the toplevel Tk directory) or you forgot to configure Tk?) - 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/win/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/win; pwd)`" + break + fi + done + fi - AC_MSG_RESULT([$TK_BIN_DIR/tkConfig.sh]) + # 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 /cygdrive/c/Tcl/lib 2>/dev/null` \ + `ls -d /cygdrive/c/Progra~1/Tcl/lib 2>/dev/null` \ + `ls -d /c/Tcl/lib 2>/dev/null` \ + `ls -d /c/Progra~1/Tcl/lib 2>/dev/null` \ + `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/win/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/win; pwd)`" + break + fi + done + fi + ]) + + if test x"${ac_cv_c_tkconfig}" = x ; then + TK_BIN_DIR="# no Tk configs found" + AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh]) + else + no_tk= + TK_BIN_DIR="${ac_cv_c_tkconfig}" + AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh]) + fi + fi ]) #------------------------------------------------------------------------ @@ -103,13 +255,13 @@ AC_DEFUN([SC_PATH_TKCONFIG], [ #------------------------------------------------------------------------ AC_DEFUN([SC_LOAD_TCLCONFIG], [ - AC_MSG_CHECKING([for existence of $TCL_BIN_DIR/tclConfig.sh]) + AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh]) - if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then + if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then AC_MSG_RESULT([loading]) - . $TCL_BIN_DIR/tclConfig.sh + . "${TCL_BIN_DIR}/tclConfig.sh" else - AC_MSG_RESULT([file not found]) + AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh]) fi # @@ -158,7 +310,6 @@ AC_DEFUN([SC_LOAD_TCLCONFIG], [ # SC_LOAD_TKCONFIG -- # # Load the tkConfig.sh file -# Currently a no-op for Windows # # Arguments: # @@ -172,13 +323,13 @@ AC_DEFUN([SC_LOAD_TCLCONFIG], [ #------------------------------------------------------------------------ AC_DEFUN([SC_LOAD_TKCONFIG], [ - AC_MSG_CHECKING([for existence of $TK_BIN_DIR/tkConfig.sh]) + AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh]) - if test -f "$TK_BIN_DIR/tkConfig.sh" ; then + if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then AC_MSG_RESULT([loading]) - . $TK_BIN_DIR/tkConfig.sh + . "${TK_BIN_DIR}/tkConfig.sh" else - AC_MSG_RESULT([could not find $TK_BIN_DIR/tkConfig.sh]) + AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh]) fi @@ -212,7 +363,7 @@ AC_DEFUN([SC_ENABLE_SHARED], [ AC_MSG_CHECKING([how to build libraries]) AC_ARG_ENABLE(shared, [ --enable-shared build and link with shared libraries (default: on)], - [tcl_ok=$enableval], [tcl_ok=yes]) + [tcl_ok=$enableval], [tcl_ok=yes]) if test "${enable_shared+set}" = set; then enableval="$enable_shared" @@ -227,7 +378,7 @@ AC_DEFUN([SC_ENABLE_SHARED], [ else AC_MSG_RESULT([static]) SHARED_BUILD=0 - AC_DEFINE(STATIC_BUILD) + AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?]) fi ]) @@ -270,7 +421,7 @@ AC_DEFUN([SC_ENABLE_THREADS], [ #------------------------------------------------------------------------ # SC_ENABLE_SYMBOLS -- # -# Specify if debugging symbols should be used +# Specify if debugging symbols should be used. # Memory (TCL_MEM_DEBUG) and compile (TCL_COMPILE_DEBUG) debugging # can also be enabled. # @@ -372,6 +523,7 @@ AC_DEFUN([SC_ENABLE_SYMBOLS], [ # RES # # MAKE_LIB +# MAKE_STUB_LIB # MAKE_EXE # MAKE_DLL # @@ -481,6 +633,8 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ # set various compiler flags depending on whether we are using gcc or cl if test "${GCC}" = "yes" ; then + extra_cflags="-pipe" + extra_ldflags="-pipe -static-libgcc" AC_CACHE_CHECK(for mingw32 version of gcc, ac_cv_win32, AC_TRY_COMPILE([ @@ -510,13 +664,11 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ RC_DEFINE=--define RES=res.o MAKE_LIB="\${STLIB_LD} \[$]@" + MAKE_STUB_LIB="\${STLIB_LD} \[$]@" POST_MAKE_LIB="\${RANLIB} \[$]@" MAKE_EXE="\${CC} -o \[$]@" LIBPREFIX="lib" - extra_cflags="-pipe" - extra_ldflags="-pipe" - if test "${SHARED_BUILD}" = "0" ; then # static AC_MSG_RESULT([using static flags]) @@ -538,9 +690,8 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ runtime= # Link with gcc since ld does not link to default libs like - # -luser32 and -lmsvcrt by default. Make sure CFLAGS is - # included so -mno-cygwin passed the correct libs to the linker. - SHLIB_LD='${CC} -shared ${CFLAGS}' + # -luser32 and -lmsvcrt by default. + SHLIB_LD='${CC} -shared' SHLIB_LD_LIBS='${LIBS}' # Add SHLIB_LD_LIBS to the Make rule, not here. MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \[$]@ ${extra_ldflags} \ @@ -798,6 +949,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ RC_DEFINE=-d RES=res MAKE_LIB="\${STLIB_LD} -out:\[$]@" + MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\[$]@" POST_MAKE_LIB= MAKE_EXE="\${CC} -Fe\[$]@" LIBPREFIX="" diff --git a/win/tkWin32Dll.c b/win/tkWin32Dll.c index efefe86..3c3d83a 100644 --- a/win/tkWin32Dll.c +++ b/win/tkWin32Dll.c @@ -17,17 +17,17 @@ /* * Unlike Borland and Microsoft, we don't register exception handlers by * pushing registration records onto the runtime stack. Instead, we register - * them by creating an EXCEPTION_REGISTRATION within the activation record. + * them by creating an TCLEXCEPTION_REGISTRATION within the activation record. */ -typedef struct EXCEPTION_REGISTRATION { - struct EXCEPTION_REGISTRATION *link; +typedef struct TCLEXCEPTION_REGISTRATION { + struct TCLEXCEPTION_REGISTRATION *link; EXCEPTION_DISPOSITION (*handler)( struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*); void *ebp; void *esp; int status; -} EXCEPTION_REGISTRATION; +} TCLEXCEPTION_REGISTRATION; /* * Need to add noinline flag to DllMain declaration so that gcc -O3 does not @@ -102,7 +102,7 @@ DllMain( LPVOID reserved) { #ifdef HAVE_NO_SEH - EXCEPTION_REGISTRATION registration; + TCLEXCEPTION_REGISTRATION registration; #endif /* @@ -127,21 +127,21 @@ DllMain( __asm__ __volatile__ ( /* - * Construct an EXCEPTION_REGISTRATION to protect the call to + * Construct an TCLEXCEPTION_REGISTRATION to protect the call to * TkFinalize */ "leaq %[registration], %%rdx" "\n\t" "movq %%gs:0, %%rax" "\n\t" - "movq %%rax, 0x0(%%edx)" "\n\t" /* link */ + "movq %%rax, 0x0(%%rdx)" "\n\t" /* link */ "leaq 1f, %%rax" "\n\t" "movq %%rax, 0x8(%%rdx)" "\n\t" /* handler */ - "movq %%rbp, 0x10(%%rdx)" "\n\t" /* ebp */ - "movq %%rsp, 0x18(%%rdx)" "\n\t" /* esp */ + "movq %%rbp, 0x10(%%rdx)" "\n\t" /* rbp */ + "movq %%rsp, 0x18(%%rdx)" "\n\t" /* rsp */ "movl %[error], 0x20(%%rdx)" "\n\t" /* status */ /* - * Link the EXCEPTION_REGISTRATION on the chain + * Link the TCLEXCEPTION_REGISTRATION on the chain */ "movq %%rdx, %%gs:0" "\n\t" @@ -154,7 +154,7 @@ DllMain( "call TkFinalize" "\n\t" /* - * Come here on a normal exit. Recover the EXCEPTION_REGISTRATION + * Come here on a normal exit. Recover the TCLEXCEPTION_REGISTRATION * and store a TCL_OK status */ @@ -164,7 +164,7 @@ DllMain( "jmp 2f" "\n" /* - * Come here on an exception. Get the EXCEPTION_REGISTRATION that + * Come here on an exception. Get the TCLEXCEPTION_REGISTRATION that * we previously put on the chain. */ @@ -174,7 +174,7 @@ DllMain( /* * Come here however we exited. Restore context from the - * EXCEPTION_REGISTRATION in case the stack is unbalanced. + * TCLEXCEPTION_REGISTRATION in case the stack is unbalanced. */ "2:" "\t" @@ -197,7 +197,7 @@ DllMain( __asm__ __volatile__ ( /* - * Construct an EXCEPTION_REGISTRATION to protect the call to + * Construct an TCLEXCEPTION_REGISTRATION to protect the call to * TkFinalize */ @@ -211,7 +211,7 @@ DllMain( "movl %[error], 0x10(%%edx)" "\n\t" /* status */ /* - * Link the EXCEPTION_REGISTRATION on the chain + * Link the TCLEXCEPTION_REGISTRATION on the chain */ "movl %%edx, %%fs:0" "\n\t" @@ -224,7 +224,7 @@ DllMain( "call _TkFinalize" "\n\t" /* - * Come here on a normal exit. Recover the EXCEPTION_REGISTRATION + * Come here on a normal exit. Recover the TCLEXCEPTION_REGISTRATION * and store a TCL_OK status */ @@ -234,7 +234,7 @@ DllMain( "jmp 2f" "\n" /* - * Come here on an exception. Get the EXCEPTION_REGISTRATION that + * Come here on an exception. Get the TCLEXCEPTION_REGISTRATION that * we previously put on the chain. */ @@ -245,7 +245,7 @@ DllMain( /* * Come here however we exited. Restore context from the - * EXCEPTION_REGISTRATION in case the stack is unbalanced. + * TCLEXCEPTION_REGISTRATION in case the stack is unbalanced. */ "2:" "\t" diff --git a/win/tkWinButton.c b/win/tkWinButton.c index f4d2d05..9e1960d 100644 --- a/win/tkWinButton.c +++ b/win/tkWinButton.c @@ -1265,21 +1265,29 @@ ButtonProc( return 0; } case BN_CLICKED: { - int code; - Tcl_Interp *interp = butPtr->info.interp; - - if (butPtr->info.state != STATE_DISABLED) { - Tcl_Preserve((ClientData)interp); - code = TkInvokeButton((TkButton*)butPtr); - if (code != TCL_OK && code != TCL_CONTINUE - && code != TCL_BREAK) { - Tcl_AddErrorInfo(interp, "\n (button invoke)"); - Tcl_BackgroundError(interp); + /* + * OOPS: chromium fires WM_NULL regularly to ping if plugin is still + * alive. When using an external window (i.e. via the tcl plugin), this + * causes all buttons to fire once a second, so we need to make sure + * that we are not dealing with the chromium life check. + */ + if (wParam != 0 || lParam != 0) { + int code; + Tcl_Interp *interp = butPtr->info.interp; + + if (butPtr->info.state != STATE_DISABLED) { + Tcl_Preserve((ClientData)interp); + code = TkInvokeButton((TkButton*)butPtr); + if (code != TCL_OK && code != TCL_CONTINUE + && code != TCL_BREAK) { + Tcl_AddErrorInfo(interp, "\n (button invoke)"); + Tcl_BackgroundError(interp); + } + Tcl_Release((ClientData)interp); } - Tcl_Release((ClientData)interp); + Tcl_ServiceAll(); + return 0; } - Tcl_ServiceAll(); - return 0; } default: diff --git a/win/tkWinDialog.c b/win/tkWinDialog.c index 069991b..e03862c 100644 --- a/win/tkWinDialog.c +++ b/win/tkWinDialog.c @@ -8,7 +8,6 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ - #define WINVER 0x0500 /* Requires Windows 2K definitions */ #define _WIN32_WINNT 0x0500 #include "tkWinInt.h" @@ -51,19 +50,6 @@ #define OPENFILENAME_SIZE_VERSION_400 76 #endif -/* - * The following structure is used by the new Tk_ChooseDirectoryObjCmd to pass - * data between it and its callback. Unqiue to Winodws platform. - */ - -typedef struct ChooseDirData { - TCHAR utfInitDir[MAX_PATH]; /* Initial folder to use */ - TCHAR utfRetDir[MAX_PATH]; /* Returned folder to use */ - Tcl_Interp *interp; - int mustExist; /* True if file must exist to return from - * callback */ -} CHOOSEDIRDATA; - typedef struct ThreadSpecificData { int debugFlag; /* Flags whether we should output debugging * information while displaying a builtin @@ -132,14 +118,14 @@ static const struct {int type; int btnIds[3];} allowedTypes[] = { */ #define TkWinGetHInstance(from) \ - ((HINSTANCE) GetWindowLongPtr((from), GWLP_HINSTANCE)) + ((HINSTANCE) GetWindowLongPtrW((from), GWLP_HINSTANCE)) #define TkWinGetUserData(from) \ - GetWindowLongPtr((from), GWLP_USERDATA) + GetWindowLongPtrW((from), GWLP_USERDATA) #define TkWinSetUserData(to,what) \ - SetWindowLongPtr((to), GWLP_USERDATA, (LPARAM)(what)) + SetWindowLongPtrW((to), GWLP_USERDATA, (LPARAM)(what)) /* - * The value of TK_MULTI_MAX_PATH dictactes how many files can be retrieved + * The value of TK_MULTI_MAX_PATH dictates how many files can be retrieved * with tk_get*File -multiple 1. It must be allocated on the stack, so make it * large enough but not too large. - hobbs * @@ -154,27 +140,17 @@ static const struct {int type; int btnIds[3];} allowedTypes[] = { * chooser function, Tk_ChooseDirectoryObjCmd(), and its dialog hook proc. */ -typedef struct ChooseDir { - Tcl_Interp *interp; /* Interp, used only if debug is turned on, - * for setting the "tk_dialog" variable. */ - int lastCtrl; /* Used by hook proc to keep track of last - * control that had input focus, so when OK is - * pressed we know whether to browse a new - * directory or return. */ - int lastIdx; /* Last item that was selected in directory - * browser listbox. */ - TCHAR path[MAX_PATH]; /* On return from choose directory dialog, - * holds the selected path. Cannot return - * selected path in ofnPtr->lpstrFile because - * the default dialog proc stores a '\0' in - * it, since, of course, no _file_ was - * selected. */ - OPENFILENAME *ofnPtr; /* pointer to the OFN structure */ +typedef struct { + WCHAR initDir[MAX_PATH]; /* Initial folder to use */ + WCHAR retDir[MAX_PATH]; /* Returned folder to use */ + Tcl_Interp *interp; + int mustExist; /* True if file must exist to return from + * callback */ } ChooseDir; /* - * The following structure is used to pass information between GetFileName/W - * functions and OFN dialog hook procedures. [Bug 2896501, Patch 2898255] + * The following structure is used to pass information between GetFileName + * function and OFN dialog hook procedures. [Bug 2896501, Patch 2898255] */ typedef struct OFNData { @@ -183,8 +159,7 @@ typedef struct OFNData { int dynFileBufferSize; /* Dynamic filename buffer size, stored to * avoid shrinking and expanding the buffer * when selection changes */ - char *dynFileBuffer; /* Dynamic filename buffer, cast to WCHAR* in - * UNICODE procedures */ + WCHAR *dynFileBuffer; /* Dynamic filename buffer */ } OFNData; /* @@ -195,23 +170,18 @@ static UINT APIENTRY ChooseDirectoryValidateProc(HWND hdlg, UINT uMsg, LPARAM wParam, LPARAM lParam); static UINT CALLBACK ColorDlgHookProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); -static int GetFileNameA(ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[], int isOpen); -static int GetFileNameW(ClientData clientData, +static int GetFileName(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[], int isOpen); + Tcl_Obj *const objv[], int isOpen); static int MakeFilter(Tcl_Interp *interp, Tcl_Obj *valuePtr, Tcl_DString *dsPtr, Tcl_Obj *initialPtr, - int *index); -static UINT APIENTRY OFNHookProcA(HWND hdlg, UINT uMsg, WPARAM wParam, - LPARAM lParam); -static UINT APIENTRY OFNHookProcW(HWND hdlg, UINT uMsg, WPARAM wParam, + int *indexPtr); +static UINT APIENTRY OFNHookProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK MsgBoxCBTProc(int nCode, WPARAM wParam, LPARAM lParam); static void SetTkDialog(ClientData clientData); -static char * ConvertExternalFilename(Tcl_Encoding encoding, - char *filename, Tcl_DString *dsPtr); +static const char *ConvertExternalFilename(WCHAR *filename, + Tcl_DString *dsPtr); /* *------------------------------------------------------------------------- @@ -252,10 +222,10 @@ EatSpuriousMessageBugFix(void) DWORD nTime = GetTickCount() + 250; while (GetTickCount() < nTime) { - if (PeekMessage(&msg, 0, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE)){ + if (PeekMessageA(&msg, 0, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE)){ break; } - PeekMessage(&msg, 0, WM_LBUTTONUP, WM_LBUTTONUP, PM_REMOVE); + PeekMessageA(&msg, 0, WM_LBUTTONUP, WM_LBUTTONUP, PM_REMOVE); } } @@ -312,16 +282,16 @@ Tk_ChooseColorObjCmd( ClientData clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[]) /* Argument objects. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData, parent; HWND hWnd; int i, oldMode, winCode, result; - CHOOSECOLOR chooseColor; + CHOOSECOLORW chooseColor; static int inited = 0; static COLORREF dwCustColors[16]; static long oldColor; /* the color selected last time */ - static CONST char *optionStrings[] = { + static const char *optionStrings[] = { "-initialcolor", "-parent", "-title", NULL }; enum options { @@ -345,7 +315,7 @@ Tk_ChooseColorObjCmd( } parent = tkwin; - chooseColor.lStructSize = sizeof(CHOOSECOLOR); + chooseColor.lStructSize = sizeof(CHOOSECOLORW); chooseColor.hwndOwner = NULL; chooseColor.hInstance = NULL; chooseColor.rgbResult = oldColor; @@ -353,11 +323,11 @@ Tk_ChooseColorObjCmd( chooseColor.Flags = CC_RGBINIT | CC_FULLOPEN | CC_ENABLEHOOK; chooseColor.lCustData = (LPARAM) NULL; chooseColor.lpfnHook = (LPOFNHOOKPROC) ColorDlgHookProc; - chooseColor.lpTemplateName = (LPTSTR) interp; + chooseColor.lpTemplateName = (LPWSTR) interp; for (i = 1; i < objc; i += 2) { int index; - char *string; + const char *string; Tcl_Obj *optionPtr, *valuePtr; optionPtr = objv[i]; @@ -405,7 +375,7 @@ Tk_ChooseColorObjCmd( chooseColor.hwndOwner = hWnd; oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); - winCode = ChooseColor(&chooseColor); + winCode = ChooseColorW(&chooseColor); (void) Tcl_SetServiceMode(oldMode); /* @@ -473,7 +443,7 @@ ColorDlgHookProc( ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); const char *title; - CHOOSECOLOR *ccPtr; + CHOOSECOLORW *ccPtr; if (WM_INITDIALOG == uMsg) { @@ -481,14 +451,13 @@ ColorDlgHookProc( * Set the title string of the dialog. */ - ccPtr = (CHOOSECOLOR *) lParam; + ccPtr = (CHOOSECOLORW *) lParam; title = (const char *) ccPtr->lCustData; if ((title != NULL) && (title[0] != '\0')) { Tcl_DString ds; - (*tkWinProcs->setWindowText)(hDlg, - Tcl_WinUtfToTChar(title, -1, &ds)); + SetWindowTextW(hDlg, (WCHAR *)Tcl_WinUtfToTChar(title,-1,&ds)); Tcl_DStringFree(&ds); } if (tsdPtr->debugFlag) { @@ -522,13 +491,9 @@ Tk_GetOpenFileObjCmd( ClientData clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[]) /* Argument objects. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { - if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { - return GetFileNameW(clientData, interp, objc, objv, 1); - } else { - return GetFileNameA(clientData, interp, objc, objv, 1); - } + return GetFileName(clientData, interp, objc, objv, 1); } /* @@ -553,19 +518,15 @@ Tk_GetSaveFileObjCmd( ClientData clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[]) /* Argument objects. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { - if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { - return GetFileNameW(clientData, interp, objc, objv, 0); - } else { - return GetFileNameA(clientData, interp, objc, objv, 0); - } + return GetFileName(clientData, interp, objc, objv, 0); } /* *---------------------------------------------------------------------- * - * GetFileNameW -- + * GetFileName -- * * Calls GetOpenFileName() or GetSaveFileName(). * @@ -579,11 +540,11 @@ Tk_GetSaveFileObjCmd( */ static int -GetFileNameW( +GetFileName( ClientData clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[], /* Argument objects. */ + Tcl_Obj *const objv[], /* Argument objects. */ int open) /* 1 to call GetOpenFileName(), 0 to call * GetSaveFileName(). */ { @@ -593,13 +554,12 @@ GetFileNameW( int cdlgerr; int filterIndex = 0, result = TCL_ERROR, winCode, oldMode, i, multi = 0; int confirmOverwrite = 1; - char *extension = NULL, *title = NULL; + const char *extension = NULL, *title = NULL; Tk_Window tkwin = (Tk_Window) clientData; HWND hWnd; Tcl_Obj *filterObj = NULL, *initialTypeObj = NULL, *typeVariableObj = NULL; Tcl_DString utfFilterString, utfDirString, ds; Tcl_DString extString, filterString, dirString, titleString; - Tcl_Encoding unicodeEncoding = TkWinGetUnicodeEncoding(); ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); enum options { @@ -607,10 +567,10 @@ GetFileNameW( FILE_TITLE, FILE_TYPEVARIABLE, FILE_MULTIPLE, FILE_CONFIRMOW }; struct Options { - CONST char *name; + const char *name; enum options value; }; - static CONST struct Options saveOptions[] = { + static const struct Options saveOptions[] = { {"-confirmoverwrite", FILE_CONFIRMOW}, {"-defaultextension", FILE_DEFAULT}, {"-filetypes", FILE_TYPES}, @@ -621,7 +581,7 @@ GetFileNameW( {"-typevariable", FILE_TYPEVARIABLE}, {NULL, FILE_DEFAULT/*ignored*/ } }; - static CONST struct Options openOptions[] = { + static const struct Options openOptions[] = { {"-defaultextension", FILE_DEFAULT}, {"-filetypes", FILE_TYPES}, {"-initialdir", FILE_INITDIR}, @@ -632,7 +592,7 @@ GetFileNameW( {"-typevariable", FILE_TYPEVARIABLE}, {NULL, FILE_DEFAULT/*ignored*/ } }; - CONST struct Options *options = open ? openOptions : saveOptions; + const struct Options *options = open ? openOptions : saveOptions; file[0] = '\0'; ZeroMemory(&ofnData, sizeof(OFNData)); @@ -645,7 +605,7 @@ GetFileNameW( for (i = 1; i < objc; i += 2) { int index; - char *string; + const char *string; Tcl_Obj *valuePtr = objv[i + 1]; if (Tcl_GetIndexFromObjStruct(interp, objv[i], options, @@ -679,9 +639,9 @@ GetFileNameW( if (Tcl_TranslateFileName(interp, string, &ds) == NULL) { goto end; } - Tcl_UtfToExternal(NULL, unicodeEncoding, Tcl_DStringValue(&ds), - Tcl_DStringLength(&ds), 0, NULL, (char *) file, - sizeof(file), NULL, NULL, NULL); + Tcl_UtfToExternal(NULL, TkWinGetUnicodeEncoding(), + Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), 0, NULL, + (char *) file, sizeof(file), NULL, NULL, NULL); Tcl_DStringFree(&ds); break; case FILE_PARENT: @@ -728,11 +688,11 @@ GetFileNameW( } ofn.hwndOwner = hWnd; ofn.hInstance = TkWinGetHInstance(ofn.hwndOwner); - ofn.lpstrFile = (WCHAR *) file; + ofn.lpstrFile = file; ofn.nMaxFile = TK_MULTI_MAX_PATH; ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_ENABLEHOOK| OFN_ENABLESIZING; - ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProcW; + ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProc; ofn.lCustData = (LPARAM) &ofnData; if (open != 0) { @@ -751,24 +711,22 @@ GetFileNameW( * procedure when necessary */ - ofnData.dynFileBufferSize = 1024; - ofnData.dynFileBuffer = ckalloc(1024); + ofnData.dynFileBufferSize = 512; + ofnData.dynFileBuffer = (WCHAR *)ckalloc(512 * sizeof(WCHAR)); } if (extension != NULL) { - Tcl_UtfToExternalDString(unicodeEncoding, extension, -1, &extString); + Tcl_WinUtfToTChar(extension, -1, &extString); ofn.lpstrDefExt = (WCHAR *) Tcl_DStringValue(&extString); } - Tcl_UtfToExternalDString(unicodeEncoding, - Tcl_DStringValue(&utfFilterString), + Tcl_WinUtfToTChar(Tcl_DStringValue(&utfFilterString), Tcl_DStringLength(&utfFilterString), &filterString); ofn.lpstrFilter = (WCHAR *) Tcl_DStringValue(&filterString); ofn.nFilterIndex = filterIndex; if (Tcl_DStringValue(&utfDirString)[0] != '\0') { - Tcl_UtfToExternalDString(unicodeEncoding, - Tcl_DStringValue(&utfDirString), + Tcl_WinUtfToTChar(Tcl_DStringValue(&utfDirString), Tcl_DStringLength(&utfDirString), &dirString); } else { /* @@ -784,7 +742,7 @@ GetFileNameW( Tcl_DStringValue(&utfDirString), &cwd) == NULL)) { Tcl_ResetResult(interp); } else { - Tcl_UtfToExternalDString(unicodeEncoding, Tcl_DStringValue(&cwd), + Tcl_WinUtfToTChar(Tcl_DStringValue(&cwd), Tcl_DStringLength(&cwd), &dirString); } Tcl_DStringFree(&cwd); @@ -792,7 +750,7 @@ GetFileNameW( ofn.lpstrInitialDir = (WCHAR *) Tcl_DStringValue(&dirString); if (title != NULL) { - Tcl_UtfToExternalDString(unicodeEncoding, title, -1, &titleString); + Tcl_WinUtfToTChar(title, -1, &titleString); ofn.lpstrTitle = (WCHAR *) Tcl_DStringValue(&titleString); } @@ -858,7 +816,7 @@ GetFileNameW( * first element is the directory path. */ - WCHAR *files = (WCHAR *) ofnData.dynFileBuffer; + WCHAR *files = ofnData.dynFileBuffer; Tcl_Obj *returnList = Tcl_NewObj(); int count = 0; @@ -866,8 +824,7 @@ GetFileNameW( * Get directory. */ - (void) ConvertExternalFilename(unicodeEncoding, (char *) files, - &ds); + ConvertExternalFilename(files, &ds); while (*files != '\0') { while (*files != '\0') { @@ -879,8 +836,7 @@ GetFileNameW( Tcl_DString filenameBuf; count++; - (void) ConvertExternalFilename(unicodeEncoding, - (char *) files, &filenameBuf); + ConvertExternalFilename(files, &filenameBuf); fullnameObj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); @@ -906,8 +862,8 @@ GetFileNameW( Tcl_SetObjResult(interp, returnList); Tcl_DStringFree(&ds); } else { - Tcl_AppendResult(interp, ConvertExternalFilename(unicodeEncoding, - (char *) ofn.lpstrFile, &ds), NULL); + Tcl_AppendResult(interp, ConvertExternalFilename( + ofn.lpstrFile, &ds), NULL); gotFilename = (Tcl_DStringLength(&ds) > 0); Tcl_DStringFree(&ds); } @@ -932,8 +888,8 @@ GetFileNameW( } } else if (cdlgerr == FNERR_INVALIDFILENAME) { Tcl_SetResult(interp, "invalid filename \"", TCL_STATIC); - Tcl_AppendResult(interp, ConvertExternalFilename(unicodeEncoding, - (char *) ofn.lpstrFile, &ds), "\"", NULL); + Tcl_AppendResult(interp, ConvertExternalFilename( + ofn.lpstrFile, &ds), "\"", NULL); Tcl_DStringFree(&ds); } else { result = TCL_OK; @@ -954,7 +910,7 @@ GetFileNameW( Tcl_DStringFree(&utfDirString); Tcl_DStringFree(&utfFilterString); if (ofnData.dynFileBuffer != NULL) { - ckfree(ofnData.dynFileBuffer); + ckfree((char *)ofnData.dynFileBuffer); ofnData.dynFileBuffer = NULL; } @@ -964,7 +920,7 @@ GetFileNameW( /* *------------------------------------------------------------------------- * - * OFNHookProcW -- + * OFNHookProc -- * * Dialog box hook function. This is used to sets the "tk_dialog" * variable for test/debugging when the dialog is ready to receive @@ -981,7 +937,7 @@ GetFileNameW( */ static UINT APIENTRY -OFNHookProcW( +OFNHookProc( HWND hdlg, /* Handle to child dialog window. */ UINT uMsg, /* Message identifier */ WPARAM wParam, /* Message parameter */ @@ -998,14 +954,16 @@ OFNHookProcW( OFNOTIFYW *notifyPtr = (OFNOTIFYW *) lParam; /* - * This is weird... or not. The CDN_FILEOK is NOT sent when the selection - * exceeds declared buffer size (the nMaxFile member of the OPENFILENAMEW - * struct passed to GetOpenFileNameW function). So, we have to rely on - * the most recent CDN_SELCHANGE then. Unfortunately this means, that - * gathering the selected filenames happens twice when they fit into the - * declared buffer. Luckily, it's not frequent operation so it should - * not incur any noticeable delay. See [tktoolkit-Bugs-2987995] + * This is weird... or not. The CDN_FILEOK is NOT sent when the + * selection exceeds declared buffer size (the nMaxFile member of the + * OPENFILENAME struct passed to GetOpenFileName function). So, we + * have to rely on the most recent CDN_SELCHANGE then. Unfortunately + * this means, that gathering the selected filenames happens twice + * when they fit into the declared buffer. Luckily, it's not frequent + * operation so it should not incur any noticeable delay. See [Bug + * 2987995] */ + if (notifyPtr->hdr.code == CDN_FILEOK || notifyPtr->hdr.code == CDN_SELCHANGE) { int dirsize, selsize; @@ -1019,21 +977,23 @@ OFNHookProcW( ofnPtr = notifyPtr->lpOFN; ofnData = (OFNData *) ofnPtr->lCustData; - buffer = (WCHAR *) ofnData->dynFileBuffer; + buffer = ofnData->dynFileBuffer; hdlg = GetParent(hdlg); selsize = SendMessageW(hdlg, CDM_GETSPEC, 0, 0); dirsize = SendMessageW(hdlg, CDM_GETFOLDERPATH, 0, 0); - buffersize = (selsize + dirsize + 1) * 2; + buffersize = (selsize + dirsize + 1); /* - * Just empty the buffer if dirsize indicates an error [Bug 3071836] + * Just empty the buffer if dirsize indicates an error. [Bug + * 3071836] */ + if ((selsize > 1) && (dirsize > 0)) { if (ofnData->dynFileBufferSize < buffersize) { - buffer = (WCHAR *) ckrealloc((char *) buffer, buffersize); + buffer = (WCHAR *) ckrealloc((char *) buffer, buffersize * sizeof(WCHAR)); ofnData->dynFileBufferSize = buffersize; - ofnData->dynFileBuffer = (char *) buffer; + ofnData->dynFileBuffer = buffer; } SendMessageW(hdlg, CDM_GETFOLDERPATH, dirsize, (LPARAM) buffer); @@ -1050,7 +1010,7 @@ OFNHookProcW( BOOL findquote = TRUE; WCHAR *tmp = buffer; - while(*buffer != '\0') { + while (*buffer != '\0') { if (findquote) { if (*buffer == '"') { findquote = FALSE; @@ -1066,14 +1026,24 @@ OFNHookProcW( } *tmp = '\0'; /* Second NULL terminator. */ } else { - buffer[selsize] = '\0'; /* Second NULL terminator. */ - /* - * Replace directory terminating NULL with a backslash. + /* + * Replace directory terminating NULL with a with a backslash, + * but only if not an absolute path. */ - buffer--; - *buffer = '\\'; + Tcl_DString tmpfile; + ConvertExternalFilename(buffer, &tmpfile); + if (TCL_PATH_ABSOLUTE == + Tcl_GetPathType(Tcl_DStringValue(&tmpfile))) { + /* re-get the full path to the start of the buffer */ + buffer = (WCHAR *) ofnData->dynFileBuffer; + SendMessageW(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer); + } else { + *(buffer-1) = '\\'; + } + buffer[selsize] = '\0'; /* Second NULL terminator. */ + Tcl_DStringFree(&tmpfile); } } else { /* @@ -1109,557 +1079,6 @@ OFNHookProcW( /* *---------------------------------------------------------------------- * - * GetFileNameA -- - * - * Calls GetOpenFileName() or GetSaveFileName(). - * - * Results: - * See user documentation. - * - * Side effects: - * See user documentation. - * - *---------------------------------------------------------------------- - */ - -static int -GetFileNameA( - ClientData clientData, /* Main window associated with interpreter. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[], /* Argument objects. */ - int open) /* 1 to call GetOpenFileName(), 0 to call - * GetSaveFileName(). */ -{ - OPENFILENAME ofn; - TCHAR file[TK_MULTI_MAX_PATH], savePath[MAX_PATH]; - OFNData ofnData; - int cdlgerr; - int filterIndex = 0, result = TCL_ERROR, winCode, oldMode, i, multi = 0; - char *extension = NULL, *title = NULL; - Tk_Window tkwin = (Tk_Window) clientData; - HWND hWnd; - Tcl_Obj *filterObj = NULL, *initialTypeObj = NULL, *typeVariableObj = NULL; - Tcl_DString utfFilterString, utfDirString, ds; - Tcl_DString extString, filterString, dirString, titleString; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - static CONST char *saveOptionStrings[] = { - "-defaultextension", "-filetypes", "-initialdir", "-initialfile", - "-parent", "-title", "-typevariable", NULL - }; - static CONST char *openOptionStrings[] = { - "-defaultextension", "-filetypes", "-initialdir", "-initialfile", - "-multiple", "-parent", "-title", "-typevariable", NULL - }; - CONST char **optionStrings; - - enum options { - FILE_DEFAULT, FILE_TYPES, FILE_INITDIR, FILE_INITFILE, - FILE_MULTIPLE, FILE_PARENT, FILE_TITLE, FILE_TYPEVARIABLE - }; - - file[0] = '\0'; - ZeroMemory(&ofnData, sizeof(OFNData)); - Tcl_DStringInit(&utfFilterString); - Tcl_DStringInit(&utfDirString); - - /* - * Parse the arguments. - */ - - if (open) { - optionStrings = openOptionStrings; - } else { - optionStrings = saveOptionStrings; - } - - for (i = 1; i < objc; i += 2) { - int index; - char *string; - Tcl_Obj *optionPtr, *valuePtr; - - optionPtr = objv[i]; - valuePtr = objv[i + 1]; - - if (Tcl_GetIndexFromObj(interp, optionPtr, optionStrings, "option", 0, - &index) != TCL_OK) { - goto end; - } - - /* - * We want to maximize code sharing between the open and save file - * dialog implementations; in particular, the switch statement below. - * We use different sets of option strings from the GetIndexFromObj - * call above, but a single enumeration for both. The save file dialog - * doesn't support -multiple, but it falls in the middle of the - * enumeration. Ultimately, this means that when the index found by - * GetIndexFromObj is >= FILE_MULTIPLE, when doing a save file dialog, - * we have to increment the index, so that it matches the open file - * dialog enumeration. - */ - - if (!open && index >= FILE_MULTIPLE) { - index++; - } - if (i + 1 == objc) { - string = Tcl_GetString(optionPtr); - Tcl_AppendResult(interp, "value for \"", string, "\" missing", - NULL); - goto end; - } - - string = Tcl_GetString(valuePtr); - switch ((enum options) index) { - case FILE_DEFAULT: - if (string[0] == '.') { - string++; - } - extension = string; - break; - case FILE_TYPES: - filterObj = valuePtr; - break; - case FILE_INITDIR: - Tcl_DStringFree(&utfDirString); - if (Tcl_TranslateFileName(interp, string, &utfDirString) == NULL) { - goto end; - } - break; - case FILE_INITFILE: - if (Tcl_TranslateFileName(interp, string, &ds) == NULL) { - goto end; - } - Tcl_UtfToExternal(NULL, NULL, Tcl_DStringValue(&ds), - Tcl_DStringLength(&ds), 0, NULL, (char *) file, - sizeof(file), NULL, NULL, NULL); - Tcl_DStringFree(&ds); - break; - case FILE_MULTIPLE: - if (Tcl_GetBooleanFromObj(interp, valuePtr, &multi) != TCL_OK) { - return TCL_ERROR; - } - break; - case FILE_PARENT: - tkwin = Tk_NameToWindow(interp, string, tkwin); - if (tkwin == NULL) { - goto end; - } - break; - case FILE_TITLE: - title = string; - break; - case FILE_TYPEVARIABLE: - typeVariableObj = valuePtr; - initialTypeObj = Tcl_ObjGetVar2(interp, typeVariableObj, NULL, - TCL_GLOBAL_ONLY); - break; - } - } - - if (MakeFilter(interp, filterObj, &utfFilterString, initialTypeObj, - &filterIndex) != TCL_OK) { - goto end; - } - - Tk_MakeWindowExist(tkwin); - hWnd = Tk_GetHWND(Tk_WindowId(tkwin)); - - ZeroMemory(&ofn, sizeof(OPENFILENAMEA)); - if (LOBYTE(LOWORD(GetVersion())) < 5) { - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - } else { - ofn.lStructSize = sizeof(ofn); - } - ofn.hwndOwner = hWnd; - ofn.hInstance = TkWinGetHInstance(ofn.hwndOwner); - ofn.lpstrFilter = NULL; - ofn.lpstrCustomFilter = NULL; - ofn.nMaxCustFilter = 0; - ofn.lpstrFile = (LPTSTR) file; - ofn.nMaxFile = TK_MULTI_MAX_PATH; - ofn.lpstrFileTitle = NULL; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = NULL; - ofn.lpstrTitle = NULL; - ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR - | OFN_EXPLORER | OFN_ENABLEHOOK; - ofn.nFileOffset = 0; - ofn.nFileExtension = 0; - ofn.lpstrDefExt = NULL; - ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProcA; - ofn.lCustData = (LPARAM) &ofnData; - ofn.lpTemplateName = NULL; - - if (open != 0) { - ofn.Flags |= OFN_FILEMUSTEXIST; - } else { - ofn.Flags |= OFN_OVERWRITEPROMPT; - } - - if (tsdPtr->debugFlag != 0) { - ofnData.interp = interp; - } - - if (multi != 0) { - ofn.Flags |= OFN_ALLOWMULTISELECT; - - /* - * Starting buffer size. The buffer will be expanded by the OFN dialog - * procedure when necessary - */ - - ofnData.dynFileBufferSize = 1024; - ofnData.dynFileBuffer = ckalloc(1024); - } - - if (extension != NULL) { - Tcl_UtfToExternalDString(NULL, extension, -1, &extString); - ofn.lpstrDefExt = (LPTSTR) Tcl_DStringValue(&extString); - } - Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&utfFilterString), - Tcl_DStringLength(&utfFilterString), &filterString); - ofn.lpstrFilter = (LPTSTR) Tcl_DStringValue(&filterString); - ofn.nFilterIndex = filterIndex; - - if (Tcl_DStringValue(&utfDirString)[0] != '\0') { - Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&utfDirString), - Tcl_DStringLength(&utfDirString), &dirString); - } else { - /* - * NT 5.0 changed the meaning of lpstrInitialDir, so we have to ensure - * that we set the [pwd] if the user didn't specify anything else. - */ - - Tcl_DString cwd; - - Tcl_DStringFree(&utfDirString); - if ((Tcl_GetCwd(interp, &utfDirString) == NULL) || - (Tcl_TranslateFileName(interp, - Tcl_DStringValue(&utfDirString), &cwd) == NULL)) { - Tcl_ResetResult(interp); - } else { - Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&cwd), - Tcl_DStringLength(&cwd), &dirString); - } - Tcl_DStringFree(&cwd); - } - ofn.lpstrInitialDir = (LPTSTR) Tcl_DStringValue(&dirString); - - if (title != NULL) { - Tcl_UtfToExternalDString(NULL, title, -1, &titleString); - ofn.lpstrTitle = (LPTSTR) Tcl_DStringValue(&titleString); - } - - /* - * Popup the dialog. - */ - - GetCurrentDirectory(MAX_PATH, savePath); - oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); - if (open != 0) { - winCode = GetOpenFileName(&ofn); - } else { - winCode = GetSaveFileName(&ofn); - } - Tcl_SetServiceMode(oldMode); - EatSpuriousMessageBugFix(); - SetCurrentDirectory(savePath); - - /* - * Ensure that hWnd is enabled, because it can happen that we have updated - * the wrapper of the parent, which causes us to leave this child disabled - * (Windows loses sync). - */ - - EnableWindow(hWnd, 1); - - /* - * Clear the interp result since anything may have happened during the - * modal loop. - */ - - Tcl_ResetResult(interp); - - /* - * Process the results. - * - * Use the CommDlgExtendedError() function to retrieve the error code. - * This function can return one of about two dozen codes; most of these - * indicate some sort of gross system failure (insufficient memory, bad - * window handles, etc.) Most of the error codes will be ignored; as we - * find we want specific error messages for particular errors, we can - * extend the code as needed. - */ - - cdlgerr = CommDlgExtendedError(); - - /* - * We now allow FNERR_BUFFERTOOSMALL when multiselection is enabled. The - * filename buffer has been dynamically allocated by the OFN dialog - * procedure to accomodate all selected files. - */ - - if ((winCode != 0) - || ((cdlgerr == FNERR_BUFFERTOOSMALL) - && (ofn.Flags & OFN_ALLOWMULTISELECT))) { - if (ofn.Flags & OFN_ALLOWMULTISELECT) { - /* - * The result in dynFileBuffer contains many items, separated by - * NUL characters. It is terminated with two nulls in a row. The - * first element is the directory path (if multiple files are - * selected) or the only returned file (if only a single file has - * been chosen). - */ - - char *files = ofnData.dynFileBuffer; - Tcl_Obj *returnList = Tcl_NewObj(); - int count = 0; - - /* - * Get directory. - */ - - (void) ConvertExternalFilename(NULL, (char *) files, &ds); - - while (*files != '\0') { - while (*files != '\0') { - files++; - } - files++; - if (*files != '\0') { - Tcl_Obj *fullnameObj; - Tcl_DString filename; - - count++; - (void) ConvertExternalFilename(NULL, (char *) files, - &filename); - fullnameObj = Tcl_NewStringObj(Tcl_DStringValue(&ds), - Tcl_DStringLength(&ds)); - Tcl_AppendToObj(fullnameObj, "/", -1); - Tcl_AppendToObj(fullnameObj, Tcl_DStringValue(&filename), - Tcl_DStringLength(&filename)); - Tcl_DStringFree(&filename); - Tcl_ListObjAppendElement(NULL, returnList, fullnameObj); - } - } - if (count == 0) { - /* - * Only one file was returned. - */ - - Tcl_ListObjAppendElement(NULL, returnList, Tcl_NewStringObj( - Tcl_DStringValue(&ds), Tcl_DStringLength(&ds))); - } - Tcl_SetObjResult(interp, returnList); - Tcl_DStringFree(&ds); - } else { - Tcl_AppendResult(interp, ConvertExternalFilename(NULL, - (char *) ofn.lpstrFile, &ds), NULL); - Tcl_DStringFree(&ds); - } - result = TCL_OK; - if ((ofn.nFilterIndex > 0) && - (Tcl_GetCharLength(Tcl_GetObjResult(interp)) > 0) && - typeVariableObj && filterObj) { - int listObjc, count; - Tcl_Obj **listObjv = NULL; - Tcl_Obj **typeInfo = NULL; - - if (Tcl_ListObjGetElements(interp, filterObj, &listObjc, - &listObjv) != TCL_OK) { - result = TCL_ERROR; - } else if (Tcl_ListObjGetElements(interp, - listObjv[ofn.nFilterIndex - 1], &count, - &typeInfo) != TCL_OK) { - result = TCL_ERROR; - } else if (Tcl_ObjSetVar2(interp, typeVariableObj, NULL, - typeInfo[0], TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { - result = TCL_ERROR; - } - } - } else if (cdlgerr == FNERR_INVALIDFILENAME) { - Tcl_SetResult(interp, "invalid filename \"", TCL_STATIC); - Tcl_AppendResult(interp, ConvertExternalFilename(NULL, - (char *) ofn.lpstrFile, &ds), "\"", NULL); - Tcl_DStringFree(&ds); - } else { - result = TCL_OK; - } - - if (ofn.lpstrTitle != NULL) { - Tcl_DStringFree(&titleString); - } - if (ofn.lpstrInitialDir != NULL) { - Tcl_DStringFree(&dirString); - } - Tcl_DStringFree(&filterString); - if (ofn.lpstrDefExt != NULL) { - Tcl_DStringFree(&extString); - } - - end: - Tcl_DStringFree(&utfDirString); - Tcl_DStringFree(&utfFilterString); - if (ofnData.dynFileBuffer != NULL) { - ckfree(ofnData.dynFileBuffer); - ofnData.dynFileBuffer = NULL; - } - - return result; -} - -/* - *------------------------------------------------------------------------- - * - * OFNHookProcA -- - * - * Dialog box hook function. This is used to sets the "tk_dialog" - * variable for test/debugging when the dialog is ready to receive - * messages. When multiple file selection is enabled this function - * is used to process the list of names. - * - * Results: - * Returns 0 to allow default processing of messages to occur. - * - * Side effects: - * None. - * - *------------------------------------------------------------------------- - */ - -static UINT APIENTRY -OFNHookProcA( - HWND hdlg, /* handle to child dialog window */ - UINT uMsg, /* message identifier */ - WPARAM wParam, /* message parameter */ - LPARAM lParam) /* message parameter */ -{ - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - OPENFILENAME *ofnPtr; - OFNData *ofnData; - - if (uMsg == WM_INITDIALOG) { - TkWinSetUserData(hdlg, lParam); - } else if (uMsg == WM_NOTIFY) { - OFNOTIFY *notifyPtr = (OFNOTIFY *) lParam; - - /* - * This is weird... or not. The CDN_FILEOK is NOT sent when the selection - * exceeds declared buffer size (the nMaxFile member of the OPENFILENAMEW - * struct passed to GetOpenFileNameW function). So, we have to rely on - * the most recent CDN_SELCHANGE then. Unfortunately this means, that - * gathering the selected filenames happens twice when they fit into the - * declared buffer. Luckily, it's not frequent operation so it should - * not incur any noticeable delay. See [tktoolkit-Bugs-2987995] - */ - if (notifyPtr->hdr.code == CDN_FILEOK || - notifyPtr->hdr.code == CDN_SELCHANGE) { - int dirsize, selsize; - char *buffer; - int buffersize; - - /* - * Change of selection. Unscramble the unholy mess that's in the - * selection buffer, resizing it if necessary. - */ - - ofnPtr = notifyPtr->lpOFN; - ofnData = (OFNData *) ofnPtr->lCustData; - buffer = ofnData->dynFileBuffer; - hdlg = GetParent(hdlg); - - selsize = SendMessage(hdlg, CDM_GETSPEC, 0, 0); - dirsize = SendMessage(hdlg, CDM_GETFOLDERPATH, 0, 0); - buffersize = selsize + dirsize + 1; - - /* - * Just empty the buffer if dirsize indicates an error [Bug 3071836] - */ - if ((selsize > 1) && (dirsize > 0)) { - if (ofnData->dynFileBufferSize < buffersize) { - buffer = ckrealloc(buffer, buffersize); - ofnData->dynFileBufferSize = buffersize; - ofnData->dynFileBuffer = buffer; - } - - SendMessage(hdlg, CDM_GETFOLDERPATH, dirsize, (LPARAM) buffer); - buffer += dirsize; - SendMessage(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer); - - /* - * If there are multiple files, delete the quotes and change - * every second quote to NULL terminator. - */ - - if (buffer[0] == '"') { - BOOL findquote = TRUE; - char *tmp = buffer; - - while (*buffer != '\0') { - if (findquote) { - if (*buffer == '"') { - findquote = FALSE; - } - buffer++; - } else { - if (*buffer == '"') { - findquote = TRUE; - *buffer = '\0'; - } - *tmp++ = *buffer++; - } - } - *tmp = '\0'; /* Second NULL terminator. */ - } else { - buffer[selsize] = '\0'; /* Second NULL terminator. */ - - /* - * Replace directory terminating NULL with a backslash. - */ - - buffer--; - *buffer = '\\'; - } - - } else { - /* - * Nothing is selected, so just empty the string. - */ - - if (buffer != NULL) { - *buffer = '\0'; - } - } - } - } else if (uMsg == WM_WINDOWPOSCHANGED) { - /* - * This message is delivered at the right time to both old-style and - * explorer-style hook procs to enable Tk to set the debug - * information. Unhooks itself so it won't set the debug information - * every time it gets a WM_WINDOWPOSCHANGED message. - */ - - ofnPtr = (OPENFILENAME *) TkWinGetUserData(hdlg); - if (ofnPtr != NULL) { - ofnData = (OFNData *) ofnPtr->lCustData; - if (ofnData->interp != NULL) { - if (ofnPtr->Flags & OFN_EXPLORER) { - hdlg = GetParent(hdlg); - } - tsdPtr->debugInterp = ofnData->interp; - Tcl_DoWhenIdle(SetTkDialog, hdlg); - } - TkWinSetUserData(hdlg, NULL); - } - } - return 0; -} - -/* - *---------------------------------------------------------------------- - * * MakeFilter -- * * Allocate a buffer to store the filters in a format understood by @@ -1680,18 +1099,18 @@ MakeFilter( Tcl_Obj *valuePtr, /* Value of the -filetypes option */ Tcl_DString *dsPtr, /* Filled with windows filter string. */ Tcl_Obj *initialPtr, /* Initial type name */ - int *index) /* Index of initial type in filter string */ + int *indexPtr) /* Index of initial type in filter string */ { char *filterStr; char *p; - char *initial = NULL; + const char *initial = NULL; int pass; int ix = 0; /* index counter */ FileFilterList flist; FileFilter *filterPtr; if (initialPtr) { - initial = Tcl_GetStringFromObj(initialPtr, NULL); + initial = Tcl_GetString(initialPtr); } TkInitFileFilters(&flist); if (TkGetFileFilters(interp, &flist, valuePtr, 1) != TCL_OK) { @@ -1702,9 +1121,9 @@ MakeFilter( /* * Use "All Files (*.*) as the default filter if none is specified */ - char *defaultFilter = "All Files (*.*)"; + const char *defaultFilter = "All Files (*.*)"; - p = filterStr = (char*)ckalloc(30 * sizeof(char)); + p = filterStr = ckalloc(30); strcpy(p, defaultFilter); p+= strlen(defaultFilter); @@ -1744,16 +1163,18 @@ MakeFilter( for (filterPtr = flist.filters, p = filterStr; filterPtr; filterPtr = filterPtr->next) { - char *sep; + const char *sep; FileFilterClause *clausePtr; /* - * Check initial index for match, set index. Filter index is 1 + * Check initial index for match, set *indexPtr. Filter index is 1 * based so increment first */ + ix++; - if (index && initial && (strcmp(initial, filterPtr->name) == 0)) { - *index = ix; + if (indexPtr && initial + && (strcmp(initial, filterPtr->name) == 0)) { + *indexPtr = ix; } /* @@ -1889,22 +1310,23 @@ Tk_ChooseDirectoryObjCmd( ClientData clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[]) /* Argument objects. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { - char path[MAX_PATH]; + WCHAR path[MAX_PATH]; int oldMode, result = TCL_ERROR, i; LPCITEMIDLIST pidl; /* Returned by browser */ - BROWSEINFO bInfo; /* Used by browser */ - CHOOSEDIRDATA cdCBData; /* Structure to pass back and forth */ + BROWSEINFOW bInfo; /* Used by browser */ + ChooseDir cdCBData; /* Structure to pass back and forth */ LPMALLOC pMalloc; /* Used by shell */ Tk_Window tkwin = (Tk_Window) clientData; HWND hWnd; - char *utfTitle = NULL;/* Title for window */ - TCHAR saveDir[MAX_PATH]; - Tcl_DString titleString; /* UTF Title */ + const char *utfTitle = NULL;/* Title for window */ + WCHAR saveDir[MAX_PATH]; + Tcl_DString titleString; /* Title */ Tcl_DString initDirString; /* Initial directory */ + Tcl_DString tempString; /* temporary */ Tcl_Obj *objPtr; - static CONST char *optionStrings[] = { + static const char *optionStrings[] = { "-initialdir", "-mustexist", "-parent", "-title", NULL }; enum options { @@ -1916,7 +1338,7 @@ Tk_ChooseDirectoryObjCmd( */ path[0] = '\0'; - ZeroMemory(&cdCBData, sizeof(CHOOSEDIRDATA)); + ZeroMemory(&cdCBData, sizeof(ChooseDir)); cdCBData.interp = interp; /* @@ -1925,7 +1347,8 @@ Tk_ChooseDirectoryObjCmd( for (i = 1; i < objc; i += 2) { int index; - char *string; + const char *string; + const WCHAR *uniStr; Tcl_Obj *optionPtr, *valuePtr; optionPtr = objv[i]; @@ -1948,16 +1371,19 @@ Tk_ChooseDirectoryObjCmd( if (Tcl_TranslateFileName(interp,string,&initDirString) == NULL) { goto cleanup; } - string = Tcl_DStringValue(&initDirString); + Tcl_WinUtfToTChar(Tcl_DStringValue(&initDirString), -1, + &tempString); + uniStr = (WCHAR *) Tcl_DStringValue(&tempString); /* * Convert possible relative path to full path to keep dialog * happy. */ - GetFullPathName(string, MAX_PATH, saveDir, NULL); - lstrcpyn(cdCBData.utfInitDir, saveDir, MAX_PATH); + GetFullPathNameW(uniStr, MAX_PATH, saveDir, NULL); + wcsncpy(cdCBData.initDir, saveDir, MAX_PATH); Tcl_DStringFree(&initDirString); + Tcl_DStringFree(&tempString); break; case DIR_EXIST: if (Tcl_GetBooleanFromObj(interp, valuePtr, @@ -1991,16 +1417,16 @@ Tk_ChooseDirectoryObjCmd( bInfo.hwndOwner = hWnd; bInfo.pszDisplayName = path; bInfo.pidlRoot = NULL; - if (lstrlen(cdCBData.utfInitDir) == 0) { - GetCurrentDirectory(MAX_PATH, cdCBData.utfInitDir); + if (wcslen(cdCBData.initDir) == 0) { + GetCurrentDirectoryW(MAX_PATH, cdCBData.initDir); } bInfo.lParam = (LPARAM) &cdCBData; if (utfTitle != NULL) { - Tcl_UtfToExternalDString(NULL, utfTitle, -1, &titleString); - bInfo.lpszTitle = (LPTSTR) Tcl_DStringValue(&titleString); + Tcl_WinUtfToTChar(utfTitle, -1, &titleString); + bInfo.lpszTitle = (LPWSTR) Tcl_DStringValue(&titleString); } else { - bInfo.lpszTitle = "Please choose a directory, then select OK."; + bInfo.lpszTitle = L"Please choose a directory, then select OK."; } /* @@ -2033,15 +1459,16 @@ Tk_ChooseDirectoryObjCmd( */ oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); - GetCurrentDirectory(MAX_PATH, saveDir); + GetCurrentDirectoryW(MAX_PATH, saveDir); if (SHGetMalloc(&pMalloc) == NOERROR) { - pidl = SHBrowseForFolder(&bInfo); + pidl = SHBrowseForFolderW(&bInfo); /* - * This is a fix for Windows 2000, which seems to modify the folder name - * buffer even when the dialog is canceled (in this case the buffer - * contains garbage). See [Bug #3002230] + * This is a fix for Windows 2000, which seems to modify the folder + * name buffer even when the dialog is canceled (in this case the + * buffer contains garbage). See [Bug #3002230] */ + path[0] = '\0'; /* @@ -2049,17 +1476,17 @@ Tk_ChooseDirectoryObjCmd( */ if (pidl != NULL) { - if (!SHGetPathFromIDList(pidl, path)) { + if (!SHGetPathFromIDListW(pidl, path)) { Tcl_SetResult(interp, "Error: Not a file system folder\n", TCL_VOLATILE); - }; + } pMalloc->lpVtbl->Free(pMalloc, (void *) pidl); - } else if (lstrlen(cdCBData.utfRetDir) > 0) { - lstrcpy(path, cdCBData.utfRetDir); + } else if (wcslen(cdCBData.retDir) > 0) { + wcscpy(path, cdCBData.retDir); } pMalloc->lpVtbl->Release(pMalloc); } - SetCurrentDirectory(saveDir); + SetCurrentDirectoryW(saveDir); Tcl_SetServiceMode(oldMode); /* @@ -2079,7 +1506,7 @@ Tk_ChooseDirectoryObjCmd( if (*path) { Tcl_DString ds; - Tcl_AppendResult(interp, ConvertExternalFilename(NULL, (char *) path, + Tcl_AppendResult(interp, ConvertExternalFilename(path, &ds), NULL); Tcl_DStringFree(&ds); } @@ -2117,10 +1544,11 @@ ChooseDirectoryValidateProc( LPARAM lParam, LPARAM lpData) { - TCHAR selDir[MAX_PATH]; - CHOOSEDIRDATA *chooseDirSharedData = (CHOOSEDIRDATA *) lpData; + WCHAR selDir[MAX_PATH]; + ChooseDir *chooseDirSharedData = (ChooseDir *) lpData; + Tcl_DString tempString; Tcl_DString initDirString; - char string[MAX_PATH]; + WCHAR string[MAX_PATH]; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); @@ -2128,7 +1556,7 @@ ChooseDirectoryValidateProc( tsdPtr->debugInterp = (Tcl_Interp *) chooseDirSharedData->interp; Tcl_DoWhenIdle(SetTkDialog, (ClientData) hwnd); } - chooseDirSharedData->utfRetDir[0] = '\0'; + chooseDirSharedData->retDir[0] = '\0'; switch (message) { case BFFM_VALIDATEFAILED: /* @@ -2140,21 +1568,25 @@ ChooseDirectoryValidateProc( * like ~ are converted correctly. */ + Tcl_WinTCharToUtf((TCHAR *) lParam, -1, &initDirString); if (Tcl_TranslateFileName(chooseDirSharedData->interp, - (char *) lParam, &initDirString) == NULL) { + Tcl_DStringValue(&initDirString), &tempString) == NULL) { /* * Should we expose the error (in the interp result) to the user * at this point? */ - chooseDirSharedData->utfRetDir[0] = '\0'; + chooseDirSharedData->retDir[0] = '\0'; return 1; } - lstrcpyn(string, Tcl_DStringValue(&initDirString), MAX_PATH); + Tcl_DStringFree(&initDirString); + Tcl_WinUtfToTChar(Tcl_DStringValue(&tempString), -1, &initDirString); + Tcl_DStringFree(&tempString); + wcsncpy(string, (WCHAR *) Tcl_DStringValue(&initDirString), + MAX_PATH); Tcl_DStringFree(&initDirString); - if (SetCurrentDirectory((char *)string) == 0) { - LPTSTR lpFilePart[MAX_PATH]; + if (SetCurrentDirectoryW(string) == 0) { /* * Get the full path name to the user entry, at this point it does @@ -2162,16 +1594,17 @@ ChooseDirectoryValidateProc( * it. */ - GetFullPathName(string, MAX_PATH, - chooseDirSharedData->utfRetDir, /*unused*/ lpFilePart); + GetFullPathNameW(string, MAX_PATH, + chooseDirSharedData->retDir, NULL); if (chooseDirSharedData->mustExist) { /* * User HAS to select a valid directory. */ - wsprintf(selDir, TEXT("Directory '%.200s' does not exist,\nplease select or enter an existing directory."), chooseDirSharedData->utfRetDir); - MessageBox(NULL, selDir, NULL, MB_ICONEXCLAMATION|MB_OK); - chooseDirSharedData->utfRetDir[0] = '\0'; + wsprintfW(selDir, L"Directory '%.200s' does not exist,\nplease select or enter an existing directory.", + chooseDirSharedData->retDir); + MessageBoxW(NULL, selDir, NULL, MB_ICONEXCLAMATION|MB_OK); + chooseDirSharedData->retDir[0] = '\0'; return 1; } } else { @@ -2180,7 +1613,7 @@ ChooseDirectoryValidateProc( * directory in utfRetDir. */ - GetCurrentDirectory(MAX_PATH, chooseDirSharedData->utfRetDir); + GetCurrentDirectoryW(MAX_PATH, chooseDirSharedData->retDir); return 0; } return 0; @@ -2195,13 +1628,13 @@ ChooseDirectoryValidateProc( * Not called when user changes edit box directly. */ - if (SHGetPathFromIDList((LPITEMIDLIST) lParam, selDir)) { - SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM) selDir); + if (SHGetPathFromIDListW((LPITEMIDLIST) lParam, selDir)) { + SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM) selDir); // enable the OK button - SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1); + SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1); } else { // disable the OK button - SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 0); + SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 0); } UpdateWindow(hwnd); return 1; @@ -2212,9 +1645,10 @@ ChooseDirectoryValidateProc( * specified parameter. */ - char *initDir = chooseDirSharedData->utfInitDir; + WCHAR *initDir = chooseDirSharedData->initDir; + + SetCurrentDirectoryW(initDir); - SetCurrentDirectory(initDir); if (*initDir == '\\') { /* * BFFM_SETSELECTION only understands UNC paths as pidls, so @@ -2228,27 +1662,23 @@ ChooseDirectoryValidateProc( if (SUCCEEDED(SHGetDesktopFolder(&psfFolder))) { LPITEMIDLIST pidlMain; ULONG ulCount, ulAttr; - Tcl_DString ds; - Tcl_UtfToExternalDString(TkWinGetUnicodeEncoding(), - initDir, -1, &ds); if (SUCCEEDED(psfFolder->lpVtbl->ParseDisplayName( psfFolder, hwnd, NULL, (WCHAR *) - Tcl_DStringValue(&ds), &ulCount,&pidlMain,&ulAttr)) + initDir, &ulCount,&pidlMain,&ulAttr)) && (pidlMain != NULL)) { - SendMessage(hwnd, BFFM_SETSELECTION, FALSE, + SendMessageW(hwnd, BFFM_SETSELECTIONW, FALSE, (LPARAM) pidlMain); pMalloc->lpVtbl->Free(pMalloc, pidlMain); } psfFolder->lpVtbl->Release(psfFolder); - Tcl_DStringFree(&ds); } pMalloc->lpVtbl->Release(pMalloc); } } else { - SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM) initDir); + SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, (LPARAM) initDir); } - SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1); + SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1); break; } @@ -2279,7 +1709,7 @@ Tk_MessageBoxObjCmd( ClientData clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[]) /* Argument objects. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData, parent; HWND hWnd; @@ -2287,7 +1717,7 @@ Tk_MessageBoxObjCmd( int defaultBtn, icon, type; int i, oldMode, winCode; UINT flags; - static CONST char *optionStrings[] = { + static const char *optionStrings[] = { "-default", "-detail", "-icon", "-message", "-parent", "-title", "-type", NULL }; @@ -2298,7 +1728,6 @@ Tk_MessageBoxObjCmd( ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - (void) TkWinGetUnicodeEncoding(); defaultBtn = -1; detailObj = NULL; icon = MB_ICONINFORMATION; @@ -2309,7 +1738,6 @@ Tk_MessageBoxObjCmd( for (i = 1; i < objc; i += 2) { int index; - char *string; Tcl_Obj *optionPtr, *valuePtr; optionPtr = objv[i]; @@ -2320,7 +1748,7 @@ Tk_MessageBoxObjCmd( return TCL_ERROR; } if (i + 1 == objc) { - string = Tcl_GetString(optionPtr); + const char *string = Tcl_GetString(optionPtr); Tcl_AppendResult(interp, "value for \"", string, "\" missing", NULL); return TCL_ERROR; @@ -2425,7 +1853,7 @@ Tk_MessageBoxObjCmd( tsdPtr->hSmallIcon = TkWinGetIcon(parent, ICON_SMALL); tsdPtr->hBigIcon = TkWinGetIcon(parent, ICON_BIG); - tsdPtr->hMsgBoxHook = SetWindowsHookEx(WH_CBT, MsgBoxCBTProc, NULL, + tsdPtr->hMsgBoxHook = SetWindowsHookExW(WH_CBT, MsgBoxCBTProc, NULL, GetCurrentThreadId()); winCode = MessageBoxW(hWnd, Tcl_GetUnicode(tmpObj), titleObj ? Tcl_GetUnicode(titleObj) : L"", flags); @@ -2453,7 +1881,7 @@ MsgBoxCBTProc( LPARAM lParam) { ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (nCode == HCBT_CREATEWND) { /* @@ -2469,9 +1897,9 @@ MsgBoxCBTProc( if (WC_DIALOG == lpcbtcreate->lpcs->lpszClass) { HWND hwnd = (HWND) wParam; - SendMessage(hwnd, WM_SETICON, ICON_SMALL, + SendMessageW(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) tsdPtr->hSmallIcon); - SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) tsdPtr->hBigIcon); + SendMessageW(hwnd, WM_SETICON, ICON_BIG, (LPARAM) tsdPtr->hBigIcon); } } @@ -2510,15 +1938,15 @@ SetTkDialog( /* * Factored out a common pattern in use in this file. */ -static char * + +static const char * ConvertExternalFilename( - Tcl_Encoding encoding, - char *filename, + WCHAR *filename, Tcl_DString *dsPtr) { char *p; - Tcl_ExternalToUtfDString(encoding, filename, -1, dsPtr); + Tcl_WinTCharToUtf((TCHAR *) filename, -1, dsPtr); for (p = Tcl_DStringValue(dsPtr); *p != '\0'; p++) { /* * Change the pathname to the Tcl "normalized" pathname, where back diff --git a/win/tkWinInit.c b/win/tkWinInit.c index 19556dd..31304d3 100644 --- a/win/tkWinInit.c +++ b/win/tkWinInit.c @@ -120,6 +120,20 @@ TkpDisplayWarning( WCHAR msgString[TK_MAX_WARN_LEN + 5]; WCHAR titleString[TK_MAX_WARN_LEN + 1]; + /* If running on Cygwin and we have a stderr channel, use it. */ +#if !defined(STATIC_BUILD) + if (tclStubsPtr->reserved9) { + Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR); + if (errChannel) { + Tcl_WriteChars(errChannel, title, -1); + Tcl_WriteChars(errChannel, ": ", 2); + Tcl_WriteChars(errChannel, msg, -1); + Tcl_WriteChars(errChannel, "\n", 1); + return; + } + } +#endif /* !STATIC_BUILD */ + MultiByteToWideChar(CP_UTF8, 0, msg, -1, msgString, TK_MAX_WARN_LEN); MultiByteToWideChar(CP_UTF8, 0, title, -1, titleString, TK_MAX_WARN_LEN); /* diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index cb40c50..48bc16b 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.c @@ -3205,7 +3205,7 @@ SetDefaults( int padding; #endif } nc; - OSVERSIONINFO os; + OSVERSIONINFOW os; /* * Set all of the default options. The loop will terminate when we run out @@ -3225,8 +3225,8 @@ SetDefaults( nc.metrics.cbSize = sizeof(nc); - os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&os); + os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + GetVersionExW(&os); if (os.dwMajorVersion < 6) { nc.metrics.cbSize -= sizeof(int); } diff --git a/win/tkWinPort.h b/win/tkWinPort.h index 14f949c..8d7778c 100644 --- a/win/tkWinPort.h +++ b/win/tkWinPort.h @@ -63,8 +63,8 @@ #ifndef __GNUC__ -# define strncasecmp strnicmp -# define strcasecmp stricmp +# define strncasecmp _strnicmp +# define strcasecmp _stricmp #endif #define NBBY 8 diff --git a/win/tkWinScrlbr.c b/win/tkWinScrlbr.c index 2ec6883..46aad58 100644 --- a/win/tkWinScrlbr.c +++ b/win/tkWinScrlbr.c @@ -553,7 +553,7 @@ ScrollbarProc( } interp = scrollPtr->info.interp; - code = Tcl_GlobalEval(interp, cmdString.string); + code = Tcl_EvalEx(interp, cmdString.string, -1, TCL_EVAL_GLOBAL); if (code != TCL_OK && code != TCL_CONTINUE && code != TCL_BREAK) { Tcl_AddErrorInfo(interp, "\n (scrollbar command)"); Tcl_BackgroundError(interp); diff --git a/win/tkWinWm.c b/win/tkWinWm.c index e3816ca..9ea4957 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -5309,11 +5309,6 @@ WmStateCmd( return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, - &index) != TCL_OK) { - return TCL_ERROR; - } - if (winPtr->flags & TK_EMBEDDED) { int state = 0; @@ -6590,7 +6585,7 @@ TkWmProtocolEventProc( Tcl_Preserve((ClientData) protPtr); interp = protPtr->interp; Tcl_Preserve((ClientData) interp); - result = Tcl_GlobalEval(interp, protPtr->command); + result = Tcl_EvalEx(interp, protPtr->command, -1, TCL_EVAL_GLOBAL); if (result != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (command for \""); Tcl_AddErrorInfo(interp, name); diff --git a/win/tkWinX.c b/win/tkWinX.c index 1e218ec..cbd6032 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -166,20 +166,32 @@ TkGetServerInfo( Tk_Window tkwin) /* Token for window; this selects a particular * display and server. */ { - char buffer[60]; - OSVERSIONINFO os; - - os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&os); - sprintf(buffer, "Windows %d.%d %d %s", (int)os.dwMajorVersion, - (int)os.dwMinorVersion, (int)os.dwBuildNumber, + static char buffer[32]; /* Empty string means not initialized yet. */ + OSVERSIONINFOW os; + + if (!buffer[0]) { + HANDLE handle = LoadLibraryW(L"NTDLL"); + int(__stdcall *getversion)(void *) = + (int(__stdcall *)(void *))GetProcAddress(handle, "RtlGetVersion"); + os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + if (!getversion || getversion(&os)) { + GetVersionExW(&os); + } + if (handle) { + FreeLibrary(handle); + } + /* Write the first character last, preventing multi-thread issues. */ + sprintf(buffer+1, "indows %d.%d %d %s", (int)os.dwMajorVersion, + (int)os.dwMinorVersion, (int)os.dwBuildNumber, #ifdef _WIN64 - "Win64" + "Win64" #else - "Win32" + "Win32" #endif - ); - Tcl_SetResult(interp, buffer, TCL_VOLATILE); + ); + buffer[0] = 'W'; + } + Tcl_SetResult(interp, buffer, TCL_STATIC); } /* @@ -378,10 +390,10 @@ int TkWinGetPlatformId(void) { if (tkPlatformId == 0) { - OSVERSIONINFO os; + OSVERSIONINFOW os; - os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&os); + os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + GetVersionExW(&os); tkPlatformId = os.dwPlatformId; /* diff --git a/win/ttkWinXPTheme.c b/win/ttkWinXPTheme.c index fda7b04..80b616d 100644 --- a/win/ttkWinXPTheme.c +++ b/win/ttkWinXPTheme.c @@ -1256,10 +1256,10 @@ MODULE_SCOPE int TtkXPTheme_Init(Tcl_Interp *interp, HWND hwnd) HINSTANCE hlibrary; Ttk_Theme themePtr, parentPtr, vistaPtr; ElementInfo *infoPtr; - OSVERSIONINFO os; + OSVERSIONINFOW os; - os.dwOSVersionInfoSize = sizeof(os); - GetVersionEx(&os); + os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + GetVersionExW(&os); procs = LoadXPThemeProcs(&hlibrary); if (!procs) diff --git a/win/winMain.c b/win/winMain.c index eea7004..01a5e23 100644 --- a/win/winMain.c +++ b/win/winMain.c @@ -16,6 +16,10 @@ #undef WIN32_LEAN_AND_MEAN #include <locale.h> +#if defined(__GNUC__) +int _CRT_glob = 0; +#endif /* __GNUC__ */ + /* * The following declarations refer to internal Tk routines. These interfaces * are available for use, but are not supported. diff --git a/win/wish.exe.manifest.in b/win/wish.exe.manifest.in index 2cae0c0..4829471 100644 --- a/win/wish.exe.manifest.in +++ b/win/wish.exe.manifest.in @@ -8,6 +8,30 @@ type="win32" /> <description>Tcl/Tk windowing shell (wish)</description> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <requestedExecutionLevel + level="asInvoker" + uiAccess="false" + /> + </requestedPrivileges> + </security> + </trustInfo> + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <!-- Windows 10 --> + <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> + <!-- Windows 8.1 --> + <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> + <!-- Windows 8 --> + <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> + <!-- Windows 7 --> + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> + <!-- Windows Vista --> + <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> + </application> + </compatibility> <asmv3:application> <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> |