summaryrefslogtreecommitdiff
path: root/tk/win
diff options
context:
space:
mode:
authorIan Roxborough <irox@redhat.com>2001-09-10 00:22:29 +0000
committerIan Roxborough <irox@redhat.com>2001-09-10 00:22:29 +0000
commitee7709783c85577eba6af30cd711e17e403befed (patch)
tree74233a880ee1f7e13c7ded61d093318e8c6e7d5c /tk/win
parenta850c17c374d03259483e799b09326d255e17487 (diff)
downloadgdb-ee7709783c85577eba6af30cd711e17e403befed.tar.gz
Tk 8.3 upgradeTK_8_3
Diffstat (limited to 'tk/win')
-rw-r--r--tk/win/Makefile.in1029
-rw-r--r--tk/win/README119
-rw-r--r--tk/win/aclocal.m42
-rwxr-xr-xtk/win/configure1895
-rwxr-xr-xtk/win/configure.in304
-rw-r--r--tk/win/makefile.vc268
-rw-r--r--tk/win/mkd.bat1
-rw-r--r--tk/win/rc/tk.rc101
-rw-r--r--tk/win/rc/tk_base.rc130
-rw-r--r--tk/win/rc/tk_dll.rc169
-rw-r--r--tk/win/rc/wish.icobin1398 -> 3630 bytes
-rw-r--r--tk/win/rc/wish.rc9
-rw-r--r--tk/win/rc/wish_static.rc177
-rw-r--r--tk/win/rmd.bat1
-rw-r--r--tk/win/stubs.c6
-rw-r--r--tk/win/tcl.m4634
-rw-r--r--tk/win/tkConfig.sh.in92
-rw-r--r--tk/win/tkWin.h14
-rw-r--r--tk/win/tkWin32Dll.c7
-rw-r--r--tk/win/tkWin3d.c98
-rw-r--r--tk/win/tkWinButton.c177
-rw-r--r--tk/win/tkWinClipboard.c249
-rw-r--r--tk/win/tkWinColor.c75
-rw-r--r--tk/win/tkWinConfig.c61
-rw-r--r--tk/win/tkWinCursor.c35
-rw-r--r--tk/win/tkWinDefault.h13
-rw-r--r--tk/win/tkWinDialog.c1981
-rw-r--r--tk/win/tkWinDraw.c253
-rw-r--r--tk/win/tkWinEmbed.c60
-rw-r--r--tk/win/tkWinFont.c2281
-rw-r--r--tk/win/tkWinImage.c5
-rw-r--r--tk/win/tkWinInit.c23
-rw-r--r--tk/win/tkWinInt.h100
-rw-r--r--tk/win/tkWinKey.c648
-rw-r--r--tk/win/tkWinMenu.c1014
-rw-r--r--tk/win/tkWinPixmap.c47
-rw-r--r--tk/win/tkWinPointer.c59
-rw-r--r--tk/win/tkWinPort.h35
-rw-r--r--tk/win/tkWinRegion.c1
-rw-r--r--tk/win/tkWinScrlbr.c34
-rw-r--r--tk/win/tkWinTest.c250
-rw-r--r--tk/win/tkWinWindow.c49
-rw-r--r--tk/win/tkWinWm.c726
-rw-r--r--tk/win/tkWinX.c254
-rw-r--r--tk/win/winDumpExts.c503
-rw-r--r--tk/win/winMain.c160
46 files changed, 10615 insertions, 3534 deletions
diff --git a/tk/win/Makefile.in b/tk/win/Makefile.in
index 272627eeeb9..7af644ea916 100644
--- a/tk/win/Makefile.in
+++ b/tk/win/Makefile.in
@@ -1,446 +1,478 @@
-# Visual C++ 2.x and 4.0 makefile
+# This file is a Makefile for Tk. 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.
#
-# See the file "license.terms" for information on usage and redistribution
-# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-#
-# Copyright (c) 1995-1996 Sun Microsystems, Inc.
-# SCCS: @(#) makefile.vc 1.63 97/08/13 13:33:32
-
-# Does not depend on the presence of any environment variables in
-# order to compile tcl; all needed information is derived from
-# location of the compiler directories.
-
-# This file is CYGNUS LOCAL. It is a copy of makefile.vc from the
-# standard tk distribution, modified to work with cygwin and an
-# autoconf configure script. I have chosen to minimize the number of
-# changes, so the comments continue to refer to Visual C++ and the
-# like. This should make it easier to merge in a new version if that
-# is necessary.
-
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-VPATH = @srcdir@:@srcdir@/../xlib:@srcdir@/../generic:@srcdir@/../unix:@srcdir@/../win/rc
-srcdir = @srcdir@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-
-CC = @CC@
-CFLAGS = @CFLAGS@
-NM = @NM@
-AS = @AS@
-LD = @LD@
-DLLTOOL = @DLLTOOL@
-WINDRES = @WINDRES@
-
-OBJEXT=@OBJEXT@
-
-DLL_LDFLAGS = @DLL_LDFLAGS@
-DLL_LDLIBS = @DLL_LDLIBS@
-
-# Current Tk version; used in various names.
-
-DIRVERSION = @TK_VERSION@
+# RCS: @(#) $Id$
+
+TCLVERSION = @TCL_VERSION@
+VERSION = @TK_VERSION@
+
+#----------------------------------------------------------------
+# Things you can change to personalize the Makefile for your own
+# site (you can make these changes in either Makefile.in or
+# Makefile, but changes to Makefile will get lost if you re-run
+# the configuration script).
+#----------------------------------------------------------------
+
+# Default top-level directories in which to install architecture-
+# specific files (exec_prefix) and machine-independent files such
+# as scripts (prefix). The values specified here may be overridden
+# at configure-time with the --exec-prefix and --prefix options
+# to the "configure" script.
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libdir = @libdir@
+includedir = @includedir@
+mandir = @mandir@
# The following definition can be set to non-null for special systems
# like AFS with replication. It allows the pathnames used for installation
# to be different than those used for actually reference files at
# run-time. INSTALL_ROOT is prepended to $prefix and $exec_prefix
# when installing files.
-INSTALL_ROOT =
+INSTALL_ROOT =
-# Directory from which applications will reference the library of Tcl
+# Directory from which applications will reference the library of Tk
# scripts (note: you can set the TK_LIBRARY environment variable at
-# run-time to override the compiled-in location):
-TK_LIBRARY = @datadir@/tk$(DIRVERSION)
+# run-time to override this value):
+TK_LIBRARY = @datadir@/tk$(VERSION)
-# Path name to use when installing library scripts:
-SCRIPT_INSTALL_DIR = $(INSTALL_ROOT)$(TK_LIBRARY)
+# Path to use at runtime to refer to LIB_INSTALL_DIR:
+LIB_RUNTIME_DIR = $(libdir)
+
+# Directory in which to install the program wish:
+BIN_INSTALL_DIR = $(INSTALL_ROOT)$(bindir)
# Directory in which to install the .a or .so binary for the Tk library:
-LIB_INSTALL_DIR = $(INSTALL_ROOT)@libdir@
+LIB_INSTALL_DIR = $(INSTALL_ROOT)$(libdir)
-# Directory in which to install the program wish:
-BIN_INSTALL_DIR = $(INSTALL_ROOT)@bindir@
+# Path name to use when installing library scripts:
+SCRIPT_INSTALL_DIR = $(INSTALL_ROOT)$(TK_LIBRARY)
# Directory in which to install the include file tk.h:
-INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)@includedir@
+INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(includedir)
+
+# Top-level directory for manual entries:
+MAN_INSTALL_DIR = $(INSTALL_ROOT)$(mandir)
-# Directory in which to install the X11 header files. These files are
-# not machine independent, so they should not go in includedir.
-X11_INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)@exec_prefix@/@host_alias@/include/X11
+# Directory in which to install manual entry for wish:
+MAN1_INSTALL_DIR = $(MAN_INSTALL_DIR)/man1
+
+# Directory in which to install manual entries for Tk's C library
+# procedures:
+MAN3_INSTALL_DIR = $(MAN_INSTALL_DIR)/man3
+
+# Directory in which to install manual entries for the built-in
+# Tk commands:
+MANN_INSTALL_DIR = $(MAN_INSTALL_DIR)/mann
+
+# Libraries built with optimization switches have this additional extension
+TK_DBGX = @TK_DBGX@
+
+# The directory containing the Tcl source and header files.
+TCL_SRC_DIR = @TCL_SRC_DIR@
+
+# The directory containing the Tcl library archive file appropriate
+# for this version of Tk:
+TCL_BIN_DIR = @TCL_BIN_DIR@
+
+# The directory containing the Tcl sources and headers appropriate
+# for this version of Tk ("srcdir" will be replaced or has already
+# been replaced by the configure script):
+TCL_GENERIC_DIR = @TCL_SRC_DIR@/generic
+
+# This program converts from POSIX to Windows native paths.
+CYGPATH = @CYGPATH@
+
+# The name of the Tcl library.
+TCL_LIB_SPEC = @TCL_BUILD_LIB_SPEC@
+TCL_STUB_LIB_SPEC = @TCL_BUILD_STUB_LIB_SPEC@
+
+SRC_DIR = @srcdir@
+ROOT_DIR = $(SRC_DIR)/..
+WIN_DIR = $(SRC_DIR)
+UNIX_DIR = $(SRC_DIR)/../unix
+GENERIC_DIR = $(SRC_DIR)/../generic
+BITMAP_DIR = $(ROOT_DIR)/bitmaps
+XLIB_DIR = $(ROOT_DIR)/xlib
+RC_DIR = $(WIN_DIR)/rc
+
+ROOT_DIR_NATIVE = $(shell $(CYGPATH) '$(ROOT_DIR)')
+WIN_DIR_NATIVE = $(shell $(CYGPATH) '$(WIN_DIR)')
+GENERIC_DIR_NATIVE = $(shell $(CYGPATH) '$(GENERIC_DIR)')
+BITMAP_DIR_NATIVE = $(shell $(CYGPATH) '$(ROOT_DIR)/bitmaps')
+XLIB_DIR_NATIVE = $(shell $(CYGPATH) '$(ROOT_DIR)/xlib')
+TCL_GENERIC_NATIVE = $(shell $(CYGPATH) '$(TCL_GENERIC_DIR)')
+TCL_SRC_DIR_NATIVE = $(shell $(CYGPATH) '$(TCL_SRC_DIR)')
+TCL_BIN_DIR_NATIVE = $(shell $(CYGPATH) '$(TCL_BIN_DIR)')
+RC_DIR_NATIVE = $(shell $(CYGPATH) '$(RC_DIR)')
+
+DLLSUFFIX = @DLLSUFFIX@
+LIBSUFFIX = @LIBSUFFIX@
+EXESUFFIX = @EXESUFFIX@
+
+TK_STUB_LIB_FILE = @TK_STUB_LIB_FILE@
+TK_LIB_FILE = @TK_LIB_FILE@
+TK_DLL_FILE = @TK_DLL_FILE@
+
+SHARED_LIBRARIES = $(TK_DLL_FILE) $(TK_STUB_LIB_FILE)
+STATIC_LIBRARIES = $(TK_LIB_FILE)
+
+WISH_RES = @WISH_RES@
+TK_RES = @TK_RES@
+
+WISH = wish$(VER)${EXESUFFIX}
+TKTEST = tktest${EXEEXT}
+CAT32 = cat32$(EXEEXT)
+MAN2TCL = man2tcl$(EXEEXT)
+
+@SET_MAKE@
+
+# Setting the VPATH variable to a list of paths will cause the
+# makefile to look into these paths when resolving .c to .obj
+# dependencies.
+
+VPATH = $(GENERIC_DIR):$(WIN_DIR):$(UNIX_DIR):$(XLIB_DIR):$(RC_DIR)
+
+# warning flags
+CFLAGS_WARNING = @CFLAGS_WARNING@
+
+# The default switches for optimization or debugging
+CFLAGS_DEBUG = @CFLAGS_DEBUG@
+CFLAGS_OPTIMIZE = @CFLAGS_OPTIMIZE@
+
+# The default switches for optimization or debugging
+LDFLAGS_DEBUG = @LDFLAGS_DEBUG@
+LDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@
+
+# To change the compiler switches, for example to change from optimization to
+# debugging symbols, change the following line:
+#CFLAGS = $(CFLAGS_DEBUG)
+#CFLAGS = $(CFLAGS_OPTIMIZE)
+#CFLAGS = $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)
+CFLAGS = @CFLAGS@ @CFLAGS_DEFAULT@
+
+# Special compiler flags to use when building man2tcl on Windows.
+MAN2TCLFLAGS = @MAN2TCLFLAGS@
+
+AR = @AR@
+RANLIB = @RANLIB@
+CC = @CC@
+RC = @RC@
+RES = @RES@
+AC_FLAGS = @EXTRA_CFLAGS@ @DEFS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@ @LDFLAGS_DEFAULT@
+LDFLAGS_CONSOLE = @LDFLAGS_CONSOLE@
+LDFLAGS_WINDOW = @LDFLAGS_WINDOW@
+EXEEXT = @EXEEXT@
+OBJEXT = @OBJEXT@
+LIBS_GUI = @LIBS_GUI@
+STLIB_LD = @STLIB_LD@
+SHLIB_LD = @SHLIB_LD@
+SHLIB_CFLAGS = @SHLIB_CFLAGS@
+SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ $(TCL_STUB_LIB_SPEC) $(LIBS_GUI)
+SHLIB_SUFFIX = @SHLIB_SUFFIX@
+VER = @TK_MAJOR_VERSION@@TK_MINOR_VERSION@
+DOTVER = @TK_MAJOR_VERSION@.@TK_MINOR_VERSION@
+LIBS = @LIBS@ $(LIBS_GUI)
+RMDIR = rm -rf
+MKDIR = mkdir -p
+SHELL = @SHELL@
+RM = rm -f
+COPY = cp
+
+# FIXME: Add a "make shell SCRIPT=foo.tcl" argument
+# so that a shell can easily be run from the build dir.
+TCLSH_PROG = $(TCL_BIN_DIR)/tclsh$(VER)
+
+CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
+-I"${GENERIC_DIR_NATIVE}" -I"${WIN_DIR_NATIVE}" \
+-I"${XLIB_DIR_NATIVE}" -I"${BITMAP_DIR_NATIVE}" \
+ -I"${TCL_GENERIC_NATIVE}" ${AC_FLAGS}
+
+CC_OBJNAME = @CC_OBJNAME@
+CC_EXENAME = @CC_EXENAME@
+
+STUB_CC_SWITCHES = ${CC_SWITCHES} -DUSE_TCL_STUBS
+CON_CC_SWITCHES = ${CC_SWITCHES} -DCONSOLE
+
+# Tk used to let the configure script choose which program to use
+# for installing, but there are just too many different versions of
+# "install" around; better to use the install-sh script that comes
+# with the distribution, which is slower but guaranteed to work.
+
+INSTALL = cp
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL}
+
+WISH_OBJS = \
+ winMain.$(OBJEXT)
+
+TCLTEST_OBJS = \
+ ${TCL_BIN_DIR}/tclThreadTest.$(OBJEXT)
+
+TCLTEST_OBJS_NATIVE = \
+ "${TCL_BIN_DIR_NATIVE}/tclThreadTest.$(OBJEXT)"
+
+TKTEST_OBJS = \
+ $(TCLTEST_OBJS) \
+ testMain.$(OBJEXT) \
+ tkSquare.$(OBJEXT) \
+ tkTest.$(OBJEXT) \
+ tkWinTest.$(OBJEXT)
+
+TKTEST_OBJS_NATIVE = \
+ $(TCLTEST_OBJS_NATIVE) \
+ testMain.$(OBJEXT) \
+ tkSquare.$(OBJEXT) \
+ tkTest.$(OBJEXT) \
+ tkWinTest.$(OBJEXT)
+
+XLIB_OBJS = \
+ xcolors.$(OBJEXT) \
+ xdraw.$(OBJEXT) \
+ xgc.$(OBJEXT) \
+ ximage.$(OBJEXT) \
+ xutil.$(OBJEXT)
+
+TK_OBJS = \
+ tkConsole.$(OBJEXT) \
+ tkUnixMenubu.$(OBJEXT) \
+ tkUnixScale.$(OBJEXT) \
+ $(XLIB_OBJS) \
+ tkWin3d.$(OBJEXT) \
+ tkWin32Dll.$(OBJEXT) \
+ tkWinButton.$(OBJEXT) \
+ tkWinClipboard.$(OBJEXT) \
+ tkWinColor.$(OBJEXT) \
+ tkWinConfig.$(OBJEXT) \
+ tkWinCursor.$(OBJEXT) \
+ tkWinDialog.$(OBJEXT) \
+ tkWinDraw.$(OBJEXT) \
+ tkWinEmbed.$(OBJEXT) \
+ tkWinFont.$(OBJEXT) \
+ tkWinImage.$(OBJEXT) \
+ tkWinInit.$(OBJEXT) \
+ tkWinKey.$(OBJEXT) \
+ tkWinMenu.$(OBJEXT) \
+ tkWinPixmap.$(OBJEXT) \
+ tkWinPointer.$(OBJEXT) \
+ tkWinRegion.$(OBJEXT) \
+ tkWinScrlbr.$(OBJEXT) \
+ tkWinSend.$(OBJEXT) \
+ tkWinWindow.$(OBJEXT) \
+ tkWinWm.$(OBJEXT) \
+ tkWinX.$(OBJEXT) \
+ stubs.$(OBJEXT) \
+ tk3d.$(OBJEXT) \
+ tkArgv.$(OBJEXT) \
+ tkAtom.$(OBJEXT) \
+ tkBind.$(OBJEXT) \
+ tkBitmap.$(OBJEXT) \
+ tkButton.$(OBJEXT) \
+ tkCanvArc.$(OBJEXT) \
+ tkCanvBmap.$(OBJEXT) \
+ tkCanvImg.$(OBJEXT) \
+ tkCanvLine.$(OBJEXT) \
+ tkCanvPoly.$(OBJEXT) \
+ tkCanvPs.$(OBJEXT) \
+ tkCanvText.$(OBJEXT) \
+ tkCanvUtil.$(OBJEXT) \
+ tkCanvWind.$(OBJEXT) \
+ tkCanvas.$(OBJEXT) \
+ tkClipboard.$(OBJEXT) \
+ tkCmds.$(OBJEXT) \
+ tkColor.$(OBJEXT) \
+ tkConfig.$(OBJEXT) \
+ tkCursor.$(OBJEXT) \
+ tkEntry.$(OBJEXT) \
+ tkError.$(OBJEXT) \
+ tkEvent.$(OBJEXT) \
+ tkFileFilter.$(OBJEXT) \
+ tkFocus.$(OBJEXT) \
+ tkFont.$(OBJEXT) \
+ tkFrame.$(OBJEXT) \
+ tkGC.$(OBJEXT) \
+ tkGeometry.$(OBJEXT) \
+ tkGet.$(OBJEXT) \
+ tkGrab.$(OBJEXT) \
+ tkGrid.$(OBJEXT) \
+ tkImage.$(OBJEXT) \
+ tkImgBmap.$(OBJEXT) \
+ tkImgGIF.$(OBJEXT) \
+ tkImgPPM.$(OBJEXT) \
+ tkImgPhoto.$(OBJEXT) \
+ tkImgUtil.$(OBJEXT) \
+ tkListbox.$(OBJEXT) \
+ tkMacWinMenu.$(OBJEXT) \
+ tkMain.$(OBJEXT) \
+ tkMenu.$(OBJEXT) \
+ tkMenubutton.$(OBJEXT) \
+ tkMenuDraw.$(OBJEXT) \
+ tkMessage.$(OBJEXT) \
+ tkObj.$(OBJEXT) \
+ tkOldConfig.$(OBJEXT) \
+ tkOption.$(OBJEXT) \
+ tkPack.$(OBJEXT) \
+ tkPlace.$(OBJEXT) \
+ tkPointer.$(OBJEXT) \
+ tkRectOval.$(OBJEXT) \
+ tkScale.$(OBJEXT) \
+ tkScrollbar.$(OBJEXT) \
+ tkSelect.$(OBJEXT) \
+ tkText.$(OBJEXT) \
+ tkTextBTree.$(OBJEXT) \
+ tkTextDisp.$(OBJEXT) \
+ tkTextImage.$(OBJEXT) \
+ tkTextIndex.$(OBJEXT) \
+ tkTextMark.$(OBJEXT) \
+ tkTextTag.$(OBJEXT) \
+ tkTextWind.$(OBJEXT) \
+ tkTrig.$(OBJEXT) \
+ tkUtil.$(OBJEXT) \
+ tkVisual.$(OBJEXT) \
+ tkStubInit.$(OBJEXT) \
+ tkStubLib.$(OBJEXT) \
+ tkWindow.$(OBJEXT)
+
+STUB_OBJS = \
+ tkStubLib.$(OBJEXT) \
+ tkStubImg.$(OBJEXT)
+
+TCL_DOCS = "$(TCL_SRC_DIR_NATIVE)"/doc/*.[13n]
+TK_DOCS = "$(ROOT_DIR_NATIVE)"/doc/*.[13n]
+CORE_DOCS = $(TCL_DOCS) $(TK_DOCS)
DEMOPROGS = browse hello ixset rmt rolodex square tcolor timer widget
-#
-# Project directories
-#
-# ROOT = top of source tree
-#
-# TMPDIR = location where .obj files should be stored during build
-#
-# TOOLS32 = location of VC++ 32-bit development tools. Note that the
-# VC++ 2.0 header files are broken, so you need to use the
-# ones that come with the developer network CD's, or later
-# versions of VC++.
-#
-# TCLDIR = location of top of Tcl source heirarchy
-#
+# Main targets. The default target -- all -- builds the binaries,
+# performs any post processing on libraries or documents.
+
+all: binaries libraries doc
+
+binaries: @LIBRARIES@ $(WISH)
+
+libraries:
+
+$(ROOT_DIR)/doc/man.macros:
+ $(INSTALL_DATA) @TCL_SRC_DIR@/doc/man.macros $(ROOT_DIR)/doc/man.macros
+
+doc: $(ROOT_DIR)/doc/man.macros
-ROOT = $(srcdir)/..
-TMPDIR = .
-TOOLS32 = c:\msdev
-TCLDIR = $(srcdir)/../../tcl
-
-# Set this to the appropriate value of /MACHINE: for your platform
-MACHINE = IX86
-
-# Comment the following line to compile with symbols
-NODEBUG=1
-
-# uncomment the following two lines to compile with TCL_MEM_DEBUG
-#DEBUGDEFINES =-DTCL_MEM_DEBUG
-
-######################################################################
-# Do not modify below this line
-######################################################################
-
-VERSION = 80
-
-TCLDLL = cygtcl$(VERSION).dll
-TCLLIB = libtcl$(VERSION).a
-TCLPLUGINDLL = cygtcl$(VERSION)p.dll
-TCLPLUGINLIB = libtcl$(VERSION)p.a
-TKDLL = cygtk$(VERSION).dll
-TKLIB = libtk$(VERSION).a
-TKPLUGINDLL = cygtk$(VERSION)p.dll
-TKPLUGINLIB = libtk$(VERSION)p.a
-
-WISH = cygwish$(VERSION).exe
-WISHP = cygwishp$(VERSION).exe
-TKTEST = tktest.exe
-DUMPEXTS = $(TMPDIR)/dumpexts.exe
-
-WISHOBJS = \
- $(TMPDIR)/tkConsole.$(OBJEXT) \
- $(TMPDIR)/winMain.$(OBJEXT)
-
-TKTESTOBJS = \
- $(TMPDIR)/tkConsole.$(OBJEXT) \
- $(TMPDIR)/tkTest.$(OBJEXT) \
- $(TMPDIR)/tkSquare.$(OBJEXT) \
- $(TMPDIR)/testMain.$(OBJEXT)
-
-XLIBOBJS = \
- $(TMPDIR)/xcolors.$(OBJEXT) \
- $(TMPDIR)/xdraw.$(OBJEXT) \
- $(TMPDIR)/xgc.$(OBJEXT) \
- $(TMPDIR)/ximage.$(OBJEXT) \
- $(TMPDIR)/xutil.$(OBJEXT)
-
-TKOBJS = \
- $(TMPDIR)/tkUnixMenubu.$(OBJEXT) \
- $(TMPDIR)/tkUnixScale.$(OBJEXT) \
- $(XLIBOBJS) \
- $(TMPDIR)/tkWin3d.$(OBJEXT) \
- $(TMPDIR)/tkWin32Dll.$(OBJEXT) \
- $(TMPDIR)/tkWinButton.$(OBJEXT) \
- $(TMPDIR)/tkWinClipboard.$(OBJEXT) \
- $(TMPDIR)/tkWinColor.$(OBJEXT) \
- $(TMPDIR)/tkWinCursor.$(OBJEXT) \
- $(TMPDIR)/tkWinDialog.$(OBJEXT) \
- $(TMPDIR)/tkWinDraw.$(OBJEXT) \
- $(TMPDIR)/tkWinEmbed.$(OBJEXT) \
- $(TMPDIR)/tkWinFont.$(OBJEXT) \
- $(TMPDIR)/tkWinImage.$(OBJEXT) \
- $(TMPDIR)/tkWinInit.$(OBJEXT) \
- $(TMPDIR)/tkWinKey.$(OBJEXT) \
- $(TMPDIR)/tkWinMenu.$(OBJEXT) \
- $(TMPDIR)/tkWinPixmap.$(OBJEXT) \
- $(TMPDIR)/tkWinPointer.$(OBJEXT) \
- $(TMPDIR)/tkWinRegion.$(OBJEXT) \
- $(TMPDIR)/tkWinScrlbr.$(OBJEXT) \
- $(TMPDIR)/tkWinSend.$(OBJEXT) \
- $(TMPDIR)/tkWinWindow.$(OBJEXT) \
- $(TMPDIR)/tkWinWm.$(OBJEXT) \
- $(TMPDIR)/tkWinX.$(OBJEXT) \
- $(TMPDIR)/stubs.$(OBJEXT) \
- $(TMPDIR)/tk3d.$(OBJEXT) \
- $(TMPDIR)/tkArgv.$(OBJEXT) \
- $(TMPDIR)/tkAtom.$(OBJEXT) \
- $(TMPDIR)/tkBind.$(OBJEXT) \
- $(TMPDIR)/tkBitmap.$(OBJEXT) \
- $(TMPDIR)/tkButton.$(OBJEXT) \
- $(TMPDIR)/tkCanvArc.$(OBJEXT) \
- $(TMPDIR)/tkCanvBmap.$(OBJEXT) \
- $(TMPDIR)/tkCanvImg.$(OBJEXT) \
- $(TMPDIR)/tkCanvLine.$(OBJEXT) \
- $(TMPDIR)/tkCanvPoly.$(OBJEXT) \
- $(TMPDIR)/tkCanvPs.$(OBJEXT) \
- $(TMPDIR)/tkCanvText.$(OBJEXT) \
- $(TMPDIR)/tkCanvUtil.$(OBJEXT) \
- $(TMPDIR)/tkCanvWind.$(OBJEXT) \
- $(TMPDIR)/tkCanvas.$(OBJEXT) \
- $(TMPDIR)/tkClipboard.$(OBJEXT) \
- $(TMPDIR)/tkCmds.$(OBJEXT) \
- $(TMPDIR)/tkColor.$(OBJEXT) \
- $(TMPDIR)/tkConfig.$(OBJEXT) \
- $(TMPDIR)/tkCursor.$(OBJEXT) \
- $(TMPDIR)/tkEntry.$(OBJEXT) \
- $(TMPDIR)/tkError.$(OBJEXT) \
- $(TMPDIR)/tkEvent.$(OBJEXT) \
- $(TMPDIR)/tkFileFilter.$(OBJEXT) \
- $(TMPDIR)/tkFocus.$(OBJEXT) \
- $(TMPDIR)/tkFont.$(OBJEXT) \
- $(TMPDIR)/tkFrame.$(OBJEXT) \
- $(TMPDIR)/tkGC.$(OBJEXT) \
- $(TMPDIR)/tkGeometry.$(OBJEXT) \
- $(TMPDIR)/tkGet.$(OBJEXT) \
- $(TMPDIR)/tkGrab.$(OBJEXT) \
- $(TMPDIR)/tkGrid.$(OBJEXT) \
- $(TMPDIR)/tkImage.$(OBJEXT) \
- $(TMPDIR)/tkImgBmap.$(OBJEXT) \
- $(TMPDIR)/tkImgGIF.$(OBJEXT) \
- $(TMPDIR)/tkImgPPM.$(OBJEXT) \
- $(TMPDIR)/tkImgPhoto.$(OBJEXT) \
- $(TMPDIR)/tkImgUtil.$(OBJEXT) \
- $(TMPDIR)/tkListbox.$(OBJEXT) \
- $(TMPDIR)/tkMacWinMenu.$(OBJEXT) \
- $(TMPDIR)/tkMain.$(OBJEXT) \
- $(TMPDIR)/tkMenu.$(OBJEXT) \
- $(TMPDIR)/tkMenubutton.$(OBJEXT) \
- $(TMPDIR)/tkMenuDraw.$(OBJEXT) \
- $(TMPDIR)/tkMessage.$(OBJEXT) \
- $(TMPDIR)/tkOption.$(OBJEXT) \
- $(TMPDIR)/tkPack.$(OBJEXT) \
- $(TMPDIR)/tkPlace.$(OBJEXT) \
- $(TMPDIR)/tkPointer.$(OBJEXT) \
- $(TMPDIR)/tkRectOval.$(OBJEXT) \
- $(TMPDIR)/tkScale.$(OBJEXT) \
- $(TMPDIR)/tkScrollbar.$(OBJEXT) \
- $(TMPDIR)/tkSelect.$(OBJEXT) \
- $(TMPDIR)/tkText.$(OBJEXT) \
- $(TMPDIR)/tkTextBTree.$(OBJEXT) \
- $(TMPDIR)/tkTextDisp.$(OBJEXT) \
- $(TMPDIR)/tkTextImage.$(OBJEXT) \
- $(TMPDIR)/tkTextIndex.$(OBJEXT) \
- $(TMPDIR)/tkTextMark.$(OBJEXT) \
- $(TMPDIR)/tkTextTag.$(OBJEXT) \
- $(TMPDIR)/tkTextWind.$(OBJEXT) \
- $(TMPDIR)/tkTrig.$(OBJEXT) \
- $(TMPDIR)/tkUtil.$(OBJEXT) \
- $(TMPDIR)/tkVisual.$(OBJEXT) \
- $(TMPDIR)/tkWindow.$(OBJEXT)
-
-cc32 = $(TOOLS32)\bin\cl.exe
-link32 = $(TOOLS32)\bin\link.exe
-rc32 = $(TOOLS32)\bin\rc.exe
-include32 = -I$(TOOLS32)\include
-
-WINDIR = $(ROOT)/win
-GENERICDIR = $(ROOT)/generic
-XLIBDIR = $(ROOT)/xlib
-BITMAPDIR = $(ROOT)/bitmaps
-TCLLIBDIR = ../../tcl/win
-RCDIR = $(WINDIR)/rc
-
-TK_INCLUDES = -I$(WINDIR) -I$(GENERICDIR) -I$(BITMAPDIR) -I$(XLIBDIR) \
- -I$(TCLDIR)/generic
-TK_DEFINES = $(DEBUGDEFINES)
-
-TK_CFLAGS = $(cdebug) $(cflags) $(cvarsdll) \
- $(TK_INCLUDES) $(TK_DEFINES) $(CFLAGS)
-
-######################################################################
-# Link flags
-######################################################################
-
-#!IFDEF NODEBUG
-#ldebug = /RELEASE
-#!ELSE
-#ldebug = -debug:full -debugtype:cv
-#!ENDIF
-
-# declarations common to all linker options
-# lcommon = /NODEFAULTLIB /RELEASE /NOLOGO
-
-# declarations for use on Intel i386, i486, and Pentium systems
-#!IF "$(MACHINE)" == "IX86"
-#DLLENTRY = @12
-#lflags = $(lcommon) -align:0x1000 /MACHINE:$(MACHINE)
-#!ELSE
-#lflags = $(lcommon) /MACHINE:$(MACHINE)
-#!ENDIF
-
-ifeq ($(OBJEXT),obj)
-
-lcommon = /NODEFAULTLIB /RELEASE /NOLOGO
-lflags = $(lcommon) -align:0x1000 /MACHINE:$(MACHINE)
-conlflags = $(lflags) -subsystem:console -entry:mainCRTStartup
-guilflags = $(lflags) -subsystem:windows -entry:WinMainCRTStartup
-dlllflags = $(lflags) -entry:_DllMainCRTStartup@12 -dll
-
-else
-
-conlflags = $(lflags) -Wl,--subsystem,console -mwindows
-guilflags = $(lflags) -mwindows
-dlllflags = $(lflags)
-
-endif
-
-#!IF "$(MACHINE)" == "PPC"
-#libc = libc.lib
-#libcdll = crtdll.lib
-#!ELSE
-#libc = libc.lib oldnames.lib
-#libcdll = msvcrt.lib oldnames.lib
-#!ENDIF
-
-ifeq ($(OBJEXT),o)
-
-baselibs = -lkernel32 $(optlibs) -ladvapi32
-winlibs = $(baselibs) -luser32 -lgdi32 -lcomdlg32 -lwinspool
-
-else
-
-baselibs = kernel32.lib $(optlibs) advapi32.lib
-winlibs = $(baselibs) user32.lib gdi32.lib comdlg32.lib winspool.lib
-libcdll = msvcrt.lib oldnames.lib
-
-endif
-
-guilibs = $(libc) $(winlibs)
-
-guilibsdll = $(libcdll) $(winlibs)
-
-######################################################################
-# Compile flags
-######################################################################
-
-#!IFDEF NODEBUG
-#cdebug = -Ox
-#!ELSE
-#cdebug = -Z7 -Od -WX
-#!ENDIF
-
-# declarations common to all compiler options
-#ccommon = -c -W3 -nologo -YX
-
-#!IF "$(MACHINE)" == "IX86"
-#cflags = $(ccommon) -D_X86_=1
-#!ELSE
-#!IF "$(MACHINE)" == "MIPS"
-#cflags = $(ccommon) -D_MIPS_=1
-#!ELSE
-#!IF "$(MACHINE)" == "PPC"
-#cflags = $(ccommon) -D_PPC_=1
-#!ELSE
-#!IF "$(MACHINE)" == "ALPHA"
-#cflags = $(ccommon) -D_ALPHA_=1
-#!ENDIF
-#!ENDIF
-#!ENDIF
-#!ENDIF
+winhelp: $(TCL_SRC_DIR_NATIVE)/tools/man2help.tcl $(MAN2TCL)
+ TCL_LIBRARY="$(TCL_SRC_DIR_NATIVE)/library"; export TCL_LIBRARY; \
+ TK_LIBRARY="$(ROOT_DIR_NATIVE)/library"; export TK_LIBRARY; \
+ PATH="$(PATH):$(TCL_BIN_DIR)"; export PATH; \
+ $(TCLSH_PROG) "$(TCL_SRC_DIR_NATIVE)"/tools/man2help.tcl tcl "$(VER)" $(CORE_DOCS)
+ $(COPY) "$(TCL_BIN_DIR)"/tcl.hpj ./
+ hcw /c /e tcl.hpj
+ $(COPY) ./tcl$(VER).cnt ./TCL$(VER).HLP "$(TCL_SRC_DIR_NATIVE)"/tools/
-cvars = -DWIN32 -D_WIN32
-cvarsmt = $(cvars) -D_MT
-cvarsdll = $(cvarsmt) -D_DLL
+$(MAN2TCL): $(TCL_SRC_DIR_NATIVE)/tools/man2tcl.c
+ $(CC) $(CFLAGS_OPTIMIZE) $(MAN2TCLFLAGS) -o $(MAN2TCL) "$(TCL_SRC_DIR_NATIVE)"/tools/man2tcl.c
-CON_CFLAGS = $(cdebug) $(cflags) $(cvars) $(include32) -DCONSOLE
+test: binaries $(TKTEST)
+ @TCL_LIBRARY="$(TCL_SRC_DIR_NATIVE)/library"; export TCL_LIBRARY; \
+ TK_LIBRARY="$(ROOT_DIR_NATIVE)/library"; export TK_LIBRARY; \
+ PATH="$(PATH):$(TCL_BIN_DIR)"; export PATH; \
+ ./$(TKTEST) "$(ROOT_DIR_NATIVE)/tests/all.tcl" $(TESTFLAGS) \
+ | ./$(CAT32)
-######################################################################
-# Project specific targets
-######################################################################
-
-all: $(TKDLL) $(TKLIB) $(WISH)
-test: $(TKTEST)
-plugin: $(TKPLUGINDLL) $(WISHP)
-
-install: install-binaries install-libraries install-demos
+runtest: tktest
+ @TCL_LIBRARY="$(TCL_SRC_DIR_NATIVE)/library"; export TCL_LIBRARY; \
+ TK_LIBRARY="$(ROOT_DIR_NATIVE)/library"; export TK_LIBRARY; \
+ PATH="$(PATH):$(TCL_BIN_DIR)"; export PATH; \
+ ./$(TKTEST)
-install-binaries: $(TKDLL) $(TKLIB) $(WISH)
+install: all install-binaries install-libraries install-doc install-demos
+
+install-binaries:
@for i in $(LIB_INSTALL_DIR) $(BIN_INSTALL_DIR) ; \
do \
if [ ! -d $$i ] ; then \
echo "Making directory $$i"; \
- mkdir $$i; \
+ $(MKDIR) $$i; \
chmod 755 $$i; \
else true; \
fi; \
done;
- @echo "Installing $(TKLIB)"
- @$(INSTALL_DATA) $(TKLIB) $(LIB_INSTALL_DIR)/$(TKLIB)
- @chmod 555 $(LIB_INSTALL_DIR)/$(TKLIB)
- @echo "Installing wish"
+ @echo "Installing $(TK_LIB_FILE) to $(LIB_INSTALL_DIR)/"
+ @$(INSTALL_DATA) $(TK_LIB_FILE) $(LIB_INSTALL_DIR)/$(TK_LIB_FILE)
+ @echo "Installing $(WISH) as $(BIN_INSTALL_DIR)/wish$(VERSION)"
@$(INSTALL_PROGRAM) $(WISH) $(BIN_INSTALL_DIR)/$(WISH)
- @echo "Installing tkConfig.sh"
- @$(INSTALL_DATA) ../unix/tkConfig.sh $(LIB_INSTALL_DIR)/tkConfig.sh
+ @echo "Installing tkConfig.sh to $(LIB_INSTALL_DIR)/"
+ @$(INSTALL_DATA) tkConfig.sh $(LIB_INSTALL_DIR)/tkConfig.sh
+ @if test "$(DLLSUFFIX)" != "" ; then \
+ echo "Installing $(TK_DLL_FILE) to $(LIB_INSTALL_DIR)/" ; \
+ $(INSTALL_PROGRAM) $(TK_DLL_FILE) \
+ $(BIN_INSTALL_DIR)/$(TK_DLL_FILE) ; \
+ fi
+ @if test "$(TK_STUB_LIB_FILE)" != "" ; then \
+ if [ -f $(TK_STUB_LIB_FILE) ]; then \
+ echo "Installing $(TK_STUB_LIB_FILE) to $(LIB_INSTALL_DIR)/"; \
+ $(INSTALL_DATA) $(TK_STUB_LIB_FILE) \
+ $(LIB_INSTALL_DIR)/$(TK_STUB_LIB_FILE); \
+ fi; \
+ fi
install-libraries:
- @echo "Installing DLL"
- @$(INSTALL_DATA) $(TKDLL) $(BIN_INSTALL_DIR)/$(TKDLL)
- @for i in $(INSTALL_ROOT)@datadir@ $(INCLUDE_INSTALL_DIR) \
- $(SCRIPT_INSTALL_DIR) $(INSTALL_ROOT)@exec_prefix@ \
- $(INSTALL_ROOT)@exec_prefix@/@host_alias@ \
- $(INSTALL_ROOT)@exec_prefix@/@host_alias@/include \
- $(X11_INCLUDE_INSTALL_DIR) ; \
+ @for i in $(INSTALL_ROOT)$(prefix)/lib \
+ $(INCLUDE_INSTALL_DIR) $(INCLUDE_INSTALL_DIR)/X11 \
+ $(SCRIPT_INSTALL_DIR) $(SCRIPT_INSTALL_DIR)/images; \
do \
if [ ! -d $$i ] ; then \
echo "Making directory $$i"; \
- mkdir $$i; \
+ $(MKDIR) $$i; \
chmod 755 $$i; \
else true; \
fi; \
done;
- @echo "Installing tk.h"
- @$(INSTALL_DATA) $(GENERICDIR)/tk.h $(INCLUDE_INSTALL_DIR)/tk.h
- for i in $(XLIBDIR)/X11/*.h; \
+ @echo "Installing header files";
+ @for i in $(GENERIC_DIR)/tk.h $(GENERIC_DIR)/tkDecls.h \
+ $(GENERIC_DIR)/tkIntXlibDecls.h ; \
do \
- echo "Installing $$i"; \
- $(INSTALL_DATA) $$i $(X11_INCLUDE_INSTALL_DIR); \
+ $(INSTALL_DATA) $$i $(INCLUDE_INSTALL_DIR); \
done;
- for i in $(ROOT)/library/*.tcl $(ROOT)/library/tclIndex $(ROOT)/library/prolog.ps $(ROOT)/unix/tkAppInit.c; \
+ @for i in $(XLIB_DIR)/X11/*.h; \
do \
- echo "Installing $$i"; \
- $(INSTALL_DATA) $$i $(SCRIPT_INSTALL_DIR); \
+ $(INSTALL_DATA) $$i $(INCLUDE_INSTALL_DIR)/X11; \
done;
-
-install-minimal:
- @echo "Installing DLL"
- @$(INSTALL_DATA) $(TKDLL) $(BIN_INSTALL_DIR)/$(TKDLL)
- @for i in $(INSTALL_ROOT)@datadir@ $(SCRIPT_INSTALL_DIR) ; \
+ @echo "Installing library files to $(SCRIPT_INSTALL_DIR)";
+ @for i in $(ROOT_DIR)/library/*.tcl $(GENERIC_DIR)/prolog.ps \
+ $(ROOT_DIR)/library/tclIndex $(UNIX_DIR)/tkAppInit.c; \
do \
- if [ ! -d $$i ] ; then \
- echo "Making directory $$i"; \
- mkdir $$i; \
- chmod 755 $$i; \
- else true; \
- fi; \
+ $(INSTALL_DATA) $$i $(SCRIPT_INSTALL_DIR); \
done;
- for i in $(ROOT)/library/*.tcl $(ROOT)/library/tclIndex $(ROOT)/library/prolog.ps; \
+ @echo "Installing library images directory";
+ @for i in $(ROOT_DIR)/library/images/*; \
do \
- echo "Installing $$i"; \
- $(INSTALL_DATA) $$i $(SCRIPT_INSTALL_DIR); \
+ if [ -f $$i ] ; then \
+ $(INSTALL_DATA) $$i $(SCRIPT_INSTALL_DIR)/images; \
+ fi; \
done;
install-demos:
- @for i in $(INSTALL_ROOT)@datadir@ $(SCRIPT_INSTALL_DIR) \
+ @for i in $(INSTALL_ROOT)$(prefix)/lib $(SCRIPT_INSTALL_DIR) \
$(SCRIPT_INSTALL_DIR)/demos \
$(SCRIPT_INSTALL_DIR)/demos/images ; \
do \
if [ ! -d $$i ] ; then \
echo "Making directory $$i"; \
- mkdir $$i; \
+ $(MKDIR) $$i; \
chmod 755 $$i; \
else true; \
fi; \
done;
- @for i in $(ROOT)/library/demos/*; \
+ @echo "Installing demos to $(SCRIPT_INSTALL_DIR)/demos/";
+ @for i in $(ROOT_DIR)/library/demos/*; \
do \
if [ -f $$i ] ; then \
- echo "Installing $$i"; \
- sed -e '3 s|exec wish|exec $(WISH)|' \
+ sed -e '3 s|exec $(WISH)|exec $(WISH)|' \
$$i > $(SCRIPT_INSTALL_DIR)/demos/`basename $$i`; \
fi; \
done;
@@ -448,199 +480,114 @@ install-demos:
do \
chmod 755 $(SCRIPT_INSTALL_DIR)/demos/$$i; \
done;
- @for i in $(ROOT)/library/demos/images/*; \
+ @echo "Installing demo images";
+ @for i in $(ROOT_DIR)/library/demos/images/*; \
do \
if [ -f $$i ] ; then \
- echo "Installing $$i"; \
$(INSTALL_DATA) $$i $(SCRIPT_INSTALL_DIR)/demos/images; \
fi; \
done;
-ifeq ($(OBJEXT),o)
+install-doc:
-$(TKDLL): $(TKOBJS) tkres.$(OBJEXT) tkcyg.def
- $(CC) -s $(DLL_LDFLAGS) -Wl,--base-file,tk.base -o $(TKDLL) $(TKOBJS) tkres.$(OBJEXT) $(TCLLIBDIR)/$(TCLLIB) $(DLL_LDLIBS) -mwindows -Wl,-e,_DllMain@12 -Wl,--image-base,0x66300000
- $(DLLTOOL) --as=$(AS) --dllname $(TKDLL) --def $(TMPDIR)/tkcyg.def --base-file tk.base --output-exp tk.exp
- $(CC) -s $(DLL_LDFLAGS) -Wl,--base-file,tk.base tk.exp -o $(TKDLL) $(TKOBJS) tkres.$(OBJEXT) $(TCLLIBDIR)/$(TCLLIB) $(DLL_LDLIBS) -mwindows -Wl,-e,_DllMain@12 -Wl,--image-base,0x66300000
- $(DLLTOOL) --as=$(AS) --dllname $(TKDLL) --def $(TMPDIR)/tkcyg.def --base-file tk.base --output-exp tk.exp
- $(CC) $(DLL_LDFLAGS) tk.exp -o $(TKDLL) $(TKOBJS) tkres.$(OBJEXT) $(TCLLIBDIR)/$(TCLLIB) $(DLL_LDLIBS) -mwindows -Wl,-e,_DllMain@12 -Wl,--image-base,0x66300000
-else
+$(WISH): $(TK_LIB_FILE) $(WISH_OBJS) $(WISH_RES)
+ $(CC) $(CFLAGS) $(WISH_OBJS) $(TCL_LIB_SPEC) $(TK_LIB_FILE) $(LIBS) \
+ $(WISH_RES) $(CC_EXENAME) $(LDFLAGS_WINDOW)
-$(TKDLL): $(TKOBJS) tkres.$(OBJEXT) tkcyg.def
- link $(ldebug) $(dlllflags) -def:tkcyg.def \
- -out:$@ tkres.$(OBJEXT) $(TCLLIBDIR)/$(TCLLIB) \
- $(guilibsdll) $(TKOBJS)
- mv cygtk80.lib libtk80.a
-endif
+tktest : $(TKTEST)
-ifeq ($(OBJEXT),o)
+$(TKTEST): $(TK_LIB_FILE) $(TKTEST_OBJS) $(WISH_RES) $(CAT32)
+ $(CC) $(CFLAGS) $(TKTEST_OBJS_NATIVE) $(TCL_LIB_SPEC) \
+ $(TK_LIB_FILE) $(LIBS) \
+ $(WISH_RES) $(CC_EXENAME) $(LDFLAGS_WINDOW)
-$(TKLIB): $(TMPDIR)/tkcyg.def
- $(DLLTOOL) --as=$(AS) --dllname $(TKDLL) --def $(TMPDIR)/tkcyg.def --output-lib $(TKLIB)
+cat32.${OBJEXT}: $(TCL_SRC_DIR)/win/cat.c
+ $(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)
-else
+$(CAT32): cat32.${OBJEXT}
+ $(CC) $(CFLAGS) cat32.$(OBJEXT) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
-$(TKLIB): $(TKDLL)
+# WISH_RES
+$(RC_DIR)/wish_static.rc : $(RC_DIR)/wish.rc $(RC_DIR)/tk_base.rc
+ cat $(RC_DIR)/wish.rc $(RC_DIR)/tk_base.rc > $(RC_DIR)/wish_static.rc
-endif
+wish_static.$(RES) : $(RC_DIR)/wish_static.rc
+ $(RC) @RC_OUT@ $@ @RC_TYPE@ @RC_INCLUDE@ "$(GENERIC_DIR_NATIVE)" @RC_INCLUDE@ "$(TCL_GENERIC_NATIVE)" @RC_INCLUDE@ "$(RC_DIR_NATIVE)" @DEPARG@
-$(TKPLUGINLIB): $(TMPDIR)/plugin.def
- $(DLLTOOL) --as=$(AS) --dllname $(TKPLUGINDLL) --def $(TMPDIR)/plugin.def --output-lib $(TKPLUGINLIB)
-$(TKPLUGINDLL): $(TKOBJS) tkres.$(OBJEXT) $(TMPDIR)/plugin.def
- $(CC) $(DLL_LDFLAGS) -Wl,--base-file,tkplugin.base -o $(TKPLUGINDLL) $(TKOBJS) tkres.$(OBJEXT) $(TCLLIBDIR)/$(TCLLIB) $(DLL_LDLIBS) -mwindows -Wl,-e,_DllMain@12 -Wl,--image-base,0x66800000
- $(DLLTOOL) --as=$(AS) --dllname $(TKPLUGINDLL) --def $(TMPDIR)/plugin.def --base-file tkplugin.base --output-exp tk.exp
- $(CC) $(DLL_LDFLAGS) -Wl,--base-file,tkplugin.base tk.exp -o $(TKPLUGINDLL) $(TKOBJS) tkres.$(OBJEXT) $(TCLLIBDIR)/$(TCLLIB) $(DLL_LDLIBS) -mwindows -Wl,-e,_DllMain@12 -Wl,--image-base,0x66800000
- $(DLLTOOL) --as=$(AS) --dllname $(TKPLUGINDLL) --def $(TMPDIR)/plugin.def --base-file tkplugin.base --output-exp tk.exp
- $(CC) $(DLL_LDFLAGS) tk.exp -o $(TKPLUGINDLL) $(TKOBJS) tkres.$(OBJEXT) $(TCLLIBDIR)/$(TCLLIB) $(DLL_LDLIBS) -mwindows -Wl,-e,_DllMain@12 -Wl,--image-base,0x66800000
+# TK_RES
+$(RC_DIR)/tk_dll.rc : $(RC_DIR)/tk.rc $(RC_DIR)/tk_base.rc
+ cat $(RC_DIR)/tk.rc $(RC_DIR)/tk_base.rc > $(RC_DIR)/tk_dll.rc
-ifeq ($(OBJEXT),o)
+tk_dll.$(RES) : $(RC_DIR)/tk_dll.rc
+ $(RC) @RC_OUT@ $@ @RC_TYPE@ @RC_INCLUDE@ "$(GENERIC_DIR_NATIVE)" @RC_INCLUDE@ "$(TCL_GENERIC_NATIVE)" @RC_INCLUDE@ "$(RC_DIR_NATIVE)" @DEPARG@
-$(WISH): $(WISHOBJS) wishres.$(OBJEXT) $(TKLIB)
- $(CC) $(ldebug) $(guilflags) $(WISHOBJS) wishres.$(OBJEXT) -o $@ \
- $(TKLIB) $(TCLLIBDIR)/$(TCLLIB) $(guilibsdll)
+# The following targets are configured by autoconf to generate either
+# a shared library or static library
-else
+${TK_STUB_LIB_FILE}: ${STUB_OBJS}
+ @$(RM) ${TK_STUB_LIB_FILE}
+ @MAKE_LIB@ ${STUB_OBJS}
+ @POST_MAKE_LIB@
-$(WISH): $(WISHOBJS) wishres.$(OBJEXT) $(TKLIB)
- link $(ldebug) $(guilflags) $(WISHOBJS) wishres.$(OBJEXT) -OUT:$@ \
- $(TKLIB) $(TCLLIBDIR)/$(TCLLIB) $(guilibsdll)
-endif
+${TK_DLL_FILE}: ${TK_OBJS} $(TK_RES)
+ @$(RM) ${TK_DLL_FILE}
+ @MAKE_DLL@ ${TK_OBJS} $(TK_RES) $(SHLIB_LD_LIBS)
-$(WISHP): $(WISHOBJS) $(TKPLUGINLIB) wishres.$(OBJEXT)
- $(CC) $(ldebug) $(guilflags) $(WISHOBJS) wishres.$(OBJEXT) -o $@ \
- $(TKPLUGINLIB) $(TCLLIBDIR)/$(TCLPLUGINLIB) $(guilibsdll)
+${GNU_TK_LIB_FILE}: ${TK_DLL_FILE}
-$(TKTEST): $(TKTESTOBJS) wishres.$(OBJEXT) $(TKLIB)
- $(CC) $(ldebug) $(guilflags) $(TKTESTOBJS) wishres.$(OBJEXT) -o $@ \
- $(TKLIB) $(TCLLIBDIR)/$(TCLLIB) $(guilibsdll)
+${MSVC_TK_LIB_FILE}: ${TK_OBJS}
+ @$(RM) ${TK_LIB_FILE}
+ @MAKE_LIB@ ${TK_OBJS}
+ @POST_MAKE_LIB@
-ifeq ($(OBJEXT),o)
-tkcyg.def: $(TKOBJS)
- echo 'EXPORTS' > tmp.def
- for o in $(TKOBJS); do \
- $(NM) --extern-only --defined-only $$o | sed -e 's/[^ ]* [^ ]* //' -e 's/^_//' | fgrep -v DllEntryPoint | fgrep -v DllMain | fgrep -v impure_ptr >> tmp.def; \
- done
- mv tmp.def $(TMPDIR)/tkcyg.def
+# Special case object file targets
-plugin.def: $(TKOBJS)
- echo 'EXPORTS' > tmp.def
- for o in $(TKOBJS); do \
- $(NM) --extern-only --defined-only $$o | sed -e 's/[^ ]* [^ ]* //' -e 's/^_//' | fgrep -v DllEntryPoint | fgrep -v DllMain | fgrep -v impure_ptr >> tmp.def; \
- done
- mv tmp.def $(TMPDIR)/plugin.def
+winMain.$(OBJEXT): winMain.c
+ $(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)
-else
+testMain.$(OBJEXT): winMain.c
+ $(CC) -c $(CC_SWITCHES) @DEPARG@ -DTK_TEST $(CC_OBJNAME)
-# Source-Navigator need the extra Symbols.
+tkTest.$(OBJEXT): tkTest.c
+ $(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)
-tkcyg.def: $(TKOBJS) $(DUMPEXTS)
- $(DUMPEXTS) -o tkcyg.def $(TKDLL) $(TKOBJS)
- echo " tkWindowType" >> tkcyg.def
- echo " tkArcType" >> tkcyg.def
- echo " tkBitmapType" >> tkcyg.def
- echo " tkOvalType" >> tkcyg.def
- echo " tkImageType" >> tkcyg.def
- echo " tkPolygonType" >> tkcyg.def
- echo " tkLineType" >> tkcyg.def
- echo " tkTextType" >> tkcyg.def
- echo " tkRectangleType" >> tkcyg.def
- echo " tkTextCharType" >> tkcyg.def
+tkWinTest.$(OBJEXT): tkWinTest.c
+ $(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)
-plugin.def: $(TKOBJS) $(DUMPEXTS)
- $(DUMPEXTS) -o tkcyg.def $(TKDLL) $(TKOBJS)
+tkSquare.$(OBJEXT): tkSquare.c
+ $(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME)
+tclThreadTest.$(OBJEXT): $(TCL_BIN_DIR)/tclThreadTest.$(OBJEXT)
-$(DUMPEXTS): $(TCLDIR)/win/winDumpExts.c
- $(CC) $(TCLDIR)/win/winDumpExts.c user32.lib -link -OUT:$(DUMPEXTS)
+# Add the object extension to the implicit rules. By default .obj is not
+# automatically added.
-endif
+.SUFFIXES: .${OBJEXT}
+.SUFFIXES: .$(RES)
+.SUFFIXES: .rc
-#$(DUMPEXTS): $(TCLDIR)\win\winDumpExts.c
-# $(cc32) $(CON_CFLAGS) -Fo$(TMPDIR)\ $?
-# set LIB=$(TOOLS32)\lib
-# $(link32) $(ldebug) $(conlflags) $(guilibs) -out:$@ \
-# $(TMPDIR)\winDumpExts.$(OBJEXT)bj
+# Implicit rule for all object files that will end up in the Tcl library
-#
-# Special case object file targets
-#
+.c.$(OBJEXT):
+ $(CC) -c $(STUB_CC_SWITCHES) -DBUILD_tk @DEPARG@ $(CC_OBJNAME)
-$(TMPDIR)/testMain.$(OBJEXT): $(ROOT)/win/winMain.c
- $(CC) -c $(TK_CFLAGS) -DTK_TEST -o $@ $?
+.rc.$(RES):
+ $(RC) @RC_OUT@ $@ @RC_TYPE@ @RC_INCLUDE@ "$(GENERIC_DIR_NATIVE)" @RC_INCLUDE@ "$(TCL_GENERIC_NATIVE)" @RC_INCLUDE@ "$(RC_DIR_NATIVE)" @DEPARG@
-#
-# Implicit rules
-#
-.SUFFIXES: .S .c .o .obj .s
-.c.$(OBJEXT):
- $(CC) -c $(TK_CFLAGS) $<
-
-ifeq ($(OBJEXT),o)
-
-tkres.$(OBJEXT): $(ROOT)/win/rc/tk.rc
- $(WINDRES) --include $(ROOT)/win/rc --include $(ROOT)/generic --define VS_VERSION_INFO=1 $(ROOT)/win/rc/tk.rc tkres.$(OBJEXT)
-
-wishres.$(OBJEXT): $(ROOT)/win/rc/wish.rc
- $(WINDRES) --include $(ROOT)/win/rc --include $(ROOT)/generic --define VS_VERSION_INFO=1 $(ROOT)/win/rc/wish.rc wishres.$(OBJEXT)
-
-else
-
-tkres.$(OBJEXT): $(ROOT)/win/rc/tk.rc
- rc -i$(ROOT)/win/rc -i$(ROOT)/generic -dVS_VERSION_INFO=1 -fotkres.$(OBJEXT) $(ROOT)/win/rc/tk.rc
-
-wishres.$(OBJEXT): $(ROOT)/win/rc/wish.rc
- rc -i$(ROOT)/win/rc -i$(ROOT)/generic -dVS_VERSION_INFO=1 -fowishres.$(OBJEXT) $(ROOT)/win/rc/wish.rc
-
-endif
-
-#{$(ROOT)\win\rc}.rc{$(TMPDIR)}.res:
-# $(rc32) -fo $@ -r -i $(ROOT)\generic $<
-
-clean:
- rm -f *.exp *.a *.dll *.exe $(TMPDIR)/*.$(OBJEXT) *.res *.def
- rm -f tk.base tkplugin.base
-
-# dependencies
-
-$(TMPDIR)/tk.res: \
- $(RCDIR)/buttons.bmp \
- $(RCDIR)/cursor*.cur \
- $(RCDIR)/tk.ico
-
-$(GENERICDIR)/default.h: $(WINDIR)/tkWinDefault.h
-$(GENERICDIR)/tkButton.c: $(GENERICDIR)/default.h
-$(GENERICDIR)/tkCanvas.c: $(GENERICDIR)/default.h
-$(GENERICDIR)/tkEntry.c: $(GENERICDIR)/default.h
-$(GENERICDIR)/tkFrame.c: $(GENERICDIR)/default.h
-$(GENERICDIR)/tkListbox.c: $(GENERICDIR)/default.h
-$(GENERICDIR)/tkMenu.c: $(GENERICDIR)/default.h
-$(GENERICDIR)/tkMenubutton.c: $(GENERICDIR)/default.h
-$(GENERICDIR)/tkMessage.c: $(GENERICDIR)/default.h
-$(GENERICDIR)/tkScale.c: $(GENERICDIR)/default.h
-$(GENERICDIR)/tkScrollbar.c: $(GENERICDIR)/default.h
-$(GENERICDIR)/tkText.c: $(GENERICDIR)/default.h
-$(GENERICDIR)/tkTextIndex.c: $(GENERICDIR)/default.h
-$(GENERICDIR)/tkTextTag.c: $(GENERICDIR)/default.h
-
-$(GENERICDIR)/tkText.c: $(GENERICDIR)/tkText.h
-$(GENERICDIR)/tkTextBTree.c: $(GENERICDIR)/tkText.h
-$(GENERICDIR)/tkTextDisp.c: $(GENERICDIR)/tkText.h
-$(GENERICDIR)/tkTextDisp.c: $(GENERICDIR)/tkText.h
-$(GENERICDIR)/tkTextImage.c: $(GENERICDIR)/tkText.h
-$(GENERICDIR)/tkTextIndex.c: $(GENERICDIR)/tkText.h
-$(GENERICDIR)/tkTextMark.c: $(GENERICDIR)/tkText.h
-$(GENERICDIR)/tkTextTag.c: $(GENERICDIR)/tkText.h
-$(GENERICDIR)/tkTextWind.c: $(GENERICDIR)/tkText.h
-
-$(GENERICDIR)/tkMacWinMenu.c: $(GENERICDIR)/tkMenu.h
-$(GENERICDIR)/tkMenu.c: $(GENERICDIR)/tkMenu.h
-$(GENERICDIR)/tkMenuDraw.c: $(GENERICDIR)/tkMenu.h
-$(WINDIR)/tkWinMenu.c: $(GENERICDIR)/tkMenu.h
-
-Makefile: $(WINDIR)/Makefile.in config.status
- $(SHELL) config.status
-
-config.status: $(WINDIR)/configure
- ./config.status --recheck
+depend:
+
+cleanhelp:
+ $(RM) *.hlp *.cnt *.hpj *.GID *.rtf man2tcl${EXEEXT}
+
+clean: cleanhelp
+ $(RM) *.lib *.a *.exp *.dll *.$(RES) *.${OBJEXT} *~ \#* TAGS a.out
+ $(RM) $(WISH) $(TKTEST) $(CAT32)
+ $(RM) *.pch *.ilk *.pdb
+
+distclean: clean
+ $(RM) Makefile config.status config.cache config.log tkConfig.sh
+
+Makefile: $(SRC_DIR)/Makefile.in
+ ./config.status
diff --git a/tk/win/README b/tk/win/README
index f0206a6f2f5..fe3790e478b 100644
--- a/tk/win/README
+++ b/tk/win/README
@@ -1,4 +1,4 @@
-Tk 8.0.4 for Windows
+Tk 8.3 for Windows
by Scott Stanton
Scriptics Corporation
@@ -6,117 +6,20 @@ scott.stanton@scriptics.com
RCS: @(#) $Id$
-1. Introduction
----------------
-
This is the directory where you configure and compile the Windows
version of Tk. This directory also contains source files for Tk
that are specific to Microsoft Windows. The rest of this file
contains information specific to the Windows version of Tk.
-2. Distribution notes
----------------------
-
-Tk 8.0 for Windows is distributed in binary form in addition to the
-common source release. The binary distribution is a self-extracting
-archive with a built-in installation script.
-
-Look for the binary release in the same location as the source release
-(ftp.scriptics.com:/pub/tcl/tcl8_0 or any of the mirror sites). For most users,
-the binary release will be much easier to install and use. You only
-need the source release if you plan to modify the core of Tcl, or if
-you need to compile with a different compiler. With the addition of
-the dynamic loading interface, it is no longer necessary to have the
-source distribution in order to build and use extensions.
-
-3. Compiling Tk
-----------------
-
-In order to compile Tk for Windows, you need the following items:
-
- Tcl 8.0 Source Distribution (plus any patches)
- Tk 8.0 Source Distribution (plus any patches)
-
- The latest Win32 SDK header files
-
- Borland C++ 4.5 or later (32-bit compiler)
- or
- Visual C++ 2.x or later
-
-In practice, 8.0.4 was built with Visual C++ 5.0
-
-In the "win" subdirectory of the source release, you will find two
-files called "makefile.bc" and "makefile.vc". These are the makefiles
-for the Borland and Visual C++ compilers respectively. You should
-copy the appropriate one to "makefile" and update the paths at the top
-of the file to reflect your system configuration. Now you can use
-"make" (or "nmake" for VC++) to build the tk libraries and the wish
-executable.
-
-In order to use the binaries generated by these makefiles, you will
-need to place the Tk script library files someplace where Tk can
-find them. Tk looks in one of two places for the library files:
-
- 1) The environment variable "TK_LIBRARY".
-
- 2) In the lib\tk8.0 directory under the Tcl installation directory
- as specified in the registry:
-
- For Windows NT & 95:
- HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.0
- Value Name is "Root"
-
- For Win32s:
- HKEY_CLASSES_ROOT\SOFTWARE\Scriptics\Tcl\8.0\
-
- 2) Relative to the directory containing the current .exe.
- Tk will look for a directory "..\lib\tk8.0" relative to the
- directory containing the currently running .exe.
-
-Note that in order to run wish80.exe, you must ensure that tcl80.dll,
-tclpip80.dll (plus tcl1680.dll under Win32s), and tk80.dll are on your
-path, in the system directory, or in the directory containing
-wish80.exe.
-
-4. Test suite
--------------
-
-The Windows version of Tk does not pass many of the tests in the test
-suite. This is primarily due to dependencies in the test suite on the
-size of particular X fonts, and other X related features as well as
-problems with "exec". We will be working to develop a more general
-test suite for Tk under Windows, but for now, you will not be able to
-pass many of the tests.
-
-5. Known Bugs
--------------
-
-Here is the current list of known bugs/missing features for the
-Windows beta version of Tk:
-
-- There is no support for custom cursors/application icons. The core
- set of X cursors is supported, although you cannot change their color.
-- Stippling of arcs isn't implemented yet.
-- Some "wm" functions don't map to Windows and aren't implemented;
- others should map, but just aren't implemented. The worst offenders
- are the icon manipulation routines.
-- Under Win32s, you can only start one instance of Wish at a time.
-- Color management on some displays doesn't work properly resulting in
- Tk switching to monochrome mode.
-- Tk seems to fail to draw anything on some Matrox Millenium cards.
-- Printing does not work for images (e.g. GIF) on a canvas.
-- Tk_dialog appears in the upper left corner. This is a symptom of a
- larger problem with "wm geometry" when applied to unmapped or
- iconified windows.
-- Some keys don't work on international keyboards.
-- PPM images are using the wrong translation mode for writing to
- files, resulting in CR/LF terminated PPM files.
-- Tk crashes if the display depth changes while it is running. Tk
- also doesn't consistently track changes in the system colors.
-
-If you have comments or bug reports for the Windows version of Tk,
-please direct them to:
+Please see the README and win/README files that come with the
+associated Tcl release for an extensive set of pointers to
+documentation. You will need to obtain and compile the
+Tcl release before using the Tk source distrition.
-<bugs@scriptics.com>
+If you install the Tk sources next to the Tcl sources, then
+the Tk Makefiles (e.g., makefile.vc for VC++) will properly
+locate the necessary Tcl files. Otherwise you may need to
+edit makefile.vc and adjust the path to Tcl accordingly.
-or post them to the newsgroup comp.lang.tcl.
+Information about compiling for windows is maintained at:
+ http://dev.scriptics.com/doc/howto/compile.html
diff --git a/tk/win/aclocal.m4 b/tk/win/aclocal.m4
new file mode 100644
index 00000000000..005783c4aae
--- /dev/null
+++ b/tk/win/aclocal.m4
@@ -0,0 +1,2 @@
+builtin(include,tcl.m4)
+builtin(include,../cygtcl.m4)
diff --git a/tk/win/configure b/tk/win/configure
index 20cf223f653..601e2868c1c 100755
--- a/tk/win/configure
+++ b/tk/win/configure
@@ -1,7 +1,7 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.12.2
+# Generated automatically using autoconf version 2.13
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
@@ -12,7 +12,13 @@ ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:
ac_help="$ac_help
- --with-tcl=DIR use Tcl 8.0 binaries from DIR"
+ --enable-threads build with threads"
+ac_help="$ac_help
+ --enable-shared build and link with shared libraries [--enable-shared]"
+ac_help="$ac_help
+ --enable-symbols build with debugging symbols [--disable-symbols]"
+ac_help="$ac_help
+ --with-tcl=DIR use Tcl 8.3 binaries from DIR"
# Initialize some variables set by options.
# The variables have the same names as the options, with
@@ -30,6 +36,7 @@ program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
+sitefile=
srcdir=
target=NONE
verbose=
@@ -144,6 +151,7 @@ Configuration:
--help print this message
--no-create do not create output files
--quiet, --silent do not print \`checking...' messages
+ --site-file=FILE use FILE as the site file
--version print the version of autoconf that created configure
Directory and file names:
--prefix=PREFIX install architecture-independent files in PREFIX
@@ -314,6 +322,11 @@ EOF
-site=* | --site=* | --sit=*)
site="$ac_optarg" ;;
+ -site-file | --site-file | --site-fil | --site-fi | --site-f)
+ ac_prev=sitefile ;;
+ -site-file=* | --site-file=* | --site-fil=* | --site-fi=* | --site-f=*)
+ sitefile="$ac_optarg" ;;
+
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
@@ -335,7 +348,7 @@ EOF
verbose=yes ;;
-version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.12.2"
+ echo "configure generated by autoconf version 2.13"
exit 0 ;;
-with-* | --with-*)
@@ -479,12 +492,16 @@ fi
srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
- if test "x$prefix" != xNONE; then
- CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
- else
- CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+if test -z "$sitefile"; then
+ if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
fi
+else
+ CONFIG_SITE="$sitefile"
fi
for ac_site_file in $CONFIG_SITE; do
if test -r "$ac_site_file"; then
@@ -524,6 +541,12 @@ fi
+TK_VERSION=8.3
+TK_MAJOR_VERSION=8
+TK_MINOR_VERSION=3
+TK_PATCH_LEVEL=".2"
+VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION
+
if test "${prefix}" = "NONE"; then
prefix=/usr/local
fi
@@ -531,57 +554,14 @@ if test "${exec_prefix}" = "NONE"; then
exec_prefix=$prefix
fi
-ac_aux_dir=
-for ac_dir in $srcdir $srcdir/.. $srcdir/../..; 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
- fi
-done
-if test -z "$ac_aux_dir"; then
- { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
-fi
-ac_config_guess=$ac_aux_dir/config.guess
-ac_config_sub=$ac_aux_dir/config.sub
-ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
-
-
-# Make sure we can run config.sub.
-if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
-else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
-fi
-
-echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:561: checking host system type" >&5
-
-host_alias=$host
-case "$host_alias" in
-NONE)
- case $nonopt in
- NONE)
- if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
- else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
- fi ;;
- *) host_alias=$nonopt ;;
- esac ;;
-esac
-
-host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
-host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-echo "$ac_t""$host" 1>&6
-
+#------------------------------------------------------------------------
+# Standard compiler checks
+#------------------------------------------------------------------------
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:585: checking for $ac_word" >&5
+echo "configure:565: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -589,7 +569,8 @@ else
ac_cv_prog_CC="$CC" # Let the user override the test.
else
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- for ac_dir in $PATH; do
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
ac_cv_prog_CC="gcc"
@@ -610,7 +591,7 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:614: checking for $ac_word" >&5
+echo "configure:595: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -619,7 +600,8 @@ else
else
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
ac_prog_rejected=no
- for ac_dir in $PATH; do
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
@@ -660,7 +642,7 @@ fi
# Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:664: checking for $ac_word" >&5
+echo "configure:646: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -668,7 +650,8 @@ else
ac_cv_prog_CC="$CC" # Let the user override the test.
else
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- for ac_dir in $PATH; do
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$ac_word; then
ac_cv_prog_CC="cl"
@@ -691,7 +674,7 @@ fi
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:695: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:678: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -700,12 +683,14 @@ ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross
-cat > conftest.$ac_ext <<EOF
-#line 705 "configure"
+cat > conftest.$ac_ext << EOF
+
+#line 689 "configure"
#include "confdefs.h"
+
main(){return(0);}
EOF
-if { (eval echo configure:709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:694: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
@@ -719,18 +704,24 @@ else
ac_cv_prog_cc_works=no
fi
rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:729: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:720: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:734: checking whether we are using GNU C" >&5
+echo "configure:725: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -739,7 +730,7 @@ else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:743: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:734: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@@ -758,7 +749,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:762: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:753: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -789,14 +780,361 @@ else
fi
fi
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; 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
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:811: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:832: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+if test $host != $build; then
+ ac_tool_prefix=${host_alias}-
+else
+ ac_tool_prefix=
+fi
+
+# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:858: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+AR="$ac_cv_prog_AR"
+if test -n "$AR"; then
+ echo "$ac_t""$AR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_AR"; then
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:890: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AR="ar"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_AR" && ac_cv_prog_AR=":"
+fi
+fi
+AR="$ac_cv_prog_AR"
+if test -n "$AR"; then
+ echo "$ac_t""$AR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ AR=":"
+fi
+fi
+
+# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:925: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_RANLIB"; then
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:957: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ RANLIB=":"
+fi
+fi
+
+# Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args.
+set dummy ${ac_tool_prefix}windres; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:992: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RC"; then
+ ac_cv_prog_RC="$RC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RC="${ac_tool_prefix}windres"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+RC="$ac_cv_prog_RC"
+if test -n "$RC"; then
+ echo "$ac_t""$RC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_RC"; then
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "windres", so it can be a program name with args.
+set dummy windres; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1024: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RC"; then
+ ac_cv_prog_RC="$RC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RC="windres"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RC" && ac_cv_prog_RC=":"
+fi
+fi
+RC="$ac_cv_prog_RC"
+if test -n "$RC"; then
+ echo "$ac_t""$RC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ RC=":"
+fi
+fi
+
+
+#--------------------------------------------------------------------
+# Checks to see if the make progeam sets the $MAKE variable.
+#--------------------------------------------------------------------
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:1062: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+#--------------------------------------------------------------------
+# These two macros perform additinal compiler test.
+#--------------------------------------------------------------------
+
+echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+echo "configure:1094: checking for Cygwin environment" >&5
+if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1099 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#ifndef __CYGWIN__
+#define __CYGWIN__ __CYGWIN32__
+#endif
+return __CYGWIN__;
+; return 0; }
+EOF
+if { (eval echo configure:1110: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_cygwin=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_cygwin=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_cygwin" 1>&6
+CYGWIN=
+test "$ac_cv_cygwin" = yes && CYGWIN=yes
+
+#--------------------------------------------------------------------
+# Determines the correct binary file extension (.o, .obj, .exe etc.)
+#--------------------------------------------------------------------
+
echo $ac_n "checking for object suffix""... $ac_c" 1>&6
-echo "configure:794: checking for object suffix" >&5
+echo "configure:1132: checking for object suffix" >&5
if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
rm -f conftest*
echo 'int i = 1;' > conftest.$ac_ext
-if { (eval echo configure:800: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1138: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
for ac_file in conftest.*; do
case $ac_file in
*.c) ;;
@@ -813,145 +1151,1237 @@ echo "$ac_t""$ac_cv_objext" 1>&6
OBJEXT=$ac_cv_objext
ac_objext=$ac_cv_objext
-NM=${NM-nm}
+echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
+echo "configure:1156: checking for mingw32 environment" >&5
+if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1161 "configure"
+#include "confdefs.h"
-AS=${AS-as}
+int main() {
+return __MINGW32__;
+; return 0; }
+EOF
+if { (eval echo configure:1168: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_mingw32=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_mingw32=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
-LD=${LD-ld}
+echo "$ac_t""$ac_cv_mingw32" 1>&6
+MINGW32=
+test "$ac_cv_mingw32" = yes && MINGW32=yes
-DLLTOOL=${DLLTOOL-dlltool}
-WINDRES=${WINDRES-windres}
+echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+echo "configure:1187: checking for executable suffix" >&5
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+ ac_cv_exeext=.exe
+else
+ rm -f conftest*
+ echo 'int main () { return 0; }' > conftest.$ac_ext
+ ac_cv_exeext=
+ if { (eval echo configure:1197: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ for file in conftest.*; do
+ case $file in
+ *.c | *.o | *.obj | *.ilk | *.pdb) ;;
+ *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
+ esac
+ done
+ else
+ { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
+ fi
+ rm -f conftest*
+ test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
+fi
+fi
+
+EXEEXT=""
+test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
+echo "$ac_t""${ac_cv_exeext}" 1>&6
+ac_exeext=$EXEEXT
+
+
+#--------------------------------------------------------------------
+# Check whether --enable-threads or --disable-threads was given.
+#--------------------------------------------------------------------
+
+
+ echo $ac_n "checking for building with threads""... $ac_c" 1>&6
+echo "configure:1224: checking for building with threads" >&5
+ # Check whether --enable-threads or --disable-threads was given.
+if test "${enable_threads+set}" = set; then
+ enableval="$enable_threads"
+ tcl_ok=$enableval
+else
+ tcl_ok=no
+fi
+
+
+ if test "$tcl_ok" = "yes"; then
+ echo "$ac_t""yes" 1>&6
+ TCL_THREADS=1
+ cat >> confdefs.h <<\EOF
+#define TCL_THREADS 1
+EOF
+
+ else
+ TCL_THREADS=0
+ echo "$ac_t""no (default)" 1>&6
+ fi
+
+
+#--------------------------------------------------------------------
+# The statements below define a collection of symbols related to
+# building libtk as a shared library instead of a static library.
+#--------------------------------------------------------------------
+
+
+ echo $ac_n "checking how to build libraries""... $ac_c" 1>&6
+echo "configure:1254: checking how to build libraries" >&5
+ # Check whether --enable-shared or --disable-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 "$ac_t""shared" 1>&6
+ SHARED_BUILD=1
+ else
+ echo "$ac_t""static" 1>&6
+ SHARED_BUILD=0
+ cat >> confdefs.h <<\EOF
+#define STATIC_BUILD 1
+EOF
+
+ fi
-# 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
-# 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"
-# ./install, which can be erroneously created by make from ./install.sh.
-echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:839: checking for a BSD compatible install" >&5
-if test -z "$INSTALL"; then
-if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+
+#--------------------------------------------------------------------
+# The statements below define a collection of compile flags. This
+# macro depends on the value of SHARED_BUILD, and should be called
+# after SC_ENABLE_SHARED checks the configure switches.
+#--------------------------------------------------------------------
+
+
+ TCL_LIB_VERSIONS_OK=nodots
+
+ # Extract the first word of "cygpath", so it can be a program name with args.
+set dummy cygpath; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1296: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CYGPATH'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
- for ac_dir in $PATH; do
- # Account for people who put trailing slashes in PATH elements.
- case "$ac_dir/" in
- /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/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
- if test -f $ac_dir/$ac_prog; then
- if test $ac_prog = install &&
- grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- else
- ac_cv_path_install="$ac_dir/$ac_prog -c"
- break 2
- fi
- fi
- done
- ;;
- esac
+ if test -n "$CYGPATH"; then
+ ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CYGPATH="cygpath -w"
+ break
+ fi
done
- IFS="$ac_save_IFS"
+ IFS="$ac_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 "$ac_t""$CYGPATH" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+ # 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 "$GCC" = "yes" && test "$CYGPATH" != "echo" ; then
+ conftest=/tmp/conftest.rc
+ echo "STRINGTABLE BEGIN" > $conftest
+ echo "101 \"name\"" >> $conftest
+ echo "END" >> $conftest
+
+ echo $ac_n "checking for Windows native path bug in windres""... $ac_c" 1>&6
+echo "configure:1338: checking for Windows native path bug in windres" >&5
+ cyg_conftest=`$CYGPATH $conftest`
+ if { ac_try='$RC -o conftest.res.o $cyg_conftest'; { (eval echo configure:1340: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } ; then
+ echo "$ac_t""no" 1>&6
+ else
+ echo "$ac_t""yes" 1>&6
+ CYGPATH=echo
+ fi
+ conftest=
+ cyg_conftest=
+ fi
+
+ if test "$CYGPATH" = "echo" || test "$ac_cv_cygwin" = "yes"; then
+ DEPARG='"$<"'
+ else
+ DEPARG='"$(shell $(CYGPATH) $<)"'
+ fi
+
+ VENDORPREFIX=""
+
+ # set various compiler flags depending on whether we are using gcc or cl
+
+ echo $ac_n "checking compiler flags""... $ac_c" 1>&6
+echo "configure:1361: checking compiler flags" >&5
+ if test "${GCC}" = "yes" ; then
+
+ # CYGNUS LOCAL
+ VENDORPREFIX="cyg"
+
+ SHLIB_LD=""
+ SHLIB_LD_LIBS=""
+ LIBS=""
+ LIBS_GUI="-lgdi32 -lcomdlg32"
+ STLIB_LD="${AR} cr"
+ RC_OUT=-o
+ RC_TYPE=
+ RC_INCLUDE=--include
+ RES=res.o
+ MAKE_LIB="\${STLIB_LD} \$@"
+ POST_MAKE_LIB="\${RANLIB} \$@"
+ MAKE_EXE="\${CC} -o \$@"
+ LIBPREFIX="lib${VENDORPREFIX}"
+
+ if test "${SHARED_BUILD}" = "0" ; then
+ # static
+ echo "$ac_t""using static flags" 1>&6
+ runtime=
+ MAKE_DLL="echo "
+ LIBSUFFIX="s\${DBGX}.a"
+ LIBRARIES="\${STATIC_LIBRARIES}"
+ EXESUFFIX="s\${DBGX}.exe"
+ DLLSUFFIX=""
+ else
+ # dynamic
+ echo "$ac_t""using shared flags" 1>&6
+
+ # ad-hoc check to see if CC supports -shared.
+ if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then
+ { echo "configure: error: ${CC} does not support the -shared option.
+ You will need to upgrade to a newer version of the toolchain." 1>&2; exit 1; }
+ fi
+
+ runtime=
+ # Link with gcc since ld does not link to default libs like
+ # -luser32 and -lmsvcrt. We also need to add CFLAGS so important
+ # flags like -mno-cygwin get passed in to CC.
+ SHLIB_LD='${CC} -shared ${CFLAGS}'
+ # Add SHLIB_LD_LIBS to the Make rule, not here.
+ MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \$@ ${extra_ldflags} \
+ -Wl,--out-implib,\$(patsubst %.dll,lib%.a,\$@)"
+
+ LIBSUFFIX="\${DBGX}.a"
+ DLLSUFFIX="\${DBGX}.dll"
+ EXESUFFIX="\${DBGX}.exe"
+ LIBRARIES="\${SHARED_LIBRARIES}"
+ fi
+
+ CFLAGS_DEBUG=-g
+ CFLAGS_OPTIMIZE=-O
+ CFLAGS_WARNING="-Wall -Wconversion"
+ LDFLAGS_DEBUG=
+ LDFLAGS_OPTIMIZE=
+
+ # Specify the CC output file names based on the target name
+ CC_OBJNAME="-o \$@"
+ CC_EXENAME="-o \$@"
+
+ # Specify linker flags depending on the type of app being
+ # built -- Console vs. Window.
+ #
+ # We need to pass -e _WinMain@16 so that ld will use
+ # WinMain() instead of main() as the entry point. We can't
+ # use autoconf to check for this case since it would need
+ # to run an executable and that does not work when
+ # cross compiling. Remove this -e workaround once we
+ # require a gcc that does not have this bug.
+ LDFLAGS_CONSOLE="-mconsole ${extra_ldflags}"
+ LDFLAGS_WINDOW="-mwindows -e _WinMain@16 ${extra_ldflags}"
+ else
+ # CYGNUS LOCAL
+ VENDORPREFIX="sn"
+
+ SHLIB_LD="link -dll -nologo"
+ SHLIB_LD_LIBS="user32.lib advapi32.lib"
+ LIBS="user32.lib advapi32.lib"
+ LIBS_GUI="gdi32.lib comdlg32.lib"
+ STLIB_LD="lib -nologo"
+ RC="rc"
+ RC_OUT=-fo
+ RC_TYPE=-r
+ RC_INCLUDE=-i
+ RES=res
+ MAKE_LIB="\${STLIB_LD} -out:\$@"
+ POST_MAKE_LIB=
+ MAKE_EXE="\${CC} -Fe\$@"
+ LIBPREFIX=${VENDORPREFIX}
+
+ if test "${SHARED_BUILD}" = "0" ; then
+ # static
+ echo "$ac_t""using static flags" 1>&6
+ runtime=-MT
+ MAKE_DLL="echo "
+ LIBSUFFIX="s\${DBGX}.lib"
+ LIBRARIES="\${STATIC_LIBRARIES}"
+ EXESUFFIX="s\${DBGX}.exe"
+ DLLSUFFIX=""
+ else
+ # dynamic
+ echo "$ac_t""using shared flags" 1>&6
+ runtime=-MD
+ # Add SHLIB_LD_LIBS to the Make rule, not here.
+ MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -out:\$@"
+ LIBSUFFIX="\${DBGX}.lib"
+ DLLSUFFIX="\${DBGX}.dll"
+ EXESUFFIX="\${DBGX}.exe"
+ LIBRARIES="\${SHARED_LIBRARIES}"
+ fi
+
+ EXTRA_CFLAGS="-YX"
+ CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
+# CFLAGS_OPTIMIZE="-nologo -O2 -Gs -GD ${runtime}"
+ CFLAGS_OPTIMIZE="-nologo -Oti -Gs -GD ${runtime}"
+ CFLAGS_WARNING="-W3"
+ LDFLAGS_DEBUG="-debug:full -debugtype:cv"
+ LDFLAGS_OPTIMIZE="-release"
+
+ # Specify the CC output file names based on the target name
+ CC_OBJNAME="-Fo\$@"
+ CC_EXENAME="-Fe\"\$(shell \$(CYGPATH) '\$@')\""
+
+ # Specify linker flags depending on the type of app being
+ # built -- Console vs. Window.
+ LDFLAGS_CONSOLE="-link -subsystem:console"
+ LDFLAGS_WINDOW="-link -subsystem:windows"
+ fi
+ # TCL_LIB_SUFFIX is defined here and in tclConfig.sh so that macros
+ # can use a single variable name for both Tcl and extensions.
+ TCL_LIB_SUFFIX=$LIBSUFFIX
+
+
+#--------------------------------------------------------------------
+# man2tcl needs this so that it can use errno.h
+#--------------------------------------------------------------------
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1504: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
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. We don't cache a
- # path for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the path is relative.
- INSTALL="$ac_install_sh"
- fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 1519 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1525: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1536 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1542: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 1553 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1559: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
fi
-echo "$ac_t""$INSTALL" 1>&6
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&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}'
+ac_safe=`echo "errno.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for errno.h""... $ac_c" 1>&6
+echo "configure:1585: checking for errno.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1590 "configure"
+#include "confdefs.h"
+#include <errno.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1595: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+MAN2TCLFLAGS="-DNO_ERRNO_H"
+fi
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-# needed for the subtle differences between cygwin and mingw32
-case "${host}" in
-*-*-cygwin*)
- DLL_LDLIBS=-lcygwin
- DLL_LDFLAGS='-nostartfiles -Wl,--dll'
- ;;
-*-*-mingw32*)
- DLL_LDLIBS=
- DLL_LDFLAGS='-mdll'
- ;;
-esac
+#--------------------------------------------------------------------
+# Set the default compiler switches based on the --enable-symbols
+# option. This macro depends on C flags, and should be called
+# after SC_CONFIG_CFLAGS macro is called.
+#--------------------------------------------------------------------
+
+
+ echo $ac_n "checking for build with symbols""... $ac_c" 1>&6
+echo "configure:1627: checking for build with symbols" >&5
+ # Check whether --enable-symbols or --disable-symbols was given.
+if test "${enable_symbols+set}" = set; then
+ enableval="$enable_symbols"
+ tcl_ok=$enableval
+else
+ tcl_ok=no
+fi
+
+
+ if test "$tcl_ok" = "yes"; then
+ CFLAGS_DEFAULT='$(CFLAGS_DEBUG)'
+ LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'
+ DBGX=d
+ echo "$ac_t""yes" 1>&6
+ else
+ CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
+ LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
+ DBGX=""
+ echo "$ac_t""no" 1>&6
+ fi
+TK_DBGX=${DBGX}
+#--------------------------------------------------------------------
+# Locate and source the tclConfig.sh file.
+#--------------------------------------------------------------------
-# The following stuff is just for tkConfig.sh, not for Makefile.
+ echo $ac_n "checking the location of tclConfig.sh""... $ac_c" 1>&6
+echo "configure:1658: checking the location of tclConfig.sh" >&5
-# Check whether --with-tcl or --without-tcl was given.
+# CYGNUS LOCAL
+ if test -d ../../tcl8.1/win; then
+ TCL_BIN_DIR_DEFAULT=../../tcl8.1/win
+ else
+ TCL_BIN_DIR_DEFAULT=../../tcl/win
+ fi
+# END CYGNUS LOCAL
+
+ # 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/unix; pwd`
+ TCL_BIN_DIR=`cd $TCL_BIN_DIR_DEFAULT; pwd`
fi
-if test ! -d $TCL_BIN_DIR; then
- { echo "configure: error: Tcl directory $TCL_BIN_DIR doesn't exist" 1>&2; exit 1; }
+ if test ! -d $TCL_BIN_DIR; then
+ { echo "configure: error: Tcl directory $TCL_BIN_DIR does not exist" 1>&2; exit 1; }
+ fi
+ if test ! -f $TCL_BIN_DIR/tclConfig.sh; then
+ { echo "configure: 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?" 1>&2; exit 1; }
+ fi
+ echo "$ac_t""$TCL_BIN_DIR/tclConfig.sh" 1>&6
+
+
+ echo $ac_n "checking for existence of $TCL_BIN_DIR/tclConfig.sh""... $ac_c" 1>&6
+echo "configure:1686: checking for existence of $TCL_BIN_DIR/tclConfig.sh" >&5
+
+ if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
+ echo "$ac_t""loading" 1>&6
+ . $TCL_BIN_DIR/tclConfig.sh
+ else
+ echo "$ac_t""file not found" 1>&6
+ fi
+
+ # The eval is required to do the TCL_DBGX substitution in the
+ # TCL_LIB_FILE variable.
+
+ eval TCL_LIB_FILE=${TCL_LIB_FILE}
+ eval TCL_LIB_FLAG=${TCL_LIB_FLAG}
+
+
+
+
+
+
+#------------------------------------------------------------------------
+# tkConfig.sh refers to this by a different name
+#------------------------------------------------------------------------
+
+TK_SHARED_BUILD=${SHARED_BUILD}
+
+#--------------------------------------------------------------------
+# Perform final evaluations of variables with possible substitutions.
+#--------------------------------------------------------------------
+
+NODOT_VERSION=${VER}
+
+TK_SHARED_LIB_SUFFIX="\${NODOT_VERSION}${DLLSUFFIX}"
+TK_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
+TK_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
+
+
+ val="`cd $srcdir/..; pwd`"
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable TK_SRC_DIR" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ TK_SRC_DIR=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ TK_SRC_DIR="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ TK_SRC_DIR=$val
+ ;;
+ esac
+
+
+
+ libname=tk
+ suffix=${TK_SHARED_LIB_SUFFIX}
+
+ case "${host}" in
+ *windows32* | *mingw32* | *cygwin*)
+ eval "long_libname=\"${TCL_VENDOR_PREFIX}${libname}${suffix}\""
+ ;;
+ *)
+ eval "long_libname=\"lib${TCL_VENDOR_PREFIX}${libname}${suffix}\""
+ ;;
+ esac
+
+ eval "long_libname=${long_libname}"
+
+ # Trick to replace DBGX with TCL_DBGX
+ DBGX='${TCL_DBGX}'
+ eval "long_libname=${long_libname}"
+
+ TK_DLL_FILE=$long_libname
+
+
+ libname=tk
+ suffix=${TK_UNSHARED_LIB_SUFFIX}
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "$GCC" != yes; then
+ eval "long_libname=\"${TCL_VENDOR_PREFIX}${libname}${suffix}\""
+ else
+ eval "long_libname=\"lib${TCL_VENDOR_PREFIX}${libname}${suffix}\""
+ fi
+ ;;
+ *)
+ eval "long_libname=\"lib${TCL_VENDOR_PREFIX}${libname}${suffix}\""
+ ;;
+ esac
+
+ eval "long_libname=${long_libname}"
+
+ # Trick to replace DBGX with TCL_DBGX
+ DBGX='${TCL_DBGX}'
+ eval "long_libname=${long_libname}"
+
+ TK_LIB_FILE=$long_libname
+
+
+ libname=tkstub
+ suffix=${TK_UNSHARED_LIB_SUFFIX}
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "$GCC" != yes; then
+ eval "long_libname=\"${TCL_VENDOR_PREFIX}${libname}${suffix}\""
+ else
+ eval "long_libname=\"lib${TCL_VENDOR_PREFIX}${libname}${suffix}\""
+ fi
+ ;;
+ *)
+ eval "long_libname=\"lib${TCL_VENDOR_PREFIX}${libname}${suffix}\""
+ ;;
+ esac
+
+ eval "long_libname=${long_libname}"
+
+ # Trick to replace DBGX with TCL_DBGX
+ DBGX='${TCL_DBGX}'
+ eval "long_libname=${long_libname}"
+
+ TK_STUB_LIB_FILE=$long_libname
+
+
+if test "$GCC" = "yes"; then
+ GNU_TK_LIB_FILE=${TK_LIB_FILE}
+ MSVC_TK_LIB_FILE=
+else
+ GNU_TK_LIB_FILE=
+ MSVC_TK_LIB_FILE=${TK_LIB_FILE}
fi
-if test ! -f $TCL_BIN_DIR/tclConfig.sh; then
- { echo "configure: error: There's no tclConfig.sh in $TCL_BIN_DIR; perhaps you didn't specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?" 1>&2; exit 1; }
+
+
+ libname=tkstub
+ version=${TK_VERSION}
+
+ if test "$TCL_LIB_SUFFIX" = "" ; then
+ { echo "configure: error: The TCL_LIB_SUFFIX variable is not defined" 1>&2; exit 1; }
+ fi
+
+ # If the . character is not allowed in lib name, remove it from version
+ if test "${TCL_LIB_VERSIONS_OK}" != "ok"; then
+ version=`echo $version | tr -d .`
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "$GCC" != yes; then
+ eval "short_libname=\"${TCL_VENDOR_PREFIX}${libname}${version}${TCL_LIB_SUFFIX}\""
+ else
+ short_libname="-l${TCL_VENDOR_PREFIX}${libname}${version}${TCL_DBGX}"
+ fi
+ ;;
+ *)
+ short_libname="-l${TCL_VENDOR_PREFIX}${libname}${version}\${TCL_DBGX}"
+ ;;
+ esac
+
+ TK_STUB_LIB_FLAG=$short_libname
+
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "$GCC" != yes; then
+
+ val="`pwd`/${TK_STUB_LIB_FLAG}"
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable TK_BUILD_STUB_LIB_SPEC" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ TK_BUILD_STUB_LIB_SPEC=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ TK_BUILD_STUB_LIB_SPEC="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ TK_BUILD_STUB_LIB_SPEC=$val
+ ;;
+ esac
+
+ else
+
+ val=`pwd`
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable dirname" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ dirname=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ dirname="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ dirname=$val
+ ;;
+ esac
+
+ TK_BUILD_STUB_LIB_SPEC="-L${dirname} ${TK_STUB_LIB_FLAG}"
+ fi
+ ;;
+ *)
+ TK_BUILD_STUB_LIB_SPEC="-L`pwd` ${TK_STUB_LIB_FLAG}"
+ ;;
+ esac
+
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "$GCC" != yes; then
+
+ val="${exec_prefix}/lib/${TK_STUB_LIB_FLAG}"
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable TK_STUB_LIB_SPEC" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ TK_STUB_LIB_SPEC=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ TK_STUB_LIB_SPEC="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ TK_STUB_LIB_SPEC=$val
+ ;;
+ esac
+
+ else
+
+ val=${exec_prefix}/lib
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable dirname" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ dirname=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ dirname="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ dirname=$val
+ ;;
+ esac
+
+ TK_STUB_LIB_SPEC="-L${dirname} ${TK_STUB_LIB_FLAG}"
+ fi
+ ;;
+ *)
+ TK_STUB_LIB_SPEC="-L${exec_prefix}/lib ${TK_STUB_LIB_FLAG}"
+ ;;
+ esac
+
+
+
+
+ val="`pwd`/${TK_STUB_LIB_FILE}"
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable TK_BUILD_STUB_LIB_PATH" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ TK_BUILD_STUB_LIB_PATH=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ TK_BUILD_STUB_LIB_PATH="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ TK_BUILD_STUB_LIB_PATH=$val
+ ;;
+ esac
+
+
+
+
+ val="${exec_prefix}/lib/${TK_STUB_LIB_FILE}"
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable TK_STUB_LIB_PATH" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ TK_STUB_LIB_PATH=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ TK_STUB_LIB_PATH="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ TK_STUB_LIB_PATH=$val
+ ;;
+ esac
+
+
+
+eval "DLLSUFFIX=${DLLSUFFIX}"
+eval "LIBPREFIX=${LIBPREFIX}"
+eval "LIBSUFFIX=${LIBSUFFIX}"
+eval "EXESUFFIX=${EXESUFFIX}"
+
+
+ libname=tk
+ version=$TK_VERSION
+
+ if test "$TCL_LIB_SUFFIX" = "" ; then
+ { echo "configure: error: The TCL_LIB_SUFFIX variable is not defined" 1>&2; exit 1; }
+ fi
+
+ # If the . character is not allowed in lib name, remove it from version
+ if test "${TCL_LIB_VERSIONS_OK}" != "ok"; then
+ version=`echo $version | tr -d .`
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "$GCC" != yes; then
+ eval "short_libname=\"${TCL_VENDOR_PREFIX}${libname}${version}${TCL_LIB_SUFFIX}\""
+ else
+ short_libname="-l${TCL_VENDOR_PREFIX}${libname}${version}${TCL_DBGX}"
+ fi
+ ;;
+ *)
+ short_libname="-l${TCL_VENDOR_PREFIX}${libname}${version}\${TCL_DBGX}"
+ ;;
+ esac
+
+ TK_LIB_FLAG=$short_libname
+
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "$GCC" != yes; then
+
+ val="`pwd`/${TK_LIB_FLAG}"
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable TK_BUILD_LIB_SPEC" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ TK_BUILD_LIB_SPEC=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ TK_BUILD_LIB_SPEC="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ TK_BUILD_LIB_SPEC=$val
+ ;;
+ esac
+
+ else
+
+ val=`pwd`
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable dirname" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ dirname=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ dirname="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ dirname=$val
+ ;;
+ esac
+
+ TK_BUILD_LIB_SPEC="-L${dirname} ${TK_LIB_FLAG}"
+ fi
+ ;;
+ *)
+ TK_BUILD_LIB_SPEC="-L`pwd` ${TK_LIB_FLAG}"
+ ;;
+ esac
+
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "$GCC" != yes; then
+
+ val="${exec_prefix}/lib/${TK_LIB_FLAG}"
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable TK_LIB_SPEC" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ TK_LIB_SPEC=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ TK_LIB_SPEC="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ TK_LIB_SPEC=$val
+ ;;
+ esac
+
+ else
+
+ val=${exec_prefix}/lib
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable dirname" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ dirname=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ dirname="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ dirname=$val
+ ;;
+ esac
+
+ TK_LIB_SPEC="-L${dirname} ${TK_LIB_FLAG}"
+ fi
+ ;;
+ *)
+ TK_LIB_SPEC="-L${exec_prefix}/lib ${TK_LIB_FLAG}"
+ ;;
+ esac
+
+
+
+ val="`pwd`/${TK_LIB_FILE}"
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable TK_LIB_FULL_PATH" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ TK_LIB_FULL_PATH=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ TK_LIB_FULL_PATH="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ TK_LIB_FULL_PATH=$val
+ ;;
+ esac
+
+
+
+if test "$SHARED_BUILD" = 0 -o $TCL_NEEDS_EXP_FILE = 0; then
+ WISH_RES=wish_static.${RES}
+ TK_RES=
+else
+ WISH_RES=wish_static.${RES}
+ TK_RES=tk_dll.${RES}
fi
+TK_SHARED_BUILD=${SHARED_BUILD}
+
+CFG_TK_SHARED_LIB_SUFFIX=${TK_SHARED_LIB_SUFFIX}
+CFG_TK_UNSHARED_LIB_SUFFIX=${TK_UNSHARED_LIB_SUFFIX}
+CFG_TK_EXPORT_FILE_SUFFIX=${TK_EXPORT_FILE_SUFFIX}
+
+# Add X include path, it must be in a format
+# like -I"C:/Dir" and not -I"C:\Dir" or VC++ will puke.
+
+ val=$srcdir/../xlib
+
+ if test "$val" = "" ; then
+ { echo "configure: error: Empty value for variable XINCLUDES" 1>&2; exit 1; }
+ fi
+
+ case "${host}" in
+ *windows32* | *mingw32*)
+ if test "${CYGPATH}" = ""; then
+ { echo "configure: error: CYGPATH variable is not defined." 1>&2; exit 1; }
+ elif test "${CYGPATH}" = "echo"; then
+ # No cygpath when cross compiling
+ XINCLUDES=$val
+ else
+ # store literal argument text in a variable
+ val=$val
+ # Convert Cygwin to Windows path (/tmp/foo -> C:\Tmp\foo)
+ val="`${CYGPATH} $val`"
+ # Convert path like C:\Tmp\foo to C:/Tmp/foo
+ XINCLUDES="`echo $val | sed -e s#\\\\\\\\#/#g`"
+ fi
+ ;;
+ *)
+ # Default to a no-op under Unix or Cygwin gcc
+ XINCLUDES=$val
+ ;;
+ esac
+
+XINCLUDES="-I\"${XINCLUDES}\""
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-file=$TCL_BIN_DIR/tclConfig.sh
-. $file
-SHLIB_CFLAGS=$TCL_SHLIB_CFLAGS
-SHLIB_LD=$TCL_SHLIB_LD
-SHLIB_LD_LIBS=$TCL_SHLIB_LD_LIBS
-SHLIB_SUFFIX=$TCL_SHLIB_SUFFIX
-SHLIB_VERSION=$TCL_SHLIB_VERSION
-DL_LIBS=$TCL_DL_LIBS
-LD_FLAGS=$TCL_LD_FLAGS
-TK_LD_SEARCH_FLAGS=$TCL_LD_SEARCH_FLAGS
-LIBOBJS=
-TK_VERSION=8.0
-TK_MAJOR_VERSION=8
-TK_MINOR_VERSION=0
-TK_PATCH_LEVEL=p2
-VERSION=${TK_VERSION}
-MATH_LIBS=-lm
-LIBOBJS=
-TK_SHLIB_CFLAGS=""
-eval "TK_LIB_FILE=libtk${TCL_UNSHARED_LIB_SUFFIX}"
-TK_UNSHARED_LIB_FILE="$TK_LIB_FILE"
-TK_SRC_DIR=`cd $srcdir/..; pwd`
-XINCLUDES="-I`cd $srcdir/../xlib; pwd`"
-XLIBSW=
-TK_BUILD_INCLUDES="-I`cd $srcdir/../generic; pwd` -I`cd $srcdir/../xlib; pwd`"
-TK_BUILD_LIB_SPEC="-L`pwd` -ltk`echo ${VERSION} | tr -d .`"
-TK_LIB_SPEC="-L${exec_prefix}/lib -ltk`echo ${VERSION} | tr -d .`"
@@ -991,7 +2421,7 @@ EOF
# 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.
(set) 2>&1 |
- case `(ac_space=' '; set) 2>&1 | grep ac_space` in
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
*ac_space=\ *)
# `set' does not quote correctly, so add quotes (double-quote substitution
# turns \\\\ into \\, and sed turns \\ into \).
@@ -1070,7 +2500,7 @@ do
echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
-version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.12.2"
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
exit 0 ;;
-help | --help | --hel | --he | --h)
echo "\$ac_cs_usage"; exit 0 ;;
@@ -1079,9 +2509,8 @@ do
done
ac_given_srcdir=$srcdir
-ac_given_INSTALL="$INSTALL"
-trap 'rm -fr `echo "Makefile ../unix/tkConfig.sh" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+trap 'rm -fr `echo "Makefile tkConfig.sh" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF
@@ -1094,6 +2523,7 @@ s%@SHELL@%$SHELL%g
s%@CFLAGS@%$CFLAGS%g
s%@CPPFLAGS@%$CPPFLAGS%g
s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
s%@DEFS@%$DEFS%g
s%@LDFLAGS@%$LDFLAGS%g
s%@LIBS@%$LIBS%g
@@ -1112,38 +2542,100 @@ s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g
+s%@CC@%$CC%g
s%@host@%$host%g
s%@host_alias@%$host_alias%g
s%@host_cpu@%$host_cpu%g
s%@host_vendor@%$host_vendor%g
s%@host_os@%$host_os%g
-s%@CC@%$CC%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@AR@%$AR%g
+s%@RANLIB@%$RANLIB%g
+s%@RC@%$RC%g
+s%@SET_MAKE@%$SET_MAKE%g
s%@OBJEXT@%$OBJEXT%g
-s%@NM@%$NM%g
-s%@AS@%$AS%g
-s%@LD@%$LD%g
-s%@DLLTOOL@%$DLLTOOL%g
-s%@WINDRES@%$WINDRES%g
-s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
-s%@INSTALL_DATA@%$INSTALL_DATA%g
-s%@TCL_ALLOC_OBJ@%$TCL_ALLOC_OBJ%g
-s%@DLL_LDFLAGS@%$DLL_LDFLAGS%g
-s%@DLL_LDLIBS@%$DLL_LDLIBS%g
-s%@LIBOBJS@%$LIBOBJS%g
-s%@DL_LIBS@%$DL_LIBS%g
-s%@LD_FLAGS@%$LD_FLAGS%g
-s%@MATH_LIBS@%$MATH_LIBS%g
-s%@TK_BUILD_INCLUDES@%$TK_BUILD_INCLUDES%g
-s%@TK_BUILD_LIB_SPEC@%$TK_BUILD_LIB_SPEC%g
-s%@TK_LIB_FILE@%$TK_LIB_FILE%g
-s%@TK_LIB_SPEC@%$TK_LIB_SPEC%g
+s%@EXEEXT@%$EXEEXT%g
+s%@CYGPATH@%$CYGPATH%g
+s%@CPP@%$CPP%g
+s%@MAN2TCLFLAGS@%$MAN2TCLFLAGS%g
+s%@TCL_BIN_DIR@%$TCL_BIN_DIR%g
+s%@TCL_SRC_DIR@%$TCL_SRC_DIR%g
+s%@TCL_LIB_FILE@%$TCL_LIB_FILE%g
+s%@TK_VERSION@%$TK_VERSION%g
s%@TK_MAJOR_VERSION@%$TK_MAJOR_VERSION%g
s%@TK_MINOR_VERSION@%$TK_MINOR_VERSION%g
s%@TK_PATCH_LEVEL@%$TK_PATCH_LEVEL%g
+s%@TK_DBGX@%$TK_DBGX%g
+s%@TK_LIB_FILE@%$TK_LIB_FILE%g
+s%@GNU_TK_LIB_FILE@%$GNU_TK_LIB_FILE%g
+s%@MSVC_TK_LIB_FILE@%$MSVC_TK_LIB_FILE%g
+s%@TK_DLL_FILE@%$TK_DLL_FILE%g
+s%@TK_LIB_FLAG@%$TK_LIB_FLAG%g
+s%@TK_STUB_LIB_FILE@%$TK_STUB_LIB_FILE%g
+s%@TK_STUB_LIB_FLAG@%$TK_STUB_LIB_FLAG%g
+s%@TK_STUB_LIB_SPEC@%$TK_STUB_LIB_SPEC%g
+s%@TK_STUB_LIB_PATH@%$TK_STUB_LIB_PATH%g
+s%@TK_BUILD_STUB_LIB_SPEC@%$TK_BUILD_STUB_LIB_SPEC%g
+s%@TK_BUILD_STUB_LIB_PATH@%$TK_BUILD_STUB_LIB_PATH%g
s%@TK_SRC_DIR@%$TK_SRC_DIR%g
-s%@TK_VERSION@%$TK_VERSION%g
+s%@TK_BIN_DIR@%$TK_BIN_DIR%g
+s%@TK_BUILD_LIB_SPEC@%$TK_BUILD_LIB_SPEC%g
+s%@TK_LIB_SPEC@%$TK_LIB_SPEC%g
+s%@TK_LIB_FULL_PATH@%$TK_LIB_FULL_PATH%g
+s%@TK_SHARED_BUILD@%$TK_SHARED_BUILD%g
+s%@WISH_RES@%$WISH_RES%g
+s%@TK_RES@%$TK_RES%g
+s%@TCL_VERSION@%$TCL_VERSION%g
+s%@TCL_MAJOR_VERSION@%$TCL_MAJOR_VERSION%g
+s%@TCL_MINOR_VERSION@%$TCL_MINOR_VERSION%g
+s%@TCL_PATCH_LEVEL@%$TCL_PATCH_LEVEL%g
+s%@TCL_DLL_FILE@%$TCL_DLL_FILE%g
+s%@TCL_STUB_LIB_FILE@%$TCL_STUB_LIB_FILE%g
+s%@TCL_STUB_LIB_FLAG@%$TCL_STUB_LIB_FLAG%g
+s%@TCL_BUILD_LIB_SPEC@%$TCL_BUILD_LIB_SPEC%g
+s%@TCL_BUILD_STUB_LIB_SPEC@%$TCL_BUILD_STUB_LIB_SPEC%g
+s%@TCL_DBGX@%$TCL_DBGX%g
+s%@CFG_TK_SHARED_LIB_SUFFIX@%$CFG_TK_SHARED_LIB_SUFFIX%g
+s%@CFG_TK_UNSHARED_LIB_SUFFIX@%$CFG_TK_UNSHARED_LIB_SUFFIX%g
+s%@CFG_TK_EXPORT_FILE_SUFFIX@%$CFG_TK_EXPORT_FILE_SUFFIX%g
+s%@DEPARG@%$DEPARG%g
+s%@CFLAGS_DEFAULT@%$CFLAGS_DEFAULT%g
+s%@CFLAGS_DEBUG@%$CFLAGS_DEBUG%g
+s%@CFLAGS_OPTIMIZE@%$CFLAGS_OPTIMIZE%g
+s%@CFLAGS_WARNING@%$CFLAGS_WARNING%g
+s%@EXTRA_CFLAGS@%$EXTRA_CFLAGS%g
+s%@STLIB_LD@%$STLIB_LD%g
+s%@SHLIB_LD@%$SHLIB_LD%g
+s%@SHLIB_LD_LIBS@%$SHLIB_LD_LIBS%g
+s%@SHLIB_CFLAGS@%$SHLIB_CFLAGS%g
+s%@SHLIB_SUFFIX@%$SHLIB_SUFFIX%g
+s%@CC_OBJNAME@%$CC_OBJNAME%g
+s%@CC_EXENAME@%$CC_EXENAME%g
+s%@LDFLAGS_DEFAULT@%$LDFLAGS_DEFAULT%g
+s%@LDFLAGS_DEBUG@%$LDFLAGS_DEBUG%g
+s%@LDFLAGS_OPTIMIZE@%$LDFLAGS_OPTIMIZE%g
+s%@LDFLAGS_CONSOLE@%$LDFLAGS_CONSOLE%g
+s%@LDFLAGS_WINDOW@%$LDFLAGS_WINDOW%g
+s%@RC_OUT@%$RC_OUT%g
+s%@RC_TYPE@%$RC_TYPE%g
+s%@RC_INCLUDE@%$RC_INCLUDE%g
+s%@RES@%$RES%g
+s%@LIBS_GUI@%$LIBS_GUI%g
+s%@DLLSUFFIX@%$DLLSUFFIX%g
+s%@LIBPREFIX@%$LIBPREFIX%g
+s%@LIBSUFFIX@%$LIBSUFFIX%g
+s%@EXESUFFIX@%$EXESUFFIX%g
+s%@LIBRARIES@%$LIBRARIES%g
+s%@MAKE_LIB@%$MAKE_LIB%g
+s%@POST_MAKE_LIB@%$POST_MAKE_LIB%g
+s%@MAKE_DLL@%$MAKE_DLL%g
+s%@MAKE_EXE@%$MAKE_EXE%g
+s%@TK_XINCLUDES@%$TK_XINCLUDES%g
s%@XINCLUDES@%$XINCLUDES%g
-s%@XLIBSW@%$XLIBSW%g
CEOF
EOF
@@ -1185,7 +2677,7 @@ EOF
cat >> $CONFIG_STATUS <<EOF
-CONFIG_FILES=\${CONFIG_FILES-"Makefile ../unix/tkConfig.sh"}
+CONFIG_FILES=\${CONFIG_FILES-"Makefile tkConfig.sh"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
@@ -1220,10 +2712,6 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
top_srcdir="$ac_dots$ac_given_srcdir" ;;
esac
- case "$ac_given_INSTALL" in
- [/$]*) INSTALL="$ac_given_INSTALL" ;;
- *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
- esac
echo creating "$ac_file"
rm -f "$ac_file"
@@ -1239,7 +2727,6 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
s%@configure_input@%$configure_input%g
s%@srcdir@%$srcdir%g
s%@top_srcdir@%$top_srcdir%g
-s%@INSTALL@%$INSTALL%g
" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
fi; done
rm -f conftest.s*
diff --git a/tk/win/configure.in b/tk/win/configure.in
index d9c6949ef9e..51be87e08dd 100755
--- a/tk/win/configure.in
+++ b/tk/win/configure.in
@@ -1,13 +1,17 @@
-nl The file is CYGNUS LOCAL. It is used for cygwin.
-
-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.
-
-AC_PREREQ(2.5)
+# This file is an input file used by the GNU "autoconf" program to
+# generate the file "configure", which is run during Tk installation
+# to configure the system for the local environment.
+#
+# RCS: @(#) $Id$
AC_INIT(../generic/tk.h)
+TK_VERSION=8.3
+TK_MAJOR_VERSION=8
+TK_MINOR_VERSION=3
+TK_PATCH_LEVEL=".2"
+VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION
+
if test "${prefix}" = "NONE"; then
prefix=/usr/local
fi
@@ -15,96 +19,226 @@ if test "${exec_prefix}" = "NONE"; then
exec_prefix=$prefix
fi
-AC_CANONICAL_HOST
+#------------------------------------------------------------------------
+# Standard compiler checks
+#------------------------------------------------------------------------
AC_PROG_CC
+
+AC_CHECK_TOOL(AR, ar, :)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(RC, windres, :)
+
+#--------------------------------------------------------------------
+# Checks to see if the make progeam sets the $MAKE variable.
+#--------------------------------------------------------------------
+
+AC_PROG_MAKE_SET
+
+#--------------------------------------------------------------------
+# These two macros perform additinal compiler test.
+#--------------------------------------------------------------------
+
+AC_CYGWIN
+
+#--------------------------------------------------------------------
+# Determines the correct binary file extension (.o, .obj, .exe etc.)
+#--------------------------------------------------------------------
+
AC_OBJEXT
-NM=${NM-nm}
-AC_SUBST(NM)
-AS=${AS-as}
-AC_SUBST(AS)
-LD=${LD-ld}
-AC_SUBST(LD)
-DLLTOOL=${DLLTOOL-dlltool}
-AC_SUBST(DLLTOOL)
-WINDRES=${WINDRES-windres}
-AC_SUBST(WINDRES)
-AC_PROG_INSTALL
-
-# needed for the subtle differences between cygwin and mingw32
-case "${host}" in
-*-*-cygwin*)
- DLL_LDLIBS=-lcygwin
- DLL_LDFLAGS='-nostartfiles -Wl,--dll'
- ;;
-*-*-mingw32*)
- DLL_LDLIBS=
- DLL_LDFLAGS='-mdll'
- ;;
-esac
-
-AC_SUBST(TCL_ALLOC_OBJ)
-AC_SUBST(DLL_LDFLAGS)
-AC_SUBST(DLL_LDLIBS)
-
-# The following stuff is just for tkConfig.sh, not for Makefile.
-
-AC_ARG_WITH(tcl, [ --with-tcl=DIR use Tcl 8.0 binaries from DIR],
- TCL_BIN_DIR=$withval, TCL_BIN_DIR=`cd ../../tcl/unix; pwd`)
-if test ! -d $TCL_BIN_DIR; then
- AC_MSG_ERROR(Tcl directory $TCL_BIN_DIR doesn't exist)
-fi
-if test ! -f $TCL_BIN_DIR/tclConfig.sh; then
- AC_MSG_ERROR(There's no tclConfig.sh in $TCL_BIN_DIR; perhaps you didn't specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?)
-fi
+AC_EXEEXT
-file=$TCL_BIN_DIR/tclConfig.sh
-. $file
-SHLIB_CFLAGS=$TCL_SHLIB_CFLAGS
-SHLIB_LD=$TCL_SHLIB_LD
-SHLIB_LD_LIBS=$TCL_SHLIB_LD_LIBS
-SHLIB_SUFFIX=$TCL_SHLIB_SUFFIX
-SHLIB_VERSION=$TCL_SHLIB_VERSION
-DL_LIBS=$TCL_DL_LIBS
-LD_FLAGS=$TCL_LD_FLAGS
-TK_LD_SEARCH_FLAGS=$TCL_LD_SEARCH_FLAGS
-
-LIBOBJS=
-AC_SUBST(LIBOBJS)
-TK_VERSION=8.0
-TK_MAJOR_VERSION=8
-TK_MINOR_VERSION=0
-TK_PATCH_LEVEL=p2
-VERSION=${TK_VERSION}
+#--------------------------------------------------------------------
+# Check whether --enable-threads or --disable-threads was given.
+#--------------------------------------------------------------------
-MATH_LIBS=-lm
-LIBOBJS=
+SC_ENABLE_THREADS
-TK_SHLIB_CFLAGS=""
-eval "TK_LIB_FILE=libtk${TCL_UNSHARED_LIB_SUFFIX}"
+#--------------------------------------------------------------------
+# The statements below define a collection of symbols related to
+# building libtk as a shared library instead of a static library.
+#--------------------------------------------------------------------
-TK_UNSHARED_LIB_FILE="$TK_LIB_FILE"
-TK_SRC_DIR=`cd $srcdir/..; pwd`
+SC_ENABLE_SHARED
-XINCLUDES="-I`cd $srcdir/../xlib; pwd`"
-XLIBSW=
-TK_BUILD_INCLUDES="-I`cd $srcdir/../generic; pwd` -I`cd $srcdir/../xlib; pwd`"
-TK_BUILD_LIB_SPEC="-L`pwd` -ltk`echo ${VERSION} | tr -d .`"
-TK_LIB_SPEC="-L${exec_prefix}/lib -ltk`echo ${VERSION} | tr -d .`"
+#--------------------------------------------------------------------
+# The statements below define a collection of compile flags. This
+# macro depends on the value of SHARED_BUILD, and should be called
+# after SC_ENABLE_SHARED checks the configure switches.
+#--------------------------------------------------------------------
-AC_SUBST(DL_LIBS)
-AC_SUBST(LD_FLAGS)
-AC_SUBST(MATH_LIBS)
-AC_SUBST(TK_BUILD_INCLUDES)
-AC_SUBST(TK_BUILD_LIB_SPEC)
-AC_SUBST(TK_LIB_FILE)
-AC_SUBST(TK_LIB_SPEC)
+SC_CONFIG_CFLAGS
+
+#--------------------------------------------------------------------
+# man2tcl needs this so that it can use errno.h
+#--------------------------------------------------------------------
+
+AC_CHECK_HEADER(errno.h, , MAN2TCLFLAGS="-DNO_ERRNO_H")
+AC_SUBST(MAN2TCLFLAGS)
+
+#--------------------------------------------------------------------
+# Set the default compiler switches based on the --enable-symbols
+# option. This macro depends on C flags, and should be called
+# after SC_CONFIG_CFLAGS macro is called.
+#--------------------------------------------------------------------
+
+SC_ENABLE_SYMBOLS
+
+TK_DBGX=${DBGX}
+
+#--------------------------------------------------------------------
+# Locate and source the tclConfig.sh file.
+#--------------------------------------------------------------------
+
+SC_PATH_TCLCONFIG($TK_PATCH_LEVEL)
+SC_LOAD_TCLCONFIG
+
+#------------------------------------------------------------------------
+# tkConfig.sh refers to this by a different name
+#------------------------------------------------------------------------
+
+TK_SHARED_BUILD=${SHARED_BUILD}
+
+#--------------------------------------------------------------------
+# Perform final evaluations of variables with possible substitutions.
+#--------------------------------------------------------------------
+
+NODOT_VERSION=${VER}
+
+TK_SHARED_LIB_SUFFIX="\${NODOT_VERSION}${DLLSUFFIX}"
+TK_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
+TK_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
+
+TCL_TOOL_PATH(TK_SRC_DIR, "`cd $srcdir/..; pwd`")
+
+TCL_TOOL_SHARED_LIB_LONGNAME(TK_DLL_FILE, tk, ${TK_SHARED_LIB_SUFFIX})
+TCL_TOOL_STATIC_LIB_LONGNAME(TK_LIB_FILE, tk, ${TK_UNSHARED_LIB_SUFFIX})
+TCL_TOOL_STATIC_LIB_LONGNAME(TK_STUB_LIB_FILE, tkstub, ${TK_UNSHARED_LIB_SUFFIX})
+
+if test "$GCC" = "yes"; then
+ GNU_TK_LIB_FILE=${TK_LIB_FILE}
+ MSVC_TK_LIB_FILE=
+else
+ GNU_TK_LIB_FILE=
+ MSVC_TK_LIB_FILE=${TK_LIB_FILE}
+fi
+
+TCL_TOOL_LIB_SHORTNAME(TK_STUB_LIB_FLAG, tkstub, ${TK_VERSION})
+TCL_TOOL_LIB_SPEC(TK_BUILD_STUB_LIB_SPEC, `pwd`, ${TK_STUB_LIB_FLAG})
+TCL_TOOL_LIB_SPEC(TK_STUB_LIB_SPEC, ${exec_prefix}/lib, ${TK_STUB_LIB_FLAG})
+
+TCL_TOOL_LIB_PATH(TK_BUILD_STUB_LIB_PATH, `pwd`, ${TK_STUB_LIB_FILE})
+TCL_TOOL_LIB_PATH(TK_STUB_LIB_PATH, ${exec_prefix}/lib, ${TK_STUB_LIB_FILE})
+
+eval "DLLSUFFIX=${DLLSUFFIX}"
+eval "LIBPREFIX=${LIBPREFIX}"
+eval "LIBSUFFIX=${LIBSUFFIX}"
+eval "EXESUFFIX=${EXESUFFIX}"
+
+TCL_TOOL_LIB_SHORTNAME(TK_LIB_FLAG, tk, $TK_VERSION)
+TCL_TOOL_LIB_SPEC(TK_BUILD_LIB_SPEC, `pwd`, ${TK_LIB_FLAG})
+TCL_TOOL_LIB_SPEC(TK_LIB_SPEC, ${exec_prefix}/lib, ${TK_LIB_FLAG})
+TCL_TOOL_LIB_PATH(TK_LIB_FULL_PATH, `pwd`, ${TK_LIB_FILE})
+
+if test "$SHARED_BUILD" = 0 -o $TCL_NEEDS_EXP_FILE = 0; then
+ WISH_RES=wish_static.${RES}
+ TK_RES=
+else
+ WISH_RES=wish_static.${RES}
+ TK_RES=tk_dll.${RES}
+fi
+TK_SHARED_BUILD=${SHARED_BUILD}
+
+CFG_TK_SHARED_LIB_SUFFIX=${TK_SHARED_LIB_SUFFIX}
+CFG_TK_UNSHARED_LIB_SUFFIX=${TK_UNSHARED_LIB_SUFFIX}
+CFG_TK_EXPORT_FILE_SUFFIX=${TK_EXPORT_FILE_SUFFIX}
+
+# Add X include path, it must be in a format
+# like -I"C:/Dir" and not -I"C:\Dir" or VC++ will puke.
+TCL_TOOL_PATH(XINCLUDES, $srcdir/../xlib)
+XINCLUDES="-I\"${XINCLUDES}\""
+
+AC_SUBST(TK_VERSION)
AC_SUBST(TK_MAJOR_VERSION)
AC_SUBST(TK_MINOR_VERSION)
AC_SUBST(TK_PATCH_LEVEL)
+AC_SUBST(TK_DBGX)
+AC_SUBST(TK_LIB_FILE)
+AC_SUBST(GNU_TK_LIB_FILE)
+AC_SUBST(MSVC_TK_LIB_FILE)
+AC_SUBST(TK_DLL_FILE)
+AC_SUBST(TK_LIB_FLAG)
+AC_SUBST(TK_STUB_LIB_FILE)
+AC_SUBST(TK_STUB_LIB_FLAG)
+AC_SUBST(TK_STUB_LIB_SPEC)
+AC_SUBST(TK_STUB_LIB_PATH)
+AC_SUBST(TK_BUILD_STUB_LIB_SPEC)
+AC_SUBST(TK_BUILD_STUB_LIB_PATH)
AC_SUBST(TK_SRC_DIR)
-AC_SUBST(TK_VERSION)
+AC_SUBST(TK_BIN_DIR)
+AC_SUBST(TK_BUILD_LIB_SPEC)
+AC_SUBST(TK_LIB_SPEC)
+AC_SUBST(TK_LIB_FULL_PATH)
+AC_SUBST(TK_SHARED_BUILD)
+AC_SUBST(WISH_RES)
+AC_SUBST(TK_RES)
+
+AC_SUBST(TCL_VERSION)
+AC_SUBST(TCL_MAJOR_VERSION)
+AC_SUBST(TCL_MINOR_VERSION)
+AC_SUBST(TCL_PATCH_LEVEL)
+AC_SUBST(TCL_LIB_FILE)
+AC_SUBST(TCL_DLL_FILE)
+AC_SUBST(TCL_STUB_LIB_FILE)
+AC_SUBST(TCL_STUB_LIB_FLAG)
+AC_SUBST(TCL_BUILD_LIB_SPEC)
+AC_SUBST(TCL_BUILD_STUB_LIB_SPEC)
+AC_SUBST(TCL_SRC_DIR)
+AC_SUBST(TCL_BIN_DIR)
+AC_SUBST(TCL_DBGX)
+AC_SUBST(CFG_TK_SHARED_LIB_SUFFIX)
+AC_SUBST(CFG_TK_UNSHARED_LIB_SUFFIX)
+AC_SUBST(CFG_TK_EXPORT_FILE_SUFFIX)
+AC_SUBST(TK_SHARED_BUILD)
+
+AC_SUBST(CYGPATH)
+AC_SUBST(DEPARG)
+AC_SUBST(CFLAGS_DEFAULT)
+AC_SUBST(CFLAGS_DEBUG)
+AC_SUBST(CFLAGS_OPTIMIZE)
+AC_SUBST(CFLAGS_WARNING)
+AC_SUBST(EXTRA_CFLAGS)
+AC_SUBST(STLIB_LD)
+AC_SUBST(SHLIB_LD)
+AC_SUBST(SHLIB_LD_LIBS)
+AC_SUBST(SHLIB_CFLAGS)
+AC_SUBST(SHLIB_SUFFIX)
+AC_SUBST(CC_OBJNAME)
+AC_SUBST(CC_EXENAME)
+AC_SUBST(LDFLAGS_DEFAULT)
+AC_SUBST(LDFLAGS_DEBUG)
+AC_SUBST(LDFLAGS_OPTIMIZE)
+AC_SUBST(LDFLAGS_CONSOLE)
+AC_SUBST(LDFLAGS_WINDOW)
+AC_SUBST(AR)
+AC_SUBST(RANLIB)
+AC_SUBST(RC)
+AC_SUBST(RC_OUT)
+AC_SUBST(RC_TYPE)
+AC_SUBST(RC_INCLUDE)
+AC_SUBST(RES)
+AC_SUBST(LIBS)
+AC_SUBST(LIBS_GUI)
+AC_SUBST(DLLSUFFIX)
+AC_SUBST(LIBPREFIX)
+AC_SUBST(LIBSUFFIX)
+AC_SUBST(EXESUFFIX)
+AC_SUBST(LIBRARIES)
+AC_SUBST(MAKE_LIB)
+AC_SUBST(POST_MAKE_LIB)
+AC_SUBST(MAKE_DLL)
+AC_SUBST(MAKE_EXE)
+AC_SUBST(TK_XINCLUDES)
AC_SUBST(XINCLUDES)
-AC_SUBST(XLIBSW)
-AC_OUTPUT(Makefile ../unix/tkConfig.sh)
+AC_OUTPUT(Makefile tkConfig.sh)
diff --git a/tk/win/makefile.vc b/tk/win/makefile.vc
index 62a43056aa2..b74f01cb95e 100644
--- a/tk/win/makefile.vc
+++ b/tk/win/makefile.vc
@@ -3,8 +3,8 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# Copyright (c) 1995-1996 Sun Microsystems, Inc.
-# SCCS: @(#) makefile.vc 1.12 98/08/12 18:41:59
+# Copyright (c) 1995-1997 Sun Microsystems, Inc.
+# RCS: @(#) $Id$
# Does not depend on the presence of any environment variables in
# order to compile tcl; all needed information is derived from
@@ -26,13 +26,23 @@
#
ROOT = ..
-TOOLS32 = c:\progra~1\devstudio\vc
-TOOLS32_rc = c:\progra~1\devstudio\sharedide
-TCLDIR = ..\..\tcl8.0
+TCLDIR = ..\..\tcl8.3
+INSTALLDIR = c:\progra~1\tcl
# Set this to the appropriate value of /MACHINE: for your platform
MACHINE = IX86
+!IF "$(MACHINE)" == "IA64"
+TOOLS32 = c:\ia64sdk17
+TOOLS32_rc = c:\ia64sdk17
+!ELSE
+TOOLS32 = c:\Progra~1\devstudio\vc
+TOOLS32_rc = c:\Progra~1\devstudio\sharedide
+!ENDIF
+
+# Uncomment the following line to compile with thread support
+#THREADDEFINES = -DTCL_THREADS=1
+
# Set NODEBUG to 0 to compile with symbols
NODEBUG = 1
@@ -46,7 +56,12 @@ NODEBUG = 1
TCLNAMEPREFIX = tcl
TKNAMEPREFIX = tk
WISHNAMEPREFIX = wish
-VERSION = 80
+VERSION = 83
+DOTVERSION = 8.3
+
+TCLSTUBPREFIX = $(TCLNAMEPREFIX)stub
+TKSTUBPREFIX = $(TKNAMEPREFIX)stub
+
BINROOT = .
!IF "$(NODEBUG)" == "1"
@@ -62,17 +77,26 @@ OUTDIR = $(TMPDIR)
TCLLIB = $(TCLNAMEPREFIX)$(VERSION)$(DBGX).lib
TCLPLUGINLIB = $(TCLNAMEPREFIX)$(VERSION)p.lib
+TCLSTUBLIB = $(TCLSTUBPREFIX)$(VERSION)$(DBGX).lib
TKDLLNAME = $(TKNAMEPREFIX)$(VERSION)$(DBGX).dll
TKDLL = $(OUTDIR)\$(TKDLLNAME)
TKLIB = $(OUTDIR)\$(TKNAMEPREFIX)$(VERSION)$(DBGX).lib
+TKSTUBLIBNAME = $(TKSTUBPREFIX)$(VERSION)$(DBGX).lib
+TKSTUBLIB = $(OUTDIR)\$(TKSTUBLIBNAME)
TKPLUGINDLLNAME = $(TKNAMEPREFIX)$(VERSION)p$(DBG).dll
TKPLUGINDLL = $(OUTDIR)\$(TKPLUGINDLLNAME)
TKPLUGINLIB = $(OUTDIR)\$(TKNAMEPREFIX)$(VERSION)p$(DBGX).lib
WISH = $(OUTDIR)\$(WISHNAMEPREFIX)$(VERSION)$(DBGX).exe
+WISHC = $(OUTDIR)\$(WISHNAMEPREFIX)c$(VERSION)$(DBGX).exe
WISHP = $(OUTDIR)\$(WISHNAMEPREFIX)p$(VERSION)$(DBGX).exe
TKTEST = $(OUTDIR)\$(TKNAMEPREFIX)test.exe
-DUMPEXTS = $(TMPDIR)\dumpexts.exe
+CAT32 = $(TMPDIR)\cat32.exe
+
+BIN_INSTALL_DIR = $(INSTALLDIR)\bin
+INCLUDE_INSTALL_DIR = $(INSTALLDIR)\include
+LIB_INSTALL_DIR = $(INSTALLDIR)\lib
+SCRIPT_INSTALL_DIR = $(LIB_INSTALL_DIR)\tk$(DOTVERSION)
WISHOBJS = \
$(TMPDIR)\winMain.obj
@@ -80,7 +104,9 @@ WISHOBJS = \
TKTESTOBJS = \
$(TMPDIR)\tkTest.obj \
$(TMPDIR)\tkSquare.obj \
- $(TMPDIR)\testMain.obj
+ $(TMPDIR)\testMain.obj \
+ $(TMPDIR)\tkWinTest.obj \
+ $(TCLLIBDIR)\tclThreadTest.obj
XLIBOBJS = \
$(TMPDIR)\xcolors.obj \
@@ -99,6 +125,7 @@ TKOBJS = \
$(TMPDIR)\tkWinButton.obj \
$(TMPDIR)\tkWinClipboard.obj \
$(TMPDIR)\tkWinColor.obj \
+ $(TMPDIR)\tkWinConfig.obj \
$(TMPDIR)\tkWinCursor.obj \
$(TMPDIR)\tkWinDialog.obj \
$(TMPDIR)\tkWinDraw.obj \
@@ -163,6 +190,8 @@ TKOBJS = \
$(TMPDIR)\tkMenubutton.obj \
$(TMPDIR)\tkMenuDraw.obj \
$(TMPDIR)\tkMessage.obj \
+ $(TMPDIR)\tkObj.obj \
+ $(TMPDIR)\tkOldConfig.obj \
$(TMPDIR)\tkOption.obj \
$(TMPDIR)\tkPack.obj \
$(TMPDIR)\tkPlace.obj \
@@ -182,12 +211,19 @@ TKOBJS = \
$(TMPDIR)\tkTrig.obj \
$(TMPDIR)\tkUtil.obj \
$(TMPDIR)\tkVisual.obj \
+ $(TMPDIR)\tkStubInit.obj \
+ $(TMPDIR)\tkStubLib.obj \
$(TMPDIR)\tkWindow.obj
-cc32 = $(TOOLS32)\bin\cl.exe
-link32 = $(TOOLS32)\bin\link.exe
-rc32 = $(TOOLS32_rc)\bin\rc.exe
-include32 = -I$(TOOLS32)\include
+TKSTUBOBJS = $(TMPDIR)\tkStubLib.obj \
+ $(TMPDIR)\tkStubImg.obj
+
+
+cc32 = "$(TOOLS32)\bin\cl.exe"
+link32 = "$(TOOLS32)\bin\link.exe"
+lib32 = "$(TOOLS32)\bin\lib.exe"
+rc32 = "$(TOOLS32_rc)\bin\rc.exe"
+include32 = -I"$(TOOLS32)\include"
WINDIR = $(ROOT)\win
GENERICDIR = $(ROOT)\generic
@@ -198,123 +234,145 @@ RCDIR = $(WINDIR)\rc
TK_INCLUDES = -I$(WINDIR) -I$(GENERICDIR) -I$(BITMAPDIR) -I$(XLIBDIR) \
-I$(TCLDIR)\generic
-TK_DEFINES = $(DEBUGDEFINES)
-
-TK_CFLAGS = $(cdebug) $(cflags) $(cvarsdll) $(include32) \
- $(TK_INCLUDES) $(TK_DEFINES)
+TK_DEFINES = -D__WIN32__ $(DEBUGDEFINES) $(THREADDEFINES)
######################################################################
-# Link flags
+# Compile flags
######################################################################
!IF "$(NODEBUG)" == "1"
-ldebug = /RELEASE
+!IF "$(MACHINE)" == "ALPHA"
+# MSVC on Alpha doesn't understand -Ot
+cdebug = -O2i -Gs -GD
!ELSE
-ldebug = -debug:full -debugtype:cv
+# NOTE: Due to a bug in MSVC, we cannot use -O2 here or Tk starts to misbehave.
+cdebug = -Oti -Gs -GD
!ENDIF
-
-# declarations common to all linker options
-lcommon = /NODEFAULTLIB /RELEASE /NOLOGO
-
-# declarations for use on Intel i386, i486, and Pentium systems
-!IF "$(MACHINE)" == "IX86"
-DLLENTRY = @12
-lflags = $(lcommon) -align:0x1000 /MACHINE:$(MACHINE)
!ELSE
-lflags = $(lcommon) /MACHINE:$(MACHINE)
-!ENDIF
-
-conlflags = $(lflags) -subsystem:console -entry:mainCRTStartup
-guilflags = $(lflags) -subsystem:windows -entry:WinMainCRTStartup
-dlllflags = $(lflags) -entry:_DllMainCRTStartup$(DLLENTRY) -dll
-
-!IF "$(MACHINE)" == "PPC"
-libc = libc.lib
-libcdll = crtdll.lib
+!IF "$(MACHINE)" == "IA64"
+cdebug = -Od -Zi
!ELSE
-libc = libc.lib oldnames.lib
-libcdll = msvcrt.lib oldnames.lib
+cdebug = -Z7 -Od -WX
+!ENDIF
!ENDIF
-baselibs = kernel32.lib $(optlibs) advapi32.lib
-winlibs = $(baselibs) user32.lib gdi32.lib comdlg32.lib winspool.lib
-guilibs = $(libc) $(winlibs)
+# declarations common to all compiler options
+cflags = -c -W3 -nologo -Fp$(TMPDIR)\ -YX
+cvarsdll = -MD$(DBGX)
-guilibsdll = $(libcdll) $(winlibs)
+CON_CFLAGS = $(cdebug) $(cflags) $(include32) -DCONSOLE
+TK_CFLAGS = $(cdebug) $(cflags) $(cvarsdll) $(include32) \
+ $(TK_INCLUDES) $(TK_DEFINES) -DUSE_TCL_STUBS
+WISH_CFLAGS = $(cdebug) $(cflags) $(cvarsdll) $(include32) \
+ $(TK_INCLUDES) $(TK_DEFINES)
######################################################################
-# Compile flags
+# Link flags
######################################################################
!IF "$(NODEBUG)" == "1"
-!IF "$(MACHINE)" == "ALPHA"
-# MSVC on Alpha doesn't understand -Ot
-cdebug = -O2i -Gs -GD
-!ELSE
-cdebug = -Oti -Gs -GD
-!ENDIF
+ldebug = /RELEASE
!ELSE
-cdebug = -Z7 -Od -WX
+ldebug = -debug:full -debugtype:cv
!ENDIF
-# declarations common to all compiler options
-ccommon = -c -W3 -nologo -Fp$(TMPDIR)\ -YX
+# declarations common to all linker options
+lcommon = /NODEFAULTLIB /RELEASE /NOLOGO
+lflags = $(lcommon) /MACHINE:$(MACHINE)
+# declarations for use on Intel i386, i486, and Pentium systems
!IF "$(MACHINE)" == "IX86"
-cflags = $(ccommon) -D_X86_=1
-!ELSE
-!IF "$(MACHINE)" == "MIPS"
-cflags = $(ccommon) -D_MIPS_=1
-!ELSE
-!IF "$(MACHINE)" == "PPC"
-cflags = $(ccommon) -D_PPC_=1
-!ELSE
-!IF "$(MACHINE)" == "ALPHA"
-cflags = $(ccommon) -D_ALPHA_=1
-!ENDIF
-!ENDIF
-!ENDIF
+DLLENTRY = @12
!ENDIF
-cvars = -DWIN32 -D_WIN32
-cvarsmt = $(cvars) -D_MT
-cvarsdll = $(cvarsmt) -D_DLL
+conlflags = $(lflags) -subsystem:console -entry:mainCRTStartup
+guilflags = $(lflags) -subsystem:windows -entry:WinMainCRTStartup
+dlllflags = $(lflags) -entry:_DllMainCRTStartup$(DLLENTRY) -dll
-!IF "$(NODEBUG)" == "1"
-cvarsdll = $(cvars) -MD
+!IF "$(MACHINE)" == "PPC"
+libc = libc$(DBGX).lib
+libcdll = crtdll$(DBGX).lib
!ELSE
-cvarsdll = $(cvars) -MDd
+libc = libc$(DBGX).lib oldnames.lib
+libcdll = msvcrt$(DBGX).lib oldnames.lib
!ENDIF
-CON_CFLAGS = $(cdebug) $(cflags) $(cvars) $(include32) -DCONSOLE
+baselibs = kernel32.lib $(optlibs) advapi32.lib
+winlibs = $(baselibs) user32.lib gdi32.lib comdlg32.lib winspool.lib
+guilibs = $(libc) $(winlibs)
+conlibs = $(libc) $(baselibs)
+guilibsdll = $(libcdll) $(winlibs)
######################################################################
# Project specific targets
######################################################################
-all: setup $(WISH)
-test: setup $(TKTEST)
+all: setup $(WISH) $(CAT32)
+install: install-binaries install-libraries
plugin: setup $(TKPLUGINDLL) $(WISHP)
+tktest: setup $(TKTEST) $(CAT32)
+test: setup $(TKTEST) $(TKLIB) $(CAT32)
+ set TCL_LIBRARY=$(TCLDIR)/library
+ set PATH=$(TCLDIR)\win\$(TMPDIRNAME);$(PATH)
+ $(TKTEST) $(ROOT)/tests/all.tcl | $(CAT32)
+
+runtest: setup $(TKTEST) $(TKLIB) $(CAT32)
+ set TCL_LIBRARY=$(TCLDIR)/library
+ set PATH=$(TCLDIR)\win\$(TMPDIRNAME);$(PATH)
+ $(TKTEST)
+
+console-wish : all $(WISHC)
+
+stubs:
+ $(TCLDIR)\win\$(TMPDIRNAME)\tclsh$(VERSION)$(DBGX) \
+ $(TCLDIR)\tools\genStubs.tcl $(GENERICDIR) \
+ $(GENERICDIR)\tk.decls $(GENERICDIR)\tkInt.decls
setup:
@mkd $(TMPDIR)
@mkd $(OUTDIR)
-$(TKLIB): $(TKDLL)
-
-$(TKDLL): $(TKOBJS) $(TMPDIR)\tk.res $(TMPDIR)\tk.def
+install-binaries:
+ @mkd "$(BIN_INSTALL_DIR)"
+ copy $(TKDLL) "$(BIN_INSTALL_DIR)"
+ copy $(WISH) "$(BIN_INSTALL_DIR)"
+ @mkd "$(LIB_INSTALL_DIR)"
+ copy $(TKLIB) "$(LIB_INSTALL_DIR)"
+
+install-libraries:
+ @mkd "$(INCLUDE_INSTALL_DIR)"
+ @mkd "$(INCLUDE_INSTALL_DIR)\X11"
+ copy "$(ROOT)\generic\tk.h" "$(INCLUDE_INSTALL_DIR)"
+ copy "$(ROOT)\generic\tkDecls.h" "$(INCLUDE_INSTALL_DIR)"
+ copy "$(ROOT)\generic\tkIntXlibDecls.h" "$(INCLUDE_INSTALL_DIR)"
+ xcopy "$(ROOT)\xlib\X11\*.h" "$(INCLUDE_INSTALL_DIR)\X11"
+ @mkd "$(SCRIPT_INSTALL_DIR)"
+ @mkd "$(SCRIPT_INSTALL_DIR)\images"
+ @mkd "$(SCRIPT_INSTALL_DIR)\demos"
+ @mkd "$(SCRIPT_INSTALL_DIR)\demos\images"
+ xcopy "$(ROOT)\library" "$(SCRIPT_INSTALL_DIR)"
+ xcopy "$(ROOT)\library\images" "$(SCRIPT_INSTALL_DIR)\images"
+ xcopy "$(ROOT)\library\demos" "$(SCRIPT_INSTALL_DIR)\demos"
+ xcopy "$(ROOT)\library\demos\images" "$(SCRIPT_INSTALL_DIR)\demos\images"
+
+$(TKLIB): $(TKDLL) $(TKSTUBLIB)
+
+$(TKSTUBLIB): $(TKSTUBOBJS)
+ $(lib32) /out:$@ $(TKSTUBOBJS)
+
+$(TKDLL): $(TKOBJS) $(TMPDIR)\tk.res
set LIB=$(TOOLS32)\lib
- $(link32) $(ldebug) $(dlllflags) -def:$(TMPDIR)\tk.def \
- -out:$@ $(TMPDIR)\tk.res $(TCLLIBDIR)\$(TCLLIB) \
+ $(link32) $(ldebug) $(dlllflags) \
+ -out:$@ $(TMPDIR)\tk.res $(TCLLIBDIR)\$(TCLSTUBLIB) \
$(guilibsdll) @<<
$(TKOBJS)
<<
$(TKPLUGINLIB): $(TKPLUGINDLL)
-$(TKPLUGINDLL): $(TKOBJS) $(TMPDIR)\tk.res $(TMPDIR)\plugin.def
+$(TKPLUGINDLL): $(TKOBJS) $(TMPDIR)\tk.res
set LIB=$(TOOLS32)\lib
- $(link32) $(ldebug) $(dlllflags) -def:$(TMPDIR)\plugin.def \
+ $(link32) $(ldebug) $(dlllflags) \
-out:$@ $(TMPDIR)\tk.res $(TCLLIBDIR)\$(TCLPLUGINLIB) \
$(guilibsdll) @<<
$(TKOBJS)
@@ -325,6 +383,11 @@ $(WISH): $(WISHOBJS) $(TKLIB) $(TMPDIR)\wish.res
$(link32) $(ldebug) $(guilflags) $(TMPDIR)\wish.res -out:$@ \
$(guilibsdll) $(TCLLIBDIR)\$(TCLLIB) $(TKLIB) $(WISHOBJS)
+$(WISHC): $(WISHOBJS) $(TKLIB) $(TMPDIR)\wish.res
+ set LIB=$(TOOLS32)\lib
+ $(link32) $(ldebug) $(conlflags) $(TMPDIR)\wish.res -out:$@ \
+ $(guilibsdll) $(TCLLIBDIR)\$(TCLLIB) $(TKLIB) $(WISHOBJS)
+
$(WISHP): $(WISHOBJS) $(TKPLUGINLIB) $(TMPDIR)\wish.res
set LIB=$(TOOLS32)\lib
$(link32) $(ldebug) $(guilflags) $(TMPDIR)\wish.res -out:$@ \
@@ -336,36 +399,39 @@ $(TKTEST): $(TKTESTOBJS) $(TKLIB) $(TMPDIR)\wish.res
$(link32) $(ldebug) $(guilflags) $(TMPDIR)\wish.res -out:$@ \
$(guilibsdll) $(TCLLIBDIR)\$(TCLLIB) $(TKLIB) $(TKTESTOBJS)
-$(TMPDIR)\tk.def: $(DUMPEXTS) $(TKOBJS)
- $(DUMPEXTS) -o $@ $(TKDLLNAME) @<<
- $(TKOBJS)
-<<
-
-$(TMPDIR)\plugin.def: $(DUMPEXTS) $(TKOBJS)
- $(DUMPEXTS) -o $@ $(TKPLUGINDLLNAME) @<<
- $(TKOBJS)
-<<
-
-$(DUMPEXTS): $(TCLDIR)\win\winDumpExts.c
+$(CAT32): $(TCLDIR)\win\cat.c
$(cc32) $(CON_CFLAGS) -Fo$(TMPDIR)\ $?
set LIB=$(TOOLS32)\lib
- $(link32) $(ldebug) $(conlflags) $(guilibs) -out:$@ \
- $(TMPDIR)\winDumpExts.obj
+ $(link32) $(conlflags) -out:$@ -stack:16384 $(TMPDIR)\cat.obj $(conlibs)
+
+#
+# Regenerate the stubs files.
+#
+
+genstubs:
+ tclsh$(VERSION) $(TCLDIR)\tools\genStubs.tcl $(GENERICDIR) \
+ $(GENERICDIR)\tk.decls $(GENERICDIR)\tkInt.decls
#
# Special case object file targets
#
$(TMPDIR)\testMain.obj: $(ROOT)\win\winMain.c
- $(cc32) $(TK_CFLAGS) -DSTATIC_BUILD -DTK_TEST -Fo$@ $?
+ $(cc32) $(WISH_CFLAGS) -DTK_TEST -Fo$@ $?
$(TMPDIR)\tkTest.obj: $(ROOT)\generic\tkTest.c
- $(cc32) $(TK_CFLAGS) -DSTATIC_BUILD -Fo$@ $?
+ $(cc32) $(WISH_CFLAGS) -Fo$@ $?
+
+$(TMPDIR)\tkWinTest.obj: $(ROOT)\generic\tkWinTest.c
+ $(cc32) $(WISH_CFLAGS) -Fo$@ $?
$(TMPDIR)\tkSquare.obj: $(ROOT)\generic\tkSquare.c
- $(cc32) $(TK_CFLAGS) -Fo$@ $?
+ $(cc32) $(WISH_CFLAGS) -Fo$@ $?
$(TMPDIR)\winMain.obj: $(ROOT)\win\winMain.c
+ $(cc32) $(WISH_CFLAGS) -Fo$@ $?
+
+$(TMPDIR)\tkStubLib.obj : $(GENERICDIR)\tkStubLib.c
$(cc32) $(TK_CFLAGS) -DSTATIC_BUILD -Fo$@ $?
#
@@ -385,7 +451,8 @@ $(TMPDIR)\winMain.obj: $(ROOT)\win\winMain.c
$(cc32) -DDLL_BUILD -DBUILD_tk $(TK_CFLAGS) -Fo$(TMPDIR)\ $<
{$(RCDIR)}.rc{$(TMPDIR)}.res:
- $(rc32) -fo $@ -r -i $(GENERICDIR) $<
+ $(rc32) -fo $@ -r -i "$(GENERICDIR)" -i "$(TOOLS32)\include" \
+ -i "$(TCLDIR)\generic" $<
clean:
-@del $(OUTDIR)\*.exp
@@ -396,7 +463,6 @@ clean:
-@del $(TMPDIR)\*.pch
-@del $(TMPDIR)\*.obj
-@del $(TMPDIR)\*.res
- -@del $(TMPDIR)\*.def
-@del $(TMPDIR)\*.exe
-@rmd $(OUTDIR)
-@rmd $(TMPDIR)
@@ -438,3 +504,5 @@ $(GENERICDIR)/tkMenu.c: $(GENERICDIR)/tkMenu.h
$(GENERICDIR)/tkMenuDraw.c: $(GENERICDIR)/tkMenu.h
$(WINDIR)/tkWinMenu.c: $(GENERICDIR)/tkMenu.h
+
+
diff --git a/tk/win/mkd.bat b/tk/win/mkd.bat
index 2bd2388394f..13203f1c7a1 100644
--- a/tk/win/mkd.bat
+++ b/tk/win/mkd.bat
@@ -19,3 +19,4 @@ echo TAG >%1\tag.txt
echo created directory %1
:end
+
diff --git a/tk/win/rc/tk.rc b/tk/win/rc/tk.rc
index 67f3e1422be..00d90046acb 100644
--- a/tk/win/rc/tk.rc
+++ b/tk/win/rc/tk.rc
@@ -1,8 +1,9 @@
-// SCCS: @(#) tk.rc 1.22 97/03/21 18:35:14
+// RCS: @(#) $Id$
//
// Version
//
+#include <windows.h>
#define RESOURCE_INCLUDED
#include <tk.h>
@@ -24,9 +25,9 @@ BEGIN
BEGIN
VALUE "FileDescription", "Tk DLL\0"
VALUE "OriginalFilename", "tk" STRINGIFY(TK_MAJOR_VERSION) STRINGIFY(TK_MINOR_VERSION) ".dll\0"
- VALUE "CompanyName", "Sun Microsystems, Inc.\0"
+ VALUE "CompanyName", "Scriptics Corporation\0"
VALUE "FileVersion", TK_PATCH_LEVEL
- VALUE "LegalCopyright", "Copyright \251 1995-1996\0"
+ VALUE "LegalCopyright", "Copyright \251 2000 by Scriptics Corporation\0"
VALUE "ProductName", "Tk " TK_VERSION " for Windows\0"
VALUE "ProductVersion", TK_PATCH_LEVEL
END
@@ -36,97 +37,3 @@ BEGIN
VALUE "Translation", 0x409, 1200
END
END
-
-//
-// Icons
-//
-
-tk ICON DISCARDABLE "cygnus.ico"
-
-//
-// Bitmaps
-//
-
-buttons BITMAP DISCARDABLE "buttons.bmp"
-
-//
-// Cursors
-//
-
-X_cursor CURSOR DISCARDABLE "cursor00.cur"
-arrow CURSOR DISCARDABLE "cursor02.cur"
-based_arrow_down CURSOR DISCARDABLE "cursor04.cur"
-based_arrow_up CURSOR DISCARDABLE "cursor06.cur"
-boat CURSOR DISCARDABLE "cursor08.cur"
-bogosity CURSOR DISCARDABLE "cursor0a.cur"
-bottom_left_corner CURSOR DISCARDABLE "cursor0c.cur"
-bottom_right_corner CURSOR DISCARDABLE "cursor0e.cur"
-bottom_side CURSOR DISCARDABLE "cursor10.cur"
-bottom_tee CURSOR DISCARDABLE "cursor12.cur"
-box_spiral CURSOR DISCARDABLE "cursor14.cur"
-center_ptr CURSOR DISCARDABLE "cursor16.cur"
-circle CURSOR DISCARDABLE "cursor18.cur"
-clock CURSOR DISCARDABLE "cursor1a.cur"
-coffee_mug CURSOR DISCARDABLE "cursor1c.cur"
-cross CURSOR DISCARDABLE "cursor1e.cur"
-cross_reverse CURSOR DISCARDABLE "cursor20.cur"
-crosshair CURSOR DISCARDABLE "cursor22.cur"
-diamond_cross CURSOR DISCARDABLE "cursor24.cur"
-dot CURSOR DISCARDABLE "cursor26.cur"
-dotbox CURSOR DISCARDABLE "cursor28.cur"
-double_arrow CURSOR DISCARDABLE "cursor2a.cur"
-draft_large CURSOR DISCARDABLE "cursor2c.cur"
-draft_small CURSOR DISCARDABLE "cursor2e.cur"
-draped_box CURSOR DISCARDABLE "cursor30.cur"
-exchange CURSOR DISCARDABLE "cursor32.cur"
-fleur CURSOR DISCARDABLE "cursor34.cur"
-gobbler CURSOR DISCARDABLE "cursor36.cur"
-gumby CURSOR DISCARDABLE "cursor38.cur"
-hand1 CURSOR DISCARDABLE "cursor3a.cur"
-hand2 CURSOR DISCARDABLE "cursor3c.cur"
-heart CURSOR DISCARDABLE "cursor3e.cur"
-icon CURSOR DISCARDABLE "cursor40.cur"
-iron_cross CURSOR DISCARDABLE "cursor42.cur"
-left_ptr CURSOR DISCARDABLE "cursor44.cur"
-left_side CURSOR DISCARDABLE "cursor46.cur"
-left_tee CURSOR DISCARDABLE "cursor48.cur"
-leftbutton CURSOR DISCARDABLE "cursor4a.cur"
-ll_angle CURSOR DISCARDABLE "cursor4c.cur"
-lr_angle CURSOR DISCARDABLE "cursor4e.cur"
-man CURSOR DISCARDABLE "cursor50.cur"
-middlebutton CURSOR DISCARDABLE "cursor52.cur"
-mouse CURSOR DISCARDABLE "cursor54.cur"
-pencil CURSOR DISCARDABLE "cursor56.cur"
-pirate CURSOR DISCARDABLE "cursor58.cur"
-plus CURSOR DISCARDABLE "cursor5a.cur"
-question_arrow CURSOR DISCARDABLE "cursor5c.cur"
-right_ptr CURSOR DISCARDABLE "cursor5e.cur"
-right_side CURSOR DISCARDABLE "cursor60.cur"
-right_tee CURSOR DISCARDABLE "cursor62.cur"
-rightbutton CURSOR DISCARDABLE "cursor64.cur"
-rtl_logo CURSOR DISCARDABLE "cursor66.cur"
-sailboat CURSOR DISCARDABLE "cursor68.cur"
-sb_down_arrow CURSOR DISCARDABLE "cursor6a.cur"
-sb_h_double_arrow CURSOR DISCARDABLE "cursor6c.cur"
-sb_left_arrow CURSOR DISCARDABLE "cursor6e.cur"
-sb_right_arrow CURSOR DISCARDABLE "cursor70.cur"
-sb_up_arrow CURSOR DISCARDABLE "cursor72.cur"
-sb_v_double_arrow CURSOR DISCARDABLE "cursor74.cur"
-shuttle CURSOR DISCARDABLE "cursor76.cur"
-sizing CURSOR DISCARDABLE "cursor78.cur"
-spider CURSOR DISCARDABLE "cursor7a.cur"
-spraycan CURSOR DISCARDABLE "cursor7c.cur"
-star CURSOR DISCARDABLE "cursor7e.cur"
-target CURSOR DISCARDABLE "cursor80.cur"
-tcross CURSOR DISCARDABLE "cursor82.cur"
-top_left_arrow CURSOR DISCARDABLE "cursor84.cur"
-top_left_corner CURSOR DISCARDABLE "cursor86.cur"
-top_right_corner CURSOR DISCARDABLE "cursor88.cur"
-top_side CURSOR DISCARDABLE "cursor8a.cur"
-top_tee CURSOR DISCARDABLE "cursor8c.cur"
-trek CURSOR DISCARDABLE "cursor8e.cur"
-ul_angle CURSOR DISCARDABLE "cursor90.cur"
-umbrella CURSOR DISCARDABLE "cursor92.cur"
-ur_angle CURSOR DISCARDABLE "cursor94.cur"
-watch CURSOR DISCARDABLE "cursor96.cur"
-xterm CURSOR DISCARDABLE "cursor98.cur"
diff --git a/tk/win/rc/tk_base.rc b/tk/win/rc/tk_base.rc
new file mode 100644
index 00000000000..52d64d21ae9
--- /dev/null
+++ b/tk/win/rc/tk_base.rc
@@ -0,0 +1,130 @@
+// RCS: @(#) $Id$
+//
+// Base resources needed by Tk whether it's a DLL or a static library.
+//
+
+//
+// Tk Icon
+//
+
+tk ICON DISCARDABLE "tk.ico"
+
+#include <dlgs.h>
+
+FILEOPENORD DIALOG DISCARDABLE 36, 24, 218, 138
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Choose Directory"
+FONT 8, "Helv"
+BEGIN
+ LTEXT "Directory &name:",-1,8,6,118,9
+ EDITTEXT edt10,8,26,144,12, WS_TABSTOP | ES_AUTOHSCROLL
+ LISTBOX lst2,8,40,144,64,LBS_SORT | LBS_OWNERDRAWFIXED |
+ LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT |
+ LBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Dri&ves:",stc4,8,106,92,9
+ COMBOBOX cmb2,8,115,144,68,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED |
+ CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER |
+ WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK",1,160,6,50,14,WS_GROUP
+ PUSHBUTTON "Cancel",2,160,24,50,14,WS_GROUP
+ PUSHBUTTON "&Help",psh15,160,42,50,14,WS_GROUP
+ CHECKBOX "&Read only",chx1,160,66,50,12,WS_GROUP
+ PUSHBUTTON "Net&work...",psh14,160,115,50,14,WS_GROUP
+
+ LTEXT "a",stc3,9,143,114,15
+ EDITTEXT edt1,7,158,135,20,NOT WS_TABSTOP
+ LISTBOX lst1,8,205,134,42,LBS_NOINTEGRALHEIGHT
+ COMBOBOX cmb1,8,253,135,21,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED |
+ CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER |
+ WS_VSCROLL
+
+END
+
+
+//
+// Bitmaps
+//
+
+buttons BITMAP DISCARDABLE "buttons.bmp"
+
+//
+// Cursors
+//
+
+X_cursor CURSOR DISCARDABLE "cursor00.cur"
+arrow CURSOR DISCARDABLE "cursor02.cur"
+based_arrow_down CURSOR DISCARDABLE "cursor04.cur"
+based_arrow_up CURSOR DISCARDABLE "cursor06.cur"
+boat CURSOR DISCARDABLE "cursor08.cur"
+bogosity CURSOR DISCARDABLE "cursor0a.cur"
+bottom_left_corner CURSOR DISCARDABLE "cursor0c.cur"
+bottom_right_corner CURSOR DISCARDABLE "cursor0e.cur"
+bottom_side CURSOR DISCARDABLE "cursor10.cur"
+bottom_tee CURSOR DISCARDABLE "cursor12.cur"
+box_spiral CURSOR DISCARDABLE "cursor14.cur"
+center_ptr CURSOR DISCARDABLE "cursor16.cur"
+circle CURSOR DISCARDABLE "cursor18.cur"
+clock CURSOR DISCARDABLE "cursor1a.cur"
+coffee_mug CURSOR DISCARDABLE "cursor1c.cur"
+cross CURSOR DISCARDABLE "cursor1e.cur"
+cross_reverse CURSOR DISCARDABLE "cursor20.cur"
+crosshair CURSOR DISCARDABLE "cursor22.cur"
+diamond_cross CURSOR DISCARDABLE "cursor24.cur"
+dot CURSOR DISCARDABLE "cursor26.cur"
+dotbox CURSOR DISCARDABLE "cursor28.cur"
+double_arrow CURSOR DISCARDABLE "cursor2a.cur"
+draft_large CURSOR DISCARDABLE "cursor2c.cur"
+draft_small CURSOR DISCARDABLE "cursor2e.cur"
+draped_box CURSOR DISCARDABLE "cursor30.cur"
+exchange CURSOR DISCARDABLE "cursor32.cur"
+fleur CURSOR DISCARDABLE "cursor34.cur"
+gobbler CURSOR DISCARDABLE "cursor36.cur"
+gumby CURSOR DISCARDABLE "cursor38.cur"
+hand1 CURSOR DISCARDABLE "cursor3a.cur"
+hand2 CURSOR DISCARDABLE "cursor3c.cur"
+heart CURSOR DISCARDABLE "cursor3e.cur"
+icon CURSOR DISCARDABLE "cursor40.cur"
+iron_cross CURSOR DISCARDABLE "cursor42.cur"
+left_ptr CURSOR DISCARDABLE "cursor44.cur"
+left_side CURSOR DISCARDABLE "cursor46.cur"
+left_tee CURSOR DISCARDABLE "cursor48.cur"
+leftbutton CURSOR DISCARDABLE "cursor4a.cur"
+ll_angle CURSOR DISCARDABLE "cursor4c.cur"
+lr_angle CURSOR DISCARDABLE "cursor4e.cur"
+man CURSOR DISCARDABLE "cursor50.cur"
+middlebutton CURSOR DISCARDABLE "cursor52.cur"
+mouse CURSOR DISCARDABLE "cursor54.cur"
+pencil CURSOR DISCARDABLE "cursor56.cur"
+pirate CURSOR DISCARDABLE "cursor58.cur"
+plus CURSOR DISCARDABLE "cursor5a.cur"
+question_arrow CURSOR DISCARDABLE "cursor5c.cur"
+right_ptr CURSOR DISCARDABLE "cursor5e.cur"
+right_side CURSOR DISCARDABLE "cursor60.cur"
+right_tee CURSOR DISCARDABLE "cursor62.cur"
+rightbutton CURSOR DISCARDABLE "cursor64.cur"
+rtl_logo CURSOR DISCARDABLE "cursor66.cur"
+sailboat CURSOR DISCARDABLE "cursor68.cur"
+sb_down_arrow CURSOR DISCARDABLE "cursor6a.cur"
+sb_h_double_arrow CURSOR DISCARDABLE "cursor6c.cur"
+sb_left_arrow CURSOR DISCARDABLE "cursor6e.cur"
+sb_right_arrow CURSOR DISCARDABLE "cursor70.cur"
+sb_up_arrow CURSOR DISCARDABLE "cursor72.cur"
+sb_v_double_arrow CURSOR DISCARDABLE "cursor74.cur"
+shuttle CURSOR DISCARDABLE "cursor76.cur"
+sizing CURSOR DISCARDABLE "cursor78.cur"
+spider CURSOR DISCARDABLE "cursor7a.cur"
+spraycan CURSOR DISCARDABLE "cursor7c.cur"
+star CURSOR DISCARDABLE "cursor7e.cur"
+target CURSOR DISCARDABLE "cursor80.cur"
+tcross CURSOR DISCARDABLE "cursor82.cur"
+top_left_arrow CURSOR DISCARDABLE "cursor84.cur"
+top_left_corner CURSOR DISCARDABLE "cursor86.cur"
+top_right_corner CURSOR DISCARDABLE "cursor88.cur"
+top_side CURSOR DISCARDABLE "cursor8a.cur"
+top_tee CURSOR DISCARDABLE "cursor8c.cur"
+trek CURSOR DISCARDABLE "cursor8e.cur"
+ul_angle CURSOR DISCARDABLE "cursor90.cur"
+umbrella CURSOR DISCARDABLE "cursor92.cur"
+ur_angle CURSOR DISCARDABLE "cursor94.cur"
+watch CURSOR DISCARDABLE "cursor96.cur"
+xterm CURSOR DISCARDABLE "cursor98.cur"
diff --git a/tk/win/rc/tk_dll.rc b/tk/win/rc/tk_dll.rc
new file mode 100644
index 00000000000..4cea329b679
--- /dev/null
+++ b/tk/win/rc/tk_dll.rc
@@ -0,0 +1,169 @@
+// RCS: @(#) $Id$
+//
+// Version
+//
+
+#include <windows.h>
+#define RESOURCE_INCLUDED
+#include <tk.h>
+
+#define STRINGIFY1(x) #x
+#define STRINGIFY(x) STRINGIFY1(x)
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL
+ PRODUCTVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL
+ FILEFLAGSMASK 0x3fL
+ FILEFLAGS 0x0L
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "Tk DLL\0"
+ VALUE "OriginalFilename", "tk" STRINGIFY(TK_MAJOR_VERSION) STRINGIFY(TK_MINOR_VERSION) ".dll\0"
+ VALUE "CompanyName", "Scriptics Corporation\0"
+ VALUE "FileVersion", TK_PATCH_LEVEL
+ VALUE "LegalCopyright", "Copyright \251 2000 by Scriptics Corporation\0"
+ VALUE "ProductName", "Tk " TK_VERSION " for Windows\0"
+ VALUE "ProductVersion", TK_PATCH_LEVEL
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+// RCS: @(#) $Id$
+//
+// Base resources needed by Tk whether it's a DLL or a static library.
+//
+
+//
+// Tk Icon
+//
+
+tk ICON DISCARDABLE "tk.ico"
+
+#include <dlgs.h>
+
+FILEOPENORD DIALOG DISCARDABLE 36, 24, 218, 138
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Choose Directory"
+FONT 8, "Helv"
+BEGIN
+ LTEXT "Directory &name:",-1,8,6,118,9
+ EDITTEXT edt10,8,26,144,12, WS_TABSTOP | ES_AUTOHSCROLL
+ LISTBOX lst2,8,40,144,64,LBS_SORT | LBS_OWNERDRAWFIXED |
+ LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT |
+ LBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Dri&ves:",stc4,8,106,92,9
+ COMBOBOX cmb2,8,115,144,68,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED |
+ CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER |
+ WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK",1,160,6,50,14,WS_GROUP
+ PUSHBUTTON "Cancel",2,160,24,50,14,WS_GROUP
+ PUSHBUTTON "&Help",psh15,160,42,50,14,WS_GROUP
+ CHECKBOX "&Read only",chx1,160,66,50,12,WS_GROUP
+ PUSHBUTTON "Net&work...",psh14,160,115,50,14,WS_GROUP
+
+ LTEXT "a",stc3,9,143,114,15
+ EDITTEXT edt1,7,158,135,20,NOT WS_TABSTOP
+ LISTBOX lst1,8,205,134,42,LBS_NOINTEGRALHEIGHT
+ COMBOBOX cmb1,8,253,135,21,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED |
+ CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER |
+ WS_VSCROLL
+
+END
+
+
+//
+// Bitmaps
+//
+
+buttons BITMAP DISCARDABLE "buttons.bmp"
+
+//
+// Cursors
+//
+
+X_cursor CURSOR DISCARDABLE "cursor00.cur"
+arrow CURSOR DISCARDABLE "cursor02.cur"
+based_arrow_down CURSOR DISCARDABLE "cursor04.cur"
+based_arrow_up CURSOR DISCARDABLE "cursor06.cur"
+boat CURSOR DISCARDABLE "cursor08.cur"
+bogosity CURSOR DISCARDABLE "cursor0a.cur"
+bottom_left_corner CURSOR DISCARDABLE "cursor0c.cur"
+bottom_right_corner CURSOR DISCARDABLE "cursor0e.cur"
+bottom_side CURSOR DISCARDABLE "cursor10.cur"
+bottom_tee CURSOR DISCARDABLE "cursor12.cur"
+box_spiral CURSOR DISCARDABLE "cursor14.cur"
+center_ptr CURSOR DISCARDABLE "cursor16.cur"
+circle CURSOR DISCARDABLE "cursor18.cur"
+clock CURSOR DISCARDABLE "cursor1a.cur"
+coffee_mug CURSOR DISCARDABLE "cursor1c.cur"
+cross CURSOR DISCARDABLE "cursor1e.cur"
+cross_reverse CURSOR DISCARDABLE "cursor20.cur"
+crosshair CURSOR DISCARDABLE "cursor22.cur"
+diamond_cross CURSOR DISCARDABLE "cursor24.cur"
+dot CURSOR DISCARDABLE "cursor26.cur"
+dotbox CURSOR DISCARDABLE "cursor28.cur"
+double_arrow CURSOR DISCARDABLE "cursor2a.cur"
+draft_large CURSOR DISCARDABLE "cursor2c.cur"
+draft_small CURSOR DISCARDABLE "cursor2e.cur"
+draped_box CURSOR DISCARDABLE "cursor30.cur"
+exchange CURSOR DISCARDABLE "cursor32.cur"
+fleur CURSOR DISCARDABLE "cursor34.cur"
+gobbler CURSOR DISCARDABLE "cursor36.cur"
+gumby CURSOR DISCARDABLE "cursor38.cur"
+hand1 CURSOR DISCARDABLE "cursor3a.cur"
+hand2 CURSOR DISCARDABLE "cursor3c.cur"
+heart CURSOR DISCARDABLE "cursor3e.cur"
+icon CURSOR DISCARDABLE "cursor40.cur"
+iron_cross CURSOR DISCARDABLE "cursor42.cur"
+left_ptr CURSOR DISCARDABLE "cursor44.cur"
+left_side CURSOR DISCARDABLE "cursor46.cur"
+left_tee CURSOR DISCARDABLE "cursor48.cur"
+leftbutton CURSOR DISCARDABLE "cursor4a.cur"
+ll_angle CURSOR DISCARDABLE "cursor4c.cur"
+lr_angle CURSOR DISCARDABLE "cursor4e.cur"
+man CURSOR DISCARDABLE "cursor50.cur"
+middlebutton CURSOR DISCARDABLE "cursor52.cur"
+mouse CURSOR DISCARDABLE "cursor54.cur"
+pencil CURSOR DISCARDABLE "cursor56.cur"
+pirate CURSOR DISCARDABLE "cursor58.cur"
+plus CURSOR DISCARDABLE "cursor5a.cur"
+question_arrow CURSOR DISCARDABLE "cursor5c.cur"
+right_ptr CURSOR DISCARDABLE "cursor5e.cur"
+right_side CURSOR DISCARDABLE "cursor60.cur"
+right_tee CURSOR DISCARDABLE "cursor62.cur"
+rightbutton CURSOR DISCARDABLE "cursor64.cur"
+rtl_logo CURSOR DISCARDABLE "cursor66.cur"
+sailboat CURSOR DISCARDABLE "cursor68.cur"
+sb_down_arrow CURSOR DISCARDABLE "cursor6a.cur"
+sb_h_double_arrow CURSOR DISCARDABLE "cursor6c.cur"
+sb_left_arrow CURSOR DISCARDABLE "cursor6e.cur"
+sb_right_arrow CURSOR DISCARDABLE "cursor70.cur"
+sb_up_arrow CURSOR DISCARDABLE "cursor72.cur"
+sb_v_double_arrow CURSOR DISCARDABLE "cursor74.cur"
+shuttle CURSOR DISCARDABLE "cursor76.cur"
+sizing CURSOR DISCARDABLE "cursor78.cur"
+spider CURSOR DISCARDABLE "cursor7a.cur"
+spraycan CURSOR DISCARDABLE "cursor7c.cur"
+star CURSOR DISCARDABLE "cursor7e.cur"
+target CURSOR DISCARDABLE "cursor80.cur"
+tcross CURSOR DISCARDABLE "cursor82.cur"
+top_left_arrow CURSOR DISCARDABLE "cursor84.cur"
+top_left_corner CURSOR DISCARDABLE "cursor86.cur"
+top_right_corner CURSOR DISCARDABLE "cursor88.cur"
+top_side CURSOR DISCARDABLE "cursor8a.cur"
+top_tee CURSOR DISCARDABLE "cursor8c.cur"
+trek CURSOR DISCARDABLE "cursor8e.cur"
+ul_angle CURSOR DISCARDABLE "cursor90.cur"
+umbrella CURSOR DISCARDABLE "cursor92.cur"
+ur_angle CURSOR DISCARDABLE "cursor94.cur"
+watch CURSOR DISCARDABLE "cursor96.cur"
+xterm CURSOR DISCARDABLE "cursor98.cur"
diff --git a/tk/win/rc/wish.ico b/tk/win/rc/wish.ico
index a32e749fd55..182575166f5 100644
--- a/tk/win/rc/wish.ico
+++ b/tk/win/rc/wish.ico
Binary files differ
diff --git a/tk/win/rc/wish.rc b/tk/win/rc/wish.rc
index 76cf1240372..5505c7b2c6a 100644
--- a/tk/win/rc/wish.rc
+++ b/tk/win/rc/wish.rc
@@ -1,7 +1,8 @@
-// SCCS: @(#) wish.rc 1.15 96/09/17 13:24:11
+// RCS: @(#) $Id$
//
// Version
//
+#include <windows.h>
#define RESOURCE_INCLUDED
#include <tk.h>
@@ -24,9 +25,9 @@ BEGIN
BEGIN
VALUE "FileDescription", "Wish Application\0"
VALUE "OriginalFilename", "wish" STRINGIFY(TK_MAJOR_VERSION) STRINGIFY(TK_MINOR_VERSION) ".exe\0"
- VALUE "CompanyName", "Sun Microsystems, Inc.\0"
+ VALUE "CompanyName", "Scriptics Corporation\0"
VALUE "FileVersion", TK_PATCH_LEVEL
- VALUE "LegalCopyright", "Copyright \251 1995-1996\0"
+ VALUE "LegalCopyright", "Copyright \251 2000 by Scriptics Corporation\0"
VALUE "ProductName", "Tk " TK_VERSION " for Windows\0"
VALUE "ProductVersion", TK_PATCH_LEVEL
END
@@ -42,3 +43,5 @@ END
//
wish ICON DISCARDABLE "wish.ico"
+
+
diff --git a/tk/win/rc/wish_static.rc b/tk/win/rc/wish_static.rc
new file mode 100644
index 00000000000..80c3398a91d
--- /dev/null
+++ b/tk/win/rc/wish_static.rc
@@ -0,0 +1,177 @@
+// RCS: @(#) $Id$
+//
+// Version
+//
+#include <windows.h>
+
+#define RESOURCE_INCLUDED
+#include <tk.h>
+
+#define STRINGIFY1(x) #x
+#define STRINGIFY(x) STRINGIFY1(x)
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL
+ PRODUCTVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL
+ FILEFLAGSMASK 0x3fL
+ FILEFLAGS 0x0L
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "Wish Application\0"
+ VALUE "OriginalFilename", "wish" STRINGIFY(TK_MAJOR_VERSION) STRINGIFY(TK_MINOR_VERSION) ".exe\0"
+ VALUE "CompanyName", "Scriptics Corporation\0"
+ VALUE "FileVersion", TK_PATCH_LEVEL
+ VALUE "LegalCopyright", "Copyright \251 2000 by Scriptics Corporation\0"
+ VALUE "ProductName", "Tk " TK_VERSION " for Windows\0"
+ VALUE "ProductVersion", TK_PATCH_LEVEL
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+//
+// Icon
+//
+
+wish ICON DISCARDABLE "wish.ico"
+
+
+// RCS: @(#) $Id$
+//
+// Base resources needed by Tk whether it's a DLL or a static library.
+//
+
+//
+// Tk Icon
+//
+
+tk ICON DISCARDABLE "tk.ico"
+
+#include <dlgs.h>
+
+FILEOPENORD DIALOG DISCARDABLE 36, 24, 218, 138
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Choose Directory"
+FONT 8, "Helv"
+BEGIN
+ LTEXT "Directory &name:",-1,8,6,118,9
+ EDITTEXT edt10,8,26,144,12, WS_TABSTOP | ES_AUTOHSCROLL
+ LISTBOX lst2,8,40,144,64,LBS_SORT | LBS_OWNERDRAWFIXED |
+ LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT |
+ LBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Dri&ves:",stc4,8,106,92,9
+ COMBOBOX cmb2,8,115,144,68,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED |
+ CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER |
+ WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK",1,160,6,50,14,WS_GROUP
+ PUSHBUTTON "Cancel",2,160,24,50,14,WS_GROUP
+ PUSHBUTTON "&Help",psh15,160,42,50,14,WS_GROUP
+ CHECKBOX "&Read only",chx1,160,66,50,12,WS_GROUP
+ PUSHBUTTON "Net&work...",psh14,160,115,50,14,WS_GROUP
+
+ LTEXT "a",stc3,9,143,114,15
+ EDITTEXT edt1,7,158,135,20,NOT WS_TABSTOP
+ LISTBOX lst1,8,205,134,42,LBS_NOINTEGRALHEIGHT
+ COMBOBOX cmb1,8,253,135,21,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED |
+ CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER |
+ WS_VSCROLL
+
+END
+
+
+//
+// Bitmaps
+//
+
+buttons BITMAP DISCARDABLE "buttons.bmp"
+
+//
+// Cursors
+//
+
+X_cursor CURSOR DISCARDABLE "cursor00.cur"
+arrow CURSOR DISCARDABLE "cursor02.cur"
+based_arrow_down CURSOR DISCARDABLE "cursor04.cur"
+based_arrow_up CURSOR DISCARDABLE "cursor06.cur"
+boat CURSOR DISCARDABLE "cursor08.cur"
+bogosity CURSOR DISCARDABLE "cursor0a.cur"
+bottom_left_corner CURSOR DISCARDABLE "cursor0c.cur"
+bottom_right_corner CURSOR DISCARDABLE "cursor0e.cur"
+bottom_side CURSOR DISCARDABLE "cursor10.cur"
+bottom_tee CURSOR DISCARDABLE "cursor12.cur"
+box_spiral CURSOR DISCARDABLE "cursor14.cur"
+center_ptr CURSOR DISCARDABLE "cursor16.cur"
+circle CURSOR DISCARDABLE "cursor18.cur"
+clock CURSOR DISCARDABLE "cursor1a.cur"
+coffee_mug CURSOR DISCARDABLE "cursor1c.cur"
+cross CURSOR DISCARDABLE "cursor1e.cur"
+cross_reverse CURSOR DISCARDABLE "cursor20.cur"
+crosshair CURSOR DISCARDABLE "cursor22.cur"
+diamond_cross CURSOR DISCARDABLE "cursor24.cur"
+dot CURSOR DISCARDABLE "cursor26.cur"
+dotbox CURSOR DISCARDABLE "cursor28.cur"
+double_arrow CURSOR DISCARDABLE "cursor2a.cur"
+draft_large CURSOR DISCARDABLE "cursor2c.cur"
+draft_small CURSOR DISCARDABLE "cursor2e.cur"
+draped_box CURSOR DISCARDABLE "cursor30.cur"
+exchange CURSOR DISCARDABLE "cursor32.cur"
+fleur CURSOR DISCARDABLE "cursor34.cur"
+gobbler CURSOR DISCARDABLE "cursor36.cur"
+gumby CURSOR DISCARDABLE "cursor38.cur"
+hand1 CURSOR DISCARDABLE "cursor3a.cur"
+hand2 CURSOR DISCARDABLE "cursor3c.cur"
+heart CURSOR DISCARDABLE "cursor3e.cur"
+icon CURSOR DISCARDABLE "cursor40.cur"
+iron_cross CURSOR DISCARDABLE "cursor42.cur"
+left_ptr CURSOR DISCARDABLE "cursor44.cur"
+left_side CURSOR DISCARDABLE "cursor46.cur"
+left_tee CURSOR DISCARDABLE "cursor48.cur"
+leftbutton CURSOR DISCARDABLE "cursor4a.cur"
+ll_angle CURSOR DISCARDABLE "cursor4c.cur"
+lr_angle CURSOR DISCARDABLE "cursor4e.cur"
+man CURSOR DISCARDABLE "cursor50.cur"
+middlebutton CURSOR DISCARDABLE "cursor52.cur"
+mouse CURSOR DISCARDABLE "cursor54.cur"
+pencil CURSOR DISCARDABLE "cursor56.cur"
+pirate CURSOR DISCARDABLE "cursor58.cur"
+plus CURSOR DISCARDABLE "cursor5a.cur"
+question_arrow CURSOR DISCARDABLE "cursor5c.cur"
+right_ptr CURSOR DISCARDABLE "cursor5e.cur"
+right_side CURSOR DISCARDABLE "cursor60.cur"
+right_tee CURSOR DISCARDABLE "cursor62.cur"
+rightbutton CURSOR DISCARDABLE "cursor64.cur"
+rtl_logo CURSOR DISCARDABLE "cursor66.cur"
+sailboat CURSOR DISCARDABLE "cursor68.cur"
+sb_down_arrow CURSOR DISCARDABLE "cursor6a.cur"
+sb_h_double_arrow CURSOR DISCARDABLE "cursor6c.cur"
+sb_left_arrow CURSOR DISCARDABLE "cursor6e.cur"
+sb_right_arrow CURSOR DISCARDABLE "cursor70.cur"
+sb_up_arrow CURSOR DISCARDABLE "cursor72.cur"
+sb_v_double_arrow CURSOR DISCARDABLE "cursor74.cur"
+shuttle CURSOR DISCARDABLE "cursor76.cur"
+sizing CURSOR DISCARDABLE "cursor78.cur"
+spider CURSOR DISCARDABLE "cursor7a.cur"
+spraycan CURSOR DISCARDABLE "cursor7c.cur"
+star CURSOR DISCARDABLE "cursor7e.cur"
+target CURSOR DISCARDABLE "cursor80.cur"
+tcross CURSOR DISCARDABLE "cursor82.cur"
+top_left_arrow CURSOR DISCARDABLE "cursor84.cur"
+top_left_corner CURSOR DISCARDABLE "cursor86.cur"
+top_right_corner CURSOR DISCARDABLE "cursor88.cur"
+top_side CURSOR DISCARDABLE "cursor8a.cur"
+top_tee CURSOR DISCARDABLE "cursor8c.cur"
+trek CURSOR DISCARDABLE "cursor8e.cur"
+ul_angle CURSOR DISCARDABLE "cursor90.cur"
+umbrella CURSOR DISCARDABLE "cursor92.cur"
+ur_angle CURSOR DISCARDABLE "cursor94.cur"
+watch CURSOR DISCARDABLE "cursor96.cur"
+xterm CURSOR DISCARDABLE "cursor98.cur"
diff --git a/tk/win/rmd.bat b/tk/win/rmd.bat
index 15fd8c1fabc..63bf7619ac5 100644
--- a/tk/win/rmd.bat
+++ b/tk/win/rmd.bat
@@ -23,3 +23,4 @@ if errorlevel 1 goto end
echo deleted directory %1
:end
+
diff --git a/tk/win/stubs.c b/tk/win/stubs.c
index c9b97f5550c..e827b0fe853 100644
--- a/tk/win/stubs.c
+++ b/tk/win/stubs.c
@@ -1,8 +1,4 @@
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <stdio.h>
-#include <tkInt.h>
-#include <tkPort.h>
+#include "tk.h"
/*
* Undocumented Xlib internal function
diff --git a/tk/win/tcl.m4 b/tk/win/tcl.m4
new file mode 100644
index 00000000000..1522bbb5b09
--- /dev/null
+++ b/tk/win/tcl.m4
@@ -0,0 +1,634 @@
+#------------------------------------------------------------------------
+# SC_PATH_TCLCONFIG --
+#
+# 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.
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --with-tcl=...
+#
+# Sets the following vars:
+# TCL_BIN_DIR Full path to the tclConfig.sh file
+#------------------------------------------------------------------------
+
+AC_DEFUN(SC_PATH_TCLCONFIG, [
+ AC_MSG_CHECKING([the location of tclConfig.sh])
+
+# CYGNUS LOCAL
+ if test -d ../../tcl8.1/win; then
+ TCL_BIN_DIR_DEFAULT=../../tcl8.1/win
+ else
+ TCL_BIN_DIR_DEFAULT=../../tcl/win
+ fi
+# END CYGNUS LOCAL
+
+ AC_ARG_WITH(tcl, [ --with-tcl=DIR use Tcl 8.3 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
+ 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?)
+ 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
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --with-tk=...
+#
+# Sets the following vars:
+# TK_BIN_DIR Full path to the tkConfig.sh file
+#------------------------------------------------------------------------
+
+AC_DEFUN(SC_PATH_TKCONFIG, [
+ AC_MSG_CHECKING([the location of tkConfig.sh])
+
+ if test -d ../../tk8.3$1/win; then
+ TK_BIN_DIR_DEFAULT=../../tk8.3$1/win
+ else
+ TK_BIN_DIR_DEFAULT=../../tk8.3/win
+ fi
+
+ AC_ARG_WITH(tk, [ --with-tk=DIR use Tk 8.3 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
+
+ AC_MSG_RESULT([$TK_BIN_DIR/tkConfig.sh])
+])
+
+#------------------------------------------------------------------------
+# SC_LOAD_TCLCONFIG --
+#
+# Load the tclConfig.sh file
+# Currently a no-op for Windows
+#
+# 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(SC_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([file not found])
+ fi
+
+ # The eval is required to do the TCL_DBGX substitution in the
+ # TCL_LIB_FILE variable.
+
+ eval TCL_LIB_FILE=${TCL_LIB_FILE}
+ eval TCL_LIB_FLAG=${TCL_LIB_FLAG}
+
+ AC_SUBST(TCL_BIN_DIR)
+ AC_SUBST(TCL_SRC_DIR)
+ AC_SUBST(TCL_LIB_FILE)
+])
+
+#------------------------------------------------------------------------
+# SC_LOAD_TKCONFIG --
+#
+# Load the tkConfig.sh file
+# Currently a no-op for Windows
+#
+# 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(SC_LOAD_TKCONFIG, [
+ AC_MSG_CHECKING([for existence of $TCLCONFIG])
+
+ if test -f "$TK_BIN_DIR/tkConfig.sh" ; then
+ AC_MSG_CHECKING([loading $TK_BIN_DIR/tkConfig.sh])
+ . $TK_BIN_DIR/tkConfig.sh
+ else
+ AC_MSG_RESULT([could not find $TK_BIN_DIR/tkConfig.sh])
+ fi
+
+
+ AC_SUBST(TK_BIN_DIR)
+ AC_SUBST(TK_SRC_DIR)
+ AC_SUBST(TK_LIB_FILE)
+])
+
+#------------------------------------------------------------------------
+# SC_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(SC_ENABLE_SHARED, [
+ AC_MSG_CHECKING([how to build libraries])
+ AC_ARG_ENABLE(shared,
+ [ --enable-shared build and link with shared libraries [--enable-shared]],
+ [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)
+ fi
+])
+
+#------------------------------------------------------------------------
+# SC_ENABLE_THREADS --
+#
+# Specify if thread support should be enabled
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-threads=yes|no
+#
+# Defines the following vars:
+# TCL_THREADS
+#------------------------------------------------------------------------
+
+AC_DEFUN(SC_ENABLE_THREADS, [
+ AC_MSG_CHECKING(for building with threads)
+ AC_ARG_ENABLE(threads, [ --enable-threads build with threads],
+ [tcl_ok=$enableval], [tcl_ok=no])
+
+ if test "$tcl_ok" = "yes"; then
+ AC_MSG_RESULT(yes)
+ TCL_THREADS=1
+ AC_DEFINE(TCL_THREADS)
+ else
+ TCL_THREADS=0
+ AC_MSG_RESULT([no (default)])
+ fi
+])
+
+#------------------------------------------------------------------------
+# SC_ENABLE_SYMBOLS --
+#
+# Specify if debugging symbols should be used
+#
+# Arguments:
+# none
+#
+# Requires the following vars to be set in the Makefile:
+# CFLAGS_DEBUG
+# CFLAGS_OPTIMIZE
+# LDFLAGS_DEBUG
+# LDFLAGS_OPTIMIZE
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-symbols
+#
+# Defines the following vars:
+# CFLAGS_DEFAULT Set to $(CFLAGS_DEBUG) if true
+# Set to $(CFLAGS_OPTIMIZE) if false
+# LDFLAGS_DEFAULT Set to $(LDFLAGS_DEBUG) if true
+# Set to $(LDFLAGS_OPTIMIZE) if false
+# DBGX Debug library extension
+#
+#------------------------------------------------------------------------
+
+AC_DEFUN(SC_ENABLE_SYMBOLS, [
+ AC_MSG_CHECKING([for build with symbols])
+ AC_ARG_ENABLE(symbols, [ --enable-symbols build with debugging symbols [--disable-symbols]], [tcl_ok=$enableval], [tcl_ok=no])
+
+ if test "$tcl_ok" = "yes"; then
+ CFLAGS_DEFAULT='$(CFLAGS_DEBUG)'
+ LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'
+ DBGX=d
+ AC_MSG_RESULT([yes])
+ else
+ CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
+ LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
+ DBGX=""
+ AC_MSG_RESULT([no])
+ fi
+])
+
+
+#--------------------------------------------------------------------
+# SC_CONFIG_CFLAGS
+#
+# Try to determine the proper flags to pass to the compiler
+# for building shared libraries and other such nonsense.
+#
+# NOTE: The backslashes in quotes below are substituted twice
+# due to the fact that they are in a macro and then inlined
+# in the final configure script.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Can set the following vars:
+# EXTRA_CFLAGS
+# CFLAGS_DEBUG
+# CFLAGS_OPTIMIZE
+# CFLAGS_WARNING
+# LDFLAGS_DEBUG
+# LDFLAGS_OPTIMIZE
+# LDFLAGS_CONSOLE
+# LDFLAGS_WINDOW
+# CC_OBJNAME
+# CC_EXENAME
+# CYGPATH
+# STLIB_LD
+# SHLIB_LD
+# SHLIB_LD_LIBS
+# LIBS
+# AR
+# RC
+# RES
+#
+# MAKE_LIB
+# MAKE_EXE
+# MAKE_DLL
+#
+# LIBSUFFIX
+# LIBPREFIX
+# VENDORPREFIX
+# LIBRARIES
+# EXESUFFIX
+# DLLSUFFIX
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN(SC_CONFIG_CFLAGS, [
+ TCL_LIB_VERSIONS_OK=nodots
+
+ AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo)
+
+ # 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 "$GCC" = "yes" && test "$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])
+ else
+ AC_MSG_RESULT([yes])
+ CYGPATH=echo
+ fi
+ conftest=
+ cyg_conftest=
+ fi
+
+ if test "$CYGPATH" = "echo" || test "$ac_cv_cygwin" = "yes"; then
+ DEPARG='"$<"'
+ else
+ DEPARG='"$(shell $(CYGPATH) $<)"'
+ fi
+
+ VENDORPREFIX=""
+
+ # set various compiler flags depending on whether we are using gcc or cl
+
+ AC_MSG_CHECKING([compiler flags])
+ if test "${GCC}" = "yes" ; then
+
+ # CYGNUS LOCAL
+ VENDORPREFIX="cyg"
+
+ SHLIB_LD=""
+ SHLIB_LD_LIBS=""
+ LIBS=""
+ LIBS_GUI="-lgdi32 -lcomdlg32"
+ STLIB_LD="${AR} cr"
+ RC_OUT=-o
+ RC_TYPE=
+ RC_INCLUDE=--include
+ RES=res.o
+ MAKE_LIB="\${STLIB_LD} \[$]@"
+ POST_MAKE_LIB="\${RANLIB} \[$]@"
+ MAKE_EXE="\${CC} -o \[$]@"
+ LIBPREFIX="lib${VENDORPREFIX}"
+
+ if test "${SHARED_BUILD}" = "0" ; then
+ # static
+ AC_MSG_RESULT([using static flags])
+ runtime=
+ MAKE_DLL="echo "
+ LIBSUFFIX="s\${DBGX}.a"
+ LIBRARIES="\${STATIC_LIBRARIES}"
+ EXESUFFIX="s\${DBGX}.exe"
+ DLLSUFFIX=""
+ else
+ # dynamic
+ AC_MSG_RESULT([using shared flags])
+
+ # ad-hoc check to see if CC supports -shared.
+ if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then
+ AC_MSG_ERROR([${CC} does not support the -shared option.
+ You will need to upgrade to a newer version of the toolchain.])
+ fi
+
+ runtime=
+ # Link with gcc since ld does not link to default libs like
+ # -luser32 and -lmsvcrt. We also need to add CFLAGS so important
+ # flags like -mno-cygwin get passed in to CC.
+ SHLIB_LD='${CC} -shared ${CFLAGS}'
+ # Add SHLIB_LD_LIBS to the Make rule, not here.
+ MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \[$]@ ${extra_ldflags} \
+ -Wl,--out-implib,\$(patsubst %.dll,lib%.a,\[$]@)"
+
+ LIBSUFFIX="\${DBGX}.a"
+ DLLSUFFIX="\${DBGX}.dll"
+ EXESUFFIX="\${DBGX}.exe"
+ LIBRARIES="\${SHARED_LIBRARIES}"
+ fi
+
+ CFLAGS_DEBUG=-g
+ CFLAGS_OPTIMIZE=-O
+ CFLAGS_WARNING="-Wall -Wconversion"
+ LDFLAGS_DEBUG=
+ LDFLAGS_OPTIMIZE=
+
+ # Specify the CC output file names based on the target name
+ CC_OBJNAME="-o \[$]@"
+ CC_EXENAME="-o \[$]@"
+
+ # Specify linker flags depending on the type of app being
+ # built -- Console vs. Window.
+ #
+ # We need to pass -e _WinMain@16 so that ld will use
+ # WinMain() instead of main() as the entry point. We can't
+ # use autoconf to check for this case since it would need
+ # to run an executable and that does not work when
+ # cross compiling. Remove this -e workaround once we
+ # require a gcc that does not have this bug.
+ LDFLAGS_CONSOLE="-mconsole ${extra_ldflags}"
+ LDFLAGS_WINDOW="-mwindows -e _WinMain@16 ${extra_ldflags}"
+ else
+ # CYGNUS LOCAL
+ VENDORPREFIX="sn"
+
+ SHLIB_LD="link -dll -nologo"
+ SHLIB_LD_LIBS="user32.lib advapi32.lib"
+ LIBS="user32.lib advapi32.lib"
+ LIBS_GUI="gdi32.lib comdlg32.lib"
+ STLIB_LD="lib -nologo"
+ RC="rc"
+ RC_OUT=-fo
+ RC_TYPE=-r
+ RC_INCLUDE=-i
+ RES=res
+ MAKE_LIB="\${STLIB_LD} -out:\[$]@"
+ POST_MAKE_LIB=
+ MAKE_EXE="\${CC} -Fe\[$]@"
+ LIBPREFIX=${VENDORPREFIX}
+
+ if test "${SHARED_BUILD}" = "0" ; then
+ # static
+ AC_MSG_RESULT([using static flags])
+ runtime=-MT
+ MAKE_DLL="echo "
+ LIBSUFFIX="s\${DBGX}.lib"
+ LIBRARIES="\${STATIC_LIBRARIES}"
+ EXESUFFIX="s\${DBGX}.exe"
+ DLLSUFFIX=""
+ else
+ # dynamic
+ AC_MSG_RESULT([using shared flags])
+ runtime=-MD
+ # Add SHLIB_LD_LIBS to the Make rule, not here.
+ MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -out:\[$]@"
+ LIBSUFFIX="\${DBGX}.lib"
+ DLLSUFFIX="\${DBGX}.dll"
+ EXESUFFIX="\${DBGX}.exe"
+ LIBRARIES="\${SHARED_LIBRARIES}"
+ fi
+
+ EXTRA_CFLAGS="-YX"
+ CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
+# CFLAGS_OPTIMIZE="-nologo -O2 -Gs -GD ${runtime}"
+ CFLAGS_OPTIMIZE="-nologo -Oti -Gs -GD ${runtime}"
+ CFLAGS_WARNING="-W3"
+ LDFLAGS_DEBUG="-debug:full -debugtype:cv"
+ LDFLAGS_OPTIMIZE="-release"
+
+ # Specify the CC output file names based on the target name
+ CC_OBJNAME="-Fo\[$]@"
+ CC_EXENAME="-Fe\"\$(shell \$(CYGPATH) '\[$]@')\""
+
+ # Specify linker flags depending on the type of app being
+ # built -- Console vs. Window.
+ LDFLAGS_CONSOLE="-link -subsystem:console"
+ LDFLAGS_WINDOW="-link -subsystem:windows"
+ fi
+
+ # TCL_LIB_SUFFIX is defined here and in tclConfig.sh so that macros
+ # can use a single variable name for both Tcl and extensions.
+ TCL_LIB_SUFFIX=$LIBSUFFIX
+])
+
+#------------------------------------------------------------------------
+# SC_WITH_TCL --
+#
+# Location of the Tcl build directory.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --with-tcl=...
+#
+# Defines the following vars:
+# TCL_BIN_DIR Full path to the tcl build dir.
+#------------------------------------------------------------------------
+
+AC_DEFUN(SC_WITH_TCL, [
+ if test -d ../../tcl8.3$1/win; then
+ TCL_BIN_DEFAULT=../../tcl8.3$1/win
+ else
+ TCL_BIN_DEFAULT=../../tcl8.3/win
+ fi
+
+ AC_ARG_WITH(tcl, [ --with-tcl=DIR use Tcl 8.3 binaries from DIR],
+ TCL_BIN_DIR=$withval, TCL_BIN_DIR=`cd $TCL_BIN_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/Makefile; then
+ AC_MSG_ERROR(There is no Makefile in $TCL_BIN_DIR: perhaps you did not specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?)
+ else
+ echo "building against Tcl binaries in: $TCL_BIN_DIR"
+ fi
+ AC_SUBST(TCL_BIN_DIR)
+])
+
+#--------------------------------------------------------------------
+# SC_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(SC_TIME_HANDLER, [
+ AC_CHECK_HEADERS(sys/time.h)
+ AC_HEADER_TIME
+ AC_STRUCT_TIMEZONE
+
+ AC_MSG_CHECKING([tm_tzadj in struct tm])
+ AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],
+ [AC_DEFINE(HAVE_TM_TZADJ)
+ AC_MSG_RESULT(yes)],
+ AC_MSG_RESULT(no))
+
+ AC_MSG_CHECKING([tm_gmtoff in struct tm])
+ AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;],
+ [AC_DEFINE(HAVE_TM_GMTOFF)
+ AC_MSG_RESULT(yes)],
+ AC_MSG_RESULT(no))
+
+ #
+ # Its important to include time.h in this check, as some systems
+ # (like convex) have timezone functions, etc.
+ #
+ have_timezone=no
+ AC_MSG_CHECKING([long timezone variable])
+ AC_TRY_COMPILE([#include <time.h>],
+ [extern long timezone;
+ timezone += 1;
+ exit (0);],
+ [have_timezone=yes
+ AC_DEFINE(HAVE_TIMEZONE_VAR)
+ AC_MSG_RESULT(yes)],
+ AC_MSG_RESULT(no))
+
+ #
+ # On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
+ #
+ if test "$have_timezone" = no; then
+ AC_MSG_CHECKING([time_t timezone variable])
+ AC_TRY_COMPILE([#include <time.h>],
+ [extern time_t timezone;
+ timezone += 1;
+ exit (0);],
+ [AC_DEFINE(HAVE_TIMEZONE_VAR)
+ AC_MSG_RESULT(yes)],
+ AC_MSG_RESULT(no))
+ fi
+
+ #
+ # On some systems (eg Solaris 2.5.1), timezone is not declared in
+ # time.h unless you jump through hoops. Instead of that, we just
+ # declare it ourselves when necessary.
+ #
+ if test "$have_timezone" = yes; then
+ AC_MSG_CHECKING(for timezone declaration)
+ changequote(<<,>>)
+ tzrx='^[ ]*extern.*timezone'
+ changequote([,])
+ AC_EGREP_HEADER($tzrx, time.h, [
+ AC_DEFINE(HAVE_TIMEZONE_DECL)
+ AC_MSG_RESULT(found)], AC_MSG_RESULT(missing))
+ fi
+
+ #
+ # 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.
+ #
+
+ if test "`uname -s`" = "AIX" ; then
+ AC_CHECK_LIB(bsd, gettimeofday, libbsd=yes)
+ if test $libbsd = yes; then
+ AC_DEFINE(USE_DELTA_FOR_TZ)
+ fi
+ fi
+])
+
diff --git a/tk/win/tkConfig.sh.in b/tk/win/tkConfig.sh.in
new file mode 100644
index 00000000000..3e2dbf33846
--- /dev/null
+++ b/tk/win/tkConfig.sh.in
@@ -0,0 +1,92 @@
+# tkConfig.sh --
+#
+# This shell script (for sh) is generated automatically by Tk's
+# configure script. It will create shell variables for most of
+# the configuration options discovered by the configure script.
+# This script is intended to be included by the configure scripts
+# for Tk extensions so that they don't have to figure this all
+# out for themselves. This file does not duplicate information
+# already provided by tclConfig.sh, so you may need to use that
+# file in addition to this one.
+#
+# The information in this file is specific to a single platform.
+#
+# RCS: @(#) $Id$
+
+# Tk's version number.
+TK_VERSION='@TK_VERSION@'
+TK_MAJOR_VERSION='@TK_MAJOR_VERSION@'
+TK_MINOR_VERSION='@TK_MINOR_VERSION@'
+TK_PATCH_LEVEL='@TK_PATCH_LEVEL@'
+
+# -D flags for use with the C compiler.
+TK_DEFS='@DEFS@'
+
+# Flag, 1: we built a shared lib, 0 we didn't
+TK_SHARED_BUILD=@TK_SHARED_BUILD@
+
+# This indicates if Tk was build with debugging symbols
+TK_DBGX=@TK_DBGX@
+
+# The name of the Tk library (may be either a .a file or a shared library):
+TK_LIB_FILE='@TK_LIB_FILE@'
+
+# Additional libraries to use when linking Tk.
+TK_LIBS='@LIBS@ @LIBS_GUI@'
+LIBS_GUI='@LIBS_GUI@'
+
+# Top-level directory in which Tcl's platform-independent files are
+# installed.
+TK_PREFIX='@prefix@'
+
+# Top-level directory in which Tcl's platform-specific files (e.g.
+# executables) are installed.
+TK_EXEC_PREFIX='@exec_prefix@'
+
+# -I switch(es) to use to make all of the X11 include files accessible:
+TK_XINCLUDES='@XINCLUDES@'
+
+# -l flag to pass to the linker to pick up the Tcl library
+TK_LIB_FLAG='@TK_LIB_FLAG@'
+
+# String to pass to linker to pick up the Tk library from its
+# build directory.
+TK_BUILD_LIB_SPEC='@TK_BUILD_LIB_SPEC@'
+
+# String to pass to linker to pick up the Tk library from its
+# installed directory.
+TK_LIB_SPEC='@TK_LIB_SPEC@'
+
+# Location of the top-level source directory from which Tk was built.
+# This is the directory that contains a README file as well as
+# subdirectories such as generic, unix, etc. If Tk was compiled in a
+# different place than the directory containing the source files, this
+# points to the location of the sources, not the location where Tk was
+# compiled.
+TK_SRC_DIR='@TK_SRC_DIR@'
+
+# Needed if you want to make a 'fat' shared library library
+# containing tk objects or link a different wish.
+TK_CC_SEARCH_FLAGS='@TK_CC_SEARCH_FLAGS@'
+TK_LD_SEARCH_FLAGS='@TK_LD_SEARCH_FLAGS@'
+
+# The name of the Tk stub library (.a):
+TK_STUB_LIB_FILE='@TK_STUB_LIB_FILE@'
+
+# -l flag to pass to the linker to pick up the Tk stub library
+TK_STUB_LIB_FLAG='@TK_STUB_LIB_FLAG@'
+
+# String to pass to linker to pick up the Tk stub library from its
+# build directory.
+TK_BUILD_STUB_LIB_SPEC='@TK_BUILD_STUB_LIB_SPEC@'
+
+# String to pass to linker to pick up the Tk stub library from its
+# installed directory.
+TK_STUB_LIB_SPEC='@TK_STUB_LIB_SPEC@'
+
+# Path to the Tk stub library in the build directory.
+TK_BUILD_STUB_LIB_PATH='@TK_BUILD_STUB_LIB_PATH@'
+
+# Path to the Tk stub library in the install directory.
+TK_STUB_LIB_PATH='@TK_STUB_LIB_PATH@'
+
diff --git a/tk/win/tkWin.h b/tk/win/tkWin.h
index 40e7a24bb9d..f92ec8d322c 100644
--- a/tk/win/tkWin.h
+++ b/tk/win/tkWin.h
@@ -4,7 +4,7 @@
* Declarations of public types and interfaces that are only
* available under Windows.
*
- * Copyright (c) 1996 by Sun Microsystems, Inc.
+ * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -47,18 +47,10 @@
*--------------------------------------------------------------
*/
-EXTERN Window Tk_AttachHWND _ANSI_ARGS_((Tk_Window tkwin,
- HWND hwnd));
-EXTERN HINSTANCE Tk_GetHINSTANCE _ANSI_ARGS_((void));
-EXTERN HWND Tk_GetHWND _ANSI_ARGS_((Window window));
-EXTERN Tk_Window Tk_HWNDToWindow _ANSI_ARGS_((HWND hwnd));
-EXTERN void Tk_PointerEvent _ANSI_ARGS_((HWND hwnd,
- int x, int y));
-EXTERN int Tk_TranslateWinEvent _ANSI_ARGS_((HWND hwnd,
- UINT message, WPARAM wParam, LPARAM lParam,
- LRESULT *result));
+#include "tkPlatDecls.h"
# undef TCL_STORAGE_CLASS
# define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TKWIN */
+
diff --git a/tk/win/tkWin32Dll.c b/tk/win/tkWin32Dll.c
index 7c2fec7c3b4..48fdd0ac671 100644
--- a/tk/win/tkWin32Dll.c
+++ b/tk/win/tkWin32Dll.c
@@ -11,7 +11,6 @@
* RCS: @(#) $Id$
*/
-#include "tkPort.h"
#include "tkWinInt.h"
/*
@@ -25,7 +24,7 @@ BOOL APIENTRY DllMain _ANSI_ARGS_((HINSTANCE hInst,
/* cygwin32 requires an impure pointer variable, which must be
explicitly initialized when the DLL starts up. */
struct _reent *_impure_ptr;
-extern struct _reent *_imp__reent_data;
+extern struct _reent __declspec(dllimport) reent_data;
#endif
/* END CYGNUS LOCAL */
@@ -78,11 +77,10 @@ DllMain(hInstance, reason, reserved)
DWORD reason;
LPVOID reserved;
{
- /* CYGNUS LOCAL */
#ifdef __CYGWIN32__
/* cygwin32 requires the impure data pointer to be initialized
when the DLL starts up. */
- _impure_ptr = _imp__reent_data;
+ _impure_ptr = &reent_data;
#endif
/* END CYGNUS LOCAL */
@@ -99,3 +97,4 @@ DllMain(hInstance, reason, reserved)
}
return(TRUE);
}
+
diff --git a/tk/win/tkWin3d.c b/tk/win/tkWin3d.c
index 9e0bd586530..35d71c81f1d 100644
--- a/tk/win/tkWin3d.c
+++ b/tk/win/tkWin3d.c
@@ -12,8 +12,8 @@
* RCS: @(#) $Id$
*/
-#include <tk3d.h>
-#include <tkWinInt.h>
+#include "tkWinInt.h"
+#include "tk3d.h"
/*
* This structure is used to keep track of the extra colors used by
@@ -146,10 +146,10 @@ Tk_3DVerticalBevel(tkwin, drawable, border, x, y, width, height,
break;
case TK_RELIEF_SUNKEN:
left = (leftBevel)
- ? borderPtr->darkGC->foreground
+ ? ((WinBorder *)borderPtr)->dark2ColorPtr->pixel
: ((WinBorder *)borderPtr)->light2ColorPtr->pixel;
right = (leftBevel)
- ? ((WinBorder *)borderPtr)->dark2ColorPtr->pixel
+ ? borderPtr->darkGC->foreground
: borderPtr->lightGC->foreground;
break;
case TK_RELIEF_RIDGE:
@@ -247,10 +247,10 @@ Tk_3DHorizontalBevel(tkwin, drawable, border, x, y, width, height,
break;
case TK_RELIEF_SUNKEN:
topColor = (topBevel)
- ? borderPtr->darkGC->foreground
+ ? ((WinBorder *)borderPtr)->dark2ColorPtr->pixel
: ((WinBorder *)borderPtr)->light2ColorPtr->pixel;
bottomColor = (topBevel)
- ? ((WinBorder *)borderPtr)->dark2ColorPtr->pixel
+ ? borderPtr->darkGC->foreground
: borderPtr->lightGC->foreground;
break;
case TK_RELIEF_RIDGE:
@@ -342,6 +342,7 @@ TkpGetShadows(borderPtr, tkwin)
{
XColor lightColor, darkColor;
int tmp1, tmp2;
+ int r, g, b;
XGCValues gcValues;
if (borderPtr->lightGC != None) {
@@ -392,42 +393,81 @@ TkpGetShadows(borderPtr, tkwin)
/*
* This is a color display with lots of colors. For the dark
* shadow, cut 40% from each of the background color components.
+ * But if the background is already very dark, make the
+ * dark color a little lighter than the background by increasing
+ * each color component 1/4th of the way to MAX_INTENSITY.
+ *
* For the light shadow, boost each component by 40% or half-way
* to white, whichever is greater (the first approach works
* better for unsaturated colors, the second for saturated ones).
+ * But if the background is already very bright, instead choose a
+ * slightly darker color for the light shadow by reducing each
+ * color component by 10%.
+ *
+ * Compute the colors using integers, not using lightColor.red
+ * etc.: these are shorts and may have problems with integer
+ * overflow.
+ */
+
+ /*
+ * Compute the dark shadow color
+ */
+
+ r = (int) borderPtr->bgColorPtr->red;
+ g = (int) borderPtr->bgColorPtr->green;
+ b = (int) borderPtr->bgColorPtr->blue;
+
+ if (r*0.5*r + g*1.0*g + b*0.28*b < MAX_INTENSITY*0.05*MAX_INTENSITY) {
+ darkColor.red = (MAX_INTENSITY + 3*r)/4;
+ darkColor.green = (MAX_INTENSITY + 3*g)/4;
+ darkColor.blue = (MAX_INTENSITY + 3*b)/4;
+ } else {
+ darkColor.red = (60 * r)/100;
+ darkColor.green = (60 * g)/100;
+ darkColor.blue = (60 * b)/100;
+ }
+
+ /*
+ * Allocate the dark shadow color and its GC
*/
- darkColor.red = (60 * (int) borderPtr->bgColorPtr->red)/100;
- darkColor.green = (60 * (int) borderPtr->bgColorPtr->green)/100;
- darkColor.blue = (60 * (int) borderPtr->bgColorPtr->blue)/100;
borderPtr->darkColorPtr = Tk_GetColorByValue(tkwin, &darkColor);
gcValues.foreground = borderPtr->darkColorPtr->pixel;
borderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
/*
- * Compute the colors using integers, not using lightColor.red
- * etc.: these are shorts and may have problems with integer
- * overflow.
+ * Compute the light shadow color
*/
- tmp1 = (14 * (int) borderPtr->bgColorPtr->red)/10;
- if (tmp1 > MAX_INTENSITY) {
- tmp1 = MAX_INTENSITY;
- }
- tmp2 = (MAX_INTENSITY + (int) borderPtr->bgColorPtr->red)/2;
- lightColor.red = (tmp1 > tmp2) ? tmp1 : tmp2;
- tmp1 = (14 * (int) borderPtr->bgColorPtr->green)/10;
- if (tmp1 > MAX_INTENSITY) {
- tmp1 = MAX_INTENSITY;
- }
- tmp2 = (MAX_INTENSITY + (int) borderPtr->bgColorPtr->green)/2;
- lightColor.green = (tmp1 > tmp2) ? tmp1 : tmp2;
- tmp1 = (14 * (int) borderPtr->bgColorPtr->blue)/10;
- if (tmp1 > MAX_INTENSITY) {
- tmp1 = MAX_INTENSITY;
+ if (g > MAX_INTENSITY*0.95) {
+ lightColor.red = (90 * r)/100;
+ lightColor.green = (90 * g)/100;
+ lightColor.blue = (90 * b)/100;
+ } else {
+ tmp1 = (14 * r)/10;
+ if (tmp1 > MAX_INTENSITY) {
+ tmp1 = MAX_INTENSITY;
+ }
+ tmp2 = (MAX_INTENSITY + r)/2;
+ lightColor.red = (tmp1 > tmp2) ? tmp1 : tmp2;
+ tmp1 = (14 * g)/10;
+ if (tmp1 > MAX_INTENSITY) {
+ tmp1 = MAX_INTENSITY;
+ }
+ tmp2 = (MAX_INTENSITY + g)/2;
+ lightColor.green = (tmp1 > tmp2) ? tmp1 : tmp2;
+ tmp1 = (14 * b)/10;
+ if (tmp1 > MAX_INTENSITY) {
+ tmp1 = MAX_INTENSITY;
+ }
+ tmp2 = (MAX_INTENSITY + b)/2;
+ lightColor.blue = (tmp1 > tmp2) ? tmp1 : tmp2;
}
- tmp2 = (MAX_INTENSITY + (int) borderPtr->bgColorPtr->blue)/2;
- lightColor.blue = (tmp1 > tmp2) ? tmp1 : tmp2;
+
+ /*
+ * Allocate the light shadow color and its GC
+ */
+
borderPtr->lightColorPtr = Tk_GetColorByValue(tkwin, &lightColor);
gcValues.foreground = borderPtr->lightColorPtr->pixel;
borderPtr->lightGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
diff --git a/tk/win/tkWinButton.c b/tk/win/tkWinButton.c
index 3335d66d88b..6b4da6ecc1c 100644
--- a/tk/win/tkWinButton.c
+++ b/tk/win/tkWinButton.c
@@ -4,7 +4,7 @@
* This file implements the Windows specific portion of the button
* widgets.
*
- * Copyright (c) 1996 by Sun Microsystems, Inc.
+ * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -66,26 +66,20 @@ enum {
};
/*
- * Set to non-zero if this module is initialized.
+ * Cached information about the boxes bitmap, and the default border
+ * width for a button in string form for use in Tk_OptionSpec for
+ * the various button widget classes.
*/
-static int initialized = 0;
-
-/*
- * Variables for the cached information about the boxes bitmap.
- */
-
-static BITMAPINFOHEADER *boxesPtr = NULL; /* Information about the bitmap. */
-static DWORD *boxesPalette = NULL; /* Pointer to color palette. */
-static LPSTR boxesBits = NULL; /* Pointer to bitmap data. */
-static DWORD boxHeight = 0, boxWidth = 0; /* Size of each sub-image. */
-
-/*
- * This variable holds the default border width for a button in string
- * form for use in a Tk_ConfigSpec.
- */
-
-static char defWidth[8];
+typedef struct ThreadSpecificData {
+ BITMAPINFOHEADER *boxesPtr; /* Information about the bitmap. */
+ DWORD *boxesPalette; /* Pointer to color palette. */
+ LPSTR boxesBits; /* Pointer to bitmap data. */
+ DWORD boxHeight; /* Height of each sub-image. */
+ DWORD boxWidth ; /* Width of each sub-image. */
+ char defWidth[TCL_INTEGER_SPACE];
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* Declarations for functions defined in this file.
@@ -100,7 +94,6 @@ static DWORD ComputeStyle _ANSI_ARGS_((WinButton* butPtr));
static Window CreateProc _ANSI_ARGS_((Tk_Window tkwin,
Window parent, ClientData instanceData));
static void InitBoxes _ANSI_ARGS_((void));
-static void UpdateButtonDefaults _ANSI_ARGS_((void));
/* CYGNUS LOCAL. */
static void TkpRealDisplayButton _ANSI_ARGS_((ClientData, int));
@@ -150,65 +143,75 @@ InitBoxes()
HGLOBAL hblk;
LPBITMAPINFOHEADER newBitmap;
DWORD size;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
hrsrc = FindResource(module, "buttons", RT_BITMAP);
if (hrsrc) {
hblk = LoadResource(module, hrsrc);
- boxesPtr = (LPBITMAPINFOHEADER)LockResource(hblk);
+ tsdPtr->boxesPtr = (LPBITMAPINFOHEADER)LockResource(hblk);
}
/*
* Copy the DIBitmap into writable memory.
*/
- if (boxesPtr != NULL && !(boxesPtr->biWidth % 4)
- && !(boxesPtr->biHeight % 2)) {
- size = boxesPtr->biSize + (1 << boxesPtr->biBitCount) * sizeof(RGBQUAD)
- + boxesPtr->biSizeImage;
+ if (tsdPtr->boxesPtr != NULL && !(tsdPtr->boxesPtr->biWidth % 4)
+ && !(tsdPtr->boxesPtr->biHeight % 2)) {
+ size = tsdPtr->boxesPtr->biSize + (1 << tsdPtr->boxesPtr->biBitCount)
+ * sizeof(RGBQUAD) + tsdPtr->boxesPtr->biSizeImage;
newBitmap = (LPBITMAPINFOHEADER) ckalloc(size);
- memcpy(newBitmap, boxesPtr, size);
- boxesPtr = newBitmap;
- boxWidth = boxesPtr->biWidth / 4;
- boxHeight = boxesPtr->biHeight / 2;
- boxesPalette = (DWORD*) (((LPSTR)boxesPtr) + boxesPtr->biSize);
- boxesBits = ((LPSTR)boxesPalette)
- + ((1 << boxesPtr->biBitCount) * sizeof(RGBQUAD));
+ memcpy(newBitmap, tsdPtr->boxesPtr, size);
+ tsdPtr->boxesPtr = newBitmap;
+ tsdPtr->boxWidth = tsdPtr->boxesPtr->biWidth / 4;
+ tsdPtr->boxHeight = tsdPtr->boxesPtr->biHeight / 2;
+ tsdPtr->boxesPalette = (DWORD*) (((LPSTR) tsdPtr->boxesPtr)
+ + tsdPtr->boxesPtr->biSize);
+ tsdPtr->boxesBits = ((LPSTR) tsdPtr->boxesPalette)
+ + ((1 << tsdPtr->boxesPtr->biBitCount) * sizeof(RGBQUAD));
} else {
- boxesPtr = NULL;
+ tsdPtr->boxesPtr = NULL;
}
}
/*
*----------------------------------------------------------------------
*
- * UpdateButtonDefaults --
+ * TkpButtonSetDefaults --
*
- * This function retrieves the current system defaults for
- * the button widgets.
+ * This procedure is invoked before option tables are created for
+ * buttons. It modifies some of the default values to match the
+ * current values defined for this platform.
*
* Results:
- * None.
+ * Some of the default values in *specPtr are modified.
*
* Side effects:
- * Updates the configuration defaults for buttons.
+ * Updates some of.
*
*----------------------------------------------------------------------
*/
void
-UpdateButtonDefaults()
+TkpButtonSetDefaults(specPtr)
+ Tk_OptionSpec *specPtr; /* Points to an array of option specs,
+ * terminated by one with type
+ * TK_OPTION_END. */
{
- Tk_ConfigSpec *specPtr;
- int width = GetSystemMetrics(SM_CXEDGE);
-
- if (width == 0) {
- width = 1;
+ int width;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (tsdPtr->defWidth[0] == 0) {
+ width = GetSystemMetrics(SM_CXEDGE);
+ if (width == 0) {
+ width = 1;
+ }
+ sprintf(tsdPtr->defWidth, "%d", width);
}
- sprintf(defWidth, "%d", width);
- for (specPtr = tkpButtonConfigSpecs; specPtr->type != TK_CONFIG_END;
- specPtr++) {
- if (specPtr->offset == Tk_Offset(TkButton, borderWidth)) {
- specPtr->defValue = defWidth;
+ for ( ; specPtr->type != TK_OPTION_END; specPtr++) {
+ if (specPtr->internalOffset == Tk_Offset(TkButton, borderWidth)) {
+ specPtr->defValue = tsdPtr->defWidth;
}
}
}
@@ -235,11 +238,6 @@ TkpCreateButton(tkwin)
{
WinButton *butPtr;
- if (!initialized) {
- UpdateButtonDefaults();
- initialized = 1;
- }
-
butPtr = (WinButton *)ckalloc(sizeof(WinButton));
butPtr->hwnd = NULL;
/* CYGNUS LOCAL: Use the pixmap field. */
@@ -379,13 +377,12 @@ TkpRealDisplayButton(clientData, force)
* it is a flavor of button, so we offset
* the text to make the button appear to
* move up and down as the relief changes. */
+ DWORD *boxesPalette;
- /* CYGNUS LOCAL: If the generic code has asked us to draw
- ourselves, force a full refresh. */
- if ((butPtr->flags & REDRAW_PENDING) != 0) {
- force = 1;
- }
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ boxesPalette= tsdPtr->boxesPalette;
butPtr->flags &= ~REDRAW_PENDING;
if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
return;
@@ -407,16 +404,16 @@ TkpRealDisplayButton(clientData, force)
}
border = butPtr->normalBorder;
- if ((butPtr->state == tkDisabledUid) && (butPtr->disabledFg != NULL)) {
+ if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {
gc = butPtr->disabledGC;
- } else if ((butPtr->state == tkActiveUid)
+ } else if ((butPtr->state == STATE_ACTIVE)
&& !Tk_StrictMotif(butPtr->tkwin)) {
gc = butPtr->activeTextGC;
border = butPtr->activeBorder;
} else {
gc = butPtr->normalTextGC;
}
- if ((butPtr->flags & SELECTED) && (butPtr->state != tkActiveUid)
+ if ((butPtr->flags & SELECTED) && (butPtr->state != STATE_ACTIVE)
&& (butPtr->selectBorder != NULL) && !butPtr->indicatorOn) {
border = butPtr->selectBorder;
}
@@ -437,7 +434,7 @@ TkpRealDisplayButton(clientData, force)
*/
if (butPtr->type == TYPE_BUTTON) {
- defaultWidth = ((butPtr->defaultState == tkActiveUid)
+ defaultWidth = ((butPtr->defaultState == DEFAULT_ACTIVE)
? butPtr->highlightWidth : 0);
offset = 1;
} else {
@@ -546,17 +543,17 @@ TkpRealDisplayButton(clientData, force)
*/
if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn
- && boxesPtr) {
+ && tsdPtr->boxesPtr) {
int xSrc, ySrc;
x -= butPtr->indicatorSpace;
y -= butPtr->indicatorDiameter / 2;
- xSrc = (butPtr->flags & SELECTED) ? boxWidth : 0;
- if (butPtr->state == tkActiveUid) {
- xSrc += boxWidth*2;
+ xSrc = (butPtr->flags & SELECTED) ? tsdPtr->boxWidth : 0;
+ if (butPtr->state == STATE_ACTIVE) {
+ xSrc += tsdPtr->boxWidth*2;
}
- ySrc = (butPtr->type == TYPE_RADIO_BUTTON) ? 0 : boxHeight;
+ ySrc = (butPtr->type == TYPE_RADIO_BUTTON) ? 0 : tsdPtr->boxHeight;
/*
* Update the palette in the boxes bitmap to reflect the current
@@ -576,7 +573,7 @@ TkpRealDisplayButton(clientData, force)
border, TK_3D_LIGHT2));
boxesPalette[PAL_BOTTOM_OUTER] = FlipColor(TkWinGetBorderPixels(tkwin,
border, TK_3D_LIGHT_GC));
- if (butPtr->state == tkDisabledUid) {
+ if (butPtr->state == STATE_DISABLED) {
boxesPalette[PAL_INTERIOR] = FlipColor(TkWinGetBorderPixels(tkwin,
border, TK_3D_LIGHT2));
} else if (butPtr->selectBorder != NULL) {
@@ -589,9 +586,10 @@ TkpRealDisplayButton(clientData, force)
border, TK_3D_FLAT_GC));
dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state);
- StretchDIBits(dc, x, y, boxWidth, boxHeight, xSrc, ySrc,
- boxWidth, boxHeight, boxesBits, (LPBITMAPINFO)boxesPtr,
- DIB_RGB_COLORS, SRCCOPY);
+ StretchDIBits(dc, x, y, tsdPtr->boxWidth, tsdPtr->boxHeight,
+ xSrc, ySrc, tsdPtr->boxWidth, tsdPtr->boxHeight,
+ tsdPtr->boxesBits, (LPBITMAPINFO) tsdPtr->boxesPtr,
+ DIB_RGB_COLORS, SRCCOPY);
TkWinReleaseDrawableDC(pixmap, dc, &state);
}
@@ -602,7 +600,7 @@ TkpRealDisplayButton(clientData, force)
* must temporarily modify the GC.
*/
- if ((butPtr->state == tkDisabledUid)
+ if ((butPtr->state == STATE_DISABLED)
&& ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) {
if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn
&& (butPtr->selectBorder != NULL)) {
@@ -688,6 +686,8 @@ TkpComputeButtonGeometry(butPtr)
{
int width, height, avgWidth;
Tk_FontMetrics fm;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (butPtr->highlightWidth < 0) {
butPtr->highlightWidth = 0;
@@ -695,7 +695,7 @@ TkpComputeButtonGeometry(butPtr)
butPtr->inset = butPtr->highlightWidth + butPtr->borderWidth;
butPtr->indicatorSpace = 0;
- if (!boxesPtr) {
+ if (!tsdPtr->boxesPtr) {
InitBoxes();
}
@@ -709,8 +709,8 @@ TkpComputeButtonGeometry(butPtr)
height = butPtr->height;
}
if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
- butPtr->indicatorSpace = boxWidth * 2;
- butPtr->indicatorDiameter = boxHeight;
+ butPtr->indicatorSpace = tsdPtr->boxWidth * 2;
+ butPtr->indicatorDiameter = tsdPtr->boxHeight;
}
} else if (butPtr->bitmap != None) {
Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
@@ -718,8 +718,8 @@ TkpComputeButtonGeometry(butPtr)
} else {
Tk_FreeTextLayout(butPtr->textLayout);
butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,
- butPtr->text, -1, butPtr->wrapLength, butPtr->justify, 0,
- &butPtr->textWidth, &butPtr->textHeight);
+ Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength,
+ butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);
width = butPtr->textWidth;
height = butPtr->textHeight;
@@ -729,12 +729,15 @@ TkpComputeButtonGeometry(butPtr)
if (butPtr->width > 0) {
width = butPtr->width * avgWidth;
}
- if (butPtr->height > 0) {
+
+ if (butPtr->type == TYPE_BUTTON) {
+ height = butPtr->height * fm.ascent;
+ } else {
height = butPtr->height * fm.linespace;
}
if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
- butPtr->indicatorDiameter = boxHeight;
+ butPtr->indicatorDiameter = tsdPtr->boxHeight;
butPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth;
}
@@ -840,14 +843,21 @@ ButtonProc(hwnd, message, wParam, lParam)
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
- /* CYGNUS LOCAL: Don't force the button to be recomputed. */
- TkpRealDisplayButton((ClientData)butPtr, 0);
+ TkpDisplayButton((ClientData)butPtr);
+
+ /*
+ * Special note: must cancel any existing idle handler
+ * for TkpDisplayButton; it's no longer needed, and
+ * TkpDisplayButton cleared the REDRAW_PENDING flag.
+ */
+
+ Tcl_CancelIdleCall(TkpDisplayButton, (ClientData)butPtr);
return 0;
}
case BN_CLICKED: {
int code;
Tcl_Interp *interp = butPtr->info.interp;
- if (butPtr->info.state != tkDisabledUid) {
+ if (butPtr->info.state != STATE_DISABLED) {
Tcl_Preserve((ClientData)interp);
code = TkInvokeButton((TkButton*)butPtr);
if (code != TCL_OK && code != TCL_CONTINUE
@@ -868,3 +878,4 @@ ButtonProc(hwnd, message, wParam, lParam)
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
+
diff --git a/tk/win/tkWinClipboard.c b/tk/win/tkWinClipboard.c
index d7d73d71995..df94a49aec0 100644
--- a/tk/win/tkWinClipboard.c
+++ b/tk/win/tkWinClipboard.c
@@ -3,7 +3,8 @@
*
* This file contains functions for managing the clipboard.
*
- * Copyright (c) 1995 Sun Microsystems, Inc.
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-2000 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -14,6 +15,7 @@
#include "tkWinInt.h"
#include "tkSelect.h"
+static void UpdateClipboard _ANSI_ARGS_((HWND hwnd));
/*
*----------------------------------------------------------------------
@@ -27,7 +29,7 @@
* Results:
* The return value is a standard Tcl return value.
* If an error occurs (such as no selection exists)
- * then an error message is left in interp->result.
+ * then an error message is left in the interp's result.
*
* Side effects:
* None.
@@ -49,40 +51,126 @@ TkSelGetSelection(interp, tkwin, selection, target, proc, clientData)
* selection, once it has been retrieved. */
ClientData clientData; /* Arbitrary value to pass to proc. */
{
- char *data, *buffer, *destPtr;
+ char *data, *destPtr;
+ Tcl_DString ds;
HGLOBAL handle;
- int result, length;
-
- if ((selection == Tk_InternAtom(tkwin, "CLIPBOARD"))
- && (target == XA_STRING)) {
- if (OpenClipboard(NULL)) {
- handle = GetClipboardData(CF_TEXT);
- if (handle != NULL) {
- data = GlobalLock(handle);
- length = strlen(data);
- buffer = ckalloc(length+1);
- destPtr = buffer;
- while (*data != '\0') {
- if (*data != '\r') {
- *destPtr = *data;
- destPtr++;
- }
- data++;
- }
- *destPtr = '\0';
- GlobalUnlock(handle);
+ Tcl_Encoding encoding;
+ int result, locale;
+
+ if ((selection != Tk_InternAtom(tkwin, "CLIPBOARD"))
+ || (target != XA_STRING)
+ || !OpenClipboard(NULL)) {
+ goto error;
+ }
+
+ /*
+ * Attempt to get the data in Unicode form if available as this is
+ * less work that CF_TEXT.
+ */
+
+ result = TCL_ERROR;
+ if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
+ handle = GetClipboardData(CF_UNICODETEXT);
+ if (!handle) {
+ CloseClipboard();
+ goto error;
+ }
+ data = GlobalLock(handle);
+ Tcl_DStringInit(&ds);
+ Tcl_UniCharToUtfDString((Tcl_UniChar *)data,
+ Tcl_UniCharLen((Tcl_UniChar *)data), &ds);
+ GlobalUnlock(handle);
+ } else if (IsClipboardFormatAvailable(CF_TEXT)) {
+ /*
+ * Determine the encoding to use to convert this text.
+ */
+
+ if (IsClipboardFormatAvailable(CF_LOCALE)) {
+ handle = GetClipboardData(CF_LOCALE);
+ if (!handle) {
CloseClipboard();
- result = (*proc)(clientData, interp, buffer);
- ckfree(buffer);
- return result;
+ goto error;
+ }
+
+ /*
+ * Get the locale identifier, determine the proper code page
+ * to use, and find the corresponding encoding.
+ */
+
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds, "cp######", -1);
+ data = GlobalLock(handle);
+
+
+ /*
+ * Even though the documentation claims that GetLocaleInfo
+ * expects an LCID, on Windows 9x it really seems to expect
+ * a LanguageID.
+ */
+
+ locale = LANGIDFROMLCID(*((int*)data));
+ GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE,
+ Tcl_DStringValue(&ds)+2, Tcl_DStringLength(&ds)-2);
+ GlobalUnlock(handle);
+
+ encoding = Tcl_GetEncoding(NULL, Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+ } else {
+ encoding = NULL;
+ }
+
+ /*
+ * Fetch the text and convert it to UTF.
+ */
+
+ handle = GetClipboardData(CF_TEXT);
+ if (!handle) {
+ if (encoding) {
+ Tcl_FreeEncoding(encoding);
}
CloseClipboard();
+ goto error;
+ }
+ data = GlobalLock(handle);
+ Tcl_ExternalToUtfDString(encoding, data, -1, &ds);
+ GlobalUnlock(handle);
+ if (encoding) {
+ Tcl_FreeEncoding(encoding);
}
+
+ } else {
+ CloseClipboard();
+ goto error;
}
+ /*
+ * Translate CR/LF to LF.
+ */
+
+ data = destPtr = Tcl_DStringValue(&ds);
+ while (*data) {
+ if (data[0] == '\r' && data[1] == '\n') {
+ data++;
+ } else {
+ *destPtr++ = *data++;
+ }
+ }
+ *destPtr = '\0';
+
+ /*
+ * Pass the data off to the selection procedure.
+ */
+
+ result = (*proc)(clientData, interp, Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+ CloseClipboard();
+ return result;
+
+error:
Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection),
- " selection doesn't exist or form \"", Tk_GetAtomName(tkwin, target),
- "\" not defined", (char *) NULL);
+ " selection doesn't exist or form \"",
+ Tk_GetAtomName(tkwin, target),
+ "\" not defined", (char *) NULL);
return TCL_ERROR;
}
@@ -119,7 +207,7 @@ XSetSelectionOwner(display, selection, owner, time)
* It expects a Tk_Window, even though it only needs a Tk_Display.
*/
- tkwin = (Tk_Window)tkMainWindowList->winPtr;
+ tkwin = (Tk_Window) TkGetMainInfoList()->winPtr;
if (selection == Tk_InternAtom(tkwin, "CLIPBOARD")) {
@@ -129,10 +217,7 @@ XSetSelectionOwner(display, selection, owner, time)
*/
if (GetClipboardOwner() != hwnd) {
- OpenClipboard(hwnd);
- EmptyClipboard();
- SetClipboardData(CF_TEXT, NULL);
- CloseClipboard();
+ UpdateClipboard(hwnd);
}
}
}
@@ -162,14 +247,21 @@ TkWinClipboardRender(dispPtr, format)
TkClipboardTarget *targetPtr;
TkClipboardBuffer *cbPtr;
HGLOBAL handle;
- char *buffer, *p, *endPtr;
+ char *buffer, *p, *rawText, *endPtr;
int length;
+ Tcl_DString ds;
for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;
targetPtr = targetPtr->nextPtr) {
if (targetPtr->type == XA_STRING)
break;
}
+
+ /*
+ * Count the number of newlines so we can add space for them in
+ * the resulting string.
+ */
+
length = 0;
if (targetPtr != NULL) {
for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
@@ -183,11 +275,12 @@ TkWinClipboardRender(dispPtr, format)
}
}
}
- handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, length+1);
- if (!handle) {
- return;
- }
- buffer = GlobalLock(handle);
+
+ /*
+ * Copy the data and change EOL characters.
+ */
+
+ buffer = rawText = ckalloc(length + 1);
if (targetPtr != NULL) {
for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
cbPtr = cbPtr->nextPtr) {
@@ -201,8 +294,43 @@ TkWinClipboardRender(dispPtr, format)
}
}
*buffer = '\0';
- GlobalUnlock(handle);
- SetClipboardData(CF_TEXT, handle);
+
+ /*
+ * Depending on the platform, turn the data into Unicode or the
+ * system encoding before placing it on the clipboard.
+ */
+
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
+ Tcl_DStringInit(&ds);
+ Tcl_UtfToUniCharDString(rawText, -1, &ds);
+ ckfree(rawText);
+ handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
+ Tcl_DStringLength(&ds)+2);
+ if (!handle) {
+ Tcl_DStringFree(&ds);
+ return;
+ }
+ buffer = GlobalLock(handle);
+ memcpy(buffer, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds) + 2);
+ GlobalUnlock(handle);
+ Tcl_DStringFree(&ds);
+ SetClipboardData(CF_UNICODETEXT, handle);
+ } else {
+ Tcl_UtfToExternalDString(NULL, rawText, -1, &ds);
+ ckfree(rawText);
+ handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
+ Tcl_DStringLength(&ds)+1);
+ if (!handle) {
+ Tcl_DStringFree(&ds);
+ return;
+ }
+ buffer = GlobalLock(handle);
+ memcpy(buffer, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds) + 1);
+ GlobalUnlock(handle);
+ Tcl_DStringFree(&ds);
+ SetClipboardData(CF_TEXT, handle);
+ }
+
return;
}
@@ -229,11 +357,46 @@ TkSelUpdateClipboard(winPtr, targetPtr)
TkClipboardTarget *targetPtr;
{
HWND hwnd = TkWinGetHWND(winPtr->window);
+ UpdateClipboard(hwnd);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateClipboard --
+ *
+ * Take ownership of the clipboard, clear it, and indicate to the
+ * system the supported formats.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+UpdateClipboard(hwnd)
+ HWND hwnd;
+{
+ TkWinUpdatingClipboard(TRUE);
OpenClipboard(hwnd);
EmptyClipboard();
- SetClipboardData(CF_TEXT, NULL);
+
+ /*
+ * CF_UNICODETEXT is only supported on NT, but it it is prefered
+ * when possible.
+ */
+
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
+ SetClipboardData(CF_UNICODETEXT, NULL);
+ } else {
+ SetClipboardData(CF_TEXT, NULL);
+ }
CloseClipboard();
+ TkWinUpdatingClipboard(FALSE);
}
/*
@@ -289,3 +452,5 @@ TkSelPropProc(eventPtr)
register XEvent *eventPtr; /* X PropertyChange event. */
{
}
+
+
diff --git a/tk/win/tkWinColor.c b/tk/win/tkWinColor.c
index 20dd3ed13a0..e05f0c692e0 100644
--- a/tk/win/tkWinColor.c
+++ b/tk/win/tkWinColor.c
@@ -12,8 +12,8 @@
* RCS: @(#) $Id$
*/
-#include <tkColor.h>
-#include <tkWinInt.h>
+#include "tkWinInt.h"
+#include "tkColor.h"
/*
* The following structure is used to keep track of each color that is
@@ -27,12 +27,6 @@ typedef struct WinColor {
} WinColor;
/*
- * colorTable is a hash table used to look up X colors by name.
- */
-
-static Tcl_HashTable colorTable;
-
-/*
* The sysColors array contains the names and index values for the
* Windows indirect system color names. In use, all of the names
* will have the string "System" prepended, but we omit it in the table
@@ -75,7 +69,10 @@ static SystemColorEntry sysColors[] = {
NULL, 0
};
-static int ncolors = 0;
+typedef struct ThreadSpecificData {
+ int ncolors;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* Forward declarations for functions defined later in this file.
@@ -111,13 +108,15 @@ FindSystemColor(name, colorPtr, indexPtr)
int *indexPtr; /* Out parameter to store color index. */
{
int l, u, r, i;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* Count the number of elements in the color array if we haven't
* done so yet.
*/
- if (ncolors == 0) {
+ if (tsdPtr->ncolors == 0) {
SystemColorEntry *ePtr;
int version;
@@ -130,7 +129,7 @@ FindSystemColor(name, colorPtr, indexPtr)
ePtr->index = COLOR_BTNHIGHLIGHT;
}
}
- ncolors++;
+ tsdPtr->ncolors++;
}
}
@@ -139,7 +138,7 @@ FindSystemColor(name, colorPtr, indexPtr)
*/
l = 0;
- u = ncolors - 1;
+ u = tsdPtr->ncolors - 1;
while (l <= u) {
i = (l + u) / 2;
r = strcasecmp(name, sysColors[i].name);
@@ -157,9 +156,13 @@ FindSystemColor(name, colorPtr, indexPtr)
*indexPtr = sysColors[i].index;
colorPtr->pixel = GetSysColor(sysColors[i].index);
- colorPtr->red = GetRValue(colorPtr->pixel) << 8;
- colorPtr->green = GetGValue(colorPtr->pixel) << 8;
- colorPtr->blue = GetBValue(colorPtr->pixel) << 8;
+ /*
+ * x257 is (value<<8 + value) to get the properly bit shifted
+ * and padded value. [Bug: 4919]
+ */
+ colorPtr->red = GetRValue(colorPtr->pixel) * 257;
+ colorPtr->green = GetGValue(colorPtr->pixel) * 257;
+ colorPtr->blue = GetBValue(colorPtr->pixel) * 257;
colorPtr->flags = DoRed|DoGreen|DoBlue;
colorPtr->pad = 0;
return 1;
@@ -339,7 +342,7 @@ XAllocColor(display, colormap, color)
TkWinColormap *cmap = (TkWinColormap *) colormap;
PALETTEENTRY entry, closeEntry;
HDC dc = GetDC(NULL);
-
+
entry.peRed = (color->red) >> 8;
entry.peGreen = (color->green) >> 8;
entry.peBlue = (color->blue) >> 8;
@@ -374,9 +377,9 @@ XAllocColor(display, colormap, color)
if ((index >= cmap->size) || (newPixel != closePixel)) {
if (cmap->size == sizePalette) {
- color->red = closeEntry.peRed << 8;
- color->green = closeEntry.peGreen << 8;
- color->blue = closeEntry.peBlue << 8;
+ color->red = closeEntry.peRed * 257;
+ color->green = closeEntry.peGreen * 257;
+ color->blue = closeEntry.peBlue * 257;
entry = closeEntry;
if (index >= cmap->size) {
OutputDebugString("XAllocColor: Colormap is bigger than we thought");
@@ -405,9 +408,9 @@ XAllocColor(display, colormap, color)
color->pixel = GetNearestColor(dc,
RGB(entry.peRed, entry.peGreen, entry.peBlue));
- color->red = (GetRValue(color->pixel) << 8);
- color->green = (GetGValue(color->pixel) << 8);
- color->blue = (GetBValue(color->pixel) << 8);
+ color->red = GetRValue(color->pixel) * 257;
+ color->green = GetGValue(color->pixel) * 257;
+ color->blue = GetBValue(color->pixel) * 257;
}
ReleaseDC(NULL, dc);
@@ -613,31 +616,3 @@ TkWinSelectPalette(dc, colormap)
RealizePalette(dc);
return oldPalette;
}
-
-/* CYGNUS LOCAL: The system colors have changed. Update them. */
-
-static void
-ChangeColor(tkColPtr)
- TkColor *tkColPtr;
-{
- WinColor *winColPtr = (WinColor *) tkColPtr;
-
- if (winColPtr->index != -1) {
- unsigned long pixel;
-
- pixel = GetSysColor(winColPtr->index);
- if (pixel != winColPtr->info.color.pixel) {
- winColPtr->info.color.pixel = pixel;
- winColPtr->info.color.red = GetRValue(pixel) << 8;
- winColPtr->info.color.green = GetGValue(pixel) << 8;
- winColPtr->info.color.blue = GetBValue(pixel) << 8;
- TkColorChanged((TkColor *) winColPtr);
- }
- }
-}
-
-void
-TkWinSysColorChange()
-{
- TkMapOverColors(ChangeColor);
-}
diff --git a/tk/win/tkWinConfig.c b/tk/win/tkWinConfig.c
new file mode 100644
index 00000000000..c8c4f76cf55
--- /dev/null
+++ b/tk/win/tkWinConfig.c
@@ -0,0 +1,61 @@
+/*
+ * tkWinConfig.c --
+ *
+ * This module implements the Windows system defaults for
+ * the configuration package.
+ *
+ * Copyright (c) 1997 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#include "tk.h"
+#include "tkInt.h"
+#include "tkWinInt.h"
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetSystemDefault --
+ *
+ * Given a dbName and className for a configuration option,
+ * return a string representation of the option.
+ *
+ * Results:
+ * Returns a Tk_Uid that is the string identifier that identifies
+ * this option. Returns NULL if there are no system defaults
+ * that match this pair.
+ *
+ * Side effects:
+ * None, once the package is initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TkpGetSystemDefault(
+ Tk_Window tkwin, /* A window to use. */
+ char *dbName, /* The option database name. */
+ char *className) /* The name of the option class. */
+{
+ Tcl_Obj *valueObjPtr;
+ Tk_Uid classUid;
+
+ if (tkwin == NULL) {
+ return NULL;
+ }
+
+ valueObjPtr = NULL;
+ classUid = Tk_Class(tkwin);
+
+ if (strcmp(classUid, "Menu") == 0) {
+ valueObjPtr = TkWinGetMenuSystemDefault(tkwin, dbName, className);
+ }
+
+ return valueObjPtr;
+}
+
diff --git a/tk/win/tkWinCursor.c b/tk/win/tkWinCursor.c
index 33c5ef9c213..6ed11a7a90d 100644
--- a/tk/win/tkWinCursor.c
+++ b/tk/win/tkWinCursor.c
@@ -109,7 +109,36 @@ TkGetCursorByName(interp, tkwin, string)
cursorPtr->winCursor = LoadCursor(Tk_GetHINSTANCE(), string);
cursorPtr->system = 0;
}
+ if (string[0] == '@') {
+ int argc;
+ char **argv = NULL;
+ if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) {
+ return NULL;
+ }
+ /*
+ * Check for system cursor of type @<filename>, where only
+ * the name is allowed. This accepts either:
+ * -cursor @/winnt/cursors/globe.ani
+ * -cursor @C:/Winnt/cursors/E_arrow.cur
+ * -cursor {@C:/Program\ Files/Cursors/bart.ani}
+ */
+ if ((argc != 1) || (argv[0][0] != '@')) {
+ ckfree((char *) argv);
+ goto badCursorSpec;
+ }
+ if (Tcl_IsSafe(interp)) {
+ Tcl_AppendResult(interp, "can't get cursor from a file in",
+ " a safe interpreter", (char *) NULL);
+ ckfree((char *) argv);
+ ckfree((char *)cursorPtr);
+ return NULL;
+ }
+ cursorPtr->winCursor = LoadCursorFromFile(&(argv[0][1]));
+ cursorPtr->system = 0;
+ ckfree((char *) argv);
+ }
if (cursorPtr->winCursor == NULL) {
+ badCursorSpec:
ckfree((char *)cursorPtr);
Tcl_AppendResult(interp, "bad cursor spec \"", string, "\"",
(char *) NULL);
@@ -152,7 +181,7 @@ TkCreateCursorFromData(tkwin, source, mask, width, height, xHot, yHot,
/*
*----------------------------------------------------------------------
*
- * TkFreeCursor --
+ * TkpFreeCursor --
*
* This procedure is called to release a cursor allocated by
* TkGetCursorByName.
@@ -167,11 +196,10 @@ TkCreateCursorFromData(tkwin, source, mask, width, height, xHot, yHot,
*/
void
-TkFreeCursor(cursorPtr)
+TkpFreeCursor(cursorPtr)
TkCursor *cursorPtr;
{
TkWinCursor *winCursorPtr = (TkWinCursor *) cursorPtr;
- ckfree((char *) winCursorPtr);
}
/*
@@ -208,3 +236,4 @@ TkpSetCursor(cursor)
SetCursor(hcursor);
}
}
+
diff --git a/tk/win/tkWinDefault.h b/tk/win/tkWinDefault.h
index 65ea546d659..3860cce0a33 100644
--- a/tk/win/tkWinDefault.h
+++ b/tk/win/tkWinDefault.h
@@ -65,7 +65,8 @@
#define DEF_CHKRAD_FG TEXT_FG
#define DEF_BUTTON_FONT CTL_FONT
#define DEF_BUTTON_HEIGHT "0"
-#define DEF_BUTTON_HIGHLIGHT_BG NORMAL_BG
+#define DEF_BUTTON_HIGHLIGHT_BG_COLOR DEF_BUTTON_BG_COLOR
+#define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO
#define DEF_BUTTON_HIGHLIGHT HIGHLIGHT
#define DEF_LABEL_HIGHLIGHT_WIDTH "0"
#define DEF_BUTTON_HIGHLIGHT_WIDTH "1"
@@ -76,7 +77,7 @@
#define DEF_BUTTON_ON_VALUE "1"
#define DEF_BUTTON_PADX "1"
#define DEF_LABCHKRAD_PADX "1"
-#define DEF_BUTTON_PADY "1"
+#define DEF_BUTTON_PADY "4.5"
#define DEF_LABCHKRAD_PADY "1"
#define DEF_BUTTON_RELIEF "raised"
#define DEF_LABCHKRAD_RELIEF "flat"
@@ -203,6 +204,7 @@
#define DEF_LISTBOX_HIGHLIGHT_WIDTH "1"
#define DEF_LISTBOX_RELIEF "sunken"
#define DEF_LISTBOX_SCROLL_COMMAND ""
+#define DEF_LISTBOX_LIST_VARIABLE ""
#define DEF_LISTBOX_SELECT_COLOR SELECT_BG
#define DEF_LISTBOX_SELECT_MONO BLACK
#define DEF_LISTBOX_SELECT_BD "1"
@@ -288,7 +290,8 @@
#define DEF_MENUBUTTON_FONT CTL_FONT
#define DEF_MENUBUTTON_FG NORMAL_FG
#define DEF_MENUBUTTON_HEIGHT "0"
-#define DEF_MENUBUTTON_HIGHLIGHT_BG NORMAL_BG
+#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR
+#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO
#define DEF_MENUBUTTON_HIGHLIGHT HIGHLIGHT
#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0"
#define DEF_MENUBUTTON_IMAGE (char *) NULL
@@ -347,7 +350,8 @@
#define DEF_SCALE_FG_COLOR NORMAL_FG
#define DEF_SCALE_FG_MONO BLACK
#define DEF_SCALE_FROM "0"
-#define DEF_SCALE_HIGHLIGHT_BG NORMAL_BG
+#define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR
+#define DEF_SCALE_HIGHLIGHT_BG_MONO DEF_SCALE_BG_MONO
#define DEF_SCALE_HIGHLIGHT HIGHLIGHT
#define DEF_SCALE_HIGHLIGHT_WIDTH "2"
#define DEF_SCALE_LABEL ""
@@ -455,3 +459,4 @@
#define DEF_TOPLEVEL_SCREEN ""
#endif /* _TKWINDEFAULT */
+
diff --git a/tk/win/tkWinDialog.c b/tk/win/tkWinDialog.c
index d2229d6bf56..3d0b2e1fddd 100644
--- a/tk/win/tkWinDialog.c
+++ b/tk/win/tkWinDialog.c
@@ -1,3 +1,4 @@
+
/*
* tkWinDialog.c --
*
@@ -11,7 +12,7 @@
* RCS: @(#) $Id$
*
*/
-
+
#include "tkWinInt.h"
#include "tkFileFilter.h"
@@ -19,138 +20,144 @@
#include <dlgs.h> /* includes common dialog template defines */
#include <cderr.h> /* includes the common dialog error codes */
-#if ((TK_MAJOR_VERSION == 4) && (TK_MINOR_VERSION <= 2))
+typedef struct ThreadSpecificData {
+ int debugFlag; /* Flags whether we should output debugging
+ * information while displaying a builtin
+ * dialog. */
+ Tcl_Interp *debugInterp; /* Interpreter to used for debugging. */
+ UINT WM_LBSELCHANGED; /* Holds a registered windows event used for
+ * communicating between the Directory
+ * Chooser dialog and its hook proc. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
/*
- * The following function is implemented on tk4.3 and after only
+ * The following structures are used by Tk_MessageBoxCmd() to parse
+ * arguments and return results.
*/
-#define Tk_GetHWND TkWinGetHWND
-#endif
-#define SAVE_FILE 0
-#define OPEN_FILE 1
+static const TkStateMap iconMap[] = {
+ {MB_ICONERROR, "error"},
+ {MB_ICONINFORMATION, "info"},
+ {MB_ICONQUESTION, "question"},
+ {MB_ICONWARNING, "warning"},
+ {-1, NULL}
+};
+
+static const TkStateMap typeMap[] = {
+ {MB_ABORTRETRYIGNORE, "abortretryignore"},
+ {MB_OK, "ok"},
+ {MB_OKCANCEL, "okcancel"},
+ {MB_RETRYCANCEL, "retrycancel"},
+ {MB_YESNO, "yesno"},
+ {MB_YESNOCANCEL, "yesnocancel"},
+ {-1, NULL}
+};
-/*----------------------------------------------------------------------
- * MsgTypeInfo --
- *
- * This structure stores the type of available message box in an
- * easy-to-process format. Used by th Tk_MessageBox() function
- *----------------------------------------------------------------------
- */
-typedef struct MsgTypeInfo {
- char * name;
- int type;
- int numButtons;
- char * btnNames[3];
-} MsgTypeInfo;
-
-#define NUM_TYPES 6
-
-static MsgTypeInfo
-msgTypeInfo[NUM_TYPES] = {
- {"abortretryignore", MB_ABORTRETRYIGNORE, 3, {"abort", "retry", "ignore"}},
- {"ok", MB_OK, 1, {"ok" }},
- {"okcancel", MB_OKCANCEL, 2, {"ok", "cancel" }},
- {"retrycancel", MB_RETRYCANCEL, 2, {"retry", "cancel" }},
- {"yesno", MB_YESNO, 2, {"yes", "no" }},
- {"yesnocancel", MB_YESNOCANCEL, 3, {"yes", "no", "cancel"}}
+static const TkStateMap buttonMap[] = {
+ {IDABORT, "abort"},
+ {IDRETRY, "retry"},
+ {IDIGNORE, "ignore"},
+ {IDOK, "ok"},
+ {IDCANCEL, "cancel"},
+ {IDNO, "no"},
+ {IDYES, "yes"},
+ {-1, NULL}
};
+static const int buttonFlagMap[] = {
+ MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON3, MB_DEFBUTTON4
+};
+
+static const struct {int type; int btnIds[3];} allowedTypes[] = {
+ {MB_ABORTRETRYIGNORE, {IDABORT, IDRETRY, IDIGNORE}},
+ {MB_OK, {IDOK, -1, -1 }},
+ {MB_OKCANCEL, {IDOK, IDCANCEL, -1 }},
+ {MB_RETRYCANCEL, {IDRETRY, IDCANCEL, -1 }},
+ {MB_YESNO, {IDYES, IDNO, -1 }},
+ {MB_YESNOCANCEL, {IDYES, IDNO, IDCANCEL}}
+};
+
+#define NUM_TYPES (sizeof(allowedTypes) / sizeof(allowedTypes[0]))
+
/*
- * The following structure is used in the GetOpenFileName() and
- * GetSaveFileName() calls.
+ * The following structure is used to pass information between the directory
+ * chooser procedure, Tk_ChooseDirectoryObjCmd(), and its dialog hook proc.
*/
-typedef struct _OpenFileData {
- Tcl_Interp * interp;
- TCHAR szFile[(256*MAX_PATH)+1];
-} OpenFileData;
+
+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. */
+} ChooseDir;
/*
- * The following structure is used in the ChooseColor() call.
+ * Definitions of procedures used only in this file.
*/
-typedef struct _ChooseColorData {
- Tcl_Interp * interp;
- char * title; /* Title of the color dialog */
-} ChooseColorData;
-
-
-static int GetFileName _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv,
- int isOpen));
-static UINT CALLBACK ColorDlgHookProc _ANSI_ARGS_((HWND hDlg, UINT uMsg,
- WPARAM wParam, LPARAM lParam));
-static int MakeFilter _ANSI_ARGS_((Tcl_Interp *interp,
- OPENFILENAME *ofnPtr, char * string));
-static int ParseFileDlgArgs _ANSI_ARGS_((Tcl_Interp * interp,
- OPENFILENAME *ofnPtr, int argc, char ** argv,
- int isOpen));
-static int ProcessCDError _ANSI_ARGS_((Tcl_Interp * interp,
- DWORD dwErrorCode, HWND hWnd));
+
+static UINT APIENTRY ChooseDirectoryHookProc(HWND hdlg, UINT uMsg,
+ WPARAM 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,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[], int isOpen);
+static int MakeFilter(Tcl_Interp *interp, char *string,
+ Tcl_DString *dsPtr);
+static UINT APIENTRY OFNHookProc(HWND hdlg, UINT uMsg, WPARAM wParam,
+ LPARAM lParam);
+static UINT APIENTRY OFNHookProcW(HWND hdlg, UINT uMsg, WPARAM wParam,
+ LPARAM lParam);
+static void SetTkDialog(ClientData clientData);
+static int TrySetDirectory(HWND hwnd, const TCHAR *dir);
/*
- *----------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*
- * EvalArgv --
+ * TkWinDialogDebug --
*
- * Invokes the Tcl procedure with the arguments. argv[0] is set by
- * the caller of this function. It may be different than cmdName.
- * The TCL command will see argv[0], not cmdName, as its name if it
- * invokes [lindex [info level 0] 0]
+ * Function to turn on/off debugging support for common dialogs under
+ * windows. The variable "tk_debug" is set to the identifier of the
+ * dialog window when the modal dialog window pops up and it is safe to
+ * send messages to the dialog.
*
* Results:
- * TCL_ERROR if the command does not exist and cannot be autoloaded.
- * Otherwise, return the result of the evaluation of the command.
+ * None.
*
* Side effects:
- * The command may be autoloaded.
+ * This variable only makes sense if just one dialog is up at a time.
*
- *----------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*/
-static int
-EvalArgv(interp, cmdName, argc, argv)
- Tcl_Interp *interp; /* Current interpreter. */
- char * cmdName; /* Name of the TCL command to call */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+void
+TkWinDialogDebug(
+ int debug)
{
- Tcl_CmdInfo cmdInfo;
-
- if (!Tcl_GetCommandInfo(interp, cmdName, &cmdInfo)) {
- char * cmdArgv[2];
-
- /*
- * This comand is not in the interpreter yet -- looks like we
- * have to auto-load it
- */
- if (!Tcl_GetCommandInfo(interp, "auto_load", &cmdInfo)) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "cannot execute command \"auto_load\"",
- NULL);
- return TCL_ERROR;
- }
-
- cmdArgv[0] = "auto_load";
- cmdArgv[1] = cmdName;
-
- if ((*cmdInfo.proc)(cmdInfo.clientData, interp, 2, cmdArgv)!= TCL_OK){
- return TCL_ERROR;
- }
-
- if (!Tcl_GetCommandInfo(interp, cmdName, &cmdInfo)) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "cannot auto-load command \"",
- cmdName, "\"",NULL);
- return TCL_ERROR;
- }
- }
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- return (*cmdInfo.proc)(cmdInfo.clientData, interp, argc, argv);
+ tsdPtr->debugFlag = debug;
}
/*
- *----------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*
- * Tk_ChooseColorCmd --
+ * Tk_ChooseColorObjCmd --
*
* This procedure implements the color dialog box for the Windows
* platform. See the user documentation for details on what it
@@ -164,111 +171,120 @@ EvalArgv(interp, cmdName, argc, argv)
* This window is not destroyed and will be reused the next time the
* application invokes the "tk_chooseColor" command.
*
- *----------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*/
int
-Tk_ChooseColorCmd(clientData, interp, argc, argv)
+Tk_ChooseColorObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
{
- Tk_Window parent = Tk_MainWindow(interp);
- ChooseColorData custData;
- int oldMode;
+ Tk_Window tkwin, parent;
+ HWND hWnd;
+ int i, oldMode, winCode;
CHOOSECOLOR chooseColor;
- char * colorStr = NULL;
- int i;
- int winCode, tclCode;
- XColor * colorPtr = NULL;
static inited = 0;
- static long dwCustColors[16];
+ static COLORREF dwCustColors[16];
static long oldColor; /* the color selected last time */
-
- custData.title = NULL;
-
- if (!inited) {
+ static char *optionStrings[] = {
+ "-initialcolor", "-parent", "-title", NULL
+ };
+ enum options {
+ COLOR_INITIAL, COLOR_PARENT, COLOR_TITLE
+ };
+
+ if (inited == 0) {
/*
* dwCustColors stores the custom color which the user can
- * modify. We store these colors in a fixed array so that the next
+ * modify. We store these colors in a static array so that the next
* time the color dialog pops up, the same set of custom colors
* remain in the dialog.
*/
- for (i=0; i<16; i++) {
- dwCustColors[i] = (RGB(255-i*10, i, i*10)) ;
+ for (i = 0; i < 16; i++) {
+ dwCustColors[i] = RGB(255-i * 10, i, i * 10);
}
- oldColor = RGB(0xa0,0xa0,0xa0);
+ oldColor = RGB(0xa0, 0xa0, 0xa0);
inited = 1;
}
- /*
- * 1. Parse the arguments
- */
-
- chooseColor.lStructSize = sizeof(CHOOSECOLOR) ;
- chooseColor.hwndOwner = 0; /* filled in below */
- chooseColor.hInstance = 0;
- chooseColor.rgbResult = oldColor;
- chooseColor.lpCustColors = (LPDWORD) dwCustColors ;
- chooseColor.Flags = CC_RGBINIT | CC_FULLOPEN | CC_ENABLEHOOK;
- chooseColor.lCustData = (LPARAM)&custData;
- chooseColor.lpfnHook = ColorDlgHookProc;
- chooseColor.lpTemplateName = NULL;
-
- for (i=1; i<argc; i+=2) {
- int v = i+1;
- int len = strlen(argv[i]);
-
- if (strncmp(argv[i], "-initialcolor", len)==0) {
- if (v==argc) {goto arg_missing;}
-
- colorStr = argv[v];
- }
- else if (strncmp(argv[i], "-parent", len)==0) {
- if (v==argc) {goto arg_missing;}
-
- parent=Tk_NameToWindow(interp, argv[v], Tk_MainWindow(interp));
- if (parent == NULL) {
- return TCL_ERROR;
- }
- }
- else if (strncmp(argv[i], "-title", len)==0) {
- if (v==argc) {goto arg_missing;}
-
- custData.title = argv[v];
+ tkwin = (Tk_Window) clientData;
+
+ parent = tkwin;
+ chooseColor.lStructSize = sizeof(CHOOSECOLOR);
+ chooseColor.hwndOwner = NULL;
+ chooseColor.hInstance = NULL;
+ chooseColor.rgbResult = oldColor;
+ chooseColor.lpCustColors = dwCustColors;
+ chooseColor.Flags = CC_RGBINIT | CC_FULLOPEN | CC_ENABLEHOOK;
+ chooseColor.lCustData = (LPARAM) NULL;
+ chooseColor.lpfnHook = ColorDlgHookProc;
+ chooseColor.lpTemplateName = (LPTSTR) interp;
+
+ 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",
+ TCL_EXACT, &index) != TCL_OK) {
+ return TCL_ERROR;
}
- else {
- Tcl_AppendResult(interp, "unknown option \"",
- argv[i], "\", must be -initialcolor, -parent or -title",
- NULL);
- return TCL_ERROR;
+ if (i + 1 == objc) {
+ string = Tcl_GetStringFromObj(optionPtr, NULL);
+ Tcl_AppendResult(interp, "value for \"", string, "\" missing",
+ (char *) NULL);
+ return TCL_ERROR;
}
- }
- if (Tk_WindowId(parent) == None) {
- Tk_MakeWindowExist(parent);
- }
- chooseColor.hwndOwner = Tk_GetHWND(Tk_WindowId(parent));
+ string = Tcl_GetStringFromObj(valuePtr, NULL);
+ switch ((enum options) index) {
+ case COLOR_INITIAL: {
+ XColor *colorPtr;
- if (colorStr != NULL) {
- colorPtr = Tk_GetColor(interp, Tk_MainWindow(interp), colorStr);
- if (!colorPtr) {
- return TCL_ERROR;
+ colorPtr = Tk_GetColor(interp, tkwin, string);
+ if (colorPtr == NULL) {
+ return TCL_ERROR;
+ }
+ chooseColor.rgbResult = RGB(colorPtr->red / 0x100,
+ colorPtr->green / 0x100, colorPtr->blue / 0x100);
+ break;
+ }
+ case COLOR_PARENT: {
+ parent = Tk_NameToWindow(interp, string, tkwin);
+ if (parent == NULL) {
+ return TCL_ERROR;
+ }
+ break;
+ }
+ case COLOR_TITLE: {
+ chooseColor.lCustData = (LPARAM) string;
+ break;
+ }
}
- chooseColor.rgbResult = RGB((colorPtr->red/0x100),
- (colorPtr->green/0x100), (colorPtr->blue/0x100));
- }
-
- /*
- * 2. Popup the dialog
- */
+ }
+ Tk_MakeWindowExist(parent);
+ chooseColor.hwndOwner = NULL;
+ hWnd = Tk_GetHWND(Tk_WindowId(parent));
+ chooseColor.hwndOwner = hWnd;
+
oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
winCode = ChooseColor(&chooseColor);
(void) Tcl_SetServiceMode(oldMode);
/*
+ * 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.
*/
@@ -278,6 +294,7 @@ Tk_ChooseColorCmd(clientData, interp, argc, argv)
/*
* 3. Process the result of the dialog
*/
+
if (winCode) {
/*
* User has selected a color
@@ -285,75 +302,67 @@ Tk_ChooseColorCmd(clientData, interp, argc, argv)
char result[100];
sprintf(result, "#%02x%02x%02x",
- GetRValue(chooseColor.rgbResult),
- GetGValue(chooseColor.rgbResult),
- GetBValue(chooseColor.rgbResult));
+ GetRValue(chooseColor.rgbResult),
+ GetGValue(chooseColor.rgbResult),
+ GetBValue(chooseColor.rgbResult));
Tcl_AppendResult(interp, result, NULL);
- tclCode = TCL_OK;
-
oldColor = chooseColor.rgbResult;
- } else {
- /*
- * User probably pressed Cancel, or an error occurred
- */
- tclCode = ProcessCDError(interp, CommDlgExtendedError(),
- chooseColor.hwndOwner);
- }
-
- if (colorPtr) {
- Tk_FreeColor(colorPtr);
}
-
- return tclCode;
-
- arg_missing:
- Tcl_AppendResult(interp, "value for \"", argv[argc-1], "\" missing",
- NULL);
- return TCL_ERROR;
+ return TCL_OK;
}
/*
- *----------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*
* ColorDlgHookProc --
*
- * Gets called during the execution of the color dialog. It processes
- * the "interesting" messages that Windows send to the dialog.
+ * Provides special handling of messages for the Color common dialog
+ * box. Used to set the title when the dialog first appears.
*
* Results:
- * TRUE if the message has been processed, FALSE otherwise.
+ * The return value is 0 if the default dialog box procedure should
+ * handle the message, non-zero otherwise.
*
* Side effects:
- * Changes the title of the dialog window when it is popped up.
+ * Changes the title of the dialog window.
*
*----------------------------------------------------------------------
*/
-static UINT
-CALLBACK ColorDlgHookProc(hDlg, uMsg, wParam, lParam)
- HWND hDlg; /* Handle to the color dialog */
- UINT uMsg; /* Type of message */
- WPARAM wParam; /* word param, interpretation depends on uMsg*/
- LPARAM lParam; /* long param, interpretation depends on uMsg*/
+static UINT CALLBACK
+ColorDlgHookProc(hDlg, uMsg, wParam, lParam)
+ HWND hDlg; /* Handle to the color dialog. */
+ UINT uMsg; /* Type of message. */
+ WPARAM wParam; /* First message parameter. */
+ LPARAM lParam; /* Second message parameter. */
{
- CHOOSECOLOR * ccPtr;
- ChooseColorData * pCustData;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
switch (uMsg) {
- case WM_INITDIALOG:
- /* Save the pointer to CHOOSECOLOR so that we can use it later */
- SetWindowLong(hDlg, DWL_USER, lParam);
-
- /* Set the title string of the dialog */
- ccPtr = (CHOOSECOLOR*)lParam;
- pCustData = (ChooseColorData*)(ccPtr->lCustData);
- if (pCustData->title && *(pCustData->title)) {
- SetWindowText(hDlg, (LPCSTR)pCustData->title);
- }
+ case WM_INITDIALOG: {
+ const char *title;
+ CHOOSECOLOR *ccPtr;
+ Tcl_DString ds;
- return TRUE;
- }
+ /*
+ * Set the title string of the dialog.
+ */
+ ccPtr = (CHOOSECOLOR *) lParam;
+ title = (const char *) ccPtr->lCustData;
+ if ((title != NULL) && (title[0] != '\0')) {
+ Tcl_UtfToExternalDString(NULL, title, -1, &ds);
+ SetWindowText(hDlg, (TCHAR *) Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+ }
+ if (tsdPtr->debugFlag) {
+ tsdPtr->debugInterp = (Tcl_Interp *) ccPtr->lpTemplateName;
+ Tcl_DoWhenIdle(SetTkDialog, (ClientData) hDlg);
+ }
+ return TRUE;
+ }
+ }
return FALSE;
}
@@ -371,21 +380,22 @@ CALLBACK ColorDlgHookProc(hDlg, uMsg, wParam, lParam)
*
* Side effects:
* A dialog window is created the first this procedure is called.
- * This window is not destroyed and will be reused the next time
- * the application invokes the "tk_getOpenFile" or
- * "tk_getSaveFile" command.
*
*----------------------------------------------------------------------
*/
int
-Tk_GetOpenFileCmd(clientData, interp, argc, argv)
+Tk_GetOpenFileObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
{
- return GetFileName(clientData, interp, argc, argv, OPEN_FILE);
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
+ return GetFileNameW(clientData, interp, objc, objv, 1);
+ } else {
+ return GetFileNameA(clientData, interp, objc, objv, 1);
+ }
}
/*
@@ -406,19 +416,23 @@ Tk_GetOpenFileCmd(clientData, interp, argc, argv)
*/
int
-Tk_GetSaveFileCmd(clientData, interp, argc, argv)
+Tk_GetSaveFileObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
{
- return GetFileName(clientData, interp, argc, argv, SAVE_FILE);
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
+ return GetFileNameW(clientData, interp, objc, objv, 0);
+ } else {
+ return GetFileNameA(clientData, interp, objc, objv, 0);
+ }
}
/*
*----------------------------------------------------------------------
*
- * GetFileName --
+ * GetFileNameW --
*
* Calls GetOpenFileName() or GetSaveFileName().
*
@@ -432,41 +446,197 @@ Tk_GetSaveFileCmd(clientData, interp, argc, argv)
*/
static int
-GetFileName(clientData, interp, argc, argv, isOpen)
+GetFileNameW(clientData, interp, objc, objv, open)
ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
- int isOpen; /* true if we should call GetOpenFileName(),
- * false if we should call GetSaveFileName() */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+ int open; /* 1 to call GetOpenFileName(), 0 to
+ * call GetSaveFileName(). */
{
- OPENFILENAME openFileName, *ofnPtr;
- int tclCode, winCode, oldMode;
- OpenFileData *custData;
- char buffer[MAX_PATH+1];
-
- ofnPtr = &openFileName;
+ Tcl_Encoding unicodeEncoding = Tcl_GetEncoding(NULL, "unicode");
+ OPENFILENAMEW ofn;
+ WCHAR file[MAX_PATH];
+ int result, winCode, oldMode, i;
+ char *extension, *filter, *title;
+ Tk_Window tkwin;
+ HWND hWnd;
+ Tcl_DString utfFilterString, utfDirString;
+ Tcl_DString extString, filterString, dirString, titleString;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ static char *optionStrings[] = {
+ "-defaultextension", "-filetypes", "-initialdir", "-initialfile",
+ "-parent", "-title", NULL
+ };
+ enum options {
+ FILE_DEFAULT, FILE_TYPES, FILE_INITDIR, FILE_INITFILE,
+ FILE_PARENT, FILE_TITLE
+ };
+
+ result = TCL_ERROR;
+ file[0] = '\0';
/*
- * 1. Parse the arguments.
+ * Parse the arguments.
*/
- if (ParseFileDlgArgs(interp, ofnPtr, argc, argv, isOpen) != TCL_OK) {
- return TCL_ERROR;
+
+ extension = NULL;
+ filter = NULL;
+ Tcl_DStringInit(&utfFilterString);
+ Tcl_DStringInit(&utfDirString);
+ tkwin = (Tk_Window) clientData;
+ title = NULL;
+
+ 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;
+ }
+ if (i + 1 == objc) {
+ string = Tcl_GetStringFromObj(optionPtr, NULL);
+ Tcl_AppendResult(interp, "value for \"", string, "\" missing",
+ (char *) NULL);
+ goto end;
+ }
+
+ string = Tcl_GetStringFromObj(valuePtr, NULL);
+ switch ((enum options) index) {
+ case FILE_DEFAULT: {
+ if (string[0] == '.') {
+ string++;
+ }
+ extension = string;
+ break;
+ }
+ case FILE_TYPES: {
+ Tcl_DStringFree(&utfFilterString);
+ if (MakeFilter(interp, string, &utfFilterString) != TCL_OK) {
+ goto end;
+ }
+ filter = Tcl_DStringValue(&utfFilterString);
+ break;
+ }
+ case FILE_INITDIR: {
+ Tcl_DStringFree(&utfDirString);
+ if (Tcl_TranslateFileName(interp, string,
+ &utfDirString) == NULL) {
+ goto end;
+ }
+ break;
+ }
+ case FILE_INITFILE: {
+ Tcl_DString ds;
+
+ 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);
+ break;
+ }
+ case FILE_PARENT: {
+ tkwin = Tk_NameToWindow(interp, string, tkwin);
+ if (tkwin == NULL) {
+ goto end;
+ }
+ break;
+ }
+ case FILE_TITLE: {
+ title = string;
+ break;
+ }
+ }
+ }
+
+ if (filter == NULL) {
+ if (MakeFilter(interp, "", &utfFilterString) != TCL_OK) {
+ goto end;
+ }
+ }
+
+ Tk_MakeWindowExist(tkwin);
+ hWnd = Tk_GetHWND(Tk_WindowId(tkwin));
+
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hWnd;
+ ofn.hInstance = (HINSTANCE) GetWindowLong(ofn.hwndOwner,
+ GWL_HINSTANCE);
+ ofn.lpstrFilter = NULL;
+ ofn.lpstrCustomFilter = NULL;
+ ofn.nMaxCustFilter = 0;
+ ofn.nFilterIndex = 0;
+ ofn.lpstrFile = (WCHAR *) file;
+ ofn.nMaxFile = 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.nFileOffset = 0;
+ ofn.nFileExtension = 0;
+ ofn.lpstrDefExt = NULL;
+ ofn.lpfnHook = OFNHookProcW;
+ ofn.lCustData = (LPARAM) interp;
+ ofn.lpTemplateName = NULL;
+
+ if (open != 0) {
+ ofn.Flags |= OFN_FILEMUSTEXIST;
+ } else {
+ ofn.Flags |= OFN_OVERWRITEPROMPT;
+ }
+
+ if (tsdPtr->debugFlag != 0) {
+ ofn.Flags |= OFN_ENABLEHOOK;
+ }
+
+ if (extension != NULL) {
+ Tcl_UtfToExternalDString(unicodeEncoding, extension, -1, &extString);
+ ofn.lpstrDefExt = (WCHAR *) Tcl_DStringValue(&extString);
+ }
+
+ Tcl_UtfToExternalDString(unicodeEncoding, Tcl_DStringValue(&utfFilterString),
+ Tcl_DStringLength(&utfFilterString), &filterString);
+ ofn.lpstrFilter = (WCHAR *) Tcl_DStringValue(&filterString);
+
+ if (Tcl_DStringValue(&utfDirString)[0] != '\0') {
+ Tcl_UtfToExternalDString(unicodeEncoding, Tcl_DStringValue(&utfDirString),
+ Tcl_DStringLength(&utfDirString), &dirString);
+ ofn.lpstrInitialDir = (WCHAR *) Tcl_DStringValue(&dirString);
+ }
+
+ if (title != NULL) {
+ Tcl_UtfToExternalDString(unicodeEncoding, title, -1, &titleString);
+ ofn.lpstrTitle = (WCHAR *) Tcl_DStringValue(&titleString);
}
- custData = (OpenFileData*) ofnPtr->lCustData;
/*
- * 2. Call the common dialog function.
+ * Popup the dialog.
*/
+
oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
- GetCurrentDirectory(MAX_PATH+1, buffer);
- if (isOpen) {
- winCode = GetOpenFileName(ofnPtr);
+ if (open != 0) {
+ winCode = GetOpenFileNameW(&ofn);
} else {
- winCode = GetSaveFileName(ofnPtr);
+ winCode = GetSaveFileNameW(&ofn);
}
- SetCurrentDirectory(buffer);
- (void) Tcl_SetServiceMode(oldMode);
+ Tcl_SetServiceMode(oldMode);
+
+ /*
+ * 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
@@ -475,256 +645,404 @@ GetFileName(clientData, interp, argc, argv, isOpen)
Tcl_ResetResult(interp);
- if (ofnPtr->lpstrInitialDir != NULL) {
- ckfree((char*) ofnPtr->lpstrInitialDir);
- }
-
/*
- * 3. Process the results.
+ * Process the results.
*/
- if (winCode) {
- if (ofnPtr->Flags & OFN_ALLOWMULTISELECT) {
- /* The result in custData->szFile contains many items,
- separated with null characters. It is terminated with
- two nulls in a row. The first element is the directory
- path. */
- char *dir;
- int dirlen;
- char *p;
- Tcl_DString fullname;
- Tcl_ResetResult(interp);
-
- /* Get directory */
- dir = custData->szFile;
- for (p = custData->szFile; p && *p; p++) {
- /*
- * Change the pathname to the Tcl "normalized" pathname, where
- * back slashes are used instead of forward slashes
- */
- if (*p == '\\') {
- *p = '/';
- }
- }
- if (p[1] == '\0') {
- /* Only one file was returned. */
- Tcl_AppendElement(interp, dir);
- } else {
- while (*(++p)) {
- char *filname = p;
- for (; p && *p; p++) {
- if (*p == '\\') { *p = '/'; }
- }
- Tcl_DStringInit(&fullname);
- /* Add "dir/fname" to list */
- Tcl_DStringAppend(&fullname, dir, -1);
- Tcl_DStringAppend(&fullname, "/", -1);
- Tcl_DStringAppend(&fullname, filname, -1);
- /* Add to result string */
- Tcl_AppendElement(interp, Tcl_DStringValue(&fullname));
- /* Reset dynamic string */
- Tcl_DStringFree(&fullname);
- }
- }
- tclCode = TCL_OK;
- } else {
- /* Not a multiple-selection box; just treat it as a single
- element. */
- char *p;
- Tcl_ResetResult(interp);
-
- for (p = custData->szFile; p && *p; p++) {
- /*
- * Change the pathname to the Tcl "normalized" pathname, where
- * back slashes are used instead of forward slashes
- */
- if (*p == '\\') {
- *p = '/';
- }
+ if (winCode != 0) {
+ char *p;
+ Tcl_DString ds;
+
+ Tcl_ExternalToUtfDString(unicodeEncoding, (char *) ofn.lpstrFile, -1, &ds);
+ for (p = Tcl_DStringValue(&ds); *p != '\0'; p++) {
+ /*
+ * Change the pathname to the Tcl "normalized" pathname, where
+ * back slashes are used instead of forward slashes
+ */
+ if (*p == '\\') {
+ *p = '/';
}
- Tcl_AppendResult(interp, custData->szFile, NULL);
- tclCode = TCL_OK;
}
- } else {
- tclCode = ProcessCDError(interp, CommDlgExtendedError(),
- ofnPtr->hwndOwner);
+ Tcl_AppendResult(interp, Tcl_DStringValue(&ds), NULL);
+ Tcl_DStringFree(&ds);
}
- if (custData) {
- ckfree((char*)custData);
+ if (ofn.lpstrTitle != NULL) {
+ Tcl_DStringFree(&titleString);
}
- if (ofnPtr->lpstrFilter) {
- ckfree((char*)ofnPtr->lpstrFilter);
+ if (ofn.lpstrInitialDir != NULL) {
+ Tcl_DStringFree(&dirString);
}
+ Tcl_DStringFree(&filterString);
+ if (ofn.lpstrDefExt != NULL) {
+ Tcl_DStringFree(&extString);
+ }
+ result = TCL_OK;
+
+ end:
+ Tcl_DStringFree(&utfDirString);
+ Tcl_DStringFree(&utfFilterString);
- return tclCode;
+ return result;
}
/*
- *----------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*
- * ParseFileDlgArgs --
+ * OFNHookProcW --
*
- * Parses the arguments passed to tk_getOpenFile and tk_getSaveFile.
+ * Hook procedure called only if debugging is turned on. Sets
+ * the "tk_dialog" variable when the dialog is ready to receive
+ * messages.
*
* Results:
- * A standard TCL return value.
+ * Returns 0 to allow default processing of messages to occur.
*
* Side effects:
- * The OPENFILENAME structure is initialized and modified according
- * to the arguments.
+ * None.
*
- *----------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*/
-static int
-ParseFileDlgArgs(interp, ofnPtr, argc, argv, isOpen)
- Tcl_Interp * interp; /* Current interpreter. */
- OPENFILENAME *ofnPtr; /* Info about the file dialog */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
- int isOpen; /* true if we should call GetOpenFileName(),
- * false if we should call GetSaveFileName() */
+static UINT APIENTRY
+OFNHookProcW(
+ HWND hdlg, // handle to child dialog window
+ UINT uMsg, // message identifier
+ WPARAM wParam, // message parameter
+ LPARAM lParam) // message parameter
{
- OpenFileData * custData;
- int i;
- Tk_Window parent = Tk_MainWindow(interp);
- int doneFilter = 0;
- int windowsMajorVersion;
- Tcl_DString buffer;
-
- custData = (OpenFileData*)ckalloc(sizeof(OpenFileData));
- custData->interp = interp;
- strcpy(custData->szFile, "");
-
- /* Fill in the OPENFILENAME structure to */
- ofnPtr->lStructSize = sizeof(OPENFILENAME);
- ofnPtr->hwndOwner = 0; /* filled in below */
- ofnPtr->lpstrFilter = NULL;
- ofnPtr->lpstrCustomFilter = NULL;
- ofnPtr->nMaxCustFilter = 0;
- ofnPtr->nFilterIndex = 0;
- ofnPtr->lpstrFile = custData->szFile;
- ofnPtr->nMaxFile = sizeof(custData->szFile);
- ofnPtr->lpstrFileTitle = NULL;
- ofnPtr->nMaxFileTitle = 0;
- ofnPtr->lpstrInitialDir = NULL;
- ofnPtr->lpstrTitle = NULL;
- ofnPtr->nFileOffset = 0;
- ofnPtr->nFileExtension = 0;
- ofnPtr->lpstrDefExt = NULL;
- ofnPtr->lpfnHook = NULL;
- ofnPtr->lCustData = (DWORD)custData;
- ofnPtr->lpTemplateName = NULL;
- ofnPtr->Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
-
- windowsMajorVersion = LOBYTE(LOWORD(GetVersion()));
- if (windowsMajorVersion >= 4) {
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ OPENFILENAMEW *ofnPtr;
+
+ if (uMsg == WM_INITDIALOG) {
+ SetWindowLong(hdlg, GWL_USERDATA, lParam);
+ } else if (uMsg == WM_WINDOWPOSCHANGED) {
/*
- * Use the "explorer" style file selection box on platforms that
- * support it (Win95 and NT4.0, both have a major version number
- * of 4)
+ * This message is delivered at the right time 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->Flags |= OFN_EXPLORER;
+
+ ofnPtr = (OPENFILENAMEW *) GetWindowLong(hdlg, GWL_USERDATA);
+ if (ofnPtr != NULL) {
+ hdlg = GetParent(hdlg);
+ tsdPtr->debugInterp = (Tcl_Interp *) ofnPtr->lCustData;
+ Tcl_DoWhenIdle(SetTkDialog, (ClientData) hdlg);
+ SetWindowLong(hdlg, GWL_USERDATA, (LPARAM) NULL);
+ }
}
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetFileNameA --
+ *
+ * Calls GetOpenFileName() or GetSaveFileName().
+ *
+ * Results:
+ * See user documentation.
+ *
+ * Side effects:
+ * See user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+GetFileNameA(clientData, interp, objc, objv, open)
+ 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[MAX_PATH], savePath[MAX_PATH];
+ int result, winCode, oldMode, i;
+ char *extension, *filter, *title;
+ Tk_Window tkwin;
+ HWND hWnd;
+ Tcl_DString utfFilterString, utfDirString;
+ Tcl_DString extString, filterString, dirString, titleString;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ static char *optionStrings[] = {
+ "-defaultextension", "-filetypes", "-initialdir", "-initialfile",
+ "-parent", "-title", NULL
+ };
+ enum options {
+ FILE_DEFAULT, FILE_TYPES, FILE_INITDIR, FILE_INITFILE,
+ FILE_PARENT, FILE_TITLE
+ };
+
+ result = TCL_ERROR;
+ file[0] = '\0';
- if (isOpen) {
- ofnPtr->Flags |= OFN_FILEMUSTEXIST;
- } else {
- ofnPtr->Flags |= OFN_OVERWRITEPROMPT;
- }
+ /*
+ * Parse the arguments.
+ */
- for (i=1; i<argc; i+=2) {
- int v = i+1;
- int len = strlen(argv[i]);
+ extension = NULL;
+ filter = NULL;
+ Tcl_DStringInit(&utfFilterString);
+ Tcl_DStringInit(&utfDirString);
+ tkwin = (Tk_Window) clientData;
+ title = NULL;
- if (strncmp(argv[i], "-defaultextension", len)==0) {
- if (v==argc) {goto arg_missing;}
+ for (i = 1; i < objc; i += 2) {
+ int index;
+ char *string;
+ Tcl_Obj *optionPtr, *valuePtr;
- ofnPtr->lpstrDefExt = argv[v];
- if (ofnPtr->lpstrDefExt[0] == '.') {
- /* Windows will insert the dot for us */
- ofnPtr->lpstrDefExt ++;
- }
- }
- else if (strncmp(argv[i], "-filetypes", len)==0) {
- if (v==argc) {goto arg_missing;}
+ optionPtr = objv[i];
+ valuePtr = objv[i + 1];
- if (MakeFilter(interp, ofnPtr, argv[v]) != TCL_OK) {
- return TCL_ERROR;
- }
- doneFilter = 1;
+ if (Tcl_GetIndexFromObj(interp, optionPtr, optionStrings, "option",
+ 0, &index) != TCL_OK) {
+ goto end;
}
- else if (strncmp(argv[i], "-initialdir", len)==0) {
- if (v==argc) {goto arg_missing;}
-
- if (Tcl_TranslateFileName(interp, argv[v], &buffer) == NULL) {
- return TCL_ERROR;
- }
- ofnPtr->lpstrInitialDir = ckalloc(Tcl_DStringLength(&buffer)+1);
- strcpy((char*)ofnPtr->lpstrInitialDir, Tcl_DStringValue(&buffer));
- Tcl_DStringFree(&buffer);
+ if (i + 1 == objc) {
+ string = Tcl_GetStringFromObj(optionPtr, NULL);
+ Tcl_AppendResult(interp, "value for \"", string, "\" missing",
+ (char *) NULL);
+ goto end;
}
- else if (strncmp(argv[i], "-initialfile", len)==0) {
- if (v==argc) {goto arg_missing;}
- if (Tcl_TranslateFileName(interp, argv[v], &buffer) == NULL) {
- return TCL_ERROR;
+ string = Tcl_GetStringFromObj(valuePtr, NULL);
+ switch ((enum options) index) {
+ case FILE_DEFAULT: {
+ if (string[0] == '.') {
+ string++;
+ }
+ extension = string;
+ break;
}
- strcpy(ofnPtr->lpstrFile, Tcl_DStringValue(&buffer));
- Tcl_DStringFree(&buffer);
- }
- else if (strncmp(argv[i], "-parent", len)==0) {
- if (v==argc) {goto arg_missing;}
-
- parent=Tk_NameToWindow(interp, argv[v], Tk_MainWindow(interp));
- if (parent == NULL) {
- return TCL_ERROR;
+ case FILE_TYPES: {
+ Tcl_DStringFree(&utfFilterString);
+ if (MakeFilter(interp, string, &utfFilterString) != TCL_OK) {
+ goto end;
+ }
+ filter = Tcl_DStringValue(&utfFilterString);
+ break;
}
- }
- else if (strncmp(argv[i], "-title", len)==0) {
- if (v==argc) {goto arg_missing;}
-
- ofnPtr->lpstrTitle = argv[v];
- }
- else if (strncmp(argv[i], "-multiple", len)==0) {
- int tmp;
- if (v==argc) {goto arg_missing;}
+ case FILE_INITDIR: {
+ Tcl_DStringFree(&utfDirString);
+ if (Tcl_TranslateFileName(interp, string,
+ &utfDirString) == NULL) {
+ goto end;
+ }
+ break;
+ }
+ case FILE_INITFILE: {
+ Tcl_DString ds;
- if (Tcl_GetBoolean(interp, argv[i+1], &tmp) != TCL_OK) {
- return TCL_ERROR;
+ 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);
+ break;
}
- if (tmp) {
- ofnPtr->Flags |= OFN_ALLOWMULTISELECT;
+ case FILE_PARENT: {
+ tkwin = Tk_NameToWindow(interp, string, tkwin);
+ if (tkwin == NULL) {
+ goto end;
+ }
+ break;
+ }
+ case FILE_TITLE: {
+ title = string;
+ break;
}
}
- else {
- Tcl_AppendResult(interp, "unknown option \"",
- argv[i], "\", must be -defaultextension, ",
- "-filetypes, -initialdir, -initialfile, -parent or -title",
- NULL);
- return TCL_ERROR;
+ }
+
+ if (filter == NULL) {
+ if (MakeFilter(interp, "", &utfFilterString) != TCL_OK) {
+ goto end;
}
}
- if (!doneFilter) {
- if (MakeFilter(interp, ofnPtr, "") != TCL_OK) {
- return TCL_ERROR;
+ Tk_MakeWindowExist(tkwin);
+ hWnd = Tk_GetHWND(Tk_WindowId(tkwin));
+
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hWnd;
+ ofn.hInstance = (HINSTANCE) GetWindowLong(ofn.hwndOwner,
+ GWL_HINSTANCE);
+ ofn.lpstrFilter = NULL;
+ ofn.lpstrCustomFilter = NULL;
+ ofn.nMaxCustFilter = 0;
+ ofn.nFilterIndex = 0;
+ ofn.lpstrFile = (LPTSTR) file;
+ ofn.nMaxFile = 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.nFileOffset = 0;
+ ofn.nFileExtension = 0;
+ ofn.lpstrDefExt = NULL;
+ ofn.lpfnHook = OFNHookProc;
+ ofn.lCustData = (LPARAM) interp;
+ ofn.lpTemplateName = NULL;
+
+ if (open != 0) {
+ ofn.Flags |= OFN_FILEMUSTEXIST;
+ } else {
+ ofn.Flags |= OFN_OVERWRITEPROMPT;
+ }
+
+ if (tsdPtr->debugFlag != 0) {
+ ofn.Flags |= OFN_ENABLEHOOK;
+ }
+
+ 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);
+
+ if (Tcl_DStringValue(&utfDirString)[0] != '\0') {
+ Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&utfDirString),
+ Tcl_DStringLength(&utfDirString), &dirString);
+ 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);
+ 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.
+ */
+
+ if (winCode != 0) {
+ char *p;
+ Tcl_DString ds;
+
+ Tcl_ExternalToUtfDString(NULL, (char *) ofn.lpstrFile, -1, &ds);
+ for (p = Tcl_DStringValue(&ds); *p != '\0'; p++) {
+ /*
+ * Change the pathname to the Tcl "normalized" pathname, where
+ * back slashes are used instead of forward slashes
+ */
+ if (*p == '\\') {
+ *p = '/';
+ }
}
+ Tcl_AppendResult(interp, Tcl_DStringValue(&ds), NULL);
+ Tcl_DStringFree(&ds);
}
- if (Tk_WindowId(parent) == None) {
- Tk_MakeWindowExist(parent);
+ if (ofn.lpstrTitle != NULL) {
+ Tcl_DStringFree(&titleString);
}
- ofnPtr->hwndOwner = Tk_GetHWND(Tk_WindowId(parent));
+ if (ofn.lpstrInitialDir != NULL) {
+ Tcl_DStringFree(&dirString);
+ }
+ Tcl_DStringFree(&filterString);
+ if (ofn.lpstrDefExt != NULL) {
+ Tcl_DStringFree(&extString);
+ }
+ result = TCL_OK;
- return TCL_OK;
+ end:
+ Tcl_DStringFree(&utfDirString);
+ Tcl_DStringFree(&utfFilterString);
+
+ return result;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * OFNHookProc --
+ *
+ * Hook procedure called only if debugging is turned on. Sets
+ * the "tk_dialog" variable when the dialog is ready to receive
+ * messages.
+ *
+ * Results:
+ * Returns 0 to allow default processing of messages to occur.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
- arg_missing:
- Tcl_AppendResult(interp, "value for \"", argv[argc-1], "\" missing",
- NULL);
- return TCL_ERROR;
+static UINT APIENTRY
+OFNHookProc(
+ 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;
+
+ if (uMsg == WM_INITDIALOG) {
+ SetWindowLong(hdlg, GWL_USERDATA, lParam);
+ } 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 *) GetWindowLong(hdlg, GWL_USERDATA);
+ if (ofnPtr != NULL) {
+ if (ofnPtr->Flags & OFN_EXPLORER) {
+ hdlg = GetParent(hdlg);
+ }
+ tsdPtr->debugInterp = (Tcl_Interp *) ofnPtr->lCustData;
+ Tcl_DoWhenIdle(SetTkDialog, (ClientData) hdlg);
+ SetWindowLong(hdlg, GWL_USERDATA, (LPARAM) NULL);
+ }
+ }
+ return 0;
}
/*
@@ -743,10 +1061,11 @@ ParseFileDlgArgs(interp, ofnPtr, argc, argv, isOpen)
*
*----------------------------------------------------------------------
*/
-static int MakeFilter(interp, ofnPtr, string)
+static int
+MakeFilter(interp, string, dsPtr)
Tcl_Interp *interp; /* Current interpreter. */
- OPENFILENAME *ofnPtr; /* Info about the file dialog */
char *string; /* String value of the -filetypes option */
+ Tcl_DString *dsPtr; /* Filled with windows filter string. */
{
char *filterStr;
char *p;
@@ -761,7 +1080,7 @@ static int MakeFilter(interp, ofnPtr, string)
if (flist.filters == NULL) {
/*
- * Use "All Files (*.*) as the default filter is none is specified
+ * Use "All Files (*.*) as the default filter if none is specified
*/
char *defaultFilter = "All Files (*.*)";
@@ -849,10 +1168,8 @@ static int MakeFilter(interp, ofnPtr, string)
*p = '\0';
}
- if (ofnPtr->lpstrFilter != NULL) {
- ckfree((char*)ofnPtr->lpstrFilter);
- }
- ofnPtr->lpstrFilter = filterStr;
+ Tcl_DStringAppend(dsPtr, filterStr, p - filterStr);
+ ckfree((char *) filterStr);
TkFreeFileFilters(&flist);
return TCL_OK;
@@ -861,276 +1178,594 @@ static int MakeFilter(interp, ofnPtr, string)
/*
*----------------------------------------------------------------------
*
- * Tk_MessageBoxCmd --
+ * Tk_ChooseDirectoryObjCmd --
*
- * This procedure implements the MessageBox window for the
- * Windows platform. See the user documentation for details on what
- * it does.
+ * This procedure implements the "tk_chooseDirectory" dialog box
+ * for the Windows platform. See the user documentation for details
+ * on what it does.
*
* Results:
* See user documentation.
*
* Side effects:
- * None. The MessageBox window will be destroy before this procedure
- * returns.
+ * A modal dialog window is created. Tcl_SetServiceMode() is
+ * called to allow background events to be processed
*
*----------------------------------------------------------------------
*/
int
-Tk_MessageBoxCmd(clientData, interp, argc, argv)
+Tk_ChooseDirectoryObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
{
- int flags;
- Tk_Window parent = NULL;
+ OPENFILENAME ofn;
+ TCHAR path[MAX_PATH], savePath[MAX_PATH];
+ ChooseDir cd;
+ int result, mustExist, code, mode, i;
+ Tk_Window tkwin;
HWND hWnd;
- char *message = "";
- char *title = "";
- int icon = MB_ICONINFORMATION;
- int type = MB_OK;
- int modal = MB_SYSTEMMODAL;
- int i, j;
- char *result;
- int code, oldMode;
- char *defaultBtn = NULL;
- int defaultBtnIdx = -1;
-
- for (i=1; i<argc; i+=2) {
- int v = i+1;
- int len = strlen(argv[i]);
-
- if (strncmp(argv[i], "-default", len)==0) {
- if (v==argc) {goto arg_missing;}
-
- defaultBtn = argv[v];
+ char *utfTitle;
+ Tcl_DString utfDirString;
+ Tcl_DString titleString, dirString;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ static char *optionStrings[] = {
+ "-initialdir", "-mustexist", "-parent", "-title",
+ NULL
+ };
+ enum options {
+ DIR_INITIAL, DIR_EXIST, DIR_PARENT, FILE_TITLE
+ };
+
+ if (tsdPtr->WM_LBSELCHANGED == 0) {
+ tsdPtr->WM_LBSELCHANGED = RegisterWindowMessage(LBSELCHSTRING);
+ }
+
+ result = TCL_ERROR;
+ path[0] = '\0';
+
+ Tcl_DStringInit(&utfDirString);
+ mustExist = 0;
+ tkwin = (Tk_Window) clientData;
+ utfTitle = NULL;
+
+ 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 cleanup;
+ }
+ if (i + 1 == objc) {
+ string = Tcl_GetStringFromObj(optionPtr, NULL);
+ Tcl_AppendResult(interp, "value for \"", string, "\" missing",
+ (char *) NULL);
+ goto cleanup;
}
- else if (strncmp(argv[i], "-icon", len)==0) {
- if (v==argc) {goto arg_missing;}
- if (strcmp(argv[v], "error") == 0) {
- icon = MB_ICONERROR;
+ string = Tcl_GetStringFromObj(valuePtr, NULL);
+ switch ((enum options) index) {
+ case DIR_INITIAL: {
+ Tcl_DStringFree(&utfDirString);
+ if (Tcl_TranslateFileName(interp, string,
+ &utfDirString) == NULL) {
+ goto cleanup;
+ }
+ break;
}
- else if (strcmp(argv[v], "info") == 0) {
- icon = MB_ICONINFORMATION;
+ case DIR_EXIST: {
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &mustExist) != TCL_OK) {
+ goto cleanup;
+ }
+ break;
}
- else if (strcmp(argv[v], "question") == 0) {
- icon = MB_ICONQUESTION;
+ case DIR_PARENT: {
+ tkwin = Tk_NameToWindow(interp, string, tkwin);
+ if (tkwin == NULL) {
+ goto cleanup;
+ }
+ break;
}
- else if (strcmp(argv[v], "warning") == 0) {
- icon = MB_ICONWARNING;
+ case FILE_TITLE: {
+ utfTitle = string;
+ break;
}
- else {
- Tcl_AppendResult(interp, "invalid icon \"", argv[v],
- "\", must be error, info, question or warning", NULL);
- return TCL_ERROR;
+ }
+ }
+
+ Tk_MakeWindowExist(tkwin);
+ hWnd = Tk_GetHWND(Tk_WindowId(tkwin));
+
+ cd.interp = interp;
+
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hWnd;
+ ofn.hInstance = (HINSTANCE) GetWindowLong(ofn.hwndOwner,
+ GWL_HINSTANCE);
+ ofn.lpstrFilter = NULL;
+ ofn.lpstrCustomFilter = NULL;
+ ofn.nMaxCustFilter = 0;
+ ofn.nFilterIndex = 0;
+ ofn.lpstrFile = NULL; //(TCHAR *) path;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = NULL;
+ ofn.lpstrTitle = NULL;
+ ofn.Flags = OFN_HIDEREADONLY
+ | OFN_ENABLEHOOK | OFN_ENABLETEMPLATE;
+ ofn.nFileOffset = 0;
+ ofn.nFileExtension = 0;
+ ofn.lpstrDefExt = NULL;
+ ofn.lCustData = (LPARAM) &cd;
+ ofn.lpfnHook = ChooseDirectoryHookProc;
+ ofn.lpTemplateName = MAKEINTRESOURCE(FILEOPENORD);
+
+ if (Tcl_DStringValue(&utfDirString)[0] != '\0') {
+ Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&utfDirString),
+ Tcl_DStringLength(&utfDirString), &dirString);
+ ofn.lpstrInitialDir = (LPTSTR) Tcl_DStringValue(&dirString);
+ }
+ if (mustExist) {
+ ofn.Flags |= OFN_PATHMUSTEXIST;
+ }
+ if (utfTitle != NULL) {
+ Tcl_UtfToExternalDString(NULL, utfTitle, -1, &titleString);
+ ofn.lpstrTitle = (LPTSTR) Tcl_DStringValue(&titleString);
+ }
+
+ /*
+ * Display dialog. The choose directory dialog doesn't preserve the
+ * current directory, so it must be saved and restored here.
+ */
+
+ GetCurrentDirectory(MAX_PATH, savePath);
+ mode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
+ code = GetOpenFileName(&ofn);
+ Tcl_SetServiceMode(mode);
+ 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);
+
+ Tcl_ResetResult(interp);
+ if (code != 0) {
+ /*
+ * Change the pathname to the Tcl "normalized" pathname, where
+ * back slashes are used instead of forward slashes
+ */
+
+ char *p;
+ Tcl_DString ds;
+
+ Tcl_ExternalToUtfDString(NULL, (char *) cd.path, -1, &ds);
+ for (p = Tcl_DStringValue(&ds); *p != '\0'; p++) {
+ if (*p == '\\') {
+ *p = '/';
}
}
- else if (strncmp(argv[i], "-message", len)==0) {
- if (v==argc) {goto arg_missing;}
+ Tcl_AppendResult(interp, Tcl_DStringValue(&ds), NULL);
+ Tcl_DStringFree(&ds);
+ }
+
+ if (ofn.lpstrTitle != NULL) {
+ Tcl_DStringFree(&titleString);
+ }
+ if (ofn.lpstrInitialDir != NULL) {
+ Tcl_DStringFree(&dirString);
+ }
+ result = TCL_OK;
+
+ cleanup:
+ Tcl_DStringFree(&utfDirString);
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ChooseDirectoryHookProc --
+ *
+ * Hook procedure called by the ChooseDirectory dialog to modify
+ * its default behavior. The ChooseDirectory dialog is really an
+ * OpenFile dialog with certain controls rearranged and certain
+ * behaviors changed. For instance, typing a name in the
+ * ChooseDirectory dialog selects a directory, rather than
+ * selecting a file.
+ *
+ * Results:
+ * Returns 0 to allow default processing of message, or 1 to
+ * tell default dialog procedure not to process the message.
+ *
+ * Side effects:
+ * A dialog window is created the first this procedure is called.
+ * This window is not destroyed and will be reused the next time
+ * the application invokes the "tk_getOpenFile" or
+ * "tk_getSaveFile" command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static UINT APIENTRY
+ChooseDirectoryHookProc(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ OPENFILENAME *ofnPtr;
+
+ /*
+ * GWL_USERDATA keeps track of ofnPtr.
+ */
+
+ ofnPtr = (OPENFILENAME *) GetWindowLong(hwnd, GWL_USERDATA);
+
+ if (message == WM_INITDIALOG) {
+ ChooseDir *cdPtr;
- message = argv[v];
+ SetWindowLong(hwnd, GWL_USERDATA, lParam);
+ ofnPtr = (OPENFILENAME *) lParam;
+ cdPtr = (ChooseDir *) ofnPtr->lCustData;
+ cdPtr->lastCtrl = 0;
+ cdPtr->lastIdx = 1000;
+ cdPtr->path[0] = '\0';
+
+ if (ofnPtr->lpstrInitialDir == NULL) {
+ GetCurrentDirectory(MAX_PATH, cdPtr->path);
+ } else {
+ lstrcpy(cdPtr->path, ofnPtr->lpstrInitialDir);
}
- else if (strncmp(argv[i], "-parent", len)==0) {
- if (v==argc) {goto arg_missing;}
+ SetDlgItemText(hwnd, edt10, cdPtr->path);
+ SendDlgItemMessage(hwnd, edt10, EM_SETSEL, 0, -1);
+ if (tsdPtr->debugFlag) {
+ tsdPtr->debugInterp = cdPtr->interp;
+ Tcl_DoWhenIdle(SetTkDialog, (ClientData) hwnd);
+ }
+ return 0;
+ }
+ if (ofnPtr == NULL) {
+ return 0;
+ }
- parent=Tk_NameToWindow(interp, argv[v], Tk_MainWindow(interp));
- if (parent == NULL) {
- return TCL_ERROR;
+ if (message == tsdPtr->WM_LBSELCHANGED) {
+ /*
+ * Called when double-clicking on directory.
+ * If directory wasn't already open, browse that directory.
+ * If directory was already open, return selected directory.
+ */
+
+ ChooseDir *cdPtr;
+ int idCtrl, thisItem;
+
+ idCtrl = (int) wParam;
+ thisItem = LOWORD(lParam);
+ cdPtr = (ChooseDir *) ofnPtr->lCustData;
+
+ GetCurrentDirectory(MAX_PATH, cdPtr->path);
+ if (idCtrl == lst2) {
+ if (cdPtr->lastIdx == thisItem) {
+ EndDialog(hwnd, IDOK);
+ return 1;
}
+ cdPtr->lastIdx = thisItem;
}
- else if (strncmp(argv[i], "-title", len)==0) {
- if (v==argc) {goto arg_missing;}
+ SetDlgItemText(hwnd, edt10, cdPtr->path);
+ SendDlgItemMessage(hwnd, edt10, EM_SETSEL, 0, -1);
+ } else if (message == WM_COMMAND) {
+ ChooseDir *cdPtr;
+ int idCtrl, notifyCode;
+
+ idCtrl = LOWORD(wParam);
+ notifyCode = HIWORD(wParam);
+ cdPtr = (ChooseDir *) ofnPtr->lCustData;
+
+ if ((idCtrl != IDOK) || (notifyCode != BN_CLICKED)) {
+ /*
+ * OK Button wasn't clicked. Do the default.
+ */
- title = argv[v];
+ if ((idCtrl == lst2) || (idCtrl == edt10)) {
+ cdPtr->lastCtrl = idCtrl;
+ }
+ return 0;
}
- else if (strncmp(argv[i], "-type", len)==0) {
- int found = 0;
- if (v==argc) {goto arg_missing;}
+ /*
+ * Dialogs also get the message that OK was clicked when Enter
+ * is pressed in some other control. Find out what window
+ * we were really in when we got the supposed "OK", because the
+ * behavior is different.
+ */
+
+ if (cdPtr->lastCtrl == edt10) {
+ /*
+ * Hit Enter or clicked OK while typing a directory name in the
+ * edit control.
+ * If it's a new name, try to go to that directory.
+ * If the name hasn't changed since last time, return selected
+ * directory.
+ */
+
+ int changed;
+ TCHAR tmp[MAX_PATH];
- for (j=0; j<NUM_TYPES; j++) {
- if (strcmp(argv[v], msgTypeInfo[j].name) == 0) {
- type = msgTypeInfo[j].type;
- found = 1;
- break;
+ if (GetDlgItemText(hwnd, edt10, tmp, MAX_PATH) == 0) {
+ return 0;
+ }
+
+ changed = lstrcmp(cdPtr->path, tmp);
+ lstrcpy(cdPtr->path, tmp);
+
+ if (SetCurrentDirectory(cdPtr->path) == 0) {
+ /*
+ * Non-existent directory.
+ */
+
+ if (ofnPtr->Flags & OFN_PATHMUSTEXIST) {
+ /*
+ * Directory must exist. Complain, then rehighlight text.
+ */
+
+ wsprintf(tmp, _T("Cannot change directory to \"%.200s\"."),
+ cdPtr->path);
+ MessageBox(hwnd, tmp, NULL, MB_OK);
+ SendDlgItemMessage(hwnd, edt10, EM_SETSEL, 0, -1);
+ return 0;
+ }
+ if (changed) {
+ /*
+ * Directory was invalid, but we want to keep displaying
+ * this name. Don't update the listbox that displays the
+ * current directory heirarchy, or it'll erase the name.
+ */
+
+ SendDlgItemMessage(hwnd, edt10, EM_SETSEL, 0, -1);
+ return 0;
}
}
- if (!found) {
- Tcl_AppendResult(interp, "invalid message box type \"",
- argv[v], "\", must be abortretryignore, ok, ",
- "okcancel, retrycancel, yesno or yesnocancel", NULL);
- return TCL_ERROR;
+ if (changed == 0) {
+ /*
+ * Name hasn't changed since the last time we hit return
+ * or double-clicked on a directory, so return this.
+ */
+
+ EndDialog(hwnd, IDOK);
+ return 1;
}
- }
- else if (strncmp (argv[i], "-modal", len) == 0) {
- if (v==argc) {goto arg_missing;}
+
+ cdPtr->lastCtrl = IDOK;
+
+ /*
+ * The following is the magic code, determined by running
+ * Spy++ on some other directory chooser, that it takes to
+ * get this dialog to update the listbox to display the
+ * current directory.
+ */
- if (strcmp(argv[v], "system") == 0) {
- modal = MB_SYSTEMMODAL;
+ SetDlgItemText(hwnd, edt1, cdPtr->path);
+ SendMessage(hwnd, WM_COMMAND, (WPARAM) MAKELONG(cmb2, 0x8003),
+ (LPARAM) GetDlgItem(hwnd, cmb2));
+ return 0;
+ } else if (idCtrl == lst2) {
+ /*
+ * Enter key was pressed while in listbox.
+ * If it's a new directory, allow default behavior to open dir.
+ * If the directory hasn't changed, return selected directory.
+ */
+
+ int thisItem;
+
+ thisItem = (int) SendDlgItemMessage(hwnd, lst2, LB_GETCURSEL, 0, 0);
+ if (cdPtr->lastIdx == thisItem) {
+ GetCurrentDirectory(MAX_PATH, cdPtr->path);
+ EndDialog(hwnd, IDOK);
+ return 1;
}
- else if (strcmp(argv[v], "task") == 0) {
- modal = MB_TASKMODAL;
+ } else if (idCtrl == IDOK) {
+ /*
+ * The OK button was clicked. Return the value currently selected
+ * in the entry.
+ */
+
+ GetCurrentDirectory(MAX_PATH, cdPtr->path);
+ EndDialog(hwnd, IDOK);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_MessageBoxObjCmd --
+ *
+ * This procedure implements the MessageBox window for the
+ * Windows platform. See the user documentation for details on what
+ * it does.
+ *
+ * Results:
+ * See user documentation.
+ *
+ * Side effects:
+ * None. The MessageBox window will be destroy before this procedure
+ * returns.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_MessageBoxObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Main window associated with interpreter. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ Tk_Window tkwin, parent;
+ HWND hWnd;
+ char *message, *title;
+ int defaultBtn, icon, type;
+ int i, oldMode, flags, winCode;
+ Tcl_DString messageString, titleString;
+ static char *optionStrings[] = {
+ "-default", "-icon", "-message", "-parent",
+ "-title", "-type", NULL
+ };
+ enum options {
+ MSG_DEFAULT, MSG_ICON, MSG_MESSAGE, MSG_PARENT,
+ MSG_TITLE, MSG_TYPE
+ };
+
+ tkwin = (Tk_Window) clientData;
+
+ defaultBtn = -1;
+ icon = MB_ICONINFORMATION;
+ message = NULL;
+ parent = tkwin;
+ title = NULL;
+ type = MB_OK;
+
+ 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",
+ TCL_EXACT, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (i + 1 == objc) {
+ string = Tcl_GetStringFromObj(optionPtr, NULL);
+ Tcl_AppendResult(interp, "value for \"", string, "\" missing",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ string = Tcl_GetStringFromObj(valuePtr, NULL);
+ switch ((enum options) index) {
+ case MSG_DEFAULT:
+ defaultBtn = TkFindStateNumObj(interp, optionPtr, buttonMap,
+ valuePtr);
+ if (defaultBtn < 0) {
+ return TCL_ERROR;
}
- else if (strcmp(argv[v], "owner") == 0) {
- modal = MB_APPLMODAL;
+ break;
+
+ case MSG_ICON:
+ icon = TkFindStateNumObj(interp, optionPtr, iconMap, valuePtr);
+ if (icon < 0) {
+ return TCL_ERROR;
}
- else {
- Tcl_AppendResult(interp, "invalid modality \"", argv[v],
- "\", must be system, task or owner", NULL);
+ break;
+
+ case MSG_MESSAGE:
+ message = string;
+ break;
+
+ case MSG_PARENT:
+ parent = Tk_NameToWindow(interp, string, tkwin);
+ if (parent == NULL) {
return TCL_ERROR;
}
- }
- else {
- Tcl_AppendResult(interp, "unknown option \"",
- argv[i], "\", must be -default, -icon, ",
- "-message, -parent, -title or -type", NULL);
+ break;
+
+ case MSG_TITLE:
+ title = string;
+ break;
+
+ case MSG_TYPE:
+ type = TkFindStateNumObj(interp, optionPtr, typeMap, valuePtr);
+ if (type < 0) {
return TCL_ERROR;
- }
- }
+ }
+ break;
- /* Make sure we have a valid hWnd to act as the parent of this message box
- */
- if (parent == NULL && modal == MB_TASKMODAL) {
- hWnd = NULL;
- }
- else {
- if (parent == NULL) {
- parent = Tk_MainWindow(interp);
}
- if (Tk_WindowId(parent) == None) {
- Tk_MakeWindowExist(parent);
- }
- hWnd = Tk_GetHWND(Tk_WindowId(parent));
}
- if (defaultBtn != NULL) {
- for (i=0; i<NUM_TYPES; i++) {
- if (type == msgTypeInfo[i].type) {
- for (j=0; j<msgTypeInfo[i].numButtons; j++) {
- if (strcmp(defaultBtn, msgTypeInfo[i].btnNames[j])==0) {
- defaultBtnIdx = j;
+ Tk_MakeWindowExist(parent);
+ hWnd = Tk_GetHWND(Tk_WindowId(parent));
+
+ flags = 0;
+ if (defaultBtn >= 0) {
+ int defaultBtnIdx;
+
+ defaultBtnIdx = -1;
+ for (i = 0; i < NUM_TYPES; i++) {
+ if (type == allowedTypes[i].type) {
+ int j;
+
+ for (j = 0; j < 3; j++) {
+ if (allowedTypes[i].btnIds[j] == defaultBtn) {
+ defaultBtnIdx = j;
break;
}
}
if (defaultBtnIdx < 0) {
Tcl_AppendResult(interp, "invalid default button \"",
- defaultBtn, "\"", NULL);
+ TkFindStateString(buttonMap, defaultBtn),
+ "\"", NULL);
return TCL_ERROR;
}
break;
}
}
-
- switch (defaultBtnIdx) {
- case 0: flags = MB_DEFBUTTON1; break;
- case 1: flags = MB_DEFBUTTON2; break;
- case 2: flags = MB_DEFBUTTON3; break;
- case 3: flags = MB_DEFBUTTON4; break;
- }
- } else {
- flags = 0;
+ flags = buttonFlagMap[defaultBtnIdx];
}
-
- flags |= icon | type;
+
+ flags |= icon | type | MB_SYSTEMMODAL;
+
+ Tcl_UtfToExternalDString(NULL, message, -1, &messageString);
+ Tcl_UtfToExternalDString(NULL, title, -1, &titleString);
+
oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
- code = MessageBox(hWnd, message, title, flags|modal);
+ winCode = MessageBox(hWnd, Tcl_DStringValue(&messageString),
+ Tcl_DStringValue(&titleString), flags);
(void) Tcl_SetServiceMode(oldMode);
- switch (code) {
- case IDABORT: result = "abort"; break;
- case IDCANCEL: result = "cancel"; break;
- case IDIGNORE: result = "ignore"; break;
- case IDNO: result = "no"; break;
- case IDOK: result = "ok"; break;
- case IDRETRY: result = "retry"; break;
- case IDYES: result = "yes"; break;
- default: result = "";
- }
-
/*
- * When we come to here interp->result may have been changed by some
- * background scripts. Call Tcl_SetResult() to make sure that any stuff
- * lingering in interp->result will not appear in the result of
- * this command.
+ * 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);
- Tcl_SetResult(interp, result, TCL_STATIC);
- return TCL_OK;
+ Tcl_DStringFree(&messageString);
+ Tcl_DStringFree(&titleString);
- arg_missing:
- Tcl_AppendResult(interp, "value for \"", argv[argc-1], "\" missing",
- NULL);
- return TCL_ERROR;
+ Tcl_SetResult(interp, TkFindStateString(buttonMap, winCode), TCL_STATIC);
+ return TCL_OK;
}
-
-/*
- *----------------------------------------------------------------------
- *
- * ProcessCDError --
- *
- * This procedure gets called if a Windows-specific error message
- * has occurred during the execution of a common dialog or the
- * user has pressed the CANCEL button.
- *
- * Results:
- * If an error has indeed happened, returns a standard TCL result
- * that reports the error code in string format. If the user has
- * pressed the CANCEL button (dwErrorCode == 0), resets
- * interp->result to the empty string.
- *
- * Side effects:
- * interp->result is changed.
- *
- *----------------------------------------------------------------------
- */
-static int ProcessCDError(interp, dwErrorCode, hWnd)
- Tcl_Interp * interp; /* Current interpreter. */
- DWORD dwErrorCode; /* The Windows-specific error code */
- HWND hWnd; /* window in which the error happened*/
-{
- char *string;
- Tcl_ResetResult(interp);
+static void
+SetTkDialog(ClientData clientData)
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ char buf[32];
+ HWND hwnd;
- switch(dwErrorCode) {
- case 0: /* User has hit CANCEL */
- return TCL_OK;
-
- case CDERR_DIALOGFAILURE: string="CDERR_DIALOGFAILURE"; break;
- case CDERR_STRUCTSIZE: string="CDERR_STRUCTSIZE"; break;
- case CDERR_INITIALIZATION: string="CDERR_INITIALIZATION"; break;
- case CDERR_NOTEMPLATE: string="CDERR_NOTEMPLATE"; break;
- case CDERR_NOHINSTANCE: string="CDERR_NOHINSTANCE"; break;
- case CDERR_LOADSTRFAILURE: string="CDERR_LOADSTRFAILURE"; break;
- case CDERR_FINDRESFAILURE: string="CDERR_FINDRESFAILURE"; break;
- case CDERR_LOADRESFAILURE: string="CDERR_LOADRESFAILURE"; break;
- case CDERR_LOCKRESFAILURE: string="CDERR_LOCKRESFAILURE"; break;
- case CDERR_MEMALLOCFAILURE: string="CDERR_MEMALLOCFAILURE"; break;
- case CDERR_MEMLOCKFAILURE: string="CDERR_MEMLOCKFAILURE"; break;
- case CDERR_NOHOOK: string="CDERR_NOHOOK"; break;
- case PDERR_SETUPFAILURE: string="PDERR_SETUPFAILURE"; break;
- case PDERR_PARSEFAILURE: string="PDERR_PARSEFAILURE"; break;
- case PDERR_RETDEFFAILURE: string="PDERR_RETDEFFAILURE"; break;
- case PDERR_LOADDRVFAILURE: string="PDERR_LOADDRVFAILURE"; break;
- case PDERR_GETDEVMODEFAIL: string="PDERR_GETDEVMODEFAIL"; break;
- case PDERR_INITFAILURE: string="PDERR_INITFAILURE"; break;
- case PDERR_NODEVICES: string="PDERR_NODEVICES"; break;
- case PDERR_NODEFAULTPRN: string="PDERR_NODEFAULTPRN"; break;
- case PDERR_DNDMMISMATCH: string="PDERR_DNDMMISMATCH"; break;
- case PDERR_CREATEICFAILURE: string="PDERR_CREATEICFAILURE"; break;
- case PDERR_PRINTERNOTFOUND: string="PDERR_PRINTERNOTFOUND"; break;
- case CFERR_NOFONTS: string="CFERR_NOFONTS"; break;
- case FNERR_SUBCLASSFAILURE: string="FNERR_SUBCLASSFAILURE"; break;
- case FNERR_INVALIDFILENAME: string="FNERR_INVALIDFILENAME"; break;
- case FNERR_BUFFERTOOSMALL: string="FNERR_BUFFERTOOSMALL"; break;
-
- default:
- string="unknown error";
- }
+ hwnd = (HWND) clientData;
- Tcl_AppendResult(interp, "Win32 internal error: ", string, NULL);
- return TCL_ERROR;
+ sprintf(buf, "0x%08x", hwnd);
+ Tcl_SetVar(tsdPtr->debugInterp, "tk_dialog", buf, TCL_GLOBAL_ONLY);
}
diff --git a/tk/win/tkWinDraw.c b/tk/win/tkWinDraw.c
index 445166705d8..eafe1effd78 100644
--- a/tk/win/tkWinDraw.c
+++ b/tk/win/tkWinDraw.c
@@ -106,6 +106,12 @@ static int bltModes[] = {
typedef BOOL (CALLBACK *WinDrawFunc) _ANSI_ARGS_((HDC dc,
CONST POINT* points, int npoints));
+typedef struct ThreadSpecificData {
+ POINT *winPoints; /* Array of points that is reused. */
+ int nWinPoints; /* Current size of point array. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
/*
* Forward declarations for procedures defined in this file:
*/
@@ -119,6 +125,7 @@ static void DrawOrFillArc _ANSI_ARGS_((Display *display,
static void RenderObject _ANSI_ARGS_((HDC dc, GC gc,
XPoint* points, int npoints, int mode, HPEN pen,
WinDrawFunc func));
+static HPEN SetUpGraphicsPort _ANSI_ARGS_((GC gc));
/*
*----------------------------------------------------------------------
@@ -166,6 +173,7 @@ TkWinGetDrawableDC(display, d, state)
cmap = twdPtr->bitmap.colormap;
}
state->palette = TkWinSelectPalette(dc, cmap);
+ state->bkmode = GetBkMode(dc);
return dc;
}
@@ -192,6 +200,7 @@ TkWinReleaseDrawableDC(d, dc, state)
TkWinDCState *state;
{
TkWinDrawable *twdPtr = (TkWinDrawable *)d;
+ SetBkMode(dc, state->bkmode);
SelectPalette(dc, state->palette, TRUE);
RealizePalette(dc);
if (twdPtr->type == TWD_WINDOW) {
@@ -212,7 +221,8 @@ TkWinReleaseDrawableDC(d, dc, state)
* Returns the converted array of POINTs.
*
* Side effects:
- * Allocates a block of memory that should not be freed.
+ * Allocates a block of memory in thread local storage that
+ * should not be freed.
*
*----------------------------------------------------------------------
*/
@@ -224,8 +234,8 @@ ConvertPoints(points, npoints, mode, bbox)
int mode; /* CoordModeOrigin or CoordModePrevious. */
RECT *bbox; /* Bounding box of points. */
{
- static POINT *winPoints = NULL; /* Array of points that is reused. */
- static int nWinPoints = -1; /* Current size of point array. */
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
int i;
/*
@@ -233,16 +243,16 @@ ConvertPoints(points, npoints, mode, bbox)
* we reuse the last array if it is large enough.
*/
- if (npoints > nWinPoints) {
- if (winPoints != NULL) {
- ckfree((char *) winPoints);
+ if (npoints > tsdPtr->nWinPoints) {
+ if (tsdPtr->winPoints != NULL) {
+ ckfree((char *) tsdPtr->winPoints);
}
- winPoints = (POINT *) ckalloc(sizeof(POINT) * npoints);
- if (winPoints == NULL) {
- nWinPoints = -1;
+ tsdPtr->winPoints = (POINT *) ckalloc(sizeof(POINT) * npoints);
+ if (tsdPtr->winPoints == NULL) {
+ tsdPtr->nWinPoints = -1;
return NULL;
}
- nWinPoints = npoints;
+ tsdPtr->nWinPoints = npoints;
}
bbox->left = bbox->right = points[0].x;
@@ -250,26 +260,26 @@ ConvertPoints(points, npoints, mode, bbox)
if (mode == CoordModeOrigin) {
for (i = 0; i < npoints; i++) {
- winPoints[i].x = points[i].x;
- winPoints[i].y = points[i].y;
- bbox->left = MIN(bbox->left, winPoints[i].x);
- bbox->right = MAX(bbox->right, winPoints[i].x);
- bbox->top = MIN(bbox->top, winPoints[i].y);
- bbox->bottom = MAX(bbox->bottom, winPoints[i].y);
+ tsdPtr->winPoints[i].x = points[i].x;
+ tsdPtr->winPoints[i].y = points[i].y;
+ bbox->left = MIN(bbox->left, tsdPtr->winPoints[i].x);
+ bbox->right = MAX(bbox->right, tsdPtr->winPoints[i].x);
+ bbox->top = MIN(bbox->top, tsdPtr->winPoints[i].y);
+ bbox->bottom = MAX(bbox->bottom, tsdPtr->winPoints[i].y);
}
} else {
- winPoints[0].x = points[0].x;
- winPoints[0].y = points[0].y;
+ tsdPtr->winPoints[0].x = points[0].x;
+ tsdPtr->winPoints[0].y = points[0].y;
for (i = 1; i < npoints; i++) {
- winPoints[i].x = winPoints[i-1].x + points[i].x;
- winPoints[i].y = winPoints[i-1].y + points[i].y;
- bbox->left = MIN(bbox->left, winPoints[i].x);
- bbox->right = MAX(bbox->right, winPoints[i].x);
- bbox->top = MIN(bbox->top, winPoints[i].y);
- bbox->bottom = MAX(bbox->bottom, winPoints[i].y);
+ tsdPtr->winPoints[i].x = tsdPtr->winPoints[i-1].x + points[i].x;
+ tsdPtr->winPoints[i].y = tsdPtr->winPoints[i-1].y + points[i].y;
+ bbox->left = MIN(bbox->left, tsdPtr->winPoints[i].x);
+ bbox->right = MAX(bbox->right, tsdPtr->winPoints[i].x);
+ bbox->top = MIN(bbox->top, tsdPtr->winPoints[i].y);
+ bbox->bottom = MAX(bbox->bottom, tsdPtr->winPoints[i].y);
}
}
- return winPoints;
+ return tsdPtr->winPoints;
}
/*
@@ -555,33 +565,7 @@ TkPutImage(colors, ncolors, display, d, gc, image, src_x, src_y, dest_x,
infoPtr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
infoPtr->bmiHeader.biWidth = image->width;
-
- /*
- * The following code works around a bug in Win32s. CreateDIBitmap
- * fails under Win32s for top-down images. So we have to reverse the
- * order of the scanlines. If we are not running under Win32s, we can
- * just declare the image to be top-down.
- */
-
- if (tkpIsWin32s) {
- int y;
- char *srcPtr, *dstPtr, *temp;
-
- temp = ckalloc((unsigned) image->bytes_per_line);
- srcPtr = image->data;
- dstPtr = image->data+(image->bytes_per_line * (image->height - 1));
- for (y = 0; y < (image->height/2); y++) {
- memcpy(temp, srcPtr, image->bytes_per_line);
- memcpy(srcPtr, dstPtr, image->bytes_per_line);
- memcpy(dstPtr, temp, image->bytes_per_line);
- srcPtr += image->bytes_per_line;
- dstPtr -= image->bytes_per_line;
- }
- ckfree(temp);
- infoPtr->bmiHeader.biHeight = image->height; /* Bottom-up order */
- } else {
- infoPtr->bmiHeader.biHeight = -image->height; /* Top-down order */
- }
+ infoPtr->bmiHeader.biHeight = -image->height; /* Top-down order */
infoPtr->bmiHeader.biPlanes = 1;
infoPtr->bmiHeader.biBitCount = image->bits_per_pixel;
infoPtr->bmiHeader.biCompression = BI_RGB;
@@ -881,42 +865,8 @@ XDrawLines(display, d, gc, points, npoints, mode)
dc = TkWinGetDrawableDC(display, d, &state);
- if (!tkpIsWin32s && (gc->line_width > 1)) {
- LOGBRUSH lb;
- DWORD style;
-
- lb.lbStyle = BS_SOLID;
- lb.lbColor = gc->foreground;
- lb.lbHatch = 0;
-
- style = PS_GEOMETRIC|PS_COSMETIC;
- switch (gc->cap_style) {
- case CapNotLast:
- case CapButt:
- style |= PS_ENDCAP_FLAT;
- break;
- case CapRound:
- style |= PS_ENDCAP_ROUND;
- break;
- default:
- style |= PS_ENDCAP_SQUARE;
- break;
- }
- switch (gc->join_style) {
- case JoinMiter:
- style |= PS_JOIN_MITER;
- break;
- case JoinRound:
- style |= PS_JOIN_ROUND;
- break;
- default:
- style |= PS_JOIN_BEVEL;
- break;
- }
- pen = ExtCreatePen(style, gc->line_width, &lb, 0, NULL);
- } else {
- pen = CreatePen(PS_SOLID, gc->line_width, gc->foreground);
- }
+ pen = SetUpGraphicsPort(gc);
+ SetBkMode(dc, TRANSPARENT);
RenderObject(dc, gc, points, npoints, mode, pen, Polyline);
DeleteObject(pen);
@@ -1002,7 +952,8 @@ XDrawRectangle(display, d, gc, x, y, width, height)
dc = TkWinGetDrawableDC(display, d, &state);
- pen = CreatePen(PS_SOLID, gc->line_width, gc->foreground);
+ pen = SetUpGraphicsPort(gc);
+ SetBkMode(dc, TRANSPARENT);
oldPen = SelectObject(dc, pen);
oldBrush = SelectObject(dc, GetStockObject(NULL_BRUSH));
SetROP2(dc, tkpWinRopModes[gc->function]);
@@ -1164,7 +1115,7 @@ DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, fill)
* difference in pixel definitions between X and Windows.
*/
- pen = CreatePen(PS_SOLID, gc->line_width, gc->foreground);
+ pen = SetUpGraphicsPort(gc);
oldPen = SelectObject(dc, pen);
if (!fill) {
/*
@@ -1173,6 +1124,7 @@ DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, fill)
* it's only supported under Windows NT.
*/
+ SetBkMode(dc, TRANSPARENT);
Arc(dc, x, y, x+width+1, y+height+1, xstart, ystart, xend, yend);
} else {
brush = CreateSolidBrush(gc->foreground);
@@ -1191,6 +1143,92 @@ DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, fill)
/*
*----------------------------------------------------------------------
*
+ * SetUpGraphicsPort --
+ *
+ * Set up the graphics port from the given GC.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The current port is adjusted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static HPEN
+SetUpGraphicsPort(gc)
+ GC gc;
+{
+ DWORD style;
+
+ if (gc->line_style == LineOnOffDash) {
+ unsigned char *p = (unsigned char *) &(gc->dashes);
+ /* pointer to the dash-list */
+
+ /*
+ * Below is a simple translation of serveral dash patterns
+ * to valid windows pen types. Far from complete,
+ * but I don't know how to do it better.
+ * Any ideas: <mailto:j.nijtmans@chello.nl>
+ */
+
+ if (p[1] && p[2]) {
+ if (!p[3] || p[4]) {
+ style = PS_DASHDOTDOT; /* -.. */
+ } else {
+ style = PS_DASHDOT; /* -. */
+ }
+ } else {
+ if (p[0] > (4 * gc->line_width)) {
+ style = PS_DASH; /* - */
+ } else {
+ style = PS_DOT; /* . */
+ }
+ }
+ } else {
+ style = PS_SOLID;
+ }
+ if (gc->line_width < 2) {
+ return CreatePen(style, gc->line_width, gc->foreground);
+ } else {
+ LOGBRUSH lb;
+
+ lb.lbStyle = BS_SOLID;
+ lb.lbColor = gc->foreground;
+ lb.lbHatch = 0;
+
+ style |= PS_GEOMETRIC;
+ switch (gc->cap_style) {
+ case CapNotLast:
+ case CapButt:
+ style |= PS_ENDCAP_FLAT;
+ break;
+ case CapRound:
+ style |= PS_ENDCAP_ROUND;
+ break;
+ default:
+ style |= PS_ENDCAP_SQUARE;
+ break;
+ }
+ switch (gc->join_style) {
+ case JoinMiter:
+ style |= PS_JOIN_MITER;
+ break;
+ case JoinRound:
+ style |= PS_JOIN_ROUND;
+ break;
+ default:
+ style |= PS_JOIN_BEVEL;
+ break;
+ }
+ return ExtCreatePen(style, gc->line_width, &lb, 0, NULL);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkScrollWindow --
*
* Scroll a rectangle of the specified window and accumulate
@@ -1262,3 +1300,38 @@ TkWinFillRect(dc, x, y, width, height, pixel)
ExtTextOut(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
SetBkColor(dc, oldColor);
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDrawHighlightBorder --
+ *
+ * This procedure draws a rectangular ring around the outside of
+ * a widget to indicate that it has received the input focus.
+ *
+ * On Windows, we just draw the simple inset ring. On other sytems,
+ * e.g. the Mac, the focus ring is a little more complicated, so we
+ * need this abstraction.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A rectangle "width" pixels wide is drawn in "drawable",
+ * corresponding to the outer area of "tkwin".
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDrawHighlightBorder(tkwin, fgGC, bgGC, highlightWidth, drawable)
+ Tk_Window tkwin;
+ GC fgGC;
+ GC bgGC;
+ int highlightWidth;
+ Drawable drawable;
+{
+ TkDrawInsetFocusHighlight(tkwin, fgGC, highlightWidth, drawable, 0);
+}
+
+
diff --git a/tk/win/tkWinEmbed.c b/tk/win/tkWinEmbed.c
index d30a8663628..55893afa65a 100644
--- a/tk/win/tkWinEmbed.c
+++ b/tk/win/tkWinEmbed.c
@@ -6,7 +6,7 @@
* one application can use as its main window an internal window from
* another application).
*
- * Copyright (c) 1996 Sun Microsystems, Inc.
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -38,9 +38,11 @@ typedef struct Container {
* this process. */
} Container;
-static Container *firstContainerPtr = NULL;
- /* First in list of all containers
+typedef struct ThreadSpecificData {
+ Container *firstContainerPtr; /* First in list of all containers
* managed by this process. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
static void CleanupContainerList _ANSI_ARGS_((
ClientData clientData));
@@ -74,14 +76,16 @@ CleanupContainerList(clientData)
ClientData clientData;
{
Container *nextPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
for (;
- firstContainerPtr != (Container *) NULL;
- firstContainerPtr = nextPtr) {
- nextPtr = firstContainerPtr->nextPtr;
- ckfree((char *) firstContainerPtr);
+ tsdPtr->firstContainerPtr != (Container *) NULL;
+ tsdPtr->firstContainerPtr = nextPtr) {
+ nextPtr = tsdPtr->firstContainerPtr->nextPtr;
+ ckfree((char *) tsdPtr->firstContainerPtr);
}
- firstContainerPtr = (Container *) NULL;
+ tsdPtr->firstContainerPtr = (Container *) NULL;
}
/*
@@ -126,7 +130,7 @@ TkpTestembedCmd(clientData, interp, argc, argv)
* The return value is normally TCL_OK. If an error occurred (such as
* if the argument does not identify a legal Windows window handle),
* the return value is TCL_ERROR and an error message is left in the
- * interp->result if interp is not NULL.
+ * the interp's result if interp is not NULL.
*
* Side effects:
* None.
@@ -147,6 +151,8 @@ TkpUseWindow(interp, tkwin, string)
int id;
HWND hwnd;
Container *containerPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (winPtr->window != None) {
panic("TkpUseWindow: Already assigned a window");
@@ -159,7 +165,8 @@ TkpUseWindow(interp, tkwin, string)
/*
* Check if the window is a valid handle. If it is invalid, return
- * TCL_ERROR and potentially leave an error message in interp->result.
+ * TCL_ERROR and potentially leave an error message in the interp's
+ * result.
*/
if (!IsWindow(hwnd)) {
@@ -190,7 +197,7 @@ TkpUseWindow(interp, tkwin, string)
* things will get cleaned up at finalization.
*/
- if (firstContainerPtr == (Container *) NULL) {
+ if (tsdPtr->firstContainerPtr == (Container *) NULL) {
Tcl_CreateExitHandler(CleanupContainerList, (ClientData) NULL);
}
@@ -201,8 +208,8 @@ TkpUseWindow(interp, tkwin, string)
* app. are in the same process.
*/
- for (containerPtr = firstContainerPtr; containerPtr != NULL;
- containerPtr = containerPtr->nextPtr) {
+ for (containerPtr = tsdPtr->firstContainerPtr;
+ containerPtr != NULL; containerPtr = containerPtr->nextPtr) {
if (containerPtr->parentHWnd == hwnd) {
winPtr->flags |= TK_BOTH_HALVES;
containerPtr->parentPtr->flags |= TK_BOTH_HALVES;
@@ -213,8 +220,8 @@ TkpUseWindow(interp, tkwin, string)
containerPtr = (Container *) ckalloc(sizeof(Container));
containerPtr->parentPtr = NULL;
containerPtr->parentHWnd = hwnd;
- containerPtr->nextPtr = firstContainerPtr;
- firstContainerPtr = containerPtr;
+ containerPtr->nextPtr = tsdPtr->firstContainerPtr;
+ tsdPtr->firstContainerPtr = containerPtr;
}
/*
@@ -258,13 +265,15 @@ TkpMakeContainer(tkwin)
{
TkWindow *winPtr = (TkWindow *) tkwin;
Container *containerPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* If this is the first container, register an exit handler so that
* things will get cleaned up at finalization.
*/
- if (firstContainerPtr == (Container *) NULL) {
+ if (tsdPtr->firstContainerPtr == (Container *) NULL) {
Tcl_CreateExitHandler(CleanupContainerList, (ClientData) NULL);
}
@@ -279,8 +288,8 @@ TkpMakeContainer(tkwin)
containerPtr->parentHWnd = Tk_GetHWND(Tk_WindowId(tkwin));
containerPtr->embeddedHWnd = NULL;
containerPtr->embeddedPtr = NULL;
- containerPtr->nextPtr = firstContainerPtr;
- firstContainerPtr = containerPtr;
+ containerPtr->nextPtr = tsdPtr->firstContainerPtr;
+ tsdPtr->firstContainerPtr = containerPtr;
winPtr->flags |= TK_CONTAINER;
/*
@@ -358,12 +367,14 @@ TkWinEmbeddedEventProc(hwnd, message, wParam, lParam)
LPARAM lParam;
{
Container *containerPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* Find the Container structure associated with the parent window.
*/
- for (containerPtr = firstContainerPtr;
+ for (containerPtr = tsdPtr->firstContainerPtr;
containerPtr->parentHWnd != hwnd;
containerPtr = containerPtr->nextPtr) {
if (containerPtr == NULL) {
@@ -508,8 +519,10 @@ TkpGetOtherWindow(winPtr)
* embedded window. */
{
Container *containerPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- for (containerPtr = firstContainerPtr; containerPtr != NULL;
+ for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL;
containerPtr = containerPtr->nextPtr) {
if (containerPtr->embeddedPtr == winPtr) {
return containerPtr->parentPtr;
@@ -608,6 +621,8 @@ EmbedWindowDeleted(winPtr)
* was deleted. */
{
Container *containerPtr, *prevPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* Find the Container structure for this window work. Delete the
@@ -616,7 +631,7 @@ EmbedWindowDeleted(winPtr)
*/
prevPtr = NULL;
- containerPtr = firstContainerPtr;
+ containerPtr = tsdPtr->firstContainerPtr;
while (1) {
if (containerPtr->embeddedPtr == winPtr) {
containerPtr->embeddedHWnd = NULL;
@@ -636,10 +651,11 @@ EmbedWindowDeleted(winPtr)
if ((containerPtr->embeddedPtr == NULL)
&& (containerPtr->parentPtr == NULL)) {
if (prevPtr == NULL) {
- firstContainerPtr = containerPtr->nextPtr;
+ tsdPtr->firstContainerPtr = containerPtr->nextPtr;
} else {
prevPtr->nextPtr = containerPtr->nextPtr;
}
ckfree((char *) containerPtr);
}
}
+
diff --git a/tk/win/tkWinFont.c b/tk/win/tkWinFont.c
index 4f7a8095065..7f6d336ff03 100644
--- a/tk/win/tkWinFont.c
+++ b/tk/win/tkWinFont.c
@@ -4,8 +4,9 @@
* Contains the Windows implementation of the platform-independant
* font package interface.
*
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright (c) 1994 Software Research Associates, Inc.
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -17,20 +18,142 @@
#include "tkFont.h"
/*
- * The following structure represents Windows' implementation of a font.
+ * The following structure represents a font family. It is assumed that
+ * all screen fonts constructed from the same "font family" share certain
+ * properties; all screen fonts with the same "font family" point to a
+ * shared instance of this structure. The most important shared property
+ * is the character existence metrics, used to determine if a screen font
+ * can display a given Unicode character.
+ *
+ * Under Windows, a "font family" is uniquely identified by its face name.
+ */
+
+#define FONTMAP_SHIFT 10
+
+#define FONTMAP_PAGES (1 << (sizeof(Tcl_UniChar)*8 - FONTMAP_SHIFT))
+#define FONTMAP_BITSPERPAGE (1 << FONTMAP_SHIFT)
+
+typedef struct FontFamily {
+ struct FontFamily *nextPtr; /* Next in list of all known font families. */
+ int refCount; /* How many SubFonts are referring to this
+ * FontFamily. When the refCount drops to
+ * zero, this FontFamily may be freed. */
+ /*
+ * Key.
+ */
+
+ Tk_Uid faceName; /* Face name key for this FontFamily. */
+
+ /*
+ * Derived properties.
+ */
+
+ Tcl_Encoding encoding; /* Encoding for this font family. */
+ int isSymbolFont; /* Non-zero if this is a symbol font. */
+ int isWideFont; /* 1 if this is a double-byte font, 0
+ * otherwise. */
+ BOOL (WINAPI *textOutProc)(HDC, int, int, TCHAR *, int);
+ /* The procedure to use to draw text after
+ * it has been converted from UTF-8 to the
+ * encoding of this font. */
+ BOOL (WINAPI *getTextExtentPoint32Proc)(HDC, TCHAR *, int, LPSIZE);
+ /* The procedure to use to measure text after
+ * it has been converted from UTF-8 to the
+ * encoding of this font. */
+
+ char *fontMap[FONTMAP_PAGES];
+ /* Two-level sparse table used to determine
+ * quickly if the specified character exists.
+ * As characters are encountered, more pages
+ * in this table are dynamically added. The
+ * contents of each page is a bitmask
+ * consisting of FONTMAP_BITSPERPAGE bits,
+ * representing whether this font can be used
+ * to display the given character at the
+ * corresponding bit position. The high bits
+ * of the character are used to pick which
+ * page of the table is used. */
+
+ /*
+ * Cached Truetype font info.
+ */
+
+ int segCount; /* The length of the following arrays. */
+ USHORT *startCount; /* Truetype information about the font, */
+ USHORT *endCount; /* indicating which characters this font
+ * can display (malloced). The format of
+ * this information is (relatively) compact,
+ * but would take longer to search than
+ * indexing into the fontMap[][] table. */
+} FontFamily;
+
+/*
+ * The following structure encapsulates an individual screen font. A font
+ * object is made up of however many SubFonts are necessary to display a
+ * stream of multilingual characters.
+ */
+
+typedef struct SubFont {
+ char **fontMap; /* Pointer to font map from the FontFamily,
+ * cached here to save a dereference. */
+ HFONT hFont; /* The specific screen font that will be
+ * used when displaying/measuring chars
+ * belonging to the FontFamily. */
+ FontFamily *familyPtr; /* The FontFamily for this SubFont. */
+} SubFont;
+
+/*
+ * The following structure represents Windows' implementation of a font
+ * object.
*/
+#define SUBFONT_SPACE 3
+#define BASE_CHARS 128
+
typedef struct WinFont {
TkFont font; /* Stuff used by generic font package. Must
* be first in structure. */
- HFONT hFont; /* Windows information about font. */
+ SubFont staticSubFonts[SUBFONT_SPACE];
+ /* Builtin space for a limited number of
+ * SubFonts. */
+ int numSubFonts; /* Length of following array. */
+ SubFont *subFontArray; /* Array of SubFonts that have been loaded
+ * in order to draw/measure all the characters
+ * encountered by this font so far. All fonts
+ * start off with one SubFont initialized by
+ * AllocFont() from the original set of font
+ * attributes. Usually points to
+ * staticSubFonts, but may point to malloced
+ * space if there are lots of SubFonts. */
+
HWND hwnd; /* Toplevel window of application that owns
- * this font, used for getting HDC. */
+ * this font, used for getting HDC for
+ * offscreen measurements. */
+ int pixelSize; /* Original pixel size used when font was
+ * constructed. */
+ int widths[BASE_CHARS]; /* Widths of first 128 chars in the base
+ * font, for handling common case. The base
+ * font is always used to draw characters
+ * between 0x0000 and 0x007f. */
} WinFont;
/*
- * The following structure is used as to map between the Tcl strings
- * that represent the system fonts and the numbers used by Windows.
+ * The following structure is passed as the LPARAM when calling the font
+ * enumeration procedure to determine if a font can support the given
+ * character.
+ */
+
+typedef struct CanUse {
+ HDC hdc;
+ WinFont *fontPtr;
+ Tcl_DString *nameTriedPtr;
+ int ch;
+ SubFont *subFontPtr;
+} CanUse;
+
+/*
+ * The following structure is used to map between the Tcl strings that
+ * represent the system fonts and the numbers used by Windows.
*/
static TkStateMap systemMap[] = {
@@ -43,30 +166,99 @@ static TkStateMap systemMap[] = {
{-1, NULL}
};
-/* CYGNUS LOCAL: Map magic windows font names into offsets into a
- NONCLIENTMETRICS structure. */
+typedef struct ThreadSpecificData {
+ FontFamily *fontFamilyList; /* The list of font families that are
+ * currently loaded. As screen fonts
+ * are loaded, this list grows to hold
+ * information about what characters
+ * exist in each font family. */
+ Tcl_HashTable uidTable;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
-static TkStateMap nonClientMap[] = {
- {Tk_Offset(NONCLIENTMETRICS, lfCaptionFont), "caption"},
- {Tk_Offset(NONCLIENTMETRICS, lfSmCaptionFont), "smcaption"},
- {Tk_Offset(NONCLIENTMETRICS, lfMenuFont), "menu"},
- {Tk_Offset(NONCLIENTMETRICS, lfStatusFont), "status"},
- {Tk_Offset(NONCLIENTMETRICS, lfMessageFont), "message"},
- {-1, NULL}
-};
+/*
+ * Information cached about the system at startup time.
+ */
+
+static Tcl_Encoding unicodeEncoding;
+static Tcl_Encoding systemEncoding;
-#define ABS(x) (((x) < 0) ? -(x) : (x))
+/*
+ * Procedures used only in this file.
+ */
+
+static FontFamily * AllocFontFamily(HDC hdc, HFONT hFont, int base);
+static SubFont * CanUseFallback(HDC hdc, WinFont *fontPtr,
+ char *fallbackName, int ch);
+static SubFont * CanUseFallbackWithAliases(HDC hdc, WinFont *fontPtr,
+ char *faceName, int ch, Tcl_DString *nameTriedPtr);
+static int FamilyExists(HDC hdc, CONST char *faceName);
+static char * FamilyOrAliasExists(HDC hdc, CONST char *faceName);
+static SubFont * FindSubFontForChar(WinFont *fontPtr, int ch);
+static void FontMapInsert(SubFont *subFontPtr, int ch);
+static void FontMapLoadPage(SubFont *subFontPtr, int row);
+static int FontMapLookup(SubFont *subFontPtr, int ch);
+static void FreeFontFamily(FontFamily *familyPtr);
+static HFONT GetScreenFont(CONST TkFontAttributes *faPtr,
+ CONST char *faceName, int pixelSize);
+static void InitFont(Tk_Window tkwin, HFONT hFont,
+ int overstrike, WinFont *tkFontPtr);
+static void InitSubFont(HDC hdc, HFONT hFont, int base,
+ SubFont *subFontPtr);
+static int LoadFontRanges(HDC hdc, HFONT hFont,
+ USHORT **startCount, USHORT **endCount,
+ int *symbolPtr);
+static void MultiFontTextOut(HDC hdc, WinFont *fontPtr,
+ CONST char *source, int numBytes, int x, int y);
+static void ReleaseFont(WinFont *fontPtr);
+static void ReleaseSubFont(SubFont *subFontPtr);
+static int SeenName(CONST char *name, Tcl_DString *dsPtr);
+static void SwapLong(PULONG p);
+static void SwapShort(USHORT *p);
+static int CALLBACK WinFontCanUseProc(ENUMLOGFONT *lfPtr,
+ NEWTEXTMETRIC *tmPtr, int fontType,
+ LPARAM lParam);
+static int CALLBACK WinFontExistProc(ENUMLOGFONT *lfPtr,
+ NEWTEXTMETRIC *tmPtr, int fontType,
+ LPARAM lParam);
+static int CALLBACK WinFontFamilyEnumProc(ENUMLOGFONT *lfPtr,
+ NEWTEXTMETRIC *tmPtr, int fontType,
+ LPARAM lParam);
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * TkpFontPkgInit --
+ *
+ * This procedure is called when an application is created. It
+ * initializes all the structures that are used by the
+ * platform-dependent code on a per application basis.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ *
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
-static TkFont * AllocFont _ANSI_ARGS_((TkFont *tkFontPtr,
- Tk_Window tkwin, HFONT hFont));
-static char * GetProperty _ANSI_ARGS_((CONST TkFontAttributes *faPtr,
- CONST char *option));
-static int CALLBACK WinFontFamilyEnumProc _ANSI_ARGS_((ENUMLOGFONT *elfPtr,
- NEWTEXTMETRIC *ntmPtr, int fontType,
- LPARAM lParam));
+void
+TkpFontPkgInit(
+ TkMainInfo *mainPtr) /* The application being created. */
+{
+ unicodeEncoding = Tcl_GetEncoding(NULL, "unicode");
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
+ /*
+ * If running NT, then we will be calling some Unicode functions
+ * explictly. So, even if the Tcl system encoding isn't Unicode,
+ * make sure we convert to/from the Unicode char set.
+ */
-/* CYGNUS LOCAL: New static function. */
-static int FontChanged _ANSI_ARGS_((TkFontAttributes *faPtr));
+ systemEncoding = unicodeEncoding;
+ }
+}
/*
*---------------------------------------------------------------------------
@@ -89,29 +281,29 @@ static int FontChanged _ANSI_ARGS_((TkFontAttributes *faPtr));
* the contents of the generic TkFont before calling TkpDeleteFont().
*
* Side effects:
- * None.
+ * Memory allocated.
*
*---------------------------------------------------------------------------
*/
TkFont *
-TkpGetNativeFont(tkwin, name)
- Tk_Window tkwin; /* For display where font will be used. */
- CONST char *name; /* Platform-specific font name. */
+TkpGetNativeFont(
+ Tk_Window tkwin, /* For display where font will be used. */
+ CONST char *name) /* Platform-specific font name. */
{
int object;
- HFONT hFont;
-
+ WinFont *fontPtr;
+
object = TkFindStateNum(NULL, NULL, systemMap, name);
if (object < 0) {
return NULL;
}
- hFont = GetStockObject(object);
- if (hFont == NULL) {
- panic("TkpGetNativeFont: can't allocate stock font");
- }
- return AllocFont(NULL, tkwin, hFont);
+ tkwin = (Tk_Window) ((TkWindow *) tkwin)->mainPtr->winPtr;
+ fontPtr = (WinFont *) ckalloc(sizeof(WinFont));
+ InitFont(tkwin, GetStockObject(object), 0, fontPtr);
+
+ return (TkFont *) fontPtr;
}
/*
@@ -138,97 +330,86 @@ TkpGetNativeFont(tkwin, name)
* the contents of the generic TkFont before calling TkpDeleteFont().
*
* Side effects:
- * None.
+ * Memory allocated.
*
*---------------------------------------------------------------------------
*/
+
TkFont *
-TkpGetFontFromAttributes(tkFontPtr, tkwin, faPtr)
- TkFont *tkFontPtr; /* If non-NULL, store the information in
+TkpGetFontFromAttributes(
+ TkFont *tkFontPtr, /* If non-NULL, store the information in
* this existing TkFont structure, rather than
* allocating a new structure to hold the
* font; the existing contents of the font
* will be released. If NULL, a new TkFont
* structure is allocated. */
- Tk_Window tkwin; /* For display where font will be used. */
- CONST TkFontAttributes *faPtr; /* Set of attributes to match. */
+ Tk_Window tkwin, /* For display where font will be used. */
+ CONST TkFontAttributes *faPtr)
+ /* Set of attributes to match. */
{
- int offset;
- LOGFONT lf;
+ int i, j;
+ HDC hdc;
+ HWND hwnd;
HFONT hFont;
Window window;
- HWND hwnd;
- HDC hdc;
-
- /* CYGNUS LOCAL: Magic handling for fonts in the windows-* family. */
- if (faPtr->family != NULL
- && strncmp(faPtr->family, "windows-", 8) == 0
- && (offset = TkFindStateNum(NULL, NULL, nonClientMap,
- faPtr->family + 8)) >= 0) {
- NONCLIENTMETRICS ncm;
-
- ncm.cbSize = sizeof(ncm);
- if (! SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm),
- (void *) &ncm, 0)) {
- panic("TkpGetFontFromAttributes: SystemParametersInfo failed");
- }
-
- lf = *(LOGFONT *)((char *) &ncm + offset);
- } else {
- window = Tk_WindowId(((TkWindow *) tkwin)->mainPtr->winPtr);
- hwnd = (window == None) ? NULL : TkWinGetHWND(window);
-
- hdc = GetDC(hwnd);
- lf.lfHeight = -faPtr->pointsize;
- if (lf.lfHeight < 0) {
- lf.lfHeight = MulDiv(lf.lfHeight,
- 254 * WidthOfScreen(Tk_Screen(tkwin)),
- 720 * WidthMMOfScreen(Tk_Screen(tkwin)));
+ WinFont *fontPtr;
+ char ***fontFallbacks;
+ char *faceName, *fallback, *actualName;
+
+ tkwin = (Tk_Window) ((TkWindow *) tkwin)->mainPtr->winPtr;
+ window = Tk_WindowId(tkwin);
+ hwnd = (window == None) ? NULL : TkWinGetHWND(window);
+ hdc = GetDC(hwnd);
+
+ /*
+ * Algorithm to get the closest font name to the one requested.
+ *
+ * try fontname
+ * try all aliases for fontname
+ * foreach fallback for fontname
+ * try the fallback
+ * try all aliases for the fallback
+ */
+
+ faceName = faPtr->family;
+ if (faceName != NULL) {
+ actualName = FamilyOrAliasExists(hdc, faceName);
+ if (actualName != NULL) {
+ faceName = actualName;
+ goto found;
}
- lf.lfWidth = 0;
- lf.lfEscapement = 0;
- lf.lfOrientation = 0;
- lf.lfWeight = (faPtr->weight == TK_FW_NORMAL) ? FW_NORMAL : FW_BOLD;
- lf.lfItalic = faPtr->slant;
- lf.lfUnderline = faPtr->underline;
- lf.lfStrikeOut = faPtr->overstrike;
- lf.lfCharSet = DEFAULT_CHARSET;
- lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
- lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
- lf.lfQuality = DEFAULT_QUALITY;
- lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
- if (faPtr->family == NULL) {
- lf.lfFaceName[0] = '\0';
- } else {
- lstrcpyn(lf.lfFaceName, faPtr->family, sizeof(lf.lfFaceName));
+ fontFallbacks = TkFontGetFallbacks();
+ for (i = 0; fontFallbacks[i] != NULL; i++) {
+ for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {
+ if (strcasecmp(faceName, fallback) == 0) {
+ break;
+ }
+ }
+ if (fallback != NULL) {
+ for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {
+ actualName = FamilyOrAliasExists(hdc, fallback);
+ if (actualName != NULL) {
+ faceName = actualName;
+ goto found;
+ }
+ }
+ }
}
- ReleaseDC(hwnd, hdc);
+ }
- /*
- * Replace the standard X and Mac family names with the names that
- * Windows likes.
- */
+ found:
+ ReleaseDC(hwnd, hdc);
- if ((stricmp(lf.lfFaceName, "Times") == 0)
- || (stricmp(lf.lfFaceName, "New York") == 0)) {
- strcpy(lf.lfFaceName, "Times New Roman");
- } else if ((stricmp(lf.lfFaceName, "Courier") == 0)
- || (stricmp(lf.lfFaceName, "Monaco") == 0)) {
- strcpy(lf.lfFaceName, "Courier New");
- } else if ((stricmp(lf.lfFaceName, "Helvetica") == 0)
- || (stricmp(lf.lfFaceName, "Geneva") == 0)) {
- strcpy(lf.lfFaceName, "Arial");
- }
+ hFont = GetScreenFont(faPtr, faceName, TkFontGetPixels(tkwin, faPtr->size));
+ if (tkFontPtr == NULL) {
+ fontPtr = (WinFont *) ckalloc(sizeof(WinFont));
+ } else {
+ fontPtr = (WinFont *) tkFontPtr;
+ ReleaseFont(fontPtr);
}
+ InitFont(tkwin, hFont, faPtr->overstrike, fontPtr);
- hFont = CreateFontIndirect(&lf);
- if (hFont == NULL) {
- hFont = GetStockObject(SYSTEM_FONT);
- if (hFont == NULL) {
- panic("TkpGetFontFromAttributes: cannot get system font");
- }
- }
- return AllocFont(tkFontPtr, tkwin, hFont);
+ return (TkFont *) fontPtr;
}
/*
@@ -251,26 +432,25 @@ TkpGetFontFromAttributes(tkFontPtr, tkwin, faPtr)
*/
void
-TkpDeleteFont(tkFontPtr)
- TkFont *tkFontPtr; /* Token of font to be deleted. */
+TkpDeleteFont(
+ TkFont *tkFontPtr) /* Token of font to be deleted. */
{
WinFont *fontPtr;
fontPtr = (WinFont *) tkFontPtr;
- DeleteObject(fontPtr->hFont);
- ckfree((char *) fontPtr);
+ ReleaseFont(fontPtr);
}
/*
*---------------------------------------------------------------------------
*
- * TkpGetFontFamilies, WinFontEnumFamilyProc --
+ * TkpGetFontFamilies, WinFontFamilyEnumProc --
*
* Return information about the font families that are available
* on the display of the given window.
*
* Results:
- * interp->result is modified to hold a list of all the available
+ * Modifies interp's result object to hold a list of all the available
* font families.
*
* Side effects:
@@ -280,51 +460,114 @@ TkpDeleteFont(tkFontPtr)
*/
void
-TkpGetFontFamilies(interp, tkwin)
- Tcl_Interp *interp; /* Interp to hold result. */
- Tk_Window tkwin; /* For display to query. */
+TkpGetFontFamilies(
+ Tcl_Interp *interp, /* Interp to hold result. */
+ Tk_Window tkwin) /* For display to query. */
{
- Window window;
- HWND hwnd;
HDC hdc;
+ HWND hwnd;
+ Window window;
- window = Tk_WindowId(tkwin);
- hwnd = (window == (Window) NULL) ? NULL : TkWinGetHWND(window);
-
- hdc = GetDC(hwnd);
- EnumFontFamilies(hdc, NULL, (FONTENUMPROC) WinFontFamilyEnumProc,
- (LPARAM) interp);
+ window = Tk_WindowId(tkwin);
+ hwnd = (window == None) ? NULL : TkWinGetHWND(window);
+ hdc = GetDC(hwnd);
+
+ /*
+ * On any version NT, there may fonts with international names.
+ * Use the NT-only Unicode version of EnumFontFamilies to get the
+ * font names. If we used the ANSI version on a non-internationalized
+ * version of NT, we would get font names with '?' replacing all
+ * the international characters.
+ *
+ * On a non-internationalized verson of 95, fonts with international
+ * names are not allowed, so the ANSI version of EnumFontFamilies will
+ * work. On an internationalized version of 95, there may be fonts with
+ * international names; the ANSI version will work, fetching the
+ * name in the system code page. Can't use the Unicode version of
+ * EnumFontFamilies because it only exists under NT.
+ */
+
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
+ EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontFamilyEnumProc,
+ (LPARAM) interp);
+ } else {
+ EnumFontFamiliesA(hdc, NULL, (FONTENUMPROCA) WinFontFamilyEnumProc,
+ (LPARAM) interp);
+ }
ReleaseDC(hwnd, hdc);
}
-/* ARGSUSED */
-
static int CALLBACK
-WinFontFamilyEnumProc(elfPtr, ntmPtr, fontType, lParam)
- ENUMLOGFONT *elfPtr; /* Logical-font data. */
- NEWTEXTMETRIC *ntmPtr; /* Physical-font data (not used). */
- int fontType; /* Type of font (not used). */
- LPARAM lParam; /* Interp to hold result. */
+WinFontFamilyEnumProc(
+ ENUMLOGFONT *lfPtr, /* Logical-font data. */
+ NEWTEXTMETRIC *tmPtr, /* Physical-font data (not used). */
+ int fontType, /* Type of font (not used). */
+ LPARAM lParam) /* Result object to hold result. */
{
+ char *faceName;
+ Tcl_DString faceString;
+ Tcl_Obj *strPtr;
Tcl_Interp *interp;
interp = (Tcl_Interp *) lParam;
- Tcl_AppendElement(interp, elfPtr->elfLogFont.lfFaceName);
+ faceName = lfPtr->elfLogFont.lfFaceName;
+ Tcl_ExternalToUtfDString(systemEncoding, faceName, -1, &faceString);
+ strPtr = Tcl_NewStringObj(Tcl_DStringValue(&faceString),
+ Tcl_DStringLength(&faceString));
+ Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp), strPtr);
+ Tcl_DStringFree(&faceString);
return 1;
}
/*
+ *-------------------------------------------------------------------------
+ *
+ * TkpGetSubFonts --
+ *
+ * A function used by the testing package for querying the actual
+ * screen fonts that make up a font object.
+ *
+ * Results:
+ * Modifies interp's result object to hold a list containing the
+ * names of the screen fonts that make up the given font object.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+TkpGetSubFonts(
+ Tcl_Interp *interp, /* Interp to hold result. */
+ Tk_Font tkfont) /* Font object to query. */
+{
+ int i;
+ WinFont *fontPtr;
+ FontFamily *familyPtr;
+ Tcl_Obj *resultPtr, *strPtr;
+
+ resultPtr = Tcl_GetObjResult(interp);
+ fontPtr = (WinFont *) tkfont;
+ for (i = 0; i < fontPtr->numSubFonts; i++) {
+ familyPtr = fontPtr->subFontArray[i].familyPtr;
+ strPtr = Tcl_NewStringObj(familyPtr->faceName, -1);
+ Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
+ }
+}
+
+/*
*---------------------------------------------------------------------------
*
* Tk_MeasureChars --
*
- * Determine the number of characters from the string that will fit
+ * Determine the number of bytes from the string that will fit
* in the given horizontal span. The measurement is done under the
* assumption that Tk_DrawChars() will be used to actually display
* the characters.
*
* Results:
- * The return value is the number of characters from source that
+ * The return value is the number of bytes from source that
* fit into the span that extends from 0 to maxLength. *lengthPtr is
* filled with the x-coordinate of the right edge of the last
* character that did fit.
@@ -334,123 +577,204 @@ WinFontFamilyEnumProc(elfPtr, ntmPtr, fontType, lParam)
*
*---------------------------------------------------------------------------
*/
+
int
-Tk_MeasureChars(tkfont, source, numChars, maxLength, flags, lengthPtr)
- Tk_Font tkfont; /* Font in which characters will be drawn. */
- CONST char *source; /* Characters to be displayed. Need not be
+Tk_MeasureChars(
+ Tk_Font tkfont, /* Font in which characters will be drawn. */
+ CONST char *source, /* UTF-8 string to be displayed. Need not be
* '\0' terminated. */
- int numChars; /* Maximum number of characters to consider
+ int numBytes, /* Maximum number of bytes to consider
* from source string. */
- int maxLength; /* If > 0, maxLength specifies the longest
- * permissible line length; don't consider any
- * character that would cross this
- * x-position. If <= 0, then line length is
- * unbounded and the flags argument is
+ int maxLength, /* If >= 0, maxLength specifies the longest
+ * permissible line length in pixels; don't
+ * consider any character that would cross
+ * this x-position. If < 0, then line length
+ * is unbounded and the flags argument is
* ignored. */
- int flags; /* Various flag bits OR-ed together:
+ int flags, /* Various flag bits OR-ed together:
* TK_PARTIAL_OK means include the last char
* which only partially fit on this line.
* TK_WHOLE_WORDS means stop on a word
* boundary, if possible.
* TK_AT_LEAST_ONE means return at least one
* character even if no characters fit. */
- int *lengthPtr; /* Filled with x-location just after the
+ int *lengthPtr) /* Filled with x-location just after the
* terminating character. */
{
- WinFont *fontPtr;
HDC hdc;
- HFONT hFont;
- int curX, curIdx;
+ HFONT oldFont;
+ WinFont *fontPtr;
+ int curX, curByte;
+ SubFont *lastSubFontPtr;
+
+ /*
+ * According to Microsoft tech support, Windows does not use kerning
+ * or fractional character widths when displaying text on the screen.
+ * So that means we can safely measure individual characters or spans
+ * of characters and add up the widths w/o any "off-by-one-pixel"
+ * errors.
+ */
fontPtr = (WinFont *) tkfont;
hdc = GetDC(fontPtr->hwnd);
- hFont = SelectObject(hdc, fontPtr->hFont);
+ lastSubFontPtr = &fontPtr->subFontArray[0];
+ oldFont = SelectObject(hdc, lastSubFontPtr->hFont);
- if (numChars == 0) {
+ if (numBytes == 0) {
curX = 0;
- curIdx = 0;
- } else if (maxLength <= 0) {
+ curByte = 0;
+ } else if (maxLength < 0) {
+ Tcl_UniChar ch;
SIZE size;
-
- GetTextExtentPoint32(hdc, source, numChars, &size);
- curX = size.cx;
- curIdx = numChars;
+ FontFamily *familyPtr;
+ Tcl_DString runString;
+ SubFont *thisSubFontPtr;
+ CONST char *p, *end, *next;
+
+ /*
+ * A three step process:
+ * 1. Find a contiguous range of characters that can all be
+ * represented by a single screen font.
+ * 2. Convert those chars to the encoding of that font.
+ * 3. Measure converted chars.
+ */
+
+ curX = 0;
+ end = source + numBytes;
+ for (p = source; p < end; ) {
+ next = p + Tcl_UtfToUniChar(p, &ch);
+ thisSubFontPtr = FindSubFontForChar(fontPtr, ch);
+ if (thisSubFontPtr != lastSubFontPtr) {
+ familyPtr = lastSubFontPtr->familyPtr;
+ Tcl_UtfToExternalDString(familyPtr->encoding, source,
+ p - source, &runString);
+ (*familyPtr->getTextExtentPoint32Proc)(hdc,
+ Tcl_DStringValue(&runString),
+ Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
+ &size);
+ curX += size.cx;
+ Tcl_DStringFree(&runString);
+ lastSubFontPtr = thisSubFontPtr;
+ source = p;
+
+ SelectObject(hdc, lastSubFontPtr->hFont);
+ }
+ p = next;
+ }
+ familyPtr = lastSubFontPtr->familyPtr;
+ Tcl_UtfToExternalDString(familyPtr->encoding, source, p - source,
+ &runString);
+ (*familyPtr->getTextExtentPoint32Proc)(hdc,
+ Tcl_DStringValue(&runString),
+ Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
+ &size);
+ curX += size.cx;
+ Tcl_DStringFree(&runString);
+ curByte = numBytes;
} else {
- int max;
- int *partials;
+ Tcl_UniChar ch;
SIZE size;
-
- partials = (int *) ckalloc(numChars * sizeof (int));
- GetTextExtentExPoint(hdc, source, numChars, maxLength, &max,
- partials, &size);
-
- if ((flags & TK_WHOLE_WORDS) && max < numChars) {
- int sawSpace;
- int i;
-
- sawSpace = 0;
- i = max;
- while (i >= 0 && !isspace(source[i])) {
- --i;
- }
- while (i >= 0 && isspace(source[i])) {
- sawSpace = 1;
- --i;
- }
+ char buf[16];
+ FontFamily *familyPtr;
+ SubFont *thisSubFontPtr;
+ CONST char *term, *end, *p, *next;
+ int newX, termX, sawNonSpace, dstWrote;
- /*
- * If a space char was not found, and the flag for forcing
- * at least on (or more) chars to be drawn is false, then
- * set MAX to zero so no text is drawn. Otherwise, if a
- * space was found, set max to be one char past the space.
- */
-
- if ((i < 0) && !(flags & TK_AT_LEAST_ONE)) {
- max = 0;
- } else if (sawSpace) {
- max = i + 1;
+ /*
+ * How many chars will fit in the space allotted?
+ * This first version may be inefficient because it measures
+ * every character individually. There is a function call that
+ * can measure multiple characters at once and return the
+ * offset of each of them, but it only works on NT, even though
+ * the documentation claims it works for 95.
+ * TODO: verify that GetTextExtentExPoint is still broken in '95, and
+ * possibly use it for NT anyway since it should be much faster and
+ * more accurate.
+ */
+
+ next = source + Tcl_UtfToUniChar(source, &ch);
+ newX = curX = termX = 0;
+
+ term = source;
+ end = source + numBytes;
+
+ sawNonSpace = (ch > 255) || !isspace(ch);
+ for (p = source; ; ) {
+ if (ch < BASE_CHARS) {
+ newX += fontPtr->widths[ch];
+ } else {
+ thisSubFontPtr = FindSubFontForChar(fontPtr, ch);
+ if (thisSubFontPtr != lastSubFontPtr) {
+ SelectObject(hdc, thisSubFontPtr->hFont);
+ lastSubFontPtr = thisSubFontPtr;
+ }
+ familyPtr = lastSubFontPtr->familyPtr;
+ Tcl_UtfToExternal(NULL, familyPtr->encoding, p, next - p,
+ 0, NULL, buf, sizeof(buf), NULL, &dstWrote, NULL);
+ (*familyPtr->getTextExtentPoint32Proc)(hdc, buf,
+ dstWrote >> familyPtr->isWideFont, &size);
+ newX += size.cx;
+ }
+ if (newX > maxLength) {
+ break;
+ }
+ curX = newX;
+ p = next;
+ if (p >= end) {
+ term = end;
+ termX = curX;
+ break;
}
-
- }
- if (max == 0) {
- curX = 0;
- } else {
- curX = partials[max - 1];
+ next += Tcl_UtfToUniChar(next, &ch);
+ if ((ch < 256) && isspace(ch)) {
+ if (sawNonSpace) {
+ term = p;
+ termX = curX;
+ sawNonSpace = 0;
+ }
+ } else {
+ sawNonSpace = 1;
+ }
}
- if (((flags & TK_PARTIAL_OK) && max < numChars && curX < maxLength)
- || ((flags & TK_AT_LEAST_ONE) && max == 0 && numChars > 0)) {
- /* CYGNUS LOCAL - BUG ALERT - We have to pass the bogus length, and
- the dummyMax parameter, because without them the call crashes on
- NT/J Service Pack 3 and less. This is documented in the
- Microsoft Knowledge Base. */
-
- int dummyMax;
+ /*
+ * P points to the first character that doesn't fit in the desired
+ * span. Use the flags to figure out what to return.
+ */
+ if ((flags & TK_PARTIAL_OK) && (p < end) && (curX < maxLength)) {
/*
- * We want to include the first character that didn't
- * quite fit. Call the function again to include the
- * width of the extra character.
- */
-
- GetTextExtentExPoint(hdc, source, max + 1, INT_MAX, &dummyMax,
- partials, &size);
- curX = partials[max];
- ++max;
-
- }
-
- ckfree((char *) partials);
- curIdx = max;
+ * Include the first character that didn't quite fit in the desired
+ * span. The width returned will include the width of that extra
+ * character.
+ */
+
+ curX = newX;
+ p += Tcl_UtfToUniChar(p, &ch);
+ }
+ if ((flags & TK_AT_LEAST_ONE) && (term == source) && (p < end)) {
+ term = p;
+ termX = curX;
+ if (term == source) {
+ term += Tcl_UtfToUniChar(term, &ch);
+ termX = newX;
+ }
+ } else if ((p >= end) || !(flags & TK_WHOLE_WORDS)) {
+ term = p;
+ termX = curX;
+ }
+
+ curX = termX;
+ curByte = term - source;
}
- SelectObject(hdc, hFont);
+ SelectObject(hdc, oldFont);
ReleaseDC(fontPtr->hwnd, hdc);
*lengthPtr = curX;
- return curIdx;
+ return curByte;
}
/*
@@ -470,27 +794,26 @@ Tk_MeasureChars(tkfont, source, numChars, maxLength, flags, lengthPtr)
*/
void
-Tk_DrawChars(display, drawable, gc, tkfont, source, numChars, x, y)
- Display *display; /* Display on which to draw. */
- Drawable drawable; /* Window or pixmap in which to draw. */
- GC gc; /* Graphics context for drawing characters. */
- Tk_Font tkfont; /* Font in which characters will be drawn;
+Tk_DrawChars(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for drawing characters. */
+ Tk_Font tkfont, /* Font in which characters will be drawn;
* must be the same as font used in GC. */
- CONST char *source; /* Characters to be displayed. Need not be
+ CONST char *source, /* UTF-8 string to be displayed. Need not be
* '\0' terminated. All Tk meta-characters
* (tabs, control characters, and newlines)
* should be stripped out of the string that
* is passed to this function. If they are
* not stripped out, they will be displayed as
* regular printing characters. */
- int numChars; /* Number of characters in string. */
- int x, y; /* Coordinates at which to place origin of
+ int numBytes, /* Number of bytes in string. */
+ int x, int y) /* Coordinates at which to place origin of
* string when drawing. */
{
HDC dc;
- HFONT hFont;
- TkWinDCState state;
WinFont *fontPtr;
+ TkWinDCState state;
fontPtr = (WinFont *) gc->font;
display->request++;
@@ -527,18 +850,16 @@ Tk_DrawChars(display, drawable, gc, tkfont, source, numChars, x, y)
SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
oldBrush = SelectObject(dc, stipple);
- SetTextAlign(dcMem, TA_LEFT | TA_TOP);
+ SetTextAlign(dcMem, TA_LEFT | TA_BASELINE);
SetTextColor(dcMem, gc->foreground);
SetBkMode(dcMem, TRANSPARENT);
SetBkColor(dcMem, RGB(0, 0, 0));
- hFont = SelectObject(dcMem, fontPtr->hFont);
-
/*
* Compute the bounding box and create a compatible bitmap.
*/
- GetTextExtentPoint(dcMem, source, numChars, &size);
+ GetTextExtentPoint(dcMem, source, numBytes, &size);
GetTextMetrics(dcMem, &tm);
size.cx -= tm.tmOverhang;
bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
@@ -553,11 +874,11 @@ Tk_DrawChars(display, drawable, gc, tkfont, source, numChars, x, y)
*/
PatBlt(dcMem, 0, 0, size.cx, size.cy, BLACKNESS);
- TextOut(dcMem, 0, 0, source, numChars);
+ MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);
BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
0, 0, 0xEA02E9);
PatBlt(dcMem, 0, 0, size.cx, size.cy, WHITENESS);
- TextOut(dcMem, 0, 0, source, numChars);
+ MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);
BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
0, 0, 0x8A0E06);
@@ -565,7 +886,6 @@ Tk_DrawChars(display, drawable, gc, tkfont, source, numChars, x, y)
* Destroy the temporary bitmap and restore the device context.
*/
- SelectObject(dcMem, hFont);
SelectObject(dcMem, oldBitmap);
DeleteObject(bitmap);
DeleteDC(dcMem);
@@ -575,115 +895,1474 @@ Tk_DrawChars(display, drawable, gc, tkfont, source, numChars, x, y)
SetTextAlign(dc, TA_LEFT | TA_BASELINE);
SetTextColor(dc, gc->foreground);
SetBkMode(dc, TRANSPARENT);
- hFont = SelectObject(dc, fontPtr->hFont);
- TextOut(dc, x, y, source, numChars);
- SelectObject(dc, hFont);
+ MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);
}
TkWinReleaseDrawableDC(drawable, dc, &state);
}
/*
- *---------------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*
- * AllocFont --
+ * MultiFontTextOut --
*
- * Helper for TkpGetNativeFont() and TkpGetFontFromAttributes().
- * Allocates and intializes the memory for a new TkFont that
- * wraps the platform-specific data.
+ * Helper function for Tk_DrawChars. Draws characters, using the
+ * various screen fonts in fontPtr to draw multilingual characters.
+ * Note: No bidirectional support.
*
* Results:
- * Returns pointer to newly constructed TkFont.
+ * None.
+ *
+ * Side effects:
+ * Information gets drawn on the screen.
+ * Contents of fontPtr may be modified if more subfonts were loaded
+ * in order to draw all the multilingual characters in the given
+ * string.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+MultiFontTextOut(
+ HDC hdc, /* HDC to draw into. */
+ WinFont *fontPtr, /* Contains set of fonts to use when drawing
+ * following string. */
+ CONST char *source, /* Potentially multilingual UTF-8 string. */
+ int numBytes, /* Length of string in bytes. */
+ int x, int y) /* Coordinates at which to place origin *
+ * of string when drawing. */
+{
+ Tcl_UniChar ch;
+ SIZE size;
+ HFONT oldFont;
+ FontFamily *familyPtr;
+ Tcl_DString runString;
+ CONST char *p, *end, *next;
+ SubFont *lastSubFontPtr, *thisSubFontPtr;
+
+ lastSubFontPtr = &fontPtr->subFontArray[0];
+ oldFont = SelectObject(hdc, lastSubFontPtr->hFont);
+
+ end = source + numBytes;
+ for (p = source; p < end; ) {
+ next = p + Tcl_UtfToUniChar(p, &ch);
+ thisSubFontPtr = FindSubFontForChar(fontPtr, ch);
+ if (thisSubFontPtr != lastSubFontPtr) {
+ if (p > source) {
+ familyPtr = lastSubFontPtr->familyPtr;
+ Tcl_UtfToExternalDString(familyPtr->encoding, source,
+ p - source, &runString);
+ (*familyPtr->textOutProc)(hdc, x, y,
+ Tcl_DStringValue(&runString),
+ Tcl_DStringLength(&runString) >> familyPtr->isWideFont);
+ (*familyPtr->getTextExtentPoint32Proc)(hdc,
+ Tcl_DStringValue(&runString),
+ Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
+ &size);
+ x += size.cx;
+ Tcl_DStringFree(&runString);
+ }
+ lastSubFontPtr = thisSubFontPtr;
+ source = p;
+ SelectObject(hdc, lastSubFontPtr->hFont);
+ }
+ p = next;
+ }
+ if (p > source) {
+ familyPtr = lastSubFontPtr->familyPtr;
+ Tcl_UtfToExternalDString(familyPtr->encoding, source, p - source,
+ &runString);
+ (*familyPtr->textOutProc)(hdc, x, y, Tcl_DStringValue(&runString),
+ Tcl_DStringLength(&runString) >> familyPtr->isWideFont);
+ Tcl_DStringFree(&runString);
+ }
+ SelectObject(hdc, oldFont);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InitFont --
+ *
+ * Helper for TkpGetNativeFont() and TkpGetFontFromAttributes().
+ * Initializes the memory for a new WinFont that wraps the
+ * platform-specific data.
*
* The caller is responsible for initializing the fields of the
- * TkFont that are used exclusively by the generic TkFont code, and
+ * WinFont that are used exclusively by the generic TkFont code, and
* for releasing those fields before calling TkpDeleteFont().
*
+ * Results:
+ * Fills the WinFont structure.
+ *
* Side effects:
* Memory allocated.
*
*---------------------------------------------------------------------------
*/
-static TkFont *
-AllocFont(tkFontPtr, tkwin, hFont)
- TkFont *tkFontPtr; /* If non-NULL, store the information in
- * this existing TkFont structure, rather than
- * allocating a new structure to hold the
- * font; the existing contents of the font
- * will be released. If NULL, a new TkFont
- * structure is allocated. */
- Tk_Window tkwin; /* For display where font will be used. */
- HFONT hFont; /* Windows information about font. */
+static void
+InitFont(
+ Tk_Window tkwin, /* Main window of interp in which font will
+ * be used, for getting HDC. */
+ HFONT hFont, /* Windows token for font. */
+ int overstrike, /* The overstrike attribute of logfont used
+ * to allocate this font. For some reason,
+ * the TEXTMETRICs may contain incorrect info
+ * in the tmStruckOut field. */
+ WinFont *fontPtr) /* Filled with information constructed from
+ * the above arguments. */
{
- HWND hwnd;
- WinFont *fontPtr;
HDC hdc;
+ HWND hwnd;
+ HFONT oldFont;
TEXTMETRIC tm;
Window window;
- char buf[LF_FACESIZE];
+ TkFontMetrics *fmPtr;
+ Tcl_Encoding encoding;
+ Tcl_DString faceString;
TkFontAttributes *faPtr;
+ char buf[LF_FACESIZE * sizeof(WCHAR)];
+
+ window = Tk_WindowId(tkwin);
+ hwnd = (window == None) ? NULL : TkWinGetHWND(window);
+ hdc = GetDC(hwnd);
+ oldFont = SelectObject(hdc, hFont);
- if (tkFontPtr != NULL) {
- fontPtr = (WinFont *) tkFontPtr;
- DeleteObject(fontPtr->hFont);
+ GetTextMetrics(hdc, &tm);
+
+ /*
+ * On any version NT, there may fonts with international names.
+ * Use the NT-only Unicode version of GetTextFace to get the font's
+ * name. If we used the ANSI version on a non-internationalized
+ * version of NT, we would get a font name with '?' replacing all
+ * the international characters.
+ *
+ * On a non-internationalized verson of 95, fonts with international
+ * names are not allowed, so the ANSI version of GetTextFace will work.
+ * On an internationalized version of 95, there may be fonts with
+ * international names; the ANSI version will work, fetching the
+ * name in the international system code page. Can't use the Unicode
+ * version of GetTextFace because it only exists under NT.
+ */
+
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
+ GetTextFaceW(hdc, LF_FACESIZE, (WCHAR *) buf);
} else {
- fontPtr = (WinFont *) ckalloc(sizeof(WinFont));
+ GetTextFaceA(hdc, LF_FACESIZE, (char *) buf);
}
-
- window = Tk_WindowId(((TkWindow *) tkwin)->mainPtr->winPtr);
- hwnd = (window == None) ? NULL : TkWinGetHWND(window);
-
- hdc = GetDC(hwnd);
- hFont = SelectObject(hdc, hFont);
- GetTextFace(hdc, sizeof(buf), buf);
- GetTextMetrics(hdc, &tm);
+ Tcl_ExternalToUtfDString(systemEncoding, buf, -1, &faceString);
fontPtr->font.fid = (Font) fontPtr;
- faPtr = &fontPtr->font.fa;
- faPtr->family = Tk_GetUid(buf);
- faPtr->pointsize = MulDiv(tm.tmHeight - tm.tmInternalLeading,
- 720 * WidthMMOfScreen(Tk_Screen(tkwin)),
- 254 * WidthOfScreen(Tk_Screen(tkwin)));
+ faPtr = &fontPtr->font.fa;
+ faPtr->family = Tk_GetUid(Tcl_DStringValue(&faceString));
+ faPtr->size = TkFontGetPoints(tkwin, -(tm.tmHeight - tm.tmInternalLeading));
faPtr->weight = (tm.tmWeight > FW_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL;
faPtr->slant = (tm.tmItalic != 0) ? TK_FS_ITALIC : TK_FS_ROMAN;
faPtr->underline = (tm.tmUnderlined != 0) ? 1 : 0;
- faPtr->overstrike = (tm.tmStruckOut != 0) ? 1 : 0;
+ faPtr->overstrike = overstrike;
+
+ fmPtr = &fontPtr->font.fm;
+ fmPtr->ascent = tm.tmAscent;
+ fmPtr->descent = tm.tmDescent;
+ fmPtr->maxWidth = tm.tmMaxCharWidth;
+ fmPtr->fixed = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
+
+ fontPtr->hwnd = hwnd;
+ fontPtr->pixelSize = tm.tmHeight - tm.tmInternalLeading;
+
+ fontPtr->numSubFonts = 1;
+ fontPtr->subFontArray = fontPtr->staticSubFonts;
+ InitSubFont(hdc, hFont, 1, &fontPtr->subFontArray[0]);
+
+ encoding = fontPtr->subFontArray[0].familyPtr->encoding;
+ if (encoding == unicodeEncoding) {
+ GetCharWidthW(hdc, 0, BASE_CHARS - 1, fontPtr->widths);
+ } else {
+ GetCharWidthA(hdc, 0, BASE_CHARS - 1, fontPtr->widths);
+ }
+ Tcl_DStringFree(&faceString);
+
+ SelectObject(hdc, oldFont);
+ ReleaseDC(hwnd, hdc);
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * ReleaseFont --
+ *
+ * Called to release the windows-specific contents of a TkFont.
+ * The caller is responsible for freeing the memory used by the
+ * font itself.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+ReleaseFont(
+ WinFont *fontPtr) /* The font to delete. */
+{
+ int i;
- fontPtr->font.fm.ascent = tm.tmAscent;
- fontPtr->font.fm.descent = tm.tmDescent;
- fontPtr->font.fm.maxWidth = tm.tmMaxCharWidth;
- fontPtr->font.fm.fixed = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
+ for (i = 0; i < fontPtr->numSubFonts; i++) {
+ ReleaseSubFont(&fontPtr->subFontArray[i]);
+ }
+ if (fontPtr->subFontArray != fontPtr->staticSubFonts) {
+ ckfree((char *) fontPtr->subFontArray);
+ }
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * InitSubFont --
+ *
+ * Wrap a screen font and load the FontFamily that represents
+ * it. Used to prepare a SubFont so that characters can be mapped
+ * from UTF-8 to the charset of the font.
+ *
+ * Results:
+ * The subFontPtr is filled with information about the font.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+InitSubFont(
+ HDC hdc, /* HDC in which font can be selected. */
+ HFONT hFont, /* The screen font. */
+ int base, /* Non-zero if this SubFont is being used
+ * as the base font for a font object. */
+ SubFont *subFontPtr) /* Filled with SubFont constructed from
+ * above attributes. */
+{
+ subFontPtr->hFont = hFont;
+ subFontPtr->familyPtr = AllocFontFamily(hdc, hFont, base);
+ subFontPtr->fontMap = subFontPtr->familyPtr->fontMap;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * ReleaseSubFont --
+ *
+ * Called to release the contents of a SubFont. The caller is
+ * responsible for freeing the memory used by the SubFont itself.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory and resources are freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+ReleaseSubFont(
+ SubFont *subFontPtr) /* The SubFont to delete. */
+{
+ DeleteObject(subFontPtr->hFont);
+ FreeFontFamily(subFontPtr->familyPtr);
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * AllocFontFamily --
+ *
+ * Find the FontFamily structure associated with the given font
+ * name. The information should be stored by the caller in a
+ * SubFont and used when determining if that SubFont supports a
+ * character.
+ *
+ * Cannot use the string name used to construct the font as the
+ * key, because the capitalization may not be canonical. Therefore
+ * use the face name actually retrieved from the font metrics as
+ * the key.
+ *
+ * Results:
+ * A pointer to a FontFamily. The reference count in the FontFamily
+ * is automatically incremented. When the SubFont is released, the
+ * reference count is decremented. When no SubFont is using this
+ * FontFamily, it may be deleted.
+ *
+ * Side effects:
+ * A new FontFamily structure will be allocated if this font family
+ * has not been seen. TrueType character existence metrics are
+ * loaded into the FontFamily structure.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static FontFamily *
+AllocFontFamily(
+ HDC hdc, /* HDC in which font can be selected. */
+ HFONT hFont, /* Screen font whose FontFamily is to be
+ * returned. */
+ int base) /* Non-zero if this font family is to be
+ * used in the base font of a font object. */
+{
+ Tk_Uid faceName;
+ FontFamily *familyPtr;
+ Tcl_DString faceString;
+ Tcl_Encoding encoding;
+ char buf[LF_FACESIZE * sizeof(WCHAR)];
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
hFont = SelectObject(hdc, hFont);
- ReleaseDC(hwnd, hdc);
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
+ GetTextFaceW(hdc, LF_FACESIZE, (WCHAR *) buf);
+ } else {
+ GetTextFaceA(hdc, LF_FACESIZE, (char *) buf);
+ }
+ Tcl_ExternalToUtfDString(systemEncoding, buf, -1, &faceString);
+ faceName = Tk_GetUid(Tcl_DStringValue(&faceString));
+ Tcl_DStringFree(&faceString);
+ hFont = SelectObject(hdc, hFont);
- fontPtr->hFont = hFont;
- fontPtr->hwnd = hwnd;
+ familyPtr = tsdPtr->fontFamilyList;
+ for ( ; familyPtr != NULL; familyPtr = familyPtr->nextPtr) {
+ if (familyPtr->faceName == faceName) {
+ familyPtr->refCount++;
+ return familyPtr;
+ }
+ }
- return (TkFont *) fontPtr;
+ familyPtr = (FontFamily *) ckalloc(sizeof(FontFamily));
+ memset(familyPtr, 0, sizeof(FontFamily));
+ familyPtr->nextPtr = tsdPtr->fontFamilyList;
+ tsdPtr->fontFamilyList = familyPtr;
+
+ /*
+ * Set key for this FontFamily.
+ */
+
+ familyPtr->faceName = faceName;
+
+ /*
+ * An initial refCount of 2 means that FontFamily information will
+ * persist even when the SubFont that loaded the FontFamily is released.
+ * Change it to 1 to cause FontFamilies to be unloaded when not in use.
+ */
+
+ familyPtr->refCount = 2;
+
+ familyPtr->segCount = LoadFontRanges(hdc, hFont, &familyPtr->startCount,
+ &familyPtr->endCount, &familyPtr->isSymbolFont);
+
+ encoding = NULL;
+ if (familyPtr->isSymbolFont != 0) {
+ /*
+ * Symbol fonts are handled specially. For instance, Unicode 0393
+ * (GREEK CAPITAL GAMMA) must be mapped to Symbol character 0047
+ * (GREEK CAPITAL GAMMA), because the Symbol font doesn't have a
+ * GREEK CAPITAL GAMMA at location 0393. If Tk interpreted the
+ * Symbol font using the Unicode encoding, it would decide that
+ * the Symbol font has no GREEK CAPITAL GAMMA, because the Symbol
+ * encoding (of course) reports that character 0393 doesn't exist.
+ *
+ * With non-symbol Windows fonts, such as Times New Roman, if the
+ * font has a GREEK CAPITAL GAMMA, it will be found in the correct
+ * Unicode location (0393); the GREEK CAPITAL GAMMA will not be off
+ * hiding at some other location.
+ */
+
+ encoding = Tcl_GetEncoding(NULL, faceName);
+ }
+
+ if (encoding == NULL) {
+ encoding = Tcl_GetEncoding(NULL, "unicode");
+ familyPtr->textOutProc =
+ (BOOL (WINAPI *)(HDC, int, int, TCHAR *, int)) TextOutW;
+ familyPtr->getTextExtentPoint32Proc =
+ (BOOL (WINAPI *)(HDC, TCHAR *, int, LPSIZE)) GetTextExtentPoint32W;
+ familyPtr->isWideFont = 1;
+ } else {
+ familyPtr->textOutProc =
+ (BOOL (WINAPI *)(HDC, int, int, TCHAR *, int)) TextOutA;
+ familyPtr->getTextExtentPoint32Proc =
+ (BOOL (WINAPI *)(HDC, TCHAR *, int, LPSIZE)) GetTextExtentPoint32A;
+ familyPtr->isWideFont = 0;
+ }
+
+ familyPtr->encoding = encoding;
+
+ return familyPtr;
}
-/* CYGNUS LOCAL: This function is called when one of the non client
- metrics changes. We don't expect this to happen very often, so we
- always try to update all the known fonts. */
+/*
+ *-------------------------------------------------------------------------
+ *
+ * FreeFontFamily --
+ *
+ * Called to free a FontFamily when the SubFont is finished using it.
+ * Frees the contents of the FontFamily and the memory used by the
+ * FontFamily itself.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+FreeFontFamily(
+ FontFamily *familyPtr) /* The FontFamily to delete. */
+{
+ int i;
+ FontFamily **familyPtrPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-void
-TkWinNCMetricsChanged(tkwin)
- Tk_Window tkwin;
+ if (familyPtr == NULL) {
+ return;
+ }
+ familyPtr->refCount--;
+ if (familyPtr->refCount > 0) {
+ return;
+ }
+ for (i = 0; i < FONTMAP_PAGES; i++) {
+ if (familyPtr->fontMap[i] != NULL) {
+ ckfree(familyPtr->fontMap[i]);
+ }
+ }
+ if (familyPtr->startCount != NULL) {
+ ckfree((char *) familyPtr->startCount);
+ }
+ if (familyPtr->endCount != NULL) {
+ ckfree((char *) familyPtr->endCount);
+ }
+ if (familyPtr->encoding != unicodeEncoding) {
+ Tcl_FreeEncoding(familyPtr->encoding);
+ }
+
+ /*
+ * Delete from list.
+ */
+
+ for (familyPtrPtr = &tsdPtr->fontFamilyList; ; ) {
+ if (*familyPtrPtr == familyPtr) {
+ *familyPtrPtr = familyPtr->nextPtr;
+ break;
+ }
+ familyPtrPtr = &(*familyPtrPtr)->nextPtr;
+ }
+
+ ckfree((char *) familyPtr);
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * FindSubFontForChar --
+ *
+ * Determine which screen font is necessary to use to display the
+ * given character. If the font object does not have a screen font
+ * that can display the character, another screen font may be loaded
+ * into the font object, following a set of preferred fallback rules.
+ *
+ * Results:
+ * The return value is the SubFont to use to display the given
+ * character.
+ *
+ * Side effects:
+ * The contents of fontPtr are modified to cache the results
+ * of the lookup and remember any SubFonts that were dynamically
+ * loaded.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static SubFont *
+FindSubFontForChar(
+ WinFont *fontPtr, /* The font object with which the character
+ * will be displayed. */
+ int ch) /* The Unicode character to be displayed. */
{
- TkUpdateFonts(tkwin, FontChanged);
+ HDC hdc;
+ int i, j, k;
+ CanUse canUse;
+ char **aliases, **anyFallbacks;
+ char ***fontFallbacks;
+ char *fallbackName;
+ SubFont *subFontPtr;
+ Tcl_DString ds;
+
+ if (ch < BASE_CHARS) {
+ return &fontPtr->subFontArray[0];
+ }
+
+ for (i = 0; i < fontPtr->numSubFonts; i++) {
+ if (FontMapLookup(&fontPtr->subFontArray[i], ch)) {
+ return &fontPtr->subFontArray[i];
+ }
+ }
+
+ /*
+ * Keep track of all face names that we check, so we don't check some
+ * name multiple times if it can be reached by multiple paths.
+ */
+
+ Tcl_DStringInit(&ds);
+ hdc = GetDC(fontPtr->hwnd);
+
+ aliases = TkFontGetAliasList(fontPtr->font.fa.family);
+
+ fontFallbacks = TkFontGetFallbacks();
+ for (i = 0; fontFallbacks[i] != NULL; i++) {
+ for (j = 0; fontFallbacks[i][j] != NULL; j++) {
+ fallbackName = fontFallbacks[i][j];
+ if (strcasecmp(fallbackName, fontPtr->font.fa.family) == 0) {
+ /*
+ * If the base font has a fallback...
+ */
+
+ goto tryfallbacks;
+ } else if (aliases != NULL) {
+ /*
+ * Or if an alias for the base font has a fallback...
+ */
+
+ for (k = 0; aliases[k] != NULL; k++) {
+ if (strcasecmp(aliases[k], fallbackName) == 0) {
+ goto tryfallbacks;
+ }
+ }
+ }
+ }
+ continue;
+
+ /*
+ * ...then see if we can use one of the fallbacks, or an
+ * alias for one of the fallbacks.
+ */
+
+ tryfallbacks:
+ for (j = 0; fontFallbacks[i][j] != NULL; j++) {
+ fallbackName = fontFallbacks[i][j];
+ subFontPtr = CanUseFallbackWithAliases(hdc, fontPtr, fallbackName,
+ ch, &ds);
+ if (subFontPtr != NULL) {
+ goto end;
+ }
+ }
+ }
+
+ /*
+ * See if we can use something from the global fallback list.
+ */
+
+ anyFallbacks = TkFontGetGlobalClass();
+ for (i = 0; anyFallbacks[i] != NULL; i++) {
+ fallbackName = anyFallbacks[i];
+ subFontPtr = CanUseFallbackWithAliases(hdc, fontPtr, fallbackName,
+ ch, &ds);
+ if (subFontPtr != NULL) {
+ goto end;
+ }
+ }
+
+ /*
+ * Try all face names available in the whole system until we
+ * find one that can be used.
+ */
+
+ canUse.hdc = hdc;
+ canUse.fontPtr = fontPtr;
+ canUse.nameTriedPtr = &ds;
+ canUse.ch = ch;
+ canUse.subFontPtr = NULL;
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
+ EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontCanUseProc,
+ (LPARAM) &canUse);
+ } else {
+ EnumFontFamiliesA(hdc, NULL, (FONTENUMPROCA) WinFontCanUseProc,
+ (LPARAM) &canUse);
+ }
+ subFontPtr = canUse.subFontPtr;
+
+ end:
+ Tcl_DStringFree(&ds);
+
+ if (subFontPtr == NULL) {
+ /*
+ * No font can display this character. We will use the base font
+ * and have it display the "unknown" character.
+ */
+
+ subFontPtr = &fontPtr->subFontArray[0];
+ FontMapInsert(subFontPtr, ch);
+ }
+ ReleaseDC(fontPtr->hwnd, hdc);
+ return subFontPtr;
}
-/* This function returns non-zero when passed a font in a magic
- Windows non client font. */
+static int CALLBACK
+WinFontCanUseProc(
+ ENUMLOGFONT *lfPtr, /* Logical-font data. */
+ NEWTEXTMETRIC *tmPtr, /* Physical-font data (not used). */
+ int fontType, /* Type of font (not used). */
+ LPARAM lParam) /* Result object to hold result. */
+{
+ int ch;
+ HDC hdc;
+ WinFont *fontPtr;
+ CanUse *canUsePtr;
+ char *fallbackName;
+ SubFont *subFontPtr;
+ Tcl_DString faceString;
+ Tcl_DString *nameTriedPtr;
+
+ canUsePtr = (CanUse *) lParam;
+ ch = canUsePtr->ch;
+ hdc = canUsePtr->hdc;
+ fontPtr = canUsePtr->fontPtr;
+ nameTriedPtr = canUsePtr->nameTriedPtr;
+
+ fallbackName = lfPtr->elfLogFont.lfFaceName;
+ Tcl_ExternalToUtfDString(systemEncoding, fallbackName, -1, &faceString);
+ fallbackName = Tcl_DStringValue(&faceString);
+
+ if (SeenName(fallbackName, nameTriedPtr) == 0) {
+ subFontPtr = CanUseFallback(hdc, fontPtr, fallbackName, ch);
+ if (subFontPtr != NULL) {
+ canUsePtr->subFontPtr = subFontPtr;
+ Tcl_DStringFree(&faceString);
+ return 0;
+ }
+ }
+ Tcl_DStringFree(&faceString);
+ return 1;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * FontMapLookup --
+ *
+ * See if the screen font can display the given character.
+ *
+ * Results:
+ * The return value is 0 if the screen font cannot display the
+ * character, non-zero otherwise.
+ *
+ * Side effects:
+ * New pages are added to the font mapping cache whenever the
+ * character belongs to a page that hasn't been seen before.
+ * When a page is loaded, information about all the characters on
+ * that page is stored, not just for the single character in
+ * question.
+ *
+ *-------------------------------------------------------------------------
+ */
static int
-FontChanged(faPtr)
- TkFontAttributes *faPtr;
+FontMapLookup(
+ SubFont *subFontPtr, /* Contains font mapping cache to be queried
+ * and possibly updated. */
+ int ch) /* Character to be tested. */
+{
+ int row, bitOffset;
+
+ row = ch >> FONTMAP_SHIFT;
+ if (subFontPtr->fontMap[row] == NULL) {
+ FontMapLoadPage(subFontPtr, row);
+ }
+ bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
+ return (subFontPtr->fontMap[row][bitOffset >> 3] >> (bitOffset & 7)) & 1;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * FontMapInsert --
+ *
+ * Tell the font mapping cache that the given screen font should be
+ * used to display the specified character. This is called when no
+ * font on the system can be be found that can display that
+ * character; we lie to the font and tell it that it can display
+ * the character, otherwise we would end up re-searching the entire
+ * fallback hierarchy every time that character was seen.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * New pages are added to the font mapping cache whenever the
+ * character belongs to a page that hasn't been seen before.
+ * When a page is loaded, information about all the characters on
+ * that page is stored, not just for the single character in
+ * question.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+FontMapInsert(
+ SubFont *subFontPtr, /* Contains font mapping cache to be
+ * updated. */
+ int ch) /* Character to be added to cache. */
{
- return (faPtr->family != NULL
- && strncmp(faPtr->family, "windows-", 8) == 0
- && TkFindStateNum(NULL, NULL, nonClientMap,
- faPtr->family + 8) >= 0);
+ int row, bitOffset;
+
+ row = ch >> FONTMAP_SHIFT;
+ if (subFontPtr->fontMap[row] == NULL) {
+ FontMapLoadPage(subFontPtr, row);
+ }
+ bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
+ subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * FontMapLoadPage --
+ *
+ * Load information about all the characters on a given page.
+ * This information consists of one bit per character that indicates
+ * whether the associated HFONT can (1) or cannot (0) display the
+ * characters on the page.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Mempry allocated.
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+FontMapLoadPage(
+ SubFont *subFontPtr, /* Contains font mapping cache to be
+ * updated. */
+ int row) /* Index of the page to be loaded into
+ * the cache. */
+{
+ FontFamily *familyPtr;
+ Tcl_Encoding encoding;
+ char src[TCL_UTF_MAX], buf[16];
+ USHORT *startCount, *endCount;
+ int i, j, bitOffset, end, segCount;
+
+ subFontPtr->fontMap[row] = (char *) ckalloc(FONTMAP_BITSPERPAGE / 8);
+ memset(subFontPtr->fontMap[row], 0, FONTMAP_BITSPERPAGE / 8);
+
+ familyPtr = subFontPtr->familyPtr;
+ encoding = familyPtr->encoding;
+
+ if (familyPtr->encoding == unicodeEncoding) {
+ /*
+ * Font is Unicode. Few fonts are going to have all characters, so
+ * examine the TrueType character existence metrics to determine
+ * what characters actually exist in this font.
+ */
+
+ segCount = familyPtr->segCount;
+ startCount = familyPtr->startCount;
+ endCount = familyPtr->endCount;
+
+ j = 0;
+ end = (row + 1) << FONTMAP_SHIFT;
+ for (i = row << FONTMAP_SHIFT; i < end; i++) {
+ for ( ; j < segCount; j++) {
+ if (endCount[j] >= i) {
+ if (startCount[j] <= i) {
+ bitOffset = i & (FONTMAP_BITSPERPAGE - 1);
+ subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
+ }
+ break;
+ }
+ }
+ }
+ } else if (familyPtr->isSymbolFont) {
+ /*
+ * Assume that a symbol font with a known encoding has all the
+ * characters that its encoding claims it supports.
+ *
+ * The test for "encoding == unicodeEncoding"
+ * must occur before this case, to catch all symbol fonts (such
+ * as {Comic Sans MS} or Wingdings) for which we don't have
+ * encoding information; those symbol fonts are treated as if
+ * they were in the Unicode encoding and their symbolic
+ * character existence metrics are treated as if they were Unicode
+ * character existence metrics. This way, although we don't know
+ * the proper Unicode -> symbol font mapping, we can install the
+ * symbol font as the base font and access its glyphs.
+ */
+
+ end = (row + 1) << FONTMAP_SHIFT;
+ for (i = row << FONTMAP_SHIFT; i < end; i++) {
+ if (Tcl_UtfToExternal(NULL, encoding, src,
+ Tcl_UniCharToUtf(i, src), TCL_ENCODING_STOPONERROR, NULL,
+ buf, sizeof(buf), NULL, NULL, NULL) != TCL_OK) {
+ continue;
+ }
+ bitOffset = i & (FONTMAP_BITSPERPAGE - 1);
+ subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CanUseFallbackWithAliases --
+ *
+ * Helper function for FindSubFontForChar. Determine if the
+ * specified face name (or an alias of the specified face name)
+ * can be used to construct a screen font that can display the
+ * given character.
+ *
+ * Results:
+ * See CanUseFallback().
+ *
+ * Side effects:
+ * If the name and/or one of its aliases was rejected, the
+ * rejected string is recorded in nameTriedPtr so that it won't
+ * be tried again.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static SubFont *
+CanUseFallbackWithAliases(
+ HDC hdc, /* HDC in which font can be selected. */
+ WinFont *fontPtr, /* The font object that will own the new
+ * screen font. */
+ char *faceName, /* Desired face name for new screen font. */
+ int ch, /* The Unicode character that the new
+ * screen font must be able to display. */
+ Tcl_DString *nameTriedPtr) /* Records face names that have already
+ * been tried. It is possible for the same
+ * face name to be queried multiple times when
+ * trying to find a suitable screen font. */
+{
+ int i;
+ char **aliases;
+ SubFont *subFontPtr;
+
+ if (SeenName(faceName, nameTriedPtr) == 0) {
+ subFontPtr = CanUseFallback(hdc, fontPtr, faceName, ch);
+ if (subFontPtr != NULL) {
+ return subFontPtr;
+ }
+ }
+ aliases = TkFontGetAliasList(faceName);
+ if (aliases != NULL) {
+ for (i = 0; aliases[i] != NULL; i++) {
+ if (SeenName(aliases[i], nameTriedPtr) == 0) {
+ subFontPtr = CanUseFallback(hdc, fontPtr, aliases[i], ch);
+ if (subFontPtr != NULL) {
+ return subFontPtr;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SeenName --
+ *
+ * Used to determine we have already tried and rejected the given
+ * face name when looking for a screen font that can support some
+ * Unicode character.
+ *
+ * Results:
+ * The return value is 0 if this face name has not already been seen,
+ * non-zero otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+SeenName(
+ CONST char *name, /* The name to check. */
+ Tcl_DString *dsPtr) /* Contains names that have already been
+ * seen. */
+{
+ CONST char *seen, *end;
+
+ seen = Tcl_DStringValue(dsPtr);
+ end = seen + Tcl_DStringLength(dsPtr);
+ while (seen < end) {
+ if (strcasecmp(seen, name) == 0) {
+ return 1;
+ }
+ seen += strlen(seen) + 1;
+ }
+ Tcl_DStringAppend(dsPtr, (char *) name, (int) (strlen(name) + 1));
+ return 0;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * CanUseFallback --
+ *
+ * If the specified screen font has not already been loaded into
+ * the font object, determine if it can display the given character.
+ *
+ * Results:
+ * The return value is a pointer to a newly allocated SubFont, owned
+ * by the font object. This SubFont can be used to display the given
+ * character. The SubFont represents the screen font with the base set
+ * of font attributes from the font object, but using the specified
+ * font name. NULL is returned if the font object already holds
+ * a reference to the specified physical font or if the specified
+ * physical font cannot display the given character.
+ *
+ * Side effects:
+ * The font object's subFontArray is updated to contain a reference
+ * to the newly allocated SubFont.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static SubFont *
+CanUseFallback(
+ HDC hdc, /* HDC in which font can be selected. */
+ WinFont *fontPtr, /* The font object that will own the new
+ * screen font. */
+ char *faceName, /* Desired face name for new screen font. */
+ int ch) /* The Unicode character that the new
+ * screen font must be able to display. */
+{
+ int i;
+ HFONT hFont;
+ SubFont subFont;
+
+ if (FamilyExists(hdc, faceName) == 0) {
+ return NULL;
+ }
+
+ /*
+ * Skip all fonts we've already used.
+ */
+
+ for (i = 0; i < fontPtr->numSubFonts; i++) {
+ if (faceName == fontPtr->subFontArray[i].familyPtr->faceName) {
+ return NULL;
+ }
+ }
+
+ /*
+ * Load this font and see if it has the desired character.
+ */
+
+ hFont = GetScreenFont(&fontPtr->font.fa, faceName, fontPtr->pixelSize);
+ InitSubFont(hdc, hFont, 0, &subFont);
+ if (((ch < 256) && (subFont.familyPtr->isSymbolFont))
+ || (FontMapLookup(&subFont, ch) == 0)) {
+ /*
+ * Don't use a symbol font as a fallback font for characters below
+ * 256.
+ */
+
+ ReleaseSubFont(&subFont);
+ return NULL;
+ }
+
+ if (fontPtr->numSubFonts >= SUBFONT_SPACE) {
+ SubFont *newPtr;
+
+ newPtr = (SubFont *) ckalloc(sizeof(SubFont)
+ * (fontPtr->numSubFonts + 1));
+ memcpy((char *) newPtr, fontPtr->subFontArray,
+ fontPtr->numSubFonts * sizeof(SubFont));
+ if (fontPtr->subFontArray != fontPtr->staticSubFonts) {
+ ckfree((char *) fontPtr->subFontArray);
+ }
+ fontPtr->subFontArray = newPtr;
+ }
+ fontPtr->subFontArray[fontPtr->numSubFonts] = subFont;
+ fontPtr->numSubFonts++;
+ return &fontPtr->subFontArray[fontPtr->numSubFonts - 1];
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetScreenFont --
+ *
+ * Given the name and other attributes, construct an HFONT.
+ * This is where all the alias and fallback substitution bottoms
+ * out.
+ *
+ * Results:
+ * The screen font that corresponds to the attributes.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static HFONT
+GetScreenFont(
+ CONST TkFontAttributes *faPtr,
+ /* Desired font attributes for new HFONT. */
+ CONST char *faceName, /* Overrides font family specified in font
+ * attributes. */
+ int pixelSize) /* Overrides size specified in font
+ * attributes. */
+{
+ Tcl_DString ds;
+ HFONT hFont;
+ LOGFONTW lf;
+
+ lf.lfHeight = -pixelSize;
+ lf.lfWidth = 0;
+ lf.lfEscapement = 0;
+ lf.lfOrientation = 0;
+ lf.lfWeight = (faPtr->weight == TK_FW_NORMAL) ? FW_NORMAL : FW_BOLD;
+ lf.lfItalic = faPtr->slant;
+ lf.lfUnderline = faPtr->underline;
+ lf.lfStrikeOut = faPtr->overstrike;
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfOutPrecision = OUT_TT_PRECIS;
+ lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf.lfQuality = DEFAULT_QUALITY;
+ lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+
+ Tcl_UtfToExternalDString(systemEncoding, faceName, -1, &ds);
+
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
+ Tcl_UniChar *src, *dst;
+
+ /*
+ * We can only store up to LF_FACESIZE wide characters
+ */
+ if (Tcl_DStringLength(&ds) >= (LF_FACESIZE * sizeof(WCHAR))) {
+ Tcl_DStringSetLength(&ds, LF_FACESIZE);
+ }
+ src = (Tcl_UniChar *) Tcl_DStringValue(&ds);
+ dst = (Tcl_UniChar *) lf.lfFaceName;
+ while (*src != '\0') {
+ *dst++ = *src++;
+ }
+ *dst = '\0';
+ hFont = CreateFontIndirectW(&lf);
+ } else {
+ /*
+ * We can only store up to LF_FACESIZE characters
+ */
+ if (Tcl_DStringLength(&ds) >= LF_FACESIZE) {
+ Tcl_DStringSetLength(&ds, LF_FACESIZE);
+ }
+ strcpy((char *) lf.lfFaceName, Tcl_DStringValue(&ds));
+ hFont = CreateFontIndirectA((LOGFONTA *) &lf);
+ }
+ Tcl_DStringFree(&ds);
+ return hFont;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * FamilyExists, FamilyOrAliasExists, WinFontExistsProc --
+ *
+ * Determines if any physical screen font exists on the system with
+ * the given family name. If the family exists, then it should be
+ * possible to construct some physical screen font with that family
+ * name.
+ *
+ * Results:
+ * The return value is 0 if the specified font family does not exist,
+ * non-zero otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static int
+FamilyExists(
+ HDC hdc, /* HDC in which font family will be used. */
+ CONST char *faceName) /* Font family to query. */
+{
+ int result;
+ Tcl_DString faceString;
+
+ /*
+ * Just immediately rule out the following fonts, because they look so
+ * ugly on windows. The caller's fallback mechanism will cause the
+ * corresponding appropriate TrueType fonts to be selected.
+ */
+
+ if (strcasecmp(faceName, "Courier") == 0) {
+ return 0;
+ }
+ if (strcasecmp(faceName, "Times") == 0) {
+ return 0;
+ }
+ if (strcasecmp(faceName, "Helvetica") == 0) {
+ return 0;
+ }
+
+ Tcl_UtfToExternalDString(systemEncoding, faceName, -1, &faceString);
+
+ /*
+ * If the family exists, WinFontExistProc() will be called and
+ * EnumFontFamilies() will return whatever WinFontExistProc() returns.
+ * If the family doesn't exist, EnumFontFamilies() will just return a
+ * non-zero value.
+ */
+
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
+ result = EnumFontFamiliesW(hdc, (WCHAR *) Tcl_DStringValue(&faceString),
+ (FONTENUMPROCW) WinFontExistProc, 0);
+ } else {
+ result = EnumFontFamiliesA(hdc, (char *) Tcl_DStringValue(&faceString),
+ (FONTENUMPROCA) WinFontExistProc, 0);
+ }
+ Tcl_DStringFree(&faceString);
+ return (result == 0);
+}
+
+static char *
+FamilyOrAliasExists(
+ HDC hdc,
+ CONST char *faceName)
+{
+ char **aliases;
+ int i;
+
+ if (FamilyExists(hdc, faceName) != 0) {
+ return (char *) faceName;
+ }
+ aliases = TkFontGetAliasList(faceName);
+ if (aliases != NULL) {
+ for (i = 0; aliases[i] != NULL; i++) {
+ if (FamilyExists(hdc, aliases[i]) != 0) {
+ return aliases[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+static int CALLBACK
+WinFontExistProc(
+ ENUMLOGFONT *lfPtr, /* Logical-font data. */
+ NEWTEXTMETRIC *tmPtr, /* Physical-font data (not used). */
+ int fontType, /* Type of font (not used). */
+ LPARAM lParam) /* EnumFontData to hold result. */
+{
+ return 0;
+}
+
+/*
+ * The following data structures are used when querying a TrueType font file
+ * to determine which characters the font supports.
+ */
+
+#pragma pack(1) /* Structures are byte aligned in file. */
+
+#define CMAPHEX 0x636d6170 /* Key for character map resource. */
+
+typedef struct CMAPTABLE {
+ USHORT version; /* Table version number (0). */
+ USHORT numTables; /* Number of encoding tables following. */
+} CMAPTABLE;
+
+typedef struct ENCODINGTABLE {
+ USHORT platform; /* Platform for which data is targeted.
+ * 3 means data is for Windows. */
+ USHORT encoding; /* How characters in font are encoded.
+ * 1 means that the following subtable is
+ * keyed based on Unicode. */
+ ULONG offset; /* Byte offset from beginning of CMAPTABLE
+ * to the subtable for this encoding. */
+} ENCODINGTABLE;
+
+typedef struct ANYTABLE {
+ USHORT format; /* Format number. */
+ USHORT length; /* The actual length in bytes of this
+ * subtable. */
+ USHORT version; /* Version number (starts at 0). */
+} ANYTABLE;
+
+typedef struct BYTETABLE {
+ USHORT format; /* Format number is set to 0. */
+ USHORT length; /* The actual length in bytes of this
+ * subtable. */
+ USHORT version; /* Version number (starts at 0). */
+ BYTE glyphIdArray[256]; /* Array that maps up to 256 single-byte char
+ * codes to glyph indices. */
+} BYTETABLE;
+
+typedef struct SUBHEADER {
+ USHORT firstCode; /* First valid low byte for subHeader. */
+ USHORT entryCount; /* Number valid low bytes for subHeader. */
+ SHORT idDelta; /* Constant adder to get base glyph index. */
+ USHORT idRangeOffset; /* Byte offset from here to appropriate
+ * glyphIndexArray. */
+} SUBHEADER;
+
+typedef struct HIBYTETABLE {
+ USHORT format; /* Format number is set to 2. */
+ USHORT length; /* The actual length in bytes of this
+ * subtable. */
+ USHORT version; /* Version number (starts at 0). */
+ USHORT subHeaderKeys[256]; /* Maps high bytes to subHeaders: value is
+ * subHeader index * 8. */
+#if 0
+ SUBHEADER subHeaders[]; /* Variable-length array of SUBHEADERs. */
+ USHORT glyphIndexArray[]; /* Variable-length array containing subarrays
+ * used for mapping the low byte of 2-byte
+ * characters. */
+#endif
+} HIBYTETABLE;
+
+typedef struct SEGMENTTABLE {
+ USHORT format; /* Format number is set to 4. */
+ USHORT length; /* The actual length in bytes of this
+ * subtable. */
+ USHORT version; /* Version number (starts at 0). */
+ USHORT segCountX2; /* 2 x segCount. */
+ USHORT searchRange; /* 2 x (2**floor(log2(segCount))). */
+ USHORT entrySelector; /* log2(searchRange/2). */
+ USHORT rangeShift; /* 2 x segCount - searchRange. */
+#if 0
+ USHORT endCount[segCount] /* End characterCode for each segment. */
+ USHORT reservedPad; /* Set to 0. */
+ USHORT startCount[segCount];/* Start character code for each segment. */
+ USHORT idDelta[segCount]; /* Delta for all character in segment. */
+ USHORT idRangeOffset[segCount]; /* Offsets into glyphIdArray or 0. */
+ USHORT glyphIdArray[] /* Glyph index array. */
+#endif
+} SEGMENTTABLE;
+
+typedef struct TRIMMEDTABLE {
+ USHORT format; /* Format number is set to 6. */
+ USHORT length; /* The actual length in bytes of this
+ * subtable. */
+ USHORT version; /* Version number (starts at 0). */
+ USHORT firstCode; /* First character code of subrange. */
+ USHORT entryCount; /* Number of character codes in subrange. */
+#if 0
+ USHORT glyphIdArray[]; /* Array of glyph index values for
+ character codes in the range. */
+#endif
+} TRIMMEDTABLE;
+
+typedef union SUBTABLE {
+ ANYTABLE any;
+ BYTETABLE byte;
+ HIBYTETABLE hiByte;
+ SEGMENTTABLE segment;
+ TRIMMEDTABLE trimmed;
+} SUBTABLE;
+
+#pragma pack()
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * LoadFontRanges --
+ *
+ * Given an HFONT, get the information about the characters that
+ * this font can display.
+ *
+ * Results:
+ * If the font has no Unicode character information, the return value
+ * is 0 and *startCountPtr and *endCountPtr are filled with NULL.
+ * Otherwise, *startCountPtr and *endCountPtr are set to pointers to
+ * arrays of TrueType character existence information and the return
+ * value is the length of the arrays (the two arrays are always the
+ * same length as each other).
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static int
+LoadFontRanges(
+ HDC hdc, /* HDC into which font can be selected. */
+ HFONT hFont, /* HFONT to query. */
+ USHORT **startCountPtr, /* Filled with malloced pointer to
+ * character range information. */
+ USHORT **endCountPtr, /* Filled with malloced pointer to
+ * character range information. */
+ int *symbolPtr)
+ {
+ int n, i, swapped, offset, cbData, segCount;
+ DWORD cmapKey;
+ USHORT *startCount, *endCount;
+ CMAPTABLE cmapTable;
+ ENCODINGTABLE encTable;
+ SUBTABLE subTable;
+ char *s;
+
+ segCount = 0;
+ startCount = NULL;
+ endCount = NULL;
+ *symbolPtr = 0;
+
+ hFont = SelectObject(hdc, hFont);
+
+ i = 0;
+ s = (char *) &i;
+ *s = '\1';
+ swapped = 0;
+
+ if (i == 1) {
+ swapped = 1;
+ }
+
+ cmapKey = CMAPHEX;
+ if (swapped) {
+ SwapLong(&cmapKey);
+ }
+
+ n = GetFontData(hdc, cmapKey, 0, &cmapTable, sizeof(cmapTable));
+ if (n != GDI_ERROR) {
+ if (swapped) {
+ SwapShort(&cmapTable.numTables);
+ }
+ for (i = 0; i < cmapTable.numTables; i++) {
+ offset = sizeof(cmapTable) + i * sizeof(encTable);
+ GetFontData(hdc, cmapKey, offset, &encTable, sizeof(encTable));
+ if (swapped) {
+ SwapShort(&encTable.platform);
+ SwapShort(&encTable.encoding);
+ SwapLong(&encTable.offset);
+ }
+ if (encTable.platform != 3) {
+ /*
+ * Not Microsoft encoding.
+ */
+
+ continue;
+ }
+ if (encTable.encoding == 0) {
+ *symbolPtr = 1;
+ } else if (encTable.encoding != 1) {
+ continue;
+ }
+
+ GetFontData(hdc, cmapKey, encTable.offset, &subTable,
+ sizeof(subTable));
+ if (swapped) {
+ SwapShort(&subTable.any.format);
+ }
+ if (subTable.any.format == 4) {
+ if (swapped) {
+ SwapShort(&subTable.segment.segCountX2);
+ }
+ segCount = subTable.segment.segCountX2 / 2;
+ cbData = segCount * sizeof(USHORT);
+
+ startCount = (USHORT *) ckalloc(cbData);
+ endCount = (USHORT *) ckalloc(cbData);
+
+ offset = encTable.offset + sizeof(subTable.segment);
+ GetFontData(hdc, cmapKey, offset, endCount, cbData);
+ offset += cbData + sizeof(USHORT);
+ GetFontData(hdc, cmapKey, offset, startCount, cbData);
+ if (swapped) {
+ for (i = 0; i < segCount; i++) {
+ SwapShort(&endCount[i]);
+ SwapShort(&startCount[i]);
+ }
+ }
+ if (*symbolPtr != 0) {
+ /*
+ * Empirically determined: When a symbol font is
+ * loaded, the character existence metrics obtained
+ * from the system are mildly wrong. If the real range
+ * of the symbol font is from 0020 to 00FE, then the
+ * metrics are reported as F020 to F0FE. When we load
+ * a symbol font, we must fix the character existence
+ * metrics.
+ *
+ * Symbol fonts should only use the symbol encoding
+ * for 8-bit characters [note Bug: 2406]
+ */
+
+ for (i = 0; i < segCount; i++) {
+ if (((startCount[i] & 0xff00) == 0xf000)
+ && ((endCount[i] & 0xff00) == 0xf000)) {
+ startCount[i] &= 0xff;
+ endCount[i] &= 0xff;
+ }
+ }
+ }
+ }
+ }
+ }
+ SelectObject(hdc, hFont);
+
+ *startCountPtr = startCount;
+ *endCountPtr = endCount;
+ return segCount;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * SwapShort, SwapLong --
+ *
+ * Helper functions to convert the data loaded from TrueType font
+ * files to Intel byte ordering.
+ *
+ * Results:
+ * Bytes of input value are swapped and stored back in argument.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+SwapShort(PUSHORT p)
+{
+ *p = (SHORT)(HIBYTE(*p) + (LOBYTE(*p) << 8));
+}
+
+static void
+SwapLong(PULONG p)
+{
+ ULONG temp;
+
+ temp = (LONG) ((BYTE) *p);
+ temp <<= 8;
+ *p >>=8;
+
+ temp += (LONG) ((BYTE) *p);
+ temp <<= 8;
+ *p >>=8;
+
+ temp += (LONG) ((BYTE) *p);
+ temp <<= 8;
+ *p >>=8;
+
+ temp += (LONG) ((BYTE) *p);
+ *p = temp;
+}
+
diff --git a/tk/win/tkWinImage.c b/tk/win/tkWinImage.c
index dca6583b669..7cbdfde9036 100644
--- a/tk/win/tkWinImage.c
+++ b/tk/win/tkWinImage.c
@@ -35,7 +35,7 @@ static int PutPixel _ANSI_ARGS_((XImage *image, int x, int y,
*----------------------------------------------------------------------
*/
-int
+static int
DestroyImage(imagePtr)
XImage *imagePtr; /* image to free */
{
@@ -64,7 +64,7 @@ DestroyImage(imagePtr)
*----------------------------------------------------------------------
*/
-unsigned long
+static unsigned long
ImageGetPixel(image, x, y)
XImage *image;
int x, y;
@@ -327,3 +327,4 @@ XGetImage(display, d, x, y, width, height, plane_mask, format)
return imagePtr;
}
+
diff --git a/tk/win/tkWinInit.c b/tk/win/tkWinInit.c
index 4ddfd56cb4e..29f2246c977 100644
--- a/tk/win/tkWinInit.c
+++ b/tk/win/tkWinInit.c
@@ -43,6 +43,12 @@ int
TkpInit(interp)
Tcl_Interp *interp;
{
+ /*
+ * This is necessary for static initialization, and is ok
+ * otherwise because TkWinXInit flips a static bit to do
+ * its work just once.
+ */
+ TkWinXInit(GetModuleHandle(NULL));
return Tcl_Eval(interp, initScript);
}
@@ -116,6 +122,19 @@ TkpDisplayWarning(msg, title)
char *msg; /* Message to be displayed. */
char *title; /* Title of warning. */
{
- MessageBox(NULL, msg, title, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL
- | MB_SETFOREGROUND | MB_TOPMOST);
+ int l;
+
+ if ( GetStdHandle(STD_ERROR_HANDLE) != INVALID_HANDLE_VALUE &&
+ GetFileType(GetStdHandle(STD_ERROR_HANDLE)) != FILE_TYPE_UNKNOWN ) {
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), title, strlen(title), &l, NULL);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), ": " , 2 , &l, NULL);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg , strlen(msg) , &l, NULL);
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), "\n" , 1 , &l, NULL);
+ FlushFileBuffers(GetStdHandle(STD_ERROR_HANDLE));
+ } else {
+ MessageBox(NULL, msg, title, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL
+ | MB_SETFOREGROUND | MB_TOPMOST);
+ }
}
+
+
diff --git a/tk/win/tkWinInt.h b/tk/win/tkWinInt.h
index 853709861d3..37f5dda2079 100644
--- a/tk/win/tkWinInt.h
+++ b/tk/win/tkWinInt.h
@@ -5,7 +5,8 @@
* Windows-specific parts of Tk, but aren't used by the rest of
* Tk.
*
- * Copyright (c) 1995 Sun Microsystems, Inc.
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-2000 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -28,6 +29,11 @@
#include "tkWin.h"
#endif
+#ifndef _TKPORT
+#include "tkPort.h"
+#endif
+
+
/*
* Define constants missing from older Win32 SDK header files.
*/
@@ -36,12 +42,6 @@
#define WS_EX_TOOLWINDOW 0x00000080L
#endif
-#ifndef __GNUC__
-/* gcc won't let us do this--it causes a conflict with the typedef in
- tkFont.h (as it should). */
-typedef struct TkFontAttributes TkFontAttributes;
-#endif
-
/*
* The TkWinDCState is used to save the state of a device context
* so that it can be restored later.
@@ -49,6 +49,7 @@ typedef struct TkFontAttributes TkFontAttributes;
typedef struct TkWinDCState {
HPALETTE palette;
+ int bkmode;
} TkWinDCState;
/*
@@ -90,11 +91,11 @@ typedef union {
* The following macros are used to retrieve internal values from a Drawable.
*/
-#define TkWinGetHWND(w) (((TkWinDrawable *) w)->window.handle)
-#define TkWinGetWinPtr(w) (((TkWinDrawable*)w)->window.winPtr)
-#define TkWinGetHBITMAP(w) (((TkWinDrawable*)w)->bitmap.handle)
-#define TkWinGetColormap(w) (((TkWinDrawable*)w)->bitmap.colormap)
-#define TkWinGetHDC(w) (((TkWinDrawable *) w)->winDC.hdc)
+#define TkWinGetHWND(w) (((TkWinDrawable *) w)->window.handle)
+#define TkWinGetWinPtr(w) (((TkWinDrawable *) w)->window.winPtr)
+#define TkWinGetHBITMAP(w) (((TkWinDrawable *) w)->bitmap.handle)
+#define TkWinGetColormap(w) (((TkWinDrawable *) w)->bitmap.colormap)
+#define TkWinGetHDC(w) (((TkWinDrawable *) w)->winDC.hdc)
/*
* The following structure is used to encapsulate palette information.
@@ -125,13 +126,6 @@ typedef struct {
#define TK_WIN_CHILD_CLASS_NAME "TkChild"
/*
- * The following variable indicates whether we are restricted to Win32s
- * GDI calls.
- */
-
-extern int tkpIsWin32s;
-
-/*
* The following variable is a translation table between X gc functions and
* Win32 raster op modes.
*/
@@ -150,53 +144,29 @@ extern int tkpWinRopModes[];
* Internal procedures used by more than one source file.
*/
-extern LRESULT CALLBACK TkWinChildProc _ANSI_ARGS_((HWND hwnd, UINT message,
+#include "tkIntPlatDecls.h"
+
+/*
+ * We need to specially add the TkWinChildProc because of the special
+ * prototype it has (doesn't fit into stubs schema)
+ */
+#ifdef BUILD_tk
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+EXTERN LRESULT CALLBACK TkWinChildProc _ANSI_ARGS_((HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam));
-extern void TkWinClipboardRender _ANSI_ARGS_((TkDisplay *dispPtr,
- UINT format));
-extern LRESULT TkWinEmbeddedEventProc _ANSI_ARGS_((HWND hwnd,
- UINT message, WPARAM wParam, LPARAM lParam));
-extern void TkWinFillRect _ANSI_ARGS_((HDC dc, int x, int y,
- int width, int height, int pixel));
-extern COLORREF TkWinGetBorderPixels _ANSI_ARGS_((Tk_Window tkwin,
- Tk_3DBorder border, int which));
-extern HDC TkWinGetDrawableDC _ANSI_ARGS_((Display *display,
- Drawable d, TkWinDCState* state));
-extern int TkWinGetModifierState _ANSI_ARGS_((void));
-extern HPALETTE TkWinGetSystemPalette _ANSI_ARGS_((void));
-extern HWND TkWinGetWrapperWindow _ANSI_ARGS_((Tk_Window tkwin));
-extern int TkWinHandleMenuEvent _ANSI_ARGS_((HWND *phwnd,
- UINT *pMessage, WPARAM *pwParam, LPARAM *plParam,
- LRESULT *plResult));
-extern int TkWinIndexOfColor _ANSI_ARGS_((XColor *colorPtr));
-extern void TkWinPointerDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern void TkWinPointerEvent _ANSI_ARGS_((HWND hwnd, int x,
- int y));
-extern void TkWinPointerInit _ANSI_ARGS_((void));
-extern LRESULT TkWinReflectMessage _ANSI_ARGS_((HWND hwnd,
- UINT message, WPARAM wParam, LPARAM lParam));
-extern void TkWinReleaseDrawableDC _ANSI_ARGS_((Drawable d,
- HDC hdc, TkWinDCState* state));
-extern LRESULT TkWinResendEvent _ANSI_ARGS_((WNDPROC wndproc,
- HWND hwnd, XEvent *eventPtr));
-extern HPALETTE TkWinSelectPalette _ANSI_ARGS_((HDC dc,
- Colormap colormap));
-extern void TkWinSetMenu _ANSI_ARGS_((Tk_Window tkwin,
- HMENU hMenu));
-extern void TkWinSetWindowPos _ANSI_ARGS_((HWND hwnd,
- HWND siblingHwnd, int pos));
-extern void TkWinUpdateCursor _ANSI_ARGS_((TkWindow *winPtr));
-extern void TkWinWmCleanup _ANSI_ARGS_((HINSTANCE hInstance));
-extern HWND TkWinWmFindEmbedAssociation _ANSI_ARGS_((
- TkWindow *winPtr));
-extern void TkWinWmStoreEmbedAssociation _ANSI_ARGS_((
- TkWindow *winPtr, HWND hwnd));
-extern void TkWinXCleanup _ANSI_ARGS_((HINSTANCE hInstance));
-extern void TkWinXInit _ANSI_ARGS_((HINSTANCE hInstance));
-
-/* CYGNUS LOCAL. */
-extern void TkWinNCMetricsChanged _ANSI_ARGS_((Tk_Window tkwin));
-extern void TkWinSysColorChange _ANSI_ARGS_((void));
+
+/*
+ * Special proc needed as tsd accessor function between
+ * tkWinX.c:GenerateXEvent and tkWinClipboard.c:UpdateClipboard
+ */
+EXTERN void TkWinUpdatingClipboard(int mode);
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TKWININT */
+
diff --git a/tk/win/tkWinKey.c b/tk/win/tkWinKey.c
index 02d984e8119..c60d1bfa1cb 100644
--- a/tk/win/tkWinKey.c
+++ b/tk/win/tkWinKey.c
@@ -1,4 +1,4 @@
-/*
+/*
* tkWinKey.c --
*
* This file contains X emulation routines for keyboard related
@@ -13,158 +13,103 @@
*/
#include "tkWinInt.h"
-
-/*
- * FIXME - these are in i386-cygwin32/includes/Windows32/Defines.h
- * but not in the current Progressive release...
+/*
+ * The keymap table holds mappings of Windows keycodes to X keysyms.
+ * If Windows ever comes along and changes the value of their keycodes,
+ * this will break all kinds of things. However, this table lookup is much
+ * faster than the alternative, in which we walked a list of keycodes looking
+ * for a match. Since this lookup is performed for every Windows keypress
+ * event, it seems like a worthwhile improvement to use the table.
*/
-
-#ifdef __CYGWIN32__
-#define VK_LWIN (91)
-#define VK_RWIN (92)
-#define VK_APPS (93)
-#endif
-
-typedef struct {
- unsigned int keycode;
- KeySym keysym;
-} Keys;
-
-static Keys keymap[] = {
- VK_CANCEL, XK_Cancel,
- VK_BACK, XK_BackSpace,
- VK_TAB, XK_Tab,
- VK_CLEAR, XK_Clear,
- VK_RETURN, XK_Return,
- VK_SHIFT, XK_Shift_L,
- VK_CONTROL, XK_Control_L,
- VK_MENU, XK_Alt_L,
- VK_PAUSE, XK_Pause,
- VK_CAPITAL, XK_Caps_Lock,
- VK_ESCAPE, XK_Escape,
- VK_SPACE, XK_space,
- VK_PRIOR, XK_Prior,
- VK_NEXT, XK_Next,
- VK_END, XK_End,
- VK_HOME, XK_Home,
- VK_LEFT, XK_Left,
- VK_UP, XK_Up,
- VK_RIGHT, XK_Right,
- VK_DOWN, XK_Down,
- VK_SELECT, XK_Select,
- VK_PRINT, XK_Print,
- VK_EXECUTE, XK_Execute,
- VK_INSERT, XK_Insert,
- VK_DELETE, XK_Delete,
- VK_HELP, XK_Help,
- VK_F1, XK_F1,
- VK_F2, XK_F2,
- VK_F3, XK_F3,
- VK_F4, XK_F4,
- VK_F5, XK_F5,
- VK_F6, XK_F6,
- VK_F7, XK_F7,
- VK_F8, XK_F8,
- VK_F9, XK_F9,
- VK_F10, XK_F10,
- VK_F11, XK_F11,
- VK_F12, XK_F12,
- VK_F13, XK_F13,
- VK_F14, XK_F14,
- VK_F15, XK_F15,
- VK_F16, XK_F16,
- VK_F17, XK_F17,
- VK_F18, XK_F18,
- VK_F19, XK_F19,
- VK_F20, XK_F20,
- VK_F21, XK_F21,
- VK_F22, XK_F22,
- VK_F23, XK_F23,
- VK_F24, XK_F24,
- VK_NUMLOCK, XK_Num_Lock,
- VK_SCROLL, XK_Scroll_Lock,
-
- /*
- * The following support the new keys in the Microsoft keyboard.
- * Win_L and Win_R have the windows logo. App has the menu.
- */
-
- VK_LWIN, XK_Win_L,
- VK_RWIN, XK_Win_R,
- VK_APPS, XK_App,
-
- 0, NoSymbol
+#define MAX_KEYCODE 145 /* VK_SCROLL is the last entry in our table below */
+static KeySym keymap[] = {
+ NoSymbol, NoSymbol, NoSymbol, XK_Cancel, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, XK_BackSpace, XK_Tab,
+ NoSymbol, NoSymbol, XK_Clear, XK_Return, NoSymbol,
+ NoSymbol, XK_Shift_L, XK_Control_L, XK_Alt_L, XK_Pause,
+ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, XK_Escape, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, XK_space, XK_Prior, XK_Next,
+ XK_End, XK_Home, XK_Left, XK_Up, XK_Right,
+ XK_Down, XK_Select, XK_Print, XK_Execute, NoSymbol,
+ XK_Insert, XK_Delete, XK_Help, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, XK_Win_L, XK_Win_R, XK_App, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, XK_F1, XK_F2, XK_F3,
+ XK_F4, XK_F5, XK_F6, XK_F7, XK_F8,
+ XK_F9, XK_F10, XK_F11, XK_F12, XK_F13,
+ XK_F14, XK_F15, XK_F16, XK_F17, XK_F18,
+ XK_F19, XK_F20, XK_F21, XK_F22, XK_F23,
+ XK_F24, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, XK_Num_Lock,
+ XK_Scroll_Lock
};
+/*
+ * Prototypes for local procedures defined in this file:
+ */
+
+static KeySym KeycodeToKeysym _ANSI_ARGS_((unsigned int keycode,
+ int state, int noascii));
/*
*----------------------------------------------------------------------
*
- * XLookupString --
+ * TkpGetString --
*
- * Retrieve the string equivalent for the given keyboard event.
+ * Retrieve the UTF string equivalent for the given keyboard event.
*
* Results:
- * Returns the number of characters stored in buffer_return.
+ * Returns the UTF string.
*
* Side effects:
- * Retrieves the characters stored in the event and inserts them
- * into buffer_return.
+ * None.
*
*----------------------------------------------------------------------
*/
-int
-XLookupString(event_struct, buffer_return, bytes_buffer, keysym_return,
- status_in_out)
- XKeyEvent* event_struct;
- char* buffer_return;
- int bytes_buffer;
- KeySym* keysym_return;
- XComposeStatus* status_in_out;
+char *
+TkpGetString(winPtr, eventPtr, dsPtr)
+ TkWindow *winPtr; /* Window where event occurred: needed to
+ * get input context. */
+ XEvent *eventPtr; /* X keyboard event. */
+ Tcl_DString *dsPtr; /* Uninitialized or empty string to hold
+ * result. */
{
- int i, limit;
+ KeySym keysym;
+ XKeyEvent* keyEv = &eventPtr->xkey;
- if (event_struct->send_event != -1) {
+ Tcl_DStringInit(dsPtr);
+ if (eventPtr->xkey.send_event != -1) {
/*
* This is an event generated from generic code. It has no
* nchars or trans_chars members.
*/
- int index;
- KeySym keysym;
-
- index = 0;
- if (event_struct->state & ShiftMask) {
- index |= 1;
- }
- if (event_struct->state & Mod1Mask) {
- index |= 2;
- }
- keysym = XKeycodeToKeysym(event_struct->display,
- event_struct->keycode, index);
+ keysym = KeycodeToKeysym(eventPtr->xkey.keycode,
+ eventPtr->xkey.state, 0);
if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256))
|| (keysym == XK_Return)
|| (keysym == XK_Tab)) {
- buffer_return[0] = (char) keysym;
- return 1;
+ char buf[TCL_UTF_MAX];
+ int len = Tcl_UniCharToUtf((Tcl_UniChar) (keysym & 255), buf);
+ Tcl_DStringAppend(dsPtr, buf, len);
}
- return 0;
- }
- if ((event_struct->nchars <= 0) || (buffer_return == NULL)) {
- return 0;
+ } else if (eventPtr->xkey.nbytes > 0) {
+ Tcl_ExternalToUtfDString(NULL, eventPtr->xkey.trans_chars,
+ eventPtr->xkey.nbytes, dsPtr);
}
- limit = (event_struct->nchars < bytes_buffer) ? event_struct->nchars :
- bytes_buffer;
-
- for (i = 0; i < limit; i++) {
- buffer_return[i] = event_struct->trans_chars[i];
- }
-
- if (keysym_return != NULL) {
- *keysym_return = NoSymbol;
- }
- return i;
+ return Tcl_DStringValue(dsPtr);
}
/*
@@ -190,41 +135,444 @@ XKeycodeToKeysym(display, keycode, index)
unsigned int keycode;
int index;
{
- Keys* key;
+ int state = 0;
+
+ if (index & 0x01) {
+ state |= ShiftMask;
+ }
+ return KeycodeToKeysym(keycode, state, 0);
+}
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * KeycodeToKeysym --
+ *
+ * Translate from a system-dependent keycode to a
+ * system-independent keysym.
+ *
+ * Results:
+ * Returns the translated keysym, or NoSymbol on failure.
+ *
+ * Side effects:
+ * It may affect the internal state of the keyboard, such as
+ * remembered dead key or lock indicator lamps.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static KeySym
+KeycodeToKeysym(keycode, state, noascii)
+ unsigned int keycode;
+ int state;
+ int noascii;
+{
BYTE keys[256];
- int result;
+ int result, deadkey, shift;
char buf[4];
unsigned int scancode = MapVirtualKey(keycode, 0);
+ /*
+ * Do not run keycodes of lock keys through ToAscii().
+ * One of ToAscii()'s side effects is to handle the lights
+ * on the keyboard, and we don't want to mess that up.
+ */
+
+ if (noascii || keycode == VK_CAPITAL || keycode == VK_SCROLL ||
+ keycode == VK_NUMLOCK)
+ goto skipToAscii;
+
+ /*
+ * Use MapVirtualKey() to detect some dead keys.
+ */
+
+ if (MapVirtualKey(keycode, 2) > 0x7fffUL)
+ return XK_Multi_key;
+
+ /*
+ * Set up a keyboard with correct modifiers
+ */
+
memset(keys, 0, 256);
- if (index & 0x02) {
+ if (state & ShiftMask)
+ keys[VK_SHIFT] = 0x80;
+ if (state & ControlMask)
+ keys[VK_CONTROL] = 0x80;
+ if (state & Mod2Mask)
+ keys[VK_MENU] = 0x80;
+
+ /*
+ * Make sure all lock button info is correct so we don't mess up the
+ * lights
+ */
+
+ if (state & LockMask)
+ keys[VK_CAPITAL] = 1;
+ if (state & Mod3Mask)
+ keys[VK_SCROLL] = 1;
+ if (state & Mod1Mask)
keys[VK_NUMLOCK] = 1;
+
+ result = ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);
+
+ if (result < 0) {
+ /*
+ * Win95/98:
+ * This was a dead char, which is now remembered by the keyboard.
+ * Call ToAscii() again to forget it.
+ * WinNT:
+ * This was a dead char, overwriting any previously remembered
+ * key. Calling ToAscii() again does not affect anything.
+ */
+
+ ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);
+ return XK_Multi_key;
}
- if (index & 0x01) {
- keys[VK_SHIFT] = 0x80;
+ if (result == 2) {
+ /*
+ * This was a dead char, and there were one previously remembered
+ * by the keyboard.
+ * Call ToAscii() again with proper parameters to restore it.
+ */
+
+ /*
+ * Get information about the old char
+ */
+
+ deadkey = VkKeyScan(buf[0]);
+ shift = deadkey >> 8;
+ deadkey &= 255;
+ scancode = MapVirtualKey(deadkey, 0);
+
+ /*
+ * Set up a keyboard with proper modifier keys
+ */
+
+ memset(keys, 0, 256);
+ if (shift & 1)
+ keys[VK_SHIFT] = 0x80;
+ if (shift & 2)
+ keys[VK_CONTROL] = 0x80;
+ if (shift & 4)
+ keys[VK_MENU] = 0x80;
+ ToAscii(deadkey, scancode, keys, (LPWORD) buf, 0);
+ return XK_Multi_key;
}
- result = ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);
/*
* Keycode mapped to a valid Latin-1 character. Since the keysyms
* for alphanumeric characters map onto Latin-1, we just return it.
+ *
+ * We treat 0x7F as a special case mostly for backwards compatibility.
+ * In versions of Tk<=8.2, Control-Backspace returned "XK_BackSpace"
+ * as the X Keysym. This was due to the fact that we did not
+ * initialize the keys array properly when we passed it to ToAscii, above.
+ * We had previously not been setting the state bit for the Control key.
+ * When we fixed that, we found that Control-Backspace on Windows is
+ * interpreted as ASCII-127 (0x7F), which corresponds to the Delete key.
+ *
+ * Upon discovering this, we realized we had two choices: return XK_Delete
+ * or return XK_BackSpace. If we returned XK_Delete, that could be
+ * considered "more correct" (although the correctness would be dependant
+ * on whether you believe that ToAscii is doing the right thing in that
+ * case); however, this would break backwards compatibility, and worse,
+ * it would limit application programmers -- they would effectively be
+ * unable to bind to <Control-Backspace> on Windows. We therefore chose
+ * instead to return XK_BackSpace (handled here by letting the code
+ * "fall-through" to the return statement below, which works because the
+ * keycode for this event is VK_BACKSPACE, and the keymap table maps that
+ * keycode to XK_BackSpace).
*/
- if (result == 1 && buf[0] >= 0x20) {
- return (KeySym) buf[0];
+ if (result == 1 && UCHAR(buf[0]) >= 0x20 && UCHAR(buf[0]) != 0x7F) {
+ return (KeySym) UCHAR(buf[0]);
}
/*
* Keycode is a non-alphanumeric key, so we have to do the lookup.
*/
- for (key = keymap; key->keycode != 0; key++) {
- if (key->keycode == keycode) {
- return key->keysym;
+ skipToAscii:
+ if (keycode < 0 || keycode > MAX_KEYCODE) {
+ return NoSymbol;
+ }
+ switch (keycode) {
+ /*
+ * Windows only gives us an undifferentiated VK_CONTROL
+ * code (for example) when either Control key is pressed.
+ * To distinguish between left and right, we have to query the
+ * state of one of the two to determine which was actually
+ * pressed. So if the keycode indicates Control, Shift, or Menu
+ * (the key that everybody else calls Alt), do this extra test.
+ * If the right-side key was pressed, return the appropriate
+ * keycode. Otherwise, we fall through and rely on the
+ * keymap table to hold the correct keysym value.
+ */
+ case VK_CONTROL: {
+ if (GetKeyState(VK_RCONTROL) & 0x80) {
+ return XK_Control_R;
+ }
+ break;
+ }
+ case VK_SHIFT: {
+ if (GetKeyState(VK_RSHIFT) & 0x80) {
+ return XK_Shift_R;
+ }
+ break;
+ }
+ case VK_MENU: {
+ if (GetKeyState(VK_RMENU) & 0x80) {
+ return XK_Alt_R;
+ }
+ break;
}
}
+ return keymap[keycode];
+}
+
- return NoSymbol;
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetKeySym --
+ *
+ * Given an X KeyPress or KeyRelease event, map the
+ * keycode in the event into a KeySym.
+ *
+ * Results:
+ * The return value is the KeySym corresponding to
+ * eventPtr, or NoSymbol if no matching Keysym could be
+ * found.
+ *
+ * Side effects:
+ * In the first call for a given display, keycode-to-
+ * KeySym maps get loaded.
+ *
+ *----------------------------------------------------------------------
+ */
+
+KeySym
+TkpGetKeySym(dispPtr, eventPtr)
+ TkDisplay *dispPtr; /* Display in which to map keycode. */
+ XEvent *eventPtr; /* Description of X event. */
+{
+ KeySym sym;
+ int state = eventPtr->xkey.state;
+
+ /*
+ * Refresh the mapping information if it's stale
+ */
+
+ if (dispPtr->bindInfoStale) {
+ TkpInitKeymapInfo(dispPtr);
+ }
+
+ sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);
+
+ /*
+ * Special handling: if this is a ctrl-alt or shifted key, and there
+ * is no keysym defined, try without the modifiers.
+ */
+
+ if ((sym == NoSymbol) && ((state & ControlMask) || (state & Mod2Mask))) {
+ state &= ~(ControlMask | Mod2Mask);
+ sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);
+ }
+ if ((sym == NoSymbol) && (state & ShiftMask)) {
+ state &= ~ShiftMask;
+ sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);
+ }
+ return sym;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkpInitKeymapInfo --
+ *
+ * This procedure is invoked to scan keymap information
+ * to recompute stuff that's important for binding, such
+ * as the modifier key (if any) that corresponds to "mode
+ * switch".
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Keymap-related information in dispPtr is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkpInitKeymapInfo(dispPtr)
+ TkDisplay *dispPtr; /* Display for which to recompute keymap
+ * information. */
+{
+ XModifierKeymap *modMapPtr;
+ KeyCode *codePtr;
+ KeySym keysym;
+ int count, i, j, max, arraySize;
+#define KEYCODE_ARRAY_SIZE 20
+
+ dispPtr->bindInfoStale = 0;
+ modMapPtr = XGetModifierMapping(dispPtr->display);
+
+ /*
+ * Check the keycodes associated with the Lock modifier. If
+ * any of them is associated with the XK_Shift_Lock modifier,
+ * then Lock has to be interpreted as Shift Lock, not Caps Lock.
+ */
+
+ dispPtr->lockUsage = LU_IGNORE;
+ codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
+ for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+ keysym = KeycodeToKeysym(*codePtr, 0, 1);
+ if (keysym == XK_Shift_Lock) {
+ dispPtr->lockUsage = LU_SHIFT;
+ break;
+ }
+ if (keysym == XK_Caps_Lock) {
+ dispPtr->lockUsage = LU_CAPS;
+ break;
+ }
+ }
+
+ /*
+ * Look through the keycodes associated with modifiers to see if
+ * the the "mode switch", "meta", or "alt" keysyms are associated
+ * with any modifiers. If so, remember their modifier mask bits.
+ */
+
+ dispPtr->modeModMask = 0;
+ dispPtr->metaModMask = 0;
+ dispPtr->altModMask = 0;
+ codePtr = modMapPtr->modifiermap;
+ max = 8*modMapPtr->max_keypermod;
+ for (i = 0; i < max; i++, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+ keysym = KeycodeToKeysym(*codePtr, 0, 1);
+ if (keysym == XK_Mode_switch) {
+ dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
+ dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
+ dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ }
+
+ /*
+ * Create an array of the keycodes for all modifier keys.
+ */
+
+ if (dispPtr->modKeyCodes != NULL) {
+ ckfree((char *) dispPtr->modKeyCodes);
+ }
+ dispPtr->numModKeyCodes = 0;
+ arraySize = KEYCODE_ARRAY_SIZE;
+ dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
+ (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
+ for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+
+ /*
+ * Make sure that the keycode isn't already in the array.
+ */
+
+ for (j = 0; j < dispPtr->numModKeyCodes; j++) {
+ if (dispPtr->modKeyCodes[j] == *codePtr) {
+ goto nextModCode;
+ }
+ }
+ if (dispPtr->numModKeyCodes >= arraySize) {
+ KeyCode *new;
+
+ /*
+ * Ran out of space in the array; grow it.
+ */
+
+ arraySize *= 2;
+ new = (KeyCode *) ckalloc((unsigned)
+ (arraySize * sizeof(KeyCode)));
+ memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
+ (dispPtr->numModKeyCodes * sizeof(KeyCode)));
+ ckfree((char *) dispPtr->modKeyCodes);
+ dispPtr->modKeyCodes = new;
+ }
+ dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
+ dispPtr->numModKeyCodes++;
+ nextModCode: continue;
+ }
+ XFreeModifiermap(modMapPtr);
+}
+
+/*
+ * When mapping from a keysym to a keycode, need
+ * information about the modifier state that should be used
+ * so that when they call XKeycodeToKeysym taking into
+ * account the xkey.state, they will get back the original
+ * keysym.
+ */
+
+void
+TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
+ Tk_Window tkwin;
+ KeySym keySym;
+ XEvent *eventPtr;
+{
+ int i;
+ SHORT result;
+ int shift;
+
+ eventPtr->xkey.keycode = 0;
+ if (keySym == NoSymbol) {
+ return;
+ }
+
+ /*
+ * We check our private map first for a virtual keycode,
+ * as VkKeyScan will return values that don't map to X
+ * for the "extended" Syms. This may be due to just casting
+ * problems below, but this works.
+ */
+ for (i = 0; i <= MAX_KEYCODE; i++) {
+ if (keymap[i] == keySym) {
+ eventPtr->xkey.keycode = i;
+ return;
+ }
+ }
+ if (keySym >= 0x20) {
+ result = VkKeyScan((char) keySym);
+ if (result != -1) {
+ shift = result >> 8;
+ if (shift & 1)
+ eventPtr->xkey.state |= ShiftMask;
+ if (shift & 2)
+ eventPtr->xkey.state |= ControlMask;
+ if (shift & 4)
+ eventPtr->xkey.state |= Mod2Mask;
+ eventPtr->xkey.keycode = (KeyCode) (result & 0xff);
+ }
+ }
+ {
+ /* Debug log */
+ FILE *fp = fopen("c:\\temp\\tklog.txt", "a");
+ if (fp != NULL) {
+ fprintf(fp, "TkpSetKeycode. Keycode %d State %d Keysym %d\n", eventPtr->xkey.keycode, eventPtr->xkey.state, keySym);
+ fclose(fp);
+ }
+ }
}
/*
@@ -248,9 +596,23 @@ XKeysymToKeycode(display, keysym)
Display* display;
KeySym keysym;
{
- Keys* key;
+ int i;
SHORT result;
+ /*
+ * We check our private map first for a virtual keycode,
+ * as VkKeyScan will return values that don't map to X
+ * for the "extended" Syms. This may be due to just casting
+ * problems below, but this works.
+ */
+ if (keysym == NoSymbol) {
+ return 0;
+ }
+ for (i = 0; i <= MAX_KEYCODE; i++) {
+ if (keymap[i] == keysym) {
+ return ((KeyCode) i);
+ }
+ }
if (keysym >= 0x20) {
result = VkKeyScan((char) keysym);
if (result != -1) {
@@ -258,16 +620,6 @@ XKeysymToKeycode(display, keysym)
}
}
- /*
- * Couldn't map the character to a virtual keycode, so do a
- * table lookup.
- */
-
- for (key = keymap; key->keycode != 0; key++) {
- if (key->keysym == keysym) {
- return key->keycode;
- }
- }
return 0;
}
diff --git a/tk/win/tkWinMenu.c b/tk/win/tkWinMenu.c
index 8baefb25bdc..52a4aca8ea0 100644
--- a/tk/win/tkWinMenu.c
+++ b/tk/win/tkWinMenu.c
@@ -3,7 +3,8 @@
*
* This module implements the Windows platform-specific features of menus.
*
- * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -12,9 +13,10 @@
*/
#define OEMRESOURCE
-#include <string.h>
-#include "tkMenu.h"
#include "tkWinInt.h"
+#include "tkMenu.h"
+
+#include <string.h>
/*
* The class of the window for popup menus.
@@ -50,35 +52,36 @@ static int indicatorDimensions[2];
/* The dimensions of the indicator space
* in a menu entry. Calculated at init
* time to save time. */
-static Tcl_HashTable commandTable;
+
+typedef struct ThreadSpecificData {
+ Tcl_HashTable commandTable;
/* A map of command ids to menu entries */
-static int inPostMenu; /* We cannot be re-entrant like X Windows. */
-static WORD lastCommandID; /* The last command ID we allocated. */
-static HWND menuHWND; /* A window to service popup-menu messages
+ int inPostMenu; /* We cannot be re-entrant like X Windows. */
+ WORD lastCommandID; /* The last command ID we allocated. */
+ HWND menuHWND; /* A window to service popup-menu messages
* in. */
-static int oldServiceMode; /* Used while processing a menu; we need
+ int oldServiceMode; /* Used while processing a menu; we need
* to set the event mode specially when we
* enter the menu processing modal loop
* and reset it when menus go away. */
-static TkMenu *modalMenuPtr; /* The menu we are processing inside the modal
+ TkMenu *modalMenuPtr; /* The menu we are processing inside the modal
* loop. We need this to reset all of the
* active items when menus go away since
* Windows does not see fit to give this
* to us when it sends its WM_MENUSELECT. */
-static OSVERSIONINFO versionInfo;
- /* So we don't have to keep doing this */
-static Tcl_HashTable winMenuTable;
+ Tcl_HashTable winMenuTable;
/* Need this to map HMENUs back to menuPtrs */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* The following are default menu value strings.
*/
-static char borderString[5]; /* The string indicating how big the border is */
+static int defaultBorderWidth; /* The windows default border width. */
static Tcl_DString menuFontDString;
/* A buffer to store the default menu font
* string. */
-
/*
* Forward declarations for procedures defined later in this file:
*/
@@ -122,7 +125,7 @@ static void DrawWindowsSystemBitmap _ANSI_ARGS_((
GC gc, CONST RECT *rectPtr, int bitmapID,
int alignFlags));
static void FreeID _ANSI_ARGS_((int commandID));
-static char * GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr));
+static TCHAR * GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr));
static void GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr,
TkMenuEntry *mePtr, Tk_Font tkfont,
CONST Tk_FontMetrics *fmPtr, int *widthPtr,
@@ -144,7 +147,6 @@ static void GetTearoffEntryGeometry _ANSI_ARGS_((TkMenu *menuPtr,
int *heightPtr));
static int GetNewID _ANSI_ARGS_((TkMenuEntry *mePtr,
int *menuIDPtr));
-static void MenuExitProc _ANSI_ARGS_((ClientData clientData));
static int MenuKeyBindProc _ANSI_ARGS_((
ClientData clientData,
Tcl_Interp *interp, XEvent *eventPtr,
@@ -154,6 +156,7 @@ static void ReconfigureWindowsMenu _ANSI_ARGS_((
ClientData clientData));
static void RecursivelyClearActiveMenu _ANSI_ARGS_((
TkMenu *menuPtr));
+static void SetDefaults _ANSI_ARGS_((int firstTime));
static LRESULT CALLBACK TkWinMenuProc _ANSI_ARGS_((HWND hwnd,
UINT message, WPARAM wParam,
LPARAM lParam));
@@ -189,16 +192,18 @@ GetNewID(mePtr, menuIDPtr)
int newEntry;
Tcl_HashEntry *commandEntryPtr;
WORD returnID;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- WORD curID = lastCommandID + 1;
+ WORD curID = tsdPtr->lastCommandID + 1;
/*
* The following code relies on WORD wrapping when the highest value is
* incremented.
*/
- while (curID != lastCommandID) {
- commandEntryPtr = Tcl_CreateHashEntry(&commandTable,
+ while (curID != tsdPtr->lastCommandID) {
+ commandEntryPtr = Tcl_CreateHashEntry(&tsdPtr->commandTable,
(char *) curID, &newEntry);
if (newEntry == 1) {
found = 1;
@@ -211,7 +216,7 @@ GetNewID(mePtr, menuIDPtr)
if (found) {
Tcl_SetHashValue(commandEntryPtr, (char *) mePtr);
*menuIDPtr = (int) returnID;
- lastCommandID = returnID;
+ tsdPtr->lastCommandID = returnID;
return TCL_OK;
} else {
return TCL_ERROR;
@@ -238,7 +243,10 @@ static void
FreeID(commandID)
int commandID;
{
- Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&commandTable,
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
(char *) commandID);
if (entryPtr != NULL) {
@@ -272,6 +280,8 @@ TkpNewMenu(menuPtr)
HMENU winMenuHdl;
Tcl_HashEntry *hashEntryPtr;
int newEntry;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
winMenuHdl = CreatePopupMenu();
@@ -286,7 +296,7 @@ TkpNewMenu(menuPtr)
* back when dispatch messages.
*/
- hashEntryPtr = Tcl_CreateHashEntry(&winMenuTable, (char *) winMenuHdl,
+ hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable, (char *) winMenuHdl,
&newEntry);
Tcl_SetHashValue(hashEntryPtr, (char *) menuPtr);
@@ -315,6 +325,9 @@ TkpDestroyMenu(menuPtr)
TkMenu *menuPtr; /* The common menu structure */
{
HMENU winMenuHdl = (HMENU) menuPtr->platformData;
+ char *searchName;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr);
@@ -339,7 +352,8 @@ TkpDestroyMenu(menuPtr)
for (searchEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
searchEntryPtr != NULL;
searchEntryPtr = searchEntryPtr->nextCascadePtr) {
- if (strcmp(searchEntryPtr->name, menuName) == 0) {
+ searchName = Tcl_GetStringFromObj(searchEntryPtr->namePtr, NULL);
+ if (strcmp(searchName, menuName) == 0) {
Tk_Window parentTopLevelPtr = searchEntryPtr
->menuPtr->parentTopLevelPtr;
@@ -357,7 +371,8 @@ TkpDestroyMenu(menuPtr)
* Remove the menu from the menu hash table, then destroy the handle.
*/
- hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) winMenuHdl);
+ hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
+ (char *) winMenuHdl);
if (hashEntryPtr != NULL) {
Tcl_DeleteHashEntry(hashEntryPtr);
}
@@ -365,8 +380,8 @@ TkpDestroyMenu(menuPtr)
}
menuPtr->platformData = NULL;
- if (menuPtr == modalMenuPtr) {
- modalMenuPtr = NULL;
+ if (menuPtr == tsdPtr->modalMenuPtr) {
+ tsdPtr->modalMenuPtr = NULL;
}
}
@@ -431,18 +446,23 @@ GetEntryText(mePtr)
if (mePtr->type == TEAROFF_ENTRY) {
itemText = ckalloc(sizeof("(Tear-off)"));
strcpy(itemText, "(Tear-off)");
- } else if (mePtr->imageString != NULL) {
+ } else if (mePtr->imagePtr != NULL) {
itemText = ckalloc(sizeof("(Image)"));
strcpy(itemText, "(Image)");
- } else if (mePtr->bitmap != None) {
+ } else if (mePtr->bitmapPtr != NULL) {
itemText = ckalloc(sizeof("(Pixmap)"));
strcpy(itemText, "(Pixmap)");
- } else if (mePtr->label == NULL || mePtr->labelLength == 0) {
+ } else if (mePtr->labelPtr == NULL || mePtr->labelLength == 0) {
itemText = ckalloc(sizeof("( )"));
strcpy(itemText, "( )");
} else {
- int size = mePtr->labelLength + 1;
- int i, j;
+ int i;
+ char *label = (mePtr->labelPtr == NULL) ? ""
+ : Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
+ char *accel = (mePtr->accelPtr == NULL) ? ""
+ : Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
+ char *p, *next;
+ Tcl_DString itemString;
/*
* We have to construct the string with an ampersand
@@ -451,57 +471,32 @@ GetEntryText(mePtr)
* ampersands in the string.
*/
- for (i = 0; i < mePtr->labelLength; i++) {
- if (mePtr->label[i] == '&') {
- size++;
- }
- }
+ Tcl_DStringInit(&itemString);
- if (mePtr->underline >= 0) {
- size++;
- if (mePtr->label[mePtr->underline] == '&') {
- size++;
+ for (p = label, i = 0; *p != '\0'; i++, p = next) {
+ if (i == mePtr->underline) {
+ Tcl_DStringAppend(&itemString, "&", 1);
}
- }
-
- if (mePtr->accelLength > 0) {
- size += mePtr->accelLength + 1;
- }
-
- for (i = 0; i < mePtr->accelLength; i++) {
- if (mePtr->accel[i] == '&') {
- size++;
+ if (*p == '&') {
+ Tcl_DStringAppend(&itemString, "&", 1);
}
+ next = Tcl_UtfNext(p);
+ Tcl_DStringAppend(&itemString, p, next - p);
}
-
- itemText = ckalloc(size);
-
- if (mePtr->labelLength == 0) {
- itemText[0] = 0;
- } else {
- for (i = 0, j = 0; i < mePtr->labelLength; i++, j++) {
- if (mePtr->label[i] == '&') {
- itemText[j++] = '&';
- }
- if (i == mePtr->underline) {
- itemText[j++] = '&';
+ if (mePtr->accelLength > 0) {
+ Tcl_DStringAppend(&itemString, "\t", 1);
+ for (p = accel, i = 0; *p != '\0'; i++, p = next) {
+ if (*p == '&') {
+ Tcl_DStringAppend(&itemString, "&", 1);
}
- itemText[j] = mePtr->label[i];
+ next = Tcl_UtfNext(p);
+ Tcl_DStringAppend(&itemString, p, next - p);
}
- itemText[j] = '\0';
- }
+ }
- if (mePtr->accelLength > 0) {
- strcat(itemText, "\t");
- for (i = 0, j = strlen(itemText); i < mePtr->accelLength;
- i++, j++) {
- if (mePtr->accel[i] == '&') {
- itemText[j++] = '&';
- }
- itemText[j] = mePtr->accel[i];
- }
- itemText[j] = '\0';
- }
+ itemText = ckalloc(Tcl_DStringLength(&itemString) + 1);
+ strcpy(itemText, Tcl_DStringValue(&itemString));
+ Tcl_DStringFree(&itemString);
}
return itemText;
}
@@ -530,13 +525,14 @@ ReconfigureWindowsMenu(
TkMenu *menuPtr = (TkMenu *) clientData;
TkMenuEntry *mePtr;
HMENU winMenuHdl = (HMENU) menuPtr->platformData;
- char *itemText = NULL;
- LPCTSTR lpNewItem;
+ TCHAR *itemText = NULL;
+ const TCHAR *lpNewItem;
UINT flags;
UINT itemID;
int i, count, systemMenu = 0, base;
int width, height;
-
+ Tcl_DString translatedText;
+
if (NULL == winMenuHdl) {
return;
}
@@ -565,105 +561,117 @@ ReconfigureWindowsMenu(
lpNewItem = NULL;
flags = MF_BYPOSITION;
itemID = 0;
+ Tcl_DStringInit(&translatedText);
if ((menuPtr->menuType == MENUBAR) && (mePtr->type == TEAROFF_ENTRY)) {
continue;
}
- if (mePtr->type == SEPARATOR_ENTRY) {
- flags |= MF_SEPARATOR;
+ itemText = GetEntryText(mePtr);
+ if ((menuPtr->menuType == MENUBAR)
+ || (menuPtr->menuFlags & MENU_SYSTEM_MENU)) {
+ Tcl_UtfToExternalDString(NULL, itemText, -1, &translatedText);
+ lpNewItem = Tcl_DStringValue(&translatedText);
} else {
- itemText = GetEntryText(mePtr);
- if ((menuPtr->menuType == MENUBAR)
- || (menuPtr->menuFlags & MENU_SYSTEM_MENU)) {
- lpNewItem = itemText;
- } else {
- lpNewItem = (LPCTSTR) mePtr;
- flags |= MF_OWNERDRAW;
- }
-
- /*
- * Set enabling and disabling correctly.
- */
+ lpNewItem = (LPCTSTR) mePtr;
+ flags |= MF_OWNERDRAW;
+ }
- if (mePtr->state == tkDisabledUid) {
- flags |= MF_DISABLED;
- }
-
- /*
- * Set the check mark for check entries and radio entries.
- */
-
- if (((mePtr->type == CHECK_BUTTON_ENTRY)
- || (mePtr->type == RADIO_BUTTON_ENTRY))
- && (mePtr->entryFlags & ENTRY_SELECTED)) {
- flags |= MF_CHECKED;
- }
+ /*
+ * Set enabling and disabling correctly.
+ */
+
+ if (mePtr->state == ENTRY_DISABLED) {
+ flags |= MF_DISABLED | MF_GRAYED;
+ }
+
+ /*
+ * Set the check mark for check entries and radio entries.
+ */
+
+ if (((mePtr->type == CHECK_BUTTON_ENTRY)
+ || (mePtr->type == RADIO_BUTTON_ENTRY))
+ && (mePtr->entryFlags & ENTRY_SELECTED)) {
+ flags |= MF_CHECKED;
+ }
+
+ /*
+ * Set the SEPARATOR bit for separator entries. This bit is not
+ * used by our internal drawing functions, but it is used by the
+ * system when drawing the system menu (we do not draw the system menu
+ * ourselves). If this bit is not set, separator entries on the system
+ * menu will not be drawn correctly.
+ */
- if (mePtr->columnBreak) {
- flags |= MF_MENUBREAK;
+ if (mePtr->type == SEPARATOR_ENTRY) {
+ flags |= MF_SEPARATOR;
+ }
+
+ if (mePtr->columnBreak) {
+ flags |= MF_MENUBREAK;
+ }
+
+ itemID = (int) mePtr->platformEntryData;
+ if ((mePtr->type == CASCADE_ENTRY)
+ && (mePtr->childMenuRefPtr != NULL)
+ && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
+ HMENU childMenuHdl = (HMENU) mePtr->childMenuRefPtr->menuPtr
+ ->platformData;
+ if (childMenuHdl != NULL) {
+ itemID = (UINT) childMenuHdl;
+ flags |= MF_POPUP;
}
-
- itemID = (int) mePtr->platformEntryData;
- if ((mePtr->type == CASCADE_ENTRY)
- && (mePtr->childMenuRefPtr != NULL)
- && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
- HMENU childMenuHdl = (HMENU) mePtr->childMenuRefPtr->menuPtr
- ->platformData;
- if (childMenuHdl != NULL) {
- itemID = (UINT) childMenuHdl;
- flags |= MF_POPUP;
- }
- if ((menuPtr->menuType == MENUBAR)
- && !(mePtr->childMenuRefPtr->menuPtr->menuFlags
- & MENU_SYSTEM_MENU)) {
- TkMenuReferences *menuRefPtr;
- TkMenu *systemMenuPtr = mePtr->childMenuRefPtr
- ->menuPtr;
- char *systemMenuName = ckalloc(strlen(
- Tk_PathName(menuPtr->masterMenuPtr->tkwin))
- + strlen(".system") + 1);
-
- strcpy(systemMenuName,
- Tk_PathName(menuPtr->masterMenuPtr->tkwin));
- strcat(systemMenuName, ".system");
- menuRefPtr = TkFindMenuReferences(menuPtr->interp,
- systemMenuName);
- if ((menuRefPtr != NULL)
- && (menuRefPtr->menuPtr != NULL)
- && (menuPtr->parentTopLevelPtr != NULL)
- && (systemMenuPtr->masterMenuPtr
- == menuRefPtr->menuPtr)) {
- HMENU systemMenuHdl =
- (HMENU) systemMenuPtr->platformData;
- HWND wrapper = TkWinGetWrapperWindow(menuPtr
- ->parentTopLevelPtr);
- if (wrapper != NULL) {
- DestroyMenu(systemMenuHdl);
- systemMenuHdl = GetSystemMenu(wrapper, FALSE);
- systemMenuPtr->menuFlags |= MENU_SYSTEM_MENU;
- systemMenuPtr->platformData =
- (TkMenuPlatformData) systemMenuHdl;
- if (!(systemMenuPtr->menuFlags
- & MENU_RECONFIGURE_PENDING)) {
- systemMenuPtr->menuFlags
- |= MENU_RECONFIGURE_PENDING;
- Tcl_DoWhenIdle(ReconfigureWindowsMenu,
- (ClientData) systemMenuPtr);
- }
+ if ((menuPtr->menuType == MENUBAR)
+ && !(mePtr->childMenuRefPtr->menuPtr->menuFlags
+ & MENU_SYSTEM_MENU)) {
+ Tcl_DString ds;
+ TkMenuReferences *menuRefPtr;
+ TkMenu *systemMenuPtr = mePtr->childMenuRefPtr->menuPtr;
+
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds,
+ Tk_PathName(menuPtr->masterMenuPtr->tkwin), -1);
+ Tcl_DStringAppend(&ds, ".system", 7);
+
+ menuRefPtr = TkFindMenuReferences(menuPtr->interp,
+ Tcl_DStringValue(&ds));
+
+ Tcl_DStringFree(&ds);
+
+ if ((menuRefPtr != NULL)
+ && (menuRefPtr->menuPtr != NULL)
+ && (menuPtr->parentTopLevelPtr != NULL)
+ && (systemMenuPtr->masterMenuPtr
+ == menuRefPtr->menuPtr)) {
+ HMENU systemMenuHdl =
+ (HMENU) systemMenuPtr->platformData;
+ HWND wrapper = TkWinGetWrapperWindow(menuPtr
+ ->parentTopLevelPtr);
+ if (wrapper != NULL) {
+ DestroyMenu(systemMenuHdl);
+ systemMenuHdl = GetSystemMenu(wrapper, FALSE);
+ systemMenuPtr->menuFlags |= MENU_SYSTEM_MENU;
+ systemMenuPtr->platformData =
+ (TkMenuPlatformData) systemMenuHdl;
+ if (!(systemMenuPtr->menuFlags
+ & MENU_RECONFIGURE_PENDING)) {
+ systemMenuPtr->menuFlags
+ |= MENU_RECONFIGURE_PENDING;
+ Tcl_DoWhenIdle(ReconfigureWindowsMenu,
+ (ClientData) systemMenuPtr);
}
}
- ckfree(systemMenuName);
- }
- if (mePtr->childMenuRefPtr->menuPtr->menuFlags
- & MENU_SYSTEM_MENU) {
- systemMenu++;
}
}
+ if (mePtr->childMenuRefPtr->menuPtr->menuFlags
+ & MENU_SYSTEM_MENU) {
+ systemMenu++;
+ }
}
if (!systemMenu) {
InsertMenu(winMenuHdl, 0xFFFFFFFF, flags, itemID, lpNewItem);
}
+ Tcl_DStringFree(&translatedText);
if (itemText != NULL) {
ckfree(itemText);
itemText = NULL;
@@ -709,8 +717,10 @@ TkpPostMenu(interp, menuPtr, x, y)
POINT point;
Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);
int oldServiceMode = Tcl_GetServiceMode();
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- inPostMenu++;
+ tsdPtr->inPostMenu++;
if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr);
@@ -719,7 +729,7 @@ TkpPostMenu(interp, menuPtr, x, y)
result = TkPreprocessMenu(menuPtr);
if (result != TCL_OK) {
- inPostMenu--;
+ tsdPtr->inPostMenu--;
return result;
}
@@ -729,7 +739,7 @@ TkpPostMenu(interp, menuPtr, x, y)
*/
if (menuPtr->tkwin == NULL) {
- inPostMenu--;
+ tsdPtr->inPostMenu--;
return TCL_OK;
}
@@ -770,14 +780,14 @@ TkpPostMenu(interp, menuPtr, x, y)
}
TrackPopupMenu(winMenuHdl, flags, x, y, 0,
- menuHWND, &noGoawayRect);
+ tsdPtr->menuHWND, &noGoawayRect);
Tcl_SetServiceMode(oldServiceMode);
GetCursorPos(&point);
Tk_PointerEvent(NULL, point.x, point.y);
- if (inPostMenu) {
- inPostMenu = 0;
+ if (tsdPtr->inPostMenu) {
+ tsdPtr->inPostMenu = 0;
}
return TCL_OK;
}
@@ -886,24 +896,27 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
int returnResult = 0;
TkMenu *menuPtr;
TkMenuEntry *mePtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
switch (*pMessage) {
case WM_INITMENU:
TkMenuInit();
- hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) *pwParam);
+ hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
+ (char *) *pwParam);
if (hashEntryPtr != NULL) {
- oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
+ tsdPtr->oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
- modalMenuPtr = menuPtr;
+ tsdPtr->modalMenuPtr = menuPtr;
if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
Tcl_CancelIdleCall(ReconfigureWindowsMenu,
(ClientData) menuPtr);
ReconfigureWindowsMenu((ClientData) menuPtr);
}
- if (!inPostMenu) {
+ if (!tsdPtr->inPostMenu) {
Tcl_Interp *interp;
int code;
-
+
interp = menuPtr->interp;
Tcl_Preserve((ClientData)interp);
code = TkPreprocessMenu(menuPtr);
@@ -918,20 +931,17 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
*plResult = 0;
returnResult = 1;
} else {
- modalMenuPtr = NULL;
+ tsdPtr->modalMenuPtr = NULL;
}
break;
-#if 0
- /* CYGNUS LOCAL: WM_SYSCOMMAND is not the same as WM_COMMAND. */
case WM_SYSCOMMAND:
-#endif
case WM_COMMAND: {
TkMenuInit();
if (HIWORD(*pwParam) != 0) {
break;
}
- hashEntryPtr = Tcl_FindHashEntry(&commandTable,
+ hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
(char *)LOWORD(*pwParam));
if (hashEntryPtr == NULL) {
break;
@@ -952,21 +962,23 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
menuPtr = mePtr->menuPtr;
menuRefPtr = TkFindMenuReferences(menuPtr->interp,
Tk_PathName(menuPtr->tkwin));
- if ((menuRefPtr != NULL) && (menuRefPtr->parentEntryPtr
- != NULL)) {
- for (parentEntryPtr = menuRefPtr->parentEntryPtr;
- strcmp(parentEntryPtr->name,
- Tk_PathName(menuPtr->tkwin)) != 0;
- parentEntryPtr = parentEntryPtr->nextCascadePtr) {
-
- /*
- * Empty loop body.
- */
+ if ((menuRefPtr != NULL)
+ && (menuRefPtr->parentEntryPtr != NULL)) {
+ char *name;
+ for (parentEntryPtr = menuRefPtr->parentEntryPtr;
+ ;
+ parentEntryPtr =
+ parentEntryPtr->nextCascadePtr) {
+ name = Tcl_GetStringFromObj(
+ parentEntryPtr->namePtr, NULL);
+ if (strcmp(name, Tk_PathName(menuPtr->tkwin))
+ == 0) {
+ break;
+ }
}
- if (parentEntryPtr->menuPtr
- ->entries[parentEntryPtr->index]->state
- != tkDisabledUid) {
+ if (parentEntryPtr->menuPtr->entries[parentEntryPtr->index]
+ ->state != ENTRY_DISABLED) {
TkActivateMenuEntry(parentEntryPtr->menuPtr,
parentEntryPtr->index);
}
@@ -975,8 +987,8 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
interp = menuPtr->interp;
Tcl_Preserve((ClientData)interp);
code = TkInvokeMenu(interp, menuPtr, mePtr->index);
- if ((code != TCL_OK) && (code != TCL_CONTINUE)
- && (code != TCL_BREAK)) {
+ if (code != TCL_OK && code != TCL_CONTINUE
+ && code != TCL_BREAK) {
Tcl_AddErrorInfo(interp, "\n (menu invoke)");
Tcl_BackgroundError(interp);
}
@@ -990,19 +1002,27 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
case WM_MENUCHAR: {
unsigned char menuChar = (unsigned char) LOWORD(*pwParam);
- hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) *plParam);
+ hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
+ (char *) *plParam);
if (hashEntryPtr != NULL) {
int i;
*plResult = 0;
menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
for (i = 0; i < menuPtr->numEntries; i++) {
- int underline = menuPtr->entries[i]->underline;
+ int underline;
+ char *label;
+
+ underline = menuPtr->entries[i]->underline;
+ if (menuPtr->entries[i]->labelPtr != NULL) {
+ label = Tcl_GetStringFromObj(
+ menuPtr->entries[i]->labelPtr, NULL);
+ }
if ((-1 != underline)
- && (NULL != menuPtr->entries[i]->label)
+ && (NULL != menuPtr->entries[i]->labelPtr)
&& (CharUpper((LPTSTR) menuChar)
- == CharUpper((LPTSTR) (unsigned char) menuPtr
- ->entries[i]->label[underline]))) {
+ == CharUpper((LPTSTR) (unsigned char)
+ label[underline]))) {
*plResult = (2 << 16) | i;
returnResult = 1;
break;
@@ -1025,7 +1045,12 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
if (mePtr->hideMargin) {
itemPtr->itemWidth += 2 - indicatorDimensions[1];
} else {
- itemPtr->itemWidth += 2 * menuPtr->activeBorderWidth;
+ int activeBorderWidth;
+
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->activeBorderWidthPtr,
+ &activeBorderWidth);
+ itemPtr->itemWidth += 2 * activeBorderWidth;
}
*plResult = 1;
returnResult = 1;
@@ -1039,13 +1064,15 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
Tk_FontMetrics fontMetrics;
if (itemPtr != NULL) {
+ Tk_Font tkfont;
+
mePtr = (TkMenuEntry *) itemPtr->itemData;
menuPtr = mePtr->menuPtr;
twdPtr = (TkWinDrawable *) ckalloc(sizeof(TkWinDrawable));
twdPtr->type = TWD_WINDC;
twdPtr->winDC.hdc = itemPtr->hDC;
- if (mePtr->state != tkDisabledUid) {
+ if (mePtr->state != ENTRY_DISABLED) {
if (itemPtr->itemState & ODS_SELECTED) {
TkActivateMenuEntry(menuPtr, mePtr->index);
} else {
@@ -1053,8 +1080,9 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
}
}
- Tk_GetFontMetrics(menuPtr->tkfont, &fontMetrics);
- TkpDrawMenuEntry(mePtr, (Drawable) twdPtr, menuPtr->tkfont,
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
+ Tk_GetFontMetrics(tkfont, &fontMetrics);
+ TkpDrawMenuEntry(mePtr, (Drawable) twdPtr, tkfont,
&fontMetrics, itemPtr->rcItem.left,
itemPtr->rcItem.top, itemPtr->rcItem.right
- itemPtr->rcItem.left, itemPtr->rcItem.bottom
@@ -1073,14 +1101,14 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
TkMenuInit();
if ((flags == 0xFFFF) && (*plParam == 0)) {
- Tcl_SetServiceMode(oldServiceMode);
- if (modalMenuPtr != NULL) {
- RecursivelyClearActiveMenu(modalMenuPtr);
+ Tcl_SetServiceMode(tsdPtr->oldServiceMode);
+ if (tsdPtr->modalMenuPtr != NULL) {
+ RecursivelyClearActiveMenu(tsdPtr->modalMenuPtr);
}
} else {
menuPtr = NULL;
- if (*plParam != 0) {
- hashEntryPtr = Tcl_FindHashEntry(&winMenuTable,
+ if (*plParam != 0) {
+ hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
(char *) *plParam);
if (hashEntryPtr != NULL) {
menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
@@ -1093,15 +1121,17 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
if (flags & MF_POPUP) {
mePtr = menuPtr->entries[LOWORD(*pwParam)];
} else {
- hashEntryPtr = Tcl_FindHashEntry(&commandTable,
+ hashEntryPtr = Tcl_FindHashEntry(
+ &tsdPtr->commandTable,
(char *) LOWORD(*pwParam));
if (hashEntryPtr != NULL) {
- mePtr = (TkMenuEntry *) Tcl_GetHashValue(hashEntryPtr);
+ mePtr = (TkMenuEntry *)
+ Tcl_GetHashValue(hashEntryPtr);
}
}
}
- if ((mePtr == NULL) || (mePtr->state == tkDisabledUid)) {
+ if ((mePtr == NULL) || (mePtr->state == ENTRY_DISABLED)) {
TkActivateMenuEntry(menuPtr, -1);
} else {
TkActivateMenuEntry(menuPtr, mePtr->index);
@@ -1174,18 +1204,21 @@ TkpSetWindowMenuBar(tkwin, menuPtr)
TkMenu *menuPtr; /* The menu we are inserting */
{
HMENU winMenuHdl;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (menuPtr != NULL) {
Tcl_HashEntry *hashEntryPtr;
int newEntry;
winMenuHdl = (HMENU) menuPtr->platformData;
- hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) winMenuHdl);
+ hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
+ (char *) winMenuHdl);
Tcl_DeleteHashEntry(hashEntryPtr);
DestroyMenu(winMenuHdl);
winMenuHdl = CreateMenu();
- hashEntryPtr = Tcl_CreateHashEntry(&winMenuTable, (char *) winMenuHdl,
- &newEntry);
+ hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable,
+ (char *) winMenuHdl, &newEntry);
Tcl_SetHashValue(hashEntryPtr, (char *) menuPtr);
menuPtr->platformData = (TkMenuPlatformData) winMenuHdl;
TkWinSetMenu(tkwin, winMenuHdl);
@@ -1257,7 +1290,11 @@ GetMenuIndicatorGeometry (
if (mePtr->hideMargin) {
*widthPtr = 0;
} else {
- *widthPtr = indicatorDimensions[1] - menuPtr->borderWidth;
+ int borderWidth;
+
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->borderWidthPtr, &borderWidth);
+ *widthPtr = indicatorDimensions[1] - borderWidth;
}
}
@@ -1289,10 +1326,11 @@ GetMenuAccelGeometry (
*heightPtr = fmPtr->linespace;
if (mePtr->type == CASCADE_ENTRY) {
*widthPtr = 0;
- } else if (mePtr->accel == NULL) {
+ } else if (mePtr->accelPtr == NULL) {
*widthPtr = 0;
} else {
- *widthPtr = Tk_TextWidth(tkfont, mePtr->accel, mePtr->accelLength);
+ char *accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
+ *widthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength);
}
}
@@ -1355,7 +1393,7 @@ GetMenuSeparatorGeometry (
int *heightPtr) /* The resulting height */
{
*widthPtr = 0;
- *heightPtr = fmPtr->linespace;
+ *heightPtr = fmPtr->linespace - (2 * fmPtr->descent);
}
/*
@@ -1382,7 +1420,7 @@ DrawWindowsSystemBitmap(display, drawable, gc, rectPtr, bitmapID, alignFlags)
Display *display; /* The display we are drawing into */
Drawable drawable; /* The drawable we are working with */
GC gc; /* The GC to draw with */
- CONST RECT *rectPtr; /* The rectangle to draw into */
+ CONST RECT *rectPtr; /* The rectangle to draw into */
int bitmapID; /* The windows id of the system
* bitmap to draw. */
int alignFlags; /* How to align the bitmap inside the
@@ -1468,47 +1506,44 @@ DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, x,
int width;
int height;
{
- if ((mePtr->type == CHECK_BUTTON_ENTRY ||
- mePtr->type == RADIO_BUTTON_ENTRY)
- && mePtr->indicatorOn
- && mePtr->entryFlags & ENTRY_SELECTED) {
- RECT rect;
- GC whichGC;
-
- if (mePtr->state != tkNormalUid) {
- whichGC = gc;
- } else {
- whichGC = indicatorGC;
- }
-
- rect.top = y;
- rect.bottom = y + mePtr->height;
- rect.left = menuPtr->borderWidth + menuPtr->activeBorderWidth + x;
- rect.right = mePtr->indicatorSpace + x;
-
- if ((mePtr->state == tkDisabledUid) && (menuPtr->disabledFg != NULL)
- && (versionInfo.dwMajorVersion >= 4)) {
- RECT hilightRect;
- COLORREF oldFgColor = whichGC->foreground;
-
- whichGC->foreground = GetSysColor(COLOR_3DHILIGHT);
- hilightRect.top = rect.top + 1;
- hilightRect.bottom = rect.bottom + 1;
- hilightRect.left = rect.left + 1;
- hilightRect.right = rect.right + 1;
- DrawWindowsSystemBitmap(menuPtr->display, d, whichGC,
- &hilightRect, OBM_CHECK, 0);
- whichGC->foreground = oldFgColor;
- }
+ if ((mePtr->type == CHECK_BUTTON_ENTRY)
+ || (mePtr->type == RADIO_BUTTON_ENTRY)) {
+ if (mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {
+ RECT rect;
+ GC whichGC;
+ int borderWidth, activeBorderWidth;
+ if (mePtr->state != ENTRY_NORMAL) {
+ whichGC = gc;
+ } else {
+ whichGC = indicatorGC;
+ }
- DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect,
- OBM_CHECK, 0);
+ rect.top = y;
+ rect.bottom = y + mePtr->height;
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->borderWidthPtr, &borderWidth);
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->activeBorderWidthPtr, &activeBorderWidth);
+ rect.left = borderWidth + activeBorderWidth + x;
+ rect.right = mePtr->indicatorSpace + x;
+
+ if ((mePtr->state == ENTRY_DISABLED)
+ && (menuPtr->disabledFgPtr != NULL)) {
+ RECT hilightRect;
+ COLORREF oldFgColor = whichGC->foreground;
+
+ whichGC->foreground = GetSysColor(COLOR_3DHILIGHT);
+ hilightRect.top = rect.top + 1;
+ hilightRect.bottom = rect.bottom + 1;
+ hilightRect.left = rect.left + 1;
+ hilightRect.right = rect.right + 1;
+ DrawWindowsSystemBitmap(menuPtr->display, d, whichGC,
+ &hilightRect, OBM_CHECK, 0);
+ whichGC->foreground = oldFgColor;
+ }
- if ((mePtr->state == tkDisabledUid)
- && (menuPtr->disabledImageGC != None)
- && (versionInfo.dwMajorVersion < 4)) {
- XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
- rect.left, rect.top, rect.right, rect.bottom);
+ DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect,
+ OBM_CHECK, 0);
}
}
}
@@ -1553,48 +1588,43 @@ DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
{
int baseline;
int leftEdge = x + mePtr->indicatorSpace + mePtr->labelWidth;
+ char *accel;
+
+ if (mePtr->accelPtr != NULL) {
+ accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
+ }
baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
- if ((mePtr->state == tkDisabledUid) && (menuPtr->disabledFg != NULL)
- && ((mePtr->accel != NULL)
- || ((mePtr->type == CASCADE_ENTRY) && drawArrow))) {
- if (versionInfo.dwMajorVersion >= 4) {
- COLORREF oldFgColor = gc->foreground;
-
- gc->foreground = GetSysColor(COLOR_3DHILIGHT);
- if (mePtr->accel != NULL) {
- Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel,
- mePtr->accelLength, leftEdge + 1, baseline + 1);
- }
+ if ((mePtr->state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL)
+ && ((mePtr->accelPtr != NULL)
+ || ((mePtr->type == CASCADE_ENTRY) && drawArrow))) {
+ COLORREF oldFgColor = gc->foreground;
- if (mePtr->type == CASCADE_ENTRY) {
- RECT rect;
+ gc->foreground = GetSysColor(COLOR_3DHILIGHT);
+ if (mePtr->accelPtr != NULL) {
+ Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
+ mePtr->accelLength, leftEdge + 1, baseline + 1);
+ }
- rect.top = y + GetSystemMetrics(SM_CYBORDER) + 1;
- rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER) + 1;
- rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth + 1;
- rect.right = x + width;
- DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect,
- OBM_MNARROW, ALIGN_BITMAP_RIGHT);
- }
- gc->foreground = oldFgColor;
+ if (mePtr->type == CASCADE_ENTRY) {
+ RECT rect;
+
+ rect.top = y + GetSystemMetrics(SM_CYBORDER) + 1;
+ rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER) + 1;
+ rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth + 1;
+ rect.right = x + width;
+ DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect,
+ OBM_MNARROW, ALIGN_BITMAP_RIGHT);
}
+ gc->foreground = oldFgColor;
}
- if (mePtr->accel != NULL) {
- Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel,
+ if (mePtr->accelPtr != NULL) {
+ Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
mePtr->accelLength, leftEdge, baseline);
}
- if ((mePtr->state == tkDisabledUid)
- && (menuPtr->disabledImageGC != None)
- && (versionInfo.dwMajorVersion < 4)) {
- XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
- leftEdge, y, width - mePtr->labelWidth
- - mePtr->indicatorSpace, height);
- }
-
if ((mePtr->type == CASCADE_ENTRY) && drawArrow) {
RECT rect;
@@ -1604,12 +1634,6 @@ DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
rect.right = x + width - 1;
DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, OBM_MNARROW,
ALIGN_BITMAP_RIGHT);
- if ((mePtr->state == tkDisabledUid)
- && (menuPtr->disabledImageGC != None)
- && (versionInfo.dwMajorVersion < 4)) {
- XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
- rect.left, rect.top, rect.right, rect.bottom);
- }
}
}
@@ -1643,13 +1667,15 @@ DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
int height; /* height of item */
{
XPoint points[2];
+ Tk_3DBorder border;
points[0].x = x;
points[0].y = y + height / 2;
points[1].x = x + width - 1;
points[1].y = points[0].y;
- Tk_Draw3DPolygon(menuPtr->tkwin, d,
- menuPtr->border, points, 2, 1, TK_RELIEF_RAISED);
+ border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
+ Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,
+ TK_RELIEF_RAISED);
}
/*
@@ -1683,10 +1709,14 @@ DrawMenuUnderline(
int height) /* Height of entry */
{
if (mePtr->underline >= 0) {
+ char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
+ char *start = Tcl_UtfAtIndex(label, mePtr->underline);
+ char *end = Tcl_UtfNext(start);
+
Tk_UnderlineChars(menuPtr->display, d,
- gc, tkfont, mePtr->label, x + mePtr->indicatorSpace,
+ gc, tkfont, label, x + mePtr->indicatorSpace,
y + (height + fmPtr->ascent - fmPtr->descent) / 2,
- mePtr->underline, mePtr->underline + 1);
+ start - label, end - label);
}
}
@@ -1748,8 +1778,8 @@ MenuKeyBindProc(clientData, interp, eventPtr, tkwin, keySym)
CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
WM_SYSKEYDOWN, virtualKey, ((scanCode << 16)
| (1 << 29)));
- if (eventPtr->xkey.nchars > 0) {
- for (i = 0; i < eventPtr->xkey.nchars; i++) {
+ if (eventPtr->xkey.nbytes > 0) {
+ for (i = 0; i < eventPtr->xkey.nbytes; i++) {
CallWindowProc(DefWindowProc,
Tk_GetHWND(Tk_WindowId(tkwin)),
WM_SYSCHAR,
@@ -1875,9 +1905,14 @@ DrawMenuEntryLabel(
{
int baseline;
int indicatorSpace = mePtr->indicatorSpace;
- int leftEdge = x + indicatorSpace + menuPtr->activeBorderWidth;
+ int activeBorderWidth;
+ int leftEdge;
int imageHeight, imageWidth;
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->activeBorderWidthPtr, &activeBorderWidth);
+ leftEdge = x + indicatorSpace + activeBorderWidth;
+
/*
* Draw label or bitmap or image for entry.
*/
@@ -1895,27 +1930,25 @@ DrawMenuEntryLabel(
imageHeight, d, leftEdge,
(int) (y + (mePtr->height - imageHeight)/2));
}
- } else if (mePtr->bitmap != None) {
+ } else if (mePtr->bitmapPtr != NULL) {
int width, height;
-
- Tk_SizeOfBitmap(menuPtr->display,
- mePtr->bitmap, &width, &height);
- XCopyPlane(menuPtr->display,
- mePtr->bitmap, d,
- gc, 0, 0, (unsigned) width, (unsigned) height, leftEdge,
- (int) (y + (mePtr->height - height)/2), 1);
+ Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
+ Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);
+ XCopyPlane(menuPtr->display, bitmap, d, gc, 0, 0, (unsigned) width,
+ (unsigned) height, leftEdge,
+ (int) (y + (mePtr->height - height)/2), 1);
} else {
if (mePtr->labelLength > 0) {
- Tk_DrawChars(menuPtr->display, d, gc,
- tkfont, mePtr->label, mePtr->labelLength,
- leftEdge, baseline);
+ char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
+ Tk_DrawChars(menuPtr->display, d, gc, tkfont, label,
+ mePtr->labelLength, leftEdge, baseline);
DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y,
width, height);
}
}
- if (mePtr->state == tkDisabledUid) {
- if (menuPtr->disabledFg == NULL) {
+ if (mePtr->state == ENTRY_DISABLED) {
+ if (menuPtr->disabledFgPtr == NULL) {
XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
(unsigned) width, (unsigned) height);
} else if ((mePtr->image != NULL)
@@ -1986,6 +2019,7 @@ DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
{
XPoint points[2];
int segmentWidth, maxX;
+ Tk_3DBorder border;
if (menuPtr->menuType != MASTER_MENU) {
return;
@@ -1996,13 +2030,14 @@ DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
points[1].y = points[0].y;
segmentWidth = 6;
maxX = width - 1;
+ border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
while (points[0].x < maxX) {
points[1].x = points[0].x + segmentWidth;
if (points[1].x > maxX) {
points[1].x = maxX;
}
- Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1,
+ Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,
TK_RELIEF_RAISED);
points[0].x += 2*segmentWidth;
}
@@ -2017,7 +2052,7 @@ DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
*
* Results:
* Returns standard TCL result. If TCL_ERROR is returned, then
- * interp->result contains an error message.
+ * the interp's result contains an error message.
*
* Side effects:
* Configuration information get set for mePtr; old resources
@@ -2088,8 +2123,7 @@ TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height,
* Choose the gc for drawing the foreground part of the entry.
*/
- if ((mePtr->state == tkActiveUid)
- && !strictMotif) {
+ if ((mePtr->state == ENTRY_ACTIVE) && !strictMotif) {
gc = mePtr->activeGC;
if (gc == NULL) {
gc = menuPtr->activeGC;
@@ -2097,21 +2131,22 @@ TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height,
} else {
TkMenuEntry *cascadeEntryPtr;
int parentDisabled = 0;
+ char *name;
for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
cascadeEntryPtr != NULL;
cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
- if (strcmp(cascadeEntryPtr->name,
- Tk_PathName(menuPtr->tkwin)) == 0) {
- if (cascadeEntryPtr->state == tkDisabledUid) {
+ name = Tcl_GetStringFromObj(cascadeEntryPtr->namePtr, NULL);
+ if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) {
+ if (mePtr->state == ENTRY_DISABLED) {
parentDisabled = 1;
}
break;
}
}
- if (((parentDisabled || (mePtr->state == tkDisabledUid)))
- && (menuPtr->disabledFg != NULL)) {
+ if (((parentDisabled || (mePtr->state == ENTRY_DISABLED)))
+ && (menuPtr->disabledFgPtr != NULL)) {
gc = mePtr->disabledGC;
if (gc == NULL) {
gc = menuPtr->disabledGC;
@@ -2127,24 +2162,22 @@ TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height,
if (indicatorGC == NULL) {
indicatorGC = menuPtr->indicatorGC;
}
-
- bgBorder = mePtr->border;
- if (bgBorder == NULL) {
- bgBorder = menuPtr->border;
- }
+
+ bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
+ (mePtr->borderPtr == NULL) ? menuPtr->borderPtr
+ : mePtr->borderPtr);
if (strictMotif) {
activeBorder = bgBorder;
} else {
- activeBorder = mePtr->activeBorder;
- if (activeBorder == NULL) {
- activeBorder = menuPtr->activeBorder;
- }
+ activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
+ (mePtr->activeBorderPtr == NULL) ? menuPtr->activeBorderPtr
+ : mePtr->activeBorderPtr);
}
- if (mePtr->tkfont == NULL) {
+ if (mePtr->fontPtr == NULL) {
fmPtr = menuMetricsPtr;
} else {
- tkfont = mePtr->tkfont;
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
Tk_GetFontMetrics(tkfont, &entryMetrics);
fmPtr = &entryMetrics;
}
@@ -2207,13 +2240,16 @@ GetMenuLabelGeometry(mePtr, tkfont, fmPtr, widthPtr, heightPtr)
if (mePtr->image != NULL) {
Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr);
- } else if (mePtr->bitmap != (Pixmap) NULL) {
- Tk_SizeOfBitmap(menuPtr->display, mePtr->bitmap, widthPtr, heightPtr);
+ } else if (mePtr->bitmapPtr != NULL) {
+ Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
+ Tk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr);
} else {
*heightPtr = fmPtr->linespace;
- if (mePtr->label != NULL) {
- *widthPtr = Tk_TextWidth(tkfont, mePtr->label, mePtr->labelLength);
+ if (mePtr->labelPtr != NULL) {
+ char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
+
+ *widthPtr = Tk_TextWidth(tkfont, label, mePtr->labelLength);
} else {
*widthPtr = 0;
}
@@ -2250,7 +2286,7 @@ DrawMenuEntryBackground(
int width, /* width of rectangle to draw */
int height) /* height of rectangle to draw */
{
- if (mePtr->state == tkActiveUid) {
+ if (mePtr->state == ENTRY_ACTIVE) {
bgBorder = activeBorder;
}
Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder,
@@ -2280,17 +2316,20 @@ void
TkpComputeStandardMenuGeometry(
TkMenu *menuPtr) /* Structure describing menu. */
{
- Tk_Font tkfont;
+ Tk_Font menuFont, tkfont;
Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
int x, y, height, width, indicatorSpace, labelWidth, accelWidth;
int windowWidth, windowHeight, accelSpace;
int i, j, lastColumnBreak = 0;
+ int activeBorderWidth, borderWidth;
if (menuPtr->tkwin == NULL) {
return;
}
- x = y = menuPtr->borderWidth;
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->borderWidthPtr, &borderWidth);
+ x = y = borderWidth;
indicatorSpace = labelWidth = accelWidth = 0;
windowHeight = 0;
@@ -2305,19 +2344,22 @@ TkpComputeStandardMenuGeometry(
* give all of the geometry/drawing the entry's font and metrics.
*/
- Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics);
- accelSpace = Tk_TextWidth(menuPtr->tkfont, "M", 1);
+ menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
+ Tk_GetFontMetrics(menuFont, &menuMetrics);
+ accelSpace = Tk_TextWidth(menuFont, "M", 1);
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->activeBorderWidthPtr, &activeBorderWidth);
for (i = 0; i < menuPtr->numEntries; i++) {
- tkfont = menuPtr->entries[i]->tkfont;
- if (tkfont == NULL) {
- tkfont = menuPtr->tkfont;
- fmPtr = &menuMetrics;
- } else {
+ if (menuPtr->entries[i]->fontPtr == NULL) {
+ tkfont = menuFont;
+ fmPtr = &menuMetrics;
+ } else {
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
+ menuPtr->entries[i]->fontPtr);
Tk_GetFontMetrics(tkfont, &entryMetrics);
fmPtr = &entryMetrics;
}
-
if ((i > 0) && menuPtr->entries[i]->columnBreak) {
if (accelWidth != 0) {
labelWidth += accelSpace;
@@ -2326,15 +2368,15 @@ TkpComputeStandardMenuGeometry(
menuPtr->entries[j]->indicatorSpace = indicatorSpace;
menuPtr->entries[j]->labelWidth = labelWidth;
menuPtr->entries[j]->width = indicatorSpace + labelWidth
- + accelWidth + 2 * menuPtr->activeBorderWidth;
+ + accelWidth + 2 * activeBorderWidth;
menuPtr->entries[j]->x = x;
menuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN;
}
x += indicatorSpace + labelWidth + accelWidth
- + 2 * menuPtr->borderWidth;
+ + 2 * borderWidth;
indicatorSpace = labelWidth = accelWidth = 0;
lastColumnBreak = i;
- y = menuPtr->borderWidth;
+ y = borderWidth;
}
if (menuPtr->entries[i]->type == SEPARATOR_ENTRY) {
@@ -2382,7 +2424,7 @@ TkpComputeStandardMenuGeometry(
indicatorSpace = width;
}
- menuPtr->entries[i]->height += 2 * menuPtr->activeBorderWidth + 1;
+ menuPtr->entries[i]->height += 2 * activeBorderWidth + 1;
}
menuPtr->entries[i]->y = y;
y += menuPtr->entries[i]->height;
@@ -2398,16 +2440,15 @@ TkpComputeStandardMenuGeometry(
menuPtr->entries[j]->indicatorSpace = indicatorSpace;
menuPtr->entries[j]->labelWidth = labelWidth;
menuPtr->entries[j]->width = indicatorSpace + labelWidth
- + accelWidth + 2 * menuPtr->activeBorderWidth;
+ + accelWidth + 2 * activeBorderWidth;
menuPtr->entries[j]->x = x;
menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
}
windowWidth = x + indicatorSpace + labelWidth + accelWidth + accelSpace
- + 2 * menuPtr->activeBorderWidth
- + 2 * menuPtr->borderWidth;
+ + 2 * activeBorderWidth + 2 * borderWidth;
- windowHeight += menuPtr->borderWidth;
+ windowHeight += borderWidth;
/*
* The X server doesn't like zero dimensions, so round up to at least
@@ -2533,14 +2574,55 @@ static void
MenuExitHandler(
ClientData clientData) /* Not used */
{
- DestroyWindow(menuHWND);
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ DestroyWindow(tsdPtr->menuHWND);
UnregisterClass(MENU_CLASS_NAME, Tk_GetHINSTANCE());
}
/*
*----------------------------------------------------------------------
*
- * TkpMenuInit --
+ * TkWinGetMenuSystemDefault --
+ *
+ * Gets the Windows specific default value for a given X resource
+ * database name.
+ *
+ * Results:
+ * Returns a Tcl_Obj * with the default value. If there is no
+ * Windows-specific default for this attribute, returns NULL.
+ * This object has a ref count of 0.
+ *
+ * Side effects:
+ * Storage is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TkWinGetMenuSystemDefault(
+ Tk_Window tkwin, /* A window to use. */
+ char *dbName, /* The option database name. */
+ char *className) /* The name of the option class. */
+{
+ Tcl_Obj *valuePtr = NULL;
+
+ if ((strcmp(dbName, "activeBorderWidth") == 0) ||
+ (strcmp(dbName, "borderWidth") == 0)) {
+ valuePtr = Tcl_NewIntObj(defaultBorderWidth);
+ } else if (strcmp(dbName, "font") == 0) {
+ valuePtr = Tcl_NewStringObj(Tcl_DStringValue(&menuFontDString),
+ -1);
+ }
+
+ return valuePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWinMenuSetDefaults --
*
* Sets up the hash tables and the variables used by the menu package.
*
@@ -2555,123 +2637,72 @@ MenuExitHandler(
*/
void
-TkpMenuInit()
+SetDefaults(
+ int firstTime) /* Is this the first time this
+ * has been called? */
{
- WNDCLASS wndClass;
- char sizeString[4];
+ char sizeString[TCL_INTEGER_SPACE];
char faceName[LF_FACESIZE];
HDC scratchDC;
Tcl_DString boldItalicDString;
int bold = 0;
int italic = 0;
- int i;
TEXTMETRIC tm;
-
- Tcl_InitHashTable(&winMenuTable, TCL_ONE_WORD_KEYS);
- Tcl_InitHashTable(&commandTable, TCL_ONE_WORD_KEYS);
-
- wndClass.style = CS_OWNDC;
- wndClass.lpfnWndProc = TkWinMenuProc;
- wndClass.cbClsExtra = 0;
- wndClass.cbWndExtra = 0;
- wndClass.hInstance = Tk_GetHINSTANCE();
- wndClass.hIcon = NULL;
- wndClass.hCursor = NULL;
- wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wndClass.lpszMenuName = NULL;
- wndClass.lpszClassName = MENU_CLASS_NAME;
- RegisterClass(&wndClass);
-
- menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP,
- 0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);
-
- Tcl_CreateExitHandler(MenuExitHandler, (ClientData) NULL);
-
- versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
-
- /*
- * If GetVersionEx fails, it means that the version info record
- * is too big for what is compiled. Should never happen, but if
- * it does, we are later than Windows 95 or NT 4.0.
- */
-
- if (!GetVersionEx(&versionInfo)) {
- versionInfo.dwMajorVersion = 4;
- }
+ int pointSize;
+ HFONT menuFont;
+ NONCLIENTMETRICS ncMetrics;
/*
* Set all of the default options. The loop will terminate when we run
* out of options via a break statement.
*/
- for (i = 0; ; i++) {
- if (tkMenuConfigSpecs[i].type == TK_CONFIG_END) {
- break;
- }
-
- if ((strcmp(tkMenuConfigSpecs[i].dbName,
- "activeBorderWidth") == 0) ||
- (strcmp(tkMenuConfigSpecs[i].dbName, "borderWidth") == 0)) {
- int borderWidth;
-
- borderWidth = GetSystemMetrics(SM_CXBORDER);
- if (GetSystemMetrics(SM_CYBORDER) > borderWidth) {
- borderWidth = GetSystemMetrics(SM_CYBORDER);
- }
- sprintf(borderString, "%d", borderWidth);
- tkMenuConfigSpecs[i].defValue = borderString;
- } else if ((strcmp(tkMenuConfigSpecs[i].dbName, "font") == 0)) {
- int pointSize;
- HFONT menuFont;
-
- scratchDC = CreateDC("DISPLAY", NULL, NULL, NULL);
- Tcl_DStringInit(&menuFontDString);
-
- if (versionInfo.dwMajorVersion >= 4) {
- NONCLIENTMETRICS ncMetrics;
-
- ncMetrics.cbSize = sizeof(ncMetrics);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics),
- &ncMetrics, 0);
- menuFont = CreateFontIndirect(&ncMetrics.lfMenuFont);
- } else {
- menuFont = GetStockObject(SYSTEM_FONT);
- }
- SelectObject(scratchDC, menuFont);
- GetTextMetrics(scratchDC, &tm);
- GetTextFace(scratchDC, sizeof(menuFontDString), faceName);
- pointSize = MulDiv(tm.tmHeight - tm.tmInternalLeading,
- 72, GetDeviceCaps(scratchDC, LOGPIXELSY));
- if (tm.tmWeight >= 700) {
- bold = 1;
- }
- if (tm.tmItalic) {
- italic = 1;
- }
+ defaultBorderWidth = GetSystemMetrics(SM_CXBORDER);
+ if (GetSystemMetrics(SM_CYBORDER) > defaultBorderWidth) {
+ defaultBorderWidth = GetSystemMetrics(SM_CYBORDER);
+ }
- SelectObject(scratchDC, GetStockObject(SYSTEM_FONT));
- DeleteDC(scratchDC);
+ scratchDC = CreateDC("DISPLAY", NULL, NULL, NULL);
+ if (!firstTime) {
+ Tcl_DStringFree(&menuFontDString);
+ }
+ Tcl_DStringInit(&menuFontDString);
+
+ ncMetrics.cbSize = sizeof(ncMetrics);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics),
+ &ncMetrics, 0);
+ menuFont = CreateFontIndirect(&ncMetrics.lfMenuFont);
+ SelectObject(scratchDC, menuFont);
+ GetTextMetrics(scratchDC, &tm);
+ GetTextFace(scratchDC, LF_FACESIZE, faceName);
+ pointSize = MulDiv(tm.tmHeight - tm.tmInternalLeading,
+ 72, GetDeviceCaps(scratchDC, LOGPIXELSY));
+ if (tm.tmWeight >= 700) {
+ bold = 1;
+ }
+ if (tm.tmItalic) {
+ italic = 1;
+ }
- DeleteObject(menuFont);
-
- Tcl_DStringAppendElement(&menuFontDString, faceName);
- sprintf(sizeString, "%d", pointSize);
- Tcl_DStringAppendElement(&menuFontDString, sizeString);
-
- if (bold == 1 || italic == 1) {
- Tcl_DStringInit(&boldItalicDString);
- if (bold == 1) {
- Tcl_DStringAppendElement(&boldItalicDString, "bold");
- }
- if (italic == 1) {
- Tcl_DStringAppendElement(&boldItalicDString, "italic");
- }
- Tcl_DStringAppendElement(&menuFontDString,
- Tcl_DStringValue(&boldItalicDString));
- }
+ SelectObject(scratchDC, GetStockObject(SYSTEM_FONT));
+ DeleteDC(scratchDC);
- tkMenuConfigSpecs[i].defValue = Tcl_DStringValue(&menuFontDString);
+ DeleteObject(menuFont);
+
+ Tcl_DStringAppendElement(&menuFontDString, faceName);
+ sprintf(sizeString, "%d", pointSize);
+ Tcl_DStringAppendElement(&menuFontDString, sizeString);
+
+ if (bold == 1 || italic == 1) {
+ Tcl_DStringInit(&boldItalicDString);
+ if (bold == 1) {
+ Tcl_DStringAppendElement(&boldItalicDString, "bold");
+ }
+ if (italic == 1) {
+ Tcl_DStringAppendElement(&boldItalicDString, "italic");
}
+ Tcl_DStringAppendElement(&menuFontDString,
+ Tcl_DStringValue(&boldItalicDString));
}
/*
@@ -2684,7 +2715,7 @@ TkpMenuInit()
* documented.
*/
- if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
+ if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_WINDOWS) {
indicatorDimensions[0] = GetSystemMetrics(SM_CYMENUCHECK);
indicatorDimensions[1] = ((GetSystemMetrics(SM_CXFIXEDFRAME) +
GetSystemMetrics(SM_CXBORDER)
@@ -2695,5 +2726,72 @@ TkpMenuInit()
indicatorDimensions[0] = HIWORD(dimensions);
indicatorDimensions[1] = LOWORD(dimensions);
}
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMenuInit --
+ *
+ * Sets up the process-wide variables used by the menu package.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * lastMenuID gets initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpMenuInit()
+{
+ WNDCLASS wndClass;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ wndClass.style = CS_OWNDC;
+ wndClass.lpfnWndProc = TkWinMenuProc;
+ wndClass.cbClsExtra = 0;
+ wndClass.cbWndExtra = 0;
+ wndClass.hInstance = Tk_GetHINSTANCE();
+ wndClass.hIcon = NULL;
+ wndClass.hCursor = NULL;
+ wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ wndClass.lpszMenuName = NULL;
+ wndClass.lpszClassName = MENU_CLASS_NAME;
+ RegisterClass(&wndClass);
+
+ tsdPtr->menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP,
+ 0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);
+
+ Tcl_CreateExitHandler(MenuExitHandler, (ClientData) NULL);
+ SetDefaults(1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMenuThreadInit --
+ *
+ * Sets up the thread-local hash tables used by the menu module.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Hash tables winMenuTable and commandTable are initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpMenuThreadInit()
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_InitHashTable(&tsdPtr->winMenuTable, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&tsdPtr->commandTable, TCL_ONE_WORD_KEYS);
}
diff --git a/tk/win/tkWinPixmap.c b/tk/win/tkWinPixmap.c
index 7dae990623a..62b90180aee 100644
--- a/tk/win/tkWinPixmap.c
+++ b/tk/win/tkWinPixmap.c
@@ -138,7 +138,7 @@ TkSetPixmapColormap(pixmap, colormap)
*
* Retrieve the geometry of the given drawable. Note that
* this is a degenerate implementation that only returns the
- * size of a pixmap.
+ * size of a pixmap or window.
*
* Results:
* Returns 0.
@@ -163,22 +163,37 @@ XGetGeometry(display, d, root_return, x_return, y_return, width_return,
unsigned int* depth_return;
{
TkWinDrawable *twdPtr = (TkWinDrawable *)d;
- HDC dc;
- BITMAPINFO info;
- if ((twdPtr->type != TWD_BITMAP) || (twdPtr->bitmap.handle == NULL)) {
- panic("XGetGeometry: invalid pixmap");
- }
- dc = GetDC(NULL);
- info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- info.bmiHeader.biBitCount = 0;
- if (!GetDIBits(dc, twdPtr->bitmap.handle, 0, 0, NULL, &info,
- DIB_RGB_COLORS)) {
- panic("XGetGeometry: unable to get bitmap size");
- }
- ReleaseDC(NULL, dc);
+ if (twdPtr->type == TWD_BITMAP) {
+ HDC dc;
+ BITMAPINFO info;
+
+ if (twdPtr->bitmap.handle == NULL) {
+ panic("XGetGeometry: invalid pixmap");
+ }
+ dc = GetDC(NULL);
+ info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ info.bmiHeader.biBitCount = 0;
+ if (!GetDIBits(dc, twdPtr->bitmap.handle, 0, 0, NULL, &info,
+ DIB_RGB_COLORS)) {
+ panic("XGetGeometry: unable to get bitmap size");
+ }
+ ReleaseDC(NULL, dc);
+
+ *width_return = info.bmiHeader.biWidth;
+ *height_return = info.bmiHeader.biHeight;
+ } else if (twdPtr->type == TWD_WINDOW) {
+ RECT rect;
- *width_return = info.bmiHeader.biWidth;
- *height_return = info.bmiHeader.biHeight;
+ if (twdPtr->window.handle == NULL) {
+ panic("XGetGeometry: invalid window");
+ }
+ GetClientRect(twdPtr->window.handle, &rect);
+ *width_return = rect.right - rect.left;
+ *height_return = rect.bottom - rect.top;
+ } else {
+ panic("XGetGeometry: invalid window");
+ }
return 1;
}
+
diff --git a/tk/win/tkWinPointer.c b/tk/win/tkWinPointer.c
index dd747abfc60..3ed9aa97f42 100644
--- a/tk/win/tkWinPointer.c
+++ b/tk/win/tkWinPointer.c
@@ -4,6 +4,7 @@
* Windows specific mouse tracking code.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -62,7 +63,7 @@ TkWinGetModifierState()
state |= ControlMask;
}
if (GetKeyState(VK_MENU) & 0x8000) {
- state |= Mod2Mask;
+ state |= ALT_MASK;
}
if (GetKeyState(VK_CAPITAL) & 0x0001) {
state |= LockMask;
@@ -237,8 +238,22 @@ MouseTimerProc(clientData)
GetCursorPos(&pos);
Tk_PointerEvent(NULL, pos.x, pos.y);
}
-
-/* CYGNUS LOCAL: Cancel any current mouse timer. */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWinCancelMouseTimer --
+ *
+ * If the mouse timer is set, cancel it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May cancel the mouse timer.
+ *
+ *----------------------------------------------------------------------
+ */
void
TkWinCancelMouseTimer()
@@ -316,6 +331,42 @@ XQueryPointer(display, w, root_return, child_return, root_x_return,
*mask_return = TkWinGetModifierState();
return True;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XWarpPointer --
+ *
+ * Move pointer to new location. This is not a complete
+ * implementation of this function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Mouse pointer changes position on screen.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XWarpPointer(display, src_w, dest_w, src_x, src_y, src_width,
+ src_height, dest_x, dest_y)
+ Display* display;
+ Window src_w;
+ Window dest_w;
+ int src_x;
+ int src_y;
+ unsigned int src_width;
+ unsigned int src_height;
+ int dest_x;
+ int dest_y;
+{
+ RECT r;
+
+ GetWindowRect(Tk_GetHWND(dest_w), &r);
+ SetCursorPos(r.left+dest_x, r.top+dest_y);
+}
/*
*----------------------------------------------------------------------
@@ -427,7 +478,7 @@ TkpChangeFocus(winPtr, force)
*/
if (force) {
- SetForegroundWindow(Tk_GetHWND(winPtr->window));
+ TkWinSetForegroundWindow(winPtr);
}
XSetInputFocus(dispPtr->display, winPtr->window, RevertToParent,
CurrentTime);
diff --git a/tk/win/tkWinPort.h b/tk/win/tkWinPort.h
index 532c9d1200b..c04862bf3b3 100644
--- a/tk/win/tkWinPort.h
+++ b/tk/win/tkWinPort.h
@@ -6,7 +6,6 @@
* file that contains #ifdefs to handle different flavors of OS.
*
* Copyright (c) 1995-1996 Sun Microsystems, Inc.
- * Copyright (c) 1998 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -32,19 +31,29 @@
#include <limits.h>
#include <fcntl.h>
#include <io.h>
+
+/*
+ * Need to block out this include for building extensions with MetroWerks
+ * compiler for Win32.
+ */
+
+#ifndef __MWERKS__
#include <sys/stat.h>
+#endif
+
#include <time.h>
#ifdef _MSC_VER
+#include <tchar.h>
+#endif
+
+#ifdef _MSC_VER
# define hypot _hypot
#endif /* _MSC_VER */
-#ifdef __CYGWIN32__
-#define strnicmp strncasecmp
-#define stricmp strcasecmp
-#else
-#define strncasecmp strnicmp
-#define strcasecmp stricmp
+#ifndef __GNUC__
+# define strncasecmp strnicmp
+# define strcasecmp stricmp
#endif
#define NBBY 8
@@ -123,13 +132,11 @@ struct timezone {
int tz_dsttime;
};
+#endif
-struct timeval;
-
-extern int gettimeofday(struct timeval *, struct timezone *);
-
-#endif /* ! __MINGW32__ */
-
-EXTERN void panic _ANSI_ARGS_(TCL_VARARGS(char *,format));
+#ifndef _TCLINT
+#include <tclInt.h>
+#endif
#endif /* _WINPORT */
+
diff --git a/tk/win/tkWinRegion.c b/tk/win/tkWinRegion.c
index 1866971864b..3f4024da24e 100644
--- a/tk/win/tkWinRegion.c
+++ b/tk/win/tkWinRegion.c
@@ -177,3 +177,4 @@ TkRectInRegion(r, x, y, width, height)
rect.right = x+width;
return RectInRegion((HRGN)r, &rect) ? RectanglePart : RectangleOut;
}
+
diff --git a/tk/win/tkWinScrlbr.c b/tk/win/tkWinScrlbr.c
index 12f4ea212eb..fa622ca365d 100644
--- a/tk/win/tkWinScrlbr.c
+++ b/tk/win/tkWinScrlbr.c
@@ -57,12 +57,14 @@ static int initialized = 0;
static int hArrowWidth, hThumb; /* Horizontal control metrics. */
static int vArrowWidth, vArrowHeight, vThumb; /* Vertical control metrics. */
+TCL_DECLARE_MUTEX(winScrlbrMutex)
+
/*
* This variable holds the default width for a scrollbar in string
* form for use in a Tk_ConfigSpec.
*/
-static char defWidth[8];
+static char defWidth[TCL_INTEGER_SPACE];
/*
* Declarations for functions defined in this file.
@@ -116,8 +118,10 @@ TkpCreateScrollbar(tkwin)
TkWindow *winPtr = (TkWindow *)tkwin;
if (!initialized) {
+ Tcl_MutexLock(&winScrlbrMutex);
UpdateScrollbarMetrics();
initialized = 1;
+ Tcl_MutexUnlock(&winScrlbrMutex);
}
scrollPtr = (WinScrollbar *) ckalloc(sizeof(WinScrollbar));
@@ -173,11 +177,7 @@ UpdateScrollbar(scrollPtr)
scrollInfo.nMin = 0;
scrollInfo.nMax = MAX_SCROLL;
thumbSize = (scrollPtr->info.lastFraction - scrollPtr->info.firstFraction);
- if (tkpIsWin32s) {
- scrollInfo.nPage = 0;
- } else {
- scrollInfo.nPage = ((UINT) (thumbSize * (double) MAX_SCROLL)) + 1;
- }
+ scrollInfo.nPage = ((UINT) (thumbSize * (double) MAX_SCROLL)) + 1;
if (thumbSize < 1.0) {
scrollInfo.nPos = (int)
((scrollPtr->info.firstFraction / (1.0-thumbSize))
@@ -668,16 +668,18 @@ ModalLoopProc(tkwin, eventPtr)
WinScrollbar *scrollPtr = (WinScrollbar *) winPtr->instanceData;
int oldMode;
- Tcl_Preserve((ClientData)scrollPtr);
- scrollPtr->winFlags |= IN_MODAL_LOOP;
- oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
- TkWinResendEvent(scrollPtr->oldProc, scrollPtr->hwnd, eventPtr);
- (void) Tcl_SetServiceMode(oldMode);
- scrollPtr->winFlags &= ~IN_MODAL_LOOP;
- if (scrollPtr->hwnd && scrollPtr->winFlags & ALREADY_DEAD) {
- DestroyWindow(scrollPtr->hwnd);
+ if (scrollPtr->hwnd) {
+ Tcl_Preserve((ClientData)scrollPtr);
+ scrollPtr->winFlags |= IN_MODAL_LOOP;
+ oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
+ TkWinResendEvent(scrollPtr->oldProc, scrollPtr->hwnd, eventPtr);
+ (void) Tcl_SetServiceMode(oldMode);
+ scrollPtr->winFlags &= ~IN_MODAL_LOOP;
+ if (scrollPtr->hwnd && scrollPtr->winFlags & ALREADY_DEAD) {
+ DestroyWindow(scrollPtr->hwnd);
+ }
+ Tcl_Release((ClientData)scrollPtr);
}
- Tcl_Release((ClientData)scrollPtr);
}
/*
@@ -743,3 +745,5 @@ TkpScrollbarPosition(scrollPtr, x, y)
}
return BOTTOM_GAP;
}
+
+
diff --git a/tk/win/tkWinTest.c b/tk/win/tkWinTest.c
new file mode 100644
index 00000000000..dd66ce05f46
--- /dev/null
+++ b/tk/win/tkWinTest.c
@@ -0,0 +1,250 @@
+/*
+ * tkWinTest.c --
+ *
+ * Contains commands for platform specific tests for
+ * the Windows platform.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ * Copyright (c) 2000 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#include "tkWinInt.h"
+
+HWND tkWinCurrentDialog;
+
+/*
+ * Forward declarations of procedures defined later in this file:
+ */
+
+int TkplatformtestInit(Tcl_Interp *interp);
+static int TestclipboardObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]);
+static int TestwineventCmd(ClientData clientData,
+ Tcl_Interp *interp, int argc, char **argv);
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkplatformtestInit --
+ *
+ * Defines commands that test platform specific functionality for
+ * Unix platforms.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Defines new commands.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkplatformtestInit(
+ Tcl_Interp *interp) /* Interpreter to add commands to. */
+{
+ /*
+ * Add commands for platform specific tests on MacOS here.
+ */
+
+ Tcl_CreateObjCommand(interp, "testclipboard", TestclipboardObjCmd,
+ (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateCommand(interp, "testwinevent", TestwineventCmd,
+ (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestclipboardObjCmd --
+ *
+ * This procedure implements the testclipboard command. It provides
+ * a way to determine the actual contents of the Windows clipboard.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestclipboardObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Main window for application. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument values. */
+{
+ TkWindow *winPtr = (TkWindow *) clientData;
+ HGLOBAL handle;
+ char *data;
+
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (OpenClipboard(NULL)) {
+ /*
+ * We could consider using CF_UNICODETEXT on NT, but then we
+ * would have to convert it from External. Instead we'll just
+ * take this and do "bytestring" at the Tcl level for Unicode
+ * inclusive text
+ */
+ handle = GetClipboardData(CF_TEXT);
+ if (handle != NULL) {
+ data = GlobalLock(handle);
+ Tcl_AppendResult(interp, data, (char *) NULL);
+ GlobalUnlock(handle);
+ } else {
+ Tcl_AppendResult(interp, "null clipboard handle", (char *) NULL);
+ return TCL_ERROR;
+ }
+ CloseClipboard();
+ } else {
+ Tcl_AppendResult(interp, "couldn't open clipboard", (char *) NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestwineventCmd --
+ *
+ * This procedure implements the testwinevent command. It provides
+ * a way to send messages to windows dialogs.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestwineventCmd(clientData, interp, argc, argv)
+ ClientData clientData; /* Main window for application. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int argc; /* Number of arguments. */
+ char **argv; /* Argument strings. */
+{
+ HWND hwnd;
+ int id;
+ char *rest;
+ UINT message;
+ WPARAM wParam;
+ LPARAM lParam;
+ static TkStateMap messageMap[] = {
+ {WM_LBUTTONDOWN, "WM_LBUTTONDOWN"},
+ {WM_LBUTTONUP, "WM_LBUTTONUP"},
+ {WM_CHAR, "WM_CHAR"},
+ {WM_GETTEXT, "WM_GETTEXT"},
+ {WM_SETTEXT, "WM_SETTEXT"},
+ {-1, NULL}
+ };
+
+ if ((argc == 3) && (strcmp(argv[1], "debug") == 0)) {
+ int i;
+
+ if (Tcl_GetBoolean(interp, argv[2], &i) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ TkWinDialogDebug(i);
+ return TCL_OK;
+ }
+
+ if (argc < 4) {
+ return TCL_ERROR;
+ }
+
+ hwnd = (HWND) strtol(argv[1], &rest, 0);
+ if (rest == argv[2]) {
+ hwnd = FindWindow(NULL, argv[1]);
+ if (hwnd == NULL) {
+ Tcl_SetResult(interp, "no such window", TCL_STATIC);
+ return TCL_ERROR;
+ }
+ }
+ UpdateWindow(hwnd);
+
+ id = strtol(argv[2], &rest, 0);
+ if (rest == argv[2]) {
+ HWND child;
+ char buf[256];
+
+ child = GetWindow(hwnd, GW_CHILD);
+ while (child != NULL) {
+ SendMessage(child, WM_GETTEXT, (WPARAM) sizeof(buf), (LPARAM) buf);
+ if (strcasecmp(buf, argv[2]) == 0) {
+ id = GetDlgCtrlID(child);
+ break;
+ }
+ child = GetWindow(child, GW_HWNDNEXT);
+ }
+ if (child == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ message = TkFindStateNum(NULL, NULL, messageMap, argv[3]);
+ if (message < 0) {
+ message = strtol(argv[3], NULL, 0);
+ }
+ wParam = 0;
+ lParam = 0;
+
+ if (argc > 4) {
+ wParam = strtol(argv[4], NULL, 0);
+ }
+ if (argc > 5) {
+ lParam = strtol(argv[5], NULL, 0);
+ }
+
+ switch (message) {
+ case WM_GETTEXT: {
+ Tcl_DString ds;
+ char buf[256];
+
+ GetDlgItemText(hwnd, id, buf, 256);
+ Tcl_ExternalToUtfDString(NULL, buf, -1, &ds);
+ Tcl_AppendResult(interp, Tcl_DStringValue(&ds), NULL);
+ Tcl_DStringFree(&ds);
+ break;
+ }
+ case WM_SETTEXT: {
+ Tcl_DString ds;
+
+ Tcl_UtfToExternalDString(NULL, argv[4], -1, &ds);
+ SetDlgItemText(hwnd, id, Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+ break;
+ }
+ default: {
+ char buf[TCL_INTEGER_SPACE];
+
+ sprintf(buf, "%d",
+ SendDlgItemMessage(hwnd, id, message, wParam, lParam));
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ break;
+ }
+ }
+ return TCL_OK;
+}
+
+
+
+
+
diff --git a/tk/win/tkWinWindow.c b/tk/win/tkWinWindow.c
index f78dd0b9c74..6980f39bca1 100644
--- a/tk/win/tkWinWindow.c
+++ b/tk/win/tkWinWindow.c
@@ -4,7 +4,7 @@
* Xlib emulation routines for Windows related to creating,
* displaying and destroying windows.
*
- * Copyright (c) 1995 Sun Microsystems, Inc.
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -14,17 +14,12 @@
#include "tkWinInt.h"
-/*
- * The windowTable maps from HWND to Tk_Window handles.
- */
-
-static Tcl_HashTable windowTable;
-
-/*
- * Have statics in this module been initialized?
- */
-
-static int initialized = 0;
+typedef struct ThreadSpecificData {
+ int initialized; /* 0 means table below needs initializing. */
+ Tcl_HashTable windowTable; /* The windowTable maps from HWND to
+ * Tk_Window handles. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* Forward declarations for procedures defined in this file:
@@ -61,10 +56,12 @@ Tk_AttachHWND(tkwin, hwnd)
int new;
Tcl_HashEntry *entryPtr;
TkWinDrawable *twdPtr = (TkWinDrawable *) Tk_WindowId(tkwin);
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- if (!initialized) {
- Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS);
- initialized = 1;
+ if (!tsdPtr->initialized) {
+ Tcl_InitHashTable(&tsdPtr->windowTable, TCL_ONE_WORD_KEYS);
+ tsdPtr->initialized = 1;
}
/*
@@ -77,7 +74,7 @@ Tk_AttachHWND(tkwin, hwnd)
twdPtr->type = TWD_WINDOW;
twdPtr->window.winPtr = (TkWindow *) tkwin;
} else if (twdPtr->window.handle != NULL) {
- entryPtr = Tcl_FindHashEntry(&windowTable,
+ entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable,
(char *)twdPtr->window.handle);
Tcl_DeleteHashEntry(entryPtr);
}
@@ -87,7 +84,7 @@ Tk_AttachHWND(tkwin, hwnd)
*/
twdPtr->window.handle = hwnd;
- entryPtr = Tcl_CreateHashEntry(&windowTable, (char *)hwnd, &new);
+ entryPtr = Tcl_CreateHashEntry(&tsdPtr->windowTable, (char *)hwnd, &new);
Tcl_SetHashValue(entryPtr, (ClientData)tkwin);
return (Window)twdPtr;
@@ -115,11 +112,14 @@ Tk_HWNDToWindow(hwnd)
HWND hwnd;
{
Tcl_HashEntry *entryPtr;
- if (!initialized) {
- Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS);
- initialized = 1;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (!tsdPtr->initialized) {
+ Tcl_InitHashTable(&tsdPtr->windowTable, TCL_ONE_WORD_KEYS);
+ tsdPtr->initialized = 1;
}
- entryPtr = Tcl_FindHashEntry(&windowTable, (char*)hwnd);
+ entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, (char*)hwnd);
if (entryPtr != NULL) {
return (Tk_Window) Tcl_GetHashValue(entryPtr);
}
@@ -190,7 +190,7 @@ TkpPrintWindowId(buf, window)
* The return value is normally TCL_OK; in this case *idPtr
* will be set to the X Window id equivalent to string. If
* string is improperly formed then TCL_ERROR is returned and
- * an error message will be left in interp->result. If the
+ * an error message will be left in the interp's result. If the
* number does not correspond to a Tk Window, then *idPtr will
* be set to None.
*
@@ -295,6 +295,8 @@ XDestroyWindow(display, w)
TkWinDrawable *twdPtr = (TkWinDrawable *)w;
TkWindow *winPtr = TkWinGetWinPtr(w);
HWND hwnd = Tk_GetHWND(w);
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
display->request++;
@@ -305,7 +307,7 @@ XDestroyWindow(display, w)
TkPointerDeadWindow(winPtr);
- entryPtr = Tcl_FindHashEntry(&windowTable, (char*)hwnd);
+ entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, (char*)hwnd);
if (entryPtr != NULL) {
Tcl_DeleteHashEntry(entryPtr);
}
@@ -799,3 +801,4 @@ TkpWindowWasRecentlyDeleted(win, dispPtr)
{
return 0;
}
+
diff --git a/tk/win/tkWinWm.c b/tk/win/tkWinWm.c
index c8b17d8dcd0..8f7ba87d999 100644
--- a/tk/win/tkWinWm.c
+++ b/tk/win/tkWinWm.c
@@ -7,7 +7,7 @@
* to the window manager.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
- * Copyright (c) 1998 by Scriptics Corporation.
+ * Copyright (c) 1998-2000 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -164,6 +164,7 @@ typedef struct TkWmInfo {
char *clientMachine; /* String to store in WM_CLIENT_MACHINE
* property, or NULL. */
int flags; /* Miscellaneous flags, defined below. */
+ int numTransients; /* number of transients on this window */
struct TkWmInfo *nextPtr; /* Next in list of all top-level windows. */
} WmInfo;
@@ -183,7 +184,7 @@ typedef struct TkWmInfo {
* pixels up from bottom of screen, rather than
* down from top.
* WM_UPDATE_SIZE_HINTS - non-zero means that new size hints need to be
- * propagated to window manager.
+ * propagated to window manager. Not used on Win.
* WM_SYNC_PENDING - set to non-zero while waiting for the window
* manager to respond to some state change.
* WM_MOVE_PENDING - non-zero means the application has requested
@@ -223,33 +224,8 @@ typedef struct TkWmInfo {
#define WM_TRANSIENT_STYLE \
(WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS|CS_DBLCLKS)
-/* CYGNUS LOCAL: We don't want WS_EX_TOOLWINDOW for most of our
- transient windows. If necessary, we can add some option to set
- this.
- #define EX_TRANSIENT_STYLE (WS_EX_TOOLWINDOW | WS_EX_DLGMODALFRAME)
- We also don't use WS_EX_DLGMODALFRAME. Using this doesn't give any
- obvious benefit. However, it does have a drawback: if the window
- is marked as not resizable, then use of WS_EX_DLGMODALFRAME will
- cause the resize items on the window's system menu to remain
- active. No, I don't understand.
- */
-#define EX_TRANSIENT_STYLE (0)
-
-/*
- * This module keeps a list of all top-level windows.
- */
-
-static WmInfo *firstWmPtr = NULL; /* Points to first top-level window. */
-static WmInfo *foregroundWmPtr = NULL; /* Points to the foreground window. */
-
-/*
- * The variable below is used to enable or disable tracing in this
- * module. If tracing is enabled, then information is printed on
- * standard output about interesting interactions with the window
- * manager.
- */
-
-static int wmTracing = 0;
+#define EX_TRANSIENT_STYLE \
+ (WS_EX_TOOLWINDOW|WS_EX_DLGMODALFRAME)
/*
* The following structure is the official type record for geometry
@@ -264,41 +240,36 @@ static Tk_GeomMgr wmMgrType = {
(Tk_GeomLostSlaveProc *) NULL, /* lostSlaveProc */
};
-/*
- * Global system palette. This value always refers to the currently
- * installed foreground logical palette.
- */
-
-static HPALETTE systemPalette = NULL;
+typedef struct ThreadSpecificData {
+ HPALETTE systemPalette; /* System palette; refers to the
+ * currently installed foreground logical
+ * palette. */
+ TkWindow *createWindow; /* Window that is being constructed. This
+ * value is set immediately before a
+ * call to CreateWindowEx, and is used
+ * by SetLimits. This is a gross hack
+ * needed to work around Windows brain
+ * damage where it sends the
+ * WM_GETMINMAXINFO message before the
+ * WM_CREATE window. */
+ int initialized; /* Flag indicating whether thread-
+ * specific elements of module have
+ * been initialized. */
+ int firstWindow; /* Flag, cleared when the first window
+ * is mapped in a non-iconic state. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
- * Window that is being constructed. This value is set immediately
- * before a call to CreateWindowEx, and is used by SetLimits.
- * This is a gross hack needed to work around Windows brain damage
- * where it sends the WM_GETMINMAXINFO message before the WM_CREATE
- * window.
+ * The following variables cannot be placed in thread local storage
+ * because they must be shared across threads.
*/
-static TkWindow *createWindow = NULL;
+static WNDCLASS toplevelClass; /* Class for toplevel windows. */
+static int initialized; /* Flag indicating whether module has
+ * been initialized. */
+TCL_DECLARE_MUTEX(winWmMutex)
-/*
- * Flag indicating whether this module has been initialized yet.
- */
-
-static int initialized = 0;
-
-/*
- * Class for toplevel windows.
- */
-
-static WNDCLASS toplevelClass;
-
-/*
- * This flag is cleared when the first window is mapped in a non-iconic
- * state.
- */
-
-static int firstWindow = 1;
/*
* Forward declarations for procedures defined in this file:
@@ -323,7 +294,8 @@ static void InvalidateSubTree _ANSI_ARGS_((TkWindow *winPtr,
Colormap colormap));
static int ParseGeometry _ANSI_ARGS_((Tcl_Interp *interp,
char *string, TkWindow *winPtr));
-static void RefreshColormap _ANSI_ARGS_((Colormap colormap));
+static void RefreshColormap _ANSI_ARGS_((Colormap colormap,
+ TkDisplay *dispPtr));
static void SetLimits _ANSI_ARGS_((HWND hwnd, MINMAXINFO *info));
static LRESULT CALLBACK TopLevelProc _ANSI_ARGS_((HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam));
@@ -336,6 +308,8 @@ static void UpdateGeometryInfo _ANSI_ARGS_((
static void UpdateWrapper _ANSI_ARGS_((TkWindow *winPtr));
static LRESULT CALLBACK WmProc _ANSI_ARGS_((HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam));
+static void WmWaitVisibilityProc _ANSI_ARGS_((
+ ClientData clientData, XEvent *eventPtr));
/*
*----------------------------------------------------------------------
@@ -356,28 +330,49 @@ static LRESULT CALLBACK WmProc _ANSI_ARGS_((HWND hwnd, UINT message,
static void
InitWm(void)
{
- if (initialized) {
- return;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ WNDCLASS * classPtr;
+
+ if (! tsdPtr->initialized) {
+ tsdPtr->initialized = 1;
+ tsdPtr->firstWindow = 1;
}
- initialized = 1;
-
- toplevelClass.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC;
- toplevelClass.cbClsExtra = 0;
- toplevelClass.cbWndExtra = 0;
- toplevelClass.hInstance = Tk_GetHINSTANCE();
- toplevelClass.hbrBackground = NULL;
- toplevelClass.lpszMenuName = NULL;
- toplevelClass.lpszClassName = TK_WIN_TOPLEVEL_CLASS_NAME;
- toplevelClass.lpfnWndProc = WmProc;
- /* CYGNUS LOCAL: First try the application's resource file. If
- that fails, then try the Tk DLL. */
- toplevelClass.hIcon = LoadIcon (GetModuleHandle (NULL), "tk");
- if (toplevelClass.hIcon == NULL)
- toplevelClass.hIcon = LoadIcon(Tk_GetHINSTANCE(), "tk");
- toplevelClass.hCursor = LoadCursor(NULL, IDC_ARROW);
-
- if (!RegisterClass(&toplevelClass)) {
- panic("Unable to register TkTopLevel class");
+ if (! initialized) {
+ Tcl_MutexLock(&winWmMutex);
+ if (! initialized) {
+ initialized = 1;
+ classPtr = &toplevelClass;
+
+ /*
+ * When threads are enabled, we cannot use CLASSDC because
+ * threads will then write into the same device context.
+ *
+ * This is a hack; we should add a subsystem that manages
+ * device context on a per-thread basis. See also tkWinX.c,
+ * which also initializes a WNDCLASS structure.
+ */
+
+#ifdef TCL_THREADS
+ classPtr->style = CS_HREDRAW | CS_VREDRAW;
+#else
+ classPtr->style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC;
+#endif
+ classPtr->cbClsExtra = 0;
+ classPtr->cbWndExtra = 0;
+ classPtr->hInstance = Tk_GetHINSTANCE();
+ classPtr->hbrBackground = NULL;
+ classPtr->lpszMenuName = NULL;
+ classPtr->lpszClassName = TK_WIN_TOPLEVEL_CLASS_NAME;
+ classPtr->lpfnWndProc = WmProc;
+ classPtr->hIcon = LoadIcon(Tk_GetHINSTANCE(), "tk");
+ classPtr->hCursor = LoadCursor(NULL, IDC_ARROW);
+
+ if (!RegisterClass(classPtr)) {
+ panic("Unable to register TkTopLevel class");
+ }
+ }
+ Tcl_MutexUnlock(&winWmMutex);
}
}
@@ -402,14 +397,17 @@ static TkWindow *
GetTopLevel(hwnd)
HWND hwnd;
{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
/*
* If this function is called before the CreateWindowEx call
* has completed, then the user data slot will not have been
* set yet, so we use the global createWindow variable.
*/
- if (createWindow) {
- return createWindow;
+ if (tsdPtr->createWindow) {
+ return tsdPtr->createWindow;
}
return (TkWindow *) GetWindowLong(hwnd, GWL_USERDATA);
}
@@ -523,10 +521,26 @@ void
TkWinWmCleanup(hInstance)
HINSTANCE hInstance;
{
- if (!initialized) {
+ ThreadSpecificData *tsdPtr;
+
+ /*
+ * If we're using stubs to access the Tcl library, and they
+ * haven't been initialized, we can't call Tcl_GetThreadData.
+ */
+
+#ifdef USE_TCL_STUBS
+ if (tclStubsPtr == NULL) {
return;
}
- initialized = 0;
+#endif
+
+ tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (!tsdPtr->initialized) {
+ return;
+ }
+ tsdPtr->initialized = 0;
UnregisterClass(TK_WIN_TOPLEVEL_CLASS_NAME, hInstance);
}
@@ -602,6 +616,7 @@ TkWmNewWindow(winPtr)
wmPtr->cmapList = NULL;
wmPtr->cmapCount = 0;
+ wmPtr->numTransients = 0;
wmPtr->configWidth = -1;
wmPtr->configHeight = -1;
@@ -609,8 +624,8 @@ TkWmNewWindow(winPtr)
wmPtr->cmdArgv = NULL;
wmPtr->clientMachine = NULL;
wmPtr->flags = WM_NEVER_MAPPED;
- wmPtr->nextPtr = firstWmPtr;
- firstWmPtr = wmPtr;
+ wmPtr->nextPtr = winPtr->dispPtr->firstWmPtr;
+ winPtr->dispPtr->firstWmPtr = wmPtr;
/*
* Tk must monitor structure events for top-level windows, in order
@@ -657,9 +672,13 @@ UpdateWrapper(winPtr)
HWND child = TkWinGetHWND(winPtr->window);
int x, y, width, height, state;
WINDOWPLACEMENT place;
+ Tcl_DString titleString;
+ int *childStateInfo = NULL;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
parentHWND = NULL;
- child = TkWinGetHWND(winPtr->window);
+ child = TkWinGetHWND(winPtr->window);
if (winPtr->flags & TK_EMBEDDED) {
wmPtr->wrapper = (HWND) winPtr->privatePtr;
@@ -675,11 +694,11 @@ UpdateWrapper(winPtr)
* Pick the decorative frame style. Override redirect windows get
* created as undecorated popups. Transient windows get a modal
* dialog frame. Neither override, nor transient windows appear in
- * the Win95 taskbar. Note that a transient window does not resize
+ * the Windows taskbar. Note that a transient window does not resize
* by default, so we need to explicitly add the WS_THICKFRAME style
* if we want it to be resizeable.
*/
-
+
if (winPtr->atts.override_redirect) {
wmPtr->style = WM_OVERRIDE_STYLE;
wmPtr->exStyle = EX_OVERRIDE_STYLE;
@@ -696,10 +715,8 @@ UpdateWrapper(winPtr)
wmPtr->exStyle = EX_TOPLEVEL_STYLE;
}
- /* CYGNUS LOCAL: nonresizable windows have no maximize box,
- and no "sizebox". */
if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE)
- && (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) {
+ && (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) {
wmPtr->style &= ~ (WS_MAXIMIZEBOX | WS_SIZEBOX);
}
@@ -720,7 +737,6 @@ UpdateWrapper(winPtr)
* pick a location.
*/
-
if (!(wmPtr->sizeHintsFlags & (USPosition | PPosition))
&& (wmPtr->flags & WM_NEVER_MAPPED)) {
x = CW_USEDEFAULT;
@@ -735,13 +751,15 @@ UpdateWrapper(winPtr)
* to the TkWindow.
*/
- createWindow = winPtr;
+ tsdPtr->createWindow = winPtr;
+ Tcl_UtfToExternalDString(NULL, wmPtr->titleUid, -1, &titleString);
wmPtr->wrapper = CreateWindowEx(wmPtr->exStyle,
TK_WIN_TOPLEVEL_CLASS_NAME,
- wmPtr->titleUid, wmPtr->style, x, y, width, height,
- parentHWND, NULL, Tk_GetHINSTANCE(), NULL);
+ Tcl_DStringValue(&titleString), wmPtr->style, x, y, width,
+ height, parentHWND, NULL, Tk_GetHINSTANCE(), NULL);
+ Tcl_DStringFree(&titleString);
SetWindowLong(wmPtr->wrapper, GWL_USERDATA, (LONG) winPtr);
- createWindow = NULL;
+ tsdPtr->createWindow = NULL;
place.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(wmPtr->wrapper, &place);
@@ -767,6 +785,26 @@ UpdateWrapper(winPtr)
&& (oldWrapper != GetDesktopWindow())) {
SetWindowLong(oldWrapper, GWL_USERDATA, (LONG) NULL);
+ if (wmPtr->numTransients > 0) {
+ /*
+ * Unset the current wrapper as the parent for all transient
+ * children for whom this is the master
+ */
+ WmInfo *wmPtr2;
+
+ childStateInfo = (int *)ckalloc((unsigned) wmPtr->numTransients
+ * sizeof(int));
+ state = 0;
+ for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
+ wmPtr2 = wmPtr2->nextPtr) {
+ if (wmPtr2->masterPtr == winPtr) {
+ if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
+ childStateInfo[state++] = wmPtr2->hints.initial_state;
+ SetParent(TkWinGetHWND(wmPtr2->winPtr->window), NULL);
+ }
+ }
+ }
+ }
/*
* Remove the menubar before destroying the window so the menubar
* isn't destroyed.
@@ -775,6 +813,7 @@ UpdateWrapper(winPtr)
SetMenu(oldWrapper, NULL);
DestroyWindow(oldWrapper);
}
+
wmPtr->flags &= ~WM_NEVER_MAPPED;
SendMessage(wmPtr->wrapper, TK_ATTACHWINDOW, (WPARAM) child, 0);
@@ -810,13 +849,35 @@ UpdateWrapper(winPtr)
wmPtr->flags &= ~WM_SYNC_PENDING;
}
+ if (childStateInfo) {
+ if (wmPtr->numTransients > 0) {
+ /*
+ * Reset all transient children for whom this is the master
+ */
+ WmInfo *wmPtr2;
+
+ state = 0;
+ for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
+ wmPtr2 = wmPtr2->nextPtr) {
+ if (wmPtr2->masterPtr == winPtr) {
+ if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
+ UpdateWrapper(wmPtr2->winPtr);
+ TkpWmSetState(wmPtr2->winPtr, childStateInfo[state++]);
+ }
+ }
+ }
+ }
+
+ ckfree((char *) childStateInfo);
+ }
+
/*
* If this is the first window created by the application, then
* we should activate the initial window.
*/
- if (firstWindow) {
- firstWindow = 0;
+ if (tsdPtr->firstWindow) {
+ tsdPtr->firstWindow = 0;
SetActiveWindow(wmPtr->wrapper);
}
}
@@ -850,8 +911,10 @@ TkWmMapWindow(winPtr)
* be mapped. */
{
register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- if (!initialized) {
+ if (!tsdPtr->initialized) {
InitWm();
}
@@ -931,8 +994,9 @@ TkpWmSetState(winPtr, state)
{
WmInfo *wmPtr = winPtr->wmInfoPtr;
int cmd;
-
- if (wmPtr->flags & WM_NEVER_MAPPED) {
+
+ if ((wmPtr->flags & WM_NEVER_MAPPED) ||
+ (wmPtr->masterPtr && !Tk_IsMapped(wmPtr->masterPtr))) {
wmPtr->hints.initial_state = state;
return;
}
@@ -947,6 +1011,7 @@ TkpWmSetState(winPtr, state)
} else if (state == ZoomState) {
cmd = SW_SHOWMAXIMIZED;
}
+
ShowWindow(wmPtr->wrapper, cmd);
wmPtr->flags &= ~WM_SYNC_PENDING;
}
@@ -984,11 +1049,12 @@ TkWmDeadWindow(winPtr)
* Clean up event related window info.
*/
- if (firstWmPtr == wmPtr) {
- firstWmPtr = wmPtr->nextPtr;
+ if (winPtr->dispPtr->firstWmPtr == wmPtr) {
+ winPtr->dispPtr->firstWmPtr = wmPtr->nextPtr;
} else {
register WmInfo *prevPtr;
- for (prevPtr = firstWmPtr; ; prevPtr = prevPtr->nextPtr) {
+ for (prevPtr = winPtr->dispPtr->firstWmPtr; ;
+ prevPtr = prevPtr->nextPtr) {
if (prevPtr == NULL) {
panic("couldn't unlink window in TkWmDeadWindow");
}
@@ -1003,7 +1069,8 @@ TkWmDeadWindow(winPtr)
* Reset all transient windows whose master is the dead window.
*/
- for (wmPtr2 = firstWmPtr; wmPtr2 != NULL; wmPtr2 = wmPtr2->nextPtr) {
+ for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
+ wmPtr2 = wmPtr2->nextPtr) {
if (wmPtr2->masterPtr == winPtr) {
wmPtr2->masterPtr = NULL;
if ((wmPtr2->wrapper != None)
@@ -1047,6 +1114,20 @@ TkWmDeadWindow(winPtr)
if (wmPtr->flags & WM_UPDATE_PENDING) {
Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
}
+ if (wmPtr->masterPtr != NULL) {
+ wmPtr2 = wmPtr->masterPtr->wmInfoPtr;
+ /*
+ * If we had a master, tell them that we aren't tied
+ * to them anymore
+ */
+ if (wmPtr2 != NULL) {
+ wmPtr2->numTransients--;
+ }
+ Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr,
+ VisibilityChangeMask,
+ WmWaitVisibilityProc, (ClientData) winPtr);
+ wmPtr->masterPtr = NULL;
+ }
/*
* Destroy the decorative frame window.
@@ -1117,10 +1198,11 @@ Tk_WmCmd(clientData, interp, argc, argv)
char **argv; /* Argument strings. */
{
Tk_Window tkwin = (Tk_Window) clientData;
- TkWindow *winPtr;
+ TkWindow *winPtr = NULL;
register WmInfo *wmPtr;
int c;
size_t length;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
if (argc < 2) {
wrongNumArgs:
@@ -1138,10 +1220,11 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 2) {
- interp->result = (wmTracing) ? "on" : "off";
+ Tcl_SetResult(interp, ((dispPtr->wmTracing) ? "on" : "off"),
+ TCL_STATIC);
return TCL_OK;
}
- return Tcl_GetBoolean(interp, argv[2], &wmTracing);
+ return Tcl_GetBoolean(interp, argv[2], &dispPtr->wmTracing);
}
if (argc < 3) {
@@ -1168,9 +1251,12 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->sizeHintsFlags & PAspect) {
- sprintf(interp->result, "%d %d %d %d", wmPtr->minAspect.x,
+ char buf[TCL_INTEGER_SPACE * 4];
+
+ sprintf(buf, "%d %d %d %d", wmPtr->minAspect.x,
wmPtr->minAspect.y, wmPtr->maxAspect.x,
wmPtr->maxAspect.y);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
return TCL_OK;
}
@@ -1185,7 +1271,8 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) ||
(denom2 <= 0)) {
- interp->result = "aspect number can't be <= 0";
+ Tcl_SetResult(interp, "aspect number can't be <= 0",
+ TCL_STATIC);
return TCL_ERROR;
}
wmPtr->minAspect.x = numer1;
@@ -1205,7 +1292,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->clientMachine != NULL) {
- interp->result = wmPtr->clientMachine;
+ Tcl_SetResult(interp, wmPtr->clientMachine, TCL_STATIC);
}
return TCL_OK;
}
@@ -1301,7 +1388,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
* Now we need to force the updated colormaps to be installed.
*/
- if (wmPtr == foregroundWmPtr) {
+ if (wmPtr == winPtr->dispPtr->foregroundWmPtr) {
InstallColormaps(wmPtr->wrapper, WM_QUERYNEWPALETTE, 1);
} else {
InstallColormaps(wmPtr->wrapper, WM_PALETTECHANGED, 0);
@@ -1320,8 +1407,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->cmdArgv != NULL) {
- interp->result = Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv);
- interp->freeProc = TCL_DYNAMIC;
+ Tcl_SetResult(interp,
+ Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv),
+ TCL_DYNAMIC);
}
return TCL_OK;
}
@@ -1363,7 +1451,34 @@ Tk_WmCmd(clientData, interp, argc, argv)
": it is an embedded window", (char *) NULL);
return TCL_ERROR;
}
- TkpWmSetState(winPtr, NormalState);
+ /*
+ * If WM_UPDATE_PENDING is true, a pending UpdateGeometryInfo may
+ * need to be called first to update a withdrew toplevel's geometry
+ * before it is deiconified by TkpWmSetState.
+ * Don't bother if we've never been mapped.
+ */
+ if (wmPtr->flags & WM_UPDATE_PENDING) {
+ Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
+ UpdateGeometryInfo((ClientData) winPtr);
+ }
+
+ /*
+ * If we were in the ZoomState (maximized), 'wm deiconify'
+ * should not cause the window to shrink
+ */
+ if (wmPtr->hints.initial_state == ZoomState) {
+ TkpWmSetState(winPtr, ZoomState);
+ } else {
+ TkpWmSetState(winPtr, NormalState);
+ }
+
+ /*
+ * Follow Windows-like style here, raising the window to the top.
+ */
+ TkWmRestackToplevel(winPtr, Above, NULL);
+ if (!(Tk_Attributes((Tk_Window) winPtr)->override_redirect)) {
+ TkSetFocusWin(winPtr, 1);
+ }
} else if ((c == 'f') && (strncmp(argv[1], "focusmodel", length) == 0)
&& (length >= 2)) {
if ((argc != 3) && (argc != 4)) {
@@ -1373,7 +1488,8 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
- interp->result = wmPtr->hints.input ? "passive" : "active";
+ Tcl_SetResult(interp, (wmPtr->hints.input ? "passive" : "active"),
+ TCL_STATIC);
return TCL_OK;
}
c = argv[3][0];
@@ -1390,6 +1506,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
} else if ((c == 'f') && (strncmp(argv[1], "frame", length) == 0)
&& (length >= 2)) {
HWND hwnd;
+ char buf[TCL_INTEGER_SPACE];
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # arguments: must be \"",
@@ -1403,7 +1520,8 @@ Tk_WmCmd(clientData, interp, argc, argv)
if (hwnd == NULL) {
hwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) winPtr));
}
- sprintf(interp->result, "0x%x", (unsigned int) hwnd);
+ sprintf(buf, "0x%x", (unsigned int) hwnd);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'g') && (strncmp(argv[1], "geometry", length) == 0)
&& (length >= 2)) {
char xSign, ySign;
@@ -1416,6 +1534,8 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
+ char buf[16 + TCL_INTEGER_SPACE * 4];
+
xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';
ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';
if (wmPtr->gridWin != NULL) {
@@ -1427,8 +1547,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
width = winPtr->changes.width;
height = winPtr->changes.height;
}
- sprintf(interp->result, "%dx%d%c%d%c%d", width, height,
- xSign, wmPtr->x, ySign, wmPtr->y);
+ sprintf(buf, "%dx%d%c%d%c%d", width, height, xSign, wmPtr->x,
+ ySign, wmPtr->y);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_OK;
}
if (*argv[3] == '\0') {
@@ -1449,9 +1570,12 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->sizeHintsFlags & PBaseSize) {
- sprintf(interp->result, "%d %d %d %d", wmPtr->reqGridWidth,
+ char buf[TCL_INTEGER_SPACE * 4];
+
+ sprintf(buf, "%d %d %d %d", wmPtr->reqGridWidth,
wmPtr->reqGridHeight, wmPtr->widthInc,
wmPtr->heightInc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
return TCL_OK;
}
@@ -1478,19 +1602,19 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (reqWidth < 0) {
- interp->result = "baseWidth can't be < 0";
+ Tcl_SetResult(interp, "baseWidth can't be < 0", TCL_STATIC);
return TCL_ERROR;
}
if (reqHeight < 0) {
- interp->result = "baseHeight can't be < 0";
+ Tcl_SetResult(interp, "baseHeight can't be < 0", TCL_STATIC);
return TCL_ERROR;
}
if (widthInc < 0) {
- interp->result = "widthInc can't be < 0";
+ Tcl_SetResult(interp, "widthInc can't be < 0", TCL_STATIC);
return TCL_ERROR;
}
if (heightInc < 0) {
- interp->result = "heightInc can't be < 0";
+ Tcl_SetResult(interp, "heightInc can't be < 0", TCL_STATIC);
return TCL_ERROR;
}
Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
@@ -1509,7 +1633,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->hints.flags & WindowGroupHint) {
- interp->result = wmPtr->leaderName;
+ Tcl_SetResult(interp, wmPtr->leaderName, TCL_STATIC);
}
return TCL_OK;
}
@@ -1542,8 +1666,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->hints.flags & IconPixmapHint) {
- interp->result = Tk_NameOfBitmap(winPtr->display,
- wmPtr->hints.icon_pixmap);
+ Tcl_SetResult(interp,
+ Tk_NameOfBitmap(winPtr->display,
+ wmPtr->hints.icon_pixmap), TCL_STATIC);
}
return TCL_OK;
}
@@ -1601,8 +1726,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->hints.flags & IconMaskHint) {
- interp->result = Tk_NameOfBitmap(winPtr->display,
- wmPtr->hints.icon_mask);
+ Tcl_SetResult(interp,
+ Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask),
+ TCL_STATIC);
}
return TCL_OK;
}
@@ -1627,7 +1753,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
- interp->result = (wmPtr->iconName != NULL) ? wmPtr->iconName : "";
+ Tcl_SetResult(interp,
+ ((wmPtr->iconName != NULL) ? wmPtr->iconName : ""),
+ TCL_STATIC);
return TCL_OK;
} else {
wmPtr->iconName = Tk_GetUid(argv[3]);
@@ -1647,8 +1775,11 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->hints.flags & IconPositionHint) {
- sprintf(interp->result, "%d %d", wmPtr->hints.icon_x,
+ char buf[TCL_INTEGER_SPACE * 2];
+
+ sprintf(buf, "%d %d", wmPtr->hints.icon_x,
wmPtr->hints.icon_y);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
return TCL_OK;
}
@@ -1677,7 +1808,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->icon != NULL) {
- interp->result = Tk_PathName(wmPtr->icon);
+ Tcl_SetResult(interp, Tk_PathName(wmPtr->icon), TCL_STATIC);
}
return TCL_OK;
}
@@ -1744,8 +1875,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
if (XWithdrawWindow(Tk_Display(tkwin2), Tk_WindowId(tkwin2),
Tk_ScreenNumber(tkwin2)) == 0) {
- interp->result =
- "couldn't send withdraw message to window manager";
+ Tcl_SetResult(interp,
+ "couldn't send withdraw message to window manager",
+ TCL_STATIC);
return TCL_ERROR;
}
}
@@ -1760,8 +1892,11 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
+ char buf[TCL_INTEGER_SPACE * 2];
+
GetMaxSize(wmPtr, &width, &height);
- sprintf(interp->result, "%d %d", width, height);
+ sprintf(buf, "%d %d", width, height);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_OK;
}
if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)
@@ -1781,8 +1916,11 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
+ char buf[TCL_INTEGER_SPACE * 2];
+
GetMinSize(wmPtr, &width, &height);
- sprintf(interp->result, "%d %d", width, height);
+ sprintf(buf, "%d %d", width, height);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_OK;
}
if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)
@@ -1794,7 +1932,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
goto updateGeom;
} else if ((c == 'o')
&& (strncmp(argv[1], "overrideredirect", length) == 0)) {
- int boolean;
+ int boolean, curValue;
XSetWindowAttributes atts;
if ((argc != 3) && (argc != 4)) {
@@ -1803,23 +1941,26 @@ Tk_WmCmd(clientData, interp, argc, argv)
(char *) NULL);
return TCL_ERROR;
}
+ curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
if (argc == 3) {
- if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
- interp->result = "1";
- } else {
- interp->result = "0";
- }
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), curValue);
return TCL_OK;
}
if (Tcl_GetBoolean(interp, argv[3], &boolean) != TCL_OK) {
return TCL_ERROR;
}
- atts.override_redirect = (boolean) ? True : False;
- Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,
- &atts);
- if (!(wmPtr->flags & (WM_NEVER_MAPPED)
- && !(winPtr->flags & TK_EMBEDDED))) {
- UpdateWrapper(winPtr);
+ if (curValue != boolean) {
+ /*
+ * Only do this if we are really changing value, because it
+ * causes some funky stuff to occur
+ */
+ atts.override_redirect = (boolean) ? True : False;
+ Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,
+ &atts);
+ if (!(wmPtr->flags & (WM_NEVER_MAPPED)
+ && !(winPtr->flags & TK_EMBEDDED))) {
+ UpdateWrapper(winPtr);
+ }
}
} else if ((c == 'p') && (strncmp(argv[1], "positionfrom", length) == 0)
&& (length >= 2)) {
@@ -1831,9 +1972,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->sizeHintsFlags & USPosition) {
- interp->result = "user";
+ Tcl_SetResult(interp, "user", TCL_STATIC);
} else if (wmPtr->sizeHintsFlags & PPosition) {
- interp->result = "program";
+ Tcl_SetResult(interp, "program", TCL_STATIC);
}
return TCL_OK;
}
@@ -1887,7 +2028,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
for (protPtr = wmPtr->protPtr; protPtr != NULL;
protPtr = protPtr->nextPtr) {
if (protPtr->protocol == protocol) {
- interp->result = protPtr->command;
+ Tcl_SetResult(interp, protPtr->command, TCL_STATIC);
return TCL_OK;
}
}
@@ -1931,9 +2072,12 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
- sprintf(interp->result, "%d %d",
+ char buf[TCL_INTEGER_SPACE * 2];
+
+ sprintf(buf, "%d %d",
(wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) ? 0 : 1,
(wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) ? 0 : 1);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_OK;
}
if ((Tcl_GetBoolean(interp, argv[3], &width) != TCL_OK)
@@ -1950,7 +2094,10 @@ Tk_WmCmd(clientData, interp, argc, argv)
} else {
wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;
}
- wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ if (!((wmPtr->flags & WM_NEVER_MAPPED)
+ && !(winPtr->flags & TK_EMBEDDED))) {
+ UpdateWrapper(winPtr);
+ }
goto updateGeom;
} else if ((c == 's') && (strncmp(argv[1], "sizefrom", length) == 0)
&& (length >= 2)) {
@@ -1962,9 +2109,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->sizeHintsFlags & USSize) {
- interp->result = "user";
+ Tcl_SetResult(interp, "user", TCL_STATIC);
} else if (wmPtr->sizeHintsFlags & PSize) {
- interp->result = "program";
+ Tcl_SetResult(interp, "program", TCL_STATIC);
}
return TCL_OK;
}
@@ -1989,27 +2136,80 @@ Tk_WmCmd(clientData, interp, argc, argv)
goto updateGeom;
} else if ((c == 's') && (strncmp(argv[1], "state", length) == 0)
&& (length >= 2)) {
- if (argc != 3) {
+ if ((argc < 3) || (argc > 4)) {
Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " state window\"", (char *) NULL);
+ argv[0], " state window ?state?\"", (char *) NULL);
return TCL_ERROR;
}
- if (wmPtr->iconFor != NULL) {
- interp->result = "icon";
+ if (argc == 4) {
+ if (wmPtr->iconFor != NULL) {
+ Tcl_AppendResult(interp, "can't change state of ", argv[2],
+ ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (winPtr->flags & TK_EMBEDDED) {
+ Tcl_AppendResult(interp, "can't change state of ",
+ winPtr->pathName, ": it is an embedded window",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ c = argv[3][0];
+ length = strlen(argv[3]);
+
+ if ((c == 'n') && (strncmp(argv[3], "normal", length) == 0)) {
+ TkpWmSetState(winPtr, NormalState);
+ /*
+ * This varies from 'wm deiconify' because it does not
+ * force the window to be raised and receive focus
+ */
+ } else if ((c == 'i')
+ && (strncmp(argv[3], "iconic", length) == 0)) {
+ if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
+ Tcl_AppendResult(interp, "can't iconify \"",
+ winPtr->pathName,
+ "\": override-redirect flag is set",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (wmPtr->masterPtr != NULL) {
+ Tcl_AppendResult(interp, "can't iconify \"",
+ winPtr->pathName,
+ "\": it is a transient", (char *) NULL);
+ return TCL_ERROR;
+ }
+ TkpWmSetState(winPtr, IconicState);
+ } else if ((c == 'w')
+ && (strncmp(argv[3], "withdrawn", length) == 0)) {
+ TkpWmSetState(winPtr, WithdrawnState);
+ } else if ((c == 'z')
+ && (strncmp(argv[3], "zoomed", length) == 0)) {
+ TkpWmSetState(winPtr, ZoomState);
+ } else {
+ Tcl_AppendResult(interp, "bad argument \"", argv[3],
+ "\": must be normal, iconic, withdrawn or zoomed",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
} else {
- switch (wmPtr->hints.initial_state) {
- case NormalState:
- interp->result = "normal";
- break;
- case IconicState:
- interp->result = "iconic";
- break;
- case WithdrawnState:
- interp->result = "withdrawn";
- break;
- case ZoomState:
- interp->result = "zoomed";
- break;
+ if (wmPtr->iconFor != NULL) {
+ Tcl_SetResult(interp, "icon", TCL_STATIC);
+ } else {
+ switch (wmPtr->hints.initial_state) {
+ case NormalState:
+ Tcl_SetResult(interp, "normal", TCL_STATIC);
+ break;
+ case IconicState:
+ Tcl_SetResult(interp, "iconic", TCL_STATIC);
+ break;
+ case WithdrawnState:
+ Tcl_SetResult(interp, "withdrawn", TCL_STATIC);
+ break;
+ case ZoomState:
+ Tcl_SetResult(interp, "zoomed", TCL_STATIC);
+ break;
+ }
}
}
} else if ((c == 't') && (strncmp(argv[1], "title", length) == 0)
@@ -2020,18 +2220,22 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
- interp->result = (wmPtr->titleUid != NULL) ? wmPtr->titleUid
- : winPtr->nameUid;
+ Tcl_SetResult(interp, ((wmPtr->titleUid != NULL) ?
+ wmPtr->titleUid : winPtr->nameUid), TCL_STATIC);
return TCL_OK;
} else {
wmPtr->titleUid = Tk_GetUid(argv[3]);
if (!(wmPtr->flags & WM_NEVER_MAPPED) && wmPtr->wrapper != NULL) {
- SetWindowText(wmPtr->wrapper, wmPtr->titleUid);
+ Tcl_DString titleString;
+ Tcl_UtfToExternalDString(NULL, wmPtr->titleUid, -1,
+ &titleString);
+ SetWindowText(wmPtr->wrapper, Tcl_DStringValue(&titleString));
+ Tcl_DStringFree(&titleString);
}
}
} else if ((c == 't') && (strncmp(argv[1], "transient", length) == 0)
&& (length >= 3)) {
- TkWindow *masterPtr;
+ TkWindow *masterPtr = wmPtr->masterPtr;
if ((argc != 3) && (argc != 4)) {
Tcl_AppendResult(interp, "wrong # arguments: must be \"",
@@ -2039,12 +2243,21 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
- if (wmPtr->masterPtr != NULL) {
- Tcl_SetResult(interp, Tk_PathName(wmPtr->masterPtr),
- TCL_STATIC);
+ if (masterPtr != NULL) {
+ Tcl_SetResult(interp, Tk_PathName(masterPtr), TCL_STATIC);
}
return TCL_OK;
}
+ if (masterPtr != NULL) {
+ /*
+ * If we had a master, tell them that we aren't tied
+ * to them anymore
+ */
+ masterPtr->wmInfoPtr->numTransients--;
+ Tk_DeleteEventHandler((Tk_Window) masterPtr,
+ VisibilityChangeMask,
+ WmWaitVisibilityProc, (ClientData) winPtr);
+ }
if (argv[3][0] == '\0') {
wmPtr->masterPtr = NULL;
} else {
@@ -2054,7 +2267,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (masterPtr == winPtr) {
wmPtr->masterPtr = NULL;
- } else {
+ } else if (masterPtr != wmPtr->masterPtr) {
Tk_MakeWindowExist((Tk_Window)masterPtr);
/*
@@ -2065,16 +2278,20 @@ Tk_WmCmd(clientData, interp, argc, argv)
masterPtr = masterPtr->parentPtr;
}
wmPtr->masterPtr = masterPtr;
+ masterPtr->wmInfoPtr->numTransients++;
/*
- * Ensure that the transient window is either mapped or
- * unmapped like its master.
+ * Bind a visibility event handler to the master window,
+ * to ensure that when it is mapped, the children will
+ * have their state set properly.
*/
- TkpWmSetState(winPtr, NormalState);
+ Tk_CreateEventHandler((Tk_Window) masterPtr,
+ VisibilityChangeMask,
+ WmWaitVisibilityProc, (ClientData) winPtr);
}
}
- if (!(wmPtr->flags & (WM_NEVER_MAPPED)
+ if (!((wmPtr->flags & WM_NEVER_MAPPED)
&& !(winPtr->flags & TK_EMBEDDED))) {
UpdateWrapper(winPtr);
}
@@ -2111,6 +2328,26 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
return TCL_OK;
}
+ /*ARGSUSED*/
+static void
+WmWaitVisibilityProc(clientData, eventPtr)
+ ClientData clientData; /* Pointer to window. */
+ XEvent *eventPtr; /* Information about event. */
+{
+ TkWindow *winPtr = (TkWindow *) clientData;
+ TkWindow *masterPtr = winPtr->wmInfoPtr->masterPtr;
+
+ if ((eventPtr->type == VisibilityNotify) && (masterPtr != NULL)) {
+ int state = masterPtr->wmInfoPtr->hints.initial_state;
+
+ if ((state == NormalState) || (state == ZoomState)) {
+ state = winPtr->wmInfoPtr->hints.initial_state;
+ if ((state == NormalState) || (state == ZoomState)) {
+ UpdateWrapper(winPtr);
+ }
+ }
+ }
+}
/*
*----------------------------------------------------------------------
@@ -2621,7 +2858,7 @@ UpdateGeometryInfo(clientData)
*
* Results:
* A standard Tcl return value, plus an error message in
- * interp->result if an error occurs.
+ * the interp's result if an error occurs.
*
* Side effects:
* The size and/or location of winPtr may change.
@@ -2968,14 +3205,19 @@ TkWmProtocolEventProc(winPtr, eventPtr)
for (protPtr = wmPtr->protPtr; protPtr != NULL;
protPtr = protPtr->nextPtr) {
if (protocol == protPtr->protocol) {
+ /*
+ * Cache atom name, as we might destroy the window as a
+ * result of the eval.
+ */
+ char *name = Tk_GetAtomName((Tk_Window) winPtr, protocol);
+
Tcl_Preserve((ClientData) protPtr);
interp = protPtr->interp;
Tcl_Preserve((ClientData) interp);
result = Tcl_GlobalEval(interp, protPtr->command);
if (result != TCL_OK) {
Tcl_AddErrorInfo(interp, "\n (command for \"");
- Tcl_AddErrorInfo(interp,
- Tk_GetAtomName((Tk_Window) winPtr, protocol));
+ Tcl_AddErrorInfo(interp, name);
Tcl_AddErrorInfo(interp, "\" window manager protocol)");
Tcl_BackgroundError(interp);
}
@@ -3038,7 +3280,6 @@ TkWmRestackToplevel(winPtr, aboveBelow, otherPtr)
hwnd = (winPtr->wmInfoPtr->wrapper != NULL)
? winPtr->wmInfoPtr->wrapper : Tk_GetHWND(winPtr->window);
-
if (otherPtr != NULL) {
if (otherPtr->window == None) {
Tk_MakeWindowExist((Tk_Window) otherPtr);
@@ -3146,7 +3387,7 @@ TkWmAddToColormapWindows(winPtr)
* Now we need to force the updated colormaps to be installed.
*/
- if (topPtr->wmInfoPtr == foregroundWmPtr) {
+ if (topPtr->wmInfoPtr == winPtr->dispPtr->foregroundWmPtr) {
InstallColormaps(topPtr->wmInfoPtr->wrapper, WM_QUERYNEWPALETTE, 1);
} else {
InstallColormaps(topPtr->wmInfoPtr->wrapper, WM_PALETTECHANGED, 0);
@@ -3344,8 +3585,7 @@ ConfigureTopLevel(pos)
*/
if (!(wmPtr->flags & WM_UPDATE_PENDING)) {
- Tcl_DoWhenIdle(UpdateGeometryInfo,
- (ClientData) winPtr);
+ Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
wmPtr->flags |= WM_UPDATE_PENDING;
}
/* fall through */
@@ -3544,6 +3784,8 @@ InstallColormaps(hwnd, message, isForemost)
HPALETTE oldPalette;
TkWindow *winPtr = GetTopLevel(hwnd);
WmInfo *wmPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (winPtr == NULL) {
return 0;
@@ -3560,17 +3802,17 @@ InstallColormaps(hwnd, message, isForemost)
* secondary palettes are installed properly.
*/
- foregroundWmPtr = wmPtr;
+ winPtr->dispPtr->foregroundWmPtr = wmPtr;
if (wmPtr->cmapCount > 0) {
winPtr = wmPtr->cmapList[0];
}
- systemPalette = TkWinGetPalette(winPtr->atts.colormap);
+ tsdPtr->systemPalette = TkWinGetPalette(winPtr->atts.colormap);
dc = GetDC(hwnd);
- oldPalette = SelectPalette(dc, systemPalette, FALSE);
+ oldPalette = SelectPalette(dc, tsdPtr->systemPalette, FALSE);
if (RealizePalette(dc)) {
- RefreshColormap(winPtr->atts.colormap);
+ RefreshColormap(winPtr->atts.colormap, winPtr->dispPtr);
} else if (wmPtr->cmapCount > 1) {
SelectPalette(dc, oldPalette, TRUE);
RealizePalette(dc);
@@ -3606,13 +3848,13 @@ InstallColormaps(hwnd, message, isForemost)
oldPalette = SelectPalette(dc,
TkWinGetPalette(winPtr->atts.colormap), TRUE);
if (RealizePalette(dc)) {
- RefreshColormap(winPtr->atts.colormap);
+ RefreshColormap(winPtr->atts.colormap, winPtr->dispPtr);
}
for (; i < wmPtr->cmapCount; i++) {
winPtr = wmPtr->cmapList[i];
SelectPalette(dc, TkWinGetPalette(winPtr->atts.colormap), TRUE);
if (RealizePalette(dc)) {
- RefreshColormap(winPtr->atts.colormap);
+ RefreshColormap(winPtr->atts.colormap, winPtr->dispPtr);
}
}
}
@@ -3644,13 +3886,14 @@ InstallColormaps(hwnd, message, isForemost)
*/
static void
-RefreshColormap(colormap)
+RefreshColormap(colormap, dispPtr)
Colormap colormap;
+ TkDisplay *dispPtr;
{
WmInfo *wmPtr;
int i;
- for (wmPtr = firstWmPtr; wmPtr != NULL; wmPtr = wmPtr->nextPtr) {
+ for (wmPtr = dispPtr->firstWmPtr; wmPtr != NULL; wmPtr = wmPtr->nextPtr) {
if (wmPtr->cmapCount > 0) {
for (i = 0; i < wmPtr->cmapCount; i++) {
if ((wmPtr->cmapList[i]->atts.colormap == colormap)
@@ -3732,7 +3975,10 @@ InvalidateSubTree(winPtr, colormap)
HPALETTE
TkWinGetSystemPalette()
{
- return systemPalette;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ return tsdPtr->systemPalette;
}
/*
@@ -3960,8 +4206,8 @@ WmProc(hwnd, message, wParam, lParam)
* leaving move/size mode. Note that this mechanism
* assumes move/size is only one level deep. */
LRESULT result;
- TkWindow *winPtr;
-
+ TkWindow *winPtr = NULL;
+
if (TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam, &result)) {
goto done;
}
@@ -3975,10 +4221,12 @@ WmProc(hwnd, message, wParam, lParam)
case WM_ENTERSIZEMOVE:
inMoveSize = 1;
- /* CYGNUS LOCAL: Cancel any current mouse timer before we
- start looking for events. If the mouse timer fires, it
- will release the size/move mouse capture, which is
- wrong. */
+ /*
+ * Cancel any current mouse timer. If the mouse timer
+ * fires during the size/move mouse capture, it will
+ * release the capture, which is wrong.
+ */
+
TkWinCancelMouseTimer();
oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
@@ -4032,9 +4280,18 @@ WmProc(hwnd, message, wParam, lParam)
ActivateEvent *eventPtr;
winPtr = GetTopLevel((HWND) wParam);
+ if (winPtr && (TkGrabState(winPtr) != TK_GRAB_EXCLUDED)) {
+ /*
+ * This allows us to pass the message onto the
+ * native menus [Bug: 2272]
+ */
+ result = DefWindowProc(hwnd, message, wParam, lParam);
+ goto done;
+ }
+
/*
- * Don't activate the window yet since there may be grabs
- * that should take precedence. Instead we need to queue
+ * Don't activate the window yet since there is a grab
+ * that takes precedence. Instead we need to queue
* an event so we can check the grab state right before we
* handle the mouse event.
*/
@@ -4049,21 +4306,6 @@ WmProc(hwnd, message, wParam, lParam)
goto done;
}
- /* CYGNUS LOCAL. */
- case WM_SETTINGCHANGE:
- if (wParam == SPI_SETNONCLIENTMETRICS) {
- winPtr = GetTopLevel(hwnd);
- if (winPtr != NULL) {
- TkWinNCMetricsChanged((Tk_Window) winPtr);
- }
- }
- break;
-
- /* CYGNUS LOCAL. */
- case WM_SYSCOLORCHANGE:
- TkWinSysColorChange();
- break;
-
default:
break;
}
@@ -4099,7 +4341,7 @@ WmProc(hwnd, message, wParam, lParam)
* None.
*
* Side effects:
- * Changes the style bit used to create a new Mac toplevel.
+ * Changes the style bit used to create a new toplevel.
*
*----------------------------------------------------------------------
*/
@@ -4258,3 +4500,35 @@ ActivateWindow(
return 1;
}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWinSetForegroundWindow --
+ *
+ * This function is a wrapper for SetForegroundWindow, calling
+ * it on the wrapper window because it has no affect on child
+ * windows.
+ *
+ * Results:
+ * none
+ *
+ * Side effects:
+ * May activate the toplevel window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkWinSetForegroundWindow(winPtr)
+ TkWindow *winPtr;
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+
+ if (wmPtr->wrapper != NULL) {
+ SetForegroundWindow(wmPtr->wrapper);
+ } else {
+ SetForegroundWindow(Tk_GetHWND(winPtr->window));
+ }
+}
diff --git a/tk/win/tkWinX.c b/tk/win/tkWinX.c
index 3a5bbe9d1ee..aed6113e888 100644
--- a/tk/win/tkWinX.c
+++ b/tk/win/tkWinX.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 1995-1996 Sun Microsystems, Inc.
* Copyright (c) 1994 Software Research Associates, Inc.
- * Copyright (c) 1998 by Scriptics Corporation.
+ * Copyright (c) 1998-2000 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -13,50 +13,37 @@
* RCS: @(#) $Id$
*/
-#include "tkInt.h"
#include "tkWinInt.h"
-#if defined (__CYGWIN32__) || defined (__MINGW32__)
-/* GCC ports that use Windows32api headers don't provide
- GetCurrentTime, and the function is obsolete anyhow. */
-#define GetCurrentTime GetTickCount
-#endif
-
-/*
- * CYGNUS LOCAL:
- * We don't have a zmouse.h, AND as of gnupro 98r2, the WM_MOUSEWHEEL
- * message is not added to any of the Cygwin defines. So we include
- * it here.
- * FIXME -- remove the define when it gets into the Cygwin header files
- */
-
-#ifdef __CYGWIN32__
-#define WM_MOUSEWHEEL 0x020A
-#else
/*
* The zmouse.h file includes the definition for WM_MOUSEWHEEL.
*/
#include <zmouse.h>
-#endif
/*
- * Definitions of extern variables supplied by this file.
+ * Declarations of static variables used in this file.
*/
-int tkpIsWin32s = -1;
+static char winScreenName[] = ":0"; /* Default name of windows display. */
+static HINSTANCE tkInstance; /* Application instance handle. */
+static int childClassInitialized; /* Registered child class? */
+static WNDCLASS childClass; /* Window class for child windows. */
+static int tkPlatformId; /* version of Windows platform */
+
+TCL_DECLARE_MUTEX(winXMutex)
/*
- * Declarations of static variables used in this file.
+ * Thread local storage. Notice that now each thread must have its
+ * own TkDisplay structure, since this structure contains most of
+ * the thread-specific date for threads.
*/
-
-static HINSTANCE tkInstance = (HINSTANCE) NULL;
- /* Global application instance handle. */
-static TkDisplay *winDisplay; /* Display that represents Windows screen. */
-static char winScreenName[] = ":0";
- /* Default name of windows display. */
-static WNDCLASS childClass; /* Window class for child windows. */
-static childClassInitialized = 0; /* Registered child class? */
+typedef struct ThreadSpecificData {
+ TkDisplay *winDisplay; /* TkDisplay structure that *
+ * represents Windows screen. */
+ int updatingClipboard; /* If 1, we are updating the clipboard */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* Forward declarations of procedures used in this file.
@@ -93,16 +80,14 @@ TkGetServerInfo(interp, tkwin)
Tk_Window tkwin; /* Token for window; this selects a
* particular display and server. */
{
- char buffer[50];
- OSVERSIONINFO info;
-
- info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&info);
- sprintf(buffer, "Windows %d.%d %d ", info.dwMajorVersion,
- info.dwMinorVersion, info.dwBuildNumber);
- Tcl_AppendResult(interp, buffer,
- (info.dwPlatformId == VER_PLATFORM_WIN32s) ? "Win32s" : "Win32",
- (char *) NULL);
+ char buffer[60];
+ OSVERSIONINFO os;
+
+ os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&os);
+ sprintf(buffer, "Windows %d.%d %d Win32", os.dwMajorVersion,
+ os.dwMinorVersion, os.dwBuildNumber);
+ Tcl_SetResult(interp, buffer, TCL_VOLATILE);
}
/*
@@ -147,11 +132,7 @@ void
TkWinXInit(hInstance)
HINSTANCE hInstance;
{
- OSVERSIONINFO info;
-
- info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&info);
- tkpIsWin32s = (info.dwPlatformId == VER_PLATFORM_WIN32s);
+ OSVERSIONINFO os;
if (childClassInitialized != 0) {
return;
@@ -160,7 +141,25 @@ TkWinXInit(hInstance)
tkInstance = hInstance;
+ os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&os);
+ tkPlatformId = os.dwPlatformId;
+
+ /*
+ * When threads are enabled, we cannot use CLASSDC because
+ * threads will then write into the same device context.
+ *
+ * This is a hack; we should add a subsystem that manages
+ * device context on a per-thread basis. See also tkWinWm.c,
+ * which also initializes a WNDCLASS structure.
+ */
+
+#ifdef TCL_THREADS
+ childClass.style = CS_HREDRAW | CS_VREDRAW;
+#else
childClass.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC;
+#endif
+
childClass.cbClsExtra = 0;
childClass.cbWndExtra = 0;
childClass.hInstance = hInstance;
@@ -220,6 +219,32 @@ TkWinXCleanup(hInstance)
/*
*----------------------------------------------------------------------
*
+ * TkWinGetPlatformId --
+ *
+ * Determines whether running under NT, 95, or Win32s, to allow
+ * runtime conditional code.
+ *
+ * Results:
+ * The return value is one of:
+ * VER_PLATFORM_WIN32s Win32s on Windows 3.1.
+ * VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95.
+ * VER_PLATFORM_WIN32_NT Win32 on Windows NT
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkWinGetPlatformId()
+{
+ return tkPlatformId;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkGetDefaultScreenName --
*
* Returns the name of the screen that Tk should use during
@@ -254,10 +279,10 @@ TkGetDefaultScreenName(interp, screenName)
* specific information.
*
* Results:
- * Returns a Display structure on success or NULL on failure.
+ * Returns a TkDisplay structure on success or NULL on failure.
*
* Side effects:
- * Allocates a new Display structure.
+ * Allocates a new TkDisplay structure.
*
*----------------------------------------------------------------------
*/
@@ -270,10 +295,13 @@ TkpOpenDisplay(display_name)
HDC dc;
TkWinDrawable *twdPtr;
Display *display;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- if (winDisplay != NULL) {
- if (strcmp(winDisplay->display->display_name, display_name) == 0) {
- return winDisplay;
+ if (tsdPtr->winDisplay != NULL) {
+ if (strcmp(tsdPtr->winDisplay->display->display_name, display_name)
+ == 0) {
+ return tsdPtr->winDisplay;
} else {
return NULL;
}
@@ -370,14 +398,15 @@ TkpOpenDisplay(display_name)
screen->white_pixel = RGB(255, 255, 255);
screen->black_pixel = RGB(0, 0, 0);
- display->screens = screen;
- display->nscreens = 1;
- display->default_screen = 0;
+ display->screens = screen;
+ display->nscreens = 1;
+ display->default_screen = 0;
screen->cmap = XCreateColormap(display, None, screen->root_visual,
AllocNone);
- winDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay));
- winDisplay->display = display;
- return winDisplay;
+ tsdPtr->winDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay));
+ tsdPtr->winDisplay->display = display;
+ tsdPtr->updatingClipboard = FALSE;
+ return tsdPtr->winDisplay;
}
/*
@@ -403,8 +432,10 @@ TkpCloseDisplay(dispPtr)
{
Display *display = dispPtr->display;
HWND hwnd;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- if (dispPtr != winDisplay) {
+ if (dispPtr != tsdPtr->winDisplay) {
panic("TkpCloseDisplay: tried to call TkpCloseDisplay on another display");
return;
}
@@ -423,7 +454,7 @@ TkpCloseDisplay(dispPtr)
}
}
- winDisplay = NULL;
+ tsdPtr->winDisplay = NULL;
if (display->display_name != (char *) NULL) {
ckfree(display->display_name);
@@ -506,7 +537,6 @@ TkWinChildProc(hwnd, message, wParam, lParam)
case WM_CREATE:
case WM_ERASEBKGND:
- case WM_WINDOWPOSCHANGED:
result = 0;
break;
@@ -654,6 +684,8 @@ GenerateXEvent(hwnd, message, wParam, lParam)
{
XEvent event;
TkWindow *winPtr = (TkWindow *)Tk_HWNDToWindow(hwnd);
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (!winPtr || winPtr->window == None) {
return;
@@ -718,14 +750,19 @@ GenerateXEvent(hwnd, message, wParam, lParam)
}
case WM_DESTROYCLIPBOARD:
+ if (tsdPtr->updatingClipboard == TRUE) {
+ /*
+ * We want to avoid this event if we are the ones that caused
+ * this event.
+ */
+ return;
+ }
event.type = SelectionClear;
event.xselectionclear.selection =
Tk_InternAtom((Tk_Window)winPtr, "CLIPBOARD");
event.xselectionclear.time = TkpGetMS();
break;
- /* CYGNUS LOCAL: Handle WM_MENUCHAR. */
- case WM_MENUCHAR:
case WM_MOUSEWHEEL:
/*
* The mouse wheel event is closer to a key event than a
@@ -815,26 +852,61 @@ GenerateXEvent(hwnd, message, wParam, lParam)
*/
event.type = KeyRelease;
event.xkey.keycode = wParam;
- event.xkey.nchars = 0;
+ event.xkey.nbytes = 0;
break;
- /* CYGNUS LOCAL: Handle WM_MENUCHAR. */
- case WM_MENUCHAR:
- /* For a WM_MENUCHAR message, the character code is
- only the low word. */
- wParam = LOWORD (wParam);
- /* Fall through. */
-
case WM_CHAR:
/*
* Synthesize both a KeyPress and a KeyRelease.
+ * Strings generated by Input Method Editor are handled
+ * in the following manner:
+ * 1. A series of WM_KEYDOWN & WM_KEYUP messages that
+ * cause GetTranslatedKey() to be called and return
+ * immediately because the WM_KEYDOWNs have no
+ * associated WM_CHAR messages -- the IME window is
+ * accumulating the characters and translating them
+ * itself. In the "bind" command, you get an event
+ * with a mystery keysym and %A == "" for each
+ * WM_KEYDOWN that actually was meant for the IME.
+ * 2. A WM_KEYDOWN corresponding to the "confirm typing"
+ * character. This causes GetTranslatedKey() to be
+ * called.
+ * 3. A WM_IME_NOTIFY message saying that the IME is
+ * done. A side effect of this message is that
+ * GetTranslatedKey() thinks this means that there
+ * are no WM_CHAR messages and returns immediately.
+ * In the "bind" command, you get an another event
+ * with a mystery keysym and %A == "".
+ * 4. A sequence of WM_CHAR messages that correspond to
+ * the characters in the IME window. A bunch of
+ * simulated KeyPress/KeyRelease events will be
+ * generated, one for each character. Adjacent
+ * WM_CHAR messages may actually specify the high
+ * and low bytes of a multi-byte character -- in that
+ * case the two WM_CHAR messages will be combined into
+ * one event. It is the event-consumer's
+ * responsibility to convert the string returned from
+ * XLookupString from system encoding to UTF-8.
+ * 5. And finally we get the WM_KEYUP for the "confirm
+ * typing" character.
*/
event.type = KeyPress;
event.xany.send_event = -1;
event.xkey.keycode = 0;
- event.xkey.nchars = 1;
+ event.xkey.nbytes = 1;
event.xkey.trans_chars[0] = (char) wParam;
+
+ if (IsDBCSLeadByte((BYTE) wParam)) {
+ MSG msg;
+
+ if ((PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) != 0)
+ && (msg.message == WM_CHAR)) {
+ GetMessage(&msg, NULL, 0, 0);
+ event.xkey.nbytes = 2;
+ event.xkey.trans_chars[1] = (char) msg.wParam;
+ }
+ }
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
event.type = KeyRelease;
break;
@@ -893,7 +965,7 @@ GetState(message, wParam, lParam)
mask = ControlMask;
break;
case VK_MENU:
- mask = Mod2Mask;
+ mask = ALT_MASK;
break;
case VK_CAPITAL:
if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
@@ -933,7 +1005,7 @@ GetState(message, wParam, lParam)
* given KeyPress event.
*
* Results:
- * Sets the trans_chars and nchars member of the key event.
+ * Sets the trans_chars and nbytes member of the key event.
*
* Side effects:
* Removes any WM_CHAR messages waiting on the top of the system
@@ -947,14 +1019,13 @@ GetTranslatedKey(xkey)
XKeyEvent *xkey;
{
MSG msg;
+ char buf[XMaxTransChars];
- xkey->nchars = 0;
+ xkey->nbytes = 0;
- while (xkey->nchars < XMaxTransChars
+ while ((xkey->nbytes < XMaxTransChars)
&& PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
if ((msg.message == WM_CHAR) || (msg.message == WM_SYSCHAR)) {
- xkey->trans_chars[xkey->nchars] = (char) msg.wParam;
- xkey->nchars++;
GetMessage(&msg, NULL, 0, 0);
/*
@@ -968,6 +1039,9 @@ GetTranslatedKey(xkey)
if ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) {
xkey->state = 0;
}
+ buf[xkey->nbytes] = (char) msg.wParam;
+ xkey->trans_chars[xkey->nbytes] = (char) msg.wParam;
+ xkey->nbytes++;
} else {
break;
}
@@ -1084,5 +1158,29 @@ TkWinResendEvent(wndproc, hwnd, eventPtr)
unsigned long
TkpGetMS()
{
- return GetCurrentTime();
+ return GetTickCount();
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWinUpdatingClipboard --
+ *
+ *
+ * Results:
+ * Number of milliseconds.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkWinUpdatingClipboard(int mode)
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ tsdPtr->updatingClipboard = mode;
}
diff --git a/tk/win/winDumpExts.c b/tk/win/winDumpExts.c
new file mode 100644
index 00000000000..8bc496e01e4
--- /dev/null
+++ b/tk/win/winDumpExts.c
@@ -0,0 +1,503 @@
+/*
+ * winDumpExts.c --
+ * Author: Gordon Chaffee, Scott Stanton
+ *
+ * History: The real functionality of this file was written by
+ * Matt Pietrek in 1993 in his pedump utility. I've
+ * modified it to dump the externals in a bunch of object
+ * files to create a .def file.
+ *
+ * 10/12/95 Modified by Scott Stanton to support Relocatable Object Module
+ * Format files for Borland C++ 4.5.
+ *
+ * Notes: Visual C++ puts an underscore before each exported symbol.
+ * This file removes them. I don't know if this is a problem
+ * this other compilers. If _MSC_VER is defined,
+ * the underscore is removed. If not, it isn't. To get a
+ * full dump of an object file, use the -f option. This can
+ * help determine the something that may be different with a
+ * compiler other than Visual C++.
+ *----------------------------------------------------------------------
+ *
+ * SCCS: @(#) winDumpExts.c 1.11 96/09/18 15:25:11
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <process.h>
+
+#ifdef _ALPHA_
+#define e_magic_number IMAGE_FILE_MACHINE_ALPHA
+#else
+#define e_magic_number IMAGE_FILE_MACHINE_I386
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ * GetArgcArgv --
+ *
+ * Break up a line into argc argv
+ *----------------------------------------------------------------------
+ */
+int
+GetArgcArgv(char *s, char **argv)
+{
+ int quote = 0;
+ int argc = 0;
+ char *bp;
+
+ bp = s;
+ while (1) {
+ while (isspace(*bp)) {
+ bp++;
+ }
+ if (*bp == '\n' || *bp == '\0') {
+ *bp = '\0';
+ return argc;
+ }
+ if (*bp == '\"') {
+ quote = 1;
+ bp++;
+ }
+ argv[argc++] = bp;
+
+ while (*bp != '\0') {
+ if (quote) {
+ if (*bp == '\"') {
+ quote = 0;
+ *bp = '\0';
+ bp++;
+ break;
+ }
+ bp++;
+ continue;
+ }
+ if (isspace(*bp)) {
+ *bp = '\0';
+ bp++;
+ break;
+ }
+ bp++;
+ }
+ }
+}
+
+/*
+ * The names of the first group of possible symbol table storage classes
+ */
+char * SzStorageClass1[] = {
+ "NULL","AUTOMATIC","EXTERNAL","STATIC","REGISTER","EXTERNAL_DEF","LABEL",
+ "UNDEFINED_LABEL","MEMBER_OF_STRUCT","ARGUMENT","STRUCT_TAG",
+ "MEMBER_OF_UNION","UNION_TAG","TYPE_DEFINITION","UNDEFINED_STATIC",
+ "ENUM_TAG","MEMBER_OF_ENUM","REGISTER_PARAM","BIT_FIELD"
+};
+
+/*
+ * The names of the second group of possible symbol table storage classes
+ */
+char * SzStorageClass2[] = {
+ "BLOCK","FUNCTION","END_OF_STRUCT","FILE","SECTION","WEAK_EXTERNAL"
+};
+
+/*
+ *----------------------------------------------------------------------
+ * GetSZStorageClass --
+ *
+ * Given a symbol storage class value, return a descriptive
+ * ASCII string
+ *----------------------------------------------------------------------
+ */
+PSTR
+GetSZStorageClass(BYTE storageClass)
+{
+ if ( storageClass <= IMAGE_SYM_CLASS_BIT_FIELD )
+ return SzStorageClass1[storageClass];
+ else if ( (storageClass >= IMAGE_SYM_CLASS_BLOCK)
+ && (storageClass <= IMAGE_SYM_CLASS_WEAK_EXTERNAL) )
+ return SzStorageClass2[storageClass-IMAGE_SYM_CLASS_BLOCK];
+ else
+ return "???";
+}
+
+/*
+ *----------------------------------------------------------------------
+ * GetSectionName --
+ *
+ * Used by DumpSymbolTable, it gives meaningful names to
+ * the non-normal section number.
+ *
+ * Results:
+ * A name is returned in buffer
+ *----------------------------------------------------------------------
+ */
+void
+GetSectionName(WORD section, PSTR buffer, unsigned cbBuffer)
+{
+ char tempbuffer[10];
+
+ switch ( (SHORT)section )
+ {
+ case IMAGE_SYM_UNDEFINED: strcpy(tempbuffer, "UNDEF"); break;
+ case IMAGE_SYM_ABSOLUTE: strcpy(tempbuffer, "ABS "); break;
+ case IMAGE_SYM_DEBUG: strcpy(tempbuffer, "DEBUG"); break;
+ default: wsprintf(tempbuffer, "%-5X", section);
+ }
+
+ strncpy(buffer, tempbuffer, cbBuffer-1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ * DumpSymbolTable --
+ *
+ * Dumps a COFF symbol table from an EXE or OBJ. We only use
+ * it to dump tables from OBJs.
+ *----------------------------------------------------------------------
+ */
+void
+DumpSymbolTable(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols)
+{
+ unsigned i;
+ PSTR stringTable;
+ char sectionName[10];
+
+ fprintf(fout, "Symbol Table - %X entries (* = auxillary symbol)\n",
+ cSymbols);
+
+ fprintf(fout,
+ "Indx Name Value Section cAux Type Storage\n"
+ "---- -------------------- -------- ---------- ----- ------- --------\n");
+
+ /*
+ * The string table apparently starts right after the symbol table
+ */
+ stringTable = (PSTR)&pSymbolTable[cSymbols];
+
+ for ( i=0; i < cSymbols; i++ ) {
+ fprintf(fout, "%04X ", i);
+ if ( pSymbolTable->N.Name.Short != 0 )
+ fprintf(fout, "%-20.8s", pSymbolTable->N.ShortName);
+ else
+ fprintf(fout, "%-20s", stringTable + pSymbolTable->N.Name.Long);
+
+ fprintf(fout, " %08X", pSymbolTable->Value);
+
+ GetSectionName(pSymbolTable->SectionNumber, sectionName,
+ sizeof(sectionName));
+ fprintf(fout, " sect:%s aux:%X type:%02X st:%s\n",
+ sectionName,
+ pSymbolTable->NumberOfAuxSymbols,
+ pSymbolTable->Type,
+ GetSZStorageClass(pSymbolTable->StorageClass) );
+#if 0
+ if ( pSymbolTable->NumberOfAuxSymbols )
+ DumpAuxSymbols(pSymbolTable);
+#endif
+
+ /*
+ * Take into account any aux symbols
+ */
+ i += pSymbolTable->NumberOfAuxSymbols;
+ pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
+ pSymbolTable++;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ * DumpExternals --
+ *
+ * Dumps a COFF symbol table from an EXE or OBJ. We only use
+ * it to dump tables from OBJs.
+ *----------------------------------------------------------------------
+ */
+void
+DumpExternals(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols)
+{
+ unsigned i;
+ PSTR stringTable;
+ char *s, *f;
+ char symbol[1024];
+
+ /*
+ * The string table apparently starts right after the symbol table
+ */
+ stringTable = (PSTR)&pSymbolTable[cSymbols];
+
+ for ( i=0; i < cSymbols; i++ ) {
+ if (pSymbolTable->SectionNumber > 0 && pSymbolTable->Type == 0x20) {
+ if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
+ if (pSymbolTable->N.Name.Short != 0) {
+ strncpy(symbol, pSymbolTable->N.ShortName, 8);
+ symbol[8] = 0;
+ } else {
+ s = stringTable + pSymbolTable->N.Name.Long;
+ strcpy(symbol, s);
+ }
+ s = symbol;
+ f = strchr(s, '@');
+ if (f) {
+ *f = 0;
+ }
+#if defined(_MSC_VER) && defined(_X86_)
+ if (symbol[0] == '_') {
+ s = &symbol[1];
+ }
+#endif
+ if ((stricmp(s, "DllEntryPoint") != 0)
+ && (stricmp(s, "DllMain") != 0)) {
+ fprintf(fout, "\t%s\n", s);
+ }
+ }
+ }
+
+ /*
+ * Take into account any aux symbols
+ */
+ i += pSymbolTable->NumberOfAuxSymbols;
+ pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
+ pSymbolTable++;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ * DumpObjFile --
+ *
+ * Dump an object file--either a full listing or just the exported
+ * symbols.
+ *----------------------------------------------------------------------
+ */
+void
+DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout, int full)
+{
+ PIMAGE_SYMBOL PCOFFSymbolTable;
+ DWORD COFFSymbolCount;
+
+ PCOFFSymbolTable = (PIMAGE_SYMBOL)
+ ((DWORD)pImageFileHeader + pImageFileHeader->PointerToSymbolTable);
+ COFFSymbolCount = pImageFileHeader->NumberOfSymbols;
+
+ if (full) {
+ DumpSymbolTable(PCOFFSymbolTable, fout, COFFSymbolCount);
+ } else {
+ DumpExternals(PCOFFSymbolTable, fout, COFFSymbolCount);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ * SkipToNextRecord --
+ *
+ * Skip over the current ROMF record and return the type of the
+ * next record.
+ *----------------------------------------------------------------------
+ */
+
+BYTE
+SkipToNextRecord(BYTE **ppBuffer)
+{
+ int length;
+ (*ppBuffer)++; /* Skip over the type.*/
+ length = *((WORD*)(*ppBuffer))++; /* Retrieve the length. */
+ *ppBuffer += length; /* Skip over the rest. */
+ return **ppBuffer; /* Return the type. */
+}
+
+/*
+ *----------------------------------------------------------------------
+ * DumpROMFObjFile --
+ *
+ * Dump a Relocatable Object Module Format file, displaying only
+ * the exported symbols.
+ *----------------------------------------------------------------------
+ */
+void
+DumpROMFObjFile(LPVOID pBuffer, FILE *fout)
+{
+ BYTE type, length;
+ char symbol[1024], *s;
+
+ while (1) {
+ type = SkipToNextRecord(&(BYTE*)pBuffer);
+ if (type == 0x90) { /* PUBDEF */
+ if (((BYTE*)pBuffer)[4] != 0) {
+ length = ((BYTE*)pBuffer)[5];
+ strncpy(symbol, ((char*)pBuffer) + 6, length);
+ symbol[length] = '\0';
+ s = symbol;
+ if ((stricmp(s, "DllEntryPoint") != 0)
+ && (stricmp(s, "DllMain") != 0)) {
+ if (s[0] == '_') {
+ s++;
+ fprintf(fout, "\t_%s\n\t%s=_%s\n", s, s, s);
+ } else {
+ fprintf(fout, "\t%s\n", s);
+ }
+ }
+ }
+ } else if (type == 0x8B || type == 0x8A) { /* MODEND */
+ break;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ * DumpFile --
+ *
+ * Open up a file, memory map it, and call the appropriate
+ * dumping routine
+ *----------------------------------------------------------------------
+ */
+void
+DumpFile(LPSTR filename, FILE *fout, int full)
+{
+ HANDLE hFile;
+ HANDLE hFileMapping;
+ LPVOID lpFileBase;
+ PIMAGE_DOS_HEADER dosHeader;
+
+ hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "Couldn't open file with CreateFile()\n");
+ return;
+ }
+
+ hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (hFileMapping == 0) {
+ CloseHandle(hFile);
+ fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n");
+ return;
+ }
+
+ lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
+ if (lpFileBase == 0) {
+ CloseHandle(hFileMapping);
+ CloseHandle(hFile);
+ fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n");
+ return;
+ }
+
+ dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
+ if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
+#if 0
+ DumpExeFile( dosHeader );
+#else
+ fprintf(stderr, "File is an executable. I don't dump those.\n");
+ return;
+#endif
+ }
+ /* Does it look like a i386 COFF OBJ file??? */
+ else if ((dosHeader->e_magic == e_magic_number)
+ && (dosHeader->e_sp == 0)) {
+ /*
+ * The two tests above aren't what they look like. They're
+ * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C)
+ * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
+ */
+ DumpObjFile((PIMAGE_FILE_HEADER) lpFileBase, fout, full);
+ } else if (*((BYTE *)lpFileBase) == 0x80) {
+ /*
+ * This file looks like it might be a ROMF file.
+ */
+ DumpROMFObjFile(lpFileBase, fout);
+ } else {
+ printf("unrecognized file format\n");
+ }
+ UnmapViewOfFile(lpFileBase);
+ CloseHandle(hFileMapping);
+ CloseHandle(hFile);
+}
+
+void
+main(int argc, char **argv)
+{
+ char *fargv[1000];
+ char cmdline[10000];
+ int i, arg;
+ FILE *fout;
+ int pos;
+ int full = 0;
+ char *outfile = NULL;
+
+ if (argc < 3) {
+ Usage:
+ fprintf(stderr, "Usage: %s ?-o outfile? ?-f(ull)? <dllname> <object filenames> ..\n", argv[0]);
+ exit(1);
+ }
+
+ arg = 1;
+ while (argv[arg][0] == '-') {
+ if (strcmp(argv[arg], "--") == 0) {
+ arg++;
+ break;
+ } else if (strcmp(argv[arg], "-f") == 0) {
+ full = 1;
+ } else if (strcmp(argv[arg], "-o") == 0) {
+ arg++;
+ if (arg == argc) {
+ goto Usage;
+ }
+ outfile = argv[arg];
+ }
+ arg++;
+ }
+ if (arg == argc) {
+ goto Usage;
+ }
+
+ if (outfile) {
+ fout = fopen(outfile, "w+");
+ if (fout == NULL) {
+ fprintf(stderr, "Unable to open \'%s\' for writing:\n",
+ argv[arg]);
+ perror("");
+ exit(1);
+ }
+ } else {
+ fout = stdout;
+ }
+
+ if (! full) {
+ char *dllname = argv[arg];
+ arg++;
+ if (arg == argc) {
+ goto Usage;
+ }
+ fprintf(fout, "LIBRARY %s\n", dllname);
+ fprintf(fout, "EXETYPE WINDOWS\n");
+ fprintf(fout, "CODE PRELOAD MOVEABLE DISCARDABLE\n");
+ fprintf(fout, "DATA PRELOAD MOVEABLE MULTIPLE\n\n");
+ fprintf(fout, "EXPORTS\n");
+ }
+
+ for (; arg < argc; arg++) {
+ if (argv[arg][0] == '@') {
+ FILE *fargs = fopen(&argv[arg][1], "r");
+ if (fargs == NULL) {
+ fprintf(stderr, "Unable to open \'%s\' for reading:\n",
+ argv[arg]);
+ perror("");
+ exit(1);
+ }
+ pos = 0;
+ for (i = 0; i < arg; i++) {
+ strcpy(&cmdline[pos], argv[i]);
+ pos += strlen(&cmdline[pos]) + 1;
+ fargv[i] = argv[i];
+ }
+ fgets(&cmdline[pos], sizeof(cmdline), fargs);
+ fprintf(stderr, "%s\n", &cmdline[pos]);
+ fclose(fargs);
+ i += GetArgcArgv(&cmdline[pos], &fargv[i]);
+ argc = i;
+ argv = fargv;
+ }
+ DumpFile(argv[arg], fout, full);
+ }
+ exit(0);
+}
diff --git a/tk/win/winMain.c b/tk/win/winMain.c
index af989d50948..8cc6b7773e2 100644
--- a/tk/win/winMain.c
+++ b/tk/win/winMain.c
@@ -3,7 +3,8 @@
*
* Main entry point for wish and other Tk-based applications.
*
- * Copyright (c) 1995 Sun Microsystems, Inc.
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -18,13 +19,13 @@
#include <malloc.h>
#include <locale.h>
+#include "tkInt.h"
+
/*
* The following declarations refer to internal Tk routines. These
* interfaces are available for use, but are not supported.
*/
-EXTERN void TkConsoleCreate(void);
-EXTERN int TkConsoleInit(Tcl_Interp *interp);
/*
* Forward declarations for procedures defined later in this file:
@@ -34,9 +35,38 @@ static void setargv _ANSI_ARGS_((int *argcPtr, char ***argvPtr));
static void WishPanic _ANSI_ARGS_(TCL_VARARGS(char *,format));
#ifdef TK_TEST
-EXTERN int Tktest_Init(Tcl_Interp *interp);
+extern int Tktest_Init(Tcl_Interp *interp);
#endif /* TK_TEST */
+#ifdef TCL_TEST
+extern int TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp));
+extern int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp));
+#endif /* TCL_TEST */
+
+static BOOL consoleRequired = TRUE;
+
+/*
+ * The following #if block allows you to change the AppInit
+ * function by using a #define of TCL_LOCAL_APPINIT instead
+ * of rewriting this entire file. The #if checks for that
+ * #define and uses Tcl_AppInit if it doesn't exist.
+ */
+
+#ifndef TK_LOCAL_APPINIT
+#define TK_LOCAL_APPINIT Tcl_AppInit
+#endif
+extern int TK_LOCAL_APPINIT _ANSI_ARGS_((Tcl_Interp *interp));
+
+/*
+ * The following #if block allows you to change how Tcl finds the startup
+ * script, prime the library or encoding paths, fiddle with the argv,
+ * etc., without needing to rewrite Tk_Main()
+ */
+
+#ifdef TK_LOCAL_MAIN_HOOK
+extern int TK_LOCAL_MAIN_HOOK _ANSI_ARGS_((int *argc, char ***argv));
+#endif
+
/*
*----------------------------------------------------------------------
@@ -62,37 +92,37 @@ WinMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
LPSTR lpszCmdLine;
int nCmdShow;
{
- char **argv, *p;
+ char **argv;
int argc;
- char buffer[MAX_PATH];
+ char buffer[MAX_PATH+1];
+ char *p;
Tcl_SetPanicProc(WishPanic);
/*
- * Set up the default locale to be standard "C" locale so parsing
- * is performed correctly.
- */
-
- setlocale(LC_ALL, "C");
-
-
- /*
* Increase the application queue size from default value of 8.
* At the default value, cross application SendMessage of WM_KILLFOCUS
* will fail because the handler will not be able to do a PostMessage!
* This is only needed for Windows 3.x, since NT dynamically expands
* the queue.
*/
+
SetMessageQueue(64);
/*
* Create the console channels and install them as the standard
- * channels. All I/O will be discarded until TkConsoleInit is
+ * channels. All I/O will be discarded until Tk_CreateConsoleWindow is
* called to attach the console to a text widget.
*/
- TkConsoleCreate();
+ consoleRequired = TRUE;
+ /*
+ * Set up the default locale to be standard "C" locale so parsing
+ * is performed correctly.
+ */
+
+ setlocale(LC_ALL, "C");
setargv(&argc, &argv);
/*
@@ -108,7 +138,11 @@ WinMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
}
}
- Tk_Main(argc, argv, Tcl_AppInit);
+#ifdef TK_LOCAL_MAIN_HOOK
+ TK_LOCAL_MAIN_HOOK(&argc, &argv);
+#endif
+
+ Tk_Main(argc, argv, TK_LOCAL_APPINIT);
return 1;
}
@@ -124,7 +158,7 @@ WinMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
*
* Results:
* Returns a standard Tcl completion code, and leaves an error
- * message in interp->result if an error occurs.
+ * message in the interp's result if an error occurs.
*
* Side effects:
* Depends on the startup script.
@@ -149,9 +183,22 @@ Tcl_AppInit(interp)
* application.
*/
- if (TkConsoleInit(interp) == TCL_ERROR) {
- goto error;
+ if (consoleRequired) {
+ if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) {
+ goto error;
+ }
+ }
+
+#ifdef TCL_TEST
+ if (Tcltest_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init,
+ (Tcl_PackageInitProc *) NULL);
+ if (TclObjTest_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
}
+#endif /* TCL_TEST */
#ifdef TK_TEST
if (Tktest_Init(interp) == TCL_ERROR) {
@@ -165,7 +212,11 @@ Tcl_AppInit(interp)
return TCL_OK;
error:
- WishPanic(interp->result);
+ MessageBeep(MB_ICONEXCLAMATION);
+ MessageBox(NULL, Tcl_GetStringResult(interp), "Error in Wish",
+ MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
+ ExitProcess(1);
+ /* we won't reach this, but we need the return */
return TCL_ERROR;
}
@@ -239,7 +290,7 @@ setargv(argcPtr, argvPtr)
char **argv;
int argc, size, inquote, copy, slashes;
- cmdLine = GetCommandLine();
+ cmdLine = GetCommandLine(); /* INTL: BUG */
/*
* Precompute an overly pessimistic guess at the number of arguments
@@ -248,9 +299,9 @@ setargv(argcPtr, argvPtr)
size = 2;
for (p = cmdLine; *p != '\0'; p++) {
- if (isspace(*p)) {
+ if ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */
size++;
- while (isspace(*p)) {
+ while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */
p++;
}
if (*p == '\0') {
@@ -258,8 +309,8 @@ setargv(argcPtr, argvPtr)
}
}
}
- argSpace = (char *) ckalloc((unsigned) (size * sizeof(char *)
- + strlen(cmdLine) + 1));
+ argSpace = (char *) Tcl_Alloc(
+ (unsigned) (size * sizeof(char *) + strlen(cmdLine) + 1));
argv = (char **) argSpace;
argSpace += size * sizeof(char *);
size--;
@@ -267,7 +318,7 @@ setargv(argcPtr, argvPtr)
p = cmdLine;
for (argc = 0; argc < size; argc++) {
argv[argc] = arg = argSpace;
- while (isspace(*p)) {
+ while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */
p++;
}
if (*p == '\0') {
@@ -301,7 +352,8 @@ setargv(argcPtr, argvPtr)
slashes--;
}
- if ((*p == '\0') || (!inquote && isspace(*p))) {
+ if ((*p == '\0')
+ || (!inquote && ((*p == ' ') || (*p == '\t')))) { /* INTL: ISO space. */
break;
}
if (copy != 0) {
@@ -319,3 +371,55 @@ setargv(argcPtr, argvPtr)
*argvPtr = argv;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * main --
+ *
+ * Main entry point from the console.
+ *
+ * Results:
+ * None: Tk_Main never returns here, so this procedure never
+ * returns either.
+ *
+ * Side effects:
+ * Whatever the applications does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int main(int argc, char **argv)
+{
+ Tcl_SetPanicProc(WishPanic);
+
+ /*
+ * Set up the default locale to be standard "C" locale so parsing
+ * is performed correctly.
+ */
+
+ setlocale(LC_ALL, "C");
+ /*
+ * Increase the application queue size from default value of 8.
+ * At the default value, cross application SendMessage of WM_KILLFOCUS
+ * will fail because the handler will not be able to do a PostMessage!
+ * This is only needed for Windows 3.x, since NT dynamically expands
+ * the queue.
+ */
+
+ SetMessageQueue(64);
+
+ /*
+ * Create the console channels and install them as the standard
+ * channels. All I/O will be discarded until Tk_CreateConsoleWindow is
+ * called to attach the console to a text widget.
+ */
+
+ consoleRequired = FALSE;
+
+ Tk_Main(argc, argv, Tcl_AppInit);
+ return 0;
+}
+
+
+