diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2018-12-25 19:56:49 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2018-12-25 19:56:49 (GMT) |
commit | d5a4b3667e9d26b9c13905ccb51021d13ce87c58 (patch) | |
tree | fc0f3692516c8c3e8090df20223d342a1b64df93 /tk8.6/unix | |
parent | ff51550ee89b473c63df78de6b2a413f21105687 (diff) | |
download | blt-d5a4b3667e9d26b9c13905ccb51021d13ce87c58.zip blt-d5a4b3667e9d26b9c13905ccb51021d13ce87c58.tar.gz blt-d5a4b3667e9d26b9c13905ccb51021d13ce87c58.tar.bz2 |
update tcl/tk
Diffstat (limited to 'tk8.6/unix')
40 files changed, 45649 insertions, 0 deletions
diff --git a/tk8.6/unix/Makefile.in b/tk8.6/unix/Makefile.in new file mode 100644 index 0000000..4652052 --- /dev/null +++ b/tk8.6/unix/Makefile.in @@ -0,0 +1,1703 @@ +# +# 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. + +# Current Tk version; used in various names. + +TCLVERSION = @TCL_VERSION@ +TCLPATCHL = @TCL_PATCH_LEVEL@ +VERSION = @TK_VERSION@ +MAJOR_VERSION = @TK_MAJOR_VERSION@ +MINOR_VERSION = @TK_MINOR_VERSION@ +PATCH_LEVEL = @TK_PATCH_LEVEL@ +LOCALES = @LOCALES@ + +#---------------------------------------------------------------- +# 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. The *dir vars are standard configure +# substitutions that are based off prefix and exec_prefix. + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +includedir = @includedir@ +datarootdir = @datarootdir@ +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 = $(DESTDIR) + +# Directory from which applications will reference the library of Tcl +# scripts (note: you can set the TK_LIBRARY environment variable at +# run-time to override the compiled-in location): +TK_LIBRARY = @TK_LIBRARY@ + +# Path to use at runtime to refer to LIB_INSTALL_DIR: +LIB_RUNTIME_DIR = @LIB_RUNTIME_DIR@ + +# 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) +DLL_INSTALL_DIR = @DLL_INSTALL_DIR@ + +# 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) + +# Path to the private tk header dir: +PRIVATE_INCLUDE_DIR = @PRIVATE_INCLUDE_DIR@ + +# Directory in which to (optionally) install the private tk headers: +PRIVATE_INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(PRIVATE_INCLUDE_DIR) + +# Top-level directory in which to install manual entries: +MAN_INSTALL_DIR = $(INSTALL_ROOT)$(mandir) + +# 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 +# Tcl commands implemented by Tk: +MANN_INSTALL_DIR = $(MAN_INSTALL_DIR)/mann + +# Path to the html documentation dir: +HTML_DIR = @HTML_DIR@ + +# Directory in which to install html documentation: +HTML_INSTALL_DIR = $(INSTALL_ROOT)$(HTML_DIR) + +# Directory in which to install the configuration file tkConfig.sh: +CONFIG_INSTALL_DIR = $(INSTALL_ROOT)$(libdir) + +# Directory in which to install the demo files: +DEMO_INSTALL_DIR = $(INSTALL_ROOT)$(TK_LIBRARY)/demos + +# 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 + +# The directory containing the platform specific Tcl sources and headers +# appropriate for this version of Tk: +TCL_PLATFORM_DIR = @TCL_SRC_DIR@/unix + +# The directory containing the Tcl library archive file appropriate +# for this version of Tk: +TCL_BIN_DIR = @TCL_BIN_DIR@ + +# The linker flags needed to link in the Tcl library (ex: -ltcl8.2) +TCL_LIB_FLAG = @TCL_LIB_FLAG@ + +# Flag, 1: we're building a shared lib, 0 we're not +TK_SHARED_BUILD = @TK_SHARED_BUILD@ + +# Subdirectory of $(libdir) containing the pkgIndex.tcl file for loadable Tk +TK_PKG_DIR = @TK_PKG_DIR@ + +# Directory in which to install the pkgIndex.tcl file for loadable Tk +PKG_INSTALL_DIR = $(LIB_INSTALL_DIR)/$(TK_PKG_DIR) + +# Package index file for loadable Tk +PKG_INDEX = $(PKG_INSTALL_DIR)/pkgIndex.tcl + +# warning flags +CFLAGS_WARNING = @CFLAGS_WARNING@ + +# The default switches for optimization or debugging +CFLAGS_DEBUG = @CFLAGS_DEBUG@ +CFLAGS_OPTIMIZE = @CFLAGS_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_DEFAULT@ @CFLAGS@ + +# Flags to pass to the linker +LDFLAGS_DEBUG = @LDFLAGS_DEBUG@ +LDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@ +LDFLAGS = @LDFLAGS_DEFAULT@ @LDFLAGS@ + +# A "-I" switch that can be used when compiling to make all of the +# X11 include files accessible (the configure script will try to +# set this value, and will cause it to be an empty string if the +# include files are accessible via /usr/include). +X11_INCLUDES = @XINCLUDES@ + +AQUA_INCLUDES = -I$(MAC_OSX_DIR) -I$(XLIB_DIR) + +# Linker switch(es) to use to link with the X11 library archive (the +# configure script will try to set this value automatically, but you +# can override it). +X11_LIB_SWITCHES = $(XFT_LIBS) @XLIBSW@ + + +# To turn off the security checks that disallow incoming sends when +# the X server appears to be insecure, reverse the comments on the +# following lines: +SECURITY_FLAGS = +#SECURITY_FLAGS = -DTK_NO_SECURITY + +# To disable ANSI-C procedure prototypes reverse the comment characters +# on the following lines: +PROTO_FLAGS = +#PROTO_FLAGS = -DNO_PROTOTYPE + +# To enable memory debugging reverse the comment characters on the following +# lines or call configure with --enable-symbols=mem +# Warning: if you enable memory debugging, you must do it *everywhere*, +# including all the code that calls Tcl, and you must use ckalloc and +# ckfree everywhere instead of malloc and free. +MEM_DEBUG_FLAGS = +#MEM_DEBUG_FLAGS = -DTCL_MEM_DEBUG + +# If your X server is X11R4 or earlier, then you may wish to reverse +# the comment characters on the following two lines. This will enable +# extra code to speed up XStringToKeysym. In X11R5 and later releases +# XStringToKeysym is plenty fast, so you needn't define REDO_KEYSYM_LOOKUP. +KEYSYM_FLAGS = +#KEYSYM_FLAGS = -DREDO_KEYSYM_LOOKUP + +# Tk does not used deprecated Tcl constructs so it should +# compile fine with -DTCL_NO_DEPRECATED. To remove its own +# set of deprecated code uncomment the second line. +NO_DEPRECATED_FLAGS = +#NO_DEPRECATED_FLAGS = -DTK_NO_DEPRECATED + +# Some versions of make, like SGI's, use the following variable to +# determine which shell to use for executing commands: +SHELL = @SHELL@ + +# BUILD_TCLSH is the fully qualified path name of the tclsh shell +# in the Tcl build directory. Test that need to be run in the +# version of tclsh that we are building against should use this +# path. Targets that need an installed tclsh should not depend +# on this variable. + +BUILD_TCLSH = @BUILD_TCLSH@ + +# TCL_EXE is the name of a tclsh executable that is available *BEFORE* +# running make for the first time. Certain build targets (make genstubs) +# need it to be available on the PATH. This executable should *NOT* be +# required just to do a normal build although it can be required to run +# make dist. This variable is set to "" if no tclsh is available. +EXE_SUFFIX = @EXEEXT@ +TCL_EXE = @TCLSH_PROG@ +WISH_EXE = wish${EXE_SUFFIX} +TKTEST_EXE = tktest${EXE_SUFFIX} + +# 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_STRIP_PROGRAM = -s +INSTALL_STRIP_LIBRARY = -S -x + +INSTALL = $(SHELL) $(UNIX_DIR)/install-sh -c +INSTALL_PROGRAM = ${INSTALL} +INSTALL_LIBRARY = ${INSTALL} +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_DATA_DIR = ${INSTALL} -d -m 755 + +# The symbol below provides support for dynamic loading and shared +# libraries. See configure.in for a description of what it means. +# The value of the symbol is normally set by the configure script. + +SHLIB_CFLAGS = @SHLIB_CFLAGS@ -DBUILD_tk + +# To enable support for stubs in Tcl. +STUB_LIB_FILE = @TK_STUB_LIB_FILE@ + +TK_STUB_LIB_FILE = @TK_STUB_LIB_FILE@ +#TK_STUB_LIB_FILE = libtkstub.a + +# Generic stub lib name used in rules that apply to tcl and tk +STUB_LIB_FILE = ${TK_STUB_LIB_FILE} + +TK_STUB_LIB_FLAG = @TK_STUB_LIB_FLAG@ +#TK_STUB_LIB_FLAG = -ltkstub + +TK_LIB_FILE = @TK_LIB_FILE@ +#TK_LIB_FILE = libtk.a + +# Generic lib name used in rules that apply to tcl and tk +LIB_FILE = ${TK_LIB_FILE} + +TK_LIB_FLAG = @TK_LIB_FLAG@ +#TK_LIB_FLAG = -ltk + +TCL_LIB_SPEC = @TCL_LIB_SPEC@ +TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ +TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ +TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ + +TCL_STUB_FLAGS = @TCL_STUB_FLAGS@ + +# Libraries to use when linking. This definition is determined by the +# configure script. +LIBS = @LIBS@ $(X11_LIB_SWITCHES) @TCL_LIBS@ +WISH_LIBS = $(TCL_LIB_SPEC) @LIBS@ $(X11_LIB_SWITCHES) @TCL_LIBS@ @EXTRA_WISH_LIBS@ + +# The symbols below provide support for dynamic loading and shared +# libraries. See configure.in for a description of what the +# symbols mean. The values of the symbols are normally set by the +# configure script. You shouldn't normally need to modify any of +# these definitions by hand. + +STLIB_LD = @STLIB_LD@ +SHLIB_LD = @SHLIB_LD@ +SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ +TK_SHLIB_LD_EXTRAS = @TK_SHLIB_LD_EXTRAS@ + +# Additional search flags needed to find the various shared libraries +# at run-time. The first symbol is for use when creating a binary +# with cc, and the second is for use when running ld directly. +CC_SEARCH_FLAGS = @CC_SEARCH_FLAGS@ +LD_SEARCH_FLAGS = @LD_SEARCH_FLAGS@ + +# support for embedded libraries on Darwin / Mac OS X +DYLIB_INSTALL_DIR = ${LIB_RUNTIME_DIR} + +# support for building the Aqua resource file +TK_RSRC_FILE = @TK_RSRC_FILE@ +WISH_RSRC_FILE = @WISH_RSRC_FILE@ +REZ = @REZ@ +REZ_SWITCHES = @REZ_FLAGS@ -i $(GENERIC_DIR) -i $(TCL_GENERIC_DIR) + +# support for Xft: +XFT_CFLAGS = @XFT_CFLAGS@ +XFT_LIBS = @XFT_LIBS@ + +#---------------------------------------------------------------- +# The information below is modified by the configure script when +# Makefile is generated from Makefile.in. You shouldn't normally +# modify any of this stuff by hand. +#---------------------------------------------------------------- + +AC_FLAGS = @DEFS@ +AR = @AR@ +RANLIB = @RANLIB@ +SRC_DIR = @srcdir@ +TOP_DIR = $(SRC_DIR)/.. +GENERIC_DIR = $(TOP_DIR)/generic +TTK_DIR = $(GENERIC_DIR)/ttk +UNIX_DIR = $(TOP_DIR)/unix +BMAP_DIR = $(TOP_DIR)/bitmaps +TOOL_DIR = @TCL_SRC_DIR@/tools +TEST_DIR = $(TOP_DIR)/tests +MAC_OSX_DIR = $(TOP_DIR)/macosx +XLIB_DIR = $(TOP_DIR)/xlib + +#---------------------------------------------------------------- +# The information below should be usable as is. The configure +# script won't modify it and you shouldn't need to modify it +# either. +#---------------------------------------------------------------- + +# Flags to be passed to installManPage to control how the manpages +# should be installed (symlinks, compression, package name suffix). +MAN_FLAGS = @MAN_FLAGS@ + +CC = @CC@ + +CC_SWITCHES_NO_STUBS = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \ +-I${UNIX_DIR} -I${GENERIC_DIR} -I${BMAP_DIR} -I${TCL_GENERIC_DIR} \ +-I${TCL_PLATFORM_DIR} ${@TK_WINDOWINGSYSTEM@_INCLUDES} ${AC_FLAGS} \ +${PROTO_FLAGS} ${SECURITY_FLAGS} ${MEM_DEBUG_FLAGS} ${KEYSYM_FLAGS} \ +${NO_DEPRECATED_FLAGS} @EXTRA_CC_SWITCHES@ + +CC_SWITCHES = $(CC_SWITCHES_NO_STUBS) @TCL_STUB_FLAGS@ + +APP_CC_SWITCHES = $(CC_SWITCHES_NO_STUBS) @EXTRA_APP_CC_SWITCHES@ + +DEPEND_SWITCHES = ${CFLAGS} -I${UNIX_DIR} -I${GENERIC_DIR} -I${BMAP_DIR} \ +-I${TCL_GENERIC_DIR} -I${TCL_PLATFORM_DIR} ${@TK_WINDOWINGSYSTEM@_INCLUDES} \ +${AC_FLAGS} ${PROTO_FLAGS} ${SECURITY_FLAGS} ${MEM_DEBUG_FLAGS} \ +${KEYSYM_FLAGS} @EXTRA_CC_SWITCHES@ + +WISH_OBJS = tkAppInit.o + +TKTEST_OBJS = tkTestInit.o tkTest.o tkSquare.o tkOldTest.o \ + $(@TK_WINDOWINGSYSTEM@_TKTEST_OBJS) + +WIDG_OBJS = tkButton.o tkEntry.o tkFrame.o tkListbox.o \ + tkMenu.o tkMenubutton.o tkMenuDraw.o tkMessage.o \ + tkPanedWindow.o tkScale.o tkScrollbar.o + +CANV_OBJS = tkCanvas.o tkCanvArc.o tkCanvBmap.o tkCanvImg.o \ + tkCanvLine.o tkCanvPoly.o tkCanvPs.o tkCanvText.o \ + tkCanvUtil.o tkCanvWind.o tkRectOval.o tkTrig.o + +IMAGE_OBJS = tkImage.o tkImgBmap.o tkImgGIF.o tkImgPNG.o tkImgPPM.o \ + tkImgPhoto.o tkImgPhInstance.o + +TEXT_OBJS = tkText.o tkTextBTree.o tkTextDisp.o tkTextImage.o tkTextIndex.o \ + tkTextMark.o tkTextTag.o tkTextWind.o + +# either tkUnixFont.o (default) or tkUnixRFont.o (if --enable-xft) +# +FONT_OBJS = @UNIX_FONT_OBJS@ + +GENERIC_OBJS = tk3d.o tkArgv.o tkAtom.o tkBind.o tkBitmap.o tkBusy.o \ + tkClipboard.o \ + tkCmds.o tkColor.o tkConfig.o tkConsole.o tkCursor.o tkError.o \ + tkEvent.o tkFocus.o tkFont.o tkGet.o tkGC.o tkGeometry.o tkGrab.o \ + tkGrid.o tkMain.o tkObj.o tkOldConfig.o tkOption.o tkPack.o tkPlace.o \ + tkSelect.o tkStyle.o tkUndo.o tkUtil.o tkVisual.o tkWindow.o + +TTK_OBJS = \ + ttkBlink.o ttkButton.o ttkCache.o ttkClamTheme.o ttkClassicTheme.o \ + ttkDefaultTheme.o ttkElements.o ttkEntry.o ttkFrame.o ttkImage.o \ + ttkInit.o ttkLabel.o ttkLayout.o ttkManager.o ttkNotebook.o \ + ttkPanedwindow.o ttkProgress.o ttkScale.o ttkScrollbar.o ttkScroll.o \ + ttkSeparator.o ttkSquare.o ttkState.o \ + ttkTagSet.o ttkTheme.o ttkTrace.o ttkTrack.o ttkTreeview.o \ + ttkWidget.o ttkStubInit.o + +STUB_OBJS = tkStubInit.o + +STUB_LIB_OBJS = tkStubLib.o ttkStubLib.o + +X11_OBJS = tkUnix.o tkUnix3d.o tkUnixButton.o tkUnixColor.o tkUnixConfig.o \ + tkUnixCursor.o tkUnixDraw.o tkUnixEmbed.o tkUnixEvent.o \ + tkUnixFocus.o $(FONT_OBJS) tkUnixInit.o tkUnixKey.o tkUnixMenu.o \ + tkUnixMenubu.o tkUnixScale.o tkUnixScrlbr.o tkUnixSelect.o \ + tkUnixSend.o tkUnixWm.o tkUnixXId.o + +AQUA_OBJS = tkMacOSXBitmap.o tkMacOSXButton.o tkMacOSXClipboard.o \ + tkMacOSXColor.o tkMacOSXConfig.o tkMacOSXCursor.o tkMacOSXDebug.o \ + tkMacOSXDialog.o tkMacOSXDraw.o tkMacOSXEmbed.o tkMacOSXEntry.o \ + tkMacOSXEvent.o tkMacOSXFont.o tkMacOSXHLEvents.o tkMacOSXImage.o \ + tkMacOSXInit.o tkMacOSXKeyboard.o tkMacOSXKeyEvent.o tkMacOSXMenu.o \ + tkMacOSXMenubutton.o tkMacOSXMenus.o tkMacOSXMouseEvent.o \ + tkMacOSXNotify.o tkMacOSXRegion.o tkMacOSXScrlbr.o tkMacOSXSend.o \ + tkMacOSXSubwindows.o tkMacOSXWindowEvent.o \ + tkMacOSXWm.o tkMacOSXXStubs.o \ + tkFileFilter.o tkMacWinMenu.o tkPointer.o tkUnix3d.o tkUnixScale.o \ + xcolors.o xdraw.o xgc.o ximage.o xutil.o \ + ttkMacOSXTheme.o + +AQUA_TKTEST_OBJS = tkMacOSXTest.o + +OBJS = $(GENERIC_OBJS) $(WIDG_OBJS) $(CANV_OBJS) $(IMAGE_OBJS) $(TEXT_OBJS) \ + $(STUB_OBJS) $(TTK_OBJS) \ + $(@TK_WINDOWINGSYSTEM@_OBJS) @PLAT_OBJS@ + +TK_DECLS = \ + $(GENERIC_DIR)/tk.decls \ + $(GENERIC_DIR)/tkInt.decls + +TTK_DECLS = \ + $(TTK_DIR)/ttk.decls + +GENERIC_SRCS = \ + $(GENERIC_DIR)/tk3d.c $(GENERIC_DIR)/tkArgv.c \ + $(GENERIC_DIR)/tkAtom.c $(GENERIC_DIR)/tkBind.c \ + $(GENERIC_DIR)/tkBitmap.c $(GENERIC_DIR)/tkBusy.c \ + $(GENERIC_DIR)/tkClipboard.c \ + $(GENERIC_DIR)/tkCmds.c $(GENERIC_DIR)/tkColor.c \ + $(GENERIC_DIR)/tkConfig.c $(GENERIC_DIR)/tkCursor.c \ + $(GENERIC_DIR)/tkError.c $(GENERIC_DIR)/tkEvent.c \ + $(GENERIC_DIR)/tkFocus.c $(GENERIC_DIR)/tkFont.c \ + $(GENERIC_DIR)/tkGet.c $(GENERIC_DIR)/tkGC.c \ + $(GENERIC_DIR)/tkGeometry.c $(GENERIC_DIR)/tkGrab.c \ + $(GENERIC_DIR)/tkGrid.c $(GENERIC_DIR)/tkConsole.c \ + $(GENERIC_DIR)/tkMain.c $(GENERIC_DIR)/tkOption.c \ + $(GENERIC_DIR)/tkPack.c $(GENERIC_DIR)/tkPlace.c \ + $(GENERIC_DIR)/tkSelect.c $(GENERIC_DIR)/tkStyle.c \ + $(GENERIC_DIR)/tkUndo.c $(GENERIC_DIR)/tkUtil.c \ + $(GENERIC_DIR)/tkVisual.c $(GENERIC_DIR)/tkWindow.c \ + $(GENERIC_DIR)/tkButton.c $(GENERIC_DIR)/tkObj.c \ + $(GENERIC_DIR)/tkEntry.c $(GENERIC_DIR)/tkFrame.c \ + $(GENERIC_DIR)/tkListbox.c $(GENERIC_DIR)/tkMenu.c \ + $(GENERIC_DIR)/tkMenubutton.c $(GENERIC_DIR)/tkMenuDraw.c \ + $(GENERIC_DIR)/tkMessage.c $(GENERIC_DIR)/tkPanedWindow.c \ + $(GENERIC_DIR)/tkScale.c $(GENERIC_DIR)/tkScrollbar.c \ + $(GENERIC_DIR)/tkCanvas.c $(GENERIC_DIR)/tkCanvArc.c \ + $(GENERIC_DIR)/tkCanvBmap.c $(GENERIC_DIR)/tkCanvImg.c \ + $(GENERIC_DIR)/tkCanvLine.c $(GENERIC_DIR)/tkCanvPoly.c \ + $(GENERIC_DIR)/tkCanvPs.c $(GENERIC_DIR)/tkCanvText.c \ + $(GENERIC_DIR)/tkCanvUtil.c \ + $(GENERIC_DIR)/tkCanvWind.c $(GENERIC_DIR)/tkRectOval.c \ + $(GENERIC_DIR)/tkTrig.c $(GENERIC_DIR)/tkImage.c \ + $(GENERIC_DIR)/tkImgBmap.c $(GENERIC_DIR)/tkImgGIF.c \ + $(GENERIC_DIR)/tkImgPNG.c $(GENERIC_DIR)/tkImgPPM.c \ + $(GENERIC_DIR)/tkImgPhoto.c $(GENERIC_DIR)/tkImgPhInstance.c \ + $(GENERIC_DIR)/tkText.c \ + $(GENERIC_DIR)/tkTextBTree.c $(GENERIC_DIR)/tkTextDisp.c \ + $(GENERIC_DIR)/tkTextImage.c \ + $(GENERIC_DIR)/tkTextIndex.c $(GENERIC_DIR)/tkTextMark.c \ + $(GENERIC_DIR)/tkTextTag.c $(GENERIC_DIR)/tkTextWind.c \ + $(GENERIC_DIR)/tkOldConfig.c $(GENERIC_DIR)/tkOldTest.c \ + $(GENERIC_DIR)/tkSquare.c $(GENERIC_DIR)/tkTest.c \ + $(GENERIC_DIR)/tkStubInit.c + +TTK_SRCS = \ + $(TTK_DIR)/ttkBlink.c \ + $(TTK_DIR)/ttkButton.c \ + $(TTK_DIR)/ttkCache.c \ + $(TTK_DIR)/ttkClamTheme.c \ + $(TTK_DIR)/ttkClassicTheme.c \ + $(TTK_DIR)/ttkDefaultTheme.c \ + $(TTK_DIR)/ttkElements.c \ + $(TTK_DIR)/ttkEntry.c \ + $(TTK_DIR)/ttkFrame.c \ + $(TTK_DIR)/ttkImage.c \ + $(TTK_DIR)/ttkInit.c \ + $(TTK_DIR)/ttkLabel.c \ + $(TTK_DIR)/ttkLayout.c \ + $(TTK_DIR)/ttkManager.c \ + $(TTK_DIR)/ttkNotebook.c \ + $(TTK_DIR)/ttkPanedwindow.c \ + $(TTK_DIR)/ttkProgress.c \ + $(TTK_DIR)/ttkScale.c \ + $(TTK_DIR)/ttkScrollbar.c \ + $(TTK_DIR)/ttkScroll.c \ + $(TTK_DIR)/ttkSeparator.c \ + $(TTK_DIR)/ttkSquare.c \ + $(TTK_DIR)/ttkState.c \ + $(TTK_DIR)/ttkTagSet.c \ + $(TTK_DIR)/ttkTheme.c \ + $(TTK_DIR)/ttkTrace.c \ + $(TTK_DIR)/ttkTrack.c \ + $(TTK_DIR)/ttkTreeview.c \ + $(TTK_DIR)/ttkWidget.c + +TTK_STUB_SRCS = \ + $(TTK_DIR)/ttkStubInit.c $(TTK_DIR)/ttkStubLib.c + +X11_SRCS = \ + $(UNIX_DIR)/tkAppInit.c $(UNIX_DIR)/tkUnix.c \ + $(UNIX_DIR)/tkUnix3d.c \ + $(UNIX_DIR)/tkUnixButton.c $(UNIX_DIR)/tkUnixColor.c \ + $(UNIX_DIR)/tkUnixConfig.c \ + $(UNIX_DIR)/tkUnixCursor.c \ + $(UNIX_DIR)/tkUnixDraw.c \ + $(UNIX_DIR)/tkUnixEmbed.c $(UNIX_DIR)/tkUnixEvent.c \ + $(UNIX_DIR)/tkUnixFocus.c \ + $(UNIX_DIR)/tkUnixRFont.c \ + $(UNIX_DIR)/tkUnixFont.c $(UNIX_DIR)/tkUnixInit.c \ + $(UNIX_DIR)/tkUnixKey.c \ + $(UNIX_DIR)/tkUnixMenu.c $(UNIX_DIR)/tkUnixMenubu.c \ + $(UNIX_DIR)/tkUnixScale.c $(UNIX_DIR)/tkUnixScrlbr.c \ + $(UNIX_DIR)/tkUnixSelect.c \ + $(UNIX_DIR)/tkUnixSend.c $(UNIX_DIR)/tkUnixWm.c \ + $(UNIX_DIR)/tkUnixXId.c + +AQUA_SRCS = \ + $(MAC_OSX_DIR)/tkMacOSXBitmap.c $(MAC_OSX_DIR)/tkMacOSXButton.c \ + $(MAC_OSX_DIR)/tkMacOSXClipboard.c $(MAC_OSX_DIR)/tkMacOSXColor.c \ + $(MAC_OSX_DIR)/tkMacOSXConfig.c $(MAC_OSX_DIR)/tkMacOSXCursor.c \ + $(MAC_OSX_DIR)/tkMacOSXDebug.c $(MAC_OSX_DIR)/tkMacOSXDialog.c \ + $(MAC_OSX_DIR)/tkMacOSXDraw.c $(MAC_OSX_DIR)/tkMacOSXEmbed.c \ + $(MAC_OSX_DIR)/tkMacOSXEntry.c $(MAC_OSX_DIR)/tkMacOSXEvent.c \ + $(MAC_OSX_DIR)/tkMacOSXFont.c $(MAC_OSX_DIR)/tkMacOSXHLEvents.c \ + $(MAC_OSX_DIR)/tkMacOSXImage.c \ + $(MAC_OSX_DIR)/tkMacOSXInit.c $(MAC_OSX_DIR)/tkMacOSXKeyboard.c \ + $(MAC_OSX_DIR)/tkMacOSXKeyEvent.c $(MAC_OSX_DIR)/tkMacOSXMenu.c \ + $(MAC_OSX_DIR)/tkMacOSXMenubutton.c $(MAC_OSX_DIR)/tkMacOSXMenus.c \ + $(MAC_OSX_DIR)/tkMacOSXMouseEvent.c $(MAC_OSX_DIR)/tkMacOSXNotify.c \ + $(MAC_OSX_DIR)/tkMacOSXRegion.c $(MAC_OSX_DIR)/tkMacOSXScrlbr.c \ + $(MAC_OSX_DIR)/tkMacOSXSend.c $(MAC_OSX_DIR)/tkMacOSXSubwindows.c \ + $(MAC_OSX_DIR)/tkMacOSXTest.c $(MAC_OSX_DIR)/tkMacOSXWindowEvent.c \ + $(MAC_OSX_DIR)/tkMacOSXWm.c $(MAC_OSX_DIR)/tkMacOSXXStubs.c \ + $(GENERIC_DIR)/tkFileFilter.c $(GENERIC_DIR)/tkMacWinMenu.c \ + $(GENERIC_DIR)/tkPointer.c $(UNIX_DIR)/tkUnix3d.c \ + $(UNIX_DIR)/tkUnixScale.c $(XLIB_DIR)/xcolors.c $(XLIB_DIR)/xdraw.c \ + $(XLIB_DIR)/xgc.c $(XLIB_DIR)/ximage.c $(XLIB_DIR)/xutil.c \ + $(TTK_DIR)/ttkMacOSXTheme.c + +SRCS = $(GENERIC_SRCS) $(@TK_WINDOWINGSYSTEM@_SRCS) @PLAT_SRCS@ + +AQUA_RESOURCES = \ + $(MAC_OSX_DIR)/tkAboutDlg.r $(MAC_OSX_DIR)/tkMacOSXCursors.r \ + $(MAC_OSX_DIR)/tkMacOSXXCursors.r + +AQUA_WISH_RESOURCES = $(MAC_OSX_DIR)/tkMacOSXAETE.r + +AQUA_HDRS = $(MAC_OSX_DIR)/tkMacOSX.h $(GENERIC_DIR)/tkIntXlibDecls.h + +AQUA_XLIB_HDRS = $(XLIB_DIR)/X11/*.h $(XLIB_DIR)/xbytes.h + +AQUA_PRIVATE_HDRS = $(MAC_OSX_DIR)/tkMacOSXPort.h $(MAC_OSX_DIR)/tkMacOSXInt.h + +X11_PRIVATE_HDRS = $(UNIX_DIR)/tkUnixPort.h $(UNIX_DIR)/tkUnixInt.h $(GENERIC_DIR)/tkIntXlibDecls.h + +# Currently private, eventually public +TTK_HDRS = $(TTK_DIR)/ttkTheme.h $(TTK_DIR)/ttkDecls.h + +PUBLIC_HDRS = $(GENERIC_DIR)/tk.h $(GENERIC_DIR)/tkDecls.h \ + $(GENERIC_DIR)/tkPlatDecls.h $(@TK_WINDOWINGSYSTEM@_HDRS) + +# The private headers we want installed for install-private-headers +PRIVATE_HDRS = $(GENERIC_DIR)/tkInt.h $(GENERIC_DIR)/tkIntDecls.h \ + $(GENERIC_DIR)/tkIntPlatDecls.h $(GENERIC_DIR)/tkPort.h \ + $(TTK_HDRS) $(@TK_WINDOWINGSYSTEM@_PRIVATE_HDRS) + +DEMOPROGS = browse hello ixset rmt rolodex square tcolor timer widget + +SHELL_ENV = \ + @LD_LIBRARY_PATH_VAR@="`pwd`:${TCL_BIN_DIR}:$${@LD_LIBRARY_PATH_VAR@}"; \ + export @LD_LIBRARY_PATH_VAR@; \ + TCL_LIBRARY=@TCL_SRC_DIR@/library; export TCL_LIBRARY; \ + TK_LIBRARY=@TK_SRC_DIR@/library; export TK_LIBRARY; + +all: binaries libraries doc + +binaries: ${LIB_FILE} ${WISH_EXE} + +libraries: + +$(TOP_DIR)/doc/man.macros: + $(INSTALL_DATA) @TCL_SRC_DIR@/doc/man.macros $(TOP_DIR)/doc/man.macros + +doc: $(TOP_DIR)/doc/man.macros + +# The following target is configured by autoconf to generate either +# a shared library or non-shared library for Tk. +${LIB_FILE}: ${STUB_LIB_FILE} @LIB_RSRC_FILE@ ${OBJS} + rm -f $@ + @MAKE_LIB@ + +${STUB_LIB_FILE}: ${STUB_LIB_OBJS} + @if test "x${LIB_FILE}" = "xlibtk${MAJOR_VERSION}.${MINOR_VERSION}.dll"; then \ + (cd ${TOP_DIR}/win; ${MAKE} tk${MAJOR_VERSION}${MINOR_VERSION}.dll); \ + cp "${TOP_DIR}/win/tk${MAJOR_VERSION}${MINOR_VERSION}.dll" .; \ + fi + rm -f $@ + @MAKE_STUB_LIB@ + +# Build Aqua resource files +${TK_RSRC_FILE}: $(AQUA_RESOURCES) + rm -f $@ + if test "$(REZ)" != ""; then \ + $(REZ) -o $@ $(REZ_SWITCHES) $(AQUA_RESOURCES); fi + +${WISH_RSRC_FILE}: $(AQUA_WISH_RESOURCES) + rm -f $@ + if test "$(REZ)" != ""; then \ + $(REZ) -o $@ $(REZ_SWITCHES) $(AQUA_WISH_RESOURCES); fi + +# Make target which outputs the list of the .o contained in the Tk lib +# usefull to build a single big shared library containing Tcl/Tk and other +# extensions. used for the Tcl Plugin. -- dl +tkLibObjs: + @echo ${OBJS} +# This targets actually build the objects needed for the lib in the above +# case +objs: ${OBJS} + + +${WISH_EXE}: $(TK_STUB_LIB_FILE) $(WISH_OBJS) $(TK_LIB_FILE) @APP_RSRC_FILE@ + ${CC} ${CFLAGS} ${LDFLAGS} $(WISH_OBJS) @TK_BUILD_LIB_SPEC@ \ + $(WISH_LIBS) $(CC_SEARCH_FLAGS) -o ${WISH_EXE} + +# Resetting the LIB_RUNTIME_DIR below is required so that +# the generated tktest executable gets the build directory +# burned into its ld search path. This keeps tktest from +# picking up an already installed version of the Tcl or +# Tk shared libraries. + +$(TKTEST_EXE): $(TKTEST_OBJS) $(TK_LIB_FILE) + $(MAKE) tktest-real LIB_RUNTIME_DIR="`pwd`:$(TCL_BIN_DIR)" + +tktest-real: ${TK_STUB_LIB_FILE} + ${CC} ${CFLAGS} ${LDFLAGS} $(TKTEST_OBJS) ${TK_STUB_LIB_FILE} ${TCL_STUB_LIB_SPEC} @TK_BUILD_LIB_SPEC@ \ + $(WISH_LIBS) $(CC_SEARCH_FLAGS) -o $(TKTEST_EXE) + +# # FIXME: This xttest rule seems to be broken in a number of ways. It should +# # use CC_SEARCH_FLAGS, it does not include the shared lib location logic from +# # tktest, and it is not clear where this test.o object file comes from. +# +# xttest: test.o tkTest.o tkSquare.o $(TK_LIB_FILE) ${TK_STUB_LIB_FILE} +# ${CC} ${CFLAGS} ${LDFLAGS} test.o tkTest.o tkSquare.o \ +# @TK_BUILD_LIB_SPEC@ ${TK_STUB_LIB_FILE} ${TCL_STUB_LIB_SPEC} \ +# $(WISH_LIBS) $(LD_SEARCH_FLAGS) -lXt -o xttest + +# Note, in the target below TCL_LIBRARY needs to be set or else +# "make test" won't work in the case where the compilation directory +# isn't the same as the source directory. +# Specifying TESTFLAGS on the command line is the standard way to pass +# args to tcltest, ie: +# % make test TESTFLAGS="-verbose bps -file fileName.test" + +test: test-classic test-ttk + +test-classic: $(TKTEST_EXE) + $(SHELL_ENV) ./$(TKTEST_EXE) $(TEST_DIR)/all.tcl -geometry +0+0 $(TESTFLAGS) + +test-ttk: $(TKTEST_EXE) + $(SHELL_ENV) ./$(TKTEST_EXE) $(TEST_DIR)/ttk/all.tcl -geometry +0+0 \ + $(TESTFLAGS) + +# Tests with different languages +testlang: $(TKTEST_EXE) + $(SHELL_ENV) \ + for lang in $(LOCALES) ; \ + do \ + LANG=$(lang); export LANG; \ + ./$(TKTEST_EXE) $(TEST_DIR)/all.tcl -geometry +0+0 \ + $(TESTFLAGS); \ + done + +# Useful target to launch a built tktest with the proper path,... +runtest: $(TKTEST_EXE) + $(SHELL_ENV) ./$(TKTEST_EXE) + +# This target can be used to run wish from the build directory +# via `make shell` or `make shell SCRIPT=/tmp/foo.tcl` +shell: ${WISH_EXE} + $(SHELL_ENV) ./${WISH_EXE} $(SCRIPT) + +demo: + $(SHELL_ENV) ./${WISH_EXE} $(TOP_DIR)/library/demos/widget + +# This target can be used to run wish inside either gdb or insight +gdb: ${WISH_EXE} + @echo "set env @LD_LIBRARY_PATH_VAR@=\"`pwd`:${TCL_BIN_DIR}:$${@LD_LIBRARY_PATH_VAR@}\"" > gdb.run + @echo "set env TCL_LIBRARY=@TCL_SRC_DIR@/library" >> gdb.run + @echo "set env TK_LIBRARY=@TK_SRC_DIR@/library" >> gdb.run + gdb ./${WISH_EXE} --command=gdb.run + rm gdb.run + +VALGRINDARGS=--tool=memcheck --num-callers=8 --leak-resolution=high --leak-check=yes --show-reachable=yes -v + +valgrind: $(TKTEST_EXE) + $(SHELL_ENV) valgrind $(VALGRINDARGS) ./$(TKTEST_EXE) $(TEST_DIR)/all.tcl -geometry +0+0 -singleproc 1 $(TESTFLAGS) + +valgrindshell: $(TKTEST_EXE) + $(SHELL_ENV) valgrind $(VALGRINDARGS) ./$(TKTEST_EXE) $(SCRIPT) + +INSTALL_BASE_TARGETS = install-binaries install-libraries +INSTALL_DOC_TARGETS = install-doc +INSTALL_DEV_TARGETS = install-headers +INSTALL_DEMO_TARGETS = install-demos +INSTALL_EXTRA_TARGETS = @EXTRA_INSTALL@ +INSTALL_TARGETS = $(INSTALL_BASE_TARGETS) $(INSTALL_DOC_TARGETS) $(INSTALL_DEV_TARGETS) \ + $(INSTALL_DEMO_TARGETS) $(INSTALL_EXTRA_TARGETS) + +install: $(INSTALL_TARGETS) + +install-strip: + $(MAKE) $(INSTALL_TARGETS) \ + INSTALL_PROGRAM="$(INSTALL_PROGRAM) ${INSTALL_STRIP_PROGRAM}" \ + INSTALL_LIBRARY="$(INSTALL_LIBRARY) ${INSTALL_STRIP_LIBRARY}" + +install-binaries: $(TK_STUB_LIB_FILE) $(TK_LIB_FILE) ${WISH_EXE} + @for i in "$(LIB_INSTALL_DIR)" "$(BIN_INSTALL_DIR)" \ + "$(PKG_INSTALL_DIR)" "$(CONFIG_INSTALL_DIR)" ; \ + do \ + if [ ! -d "$$i" ] ; then \ + echo "Making directory $$i"; \ + $(INSTALL_DATA_DIR) "$$i"; \ + else true; \ + fi; \ + done; + @if test "x$(TK_SHARED_BUILD)" = "x1"; then \ + echo "Creating package index $(PKG_INDEX)"; \ + rm -f "$(PKG_INDEX)"; \ + (\ + echo "if {[catch {package present Tcl 8.6.0}]} return";\ + relative=`echo | awk '{ORS=" "; split("$(TK_PKG_DIR)",a,"/"); for (f in a) {print ".."}}'`;\ + if test "x$(DLL_INSTALL_DIR)" != "x$(BIN_INSTALL_DIR)"; then \ + echo "package ifneeded Tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir $${relative}$(TK_LIB_FILE)]] Tk]";\ + else \ + echo "if {(\$$::tcl_platform(platform) eq \"unix\") && ([info exists ::env(DISPLAY)]";\ + echo " || ([info exists ::argv] && (\"-display\" in \$$::argv)))} {";\ + echo " package ifneeded Tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir $${relative}.. bin $(TK_LIB_FILE)]] Tk]";\ + echo "} else {";\ + echo " package ifneeded Tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir $${relative}.. bin tk${MAJOR_VERSION}${MINOR_VERSION}.dll]] Tk]";\ + echo "}";\ + fi \ + ) > "$(PKG_INDEX)"; \ + fi + @echo "Installing $(LIB_FILE) to $(DLL_INSTALL_DIR)/" + @@INSTALL_LIB@ + @chmod 555 "$(DLL_INSTALL_DIR)/$(LIB_FILE)" + @if test -f "tk${MAJOR_VERSION}${MINOR_VERSION}.dll"; then \ + $(INSTALL_LIBRARY) "tk${MAJOR_VERSION}${MINOR_VERSION}.dll" "$(DLL_INSTALL_DIR)";\ + chmod 555 "$(DLL_INSTALL_DIR)/tk${MAJOR_VERSION}${MINOR_VERSION}.dll";\ + $(INSTALL_LIBRARY) "../win/libtk${MAJOR_VERSION}${MINOR_VERSION}.a" "$(LIB_INSTALL_DIR)";\ + chmod 555 "$(LIB_INSTALL_DIR)/libtk${MAJOR_VERSION}${MINOR_VERSION}.a";\ + fi + @echo "Installing ${WISH_EXE} as $(BIN_INSTALL_DIR)/wish$(VERSION)${EXE_SUFFIX}" + @$(INSTALL_PROGRAM) ${WISH_EXE} "$(BIN_INSTALL_DIR)/wish$(VERSION)${EXE_SUFFIX}" + @echo "Installing tkConfig.sh to $(CONFIG_INSTALL_DIR)/" + @$(INSTALL_DATA) tkConfig.sh "$(CONFIG_INSTALL_DIR)/tkConfig.sh" + @if test "$(STUB_LIB_FILE)" != "" ; then \ + echo "Installing $(STUB_LIB_FILE) to $(LIB_INSTALL_DIR)/"; \ + @INSTALL_STUB_LIB@ ; \ + fi + @EXTRA_INSTALL_BINARIES@ + @echo "Installing pkg-config file to $(LIB_INSTALL_DIR)/pkgconfig/" + @$(INSTALL_DATA_DIR) $(LIB_INSTALL_DIR)/pkgconfig + @$(INSTALL_DATA) tk.pc $(LIB_INSTALL_DIR)/pkgconfig/tk.pc + +install-libraries: libraries + @for i in "$(SCRIPT_INSTALL_DIR)" "$(SCRIPT_INSTALL_DIR)/images" \ + "$(SCRIPT_INSTALL_DIR)/msgs" "$(SCRIPT_INSTALL_DIR)/ttk"; \ + do \ + if [ -n "$$i" -a ! -d "$$i" ] ; then \ + echo "Making directory $$i"; \ + $(INSTALL_DATA_DIR) "$$i"; \ + else true; \ + fi; \ + done; + @echo "Installing Tk library files to $(SCRIPT_INSTALL_DIR)/"; + @for i in $(TOP_DIR)/library/*.tcl $(TOP_DIR)/library/tclIndex \ + $(UNIX_DIR)/tkAppInit.c; \ + do \ + $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"; \ + done; + @echo "Installing Ttk library files to $(SCRIPT_INSTALL_DIR)/ttk/"; + @for i in $(TOP_DIR)/library/ttk/*.tcl; \ + do \ + if [ -f $$i ] ; then \ + $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/ttk"; \ + fi; \ + done; + @echo "Installing library image files to $(SCRIPT_INSTALL_DIR)/images/"; + @for i in $(TOP_DIR)/library/images/*; \ + do \ + if [ -f $$i ] ; then \ + $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/images"; \ + fi; \ + done; + @echo "Installing message catalog files to $(SCRIPT_INSTALL_DIR)/msgs/"; + @for i in $(TOP_DIR)/library/msgs/*.msg; \ + do \ + if [ -f $$i ] ; then \ + $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/msgs"; \ + fi; \ + done; + +install-demos: + @for i in "$(DEMO_INSTALL_DIR)" "$(DEMO_INSTALL_DIR)/images" ; \ + do \ + if [ ! -d "$$i" ] ; then \ + echo "Making directory $$i"; \ + $(INSTALL_DATA_DIR) "$$i"; \ + else true; \ + fi; \ + done; + @echo "Installing demo files to $(DEMO_INSTALL_DIR)/"; + @for i in $(TOP_DIR)/library/demos/*; \ + do \ + if [ -f $$i ] ; then \ + sed -e '3 s|exec wish|exec wish$(VERSION)|' \ + $$i > "$(DEMO_INSTALL_DIR)"/`basename $$i`; \ + fi; \ + done; + @for i in $(DEMOPROGS); \ + do \ + if test $$i = "square"; then \ + rm -f "$(DEMO_INSTALL_DIR)/$$i"; \ + else \ + chmod 755 "$(DEMO_INSTALL_DIR)/$$i"; \ + fi; \ + done; + @echo "Installing demo image files to $(DEMO_INSTALL_DIR)/images/"; + @for i in $(TOP_DIR)/library/demos/images/*; \ + do \ + if [ -f $$i ] ; then \ + $(INSTALL_DATA) $$i "$(DEMO_INSTALL_DIR)/images"; \ + fi; \ + done; + +install-doc: + @for i in "$(MAN_INSTALL_DIR)" "$(MAN1_INSTALL_DIR)" "$(MAN3_INSTALL_DIR)" "$(MANN_INSTALL_DIR)" ; \ + do \ + if [ ! -d "$$i" ] ; then \ + echo "Making directory $$i"; \ + $(INSTALL_DATA_DIR) "$$i"; \ + else true; \ + fi; \ + done; + @echo "Installing and cross-linking top-level (.1) docs to $(MAN1_INSTALL_DIR)/"; + @for i in $(TOP_DIR)/doc/*.1; do \ + $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MAN1_INSTALL_DIR)"; \ + done + @echo "Installing and cross-linking C API (.3) docs to $(MAN3_INSTALL_DIR)/"; + @for i in $(TOP_DIR)/doc/*.3; do \ + $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MAN3_INSTALL_DIR)"; \ + done + @echo "Installing and cross-linking command (.n) docs to $(MANN_INSTALL_DIR)/"; + @for i in $(TOP_DIR)/doc/*.n; do \ + $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MANN_INSTALL_DIR)"; \ + done + +install-headers: + @if test "$(@TK_WINDOWINGSYSTEM@_XLIB_HDRS)" != ""; then \ + XLIB_INCLUDE_INSTALL_DIR="$(INCLUDE_INSTALL_DIR)"/X11; fi; \ + for i in "$(INCLUDE_INSTALL_DIR)" "$${XLIB_INCLUDE_INSTALL_DIR}"; \ + do \ + if [ -n "$$i" -a ! -d "$$i" ] ; then \ + echo "Making directory $$i"; \ + $(INSTALL_DATA_DIR) "$$i"; \ + else true; \ + fi; \ + done; + @echo "Installing header files to $(INCLUDE_INSTALL_DIR)/"; + @for i in $(PUBLIC_HDRS); \ + do \ + $(INSTALL_DATA) $$i "$(INCLUDE_INSTALL_DIR)"; \ + done; + @list='$(@TK_WINDOWINGSYSTEM@_XLIB_HDRS)'; for i in $$list ; \ + do \ + $(INSTALL_DATA) $$i "$(INCLUDE_INSTALL_DIR)/X11"; \ + done; + +# Optional target to install private headers +install-private-headers: + @for i in "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \ + do \ + if [ ! -d "$$i" ] ; then \ + echo "Making directory $$i"; \ + $(INSTALL_DATA_DIR) "$$i"; \ + else true; \ + fi; \ + done; + @echo "Installing private header files to $(PRIVATE_INCLUDE_INSTALL_DIR)/"; + @for i in $(PRIVATE_HDRS); \ + do \ + $(INSTALL_DATA) $$i "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \ + done; + @if test -f tkConfig.h; then\ + $(INSTALL_DATA) tkConfig.h "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \ + fi; + +Makefile: $(UNIX_DIR)/Makefile.in + $(SHELL) config.status +#tkConfig.h: $(UNIX_DIR)/tkConfig.h.in +# $(SHELL) config.status + +clean: + rm -f *.a *.o libtk* core errs *~ \#* TAGS *.E a.out \ + errors ${WISH_EXE} $(TKTEST_EXE) lib.exp Tk *.rsrc + +distclean: clean + rm -rf Makefile config.status config.cache config.log tkConfig.sh \ + tkConfig.h *.plist Tk.framework tk.pc + +depend: + makedepend -- $(DEPEND_SWITCHES) -- $(SRCS) + +# Test binaries. The rule for tkTestInit.o is complicated because +# it is is compiled from tkAppInit.c. Can't use the "-o" option +# because this doesn't work on some strange compilers (e.g. UnixWare). +# To enable concurrent parallel make of wish and tktest, this target has to +# depend on wish, this ensures that linking of wish with tkTestInit.o does not +# execute concurrently with the renaming and recompiling of that same object +# file in the target below. + +tkTestInit.o: $(UNIX_DIR)/tkAppInit.c ${WISH_EXE} + @if test -f tkAppInit.o ; then \ + rm -f tkAppInit.sav; \ + mv tkAppInit.o tkAppInit.sav; \ + fi; + $(CC) -c $(APP_CC_SWITCHES) -DTK_TEST $(UNIX_DIR)/tkAppInit.c + rm -f tkTestInit.o + mv tkAppInit.o tkTestInit.o + @if test -f tkAppInit.sav ; then \ + mv tkAppInit.sav tkAppInit.o; \ + fi; + +tkAppInit.o: $(UNIX_DIR)/tkAppInit.c + $(CC) -c $(APP_CC_SWITCHES) $(UNIX_DIR)/tkAppInit.c + +tk3d.o: $(GENERIC_DIR)/tk3d.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tk3d.c + +tkArgv.o: $(GENERIC_DIR)/tkArgv.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkArgv.c + +tkAtom.o: $(GENERIC_DIR)/tkAtom.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkAtom.c + +tkBind.o: $(GENERIC_DIR)/tkBind.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkBind.c + +tkBitmap.o: $(GENERIC_DIR)/tkBitmap.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkBitmap.c + +tkBusy.o: $(GENERIC_DIR)/tkBusy.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkBusy.c + +tkClipboard.o: $(GENERIC_DIR)/tkClipboard.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkClipboard.c + +tkCmds.o: $(GENERIC_DIR)/tkCmds.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCmds.c + +tkColor.o: $(GENERIC_DIR)/tkColor.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkColor.c + +tkConfig.o: $(GENERIC_DIR)/tkConfig.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkConfig.c + +tkConsole.o: $(GENERIC_DIR)/tkConsole.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkConsole.c + +tkCursor.o: $(GENERIC_DIR)/tkCursor.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCursor.c + +tkError.o: $(GENERIC_DIR)/tkError.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkError.c + +tkEvent.o: $(GENERIC_DIR)/tkEvent.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkEvent.c + +tkFocus.o: $(GENERIC_DIR)/tkFocus.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkFocus.c + +tkFont.o: $(GENERIC_DIR)/tkFont.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkFont.c + +tkGet.o: $(GENERIC_DIR)/tkGet.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkGet.c + +tkGC.o: $(GENERIC_DIR)/tkGC.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkGC.c + +tkGeometry.o: $(GENERIC_DIR)/tkGeometry.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkGeometry.c + +tkGrab.o: $(GENERIC_DIR)/tkGrab.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkGrab.c + +tkGrid.o: $(GENERIC_DIR)/tkGrid.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkGrid.c + +tkMain.o: $(GENERIC_DIR)/tkMain.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMain.c + +tkObj.o: $(GENERIC_DIR)/tkObj.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkObj.c + +tkOldConfig.o: $(GENERIC_DIR)/tkOldConfig.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkOldConfig.c + +tkOption.o: $(GENERIC_DIR)/tkOption.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkOption.c + +tkPack.o: $(GENERIC_DIR)/tkPack.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkPack.c + +tkPlace.o: $(GENERIC_DIR)/tkPlace.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkPlace.c + +tkSelect.o: $(GENERIC_DIR)/tkSelect.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkSelect.c + +tkStyle.o: $(GENERIC_DIR)/tkStyle.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkStyle.c + +tkUtil.o: $(GENERIC_DIR)/tkUtil.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkUtil.c + +tkVisual.o: $(GENERIC_DIR)/tkVisual.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkVisual.c + +tkWindow.o: $(GENERIC_DIR)/tkWindow.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkWindow.c + +tkButton.o: $(GENERIC_DIR)/tkButton.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkButton.c + +tkEntry.o: $(GENERIC_DIR)/tkEntry.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkEntry.c + +tkFrame.o: $(GENERIC_DIR)/tkFrame.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkFrame.c + +tkListbox.o: $(GENERIC_DIR)/tkListbox.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkListbox.c + +tkMenu.o: $(GENERIC_DIR)/tkMenu.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMenu.c + +tkMenubutton.o: $(GENERIC_DIR)/tkMenubutton.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMenubutton.c + +tkMenuDraw.o: $(GENERIC_DIR)/tkMenuDraw.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMenuDraw.c + +tkMessage.o: $(GENERIC_DIR)/tkMessage.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMessage.c + +tkPanedWindow.o: $(GENERIC_DIR)/tkPanedWindow.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkPanedWindow.c + +tkScale.o: $(GENERIC_DIR)/tkScale.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkScale.c + +tkScrollbar.o: $(GENERIC_DIR)/tkScrollbar.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkScrollbar.c + +tkSquare.o: $(GENERIC_DIR)/tkSquare.c + $(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tkSquare.c + +tkCanvas.o: $(GENERIC_DIR)/tkCanvas.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvas.c + +tkCanvArc.o: $(GENERIC_DIR)/tkCanvArc.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvArc.c + +tkCanvBmap.o: $(GENERIC_DIR)/tkCanvBmap.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvBmap.c + +tkCanvImg.o: $(GENERIC_DIR)/tkCanvImg.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvImg.c + +tkCanvLine.o: $(GENERIC_DIR)/tkCanvLine.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvLine.c + +tkCanvPoly.o: $(GENERIC_DIR)/tkCanvPoly.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvPoly.c + +tkCanvPs.o: $(GENERIC_DIR)/tkCanvPs.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvPs.c + +tkCanvText.o: $(GENERIC_DIR)/tkCanvText.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvText.c + +tkCanvUtil.o: $(GENERIC_DIR)/tkCanvUtil.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvUtil.c + +tkCanvWind.o: $(GENERIC_DIR)/tkCanvWind.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkCanvWind.c + +tkRectOval.o: $(GENERIC_DIR)/tkRectOval.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkRectOval.c + +tkTrig.o: $(GENERIC_DIR)/tkTrig.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTrig.c + +tkImage.o: $(GENERIC_DIR)/tkImage.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImage.c + +tkImgBmap.o: $(GENERIC_DIR)/tkImgBmap.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgBmap.c + +tkImgGIF.o: $(GENERIC_DIR)/tkImgGIF.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgGIF.c + +tkImgPNG.o: $(GENERIC_DIR)/tkImgPNG.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgPNG.c + +tkImgPPM.o: $(GENERIC_DIR)/tkImgPPM.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgPPM.c + +tkImgPhoto.o: $(GENERIC_DIR)/tkImgPhoto.c $(GENERIC_DIR)/tkImgPhoto.h + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgPhoto.c + +tkImgPhInstance.o: $(GENERIC_DIR)/tkImgPhInstance.c $(GENERIC_DIR)/tkImgPhoto.h + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkImgPhInstance.c + +tkOldTest.o: $(GENERIC_DIR)/tkOldTest.c + $(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tkOldTest.c + +tkTest.o: $(GENERIC_DIR)/tkTest.c + $(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tkTest.c + +tkText.o: $(GENERIC_DIR)/tkText.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkText.c + +tkTextBTree.o: $(GENERIC_DIR)/tkTextBTree.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextBTree.c + +tkTextDisp.o: $(GENERIC_DIR)/tkTextDisp.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextDisp.c + +tkTextImage.o: $(GENERIC_DIR)/tkTextImage.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextImage.c + +tkTextIndex.o: $(GENERIC_DIR)/tkTextIndex.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextIndex.c + +tkTextMark.o: $(GENERIC_DIR)/tkTextMark.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextMark.c + +tkTextTag.o: $(GENERIC_DIR)/tkTextTag.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextTag.c + +tkTextWind.o: $(GENERIC_DIR)/tkTextWind.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkTextWind.c + +tkStubInit.o: $(GENERIC_DIR)/tkStubInit.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkStubInit.c + +# Stub library binaries, these must be compiled for use in a shared library +# even though they will be placed in a static archive + +tkStubLib.o: $(GENERIC_DIR)/tkStubLib.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkStubLib.c + +tkUndo.o: $(GENERIC_DIR)/tkUndo.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkUndo.c + +tkUnix.o: $(UNIX_DIR)/tkUnix.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnix.c + +tkUnix3d.o: $(UNIX_DIR)/tkUnix3d.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnix3d.c + +tkUnixButton.o: $(UNIX_DIR)/tkUnixButton.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixButton.c + +tkUnixColor.o: $(UNIX_DIR)/tkUnixColor.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixColor.c + +tkUnixConfig.o: $(UNIX_DIR)/tkUnixConfig.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixConfig.c + +tkUnixCursor.o: $(UNIX_DIR)/tkUnixCursor.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixCursor.c + +tkUnixDraw.o: $(UNIX_DIR)/tkUnixDraw.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixDraw.c + +tkUnixEmbed.o: $(UNIX_DIR)/tkUnixEmbed.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixEmbed.c + +tkUnixEvent.o: $(UNIX_DIR)/tkUnixEvent.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixEvent.c + +tkUnixFocus.o: $(UNIX_DIR)/tkUnixFocus.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixFocus.c + +tkUnixFont.o: $(UNIX_DIR)/tkUnixFont.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixFont.c + +# NB: tkUnixRFont.o uses nondefault CFLAGS +tkUnixRFont.o: $(UNIX_DIR)/tkUnixRFont.c + $(CC) -c $(CC_SWITCHES) $(XFT_CFLAGS) $(UNIX_DIR)/tkUnixRFont.c + +tkUnixInit.o: $(UNIX_DIR)/tkUnixInit.c tkConfig.sh + $(CC) -c $(CC_SWITCHES) -DTK_LIBRARY=\"${TK_LIBRARY}\" \ + $(UNIX_DIR)/tkUnixInit.c + +tkUnixKey.o: $(UNIX_DIR)/tkUnixKey.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixKey.c + +tkUnixMenu.o: $(UNIX_DIR)/tkUnixMenu.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixMenu.c + +tkUnixMenubu.o: $(UNIX_DIR)/tkUnixMenubu.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixMenubu.c + +tkUnixScale.o: $(UNIX_DIR)/tkUnixScale.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixScale.c + +tkUnixScrlbr.o: $(UNIX_DIR)/tkUnixScrlbr.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixScrlbr.c + +tkUnixSelect.o: $(UNIX_DIR)/tkUnixSelect.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixSelect.c + +tkUnixSend.o: $(UNIX_DIR)/tkUnixSend.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixSend.c + +tkUnixWm.o: $(UNIX_DIR)/tkUnixWm.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixWm.c + +tkUnixXId.o: $(UNIX_DIR)/tkUnixXId.c + $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixXId.c + +tkMacOSXBitmap.o: $(MAC_OSX_DIR)/tkMacOSXBitmap.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXBitmap.c + +tkMacOSXButton.o: $(MAC_OSX_DIR)/tkMacOSXButton.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXButton.c + +tkMacOSXClipboard.o: $(MAC_OSX_DIR)/tkMacOSXClipboard.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXClipboard.c + +tkMacOSXColor.o: $(MAC_OSX_DIR)/tkMacOSXColor.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXColor.c + +tkMacOSXConfig.o: $(MAC_OSX_DIR)/tkMacOSXConfig.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXConfig.c + +tkMacOSXCursor.o: $(MAC_OSX_DIR)/tkMacOSXCursor.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXCursor.c + +tkMacOSXDebug.o: $(MAC_OSX_DIR)/tkMacOSXDebug.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXDebug.c + +tkMacOSXDialog.o: $(MAC_OSX_DIR)/tkMacOSXDialog.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXDialog.c + +tkMacOSXDraw.o: $(MAC_OSX_DIR)/tkMacOSXDraw.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXDraw.c + +tkMacOSXEmbed.o: $(MAC_OSX_DIR)/tkMacOSXEmbed.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXEmbed.c + +tkMacOSXEntry.o: $(MAC_OSX_DIR)/tkMacOSXEntry.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXEntry.c + +tkMacOSXEvent.o: $(MAC_OSX_DIR)/tkMacOSXEvent.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXEvent.c + +tkMacOSXFont.o: $(MAC_OSX_DIR)/tkMacOSXFont.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXFont.c + +tkMacOSXHLEvents.o: $(MAC_OSX_DIR)/tkMacOSXHLEvents.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXHLEvents.c + +tkMacOSXImage.o: $(MAC_OSX_DIR)/tkMacOSXImage.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXImage.c + +tkMacOSXInit.o: $(MAC_OSX_DIR)/tkMacOSXInit.c tkConfig.sh + $(CC) -c $(CC_SWITCHES) -DTK_LIBRARY=\"${TK_LIBRARY}\" \ + $(MAC_OSX_DIR)/tkMacOSXInit.c + +tkMacOSXKeyboard.o: $(MAC_OSX_DIR)/tkMacOSXKeyboard.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXKeyboard.c + +tkMacOSXKeyEvent.o: $(MAC_OSX_DIR)/tkMacOSXKeyEvent.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXKeyEvent.c + +tkMacOSXMenu.o: $(MAC_OSX_DIR)/tkMacOSXMenu.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXMenu.c + +tkMacOSXMenubutton.o: $(MAC_OSX_DIR)/tkMacOSXMenubutton.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXMenubutton.c + +tkMacOSXMenus.o: $(MAC_OSX_DIR)/tkMacOSXMenus.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXMenus.c + +tkMacOSXMouseEvent.o: $(MAC_OSX_DIR)/tkMacOSXMouseEvent.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXMouseEvent.c + +tkMacOSXNotify.o: $(MAC_OSX_DIR)/tkMacOSXNotify.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXNotify.c + +tkMacOSXRegion.o: $(MAC_OSX_DIR)/tkMacOSXRegion.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXRegion.c + +tkMacOSXScale.o: $(MAC_OSX_DIR)/tkMacOSXScale.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXScale.c + +tkMacOSXScrlbr.o: $(MAC_OSX_DIR)/tkMacOSXScrlbr.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXScrlbr.c + +tkMacOSXSend.o: $(MAC_OSX_DIR)/tkMacOSXSend.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXSend.c + +tkMacOSXSubwindows.o: $(MAC_OSX_DIR)/tkMacOSXSubwindows.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXSubwindows.c + +tkMacOSXTest.o: $(MAC_OSX_DIR)/tkMacOSXTest.c + $(CC) -c $(APP_CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXTest.c + +tkMacOSXWindowEvent.o: $(MAC_OSX_DIR)/tkMacOSXWindowEvent.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXWindowEvent.c + +tkMacOSXWm.o: $(MAC_OSX_DIR)/tkMacOSXWm.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXWm.c + +tkMacOSXXStubs.o: $(MAC_OSX_DIR)/tkMacOSXXStubs.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXXStubs.c + +tkFileFilter.o: $(GENERIC_DIR)/tkFileFilter.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkFileFilter.c + +tkMacWinMenu.o: $(GENERIC_DIR)/tkMacWinMenu.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMacWinMenu.c + +tkPointer.o: $(GENERIC_DIR)/tkPointer.c + $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkPointer.c + +xcolors.o: $(XLIB_DIR)/xcolors.c + $(CC) -c $(CC_SWITCHES) $(XLIB_DIR)/xcolors.c + +xdraw.o: $(XLIB_DIR)/xdraw.c + $(CC) -c $(CC_SWITCHES) $(XLIB_DIR)/xdraw.c + +xgc.o: $(XLIB_DIR)/xgc.c + $(CC) -c $(CC_SWITCHES) $(XLIB_DIR)/xgc.c + +ximage.o: $(XLIB_DIR)/ximage.c + $(CC) -c $(CC_SWITCHES) $(XLIB_DIR)/ximage.c + +xutil.o: $(XLIB_DIR)/xutil.c + $(CC) -c $(CC_SWITCHES) $(XLIB_DIR)/xutil.c + +ttkBlink.o: $(TTK_DIR)/ttkBlink.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkBlink.c + +ttkButton.o: $(TTK_DIR)/ttkButton.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkButton.c + +ttkCache.o: $(TTK_DIR)/ttkCache.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkCache.c + +ttkClamTheme.o: $(TTK_DIR)/ttkClamTheme.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkClamTheme.c + +ttkClassicTheme.o: $(TTK_DIR)/ttkClassicTheme.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkClassicTheme.c + +ttkDefaultTheme.o: $(TTK_DIR)/ttkDefaultTheme.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkDefaultTheme.c + +ttkElements.o: $(TTK_DIR)/ttkElements.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkElements.c + +ttkEntry.o: $(TTK_DIR)/ttkEntry.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkEntry.c + +ttkFrame.o: $(TTK_DIR)/ttkFrame.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkFrame.c + +ttkImage.o: $(TTK_DIR)/ttkImage.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkImage.c + +ttkInit.o: $(TTK_DIR)/ttkInit.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkInit.c + +ttkLabel.o: $(TTK_DIR)/ttkLabel.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkLabel.c + +ttkLayout.o: $(TTK_DIR)/ttkLayout.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkLayout.c + +ttkManager.o: $(TTK_DIR)/ttkManager.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkManager.c + +ttkNotebook.o: $(TTK_DIR)/ttkNotebook.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkNotebook.c + +ttkPanedwindow.o: $(TTK_DIR)/ttkPanedwindow.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkPanedwindow.c + +ttkProgress.o: $(TTK_DIR)/ttkProgress.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkProgress.c + +ttkScale.o: $(TTK_DIR)/ttkScale.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkScale.c + +ttkScroll.o: $(TTK_DIR)/ttkScroll.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkScroll.c + +ttkScrollbar.o: $(TTK_DIR)/ttkScrollbar.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkScrollbar.c + +ttkSeparator.o: $(TTK_DIR)/ttkSeparator.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkSeparator.c + +ttkSquare.o: $(TTK_DIR)/ttkSquare.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkSquare.c + +ttkState.o: $(TTK_DIR)/ttkState.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkState.c + +ttkStubInit.o: $(TTK_DIR)/ttkStubInit.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkStubInit.c + +ttkStubLib.o: $(TTK_DIR)/ttkStubLib.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkStubLib.c + +ttkTagSet.o: $(TTK_DIR)/ttkTagSet.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkTagSet.c + +ttkTheme.o: $(TTK_DIR)/ttkTheme.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkTheme.c + +ttkTrace.o: $(TTK_DIR)/ttkTrace.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkTrace.c + +ttkTrack.o: $(TTK_DIR)/ttkTrack.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkTrack.c + +ttkTreeview.o: $(TTK_DIR)/ttkTreeview.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkTreeview.c + +ttkWidget.o: $(TTK_DIR)/ttkWidget.c + $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkWidget.c + +ttkMacOSXTheme.o: $(MAC_OSX_DIR)/ttkMacOSXTheme.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/ttkMacOSXTheme.c + +.c.o: + $(CC) -c $(CC_SWITCHES) $< + +# +# Target to regenerate header files and stub files from the *.decls tables. +# + +$(GENERIC_DIR)/tkStubInit.c: $(GENERIC_DIR)/tk.decls \ + $(GENERIC_DIR)/tkInt.decls + @echo "Warning: tkStubInit.c may be out of date." + @echo "Developers may want to run \"make genstubs\" to regenerate." + @echo "This warning can be safely ignored, do not report as a bug!" + +$(TTK_DIR)/ttkStubInit.c: $(TTK_DIR)/ttk.decls + @echo "Warning: ttkStubInit.c may be out of date." + @echo "Developers may want to run \"make genstubs\" to regenerate." + @echo "This warning can be safely ignored, do not report as a bug!" + +genstubs: + $(TCL_EXE) $(TOOL_DIR)/genStubs.tcl $(GENERIC_DIR) \ + $(GENERIC_DIR)/tk.decls $(GENERIC_DIR)/tkInt.decls + $(TCL_EXE) $(TTK_DIR)/ttkGenStubs.tcl $(TTK_DIR) $(TTK_DIR)/ttk.decls + +# +# Target to check that all exported functions have an entry in the stubs +# tables. +# + +checkstubs: $(TK_LIB_FILE) + -@for i in `nm -p $(TK_LIB_FILE) \ + | awk '$$2 ~ /^[TDBCS]$$/ { sub("^_", "", $$3); print $$3 }' \ + | sort -n`; do \ + match=0; \ + for j in $(TK_DECLS) $(TTK_DECLS); do \ + if [ `grep -c "$$i *(" $$j` -gt 0 ]; then \ + match=1; \ + fi; \ + done; \ + if [ $$match -eq 0 ]; then echo $$i; fi \ + done + +# +# Target to check for proper usage of UCHAR macro. +# + +checkuchar: + -egrep isalnum\|isalpha\|iscntrl\|isdigit\|islower\|isprint\|ispunct\|isspace\|isupper\|isxdigit\|toupper\|tolower $(SRCS) | grep -v UCHAR + +# +# Target to make sure that only symbols with "Tk", "tk", "Ttk", "ttk" or "X" +# prefixes are exported. +# + +checkexports: $(TK_LIB_FILE) + -@nm -p $(TK_LIB_FILE) \ + | awk '$$2 ~ /^[TDBCS]$$/ { sub("^_", "", $$3); print $$3 }' \ + | sort -n | grep -E -v '^([Tt]t?k|_?X)' || true + +# +# Target to create a Tk RPM for Linux. Requires that you be on a Linux +# system. +# + +rpm: all + rm -f THIS.TCL.SPEC + echo "%define _builddir `pwd`" > THIS.TK.SPEC + echo "%define _rpmdir `pwd`/RPMS" >> THIS.TK.SPEC + cat tk.spec >> THIS.TK.SPEC + mkdir -p RPMS/i386 + rpmbuild -bb THIS.TK.SPEC + mv RPMS/i386/*.rpm . + rm -rf RPMS THIS.TK.SPEC + +# +# Target to create a proper Tk distribution from information in the +# master source directory. DISTDIR must be defined to indicate where +# to put the distribution. DISTDIR must be an absolute path name. +# + +DISTROOT = /tmp/dist +DISTNAME = tk${VERSION}${PATCH_LEVEL} +ZIPNAME = tk${MAJOR_VERSION}${MINOR_VERSION}${PATCH_LEVEL}-src.zip +DISTDIR = $(DISTROOT)/$(DISTNAME) +TCLDIR = @TCL_SRC_DIR@ +$(UNIX_DIR)/configure: $(UNIX_DIR)/configure.in $(UNIX_DIR)/tcl.m4 \ + $(UNIX_DIR)/aclocal.m4 + cd $(UNIX_DIR); autoconf +$(MAC_OSX_DIR)/configure: $(MAC_OSX_DIR)/configure.ac $(UNIX_DIR)/configure + cd $(MAC_OSX_DIR); autoconf +$(UNIX_DIR)/tkConfig.h.in: $(MAC_OSX_DIR)/configure + cd $(MAC_OSX_DIR); autoheader; touch $@ + +dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tkConfig.h.in $(UNIX_DIR)/tk.pc.in $(MAC_OSX_DIR)/configure genstubs + rm -rf $(DISTDIR) + mkdir -p $(DISTDIR)/unix + cp -p $(UNIX_DIR)/*.c $(UNIX_DIR)/*.h $(DISTDIR)/unix + cp $(TOP_DIR)/license.terms $(UNIX_DIR)/Makefile.in $(DISTDIR)/unix + chmod 664 $(DISTDIR)/unix/Makefile.in + cp $(UNIX_DIR)/configure $(UNIX_DIR)/configure.in $(UNIX_DIR)/tk.spec \ + $(UNIX_DIR)/aclocal.m4 $(UNIX_DIR)/tcl.m4 \ + $(UNIX_DIR)/tkConfig.sh.in $(TCLDIR)/unix/install-sh \ + $(UNIX_DIR)/README $(UNIX_DIR)/installManPage \ + $(UNIX_DIR)/tkConfig.h.in $(UNIX_DIR)/tk.pc.in $(DISTDIR)/unix + chmod 775 $(DISTDIR)/unix/configure $(DISTDIR)/unix/configure.in + mkdir $(DISTDIR)/bitmaps + @(cd $(TOP_DIR); for i in bitmaps/* ; do \ + if [ -f $$i ] ; then \ + sed -e 's/static char/static unsigned char/' \ + $$i > $(DISTDIR)/$$i; \ + fi; \ + done;) + mkdir $(DISTDIR)/generic + cp -p $(GENERIC_DIR)/*.[ch] $(DISTDIR)/generic + cp -p $(GENERIC_DIR)/*.decls $(DISTDIR)/generic + cp -p $(GENERIC_DIR)/README $(DISTDIR)/generic + cp -p $(TOP_DIR)/changes $(TOP_DIR)/ChangeLog \ + $(TOP_DIR)/ChangeLog.2??? $(TOP_DIR)/README \ + $(TOP_DIR)/license.terms $(DISTDIR) + rm -f $(DISTDIR)/generic/blt*.[ch] + mkdir $(DISTDIR)/generic/ttk + cp -p $(TTK_DIR)/*.[ch] $(TTK_DIR)/ttk.decls \ + $(TTK_DIR)/ttkGenStubs.tcl $(DISTDIR)/generic/ttk + mkdir $(DISTDIR)/win + cp $(TOP_DIR)/win/Makefile.in $(DISTDIR)/win + cp $(TOP_DIR)/win/configure.in \ + $(TOP_DIR)/win/configure \ + $(TOP_DIR)/win/tkConfig.sh.in \ + $(TOP_DIR)/win/aclocal.m4 $(TOP_DIR)/win/tcl.m4 \ + $(DISTDIR)/win + cp -p $(TOP_DIR)/win/*.[ch] $(TOP_DIR)/win/*.bat $(DISTDIR)/win + cp -p $(TOP_DIR)/win/*.vc $(DISTDIR)/win + cp -p $(TOP_DIR)/win/README $(DISTDIR)/win + cp -p $(TOP_DIR)/license.terms $(DISTDIR)/win + mkdir $(DISTDIR)/win/rc + cp -p $(TOP_DIR)/win/wish.exe.manifest.in $(DISTDIR)/win/ + cp -p $(TOP_DIR)/win/rc/*.{rc,cur,ico,bmp} $(DISTDIR)/win/rc + mkdir $(DISTDIR)/macosx + cp -p $(MAC_OSX_DIR)/GNUmakefile $(MAC_OSX_DIR)/README \ + $(MAC_OSX_DIR)/*.icns $(MAC_OSX_DIR)/*.tiff \ + $(MAC_OSX_DIR)/*.[ch] $(MAC_OSX_DIR)/*.in \ + $(MAC_OSX_DIR)/*.ac $(MAC_OSX_DIR)/*.xcconfig \ + $(MAC_OSX_DIR)/*.sdef $(MAC_OSX_DIR)/configure \ + $(DISTDIR)/macosx + cp -p $(TOP_DIR)/license.terms $(DISTDIR)/macosx + mkdir $(DISTDIR)/macosx/Tk.xcode + cp -p $(MAC_OSX_DIR)/Tk.xcode/project.pbxproj \ + $(MAC_OSX_DIR)/Tk.xcode/default.pbxuser \ + $(DISTDIR)/macosx/Tk.xcode + mkdir $(DISTDIR)/macosx/Tk.xcodeproj + cp -p $(MAC_OSX_DIR)/Tk.xcodeproj/project.pbxproj \ + $(MAC_OSX_DIR)/Tk.xcodeproj/default.pbxuser \ + $(DISTDIR)/macosx/Tk.xcodeproj + mkdir $(DISTDIR)/compat + cp -p $(TOP_DIR)/license.terms $(TCLDIR)/compat/unistd.h \ + $(TCLDIR)/compat/stdlib.h \ + $(DISTDIR)/compat + mkdir $(DISTDIR)/xlib + cp -p $(XLIB_DIR)/*.[ch] $(DISTDIR)/xlib + cp -p $(TOP_DIR)/license.terms $(DISTDIR)/xlib + mkdir $(DISTDIR)/xlib/X11 + cp -p $(XLIB_DIR)/X11/*.h $(DISTDIR)/xlib/X11 + cp -p $(TOP_DIR)/license.terms $(DISTDIR)/xlib/X11 + mkdir $(DISTDIR)/library + cp -p $(TOP_DIR)/license.terms $(TOP_DIR)/library/*.tcl \ + $(TOP_DIR)/library/tclIndex \ + $(DISTDIR)/library + mkdir $(DISTDIR)/library/ttk + cp -p $(TOP_DIR)/library/ttk/*.tcl $(DISTDIR)/library/ttk + mkdir $(DISTDIR)/library/images + @(cd $(TOP_DIR); for i in library/images/* ; do \ + if [ -f $$i ] ; then \ + cp $$i $(DISTDIR)/$$i; \ + fi; \ + done;) + mkdir $(DISTDIR)/library/msgs + @(cd $(TOP_DIR); for i in library/msgs/*.msg ; do \ + if [ -f $$i ] ; then \ + cp $$i $(DISTDIR)/$$i; \ + fi; \ + done;) + mkdir $(DISTDIR)/library/demos + cp -pr $(TOP_DIR)/library/demos/*.tcl \ + $(TOP_DIR)/library/demos/*.msg \ + $(TOP_DIR)/library/demos/tclIndex \ + $(TOP_DIR)/library/demos/browse \ + $(TOP_DIR)/library/demos/hello $(TOP_DIR)/library/demos/ixset \ + $(TOP_DIR)/library/demos/rmt $(TOP_DIR)/library/demos/rolodex \ + $(TOP_DIR)/library/demos/square \ + $(TOP_DIR)/library/demos/tcolor \ + $(TOP_DIR)/library/demos/timer \ + $(TOP_DIR)/library/demos/widget \ + $(TOP_DIR)/library/demos/README \ + $(TOP_DIR)/license.terms $(DISTDIR)/library/demos + mkdir $(DISTDIR)/library/demos/images + @(cd $(TOP_DIR); for i in library/demos/images/* ; do \ + if [ -f $$i ] ; then \ + cp $$i $(DISTDIR)/$$i; \ + fi; \ + done;) + mkdir $(DISTDIR)/doc + cp -p $(TOP_DIR)/license.terms $(TOP_DIR)/doc/*.[13n] \ + $(TCLDIR)/doc/man.macros $(DISTDIR)/doc + mkdir $(DISTDIR)/tests + cp -p $(TOP_DIR)/license.terms $(TEST_DIR)/*.{test,tcl} \ + $(TEST_DIR)/README $(TEST_DIR)/*.{gif,png,ppm,xbm} \ + $(TEST_DIR)/option.file* $(DISTDIR)/tests + mkdir $(DISTDIR)/tests/ttk + cp -p $(TEST_DIR)/ttk/*.{test,tcl} $(DISTDIR)/tests/ttk + +alldist: dist + rm -f $(DISTROOT)/$(DISTNAME)-src.tar.gz $(DISTROOT)/$(ZIPNAME) + cd $(DISTROOT); tar cf $(DISTNAME)-src.tar $(DISTNAME); \ + gzip -9 $(DISTNAME)-src.tar; zip -qr8 $(ZIPNAME) $(DISTNAME) + +# +# This target creates the HTML folder for Tcl & Tk and places it +# in DISTDIR/html. It uses the tcltk-man2html.tcl tool from +# the Tcl group's tool workspace. It depends on the Tcl & Tk being +# in directories called tcl8.3 & tk8.3 up two directories from the +# TOOL_DIR. +# + +html: + $(BUILD_HTML) + @EXTRA_BUILD_HTML@ +html-tcl: + $(BUILD_HTML) --tcl + @EXTRA_BUILD_HTML@ +html-tk: + $(BUILD_HTML) --tk + @EXTRA_BUILD_HTML@ + +BUILD_HTML = \ + @if test -f "$(BUILD_TCLSH)"; then \ + $(SHELL_ENV) TCLSH="$(BUILD_TCLSH)"; else \ + TCLSH="$(TCL_EXE)"; fi ;\ + "$${TCLSH}" $(TOOL_DIR)/tcltk-man2html.tcl --htmldir="$(HTML_INSTALL_DIR)" \ + --srcdir=$(TOP_DIR)/.. $(BUILD_HTML_FLAGS) + +# +# The list of all the targets that do not correspond to real files. This stops +# 'make' from getting confused when someone makes an error in a rule. +# + +.PHONY: all binaries libraries objs doc html html-tcl html-tk test runtest +.PHONY: install install-strip install-binaries install-libraries +.PHONY: install-headers install-private-headers install-doc +.PHONY: clean distclean depend genstubs checkstubs checkexports checkuchar +.PHONY: shell gdb valgrind valgrindshell dist alldist rpm +.PHONY: tkLibObjs tktest-real test-classic test-ttk testlang +.PHONY: demo install-demos + +# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/tk8.6/unix/README b/tk8.6/unix/README new file mode 100644 index 0000000..ea5c8fe --- /dev/null +++ b/tk8.6/unix/README @@ -0,0 +1,173 @@ +Tk UNIX README +-------------- + +This is the directory where you configure, compile, test, and install UNIX +versions of Tk. This directory also contains source files for Tk that are +specific to UNIX. + +The information in this file is maintained at: + http://www.tcl.tk/doc/howto/compile.html + +For information on platforms where Tcl/Tk is known to compile, along with any +porting notes for getting it to work on those platforms, see: + http://www.tcl.tk/software/tcltk/platforms.html + +The rest of this file contains instructions on how to do this. The release +should compile and run either "out of the box" or with trivial changes on any +UNIX-like system that approximates POSIX, BSD, or System V. We know that it +runs on workstations from Sun, H-P, DEC, IBM, and SGI, as well as PCs running +Linux, BSDI, and SCO UNIX. To compile for a PC running Windows, see the README +file in the directory ../win. To compile for MacOSX, see the README file in +the directory ../macosx. + +How To Compile And Install Tk: +------------------------------ + +(a) Make sure that the Tcl release is present in the directory + ../../tcl<version> (or else use the "--with-tcl" switch described below). + This release of Tk will only work with the equivalently versioned Tcl + release. Also, be sure that you have configured Tcl before you configure + Tk. + +(b) Check for patches as described in ../README. + +(c) If you have already compiled Tk once in this directory and are now + preparing to compile again in the same directory but for a different + platform, or if you have applied patches, type "make distclean" to discard + all the configuration information computed previously. + +(d) Type "./configure". This runs a configuration script created by GNU + autoconf, which configures Tk for your system and creates a Makefile. The + configure script allows you to customize the Tk configuration for your + site; for details on how you can do this, type "./configure -help" or + refer to the autoconf documentation (not included here). Tk's "configure" + script supports the following special switches in addition to the standard + ones: + + --with-tcl=DIR Specifies the directory containing the Tcl + binaries and Tcl's platform-dependent + configuration information. By default the Tcl + directory is assumed to be in the location + given by (a) above. + --with-x=DIR Tells configure where to find an installation + of the X Window System. Not normally needed. + --enable-threads If this switch is set, Tk will compile itself + with multithreading support. + --enable-shared If this switch is specified, Tk will compile + itself as a shared library if it can figure + out how to do that on this platform. This is + the default on platforms where we know how to + build shared libraries. + --disable-shared If this switch is specified, Tk will compile + itself as a static library. + --disable-rpath Turns off use of the rpath link option on + platforms that would otherwise use it. + --enable-symbols Build with debugging symbols. By default + standard debugging symbols are used. You can + specify the value "mem" to include + TCL_MEM_DEBUG memory debugging. + --disable-symbols Build without debugging symbols + --enable-64bit Enable 64bit support (where applicable) + --disable-64bit Disable 64bit support (where applicable) + --enable-64bit-vis Enable 64bit Sparc VIS support + --disable-64bit-vis Disable 64bit Sparc VIS support + --disable-xft Disable support for antialiased fonts via the + Freetype/xft library. By default, this is + switched on whenever the configure script can + detect the required libraries. + --enable-man-symlinks Use symlinks for linking the manpages that + should be reachable under several names. + --enable-man-compression=PROG + Compress the manpages using PROG. + --enable-man-suffix=STRING + Add STRING to the name of each of the manual + pages. If specified without giving STRING, the + suffix will be "tk". + + Mac OS X only: + + --enable-framework Package Tk as a framework. + --disable-corefoundation Disable use of CoreFoundation API. + --enable-aqua Use Aqua windowingsystem rather than X11, + requires --enable-corefoundation with Tcl and + Tk. + + Note: by default gcc will be used if it can be located on the PATH. If you + want to use cc instead of gcc, set the CC environment variable to "cc" + before running configure. It is not safe to change the Makefile to use gcc + after configure is run. + + Note: be sure to use only absolute path names (those starting with "/") in + the --prefix and --exec-prefix options. + +(e) Type "make". This will create a library archive called "libtk<version>.a" + or "libtk<version>.so" and an interpreter application called "wish" that + allows you to type Tcl/Tk commands interactively or execute script files. + It will also create a stub library archive "libtkstub<version>.a" that + developers may link against other C code to produce loadable extensions + that call into Tk's public interface routines. + +(f) If the make fails then you'll have to personalize the Makefile for your + site or possibly modify the distribution in other ways. First check the + porting Web page above to see if there are hints for compiling on your + system. If you need to modify Makefile, there are comments at the + beginning of it that describe the things you might want to change and how + to change them. + +(g) Type "make install" to install Tk's binaries and script files in standard + places. You'll need write permission on the installation directories to do + this. The installation directories are determined by the "configure" + script and may be specified with the --prefix and --exec-prefix options to + "configure". See the Makefile for information on what directories were + chosen. You should not override these choices by modifying the Makefile, + or by copying files post-install. The installed binaries have embedded + within them path values relative to the install directory. If you change + your mind about where Tk should be installed, start this procedure over + again from step (a) so that the path embedded in the binaries agrees with + the install location. + +(h) At this point you can play with Tk by running the installed "wish" + executable, or via the "make shell" target, and typing Tcl/Tk commands at + the interactive prompt. + +If you have trouble compiling Tk, see the URL noted above about working +platforms. It contains information that people have provided about changes +they had to make to compile Tk in various environments. We're also interested +in hearing how to change the configuration setup so that Tk compiles on +additional platforms "out of the box". + +Note: Do not specify either of the TCL_LIBRARY and TK_LIBRARY environment +variables in a production installation, as this can cause conflicts between +different versions of the libraries. Instead, the libraries should have the +correct locations of their associated script directories built into them. + +Test suite +---------- + +Tk has a substantial self-test suite, consisting of a set of scripts in the +subdirectory "tests". To run the test suite just type "make test" in this +directory. You should then see a printout of the test files processed. If any +errors occur, you'll see a much more substantial printout for each error. In +order to avoid false error reports, be sure to run the tests with an empty +resource database (e.g., remove your .Xdefaults file or delete any entries +starting with *). Also, don't try to do anything else with your display or +keyboard while the tests are running, or you may get false violations. See the +README file in the "tests" directory for more information on the test suite. + +If the test suite generates errors, most likely they are due to non-portable +tests that are interacting badly with your system configuration. We are +gradually eliminating the non-portable tests, but this release includes many +new tests so there will probably be some portability problems. As long as the +test suite doesn't core dump, it's probably safe to conclude that any errors +represent portability problems in the test suite and not fundamental flaws +with Tk. + +There are also a number of visual tests for things such as screen layout, +Postscript generation, etc. These tests all have to be run by manually +enabling the "userInteraction" constraint when testing, and the results have +to be verified visually. This can be done with: + + make test TESTFLAGS="-constraints userInteraction" + +Some tests will present a main window with a bunch of menus, which you can use +to select various tests. diff --git a/tk8.6/unix/aclocal.m4 b/tk8.6/unix/aclocal.m4 new file mode 100644 index 0000000..90d2e39 --- /dev/null +++ b/tk8.6/unix/aclocal.m4 @@ -0,0 +1 @@ +builtin(include,../unix/tcl.m4) diff --git a/tk8.6/unix/configure b/tk8.6/unix/configure new file mode 100755 index 0000000..56e9df4 --- /dev/null +++ b/tk8.6/unix/configure @@ -0,0 +1,12293 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59 for tk 8.6. +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='tk' +PACKAGE_TARNAME='tk' +PACKAGE_VERSION='8.6' +PACKAGE_STRING='tk 8.6' +PACKAGE_BUGREPORT='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#if HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#if STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# if HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#if HAVE_STRINGS_H +# include <strings.h> +#endif +#if HAVE_INTTYPES_H +# include <inttypes.h> +#else +# if HAVE_STDINT_H +# include <stdint.h> +# endif +#endif +#if HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS TCL_VERSION TCL_PATCH_LEVEL TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCLSH_PROG BUILD_TCLSH MAN_FLAGS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP TCL_THREADS RANLIB ac_ct_RANLIB AR ac_ct_AR LIBOBJS TCL_LIBS DL_LIBS DL_OBJS PLAT_OBJS PLAT_SRCS LDAIX_SRC CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING LDFLAGS_DEBUG LDFLAGS_OPTIMIZE CC_SEARCH_FLAGS LD_SEARCH_FLAGS STLIB_LD SHLIB_LD TCL_SHLIB_LD_EXTRAS TK_SHLIB_LD_EXTRAS SHLIB_LD_LIBS SHLIB_CFLAGS SHLIB_SUFFIX MAKE_LIB MAKE_STUB_LIB INSTALL_LIB DLL_INSTALL_DIR INSTALL_STUB_LIB CFLAGS_DEFAULT LDFLAGS_DEFAULT XFT_CFLAGS XFT_LIBS UNIX_FONT_OBJS TK_VERSION TK_MAJOR_VERSION TK_MINOR_VERSION TK_PATCH_LEVEL TK_YEAR TK_LIB_FILE TK_LIB_FLAG TK_LIB_SPEC TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_STUB_LIB_SPEC TK_STUB_LIB_PATH TK_INCLUDE_SPEC TK_BUILD_STUB_LIB_SPEC TK_BUILD_STUB_LIB_PATH TK_SRC_DIR TK_SHARED_BUILD LD_LIBRARY_PATH_VAR TK_BUILD_LIB_SPEC TCL_STUB_FLAGS XINCLUDES XLIBSW LOCALES TK_WINDOWINGSYSTEM TK_PKG_DIR TK_LIBRARY LIB_RUNTIME_DIR PRIVATE_INCLUDE_DIR HTML_DIR EXTRA_CC_SWITCHES EXTRA_APP_CC_SWITCHES EXTRA_INSTALL EXTRA_INSTALL_BINARIES EXTRA_BUILD_HTML EXTRA_WISH_LIBS CFBUNDLELOCALIZATIONS TK_RSRC_FILE WISH_RSRC_FILE LIB_RSRC_FILE APP_RSRC_FILE REZ REZ_FLAGS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures tk 8.6 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of tk 8.6:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-man-symlinks use symlinks for the manpages (default: off) + --enable-man-compression=PROG + compress the manpages with PROG (default: off) + --enable-man-suffix=STRING + use STRING as a suffix to manpage file names + (default: no, tk if enabled without + specifying STRING) + --enable-threads build with threads (default: on) + --enable-shared build and link with shared libraries (default: on) + --enable-64bit enable 64bit support (default: off) + --enable-64bit-vis enable 64bit Sparc VIS support (default: off) + --disable-rpath disable rpath support (default: on) + --enable-corefoundation use CoreFoundation API on MacOSX (default: on) + --enable-load allow dynamic loading and "load" command (default: + on) + --enable-symbols build with debugging symbols (default: off) + --enable-aqua=yes|no use Aqua windowingsystem on Mac OS X (default: no) + --enable-xft use freetype/fontconfig/xft (default: on) + --enable-xss use XScreenSaver for activity timer (default: on) + --enable-framework package shared libraries in MacOSX frameworks + (default: off) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-tcl directory containing tcl configuration + (tclConfig.sh) + --with-x use the X Window System + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have + headers in a nonstandard directory <include dir> + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +tk configure 8.6 +generated by GNU Autoconf 2.59 + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by tk $as_me 8.6, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -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 +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +TK_VERSION=8.6 +TK_MAJOR_VERSION=8 +TK_MINOR_VERSION=6 +TK_PATCH_LEVEL=".9" +VERSION=${TK_VERSION} +LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv" + +#-------------------------------------------------------------------- +# Find and load the tclConfig.sh file +#-------------------------------------------------------------------- + + + # + # Ok, lets find the tcl configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tcl + # + + if test x"${no_tcl}" = x ; then + # we reset no_tcl in case something fails here + no_tcl=true + +# Check whether --with-tcl or --without-tcl was given. +if test "${with_tcl+set}" = set; then + withval="$with_tcl" + with_tclconfig="${withval}" +fi; + echo "$as_me:$LINENO: checking for Tcl configuration" >&5 +echo $ECHO_N "checking for Tcl configuration... $ECHO_C" >&6 + if test "${ac_cv_c_tclconfig+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + + # First check to see if --with-tcl was specified. + if test x"${with_tclconfig}" != x ; then + case "${with_tclconfig}" in + */tclConfig.sh ) + if test -f "${with_tclconfig}"; then + { echo "$as_me:$LINENO: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 +echo "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;} + with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" + else + { { echo "$as_me:$LINENO: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&5 +echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&2;} + { (exit 1); exit 1; }; } + fi + fi + + # then check for a private Tcl installation + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ../tcl \ + `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \ + ../../tcl \ + `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \ + ../../../tcl \ + `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + ; do + if test -f "$i/Tcl.framework/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/pkg/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ${srcdir}/../tcl \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + +fi + + + if test x"${ac_cv_c_tclconfig}" = x ; then + TCL_BIN_DIR="# no Tcl configs found" + { { echo "$as_me:$LINENO: error: Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" >&5 +echo "$as_me: error: Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" >&2;} + { (exit 1); exit 1; }; } + else + no_tcl= + TCL_BIN_DIR="${ac_cv_c_tclconfig}" + echo "$as_me:$LINENO: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 +echo "${ECHO_T}found ${TCL_BIN_DIR}/tclConfig.sh" >&6 + fi + fi + + + echo "$as_me:$LINENO: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 +echo $ECHO_N "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... $ECHO_C" >&6 + + if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then + echo "$as_me:$LINENO: result: loading" >&5 +echo "${ECHO_T}loading" >&6 + . "${TCL_BIN_DIR}/tclConfig.sh" + else + echo "$as_me:$LINENO: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 +echo "${ECHO_T}could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6 + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" + eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" + + # If the TCL_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TCL_LIB_SPEC will be set to the value + # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC + # instead of TCL_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" + TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" + TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tcl.framework installed in an arbitrary location. + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then + for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ + "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then + TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" + break + fi + done + fi + if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then + TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" + TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" + eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" + eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" + eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" + + + + + + + + + + + + + + + +if test "${TCL_MAJOR_VERSION}" -ne 8 ; then + { { echo "$as_me:$LINENO: error: ${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+ +Found config for Tcl ${TCL_VERSION}" >&5 +echo "$as_me: error: ${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+ +Found config for Tcl ${TCL_VERSION}" >&2;} + { (exit 1); exit 1; }; } +fi +if test "${TCL_MINOR_VERSION}" -lt 6 ; then + { { echo "$as_me:$LINENO: error: ${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+ +Found config for Tcl ${TCL_VERSION}" >&5 +echo "$as_me: error: ${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+ +Found config for Tcl ${TCL_VERSION}" >&2;} + { (exit 1); exit 1; }; } +fi + + + echo "$as_me:$LINENO: checking for tclsh" >&5 +echo $ECHO_N "checking for tclsh... $ECHO_C" >&6 + if test "${ac_cv_path_tclsh+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + search_path=`echo ${PATH} | sed -e 's/:/ /g'` + for dir in $search_path ; do + for j in `ls -r $dir/tclsh[8-9]* 2> /dev/null` \ + `ls -r $dir/tclsh* 2> /dev/null` ; do + if test x"$ac_cv_path_tclsh" = x ; then + if test -f "$j" ; then + ac_cv_path_tclsh=$j + break + fi + fi + done + done + +fi + + + if test -f "$ac_cv_path_tclsh" ; then + TCLSH_PROG="$ac_cv_path_tclsh" + echo "$as_me:$LINENO: result: $TCLSH_PROG" >&5 +echo "${ECHO_T}$TCLSH_PROG" >&6 + else + # It is not an error if an installed version of Tcl can't be located. + TCLSH_PROG="" + echo "$as_me:$LINENO: result: No tclsh found on PATH" >&5 +echo "${ECHO_T}No tclsh found on PATH" >&6 + fi + + + + echo "$as_me:$LINENO: checking for tclsh in Tcl build directory" >&5 +echo $ECHO_N "checking for tclsh in Tcl build directory... $ECHO_C" >&6 + BUILD_TCLSH="${TCL_BIN_DIR}"/tclsh + echo "$as_me:$LINENO: result: $BUILD_TCLSH" >&5 +echo "${ECHO_T}$BUILD_TCLSH" >&6 + + + +#------------------------------------------------------------------------ +# Handle the --prefix=... option +#------------------------------------------------------------------------ + +if test "${prefix}" = "NONE"; then + prefix="$TCL_PREFIX" +fi +if test "${exec_prefix}" = "NONE"; then + exec_prefix=$prefix +fi +# Make sure srcdir is fully qualified! +srcdir="`cd "$srcdir" ; pwd`" +TK_SRC_DIR="`cd "$srcdir"/..; pwd`" + +#------------------------------------------------------------------------ +# Compress and/or soft link the manpages? +#------------------------------------------------------------------------ + + + echo "$as_me:$LINENO: checking whether to use symlinks for manpages" >&5 +echo $ECHO_N "checking whether to use symlinks for manpages... $ECHO_C" >&6 + # Check whether --enable-man-symlinks or --disable-man-symlinks was given. +if test "${enable_man_symlinks+set}" = set; then + enableval="$enable_man_symlinks" + test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks" +else + enableval="no" +fi; + echo "$as_me:$LINENO: result: $enableval" >&5 +echo "${ECHO_T}$enableval" >&6 + + echo "$as_me:$LINENO: checking whether to compress the manpages" >&5 +echo $ECHO_N "checking whether to compress the manpages... $ECHO_C" >&6 + # Check whether --enable-man-compression or --disable-man-compression was given. +if test "${enable_man_compression+set}" = set; then + enableval="$enable_man_compression" + case $enableval in + yes) { { echo "$as_me:$LINENO: error: missing argument to --enable-man-compression" >&5 +echo "$as_me: error: missing argument to --enable-man-compression" >&2;} + { (exit 1); exit 1; }; };; + no) ;; + *) MAN_FLAGS="$MAN_FLAGS --compress $enableval";; + esac +else + enableval="no" +fi; + echo "$as_me:$LINENO: result: $enableval" >&5 +echo "${ECHO_T}$enableval" >&6 + if test "$enableval" != "no"; then + echo "$as_me:$LINENO: checking for compressed file suffix" >&5 +echo $ECHO_N "checking for compressed file suffix... $ECHO_C" >&6 + touch TeST + $enableval TeST + Z=`ls TeST* | sed 's/^....//'` + rm -f TeST* + MAN_FLAGS="$MAN_FLAGS --extension $Z" + echo "$as_me:$LINENO: result: $Z" >&5 +echo "${ECHO_T}$Z" >&6 + fi + + echo "$as_me:$LINENO: checking whether to add a package name suffix for the manpages" >&5 +echo $ECHO_N "checking whether to add a package name suffix for the manpages... $ECHO_C" >&6 + # Check whether --enable-man-suffix or --disable-man-suffix was given. +if test "${enable_man_suffix+set}" = set; then + enableval="$enable_man_suffix" + case $enableval in + yes) enableval="tk" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";; + no) ;; + *) MAN_FLAGS="$MAN_FLAGS --suffix $enableval";; + esac +else + enableval="no" +fi; + echo "$as_me:$LINENO: result: $enableval" >&5 +echo "${ECHO_T}$enableval" >&6 + + + + +#------------------------------------------------------------------------ +# Standard compiler checks +#------------------------------------------------------------------------ + +# If the user did not set CFLAGS, set it now to keep +# the AC_PROG_CC macro from adding "-g -O2". +if test "${CFLAGS+set}" != "set" ; then + CFLAGS="" +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include <stdlib.h> +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for inline" >&5 +echo $ECHO_N "checking for inline... $ECHO_C" >&6 +if test "${ac_cv_c_inline+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_inline=$ac_kw; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 +echo "${ECHO_T}$ac_cv_c_inline" >&6 + + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + + +#-------------------------------------------------------------------- +# Supply a substitute for stdlib.h if it doesn't define strtol, +# strtoul, or strtod (which it doesn't in some versions of SunOS). +#-------------------------------------------------------------------- + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ctype.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +if test "${ac_cv_header_stdlib_h+set}" = set; then + echo "$as_me:$LINENO: checking for stdlib.h" >&5 +echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6 +if test "${ac_cv_header_stdlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking stdlib.h usability" >&5 +echo $ECHO_N "checking stdlib.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <stdlib.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking stdlib.h presence" >&5 +echo $ECHO_N "checking stdlib.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: stdlib.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: stdlib.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: stdlib.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: stdlib.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: stdlib.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: stdlib.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: stdlib.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: stdlib.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------- ## +## Report this to the tk lists. ## +## ----------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for stdlib.h" >&5 +echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6 +if test "${ac_cv_header_stdlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_stdlib_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6 + +fi +if test $ac_cv_header_stdlib_h = yes; then + tk_ok=1 +else + tk_ok=0 +fi + + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strtol" >/dev/null 2>&1; then + : +else + tk_ok=0 +fi +rm -f conftest* + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strtoul" >/dev/null 2>&1; then + : +else + tk_ok=0 +fi +rm -f conftest* + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strtod" >/dev/null 2>&1; then + : +else + tk_ok=0 +fi +rm -f conftest* + +if test $tk_ok = 0; then + +cat >>confdefs.h <<\_ACEOF +#define NO_STDLIB_H 1 +_ACEOF + +fi + +#------------------------------------------------------------------------ +# If we're using GCC, see if the compiler understands -pipe. If so, use it. +# It makes compiling go faster. (This is only a performance feature.) +#------------------------------------------------------------------------ + +if test -z "$no_pipe" && test -n "$GCC"; then + echo "$as_me:$LINENO: checking if the compiler understands -pipe" >&5 +echo $ECHO_N "checking if the compiler understands -pipe... $ECHO_C" >&6 +if test "${tcl_cv_cc_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_pipe=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_pipe=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_pipe" >&5 +echo "${ECHO_T}$tcl_cv_cc_pipe" >&6 + if test $tcl_cv_cc_pipe = yes; then + CFLAGS="$CFLAGS -pipe" + fi +fi + +#------------------------------------------------------------------------ +# Threads support - this auto-enables if Tcl was compiled threaded +#------------------------------------------------------------------------ + + + # 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=yes +fi; + + if test "${TCL_THREADS}" = 1; then + tcl_threaded_core=1; + fi + + if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then + TCL_THREADS=1 + # USE_THREAD_ALLOC tells us to try the special thread-based + # allocator that significantly reduces lock contention + +cat >>confdefs.h <<\_ACEOF +#define USE_THREAD_ALLOC 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define _REENTRANT 1 +_ACEOF + + if test "`uname -s`" = "SunOS" ; then + +cat >>confdefs.h <<\_ACEOF +#define _POSIX_PTHREAD_SEMANTICS 1 +_ACEOF + + fi + +cat >>confdefs.h <<\_ACEOF +#define _THREAD_SAFE 1 +_ACEOF + + echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthread" >&5 +echo $ECHO_N "checking for pthread_mutex_init in -lpthread... $ECHO_C" >&6 +if test "${ac_cv_lib_pthread_pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_mutex_init (); +int +main () +{ +pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthread_pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pthread_pthread_mutex_init=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_pthread_pthread_mutex_init" >&6 +if test $ac_cv_lib_pthread_pthread_mutex_init = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "no"; then + # Check a little harder for __pthread_mutex_init in the same + # library, as some systems hide it there until pthread.h is + # defined. We could alternatively do an AC_TRY_COMPILE with + # pthread.h, but that will work with libpthread really doesn't + # exist, like AIX 4.2. [Bug: 4359] + echo "$as_me:$LINENO: checking for __pthread_mutex_init in -lpthread" >&5 +echo $ECHO_N "checking for __pthread_mutex_init in -lpthread... $ECHO_C" >&6 +if test "${ac_cv_lib_pthread___pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char __pthread_mutex_init (); +int +main () +{ +__pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthread___pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pthread___pthread_mutex_init=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_pthread___pthread_mutex_init" >&6 +if test $ac_cv_lib_pthread___pthread_mutex_init = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthread" + else + echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthreads" >&5 +echo $ECHO_N "checking for pthread_mutex_init in -lpthreads... $ECHO_C" >&6 +if test "${ac_cv_lib_pthreads_pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthreads $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_mutex_init (); +int +main () +{ +pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthreads_pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pthreads_pthread_mutex_init=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_pthreads_pthread_mutex_init" >&6 +if test $ac_cv_lib_pthreads_pthread_mutex_init = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthreads" + else + echo "$as_me:$LINENO: checking for pthread_mutex_init in -lc" >&5 +echo $ECHO_N "checking for pthread_mutex_init in -lc... $ECHO_C" >&6 +if test "${ac_cv_lib_c_pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_mutex_init (); +int +main () +{ +pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_c_pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_c_pthread_mutex_init=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_c_pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_c_pthread_mutex_init" >&6 +if test $ac_cv_lib_c_pthread_mutex_init = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "no"; then + echo "$as_me:$LINENO: checking for pthread_mutex_init in -lc_r" >&5 +echo $ECHO_N "checking for pthread_mutex_init in -lc_r... $ECHO_C" >&6 +if test "${ac_cv_lib_c_r_pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc_r $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_mutex_init (); +int +main () +{ +pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_c_r_pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_c_r_pthread_mutex_init=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_c_r_pthread_mutex_init" >&6 +if test $ac_cv_lib_c_r_pthread_mutex_init = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -pthread" + else + TCL_THREADS=0 + { echo "$as_me:$LINENO: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&5 +echo "$as_me: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&2;} + fi + fi + fi + fi + + # Does the pthread-implementation provide + # 'pthread_attr_setstacksize' ? + + ac_saved_libs=$LIBS + LIBS="$LIBS $THREADS_LIBS" + + +for ac_func in pthread_attr_setstacksize pthread_atfork +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + LIBS=$ac_saved_libs + else + TCL_THREADS=0 + fi + # Do checking message here to not mess up interleaved configure output + echo "$as_me:$LINENO: checking for building with threads" >&5 +echo $ECHO_N "checking for building with threads... $ECHO_C" >&6 + if test "${TCL_THREADS}" = 1; then + +cat >>confdefs.h <<\_ACEOF +#define TCL_THREADS 1 +_ACEOF + + if test "${tcl_threaded_core}" = 1; then + echo "$as_me:$LINENO: result: yes (threaded core)" >&5 +echo "${ECHO_T}yes (threaded core)" >&6 + else + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + fi + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + fi + + + + +# Add the threads support libraries +LIBS="$LIBS$THREADS_LIBS" + + + echo "$as_me:$LINENO: checking how to build libraries" >&5 +echo $ECHO_N "checking how to build libraries... $ECHO_C" >&6 + # Check whether --enable-shared 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 "$as_me:$LINENO: result: shared" >&5 +echo "${ECHO_T}shared" >&6 + SHARED_BUILD=1 + else + echo "$as_me:$LINENO: result: static" >&5 +echo "${ECHO_T}static" >&6 + SHARED_BUILD=0 + +cat >>confdefs.h <<\_ACEOF +#define STATIC_BUILD 1 +_ACEOF + + fi + + +#-------------------------------------------------------------------- +# 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. +#-------------------------------------------------------------------- + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + + + # Step 0.a: Enable 64 bit support? + + echo "$as_me:$LINENO: checking if 64bit support is requested" >&5 +echo $ECHO_N "checking if 64bit support is requested... $ECHO_C" >&6 + # Check whether --enable-64bit or --disable-64bit was given. +if test "${enable_64bit+set}" = set; then + enableval="$enable_64bit" + do64bit=$enableval +else + do64bit=no +fi; + echo "$as_me:$LINENO: result: $do64bit" >&5 +echo "${ECHO_T}$do64bit" >&6 + + # Step 0.b: Enable Solaris 64 bit VIS support? + + echo "$as_me:$LINENO: checking if 64bit Sparc VIS support is requested" >&5 +echo $ECHO_N "checking if 64bit Sparc VIS support is requested... $ECHO_C" >&6 + # Check whether --enable-64bit-vis or --disable-64bit-vis was given. +if test "${enable_64bit_vis+set}" = set; then + enableval="$enable_64bit_vis" + do64bitVIS=$enableval +else + do64bitVIS=no +fi; + echo "$as_me:$LINENO: result: $do64bitVIS" >&5 +echo "${ECHO_T}$do64bitVIS" >&6 + # Force 64bit on with VIS + if test "$do64bitVIS" = "yes"; then + do64bit=yes +fi + + + # Step 0.c: Check if visibility support is available. Do this here so + # that platform specific alternatives can be used below if this fails. + + echo "$as_me:$LINENO: checking if compiler supports visibility \"hidden\"" >&5 +echo $ECHO_N "checking if compiler supports visibility \"hidden\"... $ECHO_C" >&6 +if test "${tcl_cv_cc_visibility_hidden+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + extern __attribute__((__visibility__("hidden"))) void f(void); + void f(void) {} +int +main () +{ +f(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_visibility_hidden=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_visibility_hidden=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_visibility_hidden" >&5 +echo "${ECHO_T}$tcl_cv_cc_visibility_hidden" >&6 + if test $tcl_cv_cc_visibility_hidden = yes; then + + +cat >>confdefs.h <<\_ACEOF +#define MODULE_SCOPE extern __attribute__((__visibility__("hidden"))) +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_HIDDEN 1 +_ACEOF + + +fi + + + # Step 0.d: Disable -rpath support? + + echo "$as_me:$LINENO: checking if rpath support is requested" >&5 +echo $ECHO_N "checking if rpath support is requested... $ECHO_C" >&6 + # Check whether --enable-rpath or --disable-rpath was given. +if test "${enable_rpath+set}" = set; then + enableval="$enable_rpath" + doRpath=$enableval +else + doRpath=yes +fi; + echo "$as_me:$LINENO: result: $doRpath" >&5 +echo "${ECHO_T}$doRpath" >&6 + + # Step 1: set the variable "system" to hold the name and version number + # for the system. + + + echo "$as_me:$LINENO: checking system version" >&5 +echo $ECHO_N "checking system version... $ECHO_C" >&6 +if test "${tcl_cv_sys_version+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test -f /usr/lib/NextStep/software_version; then + tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` + else + tcl_cv_sys_version=`uname -s`-`uname -r` + if test "$?" -ne 0 ; then + { echo "$as_me:$LINENO: WARNING: can't find uname command" >&5 +echo "$as_me: WARNING: can't find uname command" >&2;} + tcl_cv_sys_version=unknown + else + # Special check for weird MP-RAS system (uname returns weird + # results, and the version is kept in special file). + + if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then + tcl_cv_sys_version=MP-RAS-`awk '{print $3}' /etc/.relid` + fi + if test "`uname -s`" = "AIX" ; then + tcl_cv_sys_version=AIX-`uname -v`.`uname -r` + fi + fi + fi + +fi +echo "$as_me:$LINENO: result: $tcl_cv_sys_version" >&5 +echo "${ECHO_T}$tcl_cv_sys_version" >&6 + system=$tcl_cv_sys_version + + + # Step 2: check for existence of -ldl library. This is needed because + # Linux can use either -ldl or -ldld for dynamic loading. + + echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_dlopen=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 +if test $ac_cv_lib_dl_dlopen = yes; then + have_dl=yes +else + have_dl=no +fi + + + # Require ranlib early so we can override it in special cases below. + + + + # Step 3: set configuration options based on system name and version. + + do64bit_ok=no + # default to '{$LIBS}' and set to "" on per-platform necessary basis + SHLIB_LD_LIBS='${LIBS}' + LDFLAGS_ORIG="$LDFLAGS" + # When ld needs options to work in 64-bit mode, put them in + # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] + # is disabled by the user. [Bug 1016796] + LDFLAGS_ARCH="" + UNSHARED_LIB_SUFFIX="" + TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`' + ECHO_VERSION='`echo ${VERSION}`' + TCL_LIB_VERSIONS_OK=ok + CFLAGS_DEBUG=-g + if test "$GCC" = yes; then + + CFLAGS_OPTIMIZE=-O2 + CFLAGS_WARNING="-Wall" + +else + + CFLAGS_OPTIMIZE=-O + CFLAGS_WARNING="" + +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 +echo "${ECHO_T}$ac_ct_AR" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + AR=$ac_ct_AR +else + AR="$ac_cv_prog_AR" +fi + + STLIB_LD='${AR} cr' + LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" + PLAT_OBJS="" + PLAT_SRCS="" + LDAIX_SRC="" + if test "x${SHLIB_VERSION}" = x; then + SHLIB_VERSION=".1.0" +else + SHLIB_VERSION=".${SHLIB_VERSION}" +fi + + case $system in + AIX-*) + if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"; then + + # AIX requires the _r compiler when gcc isn't being used + case "${CC}" in + *_r|*_r\ *) + # ok ... + ;; + *) + # Make sure only first arg gets _r + CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'` + ;; + esac + echo "$as_me:$LINENO: result: Using $CC for compiling with threads" >&5 +echo "${ECHO_T}Using $CC for compiling with threads" >&6 + +fi + + LIBS="$LIBS -lc" + SHLIB_CFLAGS="" + SHLIB_SUFFIX=".so" + + DL_OBJS="tclLoadDl.o" + LD_LIBRARY_PATH_VAR="LIBPATH" + + # ldAix No longer needed with use of -bexpall/-brtl + # but some extensions may still reference it + LDAIX_SRC='$(UNIX_DIR)/ldAix' + + # Check to enable 64-bit flags for compiler/linker + if test "$do64bit" = yes; then + + if test "$GCC" = yes; then + + { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5 +echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} + +else + + do64bit_ok=yes + CFLAGS="$CFLAGS -q64" + LDFLAGS_ARCH="-q64" + RANLIB="${RANLIB} -X64" + AR="${AR} -X64" + SHLIB_LD_FLAGS="-b64" + +fi + + +fi + + + if test "`uname -m`" = ia64; then + + # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + # AIX-5 has dl* in libc.so + DL_LIBS="" + if test "$GCC" = yes; then + + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + +else + + CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' + +fi + + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + +else + + if test "$GCC" = yes; then + + SHLIB_LD='${CC} -shared -Wl,-bexpall' + +else + + SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" + LDFLAGS="$LDFLAGS -brtl" + +fi + + SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" + DL_LIBS="-ldl" + CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +fi + + ;; + BeOS*) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -nostart' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + + #----------------------------------------------------------- + # Check for inet_ntoa in -lbind, for BeOS (which also needs + # -lsocket, even if the network functions are in -lnet which + # is always linked to, for compatibility. + #----------------------------------------------------------- + echo "$as_me:$LINENO: checking for inet_ntoa in -lbind" >&5 +echo $ECHO_N "checking for inet_ntoa in -lbind... $ECHO_C" >&6 +if test "${ac_cv_lib_bind_inet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbind $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char inet_ntoa (); +int +main () +{ +inet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_bind_inet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_bind_inet_ntoa=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_bind_inet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_bind_inet_ntoa" >&6 +if test $ac_cv_lib_bind_inet_ntoa = yes; then + LIBS="$LIBS -lbind -lsocket" +fi + + ;; + BSD/OS-2.1*|BSD/OS-3*) + SHLIB_CFLAGS="" + SHLIB_LD="shlicc -r" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + BSD/OS-4.*) + SHLIB_CFLAGS="-export-dynamic -fPIC" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="$LDFLAGS -export-dynamic" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + CYGWIN_*|MINGW32*) + SHLIB_CFLAGS="" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".dll" + DL_OBJS="tclLoadDl.o" + PLAT_OBJS='${CYGWIN_OBJS}' + PLAT_SRCS='${CYGWIN_SRCS}' + DL_LIBS="-ldl" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + TCL_NEEDS_EXP_FILE=1 + TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a' + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a" + echo "$as_me:$LINENO: checking for Cygwin version of gcc" >&5 +echo $ECHO_N "checking for Cygwin version of gcc... $ECHO_C" >&6 +if test "${ac_cv_cygwin+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #ifdef __CYGWIN__ + #error cygwin + #endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_cygwin=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_cygwin=yes +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $ac_cv_cygwin" >&5 +echo "${ECHO_T}$ac_cv_cygwin" >&6 + if test "$ac_cv_cygwin" = "no"; then + { { echo "$as_me:$LINENO: error: ${CC} is not a cygwin compiler." >&5 +echo "$as_me: error: ${CC} is not a cygwin compiler." >&2;} + { (exit 1); exit 1; }; } + fi + if test "x${TCL_THREADS}" = "x0"; then + { { echo "$as_me:$LINENO: error: CYGWIN compile is only supported with --enable-threads" >&5 +echo "$as_me: error: CYGWIN compile is only supported with --enable-threads" >&2;} + { (exit 1); exit 1; }; } + fi + do64bit_ok=yes + if test "x${SHARED_BUILD}" = "x1"; then + echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args" + # The eval makes quoting arguments work. + if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args; cd ../unix + then : + else + { echo "configure: error: configure failed for ../win" 1>&2; exit 1; } + fi + fi + ;; + dgux*) + SHLIB_CFLAGS="-K PIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + Haiku*) + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' + DL_OBJS="tclLoadDl.o" + DL_LIBS="-lroot" + echo "$as_me:$LINENO: checking for inet_ntoa in -lnetwork" >&5 +echo $ECHO_N "checking for inet_ntoa in -lnetwork... $ECHO_C" >&6 +if test "${ac_cv_lib_network_inet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnetwork $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char inet_ntoa (); +int +main () +{ +inet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_network_inet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_network_inet_ntoa=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_network_inet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_network_inet_ntoa" >&6 +if test $ac_cv_lib_network_inet_ntoa = yes; then + LIBS="$LIBS -lnetwork" +fi + + ;; + HP-UX-*.11.*) + # Use updated header definitions where possible + +cat >>confdefs.h <<\_ACEOF +#define _XOPEN_SOURCE_EXTENDED 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define _XOPEN_SOURCE 1 +_ACEOF + + LIBS="$LIBS -lxnet" # Use the XOPEN network library + + if test "`uname -m`" = ia64; then + + SHLIB_SUFFIX=".so" + +else + + SHLIB_SUFFIX=".sl" + +fi + + echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load (); +int +main () +{ +shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dld_shl_load=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 +if test $ac_cv_lib_dld_shl_load = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = yes; then + + SHLIB_CFLAGS="+z" + SHLIB_LD="ld -b" + DL_OBJS="tclLoadShl.o" + DL_LIBS="-ldld" + LDFLAGS="$LDFLAGS -Wl,-E" + CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' + LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' + LD_LIBRARY_PATH_VAR="SHLIB_PATH" + +fi + + if test "$GCC" = yes; then + + SHLIB_LD='${CC} -shared' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +else + + CFLAGS="$CFLAGS -z" + +fi + + + # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc + #CFLAGS="$CFLAGS +DAportable" + + # Check to enable 64-bit flags for compiler/linker + if test "$do64bit" = "yes"; then + + if test "$GCC" = yes; then + + case `${CC} -dumpmachine` in + hppa64*) + # 64-bit gcc in use. Fix flags for GNU ld. + do64bit_ok=yes + SHLIB_LD='${CC} -shared' + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ;; + *) + { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5 +echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} + ;; + esac + +else + + do64bit_ok=yes + CFLAGS="$CFLAGS +DD64" + LDFLAGS_ARCH="+DD64" + +fi + + +fi + ;; + HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) + SHLIB_SUFFIX=".sl" + echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load (); +int +main () +{ +shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dld_shl_load=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 +if test $ac_cv_lib_dld_shl_load = yes; then + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = yes; then + + SHLIB_CFLAGS="+z" + SHLIB_LD="ld -b" + SHLIB_LD_LIBS="" + DL_OBJS="tclLoadShl.o" + DL_LIBS="-ldld" + LDFLAGS="$LDFLAGS -Wl,-E" + CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' + LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' + LD_LIBRARY_PATH_VAR="SHLIB_PATH" + +fi + ;; + IRIX-5.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -shared -rdata_shared" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + case $LIBOBJS in + "mkstemp.$ac_objext" | \ + *" mkstemp.$ac_objext" | \ + "mkstemp.$ac_objext "* | \ + *" mkstemp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" ;; +esac + + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + + ;; + IRIX-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + case $LIBOBJS in + "mkstemp.$ac_objext" | \ + *" mkstemp.$ac_objext" | \ + "mkstemp.$ac_objext "* | \ + *" mkstemp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" ;; +esac + + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + + if test "$GCC" = yes; then + + CFLAGS="$CFLAGS -mabi=n32" + LDFLAGS="$LDFLAGS -mabi=n32" + +else + + case $system in + IRIX-6.3) + # Use to build 6.2 compatible binaries on 6.3. + CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" + ;; + *) + CFLAGS="$CFLAGS -n32" + ;; + esac + LDFLAGS="$LDFLAGS -n32" + +fi + + ;; + IRIX64-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + case $LIBOBJS in + "mkstemp.$ac_objext" | \ + *" mkstemp.$ac_objext" | \ + "mkstemp.$ac_objext "* | \ + *" mkstemp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" ;; +esac + + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + + + # Check to enable 64-bit flags for compiler/linker + + if test "$do64bit" = yes; then + + if test "$GCC" = yes; then + + { echo "$as_me:$LINENO: WARNING: 64bit mode not supported by gcc" >&5 +echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;} + +else + + do64bit_ok=yes + SHLIB_LD="ld -64 -shared -rdata_shared" + CFLAGS="$CFLAGS -64" + LDFLAGS_ARCH="-64" + +fi + + +fi + + ;; + Linux*|GNU*|NetBSD-Debian) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + + CFLAGS_OPTIMIZE="-O2" + # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings + # when you inline the string and math operations. Turn this off to + # get rid of the warnings. + #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES" + + SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + if test "`uname -m`" = "alpha"; then + CFLAGS="$CFLAGS -mieee" +fi + + if test $do64bit = yes; then + + echo "$as_me:$LINENO: checking if compiler accepts -m64 flag" >&5 +echo $ECHO_N "checking if compiler accepts -m64 flag... $ECHO_C" >&6 +if test "${tcl_cv_cc_m64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -m64" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_m64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_m64=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_m64" >&5 +echo "${ECHO_T}$tcl_cv_cc_m64" >&6 + if test $tcl_cv_cc_m64 = yes; then + + CFLAGS="$CFLAGS -m64" + do64bit_ok=yes + +fi + + +fi + + + # The combo of gcc + glibc has a bug related to inlining of + # functions like strtod(). The -fno-builtin flag should address + # this problem but it does not work. The -fno-inline flag is kind + # of overkill but it works. Disable inlining only when one of the + # files in compat/*.c is being linked in. + + if test x"${USE_COMPAT}" != x; then + CFLAGS="$CFLAGS -fno-inline" +fi + + ;; + Lynx*) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + CFLAGS_OPTIMIZE=-02 + SHLIB_LD='${CC} -shared' + DL_OBJS="tclLoadDl.o" + DL_LIBS="-mshared -ldl" + LD_FLAGS="-Wl,--export-dynamic" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + + ;; + MP-RAS-02*) + SHLIB_CFLAGS="-K PIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + MP-RAS-*) + SHLIB_CFLAGS="-K PIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="$LDFLAGS -Wl,-Bexport" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + OpenBSD-*) + arch=`arch -s` + case "$arch" in + alpha|sparc64) + SHLIB_CFLAGS="-fPIC" + ;; + *) + SHLIB_CFLAGS="-fpic" + ;; + esac + SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' + LDFLAGS="-Wl,-export-dynamic" + CFLAGS_OPTIMIZE="-O2" + if test "${TCL_THREADS}" = "1"; then + + # On OpenBSD: Compile with -pthread + # Don't link with -lpthread + LIBS=`echo $LIBS | sed s/-lpthread//` + CFLAGS="$CFLAGS -pthread" + +fi + + # OpenBSD doesn't do version numbers with dots. + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + TCL_LIB_VERSIONS_OK=nodots + ;; + NetBSD-*) + # NetBSD has ELF and can use 'cc -shared' to build shared libs + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + LDFLAGS="$LDFLAGS -export-dynamic" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + if test "${TCL_THREADS}" = "1"; then + + # The -pthread needs to go in the CFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + +fi + + ;; + DragonFly-*|FreeBSD-*) + # This configuration from FreeBSD Ports. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="${CC} -shared" + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$@" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + LDFLAGS="" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + + if test "${TCL_THREADS}" = "1"; then + + # The -pthread needs to go in the LDFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LDFLAGS="$LDFLAGS $PTHREAD_LIBS" +fi + + case $system in + FreeBSD-3.*) + # Version numbers are dot-stripped by system policy. + TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .` + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' + TCL_LIB_VERSIONS_OK=nodots + ;; + esac + ;; + Darwin-*) + CFLAGS_OPTIMIZE="-Os" + SHLIB_CFLAGS="-fno-common" + # To avoid discrepancies between what headers configure sees during + # preprocessing tests and compiling tests, move any -isysroot and + # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: + CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`" + CFLAGS="`echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`" + if test $do64bit = yes; then + + case `arch` in + ppc) + echo "$as_me:$LINENO: checking if compiler accepts -arch ppc64 flag" >&5 +echo $ECHO_N "checking if compiler accepts -arch ppc64 flag... $ECHO_C" >&6 +if test "${tcl_cv_cc_arch_ppc64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_arch_ppc64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_arch_ppc64=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_arch_ppc64" >&5 +echo "${ECHO_T}$tcl_cv_cc_arch_ppc64" >&6 + if test $tcl_cv_cc_arch_ppc64 = yes; then + + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + do64bit_ok=yes + +fi +;; + i386) + echo "$as_me:$LINENO: checking if compiler accepts -arch x86_64 flag" >&5 +echo $ECHO_N "checking if compiler accepts -arch x86_64 flag... $ECHO_C" >&6 +if test "${tcl_cv_cc_arch_x86_64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch x86_64" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_arch_x86_64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_arch_x86_64=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_arch_x86_64" >&5 +echo "${ECHO_T}$tcl_cv_cc_arch_x86_64" >&6 + if test $tcl_cv_cc_arch_x86_64 = yes; then + + CFLAGS="$CFLAGS -arch x86_64" + do64bit_ok=yes + +fi +;; + *) + { echo "$as_me:$LINENO: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5 +echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};; + esac + +else + + # Check for combined 32-bit and 64-bit fat build + if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ + && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '; then + + fat_32_64=yes +fi + + +fi + + SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}' + echo "$as_me:$LINENO: checking if ld accepts -single_module flag" >&5 +echo $ECHO_N "checking if ld accepts -single_module flag... $ECHO_C" >&6 +if test "${tcl_cv_ld_single_module+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_ld_single_module=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_ld_single_module=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$hold_ldflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_ld_single_module" >&5 +echo "${ECHO_T}$tcl_cv_ld_single_module" >&6 + if test $tcl_cv_ld_single_module = yes; then + + SHLIB_LD="${SHLIB_LD} -Wl,-single_module" + +fi + + SHLIB_SUFFIX=".dylib" + DL_OBJS="tclLoadDyld.o" + DL_LIBS="" + # Don't use -prebind when building for Mac OS X 10.4 or later only: + if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \ + "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then + + LDFLAGS="$LDFLAGS -prebind" +fi + + LDFLAGS="$LDFLAGS -headerpad_max_install_names" + echo "$as_me:$LINENO: checking if ld accepts -search_paths_first flag" >&5 +echo $ECHO_N "checking if ld accepts -search_paths_first flag... $ECHO_C" >&6 +if test "${tcl_cv_ld_search_paths_first+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_ld_search_paths_first=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_ld_search_paths_first=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$hold_ldflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_ld_search_paths_first" >&5 +echo "${ECHO_T}$tcl_cv_ld_search_paths_first" >&6 + if test $tcl_cv_ld_search_paths_first = yes; then + + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + +fi + + if test "$tcl_cv_cc_visibility_hidden" != yes; then + + +cat >>confdefs.h <<\_ACEOF +#define MODULE_SCOPE __private_extern__ +_ACEOF + + +fi + + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" + +cat >>confdefs.h <<\_ACEOF +#define MAC_OSX_TCL 1 +_ACEOF + + PLAT_OBJS='${MAC_OSX_OBJS}' + PLAT_SRCS='${MAC_OSX_SRCS}' + echo "$as_me:$LINENO: checking whether to use CoreFoundation" >&5 +echo $ECHO_N "checking whether to use CoreFoundation... $ECHO_C" >&6 + # Check whether --enable-corefoundation or --disable-corefoundation was given. +if test "${enable_corefoundation+set}" = set; then + enableval="$enable_corefoundation" + tcl_corefoundation=$enableval +else + tcl_corefoundation=yes +fi; + echo "$as_me:$LINENO: result: $tcl_corefoundation" >&5 +echo "${ECHO_T}$tcl_corefoundation" >&6 + if test $tcl_corefoundation = yes; then + + echo "$as_me:$LINENO: checking for CoreFoundation.framework" >&5 +echo $ECHO_N "checking for CoreFoundation.framework... $ECHO_C" >&6 +if test "${tcl_cv_lib_corefoundation+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_libs=$LIBS + if test "$fat_32_64" = yes; then + + for v in CFLAGS CPPFLAGS LDFLAGS; do + # On Tiger there is no 64-bit CF, so remove 64-bit + # archs from CFLAGS et al. while testing for + # presence of CF. 64-bit CF is disabled in + # tclUnixPort.h if necessary. + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' + done +fi + + LIBS="$LIBS -framework CoreFoundation" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <CoreFoundation/CoreFoundation.h> +int +main () +{ +CFBundleRef b = CFBundleGetMainBundle(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_lib_corefoundation=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_lib_corefoundation=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$fat_32_64" = yes; then + + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done +fi + + LIBS=$hold_libs +fi +echo "$as_me:$LINENO: result: $tcl_cv_lib_corefoundation" >&5 +echo "${ECHO_T}$tcl_cv_lib_corefoundation" >&6 + if test $tcl_cv_lib_corefoundation = yes; then + + LIBS="$LIBS -framework CoreFoundation" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_COREFOUNDATION 1 +_ACEOF + + +else + tcl_corefoundation=no +fi + + if test "$fat_32_64" = yes -a $tcl_corefoundation = yes; then + + echo "$as_me:$LINENO: checking for 64-bit CoreFoundation" >&5 +echo $ECHO_N "checking for 64-bit CoreFoundation... $ECHO_C" >&6 +if test "${tcl_cv_lib_corefoundation_64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <CoreFoundation/CoreFoundation.h> +int +main () +{ +CFBundleRef b = CFBundleGetMainBundle(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_lib_corefoundation_64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_lib_corefoundation_64=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done +fi +echo "$as_me:$LINENO: result: $tcl_cv_lib_corefoundation_64" >&5 +echo "${ECHO_T}$tcl_cv_lib_corefoundation_64" >&6 + if test $tcl_cv_lib_corefoundation_64 = no; then + + +cat >>confdefs.h <<\_ACEOF +#define NO_COREFOUNDATION_64 1 +_ACEOF + + LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings" + +fi + + +fi + + +fi + + ;; + NEXTSTEP-*) + SHLIB_CFLAGS="" + SHLIB_LD='${CC} -nostdlib -r' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadNext.o" + DL_LIBS="" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + OS/390-*) + SHLIB_LD_LIBS="" + CFLAGS_OPTIMIZE="" # Optimizer is buggy + +cat >>confdefs.h <<\_ACEOF +#define _OE_SOCKETS 1 +_ACEOF + + ;; + OSF1-1.0|OSF1-1.1|OSF1-1.2) + # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 + SHLIB_CFLAGS="" + # Hack: make package name same as library name + SHLIB_LD='ld -R -export :' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadOSF.o" + DL_LIBS="" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + OSF1-1.*) + # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 + SHLIB_CFLAGS="-fPIC" + if test "$SHARED_BUILD" = 1; then + SHLIB_LD="ld -shared" +else + + SHLIB_LD="ld -non_shared" + +fi + + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + OSF1-V*) + # Digital OSF/1 + SHLIB_CFLAGS="" + if test "$SHARED_BUILD" = 1; then + + SHLIB_LD='ld -shared -expect_unresolved "*"' + +else + + SHLIB_LD='ld -non_shared -expect_unresolved "*"' + +fi + + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + if test $doRpath = yes; then + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + + if test "$GCC" = yes; then + CFLAGS="$CFLAGS -mieee" +else + + CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" +fi + + # see pthread_intro(3) for pthread support on osf1, k.furukawa + if test "${TCL_THREADS}" = 1; then + + CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" + CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" + LIBS=`echo $LIBS | sed s/-lpthreads//` + if test "$GCC" = yes; then + + LIBS="$LIBS -lpthread -lmach -lexc" + +else + + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + +fi + + +fi + + ;; + QNX-6*) + # QNX RTP + # This may work for all QNX, but it was only reported for v6. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="ld -Bshareable -x" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + # dlopen is in -lc on QNX + DL_LIBS="" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SCO_SV-3.2*) + # Note, dlopen is available only on SCO 3.2.5 and greater. However, + # this test works, since "uname -s" was non-standard in 3.2.4 and + # below. + if test "$GCC" = yes; then + + SHLIB_CFLAGS="-fPIC -melf" + LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" + +else + + SHLIB_CFLAGS="-Kpic -belf" + LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" + +fi + + SHLIB_LD="ld -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SINIX*5.4*) + SHLIB_CFLAGS="-K PIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SunOS-4*) + SHLIB_CFLAGS="-PIC" + SHLIB_LD="ld" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + + # SunOS can't handle version numbers with dots in them in library + # specs, like -ltcl7.5, so use -ltcl75 instead. Also, it + # requires an extra version number at the end of .so file names. + # So, the library has to have a name like libtcl75.so.1.0 + + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + TCL_LIB_VERSIONS_OK=nodots + ;; + SunOS-5.[0-6]) + # Careful to not let 5.10+ fall into this case + + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + +cat >>confdefs.h <<\_ACEOF +#define _REENTRANT 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define _POSIX_PTHREAD_SEMANTICS 1 +_ACEOF + + + SHLIB_CFLAGS="-KPIC" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + if test "$GCC" = yes; then + + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +else + + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +fi + + ;; + SunOS-5*) + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + +cat >>confdefs.h <<\_ACEOF +#define _REENTRANT 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define _POSIX_PTHREAD_SEMANTICS 1 +_ACEOF + + + SHLIB_CFLAGS="-KPIC" + + # Check to enable 64-bit flags for compiler/linker + if test "$do64bit" = yes; then + + arch=`isainfo` + if test "$arch" = "sparcv9 sparc"; then + + if test "$GCC" = yes; then + + if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3; then + + { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 +echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;} + +else + + do64bit_ok=yes + CFLAGS="$CFLAGS -m64 -mcpu=v9" + LDFLAGS="$LDFLAGS -m64 -mcpu=v9" + SHLIB_CFLAGS="-fPIC" + +fi + + +else + + do64bit_ok=yes + if test "$do64bitVIS" = yes; then + + CFLAGS="$CFLAGS -xarch=v9a" + LDFLAGS_ARCH="-xarch=v9a" + +else + + CFLAGS="$CFLAGS -xarch=v9" + LDFLAGS_ARCH="-xarch=v9" + +fi + + # Solaris 64 uses this as well + #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" + +fi + + +else + if test "$arch" = "amd64 i386"; then + + if test "$GCC" = yes; then + + case $system in + SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) + do64bit_ok=yes + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + { echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5 +echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};; + esac + +else + + do64bit_ok=yes + case $system in + SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + CFLAGS="$CFLAGS -xarch=amd64" + LDFLAGS="$LDFLAGS -xarch=amd64";; + esac + +fi + + +else + { echo "$as_me:$LINENO: WARNING: 64bit mode not supported for $arch" >&5 +echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} +fi + +fi + + +fi + + + #-------------------------------------------------------------------- + # On Solaris 5.x i386 with the sunpro compiler we need to link + # with sunmath to get floating point rounding control + #-------------------------------------------------------------------- + if test "$GCC" = yes; then + use_sunmath=no +else + + arch=`isainfo` + echo "$as_me:$LINENO: checking whether to use -lsunmath for fp rounding control" >&5 +echo $ECHO_N "checking whether to use -lsunmath for fp rounding control... $ECHO_C" >&6 + if test "$arch" = "amd64 i386" -o "$arch" = "i386"; then + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + MATH_LIBS="-lsunmath $MATH_LIBS" + if test "${ac_cv_header_sunmath_h+set}" = set; then + echo "$as_me:$LINENO: checking for sunmath.h" >&5 +echo $ECHO_N "checking for sunmath.h... $ECHO_C" >&6 +if test "${ac_cv_header_sunmath_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sunmath_h" >&5 +echo "${ECHO_T}$ac_cv_header_sunmath_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking sunmath.h usability" >&5 +echo $ECHO_N "checking sunmath.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sunmath.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking sunmath.h presence" >&5 +echo $ECHO_N "checking sunmath.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sunmath.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sunmath.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sunmath.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sunmath.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sunmath.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sunmath.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sunmath.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sunmath.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sunmath.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sunmath.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sunmath.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sunmath.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sunmath.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sunmath.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sunmath.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sunmath.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sunmath.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------- ## +## Report this to the tk lists. ## +## ----------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for sunmath.h" >&5 +echo $ECHO_N "checking for sunmath.h... $ECHO_C" >&6 +if test "${ac_cv_header_sunmath_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sunmath_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_sunmath_h" >&5 +echo "${ECHO_T}$ac_cv_header_sunmath_h" >&6 + +fi + + + use_sunmath=yes + +else + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + use_sunmath=no + +fi + + +fi + + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + if test "$GCC" = yes; then + + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + if test "$do64bit_ok" = yes; then + + if test "$arch" = "sparcv9 sparc"; then + + # We need to specify -static-libgcc or we need to + # add the path to the sparv9 libgcc. + SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" + # for finding sparcv9 libgcc, get the regular libgcc + # path, remove so name and append 'sparcv9' + #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." + #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" + +else + if test "$arch" = "amd64 i386"; then + + SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" + +fi + +fi + + +fi + + +else + + if test "$use_sunmath" = yes; then + textmode=textoff +else + textmode=text +fi + + case $system in + SunOS-5.[1-9][0-9]*|SunOS-5.[7-9]) + SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";; + *) + SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";; + esac + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + +fi + + ;; + UNIX_SV* | UnixWare-5*) + SHLIB_CFLAGS="-KPIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers + # that don't grok the -Bexport option. Test that it does. + echo "$as_me:$LINENO: checking for ld accepts -Bexport flag" >&5 +echo $ECHO_N "checking for ld accepts -Bexport flag... $ECHO_C" >&6 +if test "${tcl_cv_ld_Bexport+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-Bexport" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_ld_Bexport=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_ld_Bexport=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$hold_ldflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_ld_Bexport" >&5 +echo "${ECHO_T}$tcl_cv_ld_Bexport" >&6 + if test $tcl_cv_ld_Bexport = yes; then + + LDFLAGS="$LDFLAGS -Wl,-Bexport" + +fi + + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + esac + + if test "$do64bit" = yes -a "$do64bit_ok" = no; then + + { echo "$as_me:$LINENO: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 +echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} + +fi + + + if test "$do64bit" = yes -a "$do64bit_ok" = yes; then + + +cat >>confdefs.h <<\_ACEOF +#define TCL_CFG_DO64BIT 1 +_ACEOF + + +fi + + + + + # Step 4: disable dynamic loading if requested via a command-line switch. + + # Check whether --enable-load or --disable-load was given. +if test "${enable_load+set}" = set; then + enableval="$enable_load" + tcl_ok=$enableval +else + tcl_ok=yes +fi; + if test "$tcl_ok" = no; then + DL_OBJS="" +fi + + + if test "x$DL_OBJS" != x; then + BUILD_DLTEST="\$(DLTEST_TARGETS)" +else + + { echo "$as_me:$LINENO: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&5 +echo "$as_me: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&2;} + SHLIB_CFLAGS="" + SHLIB_LD="" + SHLIB_SUFFIX="" + DL_OBJS="tclLoadNone.o" + DL_LIBS="" + LDFLAGS="$LDFLAGS_ORIG" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + BUILD_DLTEST="" + +fi + + LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" + + # If we're running gcc, then change the C flags for compiling shared + # libraries to the right flags for gcc, instead of those for the + # standard manufacturer compiler. + + if test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes; then + + case $system in + AIX-*) ;; + BSD/OS*) ;; + CYGWIN_*|MINGW32_*) ;; + IRIX*) ;; + NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; + Darwin-*) ;; + SCO_SV-3.2*) ;; + *) SHLIB_CFLAGS="-fPIC" ;; + esac +fi + + + if test "$tcl_cv_cc_visibility_hidden" != yes; then + + +cat >>confdefs.h <<\_ACEOF +#define MODULE_SCOPE extern +_ACEOF + + +fi + + + if test "$SHARED_LIB_SUFFIX" = ""; then + + SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}' +fi + + if test "$UNSHARED_LIB_SUFFIX" = ""; then + + UNSHARED_LIB_SUFFIX='${VERSION}.a' +fi + + DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)" + + if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then + + LIB_SUFFIX=${SHARED_LIB_SUFFIX} + MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' + if test "${SHLIB_SUFFIX}" = ".dll"; then + + INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;' + DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)" + +else + + INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"' + +fi + + +else + + LIB_SUFFIX=${UNSHARED_LIB_SUFFIX} + + if test "$RANLIB" = ""; then + + MAKE_LIB='$(STLIB_LD) $@ ${OBJS}' + +else + + MAKE_LIB='${STLIB_LD} $@ ${OBJS} ; ${RANLIB} $@' + +fi + + INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"' + +fi + + + # Stub lib does not depend on shared/static configuration + if test "$RANLIB" = ""; then + + MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS}' + +else + + MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS} ; ${RANLIB} $@' + +fi + + INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)"' + + # Define TCL_LIBS now that we know what DL_LIBS is. + # The trick here is that we don't want to change the value of TCL_LIBS if + # it is already set when tclConfig.sh had been loaded by Tk. + if test "x${TCL_LIBS}" = x; then + + TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}" +fi + + + + # See if the compiler supports casting to a union type. + # This is used to stop gcc from printing a compiler + # warning when initializing a union member. + + echo "$as_me:$LINENO: checking for cast to union support" >&5 +echo $ECHO_N "checking for cast to union support... $ECHO_C" >&6 +if test "${tcl_cv_cast_to_union+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + union foo { int i; double d; }; + union foo f = (union foo) (int) 0; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cast_to_union=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cast_to_union=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $tcl_cv_cast_to_union" >&5 +echo "${ECHO_T}$tcl_cv_cast_to_union" >&6 + if test "$tcl_cv_cast_to_union" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_CAST_TO_UNION 1 +_ACEOF + + fi + + # FIXME: This subst was left in only because the TCL_DL_LIBS + # entry in tclConfig.sh uses it. It is not clear why someone + # would use TCL_DL_LIBS instead of TCL_LIBS. + + + + + + + + + + + + + + + + + + + + + + + + + +cat >>confdefs.h <<_ACEOF +#define TCL_SHLIB_EXT "${SHLIB_SUFFIX}" +_ACEOF + + + + + + + + + + + + echo "$as_me:$LINENO: checking for build with symbols" >&5 +echo $ECHO_N "checking for build with symbols... $ECHO_C" >&6 + # Check whether --enable-symbols or --disable-symbols was given. +if test "${enable_symbols+set}" = set; then + enableval="$enable_symbols" + tcl_ok=$enableval +else + tcl_ok=no +fi; +# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT. + DBGX="" + if test "$tcl_ok" = "no"; then + CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)' + LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)' + +cat >>confdefs.h <<\_ACEOF +#define NDEBUG 1 +_ACEOF + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +cat >>confdefs.h <<\_ACEOF +#define TCL_CFG_OPTIMIZED 1 +_ACEOF + + else + CFLAGS_DEFAULT='$(CFLAGS_DEBUG)' + LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)' + if test "$tcl_ok" = "yes"; then + echo "$as_me:$LINENO: result: yes (standard debugging)" >&5 +echo "${ECHO_T}yes (standard debugging)" >&6 + fi + fi + + + + if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then + +cat >>confdefs.h <<\_ACEOF +#define TCL_MEM_DEBUG 1 +_ACEOF + + fi + + + + if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then + if test "$tcl_ok" = "all"; then + echo "$as_me:$LINENO: result: enabled symbols mem debugging" >&5 +echo "${ECHO_T}enabled symbols mem debugging" >&6 + else + echo "$as_me:$LINENO: result: enabled $tcl_ok debugging" >&5 +echo "${ECHO_T}enabled $tcl_ok debugging" >&6 + fi + fi + + +#-------------------------------------------------------------------- +# Detect what compiler flags to set for 64-bit support. +#-------------------------------------------------------------------- + + + echo "$as_me:$LINENO: checking for required early compiler flags" >&5 +echo $ECHO_N "checking for required early compiler flags... $ECHO_C" >&6 + tcl_flags="" + + if test "${tcl_cv_flag__isoc99_source+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +int +main () +{ +char *p = (char *)strtoll; char *q = (char *)strtoull; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_flag__isoc99_source=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _ISOC99_SOURCE 1 +#include <stdlib.h> +int +main () +{ +char *p = (char *)strtoll; char *q = (char *)strtoull; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_flag__isoc99_source=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_flag__isoc99_source=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define _ISOC99_SOURCE 1 +_ACEOF + + tcl_flags="$tcl_flags _ISOC99_SOURCE" + fi + + + if test "${tcl_cv_flag__largefile64_source+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +struct stat64 buf; int i = stat64("/", &buf); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_flag__largefile64_source=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _LARGEFILE64_SOURCE 1 +#include <sys/stat.h> +int +main () +{ +struct stat64 buf; int i = stat64("/", &buf); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_flag__largefile64_source=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_flag__largefile64_source=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__largefile64_source}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define _LARGEFILE64_SOURCE 1 +_ACEOF + + tcl_flags="$tcl_flags _LARGEFILE64_SOURCE" + fi + + + if test "${tcl_cv_flag__largefile_source64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +char *p = (char *)open64; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_flag__largefile_source64=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _LARGEFILE_SOURCE64 1 +#include <sys/stat.h> +int +main () +{ +char *p = (char *)open64; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_flag__largefile_source64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_flag__largefile_source64=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__largefile_source64}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define _LARGEFILE_SOURCE64 1 +_ACEOF + + tcl_flags="$tcl_flags _LARGEFILE_SOURCE64" + fi + + if test "x${tcl_flags}" = "x" ; then + echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6 + else + echo "$as_me:$LINENO: result: ${tcl_flags}" >&5 +echo "${ECHO_T}${tcl_flags}" >&6 + fi + + + + echo "$as_me:$LINENO: checking for 64-bit integer type" >&5 +echo $ECHO_N "checking for 64-bit integer type... $ECHO_C" >&6 + if test "${tcl_cv_type_64bit+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + tcl_cv_type_64bit=none + # See if the compiler knows natively about __int64 + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +__int64 value = (__int64) 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_type_64bit=__int64 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_type_64bit="long long" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + # See if we should use long anyway Note that we substitute in the + # type that is our current guess for a 64-bit type inside this check + # program, so it should be modified only carefully... + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +switch (0) { + case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; + } + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_type_64bit=${tcl_type_64bit} +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "${tcl_cv_type_64bit}" = none ; then + +cat >>confdefs.h <<\_ACEOF +#define TCL_WIDE_INT_IS_LONG 1 +_ACEOF + + echo "$as_me:$LINENO: result: using long" >&5 +echo "${ECHO_T}using long" >&6 + else + +cat >>confdefs.h <<_ACEOF +#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit} +_ACEOF + + echo "$as_me:$LINENO: result: ${tcl_cv_type_64bit}" >&5 +echo "${ECHO_T}${tcl_cv_type_64bit}" >&6 + + # Now check for auxiliary declarations + echo "$as_me:$LINENO: checking for struct dirent64" >&5 +echo $ECHO_N "checking for struct dirent64... $ECHO_C" >&6 +if test "${tcl_cv_struct_dirent64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <dirent.h> +int +main () +{ +struct dirent64 p; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_struct_dirent64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_struct_dirent64=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_struct_dirent64" >&5 +echo "${ECHO_T}$tcl_cv_struct_dirent64" >&6 + if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STRUCT_DIRENT64 1 +_ACEOF + + fi + + echo "$as_me:$LINENO: checking for DIR64" >&5 +echo $ECHO_N "checking for DIR64... $ECHO_C" >&6 +if test "${tcl_cv_DIR64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <dirent.h> +int +main () +{ +struct dirent64 *p; DIR64 d = opendir64("."); + p = readdir64(d); rewinddir64(d); closedir64(d); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_DIR64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_DIR64=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_DIR64" >&5 +echo "${ECHO_T}$tcl_cv_DIR64" >&6 + if test "x${tcl_cv_DIR64}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DIR64 1 +_ACEOF + + fi + + echo "$as_me:$LINENO: checking for struct stat64" >&5 +echo $ECHO_N "checking for struct stat64... $ECHO_C" >&6 +if test "${tcl_cv_struct_stat64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +struct stat64 p; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_struct_stat64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_struct_stat64=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_struct_stat64" >&5 +echo "${ECHO_T}$tcl_cv_struct_stat64" >&6 + if test "x${tcl_cv_struct_stat64}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STRUCT_STAT64 1 +_ACEOF + + fi + + + +for ac_func in open64 lseek64 +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + echo "$as_me:$LINENO: checking for off64_t" >&5 +echo $ECHO_N "checking for off64_t... $ECHO_C" >&6 + if test "${tcl_cv_type_off64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +int +main () +{ +off64_t offset; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_type_off64_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_type_off64_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_type_off64_t}" = "xyes" && \ + test "x${ac_cv_func_lseek64}" = "xyes" && \ + test "x${ac_cv_func_open64}" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TYPE_OFF64_T 1 +_ACEOF + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + fi + fi + + +#-------------------------------------------------------------------- +# Check endianness because we can optimize some operations +#-------------------------------------------------------------------- + +echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/param.h> + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/param.h> + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_bigendian=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +# It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int +main () +{ + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6 +case $ac_cv_c_bigendian in + yes) + +cat >>confdefs.h <<\_ACEOF +#define WORDS_BIGENDIAN 1 +_ACEOF + ;; + no) + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +#------------------------------------------------------------------------ +# If Tcl and Tk are installed in different places, adjust the library +# search path to reflect this. +#------------------------------------------------------------------------ + +LIB_RUNTIME_DIR='$(libdir)' + +if test "$TCL_EXEC_PREFIX" != "$exec_prefix"; then + LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${TCL_EXEC_PREFIX}/lib" +fi + +if test "$TCL_PREFIX" != "$prefix"; then + { echo "$as_me:$LINENO: WARNING: + Different --prefix selected for Tk and Tcl! + [package require Tk] may not work correctly in tclsh." >&5 +echo "$as_me: WARNING: + Different --prefix selected for Tk and Tcl! + [package require Tk] may not work correctly in tclsh." >&2;} +fi + +#-------------------------------------------------------------------- +# Include sys/select.h if it exists and if it supplies things +# that appear to be useful and aren't already in sys/types.h. +# This appears to be true only on the RS/6000 under AIX. Some +# systems like OSF/1 have a sys/select.h that's of no use, and +# other systems like SCO UNIX have a sys/select.h that's +# pernicious. If "fd_set" isn't defined anywhere then set a +# special flag. +#-------------------------------------------------------------------- + +echo "$as_me:$LINENO: checking for fd_set in sys/types" >&5 +echo $ECHO_N "checking for fd_set in sys/types... $ECHO_C" >&6 +if test "${tcl_cv_type_fd_set+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +int +main () +{ +fd_set readMask, writeMask; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_type_fd_set=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_type_fd_set=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_type_fd_set" >&5 +echo "${ECHO_T}$tcl_cv_type_fd_set" >&6 +tk_ok=$tcl_cv_type_fd_set +if test $tk_ok = no; then + echo "$as_me:$LINENO: checking for fd_mask in sys/select" >&5 +echo $ECHO_N "checking for fd_mask in sys/select... $ECHO_C" >&6 +if test "${tcl_cv_grep_fd_mask+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/select.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "fd_mask" >/dev/null 2>&1; then + tcl_cv_grep_fd_mask=present +else + tcl_cv_grep_fd_mask=missing +fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $tcl_cv_grep_fd_mask" >&5 +echo "${ECHO_T}$tcl_cv_grep_fd_mask" >&6 + if test $tcl_cv_grep_fd_mask = present; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_SELECT_H 1 +_ACEOF + + tk_ok=yes + fi +fi +if test $tk_ok = no; then + +cat >>confdefs.h <<\_ACEOF +#define NO_FD_SET 1 +_ACEOF + +fi + +#------------------------------------------------------------------------------ +# Find out all about time handling differences. +#------------------------------------------------------------------------------ + + +for ac_header in sys/time.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------- ## +## Report this to the tk lists. ## +## ----------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 +echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6 +if test "${ac_cv_header_time+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/time.h> +#include <time.h> + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_time=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_time=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 +echo "${ECHO_T}$ac_cv_header_time" >&6 +if test $ac_cv_header_time = yes; then + +cat >>confdefs.h <<\_ACEOF +#define TIME_WITH_SYS_TIME 1 +_ACEOF + +fi + + +#-------------------------------------------------------------------- +# Check for various typedefs and provide substitutes if +# they don't exist. +#-------------------------------------------------------------------- + +echo "$as_me:$LINENO: checking for mode_t" >&5 +echo $ECHO_N "checking for mode_t... $ECHO_C" >&6 +if test "${ac_cv_type_mode_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((mode_t *) 0) + return 0; +if (sizeof (mode_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_mode_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_mode_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_mode_t" >&5 +echo "${ECHO_T}$ac_cv_type_mode_t" >&6 +if test $ac_cv_type_mode_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define mode_t int +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for pid_t" >&5 +echo $ECHO_N "checking for pid_t... $ECHO_C" >&6 +if test "${ac_cv_type_pid_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((pid_t *) 0) + return 0; +if (sizeof (pid_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_pid_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_pid_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 +echo "${ECHO_T}$ac_cv_type_pid_t" >&6 +if test $ac_cv_type_pid_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for size_t" >&5 +echo $ECHO_N "checking for size_t... $ECHO_C" >&6 +if test "${ac_cv_type_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((size_t *) 0) + return 0; +if (sizeof (size_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_size_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_size_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 +echo "${ECHO_T}$ac_cv_type_size_t" >&6 +if test $ac_cv_type_size_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for uid_t in sys/types.h" >&5 +echo $ECHO_N "checking for uid_t in sys/types.h... $ECHO_C" >&6 +if test "${ac_cv_type_uid_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uid_t" >/dev/null 2>&1; then + ac_cv_type_uid_t=yes +else + ac_cv_type_uid_t=no +fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $ac_cv_type_uid_t" >&5 +echo "${ECHO_T}$ac_cv_type_uid_t" >&6 +if test $ac_cv_type_uid_t = no; then + +cat >>confdefs.h <<\_ACEOF +#define uid_t int +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define gid_t int +_ACEOF + +fi + + +echo "$as_me:$LINENO: checking for intptr_t" >&5 +echo $ECHO_N "checking for intptr_t... $ECHO_C" >&6 +if test "${ac_cv_type_intptr_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((intptr_t *) 0) + return 0; +if (sizeof (intptr_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_intptr_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_intptr_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_intptr_t" >&5 +echo "${ECHO_T}$ac_cv_type_intptr_t" >&6 +if test $ac_cv_type_intptr_t = yes; then + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_INTPTR_T 1 +_ACEOF + +else + + echo "$as_me:$LINENO: checking for pointer-size signed integer type" >&5 +echo $ECHO_N "checking for pointer-size signed integer type... $ECHO_C" >&6 +if test "${tcl_cv_intptr_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + for tcl_cv_intptr_t in "int" "long" "long long" none; do + if test "$tcl_cv_intptr_t" != none; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_intptr_t))]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_ok=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_ok=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + test "$tcl_ok" = yes && break; fi + done +fi +echo "$as_me:$LINENO: result: $tcl_cv_intptr_t" >&5 +echo "${ECHO_T}$tcl_cv_intptr_t" >&6 + if test "$tcl_cv_intptr_t" != none; then + +cat >>confdefs.h <<_ACEOF +#define intptr_t $tcl_cv_intptr_t +_ACEOF + + fi + +fi + +echo "$as_me:$LINENO: checking for uintptr_t" >&5 +echo $ECHO_N "checking for uintptr_t... $ECHO_C" >&6 +if test "${ac_cv_type_uintptr_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((uintptr_t *) 0) + return 0; +if (sizeof (uintptr_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_uintptr_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_uintptr_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_uintptr_t" >&5 +echo "${ECHO_T}$ac_cv_type_uintptr_t" >&6 +if test $ac_cv_type_uintptr_t = yes; then + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_UINTPTR_T 1 +_ACEOF + +else + + echo "$as_me:$LINENO: checking for pointer-size unsigned integer type" >&5 +echo $ECHO_N "checking for pointer-size unsigned integer type... $ECHO_C" >&6 +if test "${tcl_cv_uintptr_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \ + none; do + if test "$tcl_cv_uintptr_t" != none; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_uintptr_t))]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_ok=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_ok=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + test "$tcl_ok" = yes && break; fi + done +fi +echo "$as_me:$LINENO: result: $tcl_cv_uintptr_t" >&5 +echo "${ECHO_T}$tcl_cv_uintptr_t" >&6 + if test "$tcl_cv_uintptr_t" != none; then + +cat >>confdefs.h <<_ACEOF +#define uintptr_t $tcl_cv_uintptr_t +_ACEOF + + fi + +fi + + +#------------------------------------------- +# In OS/390 struct pwd has no pw_gecos field +#------------------------------------------- + +echo "$as_me:$LINENO: checking pw_gecos in struct pwd" >&5 +echo $ECHO_N "checking pw_gecos in struct pwd... $ECHO_C" >&6 +if test "${tcl_cv_pwd_pw_gecos+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <pwd.h> +int +main () +{ +struct passwd pwd; pwd.pw_gecos; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_pwd_pw_gecos=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_pwd_pw_gecos=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $tcl_cv_pwd_pw_gecos" >&5 +echo "${ECHO_T}$tcl_cv_pwd_pw_gecos" >&6 +if test $tcl_cv_pwd_pw_gecos = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PW_GECOS 1 +_ACEOF + +fi + +#-------------------------------------------------------------------- +# On Mac OS X, we can build either with X11 or with Aqua +#-------------------------------------------------------------------- + +if test "`uname -s`" = "Darwin" ; then + echo "$as_me:$LINENO: checking whether to use Aqua" >&5 +echo $ECHO_N "checking whether to use Aqua... $ECHO_C" >&6 + # Check whether --enable-aqua or --disable-aqua was given. +if test "${enable_aqua+set}" = set; then + enableval="$enable_aqua" + tk_aqua=$enableval +else + tk_aqua=no +fi; + if test $tk_aqua = yes -o $tk_aqua = cocoa; then + tk_aqua=yes + if test $tcl_corefoundation = no; then + { echo "$as_me:$LINENO: WARNING: Aqua can only be used when CoreFoundation is available" >&5 +echo "$as_me: WARNING: Aqua can only be used when CoreFoundation is available" >&2;} + tk_aqua=no + fi + if test ! -d /System/Library/Frameworks/Cocoa.framework; then + { echo "$as_me:$LINENO: WARNING: Aqua can only be used when Cocoa is available" >&5 +echo "$as_me: WARNING: Aqua can only be used when Cocoa is available" >&2;} + tk_aqua=no + fi + if test "`uname -r | awk -F. '{print $1}'`" -lt 9; then + { echo "$as_me:$LINENO: WARNING: Aqua requires Mac OS X 10.5 or later" >&5 +echo "$as_me: WARNING: Aqua requires Mac OS X 10.5 or later" >&2;} + tk_aqua=no + fi + fi + echo "$as_me:$LINENO: result: $tk_aqua" >&5 +echo "${ECHO_T}$tk_aqua" >&6 + if test "$fat_32_64" = yes; then + if test $tk_aqua = no; then + echo "$as_me:$LINENO: checking for 64-bit X11" >&5 +echo $ECHO_N "checking for 64-bit X11... $ECHO_C" >&6 +if test "${tcl_cv_lib_x11_64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" + LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Xlib.h> +int +main () +{ +XrmInitialize(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_lib_x11_64=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_lib_x11_64=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done +fi +echo "$as_me:$LINENO: result: $tcl_cv_lib_x11_64" >&5 +echo "${ECHO_T}$tcl_cv_lib_x11_64" >&6 + fi + # remove 64-bit arch flags from CFLAGS et al. for combined 32 & 64 bit + # fat builds if configuration does not support 64-bit. + if test "$tcl_cv_lib_x11_64" = no; then + { echo "$as_me:$LINENO: Removing 64-bit architectures from compiler & linker flags" >&5 +echo "$as_me: Removing 64-bit architectures from compiler & linker flags" >&6;} + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' + done + fi + fi + if test $tk_aqua = no; then + # check if weak linking whole libraries is possible. + echo "$as_me:$LINENO: checking if ld accepts -weak-l flag" >&5 +echo $ECHO_N "checking if ld accepts -weak-l flag... $ECHO_C" >&6 +if test "${tcl_cv_ld_weak_l+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-weak-lm" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <math.h> +int +main () +{ +double f = sin(1.0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_ld_weak_l=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_ld_weak_l=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$hold_ldflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_ld_weak_l" >&5 +echo "${ECHO_T}$tcl_cv_ld_weak_l" >&6 + fi + +for ac_header in AvailabilityMacros.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ----------------------------- ## +## Report this to the tk lists. ## +## ----------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + if test "$ac_cv_header_AvailabilityMacros_h" = yes; then + echo "$as_me:$LINENO: checking if weak import is available" >&5 +echo $ECHO_N "checking if weak import is available... $ECHO_C" >&6 +if test "${tcl_cv_cc_weak_import+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ + #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020 + #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020 + #endif + #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1020 + #error MAC_OS_X_VERSION_MIN_REQUIRED < 1020 + #endif + int rand(void) __attribute__((weak_import)); + +int +main () +{ +rand(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_weak_import=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_weak_import=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_weak_import" >&5 +echo "${ECHO_T}$tcl_cv_cc_weak_import" >&6 + if test $tcl_cv_cc_weak_import = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_WEAK_IMPORT 1 +_ACEOF + + fi + echo "$as_me:$LINENO: checking if Darwin SUSv3 extensions are available" >&5 +echo $ECHO_N "checking if Darwin SUSv3 extensions are available... $ECHO_C" >&6 +if test "${tcl_cv_cc_darwin_c_source+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ + #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050 + #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050 + #endif + #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + #endif + #define _DARWIN_C_SOURCE 1 + #include <sys/cdefs.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + tcl_cv_cc_darwin_c_source=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +tcl_cv_cc_darwin_c_source=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +echo "$as_me:$LINENO: result: $tcl_cv_cc_darwin_c_source" >&5 +echo "${ECHO_T}$tcl_cv_cc_darwin_c_source" >&6 + if test $tcl_cv_cc_darwin_c_source = yes; then + +cat >>confdefs.h <<\_ACEOF +#define _DARWIN_C_SOURCE 1 +_ACEOF + + fi + fi +else + tk_aqua=no +fi + +if test $tk_aqua = yes; then + +cat >>confdefs.h <<\_ACEOF +#define MAC_OSX_TK 1 +_ACEOF + + LIBS="$LIBS -framework Cocoa -framework Carbon -framework IOKit" + EXTRA_CC_SWITCHES='-std=gnu99 -x objective-c' + TK_WINDOWINGSYSTEM=AQUA + if test -n "${enable_symbols}" -a "${enable_symbols}" != no; then + +cat >>confdefs.h <<\_ACEOF +#define TK_MAC_DEBUG 1 +_ACEOF + + fi +else + #-------------------------------------------------------------------- + # Locate the X11 header files and the X11 library archive. Try + # the ac_path_x macro first, but if it doesn't find the X stuff + # (e.g. because there's no xmkmf program) then check through + # a list of possible directories. Under some conditions the + # autoconf macro will return an include directory that contains + # no include files, so double-check its result just to be safe. + #-------------------------------------------------------------------- + + + echo "$as_me:$LINENO: checking for X" >&5 +echo $ECHO_N "checking for X... $ECHO_C" >&6 + + +# Check whether --with-x or --without-x was given. +if test "${with_x+set}" = set; then + withval="$with_x" + +fi; +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then + # Both variables are already set. + have_x=yes + else + if test "${ac_cv_have_x+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -fr conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat >Imakefile <<'_ACEOF' +acfindx: + @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' +_ACEOF + if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl; do + if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && + test -f $ac_im_libdir/libX11.$ac_extension; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /lib) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -fr conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Intrinsic.h. + # First, try using that file with no special directory specified. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Intrinsic.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # We can compile using X headers with no special include directory. +ac_x_includes= +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Intrinsic.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lXt $LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Intrinsic.h> +int +main () +{ +XtMalloc (0) + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +LIBS=$ac_save_LIBS +for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl; do + if test -r $ac_dir/libXt.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +if test "$ac_x_includes" = no || test "$ac_x_libraries" = no; then + # Didn't find X anywhere. Cache the known absence of X. + ac_cv_have_x="have_x=no" +else + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" +fi +fi + + fi + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + echo "$as_me:$LINENO: result: $have_x" >&5 +echo "${ECHO_T}$have_x" >&6 + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$x_includes ac_x_libraries=$x_libraries" + echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 +echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6 +fi + + not_really_there="" + if test "$no_x" = ""; then + if test "$x_includes" = ""; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Xlib.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + not_really_there="yes" +fi +rm -f conftest.err conftest.$ac_ext + else + if test ! -r $x_includes/X11/Xlib.h; then + not_really_there="yes" + fi + fi + fi + if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then + echo "$as_me:$LINENO: checking for X11 header files" >&5 +echo $ECHO_N "checking for X11 header files... $ECHO_C" >&6 + found_xincludes="no" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Xlib.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + found_xincludes="yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + found_xincludes="no" +fi +rm -f conftest.err conftest.$ac_ext + if test "$found_xincludes" = "no"; then + dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" + for i in $dirs ; do + if test -r $i/X11/Xlib.h; then + echo "$as_me:$LINENO: result: $i" >&5 +echo "${ECHO_T}$i" >&6 + XINCLUDES=" -I$i" + found_xincludes="yes" + break + fi + done + fi + else + if test "$x_includes" != ""; then + XINCLUDES="-I$x_includes" + found_xincludes="yes" + fi + fi + if test "$found_xincludes" = "no"; then + echo "$as_me:$LINENO: result: couldn't find any!" >&5 +echo "${ECHO_T}couldn't find any!" >&6 + fi + + if test "$no_x" = yes; then + echo "$as_me:$LINENO: checking for X11 libraries" >&5 +echo $ECHO_N "checking for X11 libraries... $ECHO_C" >&6 + XLIBSW=nope + dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" + for i in $dirs ; do + if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then + echo "$as_me:$LINENO: result: $i" >&5 +echo "${ECHO_T}$i" >&6 + XLIBSW="-L$i -lX11" + x_libraries="$i" + break + fi + done + else + if test "$x_libraries" = ""; then + XLIBSW=-lX11 + else + XLIBSW="-L$x_libraries -lX11" + fi + fi + if test "$XLIBSW" = nope ; then + echo "$as_me:$LINENO: checking for XCreateWindow in -lXwindow" >&5 +echo $ECHO_N "checking for XCreateWindow in -lXwindow... $ECHO_C" >&6 +if test "${ac_cv_lib_Xwindow_XCreateWindow+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXwindow $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XCreateWindow (); +int +main () +{ +XCreateWindow (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xwindow_XCreateWindow=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xwindow_XCreateWindow=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xwindow_XCreateWindow" >&5 +echo "${ECHO_T}$ac_cv_lib_Xwindow_XCreateWindow" >&6 +if test $ac_cv_lib_Xwindow_XCreateWindow = yes; then + XLIBSW=-lXwindow +fi + + fi + if test "$XLIBSW" = nope ; then + echo "$as_me:$LINENO: result: could not find any! Using -lX11." >&5 +echo "${ECHO_T}could not find any! Using -lX11." >&6 + XLIBSW=-lX11 + fi + + TK_WINDOWINGSYSTEM=X11 +fi + +#-------------------------------------------------------------------- +# Various manipulations on the search path used at runtime to +# find shared libraries: +# 1. If the X library binaries are in a non-standard directory, +# add the X library location into that search path. +# 2. On systems such as AIX and Ultrix that use "-L" as the +# search path option, colons cannot be used to separate +# directories from each other. Change colons to " -L". +# 3. Create two sets of search flags, one for use in cc lines +# and the other for when the linker is invoked directly. In +# the second case, '-Wl,' must be stripped off and commas must +# be replaced by spaces. +#-------------------------------------------------------------------- + +if test "x${x_libraries}" != "x"; then + if test "x${x_libraries}" != "xNONE"; then + LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${x_libraries}" + fi +fi +if test "${TCL_LD_SEARCH_FLAGS}" = '-L${LIB_RUNTIME_DIR}'; then + LIB_RUNTIME_DIR=`echo ${LIB_RUNTIME_DIR} |sed -e 's/:/ -L/g'` +fi + +#-------------------------------------------------------------------- +# Check for the existence of various libraries. The order here +# is important, so that then end up in the right order in the +# command line generated by make. The -lsocket and -lnsl libraries +# require a couple of special tricks: +# 1. Use "connect" and "accept" to check for -lsocket, and +# "gethostbyname" to check for -lnsl. +# 2. Use each function name only once: can't redo a check because +# autoconf caches the results of the last check and won't redo it. +# 3. Use -lnsl and -lsocket only if they supply procedures that +# aren't already present in the normal libraries. This is because +# IRIX 5.2 has libraries, but they aren't needed and they're +# bogus: they goof up name resolution if used. +# 4. On some SVR4 systems, can't use -lsocket without -lnsl too. +# To get around this problem, check for both libraries together +# if -lsocket doesn't work by itself. +#-------------------------------------------------------------------- + +if test $tk_aqua = no; then + echo "$as_me:$LINENO: checking for main in -lXbsd" >&5 +echo $ECHO_N "checking for main in -lXbsd... $ECHO_C" >&6 +if test "${ac_cv_lib_Xbsd_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXbsd $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xbsd_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xbsd_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xbsd_main" >&5 +echo "${ECHO_T}$ac_cv_lib_Xbsd_main" >&6 +if test $ac_cv_lib_Xbsd_main = yes; then + LIBS="$LIBS -lXbsd" +fi + +fi + +#-------------------------------------------------------------------- +# One more check related to the X libraries. The standard releases +# of Ultrix don't support the "xauth" mechanism, so send won't work +# unless TK_NO_SECURITY is defined. However, there are usually copies +# of the MIT X server available as well, which do support xauth. +# Check for the MIT stuff and use it if it exists. +# +# Note: can't use ac_check_lib macro (at least, not in Autoconf 2.1) +# because it can't deal with the "-" in the library name. +#-------------------------------------------------------------------- + +if test -d /usr/include/mit -a $tk_aqua = no; then + echo "$as_me:$LINENO: checking MIT X libraries" >&5 +echo $ECHO_N "checking MIT X libraries... $ECHO_C" >&6 + tk_oldCFlags=$CFLAGS + CFLAGS="$CFLAGS -I/usr/include/mit" + tk_oldLibs=$LIBS + LIBS="$LIBS -lX11-mit" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include <X11/Xlib.h> + +int +main () +{ + + XOpenDisplay(0); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + XLIBSW="-lX11-mit" + XINCLUDES="-I/usr/include/mit" + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$tk_oldCFlags + LIBS=$tk_oldLibs +fi + +#-------------------------------------------------------------------- +# Check for freetype / fontconfig / Xft support. +#-------------------------------------------------------------------- + +if test $tk_aqua = no; then + echo "$as_me:$LINENO: checking whether to use xft" >&5 +echo $ECHO_N "checking whether to use xft... $ECHO_C" >&6 + # Check whether --enable-xft or --disable-xft was given. +if test "${enable_xft+set}" = set; then + enableval="$enable_xft" + enable_xft=$enableval +else + enable_xft="default" +fi; + XFT_CFLAGS="" + XFT_LIBS="" + if test "$enable_xft" = "no" ; then + echo "$as_me:$LINENO: result: $enable_xft" >&5 +echo "${ECHO_T}$enable_xft" >&6 + else + found_xft="yes" + XFT_CFLAGS=`xft-config --cflags 2>/dev/null` || found_xft="no" + XFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft="no" + if test "$found_xft" = "no" ; then + found_xft=yes + XFT_CFLAGS=`pkg-config --cflags xft 2>/dev/null` || found_xft="no" + XFT_LIBS=`pkg-config --libs xft 2>/dev/null` || found_xft="no" + fi + echo "$as_me:$LINENO: result: $found_xft" >&5 +echo "${ECHO_T}$found_xft" >&6 + if test "$found_xft" = "yes" ; then + tk_oldCFlags=$CFLAGS + CFLAGS="$CFLAGS $XINCLUDES $XFT_CFLAGS" + tk_oldLibs=$LIBS + LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW" + echo "$as_me:$LINENO: checking for X11/Xft/Xft.h" >&5 +echo $ECHO_N "checking for X11/Xft/Xft.h... $ECHO_C" >&6 +if test "${ac_cv_header_X11_Xft_Xft_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Xlib.h> + +#include <X11/Xft/Xft.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_X11_Xft_Xft_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_X11_Xft_Xft_h=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_X11_Xft_Xft_h" >&5 +echo "${ECHO_T}$ac_cv_header_X11_Xft_Xft_h" >&6 +if test $ac_cv_header_X11_Xft_Xft_h = yes; then + : +else + + found_xft=no + +fi + + + CFLAGS=$tk_oldCFlags + LIBS=$tk_oldLibs + fi + if test "$found_xft" = "yes" ; then + tk_oldCFlags=$CFLAGS + CFLAGS="$CFLAGS $XINCLUDES $XFT_CFLAGS" + tk_oldLibs=$LIBS + LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW" + +echo "$as_me:$LINENO: checking for XftFontOpen in -lXft" >&5 +echo $ECHO_N "checking for XftFontOpen in -lXft... $ECHO_C" >&6 +if test "${ac_cv_lib_Xft_XftFontOpen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXft $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XftFontOpen (); +int +main () +{ +XftFontOpen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xft_XftFontOpen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xft_XftFontOpen=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xft_XftFontOpen" >&5 +echo "${ECHO_T}$ac_cv_lib_Xft_XftFontOpen" >&6 +if test $ac_cv_lib_Xft_XftFontOpen = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBXFT 1 +_ACEOF + + LIBS="-lXft $LIBS" + +else + + found_xft=no + +fi + + CFLAGS=$tk_oldCFlags + LIBS=$tk_oldLibs + fi + if test "$found_xft" = "yes" ; then + tk_oldCFlags=$CFLAGS + CFLAGS="$CFLAGS $XINCLUDES $XFT_CFLAGS" + tk_oldLibs=$LIBS + LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW -lfontconfig" + echo "$as_me:$LINENO: checking for FcFontSort in -lfontconfig" >&5 +echo $ECHO_N "checking for FcFontSort in -lfontconfig... $ECHO_C" >&6 +if test "${ac_cv_lib_fontconfig_FcFontSort+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfontconfig $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char FcFontSort (); +int +main () +{ +FcFontSort (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_fontconfig_FcFontSort=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_fontconfig_FcFontSort=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_fontconfig_FcFontSort" >&5 +echo "${ECHO_T}$ac_cv_lib_fontconfig_FcFontSort" >&6 +if test $ac_cv_lib_fontconfig_FcFontSort = yes; then + + XFT_LIBS="$XFT_LIBS -lfontconfig" + +fi + + CFLAGS=$tk_oldCFlags + LIBS=$tk_oldLibs + fi + if test "$found_xft" = "no" ; then + if test "$enable_xft" = "yes" ; then + { echo "$as_me:$LINENO: WARNING: Can't find xft configuration, or xft is unusable" >&5 +echo "$as_me: WARNING: Can't find xft configuration, or xft is unusable" >&2;} + fi + enable_xft=no + XFT_CFLAGS="" + XFT_LIBS="" + else + enable_xft=yes + fi + fi + if test $enable_xft = "yes" ; then + UNIX_FONT_OBJS=tkUnixRFont.o + +cat >>confdefs.h <<\_ACEOF +#define HAVE_XFT 1 +_ACEOF + + else + UNIX_FONT_OBJS=tkUnixFont.o + fi + + + +fi + +#-------------------------------------------------------------------- +# Check for XkbKeycodeToKeysym. +#-------------------------------------------------------------------- + +if test $tk_aqua = no; then + tk_oldCFlags=$CFLAGS + tk_oldLibs=$LIBS + CFLAGS="$CFLAGS $XINCLUDES" + LIBS="$LIBS $XLIBSW" + echo "$as_me:$LINENO: checking for X11/XKBlib.h" >&5 +echo $ECHO_N "checking for X11/XKBlib.h... $ECHO_C" >&6 +if test "${ac_cv_header_X11_XKBlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Xlib.h> + +#include <X11/XKBlib.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_X11_XKBlib_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_X11_XKBlib_h=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_X11_XKBlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_X11_XKBlib_h" >&6 +if test $ac_cv_header_X11_XKBlib_h = yes; then + + xkblib_header_found=yes + +else + + xkblib_header_found=no + +fi + + + if test $xkblib_header_found = "yes" ; then + echo "$as_me:$LINENO: checking for XkbKeycodeToKeysym in -lX11" >&5 +echo $ECHO_N "checking for XkbKeycodeToKeysym in -lX11... $ECHO_C" >&6 +if test "${ac_cv_lib_X11_XkbKeycodeToKeysym+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XkbKeycodeToKeysym (); +int +main () +{ +XkbKeycodeToKeysym (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_X11_XkbKeycodeToKeysym=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_X11_XkbKeycodeToKeysym=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_X11_XkbKeycodeToKeysym" >&5 +echo "${ECHO_T}$ac_cv_lib_X11_XkbKeycodeToKeysym" >&6 +if test $ac_cv_lib_X11_XkbKeycodeToKeysym = yes; then + + xkbkeycodetokeysym_found=yes + +else + + xkbkeycodetokeysym_found=no + +fi + + else + xkbkeycodetokeysym_found=no + fi + if test $xkbkeycodetokeysym_found = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_XKBKEYCODETOKEYSYM 1 +_ACEOF + + fi + CFLAGS=$tk_oldCFlags + LIBS=$tk_oldLibs +fi + +#-------------------------------------------------------------------- +# Check whether XKeycodeToKeysym is deprecated in X11 headers. +#-------------------------------------------------------------------- + +if test $tk_aqua = no && test "$GCC" = yes; then + echo "$as_me:$LINENO: checking whether XKeycodeToKeysym is deprecated" >&5 +echo $ECHO_N "checking whether XKeycodeToKeysym is deprecated... $ECHO_C" >&6 + tk_oldCFlags=$CFLAGS + CFLAGS="$CFLAGS -Werror" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include <X11/Xlib.h> + +int +main () +{ + + XKeycodeToKeysym(0,0,0); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +cat >>confdefs.h <<\_ACEOF +#define XKEYCODETOKEYSYM_IS_DEPRECATED 1 +_ACEOF + + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$tk_oldCFlags +fi + +#-------------------------------------------------------------------- +# XXX Do this last. +# It might modify XLIBSW which could affect other tests. +# +# Check whether the header and library for the XScreenSaver +# extension are available, and set HAVE_XSS if so. +# XScreenSaver is needed for Tk_GetUserInactiveTime(). +#-------------------------------------------------------------------- + +if test $tk_aqua = no; then + tk_oldCFlags=$CFLAGS + CFLAGS="$CFLAGS $XINCLUDES" + tk_oldLibs=$LIBS + LIBS="$tk_oldLibs $XLIBSW" + xss_header_found=no + xss_lib_found=no + echo "$as_me:$LINENO: checking whether to try to use XScreenSaver" >&5 +echo $ECHO_N "checking whether to try to use XScreenSaver... $ECHO_C" >&6 + # Check whether --enable-xss or --disable-xss was given. +if test "${enable_xss+set}" = set; then + enableval="$enable_xss" + enable_xss=$enableval +else + enable_xss=yes +fi; + if test "$enable_xss" = "no" ; then + echo "$as_me:$LINENO: result: $enable_xss" >&5 +echo "${ECHO_T}$enable_xss" >&6 + else + echo "$as_me:$LINENO: result: $enable_xss" >&5 +echo "${ECHO_T}$enable_xss" >&6 + echo "$as_me:$LINENO: checking for X11/extensions/scrnsaver.h" >&5 +echo $ECHO_N "checking for X11/extensions/scrnsaver.h... $ECHO_C" >&6 +if test "${ac_cv_header_X11_extensions_scrnsaver_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <X11/Xlib.h> + +#include <X11/extensions/scrnsaver.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_X11_extensions_scrnsaver_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_X11_extensions_scrnsaver_h=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_X11_extensions_scrnsaver_h" >&5 +echo "${ECHO_T}$ac_cv_header_X11_extensions_scrnsaver_h" >&6 +if test $ac_cv_header_X11_extensions_scrnsaver_h = yes; then + + xss_header_found=yes + +fi + + + echo "$as_me:$LINENO: checking for XScreenSaverQueryInfo" >&5 +echo $ECHO_N "checking for XScreenSaverQueryInfo... $ECHO_C" >&6 +if test "${ac_cv_func_XScreenSaverQueryInfo+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define XScreenSaverQueryInfo to an innocuous variant, in case <limits.h> declares XScreenSaverQueryInfo. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define XScreenSaverQueryInfo innocuous_XScreenSaverQueryInfo + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char XScreenSaverQueryInfo (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef XScreenSaverQueryInfo + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XScreenSaverQueryInfo (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_XScreenSaverQueryInfo) || defined (__stub___XScreenSaverQueryInfo) +choke me +#else +char (*f) () = XScreenSaverQueryInfo; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != XScreenSaverQueryInfo; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_XScreenSaverQueryInfo=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_XScreenSaverQueryInfo=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_XScreenSaverQueryInfo" >&5 +echo "${ECHO_T}$ac_cv_func_XScreenSaverQueryInfo" >&6 +if test $ac_cv_func_XScreenSaverQueryInfo = yes; then + : +else + + echo "$as_me:$LINENO: checking for XScreenSaverQueryInfo in -lXext" >&5 +echo $ECHO_N "checking for XScreenSaverQueryInfo in -lXext... $ECHO_C" >&6 +if test "${ac_cv_lib_Xext_XScreenSaverQueryInfo+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXext $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XScreenSaverQueryInfo (); +int +main () +{ +XScreenSaverQueryInfo (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xext_XScreenSaverQueryInfo=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xext_XScreenSaverQueryInfo=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xext_XScreenSaverQueryInfo" >&5 +echo "${ECHO_T}$ac_cv_lib_Xext_XScreenSaverQueryInfo" >&6 +if test $ac_cv_lib_Xext_XScreenSaverQueryInfo = yes; then + + XLIBSW="$XLIBSW -lXext" + xss_lib_found=yes + +else + + echo "$as_me:$LINENO: checking for XScreenSaverQueryInfo in -lXss" >&5 +echo $ECHO_N "checking for XScreenSaverQueryInfo in -lXss... $ECHO_C" >&6 +if test "${ac_cv_lib_Xss_XScreenSaverQueryInfo+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXss -lXext $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XScreenSaverQueryInfo (); +int +main () +{ +XScreenSaverQueryInfo (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xss_XScreenSaverQueryInfo=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xss_XScreenSaverQueryInfo=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xss_XScreenSaverQueryInfo" >&5 +echo "${ECHO_T}$ac_cv_lib_Xss_XScreenSaverQueryInfo" >&6 +if test $ac_cv_lib_Xss_XScreenSaverQueryInfo = yes; then + + if test "$tcl_cv_ld_weak_l" = yes; then + # On Darwin, weak link libXss if possible, + # as it is only available on Tiger or later. + XLIBSW="$XLIBSW -Wl,-weak-lXss -lXext" + else + XLIBSW="$XLIBSW -lXss -lXext" + fi + xss_lib_found=yes + +fi + + +fi + + +fi + + fi + if test $enable_xss = yes -a $xss_lib_found = yes -a $xss_header_found = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_XSS 1 +_ACEOF + + fi + CFLAGS=$tk_oldCFlags + LIBS=$tk_oldLibs +fi + +#-------------------------------------------------------------------- +# Figure out whether "char" is unsigned. If so, set a +# #define for __CHAR_UNSIGNED__. +#-------------------------------------------------------------------- + + +echo "$as_me:$LINENO: checking whether char is unsigned" >&5 +echo $ECHO_N "checking whether char is unsigned... $ECHO_C" >&6 +if test "${ac_cv_c_char_unsigned+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((char) -1) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_char_unsigned=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_char_unsigned=yes +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_char_unsigned" >&5 +echo "${ECHO_T}$ac_cv_c_char_unsigned" >&6 +if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then + cat >>confdefs.h <<\_ACEOF +#define __CHAR_UNSIGNED__ 1 +_ACEOF + +fi + + +#-------------------------------------------------------------------- +# The statements below define a collection of symbols related to +# building libtk as a shared library instead of a static library. +#-------------------------------------------------------------------- + +eval eval "TK_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}" +eval eval "TK_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}" +eval "TK_LIB_FILE=libtk${LIB_SUFFIX}" + +# tkConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed +# since on some platforms TK_LIB_FILE contains shell escapes. + +eval "TK_LIB_FILE=${TK_LIB_FILE}" + +if test "${SHARED_BUILD}" = "1" -a "${SHLIB_SUFFIX}" != ""; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \${TCL_STUB_LIB_SPEC}" + TCL_STUB_FLAGS="-DUSE_TCL_STUBS" +fi + +TK_LIBRARY='$(prefix)/lib/tk$(VERSION)' +PRIVATE_INCLUDE_DIR='$(includedir)' +HTML_DIR='$(DISTDIR)/html' +TK_PKG_DIR='tk$(VERSION)' +TK_RSRC_FILE='tk$(VERSION).rsrc' +WISH_RSRC_FILE='wish$(VERSION).rsrc' + +# Note: in the following variable, it's important to use the absolute +# path name of the Tcl directory rather than "..": this is because +# AIX remembers this path and will attempt to use it at run-time to look +# up the Tcl library. + +if test "`uname -s`" = "Darwin" ; then + + if test "`uname -s`" = "Darwin" ; then + echo "$as_me:$LINENO: checking how to package libraries" >&5 +echo $ECHO_N "checking how to package libraries... $ECHO_C" >&6 + # Check whether --enable-framework or --disable-framework was given. +if test "${enable_framework+set}" = set; then + enableval="$enable_framework" + enable_framework=$enableval +else + enable_framework=no +fi; + if test $enable_framework = yes; then + if test $SHARED_BUILD = 0; then + { echo "$as_me:$LINENO: WARNING: Frameworks can only be built if --enable-shared is yes" >&5 +echo "$as_me: WARNING: Frameworks can only be built if --enable-shared is yes" >&2;} + enable_framework=no + fi + if test $tcl_corefoundation = no; then + { echo "$as_me:$LINENO: WARNING: Frameworks can only be used when CoreFoundation is available" >&5 +echo "$as_me: WARNING: Frameworks can only be used when CoreFoundation is available" >&2;} + enable_framework=no + fi + fi + if test $enable_framework = yes; then + echo "$as_me:$LINENO: result: framework" >&5 +echo "${ECHO_T}framework" >&6 + FRAMEWORK_BUILD=1 + else + if test $SHARED_BUILD = 1; then + echo "$as_me:$LINENO: result: shared library" >&5 +echo "${ECHO_T}shared library" >&6 + else + echo "$as_me:$LINENO: result: static library" >&5 +echo "${ECHO_T}static library" >&6 + fi + FRAMEWORK_BUILD=0 + fi + fi + + TK_SHLIB_LD_EXTRAS="-compatibility_version ${TK_VERSION} -current_version ${TK_VERSION}`echo ${TK_PATCH_LEVEL} | awk '{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}'`" + TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}/${TK_LIB_FILE}" -unexported_symbols_list $$(f=$(TK_LIB_FILE).E && nm -gp tkMacOSX*.o 2>/dev/null | awk "/^[0-9a-f]+ . \.objc/ {print \$$3}" > $$f && nm -gjp "$(TCL_BIN_DIR)"/$(TCL_STUB_LIB_FILE) | grep ^_[^_] >> $$f && echo $$f)' + echo "$LDFLAGS " | grep -q -- '-prebind ' && TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -seg1addr 0xb000000' + TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tk-Info.plist' + EXTRA_WISH_LIBS='-sectcreate __TEXT __info_plist Wish-Info.plist' + EXTRA_APP_CC_SWITCHES="${EXTRA_APP_CC_SWITCHES}"' -mdynamic-no-pic' + ac_config_files="$ac_config_files Tk-Info.plist:../macosx/Tk-Info.plist.in Wish-Info.plist:../macosx/Wish-Info.plist.in" + + for l in ${LOCALES}; do CFBUNDLELOCALIZATIONS="${CFBUNDLELOCALIZATIONS}<string>$l</string>"; done + TK_YEAR="`date +%Y`" +fi + +if test "$FRAMEWORK_BUILD" = "1" ; then + +cat >>confdefs.h <<\_ACEOF +#define TK_FRAMEWORK 1 +_ACEOF + + # Construct a fake local framework structure to make linking with + # '-framework Tk' and running of tktest work + ac_config_commands="$ac_config_commands Tk.framework" + + LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH" + if test "${libdir}" = '${exec_prefix}/lib'; then + # override libdir default + libdir="/Library/Frameworks" + fi + TK_LIB_FILE="Tk" + TK_LIB_FLAG="-framework Tk" + TK_BUILD_LIB_SPEC="-F`pwd | sed -e 's/ /\\\\ /g'` -framework Tk" + TK_LIB_SPEC="-F${libdir} -framework Tk" + libdir="${libdir}/Tk.framework/Versions/\${VERSION}" + TK_LIBRARY="${libdir}/Resources/Scripts" + TK_PKG_DIR="Resources/Scripts" + TK_RSRC_FILE="Tk.rsrc" + WISH_RSRC_FILE="Wish.rsrc" + includedir="${libdir}/Headers" + PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders" + HTML_DIR="${libdir}/Resources/Documentation/Reference/Tk" + EXTRA_INSTALL="install-private-headers html-tk" + EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)"/TkTOC.html' + EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tk-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"' + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"' + if test $tk_aqua = yes; then + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Images to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) "$(MAC_OSX_DIR)/$$i" "$(LIB_INSTALL_DIR)/Resources"; done' + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing wish$(VERSION) script to $(INSTALL_ROOT)/'"${bindir}"'/" && $(INSTALL_DATA_DIR) "$(INSTALL_ROOT)/'"${bindir}"'" && printf > "$(INSTALL_ROOT)/'"${bindir}"'/wish$(VERSION)" "#!/bin/sh\n\"\$$(dirname \$$0)'"`eval d="${bindir}"; echo "$d" | sed -e 's#/[^/][^/]*#/..#g'`"'$(bindir)/Wish\" \"\$$@\"" && chmod +x "$(INSTALL_ROOT)/'"${bindir}"'/wish$(VERSION)"' + bindir="${libdir}/Resources/Wish.app/Contents/MacOS" + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Info.plist to $(BIN_INSTALL_DIR)/.." && $(INSTALL_DATA) Wish-Info.plist "$(BIN_INSTALL_DIR)/../Info.plist" && mv -f "$(BIN_INSTALL_DIR)/wish$(VERSION)" "$(BIN_INSTALL_DIR)/Wish"' + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Wish.icns to $(BIN_INSTALL_DIR)/../Resources" && $(INSTALL_DATA_DIR) "$(BIN_INSTALL_DIR)/../Resources"' + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && $(INSTALL_DATA) "$(MAC_OSX_DIR)/Tk.icns" "$(BIN_INSTALL_DIR)/../Resources/Wish.icns"' + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Wish.sdef to $(BIN_INSTALL_DIR)/../Resources" && $(INSTALL_DATA) "$(MAC_OSX_DIR)/Wish.sdef" "$(BIN_INSTALL_DIR)/../Resources"' + fi + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tk.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tkConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."' + # Don't use AC_DEFINE for the following as the framework version define + # needs to go into the Makefile even when using autoheader, so that we + # can pick up a potential make override of VERSION. Also, don't put this + # into CFLAGS as it should not go into tkConfig.sh + EXTRA_CC_SWITCHES="$EXTRA_CC_SWITCHES"' -DTK_FRAMEWORK_VERSION=\"$(VERSION)\"' +else + if test $tk_aqua = yes; then + EXTRA_INSTALL_BINARIES='@echo "Installing Images to $(LIB_INSTALL_DIR)/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) "$(MAC_OSX_DIR)/$$i" "$(LIB_INSTALL_DIR)"; done' + fi + # libdir must be a fully qualified path and not ${exec_prefix}/lib + eval libdir="$libdir" + if test "${ac_cv_cygwin}" = "yes" -a "$SHARED_BUILD" = "1"; then + TK_LIB_FLAG="-ltk`echo ${TK_VERSION} | tr -d .`" + TK_BUILD_LIB_SPEC="-L\$(TOP_DIR)/win ${TK_LIB_FLAG}" + else + if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then + TK_LIB_FLAG="-ltk${TK_VERSION}" + else + TK_LIB_FLAG="-ltk`echo ${TK_VERSION} | tr -d .`" + fi + TK_BUILD_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TK_LIB_FLAG}" + fi + TK_LIB_SPEC="-L${libdir} ${TK_LIB_FLAG}" +fi + +#-------------------------------------------------------------------- +# The statements below define various symbols relating to Tk +# stub support. +#-------------------------------------------------------------------- + +# Replace ${VERSION} with contents of ${TK_VERSION} +eval "TK_STUB_LIB_FILE=libtkstub${TK_UNSHARED_LIB_SUFFIX}" +eval "TK_STUB_LIB_DIR=${libdir}" + +if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then + TK_STUB_LIB_FLAG="-ltkstub${TK_VERSION}" +else + TK_STUB_LIB_FLAG="-ltkstub`echo ${TK_VERSION} | tr -d .`" +fi + +TK_BUILD_STUB_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" +TK_STUB_LIB_SPEC="-L${TK_STUB_LIB_DIR} ${TK_STUB_LIB_FLAG}" +TK_BUILD_STUB_LIB_PATH="`pwd`/${TK_STUB_LIB_FILE}" +TK_STUB_LIB_PATH="${TK_STUB_LIB_DIR}/${TK_STUB_LIB_FILE}" + +# Install time header dir can be set via --includedir +eval "TK_INCLUDE_SPEC=\"-I${includedir}\"" + +#------------------------------------------------------------------------ +# tkConfig.sh refers to this by a different name +#------------------------------------------------------------------------ + +TK_SHARED_BUILD=${SHARED_BUILD} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ac_config_files="$ac_config_files Makefile:../unix/Makefile.in tkConfig.sh:../unix/tkConfig.sh.in tk.pc:../unix/tk.pc.in" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# 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 | 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 \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then we branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +cat >confdef2opt.sed <<\_ACEOF +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g +t quote +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g +t quote +d +: quote +s,[ `~#$^&*(){}\\|;'"<>?],\\&,g +s,\[,\\&,g +s,\],\\&,g +s,\$,$$,g +p +_ACEOF +# We use echo to avoid assuming a particular line-breaking character. +# The extra dot is to prevent the shell from consuming trailing +# line-breaks from the sub-command output. A line-break within +# single-quotes doesn't work because, if this script is created in a +# platform that uses two characters for line-breaks (e.g., DOS), tr +# would break. +ac_LF_and_DOT=`echo; echo .` +DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` +rm -f confdef2opt.sed + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS="" + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by tk $as_me 8.6, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Configuration commands: +$config_commands + +Report bugs to <bug-autoconf@gnu.org>." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +tk config.status 8.6 +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS section. +# + +VERSION=${TK_VERSION} && tk_aqua=${tk_aqua} + +_ACEOF + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Tk-Info.plist" ) CONFIG_FILES="$CONFIG_FILES Tk-Info.plist:../macosx/Tk-Info.plist.in" ;; + "Wish-Info.plist" ) CONFIG_FILES="$CONFIG_FILES Wish-Info.plist:../macosx/Wish-Info.plist.in" ;; + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile:../unix/Makefile.in" ;; + "tkConfig.sh" ) CONFIG_FILES="$CONFIG_FILES tkConfig.sh:../unix/tkConfig.sh.in" ;; + "tk.pc" ) CONFIG_FILES="$CONFIG_FILES tk.pc:../unix/tk.pc.in" ;; + "Tk.framework" ) CONFIG_COMMANDS="$CONFIG_COMMANDS Tk.framework" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@TCL_VERSION@,$TCL_VERSION,;t t +s,@TCL_PATCH_LEVEL@,$TCL_PATCH_LEVEL,;t t +s,@TCL_BIN_DIR@,$TCL_BIN_DIR,;t t +s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t +s,@TCL_LIB_FILE@,$TCL_LIB_FILE,;t t +s,@TCL_LIB_FLAG@,$TCL_LIB_FLAG,;t t +s,@TCL_LIB_SPEC@,$TCL_LIB_SPEC,;t t +s,@TCL_STUB_LIB_FILE@,$TCL_STUB_LIB_FILE,;t t +s,@TCL_STUB_LIB_FLAG@,$TCL_STUB_LIB_FLAG,;t t +s,@TCL_STUB_LIB_SPEC@,$TCL_STUB_LIB_SPEC,;t t +s,@TCLSH_PROG@,$TCLSH_PROG,;t t +s,@BUILD_TCLSH@,$BUILD_TCLSH,;t t +s,@MAN_FLAGS@,$MAN_FLAGS,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@CPP@,$CPP,;t t +s,@EGREP@,$EGREP,;t t +s,@TCL_THREADS@,$TCL_THREADS,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@AR@,$AR,;t t +s,@ac_ct_AR@,$ac_ct_AR,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@TCL_LIBS@,$TCL_LIBS,;t t +s,@DL_LIBS@,$DL_LIBS,;t t +s,@DL_OBJS@,$DL_OBJS,;t t +s,@PLAT_OBJS@,$PLAT_OBJS,;t t +s,@PLAT_SRCS@,$PLAT_SRCS,;t t +s,@LDAIX_SRC@,$LDAIX_SRC,;t t +s,@CFLAGS_DEBUG@,$CFLAGS_DEBUG,;t t +s,@CFLAGS_OPTIMIZE@,$CFLAGS_OPTIMIZE,;t t +s,@CFLAGS_WARNING@,$CFLAGS_WARNING,;t t +s,@LDFLAGS_DEBUG@,$LDFLAGS_DEBUG,;t t +s,@LDFLAGS_OPTIMIZE@,$LDFLAGS_OPTIMIZE,;t t +s,@CC_SEARCH_FLAGS@,$CC_SEARCH_FLAGS,;t t +s,@LD_SEARCH_FLAGS@,$LD_SEARCH_FLAGS,;t t +s,@STLIB_LD@,$STLIB_LD,;t t +s,@SHLIB_LD@,$SHLIB_LD,;t t +s,@TCL_SHLIB_LD_EXTRAS@,$TCL_SHLIB_LD_EXTRAS,;t t +s,@TK_SHLIB_LD_EXTRAS@,$TK_SHLIB_LD_EXTRAS,;t t +s,@SHLIB_LD_LIBS@,$SHLIB_LD_LIBS,;t t +s,@SHLIB_CFLAGS@,$SHLIB_CFLAGS,;t t +s,@SHLIB_SUFFIX@,$SHLIB_SUFFIX,;t t +s,@MAKE_LIB@,$MAKE_LIB,;t t +s,@MAKE_STUB_LIB@,$MAKE_STUB_LIB,;t t +s,@INSTALL_LIB@,$INSTALL_LIB,;t t +s,@DLL_INSTALL_DIR@,$DLL_INSTALL_DIR,;t t +s,@INSTALL_STUB_LIB@,$INSTALL_STUB_LIB,;t t +s,@CFLAGS_DEFAULT@,$CFLAGS_DEFAULT,;t t +s,@LDFLAGS_DEFAULT@,$LDFLAGS_DEFAULT,;t t +s,@XFT_CFLAGS@,$XFT_CFLAGS,;t t +s,@XFT_LIBS@,$XFT_LIBS,;t t +s,@UNIX_FONT_OBJS@,$UNIX_FONT_OBJS,;t t +s,@TK_VERSION@,$TK_VERSION,;t t +s,@TK_MAJOR_VERSION@,$TK_MAJOR_VERSION,;t t +s,@TK_MINOR_VERSION@,$TK_MINOR_VERSION,;t t +s,@TK_PATCH_LEVEL@,$TK_PATCH_LEVEL,;t t +s,@TK_YEAR@,$TK_YEAR,;t t +s,@TK_LIB_FILE@,$TK_LIB_FILE,;t t +s,@TK_LIB_FLAG@,$TK_LIB_FLAG,;t t +s,@TK_LIB_SPEC@,$TK_LIB_SPEC,;t t +s,@TK_STUB_LIB_FILE@,$TK_STUB_LIB_FILE,;t t +s,@TK_STUB_LIB_FLAG@,$TK_STUB_LIB_FLAG,;t t +s,@TK_STUB_LIB_SPEC@,$TK_STUB_LIB_SPEC,;t t +s,@TK_STUB_LIB_PATH@,$TK_STUB_LIB_PATH,;t t +s,@TK_INCLUDE_SPEC@,$TK_INCLUDE_SPEC,;t t +s,@TK_BUILD_STUB_LIB_SPEC@,$TK_BUILD_STUB_LIB_SPEC,;t t +s,@TK_BUILD_STUB_LIB_PATH@,$TK_BUILD_STUB_LIB_PATH,;t t +s,@TK_SRC_DIR@,$TK_SRC_DIR,;t t +s,@TK_SHARED_BUILD@,$TK_SHARED_BUILD,;t t +s,@LD_LIBRARY_PATH_VAR@,$LD_LIBRARY_PATH_VAR,;t t +s,@TK_BUILD_LIB_SPEC@,$TK_BUILD_LIB_SPEC,;t t +s,@TCL_STUB_FLAGS@,$TCL_STUB_FLAGS,;t t +s,@XINCLUDES@,$XINCLUDES,;t t +s,@XLIBSW@,$XLIBSW,;t t +s,@LOCALES@,$LOCALES,;t t +s,@TK_WINDOWINGSYSTEM@,$TK_WINDOWINGSYSTEM,;t t +s,@TK_PKG_DIR@,$TK_PKG_DIR,;t t +s,@TK_LIBRARY@,$TK_LIBRARY,;t t +s,@LIB_RUNTIME_DIR@,$LIB_RUNTIME_DIR,;t t +s,@PRIVATE_INCLUDE_DIR@,$PRIVATE_INCLUDE_DIR,;t t +s,@HTML_DIR@,$HTML_DIR,;t t +s,@EXTRA_CC_SWITCHES@,$EXTRA_CC_SWITCHES,;t t +s,@EXTRA_APP_CC_SWITCHES@,$EXTRA_APP_CC_SWITCHES,;t t +s,@EXTRA_INSTALL@,$EXTRA_INSTALL,;t t +s,@EXTRA_INSTALL_BINARIES@,$EXTRA_INSTALL_BINARIES,;t t +s,@EXTRA_BUILD_HTML@,$EXTRA_BUILD_HTML,;t t +s,@EXTRA_WISH_LIBS@,$EXTRA_WISH_LIBS,;t t +s,@CFBUNDLELOCALIZATIONS@,$CFBUNDLELOCALIZATIONS,;t t +s,@TK_RSRC_FILE@,$TK_RSRC_FILE,;t t +s,@WISH_RSRC_FILE@,$WISH_RSRC_FILE,;t t +s,@LIB_RSRC_FILE@,$LIB_RSRC_FILE,;t t +s,@APP_RSRC_FILE@,$APP_RSRC_FILE,;t t +s,@REZ@,$REZ,;t t +s,@REZ_FLAGS@,$REZ_FLAGS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + Tk.framework ) n=Tk && + f=$n.framework && v=Versions/$VERSION && + rm -rf $f && mkdir -p $f/$v/Resources && + ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v && + ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist && + if test $tk_aqua = yes; then ln -s ../../../../$n.rsrc $f/$v/Resources; fi && + unset n f v + ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + diff --git a/tk8.6/unix/configure.in b/tk8.6/unix/configure.in new file mode 100755 index 0000000..0d7b0b2 --- /dev/null +++ b/tk8.6/unix/configure.in @@ -0,0 +1,848 @@ +#! /bin/bash -norc +dnl This file is an input file used by the GNU "autoconf" program to +dnl generate the file "configure", which is run during Tk installation +dnl to configure the system for the local environment. + +AC_INIT([tk],[8.6]) +AC_PREREQ(2.59) + +dnl This is only used when included from macosx/configure.ac +m4_ifdef([SC_USE_CONFIG_HEADERS], [ + AC_CONFIG_HEADERS([tkConfig.h:../unix/tkConfig.h.in]) + AC_CONFIG_COMMANDS_PRE([DEFS="-DHAVE_TK_CONFIG_H -imacros tkConfig.h"]) + AH_TOP([ + #ifndef _TKCONFIG + #define _TKCONFIG]) + AH_BOTTOM([ + /* Undef unused package specific autoheader defines so that we can + * include both tclConfig.h and tkConfig.h at the same time: */ + /* override */ #undef PACKAGE_NAME + /* override */ #undef PACKAGE_STRING + /* override */ #undef PACKAGE_TARNAME + #endif /* _TKCONFIG */]) +]) + +TK_VERSION=8.6 +TK_MAJOR_VERSION=8 +TK_MINOR_VERSION=6 +TK_PATCH_LEVEL=".9" +VERSION=${TK_VERSION} +LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv" + +#-------------------------------------------------------------------- +# Find and load the tclConfig.sh file +#-------------------------------------------------------------------- + +SC_PATH_TCLCONFIG +SC_LOAD_TCLCONFIG + +if test "${TCL_MAJOR_VERSION}" -ne 8 ; then + AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+ +Found config for Tcl ${TCL_VERSION}]) +fi +if test "${TCL_MINOR_VERSION}" -lt 6 ; then + AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+ +Found config for Tcl ${TCL_VERSION}]) +fi + +SC_PROG_TCLSH +SC_BUILD_TCLSH + +#------------------------------------------------------------------------ +# Handle the --prefix=... option +#------------------------------------------------------------------------ + +if test "${prefix}" = "NONE"; then + prefix="$TCL_PREFIX" +fi +if test "${exec_prefix}" = "NONE"; then + exec_prefix=$prefix +fi +# Make sure srcdir is fully qualified! +srcdir="`cd "$srcdir" ; pwd`" +TK_SRC_DIR="`cd "$srcdir"/..; pwd`" + +#------------------------------------------------------------------------ +# Compress and/or soft link the manpages? +#------------------------------------------------------------------------ + +SC_CONFIG_MANPAGES + +#------------------------------------------------------------------------ +# Standard compiler checks +#------------------------------------------------------------------------ + +# If the user did not set CFLAGS, set it now to keep +# the AC_PROG_CC macro from adding "-g -O2". +if test "${CFLAGS+set}" != "set" ; then + CFLAGS="" +fi + +AC_PROG_CC +AC_C_INLINE + +#-------------------------------------------------------------------- +# Supply a substitute for stdlib.h if it doesn't define strtol, +# strtoul, or strtod (which it doesn't in some versions of SunOS). +#-------------------------------------------------------------------- + +AC_CHECK_HEADER(stdlib.h, tk_ok=1, tk_ok=0) +AC_EGREP_HEADER(strtol, stdlib.h, , tk_ok=0) +AC_EGREP_HEADER(strtoul, stdlib.h, , tk_ok=0) +AC_EGREP_HEADER(strtod, stdlib.h, , tk_ok=0) +if test $tk_ok = 0; then + AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?]) +fi + +#------------------------------------------------------------------------ +# If we're using GCC, see if the compiler understands -pipe. If so, use it. +# It makes compiling go faster. (This is only a performance feature.) +#------------------------------------------------------------------------ + +if test -z "$no_pipe" && test -n "$GCC"; then + AC_CACHE_CHECK([if the compiler understands -pipe], + tcl_cv_cc_pipe, [ + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" + AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no) + CFLAGS=$hold_cflags]) + if test $tcl_cv_cc_pipe = yes; then + CFLAGS="$CFLAGS -pipe" + fi +fi + +#------------------------------------------------------------------------ +# Threads support - this auto-enables if Tcl was compiled threaded +#------------------------------------------------------------------------ + +SC_ENABLE_THREADS + +# Add the threads support libraries +LIBS="$LIBS$THREADS_LIBS" + +SC_ENABLE_SHARED + +#-------------------------------------------------------------------- +# 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. +#-------------------------------------------------------------------- + +SC_CONFIG_CFLAGS + +SC_ENABLE_SYMBOLS + +#-------------------------------------------------------------------- +# Detect what compiler flags to set for 64-bit support. +#-------------------------------------------------------------------- + +SC_TCL_EARLY_FLAGS + +SC_TCL_64BIT_FLAGS + +#-------------------------------------------------------------------- +# Check endianness because we can optimize some operations +#-------------------------------------------------------------------- + +AC_C_BIGENDIAN + +#------------------------------------------------------------------------ +# If Tcl and Tk are installed in different places, adjust the library +# search path to reflect this. +#------------------------------------------------------------------------ + +LIB_RUNTIME_DIR='$(libdir)' + +if test "$TCL_EXEC_PREFIX" != "$exec_prefix"; then + LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${TCL_EXEC_PREFIX}/lib" +fi + +if test "$TCL_PREFIX" != "$prefix"; then + AC_MSG_WARN([ + Different --prefix selected for Tk and Tcl! + [[package require Tk]] may not work correctly in tclsh.]) +fi + +#-------------------------------------------------------------------- +# Include sys/select.h if it exists and if it supplies things +# that appear to be useful and aren't already in sys/types.h. +# This appears to be true only on the RS/6000 under AIX. Some +# systems like OSF/1 have a sys/select.h that's of no use, and +# other systems like SCO UNIX have a sys/select.h that's +# pernicious. If "fd_set" isn't defined anywhere then set a +# special flag. +#-------------------------------------------------------------------- + +AC_CACHE_CHECK([for fd_set in sys/types], tcl_cv_type_fd_set, [ + AC_TRY_COMPILE([#include <sys/types.h>],[fd_set readMask, writeMask;], + tcl_cv_type_fd_set=yes, tcl_cv_type_fd_set=no)]) +tk_ok=$tcl_cv_type_fd_set +if test $tk_ok = no; then + AC_CACHE_CHECK([for fd_mask in sys/select], tcl_cv_grep_fd_mask, [ + AC_EGREP_HEADER(fd_mask, sys/select.h, + tcl_cv_grep_fd_mask=present, tcl_cv_grep_fd_mask=missing)]) + if test $tcl_cv_grep_fd_mask = present; then + AC_DEFINE(HAVE_SYS_SELECT_H, 1, [Should we include <sys/select.h>?]) + tk_ok=yes + fi +fi +if test $tk_ok = no; then + AC_DEFINE(NO_FD_SET, 1, [Do we have fd_set?]) +fi + +#------------------------------------------------------------------------------ +# Find out all about time handling differences. +#------------------------------------------------------------------------------ + +AC_CHECK_HEADERS(sys/time.h) +AC_HEADER_TIME + +#-------------------------------------------------------------------- +# Check for various typedefs and provide substitutes if +# they don't exist. +#-------------------------------------------------------------------- + +AC_TYPE_MODE_T +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_TYPE_UID_T + +AC_CHECK_TYPE([intptr_t], [ + AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [ + AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [ + for tcl_cv_intptr_t in "int" "long" "long long" none; do + if test "$tcl_cv_intptr_t" != none; then + AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT], + [[sizeof (void *) <= sizeof ($tcl_cv_intptr_t)]])], + [tcl_ok=yes], [tcl_ok=no]) + test "$tcl_ok" = yes && break; fi + done]) + if test "$tcl_cv_intptr_t" != none; then + AC_DEFINE_UNQUOTED([intptr_t], [$tcl_cv_intptr_t], [Signed integer + type wide enough to hold a pointer.]) + fi +]) +AC_CHECK_TYPE([uintptr_t], [ + AC_DEFINE([HAVE_UINTPTR_T], 1, [Do we have the uintptr_t type?])], [ + AC_CACHE_CHECK([for pointer-size unsigned integer type], tcl_cv_uintptr_t, [ + for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \ + none; do + if test "$tcl_cv_uintptr_t" != none; then + AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT], + [[sizeof (void *) <= sizeof ($tcl_cv_uintptr_t)]])], + [tcl_ok=yes], [tcl_ok=no]) + test "$tcl_ok" = yes && break; fi + done]) + if test "$tcl_cv_uintptr_t" != none; then + AC_DEFINE_UNQUOTED([uintptr_t], [$tcl_cv_uintptr_t], [Unsigned integer + type wide enough to hold a pointer.]) + fi +]) + +#------------------------------------------- +# In OS/390 struct pwd has no pw_gecos field +#------------------------------------------- + +AC_CACHE_CHECK([pw_gecos in struct pwd], tcl_cv_pwd_pw_gecos, [ + AC_TRY_COMPILE([#include <pwd.h>], + [struct passwd pwd; pwd.pw_gecos;], + tcl_cv_pwd_pw_gecos=yes, tcl_cv_pwd_pw_gecos=no)]) +if test $tcl_cv_pwd_pw_gecos = yes; then + AC_DEFINE(HAVE_PW_GECOS, 1, [Does struct password have a pw_gecos field?]) +fi + +#-------------------------------------------------------------------- +# On Mac OS X, we can build either with X11 or with Aqua +#-------------------------------------------------------------------- + +if test "`uname -s`" = "Darwin" ; then + AC_MSG_CHECKING([whether to use Aqua]) + AC_ARG_ENABLE(aqua, + AC_HELP_STRING([--enable-aqua=yes|no], + [use Aqua windowingsystem on Mac OS X (default: no)]), + [tk_aqua=$enableval], [tk_aqua=no]) + if test $tk_aqua = yes -o $tk_aqua = cocoa; then + tk_aqua=yes + if test $tcl_corefoundation = no; then + AC_MSG_WARN([Aqua can only be used when CoreFoundation is available]) + tk_aqua=no + fi + if test ! -d /System/Library/Frameworks/Cocoa.framework; then + AC_MSG_WARN([Aqua can only be used when Cocoa is available]) + tk_aqua=no + fi + if test "`uname -r | awk -F. '{print [$]1}'`" -lt 9; then + AC_MSG_WARN([Aqua requires Mac OS X 10.5 or later]) + tk_aqua=no + fi + fi + AC_MSG_RESULT([$tk_aqua]) + if test "$fat_32_64" = yes; then + if test $tk_aqua = no; then + AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [ + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" + LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" + AC_TRY_LINK([#include <X11/Xlib.h>], [XrmInitialize();], + tcl_cv_lib_x11_64=yes, tcl_cv_lib_x11_64=no) + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done]) + fi + # remove 64-bit arch flags from CFLAGS et al. for combined 32 & 64 bit + # fat builds if configuration does not support 64-bit. + if test "$tcl_cv_lib_x11_64" = no; then + AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags]) + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' + done + fi + fi + if test $tk_aqua = no; then + # check if weak linking whole libraries is possible. + AC_CACHE_CHECK([if ld accepts -weak-l flag], tcl_cv_ld_weak_l, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-weak-lm" + AC_TRY_LINK([#include <math.h>], [double f = sin(1.0);], + tcl_cv_ld_weak_l=yes, tcl_cv_ld_weak_l=no) + LDFLAGS=$hold_ldflags]) + fi + AC_CHECK_HEADERS(AvailabilityMacros.h) + if test "$ac_cv_header_AvailabilityMacros_h" = yes; then + AC_CACHE_CHECK([if weak import is available], tcl_cv_cc_weak_import, [ + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" + AC_TRY_LINK([ + #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ + #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020 + #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020 + #endif + #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1020 + #error MAC_OS_X_VERSION_MIN_REQUIRED < 1020 + #endif + int rand(void) __attribute__((weak_import)); + ], [rand();], + tcl_cv_cc_weak_import=yes, tcl_cv_cc_weak_import=no) + CFLAGS=$hold_cflags]) + if test $tcl_cv_cc_weak_import = yes; then + AC_DEFINE(HAVE_WEAK_IMPORT, 1, [Is weak import available?]) + fi + AC_CACHE_CHECK([if Darwin SUSv3 extensions are available], + tcl_cv_cc_darwin_c_source, [ + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" + AC_TRY_COMPILE([ + #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ + #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050 + #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050 + #endif + #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + #endif + #define _DARWIN_C_SOURCE 1 + #include <sys/cdefs.h> + ],,tcl_cv_cc_darwin_c_source=yes, tcl_cv_cc_darwin_c_source=no) + CFLAGS=$hold_cflags]) + if test $tcl_cv_cc_darwin_c_source = yes; then + AC_DEFINE(_DARWIN_C_SOURCE, 1, + [Are Darwin SUSv3 extensions available?]) + fi + fi +else + tk_aqua=no +fi + +if test $tk_aqua = yes; then + AC_DEFINE(MAC_OSX_TK, 1, [Are we building TkAqua?]) + LIBS="$LIBS -framework Cocoa -framework Carbon -framework IOKit" + EXTRA_CC_SWITCHES='-std=gnu99 -x objective-c' + TK_WINDOWINGSYSTEM=AQUA + if test -n "${enable_symbols}" -a "${enable_symbols}" != no; then + AC_DEFINE(TK_MAC_DEBUG, 1, [Are TkAqua debug messages enabled?]) + fi +else + #-------------------------------------------------------------------- + # Locate the X11 header files and the X11 library archive. Try + # the ac_path_x macro first, but if it doesn't find the X stuff + # (e.g. because there's no xmkmf program) then check through + # a list of possible directories. Under some conditions the + # autoconf macro will return an include directory that contains + # no include files, so double-check its result just to be safe. + #-------------------------------------------------------------------- + + SC_PATH_X + TK_WINDOWINGSYSTEM=X11 +fi + +#-------------------------------------------------------------------- +# Various manipulations on the search path used at runtime to +# find shared libraries: +# 1. If the X library binaries are in a non-standard directory, +# add the X library location into that search path. +# 2. On systems such as AIX and Ultrix that use "-L" as the +# search path option, colons cannot be used to separate +# directories from each other. Change colons to " -L". +# 3. Create two sets of search flags, one for use in cc lines +# and the other for when the linker is invoked directly. In +# the second case, '-Wl,' must be stripped off and commas must +# be replaced by spaces. +#-------------------------------------------------------------------- + +if test "x${x_libraries}" != "x"; then + if test "x${x_libraries}" != "xNONE"; then + LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${x_libraries}" + fi +fi +if test "${TCL_LD_SEARCH_FLAGS}" = '-L${LIB_RUNTIME_DIR}'; then + LIB_RUNTIME_DIR=`echo ${LIB_RUNTIME_DIR} |sed -e 's/:/ -L/g'` +fi + +#-------------------------------------------------------------------- +# Check for the existence of various libraries. The order here +# is important, so that then end up in the right order in the +# command line generated by make. The -lsocket and -lnsl libraries +# require a couple of special tricks: +# 1. Use "connect" and "accept" to check for -lsocket, and +# "gethostbyname" to check for -lnsl. +# 2. Use each function name only once: can't redo a check because +# autoconf caches the results of the last check and won't redo it. +# 3. Use -lnsl and -lsocket only if they supply procedures that +# aren't already present in the normal libraries. This is because +# IRIX 5.2 has libraries, but they aren't needed and they're +# bogus: they goof up name resolution if used. +# 4. On some SVR4 systems, can't use -lsocket without -lnsl too. +# To get around this problem, check for both libraries together +# if -lsocket doesn't work by itself. +#-------------------------------------------------------------------- + +if test $tk_aqua = no; then + AC_CHECK_LIB(Xbsd, main, [LIBS="$LIBS -lXbsd"]) +fi + +#-------------------------------------------------------------------- +# One more check related to the X libraries. The standard releases +# of Ultrix don't support the "xauth" mechanism, so send won't work +# unless TK_NO_SECURITY is defined. However, there are usually copies +# of the MIT X server available as well, which do support xauth. +# Check for the MIT stuff and use it if it exists. +# +# Note: can't use ac_check_lib macro (at least, not in Autoconf 2.1) +# because it can't deal with the "-" in the library name. +#-------------------------------------------------------------------- + +if test -d /usr/include/mit -a $tk_aqua = no; then + AC_MSG_CHECKING([MIT X libraries]) + tk_oldCFlags=$CFLAGS + CFLAGS="$CFLAGS -I/usr/include/mit" + tk_oldLibs=$LIBS + LIBS="$LIBS -lX11-mit" + AC_TRY_LINK([ + #include <X11/Xlib.h> + ], [ + XOpenDisplay(0); + ], [ + AC_MSG_RESULT([yes]) + XLIBSW="-lX11-mit" + XINCLUDES="-I/usr/include/mit" + ], AC_MSG_RESULT([no])) + CFLAGS=$tk_oldCFlags + LIBS=$tk_oldLibs +fi + +#-------------------------------------------------------------------- +# Check for freetype / fontconfig / Xft support. +#-------------------------------------------------------------------- + +if test $tk_aqua = no; then + AC_MSG_CHECKING([whether to use xft]) + AC_ARG_ENABLE(xft, + AC_HELP_STRING([--enable-xft], + [use freetype/fontconfig/xft (default: on)]), + [enable_xft=$enableval], [enable_xft="default"]) + XFT_CFLAGS="" + XFT_LIBS="" + if test "$enable_xft" = "no" ; then + AC_MSG_RESULT([$enable_xft]) + else + found_xft="yes" + dnl make sure package configurator (xft-config or pkg-config + dnl says that xft is present. + XFT_CFLAGS=`xft-config --cflags 2>/dev/null` || found_xft="no" + XFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft="no" + if test "$found_xft" = "no" ; then + found_xft=yes + XFT_CFLAGS=`pkg-config --cflags xft 2>/dev/null` || found_xft="no" + XFT_LIBS=`pkg-config --libs xft 2>/dev/null` || found_xft="no" + fi + AC_MSG_RESULT([$found_xft]) + dnl make sure that compiling against Xft header file doesn't bomb + if test "$found_xft" = "yes" ; then + tk_oldCFlags=$CFLAGS + CFLAGS="$CFLAGS $XINCLUDES $XFT_CFLAGS" + tk_oldLibs=$LIBS + LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW" + AC_CHECK_HEADER(X11/Xft/Xft.h, [], [ + found_xft=no + ],[#include <X11/Xlib.h>]) + CFLAGS=$tk_oldCFlags + LIBS=$tk_oldLibs + fi + dnl make sure that linking against Xft libraries finds freetype + if test "$found_xft" = "yes" ; then + tk_oldCFlags=$CFLAGS + CFLAGS="$CFLAGS $XINCLUDES $XFT_CFLAGS" + tk_oldLibs=$LIBS + LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW" + AC_CHECK_LIB(Xft, XftFontOpen, [], [ + found_xft=no + ]) + CFLAGS=$tk_oldCFlags + LIBS=$tk_oldLibs + fi + dnl make sure that linking against fontconfig libraries finds Fc* symbols + if test "$found_xft" = "yes" ; then + tk_oldCFlags=$CFLAGS + CFLAGS="$CFLAGS $XINCLUDES $XFT_CFLAGS" + tk_oldLibs=$LIBS + LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW -lfontconfig" + AC_CHECK_LIB(fontconfig, FcFontSort, [ + XFT_LIBS="$XFT_LIBS -lfontconfig" + ], []) + CFLAGS=$tk_oldCFlags + LIBS=$tk_oldLibs + fi + dnl print a warning if xft is unusable and was specifically requested + if test "$found_xft" = "no" ; then + if test "$enable_xft" = "yes" ; then + AC_MSG_WARN([Can't find xft configuration, or xft is unusable]) + fi + enable_xft=no + XFT_CFLAGS="" + XFT_LIBS="" + else + enable_xft=yes + fi + fi + if test $enable_xft = "yes" ; then + UNIX_FONT_OBJS=tkUnixRFont.o + AC_DEFINE(HAVE_XFT, 1, [Have we turned on XFT (antialiased fonts)?]) + else + UNIX_FONT_OBJS=tkUnixFont.o + fi + AC_SUBST(XFT_CFLAGS) + AC_SUBST(XFT_LIBS) + AC_SUBST(UNIX_FONT_OBJS) +fi + +#-------------------------------------------------------------------- +# Check for XkbKeycodeToKeysym. +#-------------------------------------------------------------------- + +if test $tk_aqua = no; then + tk_oldCFlags=$CFLAGS + tk_oldLibs=$LIBS + CFLAGS="$CFLAGS $XINCLUDES" + LIBS="$LIBS $XLIBSW" + AC_CHECK_HEADER(X11/XKBlib.h, [ + xkblib_header_found=yes + ], [ + xkblib_header_found=no + ], [#include <X11/Xlib.h>]) + if test $xkblib_header_found = "yes" ; then + AC_CHECK_LIB(X11, XkbKeycodeToKeysym, [ + xkbkeycodetokeysym_found=yes + ], [ + xkbkeycodetokeysym_found=no + ]) + else + xkbkeycodetokeysym_found=no + fi + if test $xkbkeycodetokeysym_found = "yes" ; then + AC_DEFINE(HAVE_XKBKEYCODETOKEYSYM, 1, [Do we have XkbKeycodeToKeysym?]) + fi + CFLAGS=$tk_oldCFlags + LIBS=$tk_oldLibs +fi + +#-------------------------------------------------------------------- +# Check whether XKeycodeToKeysym is deprecated in X11 headers. +#-------------------------------------------------------------------- + +if test $tk_aqua = no && test "$GCC" = yes; then + AC_MSG_CHECKING([whether XKeycodeToKeysym is deprecated]) + tk_oldCFlags=$CFLAGS + CFLAGS="$CFLAGS -Werror" + AC_TRY_LINK([ + #include <X11/Xlib.h> + ], [ + XKeycodeToKeysym(0,0,0); + ], [ + AC_MSG_RESULT([no]) + ], [ + AC_MSG_RESULT([yes]) + AC_DEFINE(XKEYCODETOKEYSYM_IS_DEPRECATED, 1, [Is XKeycodeToKeysym deprecated?]) + ]) + CFLAGS=$tk_oldCFlags +fi + +#-------------------------------------------------------------------- +# XXX Do this last. +# It might modify XLIBSW which could affect other tests. +# +# Check whether the header and library for the XScreenSaver +# extension are available, and set HAVE_XSS if so. +# XScreenSaver is needed for Tk_GetUserInactiveTime(). +#-------------------------------------------------------------------- + +if test $tk_aqua = no; then + tk_oldCFlags=$CFLAGS + CFLAGS="$CFLAGS $XINCLUDES" + tk_oldLibs=$LIBS + LIBS="$tk_oldLibs $XLIBSW" + xss_header_found=no + xss_lib_found=no + AC_MSG_CHECKING([whether to try to use XScreenSaver]) + AC_ARG_ENABLE(xss, + AC_HELP_STRING([--enable-xss], + [use XScreenSaver for activity timer (default: on)]), + [enable_xss=$enableval], [enable_xss=yes]) + if test "$enable_xss" = "no" ; then + AC_MSG_RESULT([$enable_xss]) + else + AC_MSG_RESULT([$enable_xss]) + AC_CHECK_HEADER(X11/extensions/scrnsaver.h, [ + xss_header_found=yes + ],,[#include <X11/Xlib.h>]) + AC_CHECK_FUNC(XScreenSaverQueryInfo,,[ + AC_CHECK_LIB(Xext, XScreenSaverQueryInfo, [ + XLIBSW="$XLIBSW -lXext" + xss_lib_found=yes + ], [ + AC_CHECK_LIB(Xss, XScreenSaverQueryInfo, [ + if test "$tcl_cv_ld_weak_l" = yes; then + # On Darwin, weak link libXss if possible, + # as it is only available on Tiger or later. + XLIBSW="$XLIBSW -Wl,-weak-lXss -lXext" + else + XLIBSW="$XLIBSW -lXss -lXext" + fi + xss_lib_found=yes + ],, -lXext) + ]) + ]) + fi + if test $enable_xss = yes -a $xss_lib_found = yes -a $xss_header_found = yes; then + AC_DEFINE(HAVE_XSS, 1, [Is XScreenSaver available?]) + fi + CFLAGS=$tk_oldCFlags + LIBS=$tk_oldLibs +fi + +#-------------------------------------------------------------------- +# Figure out whether "char" is unsigned. If so, set a +# #define for __CHAR_UNSIGNED__. +#-------------------------------------------------------------------- + +AC_C_CHAR_UNSIGNED + +#-------------------------------------------------------------------- +# The statements below define a collection of symbols related to +# building libtk as a shared library instead of a static library. +#-------------------------------------------------------------------- + +eval eval "TK_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}" +eval eval "TK_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}" +eval "TK_LIB_FILE=libtk${LIB_SUFFIX}" + +# tkConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed +# since on some platforms TK_LIB_FILE contains shell escapes. + +eval "TK_LIB_FILE=${TK_LIB_FILE}" + +if test "${SHARED_BUILD}" = "1" -a "${SHLIB_SUFFIX}" != ""; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \${TCL_STUB_LIB_SPEC}" + TCL_STUB_FLAGS="-DUSE_TCL_STUBS" +fi + +TK_LIBRARY='$(prefix)/lib/tk$(VERSION)' +PRIVATE_INCLUDE_DIR='$(includedir)' +HTML_DIR='$(DISTDIR)/html' +TK_PKG_DIR='tk$(VERSION)' +TK_RSRC_FILE='tk$(VERSION).rsrc' +WISH_RSRC_FILE='wish$(VERSION).rsrc' + +# Note: in the following variable, it's important to use the absolute +# path name of the Tcl directory rather than "..": this is because +# AIX remembers this path and will attempt to use it at run-time to look +# up the Tcl library. + +if test "`uname -s`" = "Darwin" ; then + SC_ENABLE_FRAMEWORK + TK_SHLIB_LD_EXTRAS="-compatibility_version ${TK_VERSION} -current_version ${TK_VERSION}`echo ${TK_PATCH_LEVEL} | awk ['{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}']`" + TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}/${TK_LIB_FILE}" -unexported_symbols_list $$(f=$(TK_LIB_FILE).E && nm -gp tkMacOSX*.o 2>/dev/null | awk "/^[[0-9a-f]]+ . \.objc/ {print \$$3}" > $$f && nm -gjp "$(TCL_BIN_DIR)"/$(TCL_STUB_LIB_FILE) | grep ^_[[^_]] >> $$f && echo $$f)' + echo "$LDFLAGS " | grep -q -- '-prebind ' && TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -seg1addr 0xb000000' + TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tk-Info.plist' + EXTRA_WISH_LIBS='-sectcreate __TEXT __info_plist Wish-Info.plist' + EXTRA_APP_CC_SWITCHES="${EXTRA_APP_CC_SWITCHES}"' -mdynamic-no-pic' + AC_CONFIG_FILES([Tk-Info.plist:../macosx/Tk-Info.plist.in Wish-Info.plist:../macosx/Wish-Info.plist.in]) + for l in ${LOCALES}; do CFBUNDLELOCALIZATIONS="${CFBUNDLELOCALIZATIONS}<string>$l</string>"; done + TK_YEAR="`date +%Y`" +fi + +if test "$FRAMEWORK_BUILD" = "1" ; then + AC_DEFINE(TK_FRAMEWORK, 1, [Is Tk built as a framework?]) + # Construct a fake local framework structure to make linking with + # '-framework Tk' and running of tktest work + AC_CONFIG_COMMANDS([Tk.framework], [n=Tk && + f=$n.framework && v=Versions/$VERSION && + rm -rf $f && mkdir -p $f/$v/Resources && + ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v && + ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist && + if test $tk_aqua = yes; then ln -s ../../../../$n.rsrc $f/$v/Resources; fi && + unset n f v + ], VERSION=${TK_VERSION} && tk_aqua=${tk_aqua}) + LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH" + if test "${libdir}" = '${exec_prefix}/lib'; then + # override libdir default + libdir="/Library/Frameworks" + fi + TK_LIB_FILE="Tk" + TK_LIB_FLAG="-framework Tk" + TK_BUILD_LIB_SPEC="-F`pwd | sed -e 's/ /\\\\ /g'` -framework Tk" + TK_LIB_SPEC="-F${libdir} -framework Tk" + libdir="${libdir}/Tk.framework/Versions/\${VERSION}" + TK_LIBRARY="${libdir}/Resources/Scripts" + TK_PKG_DIR="Resources/Scripts" + TK_RSRC_FILE="Tk.rsrc" + WISH_RSRC_FILE="Wish.rsrc" + includedir="${libdir}/Headers" + PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders" + HTML_DIR="${libdir}/Resources/Documentation/Reference/Tk" + EXTRA_INSTALL="install-private-headers html-tk" + EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)"/TkTOC.html' + EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tk-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"' + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"' + if test $tk_aqua = yes; then + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Images to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) "$(MAC_OSX_DIR)/$$i" "$(LIB_INSTALL_DIR)/Resources"; done' + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing wish$(VERSION) script to $(INSTALL_ROOT)/'"${bindir}"'/" && $(INSTALL_DATA_DIR) "$(INSTALL_ROOT)/'"${bindir}"'" && printf > "$(INSTALL_ROOT)/'"${bindir}"'/wish$(VERSION)" "#!/bin/sh\n\"\$$(dirname \$$0)'"`eval d="${bindir}"; echo "$d" | sed -e 's#/[^/][^/]*#/..#g'`"'$(bindir)/Wish\" \"\$$@\"" && chmod +x "$(INSTALL_ROOT)/'"${bindir}"'/wish$(VERSION)"' + bindir="${libdir}/Resources/Wish.app/Contents/MacOS" + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Info.plist to $(BIN_INSTALL_DIR)/.." && $(INSTALL_DATA) Wish-Info.plist "$(BIN_INSTALL_DIR)/../Info.plist" && mv -f "$(BIN_INSTALL_DIR)/wish$(VERSION)" "$(BIN_INSTALL_DIR)/Wish"' + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Wish.icns to $(BIN_INSTALL_DIR)/../Resources" && $(INSTALL_DATA_DIR) "$(BIN_INSTALL_DIR)/../Resources"' + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && $(INSTALL_DATA) "$(MAC_OSX_DIR)/Tk.icns" "$(BIN_INSTALL_DIR)/../Resources/Wish.icns"' + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Wish.sdef to $(BIN_INSTALL_DIR)/../Resources" && $(INSTALL_DATA) "$(MAC_OSX_DIR)/Wish.sdef" "$(BIN_INSTALL_DIR)/../Resources"' + fi + EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tk.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tkConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."' + # Don't use AC_DEFINE for the following as the framework version define + # needs to go into the Makefile even when using autoheader, so that we + # can pick up a potential make override of VERSION. Also, don't put this + # into CFLAGS as it should not go into tkConfig.sh + EXTRA_CC_SWITCHES="$EXTRA_CC_SWITCHES"' -DTK_FRAMEWORK_VERSION=\"$(VERSION)\"' +else + if test $tk_aqua = yes; then + EXTRA_INSTALL_BINARIES='@echo "Installing Images to $(LIB_INSTALL_DIR)/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) "$(MAC_OSX_DIR)/$$i" "$(LIB_INSTALL_DIR)"; done' + fi + # libdir must be a fully qualified path and not ${exec_prefix}/lib + eval libdir="$libdir" + if test "${ac_cv_cygwin}" = "yes" -a "$SHARED_BUILD" = "1"; then + TK_LIB_FLAG="-ltk`echo ${TK_VERSION} | tr -d .`" + TK_BUILD_LIB_SPEC="-L\$(TOP_DIR)/win ${TK_LIB_FLAG}" + else + if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then + TK_LIB_FLAG="-ltk${TK_VERSION}" + else + TK_LIB_FLAG="-ltk`echo ${TK_VERSION} | tr -d .`" + fi + TK_BUILD_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TK_LIB_FLAG}" + fi + TK_LIB_SPEC="-L${libdir} ${TK_LIB_FLAG}" +fi + +#-------------------------------------------------------------------- +# The statements below define various symbols relating to Tk +# stub support. +#-------------------------------------------------------------------- + +# Replace ${VERSION} with contents of ${TK_VERSION} +eval "TK_STUB_LIB_FILE=libtkstub${TK_UNSHARED_LIB_SUFFIX}" +eval "TK_STUB_LIB_DIR=${libdir}" + +if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then + TK_STUB_LIB_FLAG="-ltkstub${TK_VERSION}" +else + TK_STUB_LIB_FLAG="-ltkstub`echo ${TK_VERSION} | tr -d .`" +fi + +TK_BUILD_STUB_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" +TK_STUB_LIB_SPEC="-L${TK_STUB_LIB_DIR} ${TK_STUB_LIB_FLAG}" +TK_BUILD_STUB_LIB_PATH="`pwd`/${TK_STUB_LIB_FILE}" +TK_STUB_LIB_PATH="${TK_STUB_LIB_DIR}/${TK_STUB_LIB_FILE}" + +# Install time header dir can be set via --includedir +eval "TK_INCLUDE_SPEC=\"-I${includedir}\"" + +#------------------------------------------------------------------------ +# tkConfig.sh refers to this by a different name +#------------------------------------------------------------------------ + +TK_SHARED_BUILD=${SHARED_BUILD} + +AC_SUBST(TK_VERSION) +AC_SUBST(TK_MAJOR_VERSION) +AC_SUBST(TK_MINOR_VERSION) +AC_SUBST(TK_PATCH_LEVEL) +AC_SUBST(TK_YEAR) + +AC_SUBST(TK_LIB_FILE) +AC_SUBST(TK_LIB_FLAG) +AC_SUBST(TK_LIB_SPEC) +AC_SUBST(TK_STUB_LIB_FILE) +AC_SUBST(TK_STUB_LIB_FLAG) +AC_SUBST(TK_STUB_LIB_SPEC) +AC_SUBST(TK_STUB_LIB_PATH) +AC_SUBST(TK_INCLUDE_SPEC) +AC_SUBST(TK_BUILD_STUB_LIB_SPEC) +AC_SUBST(TK_BUILD_STUB_LIB_PATH) + +AC_SUBST(TK_SRC_DIR) + +AC_SUBST(TK_SHARED_BUILD) +AC_SUBST(LD_LIBRARY_PATH_VAR) + +AC_SUBST(TK_BUILD_LIB_SPEC) + +AC_SUBST(TCL_STUB_FLAGS) +AC_SUBST(XINCLUDES) +AC_SUBST(XLIBSW) +AC_SUBST(LOCALES) + +AC_SUBST(TK_WINDOWINGSYSTEM) +AC_SUBST(TK_PKG_DIR) +AC_SUBST(TK_LIBRARY) +AC_SUBST(LIB_RUNTIME_DIR) +AC_SUBST(PRIVATE_INCLUDE_DIR) +AC_SUBST(HTML_DIR) + +AC_SUBST(EXTRA_CC_SWITCHES) +AC_SUBST(EXTRA_APP_CC_SWITCHES) +AC_SUBST(EXTRA_INSTALL) +AC_SUBST(EXTRA_INSTALL_BINARIES) +AC_SUBST(EXTRA_BUILD_HTML) +AC_SUBST(EXTRA_WISH_LIBS) +AC_SUBST(CFBUNDLELOCALIZATIONS) + +AC_SUBST(TK_RSRC_FILE) +AC_SUBST(WISH_RSRC_FILE) +AC_SUBST(LIB_RSRC_FILE) +AC_SUBST(APP_RSRC_FILE) +AC_SUBST(REZ) +AC_SUBST(REZ_FLAGS) + +AC_CONFIG_FILES([ + Makefile:../unix/Makefile.in + tkConfig.sh:../unix/tkConfig.sh.in + tk.pc:../unix/tk.pc.in +]) +AC_OUTPUT + +dnl Local Variables: +dnl mode: autoconf +dnl End: diff --git a/tk8.6/unix/install-sh b/tk8.6/unix/install-sh new file mode 100755 index 0000000..7c34c3f --- /dev/null +++ b/tk8.6/unix/install-sh @@ -0,0 +1,528 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-04-20.01; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -S $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -S) stripcmd="$stripprog $2" + shift;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/tk8.6/unix/installManPage b/tk8.6/unix/installManPage new file mode 100755 index 0000000..4d615bf --- /dev/null +++ b/tk8.6/unix/installManPage @@ -0,0 +1,117 @@ +#!/bin/sh + +######################################################################## +### Parse Options +### + +Gzip=: +SymOrLoc="" +Gz="" +Suffix="" + +while true; do + case $1 in + -s | --symlinks ) SymOrLoc="-s " ;; + -z | --compress ) Gzip=$2; shift ;; + -e | --extension ) Gz=$2; shift ;; + -x | --suffix ) Suffix=$2; shift ;; + -*) cat <<EOF +Unknown option "$1". Supported options: + -s Use symbolic links for manpages with multiple names. + -z PROG Use PROG to compress manual pages. + -e EXT Defines the extension added by -z PROG when compressing. + -x SUFF Defines an extra extension suffix to use. +Option names may not be combined getopt-style. +EOF + exit 1 ;; + *) break ;; + esac + shift +done +if test "$#" != 2; then + echo "Usage: installManPages <options> file dir" + exit 1 +fi + +######################################################################## +### Parse Required Arguments +### + +ManPage=$1 +Dir=$2 +if test -f $ManPage ; then : ; else + echo "source manual page file must exist" + exit 1 +fi +if test -d $Dir ; then : ; else + echo "target directory must exist" + exit 1 +fi +test -z "$SymOrLoc" && SymOrLoc="$Dir/" + +######################################################################## +### Extract Target Names from Manual Page +### + +# A sed script to parse the alternative names out of a man page. +# +# Backslashes are trippled in the sed script, because it is in +# backticks which doesn't pass backslashes literally. +# +Names=`sed -n ' +# Look for a line that starts with .SH NAME + /^\.SH NAME/{ +# Read next line + n +# Remove all commas ... + s/,//g +# ... and backslash-escaped spaces. + s/\\\ //g +# Delete from \- to the end of line + s/ \\\-.*// +# Convert all non-space non-alphanum sequences +# to single underscores. + s/[^ A-Za-z0-9][^ A-Za-z0-9]*/_/g +# print the result and exit + p;q + }' $ManPage` + +if test -z "$Names" ; then + echo "warning: no target names found in $ManPage" +fi + +######################################################################## +### Remaining Set Up +### + +case $ManPage in + *.1) Section=1 ;; + *.3) Section=3 ;; + *.n) Section=n ;; + *) echo "unknown section for $ManPage" + exit 2 ;; +esac + +SrcDir=`dirname $ManPage` + +######################################################################## +### Process Page to Create Target Pages +### + +First="" +for Target in $Names; do + Target=$Target.$Section$Suffix + rm -f $Dir/$Target $Dir/$Target.* + if test -z "$First" ; then + First=$Target + sed -e "/man\.macros/r $SrcDir/man.macros" -e "/man\.macros/d" \ + $ManPage > $Dir/$First + chmod 444 $Dir/$First + $Gzip $Dir/$First + else + ln $SymOrLoc$First$Gz $Dir/$Target$Gz + fi +done + +######################################################################## +exit 0 diff --git a/tk8.6/unix/license.terms b/tk8.6/unix/license.terms new file mode 100644 index 0000000..0126435 --- /dev/null +++ b/tk8.6/unix/license.terms @@ -0,0 +1,40 @@ +This software is copyrighted by the Regents of the University of +California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState +Corporation, Apple Inc. and other parties. The following terms apply to +all files associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" +in the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you +are acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (b) (3) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. diff --git a/tk8.6/unix/tcl.m4 b/tk8.6/unix/tcl.m4 new file mode 100644 index 0000000..1953798 --- /dev/null +++ b/tk8.6/unix/tcl.m4 @@ -0,0 +1,3074 @@ +#------------------------------------------------------------------------ +# SC_PATH_TCLCONFIG -- +# +# Locate the tclConfig.sh file and perform a sanity check on +# the Tcl compile flags +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-tcl=... +# +# Defines the following vars: +# TCL_BIN_DIR Full path to the directory containing +# the tclConfig.sh file +#------------------------------------------------------------------------ + +AC_DEFUN([SC_PATH_TCLCONFIG], [ + # + # Ok, lets find the tcl configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tcl + # + + if test x"${no_tcl}" = x ; then + # we reset no_tcl in case something fails here + no_tcl=true + AC_ARG_WITH(tcl, + AC_HELP_STRING([--with-tcl], + [directory containing tcl configuration (tclConfig.sh)]), + with_tclconfig="${withval}") + AC_MSG_CHECKING([for Tcl configuration]) + AC_CACHE_VAL(ac_cv_c_tclconfig,[ + + # First check to see if --with-tcl was specified. + if test x"${with_tclconfig}" != x ; then + case "${with_tclconfig}" in + */tclConfig.sh ) + if test -f "${with_tclconfig}"; then + AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself]) + with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" + else + AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) + fi + fi + + # then check for a private Tcl installation + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ../tcl \ + `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../tcl \ + `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../../tcl \ + `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + ; do + if test -f "$i/Tcl.framework/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/pkg/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ${srcdir}/../tcl \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + ]) + + if test x"${ac_cv_c_tclconfig}" = x ; then + TCL_BIN_DIR="# no Tcl configs found" + AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh]) + else + no_tcl= + TCL_BIN_DIR="${ac_cv_c_tclconfig}" + AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh]) + fi + fi +]) + +#------------------------------------------------------------------------ +# SC_PATH_TKCONFIG -- +# +# Locate the tkConfig.sh file +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-tk=... +# +# Defines the following vars: +# TK_BIN_DIR Full path to the directory containing +# the tkConfig.sh file +#------------------------------------------------------------------------ + +AC_DEFUN([SC_PATH_TKCONFIG], [ + # + # Ok, lets find the tk configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tk + # + + if test x"${no_tk}" = x ; then + # we reset no_tk in case something fails here + no_tk=true + AC_ARG_WITH(tk, + AC_HELP_STRING([--with-tk], + [directory containing tk configuration (tkConfig.sh)]), + with_tkconfig="${withval}") + AC_MSG_CHECKING([for Tk configuration]) + AC_CACHE_VAL(ac_cv_c_tkconfig,[ + + # First check to see if --with-tkconfig was specified. + if test x"${with_tkconfig}" != x ; then + case "${with_tkconfig}" in + */tkConfig.sh ) + if test -f "${with_tkconfig}"; then + AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself]) + with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tkconfig}/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" + else + AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh]) + fi + fi + + # then check for a private Tk library + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ../tk \ + `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../tk \ + `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../../tk \ + `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + ; do + if test -f "$i/Tk.framework/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/pkg/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + `ls -d /usr/local/lib/tk8.6 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tk8.6 2>/dev/null` \ + ; do + if test -f "$i/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ${srcdir}/../tk \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + ]) + + if test x"${ac_cv_c_tkconfig}" = x ; then + TK_BIN_DIR="# no Tk configs found" + AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh]) + else + no_tk= + TK_BIN_DIR="${ac_cv_c_tkconfig}" + AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh]) + fi + fi +]) + +#------------------------------------------------------------------------ +# SC_LOAD_TCLCONFIG -- +# +# Load the tclConfig.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# TCL_BIN_DIR +# +# Results: +# +# Substitutes the following vars: +# TCL_BIN_DIR +# TCL_SRC_DIR +# TCL_LIB_FILE +#------------------------------------------------------------------------ + +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([could not find ${TCL_BIN_DIR}/tclConfig.sh]) + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" + eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" + + # If the TCL_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TCL_LIB_SPEC will be set to the value + # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC + # instead of TCL_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" + TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" + TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tcl.framework installed in an arbitrary location. + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then + for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ + "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then + TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" + break + fi + done + fi + if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then + TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" + TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" + eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" + eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" + eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" + + AC_SUBST(TCL_VERSION) + AC_SUBST(TCL_PATCH_LEVEL) + AC_SUBST(TCL_BIN_DIR) + AC_SUBST(TCL_SRC_DIR) + + AC_SUBST(TCL_LIB_FILE) + AC_SUBST(TCL_LIB_FLAG) + AC_SUBST(TCL_LIB_SPEC) + + AC_SUBST(TCL_STUB_LIB_FILE) + AC_SUBST(TCL_STUB_LIB_FLAG) + AC_SUBST(TCL_STUB_LIB_SPEC) +]) + +#------------------------------------------------------------------------ +# SC_LOAD_TKCONFIG -- +# +# Load the tkConfig.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# TK_BIN_DIR +# +# Results: +# +# Sets the following vars that should be in tkConfig.sh: +# TK_BIN_DIR +#------------------------------------------------------------------------ + +AC_DEFUN([SC_LOAD_TKCONFIG], [ + AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh]) + + if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then + AC_MSG_RESULT([loading]) + . "${TK_BIN_DIR}/tkConfig.sh" + else + AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh]) + fi + + # eval is required to do the TK_DBGX substitution + eval "TK_LIB_FILE=\"${TK_LIB_FILE}\"" + eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\"" + + # If the TK_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TK_LIB_SPEC will be set to the value + # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC + # instead of TK_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TK_BIN_DIR}/Makefile" ; then + TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}" + TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}" + TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tk.framework installed in an arbitrary location. + case ${TK_DEFS} in + *TK_FRAMEWORK*) + if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then + for i in "`cd "${TK_BIN_DIR}"; pwd`" \ + "`cd "${TK_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then + TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}" + break + fi + done + fi + if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then + TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" + TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TK_DBGX substitution + eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\"" + eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\"" + eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\"" + eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\"" + + AC_SUBST(TK_VERSION) + AC_SUBST(TK_BIN_DIR) + AC_SUBST(TK_SRC_DIR) + + AC_SUBST(TK_LIB_FILE) + AC_SUBST(TK_LIB_FLAG) + AC_SUBST(TK_LIB_SPEC) + + AC_SUBST(TK_STUB_LIB_FILE) + AC_SUBST(TK_STUB_LIB_FLAG) + AC_SUBST(TK_STUB_LIB_SPEC) +]) + +#------------------------------------------------------------------------ +# SC_PROG_TCLSH +# Locate a tclsh shell installed on the system path. This macro +# will only find a Tcl shell that already exists on the system. +# It will not find a Tcl shell in the Tcl build directory or +# a Tcl shell that has been installed from the Tcl build directory. +# If a Tcl shell can't be located on the PATH, then TCLSH_PROG will +# be set to "". Extensions should take care not to create Makefile +# rules that are run by default and depend on TCLSH_PROG. An +# extension can't assume that an executable Tcl shell exists at +# build time. +# +# Arguments: +# none +# +# Results: +# Substitutes the following vars: +# TCLSH_PROG +#------------------------------------------------------------------------ + +AC_DEFUN([SC_PROG_TCLSH], [ + AC_MSG_CHECKING([for tclsh]) + AC_CACHE_VAL(ac_cv_path_tclsh, [ + search_path=`echo ${PATH} | sed -e 's/:/ /g'` + for dir in $search_path ; do + for j in `ls -r $dir/tclsh[[8-9]]* 2> /dev/null` \ + `ls -r $dir/tclsh* 2> /dev/null` ; do + if test x"$ac_cv_path_tclsh" = x ; then + if test -f "$j" ; then + ac_cv_path_tclsh=$j + break + fi + fi + done + done + ]) + + if test -f "$ac_cv_path_tclsh" ; then + TCLSH_PROG="$ac_cv_path_tclsh" + AC_MSG_RESULT([$TCLSH_PROG]) + else + # It is not an error if an installed version of Tcl can't be located. + TCLSH_PROG="" + AC_MSG_RESULT([No tclsh found on PATH]) + fi + AC_SUBST(TCLSH_PROG) +]) + +#------------------------------------------------------------------------ +# SC_BUILD_TCLSH +# Determine the fully qualified path name of the tclsh executable +# in the Tcl build directory. This macro will correctly determine +# the name of the tclsh executable even if tclsh has not yet +# been built in the build directory. The build tclsh must be used +# when running tests from an extension build directory. It is not +# correct to use the TCLSH_PROG in cases like this. +# +# Arguments: +# none +# +# Results: +# Substitutes the following values: +# BUILD_TCLSH +#------------------------------------------------------------------------ + +AC_DEFUN([SC_BUILD_TCLSH], [ + AC_MSG_CHECKING([for tclsh in Tcl build directory]) + BUILD_TCLSH="${TCL_BIN_DIR}"/tclsh + AC_MSG_RESULT([$BUILD_TCLSH]) + AC_SUBST(BUILD_TCLSH) +]) + +#------------------------------------------------------------------------ +# 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, + AC_HELP_STRING([--enable-shared], + [build and link with shared libraries (default: on)]), + [tcl_ok=$enableval], [tcl_ok=yes]) + + if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + tcl_ok=$enableval + else + tcl_ok=yes + fi + + if test "$tcl_ok" = "yes" ; then + AC_MSG_RESULT([shared]) + SHARED_BUILD=1 + else + AC_MSG_RESULT([static]) + SHARED_BUILD=0 + AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?]) + fi +]) + +#------------------------------------------------------------------------ +# SC_ENABLE_FRAMEWORK -- +# +# Allows the building of shared libraries into frameworks +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-framework=yes|no +# +# Sets the following vars: +# FRAMEWORK_BUILD Value of 1 or 0 +#------------------------------------------------------------------------ + +AC_DEFUN([SC_ENABLE_FRAMEWORK], [ + if test "`uname -s`" = "Darwin" ; then + AC_MSG_CHECKING([how to package libraries]) + AC_ARG_ENABLE(framework, + AC_HELP_STRING([--enable-framework], + [package shared libraries in MacOSX frameworks (default: off)]), + [enable_framework=$enableval], [enable_framework=no]) + if test $enable_framework = yes; then + if test $SHARED_BUILD = 0; then + AC_MSG_WARN([Frameworks can only be built if --enable-shared is yes]) + enable_framework=no + fi + if test $tcl_corefoundation = no; then + AC_MSG_WARN([Frameworks can only be used when CoreFoundation is available]) + enable_framework=no + fi + fi + if test $enable_framework = yes; then + AC_MSG_RESULT([framework]) + FRAMEWORK_BUILD=1 + else + if test $SHARED_BUILD = 1; then + AC_MSG_RESULT([shared library]) + else + AC_MSG_RESULT([static library]) + fi + FRAMEWORK_BUILD=0 + fi + fi +]) + +#------------------------------------------------------------------------ +# SC_ENABLE_THREADS -- +# +# Specify if thread support should be enabled +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-threads +# +# Sets the following vars: +# THREADS_LIBS Thread library(s) +# +# Defines the following vars: +# TCL_THREADS +# _REENTRANT +# _THREAD_SAFE +#------------------------------------------------------------------------ + +AC_DEFUN([SC_ENABLE_THREADS], [ + AC_ARG_ENABLE(threads, + AC_HELP_STRING([--enable-threads], + [build with threads (default: on)]), + [tcl_ok=$enableval], [tcl_ok=yes]) + + if test "${TCL_THREADS}" = 1; then + tcl_threaded_core=1; + fi + + if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then + TCL_THREADS=1 + # USE_THREAD_ALLOC tells us to try the special thread-based + # allocator that significantly reduces lock contention + AC_DEFINE(USE_THREAD_ALLOC, 1, + [Do we want to use the threaded memory allocator?]) + AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) + if test "`uname -s`" = "SunOS" ; then + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, + [Do we really want to follow the standard? Yes we do!]) + fi + AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?]) + AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no) + if test "$tcl_ok" = "no"; then + # Check a little harder for __pthread_mutex_init in the same + # library, as some systems hide it there until pthread.h is + # defined. We could alternatively do an AC_TRY_COMPILE with + # pthread.h, but that will work with libpthread really doesn't + # exist, like AIX 4.2. [Bug: 4359] + AC_CHECK_LIB(pthread, __pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthread" + else + AC_CHECK_LIB(pthreads, pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthreads" + else + AC_CHECK_LIB(c, pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = "no"; then + AC_CHECK_LIB(c_r, pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -pthread" + else + TCL_THREADS=0 + AC_MSG_WARN([Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile...]) + fi + fi + fi + fi + + # Does the pthread-implementation provide + # 'pthread_attr_setstacksize' ? + + ac_saved_libs=$LIBS + LIBS="$LIBS $THREADS_LIBS" + AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork) + LIBS=$ac_saved_libs + else + TCL_THREADS=0 + fi + # Do checking message here to not mess up interleaved configure output + AC_MSG_CHECKING([for building with threads]) + if test "${TCL_THREADS}" = 1; then + AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?]) + if test "${tcl_threaded_core}" = 1; then + AC_MSG_RESULT([yes (threaded core)]) + else + AC_MSG_RESULT([yes]) + fi + else + AC_MSG_RESULT([no]) + fi + + AC_SUBST(TCL_THREADS) +]) + +#------------------------------------------------------------------------ +# SC_ENABLE_SYMBOLS -- +# +# Specify if debugging symbols should be used. +# Memory (TCL_MEM_DEBUG) and compile (TCL_COMPILE_DEBUG) debugging +# can also be enabled. +# +# 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 Sets to $(CFLAGS_DEBUG) if true +# Sets to $(CFLAGS_OPTIMIZE) if false +# LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true +# Sets to $(LDFLAGS_OPTIMIZE) if false +# DBGX Formerly used as debug library extension; +# always blank now. +#------------------------------------------------------------------------ + +AC_DEFUN([SC_ENABLE_SYMBOLS], [ + AC_MSG_CHECKING([for build with symbols]) + AC_ARG_ENABLE(symbols, + AC_HELP_STRING([--enable-symbols], + [build with debugging symbols (default: off)]), + [tcl_ok=$enableval], [tcl_ok=no]) +# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT. + DBGX="" + if test "$tcl_ok" = "no"; then + CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)' + LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)' + AC_DEFINE(NDEBUG, 1, [Is no debugging enabled?]) + AC_MSG_RESULT([no]) + AC_DEFINE(TCL_CFG_OPTIMIZED, 1, [Is this an optimized build?]) + else + CFLAGS_DEFAULT='$(CFLAGS_DEBUG)' + LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)' + if test "$tcl_ok" = "yes"; then + AC_MSG_RESULT([yes (standard debugging)]) + fi + fi + AC_SUBST(CFLAGS_DEFAULT) + AC_SUBST(LDFLAGS_DEFAULT) + + if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then + AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?]) + fi + + ifelse($1,bccdebug,dnl Only enable 'compile' for the Tcl core itself + if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then + AC_DEFINE(TCL_COMPILE_DEBUG, 1, [Is bytecode debugging enabled?]) + AC_DEFINE(TCL_COMPILE_STATS, 1, [Are bytecode statistics enabled?]) + fi) + + if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then + if test "$tcl_ok" = "all"; then + AC_MSG_RESULT([enabled symbols mem ]ifelse($1,bccdebug,[compile ])[debugging]) + else + AC_MSG_RESULT([enabled $tcl_ok debugging]) + fi + fi +]) + +#------------------------------------------------------------------------ +# SC_ENABLE_LANGINFO -- +# +# Allows use of modern nl_langinfo check for better l10n. +# This is only relevant for Unix. +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-langinfo=yes|no (default is yes) +# +# Defines the following vars: +# HAVE_LANGINFO Triggers use of nl_langinfo if defined. +#------------------------------------------------------------------------ + +AC_DEFUN([SC_ENABLE_LANGINFO], [ + AC_ARG_ENABLE(langinfo, + AC_HELP_STRING([--enable-langinfo], + [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]), + [langinfo_ok=$enableval], [langinfo_ok=yes]) + + HAVE_LANGINFO=0 + if test "$langinfo_ok" = "yes"; then + AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no]) + fi + AC_MSG_CHECKING([whether to use nl_langinfo]) + if test "$langinfo_ok" = "yes"; then + AC_CACHE_VAL(tcl_cv_langinfo_h, [ + AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);], + [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])]) + AC_MSG_RESULT([$tcl_cv_langinfo_h]) + if test $tcl_cv_langinfo_h = yes; then + AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?]) + fi + else + AC_MSG_RESULT([$langinfo_ok]) + fi +]) + +#-------------------------------------------------------------------- +# SC_CONFIG_MANPAGES +# +# Decide whether to use symlinks for linking the manpages, +# whether to compress the manpages after installation, and +# whether to add a package name suffix to the installed +# manpages to avoidfile name clashes. +# If compression is enabled also find out what file name suffix +# the given compression program is using. +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-man-symlinks +# --enable-man-compression=PROG +# --enable-man-suffix[=STRING] +# +# Defines the following variable: +# +# MAN_FLAGS - The apropriate flags for installManPage +# according to the user's selection. +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_CONFIG_MANPAGES], [ + AC_MSG_CHECKING([whether to use symlinks for manpages]) + AC_ARG_ENABLE(man-symlinks, + AC_HELP_STRING([--enable-man-symlinks], + [use symlinks for the manpages (default: off)]), + test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks", + enableval="no") + AC_MSG_RESULT([$enableval]) + + AC_MSG_CHECKING([whether to compress the manpages]) + AC_ARG_ENABLE(man-compression, + AC_HELP_STRING([--enable-man-compression=PROG], + [compress the manpages with PROG (default: off)]), + [case $enableval in + yes) AC_MSG_ERROR([missing argument to --enable-man-compression]);; + no) ;; + *) MAN_FLAGS="$MAN_FLAGS --compress $enableval";; + esac], + enableval="no") + AC_MSG_RESULT([$enableval]) + if test "$enableval" != "no"; then + AC_MSG_CHECKING([for compressed file suffix]) + touch TeST + $enableval TeST + Z=`ls TeST* | sed 's/^....//'` + rm -f TeST* + MAN_FLAGS="$MAN_FLAGS --extension $Z" + AC_MSG_RESULT([$Z]) + fi + + AC_MSG_CHECKING([whether to add a package name suffix for the manpages]) + AC_ARG_ENABLE(man-suffix, + AC_HELP_STRING([--enable-man-suffix=STRING], + [use STRING as a suffix to manpage file names (default: no, AC_PACKAGE_NAME if enabled without specifying STRING)]), + [case $enableval in + yes) enableval="AC_PACKAGE_NAME" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";; + no) ;; + *) MAN_FLAGS="$MAN_FLAGS --suffix $enableval";; + esac], + enableval="no") + AC_MSG_RESULT([$enableval]) + + AC_SUBST(MAN_FLAGS) +]) + +#-------------------------------------------------------------------- +# SC_CONFIG_SYSTEM +# +# Determine what the system is (some things cannot be easily checked +# on a feature-driven basis, alas). This can usually be done via the +# "uname" command, but there are a few systems, like Next, where +# this doesn't work. +# +# Arguments: +# none +# +# Results: +# Defines the following var: +# +# system - System/platform/version identification code. +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_CONFIG_SYSTEM], [ + AC_CACHE_CHECK([system version], tcl_cv_sys_version, [ + if test -f /usr/lib/NextStep/software_version; then + tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` + else + tcl_cv_sys_version=`uname -s`-`uname -r` + if test "$?" -ne 0 ; then + AC_MSG_WARN([can't find uname command]) + tcl_cv_sys_version=unknown + else + # Special check for weird MP-RAS system (uname returns weird + # results, and the version is kept in special file). + + if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then + tcl_cv_sys_version=MP-RAS-`awk '{print $[3]}' /etc/.relid` + fi + if test "`uname -s`" = "AIX" ; then + tcl_cv_sys_version=AIX-`uname -v`.`uname -r` + fi + fi + fi + ]) + system=$tcl_cv_sys_version +]) + +#-------------------------------------------------------------------- +# SC_CONFIG_CFLAGS +# +# Try to determine the proper flags to pass to the compiler +# for building shared libraries and other such nonsense. +# +# Arguments: +# none +# +# Results: +# +# Defines and substitutes the following vars: +# +# DL_OBJS - Name of the object file that implements dynamic +# loading for Tcl on this system. +# DL_LIBS - Library file(s) to include in tclsh and other base +# applications in order for the "load" command to work. +# LDFLAGS - Flags to pass to the compiler when linking object +# files into an executable application binary such +# as tclsh. +# LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib", +# that tell the run-time dynamic linker where to look +# for shared libraries such as libtcl.so. Depends on +# the variable LIB_RUNTIME_DIR in the Makefile. Could +# be the same as CC_SEARCH_FLAGS if ${CC} is used to link. +# CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib", +# that tell the run-time dynamic linker where to look +# for shared libraries such as libtcl.so. Depends on +# the variable LIB_RUNTIME_DIR in the Makefile. +# MAKE_LIB - Command to execute to build the a library; +# differs when building shared or static. +# MAKE_STUB_LIB - +# Command to execute to build a stub library. +# INSTALL_LIB - Command to execute to install a library; +# differs when building shared or static. +# INSTALL_STUB_LIB - +# Command to execute to install a stub library. +# STLIB_LD - Base command to use for combining object files +# into a static library. +# SHLIB_CFLAGS - Flags to pass to cc when compiling the components +# of a shared library (may request position-independent +# code, among other things). +# SHLIB_LD - Base command to use for combining object files +# into a shared library. +# SHLIB_LD_LIBS - Dependent libraries for the linker to scan when +# creating shared libraries. This symbol typically +# goes at the end of the "ld" commands that build +# shared libraries. The value of the symbol defaults to +# "${LIBS}" if all of the dependent libraries should +# be specified when creating a shared library. If +# dependent libraries should not be specified (as on +# SunOS 4.x, where they cause the link to fail, or in +# general if Tcl and Tk aren't themselves shared +# libraries), then this symbol has an empty string +# as its value. +# SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable +# extensions. An empty string means we don't know how +# to use shared libraries on this platform. +# TCL_SHLIB_LD_EXTRAS - Additional element which are added to SHLIB_LD_LIBS +# TK_SHLIB_LD_EXTRAS for the build of Tcl and Tk, but not recorded in the +# tclConfig.sh, since they are only used for the build +# of Tcl and Tk. +# Examples: MacOS X records the library version and +# compatibility version in the shared library. But +# of course the Tcl version of this is only used for Tcl. +# LIB_SUFFIX - Specifies everything that comes after the "libfoo" +# in a static or shared library name, using the $VERSION variable +# to put the version in the right place. This is used +# by platforms that need non-standard library names. +# Examples: ${VERSION}.so.1.1 on NetBSD, since it needs +# to have a version after the .so, and ${VERSION}.a +# on AIX, since a shared library needs to have +# a .a extension whereas shared objects for loadable +# extensions have a .so extension. Defaults to +# ${VERSION}${SHLIB_SUFFIX}. +# TCL_LIBS - +# Libs to use when linking Tcl shell or some other +# shell that includes Tcl libs. +# CFLAGS_DEBUG - +# Flags used when running the compiler in debug mode +# CFLAGS_OPTIMIZE - +# Flags used when running the compiler in optimize mode +# CFLAGS - Additional CFLAGS added as necessary (usually 64-bit) +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_CONFIG_CFLAGS], [ + + # Step 0.a: Enable 64 bit support? + + AC_MSG_CHECKING([if 64bit support is requested]) + AC_ARG_ENABLE(64bit, + AC_HELP_STRING([--enable-64bit], + [enable 64bit support (default: off)]), + [do64bit=$enableval], [do64bit=no]) + AC_MSG_RESULT([$do64bit]) + + # Step 0.b: Enable Solaris 64 bit VIS support? + + AC_MSG_CHECKING([if 64bit Sparc VIS support is requested]) + AC_ARG_ENABLE(64bit-vis, + AC_HELP_STRING([--enable-64bit-vis], + [enable 64bit Sparc VIS support (default: off)]), + [do64bitVIS=$enableval], [do64bitVIS=no]) + AC_MSG_RESULT([$do64bitVIS]) + # Force 64bit on with VIS + AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes]) + + # Step 0.c: Check if visibility support is available. Do this here so + # that platform specific alternatives can be used below if this fails. + + AC_CACHE_CHECK([if compiler supports visibility "hidden"], + tcl_cv_cc_visibility_hidden, [ + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" + AC_TRY_LINK([ + extern __attribute__((__visibility__("hidden"))) void f(void); + void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes, + tcl_cv_cc_visibility_hidden=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [ + AC_DEFINE(MODULE_SCOPE, + [extern __attribute__((__visibility__("hidden")))], + [Compiler support for module scope symbols]) + AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols]) + ]) + + # Step 0.d: Disable -rpath support? + + AC_MSG_CHECKING([if rpath support is requested]) + AC_ARG_ENABLE(rpath, + AC_HELP_STRING([--disable-rpath], + [disable rpath support (default: on)]), + [doRpath=$enableval], [doRpath=yes]) + AC_MSG_RESULT([$doRpath]) + + # Step 1: set the variable "system" to hold the name and version number + # for the system. + + SC_CONFIG_SYSTEM + + # Step 2: check for existence of -ldl library. This is needed because + # Linux can use either -ldl or -ldld for dynamic loading. + + AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no) + + # Require ranlib early so we can override it in special cases below. + + AC_REQUIRE([AC_PROG_RANLIB]) + + # Step 3: set configuration options based on system name and version. + + do64bit_ok=no + # default to '{$LIBS}' and set to "" on per-platform necessary basis + SHLIB_LD_LIBS='${LIBS}' + LDFLAGS_ORIG="$LDFLAGS" + # When ld needs options to work in 64-bit mode, put them in + # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] + # is disabled by the user. [Bug 1016796] + LDFLAGS_ARCH="" + UNSHARED_LIB_SUFFIX="" + TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`' + ECHO_VERSION='`echo ${VERSION}`' + TCL_LIB_VERSIONS_OK=ok + CFLAGS_DEBUG=-g + AS_IF([test "$GCC" = yes], [ + CFLAGS_OPTIMIZE=-O2 + CFLAGS_WARNING="-Wall" + ], [ + CFLAGS_OPTIMIZE=-O + CFLAGS_WARNING="" + ]) + AC_CHECK_TOOL(AR, ar) + STLIB_LD='${AR} cr' + LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" + PLAT_OBJS="" + PLAT_SRCS="" + LDAIX_SRC="" + AS_IF([test "x${SHLIB_VERSION}" = x],[SHLIB_VERSION=".1.0"],[SHLIB_VERSION=".${SHLIB_VERSION}"]) + case $system in + AIX-*) + AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [ + # AIX requires the _r compiler when gcc isn't being used + case "${CC}" in + *_r|*_r\ *) + # ok ... + ;; + *) + # Make sure only first arg gets _r + CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'` + ;; + esac + AC_MSG_RESULT([Using $CC for compiling with threads]) + ]) + LIBS="$LIBS -lc" + SHLIB_CFLAGS="" + SHLIB_SUFFIX=".so" + + DL_OBJS="tclLoadDl.o" + LD_LIBRARY_PATH_VAR="LIBPATH" + + # ldAix No longer needed with use of -bexpall/-brtl + # but some extensions may still reference it + LDAIX_SRC='$(UNIX_DIR)/ldAix' + + # Check to enable 64-bit flags for compiler/linker + AS_IF([test "$do64bit" = yes], [ + AS_IF([test "$GCC" = yes], [ + AC_MSG_WARN([64bit mode not supported with GCC on $system]) + ], [ + do64bit_ok=yes + CFLAGS="$CFLAGS -q64" + LDFLAGS_ARCH="-q64" + RANLIB="${RANLIB} -X64" + AR="${AR} -X64" + SHLIB_LD_FLAGS="-b64" + ]) + ]) + + AS_IF([test "`uname -m`" = ia64], [ + # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + # AIX-5 has dl* in libc.so + DL_LIBS="" + AS_IF([test "$GCC" = yes], [ + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + ], [ + CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' + ]) + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + ], [ + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared -Wl,-bexpall' + ], [ + SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" + LDFLAGS="$LDFLAGS -brtl" + ]) + SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" + DL_LIBS="-ldl" + CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ]) + ;; + BeOS*) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -nostart' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + + #----------------------------------------------------------- + # Check for inet_ntoa in -lbind, for BeOS (which also needs + # -lsocket, even if the network functions are in -lnet which + # is always linked to, for compatibility. + #----------------------------------------------------------- + AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"]) + ;; + BSD/OS-2.1*|BSD/OS-3*) + SHLIB_CFLAGS="" + SHLIB_LD="shlicc -r" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + BSD/OS-4.*) + SHLIB_CFLAGS="-export-dynamic -fPIC" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="$LDFLAGS -export-dynamic" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + CYGWIN_*|MINGW32*) + SHLIB_CFLAGS="" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".dll" + DL_OBJS="tclLoadDl.o" + PLAT_OBJS='${CYGWIN_OBJS}' + PLAT_SRCS='${CYGWIN_SRCS}' + DL_LIBS="-ldl" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + TCL_NEEDS_EXP_FILE=1 + TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a' + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a" + AC_CACHE_CHECK(for Cygwin version of gcc, + ac_cv_cygwin, + AC_TRY_COMPILE([ + #ifdef __CYGWIN__ + #error cygwin + #endif + ], [], + ac_cv_cygwin=no, + ac_cv_cygwin=yes) + ) + if test "$ac_cv_cygwin" = "no"; then + AC_MSG_ERROR([${CC} is not a cygwin compiler.]) + fi + if test "x${TCL_THREADS}" = "x0"; then + AC_MSG_ERROR([CYGWIN compile is only supported with --enable-threads]) + fi + do64bit_ok=yes + if test "x${SHARED_BUILD}" = "x1"; then + echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args" + # The eval makes quoting arguments work. + if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args; cd ../unix + then : + else + { echo "configure: error: configure failed for ../win" 1>&2; exit 1; } + fi + fi + ;; + dgux*) + SHLIB_CFLAGS="-K PIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + Haiku*) + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' + DL_OBJS="tclLoadDl.o" + DL_LIBS="-lroot" + AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"]) + ;; + HP-UX-*.11.*) + # Use updated header definitions where possible + AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?]) + AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) + LIBS="$LIBS -lxnet" # Use the XOPEN network library + + AS_IF([test "`uname -m`" = ia64], [ + SHLIB_SUFFIX=".so" + ], [ + SHLIB_SUFFIX=".sl" + ]) + AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) + AS_IF([test "$tcl_ok" = yes], [ + SHLIB_CFLAGS="+z" + SHLIB_LD="ld -b" + DL_OBJS="tclLoadShl.o" + DL_LIBS="-ldld" + LDFLAGS="$LDFLAGS -Wl,-E" + CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' + LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' + LD_LIBRARY_PATH_VAR="SHLIB_PATH" + ]) + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ], [ + CFLAGS="$CFLAGS -z" + ]) + + # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc + #CFLAGS="$CFLAGS +DAportable" + + # Check to enable 64-bit flags for compiler/linker + AS_IF([test "$do64bit" = "yes"], [ + AS_IF([test "$GCC" = yes], [ + case `${CC} -dumpmachine` in + hppa64*) + # 64-bit gcc in use. Fix flags for GNU ld. + do64bit_ok=yes + SHLIB_LD='${CC} -shared' + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ;; + *) + AC_MSG_WARN([64bit mode not supported with GCC on $system]) + ;; + esac + ], [ + do64bit_ok=yes + CFLAGS="$CFLAGS +DD64" + LDFLAGS_ARCH="+DD64" + ]) + ]) ;; + HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) + SHLIB_SUFFIX=".sl" + AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) + AS_IF([test "$tcl_ok" = yes], [ + SHLIB_CFLAGS="+z" + SHLIB_LD="ld -b" + SHLIB_LD_LIBS="" + DL_OBJS="tclLoadShl.o" + DL_LIBS="-ldld" + LDFLAGS="$LDFLAGS -Wl,-E" + CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' + LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' + LD_LIBRARY_PATH_VAR="SHLIB_PATH" + ]) ;; + IRIX-5.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -shared -rdata_shared" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + AC_LIBOBJ(mkstemp) + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + ;; + IRIX-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + AC_LIBOBJ(mkstemp) + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + AS_IF([test "$GCC" = yes], [ + CFLAGS="$CFLAGS -mabi=n32" + LDFLAGS="$LDFLAGS -mabi=n32" + ], [ + case $system in + IRIX-6.3) + # Use to build 6.2 compatible binaries on 6.3. + CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" + ;; + *) + CFLAGS="$CFLAGS -n32" + ;; + esac + LDFLAGS="$LDFLAGS -n32" + ]) + ;; + IRIX64-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + AC_LIBOBJ(mkstemp) + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + + # Check to enable 64-bit flags for compiler/linker + + AS_IF([test "$do64bit" = yes], [ + AS_IF([test "$GCC" = yes], [ + AC_MSG_WARN([64bit mode not supported by gcc]) + ], [ + do64bit_ok=yes + SHLIB_LD="ld -64 -shared -rdata_shared" + CFLAGS="$CFLAGS -64" + LDFLAGS_ARCH="-64" + ]) + ]) + ;; + Linux*|GNU*|NetBSD-Debian) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + + CFLAGS_OPTIMIZE="-O2" + # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings + # when you inline the string and math operations. Turn this off to + # get rid of the warnings. + #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES" + + SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"]) + AS_IF([test $do64bit = yes], [ + AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [ + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -m64" + AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_m64 = yes], [ + CFLAGS="$CFLAGS -m64" + do64bit_ok=yes + ]) + ]) + + # The combo of gcc + glibc has a bug related to inlining of + # functions like strtod(). The -fno-builtin flag should address + # this problem but it does not work. The -fno-inline flag is kind + # of overkill but it works. Disable inlining only when one of the + # files in compat/*.c is being linked in. + + AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"]) + ;; + Lynx*) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + CFLAGS_OPTIMIZE=-02 + SHLIB_LD='${CC} -shared' + DL_OBJS="tclLoadDl.o" + DL_LIBS="-mshared -ldl" + LD_FLAGS="-Wl,--export-dynamic" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + ;; + MP-RAS-02*) + SHLIB_CFLAGS="-K PIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + MP-RAS-*) + SHLIB_CFLAGS="-K PIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="$LDFLAGS -Wl,-Bexport" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + OpenBSD-*) + arch=`arch -s` + case "$arch" in + alpha|sparc64) + SHLIB_CFLAGS="-fPIC" + ;; + *) + SHLIB_CFLAGS="-fpic" + ;; + esac + SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' + LDFLAGS="-Wl,-export-dynamic" + CFLAGS_OPTIMIZE="-O2" + AS_IF([test "${TCL_THREADS}" = "1"], [ + # On OpenBSD: Compile with -pthread + # Don't link with -lpthread + LIBS=`echo $LIBS | sed s/-lpthread//` + CFLAGS="$CFLAGS -pthread" + ]) + # OpenBSD doesn't do version numbers with dots. + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + TCL_LIB_VERSIONS_OK=nodots + ;; + NetBSD-*) + # NetBSD has ELF and can use 'cc -shared' to build shared libs + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + LDFLAGS="$LDFLAGS -export-dynamic" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + AS_IF([test "${TCL_THREADS}" = "1"], [ + # The -pthread needs to go in the CFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + ]) + ;; + DragonFly-*|FreeBSD-*) + # This configuration from FreeBSD Ports. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="${CC} -shared" + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$[@]" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + LDFLAGS="" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + AS_IF([test "${TCL_THREADS}" = "1"], [ + # The -pthread needs to go in the LDFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LDFLAGS="$LDFLAGS $PTHREAD_LIBS"]) + case $system in + FreeBSD-3.*) + # Version numbers are dot-stripped by system policy. + TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .` + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' + TCL_LIB_VERSIONS_OK=nodots + ;; + esac + ;; + Darwin-*) + CFLAGS_OPTIMIZE="-Os" + SHLIB_CFLAGS="-fno-common" + # To avoid discrepancies between what headers configure sees during + # preprocessing tests and compiling tests, move any -isysroot and + # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: + CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`" + CFLAGS="`echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`" + AS_IF([test $do64bit = yes], [ + case `arch` in + ppc) + AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag], + tcl_cv_cc_arch_ppc64, [ + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes, + tcl_cv_cc_arch_ppc64=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [ + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + do64bit_ok=yes + ]);; + i386) + AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag], + tcl_cv_cc_arch_x86_64, [ + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch x86_64" + AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes, + tcl_cv_cc_arch_x86_64=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [ + CFLAGS="$CFLAGS -arch x86_64" + do64bit_ok=yes + ]);; + *) + AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);; + esac + ], [ + # Check for combined 32-bit and 64-bit fat build + AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ + && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [ + fat_32_64=yes]) + ]) + SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}' + AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" + AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no) + LDFLAGS=$hold_ldflags]) + AS_IF([test $tcl_cv_ld_single_module = yes], [ + SHLIB_LD="${SHLIB_LD} -Wl,-single_module" + ]) + SHLIB_SUFFIX=".dylib" + DL_OBJS="tclLoadDyld.o" + DL_LIBS="" + # Don't use -prebind when building for Mac OS X 10.4 or later only: + AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \ + "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [ + LDFLAGS="$LDFLAGS -prebind"]) + LDFLAGS="$LDFLAGS -headerpad_max_install_names" + AC_CACHE_CHECK([if ld accepts -search_paths_first flag], + tcl_cv_ld_search_paths_first, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes, + tcl_cv_ld_search_paths_first=no) + LDFLAGS=$hold_ldflags]) + AS_IF([test $tcl_cv_ld_search_paths_first = yes], [ + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + ]) + AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ + AC_DEFINE(MODULE_SCOPE, [__private_extern__], + [Compiler support for module scope symbols]) + ]) + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" + AC_DEFINE(MAC_OSX_TCL, 1, [Is this a Mac I see before me?]) + PLAT_OBJS='${MAC_OSX_OBJS}' + PLAT_SRCS='${MAC_OSX_SRCS}' + AC_MSG_CHECKING([whether to use CoreFoundation]) + AC_ARG_ENABLE(corefoundation, + AC_HELP_STRING([--enable-corefoundation], + [use CoreFoundation API on MacOSX (default: on)]), + [tcl_corefoundation=$enableval], [tcl_corefoundation=yes]) + AC_MSG_RESULT([$tcl_corefoundation]) + AS_IF([test $tcl_corefoundation = yes], [ + AC_CACHE_CHECK([for CoreFoundation.framework], + tcl_cv_lib_corefoundation, [ + hold_libs=$LIBS + AS_IF([test "$fat_32_64" = yes], [ + for v in CFLAGS CPPFLAGS LDFLAGS; do + # On Tiger there is no 64-bit CF, so remove 64-bit + # archs from CFLAGS et al. while testing for + # presence of CF. 64-bit CF is disabled in + # tclUnixPort.h if necessary. + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' + done]) + LIBS="$LIBS -framework CoreFoundation" + AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>], + [CFBundleRef b = CFBundleGetMainBundle();], + tcl_cv_lib_corefoundation=yes, + tcl_cv_lib_corefoundation=no) + AS_IF([test "$fat_32_64" = yes], [ + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done]) + LIBS=$hold_libs]) + AS_IF([test $tcl_cv_lib_corefoundation = yes], [ + LIBS="$LIBS -framework CoreFoundation" + AC_DEFINE(HAVE_COREFOUNDATION, 1, + [Do we have access to Darwin CoreFoundation.framework?]) + ], [tcl_corefoundation=no]) + AS_IF([test "$fat_32_64" = yes -a $tcl_corefoundation = yes],[ + AC_CACHE_CHECK([for 64-bit CoreFoundation], + tcl_cv_lib_corefoundation_64, [ + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>], + [CFBundleRef b = CFBundleGetMainBundle();], + tcl_cv_lib_corefoundation_64=yes, + tcl_cv_lib_corefoundation_64=no) + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done]) + AS_IF([test $tcl_cv_lib_corefoundation_64 = no], [ + AC_DEFINE(NO_COREFOUNDATION_64, 1, + [Is Darwin CoreFoundation unavailable for 64-bit?]) + LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings" + ]) + ]) + ]) + ;; + NEXTSTEP-*) + SHLIB_CFLAGS="" + SHLIB_LD='${CC} -nostdlib -r' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadNext.o" + DL_LIBS="" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + OS/390-*) + SHLIB_LD_LIBS="" + CFLAGS_OPTIMIZE="" # Optimizer is buggy + AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h + [Should OS/390 do the right thing with sockets?]) + ;; + OSF1-1.0|OSF1-1.1|OSF1-1.2) + # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 + SHLIB_CFLAGS="" + # Hack: make package name same as library name + SHLIB_LD='ld -R -export $@:' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadOSF.o" + DL_LIBS="" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + OSF1-1.*) + # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 + SHLIB_CFLAGS="-fPIC" + AS_IF([test "$SHARED_BUILD" = 1], [SHLIB_LD="ld -shared"], [ + SHLIB_LD="ld -non_shared" + ]) + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + OSF1-V*) + # Digital OSF/1 + SHLIB_CFLAGS="" + AS_IF([test "$SHARED_BUILD" = 1], [ + SHLIB_LD='ld -shared -expect_unresolved "*"' + ], [ + SHLIB_LD='ld -non_shared -expect_unresolved "*"' + ]) + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [ + CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"]) + # see pthread_intro(3) for pthread support on osf1, k.furukawa + AS_IF([test "${TCL_THREADS}" = 1], [ + CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" + CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" + LIBS=`echo $LIBS | sed s/-lpthreads//` + AS_IF([test "$GCC" = yes], [ + LIBS="$LIBS -lpthread -lmach -lexc" + ], [ + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + ]) + ]) + ;; + QNX-6*) + # QNX RTP + # This may work for all QNX, but it was only reported for v6. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="ld -Bshareable -x" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + # dlopen is in -lc on QNX + DL_LIBS="" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SCO_SV-3.2*) + # Note, dlopen is available only on SCO 3.2.5 and greater. However, + # this test works, since "uname -s" was non-standard in 3.2.4 and + # below. + AS_IF([test "$GCC" = yes], [ + SHLIB_CFLAGS="-fPIC -melf" + LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" + ], [ + SHLIB_CFLAGS="-Kpic -belf" + LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" + ]) + SHLIB_LD="ld -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SINIX*5.4*) + SHLIB_CFLAGS="-K PIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SunOS-4*) + SHLIB_CFLAGS="-PIC" + SHLIB_LD="ld" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + + # SunOS can't handle version numbers with dots in them in library + # specs, like -ltcl7.5, so use -ltcl75 instead. Also, it + # requires an extra version number at the end of .so file names. + # So, the library has to have a name like libtcl75.so.1.0 + + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + TCL_LIB_VERSIONS_OK=nodots + ;; + SunOS-5.[[0-6]]) + # Careful to not let 5.10+ fall into this case + + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, + [Do we really want to follow the standard? Yes we do!]) + + SHLIB_CFLAGS="-KPIC" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ], [ + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ]) + ;; + SunOS-5*) + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, + [Do we really want to follow the standard? Yes we do!]) + + SHLIB_CFLAGS="-KPIC" + + # Check to enable 64-bit flags for compiler/linker + AS_IF([test "$do64bit" = yes], [ + arch=`isainfo` + AS_IF([test "$arch" = "sparcv9 sparc"], [ + AS_IF([test "$GCC" = yes], [ + AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [ + AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system]) + ], [ + do64bit_ok=yes + CFLAGS="$CFLAGS -m64 -mcpu=v9" + LDFLAGS="$LDFLAGS -m64 -mcpu=v9" + SHLIB_CFLAGS="-fPIC" + ]) + ], [ + do64bit_ok=yes + AS_IF([test "$do64bitVIS" = yes], [ + CFLAGS="$CFLAGS -xarch=v9a" + LDFLAGS_ARCH="-xarch=v9a" + ], [ + CFLAGS="$CFLAGS -xarch=v9" + LDFLAGS_ARCH="-xarch=v9" + ]) + # Solaris 64 uses this as well + #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" + ]) + ], [AS_IF([test "$arch" = "amd64 i386"], [ + AS_IF([test "$GCC" = yes], [ + case $system in + SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) + do64bit_ok=yes + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + AC_MSG_WARN([64bit mode not supported with GCC on $system]);; + esac + ], [ + do64bit_ok=yes + case $system in + SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + CFLAGS="$CFLAGS -xarch=amd64" + LDFLAGS="$LDFLAGS -xarch=amd64";; + esac + ]) + ], [AC_MSG_WARN([64bit mode not supported for $arch])])]) + ]) + + #-------------------------------------------------------------------- + # On Solaris 5.x i386 with the sunpro compiler we need to link + # with sunmath to get floating point rounding control + #-------------------------------------------------------------------- + AS_IF([test "$GCC" = yes],[use_sunmath=no],[ + arch=`isainfo` + AC_MSG_CHECKING([whether to use -lsunmath for fp rounding control]) + AS_IF([test "$arch" = "amd64 i386" -o "$arch" = "i386"], [ + AC_MSG_RESULT([yes]) + MATH_LIBS="-lsunmath $MATH_LIBS" + AC_CHECK_HEADER(sunmath.h) + use_sunmath=yes + ], [ + AC_MSG_RESULT([no]) + use_sunmath=no + ]) + ]) + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + AS_IF([test "$do64bit_ok" = yes], [ + AS_IF([test "$arch" = "sparcv9 sparc"], [ + # We need to specify -static-libgcc or we need to + # add the path to the sparv9 libgcc. + SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" + # for finding sparcv9 libgcc, get the regular libgcc + # path, remove so name and append 'sparcv9' + #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." + #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" + ], [AS_IF([test "$arch" = "amd64 i386"], [ + SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" + ])]) + ]) + ], [ + AS_IF([test "$use_sunmath" = yes], [textmode=textoff],[textmode=text]) + case $system in + SunOS-5.[[1-9]][[0-9]]*|SunOS-5.[[7-9]]) + SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";; + *) + SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";; + esac + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + ]) + ;; + UNIX_SV* | UnixWare-5*) + SHLIB_CFLAGS="-KPIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers + # that don't grok the -Bexport option. Test that it does. + AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-Bexport" + AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no) + LDFLAGS=$hold_ldflags]) + AS_IF([test $tcl_cv_ld_Bexport = yes], [ + LDFLAGS="$LDFLAGS -Wl,-Bexport" + ]) + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + esac + + AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [ + AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform]) + ]) + + AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = yes], [ + AC_DEFINE(TCL_CFG_DO64BIT, 1, [Is this a 64-bit build?]) + ]) + +dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so +dnl # until the end of configure, as configure's compile and link tests use +dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's +dnl # preprocessing tests use only CPPFLAGS. + AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""]) + + # Step 4: disable dynamic loading if requested via a command-line switch. + + AC_ARG_ENABLE(load, + AC_HELP_STRING([--enable-load], + [allow dynamic loading and "load" command (default: on)]), + [tcl_ok=$enableval], [tcl_ok=yes]) + AS_IF([test "$tcl_ok" = no], [DL_OBJS=""]) + + AS_IF([test "x$DL_OBJS" != x], [BUILD_DLTEST="\$(DLTEST_TARGETS)"], [ + AC_MSG_WARN([Can't figure out how to do dynamic loading or shared libraries on this system.]) + SHLIB_CFLAGS="" + SHLIB_LD="" + SHLIB_SUFFIX="" + DL_OBJS="tclLoadNone.o" + DL_LIBS="" + LDFLAGS="$LDFLAGS_ORIG" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + BUILD_DLTEST="" + ]) + LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" + + # If we're running gcc, then change the C flags for compiling shared + # libraries to the right flags for gcc, instead of those for the + # standard manufacturer compiler. + + AS_IF([test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes], [ + case $system in + AIX-*) ;; + BSD/OS*) ;; + CYGWIN_*|MINGW32_*) ;; + IRIX*) ;; + NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; + Darwin-*) ;; + SCO_SV-3.2*) ;; + *) SHLIB_CFLAGS="-fPIC" ;; + esac]) + + AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ + AC_DEFINE(MODULE_SCOPE, [extern], + [No Compiler support for module scope symbols]) + ]) + + AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [ + SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}']) + AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [ + UNSHARED_LIB_SUFFIX='${VERSION}.a']) + DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)" + + AS_IF([test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""], [ + LIB_SUFFIX=${SHARED_LIB_SUFFIX} + MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' + AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [ + INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;' + DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)" + ], [ + INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"' + ]) + ], [ + LIB_SUFFIX=${UNSHARED_LIB_SUFFIX} + + AS_IF([test "$RANLIB" = ""], [ + MAKE_LIB='$(STLIB_LD) [$]@ ${OBJS}' + ], [ + MAKE_LIB='${STLIB_LD} [$]@ ${OBJS} ; ${RANLIB} [$]@' + ]) + INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"' + ]) + + # Stub lib does not depend on shared/static configuration + AS_IF([test "$RANLIB" = ""], [ + MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS}' + ], [ + MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS} ; ${RANLIB} [$]@' + ]) + INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)"' + + # Define TCL_LIBS now that we know what DL_LIBS is. + # The trick here is that we don't want to change the value of TCL_LIBS if + # it is already set when tclConfig.sh had been loaded by Tk. + AS_IF([test "x${TCL_LIBS}" = x], [ + TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}"]) + AC_SUBST(TCL_LIBS) + + # See if the compiler supports casting to a union type. + # This is used to stop gcc from printing a compiler + # warning when initializing a union member. + + AC_CACHE_CHECK(for cast to union support, + tcl_cv_cast_to_union, + AC_TRY_COMPILE([], + [ + union foo { int i; double d; }; + union foo f = (union foo) (int) 0; + ], + tcl_cv_cast_to_union=yes, + tcl_cv_cast_to_union=no) + ) + if test "$tcl_cv_cast_to_union" = "yes"; then + AC_DEFINE(HAVE_CAST_TO_UNION, 1, + [Defined when compiler supports casting to union type.]) + fi + + # FIXME: This subst was left in only because the TCL_DL_LIBS + # entry in tclConfig.sh uses it. It is not clear why someone + # would use TCL_DL_LIBS instead of TCL_LIBS. + AC_SUBST(DL_LIBS) + + AC_SUBST(DL_OBJS) + AC_SUBST(PLAT_OBJS) + AC_SUBST(PLAT_SRCS) + AC_SUBST(LDAIX_SRC) + AC_SUBST(CFLAGS) + AC_SUBST(CFLAGS_DEBUG) + AC_SUBST(CFLAGS_OPTIMIZE) + AC_SUBST(CFLAGS_WARNING) + + AC_SUBST(LDFLAGS) + AC_SUBST(LDFLAGS_DEBUG) + AC_SUBST(LDFLAGS_OPTIMIZE) + AC_SUBST(CC_SEARCH_FLAGS) + AC_SUBST(LD_SEARCH_FLAGS) + + AC_SUBST(STLIB_LD) + AC_SUBST(SHLIB_LD) + AC_SUBST(TCL_SHLIB_LD_EXTRAS) + AC_SUBST(TK_SHLIB_LD_EXTRAS) + AC_SUBST(SHLIB_LD_LIBS) + AC_SUBST(SHLIB_CFLAGS) + AC_SUBST(SHLIB_SUFFIX) + AC_DEFINE_UNQUOTED(TCL_SHLIB_EXT,"${SHLIB_SUFFIX}", + [What is the default extension for shared libraries?]) + + AC_SUBST(MAKE_LIB) + AC_SUBST(MAKE_STUB_LIB) + AC_SUBST(INSTALL_LIB) + AC_SUBST(DLL_INSTALL_DIR) + AC_SUBST(INSTALL_STUB_LIB) + AC_SUBST(RANLIB) +]) + +#-------------------------------------------------------------------- +# SC_MISSING_POSIX_HEADERS +# +# Supply substitutes for missing POSIX header files. Special +# notes: +# - stdlib.h doesn't define strtol, strtoul, or +# strtod insome versions of SunOS +# - some versions of string.h don't declare procedures such +# as strstr +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# NO_DIRENT_H +# NO_VALUES_H +# NO_STDLIB_H +# NO_STRING_H +# NO_SYS_WAIT_H +# NO_DLFCN_H +# HAVE_SYS_PARAM_H +# +# HAVE_STRING_H ? +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_MISSING_POSIX_HEADERS], [ + AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [ + AC_TRY_LINK([#include <sys/types.h> +#include <dirent.h>], [ +#ifndef _POSIX_SOURCE +# ifdef __Lynx__ + /* + * Generate compilation error to make the test fail: Lynx headers + * are only valid if really in the POSIX environment. + */ + + missing_procedure(); +# endif +#endif +DIR *d; +struct dirent *entryPtr; +char *p; +d = opendir("foobar"); +entryPtr = readdir(d); +p = entryPtr->d_name; +closedir(d); +], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)]) + + if test $tcl_cv_dirent_h = no; then + AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?]) + fi + + AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])]) + AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])]) + AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0) + AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0) + AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0) + AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0) + if test $tcl_ok = 0; then + AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?]) + fi + AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0) + AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0) + AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0) + + # See also memmove check below for a place where NO_STRING_H can be + # set and why. + + if test $tcl_ok = 0; then + AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?]) + fi + + AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])]) + AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])]) + + # OS/390 lacks sys/param.h (and doesn't need it, by chance). + AC_HAVE_HEADERS(sys/param.h) +]) + +#-------------------------------------------------------------------- +# SC_PATH_X +# +# Locate the X11 header files and the X11 library archive. Try +# the ac_path_x macro first, but if it doesn't find the X stuff +# (e.g. because there's no xmkmf program) then check through +# a list of possible directories. Under some conditions the +# autoconf macro will return an include directory that contains +# no include files, so double-check its result just to be safe. +# +# Arguments: +# none +# +# Results: +# +# Sets the following vars: +# XINCLUDES +# XLIBSW +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_PATH_X], [ + AC_PATH_X + not_really_there="" + if test "$no_x" = ""; then + if test "$x_includes" = ""; then + AC_TRY_CPP([#include <X11/Xlib.h>], , not_really_there="yes") + else + if test ! -r $x_includes/X11/Xlib.h; then + not_really_there="yes" + fi + fi + fi + if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then + AC_MSG_CHECKING([for X11 header files]) + found_xincludes="no" + AC_TRY_CPP([#include <X11/Xlib.h>], found_xincludes="yes", found_xincludes="no") + if test "$found_xincludes" = "no"; then + dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" + for i in $dirs ; do + if test -r $i/X11/Xlib.h; then + AC_MSG_RESULT([$i]) + XINCLUDES=" -I$i" + found_xincludes="yes" + break + fi + done + fi + else + if test "$x_includes" != ""; then + XINCLUDES="-I$x_includes" + found_xincludes="yes" + fi + fi + if test "$found_xincludes" = "no"; then + AC_MSG_RESULT([couldn't find any!]) + fi + + if test "$no_x" = yes; then + AC_MSG_CHECKING([for X11 libraries]) + XLIBSW=nope + dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" + for i in $dirs ; do + if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then + AC_MSG_RESULT([$i]) + XLIBSW="-L$i -lX11" + x_libraries="$i" + break + fi + done + else + if test "$x_libraries" = ""; then + XLIBSW=-lX11 + else + XLIBSW="-L$x_libraries -lX11" + fi + fi + if test "$XLIBSW" = nope ; then + AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow) + fi + if test "$XLIBSW" = nope ; then + AC_MSG_RESULT([could not find any! Using -lX11.]) + XLIBSW=-lX11 + fi +]) + +#-------------------------------------------------------------------- +# SC_BLOCKING_STYLE +# +# The statements below check for systems where POSIX-style +# non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. +# On these systems (mostly older ones), use the old BSD-style +# FIONBIO approach instead. +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# HAVE_SYS_IOCTL_H +# HAVE_SYS_FILIO_H +# USE_FIONBIO +# O_NONBLOCK +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_BLOCKING_STYLE], [ + AC_CHECK_HEADERS(sys/ioctl.h) + AC_CHECK_HEADERS(sys/filio.h) + SC_CONFIG_SYSTEM + AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O]) + case $system in + OSF*) + AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) + AC_MSG_RESULT([FIONBIO]) + ;; + SunOS-4*) + AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) + AC_MSG_RESULT([FIONBIO]) + ;; + *) + AC_MSG_RESULT([O_NONBLOCK]) + ;; + esac +]) + +#-------------------------------------------------------------------- +# 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_CHECK_FUNCS(gmtime_r localtime_r mktime) + + AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [ + AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;], + tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)]) + if test $tcl_cv_member_tm_tzadj = yes ; then + AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?]) + fi + + AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [ + AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;], + tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)]) + if test $tcl_cv_member_tm_gmtoff = yes ; then + AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?]) + fi + + # + # Its important to include time.h in this check, as some systems + # (like convex) have timezone functions, etc. + # + AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [ + AC_TRY_COMPILE([#include <time.h>], + [extern long timezone; + timezone += 1; + exit (0);], + tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)]) + if test $tcl_cv_timezone_long = yes ; then + AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) + else + # + # On some systems (eg IRIX 6.2), timezone is a time_t and not a long. + # + AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [ + AC_TRY_COMPILE([#include <time.h>], + [extern time_t timezone; + timezone += 1; + exit (0);], + tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)]) + if test $tcl_cv_timezone_time = yes ; then + AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) + fi + fi +]) + +#-------------------------------------------------------------------- +# SC_TCL_LINK_LIBS +# +# Search for the libraries needed to link the Tcl shell. +# Things like the math library (-lm) and socket stuff (-lsocket vs. +# -lnsl) are dealt with here. +# +# Arguments: +# None. +# +# Results: +# +# Might append to the following vars: +# LIBS +# MATH_LIBS +# +# Might define the following vars: +# HAVE_NET_ERRNO_H +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_TCL_LINK_LIBS], [ + #-------------------------------------------------------------------- + # On a few very rare systems, all of the libm.a stuff is + # already in libc.a. Set compiler flags accordingly. + #-------------------------------------------------------------------- + + AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm") + + #-------------------------------------------------------------------- + # Interactive UNIX requires -linet instead of -lsocket, plus it + # needs net/errno.h to define the socket-related error codes. + #-------------------------------------------------------------------- + + AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"]) + AC_CHECK_HEADER(net/errno.h, [ + AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have <net/errno.h>?])]) + + #-------------------------------------------------------------------- + # Check for the existence of the -lsocket and -lnsl libraries. + # The order here is important, so that they end up in the right + # order in the command line generated by make. Here are some + # special considerations: + # 1. Use "connect" and "accept" to check for -lsocket, and + # "gethostbyname" to check for -lnsl. + # 2. Use each function name only once: can't redo a check because + # autoconf caches the results of the last check and won't redo it. + # 3. Use -lnsl and -lsocket only if they supply procedures that + # aren't already present in the normal libraries. This is because + # IRIX 5.2 has libraries, but they aren't needed and they're + # bogus: they goof up name resolution if used. + # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. + # To get around this problem, check for both libraries together + # if -lsocket doesn't work by itself. + #-------------------------------------------------------------------- + + tcl_checkBoth=0 + AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1) + if test "$tcl_checkSocket" = 1; then + AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt, + LIBS="$LIBS -lsocket", tcl_checkBoth=1)]) + fi + if test "$tcl_checkBoth" = 1; then + tk_oldLibs=$LIBS + LIBS="$LIBS -lsocket -lnsl" + AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs]) + fi + AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname, + [LIBS="$LIBS -lnsl"])]) +]) + +#-------------------------------------------------------------------- +# SC_TCL_EARLY_FLAGS +# +# Check for what flags are needed to be passed so the correct OS +# features are available. +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# _ISOC99_SOURCE +# _LARGEFILE64_SOURCE +# _LARGEFILE_SOURCE64 +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_TCL_EARLY_FLAG],[ + AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]), + AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no, + AC_TRY_COMPILE([[#define ]$1[ 1 +]$2], $3, + [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes, + [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no))) + if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then + AC_DEFINE($1, 1, [Add the ]$1[ flag when building]) + tcl_flags="$tcl_flags $1" + fi +]) + +AC_DEFUN([SC_TCL_EARLY_FLAGS],[ + AC_MSG_CHECKING([for required early compiler flags]) + tcl_flags="" + SC_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>], + [char *p = (char *)strtoll; char *q = (char *)strtoull;]) + SC_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>], + [struct stat64 buf; int i = stat64("/", &buf);]) + SC_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>], + [char *p = (char *)open64;]) + if test "x${tcl_flags}" = "x" ; then + AC_MSG_RESULT([none]) + else + AC_MSG_RESULT([${tcl_flags}]) + fi +]) + +#-------------------------------------------------------------------- +# SC_TCL_64BIT_FLAGS +# +# Check for what is defined in the way of 64-bit features. +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# TCL_WIDE_INT_IS_LONG +# TCL_WIDE_INT_TYPE +# HAVE_STRUCT_DIRENT64, HAVE_DIR64 +# HAVE_STRUCT_STAT64 +# HAVE_TYPE_OFF64_T +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_TCL_64BIT_FLAGS], [ + AC_MSG_CHECKING([for 64-bit integer type]) + AC_CACHE_VAL(tcl_cv_type_64bit,[ + tcl_cv_type_64bit=none + # See if the compiler knows natively about __int64 + AC_TRY_COMPILE(,[__int64 value = (__int64) 0;], + tcl_type_64bit=__int64, tcl_type_64bit="long long") + # See if we should use long anyway Note that we substitute in the + # type that is our current guess for a 64-bit type inside this check + # program, so it should be modified only carefully... + AC_TRY_COMPILE(,[switch (0) { + case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ; + }],tcl_cv_type_64bit=${tcl_type_64bit})]) + if test "${tcl_cv_type_64bit}" = none ; then + AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?]) + AC_MSG_RESULT([using long]) + else + AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit}, + [What type should be used to define wide integers?]) + AC_MSG_RESULT([${tcl_cv_type_64bit}]) + + # Now check for auxiliary declarations + AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[ + AC_TRY_COMPILE([#include <sys/types.h> +#include <dirent.h>],[struct dirent64 p;], + tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)]) + if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?]) + fi + + AC_CACHE_CHECK([for DIR64], tcl_cv_DIR64,[ + AC_TRY_COMPILE([#include <sys/types.h> +#include <dirent.h>],[struct dirent64 *p; DIR64 d = opendir64("."); + p = readdir64(d); rewinddir64(d); closedir64(d);], + tcl_cv_DIR64=yes,tcl_cv_DIR64=no)]) + if test "x${tcl_cv_DIR64}" = "xyes" ; then + AC_DEFINE(HAVE_DIR64, 1, [Is 'DIR64' in <sys/types.h>?]) + fi + + AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ + AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p; +], + tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)]) + if test "x${tcl_cv_struct_stat64}" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?]) + fi + + AC_CHECK_FUNCS(open64 lseek64) + AC_MSG_CHECKING([for off64_t]) + AC_CACHE_VAL(tcl_cv_type_off64_t,[ + AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset; +], + tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)]) + dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the + dnl functions lseek64 and open64 are defined. + if test "x${tcl_cv_type_off64_t}" = "xyes" && \ + test "x${ac_cv_func_lseek64}" = "xyes" && \ + test "x${ac_cv_func_open64}" = "xyes" ; then + AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?]) + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + fi +]) + +#-------------------------------------------------------------------- +# SC_TCL_CFG_ENCODING TIP #59 +# +# Declare the encoding to use for embedded configuration information. +# +# Arguments: +# None. +# +# Results: +# Might append to the following vars: +# DEFS (implicit) +# +# Will define the following vars: +# TCL_CFGVAL_ENCODING +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_TCL_CFG_ENCODING], [ + AC_ARG_WITH(encoding, + AC_HELP_STRING([--with-encoding], + [encoding for configuration values (default: iso8859-1)]), + with_tcencoding=${withval}) + + if test x"${with_tcencoding}" != x ; then + AC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,"${with_tcencoding}", + [What encoding should be used for embedded configuration info?]) + else + AC_DEFINE(TCL_CFGVAL_ENCODING,"iso8859-1", + [What encoding should be used for embedded configuration info?]) + fi +]) + +#-------------------------------------------------------------------- +# SC_TCL_CHECK_BROKEN_FUNC +# +# Check for broken function. +# +# Arguments: +# funcName - function to test for +# advancedTest - the advanced test to run if the function is present +# +# Results: +# Might cause compatibility versions of the function to be used. +# Might affect the following vars: +# USE_COMPAT (implicit) +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_TCL_CHECK_BROKEN_FUNC],[ + AC_CHECK_FUNC($1, tcl_ok=1, tcl_ok=0) + if test ["$tcl_ok"] = 1; then + AC_CACHE_CHECK([proper ]$1[ implementation], [tcl_cv_]$1[_unbroken], + AC_TRY_RUN([[int main() {]$2[}]],[tcl_cv_]$1[_unbroken]=ok, + [tcl_cv_]$1[_unbroken]=broken,[tcl_cv_]$1[_unbroken]=unknown)) + if test ["$tcl_cv_]$1[_unbroken"] = "ok"; then + tcl_ok=1 + else + tcl_ok=0 + fi + fi + if test ["$tcl_ok"] = 0; then + AC_LIBOBJ($1) + USE_COMPAT=1 + fi +]) + +#-------------------------------------------------------------------- +# SC_TCL_GETHOSTBYADDR_R +# +# Check if we have MT-safe variant of gethostbyaddr(). +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# HAVE_GETHOSTBYADDR_R +# HAVE_GETHOSTBYADDR_R_7 +# HAVE_GETHOSTBYADDR_R_8 +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_TCL_GETHOSTBYADDR_R], [AC_CHECK_FUNC(gethostbyaddr_r, [ + AC_CACHE_CHECK([for gethostbyaddr_r with 7 args], tcl_cv_api_gethostbyaddr_r_7, [ + AC_TRY_COMPILE([ + #include <netdb.h> + ], [ + char *addr; + int length; + int type; + struct hostent *result; + char buffer[2048]; + int buflen = 2048; + int h_errnop; + + (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen, + &h_errnop); + ], tcl_cv_api_gethostbyaddr_r_7=yes, tcl_cv_api_gethostbyaddr_r_7=no)]) + tcl_ok=$tcl_cv_api_gethostbyaddr_r_7 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETHOSTBYADDR_R_7, 1, + [Define to 1 if gethostbyaddr_r takes 7 args.]) + else + AC_CACHE_CHECK([for gethostbyaddr_r with 8 args], tcl_cv_api_gethostbyaddr_r_8, [ + AC_TRY_COMPILE([ + #include <netdb.h> + ], [ + char *addr; + int length; + int type; + struct hostent *result, *resultp; + char buffer[2048]; + int buflen = 2048; + int h_errnop; + + (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen, + &resultp, &h_errnop); + ], tcl_cv_api_gethostbyaddr_r_8=yes, tcl_cv_api_gethostbyaddr_r_8=no)]) + tcl_ok=$tcl_cv_api_gethostbyaddr_r_8 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETHOSTBYADDR_R_8, 1, + [Define to 1 if gethostbyaddr_r takes 8 args.]) + fi + fi + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETHOSTBYADDR_R, 1, + [Define to 1 if gethostbyaddr_r is available.]) + fi +])]) + +#-------------------------------------------------------------------- +# SC_TCL_GETHOSTBYNAME_R +# +# Check to see what variant of gethostbyname_r() we have. +# Based on David Arnold's example from the comp.programming.threads +# FAQ Q213 +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# HAVE_GETHOSTBYADDR_R +# HAVE_GETHOSTBYADDR_R_3 +# HAVE_GETHOSTBYADDR_R_5 +# HAVE_GETHOSTBYADDR_R_6 +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_TCL_GETHOSTBYNAME_R], [AC_CHECK_FUNC(gethostbyname_r, [ + AC_CACHE_CHECK([for gethostbyname_r with 6 args], tcl_cv_api_gethostbyname_r_6, [ + AC_TRY_COMPILE([ + #include <netdb.h> + ], [ + char *name; + struct hostent *he, *res; + char buffer[2048]; + int buflen = 2048; + int h_errnop; + + (void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop); + ], tcl_cv_api_gethostbyname_r_6=yes, tcl_cv_api_gethostbyname_r_6=no)]) + tcl_ok=$tcl_cv_api_gethostbyname_r_6 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETHOSTBYNAME_R_6, 1, + [Define to 1 if gethostbyname_r takes 6 args.]) + else + AC_CACHE_CHECK([for gethostbyname_r with 5 args], tcl_cv_api_gethostbyname_r_5, [ + AC_TRY_COMPILE([ + #include <netdb.h> + ], [ + char *name; + struct hostent *he; + char buffer[2048]; + int buflen = 2048; + int h_errnop; + + (void) gethostbyname_r(name, he, buffer, buflen, &h_errnop); + ], tcl_cv_api_gethostbyname_r_5=yes, tcl_cv_api_gethostbyname_r_5=no)]) + tcl_ok=$tcl_cv_api_gethostbyname_r_5 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETHOSTBYNAME_R_5, 1, + [Define to 1 if gethostbyname_r takes 5 args.]) + else + AC_CACHE_CHECK([for gethostbyname_r with 3 args], tcl_cv_api_gethostbyname_r_3, [ + AC_TRY_COMPILE([ + #include <netdb.h> + ], [ + char *name; + struct hostent *he; + struct hostent_data data; + + (void) gethostbyname_r(name, he, &data); + ], tcl_cv_api_gethostbyname_r_3=yes, tcl_cv_api_gethostbyname_r_3=no)]) + tcl_ok=$tcl_cv_api_gethostbyname_r_3 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETHOSTBYNAME_R_3, 1, + [Define to 1 if gethostbyname_r takes 3 args.]) + fi + fi + fi + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETHOSTBYNAME_R, 1, + [Define to 1 if gethostbyname_r is available.]) + fi +])]) + +#-------------------------------------------------------------------- +# SC_TCL_GETPWUID_R +# +# Check if we have MT-safe variant of getpwuid() and if yes, +# which one exactly. +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# HAVE_GETPWUID_R +# HAVE_GETPWUID_R_4 +# HAVE_GETPWUID_R_5 +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_TCL_GETPWUID_R], [AC_CHECK_FUNC(getpwuid_r, [ + AC_CACHE_CHECK([for getpwuid_r with 5 args], tcl_cv_api_getpwuid_r_5, [ + AC_TRY_COMPILE([ + #include <sys/types.h> + #include <pwd.h> + ], [ + uid_t uid; + struct passwd pw, *pwp; + char buf[512]; + int buflen = 512; + + (void) getpwuid_r(uid, &pw, buf, buflen, &pwp); + ], tcl_cv_api_getpwuid_r_5=yes, tcl_cv_api_getpwuid_r_5=no)]) + tcl_ok=$tcl_cv_api_getpwuid_r_5 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETPWUID_R_5, 1, + [Define to 1 if getpwuid_r takes 5 args.]) + else + AC_CACHE_CHECK([for getpwuid_r with 4 args], tcl_cv_api_getpwuid_r_4, [ + AC_TRY_COMPILE([ + #include <sys/types.h> + #include <pwd.h> + ], [ + uid_t uid; + struct passwd pw; + char buf[512]; + int buflen = 512; + + (void)getpwnam_r(uid, &pw, buf, buflen); + ], tcl_cv_api_getpwuid_r_4=yes, tcl_cv_api_getpwuid_r_4=no)]) + tcl_ok=$tcl_cv_api_getpwuid_r_4 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETPWUID_R_4, 1, + [Define to 1 if getpwuid_r takes 4 args.]) + fi + fi + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETPWUID_R, 1, + [Define to 1 if getpwuid_r is available.]) + fi +])]) + +#-------------------------------------------------------------------- +# SC_TCL_GETPWNAM_R +# +# Check if we have MT-safe variant of getpwnam() and if yes, +# which one exactly. +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# HAVE_GETPWNAM_R +# HAVE_GETPWNAM_R_4 +# HAVE_GETPWNAM_R_5 +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_TCL_GETPWNAM_R], [AC_CHECK_FUNC(getpwnam_r, [ + AC_CACHE_CHECK([for getpwnam_r with 5 args], tcl_cv_api_getpwnam_r_5, [ + AC_TRY_COMPILE([ + #include <sys/types.h> + #include <pwd.h> + ], [ + char *name; + struct passwd pw, *pwp; + char buf[512]; + int buflen = 512; + + (void) getpwnam_r(name, &pw, buf, buflen, &pwp); + ], tcl_cv_api_getpwnam_r_5=yes, tcl_cv_api_getpwnam_r_5=no)]) + tcl_ok=$tcl_cv_api_getpwnam_r_5 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETPWNAM_R_5, 1, + [Define to 1 if getpwnam_r takes 5 args.]) + else + AC_CACHE_CHECK([for getpwnam_r with 4 args], tcl_cv_api_getpwnam_r_4, [ + AC_TRY_COMPILE([ + #include <sys/types.h> + #include <pwd.h> + ], [ + char *name; + struct passwd pw; + char buf[512]; + int buflen = 512; + + (void)getpwnam_r(name, &pw, buf, buflen); + ], tcl_cv_api_getpwnam_r_4=yes, tcl_cv_api_getpwnam_r_4=no)]) + tcl_ok=$tcl_cv_api_getpwnam_r_4 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETPWNAM_R_4, 1, + [Define to 1 if getpwnam_r takes 4 args.]) + fi + fi + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETPWNAM_R, 1, + [Define to 1 if getpwnam_r is available.]) + fi +])]) + +#-------------------------------------------------------------------- +# SC_TCL_GETGRGID_R +# +# Check if we have MT-safe variant of getgrgid() and if yes, +# which one exactly. +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# HAVE_GETGRGID_R +# HAVE_GETGRGID_R_4 +# HAVE_GETGRGID_R_5 +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_TCL_GETGRGID_R], [AC_CHECK_FUNC(getgrgid_r, [ + AC_CACHE_CHECK([for getgrgid_r with 5 args], tcl_cv_api_getgrgid_r_5, [ + AC_TRY_COMPILE([ + #include <sys/types.h> + #include <grp.h> + ], [ + gid_t gid; + struct group gr, *grp; + char buf[512]; + int buflen = 512; + + (void) getgrgid_r(gid, &gr, buf, buflen, &grp); + ], tcl_cv_api_getgrgid_r_5=yes, tcl_cv_api_getgrgid_r_5=no)]) + tcl_ok=$tcl_cv_api_getgrgid_r_5 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETGRGID_R_5, 1, + [Define to 1 if getgrgid_r takes 5 args.]) + else + AC_CACHE_CHECK([for getgrgid_r with 4 args], tcl_cv_api_getgrgid_r_4, [ + AC_TRY_COMPILE([ + #include <sys/types.h> + #include <grp.h> + ], [ + gid_t gid; + struct group gr; + char buf[512]; + int buflen = 512; + + (void)getgrgid_r(gid, &gr, buf, buflen); + ], tcl_cv_api_getgrgid_r_4=yes, tcl_cv_api_getgrgid_r_4=no)]) + tcl_ok=$tcl_cv_api_getgrgid_r_4 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETGRGID_R_4, 1, + [Define to 1 if getgrgid_r takes 4 args.]) + fi + fi + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETGRGID_R, 1, + [Define to 1 if getgrgid_r is available.]) + fi +])]) + +#-------------------------------------------------------------------- +# SC_TCL_GETGRNAM_R +# +# Check if we have MT-safe variant of getgrnam() and if yes, +# which one exactly. +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# HAVE_GETGRNAM_R +# HAVE_GETGRNAM_R_4 +# HAVE_GETGRNAM_R_5 +# +#-------------------------------------------------------------------- + +AC_DEFUN([SC_TCL_GETGRNAM_R], [AC_CHECK_FUNC(getgrnam_r, [ + AC_CACHE_CHECK([for getgrnam_r with 5 args], tcl_cv_api_getgrnam_r_5, [ + AC_TRY_COMPILE([ + #include <sys/types.h> + #include <grp.h> + ], [ + char *name; + struct group gr, *grp; + char buf[512]; + int buflen = 512; + + (void) getgrnam_r(name, &gr, buf, buflen, &grp); + ], tcl_cv_api_getgrnam_r_5=yes, tcl_cv_api_getgrnam_r_5=no)]) + tcl_ok=$tcl_cv_api_getgrnam_r_5 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETGRNAM_R_5, 1, + [Define to 1 if getgrnam_r takes 5 args.]) + else + AC_CACHE_CHECK([for getgrnam_r with 4 args], tcl_cv_api_getgrnam_r_4, [ + AC_TRY_COMPILE([ + #include <sys/types.h> + #include <grp.h> + ], [ + char *name; + struct group gr; + char buf[512]; + int buflen = 512; + + (void)getgrnam_r(name, &gr, buf, buflen); + ], tcl_cv_api_getgrnam_r_4=yes, tcl_cv_api_getgrnam_r_4=no)]) + tcl_ok=$tcl_cv_api_getgrnam_r_4 + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETGRNAM_R_4, 1, + [Define to 1 if getgrnam_r takes 4 args.]) + fi + fi + if test "$tcl_ok" = yes; then + AC_DEFINE(HAVE_GETGRNAM_R, 1, + [Define to 1 if getgrnam_r is available.]) + fi +])]) + +AC_DEFUN([SC_TCL_IPV6],[ + NEED_FAKE_RFC2553=0 + AC_CHECK_FUNCS(getnameinfo getaddrinfo freeaddrinfo gai_strerror,,[NEED_FAKE_RFC2553=1]) + AC_CHECK_TYPES([ + struct addrinfo, + struct in6_addr, + struct sockaddr_in6, + struct sockaddr_storage],,[NEED_FAKE_RFC2553=1],[[ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +]]) +if test "x$NEED_FAKE_RFC2553" = "x1"; then + AC_DEFINE([NEED_FAKE_RFC2553], 1, + [Use compat implementation of getaddrinfo() and friends]) + AC_LIBOBJ([fake-rfc2553]) + AC_CHECK_FUNC(strlcpy) +fi +]) +# Local Variables: +# mode: autoconf +# End: diff --git a/tk8.6/unix/tk.pc.in b/tk8.6/unix/tk.pc.in new file mode 100644 index 0000000..68f2130 --- /dev/null +++ b/tk8.6/unix/tk.pc.in @@ -0,0 +1,15 @@ +# tk pkg-config source file + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: The Tk Toolkit +Description: Tk is a cross-platform graphical user interface toolkit, the standard GUI not only for Tcl, but for many other dynamic languages as well. +URL: http://www.tcl.tk/ +Version: @TK_VERSION@@TK_PATCH_LEVEL@ +Requires: tcl >= 8.6 +Libs: -L${libdir} @TK_LIB_FLAG@ @TK_STUB_LIB_FLAG@ +Libs.private: @XFT_LIBS@ @XLIBSW@ +Cflags: -I${includedir} diff --git a/tk8.6/unix/tk.spec b/tk8.6/unix/tk.spec new file mode 100644 index 0000000..159c533 --- /dev/null +++ b/tk8.6/unix/tk.spec @@ -0,0 +1,54 @@ +# This file is the basis for a binary Tk Linux RPM. + +%{!?directory:%define directory /usr/local} + +Name: tk +Summary: Tk graphical toolkit for the Tcl scripting language. +Version: 8.6.9 +Release: 2 +License: BSD +Group: Development/Languages +Source: http://prdownloads.sourceforge.net/tcl/tk%{version}-src.tar.gz +URL: http://www.tcl.tk/ +Buildroot: /var/tmp/%{name}%{version} +Buildrequires: XFree86-devel tcl >= %version +Requires: tcl >= %version + +%description +The Tcl (Tool Command Language) provides a powerful platform for +creating integration applications that tie together diverse +applications, protocols, devices, and frameworks. When paired with +the Tk toolkit, Tcl provides the fastest and most powerful way to +create GUI applications that run on PCs, Unix, and Mac OS X. Tcl +can also be used for a variety of web-related tasks and for creating +powerful command languages for applications. + +%prep +%setup -q -n %{name}%{version} + +%build +cd unix +CFLAGS="%optflags" ./configure \ + --prefix=%{directory} \ + --exec-prefix=%{directory} \ + --libdir=%{directory}/%{_lib} +make + +%install +cd unix +make INSTALL_ROOT=%buildroot install + +%clean +rm -rf %buildroot + +%files -n tk +%defattr(-,root,root) +%if %{_lib} != lib +%{directory}/%{_lib} +%endif +%{directory}/lib +%{directory}/bin +%{directory}/include +%{directory}/man/man1 +%{directory}/man/man3 +%{directory}/man/mann diff --git a/tk8.6/unix/tkAppInit.c b/tk8.6/unix/tkAppInit.c new file mode 100644 index 0000000..13bcdde --- /dev/null +++ b/tk8.6/unix/tkAppInit.c @@ -0,0 +1,156 @@ +/* + * tkAppInit.c -- + * + * Provides a default version of the main program and Tcl_AppInit + * procedure for wish and other Tk-based applications. + * + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 1998-1999 Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#undef BUILD_tk +#undef STATIC_BUILD +#include "tk.h" + +#ifdef TK_TEST +extern Tcl_PackageInitProc Tktest_Init; +#endif /* TK_TEST */ + +/* + * 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 +#ifndef MODULE_SCOPE +# define MODULE_SCOPE extern +#endif +MODULE_SCOPE int TK_LOCAL_APPINIT(Tcl_Interp *); +MODULE_SCOPE int main(int, char **); + +/* + * 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 +MODULE_SCOPE int TK_LOCAL_MAIN_HOOK(int *argc, char ***argv); +#endif + +/* Make sure the stubbed variants of those are never used. */ +#undef Tcl_ObjSetVar2 +#undef Tcl_NewStringObj + +/* + *---------------------------------------------------------------------- + * + * main -- + * + * This is the main program for the application. + * + * Results: + * None: Tk_Main never returns here, so this procedure never returns + * either. + * + * Side effects: + * Just about anything, since from here we call arbitrary Tcl code. + * + *---------------------------------------------------------------------- + */ + +int +main( + int argc, /* Number of command-line arguments. */ + char **argv) /* Values of command-line arguments. */ +{ +#ifdef TK_LOCAL_MAIN_HOOK + TK_LOCAL_MAIN_HOOK(&argc, &argv); +#endif + + Tk_Main(argc, argv, TK_LOCAL_APPINIT); + return 0; /* Needed only to prevent compiler warning. */ +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AppInit -- + * + * This procedure performs application-specific initialization. Most + * applications, especially those that incorporate additional packages, + * will have their own version of this procedure. + * + * Results: + * Returns a standard Tcl completion code, and leaves an error message in + * the interp's result if an error occurs. + * + * Side effects: + * Depends on the startup script. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_AppInit( + Tcl_Interp *interp) /* Interpreter for application. */ +{ + if ((Tcl_Init)(interp) == TCL_ERROR) { + return TCL_ERROR; + } + + if (Tk_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); + +#ifdef TK_TEST + if (Tktest_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Tktest", Tktest_Init, 0); +#endif /* TK_TEST */ + + /* + * Call the init procedures for included packages. Each call should look + * like this: + * + * if (Mod_Init(interp) == TCL_ERROR) { + * return TCL_ERROR; + * } + * + * where "Mod" is the name of the module. (Dynamically-loadable packages + * should have the same entry-point name.) + */ + + /* + * Call Tcl_CreateObjCommand for application-specific commands, if they + * weren't already created by the init procedures called above. + */ + + /* + * Specify a user-specific startup file to invoke if the application is + * run interactively. Typically the startup file is "~/.apprc" where "app" + * is the name of the application. If this line is deleted then no user- + * specific startup file will be run under any conditions. + */ + + Tcl_ObjSetVar2(interp, Tcl_NewStringObj("tcl_rcFileName", -1), NULL, + Tcl_NewStringObj("~/.wishrc", -1), TCL_GLOBAL_ONLY); + return TCL_OK; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkConfig.h.in b/tk8.6/unix/tkConfig.h.in new file mode 100644 index 0000000..72d97c8 --- /dev/null +++ b/tk8.6/unix/tkConfig.h.in @@ -0,0 +1,256 @@ +/* ../unix/tkConfig.h.in. Generated from configure.ac by autoheader. */ + + + #ifndef _TKCONFIG + #define _TKCONFIG + +/* Define to 1 if you have the <AvailabilityMacros.h> header file. */ +#undef HAVE_AVAILABILITYMACROS_H + +/* Defined when compiler supports casting to union type. */ +#undef HAVE_CAST_TO_UNION + +/* Do we have access to Darwin CoreFoundation.framework? */ +#undef HAVE_COREFOUNDATION + +/* Is 'DIR64' in <sys/types.h>? */ +#undef HAVE_DIR64 + +/* Compiler support for module scope symbols */ +#undef HAVE_HIDDEN + +/* Do we have the intptr_t type? */ +#undef HAVE_INTPTR_T + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `Xft' library (-lXft). */ +#undef HAVE_LIBXFT + +/* Define to 1 if you have the `lseek64' function. */ +#undef HAVE_LSEEK64 + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `open64' function. */ +#undef HAVE_OPEN64 + +/* Define to 1 if you have the `pthread_atfork' function. */ +#undef HAVE_PTHREAD_ATFORK + +/* Define to 1 if you have the `pthread_attr_setstacksize' function. */ +#undef HAVE_PTHREAD_ATTR_SETSTACKSIZE + +/* Does struct password have a pw_gecos field? */ +#undef HAVE_PW_GECOS + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Is 'struct dirent64' in <sys/types.h>? */ +#undef HAVE_STRUCT_DIRENT64 + +/* Is 'struct stat64' in <sys/stat.h>? */ +#undef HAVE_STRUCT_STAT64 + +/* Should we include <sys/select.h>? */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/time.h> header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Is off64_t in <sys/types.h>? */ +#undef HAVE_TYPE_OFF64_T + +/* Do we have the uintptr_t type? */ +#undef HAVE_UINTPTR_T + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Is weak import available? */ +#undef HAVE_WEAK_IMPORT + +/* Have we turned on XFT (antialiased fonts)? */ +#undef HAVE_XFT + +/* Do we have XkbKeycodeToKeysym? */ +#undef HAVE_XKBKEYCODETOKEYSYM + +/* Is XScreenSaver available? */ +#undef HAVE_XSS + +/* Is this a Mac I see before me? */ +#undef MAC_OSX_TCL + +/* Are we building TkAqua? */ +#undef MAC_OSX_TK + +/* No Compiler support for module scope symbols */ +#undef MODULE_SCOPE + +/* Is no debugging enabled? */ +#undef NDEBUG + +/* Is Darwin CoreFoundation unavailable for 64-bit? */ +#undef NO_COREFOUNDATION_64 + +/* Do we have fd_set? */ +#undef NO_FD_SET + +/* Do we have <stdlib.h>? */ +#undef NO_STDLIB_H + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Is this a static build? */ +#undef STATIC_BUILD + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Is this a 64-bit build? */ +#undef TCL_CFG_DO64BIT + +/* Is this an optimized build? */ +#undef TCL_CFG_OPTIMIZED + +/* Is bytecode debugging enabled? */ +#undef TCL_COMPILE_DEBUG + +/* Are bytecode statistics enabled? */ +#undef TCL_COMPILE_STATS + +/* Is memory debugging enabled? */ +#undef TCL_MEM_DEBUG + +/* What is the default extension for shared libraries? */ +#undef TCL_SHLIB_EXT + +/* Are we building with threads enabled? */ +#undef TCL_THREADS + +/* Are wide integers to be implemented with C 'long's? */ +#undef TCL_WIDE_INT_IS_LONG + +/* What type should be used to define wide integers? */ +#undef TCL_WIDE_INT_TYPE + +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#undef TIME_WITH_SYS_TIME + +/* Is Tk built as a framework? */ +#undef TK_FRAMEWORK + +/* Are TkAqua debug messages enabled? */ +#undef TK_MAC_DEBUG + +/* Do we want to use the threaded memory allocator? */ +#undef USE_THREAD_ALLOC + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +/* Is XKeycodeToKeysym deprecated? */ +#undef XKEYCODETOKEYSYM_IS_DEPRECATED + +/* Are Darwin SUSv3 extensions available? */ +#undef _DARWIN_C_SOURCE + +/* Add the _ISOC99_SOURCE flag when building */ +#undef _ISOC99_SOURCE + +/* Add the _LARGEFILE64_SOURCE flag when building */ +#undef _LARGEFILE64_SOURCE + +/* Add the _LARGEFILE_SOURCE64 flag when building */ +#undef _LARGEFILE_SOURCE64 + +/* # needed in sys/socket.h Should OS/390 do the right thing with sockets? */ +#undef _OE_SOCKETS + +/* Do we really want to follow the standard? Yes we do! */ +#undef _POSIX_PTHREAD_SEMANTICS + +/* Do we want the reentrant OS API? */ +#undef _REENTRANT + +/* Do we want the thread-safe OS API? */ +#undef _THREAD_SAFE + +/* Do we want to use the XOPEN network library? */ +#undef _XOPEN_SOURCE + +/* Do we want to use the XOPEN network library? */ +#undef _XOPEN_SOURCE_EXTENDED + +/* Define to 1 if type `char' is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +# undef __CHAR_UNSIGNED__ +#endif + +/* Define to `int' if <sys/types.h> doesn't define. */ +#undef gid_t + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Signed integer type wide enough to hold a pointer. */ +#undef intptr_t + +/* Define to `int' if <sys/types.h> does not define. */ +#undef mode_t + +/* Define to `int' if <sys/types.h> does not define. */ +#undef pid_t + +/* Define to `unsigned' if <sys/types.h> does not define. */ +#undef size_t + +/* Define to `int' if <sys/types.h> doesn't define. */ +#undef uid_t + +/* Unsigned integer type wide enough to hold a pointer. */ +#undef uintptr_t + + + /* Undef unused package specific autoheader defines so that we can + * include both tclConfig.h and tkConfig.h at the same time: */ + /* override */ #undef PACKAGE_NAME + /* override */ #undef PACKAGE_STRING + /* override */ #undef PACKAGE_TARNAME + #endif /* _TKCONFIG */ diff --git a/tk8.6/unix/tkConfig.sh.in b/tk8.6/unix/tkConfig.sh.in new file mode 100644 index 0000000..bb85ad0 --- /dev/null +++ b/tk8.6/unix/tkConfig.sh.in @@ -0,0 +1,97 @@ +# 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. + +# 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@ + + +# TK_DBGX used to be used to distinguish debug vs. non-debug builds. +# This was a righteous pain so the core doesn't do that any more. +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='@XLIBSW@ @XFT_LIBS@ @LIBS@ @TCL_LIBS@' + +# Top-level directory in which Tk's platform-independent files are +# installed. +TK_PREFIX='@prefix@' + +# Top-level directory in which Tk'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@' + +# Linker switch(es) to use to link with the X11 library archive. +TK_XLIBSW='@XLIBSW@' + +# -l flag to pass to the linker to pick up the Tk 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@' + +# String to pass to the compiler so that an extension can +# find installed Tk headers. +TK_INCLUDE_SPEC='@TK_INCLUDE_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='@CC_SEARCH_FLAGS@' +TK_LD_SEARCH_FLAGS='@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/tk8.6/unix/tkUnix.c b/tk8.6/unix/tkUnix.c new file mode 100644 index 0000000..c6fff82 --- /dev/null +++ b/tk8.6/unix/tkUnix.c @@ -0,0 +1,265 @@ +/* + * tkUnix.c -- + * + * This file contains procedures that are UNIX/X-specific, and will + * probably have to be written differently for Windows or Macintosh + * platforms. + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tkInt.h" +#ifdef HAVE_XSS +# include <X11/extensions/scrnsaver.h> +# ifdef __APPLE__ +/* Support for weak-linked libXss. */ +# define HaveXSSLibrary() (XScreenSaverQueryInfo != NULL) +# else +/* Other platforms always link libXss. */ +# define HaveXSSLibrary() (1) +# endif +#endif + +/* + *---------------------------------------------------------------------- + * + * TkGetServerInfo -- + * + * Given a window, this procedure returns information about the window + * server for that window. This procedure provides the guts of the "winfo + * server" command. + * + * Results: + * Sets the interpreter result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkGetServerInfo( + Tcl_Interp *interp, /* The server information is returned in this + * interpreter's result. */ + Tk_Window tkwin) /* Token for window; this selects a particular + * display and server. */ +{ + Tcl_SetObjResult(interp, Tcl_ObjPrintf("X%dR%d %s %d", + ProtocolVersion(Tk_Display(tkwin)), + ProtocolRevision(Tk_Display(tkwin)), + ServerVendor(Tk_Display(tkwin)), + VendorRelease(Tk_Display(tkwin)))); +} + +/* + *---------------------------------------------------------------------- + * + * TkGetDefaultScreenName -- + * + * Returns the name of the screen that Tk should use during + * initialization. + * + * Results: + * Returns the argument or a string that should not be freed by the + * caller. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +const char * +TkGetDefaultScreenName( + Tcl_Interp *interp, /* Interp used to find environment + * variables. */ + const char *screenName) /* Screen name from command line, or NULL. */ +{ + if ((screenName == NULL) || (screenName[0] == '\0')) { + screenName = Tcl_GetVar2(interp, "env", "DISPLAY", TCL_GLOBAL_ONLY); + } + return screenName; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_UpdatePointer -- + * + * Unused function in UNIX + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +Tk_UpdatePointer( + Tk_Window tkwin, /* Window to which pointer event is reported. + * May be NULL. */ + int x, int y, /* Pointer location in root coords. */ + int state) /* Modifier state mask. */ +{ + /* + * This function intentionally left blank + */ +} + +/* + *---------------------------------------------------------------------- + * + * TkpBuildRegionFromAlphaData -- + * + * Set up a rectangle of the given region based on the supplied alpha + * data. + * + * Results: + * None + * + * Side effects: + * The region is updated, with extra pixels added to it. + * + *---------------------------------------------------------------------- + */ + +void +TkpBuildRegionFromAlphaData( + TkRegion region, /* Region to be updated. */ + unsigned x, unsigned y, /* Where in region to update. */ + unsigned width, unsigned height, + /* Size of rectangle to update. */ + unsigned char *dataPtr, /* Data to read from. */ + unsigned pixelStride, /* Num bytes from one piece of alpha data to + * the next in the line. */ + unsigned lineStride) /* Num bytes from one line of alpha data to + * the next line. */ +{ + unsigned char *lineDataPtr; + unsigned int x1, y1, end; + XRectangle rect; + + for (y1 = 0; y1 < height; y1++) { + lineDataPtr = dataPtr; + for (x1 = 0; x1 < width; x1 = end) { + /* + * Search for first non-transparent pixel. + */ + + while ((x1 < width) && !*lineDataPtr) { + x1++; + lineDataPtr += pixelStride; + } + end = x1; + + /* + * Search for first transparent pixel. + */ + + while ((end < width) && *lineDataPtr) { + end++; + lineDataPtr += pixelStride; + } + if (end > x1) { + rect.x = x + x1; + rect.y = y + y1; + rect.width = end - x1; + rect.height = 1; + TkUnionRectWithRegion(&rect, region, region); + } + } + dataPtr += lineStride; + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_GetUserInactiveTime -- + * + * Return the number of milliseconds the user was inactive. + * + * Results: + * The number of milliseconds since the user's latest interaction with + * the system on the given display, or -1 if the XScreenSaver extension + * is not supported by the client libraries or the X server + * implementation. + * + * Side effects: + * None. + *---------------------------------------------------------------------- + */ + +long +Tk_GetUserInactiveTime( + Display *dpy) /* The display for which to query the inactive + * time. */ +{ + long inactiveTime = -1; +#ifdef HAVE_XSS + int eventBase, errorBase, major, minor; + + /* + * Calling XScreenSaverQueryVersion seems to be needed to prevent a crash + * on some buggy versions of XFree86. + */ + + if (HaveXSSLibrary() + && XScreenSaverQueryExtension(dpy, &eventBase, &errorBase) + && XScreenSaverQueryVersion(dpy, &major, &minor)) { + XScreenSaverInfo *info = XScreenSaverAllocInfo(); + + if (info == NULL) { + /* + * We are out of memory. + */ + + Tcl_Panic("Out of memory: XScreenSaverAllocInfo failed in Tk_GetUserInactiveTime"); + } + if (XScreenSaverQueryInfo(dpy, DefaultRootWindow(dpy), info)) { + inactiveTime = info->idle; + } + XFree(info); + } +#endif /* HAVE_XSS */ + return inactiveTime; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_ResetUserInactiveTime -- + * + * Reset the user inactivity timer + * + * Results: + * none + * + * Side effects: + * The user inactivity timer of the underlaying windowing system is reset + * to zero. + * + *---------------------------------------------------------------------- + */ + +void +Tk_ResetUserInactiveTime( + Display *dpy) +{ + XResetScreenSaver(dpy); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnix3d.c b/tk8.6/unix/tkUnix3d.c new file mode 100644 index 0000000..038d4e1 --- /dev/null +++ b/tk8.6/unix/tkUnix3d.c @@ -0,0 +1,500 @@ +/* + * tkUnix3d.c -- + * + * This file contains the platform specific routines for drawing 3d + * borders in the Motif style. + * + * Copyright (c) 1996 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. + */ + +#include "tkInt.h" +#include "tk3d.h" + +#if !(defined(_WIN32) || defined(MAC_OSX_TK)) +#include "tkUnixInt.h" +#endif + +/* + * This structure is used to keep track of the extra colors used by Unix 3D + * borders. + */ + +typedef struct { + TkBorder info; + GC solidGC; /* Used to draw solid relief. */ +} UnixBorder; + +/* + *---------------------------------------------------------------------- + * + * TkpGetBorder -- + * + * This function allocates a new TkBorder structure. + * + * Results: + * Returns a newly allocated TkBorder. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkBorder * +TkpGetBorder(void) +{ + UnixBorder *borderPtr = ckalloc(sizeof(UnixBorder)); + + borderPtr->solidGC = None; + return (TkBorder *) borderPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkpFreeBorder -- + * + * This function frees any colors allocated by the platform specific part + * of this module. + * + * Results: + * None. + * + * Side effects: + * May deallocate some colors. + * + *---------------------------------------------------------------------- + */ + +void +TkpFreeBorder( + TkBorder *borderPtr) +{ + UnixBorder *unixBorderPtr = (UnixBorder *) borderPtr; + Display *display = DisplayOfScreen(borderPtr->screen); + + if (unixBorderPtr->solidGC != None) { + Tk_FreeGC(display, unixBorderPtr->solidGC); + } +} +/* + *-------------------------------------------------------------- + * + * Tk_3DVerticalBevel -- + * + * This procedure draws a vertical bevel along one side of an object. The + * bevel is always rectangular in shape: + * ||| + * ||| + * ||| + * ||| + * ||| + * ||| + * An appropriate shadow color is chosen for the bevel based on the + * leftBevel and relief arguments. Normally this procedure is called + * first, then Tk_3DHorizontalBevel is called next to draw neat corners. + * + * Results: + * None. + * + * Side effects: + * Graphics are drawn in drawable. + * + *-------------------------------------------------------------- + */ + +void +Tk_3DVerticalBevel( + Tk_Window tkwin, /* Window for which border was allocated. */ + Drawable drawable, /* X window or pixmap in which to draw. */ + Tk_3DBorder border, /* Token for border to draw. */ + int x, int y, int width, int height, + /* Area of vertical bevel. */ + int leftBevel, /* Non-zero means this bevel forms the left + * side of the object; 0 means it forms the + * right side. */ + int relief) /* Kind of bevel to draw. For example, + * TK_RELIEF_RAISED means interior of object + * should appear higher than exterior. */ +{ + TkBorder *borderPtr = (TkBorder *) border; + GC left, right; + Display *display = Tk_Display(tkwin); + + if ((borderPtr->lightGC == None) && (relief != TK_RELIEF_FLAT)) { + TkpGetShadows(borderPtr, tkwin); + } + + if (relief == TK_RELIEF_RAISED) { + XFillRectangle(display, drawable, + (leftBevel) ? borderPtr->lightGC : borderPtr->darkGC, + x, y, (unsigned) width, (unsigned) height); + } else if (relief == TK_RELIEF_SUNKEN) { + XFillRectangle(display, drawable, + (leftBevel) ? borderPtr->darkGC : borderPtr->lightGC, + x, y, (unsigned) width, (unsigned) height); + } else if (relief == TK_RELIEF_RIDGE) { + int half; + + left = borderPtr->lightGC; + right = borderPtr->darkGC; + ridgeGroove: + half = width/2; + if (!leftBevel && (width & 1)) { + half++; + } + XFillRectangle(display, drawable, left, x, y, (unsigned) half, + (unsigned) height); + XFillRectangle(display, drawable, right, x+half, y, + (unsigned) (width-half), (unsigned) height); + } else if (relief == TK_RELIEF_GROOVE) { + left = borderPtr->darkGC; + right = borderPtr->lightGC; + goto ridgeGroove; + } else if (relief == TK_RELIEF_FLAT) { + XFillRectangle(display, drawable, borderPtr->bgGC, x, y, + (unsigned) width, (unsigned) height); + } else if (relief == TK_RELIEF_SOLID) { + UnixBorder *unixBorderPtr = (UnixBorder *) borderPtr; + if (unixBorderPtr->solidGC == None) { + XGCValues gcValues; + + gcValues.foreground = BlackPixelOfScreen(borderPtr->screen); + unixBorderPtr->solidGC = Tk_GetGC(tkwin, GCForeground, &gcValues); + } + XFillRectangle(display, drawable, unixBorderPtr->solidGC, x, y, + (unsigned) width, (unsigned) height); + } +} + +/* + *-------------------------------------------------------------- + * + * Tk_3DHorizontalBevel -- + * + * This procedure draws a horizontal bevel along one side of an object. + * The bevel has mitered corners (depending on leftIn and rightIn + * arguments). + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +void +Tk_3DHorizontalBevel( + Tk_Window tkwin, /* Window for which border was allocated. */ + Drawable drawable, /* X window or pixmap in which to draw. */ + Tk_3DBorder border, /* Token for border to draw. */ + int x, int y, int width, int height, + /* Bounding box of area of bevel. Height gives + * width of border. */ + int leftIn, int rightIn, /* Describes whether the left and right edges + * of the bevel angle in or out as they go + * down. For example, if "leftIn" is true, the + * left side of the bevel looks like this: + * ___________ + * __________ + * _________ + * ________ + */ + int topBevel, /* Non-zero means this bevel forms the top + * side of the object; 0 means it forms the + * bottom side. */ + int relief) /* Kind of bevel to draw. For example, + * TK_RELIEF_RAISED means interior of object + * should appear higher than exterior. */ +{ + TkBorder *borderPtr = (TkBorder *) border; + Display *display = Tk_Display(tkwin); + int bottom, halfway, x1, x2, x1Delta, x2Delta; + UnixBorder *unixBorderPtr = (UnixBorder *) borderPtr; + GC topGC = None, bottomGC = None; + /* Initializations needed only to prevent + * compiler warnings. */ + + if ((borderPtr->lightGC == None) && (relief != TK_RELIEF_FLAT) && + (relief != TK_RELIEF_SOLID)) { + TkpGetShadows(borderPtr, tkwin); + } + + /* + * Compute a GC for the top half of the bevel and a GC for the bottom half + * (they're the same in many cases). + */ + + switch (relief) { + case TK_RELIEF_FLAT: + topGC = bottomGC = borderPtr->bgGC; + break; + case TK_RELIEF_GROOVE: + topGC = borderPtr->darkGC; + bottomGC = borderPtr->lightGC; + break; + case TK_RELIEF_RAISED: + topGC = bottomGC = (topBevel? borderPtr->lightGC : borderPtr->darkGC); + break; + case TK_RELIEF_RIDGE: + topGC = borderPtr->lightGC; + bottomGC = borderPtr->darkGC; + break; + case TK_RELIEF_SOLID: + if (unixBorderPtr->solidGC == None) { + XGCValues gcValues; + + gcValues.foreground = BlackPixelOfScreen(borderPtr->screen); + unixBorderPtr->solidGC = Tk_GetGC(tkwin, GCForeground, &gcValues); + } + XFillRectangle(display, drawable, unixBorderPtr->solidGC, x, y, + (unsigned) width, (unsigned) height); + return; + case TK_RELIEF_SUNKEN: + topGC = bottomGC = (topBevel? borderPtr->darkGC : borderPtr->lightGC); + break; + } + + /* + * Compute various other geometry-related stuff. + */ + + x1 = x; + if (!leftIn) { + x1 += height; + } + x2 = x+width; + if (!rightIn) { + x2 -= height; + } + x1Delta = (leftIn) ? 1 : -1; + x2Delta = (rightIn) ? -1 : 1; + halfway = y + height/2; + if (!topBevel && (height & 1)) { + halfway++; + } + bottom = y + height; + + /* + * Draw one line for each y-coordinate covered by the bevel. + */ + + for ( ; y < bottom; y++) { + /* + * X Dimensions are 16-bit, so avoid wraparound or display errors by + * limiting these here. + */ + + if (x1 < -32767) { + x1 = -32767; + } + if (x2 > 32767) { + x2 = 32767; + } + + /* + * In some weird cases (such as large border widths for skinny + * rectangles) x1 can be >= x2. Don't draw the lines in these cases. + */ + + if (x1 < x2) { + XFillRectangle(display, drawable, + (y < halfway) ? topGC : bottomGC, x1, y, + (unsigned) (x2-x1), (unsigned) 1); + } + x1 += x1Delta; + x2 += x2Delta; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetShadows -- + * + * This procedure computes the shadow colors for a 3-D border and fills + * in the corresponding fields of the Border structure. It's called + * lazily, so that the colors aren't allocated until something is + * actually drawn with them. That way, if a border is only used for flat + * backgrounds the shadow colors will never be allocated. + * + * Results: + * None. + * + * Side effects: + * The lightGC and darkGC fields in borderPtr get filled in, if they + * weren't already. + * + *---------------------------------------------------------------------- + */ + +void +TkpGetShadows( + TkBorder *borderPtr, /* Information about border. */ + Tk_Window tkwin) /* Window where border will be used for + * drawing. */ +{ + XColor lightColor, darkColor; + int stressed, tmp1, tmp2; + int r, g, b; + XGCValues gcValues; + + if (borderPtr->lightGC != None) { + return; + } + stressed = TkpCmapStressed(tkwin, borderPtr->colormap); + + /* + * First, handle the case of a color display with lots of colors. The + * shadow colors get computed using whichever formula results in the + * greatest change in color: + * 1. Lighter shadow is half-way to white, darker shadow is half way to + * dark. + * 2. Lighter shadow is 40% brighter than background, darker shadow is 40% + * darker than background. + */ + + if (!stressed && (Tk_Depth(tkwin) >= 6)) { + /* + * 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. + */ + + borderPtr->darkColorPtr = Tk_GetColorByValue(tkwin, &darkColor); + gcValues.foreground = borderPtr->darkColorPtr->pixel; + borderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues); + + /* + * Compute the light shadow color. + */ + + 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; + } + + /* + * 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); + return; + } + + if (borderPtr->shadow == None) { + borderPtr->shadow = Tk_GetBitmap((Tcl_Interp *) NULL, tkwin, + Tk_GetUid("gray50")); + if (borderPtr->shadow == None) { + Tcl_Panic("TkpGetShadows couldn't allocate bitmap for border"); + } + } + if (borderPtr->visual->map_entries > 2) { + /* + * This isn't a monochrome display, but the colormap either ran out of + * entries or didn't have very many to begin with. Generate the light + * shadows with a white stipple and the dark shadows with a black + * stipple. + */ + + gcValues.foreground = borderPtr->bgColorPtr->pixel; + gcValues.background = BlackPixelOfScreen(borderPtr->screen); + gcValues.stipple = borderPtr->shadow; + gcValues.fill_style = FillOpaqueStippled; + borderPtr->darkGC = Tk_GetGC(tkwin, + GCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues); + gcValues.background = WhitePixelOfScreen(borderPtr->screen); + borderPtr->lightGC = Tk_GetGC(tkwin, + GCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues); + return; + } + + /* + * This is just a measly monochrome display, hardly even worth its + * existence on this earth. Make one shadow a 50% stipple and the other + * the opposite of the background. + */ + + gcValues.foreground = WhitePixelOfScreen(borderPtr->screen); + gcValues.background = BlackPixelOfScreen(borderPtr->screen); + gcValues.stipple = borderPtr->shadow; + gcValues.fill_style = FillOpaqueStippled; + borderPtr->lightGC = Tk_GetGC(tkwin, + GCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues); + if (borderPtr->bgColorPtr->pixel + == WhitePixelOfScreen(borderPtr->screen)) { + gcValues.foreground = BlackPixelOfScreen(borderPtr->screen); + borderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues); + } else { + borderPtr->darkGC = borderPtr->lightGC; + borderPtr->lightGC = Tk_GetGC(tkwin, GCForeground, &gcValues); + } +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixButton.c b/tk8.6/unix/tkUnixButton.c new file mode 100644 index 0000000..6a99124 --- /dev/null +++ b/tk8.6/unix/tkUnixButton.c @@ -0,0 +1,1028 @@ +/* + * tkUnixButton.c -- + * + * This file implements the Unix specific portion of the button widgets. + * + * 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. + */ + +#include "tkInt.h" +#include "tkButton.h" +#include "tk3d.h" + +/* + * Shared with menu widget. + */ + +MODULE_SCOPE void TkpDrawCheckIndicator(Tk_Window tkwin, + Display *display, Drawable d, int x, int y, + Tk_3DBorder bgBorder, XColor *indicatorColor, + XColor *selectColor, XColor *disColor, int on, + int disabled, int mode); + +/* + * Declaration of Unix specific button structure. + */ + +typedef struct UnixButton { + TkButton info; /* Generic button info. */ +} UnixButton; + +/* + * The class function table for the button widgets. + */ + +const Tk_ClassProcs tkpButtonProcs = { + sizeof(Tk_ClassProcs), /* size */ + TkButtonWorldChanged, /* worldChangedProc */ + NULL, /* createProc */ + NULL /* modalProc */ +}; + +/* + * The button image. + * The header info here is ignored, it's the image that's important. The + * colors will be applied as follows: + * A = Background + * B = Background + * C = 3D light + * D = selectColor + * E = 3D dark + * F = Background + * G = Indicator Color + * H = disabled Indicator Color + */ + +/* XPM */ +static const char *const button_images[] = { + /* width height ncolors chars_per_pixel */ + "52 26 7 1", + /* colors */ + "A c #808000000000", + "B c #000080800000", + "C c #808080800000", + "D c #000000008080", + "E c #808000008080", + "F c #000080808080", + "G c #000000000000", + "H c #000080800000", + /* pixels */ + "AAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAAB", + "AEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECB", + "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB", + "AEDDDDDDDDDCBAEDDDDDDDGDCBAEFFFFFFFFFCBAEFFFFFFFHFCB", + "AEDDDDDDDDDCBAEDDDDDDGGDCBAEFFFFFFFFFCBAEFFFFFFHHFCB", + "AEDDDDDDDDDCBAEDGDDDGGGDCBAEFFFFFFFFFCBAEFHFFFHHHFCB", + "AEDDDDDDDDDCBAEDGGDGGGDDCBAEFFFFFFFFFCBAEFHHFHHHFFCB", + "AEDDDDDDDDDCBAEDGGGGGDDDCBAEFFFFFFFFFCBAEFHHHHHFFFCB", + "AEDDDDDDDDDCBAEDDGGGDDDDCBAEFFFFFFFFFCBAEFFHHHFFFFCB", + "AEDDDDDDDDDCBAEDDDGDDDDDCBAEFFFFFFFFFCBAEFFFHFFFFFCB", + "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB", + "ACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCB", + "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", + "FFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFF", + "FFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFF", + "FAEEDDDDEEBFFFAEEDDDDEEBFFFAEEFFFFEEBFFFAEEFFFFEEBFF", + "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF", + "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF", + "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF", + "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF", + "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF", + "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF", + "FACCDDDDCCBFFFACCDDDDCCBFFFACCFFFFCCBFFFACCFFFFCCBFF", + "FFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFF", + "FFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", +}; + +/* + * Sizes and offsets into above XPM file. + */ + +#define CHECK_BUTTON_DIM 13 +#define CHECK_MENU_DIM 9 +#define CHECK_START 9 +#define CHECK_ON_OFFSET 13 +#define CHECK_OFF_OFFSET 0 +#define CHECK_DISON_OFFSET 39 +#define CHECK_DISOFF_OFFSET 26 +#define RADIO_BUTTON_DIM 12 +#define RADIO_MENU_DIM 6 +#define RADIO_WIDTH 13 +#define RADIO_START 22 +#define RADIO_ON_OFFSET 13 +#define RADIO_OFF_OFFSET 0 +#define RADIO_DISON_OFFSET 39 +#define RADIO_DISOFF_OFFSET 26 + +/* + * Indicator Draw Modes + */ + +#define CHECK_BUTTON 0 +#define CHECK_MENU 1 +#define RADIO_BUTTON 2 +#define RADIO_MENU 3 + +/* + *---------------------------------------------------------------------- + * + * TkpDrawCheckIndicator - + * + * Draws the checkbox image in the drawable at the (x,y) location, value, + * and state given. This routine is use by the button and menu widgets + * + * Results: + * None. + * + * Side effects: + * An image is drawn in the drawable at the location given. + * + *---------------------------------------------------------------------- + */ + +void +TkpDrawCheckIndicator( + Tk_Window tkwin, /* handle for resource alloc */ + Display *display, + Drawable d, /* what to draw on */ + int x, int y, /* where to draw */ + Tk_3DBorder bgBorder, /* colors of the border */ + XColor *indicatorColor, /* color of the indicator */ + XColor *selectColor, /* color when selected */ + XColor *disableColor, /* color when disabled */ + int on, /* are we on? */ + int disabled, /* are we disabled? */ + int mode) /* kind of indicator to draw */ +{ + int ix, iy; + int dim; + int imgsel, imgstart; + TkBorder *bg_brdr = (TkBorder*)bgBorder; + XGCValues gcValues; + GC copyGC; + unsigned long imgColors[8]; + XImage *img; + Pixmap pixmap; + int depth; + + /* + * Sanity check. + */ + + if (tkwin == NULL || display == None || d == None || bgBorder == NULL + || indicatorColor == NULL) { + return; + } + + if (disableColor == NULL) { + disableColor = bg_brdr->bgColorPtr; + } + + if (selectColor == NULL) { + selectColor = bg_brdr->bgColorPtr; + } + + depth = Tk_Depth(tkwin); + + /* + * Compute starting point and dimensions of image inside button_images to + * be used. + */ + + switch (mode) { + default: + case CHECK_BUTTON: + imgsel = on == 2 ? CHECK_DISON_OFFSET : + on == 1 ? CHECK_ON_OFFSET : CHECK_OFF_OFFSET; + imgsel += disabled && on != 2 ? CHECK_DISOFF_OFFSET : 0; + imgstart = CHECK_START; + dim = CHECK_BUTTON_DIM; + break; + + case CHECK_MENU: + imgsel = on == 2 ? CHECK_DISOFF_OFFSET : + on == 1 ? CHECK_ON_OFFSET : CHECK_OFF_OFFSET; + imgsel += disabled && on != 2 ? CHECK_DISOFF_OFFSET : 0; + imgstart = CHECK_START + 2; + imgsel += 2; + dim = CHECK_MENU_DIM; + break; + + case RADIO_BUTTON: + imgsel = on == 2 ? RADIO_DISON_OFFSET : + on==1 ? RADIO_ON_OFFSET : RADIO_OFF_OFFSET; + imgsel += disabled && on != 2 ? RADIO_DISOFF_OFFSET : 0; + imgstart = RADIO_START; + dim = RADIO_BUTTON_DIM; + break; + + case RADIO_MENU: + imgsel = on == 2 ? RADIO_DISOFF_OFFSET : + on==1 ? RADIO_ON_OFFSET : RADIO_OFF_OFFSET; + imgsel += disabled && on != 2 ? RADIO_DISOFF_OFFSET : 0; + imgstart = RADIO_START + 3; + imgsel += 3; + dim = RADIO_MENU_DIM; + break; + } + + /* + * Allocate the drawing areas to use. Note that we use double-buffering + * here because not all code paths leading to this function do so. + */ + + pixmap = Tk_GetPixmap(display, d, dim, dim, depth); + if (pixmap == None) { + return; + } + + x -= dim/2; + y -= dim/2; + + img = XGetImage(display, pixmap, 0, 0, + (unsigned int)dim, (unsigned int)dim, AllPlanes, ZPixmap); + if (img == NULL) { + return; + } + + /* + * Set up the color mapping table. + */ + + TkpGetShadows(bg_brdr, tkwin); + + imgColors[0 /*A*/] = + Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel; + imgColors[1 /*B*/] = + Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel; + imgColors[2 /*C*/] = (bg_brdr->lightColorPtr != NULL) ? + Tk_GetColorByValue(tkwin, bg_brdr->lightColorPtr)->pixel : + WhitePixelOfScreen(bg_brdr->screen); + imgColors[3 /*D*/] = + Tk_GetColorByValue(tkwin, selectColor)->pixel; + imgColors[4 /*E*/] = (bg_brdr->darkColorPtr != NULL) ? + Tk_GetColorByValue(tkwin, bg_brdr->darkColorPtr)->pixel : + BlackPixelOfScreen(bg_brdr->screen); + imgColors[5 /*F*/] = + Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel; + imgColors[6 /*G*/] = + Tk_GetColorByValue(tkwin, indicatorColor)->pixel; + imgColors[7 /*H*/] = + Tk_GetColorByValue(tkwin, disableColor)->pixel; + + /* + * Create the image, painting it into an XImage one pixel at a time. + */ + + for (iy=0 ; iy<dim ; iy++) { + for (ix=0 ; ix<dim ; ix++) { + XPutPixel(img, ix, iy, + imgColors[button_images[imgstart+iy][imgsel+ix] - 'A']); + } + } + + /* + * Copy onto our target drawable surface. + */ + + memset(&gcValues, 0, sizeof(gcValues)); + gcValues.background = bg_brdr->bgColorPtr->pixel; + gcValues.graphics_exposures = False; + copyGC = Tk_GetGC(tkwin, 0, &gcValues); + + XPutImage(display, pixmap, copyGC, img, 0, 0, 0, 0, + (unsigned)dim, (unsigned)dim); + XCopyArea(display, pixmap, d, copyGC, 0, 0, + (unsigned)dim, (unsigned)dim, x, y); + + /* + * Tidy up. + */ + + Tk_FreeGC(display, copyGC); + XDestroyImage(img); + Tk_FreePixmap(display, pixmap); +} + +/* + *---------------------------------------------------------------------- + * + * TkpCreateButton -- + * + * Allocate a new TkButton structure. + * + * Results: + * Returns a newly allocated TkButton structure. + * + * Side effects: + * Registers an event handler for the widget. + * + *---------------------------------------------------------------------- + */ + +TkButton * +TkpCreateButton( + Tk_Window tkwin) +{ + UnixButton *butPtr = ckalloc(sizeof(UnixButton)); + + return (TkButton *) butPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkpDisplayButton -- + * + * This function is invoked to display a button widget. It is normally + * invoked as an idle handler. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the button in its current mode. + * The REDRAW_PENDING flag is cleared. + * + *---------------------------------------------------------------------- + */ + +static void +ShiftByOffset( + TkButton *butPtr, + int relief, + int *x, /* shift this x coordinate */ + int *y, /* shift this y coordinate */ + int width, /* width of image/text */ + int height) /* height of image/text */ +{ + if (relief != TK_RELIEF_RAISED + && butPtr->type == TYPE_BUTTON + && !Tk_StrictMotif(butPtr->tkwin)) { + int shiftX; + int shiftY; + + /* + * This is an (unraised) button widget, so we offset the text to make + * the button appear to move up and down as the relief changes. + */ + + shiftX = shiftY = (relief == TK_RELIEF_SUNKEN) ? 2 : 1; + + if (relief != TK_RELIEF_RIDGE) { + /* + * Take back one pixel if the padding is even, otherwise the + * content will be displayed too far right/down. + */ + + if ((Tk_Width(butPtr->tkwin) - width) % 2 == 0) { + shiftX -= 1; + } + if ((Tk_Height(butPtr->tkwin) - height) % 2 == 0) { + shiftY -= 1; + } + } + + *x += shiftX; + *y += shiftY; + } +} + +void +TkpDisplayButton( + ClientData clientData) /* Information about widget. */ +{ + register TkButton *butPtr = (TkButton *) clientData; + GC gc; + Tk_3DBorder border; + Pixmap pixmap; + int x = 0; /* Initialization only needed to stop compiler + * warning. */ + int y, relief; + Tk_Window tkwin = butPtr->tkwin; + int width = 0, height = 0, fullWidth, fullHeight; + int textXOffset, textYOffset; + int haveImage = 0, haveText = 0; + int imageWidth, imageHeight; + int imageXOffset = 0, imageYOffset = 0; + /* image information that will be used to + * restrict disabled pixmap as well */ + + butPtr->flags &= ~REDRAW_PENDING; + if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { + return; + } + + border = butPtr->normalBorder; + if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) { + gc = butPtr->disabledGC; + } 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->selectBorder != NULL) + && !butPtr->indicatorOn) { + border = butPtr->selectBorder; + } + + /* + * Override the relief specified for the button if this is a checkbutton + * or radiobutton and there's no indicator. The new relief is as follows: + * If the button is select --> "sunken" + * If relief==overrelief --> relief + * Otherwise --> overrelief + * + * The effect we are trying to achieve is as follows: + * + * value mouse-over? --> relief + * ------- ------------ -------- + * off no flat + * off yes raised + * on no sunken + * on yes sunken + * + * This is accomplished by configuring the checkbutton or radiobutton like + * this: + * + * -indicatoron 0 -overrelief raised -offrelief flat + * + * Bindings (see library/button.tcl) will copy the -overrelief into + * -relief on mouseover. Hence, we can tell if we are in mouse-over by + * comparing relief against overRelief. This is an aweful kludge, but it + * gives use the desired behavior while keeping the code backwards + * compatible. + */ + + relief = butPtr->relief; + if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) { + if (butPtr->flags & SELECTED) { + relief = TK_RELIEF_SUNKEN; + } else if (butPtr->overRelief != relief) { + relief = butPtr->offRelief; + } + } + + /* + * In order to avoid screen flashes, this function redraws the button in a + * pixmap, then copies the pixmap to the screen in a single operation. + * This means that there's no point in time where the on-screen image has + * been cleared. + */ + + pixmap = Tk_GetPixmap(butPtr->display, Tk_WindowId(tkwin), + Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); + Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin), + Tk_Height(tkwin), 0, TK_RELIEF_FLAT); + + /* + * Display image or bitmap or text for button. + */ + + if (butPtr->image != NULL) { + Tk_SizeOfImage(butPtr->image, &width, &height); + haveImage = 1; + } else if (butPtr->bitmap != None) { + Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); + haveImage = 1; + } + imageWidth = width; + imageHeight = height; + + haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); + + if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { + textXOffset = 0; + textYOffset = 0; + fullWidth = 0; + fullHeight = 0; + + switch ((enum compound) butPtr->compound) { + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text. + */ + + if (butPtr->compound == COMPOUND_TOP) { + textYOffset = height + butPtr->padY; + } else { + imageYOffset = butPtr->textHeight + butPtr->padY; + } + fullHeight = height + butPtr->textHeight + butPtr->padY; + fullWidth = (width > butPtr->textWidth ? width : + butPtr->textWidth); + textXOffset = (fullWidth - butPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text. + */ + + if (butPtr->compound == COMPOUND_LEFT) { + textXOffset = width + butPtr->padX; + } else { + imageXOffset = butPtr->textWidth + butPtr->padX; + } + fullWidth = butPtr->textWidth + butPtr->padX + width; + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textYOffset = (fullHeight - butPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed. + */ + + fullWidth = (width > butPtr->textWidth ? width : + butPtr->textWidth); + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textXOffset = (fullWidth - butPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + textYOffset = (fullHeight - butPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; + case COMPOUND_NONE: + break; + } + + TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, + butPtr->indicatorSpace + fullWidth, fullHeight, &x, &y); + + x += butPtr->indicatorSpace; + ShiftByOffset(butPtr, relief, &x, &y, width, height); + imageXOffset += x; + imageYOffset += y; + + if (butPtr->image != NULL) { + /* + * Do boundary clipping, so that Tk_RedrawImage is passed valid + * coordinates. [Bug 979239] + */ + + if (imageXOffset < 0) { + imageXOffset = 0; + } + if (imageYOffset < 0) { + imageYOffset = 0; + } + if (width > Tk_Width(tkwin)) { + width = Tk_Width(tkwin); + } + if (height > Tk_Height(tkwin)) { + height = Tk_Height(tkwin); + } + if ((width + imageXOffset) > Tk_Width(tkwin)) { + imageXOffset = Tk_Width(tkwin) - width; + } + if ((height + imageYOffset) > Tk_Height(tkwin)) { + imageYOffset = Tk_Height(tkwin) - height; + } + + if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) { + Tk_RedrawImage(butPtr->selectImage, 0, 0, + width, height, pixmap, imageXOffset, imageYOffset); + } else if ((butPtr->tristateImage != NULL) && (butPtr->flags & TRISTATED)) { + Tk_RedrawImage(butPtr->tristateImage, 0, 0, + width, height, pixmap, imageXOffset, imageYOffset); + } else { + Tk_RedrawImage(butPtr->image, 0, 0, width, + height, pixmap, imageXOffset, imageYOffset); + } + } else { + XSetClipOrigin(butPtr->display, gc, imageXOffset, imageYOffset); + XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, + 0, 0, (unsigned int) width, (unsigned int) height, + imageXOffset, imageYOffset, 1); + XSetClipOrigin(butPtr->display, gc, 0, 0); + } + + Tk_DrawTextLayout(butPtr->display, pixmap, gc, + butPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1); + Tk_UnderlineTextLayout(butPtr->display, pixmap, gc, + butPtr->textLayout, x + textXOffset, y + textYOffset, + butPtr->underline); + y += fullHeight/2; + } else { + if (haveImage) { + TkComputeAnchor(butPtr->anchor, tkwin, 0, 0, + butPtr->indicatorSpace + width, height, &x, &y); + x += butPtr->indicatorSpace; + ShiftByOffset(butPtr, relief, &x, &y, width, height); + imageXOffset += x; + imageYOffset += y; + if (butPtr->image != NULL) { + /* + * Do boundary clipping, so that Tk_RedrawImage is passed + * valid coordinates. [Bug 979239] + */ + + if (imageXOffset < 0) { + imageXOffset = 0; + } + if (imageYOffset < 0) { + imageYOffset = 0; + } + if (width > Tk_Width(tkwin)) { + width = Tk_Width(tkwin); + } + if (height > Tk_Height(tkwin)) { + height = Tk_Height(tkwin); + } + if ((width + imageXOffset) > Tk_Width(tkwin)) { + imageXOffset = Tk_Width(tkwin) - width; + } + if ((height + imageYOffset) > Tk_Height(tkwin)) { + imageYOffset = Tk_Height(tkwin) - height; + } + + if ((butPtr->selectImage != NULL) && + (butPtr->flags & SELECTED)) { + Tk_RedrawImage(butPtr->selectImage, 0, 0, width, + height, pixmap, imageXOffset, imageYOffset); + } else if ((butPtr->tristateImage != NULL) && + (butPtr->flags & TRISTATED)) { + Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, + height, pixmap, imageXOffset, imageYOffset); + } else { + Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap, + imageXOffset, imageYOffset); + } + } else { + XSetClipOrigin(butPtr->display, gc, x, y); + XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0, + (unsigned int) width, (unsigned int) height, x, y, 1); + XSetClipOrigin(butPtr->display, gc, 0, 0); + } + y += height/2; + } else { + TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, + butPtr->indicatorSpace + butPtr->textWidth, + butPtr->textHeight, &x, &y); + + x += butPtr->indicatorSpace; + ShiftByOffset(butPtr, relief, &x, &y, width, height); + Tk_DrawTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout, + x, y, 0, -1); + Tk_UnderlineTextLayout(butPtr->display, pixmap, gc, + butPtr->textLayout, x, y, butPtr->underline); + y += butPtr->textHeight/2; + } + } + + /* + * Draw the indicator for check buttons and radio buttons. At this point, + * x and y refer to the top-left corner of the text or image or bitmap. + */ + + if ((butPtr->type == TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { + if (butPtr->indicatorDiameter > 2*butPtr->borderWidth) { + TkBorder *selBorder = (TkBorder *) butPtr->selectBorder; + XColor *selColor = NULL; + + if (selBorder != NULL) { + selColor = selBorder->bgColorPtr; + } + x -= butPtr->indicatorSpace/2; + y = Tk_Height(tkwin)/2; + TkpDrawCheckIndicator(tkwin, butPtr->display, pixmap, x, y, + border, butPtr->normalFg, selColor, butPtr->disabledFg, + ((butPtr->flags & SELECTED) ? 1 : + (butPtr->flags & TRISTATED) ? 2 : 0), + (butPtr->state == STATE_DISABLED), CHECK_BUTTON); + } + } else if ((butPtr->type == TYPE_RADIO_BUTTON) && butPtr->indicatorOn) { + if (butPtr->indicatorDiameter > 2*butPtr->borderWidth) { + TkBorder *selBorder = (TkBorder *) butPtr->selectBorder; + XColor *selColor = NULL; + + if (selBorder != NULL) { + selColor = selBorder->bgColorPtr; + } + x -= butPtr->indicatorSpace/2; + y = Tk_Height(tkwin)/2; + TkpDrawCheckIndicator(tkwin, butPtr->display, pixmap, x, y, + border, butPtr->normalFg, selColor, butPtr->disabledFg, + ((butPtr->flags & SELECTED) ? 1 : + (butPtr->flags & TRISTATED) ? 2 : 0), + (butPtr->state == STATE_DISABLED), RADIO_BUTTON); + } + } + + /* + * If the button is disabled with a stipple rather than a special + * foreground color, generate the stippled effect. If the widget is + * selected and we use a different background color when selected, must + * temporarily modify the GC so the stippling is the right color. + */ + + if ((butPtr->state == STATE_DISABLED) + && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) { + if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn + && (butPtr->selectBorder != NULL)) { + XSetForeground(butPtr->display, butPtr->stippleGC, + Tk_3DBorderColor(butPtr->selectBorder)->pixel); + } + + /* + * Stipple the whole button if no disabledFg was specified, otherwise + * restrict stippling only to displayed image + */ + + if (butPtr->disabledFg == NULL) { + XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, 0, 0, + (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin)); + } else { + XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, + imageXOffset, imageYOffset, + (unsigned) imageWidth, (unsigned) imageHeight); + } + if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn + && (butPtr->selectBorder != NULL)) { + XSetForeground(butPtr->display, butPtr->stippleGC, + Tk_3DBorderColor(butPtr->normalBorder)->pixel); + } + } + + /* + * Draw the border and traversal highlight last. This way, if the button's + * contents overflow they'll be covered up by the border. This code is + * complicated by the possible combinations of focus highlight and default + * rings. We draw the focus and highlight rings using the highlight border + * and highlight foreground color. + */ + + if (relief != TK_RELIEF_FLAT) { + int inset = butPtr->highlightWidth; + + if (butPtr->defaultState == DEFAULT_ACTIVE) { + /* + * Draw the default ring with 2 pixels of space between the + * default ring and the button and the default ring and the focus + * ring. Note that we need to explicitly draw the space in the + * highlightBorder color to ensure that we overwrite any overflow + * text and/or a different button background color. + */ + + Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset, + inset, Tk_Width(tkwin) - 2*inset, + Tk_Height(tkwin) - 2*inset, 2, TK_RELIEF_FLAT); + inset += 2; + Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset, + inset, Tk_Width(tkwin) - 2*inset, + Tk_Height(tkwin) - 2*inset, 1, TK_RELIEF_SUNKEN); + inset++; + Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset, + inset, Tk_Width(tkwin) - 2*inset, + Tk_Height(tkwin) - 2*inset, 2, TK_RELIEF_FLAT); + + inset += 2; + } else if (butPtr->defaultState == DEFAULT_NORMAL) { + /* + * Leave room for the default ring and write over any text or + * background color. + */ + + Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0, + 0, Tk_Width(tkwin), Tk_Height(tkwin), 5, TK_RELIEF_FLAT); + inset += 5; + } + + /* + * Draw the button border. + */ + + Tk_Draw3DRectangle(tkwin, pixmap, border, inset, inset, + Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, + butPtr->borderWidth, relief); + } + if (butPtr->highlightWidth > 0) { + GC gc; + + if (butPtr->flags & GOT_FOCUS) { + gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap); + } else { + gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder), + pixmap); + } + + /* + * Make sure the focus ring shrink-wraps the actual button, not the + * padding space left for a default ring. + */ + + if (butPtr->defaultState == DEFAULT_NORMAL) { + TkDrawInsetFocusHighlight(tkwin, gc, butPtr->highlightWidth, + pixmap, 5); + } else { + Tk_DrawFocusHighlight(tkwin, gc, butPtr->highlightWidth, pixmap); + } + } + + /* + * Copy the information from the off-screen pixmap onto the screen, then + * delete the pixmap. + */ + + XCopyArea(butPtr->display, pixmap, Tk_WindowId(tkwin), + butPtr->copyGC, 0, 0, (unsigned) Tk_Width(tkwin), + (unsigned) Tk_Height(tkwin), 0, 0); + Tk_FreePixmap(butPtr->display, pixmap); +} + +/* + *---------------------------------------------------------------------- + * + * TkpComputeButtonGeometry -- + * + * After changes in a button's text or bitmap, this function recomputes + * the button's geometry and passes this information along to the + * geometry manager for the window. + * + * Results: + * None. + * + * Side effects: + * The button's window may change size. + * + *---------------------------------------------------------------------- + */ + +void +TkpComputeButtonGeometry( + register TkButton *butPtr) /* Button whose geometry may have changed. */ +{ + int width, height, avgWidth, txtWidth, txtHeight; + int haveImage = 0, haveText = 0; + Tk_FontMetrics fm; + + butPtr->inset = butPtr->highlightWidth + butPtr->borderWidth; + + /* + * Leave room for the default ring if needed. + */ + + if (butPtr->defaultState != DEFAULT_DISABLED) { + butPtr->inset += 5; + } + butPtr->indicatorSpace = 0; + + width = 0; + height = 0; + txtWidth = 0; + txtHeight = 0; + avgWidth = 0; + + if (butPtr->image != NULL) { + Tk_SizeOfImage(butPtr->image, &width, &height); + haveImage = 1; + } else if (butPtr->bitmap != None) { + Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); + haveImage = 1; + } + + if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) { + Tk_FreeTextLayout(butPtr->textLayout); + + butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont, + Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength, + butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight); + + txtWidth = butPtr->textWidth; + txtHeight = butPtr->textHeight; + avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1); + Tk_GetFontMetrics(butPtr->tkfont, &fm); + haveText = (txtWidth != 0 && txtHeight != 0); + } + + /* + * If the button is compound (i.e., it shows both an image and text), the + * new geometry is a combination of the image and text geometry. We only + * honor the compound bit if the button has both text and an image, + * because otherwise it is not really a compound button. + */ + + if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { + switch ((enum compound) butPtr->compound) { + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text. + */ + + height += txtHeight + butPtr->padY; + width = (width > txtWidth ? width : txtWidth); + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text. + */ + + width += txtWidth + butPtr->padX; + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed. + */ + + width = (width > txtWidth ? width : txtWidth); + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_NONE: + break; + } + if (butPtr->width > 0) { + width = butPtr->width; + } + if (butPtr->height > 0) { + height = butPtr->height; + } + + if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { + butPtr->indicatorSpace = height; + if (butPtr->type == TYPE_CHECK_BUTTON) { + butPtr->indicatorDiameter = (65*height)/100; + } else { + butPtr->indicatorDiameter = (75*height)/100; + } + } + + width += 2*butPtr->padX; + height += 2*butPtr->padY; + } else { + if (haveImage) { + if (butPtr->width > 0) { + width = butPtr->width; + } + if (butPtr->height > 0) { + height = butPtr->height; + } + + if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { + butPtr->indicatorSpace = height; + if (butPtr->type == TYPE_CHECK_BUTTON) { + butPtr->indicatorDiameter = (65*height)/100; + } else { + butPtr->indicatorDiameter = (75*height)/100; + } + } + } else { + width = txtWidth; + height = txtHeight; + + if (butPtr->width > 0) { + width = butPtr->width * avgWidth; + } + if (butPtr->height > 0) { + height = butPtr->height * fm.linespace; + } + if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { + butPtr->indicatorDiameter = fm.linespace; + if (butPtr->type == TYPE_CHECK_BUTTON) { + butPtr->indicatorDiameter = + (80*butPtr->indicatorDiameter)/100; + } + butPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth; + } + } + } + + /* + * When issuing the geometry request, add extra space for the indicator, + * if any, and for the border and padding, plus two extra pixels so the + * display can be offset by 1 pixel in either direction for the raised or + * lowered effect. + */ + + if ((butPtr->image == NULL) && (butPtr->bitmap == None)) { + width += 2*butPtr->padX; + height += 2*butPtr->padY; + } + if ((butPtr->type == TYPE_BUTTON) && !Tk_StrictMotif(butPtr->tkwin)) { + width += 2; + height += 2; + } + Tk_GeometryRequest(butPtr->tkwin, (int) (width + butPtr->indicatorSpace + + 2*butPtr->inset), (int) (height + 2*butPtr->inset)); + Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixColor.c b/tk8.6/unix/tkUnixColor.c new file mode 100644 index 0000000..43500ad --- /dev/null +++ b/tk8.6/unix/tkUnixColor.c @@ -0,0 +1,450 @@ +/* + * tkUnixColor.c -- + * + * This file contains the platform specific color routines needed for X + * support. + * + * Copyright (c) 1996 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. + */ + +#include "tkUnixInt.h" +#include "tkColor.h" + +/* + * If a colormap fills up, attempts to allocate new colors from that colormap + * will fail. When that happens, we'll just choose the closest color from + * those that are available in the colormap. One of the following structures + * will be created for each "stressed" colormap to keep track of the colors + * that are available in the colormap (otherwise we would have to re-query + * from the server on each allocation, which would be very slow). These + * entries are flushed after a few seconds, since other clients may release or + * reallocate colors over time. + */ + +struct TkStressedCmap { + Colormap colormap; /* X's token for the colormap. */ + int numColors; /* Number of entries currently active at + * *colorPtr. */ + XColor *colorPtr; /* Pointer to malloc'ed array of all colors + * that seem to be available in the colormap. + * Some may not actually be available, e.g. + * because they are read-write for another + * client; when we find this out, we remove + * them from the array. */ + struct TkStressedCmap *nextPtr; + /* Next in list of all stressed colormaps for + * the display. */ +}; + +/* + * Forward declarations for functions defined in this file: + */ + +static void DeleteStressedCmap(Display *display, + Colormap colormap); +static void FindClosestColor(Tk_Window tkwin, + XColor *desiredColorPtr, XColor *actualColorPtr); + +/* + *---------------------------------------------------------------------- + * + * TkpFreeColor -- + * + * Release the specified color back to the system. + * + * Results: + * None + * + * Side effects: + * Invalidates the colormap cache for the colormap associated with the + * given color. + * + *---------------------------------------------------------------------- + */ + +void +TkpFreeColor( + TkColor *tkColPtr) /* Color to be released. Must have been + * allocated by TkpGetColor or + * TkpGetColorByValue. */ +{ + Visual *visual; + Screen *screen = tkColPtr->screen; + + /* + * Careful! Don't free black or white, since this will make some servers + * very unhappy. Also, there is a bug in some servers (such Sun's X11/NeWS + * server) where reference counting is performed incorrectly, so that if a + * color is allocated twice in different places and then freed twice, the + * second free generates an error (this bug existed as of 10/1/92). To get + * around this problem, ignore errors that occur during the free + * operation. + */ + + visual = tkColPtr->visual; + if ((visual->class != StaticGray) && (visual->class != StaticColor) + && (tkColPtr->color.pixel != BlackPixelOfScreen(screen)) + && (tkColPtr->color.pixel != WhitePixelOfScreen(screen))) { + Tk_ErrorHandler handler; + + handler = Tk_CreateErrorHandler(DisplayOfScreen(screen), + -1, -1, -1, NULL, NULL); + XFreeColors(DisplayOfScreen(screen), tkColPtr->colormap, + &tkColPtr->color.pixel, 1, 0L); + Tk_DeleteErrorHandler(handler); + } + DeleteStressedCmap(DisplayOfScreen(screen), tkColPtr->colormap); +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetColor -- + * + * Allocate a new TkColor for the color with the given name. + * + * Results: + * Returns a newly allocated TkColor, or NULL on failure. + * + * Side effects: + * May invalidate the colormap cache associated with tkwin upon + * allocating a new colormap entry. Allocates a new TkColor structure. + * + *---------------------------------------------------------------------- + */ + +TkColor * +TkpGetColor( + Tk_Window tkwin, /* Window in which color will be used. */ + Tk_Uid name) /* Name of color to allocated (in form + * suitable for passing to XParseColor). */ +{ + Display *display = Tk_Display(tkwin); + Colormap colormap = Tk_Colormap(tkwin); + XColor color; + TkColor *tkColPtr; + + /* + * Map from the name to a pixel value. Call XAllocNamedColor rather than + * XParseColor for non-# names: this saves a server round-trip for those + * names. + */ + + if (*name != '#') { + XColor screen; + + if (((*name - 'A') & 0xdf) < sizeof(tkWebColors)/sizeof(tkWebColors[0])) { + if (!((name[0] - 'G') & 0xdf) && !((name[1] - 'R') & 0xdf) + && !((name[2] - 'A') & 0xdb) && !((name[3] - 'Y') & 0xdf) + && !name[4]) { + name = "#808080808080"; + goto gotWebColor; + } else { + const char *p = tkWebColors[((*name - 'A') & 0x1f)]; + if (p) { + const char *q = name; + while (!((*p - *(++q)) & 0xdf)) { + if (!*p++) { + name = p; + goto gotWebColor; + } + } + } + } + } + if (strlen(name) > 99) { + /* Don't bother to parse this. [Bug 2809525]*/ + return (TkColor *) NULL; + } else if (XAllocNamedColor(display, colormap, name, &screen, &color) != 0) { + DeleteStressedCmap(display, colormap); + } else { + /* + * Couldn't allocate the color. Try translating the name to a + * color value, to see whether the problem is a bad color name or + * a full colormap. If the colormap is full, then pick an + * approximation to the desired color. + */ + + if (XLookupColor(display, colormap, name, &color, &screen) == 0) { + return NULL; + } + FindClosestColor(tkwin, &screen, &color); + } + } else { + gotWebColor: + if (TkParseColor(display, colormap, name, &color) == 0) { + return NULL; + } + if (XAllocColor(display, colormap, &color) != 0) { + DeleteStressedCmap(display, colormap); + } else { + FindClosestColor(tkwin, &color, &color); + } + } + + tkColPtr = ckalloc(sizeof(TkColor)); + tkColPtr->color = color; + + return tkColPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetColorByValue -- + * + * Given a desired set of red-green-blue intensities for a color, locate + * a pixel value to use to draw that color in a given window. + * + * Results: + * The return value is a pointer to an TkColor structure that indicates + * the closest red, blue, and green intensities available to those + * specified in colorPtr, and also specifies a pixel value to use to draw + * in that color. + * + * Side effects: + * May invalidate the colormap cache for the specified window. Allocates + * a new TkColor structure. + * + *---------------------------------------------------------------------- + */ + +TkColor * +TkpGetColorByValue( + Tk_Window tkwin, /* Window in which color will be used. */ + XColor *colorPtr) /* Red, green, and blue fields indicate + * desired color. */ +{ + Display *display = Tk_Display(tkwin); + Colormap colormap = Tk_Colormap(tkwin); + TkColor *tkColPtr = ckalloc(sizeof(TkColor)); + + tkColPtr->color.red = colorPtr->red; + tkColPtr->color.green = colorPtr->green; + tkColPtr->color.blue = colorPtr->blue; + if (XAllocColor(display, colormap, &tkColPtr->color) != 0) { + DeleteStressedCmap(display, colormap); + } else { + FindClosestColor(tkwin, &tkColPtr->color, &tkColPtr->color); + } + + return tkColPtr; +} + +/* + *---------------------------------------------------------------------- + * + * FindClosestColor -- + * + * When Tk can't allocate a color because a colormap has filled up, this + * function is called to find and allocate the closest available color in + * the colormap. + * + * Results: + * There is no return value, but *actualColorPtr is filled in with + * information about the closest available color in tkwin's colormap. + * This color has been allocated via X, so it must be released by the + * caller when the caller is done with it. + * + * Side effects: + * A color is allocated. + * + *---------------------------------------------------------------------- + */ + +static void +FindClosestColor( + Tk_Window tkwin, /* Window where color will be used. */ + XColor *desiredColorPtr, /* RGB values of color that was wanted (but + * unavailable). */ + XColor *actualColorPtr) /* Structure to fill in with RGB and pixel for + * closest available color. */ +{ + TkStressedCmap *stressPtr; + double tmp, distance, closestDistance; + int i, closest, numFound; + XColor *colorPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; + Colormap colormap = Tk_Colormap(tkwin); + XVisualInfo template, *visInfoPtr; + + /* + * Find the TkStressedCmap structure for this colormap, or create a new + * one if needed. + */ + + for (stressPtr = dispPtr->stressPtr; ; stressPtr = stressPtr->nextPtr) { + if (stressPtr == NULL) { + stressPtr = ckalloc(sizeof(TkStressedCmap)); + stressPtr->colormap = colormap; + template.visualid = XVisualIDFromVisual(Tk_Visual(tkwin)); + + visInfoPtr = XGetVisualInfo(Tk_Display(tkwin), + VisualIDMask, &template, &numFound); + if (numFound < 1) { + Tcl_Panic("FindClosestColor couldn't lookup visual"); + } + + stressPtr->numColors = visInfoPtr->colormap_size; + XFree((char *) visInfoPtr); + stressPtr->colorPtr = + ckalloc(stressPtr->numColors * sizeof(XColor)); + for (i = 0; i < stressPtr->numColors; i++) { + stressPtr->colorPtr[i].pixel = (unsigned long) i; + } + + XQueryColors(dispPtr->display, colormap, stressPtr->colorPtr, + stressPtr->numColors); + + stressPtr->nextPtr = dispPtr->stressPtr; + dispPtr->stressPtr = stressPtr; + break; + } + if (stressPtr->colormap == colormap) { + break; + } + } + + /* + * Find the color that best approximates the desired one, then try to + * allocate that color. If that fails, it must mean that the color was + * read-write (so we can't use it, since it's owner might change it) or + * else it was already freed. Try again, over and over again, until + * something succeeds. + */ + + while (1) { + if (stressPtr->numColors == 0) { + Tcl_Panic("FindClosestColor ran out of colors"); + } + closestDistance = 1e30; + closest = 0; + for (colorPtr = stressPtr->colorPtr, i = 0; i < stressPtr->numColors; + colorPtr++, i++) { + /* + * Use Euclidean distance in RGB space, weighted by Y (of YIQ) as + * the objective function; this accounts for differences in the + * color sensitivity of the eye. + */ + + tmp = .30*(((int) desiredColorPtr->red) - (int) colorPtr->red); + distance = tmp*tmp; + tmp = .61*(((int) desiredColorPtr->green) - (int) colorPtr->green); + distance += tmp*tmp; + tmp = .11*(((int) desiredColorPtr->blue) - (int) colorPtr->blue); + distance += tmp*tmp; + if (distance < closestDistance) { + closest = i; + closestDistance = distance; + } + } + if (XAllocColor(dispPtr->display, colormap, + &stressPtr->colorPtr[closest]) != 0) { + *actualColorPtr = stressPtr->colorPtr[closest]; + return; + } + + /* + * Couldn't allocate the color. Remove it from the table and go back + * to look for the next best color. + */ + + stressPtr->colorPtr[closest] = + stressPtr->colorPtr[stressPtr->numColors-1]; + stressPtr->numColors -= 1; + } +} + +/* + *---------------------------------------------------------------------- + * + * DeleteStressedCmap -- + * + * This function releases the information cached for "colormap" so that + * it will be refetched from the X server the next time it is needed. + * + * Results: + * None. + * + * Side effects: + * The TkStressedCmap structure for colormap is deleted; the colormap is + * no longer considered to be "stressed". + * + * Note: + * This function is invoked whenever a color in a colormap is freed, and + * whenever a color allocation in a colormap succeeds. This guarantees + * that TkStressedCmap structures are always deleted before the + * corresponding Colormap is freed. + * + *---------------------------------------------------------------------- + */ + +static void +DeleteStressedCmap( + Display *display, /* Xlib's handle for the display containing + * the colormap. */ + Colormap colormap) /* Colormap to flush. */ +{ + TkStressedCmap *prevPtr, *stressPtr; + TkDisplay *dispPtr = TkGetDisplay(display); + + for (prevPtr = NULL, stressPtr = dispPtr->stressPtr; stressPtr != NULL; + prevPtr = stressPtr, stressPtr = stressPtr->nextPtr) { + if (stressPtr->colormap == colormap) { + if (prevPtr == NULL) { + dispPtr->stressPtr = stressPtr->nextPtr; + } else { + prevPtr->nextPtr = stressPtr->nextPtr; + } + ckfree(stressPtr->colorPtr); + ckfree(stressPtr); + return; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpCmapStressed -- + * + * Check to see whether a given colormap is known to be out of entries. + * + * Results: + * 1 is returned if "colormap" is stressed (i.e. it has run out of + * entries recently), 0 otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkpCmapStressed( + Tk_Window tkwin, /* Window that identifies the display + * containing the colormap. */ + Colormap colormap) /* Colormap to check for stress. */ +{ + TkStressedCmap *stressPtr; + + for (stressPtr = ((TkWindow *) tkwin)->dispPtr->stressPtr; + stressPtr != NULL; stressPtr = stressPtr->nextPtr) { + if (stressPtr->colormap == colormap) { + return 1; + } + } + return 0; +} + + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixConfig.c b/tk8.6/unix/tkUnixConfig.c new file mode 100644 index 0000000..3584494 --- /dev/null +++ b/tk8.6/unix/tkUnixConfig.c @@ -0,0 +1,50 @@ +/* + * tkUnixConfig.c -- + * + * This module implements the Unix 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. + */ + +#include "tkInt.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. */ + const char *dbName, /* The option database name. */ + const char *className) /* The name of the option class. */ +{ + return NULL; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixCursor.c b/tk8.6/unix/tkUnixCursor.c new file mode 100644 index 0000000..8afb92d --- /dev/null +++ b/tk8.6/unix/tkUnixCursor.c @@ -0,0 +1,650 @@ +/* + * tkUnixCursor.c -- + * + * This file contains X specific cursor manipulation routines. + * + * 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. + */ + +#include "tkInt.h" + +/* + * The following data structure is a superset of the TkCursor structure + * defined in tkCursor.c. Each system specific cursor module will define a + * different cursor structure. All of these structures must have the same + * header consisting of the fields in TkCursor. + */ + +typedef struct { + TkCursor info; /* Generic cursor info used by tkCursor.c */ + Display *display; /* Display for which cursor is valid. */ +} TkUnixCursor; + +/* + * The table below is used to map from the name of a cursor to its index in + * the official cursor font: + */ + +static const struct CursorName { + const char *name; + unsigned int shape; +} cursorNames[] = { + {"X_cursor", XC_X_cursor}, + {"arrow", XC_arrow}, + {"based_arrow_down", XC_based_arrow_down}, + {"based_arrow_up", XC_based_arrow_up}, + {"boat", XC_boat}, + {"bogosity", XC_bogosity}, + {"bottom_left_corner", XC_bottom_left_corner}, + {"bottom_right_corner", XC_bottom_right_corner}, + {"bottom_side", XC_bottom_side}, + {"bottom_tee", XC_bottom_tee}, + {"box_spiral", XC_box_spiral}, + {"center_ptr", XC_center_ptr}, + {"circle", XC_circle}, + {"clock", XC_clock}, + {"coffee_mug", XC_coffee_mug}, + {"cross", XC_cross}, + {"cross_reverse", XC_cross_reverse}, + {"crosshair", XC_crosshair}, + {"diamond_cross", XC_diamond_cross}, + {"dot", XC_dot}, + {"dotbox", XC_dotbox}, + {"double_arrow", XC_double_arrow}, + {"draft_large", XC_draft_large}, + {"draft_small", XC_draft_small}, + {"draped_box", XC_draped_box}, + {"exchange", XC_exchange}, + {"fleur", XC_fleur}, + {"gobbler", XC_gobbler}, + {"gumby", XC_gumby}, + {"hand1", XC_hand1}, + {"hand2", XC_hand2}, + {"heart", XC_heart}, + {"icon", XC_icon}, + {"iron_cross", XC_iron_cross}, + {"left_ptr", XC_left_ptr}, + {"left_side", XC_left_side}, + {"left_tee", XC_left_tee}, + {"leftbutton", XC_leftbutton}, + {"ll_angle", XC_ll_angle}, + {"lr_angle", XC_lr_angle}, + {"man", XC_man}, + {"middlebutton", XC_middlebutton}, + {"mouse", XC_mouse}, + {"pencil", XC_pencil}, + {"pirate", XC_pirate}, + {"plus", XC_plus}, + {"question_arrow", XC_question_arrow}, + {"right_ptr", XC_right_ptr}, + {"right_side", XC_right_side}, + {"right_tee", XC_right_tee}, + {"rightbutton", XC_rightbutton}, + {"rtl_logo", XC_rtl_logo}, + {"sailboat", XC_sailboat}, + {"sb_down_arrow", XC_sb_down_arrow}, + {"sb_h_double_arrow", XC_sb_h_double_arrow}, + {"sb_left_arrow", XC_sb_left_arrow}, + {"sb_right_arrow", XC_sb_right_arrow}, + {"sb_up_arrow", XC_sb_up_arrow}, + {"sb_v_double_arrow", XC_sb_v_double_arrow}, + {"shuttle", XC_shuttle}, + {"sizing", XC_sizing}, + {"spider", XC_spider}, + {"spraycan", XC_spraycan}, + {"star", XC_star}, + {"target", XC_target}, + {"tcross", XC_tcross}, + {"top_left_arrow", XC_top_left_arrow}, + {"top_left_corner", XC_top_left_corner}, + {"top_right_corner", XC_top_right_corner}, + {"top_side", XC_top_side}, + {"top_tee", XC_top_tee}, + {"trek", XC_trek}, + {"ul_angle", XC_ul_angle}, + {"umbrella", XC_umbrella}, + {"ur_angle", XC_ur_angle}, + {"watch", XC_watch}, + {"xterm", XC_xterm}, + {NULL, 0} +}; + +/* + * The table below is used to map from a cursor name to the data that defines + * the cursor. This table is used for cursors defined by Tk that don't exist + * in the X cursor table. + */ + +#define CURSOR_NONE_DATA \ +"#define none_width 1\n" \ +"#define none_height 1\n" \ +"#define none_x_hot 0\n" \ +"#define none_y_hot 0\n" \ +"static unsigned char none_bits[] = {\n" \ +" 0x00};" + +/* + * Define test cursor to check that mask fg and bg color settings are working. + * + * . configure -cursor {center_ptr green red} + * . configure -cursor {@myarrow.xbm myarrow-mask.xbm green red} + * . configure -cursor {myarrow green red} + */ + +/*#define DEFINE_MYARROW_CURSOR*/ + +#ifdef DEFINE_MYARROW_CURSOR +#define CURSOR_MYARROW_DATA \ +"#define myarrow_width 16\n" \ +"#define myarrow_height 16\n" \ +"#define myarrow_x_hot 7\n" \ +"#define myarrow_y_hot 0\n" \ +"static unsigned char myarrow_bits[] = {\n" \ +" 0x7f, 0xff, 0xbf, 0xfe, 0xdf, 0xfd, 0xef, 0xfb, 0xf7, 0xf7, 0xfb, 0xef,\n" \ +" 0xfd, 0xdf, 0xfe, 0xbf, 0x80, 0x00, 0xbf, 0xfe, 0xbf, 0xfe, 0xbf, 0xfe,\n" \ +" 0xbf, 0xfe, 0xbf, 0xfe, 0xbf, 0xfe, 0x3f, 0xfe};" + +#define CURSOR_MYARROW_MASK \ +"#define myarrow-mask_width 16\n" \ +"#define myarrow-mask_height 16\n" \ +"#define myarrow-mask_x_hot 7\n" \ +"#define myarrow-mask_y_hot 0\n" \ +"static unsigned char myarrow-mask_bits[] = {\n" \ +" 0x80, 0x00, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f, 0xfc, 0x1f,\n" \ +" 0xfe, 0x3f, 0xff, 0x7f, 0xff, 0xff, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,\n" \ +" 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01};" + +#endif /* DEFINE_MYARROW_CURSOR */ + +static const struct TkCursorName { + const char *name; + const char *data; + char *mask; +} tkCursorNames[] = { + {"none", CURSOR_NONE_DATA, NULL}, +#ifdef DEFINE_MYARROW_CURSOR + {"myarrow", CURSOR_MYARROW_DATA, CURSOR_MYARROW_MASK}, +#endif /* DEFINE_MYARROW_CURSOR */ + {NULL, NULL, NULL} +}; + +/* + * Font to use for cursors: + */ + +#ifndef CURSORFONT +#define CURSORFONT "cursor" +#endif + +static Cursor CreateCursorFromTableOrFile(Tcl_Interp *interp, + Tk_Window tkwin, int argc, const char **argv, + const struct TkCursorName *tkCursorPtr); + +/* + *---------------------------------------------------------------------- + * + * TkGetCursorByName -- + * + * Retrieve a cursor by name. Parse the cursor name into fields and + * create a cursor, either from the standard cursor font or from bitmap + * files. + * + * Results: + * Returns a new cursor, or NULL on errors. + * + * Side effects: + * Allocates a new cursor. + * + *---------------------------------------------------------------------- + */ + +TkCursor * +TkGetCursorByName( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tk_Window tkwin, /* Window in which cursor will be used. */ + Tk_Uid string) /* Description of cursor. See manual entry for + * details on legal syntax. */ +{ + TkUnixCursor *cursorPtr = NULL; + Cursor cursor = None; + int argc; + const char **argv = NULL; + Display *display = Tk_Display(tkwin); + int inTkTable = 0; + const struct TkCursorName *tkCursorPtr = NULL; + + if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) { + return NULL; + } + if (argc == 0) { + goto badString; + } + + /* + * Check Tk specific table of cursor names. The cursor names don't overlap + * with cursors defined in the X table so search order does not matter. + */ + + if (argv[0][0] != '@') { + for (tkCursorPtr = tkCursorNames; ; tkCursorPtr++) { + if (tkCursorPtr->name == NULL) { + tkCursorPtr = NULL; + break; + } + if ((tkCursorPtr->name[0] == argv[0][0]) && + (strcmp(tkCursorPtr->name, argv[0]) == 0)) { + inTkTable = 1; + break; + } + } + } + + if ((argv[0][0] != '@') && !inTkTable) { + XColor fg, bg; + unsigned int maskIndex; + register const struct CursorName *namePtr; + TkDisplay *dispPtr; + + /* + * The cursor is to come from the standard cursor font. If one arg, it + * is cursor name (use black and white for fg and bg). If two args, + * they are name and fg color (ignore mask). If three args, they are + * name, fg, bg. Some of the code below is stolen from the + * XCreateFontCursor Xlib function. + */ + + if (argc > 3) { + goto badString; + } + for (namePtr = cursorNames; ; namePtr++) { + if (namePtr->name == NULL) { + goto badString; + } + if ((namePtr->name[0] == argv[0][0]) + && (strcmp(namePtr->name, argv[0]) == 0)) { + break; + } + } + + maskIndex = namePtr->shape + 1; + if (argc == 1) { + fg.red = fg.green = fg.blue = 0; + bg.red = bg.green = bg.blue = 65535; + } else { + if (TkParseColor(display, Tk_Colormap(tkwin), argv[1], &fg) == 0) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid color name \"%s\"", argv[1])); + Tcl_SetErrorCode(interp, "TK", "CURSOR", "COLOR", NULL); + goto cleanup; + } + if (argc == 2) { + bg.red = bg.green = bg.blue = 0; + maskIndex = namePtr->shape; + } else if (TkParseColor(display, Tk_Colormap(tkwin), argv[2], + &bg) == 0) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid color name \"%s\"", argv[2])); + Tcl_SetErrorCode(interp, "TK", "CURSOR", "COLOR", NULL); + goto cleanup; + } + } + dispPtr = ((TkWindow *) tkwin)->dispPtr; + if (dispPtr->cursorFont == None) { + dispPtr->cursorFont = XLoadFont(display, CURSORFONT); + if (dispPtr->cursorFont == None) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "couldn't load cursor font", -1)); + Tcl_SetErrorCode(interp, "TK", "CURSOR", "FONT", NULL); + goto cleanup; + } + } + cursor = XCreateGlyphCursor(display, dispPtr->cursorFont, + dispPtr->cursorFont, namePtr->shape, maskIndex, + &fg, &bg); + } else { + /* + * Prevent file system access in safe interpreters. + */ + + if (!inTkTable && Tcl_IsSafe(interp)) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "can't get cursor from a file in a safe interpreter", + -1)); + Tcl_SetErrorCode(interp, "TK", "SAFE", "CURSOR_FILE", NULL); + cursorPtr = NULL; + goto cleanup; + } + + /* + * If the cursor is to be created from bitmap files, then there should + * be either two elements in the list (source, color) or four (source + * mask fg bg). A cursor defined in the Tk table accepts the same + * arguments as an X cursor. + */ + + if (inTkTable && (argc != 1) && (argc != 2) && (argc != 3)) { + goto badString; + } + + if (!inTkTable && (argc != 2) && (argc != 4)) { + goto badString; + } + + cursor = CreateCursorFromTableOrFile(interp, tkwin, argc, argv, + tkCursorPtr); + } + + if (cursor != None) { + cursorPtr = ckalloc(sizeof(TkUnixCursor)); + cursorPtr->info.cursor = (Tk_Cursor) cursor; + cursorPtr->display = display; + } + + cleanup: + if (argv != NULL) { + ckfree(argv); + } + return (TkCursor *) cursorPtr; + + badString: + if (argv) { + ckfree(argv); + } + Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad cursor spec \"%s\"", string)); + Tcl_SetErrorCode(interp, "TK", "VALUE", "CURSOR", NULL); + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * CreateCursorFromTableOrFile -- + * + * Create a cursor defined in a file or the Tk static cursor table. A + * cursor defined in a file starts with the '@' character. This method + * assumes that the number of arguments in argv has been validated + * already. + * + * Results: + * Returns a new cursor, or None on error. + * + * Side effects: + * Allocates a new X cursor. + * + *---------------------------------------------------------------------- + */ + +static Cursor +CreateCursorFromTableOrFile( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tk_Window tkwin, /* Window in which cursor will be used. */ + int argc, + const char **argv, /* Cursor spec parsed into elements. */ + const struct TkCursorName *tkCursorPtr) + /* Non-NULL when cursor is defined in Tk + * table. */ +{ + Cursor cursor = None; + + int width, height, maskWidth, maskHeight; + int xHot = -1, yHot = -1; + int dummy1, dummy2; + XColor fg, bg; + const char *fgColor; + const char *bgColor; + int inTkTable = (tkCursorPtr != NULL); + + Display *display = Tk_Display(tkwin); + Drawable drawable = RootWindowOfScreen(Tk_Screen(tkwin)); + + Pixmap source = None; + Pixmap mask = None; + + /* + * A cursor defined in a file accepts either 2 or 4 arguments. + * + * {srcfile fg} + * {srcfile maskfile fg bg} + * + * A cursor defined in the Tk table accepts 1, 2, or 3 arguments. + * + * {tkcursorname} + * {tkcursorname fg} + * {tkcursorname fg bg} + */ + + if (inTkTable) { + /* + * This logic is like TkReadBitmapFile(). + */ + + char *data; + + data = TkGetBitmapData(NULL, tkCursorPtr->data, NULL, + &width, &height, &xHot, &yHot); + if (data == NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "error reading bitmap data for \"%s\"", argv[0])); + Tcl_SetErrorCode(interp, "TK", "CURSOR", "BITMAP_DATA", NULL); + goto cleanup; + } + + source = XCreateBitmapFromData(display, drawable, data, width,height); + ckfree(data); + } else { + if (TkReadBitmapFile(display, drawable, &argv[0][1], + (unsigned *) &width, (unsigned *) &height, + &source, &xHot, &yHot) != BitmapSuccess) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "cleanup reading bitmap file \"%s\"", &argv[0][1])); + Tcl_SetErrorCode(interp, "TK", "CURSOR", "BITMAP_FILE", NULL); + goto cleanup; + } + } + + if ((xHot < 0) || (yHot < 0) || (xHot >= width) || (yHot >= height)) { + if (inTkTable) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "bad hot spot in bitmap data for \"%s\"", argv[0])); + } else { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "bad hot spot in bitmap file \"%s\"", &argv[0][1])); + } + Tcl_SetErrorCode(interp, "TK", "CURSOR", "HOTSPOT", NULL); + goto cleanup; + } + + /* + * Parse color names from optional fg and bg arguments + */ + + if (argc == 1) { + fg.red = fg.green = fg.blue = 0; + bg.red = bg.green = bg.blue = 65535; + } else if (argc == 2) { + fgColor = argv[1]; + if (TkParseColor(display, Tk_Colormap(tkwin), fgColor, &fg) == 0) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid color name \"%s\"", fgColor)); + Tcl_SetErrorCode(interp, "TK", "CURSOR", "COLOR", NULL); + goto cleanup; + } + if (inTkTable) { + bg.red = bg.green = bg.blue = 0; + } else { + bg = fg; + } + } else { + /* 3 or 4 arguments */ + if (inTkTable) { + fgColor = argv[1]; + bgColor = argv[2]; + } else { + fgColor = argv[2]; + bgColor = argv[3]; + } + if (TkParseColor(display, Tk_Colormap(tkwin), fgColor, &fg) == 0) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid color name \"%s\"", fgColor)); + Tcl_SetErrorCode(interp, "TK", "CURSOR", "COLOR", NULL); + goto cleanup; + } + if (TkParseColor(display, Tk_Colormap(tkwin), bgColor, &bg) == 0) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid color name \"%s\"", bgColor)); + Tcl_SetErrorCode(interp, "TK", "CURSOR", "COLOR", NULL); + goto cleanup; + } + } + + /* + * If there is no mask data, then create the cursor now. + */ + + if ((!inTkTable && (argc == 2)) || (inTkTable && tkCursorPtr->mask == NULL)) { + cursor = XCreatePixmapCursor(display, source, source, + &fg, &fg, (unsigned) xHot, (unsigned) yHot); + goto cleanup; + } + + /* + * Parse bitmap mask data and create cursor with fg and bg colors. + */ + + if (inTkTable) { + /* + * This logic is like TkReadBitmapFile(). + */ + + char *data; + + data = TkGetBitmapData(NULL, tkCursorPtr->mask, NULL, + &maskWidth, &maskHeight, &dummy1, &dummy2); + if (data == NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "error reading bitmap mask data for \"%s\"", argv[0])); + Tcl_SetErrorCode(interp, "TK", "CURSOR", "MASK_DATA", NULL); + goto cleanup; + } + + mask = XCreateBitmapFromData(display, drawable, data, maskWidth, + maskHeight); + + ckfree(data); + } else { + if (TkReadBitmapFile(display, drawable, argv[1], + (unsigned int *) &maskWidth, (unsigned int *) &maskHeight, + &mask, &dummy1, &dummy2) != BitmapSuccess) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "cleanup reading bitmap file \"%s\"", argv[1])); + Tcl_SetErrorCode(interp, "TK", "CURSOR", "MASK_FILE", NULL); + goto cleanup; + } + } + + if ((maskWidth != width) || (maskHeight != height)) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "source and mask bitmaps have different sizes", -1)); + Tcl_SetErrorCode(interp, "TK", "CURSOR", "SIZE_MATCH", NULL); + goto cleanup; + } + + cursor = XCreatePixmapCursor(display, source, mask, + &fg, &bg, (unsigned) xHot, (unsigned) yHot); + + cleanup: + if (source != None) { + Tk_FreePixmap(display, source); + } + if (mask != None) { + Tk_FreePixmap(display, mask); + } + return cursor; +} + +/* + *---------------------------------------------------------------------- + * + * TkCreateCursorFromData -- + * + * Creates a cursor from the source and mask bits. + * + * Results: + * Returns a new cursor, or NULL on errors. + * + * Side effects: + * Allocates a new cursor. + * + *---------------------------------------------------------------------- + */ + +TkCursor * +TkCreateCursorFromData( + Tk_Window tkwin, /* Window in which cursor will be used. */ + const char *source, /* Bitmap data for cursor shape. */ + const char *mask, /* Bitmap data for cursor mask. */ + int width, int height, /* Dimensions of cursor. */ + int xHot, int yHot, /* Location of hot-spot in cursor. */ + XColor fgColor, /* Foreground color for cursor. */ + XColor bgColor) /* Background color for cursor. */ +{ + Cursor cursor; + Pixmap sourcePixmap, maskPixmap; + TkUnixCursor *cursorPtr = NULL; + Display *display = Tk_Display(tkwin); + + sourcePixmap = XCreateBitmapFromData(display, + RootWindowOfScreen(Tk_Screen(tkwin)), source, (unsigned) width, + (unsigned) height); + maskPixmap = XCreateBitmapFromData(display, + RootWindowOfScreen(Tk_Screen(tkwin)), mask, (unsigned) width, + (unsigned) height); + cursor = XCreatePixmapCursor(display, sourcePixmap, + maskPixmap, &fgColor, &bgColor, (unsigned) xHot, (unsigned) yHot); + Tk_FreePixmap(display, sourcePixmap); + Tk_FreePixmap(display, maskPixmap); + + if (cursor != None) { + cursorPtr = ckalloc(sizeof(TkUnixCursor)); + cursorPtr->info.cursor = (Tk_Cursor) cursor; + cursorPtr->display = display; + } + return (TkCursor *) cursorPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkpFreeCursor -- + * + * This function is called to release a cursor allocated by + * TkGetCursorByName. + * + * Results: + * None. + * + * Side effects: + * The cursor data structure is deallocated. + * + *---------------------------------------------------------------------- + */ + +void +TkpFreeCursor( + TkCursor *cursorPtr) +{ + TkUnixCursor *unixCursorPtr = (TkUnixCursor *) cursorPtr; + + XFreeCursor(unixCursorPtr->display, (Cursor) unixCursorPtr->info.cursor); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixDefault.h b/tk8.6/unix/tkUnixDefault.h new file mode 100644 index 0000000..2c3854d --- /dev/null +++ b/tk8.6/unix/tkUnixDefault.h @@ -0,0 +1,533 @@ +/* + * tkUnixDefault.h -- + * + * This file defines the defaults for all options for all of + * the Tk widgets. + * + * Copyright (c) 1991-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#ifndef _TKUNIXDEFAULT +#define _TKUNIXDEFAULT + +/* + * The definitions below provide symbolic names for the default colors. + * NORMAL_BG - Normal background color. + * ACTIVE_BG - Background color when widget is active. + * SELECT_BG - Background color for selected text. + * TROUGH - Background color for troughs in scales and scrollbars. + * INDICATOR - Color for indicator when button is selected. + * DISABLED - Foreground color when widget is disabled. + */ + +#define BLACK "#000000" +#define WHITE "#ffffff" + +#define NORMAL_BG "#d9d9d9" +#define ACTIVE_BG "#ececec" +#define SELECT_BG "#c3c3c3" +#define TROUGH "#b3b3b3" +#define CHECK_INDICATOR WHITE +#define MENU_INDICATOR BLACK +#define DISABLED "#a3a3a3" + +/* + * Defaults for labels, buttons, checkbuttons, and radiobuttons: + */ + +#define DEF_BUTTON_ANCHOR "center" +#define DEF_BUTTON_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_BUTTON_ACTIVE_BG_MONO BLACK +#define DEF_BUTTON_ACTIVE_FG_COLOR BLACK +#define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR +#define DEF_BUTTON_ACTIVE_FG_MONO WHITE +#define DEF_BUTTON_BG_COLOR NORMAL_BG +#define DEF_BUTTON_BG_MONO WHITE +#define DEF_BUTTON_BITMAP "" +#define DEF_BUTTON_BORDER_WIDTH "1" +#define DEF_BUTTON_CURSOR "" +#define DEF_BUTTON_COMPOUND "none" +#define DEF_BUTTON_COMMAND "" +#define DEF_BUTTON_DEFAULT "disabled" +#define DEF_BUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_BUTTON_DISABLED_FG_MONO "" +#define DEF_BUTTON_FG BLACK +#define DEF_CHKRAD_FG DEF_BUTTON_FG +#define DEF_BUTTON_FONT "TkDefaultFont" +#define DEF_BUTTON_HEIGHT "0" +#define DEF_BUTTON_HIGHLIGHT_BG_COLOR DEF_BUTTON_BG_COLOR +#define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO +#define DEF_BUTTON_HIGHLIGHT BLACK +#define DEF_LABEL_HIGHLIGHT_WIDTH "0" +#define DEF_BUTTON_HIGHLIGHT_WIDTH "1" +#define DEF_BUTTON_IMAGE ((char *) NULL) +#define DEF_BUTTON_INDICATOR "1" +#define DEF_BUTTON_JUSTIFY "center" +#define DEF_BUTTON_OFF_VALUE "0" +#define DEF_BUTTON_ON_VALUE "1" +#define DEF_BUTTON_TRISTATE_VALUE "" +#define DEF_BUTTON_OVER_RELIEF "" +#define DEF_BUTTON_PADX "3m" +#define DEF_LABCHKRAD_PADX "1" +#define DEF_BUTTON_PADY "1m" +#define DEF_LABCHKRAD_PADY "1" +#define DEF_BUTTON_RELIEF "raised" +#define DEF_LABCHKRAD_RELIEF "flat" +#define DEF_BUTTON_REPEAT_DELAY "0" +#define DEF_BUTTON_REPEAT_INTERVAL "0" +#define DEF_BUTTON_SELECT_COLOR CHECK_INDICATOR +#define DEF_BUTTON_SELECT_MONO BLACK +#define DEF_BUTTON_SELECT_IMAGE ((char *) NULL) +#define DEF_BUTTON_STATE "normal" +#define DEF_LABEL_TAKE_FOCUS "0" +#define DEF_BUTTON_TAKE_FOCUS ((char *) NULL) +#define DEF_BUTTON_TEXT "" +#define DEF_BUTTON_TEXT_VARIABLE "" +#define DEF_BUTTON_UNDERLINE "-1" +#define DEF_BUTTON_VALUE "" +#define DEF_BUTTON_WIDTH "0" +#define DEF_BUTTON_WRAP_LENGTH "0" +#define DEF_RADIOBUTTON_VARIABLE "selectedButton" +#define DEF_CHECKBUTTON_VARIABLE "" + +/* + * Defaults for canvases: + */ + +#define DEF_CANVAS_BG_COLOR NORMAL_BG +#define DEF_CANVAS_BG_MONO WHITE +#define DEF_CANVAS_BORDER_WIDTH "0" +#define DEF_CANVAS_CLOSE_ENOUGH "1" +#define DEF_CANVAS_CONFINE "1" +#define DEF_CANVAS_CURSOR "" +#define DEF_CANVAS_HEIGHT "7c" +#define DEF_CANVAS_HIGHLIGHT_BG NORMAL_BG +#define DEF_CANVAS_HIGHLIGHT BLACK +#define DEF_CANVAS_HIGHLIGHT_WIDTH "1" +#define DEF_CANVAS_INSERT_BG BLACK +#define DEF_CANVAS_INSERT_BD_COLOR "0" +#define DEF_CANVAS_INSERT_BD_MONO "0" +#define DEF_CANVAS_INSERT_OFF_TIME "300" +#define DEF_CANVAS_INSERT_ON_TIME "600" +#define DEF_CANVAS_INSERT_WIDTH "2" +#define DEF_CANVAS_RELIEF "flat" +#define DEF_CANVAS_SCROLL_REGION "" +#define DEF_CANVAS_SELECT_COLOR SELECT_BG +#define DEF_CANVAS_SELECT_MONO BLACK +#define DEF_CANVAS_SELECT_BD_COLOR "1" +#define DEF_CANVAS_SELECT_BD_MONO "0" +#define DEF_CANVAS_SELECT_FG_COLOR BLACK +#define DEF_CANVAS_SELECT_FG_MONO WHITE +#define DEF_CANVAS_TAKE_FOCUS ((char *) NULL) +#define DEF_CANVAS_WIDTH "10c" +#define DEF_CANVAS_X_SCROLL_CMD "" +#define DEF_CANVAS_X_SCROLL_INCREMENT "0" +#define DEF_CANVAS_Y_SCROLL_CMD "" +#define DEF_CANVAS_Y_SCROLL_INCREMENT "0" + +/* + * Defaults for entries: + */ + +#define DEF_ENTRY_BG_COLOR WHITE +#define DEF_ENTRY_BG_MONO WHITE +#define DEF_ENTRY_BORDER_WIDTH "1" +#define DEF_ENTRY_CURSOR "xterm" +#define DEF_ENTRY_DISABLED_BG_COLOR NORMAL_BG +#define DEF_ENTRY_DISABLED_BG_MONO WHITE +#define DEF_ENTRY_DISABLED_FG DISABLED +#define DEF_ENTRY_EXPORT_SELECTION "1" +#define DEF_ENTRY_FONT "TkTextFont" +#define DEF_ENTRY_FG BLACK +#define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG +#define DEF_ENTRY_HIGHLIGHT BLACK +#define DEF_ENTRY_HIGHLIGHT_WIDTH "1" +#define DEF_ENTRY_INSERT_BG BLACK +#define DEF_ENTRY_INSERT_BD_COLOR "0" +#define DEF_ENTRY_INSERT_BD_MONO "0" +#define DEF_ENTRY_INSERT_OFF_TIME "300" +#define DEF_ENTRY_INSERT_ON_TIME "600" +#define DEF_ENTRY_INSERT_WIDTH "2" +#define DEF_ENTRY_JUSTIFY "left" +#define DEF_ENTRY_READONLY_BG_COLOR NORMAL_BG +#define DEF_ENTRY_READONLY_BG_MONO WHITE +#define DEF_ENTRY_RELIEF "sunken" +#define DEF_ENTRY_SCROLL_COMMAND "" +#define DEF_ENTRY_SELECT_COLOR SELECT_BG +#define DEF_ENTRY_SELECT_MONO BLACK +#define DEF_ENTRY_SELECT_BD_COLOR "0" +#define DEF_ENTRY_SELECT_BD_MONO "0" +#define DEF_ENTRY_SELECT_FG_COLOR BLACK +#define DEF_ENTRY_SELECT_FG_MONO WHITE +#define DEF_ENTRY_SHOW ((char *) NULL) +#define DEF_ENTRY_STATE "normal" +#define DEF_ENTRY_TAKE_FOCUS ((char *) NULL) +#define DEF_ENTRY_TEXT_VARIABLE "" +#define DEF_ENTRY_WIDTH "20" + +/* + * Defaults for frames: + */ + +#define DEF_FRAME_BG_COLOR NORMAL_BG +#define DEF_FRAME_BG_MONO WHITE +#define DEF_FRAME_BORDER_WIDTH "0" +#define DEF_FRAME_CLASS "Frame" +#define DEF_FRAME_COLORMAP "" +#define DEF_FRAME_CONTAINER "0" +#define DEF_FRAME_CURSOR "" +#define DEF_FRAME_HEIGHT "0" +#define DEF_FRAME_HIGHLIGHT_BG NORMAL_BG +#define DEF_FRAME_HIGHLIGHT BLACK +#define DEF_FRAME_HIGHLIGHT_WIDTH "0" +#define DEF_FRAME_LABEL "" +#define DEF_FRAME_PADX "0" +#define DEF_FRAME_PADY "0" +#define DEF_FRAME_RELIEF "flat" +#define DEF_FRAME_TAKE_FOCUS "0" +#define DEF_FRAME_VISUAL "" +#define DEF_FRAME_WIDTH "0" + +/* + * Defaults for labelframes: + */ + +#define DEF_LABELFRAME_BORDER_WIDTH "2" +#define DEF_LABELFRAME_CLASS "Labelframe" +#define DEF_LABELFRAME_RELIEF "groove" +#define DEF_LABELFRAME_FG BLACK +#define DEF_LABELFRAME_FONT "TkDefaultFont" +#define DEF_LABELFRAME_TEXT "" +#define DEF_LABELFRAME_LABELANCHOR "nw" + +/* + * Defaults for listboxes: + */ + +#define DEF_LISTBOX_ACTIVE_STYLE "dotbox" +#define DEF_LISTBOX_BG_COLOR WHITE +#define DEF_LISTBOX_BG_MONO WHITE +#define DEF_LISTBOX_BORDER_WIDTH "1" +#define DEF_LISTBOX_CURSOR "" +#define DEF_LISTBOX_DISABLED_FG DISABLED +#define DEF_LISTBOX_EXPORT_SELECTION "1" +#define DEF_LISTBOX_FONT "TkDefaultFont" +#define DEF_LISTBOX_FG BLACK +#define DEF_LISTBOX_HEIGHT "10" +#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG +#define DEF_LISTBOX_HIGHLIGHT BLACK +#define DEF_LISTBOX_HIGHLIGHT_WIDTH "1" +#define DEF_LISTBOX_JUSTIFY "left" +#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 "0" +#define DEF_LISTBOX_SELECT_FG_COLOR BLACK +#define DEF_LISTBOX_SELECT_FG_MONO WHITE +#define DEF_LISTBOX_SELECT_MODE "browse" +#define DEF_LISTBOX_SET_GRID "0" +#define DEF_LISTBOX_STATE "normal" +#define DEF_LISTBOX_TAKE_FOCUS ((char *) NULL) +#define DEF_LISTBOX_WIDTH "20" + +/* + * Defaults for individual entries of menus: + */ + +#define DEF_MENU_ENTRY_ACTIVE_BG ((char *) NULL) +#define DEF_MENU_ENTRY_ACTIVE_FG ((char *) NULL) +#define DEF_MENU_ENTRY_ACCELERATOR ((char *) NULL) +#define DEF_MENU_ENTRY_BG ((char *) NULL) +#define DEF_MENU_ENTRY_BITMAP None +#define DEF_MENU_ENTRY_COLUMN_BREAK "0" +#define DEF_MENU_ENTRY_COMMAND ((char *) NULL) +#define DEF_MENU_ENTRY_COMPOUND "none" +#define DEF_MENU_ENTRY_FG ((char *) NULL) +#define DEF_MENU_ENTRY_FONT ((char *) NULL) +#define DEF_MENU_ENTRY_HIDE_MARGIN "0" +#define DEF_MENU_ENTRY_IMAGE ((char *) NULL) +#define DEF_MENU_ENTRY_INDICATOR "1" +#define DEF_MENU_ENTRY_LABEL ((char *) NULL) +#define DEF_MENU_ENTRY_MENU ((char *) NULL) +#define DEF_MENU_ENTRY_OFF_VALUE "0" +#define DEF_MENU_ENTRY_ON_VALUE "1" +#define DEF_MENU_ENTRY_SELECT_IMAGE ((char *) NULL) +#define DEF_MENU_ENTRY_STATE "normal" +#define DEF_MENU_ENTRY_VALUE ((char *) NULL) +#define DEF_MENU_ENTRY_CHECK_VARIABLE ((char *) NULL) +#define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton" +#define DEF_MENU_ENTRY_SELECT ((char *) NULL) +#define DEF_MENU_ENTRY_UNDERLINE "-1" + +/* + * Defaults for menus overall: + */ + +#define DEF_MENU_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_MENU_ACTIVE_BG_MONO BLACK +#define DEF_MENU_ACTIVE_BORDER_WIDTH "1" +#define DEF_MENU_ACTIVE_FG_COLOR BLACK +#define DEF_MENU_ACTIVE_FG_MONO WHITE +#define DEF_MENU_BG_COLOR NORMAL_BG +#define DEF_MENU_BG_MONO WHITE +#define DEF_MENU_BORDER_WIDTH "1" +#define DEF_MENU_CURSOR "arrow" +#define DEF_MENU_DISABLED_FG_COLOR DISABLED +#define DEF_MENU_DISABLED_FG_MONO "" +#define DEF_MENU_FONT "TkMenuFont" +#define DEF_MENU_FG BLACK +#define DEF_MENU_POST_COMMAND "" +#define DEF_MENU_RELIEF "raised" +#define DEF_MENU_SELECT_COLOR MENU_INDICATOR +#define DEF_MENU_SELECT_MONO BLACK +#define DEF_MENU_TAKE_FOCUS "0" +#define DEF_MENU_TEAROFF "1" +#define DEF_MENU_TEAROFF_CMD ((char *) NULL) +#define DEF_MENU_TITLE "" +#define DEF_MENU_TYPE "normal" + +/* + * Defaults for menubuttons: + */ + +#define DEF_MENUBUTTON_ANCHOR "center" +#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_COLOR BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE +#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG +#define DEF_MENUBUTTON_BG_MONO WHITE +#define DEF_MENUBUTTON_BITMAP "" +#define DEF_MENUBUTTON_BORDER_WIDTH "1" +#define DEF_MENUBUTTON_CURSOR "" +#define DEF_MENUBUTTON_DIRECTION "below" +#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_MENUBUTTON_DISABLED_FG_MONO "" +#define DEF_MENUBUTTON_FONT "TkDefaultFont" +#define DEF_MENUBUTTON_FG BLACK +#define DEF_MENUBUTTON_HEIGHT "0" +#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR +#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO +#define DEF_MENUBUTTON_HIGHLIGHT BLACK +#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0" +#define DEF_MENUBUTTON_IMAGE ((char *) NULL) +#define DEF_MENUBUTTON_INDICATOR "0" +#define DEF_MENUBUTTON_JUSTIFY "center" +#define DEF_MENUBUTTON_MENU "" +#define DEF_MENUBUTTON_PADX "4p" +#define DEF_MENUBUTTON_PADY "3p" +#define DEF_MENUBUTTON_RELIEF "flat" +#define DEF_MENUBUTTON_STATE "normal" +#define DEF_MENUBUTTON_TAKE_FOCUS "0" +#define DEF_MENUBUTTON_TEXT "" +#define DEF_MENUBUTTON_TEXT_VARIABLE "" +#define DEF_MENUBUTTON_UNDERLINE "-1" +#define DEF_MENUBUTTON_WIDTH "0" +#define DEF_MENUBUTTON_WRAP_LENGTH "0" + +/* + * Defaults for messages: + */ + +#define DEF_MESSAGE_ANCHOR "center" +#define DEF_MESSAGE_ASPECT "150" +#define DEF_MESSAGE_BG_COLOR NORMAL_BG +#define DEF_MESSAGE_BG_MONO WHITE +#define DEF_MESSAGE_BORDER_WIDTH "1" +#define DEF_MESSAGE_CURSOR "" +#define DEF_MESSAGE_FG BLACK +#define DEF_MESSAGE_FONT "TkDefaultFont" +#define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG +#define DEF_MESSAGE_HIGHLIGHT BLACK +#define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" +#define DEF_MESSAGE_JUSTIFY "left" +#define DEF_MESSAGE_PADX "-1" +#define DEF_MESSAGE_PADY "-1" +#define DEF_MESSAGE_RELIEF "flat" +#define DEF_MESSAGE_TAKE_FOCUS "0" +#define DEF_MESSAGE_TEXT "" +#define DEF_MESSAGE_TEXT_VARIABLE "" +#define DEF_MESSAGE_WIDTH "0" + +/* + * Defaults for panedwindows + */ + +#define DEF_PANEDWINDOW_BG_COLOR NORMAL_BG +#define DEF_PANEDWINDOW_BG_MONO WHITE +#define DEF_PANEDWINDOW_BORDERWIDTH "1" +#define DEF_PANEDWINDOW_CURSOR "" +#define DEF_PANEDWINDOW_HANDLEPAD "8" +#define DEF_PANEDWINDOW_HANDLESIZE "8" +#define DEF_PANEDWINDOW_HEIGHT "" +#define DEF_PANEDWINDOW_OPAQUERESIZE "1" +#define DEF_PANEDWINDOW_ORIENT "horizontal" +#define DEF_PANEDWINDOW_PROXYBORDER "2" +#define DEF_PANEDWINDOW_RELIEF "flat" +#define DEF_PANEDWINDOW_SASHCURSOR "" +#define DEF_PANEDWINDOW_SASHPAD "0" +#define DEF_PANEDWINDOW_SASHRELIEF "flat" +#define DEF_PANEDWINDOW_SASHWIDTH "3" +#define DEF_PANEDWINDOW_SHOWHANDLE "0" +#define DEF_PANEDWINDOW_WIDTH "" + +/* + * Defaults for panedwindow panes + */ + +#define DEF_PANEDWINDOW_PANE_AFTER "" +#define DEF_PANEDWINDOW_PANE_BEFORE "" +#define DEF_PANEDWINDOW_PANE_HEIGHT "" +#define DEF_PANEDWINDOW_PANE_MINSIZE "0" +#define DEF_PANEDWINDOW_PANE_PADX "0" +#define DEF_PANEDWINDOW_PANE_PADY "0" +#define DEF_PANEDWINDOW_PANE_STICKY "nsew" +#define DEF_PANEDWINDOW_PANE_WIDTH "" +#define DEF_PANEDWINDOW_PANE_HIDE "0" +#define DEF_PANEDWINDOW_PANE_STRETCH "last" + +/* + * Defaults for scales: + */ + +#define DEF_SCALE_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCALE_ACTIVE_BG_MONO BLACK +#define DEF_SCALE_BG_COLOR NORMAL_BG +#define DEF_SCALE_BG_MONO WHITE +#define DEF_SCALE_BIG_INCREMENT "0" +#define DEF_SCALE_BORDER_WIDTH "1" +#define DEF_SCALE_COMMAND "" +#define DEF_SCALE_CURSOR "" +#define DEF_SCALE_DIGITS "0" +#define DEF_SCALE_FONT "TkDefaultFont" +#define DEF_SCALE_FG_COLOR BLACK +#define DEF_SCALE_FG_MONO BLACK +#define DEF_SCALE_FROM "0" +#define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR +#define DEF_SCALE_HIGHLIGHT_BG_MONO DEF_SCALE_BG_MONO +#define DEF_SCALE_HIGHLIGHT BLACK +#define DEF_SCALE_HIGHLIGHT_WIDTH "1" +#define DEF_SCALE_LABEL "" +#define DEF_SCALE_LENGTH "100" +#define DEF_SCALE_ORIENT "vertical" +#define DEF_SCALE_RELIEF "flat" +#define DEF_SCALE_REPEAT_DELAY "300" +#define DEF_SCALE_REPEAT_INTERVAL "100" +#define DEF_SCALE_RESOLUTION "1" +#define DEF_SCALE_TROUGH_COLOR TROUGH +#define DEF_SCALE_TROUGH_MONO WHITE +#define DEF_SCALE_SHOW_VALUE "1" +#define DEF_SCALE_SLIDER_LENGTH "30" +#define DEF_SCALE_SLIDER_RELIEF "raised" +#define DEF_SCALE_STATE "normal" +#define DEF_SCALE_TAKE_FOCUS ((char *) NULL) +#define DEF_SCALE_TICK_INTERVAL "0" +#define DEF_SCALE_TO "100" +#define DEF_SCALE_VARIABLE "" +#define DEF_SCALE_WIDTH "15" + +/* + * Defaults for scrollbars: + */ + +#define DEF_SCROLLBAR_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCROLLBAR_ACTIVE_BG_MONO BLACK +#define DEF_SCROLLBAR_ACTIVE_RELIEF "raised" +#define DEF_SCROLLBAR_BG_COLOR NORMAL_BG +#define DEF_SCROLLBAR_BG_MONO WHITE +#define DEF_SCROLLBAR_BORDER_WIDTH "1" +#define DEF_SCROLLBAR_COMMAND "" +#define DEF_SCROLLBAR_CURSOR "" +#define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1" +#define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG +#define DEF_SCROLLBAR_HIGHLIGHT BLACK +#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "0" +#define DEF_SCROLLBAR_JUMP "0" +#define DEF_SCROLLBAR_ORIENT "vertical" +#define DEF_SCROLLBAR_RELIEF "sunken" +#define DEF_SCROLLBAR_REPEAT_DELAY "300" +#define DEF_SCROLLBAR_REPEAT_INTERVAL "100" +#define DEF_SCROLLBAR_TAKE_FOCUS ((char *) NULL) +#define DEF_SCROLLBAR_TROUGH_COLOR TROUGH +#define DEF_SCROLLBAR_TROUGH_MONO WHITE +#define DEF_SCROLLBAR_WIDTH "11" + +/* + * Defaults for texts: + */ + +#define DEF_TEXT_AUTO_SEPARATORS "1" +#define DEF_TEXT_BG_COLOR WHITE +#define DEF_TEXT_BG_MONO WHITE +#define DEF_TEXT_BLOCK_CURSOR "0" +#define DEF_TEXT_BORDER_WIDTH "1" +#define DEF_TEXT_CURSOR "xterm" +#define DEF_TEXT_FG BLACK +#define DEF_TEXT_EXPORT_SELECTION "1" +#define DEF_TEXT_FONT "TkFixedFont" +#define DEF_TEXT_HEIGHT "24" +#define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG +#define DEF_TEXT_HIGHLIGHT BLACK +#define DEF_TEXT_HIGHLIGHT_WIDTH "1" +#define DEF_TEXT_INSERT_BG BLACK +#define DEF_TEXT_INSERT_BD_COLOR "0" +#define DEF_TEXT_INSERT_BD_MONO "0" +#define DEF_TEXT_INSERT_OFF_TIME "300" +#define DEF_TEXT_INSERT_ON_TIME "600" +#define DEF_TEXT_INSERT_UNFOCUSSED "none" +#define DEF_TEXT_INSERT_WIDTH "2" +#define DEF_TEXT_MAX_UNDO "0" +#define DEF_TEXT_PADX "1" +#define DEF_TEXT_PADY "1" +#define DEF_TEXT_RELIEF "sunken" +#define DEF_TEXT_INACTIVE_SELECT_COLOR SELECT_BG +#define DEF_TEXT_SELECT_COLOR SELECT_BG +#define DEF_TEXT_SELECT_MONO BLACK +#define DEF_TEXT_SELECT_BD_COLOR "0" +#define DEF_TEXT_SELECT_BD_MONO "0" +#define DEF_TEXT_SELECT_FG_COLOR BLACK +#define DEF_TEXT_SELECT_FG_MONO WHITE +#define DEF_TEXT_SELECT_RELIEF "raised" +#define DEF_TEXT_SET_GRID "0" +#define DEF_TEXT_SPACING1 "0" +#define DEF_TEXT_SPACING2 "0" +#define DEF_TEXT_SPACING3 "0" +#define DEF_TEXT_STATE "normal" +#define DEF_TEXT_TABS "" +#define DEF_TEXT_TABSTYLE "tabular" +#define DEF_TEXT_TAKE_FOCUS ((char *) NULL) +#define DEF_TEXT_UNDO "0" +#define DEF_TEXT_WIDTH "80" +#define DEF_TEXT_WRAP "char" +#define DEF_TEXT_XSCROLL_COMMAND "" +#define DEF_TEXT_YSCROLL_COMMAND "" + +/* + * Defaults for canvas text: + */ + +#define DEF_CANVTEXT_FONT "TkDefaultFont" + +/* + * Defaults for toplevels (most of the defaults for frames also apply + * to toplevels): + */ + +#define DEF_TOPLEVEL_CLASS "Toplevel" +#define DEF_TOPLEVEL_MENU "" +#define DEF_TOPLEVEL_SCREEN "" +#define DEF_TOPLEVEL_USE "" + +/* + * Defaults for busy windows: + */ + +#define DEF_BUSY_CURSOR "watch" + +#endif /* _TKUNIXDEFAULT */ diff --git a/tk8.6/unix/tkUnixDialog.c b/tk8.6/unix/tkUnixDialog.c new file mode 100644 index 0000000..afe443f --- /dev/null +++ b/tk8.6/unix/tkUnixDialog.c @@ -0,0 +1,193 @@ +/* + * tkUnixDialog.c -- + * + * Contains the Unix implementation of the common dialog boxes: + * + * Copyright (c) 1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tkUnixInt.h" + +/* + * The wrapper code for Unix is actually set up in library/tk.tcl these days; + * the procedure names used here are probably wrong too... + */ + +#ifdef TK_OBSOLETE_UNIX_DIALOG_WRAPPERS + +/* + *---------------------------------------------------------------------- + * + * EvalObjv -- + * + * Invokes the Tcl procedure with the arguments. + * + * Results: + * Returns the result of the evaluation of the command. + * + * Side effects: + * The command may be autoloaded. + * + *---------------------------------------------------------------------- + */ + +static int +EvalObjv( + Tcl_Interp *interp, /* Current interpreter. */ + char *cmdName, /* Name of the TCL command to call */ + int objc, /* Number of arguments. */ + Tcl_Obj *const *objv) /* Arguments. */ +{ + Tcl_Obj *cmdObj, **objs; + int result; + + cmdObj = Tcl_NewStringObj(cmdName, -1); + Tcl_IncrRefCount(cmdObj); + objs = ckalloc(sizeof(Tcl_Obj *) * (objc+1)); + objs[0] = cmdObj; + memcpy(objs+1, objv, sizeof(Tcl_Obj *) * (unsigned)objc); + + result = Tcl_EvalObjv(interp, objc+1, objs, 0); + + Tcl_DecrRefCount(cmdObj); + ckfree(objs); + + return result; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_ChooseColorObjCmd -- + * + * This procedure implements the color dialog box for the Unix platform. + * See the user documentation for details on what it does. + * + * Results: + * See user documentation. + * + * Side effects: + * A dialog window is created the first time this procedure is called. + * This window is not destroyed and will be reused the next time the + * application invokes the "tk_chooseColor" command. + * + *---------------------------------------------------------------------- + */ + +int +Tk_ChooseColorObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const *objv) /* Arguments. */ +{ + return EvalObjv(interp, "tk::ColorDialog", objc-1, objv+1); +} + +/* + *---------------------------------------------------------------------- + * + * Tk_GetOpenFileCmd -- + * + * This procedure implements the "open file" dialog box for the Unix + * platform. See the user documentation for details on what it does. + * + * Results: + * See user documentation. + * + * 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_GetOpenFileObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const *objv) /* Arguments. */ +{ + Tk_Window tkwin = clientData; + + if (Tk_StrictMotif(tkwin)) { + return EvalObjv(interp, "tk::MotifOpenFDialog", objc-1, objv+1); + } else { + return EvalObjv(interp, "tk::OpenFDialog", objc-1, objv+1); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_GetSaveFileCmd -- + * + * Same as Tk_GetOpenFileCmd but opens a "save file" dialog box instead. + * + * Results: + * Same as Tk_GetOpenFileCmd. + * + * Side effects: + * Same as Tk_GetOpenFileCmd. + * + *---------------------------------------------------------------------- + */ + +int +Tk_GetSaveFileObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const *objv) /* Arguments. */ +{ + Tk_Window tkwin = clientData; + + if (Tk_StrictMotif(tkwin)) { + return EvalObjv(interp, "tk::MotifSaveFDialog", objc-1, objv+1); + } else { + return EvalObjv(interp, "tk::SaveFDialog", objc-1, objv+1); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_MessageBoxCmd -- + * + * This procedure implements the MessageBox window for the Unix + * 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_MessageBoxCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const *objv) /* Arguments. */ +{ + return EvalObjv(interp, "tk::MessageBox", objc-1, objv+1); +} + +#endif /* TK_OBSOLETE_UNIX_DIALOG_WRAPPERS */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixDraw.c b/tk8.6/unix/tkUnixDraw.c new file mode 100644 index 0000000..acc0565 --- /dev/null +++ b/tk8.6/unix/tkUnixDraw.c @@ -0,0 +1,243 @@ +/* + * tkUnixDraw.c -- + * + * This file contains X specific drawing routines. + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tkInt.h" + +#ifndef _WIN32 +#include "tkUnixInt.h" +#endif + +/* + * The following structure is used to pass information to ScrollRestrictProc + * from TkScrollWindow. + */ + +typedef struct ScrollInfo { + int done; /* Flag is 0 until filtering is done. */ + Display *display; /* Display to filter. */ + Window window; /* Window to filter. */ + TkRegion region; /* Region into which damage is accumulated. */ + int dx, dy; /* Amount by which window was shifted. */ +} ScrollInfo; + +/* + * Forward declarations for functions declared later in this file: + */ + +static Tk_RestrictProc ScrollRestrictProc; + +/* + *---------------------------------------------------------------------- + * + * TkScrollWindow -- + * + * Scroll a rectangle of the specified window and accumulate damage + * information in the specified Region. + * + * Results: + * Returns 0 if no damage additional damage was generated. Sets damageRgn + * to contain the damaged areas and returns 1 if GraphicsExpose events + * were detected. + * + * Side effects: + * Scrolls the bits in the window and enters the event loop looking for + * damage events. + * + *---------------------------------------------------------------------- + */ + +int +TkScrollWindow( + Tk_Window tkwin, /* The window to be scrolled. */ + GC gc, /* GC for window to be scrolled. */ + int x, int y, int width, int height, + /* Position rectangle to be scrolled. */ + int dx, int dy, /* Distance rectangle should be moved. */ + TkRegion damageRgn) /* Region to accumulate damage in. */ +{ + Tk_RestrictProc *prevProc; + ClientData prevArg; + ScrollInfo info; + + XCopyArea(Tk_Display(tkwin), Tk_WindowId(tkwin), Tk_WindowId(tkwin), gc, + x, y, (unsigned) width, (unsigned) height, x+dx, y+dy); + + info.done = 0; + info.window = Tk_WindowId(tkwin); + info.display = Tk_Display(tkwin); + info.region = damageRgn; + info.dx = dx; + info.dy = dy; + + /* + * Sync the event stream so all of the expose events will be on the Tk + * event queue before we start filtering. This avoids busy waiting while + * we filter events. + */ + + TkpSync(info.display); + prevProc = Tk_RestrictEvents(ScrollRestrictProc, &info, &prevArg); + while (!info.done) { + Tcl_ServiceEvent(TCL_WINDOW_EVENTS); + } + Tk_RestrictEvents(prevProc, prevArg, &prevArg); + + if (XEmptyRegion((Region) damageRgn)) { + return 0; + } else { + return 1; + } +} + +/* + *---------------------------------------------------------------------- + * + * ScrollRestrictProc -- + * + * A Tk_RestrictProc used by TkScrollWindow to gather up Expose + * information into a single damage region. It accumulates damage events + * on the specified window until a NoExpose or the last GraphicsExpose + * event is detected. + * + * Results: + * None. + * + * Side effects: + * Discards Expose events after accumulating damage information + * for a particular window. + * + *---------------------------------------------------------------------- + */ + +static Tk_RestrictAction +ScrollRestrictProc( + ClientData arg, + XEvent *eventPtr) +{ + ScrollInfo *info = (ScrollInfo *) arg; + XRectangle rect; + + /* + * Defer events which aren't for the specified window. + */ + + if (info->done || (eventPtr->xany.display != info->display) + || (eventPtr->xany.window != info->window)) { + return TK_DEFER_EVENT; + } + + if (eventPtr->type == NoExpose) { + info->done = 1; + } else if (eventPtr->type == GraphicsExpose) { + rect.x = eventPtr->xgraphicsexpose.x; + rect.y = eventPtr->xgraphicsexpose.y; + rect.width = eventPtr->xgraphicsexpose.width; + rect.height = eventPtr->xgraphicsexpose.height; + XUnionRectWithRegion(&rect, (Region) info->region, + (Region) info->region); + + if (eventPtr->xgraphicsexpose.count == 0) { + info->done = 1; + } + } else if (eventPtr->type == Expose) { + /* + * This case is tricky. This event was already queued before the + * XCopyArea was issued. If this area overlaps the area being copied, + * then some of the copied area may be invalid. The easiest way to + * handle this case is to mark both the original area and the shifted + * area as damaged. + */ + + rect.x = eventPtr->xexpose.x; + rect.y = eventPtr->xexpose.y; + rect.width = eventPtr->xexpose.width; + rect.height = eventPtr->xexpose.height; + XUnionRectWithRegion(&rect, (Region) info->region, + (Region) info->region); + rect.x += info->dx; + rect.y += info->dy; + XUnionRectWithRegion(&rect, (Region) info->region, + (Region) info->region); + } else { + return TK_DEFER_EVENT; + } + return TK_DISCARD_EVENT; +} + +/* + *---------------------------------------------------------------------- + * + * TkpDrawHighlightBorder -- + * + * This function draws a rectangular ring around the outside of a widget + * to indicate that it has received the input focus. + * + * On Unix, 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( + Tk_Window tkwin, + GC fgGC, + GC bgGC, + int highlightWidth, + Drawable drawable) +{ + TkDrawInsetFocusHighlight(tkwin, fgGC, highlightWidth, drawable, 0); +} + +/* + *---------------------------------------------------------------------- + * + * TkpDrawFrame -- + * + * This function draws the rectangular frame area. + * + * Results: + * None. + * + * Side effects: + * Draws inside the tkwin area. + * + *---------------------------------------------------------------------- + */ + +void +TkpDrawFrame( + Tk_Window tkwin, + Tk_3DBorder border, + int highlightWidth, + int borderWidth, + int relief) +{ + Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, highlightWidth, + highlightWidth, Tk_Width(tkwin) - 2*highlightWidth, + Tk_Height(tkwin) - 2*highlightWidth, borderWidth, relief); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixEmbed.c b/tk8.6/unix/tkUnixEmbed.c new file mode 100644 index 0000000..b170ad0 --- /dev/null +++ b/tk8.6/unix/tkUnixEmbed.c @@ -0,0 +1,1185 @@ +/* + * tkUnixEmbed.c -- + * + * This file contains platform-specific functions for UNIX to provide + * basic operations needed for application embedding (where one + * application can use as its main window an internal window from some + * other application). Also includes code to support busy windows. + * + * 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. + */ + +#include "tkUnixInt.h" +#include "tkBusy.h" + +/* + * One of the following structures exists for each container in this + * application. It keeps track of the container window and its associated + * embedded window. + */ + +typedef struct Container { + Window parent; /* X's window id for the parent of the pair + * (the container). */ + Window parentRoot; /* Id for the root window of parent's + * screen. */ + TkWindow *parentPtr; /* Tk's information about the container, or + * NULL if the container isn't in this + * process. */ + Window wrapper; /* X's window id for the wrapper window for + * the embedded window. Starts off as None, + * but gets filled in when the window is + * eventually created. */ + TkWindow *embeddedPtr; /* Tk's information about the embedded window, + * or NULL if the embedded application isn't + * in this process. Note that this is *not* + * the same window as wrapper: wrapper is the + * parent of embeddedPtr. */ + struct Container *nextPtr; /* Next in list of all containers in this + * process. */ +} Container; + +typedef struct ThreadSpecificData { + Container *firstContainerPtr; + /* First in list of all containers managed by + * this process. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + +/* + * Prototypes for static functions defined in this file: + */ + +static void ContainerEventProc(ClientData clientData, + XEvent *eventPtr); +static void EmbeddedEventProc(ClientData clientData, + XEvent *eventPtr); +static int EmbedErrorProc(ClientData clientData, + XErrorEvent *errEventPtr); +static void EmbedFocusProc(ClientData clientData, + XEvent *eventPtr); +static void EmbedGeometryRequest(Container *containerPtr, + int width, int height); +static void EmbedSendConfigure(Container *containerPtr); +static void EmbedStructureProc(ClientData clientData, + XEvent *eventPtr); +static void EmbedWindowDeleted(TkWindow *winPtr); + +/* + *---------------------------------------------------------------------- + * + * TkpUseWindow -- + * + * This function causes a Tk window to use a given X window as its parent + * window, rather than the root window for the screen. It is invoked by + * an embedded application to specify the window in which it is embedded. + * + * Results: + * The return value is normally TCL_OK. If an error occurs (such as + * string not being a valid window spec), then the return value is + * TCL_ERROR and an error message is left in the interp's result if + * interp is non-NULL. + * + * Side effects: + * Changes the colormap and other visual information to match that of the + * parent window given by "string". + * + *---------------------------------------------------------------------- + */ + +int +TkpUseWindow( + Tcl_Interp *interp, /* If not NULL, used for error reporting if + * string is bogus. */ + Tk_Window tkwin, /* Tk window that does not yet have an + * associated X window. */ + const char *string) /* String identifying an X window to use for + * tkwin; must be an integer value. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + TkWindow *usePtr; + int anyError; + Window parent; + Tk_ErrorHandler handler; + Container *containerPtr; + XWindowAttributes parentAtts; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (winPtr->window != None) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "can't modify container after widget is created", -1)); + Tcl_SetErrorCode(interp, "TK", "EMBED", "POST_CREATE", NULL); + return TCL_ERROR; + } + if (TkpScanWindowId(interp, string, &parent) != TCL_OK) { + return TCL_ERROR; + } + + usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, parent); + if (usePtr != NULL && !(usePtr->flags & TK_CONTAINER)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "window \"%s\" doesn't have -container option set", + usePtr->pathName)); + Tcl_SetErrorCode(interp, "TK", "EMBED", "CONTAINER", NULL); + return TCL_ERROR; + } + + /* + * Tk sets the window colormap to the screen default colormap in + * tkWindow.c:AllocWindow. This doesn't work well for embedded windows. So + * we override the colormap and visual settings to be the same as the + * parent window (which is in the container app). + */ + + anyError = 0; + handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, + EmbedErrorProc, &anyError); + if (!XGetWindowAttributes(winPtr->display, parent, &parentAtts)) { + anyError = 1; + } + XSync(winPtr->display, False); + Tk_DeleteErrorHandler(handler); + if (anyError) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "couldn't create child of window \"%s\"", string)); + Tcl_SetErrorCode(interp, "TK", "EMBED", "NO_TARGET", NULL); + } + return TCL_ERROR; + } + Tk_SetWindowVisual(tkwin, parentAtts.visual, parentAtts.depth, + parentAtts.colormap); + + /* + * Create an event handler to clean up the Container structure when tkwin + * is eventually deleted. + */ + + Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc, + winPtr); + + /* + * Save information about the container and the embedded window in a + * Container structure. If there is already an existing Container + * structure, it means that both container and embedded app. are in the + * same process. + */ + + for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL; + containerPtr = containerPtr->nextPtr) { + if (containerPtr->parent == parent) { + winPtr->flags |= TK_BOTH_HALVES; + containerPtr->parentPtr->flags |= TK_BOTH_HALVES; + break; + } + } + if (containerPtr == NULL) { + containerPtr = ckalloc(sizeof(Container)); + containerPtr->parent = parent; + containerPtr->parentRoot = parentAtts.root; + containerPtr->parentPtr = NULL; + containerPtr->wrapper = None; + containerPtr->nextPtr = tsdPtr->firstContainerPtr; + tsdPtr->firstContainerPtr = containerPtr; + } + containerPtr->embeddedPtr = winPtr; + winPtr->flags |= TK_EMBEDDED; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TkpMakeWindow -- + * + * Create an actual window system window object based on the current + * attributes of the specified TkWindow. + * + * Results: + * Returns the handle to the new window, or None on failure. + * + * Side effects: + * Creates a new X window. + * + *---------------------------------------------------------------------- + */ + +Window +TkpMakeWindow( + TkWindow *winPtr, /* Tk's information about the window that is + * to be instantiated. */ + Window parent) /* Window system token for the parent in which + * the window is to be created. */ +{ + Container *containerPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (winPtr->flags & TK_EMBEDDED) { + /* + * This window is embedded. Don't create the new window in the given + * parent; instead, create it as a child of the root window of the + * container's screen. The window will get reparented into a wrapper + * window later. + */ + + for (containerPtr = tsdPtr->firstContainerPtr; ; + containerPtr = containerPtr->nextPtr) { + if (containerPtr == NULL) { + Tcl_Panic("TkMakeWindow couldn't find container for window"); + } + if (containerPtr->embeddedPtr == winPtr) { + break; + } + } + parent = containerPtr->parentRoot; + } + + return XCreateWindow(winPtr->display, parent, winPtr->changes.x, + winPtr->changes.y, (unsigned) winPtr->changes.width, + (unsigned) winPtr->changes.height, + (unsigned) winPtr->changes.border_width, winPtr->depth, + InputOutput, winPtr->visual, winPtr->dirtyAtts, + &winPtr->atts); +} + +/* + *---------------------------------------------------------------------- + * + * TkpMakeContainer -- + * + * This function is called to indicate that a particular window will be a + * container for an embedded application. This changes certain aspects of + * the window's behavior, such as whether it will receive events anymore. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpMakeContainer( + Tk_Window tkwin) /* Token for a window that is about to become + * a container. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + Container *containerPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + /* + * Register the window as a container so that, for example, we can find + * out later if the embedded app. is in the same process. + */ + + Tk_MakeWindowExist(tkwin); + containerPtr = ckalloc(sizeof(Container)); + containerPtr->parent = Tk_WindowId(tkwin); + containerPtr->parentRoot = RootWindowOfScreen(Tk_Screen(tkwin)); + containerPtr->parentPtr = winPtr; + containerPtr->wrapper = None; + containerPtr->embeddedPtr = NULL; + containerPtr->nextPtr = tsdPtr->firstContainerPtr; + tsdPtr->firstContainerPtr = containerPtr; + winPtr->flags |= TK_CONTAINER; + + /* + * Request SubstructureNotify events so that we can find out when the + * embedded application creates its window or attempts to resize it. Also + * watch Configure events on the container so that we can resize the child + * to match. + */ + + winPtr->atts.event_mask |= SubstructureRedirectMask|SubstructureNotifyMask; + XSelectInput(winPtr->display, winPtr->window, winPtr->atts.event_mask); + Tk_CreateEventHandler(tkwin, + SubstructureNotifyMask|SubstructureRedirectMask, + ContainerEventProc, winPtr); + Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbedStructureProc, + containerPtr); + Tk_CreateEventHandler(tkwin, FocusChangeMask, EmbedFocusProc, + containerPtr); +} + +/* + *---------------------------------------------------------------------- + * + * EmbedErrorProc -- + * + * This function is invoked if an error occurs while creating an embedded + * window. + * + * Results: + * Always returns 0 to indicate that the error has been properly handled. + * + * Side effects: + * The integer pointed to by the clientData argument is set to 1. + * + *---------------------------------------------------------------------- + */ + +static int +EmbedErrorProc( + ClientData clientData, /* Points to integer to set. */ + XErrorEvent *errEventPtr) /* Points to information about error (not + * used). */ +{ + int *iPtr = clientData; + + *iPtr = 1; + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * EmbeddedEventProc -- + * + * This function is invoked by the Tk event dispatcher when various + * useful events are received for a window that is embedded in another + * application. + * + * Results: + * None. + * + * Side effects: + * Our internal state gets cleaned up when an embedded window is + * destroyed. + * + *---------------------------------------------------------------------- + */ + +static void +EmbeddedEventProc( + ClientData clientData, /* Token for container window. */ + XEvent *eventPtr) /* ResizeRequest event. */ +{ + TkWindow *winPtr = clientData; + + if (eventPtr->type == DestroyNotify) { + EmbedWindowDeleted(winPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * ContainerEventProc -- + * + * This function is invoked by the Tk event dispatcher when various + * useful events are received for the children of a container window. It + * forwards relevant information, such as geometry requests, from the + * events into the container's application. + * + * Results: + * None. + * + * Side effects: + * Depends on the event. For example, when ConfigureRequest events occur, + * geometry information gets set for the container window. + * + *---------------------------------------------------------------------- + */ + +static void +ContainerEventProc( + ClientData clientData, /* Token for container window. */ + XEvent *eventPtr) /* ResizeRequest event. */ +{ + TkWindow *winPtr = clientData; + Container *containerPtr; + Tk_ErrorHandler errHandler; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + /* + * Ignore any X protocol errors that happen in this function (almost any + * operation could fail, for example, if the embedded application has + * deleted its window). + */ + + errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, + -1, -1, NULL, NULL); + + /* + * Find the Container structure associated with the parent window. + */ + + for (containerPtr = tsdPtr->firstContainerPtr; + containerPtr->parent != eventPtr->xmaprequest.parent; + containerPtr = containerPtr->nextPtr) { + if (containerPtr == NULL) { + Tcl_Panic("ContainerEventProc couldn't find Container record"); + } + } + + if (eventPtr->type == CreateNotify) { + /* + * A new child window has been created in the container. Record its id + * in the Container structure (if more than one child is created, just + * remember the last one and ignore the earlier ones). Also set the + * child's size to match the container. + */ + + containerPtr->wrapper = eventPtr->xcreatewindow.window; + XMoveResizeWindow(eventPtr->xcreatewindow.display, + containerPtr->wrapper, 0, 0, + (unsigned) Tk_Width((Tk_Window) containerPtr->parentPtr), + (unsigned) Tk_Height((Tk_Window) containerPtr->parentPtr)); + } else if (eventPtr->type == ConfigureRequest) { + if ((eventPtr->xconfigurerequest.x != 0) + || (eventPtr->xconfigurerequest.y != 0)) { + /* + * The embedded application is trying to move itself, which isn't + * legal. At this point, the window hasn't actually moved, but we + * need to send it a ConfigureNotify event to let it know that its + * request has been denied. If the embedded application was also + * trying to resize itself, a ConfigureNotify will be sent by the + * geometry management code below, so we don't need to do + * anything. Otherwise, generate a synthetic event. + */ + + if ((eventPtr->xconfigurerequest.width == winPtr->changes.width) + && (eventPtr->xconfigurerequest.height + == winPtr->changes.height)) { + EmbedSendConfigure(containerPtr); + } + } + EmbedGeometryRequest(containerPtr, + eventPtr->xconfigurerequest.width, + eventPtr->xconfigurerequest.height); + } else if (eventPtr->type == MapRequest) { + /* + * The embedded application's map request was ignored and simply + * passed on to us, so we have to map the window for it to appear on + * the screen. + */ + + XMapWindow(eventPtr->xmaprequest.display, + eventPtr->xmaprequest.window); + } else if (eventPtr->type == DestroyNotify) { + /* + * The embedded application is gone. Destroy the container window. + */ + + Tk_DestroyWindow((Tk_Window) winPtr); + } + Tk_DeleteErrorHandler(errHandler); +} + +/* + *---------------------------------------------------------------------- + * + * EmbedStructureProc -- + * + * This function is invoked by the Tk event dispatcher when a container + * window owned by this application gets resized (and also at several + * other times that we don't care about). This function reflects the size + * change in the embedded window that corresponds to the container. + * + * Results: + * None. + * + * Side effects: + * The embedded window gets resized to match the container. + * + *---------------------------------------------------------------------- + */ + +static void +EmbedStructureProc( + ClientData clientData, /* Token for container window. */ + XEvent *eventPtr) /* ResizeRequest event. */ +{ + Container *containerPtr = clientData; + Tk_ErrorHandler errHandler; + + if (eventPtr->type == ConfigureNotify) { + if (containerPtr->wrapper != None) { + /* + * Ignore errors, since the embedded application could have + * deleted its window. + */ + + errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, + -1, -1, NULL, NULL); + XMoveResizeWindow(eventPtr->xconfigure.display, + containerPtr->wrapper, 0, 0, + (unsigned) Tk_Width((Tk_Window) containerPtr->parentPtr), + (unsigned) Tk_Height((Tk_Window) containerPtr->parentPtr)); + Tk_DeleteErrorHandler(errHandler); + } + } else if (eventPtr->type == DestroyNotify) { + EmbedWindowDeleted(containerPtr->parentPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * EmbedFocusProc -- + * + * This function is invoked by the Tk event dispatcher when FocusIn and + * FocusOut events occur for a container window owned by this + * application. It is responsible for moving the focus back and forth + * between a container application and an embedded application. + * + * Results: + * None. + * + * Side effects: + * The X focus may change. + * + *---------------------------------------------------------------------- + */ + +static void +EmbedFocusProc( + ClientData clientData, /* Token for container window. */ + XEvent *eventPtr) /* ResizeRequest event. */ +{ + Container *containerPtr = clientData; + Tk_ErrorHandler errHandler; + Display *display; + + display = Tk_Display(containerPtr->parentPtr); + if (eventPtr->type == FocusIn) { + /* + * The focus just arrived at the container. Change the X focus to move + * it to the embedded application, if there is one. Ignore X errors + * that occur during this operation (it's possible that the new focus + * window isn't mapped). + */ + + if (containerPtr->wrapper != None) { + errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, + -1, -1, NULL, NULL); + XSetInputFocus(display, containerPtr->wrapper, RevertToParent, + CurrentTime); + Tk_DeleteErrorHandler(errHandler); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * EmbedGeometryRequest -- + * + * This function is invoked when an embedded application requests a + * particular size. It processes the request (which may or may not + * actually honor the request) and reflects the results back to the + * embedded application. + * + * Results: + * None. + * + * Side effects: + * If we deny the child's size change request, a Configure event is + * synthesized to let the child know how big it ought to be. Events get + * processed while we're waiting for the geometry managers to do their + * thing. + * + *---------------------------------------------------------------------- + */ + +static void +EmbedGeometryRequest( + Container *containerPtr, /* Information about the embedding. */ + int width, int height) /* Size that the child has requested. */ +{ + TkWindow *winPtr = containerPtr->parentPtr; + + /* + * Forward the requested size into our geometry management hierarchy via + * the container window. We need to send a Configure event back to the + * embedded application if we decide not to honor its request; to make + * this happen, process all idle event handlers synchronously here (so + * that the geometry managers have had a chance to do whatever they want + * to do), and if the window's size didn't change then generate a + * configure event. + */ + + Tk_GeometryRequest((Tk_Window) winPtr, width, height); + while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) { + /* Empty loop body. */ + } + if ((winPtr->changes.width != width) + || (winPtr->changes.height != height)) { + EmbedSendConfigure(containerPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * EmbedSendConfigure -- + * + * This function synthesizes a ConfigureNotify event to notify an + * embedded application of its current size and location. This function + * is called when the embedded application made a geometry request that + * we did not grant, so that the embedded application knows that its + * geometry didn't change after all. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +EmbedSendConfigure( + Container *containerPtr) /* Information about the embedding. */ +{ + TkWindow *winPtr = containerPtr->parentPtr; + XEvent event; + + event.xconfigure.type = ConfigureNotify; + event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display); + event.xconfigure.send_event = True; + event.xconfigure.display = winPtr->display; + event.xconfigure.event = containerPtr->wrapper; + event.xconfigure.window = containerPtr->wrapper; + event.xconfigure.x = 0; + event.xconfigure.y = 0; + event.xconfigure.width = winPtr->changes.width; + event.xconfigure.height = winPtr->changes.height; + event.xconfigure.above = None; + event.xconfigure.override_redirect = False; + + /* + * Note: when sending the event below, the ButtonPressMask causes the + * event to be sent only to applications that have selected for + * ButtonPress events, which should be just the embedded application. + */ + + XSendEvent(winPtr->display, containerPtr->wrapper, False, + 0, &event); + + /* + * The following needs to be done if the embedded window is not in the + * same application as the container window. + */ + + if (containerPtr->embeddedPtr == NULL) { + XMoveResizeWindow(winPtr->display, containerPtr->wrapper, 0, 0, + (unsigned) winPtr->changes.width, + (unsigned) winPtr->changes.height); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetOtherWindow -- + * + * If both the container and embedded window are in the same process, + * this function will return either one, given the other. + * + * Results: + * If winPtr is a container, the return value is the token for the + * embedded window, and vice versa. If the "other" window isn't in this + * process, NULL is returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkWindow * +TkpGetOtherWindow( + TkWindow *winPtr) /* Tk's structure for a container or embedded + * window. */ +{ + Container *containerPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + for (containerPtr = tsdPtr->firstContainerPtr; + containerPtr != NULL; + containerPtr = containerPtr->nextPtr) { + if (containerPtr->embeddedPtr == winPtr) { + return containerPtr->parentPtr; + } else if (containerPtr->parentPtr == winPtr) { + return containerPtr->embeddedPtr; + } + } + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * TkpRedirectKeyEvent -- + * + * This function is invoked when a key press or release event arrives for + * an application that does not believe it owns the input focus. This can + * happen because of embedding; for example, X can send an event to an + * embedded application when the real focus window is in the container + * application and is an ancestor of the container. This function's job + * is to forward the event back to the application where it really + * belongs. + * + * Results: + * None. + * + * Side effects: + * The event may get sent to a different application. + * + *---------------------------------------------------------------------- + */ + +void +TkpRedirectKeyEvent( + TkWindow *winPtr, /* Window to which the event was originally + * reported. */ + XEvent *eventPtr) /* X event to redirect (should be KeyPress or + * KeyRelease). */ +{ + Container *containerPtr; + Window saved; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + /* + * First, find the top-level window corresponding to winPtr. + */ + + while (1) { + if (winPtr == NULL) { + /* + * This window is being deleted. This is too confusing a case to + * handle so discard the event. + */ + + return; + } + if (winPtr->flags & TK_TOP_HIERARCHY) { + break; + } + winPtr = winPtr->parentPtr; + } + + if (winPtr->flags & TK_EMBEDDED) { + /* + * This application is embedded. If we got a key event without + * officially having the focus, it means that the focus is really in + * the container, but the mouse was over the embedded application. + * Send the event back to the container. + */ + + for (containerPtr = tsdPtr->firstContainerPtr; + containerPtr->embeddedPtr != winPtr; + containerPtr = containerPtr->nextPtr) { + /* Empty loop body. */ + } + saved = eventPtr->xkey.window; + eventPtr->xkey.window = containerPtr->parent; + XSendEvent(eventPtr->xkey.display, eventPtr->xkey.window, False, + KeyPressMask|KeyReleaseMask, eventPtr); + eventPtr->xkey.window = saved; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpClaimFocus -- + * + * This function is invoked when someone asks or the input focus to be + * put on a window in an embedded application, but the application + * doesn't currently have the focus. It requests the input focus from the + * container application. + * + * Results: + * None. + * + * Side effects: + * The input focus may change. + * + *---------------------------------------------------------------------- + */ + +void +TkpClaimFocus( + TkWindow *topLevelPtr, /* Top-level window containing desired focus + * window; should be embedded. */ + int force) /* One means that the container should claim + * the focus if it doesn't currently have + * it. */ +{ + XEvent event; + Container *containerPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (!(topLevelPtr->flags & TK_EMBEDDED)) { + return; + } + + for (containerPtr = tsdPtr->firstContainerPtr; + containerPtr->embeddedPtr != topLevelPtr; + containerPtr = containerPtr->nextPtr) { + /* Empty loop body. */ + } + + event.xfocus.type = FocusIn; + event.xfocus.serial = LastKnownRequestProcessed(topLevelPtr->display); + event.xfocus.send_event = 1; + event.xfocus.display = topLevelPtr->display; + event.xfocus.window = containerPtr->parent; + event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS; + event.xfocus.detail = force; + XSendEvent(event.xfocus.display, event.xfocus.window, False, 0, &event); +} + +/* + *---------------------------------------------------------------------- + * + * TkpTestembedCmd -- + * + * This function implements the "testembed" command. It returns some or + * all of the information in the list pointed to by firstContainerPtr. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkpTestembedCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ +{ + int all; + Container *containerPtr; + Tcl_DString dString; + char buffer[50]; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "all") == 0)) { + all = 1; + } else { + all = 0; + } + Tcl_DStringInit(&dString); + for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL; + containerPtr = containerPtr->nextPtr) { + Tcl_DStringStartSublist(&dString); + if (containerPtr->parent == None) { + Tcl_DStringAppendElement(&dString, ""); + } else if (all) { + sprintf(buffer, "0x%x", (int) containerPtr->parent); + Tcl_DStringAppendElement(&dString, buffer); + } else { + Tcl_DStringAppendElement(&dString, "XXX"); + } + if (containerPtr->parentPtr == NULL) { + Tcl_DStringAppendElement(&dString, ""); + } else { + Tcl_DStringAppendElement(&dString, + containerPtr->parentPtr->pathName); + } + if (containerPtr->wrapper == None) { + Tcl_DStringAppendElement(&dString, ""); + } else if (all) { + sprintf(buffer, "0x%x", (int) containerPtr->wrapper); + Tcl_DStringAppendElement(&dString, buffer); + } else { + Tcl_DStringAppendElement(&dString, "XXX"); + } + if (containerPtr->embeddedPtr == NULL) { + Tcl_DStringAppendElement(&dString, ""); + } else { + Tcl_DStringAppendElement(&dString, + containerPtr->embeddedPtr->pathName); + } + Tcl_DStringEndSublist(&dString); + } + Tcl_DStringResult(interp, &dString); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * EmbedWindowDeleted -- + * + * This function is invoked when a window involved in embedding (as + * either the container or the embedded application) is destroyed. It + * cleans up the Container structure for the window. + * + * Results: + * None. + * + * Side effects: + * A Container structure may be freed. + * + *---------------------------------------------------------------------- + */ + +static void +EmbedWindowDeleted( + TkWindow *winPtr) /* Tk's information about window that was + * deleted. */ +{ + Container *containerPtr, *prevPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + /* + * Find the Container structure for this window work. Delete the + * information about the embedded application and free the container's + * record. + */ + + prevPtr = NULL; + containerPtr = tsdPtr->firstContainerPtr; + while (1) { + if (containerPtr->embeddedPtr == winPtr) { + containerPtr->wrapper = None; + containerPtr->embeddedPtr = NULL; + break; + } + if (containerPtr->parentPtr == winPtr) { + containerPtr->parentPtr = NULL; + break; + } + prevPtr = containerPtr; + containerPtr = containerPtr->nextPtr; + } + if ((containerPtr->embeddedPtr == NULL) + && (containerPtr->parentPtr == NULL)) { + if (prevPtr == NULL) { + tsdPtr->firstContainerPtr = containerPtr->nextPtr; + } else { + prevPtr->nextPtr = containerPtr->nextPtr; + } + ckfree(containerPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkUnixContainerId -- + * + * Given an embedded window, this function returns the X window + * identifier for the associated container window. + * + * Results: + * The return value is the X window identifier for winPtr's container + * window. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Window +TkUnixContainerId( + TkWindow *winPtr) /* Tk's structure for an embedded window. */ +{ + Container *containerPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + for (containerPtr = tsdPtr->firstContainerPtr; + containerPtr != NULL; containerPtr = containerPtr->nextPtr) { + if (containerPtr->embeddedPtr == winPtr) { + return containerPtr->parent; + } + } + Tcl_Panic("TkUnixContainerId couldn't find window"); + return None; +} + +/* + *---------------------------------------------------------------------- + * + * TkpShowBusyWindow -- + * + * Makes a busy window "appear". + * + * Results: + * None. + * + * Side effects: + * Arranges for the busy window to start intercepting events and the + * cursor to change to the configured "hey, I'm busy!" setting. + * + *---------------------------------------------------------------------- + */ + +void +TkpShowBusyWindow( + TkBusy busy) +{ + Busy *busyPtr = (Busy *) busy; + + if (busyPtr->tkBusy != NULL) { + Tk_MapWindow(busyPtr->tkBusy); + + /* + * Always raise the busy window just in case new sibling windows have + * been created in the meantime. Can't use Tk_RestackWindow because it + * doesn't work under Win32. + */ + + XRaiseWindow(Tk_Display(busyPtr->tkBusy), + Tk_WindowId(busyPtr->tkBusy)); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpHideBusyWindow -- + * + * Makes a busy window "disappear". + * + * Results: + * None. + * + * Side effects: + * Arranges for the busy window to stop intercepting events, and the + * cursor to change back to its normal setting. + * + *---------------------------------------------------------------------- + */ + +void +TkpHideBusyWindow( + TkBusy busy) +{ + Busy *busyPtr = (Busy *) busy; + + if (busyPtr->tkBusy != NULL) { + Tk_UnmapWindow(busyPtr->tkBusy); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpMakeTransparentWindowExist -- + * + * Construct the platform-specific resources for a transparent window. + * + * Results: + * None. + * + * Side effects: + * Moves the specified window in the stacking order. + * + *---------------------------------------------------------------------- + */ + +void +TkpMakeTransparentWindowExist( + Tk_Window tkwin, /* Token for window. */ + Window parent) /* Parent window. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + long int mask = CWDontPropagate | CWEventMask; + + /* + * Ignore the important events while the window is mapped. + */ + +#define USER_EVENTS \ + (EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask | \ + ButtonPressMask | ButtonReleaseMask | PointerMotionMask) +#define PROP_EVENTS \ + (KeyPressMask | KeyReleaseMask | ButtonPressMask | \ + ButtonReleaseMask | PointerMotionMask) + + winPtr->atts.do_not_propagate_mask = PROP_EVENTS; + winPtr->atts.event_mask = USER_EVENTS; + winPtr->changes.border_width = 0; + winPtr->depth = 0; + + winPtr->window = XCreateWindow(winPtr->display, parent, + winPtr->changes.x, winPtr->changes.y, + (unsigned) winPtr->changes.width, /* width */ + (unsigned) winPtr->changes.height, /* height */ + (unsigned) winPtr->changes.border_width, /* border_width */ + winPtr->depth, InputOnly, winPtr->visual, mask, &winPtr->atts); +} + +/* + *---------------------------------------------------------------------- + * + * TkpCreateBusy -- + * + * Construct the platform-specific parts of a busy window. Note that this + * postpones the actual creation of the window resource until later. + * + * Results: + * None. + * + * Side effects: + * Sets up part of the busy window structure. + * + *---------------------------------------------------------------------- + */ + +void +TkpCreateBusy( + Tk_FakeWin *winPtr, + Tk_Window tkRef, + Window *parentPtr, + Tk_Window tkParent, + TkBusy busy) +{ + Window root, parent, *dummy; + unsigned int count; + + if (winPtr->flags & TK_REPARENTED) { + /* + * This works around a bug in the implementation of menubars for + * non-MacIntosh window systems (Win32 and X11). Tk doesn't reset the + * pointers to the parent window when the menu is reparented (since + * winPtr->parentPtr points to the wrong window). We get around this + * by determining the parent via the native API calls. + */ + + if (XQueryTree(Tk_Display(tkRef), Tk_WindowId(tkRef), &root, + &parent, &dummy, &count) > 0) { + XFree(dummy); + *parentPtr = parent; + } else { + *parentPtr = None; + } + } else { + *parentPtr = Tk_WindowId(tkParent); + } +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixEvent.c b/tk8.6/unix/tkUnixEvent.c new file mode 100644 index 0000000..111d430 --- /dev/null +++ b/tk8.6/unix/tkUnixEvent.c @@ -0,0 +1,819 @@ +/* + * tkUnixEvent.c -- + * + * This file implements an event source for X displays for the UNIX + * version of Tk. + * + * 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. + */ + +#include "tkUnixInt.h" +#include <signal.h> +#ifdef HAVE_XKBKEYCODETOKEYSYM +# include <X11/XKBlib.h> +#else +# define XkbOpenDisplay(D,V,E,M,m,R) ((V),(E),(M),(m),(R),(NULL)) +#endif + +/* + * The following static indicates whether this module has been initialized in + * the current thread. + */ + +typedef struct ThreadSpecificData { + int initialized; +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + +/* + * Prototypes for functions that are referenced only in this file: + */ + +static void DisplayCheckProc(ClientData clientData, int flags); +static void DisplayExitHandler(ClientData clientData); +static void DisplayFileProc(ClientData clientData, int flags); +static void DisplaySetupProc(ClientData clientData, int flags); +static void TransferXEventsToTcl(Display *display); +#ifdef TK_USE_INPUT_METHODS +static void InstantiateIMCallback(Display *, XPointer client_data, XPointer call_data); +static void DestroyIMCallback(XIM im, XPointer client_data, XPointer call_data); +static void OpenIM(TkDisplay *dispPtr); +#endif + +/* + *---------------------------------------------------------------------- + * + * TkCreateXEventSource -- + * + * This function is called during Tk initialization to create the event + * source for X Window events. + * + * Results: + * None. + * + * Side effects: + * A new event source is created. + * + *---------------------------------------------------------------------- + */ + +void +TkCreateXEventSource(void) +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (!tsdPtr->initialized) { + tsdPtr->initialized = 1; + Tcl_CreateEventSource(DisplaySetupProc, DisplayCheckProc, NULL); + TkCreateExitHandler(DisplayExitHandler, NULL); + } +} + +/* + *---------------------------------------------------------------------- + * + * DisplayExitHandler -- + * + * This function is called during finalization to clean up the display + * module. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +DisplayExitHandler( + ClientData clientData) /* Not used. */ +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + Tcl_DeleteEventSource(DisplaySetupProc, DisplayCheckProc, NULL); + tsdPtr->initialized = 0; +} + +/* + *---------------------------------------------------------------------- + * + * TkpOpenDisplay -- + * + * Allocates a new TkDisplay, opens the X display, and establishes the + * file handler for the connection. + * + * Results: + * A pointer to a Tk display structure. + * + * Side effects: + * Opens a display. + * + *---------------------------------------------------------------------- + */ + +TkDisplay * +TkpOpenDisplay( + const char *displayNameStr) +{ + TkDisplay *dispPtr; + Display *display; + int event = 0; + int error = 0; + int major = 1; + int minor = 0; + int reason = 0; + unsigned int use_xkb = 0; + /* Disabled, until we have a better test. See [Bug 3613668] */ +#if 0 && defined(XKEYCODETOKEYSYM_IS_DEPRECATED) && defined(TCL_THREADS) + static int xinited = 0; + static Tcl_Mutex xinitMutex = NULL; + + if (!xinited) { + Tcl_MutexLock(&xinitMutex); + if (!xinited) { + /* Necessary for threaded apps, of no consequence otherwise */ + /* need only be called once, but must be called before *any* */ + /* Xlib call is made. If xinitMutex is still NULL after the */ + /* Tcl_MutexLock call, Tcl was compiled without threads so */ + /* we cannot use XInitThreads() either. */ + if (xinitMutex != NULL){ + XInitThreads(); + } + xinited = 1; + } + Tcl_MutexUnlock(&xinitMutex); + } +#endif + + /* + ** Bug [3607830]: Before using Xkb, it must be initialized and confirmed + ** that the serve supports it. The XkbOpenDisplay call + ** will perform this check and return NULL if the extension + ** is not supported. + ** + ** Work around un-const-ified Xkb headers using (char *) cast. + */ + display = XkbOpenDisplay((char *)displayNameStr, &event, &error, &major, + &minor, &reason); + + if (display == NULL) { + /*fprintf(stderr,"event=%d error=%d major=%d minor=%d reason=%d\nDisabling xkb\n", + event, error, major, minor, reason);*/ + display = XOpenDisplay(displayNameStr); + } else { + use_xkb = TK_DISPLAY_USE_XKB; + /*fprintf(stderr, "Using xkb %d.%d\n", major, minor);*/ + } + + if (display == NULL) { + return NULL; + } + dispPtr = ckalloc(sizeof(TkDisplay)); + memset(dispPtr, 0, sizeof(TkDisplay)); + dispPtr->display = display; + dispPtr->flags |= use_xkb; +#ifdef TK_USE_INPUT_METHODS + OpenIM(dispPtr); + XRegisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL, + InstantiateIMCallback, (XPointer) dispPtr); +#endif + Tcl_CreateFileHandler(ConnectionNumber(display), TCL_READABLE, + DisplayFileProc, dispPtr); + return dispPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkpCloseDisplay -- + * + * Cancels notifier callbacks and closes a display. + * + * Results: + * None. + * + * Side effects: + * Deallocates the displayPtr and unix-specific resources. + * + *---------------------------------------------------------------------- + */ + +void +TkpCloseDisplay( + TkDisplay *dispPtr) +{ + TkSendCleanup(dispPtr); + + TkWmCleanup(dispPtr); + +#ifdef TK_USE_INPUT_METHODS + if (dispPtr->inputXfs) { + XFreeFontSet(dispPtr->display, dispPtr->inputXfs); + } + if (dispPtr->inputMethod) { + XCloseIM(dispPtr->inputMethod); + } +#endif + + if (dispPtr->display != 0) { + Tcl_DeleteFileHandler(ConnectionNumber(dispPtr->display)); + (void) XSync(dispPtr->display, False); + (void) XCloseDisplay(dispPtr->display); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkClipCleanup -- + * + * This function is called to cleanup resources associated with claiming + * clipboard ownership and for receiving selection get results. This + * function is called in tkWindow.c. This has to be called by the display + * cleanup function because we still need the access display elements. + * + * Results: + * None. + * + * Side effects: + * Resources are freed - the clipboard may no longer be used. + * + *---------------------------------------------------------------------- + */ + +void +TkClipCleanup( + TkDisplay *dispPtr) /* Display associated with clipboard */ +{ + if (dispPtr->clipWindow != NULL) { + Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom, + dispPtr->applicationAtom); + Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom, + dispPtr->windowAtom); + + Tk_DestroyWindow(dispPtr->clipWindow); + Tcl_Release(dispPtr->clipWindow); + dispPtr->clipWindow = NULL; + } +} + +/* + *---------------------------------------------------------------------- + * + * DisplaySetupProc -- + * + * This function implements the setup part of the UNIX X display event + * source. It is invoked by Tcl_DoOneEvent before entering the notifier + * to check for events on all displays. + * + * Results: + * None. + * + * Side effects: + * If data is queued on a display inside Xlib, then the maximum block + * time will be set to 0 to ensure that the notifier returns control to + * Tcl even if there is no more data on the X connection. + * + *---------------------------------------------------------------------- + */ + +static void +DisplaySetupProc( + ClientData clientData, /* Not used. */ + int flags) +{ + TkDisplay *dispPtr; + static Tcl_Time blockTime = { 0, 0 }; + + if (!(flags & TCL_WINDOW_EVENTS)) { + return; + } + + for (dispPtr = TkGetDisplayList(); dispPtr != NULL; + dispPtr = dispPtr->nextPtr) { + /* + * Flush the display. If data is pending on the X queue, set the block + * time to zero. This ensures that we won't block in the notifier if + * there is data in the X queue, but not on the server socket. + */ + + XFlush(dispPtr->display); + if (QLength(dispPtr->display) > 0) { + Tcl_SetMaxBlockTime(&blockTime); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TransferXEventsToTcl -- + * + * Transfer events from the X event queue to the Tk event queue. + * + * Results: + * None. + * + * Side effects: + * Moves queued X events onto the Tcl event queue. + * + *---------------------------------------------------------------------- + */ + +static void +TransferXEventsToTcl( + Display *display) +{ + union { + int type; + XEvent x; + TkKeyEvent k; +#ifdef GenericEvent + xGenericEvent xge; +#endif + } event; + Window w; + TkDisplay *dispPtr = NULL; + + /* + * Transfer events from the X event queue to the Tk event queue after XIM + * event filtering. KeyPress and KeyRelease events need special treatment + * so that they get directed according to Tk's focus rules during XIM + * handling. Theoretically they can go to the wrong place still (if + * there's a focus change in the queue) but if we push the handling off + * until Tk_HandleEvent then many input methods actually cease to work + * correctly. Most of the time, Tk processes its event queue fast enough + * for this to not be an issue anyway. [Bug 1924761] + */ + + while (QLength(display) > 0) { + XNextEvent(display, &event.x); +#ifdef GenericEvent + if (event.type == GenericEvent) { + Tcl_Panic("Wild GenericEvent; panic! (extension=%d,evtype=%d)", + event.xge.extension, event.xge.evtype); + } +#endif + w = None; + if (event.type == KeyPress || event.type == KeyRelease) { + for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) { + if (dispPtr == NULL) { + break; + } else if (dispPtr->display == event.x.xany.display) { + if (dispPtr->focusPtr != NULL) { + w = dispPtr->focusPtr->window; + } + break; + } + } + } + if (XFilterEvent(&event.x, w)) { + continue; + } + if (event.type == KeyPress || event.type == KeyRelease) { + event.k.charValuePtr = NULL; + event.k.charValueLen = 0; + event.k.keysym = NoSymbol; + + /* + * Force the calling of the input method engine now. The results + * from it will be cached in the event so that they don't get lost + * (to a race condition with other XIM-handled key events) between + * entering the event queue and getting serviced. [Bug 1924761] + */ + +#ifdef TK_USE_INPUT_METHODS + if (event.type == KeyPress && dispPtr && + (dispPtr->flags & TK_DISPLAY_USE_IM)) { + if (dispPtr->focusPtr && dispPtr->focusPtr->inputContext) { + Tcl_DString ds; + + Tcl_DStringInit(&ds); + (void) TkpGetString(dispPtr->focusPtr, &event.x, &ds); + Tcl_DStringFree(&ds); + } + } +#endif + } + Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL); + } +} + +/* + *---------------------------------------------------------------------- + * + * DisplayCheckProc -- + * + * This function checks for events sitting in the X event queue. + * + * Results: + * None. + * + * Side effects: + * Moves queued events onto the Tcl event queue. + * + *---------------------------------------------------------------------- + */ + +static void +DisplayCheckProc( + ClientData clientData, /* Not used. */ + int flags) +{ + TkDisplay *dispPtr; + + if (!(flags & TCL_WINDOW_EVENTS)) { + return; + } + + for (dispPtr = TkGetDisplayList(); dispPtr != NULL; + dispPtr = dispPtr->nextPtr) { + XFlush(dispPtr->display); + TransferXEventsToTcl(dispPtr->display); + } +} + +/* + *---------------------------------------------------------------------- + * + * DisplayFileProc -- + * + * This function implements the file handler for the X connection. + * + * Results: + * None. + * + * Side effects: + * Makes entries on the Tcl event queue for all the events available from + * all the displays. + * + *---------------------------------------------------------------------- + */ + +static void +DisplayFileProc( + ClientData clientData, /* The display pointer. */ + int flags) /* Should be TCL_READABLE. */ +{ + TkDisplay *dispPtr = (TkDisplay *) clientData; + Display *display = dispPtr->display; + int numFound; + + XFlush(display); + numFound = XEventsQueued(display, QueuedAfterReading); + if (numFound == 0) { + /* + * Things are very tricky if there aren't any events readable at this + * point (after all, there was supposedly data available on the + * connection). A couple of things could have occurred: + * + * One possibility is that there were only error events in the input + * from the server. If this happens, we should return (we don't want + * to go to sleep in XNextEvent below, since this would block out + * other sources of input to the process). + * + * Another possibility is that our connection to the server has been + * closed. This will not necessarily be detected in XEventsQueued (!!) + * so if we just return then there will be an infinite loop. To detect + * such an error, generate a NoOp protocol request to exercise the + * connection to the server, then return. However, must disable + * SIGPIPE while sending the request, or else the process will die + * from the signal and won't invoke the X error function to print a + * nice (?!) message. + */ + + void (*oldHandler)(); + + oldHandler = (void (*)()) signal(SIGPIPE, SIG_IGN); + XNoOp(display); + XFlush(display); + (void) signal(SIGPIPE, oldHandler); + } + + TransferXEventsToTcl(display); +} + +/* + *---------------------------------------------------------------------- + * + * TkUnixDoOneXEvent -- + * + * This routine waits for an X event to be processed or for a timeout to + * occur. The timeout is specified as an absolute time. This routine is + * called when Tk needs to wait for a particular X event without letting + * arbitrary events be processed. The caller will typically call + * Tk_RestrictEvents to set up an event filter before calling this + * routine. This routine will service at most one event per invocation. + * + * Results: + * Returns 0 if the timeout has expired, otherwise returns 1. + * + * Side effects: + * Can invoke arbitrary Tcl scripts. + * + *---------------------------------------------------------------------- + */ + +int +TkUnixDoOneXEvent( + Tcl_Time *timePtr) /* Specifies the absolute time when the call + * should time out. */ +{ + TkDisplay *dispPtr; + static fd_mask readMask[MASK_SIZE]; + struct timeval blockTime, *timeoutPtr; + Tcl_Time now; + int fd, index, numFound, numFdBits = 0; + fd_mask bit, *readMaskPtr = readMask; + + /* + * Look for queued events first. + */ + + if (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) { + return 1; + } + + /* + * Compute the next block time and check to see if we have timed out. Note + * that HP-UX defines tv_sec to be unsigned so we have to be careful in + * our arithmetic. + */ + + if (timePtr) { + Tcl_GetTime(&now); + blockTime.tv_sec = timePtr->sec; + blockTime.tv_usec = timePtr->usec - now.usec; + if (blockTime.tv_usec < 0) { + now.sec += 1; + blockTime.tv_usec += 1000000; + } + if (blockTime.tv_sec < now.sec) { + blockTime.tv_sec = 0; + blockTime.tv_usec = 0; + } else { + blockTime.tv_sec -= now.sec; + } + timeoutPtr = &blockTime; + } else { + timeoutPtr = NULL; + } + + /* + * Set up the select mask for all of the displays. If a display has data + * pending, then we want to poll instead of blocking. + */ + + memset(readMask, 0, MASK_SIZE*sizeof(fd_mask)); + for (dispPtr = TkGetDisplayList(); dispPtr != NULL; + dispPtr = dispPtr->nextPtr) { + XFlush(dispPtr->display); + if (QLength(dispPtr->display) > 0) { + blockTime.tv_sec = 0; + blockTime.tv_usec = 0; + } + fd = ConnectionNumber(dispPtr->display); + index = fd/(NBBY*sizeof(fd_mask)); + bit = ((fd_mask)1) << (fd%(NBBY*sizeof(fd_mask))); + readMask[index] |= bit; + if (numFdBits <= fd) { + numFdBits = fd+1; + } + } + + numFound = select(numFdBits, (SELECT_MASK *) readMaskPtr, NULL, NULL, + timeoutPtr); + if (numFound <= 0) { + /* + * Some systems don't clear the masks after an error, so we have to do + * it here. + */ + + memset(readMask, 0, MASK_SIZE*sizeof(fd_mask)); + } + + /* + * Process any new events on the display connections. + */ + + for (dispPtr = TkGetDisplayList(); dispPtr != NULL; + dispPtr = dispPtr->nextPtr) { + fd = ConnectionNumber(dispPtr->display); + index = fd/(NBBY*sizeof(fd_mask)); + bit = ((fd_mask)1) << (fd%(NBBY*sizeof(fd_mask))); + if ((readMask[index] & bit) || (QLength(dispPtr->display) > 0)) { + DisplayFileProc(dispPtr, TCL_READABLE); + } + } + if (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) { + return 1; + } + + /* + * Check to see if we timed out. + */ + + if (timePtr) { + Tcl_GetTime(&now); + if ((now.sec > timePtr->sec) || ((now.sec == timePtr->sec) + && (now.usec > timePtr->usec))) { + return 0; + } + } + + /* + * We had an event but we did not generate a Tcl event from it. Behave as + * though we dealt with it. (JYL&SS) + */ + + return 1; +} + +/* + *---------------------------------------------------------------------- + * + * TkpSync -- + * + * This routine ensures that all pending X requests have been seen by the + * server, and that any pending X events have been moved onto the Tk + * event queue. + * + * Results: + * None. + * + * Side effects: + * Places new events on the Tk event queue. + * + *---------------------------------------------------------------------- + */ + +void +TkpSync( + Display *display) /* Display to sync. */ +{ + XSync(display, False); + + /* + * Transfer events from the X event queue to the Tk event queue. + */ + + TransferXEventsToTcl(display); +} +#ifdef TK_USE_INPUT_METHODS + +static void +InstantiateIMCallback( + Display *display, + XPointer client_data, + XPointer call_data) +{ + TkDisplay *dispPtr; + + dispPtr = (TkDisplay *) client_data; + OpenIM(dispPtr); + XUnregisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL, + InstantiateIMCallback, (XPointer) dispPtr); +} + +static void +DestroyIMCallback( + XIM im, + XPointer client_data, + XPointer call_data) +{ + TkDisplay *dispPtr; + + dispPtr = (TkDisplay *) client_data; + dispPtr->inputMethod = NULL; + ++dispPtr->ximGeneration; + XRegisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL, + InstantiateIMCallback, (XPointer) dispPtr); +} + +/* + *-------------------------------------------------------------- + * + * OpenIM -- + * + * Tries to open an X input method associated with the given display. + * + * Results: + * Stores the input method in dispPtr->inputMethod; if there isn't a + * suitable input method, then NULL is stored in dispPtr->inputMethod. + * + * Side effects: + * An input method gets opened. + * + *-------------------------------------------------------------- + */ + +static void +OpenIM( + TkDisplay *dispPtr) /* Tk's structure for the display. */ +{ + int i; + XIMStyles *stylePtr; + XIMStyle bestStyle = 0; + + if (XSetLocaleModifiers("") == NULL) { + return; + } + + ++dispPtr->ximGeneration; + dispPtr->inputMethod = XOpenIM(dispPtr->display, NULL, NULL, NULL); + if (dispPtr->inputMethod == NULL) { + return; + } + + /* Require X11R6 */ + { + XIMCallback destroy_cb; + + destroy_cb.callback = DestroyIMCallback; + destroy_cb.client_data = (XPointer) dispPtr; + if (XSetIMValues(dispPtr->inputMethod, XNDestroyCallback, + &destroy_cb, NULL)) + goto error; + } + + if ((XGetIMValues(dispPtr->inputMethod, XNQueryInputStyle, &stylePtr, + NULL) != NULL) || (stylePtr == NULL)) { + goto error; + } + + /* + * Select the best input style supported by both the IM and Tk. + */ + for (i = 0; i < stylePtr->count_styles; i++) { + XIMStyle thisStyle = stylePtr->supported_styles[i]; + if (thisStyle == (XIMPreeditPosition | XIMStatusNothing)) { + bestStyle = thisStyle; + break; + } else if (thisStyle == (XIMPreeditNothing | XIMStatusNothing)) { + bestStyle = thisStyle; + } + } + XFree(stylePtr); + if (bestStyle == 0) { + goto error; + } + + dispPtr->inputStyle = bestStyle; + + /* + * Create an XFontSet for preedit area. + */ + if (dispPtr->inputStyle & XIMPreeditPosition) { + char **missing_list; + int missing_count; + char *def_string; + + dispPtr->inputXfs = XCreateFontSet(dispPtr->display, + "-*-*-*-R-Normal--14-130-75-75-*-*", + &missing_list, &missing_count, &def_string); + if (missing_count > 0) { + XFreeStringList(missing_list); + } + } + + return; + +error: + if (dispPtr->inputMethod) { + XCloseIM(dispPtr->inputMethod); + dispPtr->inputMethod = NULL; + ++dispPtr->ximGeneration; + } +} +#endif /* TK_USE_INPUT_METHODS */ + +void +TkpWarpPointer( + TkDisplay *dispPtr) +{ + Window w; /* Which window to warp relative to. */ + + if (dispPtr->warpWindow != NULL) { + w = Tk_WindowId(dispPtr->warpWindow); + } else { + w = RootWindow(dispPtr->display, + Tk_ScreenNumber(dispPtr->warpMainwin)); + } + XWarpPointer(dispPtr->display, None, w, 0, 0, 0, 0, + (int) dispPtr->warpX, (int) dispPtr->warpY); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixFocus.c b/tk8.6/unix/tkUnixFocus.c new file mode 100644 index 0000000..0767618 --- /dev/null +++ b/tk8.6/unix/tkUnixFocus.c @@ -0,0 +1,149 @@ +/* + * tkUnixFocus.c -- + * + * This file contains platform specific functions that manage focus for + * Tk. + * + * Copyright (c) 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. + */ + +#include "tkUnixInt.h" + + +/* + *---------------------------------------------------------------------- + * + * TkpChangeFocus -- + * + * This function is invoked to move the official X focus from one window + * to another. + * + * Results: + * The return value is the serial number of the command that changed the + * focus. It may be needed by the caller to filter out focus change + * events that were queued before the command. If the function doesn't + * actually change the focus then it returns 0. + * + * Side effects: + * The official X focus window changes; the application's focus window + * isn't changed by this function. + * + *---------------------------------------------------------------------- + */ + +int +TkpChangeFocus( + TkWindow *winPtr, /* Window that is to receive the X focus. */ + int force) /* Non-zero means claim the focus even if it + * didn't originally belong to topLevelPtr's + * application. */ +{ + TkDisplay *dispPtr = winPtr->dispPtr; + Tk_ErrorHandler errHandler; + Window window, root, parent, *children; + unsigned int numChildren, serial; + TkWindow *winPtr2; + int dummy; + + /* + * Don't set the X focus to a window that's marked override-redirect. + * This is a hack to avoid problems with menus under olvwm: if we move + * the focus then the focus can get lost during keyboard traversal. + * Fortunately, we don't really need to move the focus for menus: events + * will still find their way to the focus window, and menus aren't + * decorated anyway so the window manager doesn't need to hear about the + * focus change in order to redecorate the menu. + */ + + serial = 0; + if (winPtr->atts.override_redirect) { + return serial; + } + + /* + * Check to make sure that the focus is still in one of the windows of + * this application or one of their descendants. Furthermore, grab the + * server to make sure that the focus doesn't change in the middle of this + * operation. + */ + + XGrabServer(dispPtr->display); + if (!force) { + /* + * Find the focus window, then see if it or one of its ancestors is a + * window in our application (it's possible that the focus window is + * in an embedded application, which may or may not be in the same + * process. + */ + + XGetInputFocus(dispPtr->display, &window, &dummy); + while (1) { + winPtr2 = (TkWindow *) Tk_IdToWindow(dispPtr->display, window); + if ((winPtr2 != NULL) && (winPtr2->mainPtr == winPtr->mainPtr)) { + break; + } + if ((window == PointerRoot) || (window == None)) { + goto done; + } + XQueryTree(dispPtr->display, window, &root, &parent, &children, + &numChildren); + if (children != NULL) { + XFree((void *) children); + } + if (parent == root) { + goto done; + } + window = parent; + } + } + + /* + * Tell X to change the focus. Ignore errors that occur when changing the + * focus: it is still possible that the window we're focussing to could + * have gotten unmapped, which will generate an error. + */ + + errHandler = Tk_CreateErrorHandler(dispPtr->display, -1,-1,-1, NULL,NULL); + if (winPtr->window == None) { + Tcl_Panic("ChangeXFocus got null X window"); + } + XSetInputFocus(dispPtr->display, winPtr->window, RevertToParent, + CurrentTime); + Tk_DeleteErrorHandler(errHandler); + + /* + * Remember the current serial number for the X server and issue a dummy + * server request. This marks the position at which we changed the focus, + * so we can distinguish FocusIn and FocusOut events on either side of the + * mark. + */ + + serial = NextRequest(winPtr->display); + XNoOp(winPtr->display); + + done: + XUngrabServer(dispPtr->display); + + /* + * After ungrabbing the server, it's important to flush the output + * immediately so that the server sees the ungrab command. Otherwise we + * might do something else that needs to communicate with the server (such + * as invoking a subprocess that needs to do I/O to the screen); if the + * ungrab command is still sitting in our output buffer, we could + * deadlock. + */ + + XFlush(dispPtr->display); + return serial; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixFont.c b/tk8.6/unix/tkUnixFont.c new file mode 100644 index 0000000..96635b4 --- /dev/null +++ b/tk8.6/unix/tkUnixFont.c @@ -0,0 +1,3334 @@ +/* + * tkUnixFont.c -- + * + * Contains the Unix implementation of the platform-independent font + * package interface. + * + * 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. + */ + +#include "tkUnixInt.h" +#include "tkFont.h" +#include <netinet/in.h> /* for htons() prototype */ +#include <arpa/inet.h> /* inet_ntoa() */ + +/* + * The preferred font encodings. + */ + +static const char *const encodingList[] = { + "iso8859-1", "jis0208", "jis0212", NULL +}; + +/* + * 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 Unix, there are three attributes that uniquely identify a "font + * family": the foundry, face name, and charset. + */ + +#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 foundry; /* Foundry key for this FontFamily. */ + Tk_Uid faceName; /* Face name key for this FontFamily. */ + Tcl_Encoding encoding; /* Encoding key for this FontFamily. */ + + /* + * Derived properties. + */ + + int isTwoByteFont; /* 1 if this is a double-byte font, 0 + * otherwise. */ + 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 alloced. 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. */ +} 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. */ + XFontStruct *fontStructPtr; /* 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 Unix's implementation of a font object. + */ + +#define SUBFONT_SPACE 3 +#define BASE_CHARS 256 + +typedef struct UnixFont { + TkFont font; /* Stuff used by generic font package. Must be + * first in structure. */ + 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. */ + SubFont controlSubFont; /* Font to use to display control-character + * expansions. */ + + Display *display; /* Display that owns font. */ + int pixelSize; /* Original pixel size used when font was + * constructed. */ + TkXLFDAttributes xa; /* Additional attributes that specify the + * preferred foundry and encoding to use when + * constructing additional SubFonts. */ + int widths[BASE_CHARS]; /* Widths of first 256 chars in the base font, + * for handling common case. */ + int underlinePos; /* Offset from baseline to origin of underline + * bar (used when drawing underlined font) + * (pixels). */ + int barHeight; /* Height of underline or overstrike bar (used + * when drawing underlined or strikeout font) + * (pixels). */ +} UnixFont; + +/* + * The following structure and definition is used to keep track of the + * alternative names for various encodings. Asking for an encoding that + * matches one of the alias patterns will result in actually getting the + * encoding by its real name. + */ + +typedef struct EncodingAlias { + const char *realName; /* The real name of the encoding to load if + * the provided name matched the pattern. */ + const char *aliasPattern; /* Pattern for encoding name, of the form that + * is acceptable to Tcl_StringMatch. */ +} EncodingAlias; + +/* + * Just some utility structures used for passing around values in helper + * functions. + */ + +typedef struct FontAttributes { + TkFontAttributes fa; + TkXLFDAttributes xa; +} FontAttributes; + +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. */ + FontFamily controlFamily; /* FontFamily used to handle control character + * expansions. The encoding of this FontFamily + * converts UTF-8 to backslashed escape + * sequences. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + +/* + * The set of builtin encoding alises to convert the XLFD names for the + * encodings into the names expected by the Tcl encoding package. + */ + +static EncodingAlias encodingAliases[] = { + {"gb2312-raw", "gb2312*"}, + {"big5", "big5*"}, + {"cns11643-1", "cns11643*-1"}, + {"cns11643-1", "cns11643*.1-0"}, + {"cns11643-2", "cns11643*-2"}, + {"cns11643-2", "cns11643*.2-0"}, + {"jis0201", "jisx0201*"}, + {"jis0201", "jisx0202*"}, + {"jis0208", "jisc6226*"}, + {"jis0208", "jisx0208*"}, + {"jis0212", "jisx0212*"}, + {"tis620", "tis620*"}, + {"ksc5601", "ksc5601*"}, + {"dingbats", "*dingbats"}, +#ifdef WORDS_BIGENDIAN + {"unicode", "iso10646-1"}, +#else + /* + * ucs-2be is needed if native order isn't BE. + */ + {"ucs-2be", "iso10646-1"}, +#endif + {NULL, NULL} +}; + +/* + * Functions used only in this file. + */ + +static void FontPkgCleanup(ClientData clientData); +static FontFamily * AllocFontFamily(Display *display, + XFontStruct *fontStructPtr, int base); +static SubFont * CanUseFallback(UnixFont *fontPtr, + const char *fallbackName, int ch, + SubFont **fixSubFontPtrPtr); +static SubFont * CanUseFallbackWithAliases(UnixFont *fontPtr, + const char *fallbackName, int ch, + Tcl_DString *nameTriedPtr, + SubFont **fixSubFontPtrPtr); +static int ControlUtfProc(ClientData clientData, const char *src, + int srcLen, int flags, Tcl_EncodingState*statePtr, + char *dst, int dstLen, int *srcReadPtr, + int *dstWrotePtr, int *dstCharsPtr); +static XFontStruct * CreateClosestFont(Tk_Window tkwin, + const TkFontAttributes *faPtr, + const TkXLFDAttributes *xaPtr); +static SubFont * FindSubFontForChar(UnixFont *fontPtr, int ch, + SubFont **fixSubFontPtrPtr); +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 *afPtr); +static const char * GetEncodingAlias(const char *name); +static int GetFontAttributes(Display *display, + XFontStruct *fontStructPtr, FontAttributes *faPtr); +static XFontStruct * GetScreenFont(Display *display, + FontAttributes *wantPtr, char **nameList, + int bestIdx[], unsigned bestScore[]); +static XFontStruct * GetSystemFont(Display *display); +static int IdentifySymbolEncodings(FontAttributes *faPtr); +static void InitFont(Tk_Window tkwin, XFontStruct *fontStructPtr, + UnixFont *fontPtr); +static void InitSubFont(Display *display, + XFontStruct *fontStructPtr, int base, + SubFont *subFontPtr); +static char ** ListFonts(Display *display, const char *faceName, + int *numNamesPtr); +static char ** ListFontOrAlias(Display *display, const char*faceName, + int *numNamesPtr); +static unsigned RankAttributes(FontAttributes *wantPtr, + FontAttributes *gotPtr); +static void ReleaseFont(UnixFont *fontPtr); +static void ReleaseSubFont(Display *display, SubFont *subFontPtr); +static int SeenName(const char *name, Tcl_DString *dsPtr); +#ifndef WORDS_BIGENDIAN +static int Ucs2beToUtfProc(ClientData clientData, const char*src, + int srcLen, int flags, Tcl_EncodingState*statePtr, + char *dst, int dstLen, int *srcReadPtr, + int *dstWrotePtr, int *dstCharsPtr); +static int UtfToUcs2beProc(ClientData clientData, const char*src, + int srcLen, int flags, Tcl_EncodingState*statePtr, + char *dst, int dstLen, int *srcReadPtr, + int *dstWrotePtr, int *dstCharsPtr); +#endif + +/* + *------------------------------------------------------------------------- + * + * FontPkgCleanup -- + * + * This function 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: + * Releases thread-specific resources used by font pkg. + * + *------------------------------------------------------------------------- + */ + +static void +FontPkgCleanup( + ClientData clientData) +{ + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (tsdPtr->controlFamily.encoding != NULL) { + FontFamily *familyPtr = &tsdPtr->controlFamily; + int i; + + Tcl_FreeEncoding(familyPtr->encoding); + for (i = 0; i < FONTMAP_PAGES; i++) { + if (familyPtr->fontMap[i] != NULL) { + ckfree(familyPtr->fontMap[i]); + } + } + tsdPtr->controlFamily.encoding = NULL; + } +} + +/* + *------------------------------------------------------------------------- + * + * TkpFontPkgInit -- + * + * This function 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. + * + *------------------------------------------------------------------------- + */ + +void +TkpFontPkgInit( + TkMainInfo *mainPtr) /* The application being created. */ +{ + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tcl_EncodingType type; + SubFont dummy; + int i; + + if (tsdPtr->controlFamily.encoding == NULL) { + type.encodingName = "X11ControlChars"; + type.toUtfProc = ControlUtfProc; + type.fromUtfProc = ControlUtfProc; + type.freeProc = NULL; + type.clientData = NULL; + type.nullSize = 0; + + tsdPtr->controlFamily.refCount = 2; + tsdPtr->controlFamily.encoding = Tcl_CreateEncoding(&type); + tsdPtr->controlFamily.isTwoByteFont = 0; + + dummy.familyPtr = &tsdPtr->controlFamily; + dummy.fontMap = tsdPtr->controlFamily.fontMap; + for (i = 0x00; i < 0x20; i++) { + FontMapInsert(&dummy, i); + FontMapInsert(&dummy, i + 0x80); + } + +#ifndef WORDS_BIGENDIAN + /* + * UCS-2BE is unicode (UCS-2) in big-endian format. Define this if + * native order isn't BE. It is used in iso10646 fonts. + */ + + type.encodingName = "ucs-2be"; + type.toUtfProc = Ucs2beToUtfProc; + type.fromUtfProc = UtfToUcs2beProc; + type.freeProc = NULL; + type.clientData = NULL; + type.nullSize = 2; + Tcl_CreateEncoding(&type); +#endif + Tcl_CreateThreadExitHandler(FontPkgCleanup, NULL); + } +} + +/* + *------------------------------------------------------------------------- + * + * ControlUtfProc -- + * + * Convert from UTF-8 into the ASCII expansion of a control character. + * + * Results: + * Returns TCL_OK if conversion was successful. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +static int +ControlUtfProc( + ClientData clientData, /* Not used. */ + const char *src, /* Source string in UTF-8. */ + int srcLen, /* Source string length in bytes. */ + int flags, /* Conversion control flags. */ + Tcl_EncodingState *statePtr,/* Place for conversion routine to store state + * information used during a piecewise + * conversion. Contents of statePtr are + * initialized and/or reset by conversion + * routine under control of flags argument. */ + char *dst, /* Output buffer in which converted string is + * stored. */ + int dstLen, /* The maximum length of output buffer in + * bytes. */ + int *srcReadPtr, /* Filled with the number of bytes from the + * source string that were converted. This may + * be less than the original source length if + * there was a problem converting some source + * characters. */ + int *dstWrotePtr, /* Filled with the number of bytes that were + * stored in the output buffer as a result of + * the conversion. */ + int *dstCharsPtr) /* Filled with the number of characters that + * correspond to the bytes stored in the + * output buffer. */ +{ + const char *srcStart, *srcEnd; + char *dstStart, *dstEnd; + int ch, result; + static char hexChars[] = "0123456789abcdef"; + static char mapChars[] = { + 0, 0, 0, 0, 0, 0, 0, + 'a', 'b', 't', 'n', 'v', 'f', 'r' + }; + + result = TCL_OK; + + srcStart = src; + srcEnd = src + srcLen; + + dstStart = dst; + dstEnd = dst + dstLen - 6; + + for ( ; src < srcEnd; ) { + if (dst > dstEnd) { + result = TCL_CONVERT_NOSPACE; + break; + } + src += TkUtfToUniChar(src, &ch); + dst[0] = '\\'; + if (((size_t) ch < sizeof(mapChars)) && (mapChars[ch] != 0)) { + dst[1] = mapChars[ch]; + dst += 2; + } else if (ch < 256) { + dst[1] = 'x'; + dst[2] = hexChars[(ch >> 4) & 0xf]; + dst[3] = hexChars[ch & 0xf]; + dst += 4; + } else if (ch < 0x10000) { + dst[1] = 'u'; + dst[2] = hexChars[(ch >> 12) & 0xf]; + dst[3] = hexChars[(ch >> 8) & 0xf]; + dst[4] = hexChars[(ch >> 4) & 0xf]; + dst[5] = hexChars[ch & 0xf]; + dst += 6; + } else { + /* TODO we can do better here */ + dst[1] = 'u'; + dst[2] = 'f'; + dst[3] = 'f'; + dst[4] = 'f'; + dst[5] = 'd'; + dst += 6; + } + } + *srcReadPtr = src - srcStart; + *dstWrotePtr = dst - dstStart; + *dstCharsPtr = dst - dstStart; + return result; +} + +#ifndef WORDS_BIGENDIAN +/* + *------------------------------------------------------------------------- + * + * Ucs2beToUtfProc -- + * + * Convert from UCS-2BE (big-endian 16-bit Unicode) to UTF-8. + * This is only defined on LE machines. + * + * Results: + * Returns TCL_OK if conversion was successful. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +static int +Ucs2beToUtfProc( + ClientData clientData, /* Not used. */ + const char *src, /* Source string in Unicode. */ + int srcLen, /* Source string length in bytes. */ + int flags, /* Conversion control flags. */ + Tcl_EncodingState *statePtr,/* Place for conversion routine to store state + * information used during a piecewise + * conversion. Contents of statePtr are + * initialized and/or reset by conversion + * routine under control of flags argument. */ + char *dst, /* Output buffer in which converted string is + * stored. */ + int dstLen, /* The maximum length of output buffer in + * bytes. */ + int *srcReadPtr, /* Filled with the number of bytes from the + * source string that were converted. This may + * be less than the original source length if + * there was a problem converting some source + * characters. */ + int *dstWrotePtr, /* Filled with the number of bytes that were + * stored in the output buffer as a result of + * the conversion. */ + int *dstCharsPtr) /* Filled with the number of characters that + * correspond to the bytes stored in the + * output buffer. */ +{ + const char *srcStart, *srcEnd; + char *dstEnd, *dstStart; + int result, numChars; + + result = TCL_OK; + + /* check alignment with ucs-2 (2 == sizeof(UCS-2)) */ + if ((srcLen % 2) != 0) { + result = TCL_CONVERT_MULTIBYTE; + srcLen--; + } + + srcStart = src; + srcEnd = src + srcLen; + + dstStart = dst; + dstEnd = dst + dstLen - TCL_UTF_MAX; + + for (numChars = 0; src < srcEnd; numChars++) { + if (dst > dstEnd) { + result = TCL_CONVERT_NOSPACE; + break; + } + + /* + * Need to swap byte-order on little-endian machines (x86) for + * UCS-2BE. We know this is an LE->BE swap. + */ + + dst += Tcl_UniCharToUtf(htons(*((short *)src)), dst); + src += 2 /* sizeof(UCS-2) */; + } + + *srcReadPtr = src - srcStart; + *dstWrotePtr = dst - dstStart; + *dstCharsPtr = numChars; + return result; +} + +/* + *------------------------------------------------------------------------- + * + * UtfToUcs2beProc -- + * + * Convert from UTF-8 to UCS-2BE (fixed 2-byte encoding). + * + * Results: + * Returns TCL_OK if conversion was successful. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +static int +UtfToUcs2beProc( + ClientData clientData, /* TableEncodingData that specifies + * encoding. */ + const char *src, /* Source string in UTF-8. */ + int srcLen, /* Source string length in bytes. */ + int flags, /* Conversion control flags. */ + Tcl_EncodingState *statePtr,/* Place for conversion routine to store state + * information used during a piecewise + * conversion. Contents of statePtr are + * initialized and/or reset by conversion + * routine under control of flags argument. */ + char *dst, /* Output buffer in which converted string is + * stored. */ + int dstLen, /* The maximum length of output buffer in + * bytes. */ + int *srcReadPtr, /* Filled with the number of bytes from the + * source string that were converted. This may + * be less than the original source length if + * there was a problem converting some source + * characters. */ + int *dstWrotePtr, /* Filled with the number of bytes that were + * stored in the output buffer as a result of + * the conversion. */ + int *dstCharsPtr) /* Filled with the number of characters that + * correspond to the bytes stored in the + * output buffer. */ +{ + const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd; + int result, numChars; + Tcl_UniChar ch; + + srcStart = src; + srcEnd = src + srcLen; + srcClose = srcEnd; + if (!(flags & TCL_ENCODING_END)) { + srcClose -= TCL_UTF_MAX; + } + + dstStart = dst; + dstEnd = dst + dstLen - 2 /* sizeof(UCS-2) */; + + result = TCL_OK; + for (numChars = 0; src < srcEnd; numChars++) { + if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) { + /* + * If there is more string to follow, this will ensure that the + * last UTF-8 character in the source buffer hasn't been cut off. + */ + + result = TCL_CONVERT_MULTIBYTE; + break; + } + if (dst > dstEnd) { + result = TCL_CONVERT_NOSPACE; + break; + } + src += Tcl_UtfToUniChar(src, &ch); + + /* + * Ensure big-endianness (store big bits first). + * XXX: This hard-codes the assumed size of Tcl_UniChar as 2. Make + * sure to work in char* for Tcl_UtfToUniChar alignment. [Bug 1122671] + */ + + *dst++ = (ch >> 8); + *dst++ = (ch & 0xFF); + } + *srcReadPtr = src - srcStart; + *dstWrotePtr = dst - dstStart; + *dstCharsPtr = numChars; + return result; +} +#endif /* WORDS_BIGENDIAN */ + +/* + *--------------------------------------------------------------------------- + * + * TkpGetNativeFont -- + * + * Map a platform-specific native font name to a TkFont. + * + * Results: + * The return value is a pointer to a TkFont that represents the native + * font. If a native font by the given name could not be found, the + * return value is NULL. + * + * Every call to this function returns a new TkFont structure, even if + * the name has already been seen before. The caller should call + * TkpDeleteFont() when the font is no longer needed. + * + * The caller is responsible for initializing the memory associated with + * the generic TkFont when this function returns and releasing the + * contents of the generic TkFont before calling TkpDeleteFont(). + * + * Side effects: + * Memory allocated. + * + *--------------------------------------------------------------------------- + */ + +TkFont * +TkpGetNativeFont( + Tk_Window tkwin, /* For display where font will be used. */ + const char *name) /* Platform-specific font name. */ +{ + UnixFont *fontPtr; + XFontStruct *fontStructPtr; + FontAttributes fa; + const char *p; + int hasSpace, dashes, hasWild; + + /* + * The behavior of X when given a name that isn't an XLFD is unspecified. + * For example, Exceed 6 returns a valid font for any random string. This + * is awkward since system names have higher priority than the other Tk + * font syntaxes. So, we need to perform a quick sanity check on the name + * and fail if it looks suspicious. We fail if the name: + * - contains a space immediately before a dash + * - contains a space, but no '*' characters and fewer than 14 dashes + */ + + hasSpace = dashes = hasWild = 0; + for (p = name; *p != '\0'; p++) { + if (*p == ' ') { + if (p[1] == '-') { + return NULL; + } + hasSpace = 1; + } else if (*p == '-') { + dashes++; + } else if (*p == '*') { + hasWild = 1; + } + } + if ((dashes < 14) && !hasWild && hasSpace) { + return NULL; + } + + fontStructPtr = XLoadQueryFont(Tk_Display(tkwin), name); + if (fontStructPtr == NULL) { + /* + * Handle all names that look like XLFDs here. Otherwise, when + * TkpGetFontFromAttributes is called from generic code, any foundry + * or encoding information specified in the XLFD will have been parsed + * out and lost. But make sure we don't have an "-option value" string + * since TkFontParseXLFD would return a false success when attempting + * to parse it. + */ + + if (name[0] == '-') { + if (name[1] != '*') { + char *dash; + + dash = strchr(name + 1, '-'); + if ((dash == NULL) || (isspace(UCHAR(dash[-1])))) { + return NULL; + } + } + } else if (name[0] != '*') { + return NULL; + } + if (TkFontParseXLFD(name, &fa.fa, &fa.xa) != TCL_OK) { + return NULL; + } + fontStructPtr = CreateClosestFont(tkwin, &fa.fa, &fa.xa); + } + fontPtr = ckalloc(sizeof(UnixFont)); + InitFont(tkwin, fontStructPtr, fontPtr); + + return (TkFont *) fontPtr; +} + +/* + *--------------------------------------------------------------------------- + * + * TkpGetFontFromAttributes -- + * + * Given a desired set of attributes for a font, find a font with the + * closest matching attributes. + * + * Results: + * The return value is a pointer to a TkFont that represents the font + * with the desired attributes. If a font with the desired attributes + * could not be constructed, some other font will be substituted + * automatically. + * + * Every call to this function returns a new TkFont structure, even if + * the specified attributes have already been seen before. The caller + * should call TkpDeleteFont() to free the platform- specific data when + * the font is no longer needed. + * + * The caller is responsible for initializing the memory associated with + * the generic TkFont when this function returns and releasing the + * contents of the generic TkFont before calling TkpDeleteFont(). + * + * Side effects: + * Memory allocated. + * + *--------------------------------------------------------------------------- + */ + +TkFont * +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. */ +{ + UnixFont *fontPtr; + TkXLFDAttributes xa; + XFontStruct *fontStructPtr; + + TkInitXLFDAttributes(&xa); + fontStructPtr = CreateClosestFont(tkwin, faPtr, &xa); + + fontPtr = (UnixFont *) tkFontPtr; + if (fontPtr == NULL) { + fontPtr = ckalloc(sizeof(UnixFont)); + } else { + ReleaseFont(fontPtr); + } + InitFont(tkwin, fontStructPtr, fontPtr); + + fontPtr->font.fa.underline = faPtr->underline; + fontPtr->font.fa.overstrike = faPtr->overstrike; + + return (TkFont *) fontPtr; +} + +/* + *--------------------------------------------------------------------------- + * + * TkpDeleteFont -- + * + * Called to release a font allocated by TkpGetNativeFont() or + * TkpGetFontFromAttributes(). The caller should have already released + * the fields of the TkFont that are used exclusively by the generic + * TkFont code. + * + * Results: + * None. + * + * Side effects: + * TkFont is deallocated. + * + *--------------------------------------------------------------------------- + */ + +void +TkpDeleteFont( + TkFont *tkFontPtr) /* Token of font to be deleted. */ +{ + UnixFont *fontPtr = (UnixFont *) tkFontPtr; + + ReleaseFont(fontPtr); +} + +/* + *--------------------------------------------------------------------------- + * + * TkpGetFontFamilies -- + * + * Return information about the font families that are available on the + * display of the given window. + * + * Results: + * Modifies interp's result object to hold a list of all the available + * font families. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +void +TkpGetFontFamilies( + Tcl_Interp *interp, /* Interp to hold result. */ + Tk_Window tkwin) /* For display to query. */ +{ + int i, new, numNames; + char *family, **nameList; + Tcl_HashTable familyTable; + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + Tcl_Obj *resultPtr, *strPtr; + + Tcl_InitHashTable(&familyTable, TCL_STRING_KEYS); + nameList = ListFonts(Tk_Display(tkwin), "*", &numNames); + for (i = 0; i < numNames; i++) { + char *familyEnd; + + family = strchr(nameList[i] + 1, '-'); + if (family == NULL) { + /* + * Apparently, sometimes ListFonts() can return a font name with + * zero or one '-' character in it. This is probably indicative of + * a server misconfiguration, but crashing because of it is a very + * bad idea anyway. [Bug 1475865] + */ + + continue; + } + family++; /* Advance to char after '-'. */ + familyEnd = strchr(family, '-'); + if (familyEnd == NULL) { + continue; /* See comment above. */ + } + *familyEnd = '\0'; + Tcl_CreateHashEntry(&familyTable, family, &new); + } + XFreeFontNames(nameList); + + hPtr = Tcl_FirstHashEntry(&familyTable, &search); + resultPtr = Tcl_NewObj(); + while (hPtr != NULL) { + strPtr = Tcl_NewStringObj(Tcl_GetHashKey(&familyTable, hPtr), -1); + Tcl_ListObjAppendElement(NULL, resultPtr, strPtr); + hPtr = Tcl_NextHashEntry(&search); + } + Tcl_SetObjResult(interp, resultPtr); + + Tcl_DeleteHashTable(&familyTable); +} + +/* + *------------------------------------------------------------------------- + * + * 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, + Tk_Font tkfont) +{ + int i; + Tcl_Obj *objv[3], *resultPtr, *listPtr; + UnixFont *fontPtr; + FontFamily *familyPtr; + + resultPtr = Tcl_NewObj(); + fontPtr = (UnixFont *) tkfont; + for (i = 0; i < fontPtr->numSubFonts; i++) { + familyPtr = fontPtr->subFontArray[i].familyPtr; + objv[0] = Tcl_NewStringObj(familyPtr->faceName, -1); + objv[1] = Tcl_NewStringObj(familyPtr->foundry, -1); + objv[2] = Tcl_NewStringObj( + Tcl_GetEncodingName(familyPtr->encoding), -1); + listPtr = Tcl_NewListObj(3, objv); + Tcl_ListObjAppendElement(NULL, resultPtr, listPtr); + } + Tcl_SetObjResult(interp, resultPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetFontAttrsForChar -- + * + * Retrieve the font attributes of the actual font used to render a given + * character. + * + * Results: + * None. + * + * Side effects: + * The font attributes are stored in *faPtr. + * + *---------------------------------------------------------------------- + */ + +void +TkpGetFontAttrsForChar( + Tk_Window tkwin, /* Window on the font's display */ + Tk_Font tkfont, /* Font to query */ + int c, /* Character of interest */ + TkFontAttributes *faPtr) /* Output: Font attributes */ +{ + FontAttributes atts; + UnixFont *fontPtr = (UnixFont *) tkfont; + /* Structure describing the logical font */ + SubFont *lastSubFontPtr = &fontPtr->subFontArray[0]; + /* Pointer to subfont array in case + * FindSubFontForChar needs to fix up the + * memory allocation */ + SubFont *thisSubFontPtr = FindSubFontForChar(fontPtr, c, &lastSubFontPtr); + /* Pointer to the subfont to use for the given + * character */ + + GetFontAttributes(Tk_Display(tkwin), thisSubFontPtr->fontStructPtr, &atts); + *faPtr = atts.fa; +} + +/* + *--------------------------------------------------------------------------- + * + * Tk_MeasureChars -- + * + * Determine the number of characters 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 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. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +int +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 numBytes, /* Maximum number of bytes to consider from + * source string. */ + 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: + * 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 + * terminating character. */ +{ + UnixFont *fontPtr; + SubFont *lastSubFontPtr; + int curX, curByte, ch; + + /* + * Unix 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 = (UnixFont *) tkfont; + + lastSubFontPtr = &fontPtr->subFontArray[0]; + + if (numBytes == 0) { + curX = 0; + curByte = 0; + } else if (maxLength < 0) { + const char *p, *end, *next; + SubFont *thisSubFontPtr; + FontFamily *familyPtr; + Tcl_DString runString; + + /* + * 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 + TkUtfToUniChar(p, &ch); + thisSubFontPtr = FindSubFontForChar(fontPtr, ch, &lastSubFontPtr); + if (thisSubFontPtr != lastSubFontPtr) { + familyPtr = lastSubFontPtr->familyPtr; + Tcl_UtfToExternalDString(familyPtr->encoding, source, + p - source, &runString); + if (familyPtr->isTwoByteFont) { + curX += XTextWidth16(lastSubFontPtr->fontStructPtr, + (XChar2b *) Tcl_DStringValue(&runString), + Tcl_DStringLength(&runString) / 2); + } else { + curX += XTextWidth(lastSubFontPtr->fontStructPtr, + Tcl_DStringValue(&runString), + Tcl_DStringLength(&runString)); + } + Tcl_DStringFree(&runString); + lastSubFontPtr = thisSubFontPtr; + source = p; + } + p = next; + } + familyPtr = lastSubFontPtr->familyPtr; + Tcl_UtfToExternalDString(familyPtr->encoding, source, p - source, + &runString); + if (familyPtr->isTwoByteFont) { + curX += XTextWidth16(lastSubFontPtr->fontStructPtr, + (XChar2b *) Tcl_DStringValue(&runString), + Tcl_DStringLength(&runString) >> 1); + } else { + curX += XTextWidth(lastSubFontPtr->fontStructPtr, + Tcl_DStringValue(&runString), + Tcl_DStringLength(&runString)); + } + Tcl_DStringFree(&runString); + curByte = numBytes; + } else { + const char *p, *end, *next, *term; + int newX, termX, sawNonSpace, dstWrote; + FontFamily *familyPtr; + XChar2b buf[8]; + + /* + * How many chars will fit in the space allotted? This first version + * may be inefficient because it measures every character + * individually. + */ + + next = source + TkUtfToUniChar(source, &ch); + newX = curX = termX = 0; + + term = source; + end = source + numBytes; + + sawNonSpace = (ch > 255) || !isspace(ch); + familyPtr = lastSubFontPtr->familyPtr; + for (p = source; ; ) { + if ((ch < BASE_CHARS) && (fontPtr->widths[ch] != 0)) { + newX += fontPtr->widths[ch]; + } else { + lastSubFontPtr = FindSubFontForChar(fontPtr, ch, NULL); + familyPtr = lastSubFontPtr->familyPtr; + Tcl_UtfToExternal(NULL, familyPtr->encoding, p, next - p, 0, NULL, + (char *)&buf[0].byte1, sizeof(buf), NULL, &dstWrote, NULL); + if (familyPtr->isTwoByteFont) { + newX += XTextWidth16(lastSubFontPtr->fontStructPtr, + buf, dstWrote >> 1); + } else { + newX += XTextWidth(lastSubFontPtr->fontStructPtr, + (char *)&buf[0].byte1, dstWrote); + } + } + if (newX > maxLength) { + break; + } + curX = newX; + p = next; + if (p >= end) { + term = end; + termX = curX; + break; + } + + next += TkUtfToUniChar(next, &ch); + if ((ch < 256) && isspace(ch)) { + if (sawNonSpace) { + term = p; + termX = curX; + sawNonSpace = 0; + } + } else { + sawNonSpace = 1; + } + } + + /* + * 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)) { + /* + * 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 += TkUtfToUniChar(p, &ch); + } + if ((flags & TK_AT_LEAST_ONE) && (term == source) && (p < end)) { + term = p; + termX = curX; + if (term == source) { + term += TkUtfToUniChar(term, &ch); + termX = newX; + } + } else if ((p >= end) || !(flags & TK_WHOLE_WORDS)) { + term = p; + termX = curX; + } + + curX = termX; + curByte = term - source; + } + + *lengthPtr = curX; + return curByte; +} + +/* + *--------------------------------------------------------------------------- + * + * TkpMeasureCharsInContext -- + * + * Determine the number of bytes from the string that will fit in the + * given horizontal span. The measurement is done under the assumption + * that TkpDrawCharsInContext() will be used to actually display the + * characters. + * + * This one is almost the same as Tk_MeasureChars(), but with access to + * all the characters on the line for context. On X11 this context isn't + * consulted, so we just call Tk_MeasureChars(). + * + * Results: + * 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. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +int +TkpMeasureCharsInContext( + 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 numBytes, /* Maximum number of bytes to consider from + * source string in all. */ + int rangeStart, /* Index of first byte to measure. */ + int rangeLength, /* Length of range to measure in bytes. */ + 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 ignored. */ + 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. TK_ISOLATE_END means + * that the last character should not be + * considered in context with the rest of the + * string (used for breaking lines). */ + int *lengthPtr) /* Filled with x-location just after the + * terminating character. */ +{ + (void) numBytes; /*unused*/ + return Tk_MeasureChars(tkfont, source + rangeStart, rangeLength, + maxLength, flags, lengthPtr); +} + +/* + *--------------------------------------------------------------------------- + * + * Tk_DrawChars -- + * + * Draw a string of characters on the screen. Tk_DrawChars() expands + * control characters that occur in the string to \xNN sequences. + * + * Results: + * None. + * + * Side effects: + * Information gets drawn on the screen. + * + *--------------------------------------------------------------------------- + */ + +void +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, /* 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 numBytes, /* Number of bytes in string. */ + int x, int y) /* Coordinates at which to place origin of + * string when drawing. */ +{ + UnixFont *fontPtr = (UnixFont *) tkfont; + SubFont *thisSubFontPtr, *lastSubFontPtr; + Tcl_DString runString; + const char *p, *end, *next; + int xStart, needWidth, window_width, do_width, ch; + FontFamily *familyPtr; +#ifdef TK_DRAW_CHAR_XWINDOW_CHECK + int rx, ry; + unsigned width, height, border_width, depth; + Drawable root; +#endif + + lastSubFontPtr = &fontPtr->subFontArray[0]; + xStart = x; + +#ifdef TK_DRAW_CHAR_XWINDOW_CHECK + /* + * Get the window width so we can abort drawing outside of the window + */ + + if (XGetGeometry(display, drawable, &root, &rx, &ry, &width, &height, + &border_width, &depth) == False) { + window_width = INT_MAX; + } else { + window_width = width; + } +#else + /* + * This is used by default until we find a solution that doesn't do a + * round-trip to the X server (needed to get Tk cached window width). + */ + + window_width = 32768; +#endif + + end = source + numBytes; + needWidth = fontPtr->font.fa.underline + fontPtr->font.fa.overstrike; + for (p = source; p <= end; ) { + if (p < end) { + next = p + TkUtfToUniChar(p, &ch); + thisSubFontPtr = FindSubFontForChar(fontPtr, ch, &lastSubFontPtr); + } else { + next = p + 1; + thisSubFontPtr = lastSubFontPtr; + } + if ((thisSubFontPtr != lastSubFontPtr) + || (p == end) || (p-source > 200)) { + if (p > source) { + do_width = (needWidth || (p != end)) ? 1 : 0; + familyPtr = lastSubFontPtr->familyPtr; + + Tcl_UtfToExternalDString(familyPtr->encoding, source, + p - source, &runString); + if (familyPtr->isTwoByteFont) { + XDrawString16(display, drawable, gc, x, y, + (XChar2b *) Tcl_DStringValue(&runString), + Tcl_DStringLength(&runString) / 2); + if (do_width) { + x += XTextWidth16(lastSubFontPtr->fontStructPtr, + (XChar2b *) Tcl_DStringValue(&runString), + Tcl_DStringLength(&runString) / 2); + } + } else { + XDrawString(display, drawable, gc, x, y, + Tcl_DStringValue(&runString), + Tcl_DStringLength(&runString)); + if (do_width) { + x += XTextWidth(lastSubFontPtr->fontStructPtr, + Tcl_DStringValue(&runString), + Tcl_DStringLength(&runString)); + } + } + Tcl_DStringFree(&runString); + } + lastSubFontPtr = thisSubFontPtr; + source = p; + XSetFont(display, gc, lastSubFontPtr->fontStructPtr->fid); + if (x > window_width) { + break; + } + } + p = next; + } + + if (lastSubFontPtr != &fontPtr->subFontArray[0]) { + XSetFont(display, gc, fontPtr->subFontArray[0].fontStructPtr->fid); + } + + if (fontPtr->font.fa.underline != 0) { + XFillRectangle(display, drawable, gc, xStart, + y + fontPtr->underlinePos, + (unsigned) (x - xStart), (unsigned) fontPtr->barHeight); + } + if (fontPtr->font.fa.overstrike != 0) { + y -= fontPtr->font.fm.descent + (fontPtr->font.fm.ascent) / 10; + XFillRectangle(display, drawable, gc, xStart, y, + (unsigned) (x - xStart), (unsigned) fontPtr->barHeight); + } +} + +/* + *--------------------------------------------------------------------------- + * + * TkpDrawCharsInContext -- + * + * Draw a string of characters on the screen like Tk_DrawChars(), but + * with access to all the characters on the line for context. On X11 this + * context isn't consulted, so we just call Tk_DrawChars(). + * + * Results: + * None. + * + * Side effects: + * Information gets drawn on the screen. + * + *--------------------------------------------------------------------------- + */ + +void +TkpDrawCharsInContext( + 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, /* 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 numBytes, /* Number of bytes in string. */ + int rangeStart, /* Index of first byte to draw. */ + int rangeLength, /* Length of range to draw in bytes. */ + int x, int y) /* Coordinates at which to place origin of the + * whole (not just the range) string when + * drawing. */ +{ + int widthUntilStart; + + (void) numBytes; /*unused*/ + + Tk_MeasureChars(tkfont, source, rangeStart, -1, 0, &widthUntilStart); + Tk_DrawChars(display, drawable, gc, tkfont, source + rangeStart, + rangeLength, x+widthUntilStart, y); +} + +/* + *------------------------------------------------------------------------- + * + * CreateClosestFont -- + * + * Helper for TkpGetNativeFont() and TkpGetFontFromAttributes(). Given a + * set of font attributes, construct a close XFontStruct. If requested + * face name is not available, automatically substitutes an alias for + * requested face name. If encoding is not specified (or the requested + * one is not available), automatically chooses another encoding from the + * list of preferred encodings. If the foundry is not specified (or is + * not available) automatically prefers "adobe" foundry. For all other + * attributes, if the requested value was not available, the appropriate + * "close" value will be used. + * + * Results: + * Return value is the XFontStruct that best matched the requested + * attributes. The return value is never NULL; some font will always be + * returned. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +static XFontStruct * +CreateClosestFont( + Tk_Window tkwin, /* For display where font will be used. */ + const TkFontAttributes *faPtr, + /* Set of generic attributes to match. */ + const TkXLFDAttributes *xaPtr) + /* Set of X-specific attributes to match. */ +{ + FontAttributes want; + char **nameList; + int numNames, nameIdx, bestIdx[2]; + Display *display; + XFontStruct *fontStructPtr; + unsigned bestScore[2]; + + want.fa = *faPtr; + want.xa = *xaPtr; + + if (want.xa.foundry == NULL) { + want.xa.foundry = Tk_GetUid("adobe"); + } + if (want.fa.family == NULL) { + want.fa.family = Tk_GetUid("fixed"); + } + want.fa.size = -TkFontGetPixels(tkwin, faPtr->size); + if (want.xa.charset == NULL || *want.xa.charset == '\0') { + want.xa.charset = Tk_GetUid("iso8859-1"); /* locale. */ + } + + display = Tk_Display(tkwin); + + /* + * Algorithm to get the closest font to the name requested. + * + * try fontname + * try all aliases for fontname + * foreach fallback for fontname + * try the fallback + * try all aliases for the fallback + */ + + nameList = ListFontOrAlias(display, want.fa.family, &numNames); + if (numNames == 0) { + const char *const *const *fontFallbacks; + int i, j; + const char *fallback; + + fontFallbacks = TkFontGetFallbacks(); + for (i = 0; fontFallbacks[i] != NULL; i++) { + for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) { + if (strcasecmp(want.fa.family, fallback) == 0) { + break; + } + } + if (fallback != NULL) { + for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) { + nameList = ListFontOrAlias(display, fallback, &numNames); + if (numNames != 0) { + goto found; + } + } + } + } + nameList = ListFonts(display, "fixed", &numNames); + if (numNames == 0) { + nameList = ListFonts(display, "*", &numNames); + } + if (numNames == 0) { + return GetSystemFont(display); + } + } + + found: + bestIdx[0] = -1; + bestIdx[1] = -1; + bestScore[0] = (unsigned) -1; + bestScore[1] = (unsigned) -1; + for (nameIdx = 0; nameIdx < numNames; nameIdx++) { + FontAttributes got; + int scalable; + unsigned score; + + if (TkFontParseXLFD(nameList[nameIdx], &got.fa, &got.xa) != TCL_OK) { + continue; + } + IdentifySymbolEncodings(&got); + scalable = (got.fa.size == 0.0); + score = RankAttributes(&want, &got); + if (score < bestScore[scalable]) { + bestIdx[scalable] = nameIdx; + bestScore[scalable] = score; + } + if (score == 0) { + break; + } + } + + fontStructPtr = GetScreenFont(display, &want, nameList, bestIdx, + bestScore); + XFreeFontNames(nameList); + + if (fontStructPtr == NULL) { + return GetSystemFont(display); + } + return fontStructPtr; +} + +/* + *--------------------------------------------------------------------------- + * + * InitFont -- + * + * Helper for TkpGetNativeFont() and TkpGetFontFromAttributes(). + * Initializes the memory for a new UnixFont 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 for + * releasing those fields before calling TkpDeleteFont(). + * + * Results: + * Fills the WinFont structure. + * + * Side effects: + * Memory allocated. + * + *--------------------------------------------------------------------------- + */ + +static void +InitFont( + Tk_Window tkwin, /* For screen where font will be used. */ + XFontStruct *fontStructPtr, /* X information about font. */ + UnixFont *fontPtr) /* Filled with information constructed from + * the above arguments. */ +{ + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + unsigned long value; + int minHi, maxHi, minLo, maxLo, fixed, width, limit, i, n; + FontAttributes fa; + TkFontAttributes *faPtr; + TkFontMetrics *fmPtr; + SubFont *controlPtr, *subFontPtr; + char *pageMap; + Display *display; + + /* + * Get all font attributes and metrics. + */ + + display = Tk_Display(tkwin); + GetFontAttributes(display, fontStructPtr, &fa); + + minHi = fontStructPtr->min_byte1; + maxHi = fontStructPtr->max_byte1; + minLo = fontStructPtr->min_char_or_byte2; + maxLo = fontStructPtr->max_char_or_byte2; + + fixed = 1; + if (fontStructPtr->per_char != NULL) { + width = 0; + limit = (maxHi - minHi + 1) * (maxLo - minLo + 1); + for (i = 0; i < limit; i++) { + n = fontStructPtr->per_char[i].width; + if (n != 0) { + if (width == 0) { + width = n; + } else if (width != n) { + fixed = 0; + break; + } + } + } + } + + fontPtr->font.fid = fontStructPtr->fid; + + faPtr = &fontPtr->font.fa; + faPtr->family = fa.fa.family; + faPtr->size = TkFontGetPoints(tkwin, fa.fa.size); + faPtr->weight = fa.fa.weight; + faPtr->slant = fa.fa.slant; + faPtr->underline = 0; + faPtr->overstrike = 0; + + fmPtr = &fontPtr->font.fm; + fmPtr->ascent = fontStructPtr->ascent; + fmPtr->descent = fontStructPtr->descent; + fmPtr->maxWidth = fontStructPtr->max_bounds.width; + fmPtr->fixed = fixed; + + fontPtr->display = display; + fontPtr->pixelSize = (int)(TkFontGetPixels(tkwin, fa.fa.size) + 0.5); + fontPtr->xa = fa.xa; + + fontPtr->numSubFonts = 1; + fontPtr->subFontArray = fontPtr->staticSubFonts; + InitSubFont(display, fontStructPtr, 1, &fontPtr->subFontArray[0]); + + fontPtr->controlSubFont = fontPtr->subFontArray[0]; + subFontPtr = FindSubFontForChar(fontPtr, '0', NULL); + controlPtr = &fontPtr->controlSubFont; + controlPtr->fontStructPtr = subFontPtr->fontStructPtr; + controlPtr->familyPtr = &tsdPtr->controlFamily; + controlPtr->fontMap = tsdPtr->controlFamily.fontMap; + + pageMap = fontPtr->subFontArray[0].fontMap[0]; + for (i = 0; i < 256; i++) { + if ((minHi > 0) || (i < minLo) || (i > maxLo) + || !((pageMap[i>>3] >> (i&7)) & 1)) { + n = 0; + } else if (fontStructPtr->per_char == NULL) { + n = fontStructPtr->max_bounds.width; + } else { + n = fontStructPtr->per_char[i - minLo].width; + } + fontPtr->widths[i] = n; + } + + if (XGetFontProperty(fontStructPtr, XA_UNDERLINE_POSITION, &value)) { + fontPtr->underlinePos = value; + } else { + /* + * If the XA_UNDERLINE_POSITION property does not exist, the X manual + * recommends using the following value: + */ + + fontPtr->underlinePos = fontStructPtr->descent / 2; + } + fontPtr->barHeight = 0; + if (XGetFontProperty(fontStructPtr, XA_UNDERLINE_THICKNESS, &value)) { + fontPtr->barHeight = value; + } + if (fontPtr->barHeight == 0) { + /* + * If the XA_UNDERLINE_THICKNESS property does not exist, the X manual + * recommends using the width of the stem on a capital letter. I don't + * know of a way to get the stem width of a letter, so guess and use + * 1/3 the width of a capital I. + */ + + fontPtr->barHeight = fontPtr->widths['I'] / 3; + if (fontPtr->barHeight == 0) { + fontPtr->barHeight = 1; + } + } + if (fontPtr->underlinePos + fontPtr->barHeight > fontStructPtr->descent) { + /* + * If this set of cobbled together values would cause the bottom of + * the underline bar to stick below the descent of the font, jack the + * underline up a bit higher. + */ + + fontPtr->barHeight = fontStructPtr->descent - fontPtr->underlinePos; + if (fontPtr->barHeight == 0) { + fontPtr->underlinePos--; + fontPtr->barHeight = 1; + } + } +} + +/* + *------------------------------------------------------------------------- + * + * ReleaseFont -- + * + * Called to release the unix-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( + UnixFont *fontPtr) /* The font to delete. */ +{ + int i; + + for (i = 0; i < fontPtr->numSubFonts; i++) { + ReleaseSubFont(fontPtr->display, &fontPtr->subFontArray[i]); + } + if (fontPtr->subFontArray != fontPtr->staticSubFonts) { + ckfree(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( + Display *display, /* Display in which font will be used. */ + XFontStruct *fontStructPtr, /* 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->fontStructPtr = fontStructPtr; + subFontPtr->familyPtr = AllocFontFamily(display, fontStructPtr, 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( + Display *display, /* Display which owns screen font. */ + SubFont *subFontPtr) /* The SubFont to delete. */ +{ + XFreeFont(display, subFontPtr->fontStructPtr); + 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( + Display *display, /* Display in which font will be used. */ + XFontStruct *fontStructPtr, /* 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. */ +{ + FontFamily *familyPtr; + FontAttributes fa; + Tcl_Encoding encoding; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + GetFontAttributes(display, fontStructPtr, &fa); + encoding = Tcl_GetEncoding(NULL, GetEncodingAlias(fa.xa.charset)); + + familyPtr = tsdPtr->fontFamilyList; + for (; familyPtr != NULL; familyPtr = familyPtr->nextPtr) { + if ((familyPtr->faceName == fa.fa.family) + && (familyPtr->foundry == fa.xa.foundry) + && (familyPtr->encoding == encoding)) { + if (encoding) { + Tcl_FreeEncoding(encoding); + } + familyPtr->refCount++; + return familyPtr; + } + } + + familyPtr = ckalloc(sizeof(FontFamily)); + memset(familyPtr, 0, sizeof(FontFamily)); + familyPtr->nextPtr = tsdPtr->fontFamilyList; + tsdPtr->fontFamilyList = familyPtr; + + /* + * Set key for this FontFamily. + */ + + familyPtr->foundry = fa.xa.foundry; + familyPtr->faceName = fa.fa.family; + familyPtr->encoding = encoding; + + /* + * 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; + + /* + * One byte/character fonts have both min_byte1 and max_byte1 0, and + * max_char_or_byte2 <= 255. Anything else specifies a two byte/character + * font. + */ + + familyPtr->isTwoByteFont = !( + (fontStructPtr->min_byte1 == 0) && + (fontStructPtr->max_byte1 == 0) && + (fontStructPtr->max_char_or_byte2 < 256)); + return familyPtr; +} + +/* + *------------------------------------------------------------------------- + * + * FreeFontFamily -- + * + * Called to free an 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. */ +{ + FontFamily **familyPtrPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + int i; + + if (familyPtr == NULL) { + return; + } + familyPtr->refCount--; + if (familyPtr->refCount > 0) { + return; + } + if (familyPtr->encoding) { + Tcl_FreeEncoding(familyPtr->encoding); + } + for (i = 0; i < FONTMAP_PAGES; i++) { + if (familyPtr->fontMap[i] != NULL) { + ckfree(familyPtr->fontMap[i]); + } + } + + /* + * Delete from list. + */ + + for (familyPtrPtr = &tsdPtr->fontFamilyList; ; ) { + if (*familyPtrPtr == familyPtr) { + *familyPtrPtr = familyPtr->nextPtr; + break; + } + familyPtrPtr = &(*familyPtrPtr)->nextPtr; + } + + ckfree(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. The + * table of SubFonts might be extended, and if a non-NULL reference to a + * subfont pointer is available, it is updated if it previously pointed + * into the old subfont table. + * + *------------------------------------------------------------------------- + */ + +static SubFont * +FindSubFontForChar( + UnixFont *fontPtr, /* The font object with which the character + * will be displayed. */ + int ch, /* The Unicode character to be displayed. */ + SubFont **fixSubFontPtrPtr) /* Subfont reference to fix up if we + * reallocate our subfont table. */ +{ + int i, j, k, numNames; + Tk_Uid faceName; + const char *fallback; + const char *const *aliases; + char **nameList; + const char *const *anyFallbacks; + const char *const *const *fontFallbacks; + SubFont *subFontPtr; + Tcl_DString ds; + + if (FontMapLookup(&fontPtr->subFontArray[0], ch)) { + return &fontPtr->subFontArray[0]; + } + + for (i = 1; i < fontPtr->numSubFonts; i++) { + if (FontMapLookup(&fontPtr->subFontArray[i], ch)) { + return &fontPtr->subFontArray[i]; + } + } + + if (FontMapLookup(&fontPtr->controlSubFont, ch)) { + return &fontPtr->controlSubFont; + } + + /* + * 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); + + /* + * Are there any other fonts with the same face name as the base font that + * could display this character, e.g., if the base font is + * adobe:fixed:iso8859-1, we could might be able to use + * misc:fixed:iso8859-8 or sony:fixed:jisx0208.1983-0 + */ + + faceName = fontPtr->font.fa.family; + if (SeenName(faceName, &ds) == 0) { + subFontPtr = CanUseFallback(fontPtr, faceName, ch, fixSubFontPtrPtr); + if (subFontPtr != NULL) { + goto end; + } + } + + aliases = TkFontGetAliasList(faceName); + + subFontPtr = NULL; + fontFallbacks = TkFontGetFallbacks(); + for (i = 0; fontFallbacks[i] != NULL; i++) { + for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) { + if (strcasecmp(fallback, faceName) == 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(fallback, aliases[k]) == 0) { + goto tryfallbacks; + } + } + } + } + continue; + + tryfallbacks: + + /* + * ...then see if we can use one of the fallbacks, or an alias for one + * of the fallbacks. + */ + + for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) { + subFontPtr = CanUseFallbackWithAliases(fontPtr, fallback, ch, &ds, + fixSubFontPtrPtr); + if (subFontPtr != NULL) { + goto end; + } + } + } + + /* + * See if we can use something from the global fallback list. + */ + + anyFallbacks = TkFontGetGlobalClass(); + for (i = 0; (fallback = anyFallbacks[i]) != NULL; i++) { + subFontPtr = CanUseFallbackWithAliases(fontPtr, fallback, ch, &ds, + fixSubFontPtrPtr); + if (subFontPtr != NULL) { + goto end; + } + } + + /* + * Try all face names available in the whole system until we find one that + * can be used. + */ + + nameList = ListFonts(fontPtr->display, "*", &numNames); + for (i = 0; i < numNames; i++) { + fallback = strchr(nameList[i] + 1, '-') + 1; + strchr(fallback, '-')[0] = '\0'; + if (SeenName(fallback, &ds) == 0) { + subFontPtr = CanUseFallback(fontPtr, fallback, ch, + fixSubFontPtrPtr); + if (subFontPtr != NULL) { + XFreeFontNames(nameList); + goto end; + } + } + } + XFreeFontNames(nameList); + + end: + Tcl_DStringFree(&ds); + + if (subFontPtr == NULL) { + /* + * No font can display this character, so it will be displayed as a + * control character expansion. + */ + + subFontPtr = &fontPtr->controlSubFont; + FontMapInsert(subFontPtr, ch); + } + return subFontPtr; +} + +/* + *------------------------------------------------------------------------- + * + * 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 +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. */ +{ + 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 screen font can (1) or cannot (0) display the + * characters on the page. + * + * Results: + * None. + * + * Side effects: + * Memory 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. */ +{ + char buf[16], src[6]; + int minHi, maxHi, minLo, maxLo, scale, checkLo; + int i, end, bitOffset, isTwoByteFont, n; + Tcl_Encoding encoding; + XFontStruct *fontStructPtr; + XCharStruct *widths; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + subFontPtr->fontMap[row] = ckalloc(FONTMAP_BITSPERPAGE / 8); + memset(subFontPtr->fontMap[row], 0, FONTMAP_BITSPERPAGE / 8); + + if (subFontPtr->familyPtr == &tsdPtr->controlFamily) { + return; + } + + fontStructPtr = subFontPtr->fontStructPtr; + encoding = subFontPtr->familyPtr->encoding; + isTwoByteFont = subFontPtr->familyPtr->isTwoByteFont; + + widths = fontStructPtr->per_char; + minHi = fontStructPtr->min_byte1; + maxHi = fontStructPtr->max_byte1; + minLo = fontStructPtr->min_char_or_byte2; + maxLo = fontStructPtr->max_char_or_byte2; + scale = maxLo - minLo + 1; + checkLo = minLo; + + if (! isTwoByteFont) { + if (minLo < 32) { + checkLo = 32; + } + } + + end = (row + 1) << FONTMAP_SHIFT; + for (i = row << FONTMAP_SHIFT; i < end; i++) { + int hi, lo; + + if (Tcl_UtfToExternal(NULL, encoding, src, TkUniCharToUtf(i, src), + TCL_ENCODING_STOPONERROR, NULL, buf, sizeof(buf), NULL, + NULL, NULL) != TCL_OK) { + continue; + } + if (isTwoByteFont) { + hi = ((unsigned char *) buf)[0]; + lo = ((unsigned char *) buf)[1]; + } else { + hi = 0; + lo = ((unsigned char *) buf)[0]; + } + if ((hi < minHi) || (hi > maxHi) || (lo < checkLo) || (lo > maxLo)) { + continue; + } + n = (hi - minHi) * scale + lo - minLo; + if ((widths == NULL) || (widths[n].width + widths[n].rbearing != 0)) { + 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. + * The table of SubFonts might be extended, and if a non-NULL reference + * to a subfont pointer is available, it is updated if it previously + * pointed into the old subfont table. + * + *--------------------------------------------------------------------------- + */ + +static SubFont * +CanUseFallbackWithAliases( + UnixFont *fontPtr, /* The font object that will own the new + * screen font. */ + const 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. */ + SubFont **fixSubFontPtrPtr) /* Subfont reference to fix up if we + * reallocate our subfont table. */ +{ + SubFont *subFontPtr; + const char *const *aliases; + int i; + + if (SeenName(faceName, nameTriedPtr) == 0) { + subFontPtr = CanUseFallback(fontPtr, faceName, ch, fixSubFontPtrPtr); + 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(fontPtr, aliases[i], ch, + fixSubFontPtrPtr); + 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, name, (int) (strlen(name) + 1)); + return 0; +} + +/* + *------------------------------------------------------------------------- + * + * CanUseFallback -- + * + * If the specified screen font has not already been loaded into the font + * object, determine if the specified screen font 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 face + * name. NULL is returned if the font object already holds a reference to + * the specified font or if the specified font doesn't exist or cannot + * display the given character. + * + * Side effects: + * The font object's subFontArray is updated to contain a reference to + * the newly allocated SubFont. The table of SubFonts might be extended, + * and if a non-NULL reference to a subfont pointer is available, it is + * updated if it previously pointed into the old subfont table. + * + *------------------------------------------------------------------------- + */ + +static SubFont * +CanUseFallback( + UnixFont *fontPtr, /* The font object that will own the new + * screen font. */ + const char *faceName, /* Desired face name for new screen font. */ + int ch, /* The Unicode character that the new screen + * font must be able to display. */ + SubFont **fixSubFontPtrPtr) /* Subfont reference to fix up if we + * reallocate our subfont table. */ +{ + int i, nameIdx, numNames, srcLen, numEncodings, bestIdx[2]; + Tk_Uid hateFoundry; + const char *charset, *hateCharset; + unsigned bestScore[2]; + char **nameList; + char **nameListOrig; + char src[6]; + FontAttributes want, got; + Display *display; + SubFont subFont; + XFontStruct *fontStructPtr; + Tcl_DString dsEncodings; + Tcl_Encoding *encodingCachePtr; + + /* + * Assume: the face name is times. + * Assume: adobe:times:iso8859-1 has already been used. + * + * Are there any versions of times that can display this character (e.g., + * perhaps linotype:times:iso8859-2)? + * a. Get list of all times fonts. + * b1. Cross out all names whose encodings we've already used. + * b2. Cross out all names whose foundry & encoding we've already seen. + * c. Cross out all names whose encoding cannot handle the character. + * d. Rank each name and pick the best match. + * e. If that font cannot actually display the character, cross out all + * names with the same foundry and encoding and go back to (c). + */ + + display = fontPtr->display; + nameList = ListFonts(display, faceName, &numNames); + if (numNames == 0) { + return NULL; + } + nameListOrig = nameList; + + srcLen = TkUniCharToUtf(ch, src); + + want.fa = fontPtr->font.fa; + want.xa = fontPtr->xa; + + want.fa.family = Tk_GetUid(faceName); + want.fa.size = (double)-fontPtr->pixelSize; + + hateFoundry = NULL; + hateCharset = NULL; + numEncodings = 0; + Tcl_DStringInit(&dsEncodings); + + charset = NULL; /* lint, since numNames must be > 0 to get here. */ + + retry: + bestIdx[0] = -1; + bestIdx[1] = -1; + bestScore[0] = (unsigned) -1; + bestScore[1] = (unsigned) -1; + for (nameIdx = 0; nameIdx < numNames; nameIdx++) { + Tcl_Encoding encoding; + char dst[16]; + int scalable, srcRead, dstWrote; + unsigned score; + + if (nameList[nameIdx] == NULL) { + continue; + } + if (TkFontParseXLFD(nameList[nameIdx], &got.fa, &got.xa) != TCL_OK) { + goto crossout; + } + IdentifySymbolEncodings(&got); + charset = GetEncodingAlias(got.xa.charset); + if (hateFoundry != NULL) { + /* + * E. If the font we picked cannot actually display the character, + * cross out all names with the same foundry and encoding. + */ + + if ((hateFoundry == got.xa.foundry) + && (strcmp(hateCharset, charset) == 0)) { + goto crossout; + } + } else { + /* + * B. Cross out all names whose encodings we've already used. + */ + + for (i = 0; i < fontPtr->numSubFonts; i++) { + encoding = fontPtr->subFontArray[i].familyPtr->encoding; + if (strcmp(charset, Tcl_GetEncodingName(encoding)) == 0) { + goto crossout; + } + } + } + + /* + * C. Cross out all names whose encoding cannot handle the character. + */ + + encodingCachePtr = (Tcl_Encoding *) Tcl_DStringValue(&dsEncodings); + for (i = numEncodings; --i >= 0; encodingCachePtr++) { + encoding = *encodingCachePtr; + if (strcmp(Tcl_GetEncodingName(encoding), charset) == 0) { + break; + } + } + if (i < 0) { + encoding = Tcl_GetEncoding(NULL, charset); + if (encoding == NULL) { + goto crossout; + } + + Tcl_DStringAppend(&dsEncodings, (char *) &encoding, + sizeof(encoding)); + numEncodings++; + } + Tcl_UtfToExternal(NULL, encoding, src, srcLen, + TCL_ENCODING_STOPONERROR, NULL, dst, sizeof(dst), &srcRead, + &dstWrote, NULL); + if (dstWrote == 0) { + goto crossout; + } + + /* + * D. Rank each name and pick the best match. + */ + + scalable = (got.fa.size == 0.0); + score = RankAttributes(&want, &got); + if (score < bestScore[scalable]) { + bestIdx[scalable] = nameIdx; + bestScore[scalable] = score; + } + if (score == 0) { + break; + } + continue; + + crossout: + if (nameList == nameListOrig) { + /* + * Not allowed to change pointers to memory that X gives you, so + * make a copy. + */ + + nameList = ckalloc(numNames * sizeof(char *)); + memcpy(nameList, nameListOrig, numNames * sizeof(char *)); + } + nameList[nameIdx] = NULL; + } + + fontStructPtr = GetScreenFont(display, &want, nameList, bestIdx, + bestScore); + + encodingCachePtr = (Tcl_Encoding *) Tcl_DStringValue(&dsEncodings); + for (i = numEncodings; --i >= 0; encodingCachePtr++) { + Tcl_FreeEncoding(*encodingCachePtr); + } + Tcl_DStringFree(&dsEncodings); + numEncodings = 0; + + if (fontStructPtr == NULL) { + if (nameList != nameListOrig) { + ckfree(nameList); + } + XFreeFontNames(nameListOrig); + return NULL; + } + + InitSubFont(display, fontStructPtr, 0, &subFont); + if (FontMapLookup(&subFont, ch) == 0) { + /* + * E. If the font we picked cannot actually display the character, + * cross out all names with the same foundry and encoding and pick + * another font. + */ + + hateFoundry = got.xa.foundry; + hateCharset = charset; + ReleaseSubFont(display, &subFont); + goto retry; + } + if (nameList != nameListOrig) { + ckfree(nameList); + } + XFreeFontNames(nameListOrig); + + if (fontPtr->numSubFonts >= SUBFONT_SPACE) { + SubFont *newPtr; + + newPtr = ckalloc(sizeof(SubFont) * (fontPtr->numSubFonts + 1)); + memcpy(newPtr, fontPtr->subFontArray, + fontPtr->numSubFonts * sizeof(SubFont)); + if (fixSubFontPtrPtr != NULL) { + register SubFont *fixSubFontPtr = *fixSubFontPtrPtr; + + if (fixSubFontPtr != &fontPtr->controlSubFont) { + *fixSubFontPtrPtr = + newPtr + (fixSubFontPtr - fontPtr->subFontArray); + } + } + if (fontPtr->subFontArray != fontPtr->staticSubFonts) { + ckfree(fontPtr->subFontArray); + } + fontPtr->subFontArray = newPtr; + } + fontPtr->subFontArray[fontPtr->numSubFonts] = subFont; + fontPtr->numSubFonts++; + return &fontPtr->subFontArray[fontPtr->numSubFonts - 1]; +} + +/* + *--------------------------------------------------------------------------- + * + * RankAttributes -- + * + * Determine how close the attributes of the font in question match the + * attributes that we want. + * + * Results: + * The return value is the score; lower numbers are better. *scalablePtr + * is set to 0 if the font was not scalable, 1 otherwise. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +static unsigned +RankAttributes( + FontAttributes *wantPtr, /* The desired attributes. */ + FontAttributes *gotPtr) /* The attributes we have to live with. */ +{ + unsigned penalty; + + penalty = 0; + if (gotPtr->xa.foundry != wantPtr->xa.foundry) { + penalty += 4500; + } + if (gotPtr->fa.family != wantPtr->fa.family) { + penalty += 9000; + } + if (gotPtr->fa.weight != wantPtr->fa.weight) { + penalty += 90; + } + if (gotPtr->fa.slant != wantPtr->fa.slant) { + penalty += 60; + } + if (gotPtr->xa.slant != wantPtr->xa.slant) { + penalty += 10; + } + if (gotPtr->xa.setwidth != wantPtr->xa.setwidth) { + penalty += 1000; + } + + if (gotPtr->fa.size == 0.0) { + /* + * A scalable font is almost always acceptable, but the corresponding + * bitmapped font would be better. + */ + + penalty += 10; + } else { + int diff; + + /* + * It's worse to be too large than to be too small. + */ + + diff = (int) (150 * (-gotPtr->fa.size - -wantPtr->fa.size)); + if (diff > 0) { + penalty += 600; + } else if (diff < 0) { + penalty += 150; + diff = -diff; + } + penalty += diff; + } + if (gotPtr->xa.charset != wantPtr->xa.charset) { + int i; + const char *gotAlias, *wantAlias; + + penalty += 65000; + gotAlias = GetEncodingAlias(gotPtr->xa.charset); + wantAlias = GetEncodingAlias(wantPtr->xa.charset); + if (strcmp(gotAlias, wantAlias) != 0) { + penalty += 30000; + for (i = 0; encodingList[i] != NULL; i++) { + if (strcmp(gotAlias, encodingList[i]) == 0) { + penalty -= 30000; + break; + } + penalty += 20000; + } + } + } + return penalty; +} + +/* + *--------------------------------------------------------------------------- + * + * GetScreenFont -- + * + * Given the names for the best scalable and best bitmapped font, + * actually construct an XFontStruct based on the best XLFD. This is + * where all the alias and fallback substitution bottoms out. + * + * Results: + * The screen font that best corresponds to the set of attributes. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +static XFontStruct * +GetScreenFont( + Display *display, /* Display for new XFontStruct. */ + FontAttributes *wantPtr, /* Contains desired actual pixel-size if the + * best font was scalable. */ + char **nameList, /* Array of XLFDs. */ + int bestIdx[2], /* Indices into above array for XLFD of best + * bitmapped and best scalable font. */ + unsigned bestScore[2]) /* Scores of best bitmapped and best scalable + * font. XLFD corresponding to lowest score + * will be constructed. */ +{ + XFontStruct *fontStructPtr; + + if ((bestIdx[0] < 0) && (bestIdx[1] < 0)) { + return NULL; + } + + /* + * Now we know which is the closest matching scalable font and the closest + * matching bitmapped font. If the scalable font was a better match, try + * getting the scalable font; however, if the scalable font was not + * actually available in the desired pointsize, fall back to the closest + * bitmapped font. + */ + + fontStructPtr = NULL; + if (bestScore[1] < bestScore[0]) { + char *str, *rest, buf[256]; + int i; + + /* + * Fill in the desired pixel size for this font. + */ + + tryscale: + str = nameList[bestIdx[1]]; + for (i = 0; i < XLFD_PIXEL_SIZE; i++) { + str = strchr(str + 1, '-'); + } + rest = str; + for (i = XLFD_PIXEL_SIZE; i < XLFD_CHARSET; i++) { + rest = strchr(rest + 1, '-'); + } + *str = '\0'; + sprintf(buf, "%.200s-%d-*-*-*-*-*%s", nameList[bestIdx[1]], + (int)(-wantPtr->fa.size+0.5), rest); + *str = '-'; + fontStructPtr = XLoadQueryFont(display, buf); + bestScore[1] = INT_MAX; + } + if (fontStructPtr == NULL) { + fontStructPtr = XLoadQueryFont(display, nameList[bestIdx[0]]); + if (fontStructPtr == NULL) { + /* + * This shouldn't happen because the font name is one of the names + * that X gave us to use, but it does anyhow. + */ + + if (bestScore[1] < INT_MAX) { + goto tryscale; + } + return GetSystemFont(display); + } + } + return fontStructPtr; +} + +/* + *--------------------------------------------------------------------------- + * + * GetSystemFont -- + * + * Absolute fallback mechanism, called when we need a font and no other + * font can be found and/or instantiated. + * + * Results: + * A pointer to a font. Never NULL. + * + * Side effects: + * If there are NO fonts installed on the system, this call will panic, + * but how did you get X running in that case? + * + *--------------------------------------------------------------------------- + */ + +static XFontStruct * +GetSystemFont( + Display *display) /* Display for new XFontStruct. */ +{ + XFontStruct *fontStructPtr; + + fontStructPtr = XLoadQueryFont(display, "fixed"); + if (fontStructPtr == NULL) { + fontStructPtr = XLoadQueryFont(display, "*"); + if (fontStructPtr == NULL) { + Tcl_Panic("TkpGetFontFromAttributes: cannot get any font"); + } + } + return fontStructPtr; +} + +/* + *--------------------------------------------------------------------------- + * + * GetFontAttributes -- + * + * Given a screen font, determine its actual attributes, which are not + * necessarily the attributes that were used to construct it. + * + * Results: + * *faPtr is filled with the screen font's attributes. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +static int +GetFontAttributes( + Display *display, /* Display that owns the screen font. */ + XFontStruct *fontStructPtr, /* Screen font to query. */ + FontAttributes *faPtr) /* For storing attributes of screen font. */ +{ + unsigned long value; + char *name; + + if ((XGetFontProperty(fontStructPtr, XA_FONT, &value) != False) && + (value != 0)) { + name = XGetAtomName(display, (Atom) value); + if (TkFontParseXLFD(name, &faPtr->fa, &faPtr->xa) != TCL_OK) { + faPtr->fa.family = Tk_GetUid(name); + faPtr->xa.foundry = Tk_GetUid(""); + faPtr->xa.charset = Tk_GetUid(""); + } + XFree(name); + } else { + TkInitFontAttributes(&faPtr->fa); + TkInitXLFDAttributes(&faPtr->xa); + } + + /* + * Do last ditch check for family. It seems that some X servers can fail + * on the X font calls above, slipping through earlier checks. X-Win32 5.4 + * is one of these. + */ + + if (faPtr->fa.family == NULL) { + faPtr->fa.family = Tk_GetUid(""); + faPtr->xa.foundry = Tk_GetUid(""); + faPtr->xa.charset = Tk_GetUid(""); + } + return IdentifySymbolEncodings(faPtr); +} + +/* + *--------------------------------------------------------------------------- + * + * ListFonts -- + * + * Utility function to return the array of all XLFDs on the system with + * the specified face name. + * + * Results: + * The return value is an array of XLFDs, which should be freed with + * XFreeFontNames(), or NULL if no XLFDs matched the requested name. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +static char ** +ListFonts( + Display *display, /* Display to query. */ + const char *faceName, /* Desired face name, or "*" for all. */ + int *numNamesPtr) /* Filled with length of returned array, or 0 + * if no names were found. */ +{ + char buf[256]; + + sprintf(buf, "-*-%.80s-*-*-*-*-*-*-*-*-*-*-*-*", faceName); + return XListFonts(display, buf, 10000, numNamesPtr); +} + +static char ** +ListFontOrAlias( + Display *display, /* Display to query. */ + const char *faceName, /* Desired face name, or "*" for all. */ + int *numNamesPtr) /* Filled with length of returned array, or 0 + * if no names were found. */ +{ + char **nameList; + const char *const *aliases; + int i; + + nameList = ListFonts(display, faceName, numNamesPtr); + if (nameList != NULL) { + return nameList; + } + aliases = TkFontGetAliasList(faceName); + if (aliases != NULL) { + for (i = 0; aliases[i] != NULL; i++) { + nameList = ListFonts(display, aliases[i], numNamesPtr); + if (nameList != NULL) { + return nameList; + } + } + } + *numNamesPtr = 0; + return NULL; +} + +/* + *--------------------------------------------------------------------------- + * + * IdentifySymbolEncodings -- + * + * If the font attributes refer to a symbol font, update the charset + * field of the font attributes so that it reflects the encoding of that + * symbol font. In general, the raw value for the charset field parsed + * from an XLFD is meaningless for symbol fonts. + * + * Symbol fonts are all fonts whose name appears in the symbolClass. + * + * Results: + * The return value is non-zero if the font attributes specify a symbol + * font, or 0 otherwise. If a non-zero value is returned the charset + * field of the font attributes will be changed to the string that + * represents the actual encoding for the symbol font. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +static int +IdentifySymbolEncodings( + FontAttributes *faPtr) +{ + int i, j; + const char *const *aliases; + const char *const *symbolClass; + + symbolClass = TkFontGetSymbolClass(); + for (i = 0; symbolClass[i] != NULL; i++) { + if (strcasecmp(faPtr->fa.family, symbolClass[i]) == 0) { + faPtr->xa.charset = Tk_GetUid(GetEncodingAlias(symbolClass[i])); + return 1; + } + aliases = TkFontGetAliasList(symbolClass[i]); + for (j = 0; (aliases != NULL) && (aliases[j] != NULL); j++) { + if (strcasecmp(faPtr->fa.family, aliases[j]) == 0) { + faPtr->xa.charset = Tk_GetUid(GetEncodingAlias(aliases[j])); + return 1; + } + } + } + return 0; +} + +/* + *--------------------------------------------------------------------------- + * + * GetEncodingAlias -- + * + * Map the name of an encoding to another name that should be used when + * actually loading the encoding. For instance, the encodings + * "jisc6226.1978", "jisx0208.1983", "jisx0208.1990", and "jisx0208.1996" + * are well-known names for the same encoding and are represented by one + * encoding table: "jis0208". + * + * Results: + * As above. If the name has no alias, the original name is returned. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +static const char * +GetEncodingAlias( + const char *name) /* The name to look up. */ +{ + EncodingAlias *aliasPtr; + + for (aliasPtr = encodingAliases; aliasPtr->aliasPattern != NULL; ) { + if (Tcl_StringMatch(name, aliasPtr->aliasPattern)) { + return aliasPtr->realName; + } + aliasPtr++; + } + return name; +} + +/* + *--------------------------------------------------------------------------- + * + * TkDrawAngledChars -- + * + * Draw some characters at an angle. This is awkward here because we have + * no reliable way of drawing any characters at an angle in classic X11; + * we have to draw on a Pixmap which is converted to an XImage (from + * helper function GetImageOfText), rotate the image (hokey code!) onto + * another XImage (from helper function InitDestImage), and then use the + * rotated image as a mask when drawing. This is pretty awful; improved + * versions are welcomed! + * + * Results: + * None. + * + * Side effects: + * Target drawable is updated. + * + *--------------------------------------------------------------------------- + */ + +static inline XImage * +GetImageOfText( + Display *display, /* Display on which to draw. */ + Drawable drawable, /* Window or pixmap in which to draw. */ + Tk_Font tkfont, /* Font in which characters will be drawn. */ + 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 numBytes, /* Number of bytes in string. */ + int *realWidthPtr, int *realHeightPtr) +{ + int width, height; + TkFont *fontPtr = (TkFont *) tkfont; + Pixmap bitmap; + GC bitmapGC; + XGCValues values; + XImage *image; + + (void) Tk_MeasureChars(tkfont, source, numBytes, -1, 0, &width); + height = fontPtr->fm.ascent + fontPtr->fm.descent; + + bitmap = Tk_GetPixmap(display, drawable, width, height, 1); + values.graphics_exposures = False; + values.foreground = BlackPixel(display, DefaultScreen(display)); + bitmapGC = XCreateGC(display, bitmap, GCGraphicsExposures|GCForeground, + &values); + XFillRectangle(display, bitmap, bitmapGC, 0, 0, width, height); + + values.font = Tk_FontId(tkfont); + values.foreground = WhitePixel(display, DefaultScreen(display)); + values.background = BlackPixel(display, DefaultScreen(display)); + XChangeGC(display, bitmapGC, GCFont|GCForeground|GCBackground, &values); + Tk_DrawChars(display, bitmap, bitmapGC, tkfont, source, numBytes, 0, + fontPtr->fm.ascent); + XFreeGC(display, bitmapGC); + + image = XGetImage(display, bitmap, 0, 0, width, height, AllPlanes, + ZPixmap); + Tk_FreePixmap(display, bitmap); + + *realWidthPtr = width; + *realHeightPtr = height; + return image; +} + +static inline XImage * +InitDestImage( + Display *display, + Drawable drawable, + int width, + int height, + Pixmap *bitmapPtr) +{ + Pixmap bitmap; + XImage *image; + GC bitmapGC; + XGCValues values; + + bitmap = Tk_GetPixmap(display, drawable, width, height, 1); + values.graphics_exposures = False; + values.foreground = BlackPixel(display, DefaultScreen(display)); + bitmapGC = XCreateGC(display, bitmap, GCGraphicsExposures|GCForeground, + &values); + XFillRectangle(display, bitmap, bitmapGC, 0, 0, width, height); + XFreeGC(display, bitmapGC); + + image = XGetImage(display, bitmap, 0, 0, width, height, AllPlanes, + ZPixmap); + *bitmapPtr = bitmap; + return image; +} + +void +TkDrawAngledChars( + 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, /* 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 numBytes, /* Number of bytes in string. */ + double x, double y, + double angle) +{ + if (angle == 0.0) { + Tk_DrawChars(display, drawable, gc, tkfont, source, numBytes, x, y); + } else { + double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0); + int bufHeight, bufWidth, srcWidth, srcHeight, i, j, dx, dy; + Pixmap buf; + XImage *srcImage = GetImageOfText(display, drawable, tkfont, source, + numBytes, &srcWidth, &srcHeight); + XImage *dstImage; + enum {Q0=1,R1,Q1,R2,Q2,R3,Q3} quadrant; + GC bwgc, cpgc; + XGCValues values; + int ascent = ((TkFont *) tkfont)->fm.ascent; + + /* + * First, work out what quadrant we are operating in. We also handle + * the rectilinear rotations as special cases. Conceptually, there's + * also R0 (angle == 0.0) but that has been already handled as a + * special case above. + * + * R1 + * Q1 | Q0 + * | + * R2 ----+---- R0 + * | + * Q2 | Q3 + * R3 + */ + + if (angle < 90.0) { + quadrant = Q0; + } else if (angle == 90.0) { + quadrant = R1; + } else if (angle < 180.0) { + quadrant = Q1; + } else if (angle == 180.0) { + quadrant = R2; + } else if (angle < 270.0) { + quadrant = Q2; + } else if (angle == 270.0) { + quadrant = R3; + } else { + quadrant = Q3; + } + + if (srcImage == NULL) { + return; + } + bufWidth = srcWidth*fabs(cosA) + srcHeight*fabs(sinA); + bufHeight = srcHeight*fabs(cosA) + srcWidth*fabs(sinA); + dstImage = InitDestImage(display, drawable, bufWidth,bufHeight, &buf); + if (dstImage == NULL) { + Tk_FreePixmap(display, buf); + XDestroyImage(srcImage); + return; + } + + /* + * Do the rotation, setting or resetting pixels in the destination + * image dependent on whether the corresponding pixel (after rotation + * to source image space) is set. + */ + + for (i=0 ; i<srcWidth ; i++) { + for (j=0 ; j<srcHeight ; j++) { + switch (quadrant) { + case Q0: + dx = ROUND16(i*cosA + j*sinA); + dy = ROUND16(j*cosA + (srcWidth - i)*sinA); + break; + case R1: + dx = j; + dy = srcWidth - i; + break; + case Q1: + dx = ROUND16((i - srcWidth)*cosA + j*sinA); + dy = ROUND16((srcWidth-i)*sinA + (j-srcHeight)*cosA); + break; + case R2: + dx = srcWidth - i; + dy = srcHeight - j; + break; + case Q2: + dx = ROUND16((i-srcWidth)*cosA + (j-srcHeight)*sinA); + dy = ROUND16((j - srcHeight)*cosA - i*sinA); + break; + case R3: + dx = srcHeight - j; + dy = i; + break; + default: + dx = ROUND16(i*cosA + (j - srcHeight)*sinA); + dy = ROUND16(j*cosA - i*sinA); + } + + if (dx < 0 || dy < 0 || dx >= bufWidth || dy >= bufHeight) { + continue; + } + XPutPixel(dstImage, dx, dy, + XGetPixel(dstImage,dx,dy) | XGetPixel(srcImage,i,j)); + } + } + XDestroyImage(srcImage); + + /* + * Schlep the data back to the Xserver. + */ + + values.function = GXcopy; + values.foreground = WhitePixel(display, DefaultScreen(display)); + values.background = BlackPixel(display, DefaultScreen(display)); + bwgc = XCreateGC(display, buf, GCFunction|GCForeground|GCBackground, + &values); + XPutImage(display, buf, bwgc, dstImage, 0,0, 0,0, bufWidth,bufHeight); + XFreeGC(display, bwgc); + XDestroyImage(dstImage); + + /* + * Calculate where we want to draw the text. + */ + + switch (quadrant) { + case Q0: + dx = x; + dy = y - srcWidth*sinA; + break; + case R1: + dx = x; + dy = y - srcWidth; + break; + case Q1: + dx = x + srcWidth*cosA; + dy = y + srcHeight*cosA - srcWidth*sinA; + break; + case R2: + dx = x - srcWidth; + dy = y - srcHeight; + break; + case Q2: + dx = x + srcWidth*cosA + srcHeight*sinA; + dy = y + srcHeight*cosA; + break; + case R3: + dx = x - srcHeight; + dy = y; + break; + default: + dx = x + srcHeight*sinA; + dy = y; + } + + /* + * Apply a correction to deal with the fact that we aren't told to + * draw from our top-left corner but rather from the left-end of our + * baseline. + */ + + dx -= ascent*sinA; + dy -= ascent*cosA; + + /* + * Transfer the text to the screen. This is done by using it as a mask + * and then drawing through that mask with the original drawing color. + */ + + values.function = GXcopy; + values.fill_style = FillSolid; + values.clip_mask = buf; + values.clip_x_origin = dx; + values.clip_y_origin = dy; + cpgc = XCreateGC(display, drawable, + GCFunction|GCFillStyle|GCClipMask|GCClipXOrigin|GCClipYOrigin, + &values); + XCopyGC(display, gc, GCForeground, cpgc); + XFillRectangle(display, drawable, cpgc, dx, dy, bufWidth, + bufHeight); + XFreeGC(display, cpgc); + + Tk_FreePixmap(display, buf); + return; + } +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixInit.c b/tk8.6/unix/tkUnixInit.c new file mode 100644 index 0000000..b0aa2fa --- /dev/null +++ b/tk8.6/unix/tkUnixInit.c @@ -0,0 +1,162 @@ +/* + * tkUnixInit.c -- + * + * This file contains Unix-specific interpreter initialization functions. + * + * 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. + */ + +#include "tkUnixInt.h" + +#ifdef HAVE_COREFOUNDATION +static int GetLibraryPath(Tcl_Interp *interp); +#else +#define GetLibraryPath(dummy) (void)0 +#endif /* HAVE_COREFOUNDATION */ + +/* + *---------------------------------------------------------------------- + * + * TkpInit -- + * + * Performs Unix-specific interpreter initialization related to the + * tk_library variable. + * + * Results: + * Returns a standard Tcl result. Leaves an error message or result in + * the interp's result. + * + * Side effects: + * Sets "tk_library" Tcl variable, runs "tk.tcl" script. + * + *---------------------------------------------------------------------- + */ + +int +TkpInit( + Tcl_Interp *interp) +{ + TkCreateXEventSource(); + GetLibraryPath(interp); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetAppName -- + * + * Retrieves the name of the current application from a platform specific + * location. For Unix, the application name is the tail of the path + * contained in the tcl variable argv0. + * + * Results: + * Returns the application name in the given Tcl_DString. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpGetAppName( + Tcl_Interp *interp, + Tcl_DString *namePtr) /* A previously initialized Tcl_DString. */ +{ + const char *p, *name; + + name = Tcl_GetVar2(interp, "argv0", NULL, TCL_GLOBAL_ONLY); + if ((name == NULL) || (*name == 0)) { + name = "tk"; + } else { + p = strrchr(name, '/'); + if (p != NULL) { + name = p+1; + } + } + Tcl_DStringAppend(namePtr, name, -1); +} + +/* + *---------------------------------------------------------------------- + * + * TkpDisplayWarning -- + * + * This routines is called from Tk_Main to display warning messages that + * occur during startup. + * + * Results: + * None. + * + * Side effects: + * Generates messages on stdout. + * + *---------------------------------------------------------------------- + */ + +void +TkpDisplayWarning( + const char *msg, /* Message to be displayed. */ + const char *title) /* Title of warning. */ +{ + Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR); + + if (errChannel) { + Tcl_WriteChars(errChannel, title, -1); + Tcl_WriteChars(errChannel, ": ", 2); + Tcl_WriteChars(errChannel, msg, -1); + Tcl_WriteChars(errChannel, "\n", 1); + } +} + +#ifdef HAVE_COREFOUNDATION + +/* + *---------------------------------------------------------------------- + * + * GetLibraryPath -- + * + * If we have a bundle structure for the Tk installation, then check + * there first to see if we can find the libraries there. + * + * Results: + * TCL_OK if we have found the tk library; TCL_ERROR otherwise. + * + * Side effects: + * Same as for Tcl_MacOSXOpenVersionedBundleResources. + * + *---------------------------------------------------------------------- + */ + +static int +GetLibraryPath( + Tcl_Interp *interp) +{ +#ifdef TK_FRAMEWORK + int foundInFramework = TCL_ERROR; + char tkLibPath[PATH_MAX + 1]; + + foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp, + "com.tcltk.tklibrary", TK_FRAMEWORK_VERSION, 0, PATH_MAX, + tkLibPath); + if (tkLibPath[0] != '\0') { + Tcl_SetVar2(interp, "tk_library", NULL, tkLibPath, TCL_GLOBAL_ONLY); + } + return foundInFramework; +#else + return TCL_ERROR; +#endif +} +#endif /* HAVE_COREFOUNDATION */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixInt.h b/tk8.6/unix/tkUnixInt.h new file mode 100644 index 0000000..805f314 --- /dev/null +++ b/tk8.6/unix/tkUnixInt.h @@ -0,0 +1,35 @@ +/* + * tkUnixInt.h -- + * + * This file contains declarations that are shared among the + * UNIX-specific parts of Tk but aren't used by the rest of Tk. + * + * 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. + */ + +#ifndef _TKUNIXINT +#define _TKUNIXINT + +#ifndef _TKINT +#include "tkInt.h" +#endif + +/* + * Prototypes for procedures that are referenced in files other than the ones + * they're defined in. + */ + +#include "tkIntPlatDecls.h" + +#endif /* _TKUNIXINT */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixKey.c b/tk8.6/unix/tkUnixKey.c new file mode 100644 index 0000000..6d4d0cf --- /dev/null +++ b/tk8.6/unix/tkUnixKey.c @@ -0,0 +1,536 @@ +/* + * tkUnixKey.c -- + * + * This file contains routines for dealing with international keyboard + * input. + * + * 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. + */ + +#include "tkInt.h" + +/* +** Bug [3607830]: Before using Xkb, it must be initialized. TkpOpenDisplay +** does this and sets the USE_XKB flag if xkb is supported. +** (should this be function ptr?) +*/ +#ifdef HAVE_XKBKEYCODETOKEYSYM +# include <X11/XKBlib.h> +#else +# define XkbKeycodeToKeysym(D,K,G,L) XKeycodeToKeysym(D,K,L) +#endif +#define TkKeycodeToKeysym(D,K,G,L) \ + ((D)->flags & TK_DISPLAY_USE_XKB) ? \ + XkbKeycodeToKeysym((D)->display,K,G,L) : \ + XKeycodeToKeysym((D)->display,K,L) + +/* + * Prototypes for local functions defined in this file: + */ + +/* + *---------------------------------------------------------------------- + * + * Tk_SetCaretPos -- + * + * This enables correct placement of the XIM caret. This is called by + * widgets to indicate their cursor placement. This is currently only + * used for over-the-spot XIM. + * + *---------------------------------------------------------------------- + */ + +void +Tk_SetCaretPos( + Tk_Window tkwin, + int x, + int y, + int height) +{ + TkWindow *winPtr = (TkWindow *) tkwin; + TkDisplay *dispPtr = winPtr->dispPtr; + + if ((dispPtr->caret.winPtr == winPtr) + && (dispPtr->caret.x == x) + && (dispPtr->caret.y == y) + && (dispPtr->caret.height == height)) { + return; + } + + dispPtr->caret.winPtr = winPtr; + dispPtr->caret.x = x; + dispPtr->caret.y = y; + dispPtr->caret.height = height; + + /* + * Adjust the XIM caret position. + */ + +#ifdef TK_USE_INPUT_METHODS + if ((dispPtr->flags & TK_DISPLAY_USE_IM) + && (dispPtr->inputStyle & XIMPreeditPosition) + && (winPtr->inputContext != NULL)) { + XVaNestedList preedit_attr; + XPoint spot; + + spot.x = dispPtr->caret.x; + spot.y = dispPtr->caret.y + dispPtr->caret.height; + preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); + XSetICValues(winPtr->inputContext, XNPreeditAttributes, preedit_attr, + NULL); + XFree(preedit_attr); + } +#endif +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetString -- + * + * Retrieve the UTF string associated with a keyboard event. + * + * Results: + * Returns the UTF string. + * + * Side effects: + * Stores the input string in the specified Tcl_DString. Modifies the + * internal input state. This routine can only be called once for a given + * event. + * + *---------------------------------------------------------------------- + */ + +const char * +TkpGetString( + TkWindow *winPtr, /* Window where event occurred */ + XEvent *eventPtr, /* X keyboard event. */ + Tcl_DString *dsPtr) /* Initialized, empty string to hold result. */ +{ + int len; + Tcl_DString buf; + TkKeyEvent *kePtr = (TkKeyEvent *) eventPtr; + + /* + * If we have the value cached already, use it now. [Bug 1373712] + */ + + if (kePtr->charValuePtr != NULL) { + Tcl_DStringSetLength(dsPtr, kePtr->charValueLen); + memcpy(Tcl_DStringValue(dsPtr), kePtr->charValuePtr, + (unsigned) kePtr->charValueLen+1); + return Tcl_DStringValue(dsPtr); + } + + /* + * Only do this for KeyPress events, otherwise + * further Xlib function behavior might be undefined. + */ + + if (eventPtr->type != KeyPress) { + len = 0; + Tcl_DStringSetLength(dsPtr, len); + goto done; + } + +#ifdef TK_USE_INPUT_METHODS + if ((winPtr->dispPtr->flags & TK_DISPLAY_USE_IM) + && (winPtr->inputContext != NULL) + && (eventPtr->type == KeyPress)) { + Status status; + +#if X_HAVE_UTF8_STRING + Tcl_DStringSetLength(dsPtr, TCL_DSTRING_STATIC_SIZE-1); + len = Xutf8LookupString(winPtr->inputContext, &eventPtr->xkey, + Tcl_DStringValue(dsPtr), Tcl_DStringLength(dsPtr), + &kePtr->keysym, &status); + + if (status == XBufferOverflow) { + /* + * Expand buffer and try again. + */ + + Tcl_DStringSetLength(dsPtr, len); + len = Xutf8LookupString(winPtr->inputContext, &eventPtr->xkey, + Tcl_DStringValue(dsPtr), Tcl_DStringLength(dsPtr), + &kePtr->keysym, &status); + } + if ((status != XLookupChars) && (status != XLookupBoth)) { + len = 0; + } + Tcl_DStringSetLength(dsPtr, len); +#else /* !X_HAVE_UTF8_STRING */ + /* + * Overallocate the dstring to the maximum stack amount. + */ + + Tcl_DStringInit(&buf); + Tcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1); + len = XmbLookupString(winPtr->inputContext, &eventPtr->xkey, + Tcl_DStringValue(&buf), Tcl_DStringLength(&buf), + &kePtr->keysym, &status); + + /* + * If the buffer wasn't big enough, grow the buffer and try again. + */ + + if (status == XBufferOverflow) { + Tcl_DStringSetLength(&buf, len); + len = XmbLookupString(winPtr->inputContext, &eventPtr->xkey, + Tcl_DStringValue(&buf), len, &kePtr->keysym, &status); + } + if ((status != XLookupChars) && (status != XLookupBoth)) { + len = 0; + } + Tcl_DStringSetLength(&buf, len); + Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&buf), len, dsPtr); + Tcl_DStringFree(&buf); +#endif /* X_HAVE_UTF8_STRING */ + } else +#endif /* TK_USE_INPUT_METHODS */ + { + /* + * Fall back to convert a keyboard event to a UTF-8 string using + * XLookupString. This is used when input methods are turned off and + * for KeyRelease events. + * + * Note: XLookupString() normally returns a single ISO Latin 1 or + * ASCII control character. + */ + + Tcl_DStringInit(&buf); + Tcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1); + len = XLookupString(&eventPtr->xkey, Tcl_DStringValue(&buf), + TCL_DSTRING_STATIC_SIZE, &kePtr->keysym, 0); + Tcl_DStringValue(&buf)[len] = '\0'; + + if (len == 1) { + len = Tcl_UniCharToUtf((unsigned char) Tcl_DStringValue(&buf)[0], + Tcl_DStringValue(dsPtr)); + Tcl_DStringSetLength(dsPtr, len); + } else { + /* + * len > 1 should only happen if someone has called XRebindKeysym. + * Assume UTF-8. + */ + + Tcl_DStringSetLength(dsPtr, len); + strncpy(Tcl_DStringValue(dsPtr), Tcl_DStringValue(&buf), len); + } + } + + /* + * Cache the string in the event so that if/when we return to this + * function, we will be able to produce it without asking X. This stops us + * from having to reenter the XIM engine. [Bug 1373712] + */ + +done: + kePtr->charValuePtr = ckalloc(len + 1); + kePtr->charValueLen = len; + memcpy(kePtr->charValuePtr, Tcl_DStringValue(dsPtr), (unsigned) len + 1); + return Tcl_DStringValue(dsPtr); +} + +/* + * When mapping from a keysym to a keycode, need information about the + * modifier state to be used so that when they call TkKeycodeToKeysym taking + * into account the xkey.state, they will get back the original keysym. + */ + +void +TkpSetKeycodeAndState( + Tk_Window tkwin, + KeySym keySym, + XEvent *eventPtr) +{ + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; + int state, mincode, maxcode; + KeyCode keycode; + + if (keySym == NoSymbol) { + keycode = 0; + } else { + keycode = XKeysymToKeycode(dispPtr->display, keySym); + } + eventPtr->xkey.keycode = keycode; + if (keycode != 0) { + for (state = 0; state < 4; state++) { + if (XLookupKeysym(&eventPtr->xkey, state) == keySym) { + if (state & 1) { + eventPtr->xkey.state |= ShiftMask; + } + if (state & 2) { + eventPtr->xkey.state |= dispPtr->modeModMask; + } + break; + } + } + } + + /* + * Filter keycodes out of range, otherwise further Xlib function + * behavior might be undefined, in particular XIM could cause crashes. + */ + + mincode = 0; + maxcode = -1; + XDisplayKeycodes(dispPtr->display, &mincode, &maxcode); + if (keycode < mincode) { + keycode = mincode; + } else if (keycode > maxcode) { + keycode = maxcode; + } + + eventPtr->xkey.keycode = keycode; +} + +/* + *---------------------------------------------------------------------- + * + * 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( + TkDisplay *dispPtr, /* Display in which to map keycode. */ + XEvent *eventPtr) /* Description of X event. */ +{ + KeySym sym; + int index; + TkKeyEvent* kePtr = (TkKeyEvent*) eventPtr; + + /* + * Refresh the mapping information if it's stale. This must happen before + * we do any input method processing. [Bug 3599312] + */ + + if (dispPtr->bindInfoStale) { + TkpInitKeymapInfo(dispPtr); + } + +#ifdef TK_USE_INPUT_METHODS + /* + * If input methods are active, we may already have determined a keysym. + * Return it. + */ + + if (eventPtr->type == KeyPress && dispPtr + && (dispPtr->flags & TK_DISPLAY_USE_IM)) { + if (kePtr->charValuePtr == NULL) { + Tcl_DString ds; + TkWindow *winPtr = (TkWindow *) + Tk_IdToWindow(eventPtr->xany.display, eventPtr->xany.window); + + Tcl_DStringInit(&ds); + (void) TkpGetString(winPtr, eventPtr, &ds); + Tcl_DStringFree(&ds); + } + if (kePtr->charValuePtr != NULL) { + return kePtr->keysym; + } + } +#endif + + /* + * Figure out which of the four slots in the keymap vector to use for this + * key. Refer to Xlib documentation for more info on how this computation + * works. + */ + + index = 0; + if (eventPtr->xkey.state & dispPtr->modeModMask) { + index = 2; + } + if ((eventPtr->xkey.state & ShiftMask) + || ((dispPtr->lockUsage != LU_IGNORE) + && (eventPtr->xkey.state & LockMask))) { + index += 1; + } + sym = TkKeycodeToKeysym(dispPtr, eventPtr->xkey.keycode, 0, + index); + + /* + * Special handling: if the key was shifted because of Lock, but lock is + * only caps lock, not shift lock, and the shifted keysym isn't upper-case + * alphabetic, then switch back to the unshifted keysym. + */ + + if ((index & 1) && !(eventPtr->xkey.state & ShiftMask) + && (dispPtr->lockUsage == LU_CAPS)) { + if (!(((sym >= XK_A) && (sym <= XK_Z)) + || ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) + || ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) { + index &= ~1; + sym = TkKeycodeToKeysym(dispPtr, eventPtr->xkey.keycode, + 0, index); + } + } + + /* + * Another bit of special handling: if this is a shifted key and there is + * no keysym defined, then use the keysym for the unshifted key. + */ + + if ((index & 1) && (sym == NoSymbol)) { + sym = TkKeycodeToKeysym(dispPtr, eventPtr->xkey.keycode, + 0, index & ~1); + } + return sym; +} + +/* + *-------------------------------------------------------------- + * + * TkpInitKeymapInfo -- + * + * This function 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( + 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 = TkKeycodeToKeysym(dispPtr, *codePtr, 0, 0); + 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 = TkKeycodeToKeysym(dispPtr, *codePtr, 0, 0); + 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(dispPtr->modKeyCodes); + } + dispPtr->numModKeyCodes = 0; + arraySize = KEYCODE_ARRAY_SIZE; + dispPtr->modKeyCodes = ckalloc(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) { + /* + * 'continue' the outer loop. + */ + + goto nextModCode; + } + } + if (dispPtr->numModKeyCodes >= arraySize) { + KeyCode *newCodes; + + /* + * Ran out of space in the array; grow it. + */ + + arraySize *= 2; + newCodes = ckalloc(arraySize * sizeof(KeyCode)); + memcpy(newCodes, dispPtr->modKeyCodes, + dispPtr->numModKeyCodes * sizeof(KeyCode)); + ckfree(dispPtr->modKeyCodes); + dispPtr->modKeyCodes = newCodes; + } + dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr; + dispPtr->numModKeyCodes++; + nextModCode: + continue; + } + XFreeModifiermap(modMapPtr); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixMenu.c b/tk8.6/unix/tkUnixMenu.c new file mode 100644 index 0000000..38b6c58 --- /dev/null +++ b/tk8.6/unix/tkUnixMenu.c @@ -0,0 +1,1825 @@ +/* + * tkUnixMenu.c -- + * + * This module implements the UNIX platform-specific features of menus. + * + * 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. + */ + +#include "default.h" +#include "tkUnixInt.h" +#include "tkMenu.h" + +/* + * Constants used for menu drawing. + */ + +#define MENU_MARGIN_WIDTH 2 +#define MENU_DIVIDER_HEIGHT 2 + +/* + * Platform specific flags for Unix. + */ + +#define ENTRY_HELP_MENU ENTRY_PLATFORM_FLAG1 + +/* + * Shared with button widget. + */ + +MODULE_SCOPE void TkpDrawCheckIndicator(Tk_Window tkwin, + Display *display, Drawable d, int x, int y, + Tk_3DBorder bgBorder, XColor *indicatorColor, + XColor *selectColor, XColor *disColor, int on, + int disabled, int mode); +/* + * Indicator Draw Modes + */ + +#define CHECK_BUTTON 0 +#define CHECK_MENU 1 +#define RADIO_BUTTON 2 +#define RADIO_MENU 3 + +/* + * Procedures used internally. + */ + +static void SetHelpMenu(TkMenu *menuPtr); +static void DrawMenuEntryAccelerator(TkMenu *menuPtr, + TkMenuEntry *mePtr, Drawable d, GC gc, + Tk_Font tkfont, const Tk_FontMetrics *fmPtr, + Tk_3DBorder activeBorder, Tk_3DBorder bgBorder, + int x, int y, int width, int height, int drawArrow); +static void DrawMenuEntryBackground(TkMenu *menuPtr, + TkMenuEntry *mePtr, Drawable d, + Tk_3DBorder activeBorder, Tk_3DBorder bgBorder, + int x, int y, int width, int heigth); +static void DrawMenuEntryIndicator(TkMenu *menuPtr, + TkMenuEntry *mePtr, Drawable d, + Tk_3DBorder border, XColor *indicatorColor, + XColor *disableColor, Tk_Font tkfont, + const Tk_FontMetrics *fmPtr, int x, int y, + int width, int height); +static void DrawMenuEntryLabel(TkMenu * menuPtr, + TkMenuEntry *mePtr, Drawable d, GC gc, + Tk_Font tkfont, const Tk_FontMetrics *fmPtr, + int x, int y, int width, int height); +static void DrawMenuSeparator(TkMenu *menuPtr, + TkMenuEntry *mePtr, Drawable d, GC gc, + Tk_Font tkfont, const Tk_FontMetrics *fmPtr, + int x, int y, int width, int height); +static void DrawTearoffEntry(TkMenu *menuPtr, + TkMenuEntry *mePtr, Drawable d, GC gc, + Tk_Font tkfont, const Tk_FontMetrics *fmPtr, + int x, int y, int width, int height); +static void DrawMenuUnderline(TkMenu *menuPtr, + TkMenuEntry *mePtr, Drawable d, GC gc, + Tk_Font tkfont, const Tk_FontMetrics *fmPtr, + int x, int y, int width, int height); +static void GetMenuAccelGeometry(TkMenu *menuPtr, + TkMenuEntry *mePtr, Tk_Font tkfont, + const Tk_FontMetrics *fmPtr, int *widthPtr, + int *heightPtr); +static void GetMenuLabelGeometry(TkMenuEntry *mePtr, + Tk_Font tkfont, const Tk_FontMetrics *fmPtr, + int *widthPtr, int *heightPtr); +static void GetMenuIndicatorGeometry(TkMenu *menuPtr, + TkMenuEntry *mePtr, Tk_Font tkfont, + const Tk_FontMetrics *fmPtr, + int *widthPtr, int *heightPtr); +static void GetMenuSeparatorGeometry(TkMenu *menuPtr, + TkMenuEntry *mePtr, Tk_Font tkfont, + const Tk_FontMetrics *fmPtr, + int *widthPtr, int *heightPtr); +static void GetTearoffEntryGeometry(TkMenu *menuPtr, + TkMenuEntry *mePtr, Tk_Font tkfont, + const Tk_FontMetrics *fmPtr, int *widthPtr, + int *heightPtr); + +/* + *---------------------------------------------------------------------- + * + * TkpNewMenu -- + * + * Gets the platform-specific piece of the menu. Invoked during idle + * after the generic part of the menu has been created. + * + * Results: + * Standard TCL error. + * + * Side effects: + * Allocates any platform specific allocations and places them in the + * platformData field of the menuPtr. + * + *---------------------------------------------------------------------- + */ + +int +TkpNewMenu( + TkMenu *menuPtr) +{ + SetHelpMenu(menuPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TkpDestroyMenu -- + * + * Destroys platform-specific menu structures. Called when the generic + * menu structure is destroyed for the menu. + * + * Results: + * None. + * + * Side effects: + * All platform-specific allocations are freed up. + * + *---------------------------------------------------------------------- + */ + +void +TkpDestroyMenu( + TkMenu *menuPtr) +{ + /* + * Nothing to do. + */ +} + +/* + *---------------------------------------------------------------------- + * + * TkpDestroyMenuEntry -- + * + * Cleans up platform-specific menu entry items. Called when entry is + * destroyed in the generic code. + * + * Results: + * None. + * + * Side effects: + * All platform specific allocations are freed up. + * + *---------------------------------------------------------------------- + */ + +void +TkpDestroyMenuEntry( + TkMenuEntry *mEntryPtr) +{ + /* + * Nothing to do. + */ +} + +/* + *---------------------------------------------------------------------- + * + * TkpConfigureMenuEntry -- + * + * Processes configuration options for menu entries. Called when the + * generic options are processed for the menu. + * + * Results: + * Returns standard TCL result. If TCL_ERROR is returned, then the + * interp's result contains an error message. + * + * Side effects: + * Configuration information get set for mePtr; old resources get freed, + * if any need it. + * + *---------------------------------------------------------------------- + */ + +int +TkpConfigureMenuEntry( + register TkMenuEntry *mePtr)/* Information about menu entry; may or may + * not already have values for some fields. */ +{ + /* + * If this is a cascade menu, and the child menu exists, check to see if + * the child menu is a help menu. + */ + + if ((mePtr->type == CASCADE_ENTRY) && (mePtr->namePtr != NULL)) { + TkMenuReferences *menuRefPtr; + + menuRefPtr = TkFindMenuReferencesObj(mePtr->menuPtr->interp, + mePtr->namePtr); + if ((menuRefPtr != NULL) && (menuRefPtr->menuPtr != NULL)) { + SetHelpMenu(menuRefPtr->menuPtr); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TkpMenuNewEntry -- + * + * Called when a new entry is created in a menu. Fills in platform + * specific data for the entry. The platformEntryData field is used to + * store the indicator diameter for radio button and check box entries. + * + * Results: + * Standard TCL error. + * + * Side effects: + * None on Unix. + * + *---------------------------------------------------------------------- + */ + +int +TkpMenuNewEntry( + TkMenuEntry *mePtr) +{ + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TkpSetWindowMenuBar -- + * + * Sets up the menu as a menubar in the given window. + * + * Results: + * None. + * + * Side effects: + * Recomputes geometry of given window. + * + *---------------------------------------------------------------------- + */ + +void +TkpSetWindowMenuBar( + Tk_Window tkwin, /* The window we are setting */ + TkMenu *menuPtr) /* The menu we are setting */ +{ + if (menuPtr == NULL) { + TkUnixSetMenubar(tkwin, NULL); + } else { + TkUnixSetMenubar(tkwin, menuPtr->tkwin); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpSetMainMenuBar -- + * + * Called when a toplevel widget is brought to front. On the Macintosh, + * sets up the menubar that goes accross the top of the main monitor. On + * other platforms, nothing is necessary. + * + * Results: + * None. + * + * Side effects: + * Recompute geometry of given window. + * + *---------------------------------------------------------------------- + */ + +void +TkpSetMainMenubar( + Tcl_Interp *interp, + Tk_Window tkwin, + const char *menuName) +{ + /* + * Nothing to do. + */ +} + +/* + *---------------------------------------------------------------------- + * + * GetMenuIndicatorGeometry -- + * + * Fills out the geometry of the indicator in a menu item. Note that the + * mePtr->height field must have already been filled in by + * GetMenuLabelGeometry since this height depends on the label height. + * + * Results: + * widthPtr and heightPtr point to the new geometry values. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetMenuIndicatorGeometry( + TkMenu *menuPtr, /* The menu we are drawing. */ + TkMenuEntry *mePtr, /* The entry we are interested in. */ + Tk_Font tkfont, /* The precalculated font */ + const Tk_FontMetrics *fmPtr,/* The precalculated metrics */ + int *widthPtr, /* The resulting width */ + int *heightPtr) /* The resulting height */ +{ + int borderWidth; + + if ((mePtr->type == CHECK_BUTTON_ENTRY) + || (mePtr->type == RADIO_BUTTON_ENTRY)) { + if (!mePtr->hideMargin && mePtr->indicatorOn) { + if ((mePtr->image != NULL) || (mePtr->bitmapPtr != NULL)) { + *widthPtr = (14 * mePtr->height) / 10; + *heightPtr = mePtr->height; + if (mePtr->type == CHECK_BUTTON_ENTRY) { + mePtr->platformEntryData = (TkMenuPlatformEntryData) + INT2PTR((65 * mePtr->height) / 100); + } else { + mePtr->platformEntryData = (TkMenuPlatformEntryData) + INT2PTR((75 * mePtr->height) / 100); + } + } else { + *widthPtr = *heightPtr = mePtr->height; + if (mePtr->type == CHECK_BUTTON_ENTRY) { + mePtr->platformEntryData = (TkMenuPlatformEntryData) + INT2PTR((80 * mePtr->height) / 100); + } else { + mePtr->platformEntryData = (TkMenuPlatformEntryData) + INT2PTR(mePtr->height); + } + } + } else { + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, + &borderWidth); + *heightPtr = 0; + *widthPtr = borderWidth; + } + } else { + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, + &borderWidth); + *heightPtr = 0; + *widthPtr = borderWidth; + } +} + +/* + *---------------------------------------------------------------------- + * + * GetMenuAccelGeometry -- + * + * Get the geometry of the accelerator area of a menu item. + * + * Results: + * heightPtr and widthPtr are set. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetMenuAccelGeometry( + TkMenu *menuPtr, /* The menu was are drawing */ + TkMenuEntry *mePtr, /* The entry we are getting the geometry for */ + Tk_Font tkfont, /* The precalculated font */ + const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */ + int *widthPtr, /* The width of the acclerator area */ + int *heightPtr) /* The height of the accelerator area */ +{ + *heightPtr = fmPtr->linespace; + if (mePtr->type == CASCADE_ENTRY) { + *widthPtr = 2 * CASCADE_ARROW_WIDTH; + } else if ((menuPtr->menuType != MENUBAR) && (mePtr->accelPtr != NULL)) { + const char *accel = Tcl_GetString(mePtr->accelPtr); + + *widthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength); + } else { + *widthPtr = 0; + } +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuEntryBackground -- + * + * This procedure draws the background part of a menu. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its current mode. + * + *---------------------------------------------------------------------- + */ + +static void +DrawMenuEntryBackground( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are drawing. */ + Drawable d, /* The drawable we are drawing into */ + Tk_3DBorder activeBorder, /* The border for an active item */ + Tk_3DBorder bgBorder, /* The background border */ + int x, /* Left coordinate of entry rect */ + int y, /* Right coordinate of entry rect */ + int width, /* Width of entry rect */ + int height) /* Height of entry rect */ +{ + if (mePtr->state == ENTRY_ACTIVE) { + int relief; + int activeBorderWidth; + + bgBorder = activeBorder; + + if ((menuPtr->menuType == MENUBAR) + && ((menuPtr->postedCascade == NULL) + || (menuPtr->postedCascade != mePtr))) { + relief = TK_RELIEF_FLAT; + } else { + relief = TK_RELIEF_RAISED; + } + + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, + menuPtr->activeBorderWidthPtr, &activeBorderWidth); + Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height, + activeBorderWidth, relief); + } else { + Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, x, y, width, height, + 0, TK_RELIEF_FLAT); + } +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuEntryAccelerator -- + * + * This procedure draws the background part of a menu. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its current mode. + * + *---------------------------------------------------------------------- + */ + +static void +DrawMenuEntryAccelerator( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are drawing */ + Drawable d, /* The drawable we are drawing into */ + GC gc, /* The precalculated gc to draw with */ + Tk_Font tkfont, /* The precalculated font */ + const Tk_FontMetrics *fmPtr,/* The precalculated metrics */ + Tk_3DBorder activeBorder, /* The border for an active item */ + Tk_3DBorder bgBorder, /* The background border */ + int x, /* Left coordinate of entry rect */ + int y, /* Top coordinate of entry rect */ + int width, /* Width of entry */ + int height, /* Height of entry */ + int drawArrow) /* Whether or not to draw arrow. */ +{ + XPoint points[3]; + int borderWidth, activeBorderWidth; + + /* + * Draw accelerator or cascade arrow. + */ + + if (menuPtr->menuType == MENUBAR) { + return; + } + + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, + &borderWidth); + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr, + &activeBorderWidth); + if ((mePtr->type == CASCADE_ENTRY) && drawArrow) { + points[0].x = x + width - borderWidth - activeBorderWidth + - CASCADE_ARROW_WIDTH; + points[0].y = y + (height - CASCADE_ARROW_HEIGHT)/2; + points[1].x = points[0].x; + points[1].y = points[0].y + CASCADE_ARROW_HEIGHT; + points[2].x = points[0].x + CASCADE_ARROW_WIDTH; + points[2].y = points[0].y + CASCADE_ARROW_HEIGHT/2; + Tk_Fill3DPolygon(menuPtr->tkwin, d, + (mePtr->state == ENTRY_ACTIVE) ? activeBorder : bgBorder, + points, 3, DECORATION_BORDER_WIDTH, + (menuPtr->postedCascade == mePtr) + ? TK_RELIEF_SUNKEN : TK_RELIEF_RAISED); + } else if (mePtr->accelPtr != NULL) { + const char *accel = Tcl_GetString(mePtr->accelPtr); + int left = x + mePtr->labelWidth + activeBorderWidth + + mePtr->indicatorSpace; + + if (menuPtr->menuType == MENUBAR) { + left += 5; + } + Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel, + mePtr->accelLength, left, + (y + (height + fmPtr->ascent - fmPtr->descent) / 2)); + } +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuEntryIndicator -- + * + * This procedure draws the background part of a menu. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its current mode. + * + *---------------------------------------------------------------------- + */ + +static void +DrawMenuEntryIndicator( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are drawing */ + Drawable d, /* The drawable to draw into */ + Tk_3DBorder border, /* The background color */ + XColor *indicatorColor, /* The color to draw indicators with */ + XColor *disableColor, /* The color use use when disabled */ + Tk_Font tkfont, /* The font to draw with */ + const Tk_FontMetrics *fmPtr,/* The font metrics of the font */ + int x, /* The left of the entry rect */ + int y, /* The top of the entry rect */ + int width, /* Width of menu entry */ + int height) /* Height of menu entry */ +{ + /* + * Draw check-button indicator. + */ + + if ((mePtr->type == CHECK_BUTTON_ENTRY) && mePtr->indicatorOn) { + int top, left, activeBorderWidth; + int disabled = (mePtr->state == ENTRY_DISABLED); + XColor *bg; + + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, + menuPtr->activeBorderWidthPtr, &activeBorderWidth); + bg = Tk_3DBorderColor(border); + top = y + height/2; + left = x + activeBorderWidth + DECORATION_BORDER_WIDTH + + mePtr->indicatorSpace/2; + + TkpDrawCheckIndicator(menuPtr->tkwin, menuPtr->display, d, left, top, + border, indicatorColor, bg, disableColor, + (mePtr->entryFlags & ENTRY_SELECTED), disabled, CHECK_MENU); + } + + /* + * Draw radio-button indicator. + */ + + if ((mePtr->type == RADIO_BUTTON_ENTRY) && mePtr->indicatorOn) { + int top, left, activeBorderWidth; + int disabled = (mePtr->state == ENTRY_DISABLED); + XColor *bg; + + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, + menuPtr->activeBorderWidthPtr, &activeBorderWidth); + bg = Tk_3DBorderColor(border); + top = y + height/2; + left = x + activeBorderWidth + DECORATION_BORDER_WIDTH + + mePtr->indicatorSpace/2; + + TkpDrawCheckIndicator(menuPtr->tkwin, menuPtr->display, d, left, top, + border, indicatorColor, bg, disableColor, + (mePtr->entryFlags & ENTRY_SELECTED), disabled, RADIO_MENU); + } +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuSeparator -- + * + * This procedure draws a separator menu item. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its current mode. + * + *---------------------------------------------------------------------- + */ + +static void +DrawMenuSeparator( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are drawing */ + Drawable d, /* The drawable we are using */ + GC gc, /* The gc to draw into */ + Tk_Font tkfont, /* The font to draw with */ + const Tk_FontMetrics *fmPtr,/* The font metrics from the font */ + int x, int y, + int width, int height) +{ + XPoint points[2]; + Tk_3DBorder border; + + if (menuPtr->menuType == MENUBAR) { + return; + } + + points[0].x = x; + points[0].y = y + height/2; + points[1].x = x + width - 1; + points[1].y = points[0].y; + border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr); + Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1, + TK_RELIEF_RAISED); +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuEntryLabel -- + * + * This procedure draws the label part of a menu. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its current mode. + * + *---------------------------------------------------------------------- + */ + +static void +DrawMenuEntryLabel( + TkMenu *menuPtr, /* The menu we are drawing. */ + TkMenuEntry *mePtr, /* The entry we are drawing. */ + Drawable d, /* What we are drawing into. */ + GC gc, /* The gc we are drawing into.*/ + Tk_Font tkfont, /* The precalculated font. */ + const Tk_FontMetrics *fmPtr,/* The precalculated font metrics. */ + int x, /* Left edge. */ + int y, /* Top edge. */ + int width, /* width of entry. */ + int height) /* height of entry. */ +{ + int indicatorSpace = mePtr->indicatorSpace; + int activeBorderWidth, leftEdge, imageHeight, imageWidth; + int textHeight = 0, textWidth = 0; /* stop GCC warning */ + int haveImage = 0, haveText = 0; + int imageXOffset = 0, imageYOffset = 0; + int textXOffset = 0, textYOffset = 0; + + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr, + &activeBorderWidth); + leftEdge = x + indicatorSpace + activeBorderWidth; + if (menuPtr->menuType == MENUBAR) { + leftEdge += 5; + } + + /* + * Work out what we will need to draw first. + */ + + if (mePtr->image != NULL) { + Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight); + haveImage = 1; + } else if (mePtr->bitmapPtr != NULL) { + Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr); + + Tk_SizeOfBitmap(menuPtr->display, bitmap, &imageWidth, &imageHeight); + haveImage = 1; + } + if (!haveImage || (mePtr->compound != COMPOUND_NONE)) { + if (mePtr->labelLength > 0) { + const char *label = Tcl_GetString(mePtr->labelPtr); + + textWidth = Tk_TextWidth(tkfont, label, mePtr->labelLength); + textHeight = fmPtr->linespace; + haveText = 1; + } + } + + /* + * Now work out what the relative positions are. + */ + + if (haveImage && haveText) { + int fullWidth = (imageWidth > textWidth ? imageWidth : textWidth); + + switch ((enum compound) mePtr->compound) { + case COMPOUND_TOP: + textXOffset = (fullWidth - textWidth)/2; + textYOffset = imageHeight/2 + 2; + imageXOffset = (fullWidth - imageWidth)/2; + imageYOffset = -textHeight/2; + break; + case COMPOUND_BOTTOM: + textXOffset = (fullWidth - textWidth)/2; + textYOffset = -imageHeight/2; + imageXOffset = (fullWidth - imageWidth)/2; + imageYOffset = textHeight/2 + 2; + break; + case COMPOUND_LEFT: + /* + * Position image in the indicator space to the left of the + * entries, unless this entry is a radio|check button because then + * the indicator space will be used. + */ + + textXOffset = imageWidth + 2; + textYOffset = 0; + imageXOffset = 0; + imageYOffset = 0; + if ((mePtr->type != CHECK_BUTTON_ENTRY) + && (mePtr->type != RADIO_BUTTON_ENTRY)) { + textXOffset -= indicatorSpace; + if (textXOffset < 0) { + textXOffset = 0; + } + imageXOffset = -indicatorSpace; + } + break; + case COMPOUND_RIGHT: + textXOffset = 0; + textYOffset = 0; + imageXOffset = textWidth + 2; + imageYOffset = 0; + break; + case COMPOUND_CENTER: + textXOffset = (fullWidth - textWidth)/2; + textYOffset = 0; + imageXOffset = (fullWidth - imageWidth)/2; + imageYOffset = 0; + break; + case COMPOUND_NONE: + break; + } + } else { + textXOffset = 0; + textYOffset = 0; + imageXOffset = 0; + imageYOffset = 0; + } + + /* + * Draw label and/or bitmap or image for entry. + */ + + if (mePtr->image != NULL) { + if ((mePtr->selectImage != NULL) + && (mePtr->entryFlags & ENTRY_SELECTED)) { + Tk_RedrawImage(mePtr->selectImage, 0, 0, + imageWidth, imageHeight, d, leftEdge + imageXOffset, + (int) (y + (mePtr->height-imageHeight)/2 + imageYOffset)); + } else { + Tk_RedrawImage(mePtr->image, 0, 0, imageWidth, + imageHeight, d, leftEdge + imageXOffset, + (int) (y + (mePtr->height-imageHeight)/2 + imageYOffset)); + } + } else if (mePtr->bitmapPtr != None) { + Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr); + + XCopyPlane(menuPtr->display, bitmap, d, gc, 0, 0, + (unsigned) imageWidth, (unsigned) imageHeight, + leftEdge + imageXOffset, + (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset), 1); + } + if ((mePtr->compound != COMPOUND_NONE) || !haveImage) { + int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2; + + if (mePtr->labelLength > 0) { + const char *label = Tcl_GetString(mePtr->labelPtr); + + Tk_DrawChars(menuPtr->display, d, gc, tkfont, label, + mePtr->labelLength, leftEdge + textXOffset, + baseline + textYOffset); + DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, + x + textXOffset, y + textYOffset, + width, height); + } + } + + 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) + && (menuPtr->disabledImageGC != None)) { + XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, + leftEdge + imageXOffset, + (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset), + (unsigned) imageWidth, (unsigned) imageHeight); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuUnderline -- + * + * On appropriate platforms, draw the underline character for the menu. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its current mode. + * + *---------------------------------------------------------------------- + */ + +static void +DrawMenuUnderline( + TkMenu *menuPtr, /* The menu to draw into */ + TkMenuEntry *mePtr, /* The entry we are drawing */ + Drawable d, /* What we are drawing into */ + GC gc, /* The gc to draw into */ + Tk_Font tkfont, /* The precalculated font */ + const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */ + int x, int y, + int width, int height) +{ + if ((mePtr->underline >= 0) && (mePtr->labelPtr != NULL)) { + int len; + + /* + * Do the unicode call just to prevent overruns. + */ + + Tcl_GetUnicodeFromObj(mePtr->labelPtr, &len); + if (mePtr->underline < len) { + int activeBorderWidth, leftEdge; + const char *label, *start, *end; + + label = Tcl_GetString(mePtr->labelPtr); + start = Tcl_UtfAtIndex(label, mePtr->underline); + end = Tcl_UtfNext(start); + + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, + menuPtr->activeBorderWidthPtr, &activeBorderWidth); + leftEdge = x + mePtr->indicatorSpace + activeBorderWidth; + if (menuPtr->menuType == MENUBAR) { + leftEdge += 5; + } + + Tk_UnderlineChars(menuPtr->display, d, gc, tkfont, label, leftEdge, + y + (height + fmPtr->ascent - fmPtr->descent) / 2, + start - label, end - label); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpPostMenu -- + * + * Posts a menu on the screen + * + * Results: + * None. + * + * Side effects: + * The menu is posted and handled. + * + *---------------------------------------------------------------------- + */ + +int +TkpPostMenu( + Tcl_Interp *interp, + TkMenu *menuPtr, + int x, int y) +{ + return TkPostTearoffMenu(interp, menuPtr, x, y); +} + +/* + *---------------------------------------------------------------------- + * + * GetMenuSeparatorGeometry -- + * + * Gets the width and height of the indicator area of a menu. + * + * Results: + * widthPtr and heightPtr are set. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetMenuSeparatorGeometry( + TkMenu *menuPtr, /* The menu we are measuring */ + TkMenuEntry *mePtr, /* The entry we are measuring */ + Tk_Font tkfont, /* The precalculated font */ + const Tk_FontMetrics *fmPtr,/* The precalcualted font metrics */ + int *widthPtr, /* The resulting width */ + int *heightPtr) /* The resulting height */ +{ + *widthPtr = 0; + *heightPtr = fmPtr->linespace; +} + +/* + *---------------------------------------------------------------------- + * + * GetTearoffEntryGeometry -- + * + * Gets the width and height of the indicator area of a menu. + * + * Results: + * widthPtr and heightPtr are set. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetTearoffEntryGeometry( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are measuring */ + Tk_Font tkfont, /* The precalculated font */ + const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */ + int *widthPtr, /* The resulting width */ + int *heightPtr) /* The resulting height */ +{ + if (menuPtr->menuType != MASTER_MENU) { + *heightPtr = 0; + *widthPtr = 0; + } else { + *heightPtr = fmPtr->linespace; + *widthPtr = Tk_TextWidth(tkfont, "W", 1); + } +} + +/* + *-------------------------------------------------------------- + * + * TkpComputeMenubarGeometry -- + * + * This procedure is invoked to recompute the size and layout of a menu + * that is a menubar clone. + * + * Results: + * None. + * + * Side effects: + * Fields of menu entries are changed to reflect their current positions, + * and the size of the menu window itself may be changed. + * + *-------------------------------------------------------------- + */ + +void +TkpComputeMenubarGeometry( + TkMenu *menuPtr) /* Structure describing menu. */ +{ + Tk_Font tkfont, menuFont; + Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr; + int width, height, i, j, x, y, currentRowHeight, maxWidth; + int maxWindowWidth, lastRowBreak, lastEntry; + int borderWidth, activeBorderWidth, helpMenuIndex = -1; + TkMenuEntry *mePtr; + + if (menuPtr->tkwin == NULL) { + return; + } + + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, + &borderWidth); + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr, + &activeBorderWidth); + maxWidth = 0; + if (menuPtr->numEntries == 0) { + height = 0; + } else { + int borderWidth; + + maxWindowWidth = Tk_Width(menuPtr->tkwin); + if (maxWindowWidth == 1) { + maxWindowWidth = 0x7ffffff; + } + currentRowHeight = 0; + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, + &borderWidth); + x = y = borderWidth; + lastRowBreak = 0; + + /* + * On the Mac especially, getting font metrics can be quite slow, so + * we want to do it intelligently. We are going to precalculate them + * and pass them down to all of the measureing and drawing routines. + * We will measure the font metrics of the menu once, and if an entry + * has a font set, we will measure it as we come to it, and then we + * decide which set to give the geometry routines. + */ + + menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); + Tk_GetFontMetrics(menuFont, &menuMetrics); + + for (i = 0; i < menuPtr->numEntries; i++) { + mePtr = menuPtr->entries[i]; + mePtr->entryFlags &= ~ENTRY_LAST_COLUMN; + if (mePtr->fontPtr != NULL) { + tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr); + Tk_GetFontMetrics(tkfont, &entryMetrics); + fmPtr = &entryMetrics; + } else { + tkfont = menuFont; + fmPtr = &menuMetrics; + } + + /* + * For every entry, we need to check to see whether or not we + * wrap. If we do wrap, then we have to adjust all of the previous + * entries' height and y position, because when we see them the + * first time, we don't know how big its neighbor might be. + */ + + if ((mePtr->type == SEPARATOR_ENTRY) + || (mePtr->type == TEAROFF_ENTRY)) { + mePtr->height = mePtr->width = 0; + } else { + GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &width, &height); + mePtr->height = height + 2 * activeBorderWidth + 10; + mePtr->width = width; + + GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, fmPtr, + &width, &height); + mePtr->indicatorSpace = width; + if (width > 0) { + mePtr->width += width; + } + mePtr->width += 2 * activeBorderWidth + 10; + } + if (mePtr->entryFlags & ENTRY_HELP_MENU) { + helpMenuIndex = i; + } else if (x + mePtr->width + borderWidth > maxWindowWidth) { + if (i == lastRowBreak) { + mePtr->y = y; + mePtr->x = x; + lastRowBreak++; + y += mePtr->height; + currentRowHeight = 0; + } else { + x = borderWidth; + for (j = lastRowBreak; j < i; j++) { + menuPtr->entries[j]->y = y + currentRowHeight + - menuPtr->entries[j]->height; + menuPtr->entries[j]->x = x; + x += menuPtr->entries[j]->width; + } + lastRowBreak = i; + y += currentRowHeight; + currentRowHeight = mePtr->height; + } + if (x > maxWidth) { + maxWidth = x; + } + x = borderWidth; + } else { + x += mePtr->width; + if (mePtr->height > currentRowHeight) { + currentRowHeight = mePtr->height; + } + } + } + + lastEntry = menuPtr->numEntries - 1; + if (helpMenuIndex == lastEntry) { + lastEntry--; + } + if ((lastEntry >= 0) && (x + menuPtr->entries[lastEntry]->width + + borderWidth > maxWidth)) { + maxWidth = x + menuPtr->entries[lastEntry]->width + borderWidth; + } + x = borderWidth; + for (j = lastRowBreak; j < menuPtr->numEntries; j++) { + if (j == helpMenuIndex) { + continue; + } + menuPtr->entries[j]->y = y + currentRowHeight + - menuPtr->entries[j]->height; + menuPtr->entries[j]->x = x; + x += menuPtr->entries[j]->width; + } + + + if (helpMenuIndex != -1) { + mePtr = menuPtr->entries[helpMenuIndex]; + if (x + mePtr->width + borderWidth > maxWindowWidth) { + y += currentRowHeight; + currentRowHeight = mePtr->height; + x = borderWidth; + } else if (mePtr->height > currentRowHeight) { + currentRowHeight = mePtr->height; + } + mePtr->x = maxWindowWidth - borderWidth - mePtr->width; + mePtr->y = y + currentRowHeight - mePtr->height; + } + height = y + currentRowHeight + borderWidth; + } + width = Tk_Width(menuPtr->tkwin); + + /* + * The X server doesn't like zero dimensions, so round up to at least 1 (a + * zero-sized menu should never really occur, anyway). + */ + + if (width <= 0) { + width = 1; + } + if (height <= 0) { + height = 1; + } + menuPtr->totalWidth = maxWidth; + menuPtr->totalHeight = height; +} + +/* + *---------------------------------------------------------------------- + * + * DrawTearoffEntry -- + * + * This procedure draws the background part of a menu. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its current mode. + * + *---------------------------------------------------------------------- + */ + +static void +DrawTearoffEntry( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are drawing */ + Drawable d, /* The drawable we are drawing into */ + GC gc, /* The gc we are drawing with */ + Tk_Font tkfont, /* The font we are drawing with */ + const Tk_FontMetrics *fmPtr,/* The metrics we are drawing with */ + int x, int y, + int width, int height) +{ + XPoint points[2]; + int segmentWidth, maxX; + Tk_3DBorder border; + + if (menuPtr->menuType != MASTER_MENU) { + return; + } + + points[0].x = x; + points[0].y = y + height/2; + points[1].y = points[0].y; + segmentWidth = 6; + maxX = x + 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, border, points, 2, 1, + TK_RELIEF_RAISED); + points[0].x += 2 * segmentWidth; + } +} + +/* + *-------------------------------------------------------------- + * + * TkpInitializeMenuBindings -- + * + * For every interp, initializes the bindings for Windows menus. Does + * nothing on Mac or XWindows. + * + * Results: + * None. + * + * Side effects: + * C-level bindings are setup for the interp which will handle Alt-key + * sequences for menus without beeping or interfering with user-defined + * Alt-key bindings. + * + *-------------------------------------------------------------- + */ + +void +TkpInitializeMenuBindings( + Tcl_Interp *interp, /* The interpreter to set. */ + Tk_BindingTable bindingTable) + /* The table to add to. */ +{ + /* + * Nothing to do. + */ +} + +/* + *---------------------------------------------------------------------- + * + * SetHelpMenu -- + * + * Given a menu, check to see whether or not it is a help menu cascade in + * a menubar. If it is, the entry that points to this menu will be + * marked. + * + * RESULTS: + * None. + * + * Side effects: + * Will set the ENTRY_HELP_MENU flag appropriately. + * + *---------------------------------------------------------------------- + */ + +static void +SetHelpMenu( + TkMenu *menuPtr) /* The menu we are checking */ +{ + TkMenuEntry *cascadeEntryPtr; + int useMotifHelp = 0; + const char *option = NULL; + if (menuPtr->tkwin) { + option = Tk_GetOption(menuPtr->tkwin, "useMotifHelp", "UseMotifHelp"); + if (option != NULL) { + Tcl_GetBoolean(NULL, option, &useMotifHelp); + } + } + + if (!useMotifHelp) { + return; + } + + for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr; + cascadeEntryPtr != NULL; + cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) { + if ((cascadeEntryPtr->menuPtr->menuType == MENUBAR) + && (cascadeEntryPtr->menuPtr->masterMenuPtr->tkwin != NULL) + && (menuPtr->masterMenuPtr->tkwin != NULL)) { + TkMenu *masterMenuPtr = cascadeEntryPtr->menuPtr->masterMenuPtr; + char *helpMenuName = ckalloc(strlen(Tk_PathName( + masterMenuPtr->tkwin)) + strlen(".help") + 1); + + strcpy(helpMenuName, Tk_PathName(masterMenuPtr->tkwin)); + strcat(helpMenuName, ".help"); + if (strcmp(helpMenuName, + Tk_PathName(menuPtr->masterMenuPtr->tkwin)) == 0) { + cascadeEntryPtr->entryFlags |= ENTRY_HELP_MENU; + } else { + cascadeEntryPtr->entryFlags &= ~ENTRY_HELP_MENU; + } + ckfree(helpMenuName); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpDrawMenuEntry -- + * + * Draws the given menu entry at the given coordinates with the given + * attributes. + * + * Results: + * None. + * + * Side effects: + * X Server commands are executed to display the menu entry. + * + *---------------------------------------------------------------------- + */ + +void +TkpDrawMenuEntry( + TkMenuEntry *mePtr, /* The entry to draw */ + Drawable d, /* What to draw into */ + Tk_Font tkfont, /* Precalculated font for menu */ + const Tk_FontMetrics *menuMetricsPtr, + /* Precalculated metrics for menu */ + int x, /* X-coordinate of topleft of entry */ + int y, /* Y-coordinate of topleft of entry */ + int width, /* Width of the entry rectangle */ + int height, /* Height of the current rectangle */ + int strictMotif, /* Boolean flag */ + int drawArrow) /* Whether or not to draw the cascade arrow + * for cascade items. */ +{ + GC gc, indicatorGC; + XColor *indicatorColor, *disableColor = NULL; + TkMenu *menuPtr = mePtr->menuPtr; + Tk_3DBorder bgBorder, activeBorder; + const Tk_FontMetrics *fmPtr; + Tk_FontMetrics entryMetrics; + int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0; + int adjustedY = y + padY; + int adjustedHeight = height - 2 * padY; + + /* + * Choose the gc for drawing the foreground part of the entry. + */ + + if ((mePtr->state == ENTRY_ACTIVE) && !strictMotif) { + gc = mePtr->activeGC; + if (gc == NULL) { + gc = menuPtr->activeGC; + } + } else { + TkMenuEntry *cascadeEntryPtr; + int parentDisabled = 0; + + for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr; + cascadeEntryPtr != NULL; + cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) { + if (cascadeEntryPtr->namePtr != NULL) { + const char *name = Tcl_GetString(cascadeEntryPtr->namePtr); + + if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) { + if (cascadeEntryPtr->state == ENTRY_DISABLED) { + parentDisabled = 1; + } + break; + } + } + } + + if (((parentDisabled || (mePtr->state == ENTRY_DISABLED))) + && (menuPtr->disabledFgPtr != NULL)) { + gc = mePtr->disabledGC; + if (gc == NULL) { + gc = menuPtr->disabledGC; + } + } else { + gc = mePtr->textGC; + if (gc == NULL) { + gc = menuPtr->textGC; + } + } + } + indicatorGC = mePtr->indicatorGC; + if (indicatorGC == NULL) { + indicatorGC = menuPtr->indicatorGC; + } + if (mePtr->indicatorFgPtr) { + indicatorColor = Tk_GetColorFromObj(menuPtr->tkwin, + mePtr->indicatorFgPtr); + } else { + indicatorColor = Tk_GetColorFromObj(menuPtr->tkwin, + menuPtr->indicatorFgPtr); + } + + if (menuPtr->disabledFgPtr != NULL) { + disableColor = Tk_GetColorFromObj(menuPtr->tkwin, + menuPtr->disabledFgPtr); + } + + bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin, + (mePtr->borderPtr == NULL) + ? menuPtr->borderPtr : mePtr->borderPtr); + if (strictMotif) { + activeBorder = bgBorder; + } else { + activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin, + (mePtr->activeBorderPtr == NULL) + ? menuPtr->activeBorderPtr : mePtr->activeBorderPtr); + } + + if (mePtr->fontPtr == NULL) { + fmPtr = menuMetricsPtr; + } else { + tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr); + Tk_GetFontMetrics(tkfont, &entryMetrics); + fmPtr = &entryMetrics; + } + + /* + * Need to draw the entire background, including padding. On Unix, for + * menubars, we have to draw the rest of the entry taking into account the + * padding. + */ + + DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder, + bgBorder, x, y, width, height); + + if (mePtr->type == SEPARATOR_ENTRY) { + DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, + fmPtr, x, adjustedY, width, adjustedHeight); + } else if (mePtr->type == TEAROFF_ENTRY) { + DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, + width, adjustedHeight); + } else { + DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, + width, adjustedHeight); + DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, + activeBorder, bgBorder, x, adjustedY, width, adjustedHeight, + drawArrow); + if (!mePtr->hideMargin) { + if (mePtr->state == ENTRY_ACTIVE) { + bgBorder = activeBorder; + } + DrawMenuEntryIndicator(menuPtr, mePtr, d, bgBorder, indicatorColor, + disableColor, tkfont, fmPtr, x, adjustedY, width, + adjustedHeight); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * GetMenuLabelGeometry -- + * + * Figures out the size of the label portion of a menu item. + * + * Results: + * widthPtr and heightPtr are filled in with the correct geometry + * information. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetMenuLabelGeometry( + TkMenuEntry *mePtr, /* The entry we are computing */ + Tk_Font tkfont, /* The precalculated font */ + const Tk_FontMetrics *fmPtr,/* The precalculated metrics */ + int *widthPtr, /* The resulting width of the label portion */ + int *heightPtr) /* The resulting height of the label + * portion */ +{ + TkMenu *menuPtr = mePtr->menuPtr; + int haveImage = 0; + + if (mePtr->image != NULL) { + Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr); + haveImage = 1; + } else if (mePtr->bitmapPtr != NULL) { + Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr); + + Tk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr); + haveImage = 1; + } else { + *heightPtr = 0; + *widthPtr = 0; + } + + if (haveImage && (mePtr->compound == COMPOUND_NONE)) { + /* + * We don't care about the text in this case. + */ + } else { + /* + * Either it is compound or we don't have an image. + */ + + if (mePtr->labelPtr != NULL) { + int textWidth; + const char *label = Tcl_GetString(mePtr->labelPtr); + + textWidth = Tk_TextWidth(tkfont, label, mePtr->labelLength); + if ((mePtr->compound != COMPOUND_NONE) && haveImage) { + switch ((enum compound) mePtr->compound) { + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + if (textWidth > *widthPtr) { + *widthPtr = textWidth; + } + + /* + * Add text and padding. + */ + + *heightPtr += fmPtr->linespace + 2; + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + if (fmPtr->linespace > *heightPtr) { + *heightPtr = fmPtr->linespace; + } + + /* + * Add text and padding. + */ + + *widthPtr += textWidth + 2; + break; + case COMPOUND_CENTER: + if (fmPtr->linespace > *heightPtr) { + *heightPtr = fmPtr->linespace; + } + if (textWidth > *widthPtr) { + *widthPtr = textWidth; + } + break; + case COMPOUND_NONE: + break; + } + } else { + /* + * We don't have an image or we're not compound. + */ + + *heightPtr = fmPtr->linespace; + *widthPtr = textWidth; + } + } else { + /* + * An empty entry still has this height. + */ + + *heightPtr = fmPtr->linespace; + } + } + *heightPtr += 1; +} + +/* + *-------------------------------------------------------------- + * + * TkpComputeStandardMenuGeometry -- + * + * This procedure is invoked to recompute the size and layout of a menu + * that is not a menubar clone. + * + * Results: + * None. + * + * Side effects: + * Fields of menu entries are changed to reflect their current positions, + * and the size of the menu window itself may be changed. + * + *-------------------------------------------------------------- + */ + +void +TkpComputeStandardMenuGeometry( + TkMenu *menuPtr) /* Structure describing menu. */ +{ + Tk_Font tkfont, menuFont; + Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr; + int x, y, height, width, indicatorSpace, labelWidth, accelWidth; + int windowWidth, windowHeight, accelSpace, i, j, lastColumnBreak = 0; + TkMenuEntry *mePtr; + int borderWidth, activeBorderWidth; + + if (menuPtr->tkwin == NULL) { + return; + } + + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, + &borderWidth); + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr, + &activeBorderWidth); + x = y = borderWidth; + indicatorSpace = labelWidth = accelWidth = 0; + windowHeight = windowWidth = 0; + + /* + * On the Mac especially, getting font metrics can be quite slow, so we + * want to do it intelligently. We are going to precalculate them and pass + * them down to all of the measuring and drawing routines. We will measure + * the font metrics of the menu once. If an entry does not have its own + * font set, then we give the geometry/drawing routines the menu's font + * and metrics. If an entry has its own font, we will measure that font + * and give all of the geometry/drawing the entry's font and metrics. + */ + + menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); + Tk_GetFontMetrics(menuFont, &menuMetrics); + accelSpace = Tk_TextWidth(menuFont, "M", 1); + + for (i = 0; i < menuPtr->numEntries; i++) { + mePtr = menuPtr->entries[i]; + if (mePtr->fontPtr == NULL) { + tkfont = menuFont; + fmPtr = &menuMetrics; + } else { + tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr); + Tk_GetFontMetrics(tkfont, &entryMetrics); + fmPtr = &entryMetrics; + } + + if ((i > 0) && mePtr->columnBreak) { + if (accelWidth != 0) { + labelWidth += accelSpace; + } + for (j = lastColumnBreak; j < i; j++) { + menuPtr->entries[j]->indicatorSpace = indicatorSpace; + menuPtr->entries[j]->labelWidth = labelWidth; + menuPtr->entries[j]->width = indicatorSpace + labelWidth + + accelWidth + 2 * activeBorderWidth; + menuPtr->entries[j]->x = x; + menuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN; + } + x += indicatorSpace + labelWidth + accelWidth + + 2 * activeBorderWidth; + windowWidth = x; + indicatorSpace = labelWidth = accelWidth = 0; + lastColumnBreak = i; + y = borderWidth; + } + + if (mePtr->type == SEPARATOR_ENTRY) { + GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont, fmPtr, + &width, &height); + mePtr->height = height; + } else if (mePtr->type == TEAROFF_ENTRY) { + GetTearoffEntryGeometry(menuPtr, mePtr, tkfont, fmPtr, + &width, &height); + mePtr->height = height; + labelWidth = width; + } else { + /* + * For each entry, compute the height required by that particular + * entry, plus three widths: the width of the label, the width to + * allow for an indicator to be displayed to the left of the label + * (if any), and the width of the accelerator to be displayed to + * the right of the label (if any). These sizes depend, of course, + * on the type of the entry. + */ + + GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &width, &height); + mePtr->height = height; + if (!mePtr->hideMargin) { + width += MENU_MARGIN_WIDTH; + } + if (width > labelWidth) { + labelWidth = width; + } + + GetMenuAccelGeometry(menuPtr, mePtr, tkfont, + fmPtr, &width, &height); + if (height > mePtr->height) { + mePtr->height = height; + } + if (!mePtr->hideMargin) { + width += MENU_MARGIN_WIDTH; + } + if (width > accelWidth) { + accelWidth = width; + } + + GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, fmPtr, + &width, &height); + if (height > mePtr->height) { + mePtr->height = height; + } + if (!mePtr->hideMargin) { + width += MENU_MARGIN_WIDTH; + } + if (width > indicatorSpace) { + indicatorSpace = width; + } + + mePtr->height += 2 * activeBorderWidth + MENU_DIVIDER_HEIGHT; + } + mePtr->y = y; + y += mePtr->height; + if (y > windowHeight) { + windowHeight = y; + } + } + + if (accelWidth != 0) { + labelWidth += accelSpace; + } + for (j = lastColumnBreak; j < menuPtr->numEntries; j++) { + menuPtr->entries[j]->indicatorSpace = indicatorSpace; + menuPtr->entries[j]->labelWidth = labelWidth; + menuPtr->entries[j]->width = indicatorSpace + labelWidth + + accelWidth + 2 * activeBorderWidth; + menuPtr->entries[j]->x = x; + menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN; + } + windowWidth = x + indicatorSpace + labelWidth + accelWidth + + 2 * activeBorderWidth + borderWidth; + + windowHeight += borderWidth; + + /* + * The X server doesn't like zero dimensions, so round up to at least 1 (a + * zero-sized menu should never really occur, anyway). + */ + + if (windowWidth <= 0) { + windowWidth = 1; + } + if (windowHeight <= 0) { + windowHeight = 1; + } + menuPtr->totalWidth = windowWidth; + menuPtr->totalHeight = windowHeight; +} + +/* + *---------------------------------------------------------------------- + * + * TkpMenuNotifyToplevelCreate -- + * + * This routine reconfigures the menu and the clones indicated by + * menuName becuase a toplevel has been created and any system menus need + * to be created. Not applicable to UNIX. + * + * Results: + * None. + * + * Side effects: + * An idle handler is set up to do the reconfiguration. + * + *---------------------------------------------------------------------- + */ + +void +TkpMenuNotifyToplevelCreate( + Tcl_Interp *interp, /* The interp the menu lives in. */ + const char *menuName) /* The name of the menu to reconfigure. */ +{ + /* + * Nothing to do. + */ +} + +/* + *---------------------------------------------------------------------- + * + * TkpMenuInit -- + * + * Does platform-specific initialization of menus. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpMenuInit(void) +{ + /* + * Nothing to do. + */ +} + + +/* + *---------------------------------------------------------------------- + * + * TkpMenuThreadInit -- + * + * Does platform-specific initialization of thread-specific menu state. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpMenuThreadInit(void) +{ + /* + * Nothing to do. + */ +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixMenubu.c b/tk8.6/unix/tkUnixMenubu.c new file mode 100644 index 0000000..ad71b7b --- /dev/null +++ b/tk8.6/unix/tkUnixMenubu.c @@ -0,0 +1,476 @@ +/* + * tkUnixMenubu.c -- + * + * This file implements the Unix specific portion of the menubutton + * widget. + * + * 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. + */ + +#include "tkInt.h" +#include "tkMenubutton.h" + + +/* + *---------------------------------------------------------------------- + * + * TkpCreateMenuButton -- + * + * Allocate a new TkMenuButton structure. + * + * Results: + * Returns a newly allocated TkMenuButton structure. + * + * Side effects: + * Registers an event handler for the widget. + * + *---------------------------------------------------------------------- + */ + +TkMenuButton * +TkpCreateMenuButton( + Tk_Window tkwin) +{ + return ckalloc(sizeof(TkMenuButton)); +} + +/* + *---------------------------------------------------------------------- + * + * TkpDisplayMenuButton -- + * + * This function is invoked to display a menubutton widget. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menubutton in its current + * mode. + * + *---------------------------------------------------------------------- + */ + +void +TkpDisplayMenuButton( + ClientData clientData) /* Information about widget. */ +{ + register TkMenuButton *mbPtr = (TkMenuButton *) clientData; + GC gc; + Tk_3DBorder border; + Pixmap pixmap; + int x = 0; /* Initialization needed only to stop compiler + * warning. */ + int y = 0; + register Tk_Window tkwin = mbPtr->tkwin; + int fullWidth, fullHeight; + int textXOffset, textYOffset; + int imageWidth, imageHeight; + int imageXOffset, imageYOffset; + int width = 0, height = 0; + /* Image information that will be used to + * restrict disabled pixmap as well */ + int haveImage = 0, haveText = 0; + + mbPtr->flags &= ~REDRAW_PENDING; + if ((mbPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { + return; + } + + if ((mbPtr->state == STATE_DISABLED) && (mbPtr->disabledFg != NULL)) { + gc = mbPtr->disabledGC; + border = mbPtr->normalBorder; + } else if ((mbPtr->state == STATE_ACTIVE) + && !Tk_StrictMotif(mbPtr->tkwin)) { + gc = mbPtr->activeTextGC; + border = mbPtr->activeBorder; + } else { + gc = mbPtr->normalTextGC; + border = mbPtr->normalBorder; + } + + if (mbPtr->image != None) { + Tk_SizeOfImage(mbPtr->image, &width, &height); + haveImage = 1; + } else if (mbPtr->bitmap != None) { + Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height); + haveImage = 1; + } + imageWidth = width; + imageHeight = height; + + haveText = (mbPtr->textWidth != 0 && mbPtr->textHeight != 0); + + /* + * In order to avoid screen flashes, this function redraws the menu button + * in a pixmap, then copies the pixmap to the screen in a single + * operation. This means that there's no point in time where the on-sreen + * image has been cleared. + */ + + pixmap = Tk_GetPixmap(mbPtr->display, Tk_WindowId(tkwin), + Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); + Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin), + Tk_Height(tkwin), 0, TK_RELIEF_FLAT); + + imageXOffset = 0; + imageYOffset = 0; + textXOffset = 0; + textYOffset = 0; + fullWidth = 0; + fullHeight = 0; + + if (mbPtr->compound != COMPOUND_NONE && haveImage && haveText) { + switch ((enum compound) mbPtr->compound) { + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text. + */ + + if (mbPtr->compound == COMPOUND_TOP) { + textYOffset = height + mbPtr->padY; + } else { + imageYOffset = mbPtr->textHeight + mbPtr->padY; + } + fullHeight = height + mbPtr->textHeight + mbPtr->padY; + fullWidth = (width > mbPtr->textWidth ? width : mbPtr->textWidth); + textXOffset = (fullWidth - mbPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text. + */ + + if (mbPtr->compound == COMPOUND_LEFT) { + textXOffset = width + mbPtr->padX; + } else { + imageXOffset = mbPtr->textWidth + mbPtr->padX; + } + fullWidth = mbPtr->textWidth + mbPtr->padX + width; + fullHeight = (height > mbPtr->textHeight ? height : + mbPtr->textHeight); + textYOffset = (fullHeight - mbPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed. + */ + + fullWidth = (width > mbPtr->textWidth ? width : mbPtr->textWidth); + fullHeight = (height > mbPtr->textHeight ? height : + mbPtr->textHeight); + textXOffset = (fullWidth - mbPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + textYOffset = (fullHeight - mbPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; + case COMPOUND_NONE: + break; + } + + TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, + mbPtr->indicatorWidth + fullWidth, fullHeight, &x, &y); + + imageXOffset += x; + imageYOffset += y; + if (mbPtr->image != NULL) { + Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap, + imageXOffset, imageYOffset); + } else if (mbPtr->bitmap != None) { + XSetClipOrigin(mbPtr->display, gc, imageXOffset, imageYOffset); + XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap, + gc, 0, 0, (unsigned) width, (unsigned) height, + imageXOffset, imageYOffset, 1); + XSetClipOrigin(mbPtr->display, gc, 0, 0); + } + + Tk_DrawTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout, + x + textXOffset, y + textYOffset, 0, -1); + Tk_UnderlineTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout, + x + textXOffset, y + textYOffset, mbPtr->underline); + } else if (haveImage) { + TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, + width + mbPtr->indicatorWidth, height, &x, &y); + imageXOffset += x; + imageYOffset += y; + if (mbPtr->image != NULL) { + Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap, + imageXOffset, imageYOffset); + } else if (mbPtr->bitmap != None) { + XSetClipOrigin(mbPtr->display, gc, x, y); + XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap, + gc, 0, 0, (unsigned) width, (unsigned) height, + x, y, 1); + XSetClipOrigin(mbPtr->display, gc, 0, 0); + } + } else { + TkComputeAnchor(mbPtr->anchor, tkwin, mbPtr->padX, mbPtr->padY, + mbPtr->textWidth + mbPtr->indicatorWidth, + mbPtr->textHeight, &x, &y); + Tk_DrawTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout, + x + textXOffset, y + textYOffset, 0, -1); + Tk_UnderlineTextLayout(mbPtr->display, pixmap, gc, + mbPtr->textLayout, x + textXOffset, y + textYOffset, + mbPtr->underline); + } + + /* + * If the menu button is disabled with a stipple rather than a special + * foreground color, generate the stippled effect. + */ + + if ((mbPtr->state == STATE_DISABLED) + && ((mbPtr->disabledFg == NULL) || (mbPtr->image != NULL))) { + /* + * Stipple the whole button if no disabledFg was specified, otherwise + * restrict stippling only to displayed image + */ + + if (mbPtr->disabledFg == NULL) { + XFillRectangle(mbPtr->display, pixmap, mbPtr->stippleGC, + mbPtr->inset, mbPtr->inset, + (unsigned) (Tk_Width(tkwin) - 2*mbPtr->inset), + (unsigned) (Tk_Height(tkwin) - 2*mbPtr->inset)); + } else { + XFillRectangle(mbPtr->display, pixmap, mbPtr->stippleGC, + imageXOffset, imageYOffset, + (unsigned) imageWidth, (unsigned) imageHeight); + } + } + + /* + * Draw the cascade indicator for the menu button on the right side of the + * window, if desired. + */ + + if (mbPtr->indicatorOn) { + int borderWidth; + + borderWidth = (mbPtr->indicatorHeight+1)/3; + if (borderWidth < 1) { + borderWidth = 1; + } + /*y += mbPtr->textHeight / 2;*/ + Tk_Fill3DRectangle(tkwin, pixmap, border, + Tk_Width(tkwin) - mbPtr->inset - mbPtr->indicatorWidth + + mbPtr->indicatorHeight, + ((int) (Tk_Height(tkwin) - mbPtr->indicatorHeight))/2, + mbPtr->indicatorWidth - 2*mbPtr->indicatorHeight, + mbPtr->indicatorHeight, borderWidth, TK_RELIEF_RAISED); + } + + /* + * Draw the border and traversal highlight last. This way, if the menu + * button's contents overflow onto the border they'll be covered up by the + * border. + */ + + if (mbPtr->relief != TK_RELIEF_FLAT) { + Tk_Draw3DRectangle(tkwin, pixmap, border, + mbPtr->highlightWidth, mbPtr->highlightWidth, + Tk_Width(tkwin) - 2*mbPtr->highlightWidth, + Tk_Height(tkwin) - 2*mbPtr->highlightWidth, + mbPtr->borderWidth, mbPtr->relief); + } + if (mbPtr->highlightWidth != 0) { + GC gc; + + if (mbPtr->flags & GOT_FOCUS) { + gc = Tk_GCForColor(mbPtr->highlightColorPtr, pixmap); + } else { + gc = Tk_GCForColor(mbPtr->highlightBgColorPtr, pixmap); + } + Tk_DrawFocusHighlight(tkwin, gc, mbPtr->highlightWidth, pixmap); + } + + /* + * Copy the information from the off-screen pixmap onto the screen, then + * delete the pixmap. + */ + + XCopyArea(mbPtr->display, pixmap, Tk_WindowId(tkwin), + mbPtr->normalTextGC, 0, 0, (unsigned) Tk_Width(tkwin), + (unsigned) Tk_Height(tkwin), 0, 0); + Tk_FreePixmap(mbPtr->display, pixmap); +} + +/* + *---------------------------------------------------------------------- + * + * TkpDestroyMenuButton -- + * + * Free data structures associated with the menubutton control. + * + * Results: + * None. + * + * Side effects: + * Restores the default control state. + * + *---------------------------------------------------------------------- + */ + +void +TkpDestroyMenuButton( + TkMenuButton *mbPtr) +{ +} + +/* + *---------------------------------------------------------------------- + * + * TkpComputeMenuButtonGeometry -- + * + * After changes in a menu button's text or bitmap, this function + * recomputes the menu button's geometry and passes this information + * along to the geometry manager for the window. + * + * Results: + * None. + * + * Side effects: + * The menu button's window may change size. + * + *---------------------------------------------------------------------- + */ + +void +TkpComputeMenuButtonGeometry( + TkMenuButton *mbPtr) /* Widget record for menu button. */ +{ + int width, height, mm, pixels; + int avgWidth, txtWidth, txtHeight; + int haveImage = 0, haveText = 0; + Tk_FontMetrics fm; + + mbPtr->inset = mbPtr->highlightWidth + mbPtr->borderWidth; + + width = 0; + height = 0; + txtWidth = 0; + txtHeight = 0; + avgWidth = 0; + + if (mbPtr->image != None) { + Tk_SizeOfImage(mbPtr->image, &width, &height); + haveImage = 1; + } else if (mbPtr->bitmap != None) { + Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height); + haveImage = 1; + } + + if (haveImage == 0 || mbPtr->compound != COMPOUND_NONE) { + Tk_FreeTextLayout(mbPtr->textLayout); + + mbPtr->textLayout = Tk_ComputeTextLayout(mbPtr->tkfont, mbPtr->text, + -1, mbPtr->wrapLength, mbPtr->justify, 0, &mbPtr->textWidth, + &mbPtr->textHeight); + txtWidth = mbPtr->textWidth; + txtHeight = mbPtr->textHeight; + avgWidth = Tk_TextWidth(mbPtr->tkfont, "0", 1); + Tk_GetFontMetrics(mbPtr->tkfont, &fm); + haveText = (txtWidth != 0 && txtHeight != 0); + } + + /* + * If the menubutton is compound (ie, it shows both an image and text), + * the new geometry is a combination of the image and text geometry. We + * only honor the compound bit if the menubutton has both text and an + * image, because otherwise it is not really a compound menubutton. + */ + + if (mbPtr->compound != COMPOUND_NONE && haveImage && haveText) { + switch ((enum compound) mbPtr->compound) { + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text. + */ + + height += txtHeight + mbPtr->padY; + width = (width > txtWidth ? width : txtWidth); + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text. + */ + + width += txtWidth + mbPtr->padX; + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed. + */ + + width = (width > txtWidth ? width : txtWidth); + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_NONE: + break; + } + if (mbPtr->width > 0) { + width = mbPtr->width; + } + if (mbPtr->height > 0) { + height = mbPtr->height; + } + width += 2*mbPtr->padX; + height += 2*mbPtr->padY; + } else { + if (haveImage) { + if (mbPtr->width > 0) { + width = mbPtr->width; + } + if (mbPtr->height > 0) { + height = mbPtr->height; + } + } else { + width = txtWidth; + height = txtHeight; + if (mbPtr->width > 0) { + width = mbPtr->width * avgWidth; + } + if (mbPtr->height > 0) { + height = mbPtr->height * fm.linespace; + } + } + } + + if (! haveImage) { + width += 2*mbPtr->padX; + height += 2*mbPtr->padY; + } + + if (mbPtr->indicatorOn) { + mm = WidthMMOfScreen(Tk_Screen(mbPtr->tkwin)); + pixels = WidthOfScreen(Tk_Screen(mbPtr->tkwin)); + mbPtr->indicatorHeight= (INDICATOR_HEIGHT * pixels)/(10*mm); + mbPtr->indicatorWidth = (INDICATOR_WIDTH * pixels)/(10*mm) + + 2*mbPtr->indicatorHeight; + width += mbPtr->indicatorWidth; + } else { + mbPtr->indicatorHeight = 0; + mbPtr->indicatorWidth = 0; + } + + Tk_GeometryRequest(mbPtr->tkwin, (int) (width + 2*mbPtr->inset), + (int) (height + 2*mbPtr->inset)); + Tk_SetInternalBorder(mbPtr->tkwin, mbPtr->inset); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixPort.h b/tk8.6/unix/tkUnixPort.h new file mode 100644 index 0000000..dbd5e09 --- /dev/null +++ b/tk8.6/unix/tkUnixPort.h @@ -0,0 +1,192 @@ +/* + * tkUnixPort.h -- + * + * This file is included by all of the Tk C files. It contains + * information that may be configuration-dependent, such as + * #includes for system include files and a few other things. + * + * Copyright (c) 1991-1993 The Regents of the University of California. + * Copyright (c) 1994-1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#ifndef _UNIXPORT +#define _UNIXPORT + +#define __UNIX__ 1 + +#include <stdio.h> +#include <ctype.h> +#include <fcntl.h> +#include <limits.h> +#include <math.h> +#include <pwd.h> +#ifdef NO_STDLIB_H +# include "../compat/stdlib.h" +#else +# include <stdlib.h> +#endif +#include <string.h> +#include <sys/types.h> +#include <sys/file.h> +#ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +#endif +#include <sys/stat.h> +#ifndef _TCL +# include <tcl.h> +#endif +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif +#if HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifndef NO_UNISTD_H +# include <unistd.h> +#else +# include "../compat/unistd.h" +#endif +#include <X11/Xlib.h> +#include <X11/cursorfont.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include <X11/Xproto.h> +#include <X11/Xresource.h> +#include <X11/Xutil.h> + +/* + * The following macro defines the type of the mask arguments to + * select: + */ + +#ifndef NO_FD_SET +# define SELECT_MASK fd_set +#else +# ifndef _AIX + typedef long fd_mask; +# endif +# if defined(_IBMR2) +# define SELECT_MASK void +# else +# define SELECT_MASK int +# endif +#endif + +/* + * The following macro defines the number of fd_masks in an fd_set: + */ + +#ifndef FD_SETSIZE +# ifdef OPEN_MAX +# define FD_SETSIZE OPEN_MAX +# else +# define FD_SETSIZE 256 +# endif +#endif +#if !defined(howmany) +# define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#ifndef NFDBITS +# define NFDBITS NBBY*sizeof(fd_mask) +#endif +#define MASK_SIZE howmany(FD_SETSIZE, NFDBITS) + +/* + * Define "NBBY" (number of bits per byte) if it's not already defined. + */ + +#ifndef NBBY +# define NBBY 8 +#endif + +#ifdef __CYGWIN__ +# include "tkIntXlibDecls.h" +# define UINT unsigned int +# define HWND void * +# define HDC void * +# define HINSTANCE void * +# define COLORREF void * +# define HMENU void * +# define TkWinDCState void +# define HPALETTE void * +# define WNDPROC void * +# define WPARAM void * +# define LPARAM void * +# define LRESULT void * + +#else /* !__CYGWIN__ */ + /* + * The TkPutImage macro strips off the color table information, which isn't + * needed for X. + */ + +# define TkPutImage(colors, ncolors, display, pixels, gc, image, srcx, srcy, destx, desty, width, height) \ + XPutImage(display, pixels, gc, image, srcx, srcy, destx, \ + desty, width, height); + +#endif /* !__CYGWIN__ */ + +/* + * Supply macros for seek offsets, if they're not already provided by + * an include file. + */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +#ifndef SEEK_CUR +# define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +# define SEEK_END 2 +#endif + +/* + * Declarations for various library procedures that may not be declared + * in any other header file. + */ + + +/* + * These functions do nothing under Unix, so we just eliminate calls to them. + */ + +#define TkpButtonSetDefaults() {} +#define TkpDestroyButton(butPtr) {} +#define TkSelUpdateClipboard(a,b) {} +#ifndef __CYGWIN__ +#define TkSetPixmapColormap(p,c) {} +#endif + +/* + * These calls implement native bitmaps which are not supported under + * UNIX. The macros eliminate the calls. + */ + +#define TkpDefineNativeBitmaps() +#define TkpCreateNativeBitmap(display, source) None +#define TkpGetNativeAppBitmap(display, name, w, h) None + +/* + * This macro stores a representation of the window handle in a string. + * This should perhaps use the real size of an XID. + */ + +#ifndef __CYGWIN__ +#define TkpPrintWindowId(buf,w) \ + sprintf((buf), "%#08lx", (unsigned long) (w)) +#endif + +#endif /* _UNIXPORT */ diff --git a/tk8.6/unix/tkUnixRFont.c b/tk8.6/unix/tkUnixRFont.c new file mode 100644 index 0000000..70aebfa --- /dev/null +++ b/tk8.6/unix/tkUnixRFont.c @@ -0,0 +1,1259 @@ +/* + * tkUnixRFont.c -- + * + * Alternate implementation of tkUnixFont.c using Xft. + * + * Copyright (c) 2002-2003 Keith Packard + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tkUnixInt.h" +#include "tkFont.h" +#include <X11/Xft/Xft.h> +#include <ctype.h> + +#define MAX_CACHED_COLORS 16 + +typedef struct { + XftFont *ftFont; + XftFont *ft0Font; + FcPattern *source; + FcCharSet *charset; + double angle; +} UnixFtFace; + +typedef struct { + XftColor color; + int next; +} UnixFtColorList; + +typedef struct { + TkFont font; /* Stuff used by generic font package. Must be + * first in structure. */ + UnixFtFace *faces; + int nfaces; + FcFontSet *fontset; + FcPattern *pattern; + + Display *display; + int screen; + XftDraw *ftDraw; + int ncolors; + int firstColor; + UnixFtColorList colors[MAX_CACHED_COLORS]; +} UnixFtFont; + +/* + * Used to describe the current clipping box. Can't be passed normally because + * the information isn't retrievable from the GC. + */ + +typedef struct ThreadSpecificData { + Region clipRegion; /* The clipping region, or None. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + +/* + * Package initialization: + * Nothing to do here except register the fact that we're using Xft in + * the TIP 59 configuration database. + */ + +#ifndef TCL_CFGVAL_ENCODING +#define TCL_CFGVAL_ENCODING "ascii" +#endif + +void +TkpFontPkgInit( + TkMainInfo *mainPtr) /* The application being created. */ +{ + static Tcl_Config cfg[] = { + { "fontsystem", "xft" }, + { 0,0 } + }; + + Tcl_RegisterConfig(mainPtr->interp, "tk", cfg, TCL_CFGVAL_ENCODING); +} + +static XftFont * +GetFont( + UnixFtFont *fontPtr, + FcChar32 ucs4, + double angle) +{ + int i; + + if (ucs4) { + for (i = 0; i < fontPtr->nfaces; i++) { + FcCharSet *charset = fontPtr->faces[i].charset; + + if (charset && FcCharSetHasChar(charset, ucs4)) { + break; + } + } + if (i == fontPtr->nfaces) { + i = 0; + } + } else { + i = 0; + } + if ((angle == 0.0 && !fontPtr->faces[i].ft0Font) || (angle != 0.0 && + (!fontPtr->faces[i].ftFont || fontPtr->faces[i].angle != angle))){ + FcPattern *pat = FcFontRenderPrepare(0, fontPtr->pattern, + fontPtr->faces[i].source); + double s = sin(angle*PI/180.0), c = cos(angle*PI/180.0); + FcMatrix mat; + XftFont *ftFont; + + /* + * Initialize the matrix manually so this can compile with HP-UX cc + * (which does not allow non-constant structure initializers). [Bug + * 2978410] + */ + + mat.xx = mat.yy = c; + mat.xy = -(mat.yx = s); + + if (angle != 0.0) { + FcPatternAddMatrix(pat, FC_MATRIX, &mat); + } + ftFont = XftFontOpenPattern(fontPtr->display, pat); + if (!ftFont) { + /* + * The previous call to XftFontOpenPattern() should not fail, but + * sometimes does anyway. Usual cause appears to be a + * misconfigured fontconfig installation; see [Bug 1090382]. Try a + * fallback: + */ + + ftFont = XftFontOpen(fontPtr->display, fontPtr->screen, + FC_FAMILY, FcTypeString, "sans", + FC_SIZE, FcTypeDouble, 12.0, + FC_MATRIX, FcTypeMatrix, &mat, + NULL); + } + if (!ftFont) { + /* + * The previous call should definitely not fail. Impossible to + * proceed at this point. + */ + + Tcl_Panic("Cannot find a usable font"); + } + + if (angle == 0.0) { + fontPtr->faces[i].ft0Font = ftFont; + } else { + if (fontPtr->faces[i].ftFont) { + XftFontClose(fontPtr->display, fontPtr->faces[i].ftFont); + } + fontPtr->faces[i].ftFont = ftFont; + fontPtr->faces[i].angle = angle; + } + } + return (angle==0.0? fontPtr->faces[i].ft0Font : fontPtr->faces[i].ftFont); +} + +/* + *--------------------------------------------------------------------------- + * + * GetTkFontAttributes -- + * Fill in TkFontAttributes from an XftFont. + */ + +static void +GetTkFontAttributes( + XftFont *ftFont, + TkFontAttributes *faPtr) +{ + const char *family = "Unknown"; + const char *const *familyPtr = &family; + int weight, slant, pxsize; + double size, ptsize; + + (void) XftPatternGetString(ftFont->pattern, XFT_FAMILY, 0, familyPtr); + if (XftPatternGetDouble(ftFont->pattern, XFT_SIZE, 0, + &ptsize) == XftResultMatch) { + size = ptsize; + } else if (XftPatternGetDouble(ftFont->pattern, XFT_PIXEL_SIZE, 0, + &ptsize) == XftResultMatch) { + size = -ptsize; + } else if (XftPatternGetInteger(ftFont->pattern, XFT_PIXEL_SIZE, 0, + &pxsize) == XftResultMatch) { + size = (double)-pxsize; + } else { + size = 12.0; + } + if (XftPatternGetInteger(ftFont->pattern, XFT_WEIGHT, 0, + &weight) != XftResultMatch) { + weight = XFT_WEIGHT_MEDIUM; + } + if (XftPatternGetInteger(ftFont->pattern, XFT_SLANT, 0, + &slant) != XftResultMatch) { + slant = XFT_SLANT_ROMAN; + } + +#if DEBUG_FONTSEL + printf("family %s size %d weight %d slant %d\n", + family, (int)size, weight, slant); +#endif /* DEBUG_FONTSEL */ + + faPtr->family = Tk_GetUid(family); + faPtr->size = size; + faPtr->weight = (weight > XFT_WEIGHT_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL; + faPtr->slant = (slant > XFT_SLANT_ROMAN) ? TK_FS_ITALIC : TK_FS_ROMAN; + faPtr->underline = 0; + faPtr->overstrike = 0; +} + +/* + *--------------------------------------------------------------------------- + * + * GetTkFontMetrics -- + * Fill in TkFontMetrics from an XftFont. + */ + +static void +GetTkFontMetrics( + XftFont *ftFont, + TkFontMetrics *fmPtr) +{ + int spacing; + + if (XftPatternGetInteger(ftFont->pattern, XFT_SPACING, 0, + &spacing) != XftResultMatch) { + spacing = XFT_PROPORTIONAL; + } + + fmPtr->ascent = ftFont->ascent; + fmPtr->descent = ftFont->descent; + fmPtr->maxWidth = ftFont->max_advance_width; + fmPtr->fixed = spacing != XFT_PROPORTIONAL; +} + +/* + *--------------------------------------------------------------------------- + * + * InitFont -- + * + * Initializes the fields of a UnixFtFont structure. If fontPtr is NULL, + * also allocates a new UnixFtFont. + * + * Results: + * On error, frees fontPtr and returns NULL, otherwise returns fontPtr. + * + *--------------------------------------------------------------------------- + */ + +static UnixFtFont * +InitFont( + Tk_Window tkwin, + FcPattern *pattern, + UnixFtFont *fontPtr) +{ + FcFontSet *set; + FcCharSet *charset; + FcResult result; + XftFont *ftFont; + int i, iWidth; + + if (!fontPtr) { + fontPtr = ckalloc(sizeof(UnixFtFont)); + } + + FcConfigSubstitute(0, pattern, FcMatchPattern); + XftDefaultSubstitute(Tk_Display(tkwin), Tk_ScreenNumber(tkwin), pattern); + + /* + * Generate the list of fonts + */ + + set = FcFontSort(0, pattern, FcTrue, NULL, &result); + if (!set) { + ckfree(fontPtr); + return NULL; + } + + fontPtr->fontset = set; + fontPtr->pattern = pattern; + fontPtr->faces = ckalloc(set->nfont * sizeof(UnixFtFace)); + fontPtr->nfaces = set->nfont; + + /* + * Fill in information about each returned font + */ + + for (i = 0; i < set->nfont; i++) { + fontPtr->faces[i].ftFont = 0; + fontPtr->faces[i].ft0Font = 0; + fontPtr->faces[i].source = set->fonts[i]; + if (FcPatternGetCharSet(set->fonts[i], FC_CHARSET, 0, + &charset) == FcResultMatch) { + fontPtr->faces[i].charset = FcCharSetCopy(charset); + } else { + fontPtr->faces[i].charset = 0; + } + fontPtr->faces[i].angle = 0.0; + } + + fontPtr->display = Tk_Display(tkwin); + fontPtr->screen = Tk_ScreenNumber(tkwin); + fontPtr->ftDraw = 0; + fontPtr->ncolors = 0; + fontPtr->firstColor = -1; + + /* + * Fill in platform-specific fields of TkFont. + */ + + ftFont = GetFont(fontPtr, 0, 0.0); + fontPtr->font.fid = XLoadFont(Tk_Display(tkwin), "fixed"); + GetTkFontAttributes(ftFont, &fontPtr->font.fa); + GetTkFontMetrics(ftFont, &fontPtr->font.fm); + + /* + * Fontconfig can't report any information about the position or thickness + * of underlines or overstrikes. Thus, we use some defaults that are + * hacked around from backup defaults in tkUnixFont.c, which are in turn + * based on recommendations in the X manual. The comments from that file + * leading to these computations were: + * + * If the XA_UNDERLINE_POSITION property does not exist, the X manual + * recommends using half the descent. + * + * If the XA_UNDERLINE_THICKNESS property does not exist, the X + * manual recommends using the width of the stem on a capital letter. + * I don't know of a way to get the stem width of a letter, so guess + * and use 1/3 the width of a capital I. + * + * Note that nothing corresponding to *either* property is reported by + * Fontconfig at all. [Bug 1961455] + */ + + { + TkFont *fPtr = &fontPtr->font; + + fPtr->underlinePos = fPtr->fm.descent / 2; + Tk_MeasureChars((Tk_Font) fPtr, "I", 1, -1, 0, &iWidth); + fPtr->underlineHeight = iWidth / 3; + if (fPtr->underlineHeight == 0) { + fPtr->underlineHeight = 1; + } + if (fPtr->underlineHeight + fPtr->underlinePos > fPtr->fm.descent) { + fPtr->underlineHeight = fPtr->fm.descent - fPtr->underlinePos; + if (fPtr->underlineHeight == 0) { + fPtr->underlinePos--; + fPtr->underlineHeight = 1; + } + } + } + + return fontPtr; +} + +static void +FinishedWithFont( + UnixFtFont *fontPtr) +{ + Display *display = fontPtr->display; + int i; + Tk_ErrorHandler handler = + Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL); + + for (i = 0; i < fontPtr->nfaces; i++) { + if (fontPtr->faces[i].ftFont) { + XftFontClose(fontPtr->display, fontPtr->faces[i].ftFont); + } + if (fontPtr->faces[i].ft0Font) { + XftFontClose(fontPtr->display, fontPtr->faces[i].ft0Font); + } + if (fontPtr->faces[i].charset) { + FcCharSetDestroy(fontPtr->faces[i].charset); + } + } + if (fontPtr->faces) { + ckfree(fontPtr->faces); + } + if (fontPtr->pattern) { + FcPatternDestroy(fontPtr->pattern); + } + if (fontPtr->ftDraw) { + XftDrawDestroy(fontPtr->ftDraw); + } + if (fontPtr->font.fid) { + XUnloadFont(fontPtr->display, fontPtr->font.fid); + } + if (fontPtr->fontset) { + FcFontSetDestroy(fontPtr->fontset); + } + Tk_DeleteErrorHandler(handler); +} + +TkFont * +TkpGetNativeFont( + Tk_Window tkwin, /* For display where font will be used. */ + const char *name) /* Platform-specific font name. */ +{ + UnixFtFont *fontPtr; + FcPattern *pattern; +#if DEBUG_FONTSEL + printf("TkpGetNativeFont %s\n", name); +#endif /* DEBUG_FONTSEL */ + + pattern = XftXlfdParse(name, FcFalse, FcFalse); + if (!pattern) { + return NULL; + } + + /* + * Should also try: pattern = FcNameParse(name); but generic/tkFont.c + * expects TkpGetNativeFont() to only work on XLFD names under Unix. + */ + + fontPtr = InitFont(tkwin, pattern, NULL); + if (!fontPtr) { + FcPatternDestroy(pattern); + return NULL; + } + return &fontPtr->font; +} + +TkFont * +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. */ +{ + XftPattern *pattern; + int weight, slant; + UnixFtFont *fontPtr; + +#if DEBUG_FONTSEL + printf("TkpGetFontFromAttributes %s-%d %d %d\n", faPtr->family, + faPtr->size, faPtr->weight, faPtr->slant); +#endif /* DEBUG_FONTSEL */ + pattern = XftPatternCreate(); + if (faPtr->family) { + XftPatternAddString(pattern, XFT_FAMILY, faPtr->family); + } + if (faPtr->size > 0.0) { + XftPatternAddDouble(pattern, XFT_SIZE, faPtr->size); + } else if (faPtr->size < 0.0) { + XftPatternAddDouble(pattern, XFT_SIZE, TkFontGetPoints(tkwin, faPtr->size)); + } else { + XftPatternAddDouble(pattern, XFT_SIZE, 12.0); + } + switch (faPtr->weight) { + case TK_FW_NORMAL: + default: + weight = XFT_WEIGHT_MEDIUM; + break; + case TK_FW_BOLD: + weight = XFT_WEIGHT_BOLD; + break; + } + XftPatternAddInteger(pattern, XFT_WEIGHT, weight); + switch (faPtr->slant) { + case TK_FS_ROMAN: + default: + slant = XFT_SLANT_ROMAN; + break; + case TK_FS_ITALIC: + slant = XFT_SLANT_ITALIC; + break; + case TK_FS_OBLIQUE: + slant = XFT_SLANT_OBLIQUE; + break; + } + XftPatternAddInteger(pattern, XFT_SLANT, slant); + + fontPtr = (UnixFtFont *) tkFontPtr; + if (fontPtr != NULL) { + FinishedWithFont(fontPtr); + } + fontPtr = InitFont(tkwin, pattern, fontPtr); + + /* + * Hack to work around issues with weird issues with Xft/Xrender + * connection. For details, see comp.lang.tcl thread starting from + * <adcc99ed-c73e-4efc-bb5d-e57a57a051e8@l35g2000pra.googlegroups.com> + */ + + if (!fontPtr) { + XftPatternAddBool(pattern, XFT_RENDER, FcFalse); + fontPtr = InitFont(tkwin, pattern, fontPtr); + } + + if (!fontPtr) { + FcPatternDestroy(pattern); + return NULL; + } + + fontPtr->font.fa.underline = faPtr->underline; + fontPtr->font.fa.overstrike = faPtr->overstrike; + return &fontPtr->font; +} + +void +TkpDeleteFont( + TkFont *tkFontPtr) /* Token of font to be deleted. */ +{ + UnixFtFont *fontPtr = (UnixFtFont *) tkFontPtr; + + FinishedWithFont(fontPtr); + /* XXX tkUnixFont.c doesn't free tkFontPtr... */ +} + +/* + *--------------------------------------------------------------------------- + * + * TkpGetFontFamilies -- + * + * Return information about the font families that are available on the + * display of the given window. + * + * Results: + * Modifies interp's result object to hold a list of all the available + * font families. + * + *--------------------------------------------------------------------------- + */ + +void +TkpGetFontFamilies( + Tcl_Interp *interp, /* Interp to hold result. */ + Tk_Window tkwin) /* For display to query. */ +{ + Tcl_Obj *resultPtr; + XftFontSet *list; + int i; + + resultPtr = Tcl_NewListObj(0, NULL); + + list = XftListFonts(Tk_Display(tkwin), Tk_ScreenNumber(tkwin), + (char *) 0, /* pattern elements */ + XFT_FAMILY, (char*) 0); /* fields */ + for (i = 0; i < list->nfont; i++) { + char *family, **familyPtr = &family; + + if (XftPatternGetString(list->fonts[i], XFT_FAMILY, 0, familyPtr) + == XftResultMatch) { + Tcl_Obj *strPtr = Tcl_NewStringObj(family, -1); + + Tcl_ListObjAppendElement(NULL, resultPtr, strPtr); + } + } + XftFontSetDestroy(list); + + Tcl_SetObjResult(interp, resultPtr); +} + +/* + *------------------------------------------------------------------------- + * + * TkpGetSubFonts -- + * + * Called by [testfont subfonts] in the Tk testing package. + * + * Results: + * Sets interp's result to a list of the faces used by tkfont + * + *------------------------------------------------------------------------- + */ + +void +TkpGetSubFonts( + Tcl_Interp *interp, + Tk_Font tkfont) +{ + Tcl_Obj *objv[3], *listPtr, *resultPtr; + UnixFtFont *fontPtr = (UnixFtFont *) tkfont; + FcPattern *pattern; + const char *family = "Unknown"; + const char *const *familyPtr = &family; + const char *foundry = "Unknown"; + const char *const *foundryPtr = &foundry; + const char *encoding = "Unknown"; + const char *const *encodingPtr = &encoding; + int i; + + resultPtr = Tcl_NewListObj(0, NULL); + + for (i = 0; i < fontPtr->nfaces ; ++i) { + pattern = FcFontRenderPrepare(0, fontPtr->pattern, + fontPtr->faces[i].source); + + XftPatternGetString(pattern, XFT_FAMILY, 0, familyPtr); + XftPatternGetString(pattern, XFT_FOUNDRY, 0, foundryPtr); + XftPatternGetString(pattern, XFT_ENCODING, 0, encodingPtr); + objv[0] = Tcl_NewStringObj(family, -1); + objv[1] = Tcl_NewStringObj(foundry, -1); + objv[2] = Tcl_NewStringObj(encoding, -1); + listPtr = Tcl_NewListObj(3, objv); + Tcl_ListObjAppendElement(NULL, resultPtr, listPtr); + } + Tcl_SetObjResult(interp, resultPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetFontAttrsForChar -- + * + * Retrieve the font attributes of the actual font used to render a given + * character. + * + *---------------------------------------------------------------------- + */ + +void +TkpGetFontAttrsForChar( + Tk_Window tkwin, /* Window on the font's display */ + Tk_Font tkfont, /* Font to query */ + int c, /* Character of interest */ + TkFontAttributes *faPtr) /* Output: Font attributes */ +{ + UnixFtFont *fontPtr = (UnixFtFont *) tkfont; + /* Structure describing the logical font */ + FcChar32 ucs4 = (FcChar32) c; + /* UCS-4 character to map */ + XftFont *ftFont = GetFont(fontPtr, ucs4, 0.0); + /* Actual font used to render the character */ + + GetTkFontAttributes(ftFont, faPtr); + faPtr->underline = fontPtr->font.fa.underline; + faPtr->overstrike = fontPtr->font.fa.overstrike; +} + +int +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 numBytes, /* Maximum number of bytes to consider from + * source string. */ + 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: + * 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 + * terminating character. */ +{ + UnixFtFont *fontPtr = (UnixFtFont *) tkfont; + XftFont *ftFont; + FcChar32 c; + XGlyphInfo extents; + int clen, curX, newX, curByte, newByte, sawNonSpace; + int termByte = 0, termX = 0; +#if DEBUG_FONTSEL + char string[256]; + int len = 0; +#endif /* DEBUG_FONTSEL */ + + curX = 0; + curByte = 0; + sawNonSpace = 0; + while (numBytes > 0) { + int unichar; + + clen = TkUtfToUniChar(source, &unichar); + c = (FcChar32) unichar; + + if (clen <= 0) { + /* + * This can't happen (but see #1185640) + */ + + *lengthPtr = curX; + return curByte; + } + + source += clen; + numBytes -= clen; + if (c < 256 && isspace(c)) { /* I18N: ??? */ + if (sawNonSpace) { + termByte = curByte; + termX = curX; + sawNonSpace = 0; + } + } else { + sawNonSpace = 1; + } + +#if DEBUG_FONTSEL + string[len++] = (char) c; +#endif /* DEBUG_FONTSEL */ + ftFont = GetFont(fontPtr, c, 0.0); + + XftTextExtents32(fontPtr->display, ftFont, &c, 1, &extents); + + newX = curX + extents.xOff; + newByte = curByte + clen; + if (maxLength >= 0 && newX > maxLength) { + if (flags & TK_PARTIAL_OK || + (flags & TK_AT_LEAST_ONE && curByte == 0)) { + curX = newX; + curByte = newByte; + } else if (flags & TK_WHOLE_WORDS) { + if ((flags & TK_AT_LEAST_ONE) && (termX == 0)) { + /* + * No space was seen before reaching the right + * of the allotted maxLength space, i.e. no word + * boundary. Return the string that fills the + * allotted space, without overfill. + * curX and curByte are already the right ones: + */ + } else { + curX = termX; + curByte = termByte; + } + } + break; + } + + curX = newX; + curByte = newByte; + } +#if DEBUG_FONTSEL + string[len] = '\0'; + printf("MeasureChars %s length %d bytes %d\n", string, curX, curByte); +#endif /* DEBUG_FONTSEL */ + *lengthPtr = curX; + return curByte; +} + +int +TkpMeasureCharsInContext( + Tk_Font tkfont, + const char *source, + int numBytes, + int rangeStart, + int rangeLength, + int maxLength, + int flags, + int *lengthPtr) +{ + (void) numBytes; /*unused*/ + + return Tk_MeasureChars(tkfont, source + rangeStart, rangeLength, + maxLength, flags, lengthPtr); +} + +/* + *---------------------------------------------------------------------- + * + * LookUpColor -- + * + * Convert a pixel value to an XftColor. This can be slow due to the + * need to call XQueryColor, which involves a server round-trip. To + * avoid that, a least-recently-used cache of up to MAX_CACHED_COLORS + * is kept, in the form of a linked list. The returned color is moved + * to the front of the list, so repeatedly asking for the same one + * should be fast. + * + * Results: + * A pointer to the XftColor structure for the requested color is + * returned. + * + * Side effects: + * The converted color is stored in a cache in the UnixFtFont structure. The cache + * can hold at most MAX_CACHED_COLORS colors. If no more slots are available, the least + * recently used color is replaced with the new one. + *---------------------------------------------------------------------- + */ + +static XftColor * +LookUpColor(Display *display, /* Display to lookup colors on */ + UnixFtFont *fontPtr, /* Font to search for cached colors */ + unsigned long pixel) /* Pixel value to translate to XftColor */ +{ + int i, last = -1, last2 = -1; + XColor xcolor; + + for (i = fontPtr->firstColor; + i >= 0; last2 = last, last = i, i = fontPtr->colors[i].next) { + + if (pixel == fontPtr->colors[i].color.pixel) { + /* + * Color found in cache. Move it to the front of the list and return it. + */ + if (last >= 0) { + fontPtr->colors[last].next = fontPtr->colors[i].next; + fontPtr->colors[i].next = fontPtr->firstColor; + fontPtr->firstColor = i; + } + + return &fontPtr->colors[i].color; + } + } + + /* + * Color wasn't found, so it needs to be added to the cache. + * If a spare slot is available, it can be put there. If not, last + * will now point to the least recently used color, so replace that one. + */ + + if (fontPtr->ncolors < MAX_CACHED_COLORS) { + last2 = -1; + last = fontPtr->ncolors++; + } + + /* + * Translate the pixel value to a color. Needs a server round-trip. + */ + xcolor.pixel = pixel; + XQueryColor(display, DefaultColormap(display, fontPtr->screen), &xcolor); + + fontPtr->colors[last].color.color.red = xcolor.red; + fontPtr->colors[last].color.color.green = xcolor.green; + fontPtr->colors[last].color.color.blue = xcolor.blue; + fontPtr->colors[last].color.color.alpha = 0xffff; + fontPtr->colors[last].color.pixel = pixel; + + /* + * Put at the front of the list. + */ + if (last2 >= 0) { + fontPtr->colors[last2].next = fontPtr->colors[last].next; + } + fontPtr->colors[last].next = fontPtr->firstColor; + fontPtr->firstColor = last; + + return &fontPtr->colors[last].color; +} + +#define NUM_SPEC 1024 + +void +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, /* 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 numBytes, /* Number of bytes in string. */ + int x, int y) /* Coordinates at which to place origin of + * string when drawing. */ +{ + const int maxCoord = 0x7FFF;/* Xft coordinates are 16 bit values */ + const int minCoord = -maxCoord-1; + UnixFtFont *fontPtr = (UnixFtFont *) tkfont; + XGCValues values; + XftColor *xftcolor; + int clen, nspec, xStart = x; + XftGlyphFontSpec specs[NUM_SPEC]; + XGlyphInfo metrics; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (fontPtr->ftDraw == 0) { +#if DEBUG_FONTSEL + printf("Switch to drawable 0x%x\n", drawable); +#endif /* DEBUG_FONTSEL */ + fontPtr->ftDraw = XftDrawCreate(display, drawable, + DefaultVisual(display, fontPtr->screen), + DefaultColormap(display, fontPtr->screen)); + } else { + Tk_ErrorHandler handler = + Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL); + + XftDrawChange(fontPtr->ftDraw, drawable); + Tk_DeleteErrorHandler(handler); + } + XGetGCValues(display, gc, GCForeground, &values); + xftcolor = LookUpColor(display, fontPtr, values.foreground); + if (tsdPtr->clipRegion != None) { + XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion); + } + nspec = 0; + while (numBytes > 0) { + XftFont *ftFont; + FcChar32 c; + + clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes); + if (clen <= 0) { + /* + * This should not happen, but it can. + */ + + goto doUnderlineStrikeout; + } + source += clen; + numBytes -= clen; + + ftFont = GetFont(fontPtr, c, 0.0); + if (ftFont) { + specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c); + XftGlyphExtents(fontPtr->display, ftFont, &specs[nspec].glyph, 1, + &metrics); + + /* + * Draw glyph only when it fits entirely into 16 bit coords. + */ + + if (x >= minCoord && y >= minCoord && + x <= maxCoord - metrics.width && + y <= maxCoord - metrics.height) { + specs[nspec].font = ftFont; + specs[nspec].x = x; + specs[nspec].y = y; + if (++nspec == NUM_SPEC) { + XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor, + specs, nspec); + nspec = 0; + } + } + x += metrics.xOff; + y += metrics.yOff; + } + } + if (nspec) { + XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor, specs, nspec); + } + + doUnderlineStrikeout: + if (tsdPtr->clipRegion != None) { + XftDrawSetClip(fontPtr->ftDraw, None); + } + if (fontPtr->font.fa.underline != 0) { + XFillRectangle(display, drawable, gc, xStart, + y + fontPtr->font.underlinePos, (unsigned) (x - xStart), + (unsigned) fontPtr->font.underlineHeight); + } + if (fontPtr->font.fa.overstrike != 0) { + y -= fontPtr->font.fm.descent + (fontPtr->font.fm.ascent) / 10; + XFillRectangle(display, drawable, gc, xStart, y, + (unsigned) (x - xStart), + (unsigned) fontPtr->font.underlineHeight); + } +} + +/* + *--------------------------------------------------------------------------- + * + * TkDrawAngledChars -- + * + * Draw some characters at an angle. This would be simple code, except + * Xft has bugs with cumulative errors in character positioning which are + * caused by trying to perform all calculations internally with integers. + * So we have to do the work ourselves with floating-point math. + * + * Results: + * None. + * + * Side effects: + * Target drawable is updated. + * + *--------------------------------------------------------------------------- + */ + +void +TkDrawAngledChars( + 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, /* 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 numBytes, /* Number of bytes in string. */ + double x, double y, /* Coordinates at which to place origin of + * string when drawing. */ + double angle) /* What angle to put text at, in degrees. */ +{ + const int maxCoord = 0x7FFF;/* Xft coordinates are 16 bit values */ + const int minCoord = -maxCoord-1; + UnixFtFont *fontPtr = (UnixFtFont *) tkfont; + XGCValues values; + XftColor *xftcolor; + int xStart = x, yStart = y; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); +#ifdef XFT_HAS_FIXED_ROTATED_PLACEMENT + int clen, nglyph; + FT_UInt glyphs[NUM_SPEC]; + XGlyphInfo metrics; + XftFont *currentFtFont; + int originX, originY; + + if (fontPtr->ftDraw == 0) { +#if DEBUG_FONTSEL + printf("Switch to drawable 0x%x\n", drawable); +#endif /* DEBUG_FONTSEL */ + fontPtr->ftDraw = XftDrawCreate(display, drawable, + DefaultVisual(display, fontPtr->screen), + DefaultColormap(display, fontPtr->screen)); + } else { + Tk_ErrorHandler handler = + Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL); + + XftDrawChange(fontPtr->ftDraw, drawable); + Tk_DeleteErrorHandler(handler); + } + + XGetGCValues(display, gc, GCForeground, &values); + xftcolor = LookUpColor(display, fontPtr, values.foreground); + if (tsdPtr->clipRegion != None) { + XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion); + } + + nglyph = 0; + currentFtFont = NULL; + originX = originY = 0; /* lint */ + + while (numBytes > 0) { + XftFont *ftFont; + FcChar32 c; + + clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes); + if (clen <= 0) { + /* + * This should not happen, but it can. + */ + + goto doUnderlineStrikeout; + } + source += clen; + numBytes -= clen; + + ftFont = GetFont(fontPtr, c, angle); + if (!ftFont) { + continue; + } + + if (ftFont != currentFtFont || nglyph == NUM_SPEC) { + if (nglyph) { + /* + * We pass multiple glyphs at once to enable the code to + * perform better rendering of sub-pixel inter-glyph spacing. + * If only the current Xft implementation could make use of + * this information... but we'll be ready when it does! + */ + + XftGlyphExtents(fontPtr->display, currentFtFont, glyphs, + nglyph, &metrics); + /* + * Draw glyph only when it fits entirely into 16 bit coords. + */ + + if (x >= minCoord && y >= minCoord && + x <= maxCoord - metrics.width && + y <= maxCoord - metrics.height) { + + /* + * NOTE: + * The whole algorithm has a design problem, the choice of + * NUM_SPEC is arbitrary, and so the inter-glyph spacing could + * look arbitrary. This algorithm has to draw the whole string + * at once (or whole blocks with same font), this requires a + * dynamic 'glyphs' array. In case of overflow the array has to + * be divided until the maximal string will fit. (GC) + * Given the resolution of current displays though, this should + * not be a huge issue since NUM_SPEC is 1024 and thus able to + * cover about 6000 pixels for a 6 pixel wide font (which is + * a very small barely readable font) + */ + + XftDrawGlyphs(fontPtr->ftDraw, xftcolor, currentFtFont, + originX, originY, glyphs, nglyph); + } + } + originX = ROUND16(x); + originY = ROUND16(y); + currentFtFont = ftFont; + } + glyphs[nglyph++] = XftCharIndex(fontPtr->display, ftFont, c); + } + if (nglyph) { + XftGlyphExtents(fontPtr->display, currentFtFont, glyphs, + nglyph, &metrics); + + /* + * Draw glyph only when it fits entirely into 16 bit coords. + */ + + if (x >= minCoord && y >= minCoord && + x <= maxCoord - metrics.width && + y <= maxCoord - metrics.height) { + XftDrawGlyphs(fontPtr->ftDraw, xftcolor, currentFtFont, + originX, originY, glyphs, nglyph); + } + } +#else /* !XFT_HAS_FIXED_ROTATED_PLACEMENT */ + int clen, nspec; + XftGlyphFontSpec specs[NUM_SPEC]; + XGlyphInfo metrics; + double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0); + + if (fontPtr->ftDraw == 0) { +#if DEBUG_FONTSEL + printf("Switch to drawable 0x%x\n", drawable); +#endif /* DEBUG_FONTSEL */ + fontPtr->ftDraw = XftDrawCreate(display, drawable, + DefaultVisual(display, fontPtr->screen), + DefaultColormap(display, fontPtr->screen)); + } else { + Tk_ErrorHandler handler = + Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL); + + XftDrawChange(fontPtr->ftDraw, drawable); + Tk_DeleteErrorHandler(handler); + } + XGetGCValues(display, gc, GCForeground, &values); + xftcolor = LookUpColor(display, fontPtr, values.foreground); + if (tsdPtr->clipRegion != None) { + XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion); + } + nspec = 0; + while (numBytes > 0) { + XftFont *ftFont, *ft0Font; + FcChar32 c; + + clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes); + if (clen <= 0) { + /* + * This should not happen, but it can. + */ + + goto doUnderlineStrikeout; + } + source += clen; + numBytes -= clen; + + ftFont = GetFont(fontPtr, c, angle); + ft0Font = GetFont(fontPtr, c, 0.0); + if (ftFont && ft0Font) { + specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c); + XftGlyphExtents(fontPtr->display, ft0Font, &specs[nspec].glyph, 1, + &metrics); + + /* + * Draw glyph only when it fits entirely into 16 bit coords. + */ + + if (x >= minCoord && y >= minCoord && + x <= maxCoord - metrics.width && + y <= maxCoord - metrics.height) { + specs[nspec].font = ftFont; + specs[nspec].x = ROUND16(x); + specs[nspec].y = ROUND16(y); + if (++nspec == NUM_SPEC) { + XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor, + specs, nspec); + nspec = 0; + } + } + x += metrics.xOff*cosA + metrics.yOff*sinA; + y += metrics.yOff*cosA - metrics.xOff*sinA; + } + } + if (nspec) { + XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor, specs, nspec); + } +#endif /* XFT_HAS_FIXED_ROTATED_PLACEMENT */ + + doUnderlineStrikeout: + if (tsdPtr->clipRegion != None) { + XftDrawSetClip(fontPtr->ftDraw, None); + } + if (fontPtr->font.fa.underline || fontPtr->font.fa.overstrike) { + XPoint points[5]; + double width = (x - xStart) * cosA + (yStart - y) * sinA; + double barHeight = fontPtr->font.underlineHeight; + double dy = fontPtr->font.underlinePos; + + if (fontPtr->font.fa.underline != 0) { + if (fontPtr->font.underlineHeight == 1) { + dy++; + } + points[0].x = xStart + ROUND16(dy*sinA); + points[0].y = yStart + ROUND16(dy*cosA); + points[1].x = xStart + ROUND16(dy*sinA + width*cosA); + points[1].y = yStart + ROUND16(dy*cosA - width*sinA); + if (fontPtr->font.underlineHeight == 1) { + XDrawLines(display, drawable, gc, points, 2, CoordModeOrigin); + } else { + points[2].x = xStart + ROUND16(dy*sinA + width*cosA + + barHeight*sinA); + points[2].y = yStart + ROUND16(dy*cosA - width*sinA + + barHeight*cosA); + points[3].x = xStart + ROUND16(dy*sinA + barHeight*sinA); + points[3].y = yStart + ROUND16(dy*cosA + barHeight*cosA); + points[4].x = points[0].x; + points[4].y = points[0].y; + XFillPolygon(display, drawable, gc, points, 5, Complex, + CoordModeOrigin); + XDrawLines(display, drawable, gc, points, 5, CoordModeOrigin); + } + } + if (fontPtr->font.fa.overstrike != 0) { + dy = -fontPtr->font.fm.descent + - (fontPtr->font.fm.ascent) / 10; + points[0].x = xStart + ROUND16(dy*sinA); + points[0].y = yStart + ROUND16(dy*cosA); + points[1].x = xStart + ROUND16(dy*sinA + width*cosA); + points[1].y = yStart + ROUND16(dy*cosA - width*sinA); + if (fontPtr->font.underlineHeight == 1) { + XDrawLines(display, drawable, gc, points, 2, CoordModeOrigin); + } else { + points[2].x = xStart + ROUND16(dy*sinA + width*cosA + + barHeight*sinA); + points[2].y = yStart + ROUND16(dy*cosA - width*sinA + + barHeight*cosA); + points[3].x = xStart + ROUND16(dy*sinA + barHeight*sinA); + points[3].y = yStart + ROUND16(dy*cosA + barHeight*cosA); + points[4].x = points[0].x; + points[4].y = points[0].y; + XFillPolygon(display, drawable, gc, points, 5, Complex, + CoordModeOrigin); + XDrawLines(display, drawable, gc, points, 5, CoordModeOrigin); + } + } + } +} + +void +TkUnixSetXftClipRegion( + TkRegion clipRegion) /* The clipping region to install. */ +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + tsdPtr->clipRegion = (Region) clipRegion; +} + +/* + * Local Variables: + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixScale.c b/tk8.6/unix/tkUnixScale.c new file mode 100644 index 0000000..8f88018 --- /dev/null +++ b/tk8.6/unix/tkUnixScale.c @@ -0,0 +1,731 @@ +/* + * tkUnixScale.c -- + * + * This file implements the X specific portion of the scrollbar widget. + * + * Copyright (c) 1996 by 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. + */ + +#include "tkInt.h" +#include "tkScale.h" + +#if defined(_WIN32) +#define snprintf _snprintf +#endif + +/* + * Forward declarations for functions defined later in this file: + */ + +static void DisplayHorizontalScale(TkScale *scalePtr, + Drawable drawable, XRectangle *drawnAreaPtr); +static void DisplayHorizontalValue(TkScale *scalePtr, + Drawable drawable, double value, int top); +static void DisplayVerticalScale(TkScale *scalePtr, + Drawable drawable, XRectangle *drawnAreaPtr); +static void DisplayVerticalValue(TkScale *scalePtr, + Drawable drawable, double value, int rightEdge); + +/* + *---------------------------------------------------------------------- + * + * TkpCreateScale -- + * + * Allocate a new TkScale structure. + * + * Results: + * Returns a newly allocated TkScale structure. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkScale * +TkpCreateScale( + Tk_Window tkwin) +{ + return ckalloc(sizeof(TkScale)); +} + +/* + *---------------------------------------------------------------------- + * + * TkpDestroyScale -- + * + * Destroy a TkScale structure. It's necessary to do this with + * Tcl_EventuallyFree to allow the Tcl_Preserve(scalePtr) to work as + * expected in TkpDisplayScale. (hobbs) + * + * Results: + * None + * + * Side effects: + * Memory is freed. + * + *---------------------------------------------------------------------- + */ + +void +TkpDestroyScale( + TkScale *scalePtr) +{ + Tcl_EventuallyFree(scalePtr, TCL_DYNAMIC); +} + +/* + *-------------------------------------------------------------- + * + * DisplayVerticalScale -- + * + * This function redraws the contents of a vertical scale window. It is + * invoked as a do-when-idle handler, so it only runs when there's + * nothing else for the application to do. + * + * Results: + * There is no return value. If only a part of the scale needs to be + * redrawn, then drawnAreaPtr is modified to reflect the area that was + * actually modified. + * + * Side effects: + * Information appears on the screen. + * + *-------------------------------------------------------------- + */ + +static void +DisplayVerticalScale( + TkScale *scalePtr, /* Widget record for scale. */ + Drawable drawable, /* Where to display scale (window or + * pixmap). */ + XRectangle *drawnAreaPtr) /* Initally contains area of window; if only a + * part of the scale is redrawn, gets modified + * to reflect the part of the window that was + * redrawn. */ +{ + Tk_Window tkwin = scalePtr->tkwin; + int x, y, width, height, shadowWidth; + double tickValue, tickInterval = scalePtr->tickInterval; + Tk_3DBorder sliderBorder; + + /* + * Display the information from left to right across the window. + */ + + if (!(scalePtr->flags & REDRAW_OTHER)) { + drawnAreaPtr->x = scalePtr->vertTickRightX; + drawnAreaPtr->y = scalePtr->inset; + drawnAreaPtr->width = scalePtr->vertTroughX + scalePtr->width + + 2*scalePtr->borderWidth - scalePtr->vertTickRightX; + drawnAreaPtr->height -= 2*scalePtr->inset; + } + Tk_Fill3DRectangle(tkwin, drawable, scalePtr->bgBorder, + drawnAreaPtr->x, drawnAreaPtr->y, drawnAreaPtr->width, + drawnAreaPtr->height, 0, TK_RELIEF_FLAT); + if (scalePtr->flags & REDRAW_OTHER) { + /* + * Display the tick marks. + */ + + if (tickInterval != 0) { + double ticks, maxTicks; + + /* + * Ensure that we will only draw enough of the tick values such + * that they don't overlap + */ + + ticks = fabs((scalePtr->toValue - scalePtr->fromValue) + / tickInterval); + maxTicks = (double) Tk_Height(tkwin) + / (double) scalePtr->fontHeight; + if (ticks > maxTicks) { + tickInterval *= (ticks / maxTicks); + } + for (tickValue = scalePtr->fromValue; ; + tickValue += tickInterval) { + /* + * The TkRoundToResolution call gets rid of accumulated + * round-off errors, if any. + */ + + tickValue = TkRoundToResolution(scalePtr, tickValue); + if (scalePtr->toValue >= scalePtr->fromValue) { + if (tickValue > scalePtr->toValue) { + break; + } + } else { + if (tickValue < scalePtr->toValue) { + break; + } + } + DisplayVerticalValue(scalePtr, drawable, tickValue, + scalePtr->vertTickRightX); + } + } + } + + /* + * Display the value, if it is desired. + */ + + if (scalePtr->showValue) { + DisplayVerticalValue(scalePtr, drawable, scalePtr->value, + scalePtr->vertValueRightX); + } + + /* + * Display the trough and the slider. + */ + + Tk_Draw3DRectangle(tkwin, drawable, + scalePtr->bgBorder, scalePtr->vertTroughX, scalePtr->inset, + scalePtr->width + 2*scalePtr->borderWidth, + Tk_Height(tkwin) - 2*scalePtr->inset, scalePtr->borderWidth, + TK_RELIEF_SUNKEN); + XFillRectangle(scalePtr->display, drawable, scalePtr->troughGC, + scalePtr->vertTroughX + scalePtr->borderWidth, + scalePtr->inset + scalePtr->borderWidth, + (unsigned) scalePtr->width, + (unsigned) (Tk_Height(tkwin) - 2*scalePtr->inset + - 2*scalePtr->borderWidth)); + if (scalePtr->state == STATE_ACTIVE) { + sliderBorder = scalePtr->activeBorder; + } else { + sliderBorder = scalePtr->bgBorder; + } + width = scalePtr->width; + height = scalePtr->sliderLength/2; + x = scalePtr->vertTroughX + scalePtr->borderWidth; + y = TkScaleValueToPixel(scalePtr, scalePtr->value) - height; + shadowWidth = scalePtr->borderWidth/2; + if (shadowWidth == 0) { + shadowWidth = 1; + } + Tk_Draw3DRectangle(tkwin, drawable, sliderBorder, x, y, width, + 2*height, shadowWidth, scalePtr->sliderRelief); + x += shadowWidth; + y += shadowWidth; + width -= 2*shadowWidth; + height -= shadowWidth; + Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y, width, + height, shadowWidth, scalePtr->sliderRelief); + Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y+height, + width, height, shadowWidth, scalePtr->sliderRelief); + + /* + * Draw the label to the right of the scale. + */ + + if ((scalePtr->flags & REDRAW_OTHER) && (scalePtr->labelLength != 0)) { + Tk_FontMetrics fm; + + Tk_GetFontMetrics(scalePtr->tkfont, &fm); + Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC, + scalePtr->tkfont, scalePtr->label, + scalePtr->labelLength, scalePtr->vertLabelX, + scalePtr->inset + (3*fm.ascent)/2); + } +} + +/* + *---------------------------------------------------------------------- + * + * DisplayVerticalValue -- + * + * This function is called to display values (scale readings) for + * vertically-oriented scales. + * + * Results: + * None. + * + * Side effects: + * The numerical value corresponding to value is displayed with its right + * edge at "rightEdge", and at a vertical position in the scale that + * corresponds to "value". + * + *---------------------------------------------------------------------- + */ + +static void +DisplayVerticalValue( + register TkScale *scalePtr, /* Information about widget in which to + * display value. */ + Drawable drawable, /* Pixmap or window in which to draw the + * value. */ + double value, /* Y-coordinate of number to display, + * specified in application coords, not in + * pixels (we'll compute pixels). */ + int rightEdge) /* X-coordinate of right edge of text, + * specified in pixels. */ +{ + register Tk_Window tkwin = scalePtr->tkwin; + int y, width, length; + char valueString[TCL_DOUBLE_SPACE]; + Tk_FontMetrics fm; + + Tk_GetFontMetrics(scalePtr->tkfont, &fm); + y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2; + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, value) < 0) { + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + } + length = (int) strlen(valueString); + width = Tk_TextWidth(scalePtr->tkfont, valueString, length); + + /* + * Adjust the y-coordinate if necessary to keep the text entirely inside + * the window. + */ + + if ((y - fm.ascent) < (scalePtr->inset + SPACING)) { + y = scalePtr->inset + SPACING + fm.ascent; + } + if ((y + fm.descent) > (Tk_Height(tkwin) - scalePtr->inset - SPACING)) { + y = Tk_Height(tkwin) - scalePtr->inset - SPACING - fm.descent; + } + Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC, + scalePtr->tkfont, valueString, length, rightEdge - width, y); +} + +/* + *-------------------------------------------------------------- + * + * DisplayHorizontalScale -- + * + * This function redraws the contents of a horizontal scale window. It is + * invoked as a do-when-idle handler, so it only runs when there's + * nothing else for the application to do. + * + * Results: + * There is no return value. If only a part of the scale needs to be + * redrawn, then drawnAreaPtr is modified to reflect the area that was + * actually modified. + * + * Side effects: + * Information appears on the screen. + * + *-------------------------------------------------------------- + */ + +static void +DisplayHorizontalScale( + TkScale *scalePtr, /* Widget record for scale. */ + Drawable drawable, /* Where to display scale (window or + * pixmap). */ + XRectangle *drawnAreaPtr) /* Initally contains area of window; if only a + * part of the scale is redrawn, gets modified + * to reflect the part of the window that was + * redrawn. */ +{ + register Tk_Window tkwin = scalePtr->tkwin; + int x, y, width, height, shadowWidth; + double tickValue, tickInterval = scalePtr->tickInterval; + Tk_3DBorder sliderBorder; + + /* + * Display the information from bottom to top across the window. + */ + + if (!(scalePtr->flags & REDRAW_OTHER)) { + drawnAreaPtr->x = scalePtr->inset; + drawnAreaPtr->y = scalePtr->horizValueY; + drawnAreaPtr->width -= 2*scalePtr->inset; + drawnAreaPtr->height = scalePtr->horizTroughY + scalePtr->width + + 2*scalePtr->borderWidth - scalePtr->horizValueY; + } + Tk_Fill3DRectangle(tkwin, drawable, scalePtr->bgBorder, + drawnAreaPtr->x, drawnAreaPtr->y, drawnAreaPtr->width, + drawnAreaPtr->height, 0, TK_RELIEF_FLAT); + if (scalePtr->flags & REDRAW_OTHER) { + /* + * Display the tick marks. + */ + + if (tickInterval != 0) { + char valueString[TCL_DOUBLE_SPACE]; + double ticks, maxTicks; + + /* + * Ensure that we will only draw enough of the tick values such + * that they don't overlap. We base this off the width that + * fromValue would take. Not exact, but better than no constraint. + */ + + ticks = fabs((scalePtr->toValue - scalePtr->fromValue) + / tickInterval); + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, + scalePtr->fromValue) < 0) { + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + } + maxTicks = (double) Tk_Width(tkwin) + / (double) Tk_TextWidth(scalePtr->tkfont, valueString, -1); + if (ticks > maxTicks) { + tickInterval *= (ticks / maxTicks); + } + for (tickValue = scalePtr->fromValue; ; + tickValue += tickInterval) { + /* + * The TkRoundToResolution call gets rid of accumulated + * round-off errors, if any. + */ + + tickValue = TkRoundToResolution(scalePtr, tickValue); + if (scalePtr->toValue >= scalePtr->fromValue) { + if (tickValue > scalePtr->toValue) { + break; + } + } else { + if (tickValue < scalePtr->toValue) { + break; + } + } + DisplayHorizontalValue(scalePtr, drawable, tickValue, + scalePtr->horizTickY); + } + } + } + + /* + * Display the value, if it is desired. + */ + + if (scalePtr->showValue) { + DisplayHorizontalValue(scalePtr, drawable, scalePtr->value, + scalePtr->horizValueY); + } + + /* + * Display the trough and the slider. + */ + + y = scalePtr->horizTroughY; + Tk_Draw3DRectangle(tkwin, drawable, + scalePtr->bgBorder, scalePtr->inset, y, + Tk_Width(tkwin) - 2*scalePtr->inset, + scalePtr->width + 2*scalePtr->borderWidth, + scalePtr->borderWidth, TK_RELIEF_SUNKEN); + XFillRectangle(scalePtr->display, drawable, scalePtr->troughGC, + scalePtr->inset + scalePtr->borderWidth, + y + scalePtr->borderWidth, + (unsigned) (Tk_Width(tkwin) - 2*scalePtr->inset + - 2*scalePtr->borderWidth), + (unsigned) scalePtr->width); + if (scalePtr->state == STATE_ACTIVE) { + sliderBorder = scalePtr->activeBorder; + } else { + sliderBorder = scalePtr->bgBorder; + } + width = scalePtr->sliderLength/2; + height = scalePtr->width; + x = TkScaleValueToPixel(scalePtr, scalePtr->value) - width; + y += scalePtr->borderWidth; + shadowWidth = scalePtr->borderWidth/2; + if (shadowWidth == 0) { + shadowWidth = 1; + } + Tk_Draw3DRectangle(tkwin, drawable, sliderBorder, + x, y, 2*width, height, shadowWidth, scalePtr->sliderRelief); + x += shadowWidth; + y += shadowWidth; + width -= shadowWidth; + height -= 2*shadowWidth; + Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y, width, height, + shadowWidth, scalePtr->sliderRelief); + Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x+width, y, + width, height, shadowWidth, scalePtr->sliderRelief); + + /* + * Draw the label at the top of the scale. + */ + + if ((scalePtr->flags & REDRAW_OTHER) && (scalePtr->labelLength != 0)) { + Tk_FontMetrics fm; + + Tk_GetFontMetrics(scalePtr->tkfont, &fm); + Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC, + scalePtr->tkfont, scalePtr->label, + scalePtr->labelLength, scalePtr->inset + fm.ascent/2, + scalePtr->horizLabelY + fm.ascent); + } +} + +/* + *---------------------------------------------------------------------- + * + * DisplayHorizontalValue -- + * + * This function is called to display values (scale readings) for + * horizontally-oriented scales. + * + * Results: + * None. + * + * Side effects: + * The numerical value corresponding to value is displayed with its + * bottom edge at "bottom", and at a horizontal position in the scale + * that corresponds to "value". + * + *---------------------------------------------------------------------- + */ + +static void +DisplayHorizontalValue( + register TkScale *scalePtr, /* Information about widget in which to + * display value. */ + Drawable drawable, /* Pixmap or window in which to draw the + * value. */ + double value, /* X-coordinate of number to display, + * specified in application coords, not in + * pixels (we'll compute pixels). */ + int top) /* Y-coordinate of top edge of text, specified + * in pixels. */ +{ + register Tk_Window tkwin = scalePtr->tkwin; + int x, y, length, width; + char valueString[TCL_DOUBLE_SPACE]; + Tk_FontMetrics fm; + + x = TkScaleValueToPixel(scalePtr, value); + Tk_GetFontMetrics(scalePtr->tkfont, &fm); + y = top + fm.ascent; + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, value) < 0) { + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + } + length = (int) strlen(valueString); + width = Tk_TextWidth(scalePtr->tkfont, valueString, length); + + /* + * Adjust the x-coordinate if necessary to keep the text entirely inside + * the window. + */ + + x -= (width)/2; + if (x < (scalePtr->inset + SPACING)) { + x = scalePtr->inset + SPACING; + } + + /* + * Check the right border so use starting point +text width for the check. + */ + + if (x + width >= (Tk_Width(tkwin) - scalePtr->inset)) { + x = Tk_Width(tkwin) - scalePtr->inset - SPACING - width; + } + Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC, + scalePtr->tkfont, valueString, length, x, y); +} + +/* + *---------------------------------------------------------------------- + * + * TkpDisplayScale -- + * + * This function is invoked as an idle handler to redisplay the contents + * of a scale widget. + * + * Results: + * None. + * + * Side effects: + * The scale gets redisplayed. + * + *---------------------------------------------------------------------- + */ + +void +TkpDisplayScale( + ClientData clientData) /* Widget record for scale. */ +{ + TkScale *scalePtr = (TkScale *) clientData; + Tk_Window tkwin = scalePtr->tkwin; + Tcl_Interp *interp = scalePtr->interp; + Pixmap pixmap; + int result; + char string[TCL_DOUBLE_SPACE]; + XRectangle drawnArea; + Tcl_DString buf; + + scalePtr->flags &= ~REDRAW_PENDING; + if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) { + goto done; + } + + /* + * Invoke the scale's command if needed. + */ + + Tcl_Preserve(scalePtr); + if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) { + Tcl_Preserve(interp); + if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format, + scalePtr->value) < 0) { + string[TCL_DOUBLE_SPACE - 1] = '\0'; + } + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, scalePtr->command, -1); + Tcl_DStringAppend(&buf, " ", -1); + Tcl_DStringAppend(&buf, string, -1); + result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0); + Tcl_DStringFree(&buf); + if (result != TCL_OK) { + Tcl_AddErrorInfo(interp, "\n (command executed by scale)"); + Tcl_BackgroundException(interp, result); + } + Tcl_Release(interp); + } + scalePtr->flags &= ~INVOKE_COMMAND; + if (scalePtr->flags & SCALE_DELETED) { + Tcl_Release(scalePtr); + return; + } + Tcl_Release(scalePtr); + +#ifndef TK_NO_DOUBLE_BUFFERING + /* + * In order to avoid screen flashes, this function redraws the scale in a + * pixmap, then copies the pixmap to the screen in a single operation. + * This means that there's no point in time where the on-sreen image has + * been cleared. + */ + + pixmap = Tk_GetPixmap(scalePtr->display, Tk_WindowId(tkwin), + Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); +#else + pixmap = Tk_WindowId(tkwin); +#endif /* TK_NO_DOUBLE_BUFFERING */ + drawnArea.x = 0; + drawnArea.y = 0; + drawnArea.width = Tk_Width(tkwin); + drawnArea.height = Tk_Height(tkwin); + + /* + * Much of the redisplay is done totally differently for horizontal and + * vertical scales. Handle the part that's different. + */ + + if (scalePtr->orient == ORIENT_VERTICAL) { + DisplayVerticalScale(scalePtr, pixmap, &drawnArea); + } else { + DisplayHorizontalScale(scalePtr, pixmap, &drawnArea); + } + + /* + * Now handle the part of redisplay that is the same for horizontal and + * vertical scales: border and traversal highlight. + */ + + if (scalePtr->flags & REDRAW_OTHER) { + if (scalePtr->relief != TK_RELIEF_FLAT) { + Tk_Draw3DRectangle(tkwin, pixmap, scalePtr->bgBorder, + scalePtr->highlightWidth, scalePtr->highlightWidth, + Tk_Width(tkwin) - 2*scalePtr->highlightWidth, + Tk_Height(tkwin) - 2*scalePtr->highlightWidth, + scalePtr->borderWidth, scalePtr->relief); + } + if (scalePtr->highlightWidth != 0) { + GC gc; + + if (scalePtr->flags & GOT_FOCUS) { + gc = Tk_GCForColor(scalePtr->highlightColorPtr, pixmap); + } else { + gc = Tk_GCForColor( + Tk_3DBorderColor(scalePtr->highlightBorder), pixmap); + } + Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth, pixmap); + } + } + +#ifndef TK_NO_DOUBLE_BUFFERING + /* + * Copy the information from the off-screen pixmap onto the screen, then + * delete the pixmap. + */ + + XCopyArea(scalePtr->display, pixmap, Tk_WindowId(tkwin), + scalePtr->copyGC, drawnArea.x, drawnArea.y, drawnArea.width, + drawnArea.height, drawnArea.x, drawnArea.y); + Tk_FreePixmap(scalePtr->display, pixmap); +#endif /* TK_NO_DOUBLE_BUFFERING */ + + done: + scalePtr->flags &= ~REDRAW_ALL; +} + +/* + *---------------------------------------------------------------------- + * + * TkpScaleElement -- + * + * Determine which part of a scale widget lies under a given point. + * + * Results: + * The return value is either TROUGH1, SLIDER, TROUGH2, or OTHER, + * depending on which of the scale's active elements (if any) is under + * the point at (x,y). + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkpScaleElement( + TkScale *scalePtr, /* Widget record for scale. */ + int x, int y) /* Coordinates within scalePtr's window. */ +{ + int sliderFirst; + + if (scalePtr->orient == ORIENT_VERTICAL) { + if ((x < scalePtr->vertTroughX) + || (x >= (scalePtr->vertTroughX + 2*scalePtr->borderWidth + + scalePtr->width))) { + return OTHER; + } + if ((y < scalePtr->inset) + || (y >= (Tk_Height(scalePtr->tkwin) - scalePtr->inset))) { + return OTHER; + } + sliderFirst = TkScaleValueToPixel(scalePtr, scalePtr->value) + - scalePtr->sliderLength/2; + if (y < sliderFirst) { + return TROUGH1; + } + if (y < (sliderFirst+scalePtr->sliderLength)) { + return SLIDER; + } + return TROUGH2; + } + + if ((y < scalePtr->horizTroughY) + || (y >= (scalePtr->horizTroughY + 2*scalePtr->borderWidth + + scalePtr->width))) { + return OTHER; + } + if ((x < scalePtr->inset) + || (x >= (Tk_Width(scalePtr->tkwin) - scalePtr->inset))) { + return OTHER; + } + sliderFirst = TkScaleValueToPixel(scalePtr, scalePtr->value) + - scalePtr->sliderLength/2; + if (x < sliderFirst) { + return TROUGH1; + } + if (x < (sliderFirst+scalePtr->sliderLength)) { + return SLIDER; + } + return TROUGH2; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixScrlbr.c b/tk8.6/unix/tkUnixScrlbr.c new file mode 100644 index 0000000..2446c3f --- /dev/null +++ b/tk8.6/unix/tkUnixScrlbr.c @@ -0,0 +1,488 @@ +/* + * tkUnixScrollbar.c -- + * + * This file implements the Unix specific portion of the scrollbar + * widget. + * + * Copyright (c) 1996 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. + */ + +#include "tkInt.h" +#include "tkScrollbar.h" + +/* + * Minimum slider length, in pixels (designed to make sure that the slider is + * always easy to grab with the mouse). + */ + +#define MIN_SLIDER_LENGTH 5 + +/* + * Declaration of Unix specific scrollbar structure. + */ + +typedef struct UnixScrollbar { + TkScrollbar info; /* Generic scrollbar info. */ + GC troughGC; /* For drawing trough. */ + GC copyGC; /* Used for copying from pixmap onto screen. */ +} UnixScrollbar; + +/* + * The class procedure table for the scrollbar widget. All fields except size + * are left initialized to NULL, which should happen automatically since the + * variable is declared at this scope. + */ + +const Tk_ClassProcs tkpScrollbarProcs = { + sizeof(Tk_ClassProcs), /* size */ + NULL, /* worldChangedProc */ + NULL, /* createProc */ + NULL /* modalProc */ +}; + +/* + *---------------------------------------------------------------------- + * + * TkpCreateScrollbar -- + * + * Allocate a new TkScrollbar structure. + * + * Results: + * Returns a newly allocated TkScrollbar structure. + * + * Side effects: + * Registers an event handler for the widget. + * + *---------------------------------------------------------------------- + */ + +TkScrollbar * +TkpCreateScrollbar( + Tk_Window tkwin) +{ + UnixScrollbar *scrollPtr = ckalloc(sizeof(UnixScrollbar)); + + scrollPtr->troughGC = None; + scrollPtr->copyGC = None; + + Tk_CreateEventHandler(tkwin, + ExposureMask|StructureNotifyMask|FocusChangeMask, + TkScrollbarEventProc, scrollPtr); + + return (TkScrollbar *) scrollPtr; +} + +/* + *-------------------------------------------------------------- + * + * TkpDisplayScrollbar -- + * + * This procedure redraws the contents of a scrollbar window. It is + * invoked as a do-when-idle handler, so it only runs when there's + * nothing else for the application to do. + * + * Results: + * None. + * + * Side effects: + * Information appears on the screen. + * + *-------------------------------------------------------------- + */ + +void +TkpDisplayScrollbar( + ClientData clientData) /* Information about window. */ +{ + register TkScrollbar *scrollPtr = (TkScrollbar *) clientData; + register Tk_Window tkwin = scrollPtr->tkwin; + XPoint points[7]; + Tk_3DBorder border; + int relief, width, elementBorderWidth; + Pixmap pixmap; + + if ((scrollPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { + goto done; + } + + if (scrollPtr->vertical) { + width = Tk_Width(tkwin) - 2*scrollPtr->inset; + } else { + width = Tk_Height(tkwin) - 2*scrollPtr->inset; + } + elementBorderWidth = scrollPtr->elementBorderWidth; + if (elementBorderWidth < 0) { + elementBorderWidth = scrollPtr->borderWidth; + } + + /* + * In order to avoid screen flashes, this procedure redraws the scrollbar + * in a pixmap, then copies the pixmap to the screen in a single + * operation. This means that there's no point in time where the on-sreen + * image has been cleared. + */ + + pixmap = Tk_GetPixmap(scrollPtr->display, Tk_WindowId(tkwin), + Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); + + if (scrollPtr->highlightWidth != 0) { + GC gc; + + if (scrollPtr->flags & GOT_FOCUS) { + gc = Tk_GCForColor(scrollPtr->highlightColorPtr, pixmap); + } else { + gc = Tk_GCForColor(scrollPtr->highlightBgColorPtr, pixmap); + } + Tk_DrawFocusHighlight(tkwin, gc, scrollPtr->highlightWidth, pixmap); + } + Tk_Draw3DRectangle(tkwin, pixmap, scrollPtr->bgBorder, + scrollPtr->highlightWidth, scrollPtr->highlightWidth, + Tk_Width(tkwin) - 2*scrollPtr->highlightWidth, + Tk_Height(tkwin) - 2*scrollPtr->highlightWidth, + scrollPtr->borderWidth, scrollPtr->relief); + XFillRectangle(scrollPtr->display, pixmap, + ((UnixScrollbar*)scrollPtr)->troughGC, + scrollPtr->inset, scrollPtr->inset, + (unsigned) (Tk_Width(tkwin) - 2*scrollPtr->inset), + (unsigned) (Tk_Height(tkwin) - 2*scrollPtr->inset)); + + /* + * Draw the top or left arrow. The coordinates of the polygon points + * probably seem odd, but they were carefully chosen with respect to X's + * rules for filling polygons. These point choices cause the arrows to + * just fill the narrow dimension of the scrollbar and be properly + * centered. + */ + + if (scrollPtr->activeField == TOP_ARROW) { + border = scrollPtr->activeBorder; + relief = scrollPtr->activeField == TOP_ARROW ? scrollPtr->activeRelief + : TK_RELIEF_RAISED; + } else { + border = scrollPtr->bgBorder; + relief = TK_RELIEF_RAISED; + } + if (scrollPtr->vertical) { + points[0].x = scrollPtr->inset - 1; + points[0].y = scrollPtr->arrowLength + scrollPtr->inset - 1; + points[1].x = width + scrollPtr->inset; + points[1].y = points[0].y; + points[2].x = width/2 + scrollPtr->inset; + points[2].y = scrollPtr->inset - 1; + Tk_Fill3DPolygon(tkwin, pixmap, border, points, 3, + elementBorderWidth, relief); + } else { + points[0].x = scrollPtr->arrowLength + scrollPtr->inset - 1; + points[0].y = scrollPtr->inset - 1; + points[1].x = scrollPtr->inset; + points[1].y = width/2 + scrollPtr->inset; + points[2].x = points[0].x; + points[2].y = width + scrollPtr->inset; + Tk_Fill3DPolygon(tkwin, pixmap, border, points, 3, + elementBorderWidth, relief); + } + + /* + * Display the bottom or right arrow. + */ + + if (scrollPtr->activeField == BOTTOM_ARROW) { + border = scrollPtr->activeBorder; + relief = scrollPtr->activeField == BOTTOM_ARROW + ? scrollPtr->activeRelief : TK_RELIEF_RAISED; + } else { + border = scrollPtr->bgBorder; + relief = TK_RELIEF_RAISED; + } + if (scrollPtr->vertical) { + points[0].x = scrollPtr->inset; + points[0].y = Tk_Height(tkwin) - scrollPtr->arrowLength + - scrollPtr->inset + 1; + points[1].x = width/2 + scrollPtr->inset; + points[1].y = Tk_Height(tkwin) - scrollPtr->inset; + points[2].x = width + scrollPtr->inset; + points[2].y = points[0].y; + Tk_Fill3DPolygon(tkwin, pixmap, border, + points, 3, elementBorderWidth, relief); + } else { + points[0].x = Tk_Width(tkwin) - scrollPtr->arrowLength + - scrollPtr->inset + 1; + points[0].y = scrollPtr->inset - 1; + points[1].x = points[0].x; + points[1].y = width + scrollPtr->inset; + points[2].x = Tk_Width(tkwin) - scrollPtr->inset; + points[2].y = width/2 + scrollPtr->inset; + Tk_Fill3DPolygon(tkwin, pixmap, border, + points, 3, elementBorderWidth, relief); + } + + /* + * Display the slider. + */ + + if (scrollPtr->activeField == SLIDER) { + border = scrollPtr->activeBorder; + relief = scrollPtr->activeField == SLIDER ? scrollPtr->activeRelief + : TK_RELIEF_RAISED; + } else { + border = scrollPtr->bgBorder; + relief = TK_RELIEF_RAISED; + } + if (scrollPtr->vertical) { + Tk_Fill3DRectangle(tkwin, pixmap, border, + scrollPtr->inset, scrollPtr->sliderFirst, + width, scrollPtr->sliderLast - scrollPtr->sliderFirst, + elementBorderWidth, relief); + } else { + Tk_Fill3DRectangle(tkwin, pixmap, border, + scrollPtr->sliderFirst, scrollPtr->inset, + scrollPtr->sliderLast - scrollPtr->sliderFirst, width, + elementBorderWidth, relief); + } + + /* + * Copy the information from the off-screen pixmap onto the screen, then + * delete the pixmap. + */ + + XCopyArea(scrollPtr->display, pixmap, Tk_WindowId(tkwin), + ((UnixScrollbar*)scrollPtr)->copyGC, 0, 0, + (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0); + Tk_FreePixmap(scrollPtr->display, pixmap); + + done: + scrollPtr->flags &= ~REDRAW_PENDING; +} + +/* + *---------------------------------------------------------------------- + * + * TkpComputeScrollbarGeometry -- + * + * After changes in a scrollbar's size or configuration, this procedure + * recomputes various geometry information used in displaying the + * scrollbar. + * + * Results: + * None. + * + * Side effects: + * The scrollbar will be displayed differently. + * + *---------------------------------------------------------------------- + */ + +extern void +TkpComputeScrollbarGeometry( + register TkScrollbar *scrollPtr) + /* Scrollbar whose geometry may have + * changed. */ +{ + int width, fieldLength; + + if (scrollPtr->highlightWidth < 0) { + scrollPtr->highlightWidth = 0; + } + scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth; + width = (scrollPtr->vertical) ? Tk_Width(scrollPtr->tkwin) + : Tk_Height(scrollPtr->tkwin); + + /* + * Next line assumes that the arrow area is a square. + */ + + scrollPtr->arrowLength = width - 2*scrollPtr->inset + 1; + fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin) + : Tk_Width(scrollPtr->tkwin)) + - 2*(scrollPtr->arrowLength + scrollPtr->inset); + if (fieldLength < 0) { + fieldLength = 0; + } + scrollPtr->sliderFirst = fieldLength*scrollPtr->firstFraction; + scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction; + + /* + * Adjust the slider so that some piece of it is always displayed in the + * scrollbar and so that it has at least a minimal width (so it can be + * grabbed with the mouse). + */ + + if (scrollPtr->sliderFirst > fieldLength - MIN_SLIDER_LENGTH) { + scrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH; + } + if (scrollPtr->sliderFirst < 0) { + scrollPtr->sliderFirst = 0; + } + if (scrollPtr->sliderLast < scrollPtr->sliderFirst + MIN_SLIDER_LENGTH) { + scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH; + } + if (scrollPtr->sliderLast > fieldLength) { + scrollPtr->sliderLast = fieldLength; + } + scrollPtr->sliderFirst += scrollPtr->arrowLength + scrollPtr->inset; + scrollPtr->sliderLast += scrollPtr->arrowLength + scrollPtr->inset; + + /* + * Register the desired geometry for the window (leave enough space for + * the two arrows plus a minimum-size slider, plus border around the whole + * window, if any). Then arrange for the window to be redisplayed. + */ + + if (scrollPtr->vertical) { + Tk_GeometryRequest(scrollPtr->tkwin, + scrollPtr->width + 2*scrollPtr->inset, + 2*(scrollPtr->arrowLength + scrollPtr->borderWidth + + scrollPtr->inset)); + } else { + Tk_GeometryRequest(scrollPtr->tkwin, + 2*(scrollPtr->arrowLength + scrollPtr->borderWidth + + scrollPtr->inset), scrollPtr->width + 2*scrollPtr->inset); + } + Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset); +} + +/* + *---------------------------------------------------------------------- + * + * TkpDestroyScrollbar -- + * + * Free data structures associated with the scrollbar control. + * + * Results: + * None. + * + * Side effects: + * Frees the GCs associated with the scrollbar. + * + *---------------------------------------------------------------------- + */ + +void +TkpDestroyScrollbar( + TkScrollbar *scrollPtr) +{ + UnixScrollbar *unixScrollPtr = (UnixScrollbar *)scrollPtr; + + if (unixScrollPtr->troughGC != None) { + Tk_FreeGC(scrollPtr->display, unixScrollPtr->troughGC); + } + if (unixScrollPtr->copyGC != None) { + Tk_FreeGC(scrollPtr->display, unixScrollPtr->copyGC); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpConfigureScrollbar -- + * + * This procedure is called after the generic code has finished + * processing configuration options, in order to configure platform + * specific options. + * + * Results: + * None. + * + * Side effects: + * Configuration info may get changed. + * + *---------------------------------------------------------------------- + */ + +void +TkpConfigureScrollbar( + register TkScrollbar *scrollPtr) + /* Information about widget; may or may not + * already have values for some fields. */ +{ + XGCValues gcValues; + GC new; + UnixScrollbar *unixScrollPtr = (UnixScrollbar *) scrollPtr; + + Tk_SetBackgroundFromBorder(scrollPtr->tkwin, scrollPtr->bgBorder); + + gcValues.foreground = scrollPtr->troughColorPtr->pixel; + new = Tk_GetGC(scrollPtr->tkwin, GCForeground, &gcValues); + if (unixScrollPtr->troughGC != None) { + Tk_FreeGC(scrollPtr->display, unixScrollPtr->troughGC); + } + unixScrollPtr->troughGC = new; + if (unixScrollPtr->copyGC == None) { + gcValues.graphics_exposures = False; + unixScrollPtr->copyGC = Tk_GetGC(scrollPtr->tkwin, + GCGraphicsExposures, &gcValues); + } +} + +/* + *-------------------------------------------------------------- + * + * TkpScrollbarPosition -- + * + * Determine the scrollbar element corresponding to a given position. + * + * Results: + * One of TOP_ARROW, TOP_GAP, etc., indicating which element of the + * scrollbar covers the position given by (x, y). If (x,y) is outside the + * scrollbar entirely, then OUTSIDE is returned. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +int +TkpScrollbarPosition( + register TkScrollbar *scrollPtr, + /* Scrollbar widget record. */ + int x, int y) /* Coordinates within scrollPtr's window. */ +{ + int length, width, tmp; + register const int inset = scrollPtr->inset; + + if (scrollPtr->vertical) { + length = Tk_Height(scrollPtr->tkwin); + width = Tk_Width(scrollPtr->tkwin); + } else { + tmp = x; + x = y; + y = tmp; + length = Tk_Width(scrollPtr->tkwin); + width = Tk_Height(scrollPtr->tkwin); + } + + if (x<inset || x>=width-inset || y<inset || y>=length-inset) { + return OUTSIDE; + } + + /* + * All of the calculations in this procedure mirror those in + * TkpDisplayScrollbar. Be sure to keep the two consistent. + */ + + if (y < inset + scrollPtr->arrowLength) { + return TOP_ARROW; + } + if (y < scrollPtr->sliderFirst) { + return TOP_GAP; + } + if (y < scrollPtr->sliderLast) { + return SLIDER; + } + if (y >= length - (scrollPtr->arrowLength + inset)) { + return BOTTOM_ARROW; + } + return BOTTOM_GAP; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixSelect.c b/tk8.6/unix/tkUnixSelect.c new file mode 100644 index 0000000..6d379ec --- /dev/null +++ b/tk8.6/unix/tkUnixSelect.c @@ -0,0 +1,1552 @@ +/* + * tkUnixSelect.c -- + * + * This file contains X specific routines for manipulating selections. + * + * 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. + */ + +#include "tkInt.h" +#include "tkSelect.h" + +typedef struct ConvertInfo { + int offset; /* The starting byte offset into the selection + * for the next chunk; -1 means all data has + * been transferred for this conversion. -2 + * means only the final zero-length transfer + * still has to be done. Otherwise it is the + * offset of the next chunk of data to + * transfer. */ + Tcl_EncodingState state; /* The encoding state needed across chunks. */ + char buffer[TCL_UTF_MAX]; /* A buffer to hold part of a UTF character + * that is split across chunks.*/ +} ConvertInfo; + +/* + * When handling INCR-style selection retrievals, the selection owner uses the + * following data structure to communicate between the ConvertSelection + * function and TkSelPropProc. + */ + +typedef struct IncrInfo { + TkWindow *winPtr; /* Window that owns selection. */ + Atom selection; /* Selection that is being retrieved. */ + Atom *multAtoms; /* Information about conversions to perform: + * one or more pairs of (target, property). + * This either points to a retrieved property + * (for MULTIPLE retrievals) or to a static + * array. */ + unsigned long numConversions; + /* Number of entries in converts (same as # of + * pairs in multAtoms). */ + ConvertInfo *converts; /* One entry for each pair in multAtoms. This + * array is malloc-ed. */ + char **tempBufs; /* One pointer for each pair in multAtoms; + * each pointer is either NULL, or it points + * to a small bit of character data that was + * left over from the previous chunk. */ + Tcl_EncodingState *state; /* One state info per pair in multAtoms: State + * info for encoding conversions that span + * multiple buffers. */ + int *flags; /* One state flag per pair in multAtoms: + * Encoding flags, set to TCL_ENCODING_START + * at the beginning of an INCR transfer. */ + int numIncrs; /* Number of entries in converts that aren't + * -1 (i.e. # of INCR-mode transfers not yet + * completed). */ + Tcl_TimerToken timeout; /* Token for timer function. */ + int idleTime; /* Number of seconds since we heard anything + * from the selection requestor. */ + Window reqWindow; /* Requestor's window id. */ + Time time; /* Timestamp corresponding to selection at + * beginning of request; used to abort + * transfer if selection changes. */ + struct IncrInfo *nextPtr; /* Next in list of all INCR-style retrievals + * currently pending. */ +} IncrInfo; + +typedef struct ThreadSpecificData { + IncrInfo *pendingIncrs; /* List of all incr structures currently + * active. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + +/* + * Largest property that we'll accept when sending or receiving the selection: + */ + +#define MAX_PROP_WORDS 100000 + +static TkSelRetrievalInfo *pendingRetrievals = NULL; + /* List of all retrievals currently being + * waited for. */ + +/* + * Forward declarations for functions defined in this file: + */ + +static void ConvertSelection(TkWindow *winPtr, + XSelectionRequestEvent *eventPtr); +static void IncrTimeoutProc(ClientData clientData); +static void SelCvtFromX32(long *propPtr, int numValues, Atom type, + Tk_Window tkwin, Tcl_DString *dsPtr); +static void SelCvtFromX8(char *propPtr, int numValues, Atom type, + Tk_Window tkwin, Tcl_DString *dsPtr); +static long * SelCvtToX(char *string, Atom type, Tk_Window tkwin, + int *numLongsPtr); +static int SelectionSize(TkSelHandler *selPtr); +static void SelRcvIncrProc(ClientData clientData, + XEvent *eventPtr); +static void SelTimeoutProc(ClientData clientData); + +/* + *---------------------------------------------------------------------- + * + * TkSelGetSelection -- + * + * Retrieve the specified selection from another process. + * + * 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 the + * interp's result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkSelGetSelection( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tk_Window tkwin, /* Window on whose behalf to retrieve the + * selection (determines display from which to + * retrieve). */ + Atom selection, /* Selection to retrieve. */ + Atom target, /* Desired form in which selection is to be + * returned. */ + Tk_GetSelProc *proc, /* Function to call to process the selection, + * once it has been retrieved. */ + ClientData clientData) /* Arbitrary value to pass to proc. */ +{ + TkSelRetrievalInfo retr; + TkWindow *winPtr = (TkWindow *) tkwin; + TkDisplay *dispPtr = winPtr->dispPtr; + + /* + * The selection is owned by some other process. To retrieve it, first + * record information about the retrieval in progress. Use an internal + * window as the requestor. + */ + + retr.interp = interp; + if (dispPtr->clipWindow == NULL) { + int result; + + result = TkClipInit(interp, dispPtr); + if (result != TCL_OK) { + return result; + } + } + retr.winPtr = (TkWindow *) dispPtr->clipWindow; + retr.selection = selection; + retr.property = selection; + retr.target = target; + retr.proc = proc; + retr.clientData = clientData; + retr.result = -1; + retr.idleTime = 0; + retr.encFlags = TCL_ENCODING_START; + retr.nextPtr = pendingRetrievals; + Tcl_DStringInit(&retr.buf); + pendingRetrievals = &retr; + + /* + * Delete the property to indicate that no parameters are supplied for + * the conversion request. + */ + + XDeleteProperty(winPtr->display, retr.winPtr->window, retr.property); + + /* + * Initiate the request for the selection. Note: can't use TkCurrentTime + * for the time. If we do, and this application hasn't received any X + * events in a long time, the current time will be way in the past and + * could even predate the time when the selection was made; if this + * happens, the request will be rejected. + */ + + XConvertSelection(winPtr->display, retr.selection, retr.target, + retr.property, retr.winPtr->window, CurrentTime); + + /* + * Enter a loop processing X events until the selection has been retrieved + * and processed. If no response is received within a few seconds, then + * timeout. + */ + + retr.timeout = Tcl_CreateTimerHandler(1000, SelTimeoutProc, + &retr); + while (retr.result == -1) { + Tcl_DoOneEvent(0); + } + Tcl_DeleteTimerHandler(retr.timeout); + + /* + * Unregister the information about the selection retrieval in progress. + */ + + if (pendingRetrievals == &retr) { + pendingRetrievals = retr.nextPtr; + } else { + TkSelRetrievalInfo *retrPtr; + + for (retrPtr = pendingRetrievals; retrPtr != NULL; + retrPtr = retrPtr->nextPtr) { + if (retrPtr->nextPtr == &retr) { + retrPtr->nextPtr = retr.nextPtr; + break; + } + } + } + Tcl_DStringFree(&retr.buf); + return retr.result; +} + +/* + *---------------------------------------------------------------------- + * + * TkSelPropProc -- + * + * This function is invoked when property-change events occur on windows + * not known to the toolkit. Its function is to implement the sending + * side of the INCR selection retrieval protocol when the selection + * requestor deletes the property containing a part of the selection. + * + * Results: + * None. + * + * Side effects: + * If the property that is receiving the selection was just deleted, then + * a new piece of the selection is fetched and placed in the property, + * until eventually there's no more selection to fetch. + * + *---------------------------------------------------------------------- + */ + +void +TkSelPropProc( + register XEvent *eventPtr) /* X PropertyChange event. */ +{ + register IncrInfo *incrPtr; + register TkSelHandler *selPtr; + int length, numItems; + unsigned long i; + Atom target, formatType; + long buffer[TK_SEL_WORDS_AT_ONCE]; + TkDisplay *dispPtr = TkGetDisplay(eventPtr->xany.display); + Tk_ErrorHandler errorHandler; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + /* + * See if this event announces the deletion of a property being used for + * an INCR transfer. If so, then add the next chunk of data to the + * property. + */ + + if (eventPtr->xproperty.state != PropertyDelete) { + return; + } + for (incrPtr = tsdPtr->pendingIncrs; incrPtr != NULL; + incrPtr = incrPtr->nextPtr) { + if (incrPtr->reqWindow != eventPtr->xproperty.window) { + continue; + } + + /* + * For each conversion that has been requested, handle any chunks that + * haven't been transmitted yet. + */ + + for (i = 0; i < incrPtr->numConversions; i++) { + if ((eventPtr->xproperty.atom != incrPtr->multAtoms[2*i + 1]) + || (incrPtr->converts[i].offset == -1)) { + continue; + } + target = incrPtr->multAtoms[2*i]; + incrPtr->idleTime = 0; + + /* + * Look for a matching selection handler. + */ + + for (selPtr = incrPtr->winPtr->selHandlerList; ; + selPtr = selPtr->nextPtr) { + if (selPtr == NULL) { + /* + * No handlers match, so mark the conversion as done. + */ + + incrPtr->multAtoms[2*i + 1] = None; + incrPtr->converts[i].offset = -1; + incrPtr->numIncrs --; + return; + } + if ((selPtr->target == target) + && (selPtr->selection == incrPtr->selection)) { + break; + } + } + + /* + * We found a handler, so get the next chunk from it. + */ + + formatType = selPtr->format; + if (incrPtr->converts[i].offset == -2) { + /* + * We already got the last chunk, so send a null chunk to + * indicate that we are finished. + */ + + numItems = 0; + length = 0; + } else { + TkSelInProgress ip; + + ip.selPtr = selPtr; + ip.nextPtr = TkSelGetInProgress(); + TkSelSetInProgress(&ip); + + /* + * Copy any bytes left over from a partial character at the + * end of the previous chunk into the beginning of the buffer. + * Pass the rest of the buffer space into the selection + * handler. + */ + + length = strlen(incrPtr->converts[i].buffer); + strcpy((char *)buffer, incrPtr->converts[i].buffer); + + numItems = selPtr->proc(selPtr->clientData, + incrPtr->converts[i].offset, + ((char *) buffer) + length, + TK_SEL_BYTES_AT_ONCE - length); + TkSelSetInProgress(ip.nextPtr); + if (ip.selPtr == NULL) { + /* + * The selection handler deleted itself. + */ + + return; + } + if (numItems < 0) { + numItems = 0; + } + numItems += length; + if (numItems > TK_SEL_BYTES_AT_ONCE) { + Tcl_Panic("selection handler returned too many bytes"); + } + } + ((char *) buffer)[numItems] = 0; + + errorHandler = Tk_CreateErrorHandler(eventPtr->xproperty.display, + -1, -1, -1, (int (*)()) NULL, NULL); + + /* + * Encode the data using the proper format for each type. + */ + + if ((formatType == XA_STRING) + || (dispPtr && formatType==dispPtr->utf8Atom) + || (dispPtr && formatType==dispPtr->compoundTextAtom)) { + Tcl_DString ds; + int encodingCvtFlags; + int srcLen, dstLen, result, srcRead, dstWrote, soFar; + char *src, *dst; + Tcl_Encoding encoding; + + /* + * Set up the encoding state based on the format and whether + * this is the first and/or last chunk. + */ + + encodingCvtFlags = 0; + if (incrPtr->converts[i].offset == 0) { + encodingCvtFlags |= TCL_ENCODING_START; + } + if (numItems < TK_SEL_BYTES_AT_ONCE) { + encodingCvtFlags |= TCL_ENCODING_END; + } + if (formatType == XA_STRING) { + encoding = Tcl_GetEncoding(NULL, "iso8859-1"); + } else if (dispPtr && formatType==dispPtr->utf8Atom) { + encoding = Tcl_GetEncoding(NULL, "utf-8"); + } else { + encoding = Tcl_GetEncoding(NULL, "iso2022"); + } + + /* + * Now convert the data. + */ + + src = (char *)buffer; + srcLen = numItems; + Tcl_DStringInit(&ds); + dst = Tcl_DStringValue(&ds); + dstLen = ds.spaceAvl - 1; + + + /* + * Now convert the data, growing the destination buffer as + * needed. + */ + + while (1) { + result = Tcl_UtfToExternal(NULL, encoding, src, srcLen, + encodingCvtFlags, &incrPtr->converts[i].state, + dst, dstLen, &srcRead, &dstWrote, NULL); + soFar = dst + dstWrote - Tcl_DStringValue(&ds); + encodingCvtFlags &= ~TCL_ENCODING_START; + src += srcRead; + srcLen -= srcRead; + if (result != TCL_CONVERT_NOSPACE) { + Tcl_DStringSetLength(&ds, soFar); + break; + } + if (Tcl_DStringLength(&ds) == 0) { + Tcl_DStringSetLength(&ds, dstLen); + } + Tcl_DStringSetLength(&ds, 2 * Tcl_DStringLength(&ds) + 1); + dst = Tcl_DStringValue(&ds) + soFar; + dstLen = Tcl_DStringLength(&ds) - soFar - 1; + } + Tcl_DStringSetLength(&ds, soFar); + + if (encoding) { + Tcl_FreeEncoding(encoding); + } + + /* + * Set the property to the encoded string value. + */ + + XChangeProperty(eventPtr->xproperty.display, + eventPtr->xproperty.window, eventPtr->xproperty.atom, + formatType, 8, PropModeReplace, + (unsigned char *) Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds)); + + /* + * Preserve any left-over bytes. + */ + + if (srcLen > TCL_UTF_MAX) { + Tcl_Panic("selection conversion left too many bytes unconverted"); + } + memcpy(incrPtr->converts[i].buffer, src, (size_t) srcLen+1); + Tcl_DStringFree(&ds); + } else { + /* + * Set the property to the encoded string value. + */ + + char *propPtr = (char *) SelCvtToX((char *) buffer, + formatType, (Tk_Window) incrPtr->winPtr, &numItems); + + if (propPtr == NULL) { + numItems = 0; + } + XChangeProperty(eventPtr->xproperty.display, + eventPtr->xproperty.window, eventPtr->xproperty.atom, + formatType, 32, PropModeReplace, + (unsigned char *) propPtr, numItems); + if (propPtr != NULL) { + ckfree(propPtr); + } + } + Tk_DeleteErrorHandler(errorHandler); + + /* + * Compute the next offset value. If this was the last chunk, then + * set the offset to -2. If this was an empty chunk, then set the + * offset to -1 to indicate we are done. + */ + + if (numItems < TK_SEL_BYTES_AT_ONCE) { + if (numItems <= 0) { + incrPtr->converts[i].offset = -1; + incrPtr->numIncrs--; + } else { + incrPtr->converts[i].offset = -2; + } + } else { + /* + * Advance over the selection data that was consumed this + * time. + */ + + incrPtr->converts[i].offset += numItems - length; + } + return; + } + } +} + +/* + *-------------------------------------------------------------- + * + * TkSelEventProc -- + * + * This function is invoked whenever a selection-related event occurs. + * It does the lion's share of the work in implementing the selection + * protocol. + * + * Results: + * None. + * + * Side effects: + * Lots: depends on the type of event. + * + *-------------------------------------------------------------- + */ + +void +TkSelEventProc( + Tk_Window tkwin, /* Window for which event was targeted. */ + register XEvent *eventPtr) /* X event: either SelectionClear, + * SelectionRequest, or SelectionNotify. */ +{ + register TkWindow *winPtr = (TkWindow *) tkwin; + TkDisplay *dispPtr = winPtr->dispPtr; + Tcl_Interp *interp; + + /* + * Case #1: SelectionClear events. + */ + + if (eventPtr->type == SelectionClear) { + TkSelClearSelection(tkwin, eventPtr); + } + + /* + * Case #2: SelectionNotify events. Call the relevant function to handle + * the incoming selection. + */ + + if (eventPtr->type == SelectionNotify) { + register TkSelRetrievalInfo *retrPtr; + char *propInfo, **propInfoPtr = &propInfo; + Atom type; + int format, result; + unsigned long numItems, bytesAfter; + Tcl_DString ds; + + for (retrPtr = pendingRetrievals; ; retrPtr = retrPtr->nextPtr) { + if (retrPtr == NULL) { + return; + } + if ((retrPtr->winPtr == winPtr) + && (retrPtr->selection == eventPtr->xselection.selection) + && (retrPtr->target == eventPtr->xselection.target) + && (retrPtr->result == -1)) { + if (retrPtr->property == eventPtr->xselection.property) { + break; + } + if (eventPtr->xselection.property == None) { + Tcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf( + "%s selection doesn't exist or form \"%s\" not defined", + Tk_GetAtomName(tkwin, retrPtr->selection), + Tk_GetAtomName(tkwin, retrPtr->target))); + Tcl_SetErrorCode(retrPtr->interp, "TK", "SELECTION", + "NONE", NULL); + retrPtr->result = TCL_ERROR; + return; + } + } + } + + propInfo = NULL; + result = XGetWindowProperty(eventPtr->xselection.display, + eventPtr->xselection.requestor, retrPtr->property, + 0, MAX_PROP_WORDS, False, (Atom) AnyPropertyType, + &type, &format, &numItems, &bytesAfter, + (unsigned char **) propInfoPtr); + if ((result != Success) || (type == None)) { + return; + } + if (bytesAfter != 0) { + Tcl_SetObjResult(retrPtr->interp, Tcl_NewStringObj( + "selection property too large", -1)); + Tcl_SetErrorCode(retrPtr->interp, "TK", "SELECTION", "SIZE",NULL); + retrPtr->result = TCL_ERROR; + XFree(propInfo); + return; + } + if ((type == XA_STRING) || (type == dispPtr->textAtom) + || (type == dispPtr->compoundTextAtom)) { + Tcl_Encoding encoding; + + if (format != 8) { + Tcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf( + "bad format for string selection: wanted \"8\", got \"%d\"", + format)); + Tcl_SetErrorCode(retrPtr->interp, "TK", "SELECTION", "FORMAT", + NULL); + retrPtr->result = TCL_ERROR; + return; + } + interp = retrPtr->interp; + Tcl_Preserve(interp); + + /* + * Convert the X selection data into UTF before passing it to the + * selection callback. Note that the COMPOUND_TEXT uses a modified + * iso2022 encoding, not the current system encoding. For now + * we'll just blindly apply the iso2022 encoding. This is probably + * wrong, but it's a placeholder until we figure out what we're + * really supposed to do. For STRING, we need to use Latin-1 + * instead. Again, it's not really the full iso8859-1 space, but + * this is close enough. + */ + + if (type == dispPtr->compoundTextAtom) { + encoding = Tcl_GetEncoding(NULL, "iso2022"); + } else { + encoding = Tcl_GetEncoding(NULL, "iso8859-1"); + } + Tcl_ExternalToUtfDString(encoding, propInfo, (int)numItems, &ds); + if (encoding) { + Tcl_FreeEncoding(encoding); + } + + retrPtr->result = retrPtr->proc(retrPtr->clientData, interp, + Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); + Tcl_Release(interp); + } else if (type == dispPtr->utf8Atom) { + /* + * The X selection data is in UTF-8 format already. We can't + * guarantee that propInfo is NULL-terminated, so we might have to + * copy the string. + */ + + char *propData = propInfo; + + if (format != 8) { + Tcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf( + "bad format for string selection: wanted \"8\", got \"%d\"", + format)); + Tcl_SetErrorCode(retrPtr->interp, "TK", "SELECTION", "FORMAT", + NULL); + retrPtr->result = TCL_ERROR; + return; + } + + if (propInfo[numItems] != '\0') { + propData = ckalloc(numItems + 1); + strcpy(propData, propInfo); + propData[numItems] = '\0'; + } + retrPtr->result = retrPtr->proc(retrPtr->clientData, + retrPtr->interp, propData); + if (propData != propInfo) { + ckfree(propData); + } + + } else if (type == dispPtr->incrAtom) { + /* + * It's a !?#@!?!! INCR-style reception. Arrange to receive the + * selection in pieces, using the ICCCM protocol, then hang around + * until either the selection is all here or a timeout occurs. + */ + + retrPtr->idleTime = 0; + Tk_CreateEventHandler(tkwin, PropertyChangeMask, SelRcvIncrProc, + retrPtr); + XDeleteProperty(Tk_Display(tkwin), Tk_WindowId(tkwin), + retrPtr->property); + while (retrPtr->result == -1) { + Tcl_DoOneEvent(0); + } + Tk_DeleteEventHandler(tkwin, PropertyChangeMask, SelRcvIncrProc, + retrPtr); + } else { + Tcl_DString ds; + + if (format != 32 && format != 8) { + Tcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf( + "bad format for selection: wanted \"32\" or " + "\"8\", got \"%d\"", format)); + Tcl_SetErrorCode(retrPtr->interp, "TK", "SELECTION", "FORMAT", + NULL); + retrPtr->result = TCL_ERROR; + return; + } + Tcl_DStringInit(&ds); + if (format == 32) { + SelCvtFromX32((long *) propInfo, (int) numItems, type, + (Tk_Window) winPtr, &ds); + } else { + SelCvtFromX8((char *) propInfo, (int) numItems, type, + (Tk_Window) winPtr, &ds); + } + interp = retrPtr->interp; + Tcl_Preserve(interp); + retrPtr->result = retrPtr->proc(retrPtr->clientData, + interp, Tcl_DStringValue(&ds)); + Tcl_Release(interp); + Tcl_DStringFree(&ds); + } + XFree(propInfo); + return; + } + + /* + * Case #3: SelectionRequest events. Call ConvertSelection to do the dirty + * work. + */ + + if (eventPtr->type == SelectionRequest) { + ConvertSelection(winPtr, &eventPtr->xselectionrequest); + return; + } +} + +/* + *---------------------------------------------------------------------- + * + * SelTimeoutProc -- + * + * This function is invoked once every second while waiting for the + * selection to be returned. After a while it gives up and aborts the + * selection retrieval. + * + * Results: + * None. + * + * Side effects: + * A new timer callback is created to call us again in another second, + * unless time has expired, in which case an error is recorded for the + * retrieval. + * + *---------------------------------------------------------------------- + */ + +static void +SelTimeoutProc( + ClientData clientData) /* Information about retrieval in progress. */ +{ + register TkSelRetrievalInfo *retrPtr = clientData; + + /* + * Make sure that the retrieval is still in progress. Then see how long + * it's been since any sort of response was received from the other side. + */ + + if (retrPtr->result != -1) { + return; + } + retrPtr->idleTime++; + if (retrPtr->idleTime >= 5) { + /* + * Use a careful function to store the error message, because the + * result could already be partially filled in with a partial + * selection return. + */ + + Tcl_SetObjResult(retrPtr->interp, Tcl_NewStringObj( + "selection owner didn't respond", -1)); + Tcl_SetErrorCode(retrPtr->interp, "TK", "SELECTION", "IGNORED", NULL); + retrPtr->result = TCL_ERROR; + } else { + retrPtr->timeout = Tcl_CreateTimerHandler(1000, SelTimeoutProc, + (ClientData) retrPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * ConvertSelection -- + * + * This function is invoked to handle SelectionRequest events. It + * responds to the requests, obeying the ICCCM protocols. + * + * Results: + * None. + * + * Side effects: + * Properties are created for the selection requestor, and a + * SelectionNotify event is generated for the selection requestor. In the + * event of long selections, this function implements INCR-mode + * transfers, using the ICCCM protocol. + * + *---------------------------------------------------------------------- + */ + +static void +ConvertSelection( + TkWindow *winPtr, /* Window that received the conversion + * request; may not be selection's current + * owner, be we set it to the current + * owner. */ + register XSelectionRequestEvent *eventPtr) + /* Event describing request. */ +{ + union { + XSelectionEvent xsel; + XEvent ev; + } reply; /* Used to notify requestor that selection + * info is ready. */ + int multiple; /* Non-zero means a MULTIPLE request is being + * handled. */ + IncrInfo incr; /* State of selection conversion. */ + Atom singleInfo[2]; /* incr.multAtoms points here except for + * multiple conversions. */ + unsigned long i; + Tk_ErrorHandler errorHandler; + TkSelectionInfo *infoPtr; + TkSelInProgress ip; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + errorHandler = Tk_CreateErrorHandler(eventPtr->display, -1, -1,-1, + (int (*)()) NULL, NULL); + + /* + * Initialize the reply event. + */ + + reply.xsel.type = SelectionNotify; + reply.xsel.serial = 0; + reply.xsel.send_event = True; + reply.xsel.display = eventPtr->display; + reply.xsel.requestor = eventPtr->requestor; + reply.xsel.selection = eventPtr->selection; + reply.xsel.target = eventPtr->target; + reply.xsel.property = eventPtr->property; + if (reply.xsel.property == None) { + reply.xsel.property = reply.xsel.target; + } + reply.xsel.time = eventPtr->time; + + for (infoPtr = winPtr->dispPtr->selectionInfoPtr; infoPtr != NULL; + infoPtr = infoPtr->nextPtr) { + if (infoPtr->selection == eventPtr->selection) { + break; + } + } + if (infoPtr == NULL) { + goto refuse; + } + winPtr = (TkWindow *) infoPtr->owner; + + /* + * Figure out which kind(s) of conversion to perform. If handling a + * MULTIPLE conversion, then read the property describing which + * conversions to perform. + */ + + incr.winPtr = winPtr; + incr.selection = eventPtr->selection; + if (eventPtr->target != winPtr->dispPtr->multipleAtom) { + multiple = 0; + singleInfo[0] = reply.xsel.target; + singleInfo[1] = reply.xsel.property; + incr.multAtoms = singleInfo; + incr.numConversions = 1; + } else { + Atom type, **multAtomsPtr = &incr.multAtoms; + int format, result; + unsigned long bytesAfter; + + multiple = 1; + incr.multAtoms = NULL; + if (eventPtr->property == None) { + goto refuse; + } + result = XGetWindowProperty(eventPtr->display, eventPtr->requestor, + eventPtr->property, 0, MAX_PROP_WORDS, False, + winPtr->dispPtr->atomPairAtom, &type, &format, + &incr.numConversions, &bytesAfter, + (unsigned char **) multAtomsPtr); + if ((result != Success) || (bytesAfter != 0) || (format != 32) + || (type == None)) { + if (incr.multAtoms != NULL) { + XFree((char *) incr.multAtoms); + } + goto refuse; + } + incr.numConversions /= 2; /* Two atoms per conversion. */ + } + + /* + * Loop through all of the requested conversions, and either return the + * entire converted selection, if it can be returned in a single bunch, or + * return INCR information only (the actual selection will be returned + * below). + */ + + incr.converts = ckalloc(incr.numConversions * sizeof(ConvertInfo)); + incr.numIncrs = 0; + for (i = 0; i < incr.numConversions; i++) { + Atom target, property, type; + long buffer[TK_SEL_WORDS_AT_ONCE]; + register TkSelHandler *selPtr; + int numItems, format; + char *propPtr; + + target = incr.multAtoms[2*i]; + property = incr.multAtoms[2*i + 1]; + incr.converts[i].offset = -1; + incr.converts[i].buffer[0] = '\0'; + + for (selPtr = winPtr->selHandlerList; selPtr != NULL; + selPtr = selPtr->nextPtr) { + if ((selPtr->target == target) + && (selPtr->selection == eventPtr->selection)) { + break; + } + } + + if (selPtr == NULL) { + /* + * Nobody seems to know about this kind of request. If it's of a + * sort that we can handle without any help, do it. Otherwise mark + * the request as an errror. + */ + + numItems = TkSelDefaultSelection(infoPtr, target, (char *) buffer, + TK_SEL_BYTES_AT_ONCE, &type); + if (numItems < 0) { + incr.multAtoms[2*i + 1] = None; + continue; + } + } else { + ip.selPtr = selPtr; + ip.nextPtr = TkSelGetInProgress(); + TkSelSetInProgress(&ip); + type = selPtr->format; + numItems = selPtr->proc(selPtr->clientData, 0, (char *) buffer, + TK_SEL_BYTES_AT_ONCE); + TkSelSetInProgress(ip.nextPtr); + if ((ip.selPtr == NULL) || (numItems < 0)) { + incr.multAtoms[2*i + 1] = None; + continue; + } + if (numItems > TK_SEL_BYTES_AT_ONCE) { + Tcl_Panic("selection handler returned too many bytes"); + } + ((char *) buffer)[numItems] = '\0'; + } + + /* + * Got the selection; store it back on the requestor's property. + */ + + if (numItems == TK_SEL_BYTES_AT_ONCE) { + /* + * Selection is too big to send at once; start an INCR-mode + * transfer. + */ + + incr.numIncrs++; + type = winPtr->dispPtr->incrAtom; + buffer[0] = SelectionSize(selPtr); + if (buffer[0] == 0) { + incr.multAtoms[2*i + 1] = None; + continue; + } + numItems = 1; + propPtr = (char *) buffer; + format = 32; + incr.converts[i].offset = 0; + XChangeProperty(reply.xsel.display, reply.xsel.requestor, + property, type, format, PropModeReplace, + (unsigned char *) propPtr, numItems); + } else if (type == winPtr->dispPtr->utf8Atom) { + /* + * This matches selection requests of type UTF8_STRING, which + * allows us to pass our utf-8 information untouched. + */ + + XChangeProperty(reply.xsel.display, reply.xsel.requestor, + property, type, 8, PropModeReplace, + (unsigned char *) buffer, numItems); + } else if ((type == XA_STRING) + || (type == winPtr->dispPtr->compoundTextAtom)) { + Tcl_DString ds; + Tcl_Encoding encoding; + + /* + * STRING is Latin-1, COMPOUND_TEXT is an iso2022 variant. We need + * to convert the selection text into these external forms before + * modifying the property. + */ + + if (type == XA_STRING) { + encoding = Tcl_GetEncoding(NULL, "iso8859-1"); + } else { + encoding = Tcl_GetEncoding(NULL, "iso2022"); + } + Tcl_UtfToExternalDString(encoding, (char *) buffer, -1, &ds); + XChangeProperty(reply.xsel.display, reply.xsel.requestor, + property, type, 8, PropModeReplace, + (unsigned char *) Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds)); + if (encoding) { + Tcl_FreeEncoding(encoding); + } + Tcl_DStringFree(&ds); + } else { + propPtr = (char *) SelCvtToX((char *) buffer, + type, (Tk_Window) winPtr, &numItems); + if (propPtr == NULL) { + goto refuse; + } + format = 32; + XChangeProperty(reply.xsel.display, reply.xsel.requestor, + property, type, format, PropModeReplace, + (unsigned char *) propPtr, numItems); + ckfree(propPtr); + } + } + + /* + * Send an event back to the requestor to indicate that the first stage of + * conversion is complete (everything is done except for long conversions + * that have to be done in INCR mode). + */ + + if (incr.numIncrs > 0) { + XSelectInput(reply.xsel.display, reply.xsel.requestor, + PropertyChangeMask); + incr.timeout = Tcl_CreateTimerHandler(1000, IncrTimeoutProc, &incr); + incr.idleTime = 0; + incr.reqWindow = reply.xsel.requestor; + incr.time = infoPtr->time; + incr.nextPtr = tsdPtr->pendingIncrs; + tsdPtr->pendingIncrs = &incr; + } + if (multiple) { + XChangeProperty(reply.xsel.display, reply.xsel.requestor, + reply.xsel.property, winPtr->dispPtr->atomPairAtom, + 32, PropModeReplace, (unsigned char *) incr.multAtoms, + (int) incr.numConversions*2); + } else { + /* + * Not a MULTIPLE request. The first property in "multAtoms" got set + * to None if there was an error in conversion. + */ + + reply.xsel.property = incr.multAtoms[1]; + } + XSendEvent(reply.xsel.display, reply.xsel.requestor, False, 0, &reply.ev); + Tk_DeleteErrorHandler(errorHandler); + + /* + * Handle any remaining INCR-mode transfers. This all happens in callbacks + * to TkSelPropProc, so just wait until the number of uncompleted INCR + * transfers drops to zero. + */ + + if (incr.numIncrs > 0) { + IncrInfo *incrPtr2; + + while (incr.numIncrs > 0) { + Tcl_DoOneEvent(0); + } + Tcl_DeleteTimerHandler(incr.timeout); + errorHandler = Tk_CreateErrorHandler(winPtr->display, + -1, -1, -1, (int (*)()) NULL, NULL); + XSelectInput(reply.xsel.display, reply.xsel.requestor, 0L); + Tk_DeleteErrorHandler(errorHandler); + if (tsdPtr->pendingIncrs == &incr) { + tsdPtr->pendingIncrs = incr.nextPtr; + } else { + for (incrPtr2 = tsdPtr->pendingIncrs; incrPtr2 != NULL; + incrPtr2 = incrPtr2->nextPtr) { + if (incrPtr2->nextPtr == &incr) { + incrPtr2->nextPtr = incr.nextPtr; + break; + } + } + } + } + + /* + * All done. Cleanup and return. + */ + + ckfree(incr.converts); + if (multiple) { + XFree((char *) incr.multAtoms); + } + return; + + /* + * An error occurred. Send back a refusal message. + */ + + refuse: + reply.xsel.property = None; + XSendEvent(reply.xsel.display, reply.xsel.requestor, False, 0, &reply.ev); + Tk_DeleteErrorHandler(errorHandler); + return; +} + +/* + *---------------------------------------------------------------------- + * + * SelRcvIncrProc -- + * + * This function handles the INCR protocol on the receiving side. It is + * invoked in response to property changes on the requestor's window + * (which hopefully are because a new chunk of the selection arrived). + * + * Results: + * None. + * + * Side effects: + * If a new piece of selection has arrived, a function is invoked to deal + * with that piece. When the whole selection is here, a flag is left for + * the higher-level function that initiated the selection retrieval. + * + *---------------------------------------------------------------------- + */ + +static void +SelRcvIncrProc( + ClientData clientData, /* Information about retrieval. */ + register XEvent *eventPtr) /* X PropertyChange event. */ +{ + register TkSelRetrievalInfo *retrPtr = clientData; + char *propInfo, **propInfoPtr = &propInfo; + Atom type; + int format, result; + unsigned long numItems, bytesAfter; + Tcl_Interp *interp; + + if ((eventPtr->xproperty.atom != retrPtr->property) + || (eventPtr->xproperty.state != PropertyNewValue) + || (retrPtr->result != -1)) { + return; + } + propInfo = NULL; + result = XGetWindowProperty(eventPtr->xproperty.display, + eventPtr->xproperty.window, retrPtr->property, 0, MAX_PROP_WORDS, + True, (Atom) AnyPropertyType, &type, &format, &numItems, + &bytesAfter, (unsigned char **) propInfoPtr); + if ((result != Success) || (type == None)) { + return; + } + if (bytesAfter != 0) { + Tcl_SetObjResult(retrPtr->interp, Tcl_NewStringObj( + "selection property too large", -1)); + Tcl_SetErrorCode(retrPtr->interp, "TK", "SELECTION", "SIZE", NULL); + retrPtr->result = TCL_ERROR; + goto done; + } + if ((type == XA_STRING) + || (type == retrPtr->winPtr->dispPtr->textAtom) + || (type == retrPtr->winPtr->dispPtr->utf8Atom) + || (type == retrPtr->winPtr->dispPtr->compoundTextAtom)) { + char *dst, *src; + int srcLen, dstLen, srcRead, dstWrote, soFar; + Tcl_Encoding encoding; + Tcl_DString *dstPtr, temp; + + if (format != 8) { + Tcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf( + "bad format for string selection: wanted \"8\", got \"%d\"", + format)); + Tcl_SetErrorCode(retrPtr->interp, "TK", "SELECTION", "FORMAT", + NULL); + retrPtr->result = TCL_ERROR; + goto done; + } + interp = retrPtr->interp; + Tcl_Preserve(interp); + + if (type == retrPtr->winPtr->dispPtr->compoundTextAtom) { + encoding = Tcl_GetEncoding(NULL, "iso2022"); + } else if (type == retrPtr->winPtr->dispPtr->utf8Atom) { + encoding = Tcl_GetEncoding(NULL, "utf-8"); + } else { + encoding = Tcl_GetEncoding(NULL, "iso8859-1"); + } + + /* + * Check to see if there is any data left over from the previous + * chunk. If there is, copy the old data and the new data into a new + * buffer. + */ + + Tcl_DStringInit(&temp); + if (Tcl_DStringLength(&retrPtr->buf) > 0) { + Tcl_DStringAppend(&temp, Tcl_DStringValue(&retrPtr->buf), + Tcl_DStringLength(&retrPtr->buf)); + if (numItems > 0) { + Tcl_DStringAppend(&temp, propInfo, (int)numItems); + } + src = Tcl_DStringValue(&temp); + srcLen = Tcl_DStringLength(&temp); + } else if (numItems == 0) { + /* + * There is no new data, so we're done. + */ + + retrPtr->result = TCL_OK; + Tcl_Release(interp); + goto done; + } else { + src = propInfo; + srcLen = numItems; + } + + /* + * Set up the destination buffer so we can use as much space as is + * available. + */ + + dstPtr = &retrPtr->buf; + dst = Tcl_DStringValue(dstPtr); + dstLen = dstPtr->spaceAvl - 1; + + /* + * Now convert the data, growing the destination buffer as needed. + */ + + while (1) { + result = Tcl_ExternalToUtf(NULL, encoding, src, srcLen, + retrPtr->encFlags, &retrPtr->encState, + dst, dstLen, &srcRead, &dstWrote, NULL); + soFar = dst + dstWrote - Tcl_DStringValue(dstPtr); + retrPtr->encFlags &= ~TCL_ENCODING_START; + src += srcRead; + srcLen -= srcRead; + if (result != TCL_CONVERT_NOSPACE) { + Tcl_DStringSetLength(dstPtr, soFar); + break; + } + if (Tcl_DStringLength(dstPtr) == 0) { + Tcl_DStringSetLength(dstPtr, dstLen); + } + Tcl_DStringSetLength(dstPtr, 2 * Tcl_DStringLength(dstPtr) + 1); + dst = Tcl_DStringValue(dstPtr) + soFar; + dstLen = Tcl_DStringLength(dstPtr) - soFar - 1; + } + Tcl_DStringSetLength(dstPtr, soFar); + + result = retrPtr->proc(retrPtr->clientData, interp, + Tcl_DStringValue(dstPtr)); + Tcl_Release(interp); + + /* + * Copy any unused data into the destination buffer so we can pick it + * up next time around. + */ + + Tcl_DStringSetLength(dstPtr, 0); + Tcl_DStringAppend(dstPtr, src, srcLen); + + Tcl_DStringFree(&temp); + if (encoding) { + Tcl_FreeEncoding(encoding); + } + if (result != TCL_OK) { + retrPtr->result = result; + } + } else if (numItems == 0) { + retrPtr->result = TCL_OK; + } else { + Tcl_DString ds; + + if (format != 32 && format != 8) { + Tcl_SetObjResult(retrPtr->interp, Tcl_ObjPrintf( + "bad format for selection: wanted \"32\" or " + "\"8\", got \"%d\"", format)); + Tcl_SetErrorCode(retrPtr->interp, "TK", "SELECTION", "FORMAT", + NULL); + retrPtr->result = TCL_ERROR; + goto done; + } + Tcl_DStringInit(&ds); + if (format == 32) { + SelCvtFromX32((long *) propInfo, (int) numItems, type, + (Tk_Window) retrPtr->winPtr, &ds); + } else { + SelCvtFromX8((char *) propInfo, (int) numItems, type, + (Tk_Window) retrPtr->winPtr, &ds); + } + interp = retrPtr->interp; + Tcl_Preserve(interp); + result = retrPtr->proc(retrPtr->clientData, interp, + Tcl_DStringValue(&ds)); + Tcl_Release(interp); + Tcl_DStringFree(&ds); + if (result != TCL_OK) { + retrPtr->result = result; + } + } + + done: + XFree(propInfo); + retrPtr->idleTime = 0; +} + +/* + *---------------------------------------------------------------------- + * + * SelectionSize -- + * + * This function is called when the selection is too large to send in a + * single buffer; it computes the total length of the selection in bytes. + * + * Results: + * The return value is the number of bytes in the selection given by + * selPtr. + * + * Side effects: + * The selection is retrieved from its current owner (this is the only + * way to compute its size). + * + *---------------------------------------------------------------------- + */ + +static int +SelectionSize( + TkSelHandler *selPtr) /* Information about how to retrieve the + * selection whose size is wanted. */ +{ + char buffer[TK_SEL_BYTES_AT_ONCE+1]; + int size, chunkSize; + TkSelInProgress ip; + + size = TK_SEL_BYTES_AT_ONCE; + ip.selPtr = selPtr; + ip.nextPtr = TkSelGetInProgress(); + TkSelSetInProgress(&ip); + + do { + chunkSize = selPtr->proc(selPtr->clientData, size, (char *) buffer, + TK_SEL_BYTES_AT_ONCE); + if (ip.selPtr == NULL) { + size = 0; + break; + } + size += chunkSize; + } while (chunkSize == TK_SEL_BYTES_AT_ONCE); + + TkSelSetInProgress(ip.nextPtr); + return size; +} + +/* + *---------------------------------------------------------------------- + * + * IncrTimeoutProc -- + * + * This function is invoked once a second while sending the selection to + * a requestor in INCR mode. After a while it gives up and aborts the + * selection operation. + * + * Results: + * None. + * + * Side effects: + * A new timeout gets registered so that this function gets called again + * in another second, unless too many seconds have elapsed, in which case + * incrPtr is marked as "all done". + * + *---------------------------------------------------------------------- + */ + +static void +IncrTimeoutProc( + ClientData clientData) /* Information about INCR-mode selection + * retrieval for which we are selection + * owner. */ +{ + register IncrInfo *incrPtr = clientData; + + incrPtr->idleTime++; + if (incrPtr->idleTime >= 5) { + incrPtr->numIncrs = 0; + } else { + incrPtr->timeout = Tcl_CreateTimerHandler(1000, IncrTimeoutProc, + incrPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * SelCvtToX -- + * + * Given a selection represented as a string (the normal Tcl form), + * convert it to the ICCCM-mandated format for X, depending on the type + * argument. This function and SelCvtFromX are inverses. + * + * Results: + * The return value is a malloc'ed buffer holding a value equivalent to + * "string", but formatted as for "type". It is the caller's + * responsibility to free the string when done with it. The word at + * *numLongsPtr is filled in with the number of 32-bit words returned in + * the result. If NULL is returned, the input list was not actually a + * list. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static long * +SelCvtToX( + char *string, /* String representation of selection. */ + Atom type, /* Atom specifying the X format that is + * desired for the selection. Should not be + * XA_STRING (if so, don't bother calling this + * function at all). */ + Tk_Window tkwin, /* Window that governs atom conversion. */ + int *numLongsPtr) /* Number of 32-bit words contained in the + * result. */ +{ + const char **field; + int numFields, i; + long *propPtr; + + /* + * The string is assumed to consist of fields separated by spaces. The + * property gets generated by converting each field to an integer number, + * in one of two ways: + * 1. If type is XA_ATOM, convert each field to its corresponding atom. + * 2. If type is anything else, convert each field from an ASCII number to + * a 32-bit binary number. + */ + + if (Tcl_SplitList(NULL, string, &numFields, &field) != TCL_OK) { + return NULL; + } + propPtr = ckalloc(numFields * sizeof(long)); + + /* + * Convert the fields one-by-one. + */ + + for (i=0 ; i<numFields ; i++) { + if (type == XA_ATOM) { + propPtr[i] = (long) Tk_InternAtom(tkwin, field[i]); + } else { + char *dummy; + + /* + * If this fails to parse a number, we just plunge on regardless + * anyway. + */ + + propPtr[i] = strtol(field[i], &dummy, 0); + } + } + + /* + * Release the parsed list. + */ + + ckfree(field); + *numLongsPtr = i; + return propPtr; +} + +/* + *---------------------------------------------------------------------- + * + * SelCvtFromX32, SelCvtFromX8 -- + * + * Given an X property value, formatted as a collection of 32-bit or + * 8-bit values according to "type" and the ICCCM conventions, convert + * the value to a string suitable for manipulation by Tcl. These + * functions are the inverse of SelCvtToX. + * + * Results: + * The return value (stored in a Tcl_DString) is the string equivalent of + * "property". It is up to the caller to initialize and free the DString. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +SelCvtFromX32( + register long *propPtr, /* Property value from X. */ + int numValues, /* Number of 32-bit values in property. */ + Atom type, /* Type of property Should not be XA_STRING + * (if so, don't bother calling this function + * at all). */ + Tk_Window tkwin, /* Window to use for atom conversion. */ + Tcl_DString *dsPtr) /* Where to store the converted string. */ +{ + /* + * Convert each long in the property to a string value, which is either + * the name of an atom (if type is XA_ATOM) or a hexadecimal string. We + * build the list in a Tcl_DString because this is easier than trying to + * get the quoting correct ourselves; this is tricky because atoms can + * contain spaces in their names (encountered when the atoms are really + * MIME types). [Bug 1353414] + */ + + for ( ; numValues > 0; propPtr++, numValues--) { + if (type == XA_ATOM) { + Tcl_DStringAppendElement(dsPtr, + Tk_GetAtomName(tkwin, (Atom) *propPtr)); + } else { + char buf[12]; + + sprintf(buf, "0x%x", (unsigned int) *propPtr); + Tcl_DStringAppendElement(dsPtr, buf); + } + } + Tcl_DStringAppend(dsPtr, " ", 1); +} + +static void +SelCvtFromX8( + register char *propPtr, /* Property value from X. */ + int numValues, /* Number of 8-bit values in property. */ + Atom type, /* Type of property Should not be XA_STRING + * (if so, don't bother calling this function + * at all). */ + Tk_Window tkwin, /* Window to use for atom conversion. */ + Tcl_DString *dsPtr) /* Where to store the converted string. */ +{ + /* + * Convert each long in the property to a string value, which is a + * hexadecimal string. We build the list in a Tcl_DString because this is + * easier than trying to get the quoting correct ourselves. + */ + + for ( ; numValues > 0; propPtr++, numValues--) { + char buf[12]; + + sprintf(buf, "0x%x", (unsigned char) *propPtr); + Tcl_DStringAppendElement(dsPtr, buf); + } + Tcl_DStringAppend(dsPtr, " ", 1); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixSend.c b/tk8.6/unix/tkUnixSend.c new file mode 100644 index 0000000..0b4f05d --- /dev/null +++ b/tk8.6/unix/tkUnixSend.c @@ -0,0 +1,2066 @@ +/* + * tkUnixSend.c -- + * + * This file provides functions that implement the "send" command, + * allowing commands to be passed from interpreter to interpreter. + * + * Copyright (c) 1989-1994 The Regents of the University of California. + * Copyright (c) 1994-1996 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. + */ + +#include "tkUnixInt.h" + +/* + * The following structure is used to keep track of the interpreters + * registered by this process. + */ + +typedef struct RegisteredInterp { + char *name; /* Interpreter's name (malloc-ed). */ + Tcl_Interp *interp; /* Interpreter associated with name. NULL + * means that the application was unregistered + * or deleted while a send was in progress to + * it. */ + TkDisplay *dispPtr; /* Display for the application. Needed because + * we may need to unregister the interpreter + * after its main window has been deleted. */ + struct RegisteredInterp *nextPtr; + /* Next in list of names associated with + * interps in this process. NULL means end of + * list. */ +} RegisteredInterp; + +/* + * A registry of all interpreters for a display is kept in a property + * "InterpRegistry" on the root window of the display. It is organized as a + * series of zero or more concatenated strings (in no particular order), each + * of the form + * window space name '\0' + * where "window" is the hex id of the comm. window to use to talk to an + * interpreter named "name". + * + * When the registry is being manipulated by an application (e.g. to add or + * remove an entry), it is loaded into memory using a structure of the + * following type: + */ + +typedef struct NameRegistry { + TkDisplay *dispPtr; /* Display from which the registry was + * read. */ + int locked; /* Non-zero means that the display was locked + * when the property was read in. */ + int modified; /* Non-zero means that the property has been + * modified, so it needs to be written out + * when the NameRegistry is closed. */ + unsigned long propLength; /* Length of the property, in bytes. */ + char *property; /* The contents of the property, or NULL if + * none. See format description above; this is + * *not* terminated by the first null + * character. Dynamically allocated. */ + int allocedByX; /* Non-zero means must free property with + * XFree; zero means use ckfree. */ +} NameRegistry; + +/* + * When a result is being awaited from a sent command, one of the following + * structures is present on a list of all outstanding sent commands. The + * information in the structure is used to process the result when it arrives. + * You're probably wondering how there could ever be multiple outstanding sent + * commands. This could happen if interpreters invoke each other recursively. + * It's unlikely, but possible. + */ + +typedef struct PendingCommand { + int serial; /* Serial number expected in result. */ + TkDisplay *dispPtr; /* Display being used for communication. */ + const char *target; /* Name of interpreter command is being sent + * to. */ + Window commWindow; /* Target's communication window. */ + Tcl_Interp *interp; /* Interpreter from which the send was + * invoked. */ + int code; /* Tcl return code for command will be stored + * here. */ + char *result; /* String result for command (malloc'ed), or + * NULL. */ + char *errorInfo; /* Information for "errorInfo" variable, or + * NULL (malloc'ed). */ + char *errorCode; /* Information for "errorCode" variable, or + * NULL (malloc'ed). */ + int gotResponse; /* 1 means a response has been received, 0 + * means the command is still outstanding. */ + struct PendingCommand *nextPtr; + /* Next in list of all outstanding commands. + * NULL means end of list. */ +} PendingCommand; + +typedef struct ThreadSpecificData { + PendingCommand *pendingCommands; + /* List of all commands currently being waited + * for. */ + RegisteredInterp *interpListPtr; + /* List of all interpreters registered in the + * current process. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + +/* + * The information below is used for communication between processes during + * "send" commands. Each process keeps a private window, never even mapped, + * with one property, "Comm". When a command is sent to an interpreter, the + * command is appended to the comm property of the communication window + * associated with the interp's process. Similarly, when a result is returned + * from a sent command, it is also appended to the comm property. + * + * Each command and each result takes the form of ASCII text. For a command, + * the text consists of a zero character followed by several null-terminated + * ASCII strings. The first string consists of the single letter "c". + * Subsequent strings have the form "option value" where the following options + * are supported: + * + * -r commWindow serial + * + * This option means that a response should be sent to the window whose X + * identifier is "commWindow" (in hex), and the response should be + * identified with the serial number given by "serial" (in decimal). If + * this option isn't specified then the send is asynchronous and no + * response is sent. + * + * -n name + * + * "Name" gives the name of the application for which the command is + * intended. This option must be present. + * + * -s script + * + * "Script" is the script to be executed. This option must be present. + * + * The options may appear in any order. The -n and -s options must be present, + * but -r may be omitted for asynchronous RPCs. For compatibility with future + * releases that may add new features, there may be additional options + * present; as long as they start with a "-" character, they will be ignored. + * + * A result also consists of a zero character followed by several null- + * terminated ASCII strings. The first string consists of the single letter + * "r". Subsequent strings have the form "option value" where the following + * options are supported: + * + * -s serial + * + * Identifies the command for which this is the result. It is the same as + * the "serial" field from the -s option in the command. This option must + * be present. + * + * -c code + * + * "Code" is the completion code for the script, in decimal. If the code + * is omitted it defaults to TCL_OK. + * + * -r result + * + * "Result" is the result string for the script, which may be either a + * result or an error message. If this field is omitted then it defaults + * to an empty string. + * + * -i errorInfo + * + * "ErrorInfo" gives a string with which to initialize the errorInfo + * variable. This option may be omitted; it is ignored unless the + * completion code is TCL_ERROR. + * + * -e errorCode + * + * "ErrorCode" gives a string with with to initialize the errorCode + * variable. This option may be omitted; it is ignored unless the + * completion code is TCL_ERROR. + * + * Options may appear in any order, and only the -s option must be present. As + * with commands, there may be additional options besides these; unknown + * options are ignored. + */ + +/* + * Other miscellaneous per-process data: + */ + +static struct { + int sendSerial; /* The serial number that was used in the last + * "send" command. */ + int sendDebug; /* This can be set while debugging to do + * things like skip locking the server. */ +} localData = {0, 0}; + +/* + * Maximum size property that can be read at one time by this module: + */ + +#define MAX_PROP_WORDS 100000 + +/* + * Forward declarations for functions defined later in this file: + */ + +static int AppendErrorProc(ClientData clientData, + XErrorEvent *errorPtr); +static void AppendPropCarefully(Display *display, + Window window, Atom property, char *value, + int length, PendingCommand *pendingPtr); +static void DeleteProc(ClientData clientData); +static void RegAddName(NameRegistry *regPtr, + const char *name, Window commWindow); +static void RegClose(NameRegistry *regPtr); +static void RegDeleteName(NameRegistry *regPtr, const char *name); +static Window RegFindName(NameRegistry *regPtr, const char *name); +static NameRegistry * RegOpen(Tcl_Interp *interp, + TkDisplay *dispPtr, int lock); +static void SendEventProc(ClientData clientData, XEvent *eventPtr); +static int SendInit(Tcl_Interp *interp, TkDisplay *dispPtr); +static Tk_RestrictProc SendRestrictProc; +static int ServerSecure(TkDisplay *dispPtr); +static void UpdateCommWindow(TkDisplay *dispPtr); +static int ValidateName(TkDisplay *dispPtr, const char *name, + Window commWindow, int oldOK); + +/* + *---------------------------------------------------------------------- + * + * RegOpen -- + * + * This function loads the name registry for a display into memory so + * that it can be manipulated. + * + * Results: + * The return value is a pointer to the loaded registry. + * + * Side effects: + * If "lock" is set then the server will be locked. It is the caller's + * responsibility to call RegClose when finished with the registry, so + * that we can write back the registry if needed, unlock the server if + * needed, and free memory. + * + *---------------------------------------------------------------------- + */ + +static NameRegistry * +RegOpen( + Tcl_Interp *interp, /* Interpreter to use for error reporting + * (errors cause a panic so in fact no error + * is ever returned, but the interpreter is + * needed anyway). */ + TkDisplay *dispPtr, /* Display whose name registry is to be + * opened. */ + int lock) /* Non-zero means lock the window server when + * opening the registry, so no-one else can + * use the registry until we close it. */ +{ + NameRegistry *regPtr; + int result, actualFormat; + unsigned long bytesAfter; + Atom actualType; + char **propertyPtr; + Tk_ErrorHandler handler; + + if (dispPtr->commTkwin == NULL) { + SendInit(interp, dispPtr); + } + + handler = Tk_CreateErrorHandler(dispPtr->display, -1, -1, -1, NULL, NULL); + + regPtr = ckalloc(sizeof(NameRegistry)); + regPtr->dispPtr = dispPtr; + regPtr->locked = 0; + regPtr->modified = 0; + regPtr->allocedByX = 1; + propertyPtr = ®Ptr->property; + + if (lock && !localData.sendDebug) { + XGrabServer(dispPtr->display); + regPtr->locked = 1; + } + + /* + * Read the registry property. + */ + + result = XGetWindowProperty(dispPtr->display, + RootWindow(dispPtr->display, 0), + dispPtr->registryProperty, 0, MAX_PROP_WORDS, + False, XA_STRING, &actualType, &actualFormat, + ®Ptr->propLength, &bytesAfter, + (unsigned char **) propertyPtr); + + if (actualType == None) { + regPtr->propLength = 0; + regPtr->property = NULL; + } else if ((result != Success) || (actualFormat != 8) + || (actualType != XA_STRING)) { + /* + * The property is improperly formed; delete it. + */ + + if (regPtr->property != NULL) { + XFree(regPtr->property); + regPtr->propLength = 0; + regPtr->property = NULL; + } + XDeleteProperty(dispPtr->display, + RootWindow(dispPtr->display, 0), + dispPtr->registryProperty); + XSync(dispPtr->display, False); + } + + Tk_DeleteErrorHandler(handler); + + /* + * Xlib placed an extra null byte after the end of the property, just to + * make sure that it is always NULL-terminated. Be sure to include this + * byte in our count if it's needed to ensure null termination (note: as + * of 8/95 I'm no longer sure why this code is needed; seems like it + * shouldn't be). + */ + + if ((regPtr->propLength > 0) + && (regPtr->property[regPtr->propLength-1] != 0)) { + regPtr->propLength++; + } + return regPtr; +} + +/* + *---------------------------------------------------------------------- + * + * RegFindName -- + * + * Given an open name registry, this function finds an entry with a given + * name, if there is one, and returns information about that entry. + * + * Results: + * The return value is the X identifier for the comm window for the + * application named "name", or None if there is no such entry in the + * registry. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static Window +RegFindName( + NameRegistry *regPtr, /* Pointer to a registry opened with a + * previous call to RegOpen. */ + const char *name) /* Name of an application. */ +{ + char *p; + + for (p=regPtr->property ; p-regPtr->property<(int)regPtr->propLength ;) { + char *entry = p; + + while ((*p != 0) && (!isspace(UCHAR(*p)))) { + p++; + } + if ((*p != 0) && (strcmp(name, p+1) == 0)) { + unsigned id; + + if (sscanf(entry, "%x", &id) == 1) { + /* + * Must cast from an unsigned int to a Window in case we are + * on a 64-bit architecture. + */ + + return (Window) id; + } + } + while (*p != 0) { + p++; + } + p++; + } + return None; +} + +/* + *---------------------------------------------------------------------- + * + * RegDeleteName -- + * + * This function deletes the entry for a given name from an open + * registry. + * + * Results: + * None. + * + * Side effects: + * If there used to be an entry named "name" in the registry, then it is + * deleted and the registry is marked as modified so it will be written + * back when closed. + * + *---------------------------------------------------------------------- + */ + +static void +RegDeleteName( + NameRegistry *regPtr, /* Pointer to a registry opened with a + * previous call to RegOpen. */ + const char *name) /* Name of an application. */ +{ + char *p; + + for (p=regPtr->property ; p-regPtr->property<(int)regPtr->propLength ;) { + char *entry = p, *entryName; + + while ((*p != 0) && (!isspace(UCHAR(*p)))) { + p++; + } + if (*p != 0) { + p++; + } + entryName = p; + while (*p != 0) { + p++; + } + p++; + if (strcmp(name, entryName) == 0) { + int count; + + /* + * Found the matching entry. Copy everything after it down on top + * of it. + */ + + count = regPtr->propLength - (p - regPtr->property); + if (count > 0) { + char *src, *dst; + + for (src=p , dst=entry ; count>0 ; src++, dst++, count--) { + *dst = *src; + } + } + regPtr->propLength -= p - entry; + regPtr->modified = 1; + return; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * RegAddName -- + * + * Add a new entry to an open registry. + * + * Results: + * None. + * + * Side effects: + * The open registry is expanded; it is marked as modified so that it + * will be written back when closed. + * + *---------------------------------------------------------------------- + */ + +static void +RegAddName( + NameRegistry *regPtr, /* Pointer to a registry opened with a + * previous call to RegOpen. */ + const char *name, /* Name of an application. The caller must + * ensure that this name isn't already + * registered. */ + Window commWindow) /* X identifier for comm. window of + * application. */ +{ + char id[30], *newProp; + int idLength, newBytes; + + sprintf(id, "%x ", (unsigned) commWindow); + idLength = strlen(id); + newBytes = idLength + strlen(name) + 1; + newProp = ckalloc(regPtr->propLength + newBytes); + strcpy(newProp, id); + strcpy(newProp+idLength, name); + if (regPtr->property != NULL) { + memcpy(newProp + newBytes, regPtr->property, regPtr->propLength); + if (regPtr->allocedByX) { + XFree(regPtr->property); + } else { + ckfree(regPtr->property); + } + } + regPtr->modified = 1; + regPtr->propLength += newBytes; + regPtr->property = newProp; + regPtr->allocedByX = 0; +} + +/* + *---------------------------------------------------------------------- + * + * RegClose -- + * + * This function is called to end a series of operations on a name + * registry. + * + * Results: + * None. + * + * Side effects: + * The registry is written back if it has been modified, and the X server + * is unlocked if it was locked. Memory for the registry is freed, so the + * caller should never use regPtr again. + * + *---------------------------------------------------------------------- + */ + +static void +RegClose( + NameRegistry *regPtr) /* Pointer to a registry opened with a + * previous call to RegOpen. */ +{ + Tk_ErrorHandler handler; + + handler = Tk_CreateErrorHandler(regPtr->dispPtr->display, -1, -1, -1, + NULL, NULL); + + if (regPtr->modified) { + if (!regPtr->locked && !localData.sendDebug) { + Tcl_Panic("The name registry was modified without being locked!"); + } + XChangeProperty(regPtr->dispPtr->display, + RootWindow(regPtr->dispPtr->display, 0), + regPtr->dispPtr->registryProperty, XA_STRING, 8, + PropModeReplace, (unsigned char *) regPtr->property, + (int) regPtr->propLength); + } + + if (regPtr->locked) { + XUngrabServer(regPtr->dispPtr->display); + } + + /* + * After ungrabbing the server, it's important to flush the output + * immediately so that the server sees the ungrab command. Otherwise we + * might do something else that needs to communicate with the server (such + * as invoking a subprocess that needs to do I/O to the screen); if the + * ungrab command is still sitting in our output buffer, we could + * deadlock. + */ + + XFlush(regPtr->dispPtr->display); + + Tk_DeleteErrorHandler(handler); + + if (regPtr->property != NULL) { + if (regPtr->allocedByX) { + XFree(regPtr->property); + } else { + ckfree(regPtr->property); + } + } + ckfree(regPtr); +} + +/* + *---------------------------------------------------------------------- + * + * ValidateName -- + * + * This function checks to see if an entry in the registry is still + * valid. + * + * Results: + * The return value is 1 if the given commWindow exists and its name is + * "name". Otherwise 0 is returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +ValidateName( + TkDisplay *dispPtr, /* Display for which to perform the + * validation. */ + const char *name, /* The name of an application. */ + Window commWindow, /* X identifier for the application's comm. + * window. */ + int oldOK) /* Non-zero means that we should consider an + * application to be valid even if it looks + * like an old-style (pre-4.0) one; 0 means + * consider these invalid. */ +{ + int result, actualFormat, argc, i; + unsigned long length, bytesAfter; + Atom actualType; + char *property, **propertyPtr = &property; + Tk_ErrorHandler handler; + const char **argv; + + property = NULL; + + /* + * Ignore X errors when reading the property (e.g., the window might not + * exist). If an error occurs, result will be some value other than + * Success. + */ + + handler = Tk_CreateErrorHandler(dispPtr->display, -1, -1, -1, NULL, NULL); + result = XGetWindowProperty(dispPtr->display, commWindow, + dispPtr->appNameProperty, 0, MAX_PROP_WORDS, + False, XA_STRING, &actualType, &actualFormat, + &length, &bytesAfter, (unsigned char **) propertyPtr); + + if ((result == Success) && (actualType == None)) { + XWindowAttributes atts; + + /* + * The comm. window exists but the property we're looking for doesn't + * exist. This probably means that the application comes from an older + * version of Tk (< 4.0) that didn't set the property; if this is the + * case, then assume for compatibility's sake that everything's OK. + * However, it's also possible that some random application has + * re-used the window id for something totally unrelated. Check a few + * characteristics of the window, such as its dimensions and mapped + * state, to be sure that it still "smells" like a commWindow. + */ + + if (!oldOK + || !XGetWindowAttributes(dispPtr->display, commWindow, &atts) + || (atts.width != 1) || (atts.height != 1) + || (atts.map_state != IsUnmapped)) { + result = 0; + } else { + result = 1; + } + } else if ((result == Success) && (actualFormat == 8) + && (actualType == XA_STRING)) { + result = 0; + if (Tcl_SplitList(NULL, property, &argc, &argv) == TCL_OK) { + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], name) == 0) { + result = 1; + break; + } + } + ckfree(argv); + } + } else { + result = 0; + } + Tk_DeleteErrorHandler(handler); + if (property != NULL) { + XFree(property); + } + return result; +} + +/* + *---------------------------------------------------------------------- + * + * ServerSecure -- + * + * Check whether a server is secure enough for us to trust Tcl scripts + * arriving via that server. + * + * Results: + * The return value is 1 if the server is secure, which means that + * host-style authentication is turned on but there are no hosts in the + * enabled list. This means that some other form of authorization + * (presumably more secure, such as xauth) is in use. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +ServerSecure( + TkDisplay *dispPtr) /* Display to check. */ +{ +#ifdef TK_NO_SECURITY + return 1; +#else + XHostAddress *addrPtr; + int numHosts, secure; + Bool enabled; + + addrPtr = XListHosts(dispPtr->display, &numHosts, &enabled); + if (!enabled) { + insecure: + secure = 0; + } else if (numHosts == 0) { + secure = 1; + } else { + /* + * Recent versions of X11 have the extra feature of allowing more + * sophisticated authorization checks to be performed than the dozy + * old ones that used to plague xhost usage. However, not all deployed + * versions of Xlib know how to deal with this feature, so this code + * is conditional on having the right #def in place. [Bug 1909931] + * + * Note that at this point we know that there's at least one entry in + * the list returned by XListHosts. However there may be multiple + * entries; as long as each is one of either 'SI:localhost:*' or + * 'SI:localgroup:*' then we will claim to be secure enough. + */ + +#ifdef FamilyServerInterpreted + XServerInterpretedAddress *siPtr; + int i; + + for (i=0 ; i<numHosts ; i++) { + if (addrPtr[i].family != FamilyServerInterpreted) { + /* + * We don't understand what the X server is letting in, so we + * err on the side of safety. + */ + + goto insecure; + } + siPtr = (XServerInterpretedAddress *) addrPtr[0].address; + + /* + * We don't check the username or group here. This is because it's + * officially non-portable and we are just making sure there + * aren't silly misconfigurations. (Apparently 'root' is not a + * very good choice, but we still don't put any effort in to spot + * that.) However we do check to see that the constraints are + * imposed against the connecting user and/or group. + */ + + if ( !(siPtr->typelength == 9 /* ==strlen("localuser") */ + && !memcmp(siPtr->type, "localuser", 9)) + && !(siPtr->typelength == 10 /* ==strlen("localgroup") */ + && !memcmp(siPtr->type, "localgroup", 10))) { + /* + * The other defined types of server-interpreted controls + * involve particular hosts. These are still insecure for the + * same reasons that classic xhost access is insecure; there's + * just no way to be sure that the users on those systems are + * the ones who should be allowed to connect to this display. + */ + + goto insecure; + } + } + secure = 1; +#else + /* + * We don't understand what the X server is letting in, so we err on + * the side of safety. + */ + + secure = 0; +#endif /* FamilyServerInterpreted */ + } + if (addrPtr != NULL) { + XFree((char *) addrPtr); + } + return secure; +#endif /* TK_NO_SECURITY */ +} + +/* + *---------------------------------------------------------------------- + * + * Tk_SetAppName -- + * + * This function is called to associate an ASCII name with a Tk + * application. If the application has already been named, the name + * replaces the old one. + * + * Results: + * The return value is the name actually given to the application. This + * will normally be the same as name, but if name was already in use for + * an application then a name of the form "name #2" will be chosen, with + * a high enough number to make the name unique. + * + * Side effects: + * Registration info is saved, thereby allowing the "send" command to be + * used later to invoke commands in the application. In addition, the + * "send" command is created in the application's interpreter. The + * registration will be removed automatically if the interpreter is + * deleted or the "send" command is removed. + * + *---------------------------------------------------------------------- + */ + +const char * +Tk_SetAppName( + Tk_Window tkwin, /* Token for any window in the application to + * be named: it is just used to identify the + * application and the display. */ + const char *name) /* The name that will be used to refer to the + * interpreter in later "send" commands. Must + * be globally unique. */ +{ + RegisteredInterp *riPtr, *riPtr2; + Window w; + TkWindow *winPtr = (TkWindow *) tkwin; + TkDisplay *dispPtr = winPtr->dispPtr; + NameRegistry *regPtr; + Tcl_Interp *interp; + const char *actualName; + Tcl_DString dString; + int offset, i; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + interp = winPtr->mainPtr->interp; + if (dispPtr->commTkwin == NULL) { + SendInit(interp, winPtr->dispPtr); + } + + /* + * See if the application is already registered; if so, remove its current + * name from the registry. + */ + + regPtr = RegOpen(interp, winPtr->dispPtr, 1); + for (riPtr = tsdPtr->interpListPtr; ; riPtr = riPtr->nextPtr) { + if (riPtr == NULL) { + /* + * This interpreter isn't currently registered; create the data + * structure that will be used to register it locally, plus add + * the "send" command to the interpreter. + */ + + riPtr = ckalloc(sizeof(RegisteredInterp)); + riPtr->interp = interp; + riPtr->dispPtr = winPtr->dispPtr; + riPtr->nextPtr = tsdPtr->interpListPtr; + tsdPtr->interpListPtr = riPtr; + riPtr->name = NULL; + Tcl_CreateObjCommand(interp, "send", Tk_SendObjCmd, riPtr, DeleteProc); + if (Tcl_IsSafe(interp)) { + Tcl_HideCommand(interp, "send", "send"); + } + break; + } + if (riPtr->interp == interp) { + /* + * The interpreter is currently registered; remove it from the + * name registry. + */ + + if (riPtr->name) { + RegDeleteName(regPtr, riPtr->name); + ckfree(riPtr->name); + } + break; + } + } + + /* + * Pick a name to use for the application. Use "name" if it's not already + * in use. Otherwise add a suffix such as " #2", trying larger and larger + * numbers until we eventually find one that is unique. + */ + + actualName = name; + offset = 0; /* Needed only to avoid "used before + * set" compiler warnings. */ + for (i = 1; ; i++) { + if (i > 1) { + if (i == 2) { + Tcl_DStringInit(&dString); + Tcl_DStringAppend(&dString, name, -1); + Tcl_DStringAppend(&dString, " #", 2); + offset = Tcl_DStringLength(&dString); + Tcl_DStringSetLength(&dString, offset+TCL_INTEGER_SPACE); + actualName = Tcl_DStringValue(&dString); + } + sprintf(Tcl_DStringValue(&dString) + offset, "%d", i); + } + w = RegFindName(regPtr, actualName); + if (w == None) { + break; + } + + /* + * The name appears to be in use already, but double-check to be sure + * (perhaps the application died without removing its name from the + * registry?). + */ + + if (w == Tk_WindowId(dispPtr->commTkwin)) { + for (riPtr2 = tsdPtr->interpListPtr; riPtr2 != NULL; + riPtr2 = riPtr2->nextPtr) { + if ((riPtr2->interp != interp) && + (strcmp(riPtr2->name, actualName) == 0)) { + goto nextSuffix; + } + } + RegDeleteName(regPtr, actualName); + break; + } else if (!ValidateName(winPtr->dispPtr, actualName, w, 1)) { + RegDeleteName(regPtr, actualName); + break; + } + nextSuffix: + continue; + } + + /* + * We've now got a name to use. Store it in the name registry and in the + * local entry for this application, plus put it in a property on the + * commWindow. + */ + + RegAddName(regPtr, actualName, Tk_WindowId(dispPtr->commTkwin)); + RegClose(regPtr); + riPtr->name = ckalloc(strlen(actualName) + 1); + strcpy(riPtr->name, actualName); + if (actualName != name) { + Tcl_DStringFree(&dString); + } + UpdateCommWindow(dispPtr); + + return riPtr->name; +} + +/* + *-------------------------------------------------------------- + * + * Tk_SendObjCmd -- + * + * This function is invoked to process the "send" Tcl command. See the + * user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *-------------------------------------------------------------- + */ + +int +Tk_SendObjCmd( + ClientData clientData, /* Information about sender (only dispPtr + * field is used). */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ +{ + enum { + SEND_ASYNC, SEND_DISPLAYOF, SEND_LAST + }; + static const char *const sendOptions[] = { + "-async", "-displayof", "--", NULL + }; + TkWindow *winPtr; + Window commWindow; + PendingCommand pending; + register RegisteredInterp *riPtr; + const char *destName; + int result, index, async, i, firstArg; + Tk_RestrictProc *prevProc; + ClientData prevArg; + TkDisplay *dispPtr; + Tcl_Time timeout; + NameRegistry *regPtr; + Tcl_DString request; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tcl_Interp *localInterp; /* Used when the interpreter to send the + * command to is within the same process. */ + + /* + * Process options, if any. + */ + + async = 0; + winPtr = (TkWindow *) Tk_MainWindow(interp); + if (winPtr == NULL) { + return TCL_ERROR; + } + for (i = 1; i < objc; i++) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], sendOptions, + sizeof(char *), "option", 0, &index) != TCL_OK) { + break; + } + if (index == SEND_ASYNC) { + ++async; + } else if (index == SEND_DISPLAYOF) { + winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[++i]), + (Tk_Window) winPtr); + if (winPtr == NULL) { + return TCL_ERROR; + } + } else if (index == SEND_LAST) { + i++; + break; + } + } + + if (objc < (i+2)) { + Tcl_WrongNumArgs(interp, 1, objv, + "?-option value ...? interpName arg ?arg ...?"); + return TCL_ERROR; + } + destName = Tcl_GetString(objv[i]); + firstArg = i+1; + + dispPtr = winPtr->dispPtr; + if (dispPtr->commTkwin == NULL) { + SendInit(interp, winPtr->dispPtr); + } + + /* + * See if the target interpreter is local. If so, execute the command + * directly without going through the X server. The only tricky thing is + * passing the result from the target interpreter to the invoking + * interpreter. Watch out: they could be the same! + */ + + for (riPtr = tsdPtr->interpListPtr; riPtr != NULL; + riPtr = riPtr->nextPtr) { + if ((riPtr->dispPtr != dispPtr) + || (strcmp(riPtr->name, destName) != 0)) { + continue; + } + Tcl_Preserve(riPtr); + localInterp = riPtr->interp; + Tcl_Preserve(localInterp); + if (firstArg == (objc-1)) { + result = Tcl_EvalEx(localInterp, Tcl_GetString(objv[firstArg]), -1, TCL_EVAL_GLOBAL); + } else { + Tcl_DStringInit(&request); + Tcl_DStringAppend(&request, Tcl_GetString(objv[firstArg]), -1); + for (i = firstArg+1; i < objc; i++) { + Tcl_DStringAppend(&request, " ", 1); + Tcl_DStringAppend(&request, Tcl_GetString(objv[i]), -1); + } + result = Tcl_EvalEx(localInterp, Tcl_DStringValue(&request), -1, TCL_EVAL_GLOBAL); + Tcl_DStringFree(&request); + } + if (interp != localInterp) { + if (result == TCL_ERROR) { + Tcl_Obj *errorObjPtr; + + /* + * An error occurred, so transfer error information from the + * destination interpreter back to our interpreter. Must clear + * interp's result before calling Tcl_AddErrorInfo, since + * Tcl_AddErrorInfo will store the interp's result in + * errorInfo before appending riPtr's $errorInfo; we've + * already got everything we need in riPtr's $errorInfo. + */ + + Tcl_ResetResult(interp); + Tcl_AddErrorInfo(interp, Tcl_GetVar2(localInterp, + "errorInfo", NULL, TCL_GLOBAL_ONLY)); + errorObjPtr = Tcl_GetVar2Ex(localInterp, "errorCode", NULL, + TCL_GLOBAL_ONLY); + Tcl_SetObjErrorCode(interp, errorObjPtr); + } + Tcl_SetObjResult(interp, Tcl_GetObjResult(localInterp)); + Tcl_ResetResult(localInterp); + } + Tcl_Release(riPtr); + Tcl_Release(localInterp); + return result; + } + + /* + * Bind the interpreter name to a communication window. + */ + + regPtr = RegOpen(interp, winPtr->dispPtr, 0); + commWindow = RegFindName(regPtr, destName); + RegClose(regPtr); + if (commWindow == None) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "no application named \"%s\"", destName)); + Tcl_SetErrorCode(interp, "TK", "LOOKUP", "APPLICATION", destName, + NULL); + return TCL_ERROR; + } + + /* + * Send the command to the target interpreter by appending it to the comm + * window in the communication window. + */ + + localData.sendSerial++; + Tcl_DStringInit(&request); + Tcl_DStringAppend(&request, "\0c\0-n ", 6); + Tcl_DStringAppend(&request, destName, -1); + if (!async) { + char buffer[TCL_INTEGER_SPACE * 2]; + + sprintf(buffer, "%x %d", + (unsigned) Tk_WindowId(dispPtr->commTkwin), + localData.sendSerial); + Tcl_DStringAppend(&request, "\0-r ", 4); + Tcl_DStringAppend(&request, buffer, -1); + } + Tcl_DStringAppend(&request, "\0-s ", 4); + Tcl_DStringAppend(&request, Tcl_GetString(objv[firstArg]), -1); + for (i = firstArg+1; i < objc; i++) { + Tcl_DStringAppend(&request, " ", 1); + Tcl_DStringAppend(&request, Tcl_GetString(objv[i]), -1); + } + + if (!async) { + /* + * Register the fact that we're waiting for a command to complete + * (this is needed by SendEventProc and by AppendErrorProc to pass + * back the command's results). Set up a timeout handler so that + * we can check during long sends to make sure that the destination + * application is still alive. + * + * We prepare the pending struct here in order to catch potential + * early X errors from AppendPropCarefully() due to XSync(). + */ + + pending.serial = localData.sendSerial; + pending.dispPtr = dispPtr; + pending.target = destName; + pending.commWindow = commWindow; + pending.interp = interp; + pending.result = NULL; + pending.errorInfo = NULL; + pending.errorCode = NULL; + pending.gotResponse = 0; + pending.nextPtr = tsdPtr->pendingCommands; + tsdPtr->pendingCommands = &pending; + } + (void) AppendPropCarefully(dispPtr->display, commWindow, + dispPtr->commProperty, Tcl_DStringValue(&request), + Tcl_DStringLength(&request) + 1, (async ? NULL : &pending)); + Tcl_DStringFree(&request); + if (async) { + /* + * This is an asynchronous send: return immediately without waiting + * for a response. + */ + + return TCL_OK; + } + + /* + * Enter a loop processing X events until the result comes in or the + * target is declared to be dead. While waiting for a result, look only at + * send-related events so that the send is synchronous with respect to + * other events in the application. + */ + + prevProc = Tk_RestrictEvents(SendRestrictProc, NULL, &prevArg); + Tcl_GetTime(&timeout); + timeout.sec += 2; + while (!pending.gotResponse) { + if (!TkUnixDoOneXEvent(&timeout)) { + /* + * An unusually long amount of time has elapsed during the + * processing of a sent command. Check to make sure that the + * target application still exists. If it does, reset the timeout. + */ + + if (!ValidateName(pending.dispPtr, pending.target, + pending.commWindow, 0)) { + const char *msg; + + if (ValidateName(pending.dispPtr, pending.target, + pending.commWindow, 1)) { + msg = "target application died or uses a Tk version before 4.0"; + } else { + msg = "target application died"; + } + pending.code = TCL_ERROR; + pending.result = ckalloc(strlen(msg) + 1); + strcpy(pending.result, msg); + pending.gotResponse = 1; + } else { + Tcl_GetTime(&timeout); + timeout.sec += 2; + } + } + } + Tk_RestrictEvents(prevProc, prevArg, &prevArg); + + /* + * Unregister the information about the pending command and return the + * result. + */ + + if (tsdPtr->pendingCommands != &pending) { + Tcl_Panic("Tk_SendCmd: corrupted send stack"); + } + tsdPtr->pendingCommands = pending.nextPtr; + if (pending.errorInfo != NULL) { + /* + * Special trick: must clear the interp's result before calling + * Tcl_AddErrorInfo, since Tcl_AddErrorInfo will store the interp's + * result in errorInfo before appending pending.errorInfo; we've + * already got everything we need in pending.errorInfo. + */ + + Tcl_ResetResult(interp); + Tcl_AddErrorInfo(interp, pending.errorInfo); + ckfree(pending.errorInfo); + } + if (pending.errorCode != NULL) { + Tcl_SetObjErrorCode(interp, Tcl_NewStringObj(pending.errorCode, -1)); + ckfree(pending.errorCode); + } + Tcl_SetObjResult(interp, Tcl_NewStringObj(pending.result, -1)); + ckfree(pending.result); + return pending.code; +} + +/* + *---------------------------------------------------------------------- + * + * TkGetInterpNames -- + * + * This function is invoked to fetch a list of all the interpreter names + * currently registered for the display of a particular window. + * + * Results: + * A standard Tcl return value. The interp's result will be set to hold a + * list of all the interpreter names defined for tkwin's display. If an + * error occurs, then TCL_ERROR is returned and the interp's result will + * hold an error message. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkGetInterpNames( + Tcl_Interp *interp, /* Interpreter for returning a result. */ + Tk_Window tkwin) /* Window whose display is to be used for the + * lookup. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + NameRegistry *regPtr; + Tcl_Obj *resultObj = Tcl_NewObj(); + char *p; + + /* + * Read the registry property, then scan through all of its entries. + * Validate each entry to be sure that its application still exists. + */ + + regPtr = RegOpen(interp, winPtr->dispPtr, 1); + for (p=regPtr->property ; p-regPtr->property<(int)regPtr->propLength ;) { + char *entry = p, *entryName; + Window commWindow; + unsigned id; + + if (sscanf(p, "%x", (unsigned *) &id) != 1) { + commWindow = None; + } else { + commWindow = id; + } + while ((*p != 0) && (!isspace(UCHAR(*p)))) { + p++; + } + if (*p != 0) { + p++; + } + entryName = p; + while (*p != 0) { + p++; + } + p++; + if (ValidateName(winPtr->dispPtr, entryName, commWindow, 1)) { + /* + * The application still exists; add its name to the result. + */ + + Tcl_ListObjAppendElement(NULL, resultObj, + Tcl_NewStringObj(entryName, -1)); + } else { + int count; + + /* + * This name is bogus (perhaps the application died without + * cleaning up its entry in the registry?). Delete the name. + */ + + count = regPtr->propLength - (p - regPtr->property); + if (count > 0) { + char *src, *dst; + + for (src = p, dst = entry; count > 0; src++, dst++, count--) { + *dst = *src; + } + } + regPtr->propLength -= p - entry; + regPtr->modified = 1; + p = entry; + } + } + RegClose(regPtr); + Tcl_SetObjResult(interp, resultObj); + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * TkSendCleanup -- + * + * This function is called to free resources used by the communication + * channels for sending commands and receiving results. + * + * Results: + * None. + * + * Side effects: + * Frees various data structures and windows. + * + *-------------------------------------------------------------- + */ + +void +TkSendCleanup( + TkDisplay *dispPtr) +{ + if (dispPtr->commTkwin != NULL) { + Tk_DeleteEventHandler(dispPtr->commTkwin, PropertyChangeMask, + SendEventProc, dispPtr); + Tk_DestroyWindow(dispPtr->commTkwin); + Tcl_Release(dispPtr->commTkwin); + dispPtr->commTkwin = NULL; + } +} + +/* + *-------------------------------------------------------------- + * + * SendInit -- + * + * This function is called to initialize the communication channels for + * sending commands and receiving results. + * + * Results: + * None. + * + * Side effects: + * Sets up various data structures and windows. + * + *-------------------------------------------------------------- + */ + +static int +SendInit( + Tcl_Interp *interp, /* Interpreter to use for error reporting (no + * errors are ever returned, but the + * interpreter is needed anyway). */ + TkDisplay *dispPtr) /* Display to initialize. */ +{ + XSetWindowAttributes atts; + + /* + * Create the window used for communication, and set up an event handler + * for it. + */ + + dispPtr->commTkwin = (Tk_Window) TkAllocWindow(dispPtr, + DefaultScreen(dispPtr->display), NULL); + Tcl_Preserve(dispPtr->commTkwin); + ((TkWindow *) dispPtr->commTkwin)->flags |= + TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED; + TkWmNewWindow((TkWindow *) dispPtr->commTkwin); + atts.override_redirect = True; + Tk_ChangeWindowAttributes(dispPtr->commTkwin, + CWOverrideRedirect, &atts); + Tk_CreateEventHandler(dispPtr->commTkwin, PropertyChangeMask, + SendEventProc, dispPtr); + Tk_MakeWindowExist(dispPtr->commTkwin); + + /* + * Get atoms used as property names. + */ + + dispPtr->commProperty = Tk_InternAtom(dispPtr->commTkwin, "Comm"); + dispPtr->registryProperty = Tk_InternAtom(dispPtr->commTkwin, + "InterpRegistry"); + dispPtr->appNameProperty = Tk_InternAtom(dispPtr->commTkwin, + "TK_APPLICATION"); + + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * SendEventProc -- + * + * This function is invoked automatically by the toolkit event manager + * when a property changes on the communication window. This function + * reads the property and handles command requests and responses. + * + * Results: + * None. + * + * Side effects: + * If there are command requests in the property, they are executed. If + * there are responses in the property, their information is saved for + * the (ostensibly waiting) "send" commands. The property is deleted. + * + *-------------------------------------------------------------- + */ + +static void +SendEventProc( + ClientData clientData, /* Display information. */ + XEvent *eventPtr) /* Information about event. */ +{ + TkDisplay *dispPtr = clientData; + char *propInfo, **propInfoPtr = &propInfo; + const char *p; + int result, actualFormat; + unsigned long numItems, bytesAfter; + Atom actualType; + Tcl_Interp *remoteInterp; /* Interp in which to execute the command. */ + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if ((eventPtr->xproperty.atom != dispPtr->commProperty) + || (eventPtr->xproperty.state != PropertyNewValue)) { + return; + } + + /* + * Read the comm property and delete it. + */ + + propInfo = NULL; + result = XGetWindowProperty(dispPtr->display, + Tk_WindowId(dispPtr->commTkwin), dispPtr->commProperty, 0, + MAX_PROP_WORDS, True, XA_STRING, &actualType, &actualFormat, + &numItems, &bytesAfter, (unsigned char **) propInfoPtr); + + /* + * If the property doesn't exist or is improperly formed then ignore it. + */ + + if ((result != Success) || (actualType != XA_STRING) + || (actualFormat != 8)) { + if (propInfo != NULL) { + XFree(propInfo); + } + return; + } + + /* + * Several commands and results could arrive in the property at one time; + * each iteration through the outer loop handles a single command or + * result. + */ + + for (p = propInfo; (p-propInfo) < (int) numItems; ) { + /* + * Ignore leading NULLs; each command or result starts with a NULL so + * that no matter how badly formed a preceding command is, we'll be + * able to tell that a new command/result is starting. + */ + + if (*p == 0) { + p++; + continue; + } + + if ((*p == 'c') && (p[1] == 0)) { + Window commWindow; + const char *interpName, *script, *serial; + char *end; + Tcl_DString reply; + RegisteredInterp *riPtr; + + /* + *---------------------------------------------------------- + * This is an incoming command from some other application. + * Iterate over all of its options. Stop when we reach the end of + * the property or something that doesn't look like an option. + *---------------------------------------------------------- + */ + + p += 2; + interpName = NULL; + commWindow = None; + serial = ""; + script = NULL; + while (((p-propInfo) < (int) numItems) && (*p == '-')) { + switch (p[1]) { + case 'r': + commWindow = (Window) strtoul(p+2, &end, 16); + if ((end == p+2) || (*end != ' ')) { + commWindow = None; + } else { + p = serial = end+1; + } + break; + case 'n': + if (p[2] == ' ') { + interpName = p+3; + } + break; + case 's': + if (p[2] == ' ') { + script = p+3; + } + break; + } + while (*p != 0) { + p++; + } + p++; + } + + if ((script == NULL) || (interpName == NULL)) { + continue; + } + + /* + * Initialize the result property, so that we're ready at any time + * if we need to return an error. + */ + + if (commWindow != None) { + Tcl_DStringInit(&reply); + Tcl_DStringAppend(&reply, "\0r\0-s ", 6); + Tcl_DStringAppend(&reply, serial, -1); + Tcl_DStringAppend(&reply, "\0-r ", 4); + } + + if (!ServerSecure(dispPtr)) { + if (commWindow != None) { + Tcl_DStringAppend(&reply, + "X server insecure (must use xauth-style " + "authorization); command ignored", -1); + } + result = TCL_ERROR; + goto returnResult; + } + + /* + * Locate the application, then execute the script. + */ + + for (riPtr = tsdPtr->interpListPtr; ; riPtr = riPtr->nextPtr) { + if (riPtr == NULL) { + if (commWindow != None) { + Tcl_DStringAppend(&reply, + "receiver never heard of interpreter \"", -1); + Tcl_DStringAppend(&reply, interpName, -1); + Tcl_DStringAppend(&reply, "\"", 1); + } + result = TCL_ERROR; + goto returnResult; + } + if (strcmp(riPtr->name, interpName) == 0) { + break; + } + } + Tcl_Preserve(riPtr); + + /* + * We must protect the interpreter because the script may enter + * another event loop, which might call Tcl_DeleteInterp. + */ + + remoteInterp = riPtr->interp; + Tcl_Preserve(remoteInterp); + + result = Tcl_EvalEx(remoteInterp, script, -1, TCL_EVAL_GLOBAL); + + /* + * The call to Tcl_Release may have released the interpreter which + * will cause the "send" command for that interpreter to be + * deleted. The command deletion callback will set the + * riPtr->interp field to NULL, hence the check below for NULL. + */ + + if (commWindow != None) { + Tcl_DStringAppend(&reply, Tcl_GetString(Tcl_GetObjResult(remoteInterp)), + -1); + if (result == TCL_ERROR) { + const char *varValue; + + varValue = Tcl_GetVar2(remoteInterp, "errorInfo", + NULL, TCL_GLOBAL_ONLY); + if (varValue != NULL) { + Tcl_DStringAppend(&reply, "\0-i ", 4); + Tcl_DStringAppend(&reply, varValue, -1); + } + varValue = Tcl_GetVar2(remoteInterp, "errorCode", + NULL, TCL_GLOBAL_ONLY); + if (varValue != NULL) { + Tcl_DStringAppend(&reply, "\0-e ", 4); + Tcl_DStringAppend(&reply, varValue, -1); + } + } + } + Tcl_Release(remoteInterp); + Tcl_Release(riPtr); + + /* + * Return the result to the sender if a commWindow was specified + * (if none was specified then this is an asynchronous call). + * Right now reply has everything but the completion code, but it + * needs the NULL to terminate the current option. + */ + + returnResult: + if (commWindow != None) { + if (result != TCL_OK) { + char buffer[TCL_INTEGER_SPACE]; + + sprintf(buffer, "%d", result); + Tcl_DStringAppend(&reply, "\0-c ", 4); + Tcl_DStringAppend(&reply, buffer, -1); + } + (void) AppendPropCarefully(dispPtr->display, commWindow, + dispPtr->commProperty, Tcl_DStringValue(&reply), + Tcl_DStringLength(&reply) + 1, NULL); + XFlush(dispPtr->display); + Tcl_DStringFree(&reply); + } + } else if ((*p == 'r') && (p[1] == 0)) { + int serial, code, gotSerial; + const char *errorInfo, *errorCode, *resultString; + PendingCommand *pcPtr; + + /* + *---------------------------------------------------------- + * This is a reply to some command that we sent out. Iterate over + * all of its options. Stop when we reach the end of the property + * or something that doesn't look like an option. + *---------------------------------------------------------- + */ + + p += 2; + code = TCL_OK; + gotSerial = 0; + errorInfo = NULL; + errorCode = NULL; + resultString = ""; + while (((p-propInfo) < (int) numItems) && (*p == '-')) { + switch (p[1]) { + case 'c': + if (sscanf(p+2, " %d", &code) != 1) { + code = TCL_OK; + } + break; + case 'e': + if (p[2] == ' ') { + errorCode = p+3; + } + break; + case 'i': + if (p[2] == ' ') { + errorInfo = p+3; + } + break; + case 'r': + if (p[2] == ' ') { + resultString = p+3; + } + break; + case 's': + if (sscanf(p+2, " %d", &serial) == 1) { + gotSerial = 1; + } + break; + } + while (*p != 0) { + p++; + } + p++; + } + + if (!gotSerial) { + continue; + } + + /* + * Give the result information to anyone who's waiting for it. + */ + + for (pcPtr = tsdPtr->pendingCommands; pcPtr != NULL; + pcPtr = pcPtr->nextPtr) { + if ((serial != pcPtr->serial) || (pcPtr->result != NULL)) { + continue; + } + pcPtr->code = code; + if (resultString != NULL) { + pcPtr->result = ckalloc(strlen(resultString) + 1); + strcpy(pcPtr->result, resultString); + } + if (code == TCL_ERROR) { + if (errorInfo != NULL) { + pcPtr->errorInfo = ckalloc(strlen(errorInfo) + 1); + strcpy(pcPtr->errorInfo, errorInfo); + } + if (errorCode != NULL) { + pcPtr->errorCode = ckalloc(strlen(errorCode) + 1); + strcpy(pcPtr->errorCode, errorCode); + } + } + pcPtr->gotResponse = 1; + break; + } + } else { + /* + * Didn't recognize this thing. Just skip through the next null + * character and try again. + */ + + while (*p != 0) { + p++; + } + p++; + } + } + XFree(propInfo); +} + +/* + *-------------------------------------------------------------- + * + * AppendPropCarefully -- + * + * Append a given property to a given window, but set up an X error + * handler so that if the append fails this function can return an error + * code rather than having Xlib panic. + * + * Results: + * None. + * + * Side effects: + * The given property on the given window is appended to. If this + * operation fails and if pendingPtr is non-NULL, then the pending + * operation is marked as complete with an error. + * + *-------------------------------------------------------------- + */ + +static void +AppendPropCarefully( + Display *display, /* Display on which to operate. */ + Window window, /* Window whose property is to be modified. */ + Atom property, /* Name of property. */ + char *value, /* Characters to append to property. */ + int length, /* Number of bytes to append. */ + PendingCommand *pendingPtr) /* Pending command to mark complete if an + * error occurs during the property op. NULL + * means just ignore the error. */ +{ + Tk_ErrorHandler handler; + + handler = Tk_CreateErrorHandler(display, -1, -1, -1, AppendErrorProc, + pendingPtr); + XChangeProperty(display, window, property, XA_STRING, 8, + PropModeAppend, (unsigned char *) value, length); + Tk_DeleteErrorHandler(handler); +} + +/* + * The function below is invoked if an error occurs during the XChangeProperty + * operation above. + */ + + /* ARGSUSED */ +static int +AppendErrorProc( + ClientData clientData, /* Command to mark complete, or NULL. */ + XErrorEvent *errorPtr) /* Information about error. */ +{ + PendingCommand *pendingPtr = clientData; + register PendingCommand *pcPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (pendingPtr == NULL) { + return 0; + } + + /* + * Make sure this command is still pending. + */ + + for (pcPtr = tsdPtr->pendingCommands; pcPtr != NULL; + pcPtr = pcPtr->nextPtr) { + if ((pcPtr == pendingPtr) && (pcPtr->result == NULL)) { + pcPtr->result = ckalloc(strlen(pcPtr->target) + 50); + sprintf(pcPtr->result, "no application named \"%s\"", + pcPtr->target); + pcPtr->code = TCL_ERROR; + pcPtr->gotResponse = 1; + break; + } + } + return 0; +} + +/* + *-------------------------------------------------------------- + * + * DeleteProc -- + * + * This function is invoked by Tcl when the "send" command is deleted in + * an interpreter. It unregisters the interpreter. + * + * Results: + * None. + * + * Side effects: + * The interpreter given by riPtr is unregistered. + * + *-------------------------------------------------------------- + */ + +static void +DeleteProc( + ClientData clientData) /* Info about registration, passed as + * ClientData. */ +{ + RegisteredInterp *riPtr = clientData; + register RegisteredInterp *riPtr2; + NameRegistry *regPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + regPtr = RegOpen(riPtr->interp, riPtr->dispPtr, 1); + RegDeleteName(regPtr, riPtr->name); + RegClose(regPtr); + + if (tsdPtr->interpListPtr == riPtr) { + tsdPtr->interpListPtr = riPtr->nextPtr; + } else { + for (riPtr2 = tsdPtr->interpListPtr; riPtr2 != NULL; + riPtr2 = riPtr2->nextPtr) { + if (riPtr2->nextPtr == riPtr) { + riPtr2->nextPtr = riPtr->nextPtr; + break; + } + } + } + ckfree(riPtr->name); + riPtr->interp = NULL; + UpdateCommWindow(riPtr->dispPtr); + Tcl_EventuallyFree(riPtr, TCL_DYNAMIC); +} + +/* + *---------------------------------------------------------------------- + * + * SendRestrictProc -- + * + * This function filters incoming events when a "send" command is + * outstanding. It defers all events except those containing send + * commands and results. + * + * Results: + * False is returned except for property-change events on a commWindow. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +static Tk_RestrictAction +SendRestrictProc( + ClientData clientData, /* Not used. */ + register XEvent *eventPtr) /* Event that just arrived. */ +{ + TkDisplay *dispPtr; + + if (eventPtr->type != PropertyNotify) { + return TK_DEFER_EVENT; + } + for (dispPtr = TkGetDisplayList(); dispPtr != NULL; + dispPtr = dispPtr->nextPtr) { + if ((eventPtr->xany.display == dispPtr->display) + && (eventPtr->xproperty.window + == Tk_WindowId(dispPtr->commTkwin))) { + return TK_PROCESS_EVENT; + } + } + return TK_DEFER_EVENT; +} + +/* + *---------------------------------------------------------------------- + * + * UpdateCommWindow -- + * + * This function updates the list of application names stored on our + * commWindow. It is typically called when interpreters are registered + * and unregistered. + * + * Results: + * None. + * + * Side effects: + * The TK_APPLICATION property on the comm window is updated. + * + *---------------------------------------------------------------------- + */ + +static void +UpdateCommWindow( + TkDisplay *dispPtr) /* Display whose commWindow is to be + * updated. */ +{ + Tcl_DString names; + RegisteredInterp *riPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + Tcl_DStringInit(&names); + for (riPtr = tsdPtr->interpListPtr; riPtr != NULL; + riPtr = riPtr->nextPtr) { + Tcl_DStringAppendElement(&names, riPtr->name); + } + XChangeProperty(dispPtr->display, Tk_WindowId(dispPtr->commTkwin), + dispPtr->appNameProperty, XA_STRING, 8, PropModeReplace, + (unsigned char *) Tcl_DStringValue(&names), + Tcl_DStringLength(&names)); + Tcl_DStringFree(&names); +} + +/* + *---------------------------------------------------------------------- + * + * TkpTestsendCmd -- + * + * This function implements the "testsend" command. It provides a set of + * functions for testing the "send" command and support function in + * tkSend.c. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * Depends on option; see below. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +TkpTestsendCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ +{ + enum { + TESTSEND_BOGUS, TESTSEND_PROP, TESTSEND_SERIAL + }; + static const char *const testsendOptions[] = { + "bogus", "prop", "serial", NULL + }; + TkWindow *winPtr = clientData; + Tk_ErrorHandler handler; + int index; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, + "option ?arg ...?"); + return TCL_ERROR; + } + + if (Tcl_GetIndexFromObjStruct(interp, objv[1], testsendOptions, + sizeof(char *), "option", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == TESTSEND_BOGUS) { + handler = Tk_CreateErrorHandler(winPtr->dispPtr->display, -1, -1, -1, + NULL, NULL); + XChangeProperty(winPtr->dispPtr->display, + RootWindow(winPtr->dispPtr->display, 0), + winPtr->dispPtr->registryProperty, XA_INTEGER, 32, + PropModeReplace, + (unsigned char *) "This is bogus information", 6); + Tk_DeleteErrorHandler(handler); + } else if (index == TESTSEND_PROP) { + int result, actualFormat; + unsigned long length, bytesAfter; + Atom actualType, propName; + char *property, **propertyPtr = &property, *p, *end; + Window w; + + if ((objc != 4) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 1, objv, + "prop window name ?value ?"); + return TCL_ERROR; + } + if (strcmp(Tcl_GetString(objv[2]), "root") == 0) { + w = RootWindow(winPtr->dispPtr->display, 0); + } else if (strcmp(Tcl_GetString(objv[2]), "comm") == 0) { + w = Tk_WindowId(winPtr->dispPtr->commTkwin); + } else { + w = strtoul(Tcl_GetString(objv[2]), &end, 0); + } + propName = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3])); + if (objc == 4) { + property = NULL; + result = XGetWindowProperty(winPtr->dispPtr->display, w, propName, + 0, 100000, False, XA_STRING, &actualType, &actualFormat, + &length, &bytesAfter, (unsigned char **) propertyPtr); + if ((result == Success) && (actualType != None) + && (actualFormat == 8) && (actualType == XA_STRING)) { + for (p = property; (unsigned long)(p-property) < length; p++) { + if (*p == 0) { + *p = '\n'; + } + } + Tcl_SetObjResult(interp, Tcl_NewStringObj(property, -1)); + } + if (property != NULL) { + XFree(property); + } + } else if (Tcl_GetString(objv[4])[0] == 0) { + handler = Tk_CreateErrorHandler(winPtr->dispPtr->display, + -1, -1, -1, NULL, NULL); + XDeleteProperty(winPtr->dispPtr->display, w, propName); + Tk_DeleteErrorHandler(handler); + } else { + Tcl_DString tmp; + + Tcl_DStringInit(&tmp); + for (p = Tcl_DStringAppend(&tmp, Tcl_GetString(objv[4]), + (int) strlen(Tcl_GetString(objv[4]))); *p != 0; p++) { + if (*p == '\n') { + *p = 0; + } + } + handler = Tk_CreateErrorHandler(winPtr->dispPtr->display, + -1, -1, -1, NULL, NULL); + XChangeProperty(winPtr->dispPtr->display, w, propName, XA_STRING, + 8, PropModeReplace, (unsigned char*)Tcl_DStringValue(&tmp), + p-Tcl_DStringValue(&tmp)); + Tk_DeleteErrorHandler(handler); + Tcl_DStringFree(&tmp); + } + } else if (index == TESTSEND_SERIAL) { + Tcl_SetObjResult(interp, Tcl_NewIntObj(localData.sendSerial+1)); + } + return TCL_OK; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixWm.c b/tk8.6/unix/tkUnixWm.c new file mode 100644 index 0000000..19ac86c --- /dev/null +++ b/tk8.6/unix/tkUnixWm.c @@ -0,0 +1,7421 @@ +/* + * tkUnixWm.c -- + * + * This module takes care of the interactions between a Tk-based + * application and the window manager. Among other things, it implements + * the "wm" command and passes geometry information to the window + * manager. + * + * Copyright (c) 1991-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tkUnixInt.h" + +/* + * A data structure of the following type holds information for each window + * manager protocol (such as WM_DELETE_WINDOW) for which a handler (i.e. a Tcl + * command) has been defined for a particular top-level window. + */ + +typedef struct ProtocolHandler { + Atom protocol; /* Identifies the protocol. */ + struct ProtocolHandler *nextPtr; + /* Next in list of protocol handlers for the + * same top-level window, or NULL for end of + * list. */ + Tcl_Interp *interp; /* Interpreter in which to invoke command. */ + char command[1]; /* Tcl command to invoke when a client message + * for this protocol arrives. The actual size + * of the structure varies to accommodate the + * needs of the actual command. THIS MUST BE + * THE LAST FIELD OF THE STRUCTURE. */ +} ProtocolHandler; + +#define HANDLER_SIZE(cmdLength) \ + ((unsigned) ((Tk_Offset(ProtocolHandler, command) + 1) + cmdLength)) + +/* + * Data for [wm attributes] command: + */ + +typedef struct { + double alpha; /* Transparency; 0.0=transparent, 1.0=opaque */ + int topmost; /* Flag: true=>stay-on-top */ + int zoomed; /* Flag: true=>maximized */ + int fullscreen; /* Flag: true=>fullscreen */ +} WmAttributes; + +typedef enum { + WMATT_ALPHA, WMATT_TOPMOST, WMATT_ZOOMED, WMATT_FULLSCREEN, + WMATT_TYPE, _WMATT_LAST_ATTRIBUTE +} WmAttribute; + +static const char *const WmAttributeNames[] = { + "-alpha", "-topmost", "-zoomed", "-fullscreen", + "-type", NULL +}; + +/* + * A data structure of the following type holds window-manager-related + * information for each top-level window in an application. + */ + +typedef struct TkWmInfo { + TkWindow *winPtr; /* Pointer to main Tk information for this + * window. */ + Window reparent; /* If the window has been reparented, this + * gives the ID of the ancestor of the window + * that is a child of the root window (may not + * be window's immediate parent). If the + * window isn't reparented, this has the value + * None. */ + char *title; /* Title to display in window caption. If + * NULL, use name of widget. Malloced. */ + char *iconName; /* Name to display in icon. Malloced. */ + XWMHints hints; /* Various pieces of information for window + * manager. */ + char *leaderName; /* Path name of leader of window group + * (corresponds to hints.window_group). + * Malloc-ed. Note: this field doesn't get + * updated if leader is destroyed. */ + TkWindow *masterPtr; /* Master window for TRANSIENT_FOR property, + * or NULL. */ + Tk_Window icon; /* Window to use as icon for this window, or + * NULL. */ + Tk_Window iconFor; /* Window for which this window is icon, or + * NULL if this isn't an icon for anyone. */ + int withdrawn; /* Non-zero means window has been withdrawn. */ + + /* + * In order to support menubars transparently under X, each toplevel + * window is encased in an additional window, called the wrapper, that + * holds the toplevel and the menubar, if any. The information below is + * used to keep track of the wrapper and the menubar. + */ + + TkWindow *wrapperPtr; /* Pointer to information about the wrapper. + * This is the "real" toplevel window as seen + * by the window manager. Although this is an + * official Tk window, it doesn't appear in + * the application's window hierarchy. NULL + * means that the wrapper hasn't been created + * yet. */ + Tk_Window menubar; /* Pointer to information about the menubar, + * or NULL if there is no menubar for this + * toplevel. */ + int menuHeight; /* Amount of vertical space needed for + * menubar, measured in pixels. If menubar is + * non-NULL, this is >= 1 (X servers don't + * like dimensions of 0). */ + + /* + * Information used to construct an XSizeHints structure for the window + * manager: + */ + + int sizeHintsFlags; /* Flags word for XSizeHints structure. If the + * PBaseSize flag is set then the window is + * gridded; otherwise it isn't gridded. */ + int minWidth, minHeight; /* Minimum dimensions of window, in pixels or + * grid units. */ + int maxWidth, maxHeight; /* Maximum dimensions of window, in pixels or + * grid units. 0 to default.*/ + Tk_Window gridWin; /* Identifies the window that controls + * gridding for this top-level, or NULL if the + * top-level isn't currently gridded. */ + int widthInc, heightInc; /* Increments for size changes (# pixels per + * step). */ + struct { + int x; /* numerator */ + int y; /* denominator */ + } minAspect, maxAspect; /* Min/max aspect ratios for window. */ + int reqGridWidth, reqGridHeight; + /* The dimensions of the window (in grid + * units) requested through the geometry + * manager. */ + int gravity; /* Desired window gravity. */ + + /* + * Information used to manage the size and location of a window. + */ + + int width, height; /* Desired dimensions of window, specified in + * pixels or grid units. These values are set + * by the "wm geometry" command and by + * ConfigureNotify events (for when wm resizes + * window). -1 means user hasn't requested + * dimensions. */ + int x, y; /* Desired X and Y coordinates for window. + * These values are set by "wm geometry", plus + * by ConfigureNotify events (when wm moves + * window). These numbers are different than + * the numbers stored in winPtr->changes + * because (a) they could be measured from the + * right or bottom edge of the screen (see + * WM_NEGATIVE_X and WM_NEGATIVE_Y flags) and + * (b) if the window has been reparented then + * they refer to the parent rather than the + * window itself. */ + int parentWidth, parentHeight; + /* Width and height of reparent, in pixels + * *including border*. If window hasn't been + * reparented then these will be the outer + * dimensions of the window, including + * border. */ + int xInParent, yInParent; /* Offset of wrapperPtr within reparent, + * measured in pixels from upper-left outer + * corner of reparent's border to upper-left + * outer corner of wrapperPtr's border. If not + * reparented then these are zero. */ + int configWidth, configHeight; + /* Dimensions passed to last request that we + * issued to change geometry of the wrapper. + * Used to eliminate redundant resize + * operations. */ + + /* + * Information about the virtual root window for this top-level, if there + * is one. + */ + + Window vRoot; /* Virtual root window for this top-level, or + * None if there is no virtual root window + * (i.e. just use the screen's root). */ + int vRootX, vRootY; /* Position of the virtual root inside the + * root window. If the WM_VROOT_OFFSET_STALE + * flag is set then this information may be + * incorrect and needs to be refreshed from + * the X server. If vRoot is None then these + * values are both 0. */ + int vRootWidth, vRootHeight;/* Dimensions of the virtual root window. If + * vRoot is None, gives the dimensions of the + * containing screen. This information is + * never stale, even though vRootX and vRootY + * can be. */ + + /* + * Miscellaneous information. + */ + + WmAttributes attributes; /* Current state of [wm attributes] */ + WmAttributes reqState; /* Requested state of [wm attributes] */ + ProtocolHandler *protPtr; /* First in list of protocol handlers for this + * window (NULL means none). */ + int cmdArgc; /* Number of elements in cmdArgv below. */ + const char **cmdArgv; /* Array of strings to store in the WM_COMMAND + * property. NULL means nothing available. */ + 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 */ + int iconDataSize; /* size of iconphoto image data */ + unsigned char *iconDataPtr; /* iconphoto image data, if set */ + struct TkWmInfo *nextPtr; /* Next in list of all top-level windows. */ +} WmInfo; + +/* + * Flag values for WmInfo structures: + * + * WM_NEVER_MAPPED - non-zero means window has never been mapped; + * need to update all info when window is first + * mapped. + * WM_UPDATE_PENDING - non-zero means a call to UpdateGeometryInfo + * has already been scheduled for this window; + * no need to schedule another one. + * WM_NEGATIVE_X - non-zero means x-coordinate is measured in + * pixels from right edge of screen, rather than + * from left edge. + * WM_NEGATIVE_Y - non-zero means y-coordinate is measured in + * 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. + * WM_SYNC_PENDING - set to non-zero while waiting for the window + * manager to respond to some state change. + * WM_VROOT_OFFSET_STALE - non-zero means that (x,y) offset information + * about the virtual root window is stale and + * needs to be fetched fresh from the X server. + * WM_ABOUT_TO_MAP - non-zero means that the window is about to be + * mapped by TkWmMapWindow. This is used by + * UpdateGeometryInfo to modify its behavior. + * WM_MOVE_PENDING - non-zero means the application has requested a + * new position for the window, but it hasn't + * been reflected through the window manager yet. + * WM_COLORMAPS_EXPLICIT - non-zero means the colormap windows were set + * explicitly via "wm colormapwindows". + * WM_ADDED_TOPLEVEL_COLORMAP - non-zero means that when "wm colormapwindows" + * was called the top-level itself wasn't + * specified, so we added it implicitly at the + * end of the list. + * WM_WIDTH_NOT_RESIZABLE - non-zero means that we're not supposed to + * allow the user to change the width of the + * window (controlled by "wm resizable" command). + * WM_HEIGHT_NOT_RESIZABLE - non-zero means that we're not supposed to + * allow the user to change the height of the + * window (controlled by "wm resizable" command). + * WM_WITHDRAWN - non-zero means that this window has explicitly + * been withdrawn. If it's a transient, it should + * not mirror state changes in the master. + */ + +#define WM_NEVER_MAPPED 1 +#define WM_UPDATE_PENDING 2 +#define WM_NEGATIVE_X 4 +#define WM_NEGATIVE_Y 8 +#define WM_UPDATE_SIZE_HINTS 0x10 +#define WM_SYNC_PENDING 0x20 +#define WM_VROOT_OFFSET_STALE 0x40 +#define WM_ABOUT_TO_MAP 0x100 +#define WM_MOVE_PENDING 0x200 +#define WM_COLORMAPS_EXPLICIT 0x400 +#define WM_ADDED_TOPLEVEL_COLORMAP 0x800 +#define WM_WIDTH_NOT_RESIZABLE 0x1000 +#define WM_HEIGHT_NOT_RESIZABLE 0x2000 +#define WM_WITHDRAWN 0x4000 + +/* + * Wrapper for XGetWindowProperty and XChangeProperty to make them a *bit* + * less verbose. + */ + +#define GetWindowProperty(wrapperPtr, atom, length, type, typePtr, formatPtr, numItemsPtr, bytesAfterPtr, itemsPtr) \ + (XGetWindowProperty((wrapperPtr)->display, (wrapperPtr)->window, \ + (atom), 0, (long) (length), False, (type), \ + (typePtr), (formatPtr), (numItemsPtr), (bytesAfterPtr), \ + (unsigned char **) (itemsPtr)) == Success) +#define SetWindowProperty(wrapperPtr, atomName, type, width, data, length) \ + XChangeProperty((wrapperPtr)->display, (wrapperPtr)->window, \ + Tk_InternAtom((Tk_Window) wrapperPtr, (atomName)), \ + (type), (width), PropModeReplace, (unsigned char *) (data), \ + (int) (length)) + +/* + * This module keeps a list of all top-level windows, primarily to simplify + * the job of Tk_CoordsToWindow. The list is called firstWmPtr and is stored + * in the TkDisplay structure. + */ + +/* + * The following structures are the official type records for geometry + * management of top-level and menubar windows. + */ + +static void TopLevelReqProc(ClientData dummy, Tk_Window tkwin); +static void RemapWindows(TkWindow *winPtr, TkWindow *parentPtr); +static void MenubarReqProc(ClientData clientData, + Tk_Window tkwin); + +static const Tk_GeomMgr wmMgrType = { + "wm", /* name */ + TopLevelReqProc, /* requestProc */ + NULL, /* lostSlaveProc */ +}; +static const Tk_GeomMgr menubarMgrType = { + "menubar", /* name */ + MenubarReqProc, /* requestProc */ + NULL, /* lostSlaveProc */ +}; + +/* + * Structures of the following type are used for communication between + * WaitForEvent, WaitRestrictProc, and WaitTimeoutProc. + */ + +typedef struct WaitRestrictInfo { + Display *display; /* Window belongs to this display. */ + WmInfo *wmInfoPtr; + int type; /* We only care about this type of event. */ + XEvent *eventPtr; /* Where to store the event when it's found. */ + int foundEvent; /* Non-zero means that an event of the desired + * type has been found. */ +} WaitRestrictInfo; + +/* + * Forward declarations for functions defined in this file: + */ + +static int ComputeReparentGeometry(WmInfo *wmPtr); +static void ConfigureEvent(WmInfo *wmPtr, + XConfigureEvent *eventPtr); +static void CreateWrapper(WmInfo *wmPtr); +static void GetMaxSize(WmInfo *wmPtr, int *maxWidthPtr, + int *maxHeightPtr); +static void MenubarDestroyProc(ClientData clientData, + XEvent *eventPtr); +static int ParseGeometry(Tcl_Interp *interp, const char *string, + TkWindow *winPtr); +static void ReparentEvent(WmInfo *wmPtr, XReparentEvent *eventPtr); +static void PropertyEvent(WmInfo *wmPtr, XPropertyEvent *eventPtr); +static void TkWmStackorderToplevelWrapperMap(TkWindow *winPtr, + Display *display, Tcl_HashTable *reparentTable); +static void TopLevelReqProc(ClientData dummy, Tk_Window tkwin); +static void RemapWindows(TkWindow *winPtr, TkWindow *parentPtr); +static void UpdateCommand(TkWindow *winPtr); +static void UpdateGeometryInfo(ClientData clientData); +static void UpdateHints(TkWindow *winPtr); +static void UpdateSizeHints(TkWindow *winPtr, + int newWidth, int newHeight); +static void UpdateTitle(TkWindow *winPtr); +static void UpdatePhotoIcon(TkWindow *winPtr); +static void UpdateVRootGeometry(WmInfo *wmPtr); +static void UpdateWmProtocols(WmInfo *wmPtr); +static int SetNetWmType(TkWindow *winPtr, Tcl_Obj *typePtr); +static Tcl_Obj * GetNetWmType(TkWindow *winPtr); +static void SetNetWmState(TkWindow*, const char *atomName, int on); +static void CheckNetWmState(WmInfo *, Atom *atoms, int numAtoms); +static void UpdateNetWmState(WmInfo *); +static void WaitForConfigureNotify(TkWindow *winPtr, + unsigned long serial); +static int WaitForEvent(Display *display, + WmInfo *wmInfoPtr, int type, XEvent *eventPtr); +static void WaitForMapNotify(TkWindow *winPtr, int mapped); +static Tk_RestrictProc WaitRestrictProc; +static void WrapperEventProc(ClientData clientData, + XEvent *eventPtr); +static void WmWaitMapProc(ClientData clientData, + XEvent *eventPtr); +static int WmAspectCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmAttributesCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmClientCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmColormapwindowsCmd(Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmCommandCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmDeiconifyCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmFocusmodelCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmForgetCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmFrameCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmGeometryCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmGridCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmGroupCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmIconbitmapCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmIconifyCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmIconmaskCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmIconnameCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmIconphotoCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmIconpositionCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmIconwindowCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmManageCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmMaxsizeCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmMinsizeCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmOverrideredirectCmd(Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmPositionfromCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmProtocolCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmResizableCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmSizefromCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmStackorderCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmStateCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmTitleCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmTransientCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmWithdrawCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static void WmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr); + +/* + *-------------------------------------------------------------- + * + * TkWmCleanup -- + * + * This function is invoked to cleanup remaining wm resources associated + * with a display. + * + * Results: + * None. + * + * Side effects: + * All WmInfo structure resources are freed and invalidated. + * + *-------------------------------------------------------------- + */ + +void TkWmCleanup( + TkDisplay *dispPtr) +{ + WmInfo *wmPtr, *nextPtr; + + for (wmPtr = dispPtr->firstWmPtr; wmPtr != NULL; wmPtr = nextPtr) { + /* + * We can't assume we have access to winPtr's anymore, so some cleanup + * requiring winPtr data is avoided. + */ + + nextPtr = wmPtr->nextPtr; + if (wmPtr->title != NULL) { + ckfree(wmPtr->title); + } + if (wmPtr->iconName != NULL) { + ckfree(wmPtr->iconName); + } + if (wmPtr->iconDataPtr != NULL) { + ckfree(wmPtr->iconDataPtr); + } + if (wmPtr->leaderName != NULL) { + ckfree(wmPtr->leaderName); + } + if (wmPtr->menubar != NULL) { + Tk_DestroyWindow(wmPtr->menubar); + } + if (wmPtr->wrapperPtr != NULL) { + Tk_DestroyWindow((Tk_Window) wmPtr->wrapperPtr); + } + while (wmPtr->protPtr != NULL) { + ProtocolHandler *protPtr = wmPtr->protPtr; + + wmPtr->protPtr = protPtr->nextPtr; + Tcl_EventuallyFree(protPtr, TCL_DYNAMIC); + } + if (wmPtr->cmdArgv != NULL) { + ckfree(wmPtr->cmdArgv); + } + if (wmPtr->clientMachine != NULL) { + ckfree(wmPtr->clientMachine); + } + ckfree(wmPtr); + } + if (dispPtr->iconDataPtr != NULL) { + ckfree(dispPtr->iconDataPtr); + dispPtr->iconDataPtr = NULL; + } +} + +/* + *-------------------------------------------------------------- + * + * TkWmNewWindow -- + * + * This function is invoked whenever a new top-level window is created. + * Its job is to initialize the WmInfo structure for the window. + * + * Results: + * None. + * + * Side effects: + * A WmInfo structure gets allocated and initialized. + * + *-------------------------------------------------------------- + */ + +void +TkWmNewWindow( + TkWindow *winPtr) /* Newly-created top-level window. */ +{ + register WmInfo *wmPtr; + TkDisplay *dispPtr = winPtr->dispPtr; + + wmPtr = ckalloc(sizeof(WmInfo)); + memset(wmPtr, 0, sizeof(WmInfo)); + wmPtr->winPtr = winPtr; + wmPtr->reparent = None; + wmPtr->masterPtr = NULL; + wmPtr->numTransients = 0; + wmPtr->hints.flags = InputHint | StateHint; + wmPtr->hints.input = True; + wmPtr->hints.initial_state = NormalState; + wmPtr->hints.icon_pixmap = None; + wmPtr->hints.icon_window = None; + wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0; + wmPtr->hints.icon_mask = None; + wmPtr->hints.window_group = None; + + /* + * Initialize attributes. + */ + + wmPtr->attributes.alpha = 1.0; + wmPtr->attributes.topmost = 0; + wmPtr->attributes.zoomed = 0; + wmPtr->attributes.fullscreen = 0; + wmPtr->reqState = wmPtr->attributes; + + /* + * Default the maximum dimensions to the size of the display, minus a + * guess about how space is needed for window manager decorations. + */ + + wmPtr->gridWin = NULL; + wmPtr->minWidth = wmPtr->minHeight = 1; + wmPtr->maxWidth = wmPtr->maxHeight = 0; + wmPtr->widthInc = wmPtr->heightInc = 1; + wmPtr->minAspect.x = wmPtr->minAspect.y = 1; + wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1; + wmPtr->reqGridWidth = wmPtr->reqGridHeight = -1; + wmPtr->gravity = NorthWestGravity; + wmPtr->width = -1; + wmPtr->height = -1; + wmPtr->x = winPtr->changes.x; + wmPtr->y = winPtr->changes.y; + wmPtr->parentWidth = winPtr->changes.width + + 2*winPtr->changes.border_width; + wmPtr->parentHeight = winPtr->changes.height + + 2*winPtr->changes.border_width; + wmPtr->configWidth = -1; + wmPtr->configHeight = -1; + wmPtr->vRoot = None; + wmPtr->flags = WM_NEVER_MAPPED; + wmPtr->nextPtr = (WmInfo *) dispPtr->firstWmPtr; + dispPtr->firstWmPtr = wmPtr; + winPtr->wmInfoPtr = wmPtr; + + UpdateVRootGeometry(wmPtr); + + /* + * Arrange for geometry requests to be reflected from the window to the + * window manager. + */ + + Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, NULL); +} + +/* + *-------------------------------------------------------------- + * + * TkWmMapWindow -- + * + * This function is invoked to map a top-level window. This module gets a + * chance to update all window-manager-related information in properties + * before the window manager sees the map event and checks the + * properties. It also gets to decide whether or not to even map the + * window after all. + * + * Results: + * None. + * + * Side effects: + * Properties of winPtr may get updated to provide up-to-date information + * to the window manager. The window may also get mapped, but it may not + * be if this function decides that isn't appropriate (e.g. because the + * window is withdrawn). + * + *-------------------------------------------------------------- + */ + +void +TkWmMapWindow( + TkWindow *winPtr) /* Top-level window that's about to be + * mapped. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + XTextProperty textProp; + + if (wmPtr->flags & WM_NEVER_MAPPED) { + Tcl_DString ds; + + wmPtr->flags &= ~WM_NEVER_MAPPED; + + /* + * This is the first time this window has ever been mapped. First + * create the wrapper window that provides space for a menubar. + */ + + if (wmPtr->wrapperPtr == NULL) { + CreateWrapper(wmPtr); + } + + /* + * Store all the window-manager-related information for the window. + */ + + TkWmSetClass(winPtr); + UpdateTitle(winPtr); + UpdatePhotoIcon(winPtr); + + if (wmPtr->masterPtr != NULL) { + /* + * Don't map a transient if the master is not mapped. + */ + + if (!Tk_IsMapped(wmPtr->masterPtr)) { + wmPtr->withdrawn = 1; + wmPtr->hints.initial_state = WithdrawnState; + } + + /* + * Make sure that we actually set the transient-for property, even + * if we are withdrawn. [Bug 1163496] + */ + + XSetTransientForHint(winPtr->display, wmPtr->wrapperPtr->window, + wmPtr->masterPtr->wmInfoPtr->wrapperPtr->window); + } + + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + UpdateHints(winPtr); + UpdateWmProtocols(wmPtr); + if (wmPtr->cmdArgv != NULL) { + UpdateCommand(winPtr); + } + if (wmPtr->clientMachine != NULL) { + Tcl_UtfToExternalDString(NULL, wmPtr->clientMachine, -1, &ds); + if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1, + &textProp) != 0) { + unsigned long pid = (unsigned long) getpid(); + + XSetWMClientMachine(winPtr->display, + wmPtr->wrapperPtr->window, &textProp); + XFree((char *) textProp.value); + + /* + * Inform the server (and more particularly any session + * manager) what our process ID is. We only do this when the + * CLIENT_MACHINE property is set since the spec for + * _NET_WM_PID requires that to be set too. + */ + + SetWindowProperty(wmPtr->wrapperPtr, "_NET_WM_PID", + XA_CARDINAL, 32, &pid, 1); + } + Tcl_DStringFree(&ds); + } + } + if (wmPtr->hints.initial_state == WithdrawnState) { + return; + } + if (wmPtr->iconFor != NULL) { + /* + * This window is an icon for somebody else. Make sure that the + * geometry is up-to-date, then return without mapping the window. + */ + + if (wmPtr->flags & WM_UPDATE_PENDING) { + Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr); + } + UpdateGeometryInfo(winPtr); + return; + } + wmPtr->flags |= WM_ABOUT_TO_MAP; + if (wmPtr->flags & WM_UPDATE_PENDING) { + Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr); + } + UpdateGeometryInfo(winPtr); + wmPtr->flags &= ~WM_ABOUT_TO_MAP; + + /* + * Update _NET_WM_STATE hints: + */ + UpdateNetWmState(wmPtr); + + /* + * Map the window, then wait to be sure that the window manager has + * processed the map operation. + */ + + XMapWindow(winPtr->display, wmPtr->wrapperPtr->window); + if (wmPtr->hints.initial_state == NormalState) { + WaitForMapNotify(winPtr, 1); + } +} + +/* + *-------------------------------------------------------------- + * + * TkWmUnmapWindow -- + * + * This function is invoked to unmap a top-level window. The only thing + * it does special is to wait for the window actually to be unmapped. + * + * Results: + * None. + * + * Side effects: + * Unmaps the window. + * + *-------------------------------------------------------------- + */ + +void +TkWmUnmapWindow( + TkWindow *winPtr) /* Top-level window that's about to be + * mapped. */ +{ + /* + * It seems to be important to wait after unmapping a top-level window + * until the window really gets unmapped. I don't completely understand + * all the interactions with the window manager, but if we go on without + * waiting, and if the window is then mapped again quickly, events seem to + * get lost so that we think the window isn't mapped when in fact it is + * mapped. I suspect that this has something to do with the window manager + * filtering Map events (and possily not filtering Unmap events?). + */ + + XUnmapWindow(winPtr->display, winPtr->wmInfoPtr->wrapperPtr->window); + WaitForMapNotify(winPtr, 0); +} + +/* + *-------------------------------------------------------------- + * + * TkWmDeadWindow -- + * + * This function is invoked when a top-level window is about to be + * deleted. It cleans up the wm-related data structures for the window. + * + * Results: + * None. + * + * Side effects: + * The WmInfo structure for winPtr gets freed up. + * + *-------------------------------------------------------------- + */ + +void +TkWmDeadWindow( + TkWindow *winPtr) /* Top-level window that's being deleted. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + WmInfo *wmPtr2; + + if (wmPtr == NULL) { + return; + } + if ((WmInfo *) winPtr->dispPtr->firstWmPtr == wmPtr) { + winPtr->dispPtr->firstWmPtr = wmPtr->nextPtr; + } else { + register WmInfo *prevPtr; + + for (prevPtr = (WmInfo *) winPtr->dispPtr->firstWmPtr; ; + prevPtr = prevPtr->nextPtr) { + /* ASSERT: prevPtr != NULL [Bug 1789819] */ + if (prevPtr->nextPtr == wmPtr) { + prevPtr->nextPtr = wmPtr->nextPtr; + break; + } + } + } + if (wmPtr->title != NULL) { + ckfree(wmPtr->title); + } + if (wmPtr->iconName != NULL) { + ckfree(wmPtr->iconName); + } + if (wmPtr->iconDataPtr != NULL) { + ckfree(wmPtr->iconDataPtr); + } + if (wmPtr->hints.flags & IconPixmapHint) { + Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap); + } + if (wmPtr->hints.flags & IconMaskHint) { + Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask); + } + if (wmPtr->leaderName != NULL) { + ckfree(wmPtr->leaderName); + } + if (wmPtr->icon != NULL) { + wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; + wmPtr2->iconFor = NULL; + wmPtr2->withdrawn = 1; + } + if (wmPtr->iconFor != NULL) { + wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr; + wmPtr2->icon = NULL; + wmPtr2->hints.flags &= ~IconWindowHint; + UpdateHints((TkWindow *) wmPtr->iconFor); + } + if (wmPtr->menubar != NULL) { + Tk_DestroyWindow(wmPtr->menubar); + } + if (wmPtr->wrapperPtr != NULL) { + /* + * The rest of Tk doesn't know that we reparent the toplevel inside + * the wrapper, so reparent it back out again before deleting the + * wrapper; otherwise the toplevel will get deleted twice (once + * implicitly by the deletion of the wrapper). + */ + + XUnmapWindow(winPtr->display, winPtr->window); + XReparentWindow(winPtr->display, winPtr->window, + XRootWindow(winPtr->display, winPtr->screenNum), 0, 0); + Tk_DestroyWindow((Tk_Window) wmPtr->wrapperPtr); + } + while (wmPtr->protPtr != NULL) { + ProtocolHandler *protPtr = wmPtr->protPtr; + + wmPtr->protPtr = protPtr->nextPtr; + Tcl_EventuallyFree(protPtr, TCL_DYNAMIC); + } + if (wmPtr->cmdArgv != NULL) { + ckfree(wmPtr->cmdArgv); + } + if (wmPtr->clientMachine != NULL) { + ckfree(wmPtr->clientMachine); + } + if (wmPtr->flags & WM_UPDATE_PENDING) { + Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr); + } + + /* + * Reset all transient windows whose master is the dead window. + */ + + for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL; + wmPtr2 = wmPtr2->nextPtr) { + if (wmPtr2->masterPtr == winPtr) { + wmPtr->numTransients--; + Tk_DeleteEventHandler((Tk_Window) wmPtr2->masterPtr, + StructureNotifyMask, WmWaitMapProc, wmPtr2->winPtr); + wmPtr2->masterPtr = NULL; + if (!(wmPtr2->flags & WM_NEVER_MAPPED)) { + XDeleteProperty(winPtr->display, wmPtr2->wrapperPtr->window, + Tk_InternAtom((Tk_Window) winPtr, "WM_TRANSIENT_FOR")); + + /* + * FIXME: Need a call like Win32's UpdateWrapper() so we can + * recreate the wrapper and get rid of the transient window + * decorations. + */ + } + } + } + /* ASSERT: numTransients == 0 [Bug 1789819] */ + + 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, + StructureNotifyMask, WmWaitMapProc, winPtr); + wmPtr->masterPtr = NULL; + } + ckfree(wmPtr); + winPtr->wmInfoPtr = NULL; +} + +/* + *-------------------------------------------------------------- + * + * TkWmSetClass -- + * + * This function is invoked whenever a top-level window's class is + * changed. If the window has been mapped then this function updates the + * window manager property for the class. If the window hasn't been + * mapped, the update is deferred until just before the first mapping. + * + * Results: + * None. + * + * Side effects: + * A window property may get updated. + * + *-------------------------------------------------------------- + */ + +void +TkWmSetClass( + TkWindow *winPtr) /* Newly-created top-level window. */ +{ + if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) { + return; + } + + if (winPtr->classUid != NULL) { + XClassHint *classPtr; + Tcl_DString name, class; + + Tcl_UtfToExternalDString(NULL, winPtr->nameUid, -1, &name); + Tcl_UtfToExternalDString(NULL, winPtr->classUid, -1, &class); + classPtr = XAllocClassHint(); + classPtr->res_name = Tcl_DStringValue(&name); + classPtr->res_class = Tcl_DStringValue(&class); + XSetClassHint(winPtr->display, winPtr->wmInfoPtr->wrapperPtr->window, + classPtr); + XFree((char *) classPtr); + Tcl_DStringFree(&name); + Tcl_DStringFree(&class); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_WmObjCmd -- + * + * This function is invoked to process the "wm" Tcl command. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +Tk_WmObjCmd( + 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 = clientData; + static const char *const optionStrings[] = { + "aspect", "attributes", "client", "colormapwindows", + "command", "deiconify", "focusmodel", "forget", + "frame", "geometry", "grid", "group", "iconbitmap", + "iconify", "iconmask", "iconname", "iconphoto", + "iconposition", "iconwindow", "manage", "maxsize", + "minsize", "overrideredirect", "positionfrom", + "protocol", "resizable", "sizefrom", "stackorder", + "state", "title", "transient", "withdraw", NULL }; + enum options { + WMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS, + WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FORGET, + WMOPT_FRAME, WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, + WMOPT_ICONBITMAP, + WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME, WMOPT_ICONPHOTO, + WMOPT_ICONPOSITION, WMOPT_ICONWINDOW, WMOPT_MANAGE, WMOPT_MAXSIZE, + WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, WMOPT_POSITIONFROM, + WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM, WMOPT_STACKORDER, + WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT, WMOPT_WITHDRAW }; + int index, length; + const char *argv1; + TkWindow *winPtr; + Tk_Window targetWin; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; + + if (objc < 2) { + wrongNumArgs: + Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?"); + return TCL_ERROR; + } + + argv1 = Tcl_GetStringFromObj(objv[1], &length); + if ((argv1[0] == 't') && (strncmp(argv1, "tracing", (size_t) length) == 0) + && (length >= 3)) { + int wmTracing; + + if ((objc != 2) && (objc != 3)) { + Tcl_WrongNumArgs(interp, 2, objv, "?boolean?"); + return TCL_ERROR; + } + if (objc == 2) { + Tcl_SetObjResult(interp, Tcl_NewBooleanObj( + dispPtr->flags & TK_DISPLAY_WM_TRACING)); + return TCL_OK; + } + if (Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing) != TCL_OK) { + return TCL_ERROR; + } + if (wmTracing) { + dispPtr->flags |= TK_DISPLAY_WM_TRACING; + } else { + dispPtr->flags &= ~TK_DISPLAY_WM_TRACING; + } + return TCL_OK; + } + + if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + + if (objc < 3) { + goto wrongNumArgs; + } + + if (TkGetWindowFromObj(interp, tkwin, objv[2], &targetWin) != TCL_OK) { + return TCL_ERROR; + } + winPtr = (TkWindow *) targetWin; + if (!Tk_IsTopLevel(winPtr) && + (index != WMOPT_MANAGE) && (index != WMOPT_FORGET)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "window \"%s\" isn't a top-level window", winPtr->pathName)); + Tcl_SetErrorCode(interp, "TK", "LOOKUP", "TOPLEVEL", winPtr->pathName, + NULL); + return TCL_ERROR; + } + + switch ((enum options) index) { + case WMOPT_ASPECT: + return WmAspectCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ATTRIBUTES: + return WmAttributesCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_CLIENT: + return WmClientCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_COLORMAPWINDOWS: + return WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_COMMAND: + return WmCommandCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_DEICONIFY: + return WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_FOCUSMODEL: + return WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_FORGET: + return WmForgetCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_FRAME: + return WmFrameCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_GEOMETRY: + return WmGeometryCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_GRID: + return WmGridCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_GROUP: + return WmGroupCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONBITMAP: + return WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONIFY: + return WmIconifyCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONMASK: + return WmIconmaskCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONNAME: + return WmIconnameCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONPHOTO: + return WmIconphotoCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONPOSITION: + return WmIconpositionCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONWINDOW: + return WmIconwindowCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_MANAGE: + return WmManageCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_MAXSIZE: + return WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_MINSIZE: + return WmMinsizeCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_OVERRIDEREDIRECT: + return WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_POSITIONFROM: + return WmPositionfromCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_PROTOCOL: + return WmProtocolCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_RESIZABLE: + return WmResizableCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_SIZEFROM: + return WmSizefromCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_STACKORDER: + return WmStackorderCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_STATE: + return WmStateCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_TITLE: + return WmTitleCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_TRANSIENT: + return WmTransientCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_WITHDRAW: + return WmWithdrawCmd(tkwin, winPtr, interp, objc, objv); + } + + /* This should not happen */ + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * WmAspectCmd -- + * + * This function is invoked to process the "wm aspect" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmAspectCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int numer1, denom1, numer2, denom2; + + if ((objc != 3) && (objc != 7)) { + Tcl_WrongNumArgs(interp, 2, objv, + "window ?minNumer minDenom maxNumer maxDenom?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->sizeHintsFlags & PAspect) { + Tcl_Obj *results[4]; + + results[0] = Tcl_NewIntObj(wmPtr->minAspect.x); + results[1] = Tcl_NewIntObj(wmPtr->minAspect.y); + results[2] = Tcl_NewIntObj(wmPtr->maxAspect.x); + results[3] = Tcl_NewIntObj(wmPtr->maxAspect.y); + Tcl_SetObjResult(interp, Tcl_NewListObj(4, results)); + } + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->sizeHintsFlags &= ~PAspect; + } else { + if ((Tcl_GetIntFromObj(interp, objv[3], &numer1) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &denom1) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[5], &numer2) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[6], &denom2) != TCL_OK)) { + return TCL_ERROR; + } + if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) || + (denom2 <= 0)) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "aspect number can't be <= 0", -1)); + Tcl_SetErrorCode(interp, "TK", "VALUE", "ASPECT", NULL); + return TCL_ERROR; + } + wmPtr->minAspect.x = numer1; + wmPtr->minAspect.y = denom1; + wmPtr->maxAspect.x = numer2; + wmPtr->maxAspect.y = denom2; + wmPtr->sizeHintsFlags |= PAspect; + } + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmSetAttribute -- + * + * Helper routine for WmAttributesCmd. Sets the value of the specified + * attribute. + * + * Returns: + * + * TCL_OK if successful, TCL_ERROR otherwise. In case of an error, leaves + * a message in the interpreter's result. + * + *---------------------------------------------------------------------- + */ + +static int +WmSetAttribute( + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter */ + WmAttribute attribute, /* Code of attribute to set */ + Tcl_Obj *value) /* New value */ +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + + switch (attribute) { + case WMATT_ALPHA: { + unsigned long opacity; /* 0=transparent, 0xFFFFFFFF=opaque */ + + if (TCL_OK != Tcl_GetDoubleFromObj(interp, value, + &wmPtr->reqState.alpha)) { + return TCL_ERROR; + } + if (wmPtr->reqState.alpha < 0.0) { + wmPtr->reqState.alpha = 0.0; + } + if (wmPtr->reqState.alpha > 1.0) { + wmPtr->reqState.alpha = 1.0; + } + + if (!wmPtr->wrapperPtr) { + break; + } + + opacity = 0xFFFFFFFFul * wmPtr->reqState.alpha; + SetWindowProperty(wmPtr->wrapperPtr, "_NET_WM_WINDOW_OPACITY", + XA_CARDINAL, 32, &opacity, 1L); + wmPtr->attributes.alpha = wmPtr->reqState.alpha; + + break; + } + case WMATT_TOPMOST: + if (Tcl_GetBooleanFromObj(interp, value, + &wmPtr->reqState.topmost) != TCL_OK) { + return TCL_ERROR; + } + SetNetWmState(winPtr, "_NET_WM_STATE_ABOVE", wmPtr->reqState.topmost); + break; + case WMATT_TYPE: + if (TCL_OK != SetNetWmType(winPtr, value)) + return TCL_ERROR; + break; + case WMATT_ZOOMED: + if (Tcl_GetBooleanFromObj(interp, value, + &wmPtr->reqState.zoomed) != TCL_OK) { + return TCL_ERROR; + } + SetNetWmState(winPtr, "_NET_WM_STATE_MAXIMIZED_VERT", + wmPtr->reqState.zoomed); + SetNetWmState(winPtr, "_NET_WM_STATE_MAXIMIZED_HORZ", + wmPtr->reqState.zoomed); + break; + case WMATT_FULLSCREEN: + if (Tcl_GetBooleanFromObj(interp, value, + &wmPtr->reqState.fullscreen) != TCL_OK) { + return TCL_ERROR; + } + SetNetWmState(winPtr, "_NET_WM_STATE_FULLSCREEN", + wmPtr->reqState.fullscreen); + break; + case _WMATT_LAST_ATTRIBUTE: /* NOTREACHED */ + return TCL_ERROR; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmGetAttribute -- + * + * Helper routine for WmAttributesCmd. Returns the current value of the + * specified attribute. + * + * See also: CheckNetWmState(). + * + *---------------------------------------------------------------------- + */ + +static Tcl_Obj * +WmGetAttribute( + TkWindow *winPtr, /* Toplevel to work with */ + WmAttribute attribute) /* Code of attribute to get */ +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + + switch (attribute) { + case WMATT_ALPHA: + return Tcl_NewDoubleObj(wmPtr->attributes.alpha); + case WMATT_TOPMOST: + return Tcl_NewBooleanObj(wmPtr->attributes.topmost); + case WMATT_ZOOMED: + return Tcl_NewBooleanObj(wmPtr->attributes.zoomed); + case WMATT_FULLSCREEN: + return Tcl_NewBooleanObj(wmPtr->attributes.fullscreen); + case WMATT_TYPE: + return GetNetWmType(winPtr); + case _WMATT_LAST_ATTRIBUTE: /*NOTREACHED*/ + break; + } + /*NOTREACHED*/ + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * WmAttributesCmd -- + * + * This function is invoked to process the "wm attributes" Tcl command. + * + * Syntax: + * + * wm attributes $win ?-attribute ?value attribute value...?? + * + * Notes: + * + * Attributes of mapped windows are set by sending a _NET_WM_STATE + * ClientMessage to the root window (see SetNetWmState). For withdrawn + * windows, we keep track of the requested attribute state, and set the + * _NET_WM_STATE property ourselves immediately prior to mapping the + * window. + * + * See also: TIP#231, EWMH. + * + *---------------------------------------------------------------------- + */ + +static int +WmAttributesCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + int attribute = 0; + + if (objc == 3) { /* wm attributes $win */ + Tcl_Obj *result = Tcl_NewListObj(0,0); + + for (attribute = 0; attribute < _WMATT_LAST_ATTRIBUTE; ++attribute) { + Tcl_ListObjAppendElement(interp, result, + Tcl_NewStringObj(WmAttributeNames[attribute], -1)); + Tcl_ListObjAppendElement(interp, result, + WmGetAttribute(winPtr, attribute)); + } + Tcl_SetObjResult(interp, result); + return TCL_OK; + } else if (objc == 4) { /* wm attributes $win -attribute */ + if (Tcl_GetIndexFromObjStruct(interp, objv[3], WmAttributeNames, + sizeof(char *), "attribute", 0, &attribute) != TCL_OK) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, WmGetAttribute(winPtr, attribute)); + return TCL_OK; + } else if ((objc - 3) % 2 == 0) { /* wm attributes $win -att value... */ + int i; + + for (i = 3; i < objc; i += 2) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], WmAttributeNames, + sizeof(char *), "attribute", 0, &attribute) != TCL_OK) { + return TCL_ERROR; + } + if (WmSetAttribute(winPtr,interp,attribute,objv[i+1]) != TCL_OK) { + return TCL_ERROR; + } + } + return TCL_OK; + } + + Tcl_WrongNumArgs(interp, 2, objv, "window ?-attribute ?value ...??"); + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * WmClientCmd -- + * + * This function is invoked to process the "wm client" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmClientCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + const char *argv3; + int length; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?name?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->clientMachine != NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj(wmPtr->clientMachine, -1)); + } + return TCL_OK; + } + argv3 = Tcl_GetStringFromObj(objv[3], &length); + if (argv3[0] == 0) { + if (wmPtr->clientMachine != NULL) { + ckfree(wmPtr->clientMachine); + wmPtr->clientMachine = NULL; + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window, + Tk_InternAtom((Tk_Window) winPtr, + "WM_CLIENT_MACHINE")); + } + } + return TCL_OK; + } + if (wmPtr->clientMachine != NULL) { + ckfree(wmPtr->clientMachine); + } + wmPtr->clientMachine = ckalloc(length + 1); + strcpy(wmPtr->clientMachine, argv3); + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + XTextProperty textProp; + Tcl_DString ds; + + Tcl_UtfToExternalDString(NULL, wmPtr->clientMachine, -1, &ds); + if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1, + &textProp) != 0) { + unsigned long pid = (unsigned long) getpid(); + + XSetWMClientMachine(winPtr->display, wmPtr->wrapperPtr->window, + &textProp); + XFree((char *) textProp.value); + + /* + * Inform the server (and more particularly any session manager) + * what our process ID is. We only do this when the CLIENT_MACHINE + * property is set since the spec for _NET_WM_PID requires that to + * be set too. + */ + + SetWindowProperty(wmPtr->wrapperPtr, "_NET_WM_PID", XA_CARDINAL, + 32, &pid, 1); + } + Tcl_DStringFree(&ds); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmColormapwindowsCmd -- + * + * This function is invoked to process the "wm colormapwindows" Tcl + * command. See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmColormapwindowsCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Window *cmapList; + TkWindow *winPtr2; + int count, i, windowObjc, gotToplevel; + Tcl_Obj **windowObjv, *resultObj; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?windowList?"); + return TCL_ERROR; + } + Tk_MakeWindowExist((Tk_Window) winPtr); + if (wmPtr->wrapperPtr == NULL) { + CreateWrapper(wmPtr); + } + if (objc == 3) { + if (XGetWMColormapWindows(winPtr->display, + wmPtr->wrapperPtr->window, &cmapList, &count) == 0) { + return TCL_OK; + } + resultObj = Tcl_NewObj(); + for (i = 0; i < count; i++) { + if ((i == (count-1)) + && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) { + break; + } + winPtr2 = (TkWindow *) + Tk_IdToWindow(winPtr->display, cmapList[i]); + if (winPtr2 == NULL) { + Tcl_ListObjAppendElement(NULL, resultObj, + Tcl_ObjPrintf("0x%lx", cmapList[i])); + } else { + Tcl_ListObjAppendElement(NULL, resultObj, + Tcl_NewStringObj(winPtr2->pathName, -1)); + } + } + XFree((char *) cmapList); + Tcl_SetObjResult(interp, resultObj); + return TCL_OK; + } + if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv) + != TCL_OK) { + return TCL_ERROR; + } + cmapList = ckalloc((windowObjc+1) * sizeof(Window)); + gotToplevel = 0; + for (i = 0; i < windowObjc; i++) { + Tk_Window mapWin; + + if (TkGetWindowFromObj(interp, tkwin, windowObjv[i], + &mapWin) != TCL_OK) { + ckfree(cmapList); + return TCL_ERROR; + } + winPtr2 = (TkWindow *) mapWin; + if (winPtr2 == winPtr) { + gotToplevel = 1; + } + if (winPtr2->window == None) { + Tk_MakeWindowExist((Tk_Window) winPtr2); + } + cmapList[i] = winPtr2->window; + } + if (!gotToplevel) { + wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP; + cmapList[windowObjc] = wmPtr->wrapperPtr->window; + windowObjc++; + } else { + wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP; + } + wmPtr->flags |= WM_COLORMAPS_EXPLICIT; + XSetWMColormapWindows(winPtr->display, wmPtr->wrapperPtr->window, + cmapList, windowObjc); + ckfree(cmapList); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmCommandCmd -- + * + * This function is invoked to process the "wm command" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmCommandCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + const char *argv3; + int cmdArgc; + const char **cmdArgv; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?value?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->cmdArgv != NULL) { + char *arg = Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv); + + Tcl_SetObjResult(interp, Tcl_NewStringObj(arg, -1)); + ckfree(arg); + } + return TCL_OK; + } + argv3 = Tcl_GetString(objv[3]); + if (argv3[0] == 0) { + if (wmPtr->cmdArgv != NULL) { + ckfree(wmPtr->cmdArgv); + wmPtr->cmdArgv = NULL; + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window, + Tk_InternAtom((Tk_Window) winPtr, "WM_COMMAND")); + } + } + return TCL_OK; + } + if (Tcl_SplitList(interp, argv3, &cmdArgc, &cmdArgv) != TCL_OK) { + return TCL_ERROR; + } + if (wmPtr->cmdArgv != NULL) { + ckfree(wmPtr->cmdArgv); + } + wmPtr->cmdArgc = cmdArgc; + wmPtr->cmdArgv = cmdArgv; + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + UpdateCommand(winPtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmDeiconifyCmd -- + * + * This function is invoked to process the "wm deiconify" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmDeiconifyCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + if (wmPtr->iconFor != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't deiconify %s: it is an icon for %s", + Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor))); + Tcl_SetErrorCode(interp, "TK", "WM", "DEICONIFY", "ICON", NULL); + return TCL_ERROR; + } + if (winPtr->flags & TK_EMBEDDED) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't deiconify %s: it is an embedded window", + winPtr->pathName)); + Tcl_SetErrorCode(interp, "TK", "WM", "DEICONIFY", "EMBEDDED", NULL); + return TCL_ERROR; + } + wmPtr->flags &= ~WM_WITHDRAWN; + TkpWmSetState(winPtr, NormalState); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmFocusmodelCmd -- + * + * This function is invoked to process the "wm focusmodel" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmFocusmodelCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + static const char *const optionStrings[] = { + "active", "passive", NULL }; + enum options { + OPT_ACTIVE, OPT_PASSIVE }; + int index; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?active|passive?"); + return TCL_ERROR; + } + if (objc == 3) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + wmPtr->hints.input ? "passive" : "active", -1)); + return TCL_OK; + } + + if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings, + sizeof(char *), "argument", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == OPT_ACTIVE) { + wmPtr->hints.input = False; + } else { /* OPT_PASSIVE */ + wmPtr->hints.input = True; + } + UpdateHints(winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmForgetCmd -- + * + * This procedure is invoked to process the "wm forget" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmForgetCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel or Frame to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register Tk_Window frameWin = (Tk_Window) winPtr; + + if (Tk_IsTopLevel(frameWin)) { + TkFocusJoin(winPtr); + Tk_UnmapWindow(frameWin); + TkWmDeadWindow(winPtr); + winPtr->flags &= + ~(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED); + RemapWindows(winPtr, winPtr->parentPtr); + + /* + * Make sure wm no longer manages this window + */ + Tk_ManageGeometry(frameWin, NULL, NULL); + + /* + * Flags (above) must be cleared before calling TkMapTopFrame (below). + */ + + TkMapTopFrame(frameWin); + } else { + /* + * Already not managed by wm - ignore it. + */ + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmFrameCmd -- + * + * This function is invoked to process the "wm frame" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmFrameCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Window window; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + window = wmPtr->reparent; + if (window == None) { + window = Tk_WindowId((Tk_Window) winPtr); + } + Tcl_SetObjResult(interp, Tcl_ObjPrintf("0x%x", (unsigned) window)); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmGeometryCmd -- + * + * This function is invoked to process the "wm geometry" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmGeometryCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char xSign, ySign; + int width, height; + const char *argv3; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?newGeometry?"); + return TCL_ERROR; + } + if (objc == 3) { + xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+'; + ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+'; + if (wmPtr->gridWin != NULL) { + width = wmPtr->reqGridWidth + (winPtr->changes.width + - winPtr->reqWidth)/wmPtr->widthInc; + height = wmPtr->reqGridHeight + (winPtr->changes.height + - winPtr->reqHeight)/wmPtr->heightInc; + } else { + width = winPtr->changes.width; + height = winPtr->changes.height; + } + Tcl_SetObjResult(interp, Tcl_ObjPrintf("%dx%d%c%d%c%d", + width, height, xSign, wmPtr->x, ySign, wmPtr->y)); + return TCL_OK; + } + argv3 = Tcl_GetString(objv[3]); + if (*argv3 == '\0') { + wmPtr->width = -1; + wmPtr->height = -1; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; + } + return ParseGeometry(interp, argv3, winPtr); +} + +/* + *---------------------------------------------------------------------- + * + * WmGridCmd -- + * + * This function is invoked to process the "wm grid" Tcl command. See the + * user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmGridCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int reqWidth, reqHeight, widthInc, heightInc; + + if ((objc != 3) && (objc != 7)) { + Tcl_WrongNumArgs(interp, 2, objv, + "window ?baseWidth baseHeight widthInc heightInc?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->sizeHintsFlags & PBaseSize) { + Tcl_Obj *results[4]; + + results[0] = Tcl_NewIntObj(wmPtr->reqGridWidth); + results[1] = Tcl_NewIntObj(wmPtr->reqGridHeight); + results[2] = Tcl_NewIntObj(wmPtr->widthInc); + results[3] = Tcl_NewIntObj(wmPtr->heightInc); + Tcl_SetObjResult(interp, Tcl_NewListObj(4, results)); + } + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + /* + * Turn off gridding and reset the width and height to make sense as + * ungridded numbers. + */ + + wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc); + if (wmPtr->width != -1) { + wmPtr->width = winPtr->reqWidth + (wmPtr->width + - wmPtr->reqGridWidth)*wmPtr->widthInc; + wmPtr->height = winPtr->reqHeight + (wmPtr->height + - wmPtr->reqGridHeight)*wmPtr->heightInc; + } + wmPtr->widthInc = 1; + wmPtr->heightInc = 1; + } else { + if ((Tcl_GetIntFromObj(interp, objv[3], &reqWidth) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &reqHeight) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[5], &widthInc) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[6], &heightInc) !=TCL_OK)) { + return TCL_ERROR; + } + if (reqWidth < 0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "baseWidth can't be < 0", -1)); + Tcl_SetErrorCode(interp, "TK", "VALUE", "GRID", NULL); + return TCL_ERROR; + } + if (reqHeight < 0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "baseHeight can't be < 0", -1)); + Tcl_SetErrorCode(interp, "TK", "VALUE", "GRID", NULL); + return TCL_ERROR; + } + if (widthInc <= 0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "widthInc can't be <= 0", -1)); + Tcl_SetErrorCode(interp, "TK", "VALUE", "GRID", NULL); + return TCL_ERROR; + } + if (heightInc <= 0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "heightInc can't be <= 0", -1)); + Tcl_SetErrorCode(interp, "TK", "VALUE", "GRID", NULL); + return TCL_ERROR; + } + Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc, + heightInc); + } + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmGroupCmd -- + * + * This function is invoked to process the "wm group" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmGroupCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Tk_Window tkwin2; + WmInfo *wmPtr2; + const char *argv3; + int length; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->hints.flags & WindowGroupHint) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->leaderName, -1)); + } + return TCL_OK; + } + argv3 = Tcl_GetStringFromObj(objv[3], &length); + if (*argv3 == '\0') { + wmPtr->hints.flags &= ~WindowGroupHint; + if (wmPtr->leaderName != NULL) { + ckfree(wmPtr->leaderName); + } + wmPtr->leaderName = NULL; + } else { + if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) { + return TCL_ERROR; + } + while (!Tk_TopWinHierarchy(tkwin2)) { + /* + * Ensure that the group leader is actually a Tk toplevel. + */ + + tkwin2 = Tk_Parent(tkwin2); + } + Tk_MakeWindowExist(tkwin2); + wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr; + if (wmPtr2->wrapperPtr == NULL) { + CreateWrapper(wmPtr2); + } + if (wmPtr->leaderName != NULL) { + ckfree(wmPtr->leaderName); + } + wmPtr->hints.window_group = Tk_WindowId(wmPtr2->wrapperPtr); + wmPtr->hints.flags |= WindowGroupHint; + wmPtr->leaderName = ckalloc(length + 1); + strcpy(wmPtr->leaderName, argv3); + } + UpdateHints(winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconbitmapCmd -- + * + * This function is invoked to process the "wm iconbitmap" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconbitmapCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Pixmap pixmap; + const char *argv3; + + if ((objc < 3) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->hints.flags & IconPixmapHint) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + Tk_NameOfBitmap(winPtr->display, + wmPtr->hints.icon_pixmap), -1)); + } + return TCL_OK; + } + argv3 = Tcl_GetString(objv[3]); + if (*argv3 == '\0') { + if (wmPtr->hints.icon_pixmap != None) { + Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap); + wmPtr->hints.icon_pixmap = None; + } + wmPtr->hints.flags &= ~IconPixmapHint; + } else { + pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, argv3); + if (pixmap == None) { + return TCL_ERROR; + } + wmPtr->hints.icon_pixmap = pixmap; + wmPtr->hints.flags |= IconPixmapHint; + } + UpdateHints(winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconifyCmd -- + * + * This function is invoked to process the "wm iconify" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconifyCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't iconify \"%s\": override-redirect flag is set", + winPtr->pathName)); + Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "OVERRIDE_REDIRECT", + NULL); + return TCL_ERROR; + } + if (wmPtr->masterPtr != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't iconify \"%s\": it is a transient", + winPtr->pathName)); + Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "TRANSIENT", NULL); + return TCL_ERROR; + } + if (wmPtr->iconFor != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't iconify %s: it is an icon for %s", + winPtr->pathName, Tk_PathName(wmPtr->iconFor))); + Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "ICON", NULL); + return TCL_ERROR; + } + if (winPtr->flags & TK_EMBEDDED) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't iconify %s: it is an embedded window", + winPtr->pathName)); + Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "EMBEDDED", NULL); + return TCL_ERROR; + } + if (TkpWmSetState(winPtr, IconicState) == 0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "couldn't send iconify message to window manager", -1)); + Tcl_SetErrorCode(interp, "TK", "WM", "COMMUNICATION", NULL); + return TCL_ERROR; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconmaskCmd -- + * + * This function is invoked to process the "wm iconmask" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconmaskCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Pixmap pixmap; + const char *argv3; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->hints.flags & IconMaskHint) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask), + -1)); + } + return TCL_OK; + } + argv3 = Tcl_GetString(objv[3]); + if (*argv3 == '\0') { + if (wmPtr->hints.icon_mask != None) { + Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask); + } + wmPtr->hints.flags &= ~IconMaskHint; + } else { + pixmap = Tk_GetBitmap(interp, tkwin, argv3); + if (pixmap == None) { + return TCL_ERROR; + } + wmPtr->hints.icon_mask = pixmap; + wmPtr->hints.flags |= IconMaskHint; + } + UpdateHints(winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconnameCmd -- + * + * This function is invoked to process the "wm iconname" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconnameCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + const char *argv3; + int length; + + if (objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?newName?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->iconName != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->iconName, -1)); + } + return TCL_OK; + } else { + if (wmPtr->iconName != NULL) { + ckfree(wmPtr->iconName); + } + argv3 = Tcl_GetStringFromObj(objv[3], &length); + wmPtr->iconName = ckalloc(length + 1); + strcpy(wmPtr->iconName, argv3); + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + UpdateTitle(winPtr); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconphotoCmd -- + * + * This function is invoked to process the "wm iconphoto" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconphotoCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Tk_PhotoHandle photo; + Tk_PhotoImageBlock block; + int i, size = 0, width, height, index = 0, x, y, isDefault = 0; + unsigned long *iconPropertyData; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2, objv, + "window ?-default? image1 ?image2 ...?"); + return TCL_ERROR; + } + if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) { + isDefault = 1; + if (objc == 4) { + Tcl_WrongNumArgs(interp, 2, objv, + "window ?-default? image1 ?image2 ...?"); + return TCL_ERROR; + } + } + + /* + * Iterate over all images to retrieve their sizes, in order to allocate a + * buffer large enough to hold all images. + */ + + for (i = 3 + isDefault; i < objc; i++) { + photo = Tk_FindPhoto(interp, Tcl_GetString(objv[i])); + if (photo == NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't use \"%s\" as iconphoto: not a photo image", + Tcl_GetString(objv[i]))); + Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "PHOTO", NULL); + return TCL_ERROR; + } + Tk_PhotoGetSize(photo, &width, &height); + + /* + * We need to cardinals for width & height and one cardinal for each + * image pixel. + */ + + size += 2 + width * height; + } + + /* + * We have calculated the size of the data. Try to allocate the needed + * memory space. This is an unsigned long array (despite this being twice + * as much as is really needed on LP64 platforms) because that's what X + * defines CARD32 arrays to use. [Bug 2902814] + */ + + iconPropertyData = attemptckalloc(sizeof(unsigned long) * size); + if (iconPropertyData == NULL) { + return TCL_ERROR; + } + memset(iconPropertyData, 0, sizeof(unsigned long) * size); + + for (i = 3 + isDefault; i < objc; i++) { + photo = Tk_FindPhoto(interp, Tcl_GetString(objv[i])); + if (photo == NULL) { + Tcl_Free((char *) iconPropertyData); + return TCL_ERROR; + } + Tk_PhotoGetSize(photo, &width, &height); + Tk_PhotoGetImage(photo, &block); + + /* + * Each image data will be placed as an array of 32bit packed + * CARDINAL, in a window property named "_NET_WM_ICON": _NET_WM_ICON + * + * _NET_WM_ICON CARDINAL[][2+n]/32 + * + * This is an array of possible icons for the client. This spec. does + * not stipulate what size these icons should be, but individual + * desktop environments or toolkits may do so. The Window Manager MAY + * scale any of these icons to an appropriate size. + * + * This is an array of 32bit packed CARDINAL ARGB with high byte being + * A, low byte being B. The first two cardinals are width, height. + * Data is in rows, left to right and top to bottom. The data will be + * endian-swapped going to the server if necessary. [Bug 2830420] + * + * The image data will be encoded in the iconPropertyData array. + */ + + iconPropertyData[index++] = (unsigned long) width; + iconPropertyData[index++] = (unsigned long) height; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + register unsigned char *pixelPtr = + block.pixelPtr + x*block.pixelSize + y*block.pitch; + register unsigned long R, G, B, A; + + R = pixelPtr[block.offset[0]]; + G = pixelPtr[block.offset[1]]; + B = pixelPtr[block.offset[2]]; + A = pixelPtr[block.offset[3]]; + iconPropertyData[index++] = A<<24 | R<<16 | G<<8 | B<<0; + } + } + } + if (wmPtr->iconDataPtr != NULL) { + ckfree(wmPtr->iconDataPtr); + wmPtr->iconDataPtr = NULL; + } + if (isDefault) { + if (winPtr->dispPtr->iconDataPtr != NULL) { + ckfree(winPtr->dispPtr->iconDataPtr); + } + winPtr->dispPtr->iconDataPtr = (unsigned char *) iconPropertyData; + winPtr->dispPtr->iconDataSize = size; + } else { + wmPtr->iconDataPtr = (unsigned char *) iconPropertyData; + wmPtr->iconDataSize = size; + } + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + UpdatePhotoIcon(winPtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconpositionCmd -- + * + * This function is invoked to process the "wm iconposition" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconpositionCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int x, y; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?x y?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->hints.flags & IconPositionHint) { + Tcl_Obj *results[2]; + + results[0] = Tcl_NewIntObj(wmPtr->hints.icon_x); + results[1] = Tcl_NewIntObj(wmPtr->hints.icon_y); + Tcl_SetObjResult(interp, Tcl_NewListObj(2, results)); + } + return TCL_OK; + } + if (Tcl_GetString(objv[3])[0] == '\0') { + wmPtr->hints.flags &= ~IconPositionHint; + } else { + if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) { + return TCL_ERROR; + } + wmPtr->hints.icon_x = x; + wmPtr->hints.icon_y = y; + wmPtr->hints.flags |= IconPositionHint; + } + UpdateHints(winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconwindowCmd -- + * + * This function is invoked to process the "wm iconwindow" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconwindowCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Tk_Window tkwin2; + WmInfo *wmPtr2; + XSetWindowAttributes atts; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->icon != NULL) { + Tcl_SetObjResult(interp, TkNewWindowObj(wmPtr->icon)); + } + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->hints.flags &= ~IconWindowHint; + if (wmPtr->icon != NULL) { + /* + * Remove the icon window relationship. In principle we should + * also re-enable button events for the window, but this doesn't + * work in general because the window manager is probably + * selecting on them (we'll get an error if we try to re-enable + * the events). So, just leave the icon window event-challenged; + * the user will have to recreate it if they want button events. + */ + + wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; + wmPtr2->iconFor = NULL; + wmPtr2->withdrawn = 1; + wmPtr2->hints.initial_state = WithdrawnState; + } + wmPtr->icon = NULL; + } else { + if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) { + return TCL_ERROR; + } + if (!Tk_IsTopLevel(tkwin2)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't use %s as icon window: not at top level", + Tcl_GetString(objv[3]))); + Tcl_SetErrorCode(interp, "TK", "WM", "ICONWINDOW", "INNER", NULL); + return TCL_ERROR; + } + wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr; + if (wmPtr2->iconFor != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "%s is already an icon for %s", + Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor))); + Tcl_SetErrorCode(interp, "TK", "WM", "ICONWINDOW", "ICON", NULL); + return TCL_ERROR; + } + if (wmPtr->icon != NULL) { + WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; + + wmPtr3->iconFor = NULL; + wmPtr3->withdrawn = 1; + wmPtr3->hints.initial_state = WithdrawnState; + } + + /* + * Disable button events in the icon window: some window managers + * (like olvwm) want to get the events themselves, but X only allows + * one application at a time to receive button events for a window. + */ + + atts.event_mask = Tk_Attributes(tkwin2)->event_mask + & ~ButtonPressMask; + Tk_ChangeWindowAttributes(tkwin2, CWEventMask, &atts); + Tk_MakeWindowExist(tkwin2); + if (wmPtr2->wrapperPtr == NULL) { + CreateWrapper(wmPtr2); + } + wmPtr->hints.icon_window = Tk_WindowId(wmPtr2->wrapperPtr); + wmPtr->hints.flags |= IconWindowHint; + wmPtr->icon = tkwin2; + wmPtr2->iconFor = (Tk_Window) winPtr; + if (!wmPtr2->withdrawn && !(wmPtr2->flags & WM_NEVER_MAPPED)) { + wmPtr2->withdrawn = 0; + if (XWithdrawWindow(Tk_Display(tkwin2), + Tk_WindowId(wmPtr2->wrapperPtr), + Tk_ScreenNumber(tkwin2)) == 0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "couldn't send withdraw message to window manager", + -1)); + Tcl_SetErrorCode(interp, "TK", "WM", "COMMUNICATION", NULL); + return TCL_ERROR; + } + WaitForMapNotify((TkWindow *) tkwin2, 0); + } + } + UpdateHints(winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmManageCmd -- + * + * This procedure is invoked to process the "wm manage" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmManageCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel or Frame to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register Tk_Window frameWin = (Tk_Window) winPtr; + register WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (!Tk_IsTopLevel(frameWin)) { + if (!Tk_IsManageable(frameWin)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "window \"%s\" is not manageable: must be a frame," + " labelframe or toplevel", Tk_PathName(frameWin))); + Tcl_SetErrorCode(interp, "TK", "WM", "MANAGE", NULL); + return TCL_ERROR; + } + TkFocusSplit(winPtr); + Tk_UnmapWindow(frameWin); + winPtr->flags |= + TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED; + if (wmPtr == NULL) { + TkWmNewWindow(winPtr); + TkWmMapWindow(winPtr); + Tk_UnmapWindow(frameWin); + } + wmPtr = winPtr->wmInfoPtr; + winPtr->flags &= ~TK_MAPPED; + RemapWindows(winPtr, wmPtr->wrapperPtr); + + /* + * Flags (above) must be set before calling TkMapTopFrame (below). + */ + + TkMapTopFrame(frameWin); + } else if (Tk_IsTopLevel(frameWin)) { + /* + * Already managed by wm - ignore it. + */ + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmMaxsizeCmd -- + * + * This function is invoked to process the "wm maxsize" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmMaxsizeCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int width, height; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?"); + return TCL_ERROR; + } + if (objc == 3) { + Tcl_Obj *results[2]; + + GetMaxSize(wmPtr, &width, &height); + results[0] = Tcl_NewIntObj(width); + results[1] = Tcl_NewIntObj(height); + Tcl_SetObjResult(interp, Tcl_NewListObj(2, results)); + return TCL_OK; + } + if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) { + return TCL_ERROR; + } + wmPtr->maxWidth = width; + wmPtr->maxHeight = height; + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + + if (width <= 0 && height <= 0) { + wmPtr->sizeHintsFlags &= ~PMaxSize; + } else { + wmPtr->sizeHintsFlags |= PMaxSize; + } + + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmMinsizeCmd -- + * + * This function is invoked to process the "wm minsize" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmMinsizeCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int width, height; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?"); + return TCL_ERROR; + } + if (objc == 3) { + Tcl_Obj *results[2]; + + results[0] = Tcl_NewIntObj(wmPtr->minWidth); + results[1] = Tcl_NewIntObj(wmPtr->minHeight); + Tcl_SetObjResult(interp, Tcl_NewListObj(2, results)); + return TCL_OK; + } + if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) { + return TCL_ERROR; + } + wmPtr->minWidth = width; + wmPtr->minHeight = height; + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmOverrideredirectCmd -- + * + * This function is invoked to process the "wm overrideredirect" Tcl + * command. See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmOverrideredirectCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + int boolean, curValue; + XSetWindowAttributes atts; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?"); + return TCL_ERROR; + } + curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect; + if (objc == 3) { + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(curValue)); + return TCL_OK; + } + if (Tcl_GetBooleanFromObj(interp, objv[3], &boolean) != TCL_OK) { + return TCL_ERROR; + } + 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 (winPtr->wmInfoPtr->wrapperPtr != NULL) { + Tk_ChangeWindowAttributes( + (Tk_Window) winPtr->wmInfoPtr->wrapperPtr, + CWOverrideRedirect, &atts); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmPositionfromCmd -- + * + * This function is invoked to process the "wm positionfrom" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmPositionfromCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + static const char *const optionStrings[] = { + "program", "user", NULL }; + enum options { + OPT_PROGRAM, OPT_USER }; + int index; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?user/program?"); + return TCL_ERROR; + } + if (objc == 3) { + const char *sourceStr = ""; + + if (wmPtr->sizeHintsFlags & USPosition) { + sourceStr = "user"; + } else if (wmPtr->sizeHintsFlags & PPosition) { + sourceStr = "program"; + } + Tcl_SetObjResult(interp, Tcl_NewStringObj(sourceStr, -1)); + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->sizeHintsFlags &= ~(USPosition|PPosition); + } else { + if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings, + sizeof(char *), "argument", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == OPT_USER) { + wmPtr->sizeHintsFlags &= ~PPosition; + wmPtr->sizeHintsFlags |= USPosition; + } else { + wmPtr->sizeHintsFlags &= ~USPosition; + wmPtr->sizeHintsFlags |= PPosition; + } + } + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmProtocolCmd -- + * + * This function is invoked to process the "wm protocol" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmProtocolCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + register ProtocolHandler *protPtr, *prevPtr; + Atom protocol; + const char *cmd; + int cmdLength; + + if ((objc < 3) || (objc > 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?name? ?command?"); + return TCL_ERROR; + } + if (objc == 3) { + /* + * Return a list of all defined protocols for the window. + */ + + Tcl_Obj *resultObj = Tcl_NewObj(); + + for (protPtr = wmPtr->protPtr; protPtr != NULL; + protPtr = protPtr->nextPtr) { + Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj( + Tk_GetAtomName((Tk_Window)winPtr, protPtr->protocol),-1)); + } + Tcl_SetObjResult(interp, resultObj); + return TCL_OK; + } + protocol = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3])); + if (objc == 4) { + /* + * Return the command to handle a given protocol. + */ + + for (protPtr = wmPtr->protPtr; protPtr != NULL; + protPtr = protPtr->nextPtr) { + if (protPtr->protocol == protocol) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj(protPtr->command, -1)); + return TCL_OK; + } + } + return TCL_OK; + } + + /* + * Special case for _NET_WM_PING: that's always handled directly. + */ + + if (strcmp(Tcl_GetString(objv[3]), "_NET_WM_PING") == 0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "may not alter handling of that protocol", -1)); + Tcl_SetErrorCode(interp, "TK", "WM", "PROTOCOL", "RESERVED", NULL); + return TCL_ERROR; + } + + /* + * Delete any current protocol handler, then create a new one with the + * specified command, unless the command is empty. + */ + + for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL; + prevPtr = protPtr, protPtr = protPtr->nextPtr) { + if (protPtr->protocol == protocol) { + if (prevPtr == NULL) { + wmPtr->protPtr = protPtr->nextPtr; + } else { + prevPtr->nextPtr = protPtr->nextPtr; + } + Tcl_EventuallyFree(protPtr, TCL_DYNAMIC); + break; + } + } + cmd = Tcl_GetStringFromObj(objv[4], &cmdLength); + if (cmdLength > 0) { + protPtr = ckalloc(HANDLER_SIZE(cmdLength)); + protPtr->protocol = protocol; + protPtr->nextPtr = wmPtr->protPtr; + wmPtr->protPtr = protPtr; + protPtr->interp = interp; + memcpy(protPtr->command, cmd, cmdLength + 1); + } + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + UpdateWmProtocols(wmPtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmResizableCmd -- + * + * This function is invoked to process the "wm resizable" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmResizableCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int width, height; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?"); + return TCL_ERROR; + } + if (objc == 3) { + Tcl_Obj *results[2]; + + results[0] = Tcl_NewBooleanObj(!(wmPtr->flags&WM_WIDTH_NOT_RESIZABLE)); + results[1] = Tcl_NewBooleanObj(!(wmPtr->flags&WM_HEIGHT_NOT_RESIZABLE)); + Tcl_SetObjResult(interp, Tcl_NewListObj(2, results)); + return TCL_OK; + } + if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK) + || (Tcl_GetBooleanFromObj(interp, objv[4], &height) != TCL_OK)) { + return TCL_ERROR; + } + if (width) { + wmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE; + } else { + wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE; + } + if (height) { + wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE; + } else { + wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE; + } + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmSizefromCmd -- + * + * This function is invoked to process the "wm sizefrom" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmSizefromCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + static const char *const optionStrings[] = { + "program", "user", NULL }; + enum options { + OPT_PROGRAM, OPT_USER }; + int index; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?user|program?"); + return TCL_ERROR; + } + if (objc == 3) { + const char *sourceStr = ""; + + if (wmPtr->sizeHintsFlags & USSize) { + sourceStr = "user"; + } else if (wmPtr->sizeHintsFlags & PSize) { + sourceStr = "program"; + } + Tcl_SetObjResult(interp, Tcl_NewStringObj(sourceStr, -1)); + return TCL_OK; + } + + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->sizeHintsFlags &= ~(USSize|PSize); + } else { + if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings, + sizeof(char *), "argument", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == OPT_USER) { + wmPtr->sizeHintsFlags &= ~PSize; + wmPtr->sizeHintsFlags |= USSize; + } else { /* OPT_PROGRAM */ + wmPtr->sizeHintsFlags &= ~USSize; + wmPtr->sizeHintsFlags |= PSize; + } + } + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmStackorderCmd -- + * + * This function is invoked to process the "wm stackorder" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmStackorderCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + TkWindow **windows, **window_ptr; + static const char *const optionStrings[] = { + "isabove", "isbelow", NULL }; + enum options { + OPT_ISABOVE, OPT_ISBELOW }; + int index; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?isabove|isbelow window?"); + return TCL_ERROR; + } + + if (objc == 3) { + windows = TkWmStackorderToplevel(winPtr); + if (windows != NULL) { + Tcl_Obj *resultObj = Tcl_NewObj(); + + /* ASSERT: true [Bug 1789819]*/ + for (window_ptr = windows; *window_ptr ; window_ptr++) { + Tcl_ListObjAppendElement(NULL, resultObj, + Tcl_NewStringObj((*window_ptr)->pathName, -1)); + } + ckfree(windows); + Tcl_SetObjResult(interp, resultObj); + return TCL_OK; + } + } else { + Tk_Window relWin; + TkWindow *winPtr2; + int index1=-1, index2=-1, result; + + if (TkGetWindowFromObj(interp, tkwin, objv[4], &relWin) != TCL_OK) { + return TCL_ERROR; + } + winPtr2 = (TkWindow *) relWin; + + if (!Tk_IsTopLevel(winPtr2)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "window \"%s\" isn't a top-level window", + winPtr2->pathName)); + Tcl_SetErrorCode(interp, "TK", "WM", "STACK", "TOPLEVEL", NULL); + return TCL_ERROR; + } + + if (!Tk_IsMapped(winPtr)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "window \"%s\" isn't mapped", winPtr->pathName)); + Tcl_SetErrorCode(interp, "TK", "WM", "STACK", "MAPPED", NULL); + return TCL_ERROR; + } + + if (!Tk_IsMapped(winPtr2)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "window \"%s\" isn't mapped", winPtr2->pathName)); + Tcl_SetErrorCode(interp, "TK", "WM", "STACK", "MAPPED", NULL); + return TCL_ERROR; + } + + /* + * Lookup stacking order of all toplevels that are children of "." and + * find the position of winPtr and winPtr2 in the stacking order. + */ + + windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr); + if (windows == NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "TkWmStackorderToplevel failed", -1)); + Tcl_SetErrorCode(interp, "TK", "WM", "COMMUNICATION", NULL); + return TCL_ERROR; + } + + for (window_ptr = windows; *window_ptr ; window_ptr++) { + if (*window_ptr == winPtr) { + index1 = (window_ptr - windows); + } + if (*window_ptr == winPtr2) { + index2 = (window_ptr - windows); + } + } + /* ASSERT: index1 != -1 && index2 != -2 [Bug 1789819] */ + ckfree(windows); + + if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings, + sizeof(char *), "argument", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == OPT_ISABOVE) { + result = index1 > index2; + } else { /* OPT_ISBELOW */ + result = index1 < index2; + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); + return TCL_OK; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmStateCmd -- + * + * This function is invoked to process the "wm state" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmStateCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + static const char *const optionStrings[] = { + "normal", "iconic", "withdrawn", NULL }; + enum options { + OPT_NORMAL, OPT_ICONIC, OPT_WITHDRAWN }; + int index; + + if ((objc < 3) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?state?"); + return TCL_ERROR; + } + if (objc == 4) { + if (wmPtr->iconFor != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't change state of %s: it is an icon for %s", + Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor))); + Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "ICON", NULL); + return TCL_ERROR; + } + + if (Tcl_GetIndexFromObjStruct(interp, objv[3], optionStrings, + sizeof(char *), "argument", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + + if (index == OPT_NORMAL) { + wmPtr->flags &= ~WM_WITHDRAWN; + (void) TkpWmSetState(winPtr, NormalState); + } else if (index == OPT_ICONIC) { + if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't iconify \"%s\": override-redirect flag is set", + winPtr->pathName)); + Tcl_SetErrorCode(interp, "TK", "WM", "STATE", + "OVERRIDE_REDIRECT", NULL); + return TCL_ERROR; + } + if (wmPtr->masterPtr != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't iconify \"%s\": it is a transient", + winPtr->pathName)); + Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "TRANSIENT", + NULL); + return TCL_ERROR; + } + if (TkpWmSetState(winPtr, IconicState) == 0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "couldn't send iconify message to window manager", + -1)); + Tcl_SetErrorCode(interp, "TK", "WM", "COMMUNICATION", NULL); + return TCL_ERROR; + } + } else { /* OPT_WITHDRAWN */ + wmPtr->flags |= WM_WITHDRAWN; + if (TkpWmSetState(winPtr, WithdrawnState) == 0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "couldn't send withdraw message to window manager", + -1)); + Tcl_SetErrorCode(interp, "TK", "WM", "COMMUNICATION", NULL); + return TCL_ERROR; + } + } + } else { + const char *state; + + if (wmPtr->iconFor != NULL) { + state = "icon"; + } else if (wmPtr->withdrawn) { + state = "withdrawn"; + } else if (Tk_IsMapped((Tk_Window) winPtr) + || ((wmPtr->flags & WM_NEVER_MAPPED) + && (wmPtr->hints.initial_state == NormalState))) { + state = "normal"; + } else { + state = "iconic"; + } + Tcl_SetObjResult(interp, Tcl_NewStringObj(state, -1)); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmTitleCmd -- + * + * This function is invoked to process the "wm title" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmTitleCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + const char *argv3; + int length; + + if (objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?newTitle?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->title) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->title, -1)); + } else { + Tcl_SetObjResult(interp, Tcl_NewStringObj(winPtr->nameUid, -1)); + } + } else { + if (wmPtr->title != NULL) { + ckfree(wmPtr->title); + } + argv3 = Tcl_GetStringFromObj(objv[3], &length); + wmPtr->title = ckalloc(length + 1); + strcpy(wmPtr->title, argv3); + + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + UpdateTitle(winPtr); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmTransientCmd -- + * + * This function is invoked to process the "wm transient" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmTransientCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + TkWindow *masterPtr = wmPtr->masterPtr; + WmInfo *wmPtr2; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?master?"); + return TCL_ERROR; + } + if (objc == 3) { + if (masterPtr != NULL) { + Tcl_SetObjResult(interp, TkNewWindowObj((Tk_Window) masterPtr)); + } + return TCL_OK; + } + if (Tcl_GetString(objv[3])[0] == '\0') { + 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, StructureNotifyMask, + WmWaitMapProc, winPtr); + + /* + * FIXME: Need a call like Win32's UpdateWrapper() so we can + * recreate the wrapper and get rid of the transient window + * decorations. + */ + } + + wmPtr->masterPtr = NULL; + } else { + Tk_Window masterWin; + + if (TkGetWindowFromObj(interp, tkwin, objv[3], &masterWin)!=TCL_OK) { + return TCL_ERROR; + } + masterPtr = (TkWindow *) masterWin; + while (!Tk_TopWinHierarchy(masterPtr)) { + /* + * Ensure that the master window is actually a Tk toplevel. + */ + + masterPtr = masterPtr->parentPtr; + } + Tk_MakeWindowExist((Tk_Window) masterPtr); + + if (wmPtr->iconFor != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't make \"%s\" a transient: it is an icon for %s", + Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor))); + Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL); + return TCL_ERROR; + } + + wmPtr2 = masterPtr->wmInfoPtr; + if (wmPtr2->wrapperPtr == NULL) { + CreateWrapper(wmPtr2); + } + + if (wmPtr2->iconFor != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't make \"%s\" a master: it is an icon for %s", + Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor))); + Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL); + return TCL_ERROR; + } + + if (masterPtr == winPtr) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't make \"%s\" its own master", Tk_PathName(winPtr))); + Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL); + return TCL_ERROR; + } else if (masterPtr != wmPtr->masterPtr) { + /* + * Remove old master map/unmap binding before setting the new + * master. The event handler will ensure that transient states + * reflect the state of the master. + */ + + if (wmPtr->masterPtr != NULL) { + wmPtr->masterPtr->wmInfoPtr->numTransients--; + Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr, + StructureNotifyMask, WmWaitMapProc, winPtr); + } + + masterPtr->wmInfoPtr->numTransients++; + Tk_CreateEventHandler((Tk_Window) masterPtr, + StructureNotifyMask, WmWaitMapProc, winPtr); + + wmPtr->masterPtr = masterPtr; + } + } + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + if (wmPtr->masterPtr != NULL && !Tk_IsMapped(wmPtr->masterPtr)) { + if (TkpWmSetState(winPtr, WithdrawnState) == 0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "couldn't send withdraw message to window manager", + -1)); + Tcl_SetErrorCode(interp, "TK", "WM", "COMMUNICATION", NULL); + return TCL_ERROR; + } + } else { + if (wmPtr->masterPtr != NULL) { + XSetTransientForHint(winPtr->display, + wmPtr->wrapperPtr->window, + wmPtr->masterPtr->wmInfoPtr->wrapperPtr->window); + } else { + XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window, + Tk_InternAtom((Tk_Window) winPtr,"WM_TRANSIENT_FOR")); + } + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmWithdrawCmd -- + * + * This function is invoked to process the "wm withdraw" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmWithdrawCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + if (wmPtr->iconFor != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't withdraw %s: it is an icon for %s", + Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor))); + Tcl_SetErrorCode(interp, "TK", "WM", "WITHDRAW", "ICON", NULL); + return TCL_ERROR; + } + wmPtr->flags |= WM_WITHDRAWN; + if (TkpWmSetState(winPtr, WithdrawnState) == 0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "couldn't send withdraw message to window manager", -1)); + Tcl_SetErrorCode(interp, "TK", "WM", "COMMUNICATION", NULL); + return TCL_ERROR; + } + return TCL_OK; +} + +/* + * Invoked by those wm subcommands that affect geometry. Schedules a geometry + * update. + */ + +static void +WmUpdateGeom( + WmInfo *wmPtr, + TkWindow *winPtr) +{ + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr); + wmPtr->flags |= WM_UPDATE_PENDING; + } +} + +/* + * Invoked when a MapNotify or UnmapNotify event is delivered for a toplevel + * that is the master of a transient toplevel. + */ + +static void +WmWaitMapProc( + ClientData clientData, /* Pointer to window. */ + XEvent *eventPtr) /* Information about event. */ +{ + TkWindow *winPtr = clientData; + TkWindow *masterPtr = winPtr->wmInfoPtr->masterPtr; + + if (masterPtr == NULL) { + return; + } + + if (eventPtr->type == MapNotify) { + if (!(winPtr->wmInfoPtr->flags & WM_WITHDRAWN)) { + (void) TkpWmSetState(winPtr, NormalState); + } + } else if (eventPtr->type == UnmapNotify) { + (void) TkpWmSetState(winPtr, WithdrawnState); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_SetGrid -- + * + * This function is invoked by a widget when it wishes to set a grid + * coordinate system that controls the size of a top-level window. It + * provides a C interface equivalent to the "wm grid" command and is + * usually associated with the -setgrid option. + * + * Results: + * None. + * + * Side effects: + * Grid-related information will be passed to the window manager, so that + * the top-level window associated with tkwin will resize on even grid + * units. If some other window already controls gridding for the + * top-level window then this function call has no effect. + * + *---------------------------------------------------------------------- + */ + +void +Tk_SetGrid( + Tk_Window tkwin, /* Token for window. New window mgr info will + * be posted for the top-level window + * associated with this window. */ + int reqWidth, /* Width (in grid units) corresponding to the + * requested geometry for tkwin. */ + int reqHeight, /* Height (in grid units) corresponding to the + * requested geometry for tkwin. */ + int widthInc, int heightInc)/* Pixel increments corresponding to a change + * of one grid unit. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + register WmInfo *wmPtr; + + /* + * Ensure widthInc and heightInc are greater than 0 + */ + + if (widthInc <= 0) { + widthInc = 1; + } + if (heightInc <= 0) { + heightInc = 1; + } + + /* + * Find the top-level window for tkwin, plus the window manager + * information. + */ + + while (!(winPtr->flags & TK_TOP_HIERARCHY)) { + winPtr = winPtr->parentPtr; + if (winPtr == NULL) { + /* + * The window is being deleted... just skip this operation. + */ + + return; + } + } + wmPtr = winPtr->wmInfoPtr; + if (wmPtr == NULL) { + return; + } + + if ((wmPtr->gridWin != NULL) && (wmPtr->gridWin != tkwin)) { + return; + } + + if ((wmPtr->reqGridWidth == reqWidth) + && (wmPtr->reqGridHeight == reqHeight) + && (wmPtr->widthInc == widthInc) + && (wmPtr->heightInc == heightInc) + && ((wmPtr->sizeHintsFlags & (PBaseSize|PResizeInc)) + == (PBaseSize|PResizeInc))) { + return; + } + + /* + * If gridding was previously off, then forget about any window size + * requests made by the user or via "wm geometry": these are in pixel + * units and there's no easy way to translate them to grid units since the + * new requested size of the top-level window in pixels may not yet have + * been registered yet (it may filter up the hierarchy in DoWhenIdle + * handlers). However, if the window has never been mapped yet then just + * leave the window size alone: assume that it is intended to be in grid + * units but just happened to have been specified before this function was + * called. + */ + + if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) { + wmPtr->width = -1; + wmPtr->height = -1; + } + + /* + * Set the new gridding information, and start the process of passing all + * of this information to the window manager. + */ + + wmPtr->gridWin = tkwin; + wmPtr->reqGridWidth = reqWidth; + wmPtr->reqGridHeight = reqHeight; + wmPtr->widthInc = widthInc; + wmPtr->heightInc = heightInc; + wmPtr->sizeHintsFlags |= PBaseSize|PResizeInc; + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr); + wmPtr->flags |= WM_UPDATE_PENDING; + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_UnsetGrid -- + * + * This function cancels the effect of a previous call to Tk_SetGrid. + * + * Results: + * None. + * + * Side effects: + * If tkwin currently controls gridding for its top-level window, + * gridding is cancelled for that top-level window; if some other window + * controls gridding then this function has no effect. + * + *---------------------------------------------------------------------- + */ + +void +Tk_UnsetGrid( + Tk_Window tkwin) /* Token for window that is currently + * controlling gridding. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + register WmInfo *wmPtr; + + /* + * Find the top-level window for tkwin, plus the window manager + * information. + */ + + while (!(winPtr->flags & TK_TOP_HIERARCHY)) { + winPtr = winPtr->parentPtr; + if (winPtr == NULL) { + /* + * The window is being deleted... just skip this operation. + */ + + return; + } + } + wmPtr = winPtr->wmInfoPtr; + if (wmPtr == NULL) { + return; + } + + if (tkwin != wmPtr->gridWin) { + return; + } + + wmPtr->gridWin = NULL; + wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc); + if (wmPtr->width != -1) { + wmPtr->width = winPtr->reqWidth + (wmPtr->width + - wmPtr->reqGridWidth)*wmPtr->widthInc; + wmPtr->height = winPtr->reqHeight + (wmPtr->height + - wmPtr->reqGridHeight)*wmPtr->heightInc; + } + wmPtr->widthInc = 1; + wmPtr->heightInc = 1; + + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr); + wmPtr->flags |= WM_UPDATE_PENDING; + } +} + +/* + *---------------------------------------------------------------------- + * + * ConfigureEvent -- + * + * This function is called to handle ConfigureNotify events on wrapper + * windows. + * + * Results: + * None. + * + * Side effects: + * Information gets updated in the WmInfo structure for the window and + * the toplevel itself gets repositioned within the wrapper. + * + *---------------------------------------------------------------------- + */ + +static void +ConfigureEvent( + WmInfo *wmPtr, /* Information about toplevel window. */ + XConfigureEvent *configEventPtr) + /* Event that just occurred for + * wmPtr->wrapperPtr. */ +{ + TkWindow *wrapperPtr = wmPtr->wrapperPtr; + TkWindow *winPtr = wmPtr->winPtr; + TkDisplay *dispPtr = wmPtr->winPtr->dispPtr; + Tk_ErrorHandler handler; + + /* + * Update size information from the event. There are a couple of tricky + * points here: + * + * 1. If the user changed the size externally then set wmPtr->width and + * wmPtr->height just as if a "wm geometry" command had been invoked + * with the same information. + * 2. However, if the size is changing in response to a request coming + * from us (WM_SYNC_PENDING is set), then don't set wmPtr->width or + * wmPtr->height if they were previously -1 (otherwise the window will + * stop tracking geometry manager requests). + */ + + if (((wrapperPtr->changes.width != configEventPtr->width) + || (wrapperPtr->changes.height != configEventPtr->height)) + && !(wmPtr->flags & WM_SYNC_PENDING)) { + if (dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("TopLevelEventProc: user changed %s size to %dx%d\n", + winPtr->pathName, configEventPtr->width, + configEventPtr->height); + } + if ((wmPtr->width == -1) + && (configEventPtr->width == winPtr->reqWidth)) { + /* + * Don't set external width, since the user didn't change it from + * what the widgets asked for. + */ + } else { + /* + * Note: if this window is embedded then don't set the external + * size, since it came from the containing application, not the + * user. In this case we want to keep sending our size requests to + * the containing application; if the user fixes the size of that + * application then it will still percolate down to us in the + * right way. + */ + + if (!(winPtr->flags & TK_EMBEDDED)) { + if (wmPtr->gridWin != NULL) { + wmPtr->width = wmPtr->reqGridWidth + + (configEventPtr->width + - winPtr->reqWidth)/wmPtr->widthInc; + if (wmPtr->width < 0) { + wmPtr->width = 0; + } + } else { + wmPtr->width = configEventPtr->width; + } + } + } + if ((wmPtr->height == -1) + && (configEventPtr->height == + (winPtr->reqHeight + wmPtr->menuHeight))) { + /* + * Don't set external height, since the user didn't change it from + * what the widgets asked for. + */ + } else { + /* + * See note for wmPtr->width about not setting external size for + * embedded windows. + */ + + if (!(winPtr->flags & TK_EMBEDDED)) { + if (wmPtr->gridWin != NULL) { + wmPtr->height = wmPtr->reqGridHeight + + (configEventPtr->height - wmPtr->menuHeight + - winPtr->reqHeight)/wmPtr->heightInc; + if (wmPtr->height < 0) { + wmPtr->height = 0; + } + } else { + wmPtr->height = configEventPtr->height - wmPtr->menuHeight; + } + } + } + wmPtr->configWidth = configEventPtr->width; + wmPtr->configHeight = configEventPtr->height; + } + + if (dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("ConfigureEvent: %s x = %d y = %d, width = %d, height = %d\n", + winPtr->pathName, configEventPtr->x, configEventPtr->y, + configEventPtr->width, configEventPtr->height); + printf(" send_event = %d, serial = %ld (win %p, wrapper %p)\n", + configEventPtr->send_event, configEventPtr->serial, + winPtr, wrapperPtr); + } + wrapperPtr->changes.width = configEventPtr->width; + wrapperPtr->changes.height = configEventPtr->height; + wrapperPtr->changes.border_width = configEventPtr->border_width; + wrapperPtr->changes.sibling = configEventPtr->above; + wrapperPtr->changes.stack_mode = Above; + + /* + * Reparenting window managers make life difficult. If the window manager + * reparents a top-level window then the x and y information that comes in + * events for the window is wrong: it gives the location of the window + * inside its decorative parent, rather than the location of the window in + * root coordinates, which is what we want. Window managers are supposed + * to send synthetic events with the correct information, but ICCCM + * doesn't require them to do this under all conditions, and the + * information provided doesn't include everything we need here. So, the + * code below maintains a bunch of information about the parent window. + * If the window hasn't been reparented, we pretend that there is a parent + * shrink-wrapped around the window. + */ + + if (dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf(" %s parent == %p, above %p\n", + winPtr->pathName, (void *) wmPtr->reparent, + (void *) configEventPtr->above); + } + + if ((wmPtr->reparent == None) || !ComputeReparentGeometry(wmPtr)) { + wmPtr->parentWidth = configEventPtr->width + + 2*configEventPtr->border_width; + wmPtr->parentHeight = configEventPtr->height + + 2*configEventPtr->border_width; + wrapperPtr->changes.x = wmPtr->x = configEventPtr->x; + wrapperPtr->changes.y = wmPtr->y = configEventPtr->y; + if (wmPtr->flags & WM_NEGATIVE_X) { + wmPtr->x = wmPtr->vRootWidth - (wmPtr->x + wmPtr->parentWidth); + } + if (wmPtr->flags & WM_NEGATIVE_Y) { + wmPtr->y = wmPtr->vRootHeight - (wmPtr->y + wmPtr->parentHeight); + } + } + + /* + * Make sure that the toplevel and menubar are properly positioned within + * the wrapper. If the menuHeight happens to be zero, we'll get a BadValue + * X error that we want to ignore [Bug: 3377] + */ + + handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, NULL, NULL); + XMoveResizeWindow(winPtr->display, winPtr->window, 0, + wmPtr->menuHeight, (unsigned) wrapperPtr->changes.width, + (unsigned) (wrapperPtr->changes.height - wmPtr->menuHeight)); + Tk_DeleteErrorHandler(handler); + if ((wmPtr->menubar != NULL) + && ((Tk_Width(wmPtr->menubar) != wrapperPtr->changes.width) + || (Tk_Height(wmPtr->menubar) != wmPtr->menuHeight))) { + Tk_MoveResizeWindow(wmPtr->menubar, 0, 0, wrapperPtr->changes.width, + wmPtr->menuHeight); + } + + /* + * Update the coordinates in the toplevel (they should refer to the + * position in root window coordinates, not the coordinates of the wrapper + * window). Then synthesize a ConfigureNotify event to tell the + * application about the change. + */ + + winPtr->changes.x = wrapperPtr->changes.x; + winPtr->changes.y = wrapperPtr->changes.y + wmPtr->menuHeight; + winPtr->changes.width = wrapperPtr->changes.width; + winPtr->changes.height = wrapperPtr->changes.height - wmPtr->menuHeight; + TkDoConfigureNotify(winPtr); +} + +/* + *---------------------------------------------------------------------- + * + * ReparentEvent -- + * + * This function is called to handle ReparentNotify events on wrapper + * windows. + * + * Results: + * None. + * + * Side effects: + * Information gets updated in the WmInfo structure for the window. + * + *---------------------------------------------------------------------- + */ + +static void +ReparentEvent( + WmInfo *wmPtr, /* Information about toplevel window. */ + XReparentEvent *reparentEventPtr) + /* Event that just occurred for + * wmPtr->wrapperPtr. */ +{ + TkWindow *wrapperPtr = wmPtr->wrapperPtr; + Window vRoot, ancestor, *children, dummy2, *virtualRootPtr, **vrPtrPtr; + Atom actualType; + int actualFormat; + unsigned long numItems, bytesAfter; + unsigned dummy; + Tk_ErrorHandler handler; + TkDisplay *dispPtr = wmPtr->winPtr->dispPtr; + Atom WM_ROOT = Tk_InternAtom((Tk_Window) wrapperPtr, "__WM_ROOT"); + Atom SWM_ROOT = Tk_InternAtom((Tk_Window) wrapperPtr, "__SWM_ROOT"); + + /* + * Identify the root window for wrapperPtr. This is tricky because of + * virtual root window managers like tvtwm. If the window has a property + * named __SWM_ROOT or __WM_ROOT then this property gives the id for a + * virtual root window that should be used instead of the root window of + * the screen. + */ + + vRoot = RootWindow(wrapperPtr->display, wrapperPtr->screenNum); + wmPtr->vRoot = None; + handler = Tk_CreateErrorHandler(wrapperPtr->display, -1,-1,-1, NULL,NULL); + vrPtrPtr = &virtualRootPtr; /* Silence GCC warning */ + if ((GetWindowProperty(wrapperPtr, WM_ROOT, 1, XA_WINDOW, + &actualType, &actualFormat, &numItems, &bytesAfter, vrPtrPtr) + && (actualType == XA_WINDOW)) + || (GetWindowProperty(wrapperPtr, SWM_ROOT, 1, XA_WINDOW, + &actualType, &actualFormat, &numItems, &bytesAfter, vrPtrPtr) + && (actualType == XA_WINDOW))) { + if ((actualFormat == 32) && (numItems == 1)) { + vRoot = wmPtr->vRoot = *virtualRootPtr; + } else if (dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("%s format %d numItems %ld\n", + "ReparentEvent got bogus VROOT property:", actualFormat, + numItems); + } + XFree((char *) virtualRootPtr); + } + Tk_DeleteErrorHandler(handler); + + if (dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("ReparentEvent: %s (%p) reparented to 0x%x, vRoot = 0x%x\n", + wmPtr->winPtr->pathName, wmPtr->winPtr, + (unsigned) reparentEventPtr->parent, (unsigned) vRoot); + } + + /* + * Fetch correct geometry information for the new virtual root. + */ + + UpdateVRootGeometry(wmPtr); + + /* + * If the window's new parent is the root window, then mark it as no + * longer reparented. + */ + + if (reparentEventPtr->parent == vRoot) { + noReparent: + wmPtr->reparent = None; + wmPtr->parentWidth = wrapperPtr->changes.width; + wmPtr->parentHeight = wrapperPtr->changes.height; + wmPtr->xInParent = wmPtr->yInParent = 0; + wrapperPtr->changes.x = reparentEventPtr->x; + wrapperPtr->changes.y = reparentEventPtr->y; + wmPtr->winPtr->changes.x = reparentEventPtr->x; + wmPtr->winPtr->changes.y = reparentEventPtr->y + wmPtr->menuHeight; + return; + } + + /* + * Search up the window hierarchy to find the ancestor of this window that + * is just below the (virtual) root. This is tricky because it's possible + * that things have changed since the event was generated so that the + * ancestry indicated by the event no longer exists. If this happens then + * an error will occur and we just discard the event (there will be a more + * up-to-date ReparentNotify event coming later). + */ + + handler = Tk_CreateErrorHandler(wrapperPtr->display, -1,-1,-1, NULL,NULL); + wmPtr->reparent = reparentEventPtr->parent; + while (1) { + if (XQueryTree(wrapperPtr->display, wmPtr->reparent, &dummy2, + &ancestor, &children, &dummy) == 0) { + Tk_DeleteErrorHandler(handler); + goto noReparent; + } + XFree((char *) children); + if ((ancestor == vRoot) || + (ancestor == RootWindow(wrapperPtr->display, + wrapperPtr->screenNum))) { + break; + } + wmPtr->reparent = ancestor; + } + Tk_DeleteErrorHandler(handler); + + if (!ComputeReparentGeometry(wmPtr)) { + goto noReparent; + } +} + +/* + *---------------------------------------------------------------------- + * + * ComputeReparentGeometry -- + * + * This function is invoked to recompute geometry information related to + * a reparented top-level window, such as the position and total size of + * the parent and the position within it of the top-level window. + * + * Results: + * The return value is 1 if everything completed successfully and 0 if an + * error occurred while querying information about winPtr's parents. In + * this case winPtr is marked as no longer being reparented. + * + * Side effects: + * Geometry information in wmPtr, wmPtr->winPtr, and wmPtr->wrapperPtr + * gets updated. + * + *---------------------------------------------------------------------- + */ + +static int +ComputeReparentGeometry( + WmInfo *wmPtr) /* Information about toplevel window whose + * reparent info is to be recomputed. */ +{ + TkWindow *wrapperPtr = wmPtr->wrapperPtr; + int width, height, bd; + unsigned dummy; + int xOffset, yOffset, x, y; + Window dummy2; + Status status; + Tk_ErrorHandler handler; + TkDisplay *dispPtr = wmPtr->winPtr->dispPtr; + + handler = Tk_CreateErrorHandler(wrapperPtr->display, -1,-1,-1, NULL,NULL); + (void) XTranslateCoordinates(wrapperPtr->display, wrapperPtr->window, + wmPtr->reparent, 0, 0, &xOffset, &yOffset, &dummy2); + status = XGetGeometry(wrapperPtr->display, wmPtr->reparent, + &dummy2, &x, &y, (unsigned *) &width, (unsigned *) &height, + (unsigned *) &bd, &dummy); + Tk_DeleteErrorHandler(handler); + if (status == 0) { + /* + * It appears that the reparented parent went away and no-one told us. + * Reset the window to indicate that it's not reparented. + */ + + wmPtr->reparent = None; + wmPtr->xInParent = wmPtr->yInParent = 0; + return 0; + } + wmPtr->xInParent = xOffset + bd; + wmPtr->yInParent = yOffset + bd; + wmPtr->parentWidth = width + 2*bd; + wmPtr->parentHeight = height + 2*bd; + + /* + * Some tricky issues in updating wmPtr->x and wmPtr->y: + * + * 1. Don't update them if the event occurred because of something we did + * (i.e. WM_SYNC_PENDING and WM_MOVE_PENDING are both set). This is + * because window managers treat coords differently than Tk, and no two + * window managers are alike. If the window manager moved the window + * because we told it to, remember the coordinates we told it, not the + * ones it actually moved it to. This allows us to move the window back to + * the same coordinates later and get the same result. Without this check, + * windows can "walk" across the screen under some conditions. + * + * 2. Don't update wmPtr->x and wmPtr->y unless wrapperPtr->changes.x or + * wrapperPtr->changes.y has changed (otherwise a size change can spoof us + * into thinking that the position changed too and defeat the intent of + * (1) above. + * + * (As of 9/96 the above 2 comments appear to be stale. They're being left + * in place as a reminder of what was once true (and perhaps should still + * be true?)). + * + * 3. Ignore size changes coming from the window system if we're about to + * change the size ourselves but haven't seen the event for it yet: our + * size change is supposed to take priority. + */ + + if (!(wmPtr->flags & WM_MOVE_PENDING) + && ((wrapperPtr->changes.x != (x + wmPtr->xInParent)) + || (wrapperPtr->changes.y != (y + wmPtr->yInParent)))) { + wmPtr->x = x; + if (wmPtr->flags & WM_NEGATIVE_X) { + wmPtr->x = wmPtr->vRootWidth - (wmPtr->x + wmPtr->parentWidth); + } + wmPtr->y = y; + if (wmPtr->flags & WM_NEGATIVE_Y) { + wmPtr->y = wmPtr->vRootHeight - (wmPtr->y + wmPtr->parentHeight); + } + } + + wrapperPtr->changes.x = x + wmPtr->xInParent; + wrapperPtr->changes.y = y + wmPtr->yInParent; + if (dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("wrapperPtr %p coords %d,%d\n", + wrapperPtr, wrapperPtr->changes.x, wrapperPtr->changes.y); + printf(" wmPtr %p coords %d,%d, offsets %d %d\n", + wmPtr, wmPtr->x, wmPtr->y, wmPtr->xInParent, wmPtr->yInParent); + } + return 1; +} + +/* + *---------------------------------------------------------------------- + * + * PropertyEvent -- + * + * Handle PropertyNotify events on wrapper windows. The following + * properties are of interest: + * + * _NET_WM_STATE: + * Used to keep wmPtr->attributes up to date. + * + *---------------------------------------------------------------------- + */ + +static void +PropertyEvent( + WmInfo *wmPtr, /* Information about toplevel window. */ + XPropertyEvent *eventPtr) /* PropertyNotify event structure */ +{ + TkWindow *wrapperPtr = wmPtr->wrapperPtr; + Atom _NET_WM_STATE = + Tk_InternAtom((Tk_Window) wmPtr->winPtr, "_NET_WM_STATE"); + + if (eventPtr->atom == _NET_WM_STATE) { + Atom actualType; + int actualFormat; + unsigned long numItems, bytesAfter; + unsigned char *propertyValue = 0; + long maxLength = 1024; + + if (GetWindowProperty(wrapperPtr, _NET_WM_STATE, maxLength, XA_ATOM, + &actualType, &actualFormat, &numItems, &bytesAfter, + &propertyValue)) { + CheckNetWmState(wmPtr, (Atom *) propertyValue, (int) numItems); + XFree(propertyValue); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * WrapperEventProc -- + * + * This function is invoked by the event loop when a wrapper window is + * restructured. + * + * Results: + * None. + * + * Side effects: + * Tk's internal data structures for the window get modified to reflect + * the structural change. + * + *---------------------------------------------------------------------- + */ + +static const unsigned WrapperEventMask = + (StructureNotifyMask | PropertyChangeMask); + +static void +WrapperEventProc( + ClientData clientData, /* Information about toplevel window. */ + XEvent *eventPtr) /* Event that just happened. */ +{ + WmInfo *wmPtr = clientData; + XEvent mapEvent; + TkDisplay *dispPtr = wmPtr->winPtr->dispPtr; + + wmPtr->flags |= WM_VROOT_OFFSET_STALE; + if (eventPtr->type == DestroyNotify) { + Tk_ErrorHandler handler; + + if (!(wmPtr->wrapperPtr->flags & TK_ALREADY_DEAD)) { + /* + * A top-level window was deleted externally (e.g., by the window + * manager). This is probably not a good thing, but cleanup as + * best we can. The error handler is needed because + * Tk_DestroyWindow will try to destroy the window, but of course + * it's already gone. + */ + + handler = Tk_CreateErrorHandler(wmPtr->winPtr->display, -1, -1, -1, + NULL, NULL); + Tk_DestroyWindow((Tk_Window) wmPtr->winPtr); + Tk_DeleteErrorHandler(handler); + } + if (dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("TopLevelEventProc: %s deleted\n", wmPtr->winPtr->pathName); + } + } else if (eventPtr->type == ConfigureNotify) { + /* + * Ignore the event if the window has never been mapped yet. Such an + * event occurs only in weird cases like changing the internal border + * width of a top-level window, which results in a synthetic Configure + * event. These events are not relevant to us, and if we process them + * confusion may result (e.g. we may conclude erroneously that the + * user repositioned or resized the window). + */ + + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + ConfigureEvent(wmPtr, &eventPtr->xconfigure); + } + } else if (eventPtr->type == MapNotify) { + wmPtr->wrapperPtr->flags |= TK_MAPPED; + wmPtr->winPtr->flags |= TK_MAPPED; + XMapWindow(wmPtr->winPtr->display, wmPtr->winPtr->window); + goto doMapEvent; + } else if (eventPtr->type == UnmapNotify) { + wmPtr->wrapperPtr->flags &= ~TK_MAPPED; + wmPtr->winPtr->flags &= ~TK_MAPPED; + XUnmapWindow(wmPtr->winPtr->display, wmPtr->winPtr->window); + goto doMapEvent; + } else if (eventPtr->type == ReparentNotify) { + ReparentEvent(wmPtr, &eventPtr->xreparent); + } else if (eventPtr->type == PropertyNotify) { + PropertyEvent(wmPtr, &eventPtr->xproperty); + } + return; + + doMapEvent: + mapEvent = *eventPtr; + mapEvent.xmap.event = wmPtr->winPtr->window; + mapEvent.xmap.window = wmPtr->winPtr->window; + Tk_HandleEvent(&mapEvent); +} + +/* + *---------------------------------------------------------------------- + * + * TopLevelReqProc -- + * + * This function is invoked by the geometry manager whenever the + * requested size for a top-level window is changed. + * + * Results: + * None. + * + * Side effects: + * Arrange for the window to be resized to satisfy the request (this + * happens as a when-idle action). + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +static void +TopLevelReqProc( + ClientData dummy, /* Not used. */ + Tk_Window tkwin) /* Information about window. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (wmPtr == NULL) { + return; + } + + if ((wmPtr->width >= 0) && (wmPtr->height >= 0)) { + /* + * Explicit dimensions have been set for this window, so we should + * ignore the geometry request. It's actually important to ignore the + * geometry request because, due to quirks in window managers, + * invoking UpdateGeometryInfo may cause the window to move. For + * example, if "wm geometry -10-20" was invoked, the window may be + * positioned incorrectly the first time it appears (because we didn't + * know the proper width of the window manager borders); if we invoke + * UpdateGeometryInfo again, the window will be positioned correctly, + * which may cause it to jump on the screen. + */ + + return; + } + + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr); + wmPtr->flags |= WM_UPDATE_PENDING; + } + + /* + * If the window isn't being positioned by its upper left corner then we + * have to move it as well. + */ + + if (wmPtr->flags & (WM_NEGATIVE_X | WM_NEGATIVE_Y)) { + wmPtr->flags |= WM_MOVE_PENDING; + } +} + +/* + *---------------------------------------------------------------------- + * + * UpdateGeometryInfo -- + * + * This function is invoked when a top-level window is first mapped, and + * also as a when-idle function, to bring the geometry and/or position of + * a top-level window back into line with what has been requested by the + * user and/or widgets. This function doesn't return until the window + * manager has responded to the geometry change. + * + * Results: + * None. + * + * Side effects: + * The size and location of both the toplevel window and its wrapper may + * change, unless the WM prevents that from happening. + * + *---------------------------------------------------------------------- + */ + +static void +UpdateGeometryInfo( + ClientData clientData) /* Pointer to the window's record. */ +{ + register TkWindow *winPtr = clientData; + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int x, y, width, height, min, max; + unsigned long serial; + + wmPtr->flags &= ~WM_UPDATE_PENDING; + + /* + * Compute the new size for the top-level window. See the user + * documentation for details on this, but the size requested depends on + * (a) the size requested internally by the window's widgets, (b) the size + * requested by the user in a "wm geometry" command or via wm-based + * interactive resizing (if any), (c) whether or not the window is + * gridded, and (d) the current min or max size for the toplevel. Don't + * permit sizes <= 0 because this upsets the X server. + */ + + if (wmPtr->width == -1) { + width = winPtr->reqWidth; + } else if (wmPtr->gridWin != NULL) { + width = winPtr->reqWidth + + (wmPtr->width - wmPtr->reqGridWidth)*wmPtr->widthInc; + } else { + width = wmPtr->width; + } + if (width <= 0) { + width = 1; + } + + /* + * Account for window max/min width + */ + + if (wmPtr->gridWin != NULL) { + min = winPtr->reqWidth + + (wmPtr->minWidth - wmPtr->reqGridWidth)*wmPtr->widthInc; + if (wmPtr->maxWidth > 0) { + max = winPtr->reqWidth + + (wmPtr->maxWidth - wmPtr->reqGridWidth)*wmPtr->widthInc; + } else { + max = 0; + } + } else { + min = wmPtr->minWidth; + max = wmPtr->maxWidth; + } + if (width < min) { + width = min; + } else if ((max > 0) && (width > max)) { + width = max; + } + + if (wmPtr->height == -1) { + height = winPtr->reqHeight; + } else if (wmPtr->gridWin != NULL) { + height = winPtr->reqHeight + + (wmPtr->height - wmPtr->reqGridHeight)*wmPtr->heightInc; + } else { + height = wmPtr->height; + } + if (height <= 0) { + height = 1; + } + + /* + * Account for window max/min height + */ + + if (wmPtr->gridWin != NULL) { + min = winPtr->reqHeight + + (wmPtr->minHeight - wmPtr->reqGridHeight)*wmPtr->heightInc; + if (wmPtr->maxHeight > 0) { + max = winPtr->reqHeight + + (wmPtr->maxHeight - wmPtr->reqGridHeight)*wmPtr->heightInc; + } else { + max = 0; + } + } else { + min = wmPtr->minHeight; + max = wmPtr->maxHeight; + } + if (height < min) { + height = min; + } else if ((max > 0) && (height > max)) { + height = max; + } + + /* + * Compute the new position for the upper-left pixel of the window's + * decorative frame. This is tricky, because we need to include the border + * widths supplied by a reparented parent in this calculation, but can't + * use the parent's current overall size since that may change as a result + * of this code. + */ + + if (wmPtr->flags & WM_NEGATIVE_X) { + x = wmPtr->vRootWidth - wmPtr->x + - (width + (wmPtr->parentWidth - winPtr->changes.width)); + } else { + x = wmPtr->x; + } + if (wmPtr->flags & WM_NEGATIVE_Y) { + y = wmPtr->vRootHeight - wmPtr->y + - (height + (wmPtr->parentHeight - winPtr->changes.height)); + } else { + y = wmPtr->y; + } + + /* + * If the window's size is going to change and the window is supposed to + * not be resizable by the user, then we have to update the size hints. + * There may also be a size-hint-update request pending from somewhere + * else, too. + */ + + if (((width != winPtr->changes.width) + || (height != winPtr->changes.height)) + && (wmPtr->gridWin == NULL) + && !(wmPtr->sizeHintsFlags & (PMinSize|PMaxSize))) { + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + } + if (wmPtr->flags & WM_UPDATE_SIZE_HINTS) { + UpdateSizeHints(winPtr, width, height); + } + + /* + * Reconfigure the wrapper if it isn't already configured correctly. A few + * tricky points: + * + * 1. If the window is embedded and the container is also in this process, + * don't actually reconfigure the window; just pass the desired size on + * to the container. Also, zero out any position information, since + * embedded windows are not allowed to move. + * 2. Sometimes the window manager will give us a different size than we + * asked for (e.g. mwm has a minimum size for windows), so base the + * size check on what we *asked for* last time, not what we got. + * 3. Can't just reconfigure always, because we may not get a + * ConfigureNotify event back if nothing changed, so + * WaitForConfigureNotify will hang a long time. + * 4. Don't move window unless a new position has been requested for it. + * This is because of "features" in some window managers (e.g. twm, as + * of 4/24/91) where they don't interpret coordinates according to + * ICCCM. Moving a window to its current location may cause it to shift + * position on the screen. + */ + + if ((winPtr->flags & (TK_EMBEDDED|TK_BOTH_HALVES)) + == (TK_EMBEDDED|TK_BOTH_HALVES)) { + TkWindow *childPtr = TkpGetOtherWindow(winPtr); + + /* + * This window is embedded and the container is also in this process, + * so we don't need to do anything special about the geometry, except + * to make sure that the desired size is known by the container. Also, + * zero out any position information, since embedded windows are not + * allowed to move. + */ + + wmPtr->x = wmPtr->y = 0; + wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y); + height += wmPtr->menuHeight; + if (childPtr != NULL) { + Tk_GeometryRequest((Tk_Window) childPtr, width, height); + } + return; + } + serial = NextRequest(winPtr->display); + height += wmPtr->menuHeight; + if (wmPtr->flags & WM_MOVE_PENDING) { + if ((x + wmPtr->xInParent == winPtr->changes.x) && + (y+wmPtr->yInParent+wmPtr->menuHeight == winPtr->changes.y) + && (width == wmPtr->wrapperPtr->changes.width) + && (height == wmPtr->wrapperPtr->changes.height)) { + /* + * The window already has the correct geometry, so don't bother to + * configure it; the X server appears to ignore these requests, so + * we won't get back a ConfigureNotify and the + * WaitForConfigureNotify call below will hang for a while. + */ + + wmPtr->flags &= ~WM_MOVE_PENDING; + return; + } + wmPtr->configWidth = width; + wmPtr->configHeight = height; + if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("UpdateGeometryInfo moving to %d %d, resizing to %dx%d,\n", + x, y, width, height); + } + XMoveResizeWindow(winPtr->display, wmPtr->wrapperPtr->window, x, y, + (unsigned) width, (unsigned) height); + } else if ((width != wmPtr->configWidth) + || (height != wmPtr->configHeight)) { + if ((width == wmPtr->wrapperPtr->changes.width) + && (height == wmPtr->wrapperPtr->changes.height)) { + /* + * The window is already just the size we want, so don't bother to + * configure it; the X server appears to ignore these requests, so + * we won't get back a ConfigureNotify and the + * WaitForConfigureNotify call below will hang for a while. + */ + + return; + } + wmPtr->configWidth = width; + wmPtr->configHeight = height; + if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("UpdateGeometryInfo resizing %p to %d x %d\n", + (void *) wmPtr->wrapperPtr->window, width, height); + } + XResizeWindow(winPtr->display, wmPtr->wrapperPtr->window, + (unsigned) width, (unsigned) height); + } else if ((wmPtr->menubar != NULL) + && ((Tk_Width(wmPtr->menubar) != wmPtr->wrapperPtr->changes.width) + || (Tk_Height(wmPtr->menubar) != wmPtr->menuHeight))) { + /* + * It is possible that the window's overall size has not changed but + * the menu size has. + */ + + Tk_MoveResizeWindow(wmPtr->menubar, 0, 0, + wmPtr->wrapperPtr->changes.width, wmPtr->menuHeight); + XResizeWindow(winPtr->display, wmPtr->wrapperPtr->window, + (unsigned) width, (unsigned) height); + } else { + return; + } + + /* + * Wait for the configure operation to complete. Don't need to do this, + * however, if the window is about to be mapped: it will be taken care of + * elsewhere. + */ + + if (!(wmPtr->flags & WM_ABOUT_TO_MAP)) { + WaitForConfigureNotify(winPtr, serial); + } +} + +/* + *-------------------------------------------------------------- + * + * UpdateSizeHints -- + * + * This function is called to update the window manager's size hints + * information from the information in a WmInfo structure. + * + * Results: + * None. + * + * Side effects: + * Properties get changed for winPtr. + * + *-------------------------------------------------------------- + */ + +static void +UpdateSizeHints( + TkWindow *winPtr, + int newWidth, + int newHeight) +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + XSizeHints *hintsPtr; + int maxWidth, maxHeight; + + wmPtr->flags &= ~WM_UPDATE_SIZE_HINTS; + + hintsPtr = XAllocSizeHints(); + if (hintsPtr == NULL) { + return; + } + + /* + * Compute the pixel-based sizes for the various fields in the size hints + * structure, based on the grid-based sizes in our structure. + */ + + GetMaxSize(wmPtr, &maxWidth, &maxHeight); + if (wmPtr->gridWin != NULL) { + hintsPtr->base_width = winPtr->reqWidth + - (wmPtr->reqGridWidth * wmPtr->widthInc); + if (hintsPtr->base_width < 0) { + hintsPtr->base_width = 0; + } + hintsPtr->base_height = winPtr->reqHeight + wmPtr->menuHeight + - (wmPtr->reqGridHeight * wmPtr->heightInc); + if (hintsPtr->base_height < 0) { + hintsPtr->base_height = 0; + } + hintsPtr->min_width = hintsPtr->base_width + + (wmPtr->minWidth * wmPtr->widthInc); + hintsPtr->min_height = hintsPtr->base_height + + (wmPtr->minHeight * wmPtr->heightInc); + hintsPtr->max_width = hintsPtr->base_width + + (maxWidth * wmPtr->widthInc); + hintsPtr->max_height = hintsPtr->base_height + + (maxHeight * wmPtr->heightInc); + } else { + hintsPtr->min_width = wmPtr->minWidth; + hintsPtr->min_height = wmPtr->minHeight; + hintsPtr->max_width = maxWidth; + hintsPtr->max_height = maxHeight; + hintsPtr->base_width = 0; + hintsPtr->base_height = 0; + } + hintsPtr->width_inc = wmPtr->widthInc; + hintsPtr->height_inc = wmPtr->heightInc; + hintsPtr->min_aspect.x = wmPtr->minAspect.x; + hintsPtr->min_aspect.y = wmPtr->minAspect.y; + hintsPtr->max_aspect.x = wmPtr->maxAspect.x; + hintsPtr->max_aspect.y = wmPtr->maxAspect.y; + hintsPtr->win_gravity = wmPtr->gravity; + hintsPtr->flags = wmPtr->sizeHintsFlags | PMinSize; + + /* + * If the window isn't supposed to be resizable, then set the minimum and + * maximum dimensions to be the same. + */ + + if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) { + hintsPtr->max_width = hintsPtr->min_width = newWidth; + hintsPtr->flags |= PMaxSize; + } + if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) { + hintsPtr->max_height = hintsPtr->min_height = + newHeight + wmPtr->menuHeight; + hintsPtr->flags |= PMaxSize; + } + + XSetWMNormalHints(winPtr->display, wmPtr->wrapperPtr->window, hintsPtr); + + XFree((char *) hintsPtr); +} + +/* + *-------------------------------------------------------------- + * + * UpdateTitle -- + * + * This function is called to update the window title and icon name. It + * sets the ICCCM-defined properties WM_NAME and WM_ICON_NAME for older + * window managers, and the freedesktop.org-defined _NET_WM_NAME and + * _NET_WM_ICON_NAME properties for newer ones. The ICCCM properties are + * stored in the system encoding, the newer properties are stored in + * UTF-8. + * + * NOTE: the ICCCM specifies that WM_NAME and WM_ICON_NAME are stored in + * ISO-Latin-1. Tk has historically used the default system encoding + * (since 8.1). It's not clear whether this is correct or not. + * + * Side effects: + * Properties get changed for winPtr. + * + *-------------------------------------------------------------- + */ + +static void +UpdateTitle( + TkWindow *winPtr) +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + Atom XA_UTF8_STRING = Tk_InternAtom((Tk_Window) winPtr, "UTF8_STRING"); + const char *string; + Tcl_DString ds; + + /* + * Set window title: + */ + + string = (wmPtr->title != NULL) ? wmPtr->title : winPtr->nameUid; + Tcl_UtfToExternalDString(NULL, string, -1, &ds); + XStoreName(winPtr->display, wmPtr->wrapperPtr->window, + Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); + + SetWindowProperty(wmPtr->wrapperPtr, "_NET_WM_NAME", XA_UTF8_STRING, 8, + string, strlen(string)); + + /* + * Set icon name: + */ + + if (wmPtr->iconName != NULL) { + Tcl_UtfToExternalDString(NULL, wmPtr->iconName, -1, &ds); + XSetIconName(winPtr->display, wmPtr->wrapperPtr->window, + Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); + + SetWindowProperty(wmPtr->wrapperPtr, "_NET_WM_ICON_NAME", + XA_UTF8_STRING, 8, wmPtr->iconName, strlen(wmPtr->iconName)); + } +} + +/* + *-------------------------------------------------------------- + * + * UpdatePhotoIcon -- + * + * This function is called to update the window photo icon. It sets the + * EWMH-defined properties _NET_WM_ICON. + * + * Side effects: + * Properties get changed for winPtr. + * + *-------------------------------------------------------------- + */ + +static void +UpdatePhotoIcon( + TkWindow *winPtr) +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + unsigned char *data = wmPtr->iconDataPtr; + int size = wmPtr->iconDataSize; + + if (data == NULL) { + data = winPtr->dispPtr->iconDataPtr; + size = winPtr->dispPtr->iconDataSize; + } + if (data != NULL) { + SetWindowProperty(wmPtr->wrapperPtr, "_NET_WM_ICON", XA_CARDINAL, 32, + data, size); + } +} + +/* + *---------------------------------------------------------------------- + * + * SetNetWmState -- + * + * Sets the specified state property by sending a _NET_WM_STATE + * ClientMessage to the root window. + * + * Preconditions: + * Wrapper window must be created. + * + * See also: + * UpdateNetWmState; EWMH spec, section _NET_WM_STATE. + * + *---------------------------------------------------------------------- + */ + +#define _NET_WM_STATE_REMOVE 0l +#define _NET_WM_STATE_ADD 1l +#define _NET_WM_STATE_TOGGLE 2l + +static void +SetNetWmState( + TkWindow *winPtr, + const char *atomName, + int on) +{ + Tk_Window tkwin = (Tk_Window) winPtr; + Atom messageType = Tk_InternAtom(tkwin, "_NET_WM_STATE"); + Atom action = on ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; + Atom property = Tk_InternAtom(tkwin, atomName); + XEvent e; + + if (!winPtr->wmInfoPtr->wrapperPtr) { + return; + } + + e.xany.type = ClientMessage; + e.xany.window = winPtr->wmInfoPtr->wrapperPtr->window; + e.xclient.message_type = messageType; + e.xclient.format = 32; + e.xclient.data.l[0] = action; + e.xclient.data.l[1] = property; + e.xclient.data.l[2] = e.xclient.data.l[3] = e.xclient.data.l[4] = 0l; + + XSendEvent(winPtr->display, + RootWindow(winPtr->display, winPtr->screenNum), 0, + SubstructureNotifyMask|SubstructureRedirectMask, &e); +} + +/* + *---------------------------------------------------------------------- + * + * CheckNetWmState -- + * + * Updates the window attributes whenever the _NET_WM_STATE property + * changes. + * + * Notes: + * + * Tk uses a single -zoomed state, while the EWMH spec supports separate + * vertical and horizontal maximization. We consider the window to be + * "zoomed" if _NET_WM_STATE_MAXIMIZED_VERT and + * _NET_WM_STATE_MAXIMIZED_HORZ are both set. + * + *---------------------------------------------------------------------- + */ + +static void +CheckNetWmState( + WmInfo *wmPtr, + Atom *atoms, + int numAtoms) +{ + Tk_Window tkwin = (Tk_Window) wmPtr->wrapperPtr; + int i; + Atom _NET_WM_STATE_ABOVE + = Tk_InternAtom(tkwin, "_NET_WM_STATE_ABOVE"), + _NET_WM_STATE_MAXIMIZED_VERT + = Tk_InternAtom(tkwin, "_NET_WM_STATE_MAXIMIZED_VERT"), + _NET_WM_STATE_MAXIMIZED_HORZ + = Tk_InternAtom(tkwin, "_NET_WM_STATE_MAXIMIZED_HORZ"), + _NET_WM_STATE_FULLSCREEN + = Tk_InternAtom(tkwin, "_NET_WM_STATE_FULLSCREEN"); + + wmPtr->attributes.topmost = 0; + wmPtr->attributes.zoomed = 0; + wmPtr->attributes.fullscreen = 0; + for (i = 0; i < numAtoms; ++i) { + if (atoms[i] == _NET_WM_STATE_ABOVE) { + wmPtr->attributes.topmost = 1; + } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT) { + wmPtr->attributes.zoomed |= 1; + } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) { + wmPtr->attributes.zoomed |= 2; + } else if (atoms[i] == _NET_WM_STATE_FULLSCREEN) { + wmPtr->attributes.fullscreen = 1; + } + } + + wmPtr->attributes.zoomed = (wmPtr->attributes.zoomed == 3); + + return; +} + +/* + *---------------------------------------------------------------------- + * + * UpdateNetWmState -- + * + * Sets the _NET_WM_STATE property to match the requested attribute state + * just prior to mapping a withdrawn window. + * + *---------------------------------------------------------------------- + */ + +#define NET_WM_STATE_MAX_ATOMS 4 + +static void +UpdateNetWmState( + WmInfo *wmPtr) +{ + Tk_Window tkwin = (Tk_Window) wmPtr->wrapperPtr; + Atom atoms[NET_WM_STATE_MAX_ATOMS]; + long numAtoms = 0; + + if (wmPtr->reqState.topmost) { + atoms[numAtoms++] = Tk_InternAtom(tkwin,"_NET_WM_STATE_ABOVE"); + } + if (wmPtr->reqState.zoomed) { + atoms[numAtoms++] = Tk_InternAtom(tkwin,"_NET_WM_STATE_MAXIMIZED_VERT"); + atoms[numAtoms++] = Tk_InternAtom(tkwin,"_NET_WM_STATE_MAXIMIZED_HORZ"); + } + if (wmPtr->reqState.fullscreen) { + atoms[numAtoms++] = Tk_InternAtom(tkwin, "_NET_WM_STATE_FULLSCREEN"); + } + + SetWindowProperty(wmPtr->wrapperPtr, "_NET_WM_STATE", XA_ATOM, 32, atoms, + numAtoms); +} + +/* + *---------------------------------------------------------------------- + * + * WaitForConfigureNotify -- + * + * This function is invoked in order to synchronize with the window + * manager. It waits for a ConfigureNotify event to arrive, signalling + * that the window manager has seen an attempt on our part to move or + * resize a top-level window. + * + * Results: + * None. + * + * Side effects: + * Delays the execution of the process until a ConfigureNotify event + * arrives with serial number at least as great as serial. This is useful + * for two reasons: + * + * 1. It's important to distinguish ConfigureNotify events that are + * coming in response to a request we've made from those generated + * spontaneously by the user. The reason for this is that if the user + * resizes the window we take that as an order to ignore geometry + * requests coming from inside the window hierarchy. If we + * accidentally interpret a response to our request as a user- + * initiated action, the window will stop responding to new geometry + * requests. To make this distinction, (a) this function sets a flag + * for TopLevelEventProc to indicate that we're waiting to sync with + * the wm, and (b) all changes to the size of a top-level window are + * followed by calls to this function. + * 2. Races and confusion can come about if there are multiple operations + * outstanding at a time (e.g. two different resizes of the top-level + * window: it's hard to tell which of the ConfigureNotify events + * coming back is for which request). + * While waiting, some events covered by StructureNotifyMask are + * processed (ConfigureNotify, MapNotify, and UnmapNotify) and all others + * are deferred. + * + *---------------------------------------------------------------------- + */ + +static void +WaitForConfigureNotify( + TkWindow *winPtr, /* Top-level window for which we want to see a + * ConfigureNotify. */ + unsigned long serial) /* Serial number of resize request. Want to be + * sure wm has seen this. */ +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + XEvent event; + int diff, code; + int gotConfig = 0; + + /* + * One more tricky detail about this function. In some cases the window + * manager will decide to ignore a configure request (e.g. because it + * thinks the window is already in the right place). To avoid hanging in + * this situation, only wait for a few seconds, then give up. + */ + + while (!gotConfig) { + wmPtr->flags |= WM_SYNC_PENDING; + code = WaitForEvent(winPtr->display, wmPtr, ConfigureNotify, &event); + wmPtr->flags &= ~WM_SYNC_PENDING; + if (code != TCL_OK) { + if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("WaitForConfigureNotify giving up on %s\n", + winPtr->pathName); + } + break; + } + diff = event.xconfigure.serial - serial; + if (diff >= 0) { + gotConfig = 1; + } + } + wmPtr->flags &= ~WM_MOVE_PENDING; + if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("WaitForConfigureNotify finished with %s, serial %ld\n", + winPtr->pathName, serial); + } +} + +/* + *---------------------------------------------------------------------- + * + * WaitForEvent -- + * + * This function is used by WaitForConfigureNotify and WaitForMapNotify + * to wait for an event of a certain type to arrive. + * + * Results: + * Under normal conditions, TCL_OK is returned and an event for display + * and window that matches "mask" is stored in *eventPtr. This event has + * already been processed by Tk before this function returns. If a long + * time goes by with no event of the right type arriving, or if an error + * occurs while waiting for the event to arrive, then TCL_ERROR is + * returned. + * + * Side effects: + * While waiting for the desired event to occur, Configurenotify, + * MapNotify, and UnmapNotify events for window are processed, as are all + * ReparentNotify events. + * + *---------------------------------------------------------------------- + */ + +static int +WaitForEvent( + Display *display, /* Display event is coming from. */ + WmInfo *wmInfoPtr, /* Window for which event is desired. */ + int type, /* Type of event that is wanted. */ + XEvent *eventPtr) /* Place to store event. */ +{ + WaitRestrictInfo info; + Tk_RestrictProc *prevProc; + ClientData prevArg; + Tcl_Time timeout; + + /* + * Set up an event filter to select just the events we want, and a timer + * handler, then wait for events until we get the event we want or a + * timeout happens. + */ + + info.display = display; + info.wmInfoPtr = wmInfoPtr; + info.type = type; + info.eventPtr = eventPtr; + info.foundEvent = 0; + prevProc = Tk_RestrictEvents(WaitRestrictProc, &info, &prevArg); + + Tcl_GetTime(&timeout); + timeout.sec += 2; + + while (!info.foundEvent) { + if (!TkUnixDoOneXEvent(&timeout)) { + break; + } + } + Tk_RestrictEvents(prevProc, prevArg, &prevArg); + if (info.foundEvent) { + return TCL_OK; + } + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * WaitRestrictProc -- + * + * This function is a Tk_RestrictProc that is used to filter events while + * WaitForEvent is active. + * + * Results: + * Returns TK_PROCESS_EVENT if the right event is found. Also returns + * TK_PROCESS_EVENT if any ReparentNotify event is found or if the event + * is a ConfigureNotify, MapNotify, or UnmapNotify for window. Otherwise + * returns TK_DEFER_EVENT. + * + * Side effects: + * An event may get stored in the area indicated by the caller of + * WaitForEvent. + * + *---------------------------------------------------------------------- + */ + +static Tk_RestrictAction +WaitRestrictProc( + ClientData clientData, /* Pointer to WaitRestrictInfo structure. */ + XEvent *eventPtr) /* Event that is about to be handled. */ +{ + WaitRestrictInfo *infoPtr = clientData; + + if (eventPtr->type == ReparentNotify) { + return TK_PROCESS_EVENT; + } + if (((eventPtr->xany.window != infoPtr->wmInfoPtr->wrapperPtr->window) + && (eventPtr->xany.window != infoPtr->wmInfoPtr->reparent)) + || (eventPtr->xany.display != infoPtr->display)) { + return TK_DEFER_EVENT; + } + if (eventPtr->type == infoPtr->type) { + *infoPtr->eventPtr = *eventPtr; + infoPtr->foundEvent = 1; + return TK_PROCESS_EVENT; + } + if (eventPtr->type == ConfigureNotify || eventPtr->type == MapNotify + || eventPtr->type == UnmapNotify) { + return TK_PROCESS_EVENT; + } + return TK_DEFER_EVENT; +} + +/* + *---------------------------------------------------------------------- + * + * WaitForMapNotify -- + * + * This function is invoked in order to synchronize with the window + * manager. It waits for the window's mapped state to reach the value + * given by mapped. + * + * Results: + * None. + * + * Side effects: + * Delays the execution of the process until winPtr becomes mapped or + * unmapped, depending on the "mapped" argument. This allows us to + * synchronize with the window manager, and allows us to identify changes + * in window size that come about when the window manager first starts + * managing the window (as opposed to those requested interactively by + * the user later). See the comments for WaitForConfigureNotify and + * WM_SYNC_PENDING. While waiting, some events covered by + * StructureNotifyMask are processed and all others are deferred. + * + *---------------------------------------------------------------------- + */ + +static void +WaitForMapNotify( + TkWindow *winPtr, /* Top-level window for which we want to see a + * particular mapping state. */ + int mapped) /* If non-zero, wait for window to become + * mapped, otherwise wait for it to become + * unmapped. */ +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + XEvent event; + int code; + + while (1) { + if (mapped) { + if (winPtr->flags & TK_MAPPED) { + break; + } + } else if (!(winPtr->flags & TK_MAPPED)) { + break; + } + wmPtr->flags |= WM_SYNC_PENDING; + code = WaitForEvent(winPtr->display, wmPtr, + mapped ? MapNotify : UnmapNotify, &event); + wmPtr->flags &= ~WM_SYNC_PENDING; + if (code != TCL_OK) { + /* + * There are some bizarre situations in which the window manager + * can't respond or chooses not to (e.g. if we've got a grab set + * it can't respond). If this happens then just quit. + */ + + if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("WaitForMapNotify giving up on %s\n", winPtr->pathName); + } + break; + } + } + wmPtr->flags &= ~WM_MOVE_PENDING; + if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("WaitForMapNotify finished with %s (winPtr %p, wmPtr %p)\n", + winPtr->pathName, winPtr, wmPtr); + } +} + +/* + *-------------------------------------------------------------- + * + * UpdateHints -- + * + * This function is called to update the window manager's hints + * information from the information in a WmInfo structure. + * + * Results: + * None. + * + * Side effects: + * Properties get changed for winPtr. + * + *-------------------------------------------------------------- + */ + +static void +UpdateHints( + TkWindow *winPtr) +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (wmPtr->flags & WM_NEVER_MAPPED) { + return; + } + XSetWMHints(winPtr->display, wmPtr->wrapperPtr->window, &wmPtr->hints); +} + +/* + *---------------------------------------------------------------------- + * + * SetNetWmType -- + * + * Set the extended window manager hints for a toplevel window to the + * types provided. The specification states that this may be a list of + * window types in preferred order. To permit for future type + * definitions, the set of names is unconstrained and names are converted + * to upper-case and appended to "_NET_WM_WINDOW_TYPE_" before being + * converted to an Atom. + * + *---------------------------------------------------------------------- + */ + +static int +SetNetWmType( + TkWindow *winPtr, + Tcl_Obj *typePtr) +{ + Atom *atoms = NULL; + WmInfo *wmPtr; + Tcl_Obj **objv; + int objc, n; + Tk_Window tkwin = (Tk_Window) winPtr; + Tcl_Interp *interp = Tk_Interp(tkwin); + + if (TCL_OK != Tcl_ListObjGetElements(interp, typePtr, &objc, &objv)) { + return TCL_ERROR; + } + + if (!Tk_HasWrapper(tkwin)) { + return TCL_OK; /* error?? */ + } + + if (objc > 0) { + atoms = ckalloc(sizeof(Atom) * objc); + } + + for (n = 0; n < objc; ++n) { + Tcl_DString ds, dsName; + int len; + char *name = Tcl_GetStringFromObj(objv[n], &len); + + Tcl_UtfToUpper(name); + Tcl_UtfToExternalDString(NULL, name, len, &dsName); + Tcl_DStringInit(&ds); + Tcl_DStringAppend(&ds, "_NET_WM_WINDOW_TYPE_", 20); + Tcl_DStringAppend(&ds, Tcl_DStringValue(&dsName), + Tcl_DStringLength(&dsName)); + Tcl_DStringFree(&dsName); + atoms[n] = Tk_InternAtom(tkwin, Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); + } + + wmPtr = winPtr->wmInfoPtr; + if (wmPtr->wrapperPtr == NULL) { + CreateWrapper(wmPtr); + } + + SetWindowProperty(wmPtr->wrapperPtr, "_NET_WM_WINDOW_TYPE", XA_ATOM, 32, + atoms, objc); + + ckfree(atoms); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * GetNetWmType -- + * + * Read the extended window manager type hint from a window and return as + * a list of names suitable for use with SetNetWmType. + * + *---------------------------------------------------------------------- + */ + +static Tcl_Obj * +GetNetWmType( + TkWindow *winPtr) +{ + Atom typeAtom, actualType, *atoms; + int actualFormat; + unsigned long n, count, bytesAfter; + unsigned char *propertyValue = NULL; + long maxLength = 1024; + Tk_Window tkwin = (Tk_Window) winPtr; + TkWindow *wrapperPtr; + Tcl_Obj *typePtr; + Tcl_Interp *interp; + Tcl_DString ds; + + interp = Tk_Interp(tkwin); + typePtr = Tcl_NewListObj(0, NULL); + + if (winPtr->wmInfoPtr->wrapperPtr == NULL) { + CreateWrapper(winPtr->wmInfoPtr); + } + wrapperPtr = winPtr->wmInfoPtr->wrapperPtr; + + typeAtom = Tk_InternAtom(tkwin, "_NET_WM_WINDOW_TYPE"); + if (GetWindowProperty(wrapperPtr, typeAtom, maxLength, XA_ATOM, + &actualType, &actualFormat, &count, &bytesAfter, &propertyValue)){ + atoms = (Atom *) propertyValue; + for (n = 0; n < count; ++n) { + const char *name = Tk_GetAtomName(tkwin, atoms[n]); + + if (strncmp("_NET_WM_WINDOW_TYPE_", name, 20) == 0) { + Tcl_ExternalToUtfDString(NULL, name+20, -1, &ds); + Tcl_UtfToLower(Tcl_DStringValue(&ds)); + Tcl_ListObjAppendElement(interp, typePtr, + Tcl_NewStringObj(Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds))); + Tcl_DStringFree(&ds); + } + } + XFree(propertyValue); + } + + return typePtr; +} + +/* + *-------------------------------------------------------------- + * + * ParseGeometry -- + * + * This function parses a geometry string and updates information used to + * control the geometry of a top-level window. + * + * Results: + * A standard Tcl return value, plus an error message in the interp's + * result if an error occurs. + * + * Side effects: + * The size and/or location of winPtr may change. + * + *-------------------------------------------------------------- + */ + +static int +ParseGeometry( + Tcl_Interp *interp, /* Used for error reporting. */ + const char *string, /* String containing new geometry. Has the + * standard form "=wxh+x+y". */ + TkWindow *winPtr) /* Pointer to top-level window whose geometry + * is to be changed. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int x, y, width, height, flags; + char *end; + register const char *p = string; + + /* + * The leading "=" is optional. + */ + + if (*p == '=') { + p++; + } + + /* + * Parse the width and height, if they are present. Don't actually update + * any of the fields of wmPtr until we've successfully parsed the entire + * geometry string. + */ + + width = wmPtr->width; + height = wmPtr->height; + x = wmPtr->x; + y = wmPtr->y; + flags = wmPtr->flags; + if (isdigit(UCHAR(*p))) { + width = strtoul(p, &end, 10); + p = end; + if (*p != 'x') { + goto error; + } + p++; + if (!isdigit(UCHAR(*p))) { + goto error; + } + height = strtoul(p, &end, 10); + p = end; + } + + /* + * Parse the X and Y coordinates, if they are present. + */ + + if (*p != '\0') { + flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y); + if (*p == '-') { + flags |= WM_NEGATIVE_X; + } else if (*p != '+') { + goto error; + } + p++; + if (!isdigit(UCHAR(*p)) && (*p != '-')) { + goto error; + } + x = strtol(p, &end, 10); + p = end; + if (*p == '-') { + flags |= WM_NEGATIVE_Y; + } else if (*p != '+') { + goto error; + } + p++; + if (!isdigit(UCHAR(*p)) && (*p != '-')) { + goto error; + } + y = strtol(p, &end, 10); + if (*end != '\0') { + goto error; + } + + /* + * Assume that the geometry information came from the user, unless an + * explicit source has been specified. Otherwise most window managers + * assume that the size hints were program-specified and they ignore + * them. + */ + + if (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) { + wmPtr->sizeHintsFlags |= USPosition; + flags |= WM_UPDATE_SIZE_HINTS; + } + } + + /* + * Everything was parsed OK. Update the fields of *wmPtr and arrange for + * the appropriate information to be percolated out to the window manager + * at the next idle moment. + */ + + wmPtr->width = width; + wmPtr->height = height; + wmPtr->x = x; + wmPtr->y = y; + flags |= WM_MOVE_PENDING; + wmPtr->flags = flags; + + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr); + wmPtr->flags |= WM_UPDATE_PENDING; + } + return TCL_OK; + + error: + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "bad geometry specifier \"%s\"", string)); + Tcl_SetErrorCode(interp, "TK", "VALUE", "GEOMETRY", NULL); + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_GetRootCoords -- + * + * Given a token for a window, this function traces through the window's + * lineage to find the (virtual) root-window coordinates corresponding to + * point (0,0) in the window. + * + * Results: + * The locations pointed to by xPtr and yPtr are filled in with the root + * coordinates of the (0,0) point in tkwin. If a virtual root window is + * in effect for the window, then the coordinates in the virtual root are + * returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +Tk_GetRootCoords( + Tk_Window tkwin, /* Token for window. */ + int *xPtr, /* Where to store x-displacement of (0,0). */ + int *yPtr) /* Where to store y-displacement of (0,0). */ +{ + int x, y; + register TkWindow *winPtr = (TkWindow *) tkwin; + + /* + * Search back through this window's parents all the way to a top-level + * window, combining the offsets of each window within its parent. + */ + + x = y = 0; + while (1) { + x += winPtr->changes.x + winPtr->changes.border_width; + y += winPtr->changes.y + winPtr->changes.border_width; + if ((winPtr->wmInfoPtr != NULL) + && (winPtr->wmInfoPtr->menubar == (Tk_Window) winPtr)) { + /* + * This window is a special menubar; switch over to its associated + * toplevel, compensate for their differences in y coordinates, + * then continue with the toplevel (in case it's embedded). + */ + + y -= winPtr->wmInfoPtr->menuHeight; + winPtr = winPtr->wmInfoPtr->winPtr; + continue; + } + if (winPtr->flags & TK_TOP_LEVEL) { + TkWindow *otherPtr; + + if (!(winPtr->flags & TK_EMBEDDED)) { + break; + } + otherPtr = TkpGetOtherWindow(winPtr); + if (otherPtr == NULL) { + /* + * The container window is not in the same application. Query + * the X server. + */ + + Window root, dummyChild; + int rootX, rootY; + + root = winPtr->wmInfoPtr->vRoot; + if (root == None) { + root = RootWindowOfScreen(Tk_Screen((Tk_Window) winPtr)); + } + XTranslateCoordinates(winPtr->display, winPtr->window, + root, 0, 0, &rootX, &rootY, &dummyChild); + x += rootX; + y += rootY; + break; + } else { + /* + * The container window is in the same application. Let's + * query its coordinates. + */ + + winPtr = otherPtr; + continue; + } + } + winPtr = winPtr->parentPtr; + if (winPtr == NULL) { + break; + } + } + *xPtr = x; + *yPtr = y; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_CoordsToWindow -- + * + * Given the (virtual) root coordinates of a point, this function returns + * the token for the top-most window covering that point, if there exists + * such a window in this application. + * + * Results: + * The return result is either a token for the window corresponding to + * rootX and rootY, or else NULL to indicate that there is no such + * window. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tk_Window +Tk_CoordsToWindow( + int rootX, int rootY, /* Coordinates of point in root window. If a + * virtual-root window manager is in use, + * these coordinates refer to the virtual + * root, not the real root. */ + Tk_Window tkwin) /* Token for any window in application; used + * to identify the display. */ +{ + Window window, parent, child; + int x, y, childX, childY, tmpx, tmpy, bd; + WmInfo *wmPtr; + TkWindow *winPtr, *childPtr, *nextPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; + Tk_ErrorHandler handler = NULL; + + /* + * Step 1: scan the list of toplevel windows to see if there is a virtual + * root for the screen we're interested in. If so, we have to translate + * the coordinates from virtual root to root coordinates. + */ + + parent = window = RootWindowOfScreen(Tk_Screen(tkwin)); + x = rootX; + y = rootY; + for (wmPtr = (WmInfo *) dispPtr->firstWmPtr; wmPtr != NULL; + wmPtr = wmPtr->nextPtr) { + if (Tk_Screen(wmPtr->winPtr) != Tk_Screen(tkwin)) { + continue; + } + if (wmPtr->vRoot == None) { + continue; + } + UpdateVRootGeometry(wmPtr); + parent = wmPtr->vRoot; + break; + } + + /* + * Step 2: work down through the window hierarchy starting at the root. + * For each window, find the child that contains the given point and then + * see if this child is either a wrapper for one of our toplevel windows + * or a window manager decoration window for one of our toplevels. This + * approach handles several tricky cases: + * + * 1. There may be a virtual root window between the root and one of our + * toplevels. + * 2. If a toplevel is embedded, we may have to search through the + * windows of the container application(s) before getting to the + * toplevel. + */ + + handler = Tk_CreateErrorHandler(Tk_Display(tkwin), -1, -1, -1, NULL, NULL); + while (1) { + if (XTranslateCoordinates(Tk_Display(tkwin), parent, window, + x, y, &childX, &childY, &child) == False) { + /* + * We can end up here when the window is in the middle of being + * deleted + */ + + Tk_DeleteErrorHandler(handler); + return NULL; + } + if (child == None) { + Tk_DeleteErrorHandler(handler); + return NULL; + } + for (wmPtr = (WmInfo *) dispPtr->firstWmPtr; wmPtr != NULL; + wmPtr = wmPtr->nextPtr) { + if (wmPtr->reparent == child) { + goto gotToplevel; + } + if (wmPtr->wrapperPtr != NULL) { + if (child == wmPtr->wrapperPtr->window) { + goto gotToplevel; + } + } else if (child == wmPtr->winPtr->window) { + goto gotToplevel; + } + } + x = childX; + y = childY; + parent = window; + window = child; + } + + gotToplevel: + if (handler) { + /* + * Check value of handler, because we can reach this label from above + * or below + */ + + Tk_DeleteErrorHandler(handler); + handler = NULL; + } + winPtr = wmPtr->winPtr; + if (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr) { + return NULL; + } + + /* + * Step 3: at this point winPtr and wmPtr refer to the toplevel that + * contains the given coordinates, and childX and childY give the + * translated coordinates in the *parent* of the toplevel. Now decide + * whether the coordinates are in the menubar or the actual toplevel, and + * translate the coordinates into the coordinate system of that window. + */ + + x = childX - winPtr->changes.x; + y = childY - winPtr->changes.y; + if ((x < 0) || (x >= winPtr->changes.width) + || (y >= winPtr->changes.height)) { + return NULL; + } + if (y < 0) { + winPtr = (TkWindow *) wmPtr->menubar; + if (winPtr == NULL) { + return NULL; + } + y += wmPtr->menuHeight; + if (y < 0) { + return NULL; + } + } + + /* + * Step 4: work down through the hierarchy underneath the current window. + * At each level, scan through all the children to find the highest one in + * the stacking order that contains the point. Then repeat the whole + * process on that child. + */ + + while (1) { + nextPtr = NULL; + for (childPtr = winPtr->childList; childPtr != NULL; + childPtr = childPtr->nextPtr) { + if (!Tk_IsMapped(childPtr) + || (childPtr->flags & TK_TOP_HIERARCHY)) { + continue; + } + if (childPtr->flags & TK_REPARENTED) { + continue; + } + tmpx = x - childPtr->changes.x; + tmpy = y - childPtr->changes.y; + bd = childPtr->changes.border_width; + if ((tmpx >= -bd) && (tmpy >= -bd) + && (tmpx < (childPtr->changes.width + bd)) + && (tmpy < (childPtr->changes.height + bd))) { + nextPtr = childPtr; + } + } + if (nextPtr == NULL) { + break; + } + winPtr = nextPtr; + x -= winPtr->changes.x; + y -= winPtr->changes.y; + if ((winPtr->flags & TK_CONTAINER) + && (winPtr->flags & TK_BOTH_HALVES)) { + /* + * The window containing the point is a container, and the + * embedded application is in this same process. Switch over to + * the toplevel for the embedded application and start processing + * that toplevel from scratch. + */ + + winPtr = TkpGetOtherWindow(winPtr); + if (winPtr == NULL) { + return NULL; + } + wmPtr = winPtr->wmInfoPtr; + childX = x; + childY = y; + goto gotToplevel; + } + } + return (Tk_Window) winPtr; +} + +/* + *---------------------------------------------------------------------- + * + * UpdateVRootGeometry -- + * + * This function is called to update all the virtual root geometry + * information in wmPtr. + * + * Results: + * None. + * + * Side effects: + * The vRootX, vRootY, vRootWidth, and vRootHeight fields in wmPtr are + * filled with the most up-to-date information. + * + *---------------------------------------------------------------------- + */ + +static void +UpdateVRootGeometry( + WmInfo *wmPtr) /* Window manager information to be updated. + * The wmPtr->vRoot field must be valid. */ +{ + TkWindow *winPtr = wmPtr->winPtr; + int bd; + unsigned dummy; + Window dummy2; + Status status; + Tk_ErrorHandler handler; + + /* + * If this isn't a virtual-root window manager, just return information + * about the screen. + */ + + wmPtr->flags &= ~WM_VROOT_OFFSET_STALE; + if (wmPtr->vRoot == None) { + noVRoot: + wmPtr->vRootX = wmPtr->vRootY = 0; + wmPtr->vRootWidth = DisplayWidth(winPtr->display, winPtr->screenNum); + wmPtr->vRootHeight = DisplayHeight(winPtr->display, winPtr->screenNum); + return; + } + + /* + * Refresh the virtual root information if it's out of date. + */ + + handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, NULL, NULL); + status = XGetGeometry(winPtr->display, wmPtr->vRoot, + &dummy2, &wmPtr->vRootX, &wmPtr->vRootY, + (unsigned *) &wmPtr->vRootWidth, + (unsigned *) &wmPtr->vRootHeight, (unsigned *) &bd, + &dummy); + if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) { + printf("UpdateVRootGeometry: x = %d, y = %d, width = %d, ", + wmPtr->vRootX, wmPtr->vRootY, wmPtr->vRootWidth); + printf("height = %d, status = %d\n", wmPtr->vRootHeight, status); + } + Tk_DeleteErrorHandler(handler); + if (status == 0) { + /* + * The virtual root is gone! Pretend that it never existed. + */ + + wmPtr->vRoot = None; + goto noVRoot; + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_GetVRootGeometry -- + * + * This function returns information about the virtual root window + * corresponding to a particular Tk window. + * + * Results: + * The values at xPtr, yPtr, widthPtr, and heightPtr are set with the + * offset and dimensions of the root window corresponding to tkwin. If + * tkwin is being managed by a virtual root window manager these values + * correspond to the virtual root window being used for tkwin; otherwise + * the offsets will be 0 and the dimensions will be those of the screen. + * + * Side effects: + * Vroot window information is refreshed if it is out of date. + * + *---------------------------------------------------------------------- + */ + +void +Tk_GetVRootGeometry( + Tk_Window tkwin, /* Window whose virtual root is to be + * queried. */ + int *xPtr, int *yPtr, /* Store x and y offsets of virtual root + * here. */ + int *widthPtr, int *heightPtr) + /* Store dimensions of virtual root here. */ +{ + WmInfo *wmPtr; + TkWindow *winPtr = (TkWindow *) tkwin; + + /* + * Find the top-level window for tkwin, and locate the window manager + * information for that window. + */ + + while (!(winPtr->flags & TK_TOP_HIERARCHY) + && (winPtr->parentPtr != NULL)) { + winPtr = winPtr->parentPtr; + } + wmPtr = winPtr->wmInfoPtr; + if (wmPtr == NULL) { + /* Punt. */ + *xPtr = 0; + *yPtr = 0; + *widthPtr = 0; + *heightPtr = 0; + } + + /* + * Make sure that the geometry information is up-to-date, then copy it out + * to the caller. + */ + + if (wmPtr->flags & WM_VROOT_OFFSET_STALE) { + UpdateVRootGeometry(wmPtr); + } + *xPtr = wmPtr->vRootX; + *yPtr = wmPtr->vRootY; + *widthPtr = wmPtr->vRootWidth; + *heightPtr = wmPtr->vRootHeight; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_MoveToplevelWindow -- + * + * This function is called instead of Tk_MoveWindow to adjust the x-y + * location of a top-level window. It delays the actual move to a later + * time and keeps window-manager information up-to-date with the move + * + * Results: + * None. + * + * Side effects: + * The window is eventually moved so that its upper-left corner + * (actually, the upper-left corner of the window's decorative frame, if + * there is one) is at (x,y). + * + *---------------------------------------------------------------------- + */ + +void +Tk_MoveToplevelWindow( + Tk_Window tkwin, /* Window to move. */ + int x, int y) /* New location for window (within parent). */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + register WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (!(winPtr->flags & TK_TOP_LEVEL)) { + Tcl_Panic("Tk_MoveToplevelWindow called with non-toplevel window"); + } + wmPtr->x = x; + wmPtr->y = y; + wmPtr->flags |= WM_MOVE_PENDING; + wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y); + if (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) { + wmPtr->sizeHintsFlags |= USPosition; + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + } + + /* + * If the window has already been mapped, must bring its geometry + * up-to-date immediately, otherwise an event might arrive from the server + * that would overwrite wmPtr->x and wmPtr->y and lose the new position. + */ + + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + if (wmPtr->flags & WM_UPDATE_PENDING) { + Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr); + } + UpdateGeometryInfo(winPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * UpdateWmProtocols -- + * + * This function transfers the most up-to-date information about window + * manager protocols from the WmInfo structure to the actual property on + * the top-level window. + * + * Results: + * None. + * + * Side effects: + * The WM_PROTOCOLS property gets changed for wmPtr's window. + * + *---------------------------------------------------------------------- + */ + +static void +UpdateWmProtocols( + register WmInfo *wmPtr) /* Information about top-level window. */ +{ + register ProtocolHandler *protPtr; + Atom deleteWindowAtom, pingAtom; + int count; + Atom *arrayPtr, *atomPtr; + + /* + * There are only two tricky parts here. First, there could be any number + * of atoms for the window, so count them and malloc an array to hold all + * of their atoms. Second, we *always* want to respond to the + * WM_DELETE_WINDOW and _NET_WM_PING protocols, even if no-one's + * officially asked. + */ + + for (protPtr = wmPtr->protPtr, count = 2; protPtr != NULL; + protPtr = protPtr->nextPtr, count++) { + /* Empty loop body; we're just counting the handlers. */ + } + arrayPtr = ckalloc(count * sizeof(Atom)); + deleteWindowAtom = Tk_InternAtom((Tk_Window) wmPtr->winPtr, + "WM_DELETE_WINDOW"); + pingAtom = Tk_InternAtom((Tk_Window) wmPtr->winPtr, "_NET_WM_PING"); + arrayPtr[0] = deleteWindowAtom; + arrayPtr[1] = pingAtom; + for (protPtr = wmPtr->protPtr, atomPtr = &arrayPtr[1]; + protPtr != NULL; protPtr = protPtr->nextPtr) { + if (protPtr->protocol != deleteWindowAtom + && protPtr->protocol != pingAtom) { + *(atomPtr++) = protPtr->protocol; + } + } + SetWindowProperty(wmPtr->wrapperPtr, "WM_PROTOCOLS", XA_ATOM, 32, + arrayPtr, atomPtr-arrayPtr); + ckfree(arrayPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TkWmProtocolEventProc -- + * + * This function is called by the Tk_HandleEvent whenever a ClientMessage + * event arrives whose type is "WM_PROTOCOLS". This function handles the + * message from the window manager in an appropriate fashion. + * + * Results: + * None. + * + * Side effects: + * Depends on what sort of handler, if any, was set up for the protocol. + * + *---------------------------------------------------------------------- + */ + +void +TkWmProtocolEventProc( + TkWindow *winPtr, /* Window to which the event was sent. */ + XEvent *eventPtr) /* X event. */ +{ + WmInfo *wmPtr; + register ProtocolHandler *protPtr; + Atom protocol; + int result; + const char *protocolName; + Tcl_Interp *interp; + + protocol = (Atom) eventPtr->xclient.data.l[0]; + + /* + * If this is a _NET_WM_PING message, send it back to the root window + * immediately. We do that here because scripts *cannot* respond correctly + * to this protocol. + */ + + if (protocol == Tk_InternAtom((Tk_Window) winPtr, "_NET_WM_PING")) { + Window root = XRootWindow(winPtr->display, winPtr->screenNum); + + eventPtr->xclient.window = root; + (void) XSendEvent(winPtr->display, root, False, + (SubstructureNotifyMask|SubstructureRedirectMask), eventPtr); + return; + } + + wmPtr = winPtr->wmInfoPtr; + if (wmPtr == NULL) { + return; + } + + /* + * Note: it's very important to retrieve the protocol name now, before + * invoking the command, even though the name won't be used until after + * the command returns. This is because the command could delete winPtr, + * making it impossible for us to use it later in the call to + * Tk_GetAtomName. + */ + + protocolName = Tk_GetAtomName((Tk_Window) winPtr, protocol); + for (protPtr = wmPtr->protPtr; protPtr != NULL; + protPtr = protPtr->nextPtr) { + if (protocol == protPtr->protocol) { + Tcl_Preserve(protPtr); + interp = protPtr->interp; + Tcl_Preserve(interp); + result = Tcl_EvalEx(interp, protPtr->command, -1, TCL_EVAL_GLOBAL); + if (result != TCL_OK) { + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (command for \"%s\" window manager protocol)", + protocolName)); + Tcl_BackgroundException(interp, result); + } + Tcl_Release(interp); + Tcl_Release(protPtr); + return; + } + } + + /* + * No handler was present for this protocol. If this is a WM_DELETE_WINDOW + * message then just destroy the window. + */ + + if (protocol == Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW")) { + Tk_DestroyWindow((Tk_Window) wmPtr->winPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkWmStackorderToplevelWrapperMap -- + * + * This function will create a table that maps the reparent wrapper X id + * for a toplevel to the TkWindow structure that is wraps. Tk keeps track + * of a mapping from the window X id to the TkWindow structure but that + * does us no good here since we only get the X id of the wrapper window. + * Only those toplevel windows that are mapped have a position in the + * stacking order. + * + * Results: + * None. + * + * Side effects: + * Adds entries to the passed hashtable. + * + *---------------------------------------------------------------------- + */ + +static void +TkWmStackorderToplevelWrapperMap( + TkWindow *winPtr, /* TkWindow to recurse on */ + Display *display, /* X display of parent window */ + Tcl_HashTable *table) /* Maps X id to TkWindow */ +{ + TkWindow *childPtr; + + if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) && + !Tk_IsEmbedded(winPtr) && (winPtr->display == display)) { + Window wrapper = (winPtr->wmInfoPtr->reparent != None) + ? winPtr->wmInfoPtr->reparent + : winPtr->wmInfoPtr->wrapperPtr->window; + Tcl_HashEntry *hPtr; + int newEntry; + + hPtr = Tcl_CreateHashEntry(table, (char *) wrapper, &newEntry); + Tcl_SetHashValue(hPtr, winPtr); + } + + for (childPtr = winPtr->childList; childPtr != NULL; + childPtr = childPtr->nextPtr) { + TkWmStackorderToplevelWrapperMap(childPtr, display, table); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkWmStackorderToplevel -- + * + * This function returns the stack order of toplevel windows. + * + * Results: + * An array of pointers to tk window objects in stacking order or else + * NULL if there was an error. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkWindow ** +TkWmStackorderToplevel( + TkWindow *parentPtr) /* Parent toplevel window. */ +{ + Window dummy1, dummy2, vRoot; + Window *children; + unsigned numChildren, i; + TkWindow *childWinPtr, **windows, **window_ptr; + Tcl_HashTable table; + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + + /* + * Map X Window ids to a TkWindow of the wrapped toplevel. + */ + + Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS); + TkWmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table); + + window_ptr = windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *)); + + /* + * Special cases: If zero or one toplevels were mapped there is no need to + * call XQueryTree. + */ + + switch (table.numEntries) { + case 0: + windows[0] = NULL; + goto done; + case 1: + hPtr = Tcl_FirstHashEntry(&table, &search); + windows[0] = Tcl_GetHashValue(hPtr); + windows[1] = NULL; + goto done; + } + + vRoot = parentPtr->wmInfoPtr->vRoot; + if (vRoot == None) { + vRoot = RootWindowOfScreen(Tk_Screen((Tk_Window) parentPtr)); + } + + if (XQueryTree(parentPtr->display, vRoot, &dummy1, &dummy2, + &children, &numChildren) == 0) { + ckfree(windows); + windows = NULL; + } else { + for (i = 0; i < numChildren; i++) { + hPtr = Tcl_FindHashEntry(&table, (char *) children[i]); + if (hPtr != NULL) { + childWinPtr = Tcl_GetHashValue(hPtr); + *window_ptr++ = childWinPtr; + } + } + + /* + * ASSERT: window_ptr - windows == table.numEntries + * (#matched toplevel windows == #children) [Bug 1789819] + */ + + *window_ptr = NULL; + if (numChildren) { + XFree((char *) children); + } + } + + done: + Tcl_DeleteHashTable(&table); + return windows; +} + +/* + *---------------------------------------------------------------------- + * + * TkWmRestackToplevel -- + * + * This function restacks a top-level window. + * + * Results: + * None. + * + * Side effects: + * WinPtr gets restacked as specified by aboveBelow and otherPtr. + * + *---------------------------------------------------------------------- + */ + +void +TkWmRestackToplevel( + TkWindow *winPtr, /* Window to restack. */ + int aboveBelow, /* Gives relative position for restacking; + * must be Above or Below. */ + TkWindow *otherPtr) /* Window relative to which to restack; if + * NULL, then winPtr gets restacked above or + * below *all* siblings. */ +{ + XWindowChanges changes; + unsigned mask; + TkWindow *wrapperPtr; + + memset(&changes, 0, sizeof(XWindowChanges)); + changes.stack_mode = aboveBelow; + mask = CWStackMode; + + /* + * Make sure that winPtr and its wrapper window have been created. + */ + + if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) { + TkWmMapWindow(winPtr); + } + wrapperPtr = winPtr->wmInfoPtr->wrapperPtr; + + if (otherPtr != NULL) { + /* + * The window is to be restacked with respect to another toplevel. + * Make sure it has been created as well. + */ + + if (otherPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) { + TkWmMapWindow(otherPtr); + } + changes.sibling = otherPtr->wmInfoPtr->wrapperPtr->window; + mask |= CWSibling; + } + + /* + * Reconfigure the window. Note that we use XReconfigureWMWindow instead + * of XConfigureWindow, in order to handle the case where the window is to + * be restacked with respect to another toplevel. See [ICCCM] 4.1.5 + * "Configuring the Window" and XReconfigureWMWindow(3) for details. + */ + + XReconfigureWMWindow(winPtr->display, wrapperPtr->window, + Tk_ScreenNumber((Tk_Window) winPtr), mask, &changes); +} + + +/* + *---------------------------------------------------------------------- + * + * TkWmAddToColormapWindows -- + * + * This function is called to add a given window to the + * WM_COLORMAP_WINDOWS property for its top-level, if it isn't already + * there. It is invoked by the Tk code that creates a new colormap, in + * order to make sure that colormap information is propagated to the + * window manager by default. + * + * Results: + * None. + * + * Side effects: + * WinPtr's window gets added to the WM_COLORMAP_WINDOWS property of its + * nearest top-level ancestor, unless the colormaps have been set + * explicitly with the "wm colormapwindows" command. + * + *---------------------------------------------------------------------- + */ + +void +TkWmAddToColormapWindows( + TkWindow *winPtr) /* Window with a non-default colormap. Should + * not be a top-level window. */ +{ + TkWindow *wrapperPtr; + TkWindow *topPtr; + Window *oldPtr, *newPtr; + int count, i; + + if (winPtr->window == None) { + return; + } + + for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) { + if (topPtr == NULL) { + /* + * Window is being deleted. Skip the whole operation. + */ + + return; + } + if (topPtr->flags & TK_TOP_HIERARCHY) { + break; + } + } + if (topPtr->wmInfoPtr == NULL) { + return; + } + + if (topPtr->wmInfoPtr->flags & WM_COLORMAPS_EXPLICIT) { + return; + } + if (topPtr->wmInfoPtr->wrapperPtr == NULL) { + CreateWrapper(topPtr->wmInfoPtr); + } + wrapperPtr = topPtr->wmInfoPtr->wrapperPtr; + + /* + * Fetch the old value of the property. + */ + + if (XGetWMColormapWindows(topPtr->display, wrapperPtr->window, + &oldPtr, &count) == 0) { + oldPtr = NULL; + count = 0; + } + + /* + * Make sure that the window isn't already in the list. + */ + + for (i = 0; i < count; i++) { + if (oldPtr[i] == winPtr->window) { + return; + } + } + + /* + * Make a new bigger array and use it to reset the property. Automatically + * add the toplevel itself as the last element of the list. + */ + + newPtr = ckalloc((count+2) * sizeof(Window)); + for (i = 0; i < count; i++) { + newPtr[i] = oldPtr[i]; + } + if (count == 0) { + count++; + } + newPtr[count-1] = winPtr->window; + newPtr[count] = topPtr->window; + XSetWMColormapWindows(topPtr->display, wrapperPtr->window, newPtr, + count+1); + ckfree(newPtr); + if (oldPtr != NULL) { + XFree((char *) oldPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkWmRemoveFromColormapWindows -- + * + * This function is called to remove a given window from the + * WM_COLORMAP_WINDOWS property for its top-level. It is invoked when + * windows are deleted. + * + * Results: + * None. + * + * Side effects: + * WinPtr's window gets removed from the WM_COLORMAP_WINDOWS property of + * its nearest top-level ancestor, unless the top-level itself is being + * deleted too. + * + *---------------------------------------------------------------------- + */ + +void +TkWmRemoveFromColormapWindows( + TkWindow *winPtr) /* Window that may be present in + * WM_COLORMAP_WINDOWS property for its + * top-level. Should not be a top-level + * window. */ +{ + TkWindow *wrapperPtr; + TkWindow *topPtr; + Window *oldPtr; + int count, i, j; + + if (winPtr->window == None) { + return; + } + + for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) { + if (topPtr == NULL) { + /* + * Ancestors have been deleted, so skip the whole operation. + * Seems like this can't ever happen? + */ + + return; + } + if (topPtr->flags & TK_TOP_HIERARCHY) { + break; + } + } + if (topPtr->flags & TK_ALREADY_DEAD) { + /* + * Top-level is being deleted, so there's no need to cleanup the + * WM_COLORMAP_WINDOWS property. + */ + + return; + } + if (topPtr->wmInfoPtr == NULL) { + return; + } + + if (topPtr->wmInfoPtr->wrapperPtr == NULL) { + CreateWrapper(topPtr->wmInfoPtr); + } + wrapperPtr = topPtr->wmInfoPtr->wrapperPtr; + if (wrapperPtr == NULL) { + return; + } + + /* + * Fetch the old value of the property. + */ + + if (XGetWMColormapWindows(topPtr->display, wrapperPtr->window, + &oldPtr, &count) == 0) { + return; + } + + /* + * Find the window and slide the following ones down to cover it up. + */ + + for (i = 0; i < count; i++) { + if (oldPtr[i] == winPtr->window) { + for (j = i ; j < count-1; j++) { + oldPtr[j] = oldPtr[j+1]; + } + XSetWMColormapWindows(topPtr->display, wrapperPtr->window, + oldPtr, count-1); + break; + } + } + XFree((char *) oldPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TkGetPointerCoords -- + * + * Fetch the position of the mouse pointer. + * + * Results: + * *xPtr and *yPtr are filled in with the (virtual) root coordinates of + * the mouse pointer for tkwin's display. If the pointer isn't on tkwin's + * screen, then -1 values are returned for both coordinates. The argument + * tkwin must be a toplevel window. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkGetPointerCoords( + Tk_Window tkwin, /* Toplevel window that identifies screen on + * which lookup is to be done. */ + int *xPtr, int *yPtr) /* Store pointer coordinates here. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + WmInfo *wmPtr; + Window w, root, child; + int rootX, rootY; + unsigned mask; + + wmPtr = winPtr->wmInfoPtr; + + w = wmPtr->vRoot; + if (w == None) { + w = RootWindow(winPtr->display, winPtr->screenNum); + } + if (XQueryPointer(winPtr->display, w, &root, &child, &rootX, &rootY, + xPtr, yPtr, &mask) != True) { + *xPtr = -1; + *yPtr = -1; + } +} + +/* + *---------------------------------------------------------------------- + * + * GetMaxSize -- + * + * This function computes the current maxWidth and maxHeight values for a + * window, taking into account the possibility that they may be + * defaulted. + * + * Results: + * The values at *maxWidthPtr and *maxHeightPtr are filled in with the + * maximum allowable dimensions of wmPtr's window, in grid units. If no + * maximum has been specified for the window, then this function computes + * the largest sizes that will fit on the screen. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetMaxSize( + WmInfo *wmPtr, /* Window manager information for the + * window. */ + int *maxWidthPtr, /* Where to store the current maximum width of + * the window. */ + int *maxHeightPtr) /* Where to store the current maximum height + * of the window. */ +{ + int tmp; + + if (wmPtr->maxWidth > 0) { + *maxWidthPtr = wmPtr->maxWidth; + } else { + /* + * Must compute a default width. Fill up the display, leaving a bit of + * extra space for the window manager's borders. + */ + + tmp = DisplayWidth(wmPtr->winPtr->display, wmPtr->winPtr->screenNum) + - 15; + if (wmPtr->gridWin != NULL) { + /* + * Gridding is turned on; convert from pixels to grid units. + */ + + tmp = wmPtr->reqGridWidth + + (tmp - wmPtr->winPtr->reqWidth)/wmPtr->widthInc; + } + *maxWidthPtr = tmp; + } + if (wmPtr->maxHeight > 0) { + *maxHeightPtr = wmPtr->maxHeight; + } else { + tmp = DisplayHeight(wmPtr->winPtr->display, wmPtr->winPtr->screenNum) + - 30; + if (wmPtr->gridWin != NULL) { + tmp = wmPtr->reqGridHeight + + (tmp - wmPtr->winPtr->reqHeight)/wmPtr->heightInc; + } + *maxHeightPtr = tmp; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkSetTransientFor -- + * + * Set a Tk window to be transient with reference to a specified + * parent or the toplevel ancestor if None is passed as parent. + * + *---------------------------------------------------------------------- + */ + +static void +TkSetTransientFor(Tk_Window tkwin, Tk_Window parent) +{ + if (parent == None) { + parent = Tk_Parent(tkwin); + while (!Tk_IsTopLevel(parent)) + parent = Tk_Parent(parent); + } + /* + * Prevent crash due to incomplete initialization, or other problems. + * [Bugs 3554026, 3561016] + */ + if (((TkWindow *)parent)->wmInfoPtr->wrapperPtr == NULL) { + CreateWrapper(((TkWindow *)parent)->wmInfoPtr); + } + XSetTransientForHint(Tk_Display(tkwin), + ((TkWindow *)tkwin)->wmInfoPtr->wrapperPtr->window, + ((TkWindow *)parent)->wmInfoPtr->wrapperPtr->window); +} + +/* + *---------------------------------------------------------------------- + * + * TkpMakeMenuWindow -- + * + * Configure the window to be either a pull-down menu, a pop-up menu, or + * as a toplevel (torn-off) menu or palette. + * + * Results: + * None. + * + * Side effects: + * Changes the style bit used to create a new Mac toplevel. + * + *---------------------------------------------------------------------- + */ + +void +TkpMakeMenuWindow( + Tk_Window tkwin, /* New window. */ + int typeFlag) /* TK_MAKE_MENU_DROPDOWN means menu is only + * posted briefly as a pulldown or cascade, + * TK_MAKE_MENU_POPUP means it is a popup. + * TK_MAKE_MENU_TEAROFF means menu is always + * visible, e.g. as a torn-off menu. + * Determines whether save_under and + * override_redirect should be set, plus how + * to flag it for the window manager. */ +{ + WmInfo *wmPtr; + XSetWindowAttributes atts; + TkWindow *wrapperPtr; + Tcl_Obj *typeObj; + + if (!Tk_HasWrapper(tkwin)) { + return; + } + wmPtr = ((TkWindow *) tkwin)->wmInfoPtr; + if (wmPtr->wrapperPtr == NULL) { + CreateWrapper(wmPtr); + } + wrapperPtr = wmPtr->wrapperPtr; + if (typeFlag == TK_MAKE_MENU_TEAROFF) { + atts.override_redirect = False; + atts.save_under = False; + typeObj = Tcl_NewStringObj("menu", -1); + TkSetTransientFor(tkwin, NULL); + } else { + atts.override_redirect = True; + atts.save_under = True; + if (typeFlag == TK_MAKE_MENU_DROPDOWN) { + typeObj = Tcl_NewStringObj("dropdown_menu", -1); + } else { + typeObj = Tcl_NewStringObj("popup_menu", -1); + } + } + SetNetWmType((TkWindow *)tkwin, typeObj); + + /* + * The override-redirect and save-under bits must be set on the wrapper + * window in order to have the desired effect. However, also set the + * override-redirect bit on the window itself, so that the "wm + * overrideredirect" command will see it. + */ + + if ((atts.override_redirect!=Tk_Attributes(wrapperPtr)->override_redirect) + || (atts.save_under != Tk_Attributes(wrapperPtr)->save_under)) { + Tk_ChangeWindowAttributes((Tk_Window) wrapperPtr, + CWOverrideRedirect|CWSaveUnder, &atts); + } + if (atts.override_redirect != Tk_Attributes(tkwin)->override_redirect) { + Tk_ChangeWindowAttributes(tkwin, CWOverrideRedirect, &atts); + } +} + +/* + *---------------------------------------------------------------------- + * + * CreateWrapper -- + * + * This function is invoked to create the wrapper window for a toplevel + * window. It is called just before a toplevel is mapped for the first + * time. + * + * Results: + * None. + * + * Side effects: + * The wrapper is created and the toplevel is reparented inside it. + * + *---------------------------------------------------------------------- + */ + +static void +CreateWrapper( + WmInfo *wmPtr) /* Window manager information for the + * window. */ +{ + TkWindow *winPtr, *wrapperPtr; + Window parent; + Tcl_HashEntry *hPtr; + int new; + + winPtr = wmPtr->winPtr; + if (winPtr->window == None) { + Tk_MakeWindowExist((Tk_Window) winPtr); + } + + /* + * The code below is copied from CreateTopLevelWindow, Tk_MakeWindowExist, + * and TkpMakeWindow. The idea is to create an "official" Tk window (so + * that we can get events on it), but to hide the window outside the + * official Tk hierarchy so that it isn't visible to the application. See + * the comments for the other functions if you have questions about this + * code. + */ + + wmPtr->wrapperPtr = wrapperPtr = TkAllocWindow(winPtr->dispPtr, + Tk_ScreenNumber((Tk_Window) winPtr), winPtr); + wrapperPtr->dirtyAtts |= CWBorderPixel; + + /* + * Tk doesn't normally select for StructureNotifyMask events because the + * events are synthesized internally. However, for wrapper windows we need + * to know when the window manager modifies the window configuration. We + * also need to select on focus change events; these are the only windows + * for which we care about focus changes. + */ + + wrapperPtr->flags |= TK_WRAPPER; + wrapperPtr->atts.event_mask |= StructureNotifyMask|FocusChangeMask; + wrapperPtr->atts.override_redirect = winPtr->atts.override_redirect; + if (winPtr->flags & TK_EMBEDDED) { + parent = TkUnixContainerId(winPtr); + } else { + parent = XRootWindow(wrapperPtr->display, wrapperPtr->screenNum); + } + wrapperPtr->window = XCreateWindow(wrapperPtr->display, + parent, wrapperPtr->changes.x, wrapperPtr->changes.y, + (unsigned) wrapperPtr->changes.width, + (unsigned) wrapperPtr->changes.height, + (unsigned) wrapperPtr->changes.border_width, wrapperPtr->depth, + InputOutput, wrapperPtr->visual, + wrapperPtr->dirtyAtts|CWOverrideRedirect, &wrapperPtr->atts); + hPtr = Tcl_CreateHashEntry(&wrapperPtr->dispPtr->winTable, + (char *) wrapperPtr->window, &new); + Tcl_SetHashValue(hPtr, wrapperPtr); + wrapperPtr->mainPtr = winPtr->mainPtr; + wrapperPtr->mainPtr->refCount++; + wrapperPtr->dirtyAtts = 0; + wrapperPtr->dirtyChanges = 0; + wrapperPtr->wmInfoPtr = wmPtr; + + /* + * Reparent the toplevel window inside the wrapper. + */ + + XReparentWindow(wrapperPtr->display, winPtr->window, wrapperPtr->window, + 0, 0); + + /* + * Tk must monitor structure events for wrapper windows in order to detect + * changes made by window managers such as resizing, mapping, unmapping, + * etc.. + */ + + Tk_CreateEventHandler((Tk_Window) wmPtr->wrapperPtr, + WrapperEventMask, WrapperEventProc, wmPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TkWmFocusToplevel -- + * + * This is a utility function invoked by focus-management code. The focus + * code responds to externally generated focus-related events on wrapper + * windows but ignores those events for any other windows. This function + * determines whether a given window is a wrapper window and, if so, + * returns the toplevel window corresponding to the wrapper. + * + * Results: + * If winPtr is a wrapper window, returns a pointer to the corresponding + * toplevel window; otherwise returns NULL. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkWindow * +TkWmFocusToplevel( + TkWindow *winPtr) /* Window that received a focus-related + * event. */ +{ + if (!(winPtr->flags & TK_WRAPPER)) { + return NULL; + } + return winPtr->wmInfoPtr->winPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkUnixSetMenubar -- + * + * This function is invoked by menu management code to specify the window + * to use as a menubar for a given toplevel window. + * + * Results: + * None. + * + * Side effects: + * The window given by menubar will be mapped and positioned inside the + * wrapper for tkwin and above tkwin. Menubar will automatically be + * resized to maintain the height specified by TkUnixSetMenuHeight the + * same width as tkwin. Any previous menubar specified for tkwin will be + * unmapped and ignored from now on. + * + *---------------------------------------------------------------------- + */ + +void +TkUnixSetMenubar( + Tk_Window tkwin, /* Token for toplevel window. */ + Tk_Window menubar) /* Token for window that is to serve as + * menubar for tkwin. Must not be a toplevel + * window. If NULL, any existing menubar is + * canceled and the menu height is reset to + * 0. */ +{ + WmInfo *wmPtr = ((TkWindow *) tkwin)->wmInfoPtr; + Tk_Window parent; + TkWindow *menubarPtr = (TkWindow *) menubar; + + /* + * Could be a Frame (i.e. not a toplevel). + */ + + if (wmPtr == NULL) { + return; + } + + if (wmPtr->menubar != NULL) { + /* + * There's already a menubar for this toplevel. If it isn't the same + * as the new menubar, unmap it so that it is out of the way, and + * reparent it back to its original parent. + */ + + if (wmPtr->menubar == menubar) { + return; + } + ((TkWindow *) wmPtr->menubar)->wmInfoPtr = NULL; + ((TkWindow *) wmPtr->menubar)->flags &= ~TK_REPARENTED; + Tk_UnmapWindow(wmPtr->menubar); + parent = Tk_Parent(wmPtr->menubar); + if (parent != NULL) { + Tk_MakeWindowExist(parent); + XReparentWindow(Tk_Display(wmPtr->menubar), + Tk_WindowId(wmPtr->menubar), Tk_WindowId(parent), 0, 0); + } + Tk_DeleteEventHandler(wmPtr->menubar, StructureNotifyMask, + MenubarDestroyProc, wmPtr->menubar); + Tk_ManageGeometry(wmPtr->menubar, NULL, NULL); + } + + wmPtr->menubar = menubar; + if (menubar == NULL) { + wmPtr->menuHeight = 0; + } else { + if ((menubarPtr->flags & TK_TOP_LEVEL) + || (Tk_Screen(menubar) != Tk_Screen(tkwin))) { + Tcl_Panic("TkUnixSetMenubar got bad menubar"); + } + wmPtr->menuHeight = Tk_ReqHeight(menubar); + if (wmPtr->menuHeight == 0) { + wmPtr->menuHeight = 1; + } + Tk_MakeWindowExist(tkwin); + Tk_MakeWindowExist(menubar); + if (wmPtr->wrapperPtr == NULL) { + CreateWrapper(wmPtr); + } + XReparentWindow(Tk_Display(menubar), Tk_WindowId(menubar), + wmPtr->wrapperPtr->window, 0, 0); + menubarPtr->wmInfoPtr = wmPtr; + Tk_MoveResizeWindow(menubar, 0, 0, Tk_Width(tkwin), wmPtr->menuHeight); + Tk_MapWindow(menubar); + Tk_CreateEventHandler(menubar, StructureNotifyMask, + MenubarDestroyProc, menubar); + Tk_ManageGeometry(menubar, &menubarMgrType, wmPtr); + menubarPtr->flags |= TK_REPARENTED; + } + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tcl_DoWhenIdle(UpdateGeometryInfo, tkwin); + wmPtr->flags |= WM_UPDATE_PENDING; + } +} + +/* + *---------------------------------------------------------------------- + * + * MenubarDestroyProc -- + * + * This function is invoked by the event dispatcher whenever a menubar + * window is destroyed (it's also invoked for a few other kinds of + * events, but we ignore those). + * + * Results: + * None. + * + * Side effects: + * The association between the window and its toplevel is broken, so that + * the window is no longer considered to be a menubar. + * + *---------------------------------------------------------------------- + */ + +static void +MenubarDestroyProc( + ClientData clientData, /* TkWindow pointer for menubar. */ + XEvent *eventPtr) /* Describes what just happened. */ +{ + WmInfo *wmPtr; + + if (eventPtr->type != DestroyNotify) { + return; + } + wmPtr = ((TkWindow *) clientData)->wmInfoPtr; + wmPtr->menubar = NULL; + wmPtr->menuHeight = 0; + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tcl_DoWhenIdle(UpdateGeometryInfo, wmPtr->winPtr); + wmPtr->flags |= WM_UPDATE_PENDING; + } +} + +/* + *---------------------------------------------------------------------- + * + * MenubarReqProc -- + * + * This function is invoked by the Tk geometry management code whenever a + * menubar calls Tk_GeometryRequest to request a new size. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +MenubarReqProc( + ClientData clientData, /* Pointer to the window manager information + * for tkwin's toplevel. */ + Tk_Window tkwin) /* Handle for menubar window. */ +{ + WmInfo *wmPtr = clientData; + + wmPtr->menuHeight = Tk_ReqHeight(tkwin); + if (wmPtr->menuHeight <= 0) { + wmPtr->menuHeight = 1; + } + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tcl_DoWhenIdle(UpdateGeometryInfo, wmPtr->winPtr); + wmPtr->flags |= WM_UPDATE_PENDING; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetWrapperWindow -- + * + * Given a toplevel window return the hidden wrapper window for the + * toplevel window if available. + * + * Results: + * The wrapper window. NULL is we were not passed a toplevel window or + * the wrapper has yet to be created. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkWindow * +TkpGetWrapperWindow( + TkWindow *winPtr) /* A toplevel window pointer. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + + if ((winPtr == NULL) || (wmPtr == NULL)) { + return NULL; + } + + return wmPtr->wrapperPtr; +} + +/* + *---------------------------------------------------------------------- + * + * UpdateCommand -- + * + * Update the WM_COMMAND property, taking care to translate the command + * strings into the external encoding. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +UpdateCommand( + TkWindow *winPtr) +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Tcl_DString cmds, ds; + int i, *offsets; + char **cmdArgv; + + /* + * Translate the argv strings into the external encoding. To avoid + * allocating lots of memory, the strings are appended to a buffer with + * nulls between each string. + * + * This code is tricky because we need to pass and array of pointers to + * XSetCommand. However, we can't compute the pointers as we go because + * the DString buffer space could get reallocated. So, store offsets for + * each element as we go, then compute pointers from the offsets once the + * entire DString is done. + */ + + cmdArgv = ckalloc(sizeof(char *) * wmPtr->cmdArgc); + offsets = ckalloc(sizeof(int) * wmPtr->cmdArgc); + Tcl_DStringInit(&cmds); + for (i = 0; i < wmPtr->cmdArgc; i++) { + Tcl_UtfToExternalDString(NULL, wmPtr->cmdArgv[i], -1, &ds); + offsets[i] = Tcl_DStringLength(&cmds); + Tcl_DStringAppend(&cmds, Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds)+1); + Tcl_DStringFree(&ds); + } + cmdArgv[0] = Tcl_DStringValue(&cmds); + for (i = 1; i < wmPtr->cmdArgc; i++) { + cmdArgv[i] = cmdArgv[0] + offsets[i]; + } + + XSetCommand(winPtr->display, wmPtr->wrapperPtr->window, + cmdArgv, wmPtr->cmdArgc); + Tcl_DStringFree(&cmds); + ckfree(cmdArgv); + ckfree(offsets); +} + +/* + *---------------------------------------------------------------------- + * + * TkpWmSetState -- + * + * Sets the window manager state for the wrapper window of a given + * toplevel window. + * + * Results: + * 0 on error, 1 otherwise + * + * Side effects: + * May minimize, restore, or withdraw a window. + * + *---------------------------------------------------------------------- + */ + +int +TkpWmSetState( + TkWindow *winPtr, /* Toplevel window to operate on. */ + int state) /* One of IconicState, NormalState, or + * WithdrawnState. */ +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (state == WithdrawnState) { + wmPtr->hints.initial_state = WithdrawnState; + wmPtr->withdrawn = 1; + if (wmPtr->flags & WM_NEVER_MAPPED) { + return 1; + } + if (XWithdrawWindow(winPtr->display, wmPtr->wrapperPtr->window, + winPtr->screenNum) == 0) { + return 0; + } + WaitForMapNotify(winPtr, 0); + } else if (state == NormalState) { + wmPtr->hints.initial_state = NormalState; + wmPtr->withdrawn = 0; + if (wmPtr->flags & WM_NEVER_MAPPED) { + return 1; + } + UpdateHints(winPtr); + Tk_MapWindow((Tk_Window) winPtr); + } else if (state == IconicState) { + wmPtr->hints.initial_state = IconicState; + if (wmPtr->flags & WM_NEVER_MAPPED) { + return 1; + } + if (wmPtr->withdrawn) { + UpdateHints(winPtr); + Tk_MapWindow((Tk_Window) winPtr); + wmPtr->withdrawn = 0; + } else { + if (XIconifyWindow(winPtr->display, wmPtr->wrapperPtr->window, + winPtr->screenNum) == 0) { + return 0; + } + WaitForMapNotify(winPtr, 0); + } + } + + return 1; +} + +/* + *---------------------------------------------------------------------- + * + * RemapWindows + * + * Adjust parent/child relationships of the given window hierarchy. + * + * Results: + * None + * + * Side effects: + * Keeps windowing system (X11) happy + * + *---------------------------------------------------------------------- + */ + +static void +RemapWindows( + TkWindow *winPtr, + TkWindow *parentPtr) +{ + XWindowAttributes win_attr; + + if (winPtr->window) { + XGetWindowAttributes(winPtr->display, winPtr->window, &win_attr); + if (parentPtr == NULL) { + XReparentWindow(winPtr->display, winPtr->window, + XRootWindow(winPtr->display, winPtr->screenNum), + win_attr.x, win_attr.y); + } else if (parentPtr->window) { + XReparentWindow(parentPtr->display, winPtr->window, + parentPtr->window, + win_attr.x, win_attr.y); + } + } +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/tk8.6/unix/tkUnixXId.c b/tk8.6/unix/tkUnixXId.c new file mode 100644 index 0000000..ec2451c --- /dev/null +++ b/tk8.6/unix/tkUnixXId.c @@ -0,0 +1,152 @@ +/* + * tkUnixXId.c -- + * + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tkUnixInt.h" + + +/* + *---------------------------------------------------------------------- + * + * Tk_FreeXId -- + * + * This function is called to indicate that an X resource identifier is + * now free. + * + * Results: + * None. + * + * Side effects: + * The identifier is added to the stack of free identifiers for its + * display, so that it can be re-used. + * + *---------------------------------------------------------------------- + */ + +void +Tk_FreeXId( + Display *display, /* Display for which xid was allocated. */ + XID xid) /* Identifier that is no longer in use. */ +{ + /* + * This does nothing, because the XC-MISC extension takes care of + * freeing XIDs for us. It has been a standard X11 extension for + * about 15 years as of 2008. Keith Packard and another X.org + * developer suggested that we remove the previous code that used: + * #define XLIB_ILLEGAL_ACCESS. + */ +} + + +/* + *---------------------------------------------------------------------- + * + * Tk_GetPixmap -- + * + * Same as the XCreatePixmap function except that it manages resource + * identifiers better. + * + * Results: + * Returns a new pixmap. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Pixmap +Tk_GetPixmap( + Display *display, /* Display for new pixmap. */ + Drawable d, /* Drawable where pixmap will be used. */ + int width, int height, /* Dimensions of pixmap. */ + int depth) /* Bits per pixel for pixmap. */ +{ + return XCreatePixmap(display, d, (unsigned) width, (unsigned) height, + (unsigned) depth); +} + +/* + *---------------------------------------------------------------------- + * + * Tk_FreePixmap -- + * + * Same as the XFreePixmap function except that it also marks the + * resource identifier as free. + * + * Results: + * None. + * + * Side effects: + * The pixmap is freed in the X server and its resource identifier is + * saved for re-use. + * + *---------------------------------------------------------------------- + */ + +void +Tk_FreePixmap( + Display *display, /* Display for which pixmap was allocated. */ + Pixmap pixmap) /* Identifier for pixmap. */ +{ + XFreePixmap(display, pixmap); +} + + +/* + *---------------------------------------------------------------------- + * + * TkpScanWindowId -- + * + * Given a string, produce the corresponding Window Id. + * + * Results: + * The return value is normally TCL_OK; in this case *idPtr will be set + * to the Window value equivalent to string. If string is improperly + * formed then TCL_ERROR is returned and an error message will be left in + * the interp's result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkpScanWindowId( + Tcl_Interp *interp, + const char *string, + Window *idPtr) +{ + int code; + Tcl_Obj obj; + + obj.refCount = 1; + obj.bytes = (char *) string; /* DANGER?! */ + obj.length = strlen(string); + obj.typePtr = NULL; + + code = Tcl_GetLongFromObj(interp, &obj, (long *)idPtr); + + if (obj.refCount > 1) { + Tcl_Panic("invalid sharing of Tcl_Obj on C stack"); + } + if (obj.typePtr && obj.typePtr->freeIntRepProc) { + obj.typePtr->freeIntRepProc(&obj); + } + return code; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |