diff options
-rw-r--r-- | ChangeLog | 39 | ||||
-rw-r--r-- | doc/wm.n | 11 | ||||
-rw-r--r-- | generic/tkMain.c | 11 | ||||
-rw-r--r-- | generic/tkRectOval.c | 9 | ||||
-rw-r--r-- | macosx/Makefile | 4 | ||||
-rw-r--r-- | macosx/README | 22 | ||||
-rw-r--r-- | macosx/Wish.pbproj/project.pbxproj | 60 | ||||
-rw-r--r-- | macosx/tkMacOSXAppInit.c | 243 | ||||
-rw-r--r-- | macosx/tkMacOSXDefault.h | 9 | ||||
-rw-r--r-- | macosx/tkMacOSXDraw.c | 751 | ||||
-rw-r--r-- | macosx/tkMacOSXInit.c | 213 | ||||
-rw-r--r-- | macosx/tkMacOSXInt.h | 9 | ||||
-rw-r--r-- | macosx/tkMacOSXMenu.c | 15 | ||||
-rw-r--r-- | macosx/tkMacOSXMouseEvent.c | 28 | ||||
-rw-r--r-- | macosx/tkMacOSXSubwindows.c | 4 | ||||
-rw-r--r-- | macosx/tkMacOSXWm.c | 258 |
16 files changed, 1060 insertions, 626 deletions
@@ -1,3 +1,42 @@ +2004-11-11 Daniel Steffen <das@users.sourceforge.net> + + * generic/tkMain.c: + * macosx/tkMacOSXAppInit.c (removed): + * macosx/Wish.pbproj/project.pbxproj: + * macosx/tkMacOSXInit.c: + * macosx/tkMacOSXInt.h: changes to make TkAqua dynamically loadable, + enabling [package require Tk] from tclsh. Startup code from + tkMacOSXAppInit.c moved into tkMacOSXInit.c, added code that + notifies the window server that an unbundled executable is a full + GUI application after loading Tk. [Patch 1035348] + + * doc/wm.n: documented [wm attributes] on Mac OS X. [Bug 606665] + * macosx/tkMacOSXWm.c: implemented TIP 222 [wm attributes -alpha] on + Mac OS X. [Patch 892194] + WmIconbitmapCmd: adopted FSRef changes from [wm atttrs -titlepath]. + + * macosx/tkMacOSXSubwindows.c: synced spacing/formatting with + core-8-4-branch. + + * generic/tkRectOval.c: + * macosx/README: + * macosx/tkMacOSXDefault.h: + * macosx/tkMacOSXDraw.c: + * macosx/tkMacOSXInit.c: + * macosx/tkMacOSXInt.h: + * macosx/tkMacOSXMenu.c: + * macosx/tkMacOSXWm.c: forward port from core-8-4-branch of Jim's + and my changes for CG drawing and [wm attributes] (corresponds to + 8.4 changes dating from 09-18, 07-27, 07-24). + + * macosx/tkMacOSXMouseEvent.c: endianness fixes. + + * macosx/Wish.pbproj/project.pbxproj: corrected path to html help + inside framework. + + * macosx/Makefile: prevent parallel make from building several + targets at the same time. + 2004-11-09 Vince Darley <vincentdarley@users.sourceforge.net> * macosx/tkMacOSXButton.c: fix to dynamic reconfiguration of @@ -5,7 +5,7 @@ '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" RCS: @(#) $Id: wm.n,v 1.20 2004/10/28 12:25:53 dkf Exp $ +'\" RCS: @(#) $Id: wm.n,v 1.21 2004/11/11 01:24:31 das Exp $ '\" .so man.macros .TH wm n 8.5 Tk "Tk Built-In Commands" @@ -70,8 +70,13 @@ outside that range will be constrained. This is supported on Windows \fB1.0\fR. .VE 8.5 .PP -On Macintosh, there are currently two attribute values: -\fB\-modified\fR and \fB\-titlepath\fR. +On Mac OS X, \fB\-modified\fR gets or sets the modification state of the +window (determines whether the window close widget contains the modification +indicator). \fB\-titlepath\fR gets or sets the path of the file referenced as +the window proxy icon (which can be dragged and dropped in lieu of the file's +finder icon). \fB\-alpha\fR sets the alpha transparency level of the window, +it accepts a value from \fB0.0\fR (fully transparent) to \fB1.0\fR (opaque), +values outside that range will be constrained. .PP On Unix, there are currently no special attribute values. .RE diff --git a/generic/tkMain.c b/generic/tkMain.c index d723218..a225b70 100644 --- a/generic/tkMain.c +++ b/generic/tkMain.c @@ -13,7 +13,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMain.c,v 1.17 2004/03/17 18:15:43 das Exp $ + * RCS: @(#) $Id: tkMain.c,v 1.18 2004/11/11 01:24:31 das Exp $ */ #include <ctype.h> @@ -31,6 +31,9 @@ #ifdef __WIN32__ #include "tkWinInt.h" #endif +#ifdef MAC_OSX_TK +#include "tkMacOSXInt.h" +#endif typedef struct ThreadSpecificData { @@ -125,6 +128,12 @@ Tk_MainEx(argc, argv, appInitProc, interp) #if defined(__WIN32__) Tk_InitConsoleChannels(interp); #endif + +#ifdef MAC_OSX_TK + if (Tcl_GetStartupScript(NULL) == NULL) { + TkMacOSXDefaultStartupScript(); + } +#endif #ifdef TCL_MEM_DEBUG Tcl_InitMemory(interp); diff --git a/generic/tkRectOval.c b/generic/tkRectOval.c index 454b9a5..8d13a60 100644 --- a/generic/tkRectOval.c +++ b/generic/tkRectOval.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkRectOval.c,v 1.11 2004/01/13 02:06:00 davygrvy Exp $ + * RCS: @(#) $Id: tkRectOval.c,v 1.12 2004/11/11 01:24:32 das Exp $ */ #include <stdio.h> @@ -672,7 +672,14 @@ ComputeRectOvalBbox(canvas, rectOvalPtr) bloat = 0; #endif } else { +#ifdef MAC_OSX_TK + /* Mac OS X CoreGraphics needs correct rounding here + * otherwise it will draw outside the bounding box. + * Probably correct on other platforms as well? */ + bloat = (int) (width+1.5)/2; +#else bloat = (int) (width+1)/2; +#endif } /* diff --git a/macosx/Makefile b/macosx/Makefile index c2fc70a..2f8f482 100644 --- a/macosx/Makefile +++ b/macosx/Makefile @@ -3,7 +3,7 @@ # Makefile to build AquaTk on Mac OS X packaged as a Framework # uses Project Builder command line tool 'pbxbuild' # -# RCS: @(#) $Id: Makefile,v 1.14 2004/07/20 11:49:16 das Exp $ +# RCS: @(#) $Id: Makefile,v 1.15 2004/11/11 01:24:32 das Exp $ # ################################################################################ @@ -128,4 +128,6 @@ cleanup-embedded: embedded-develop embedded-deploy install-embedded-develop install-embedded-deploy \ clean-develop clean-deploy cleanup-embedded +.NOTPARALLEL: + ################################################################################ diff --git a/macosx/README b/macosx/README index 0c7e698..ba58466 100644 --- a/macosx/README +++ b/macosx/README @@ -1,7 +1,7 @@ TclTkAqua README ---------------- -RCS: @(#) $Id: README,v 1.9 2003/10/01 14:35:32 das Exp $ +RCS: @(#) $Id: README,v 1.10 2004/11/11 01:24:32 das Exp $ This is the README file for the Mac OS X native versions of Tcl & Tk. @@ -83,6 +83,26 @@ you expect. (Wish started from the Finder inherits the Finder's environment variables, which are essentially those set in $HOME/.MacOSX/environment.plist and not those set by your shell configuration files). +- As of Tk 8.4.7, AquaTk has a version of the low-level drawing primitives using +the CoreGraphics routines - the code is primarily due to James Tittle. There +were numerous problems with the QD version, mostly due to the different drawing +model of QD & Tk. CG also trivially supports dashed lines, and the various end +caps & miters. So this is a great improvement. + +The old QD code is retained for now, just in case there are any +compatibility problems. To switch back to the QD drawing, just put: + +set tk::mac::useCGDrawing 0 + +in your script before you do drawing. Also the CG drawing can anti-alias line drawing. +However, anti-aliased thin lines look washed out, so the threshold for antialiasing +is set to 3 pixel width lines. You can change this if you want by putting: + +set tk::mac::CGAntialiasLimit <limit> + +in your script before drawing, in which case only lines thinner that <limit> pixels +will not be antialiased. + - Quickdraw text antialiasing is enabled by default when available (from 10.1.5 onwards). Changing the global boolean variable '::tk::mac::antialiasedtext' allows to dis/enable antialiasing on the fly from tcl (even for existing text). diff --git a/macosx/Wish.pbproj/project.pbxproj b/macosx/Wish.pbproj/project.pbxproj index 7ac813a..c5bfafc 100644 --- a/macosx/Wish.pbproj/project.pbxproj +++ b/macosx/Wish.pbproj/project.pbxproj @@ -58,8 +58,7 @@ //F53 //F54 F50D96120196176E01DC9062 = { - fallbackIsa = PBXFileReference; - isa = PBXFrameworkReference; + isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; @@ -163,7 +162,7 @@ isa = PBXShellScriptBuildPhase; runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ \"${BUILD_STYLE}\" = \"Development\" ]; then\n\t# keep copy of debug library around, so that\n\t# Deployment build can be installed on top\n\t# of Development build without overwriting it\n\tcd \"${TARGET_BUILD_DIR}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}/Versions/${FRAMEWORK_VERSION}\"\n\tcp -fp \"${PRODUCT_NAME}\" \"${PRODUCT_NAME}_debug\"\n\tln -fs \"Versions/Current/${PRODUCT_NAME}_debug\" ../..\n\tcp -fp \"libtkstub${FRAMEWORK_VERSION}.a\" \"libtkstub${FRAMEWORK_VERSION}g.a\"\n\n\t# force Deployment build to be relinked next time\n\tif [ -f \"${OBJROOT}/Deployment.build/${PROJECT_NAME}.build/${TARGET_NAME}.build/Objects-normal/LinkFileList\" ]; then\n\t touch -t `date -r \\`expr \\\\\\`date +\"%s\"\\\\\\` + 30\\` +\"%Y%m%d%H%M.%S\"` \"${OBJROOT}/Deployment.build/${PROJECT_NAME}.build/${TARGET_NAME}.build/Objects-normal/LinkFileList\"\n\tfi\nelse\n\t# force Development build to be relinked next time\n\tif [ -f \"${OBJROOT}/Development.build/${PROJECT_NAME}.build/${TARGET_NAME}.build/Objects-normal/LinkFileList\" ]; then\n\t touch -t `date -r \\`expr \\\\\\`date +\"%s\"\\\\\\` + 30\\` +\"%Y%m%d%H%M.%S\"` \"${OBJROOT}/Development.build/${PROJECT_NAME}.build/${TARGET_NAME}.build/Objects-normal/LinkFileList\"\n\tfi\nfi\n\n# fixup Framework structure\ncd \"${TARGET_BUILD_DIR}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}/Versions/${FRAMEWORK_VERSION}\"\nln -fs `ls libtkstub* | sed -e \"s|.*|Versions/${FRAMEWORK_VERSION}/&|\"` ../..\nln -fs \"Versions/Current/tkConfig.sh\" ../..\nranlib libtkstub${FRAMEWORK_VERSION}*.a"; + shellScript = "if [ \"${BUILD_STYLE}\" = \"Development\" ]; then\n\t# keep copy of debug library around, so that\n\t# Deployment build can be installed on top\n\t# of Development build without overwriting it\n\tcd \"${TARGET_BUILD_DIR}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}/Versions/${FRAMEWORK_VERSION}\"\n\tcp -fp \"${PRODUCT_NAME}\" \"${PRODUCT_NAME}_debug\"\n\tln -fs \"Versions/Current/${PRODUCT_NAME}_debug\" ../..\n\tcp -fp \"libtkstub${FRAMEWORK_VERSION}.a\" \"libtkstub${FRAMEWORK_VERSION}g.a\"\n\n\t# force Deployment build to be relinked next time\n\tif [ -f \"${OBJROOT}/Deployment.build/${PROJECT_NAME}.build/${TARGET_NAME}.build/Objects-normal/LinkFileList\" ]; then\n\t touch -t `date -r \\`expr \\\\\\`date +\"%s\"\\\\\\` + 30\\` +\"%Y%m%d%H%M.%S\"` \"${OBJROOT}/Deployment.build/${PROJECT_NAME}.build/${TARGET_NAME}.build/Objects-normal/LinkFileList\"\n\tfi\nelse\n\t# force Development build to be relinked next time\n\tif [ -f \"${OBJROOT}/Development.build/${PROJECT_NAME}.build/${TARGET_NAME}.build/Objects-normal/LinkFileList\" ]; then\n\t touch -t `date -r \\`expr \\\\\\`date +\"%s\"\\\\\\` + 30\\` +\"%Y%m%d%H%M.%S\"` \"${OBJROOT}/Development.build/${PROJECT_NAME}.build/${TARGET_NAME}.build/Objects-normal/LinkFileList\"\n\tfi\nfi\n\n# fixup Framework structure\ncd \"${TARGET_BUILD_DIR}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}/Versions/${FRAMEWORK_VERSION}\"\nln -fs `ls libtkstub* | sed -e \"s|.*|Versions/${FRAMEWORK_VERSION}/&|\"` ../..\nln -fs \"Versions/Current/tkConfig.sh\" ../..\nranlib libtkstub${FRAMEWORK_VERSION}*.a\n\n# create pkgIndex\n( echo \"if {[package vcompare [package provide Tcl] ${FRAMEWORK_VERSION}] != 0} { return }\" && \\\n echo \"package ifneeded Tk ${FRAMEWORK_VERSION} [list load [file join \\$dir .. .. Tk] Tk]\" \\\n) > \"Resources/Scripts/pkgIndex.tcl\""; }; F537552A016C352C01DC9062 = { buildSettings = { @@ -202,8 +201,6 @@ sourceTree = "<group>"; }; F537552C016C352C01DC9062 = { - buildRules = ( - ); buildSettings = { GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; @@ -218,8 +215,6 @@ name = Development; }; F537552D016C352C01DC9062 = { - buildRules = ( - ); buildSettings = { DEBUGGING_SYMBOLS = NO; GCC_ENABLE_FIX_AND_CONTINUE = NO; @@ -502,7 +497,6 @@ }; F5375546016C376E01DC9062 = { children = ( - F5375548016C376E01DC9062, F5375549016C376E01DC9062, F537554A016C376E01DC9062, 4C8A204405E0421900C18A82, @@ -543,9 +537,10 @@ fileEncoding = 5; isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; - path = tkMacOSXAppInit.c; - refType = 4; - sourceTree = "<group>"; + name = tkAppInit.c; + path = ../unix/tkAppInit.c; + refType = 2; + sourceTree = SOURCE_ROOT; }; F5375549016C376E01DC9062 = { fileEncoding = 5; @@ -1645,6 +1640,7 @@ }; F53755C9016C389901DC9062 = { children = ( + F5375548016C376E01DC9062, F53755CA016C389901DC9062, F53755CB016C389901DC9062, ); @@ -1850,8 +1846,7 @@ }; F53755DE016C38D201DC9062 = { explicitFileType = wrapper.framework; - fallbackIsa = PBXFileReference; - isa = PBXFrameworkReference; + isa = PBXFileReference; path = Tk.framework; refType = 3; sourceTree = BUILT_PRODUCTS_DIR; @@ -1873,7 +1868,7 @@ F9A61D2F04C2C861006F5A0B, ); buildSettings = { - DOCDIR = "${INSTALL_PATH}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}/Versions/${FRAMEWORK_VERSION}/Resources/English.lproj/Documentation/Reference"; + DOCDIR = "${INSTALL_PATH}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}/Versions/${FRAMEWORK_VERSION}/Resources/Documentation/Reference"; DYLIB_COMPATIBILITY_VERSION = 8.5; DYLIB_CURRENT_VERSION = "$(FRAMEWORK_VERSION)"; DYLIB_INSTALL_PATH = /Library/Frameworks; @@ -1917,7 +1912,7 @@ <key>CFBundleExecutable</key> <string>Tk</string> <key>CFBundleGetInfoString</key> - <string>Tk Library 8.5, Copyright © 2003 Tcl Core Team. + <string>Tk Library 8.5, Copyright © 2004 Tcl Core Team. MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Copyright © 2001-2002, Apple Computer, Inc.</string> <key>CFBundleIconFile</key> <string></string> @@ -3056,8 +3051,7 @@ MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Copyright  sourceTree = "<group>"; }; F537567D016C3ADB01DC9062 = { - fallbackIsa = PBXFileReference; - isa = PBXFrameworkReference; + isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; @@ -3260,8 +3254,7 @@ MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Copyright  }; F537569F016C4DD401DC9062 = { explicitFileType = wrapper.application; - fallbackIsa = PBXFileReference; - isa = PBXApplicationReference; + isa = PBXFileReference; path = "Wish Shell.app"; refType = 3; sourceTree = BUILT_PRODUCTS_DIR; @@ -3360,8 +3353,6 @@ MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Copyright  buildActionMask = 2147483647; files = ( F53756AC016C4E1D01DC9062, - F53756AD016C4E1D01DC9062, - F53756AE016C4E1D01DC9062, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -3432,18 +3423,6 @@ MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Copyright  settings = { }; }; - F53756AD016C4E1D01DC9062 = { - fileRef = F5375570016C37A601DC9062; - isa = PBXBuildFile; - settings = { - }; - }; - F53756AE016C4E1D01DC9062 = { - fileRef = F537553E016C376E01DC9062; - isa = PBXBuildFile; - settings = { - }; - }; F53756B2016C525F01DC9062 = { isa = PBXTargetDependency; target = F53755DF016C38D201DC9062; @@ -3514,8 +3493,7 @@ MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Copyright  }; F548F8CF0313CEF0016F146B = { explicitFileType = "compiled.mach-o.dylib"; - fallbackIsa = PBXFileReference; - isa = PBXLibraryReference; + isa = PBXFileReference; path = libtkstub8.5.a; refType = 3; sourceTree = BUILT_PRODUCTS_DIR; @@ -3576,8 +3554,7 @@ MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Copyright  }; }; F5875C7B016FEF1D01DC9062 = { - fallbackIsa = PBXFileReference; - isa = PBXFrameworkReference; + isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Tcl.framework; path = ../tcl/Tcl.framework; @@ -4051,9 +4028,8 @@ MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Copyright  sourceTree = SOURCE_ROOT; }; F5DF092E016CD3F901DC9062 = { - fallbackIsa = PBXFileReference; includeInIndex = 0; - isa = PBXFolderReference; + isa = PBXFileReference; lastKnownFileType = folder; name = demos; path = ../library/demos; @@ -4085,9 +4061,8 @@ MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Copyright  sourceTree = SOURCE_ROOT; }; F5DF0932016CD3F901DC9062 = { - fallbackIsa = PBXFileReference; includeInIndex = 0; - isa = PBXFolderReference; + isa = PBXFileReference; lastKnownFileType = folder; name = images; path = ../library/images; @@ -4119,9 +4094,8 @@ MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Copyright  sourceTree = SOURCE_ROOT; }; F5DF0936016CD3F901DC9062 = { - fallbackIsa = PBXFileReference; includeInIndex = 0; - isa = PBXFolderReference; + isa = PBXFileReference; lastKnownFileType = folder; name = msgs; path = ../library/msgs; diff --git a/macosx/tkMacOSXAppInit.c b/macosx/tkMacOSXAppInit.c deleted file mode 100644 index 1825219..0000000 --- a/macosx/tkMacOSXAppInit.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * tkAppInit.c -- - * - * Provides a default version of the Tcl_AppInit procedure for - * use in wish and similar Tk-based applications. - * - * Copyright (c) 1993 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright 2001, Apple Computer, Inc. - * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tkMacOSXAppInit.c,v 1.5 2004/02/16 00:19:41 wolfsuit Exp $ - */ -#include <pthread.h> -#include <sys/stat.h> -#include "tk.h" -#include "tclInt.h" -#include "locale.h" - -#include <Carbon/Carbon.h> -#include "tkPort.h" -#include "tkMacOSX.h" -#include "tkMacOSXEvent.h" - -/* - * If the App is in an App package, then we want to add the Scripts - * directory to the auto_path. But we have to wait till after the - * Tcl_Init is run, or it gets blown away. This stores what we - * figured out in main. - */ - -char scriptPath[PATH_MAX + 1]; - -extern Tcl_Interp *gStdoutInterp; - -#ifdef TK_TEST -extern int Tktest_Init _ANSI_ARGS_((Tcl_Interp *interp)); -#endif /* TK_TEST */ - -/* - *---------------------------------------------------------------------- - * - * main -- - * - * This is the main program for the application. - * - * Results: - * None: Tk_Main never returns here, so this procedure never - * returns either. - * - * Side effects: - * Whatever the application does. - * - *---------------------------------------------------------------------- - */ - -int -main(argc, argv) - int argc; /* Number of command-line arguments. */ - char **argv; /* Values of command-line arguments. */ -{ - int textEncoding; /* - * Variable used to take care of - * lazy font initialization - */ - CFBundleRef bundleRef; - - /* - * The following #if block allows you to change the AppInit - * function by using a #define of TCL_LOCAL_APPINIT instead - * of rewriting this entire file. The #if checks for that - * #define and uses Tcl_AppInit if it doesn't exist. - */ - -#ifndef TK_LOCAL_APPINIT -#define TK_LOCAL_APPINIT Tcl_AppInit -#endif - extern int TK_LOCAL_APPINIT _ANSI_ARGS_((Tcl_Interp *interp)); - - scriptPath[0] = '\0'; - - /* - * 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(). Note, if you use this - * hook, then I won't do the CFBundle lookup, since if you are messing - * around at this level, you probably don't want me to do this for you... - */ - -#ifdef TK_LOCAL_MAIN_HOOK - extern int TK_LOCAL_MAIN_HOOK _ANSI_ARGS_((int *argc, char ***argv)); - TK_LOCAL_MAIN_HOOK(&argc, &argv); -#else - - /* - * On MacOS X, we look for a file in the Resources/Scripts directory - * called AppMain.tcl and if found, we set argv[1] to that, so that - * the rest of the code will find it, and add the Scripts folder to - * the auto_path. If we don't find the startup script, we just bag - * it, assuming the user is starting up some other way. - */ - - bundleRef = CFBundleGetMainBundle(); - - if (bundleRef != NULL) { - CFURLRef appMainURL; - appMainURL = CFBundleCopyResourceURL(bundleRef, - CFSTR("AppMain"), - CFSTR("tcl"), - CFSTR("Scripts")); - - if (appMainURL != NULL) { - CFURLRef scriptFldrURL; - char *startupScript = malloc(PATH_MAX + 1); - - if (CFURLGetFileSystemRepresentation (appMainURL, true, - startupScript, PATH_MAX)) { - TclSetStartupScriptFileName(startupScript); - scriptFldrURL = CFBundleCopyResourceURL(bundleRef, - CFSTR("Scripts"), - NULL, - NULL); - CFURLGetFileSystemRepresentation(scriptFldrURL, - true, scriptPath, PATH_MAX); - CFRelease(scriptFldrURL); - } else { - free(startupScript); - } - CFRelease(appMainURL); - } - } - -#endif - textEncoding = GetApplicationTextEncoding(); - - /* - * Now add the scripts folder to the auto_path. - */ - - 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(interp) - Tcl_Interp *interp; /* Interpreter for application. */ -{ - if (Tcl_Init(interp) == TCL_ERROR) { - return TCL_ERROR; - } - if (Tk_Init(interp) == TCL_ERROR) { - return TCL_ERROR; - } - Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); - - if (scriptPath[0] != '\0') { - Tcl_SetVar(interp, "auto_path", scriptPath, - TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT|TCL_APPEND_VALUE); - } - -#ifdef TK_TEST - if (Tktest_Init(interp) == TCL_ERROR) { - return TCL_ERROR; - } - Tcl_StaticPackage(interp, "Tktest", Tktest_Init, - (Tcl_PackageInitProc *) NULL); -#endif /* TK_TEST */ - - /* - * If we don't have a TTY and stdin is a special character file of length 0, - * (e.g. /dev/null, which is what Finder sets when double clicking Wish) - * then use the Tk based console interpreter. - */ - - if (!isatty(0)) { - struct stat st; - if (fstat(0, &st) || (S_ISCHR(st.st_mode) && st.st_blocks == 0)) { - Tk_InitConsoleChannels(interp); - Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN)); - Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT)); - Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR)); - if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) { - goto error; - } - /* Only show the console if we don't have a startup script */ - if (TclGetStartupScriptPath() == NULL) { - Tcl_Eval(interp, "console show"); - } - } - } - - /* - * 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. - */ - - /* - * Call Tcl_CreateCommand for application-specific commands, if - * they weren't already created by the init procedures called above. - */ - - - /* - * Specify a user-specific startup file to invoke if the application - * is run interactively. Typically the startup file is "~/.apprc" - * where "app" is the name of the application. If this line is deleted - * then no user-specific startup file will be run under any conditions. - */ - - Tcl_SetVar(interp, "tcl_rcFileName", "~/.wishrc", TCL_GLOBAL_ONLY); - - return TCL_OK; - - error: - return TCL_ERROR; -} diff --git a/macosx/tkMacOSXDefault.h b/macosx/tkMacOSXDefault.h index 97878a1..3c04fc0 100644 --- a/macosx/tkMacOSXDefault.h +++ b/macosx/tkMacOSXDefault.h @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXDefault.h,v 1.5 2004/10/24 17:22:55 dkf Exp $ + * RCS: @(#) $Id: tkMacOSXDefault.h,v 1.6 2004/11/11 01:24:32 das Exp $ */ #ifndef _TKMACDEFAULT @@ -295,7 +295,12 @@ #define DEF_MENU_SELECT_COLOR "SystemMenuActive" #define DEF_MENU_SELECT_MONO BLACK #define DEF_MENU_TAKE_FOCUS "0" -#define DEF_MENU_TEAROFF "1" + +/* + * FIXME: Turn the default back to 1 when we make tearoff menus work again. + */ + +#define DEF_MENU_TEAROFF "0" #define DEF_MENU_TEAROFF_CMD (char *) NULL #define DEF_MENU_TITLE "" #define DEF_MENU_TYPE "normal" diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index d76b362..fff5370 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -11,9 +11,10 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.4 2004/02/23 10:48:10 das Exp $ + * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.5 2004/11/11 01:24:32 das Exp $ */ +#include "tclInt.h" #include "tkInt.h" #include "X11/X.h" #include "X11/Xlib.h" @@ -27,9 +28,9 @@ #ifndef PI # define PI 3.14159265358979323846 #endif -#define RGBFLOATRED( c ) (float)((float)(c.red) / 65535.0) -#define RGBFLOATGREEN( c ) (float)((float)(c.green) / 65535.0) -#define RGBFLOATBLUE( c ) (float)((float)(c.blue) / 65535.0) +#define RGBFLOATRED(c) (float)((float)(c.red) / 65535.0f) +#define RGBFLOATGREEN(c) (float)((float)(c.green) / 65535.0f) +#define RGBFLOATBLUE(c) (float)((float)(c.blue) / 65535.0f) /* * Temporary regions that can be reused. @@ -40,7 +41,8 @@ static RgnHandle tmpRgn2 = NULL; static PixPatHandle gPenPat = NULL; -static int useCGDrawing = 0; +static int useCGDrawing = 1; +static int tkMacOSXCGAntiAliasLimit = 1; /* * Prototypes for functions used only in this file. @@ -51,6 +53,37 @@ void TkMacOSXSetUpCGContext(MacDrawable *macWin, CGrafPtr destPort, GC gc, CGContextRef *contextPtr); void TkMacOSXReleaseCGContext(MacDrawable *macWin, CGrafPtr destPort, CGContextRef *context); +static inline double radians(double degrees) { return degrees * PI / 180.0f; } + +int +TkMacOSXInitCGDrawing(interp, enable, limit) + Tcl_Interp *interp; + int enable; + int limit; +{ + static Boolean initialized = FALSE; + + if (!initialized) { + if (Tcl_CreateNamespace(interp, "::tk::mac", NULL, NULL) == NULL) { + Tcl_ResetResult(interp); + } + if (Tcl_LinkVar(interp, "::tk::mac::useCGDrawing", + (char *) &useCGDrawing, + TCL_LINK_BOOLEAN) != TCL_OK) { + Tcl_ResetResult(interp); + } + useCGDrawing = enable; + + if (Tcl_LinkVar(interp, "::tk::mac::CGAntialiasLimit", + (char *) &tkMacOSXCGAntiAliasLimit, + TCL_LINK_INT) != TCL_OK) { + Tcl_ResetResult(interp); + } + tkMacOSXCGAntiAliasLimit = limit; + } + return TCL_OK; +} + /* *---------------------------------------------------------------------- * @@ -118,15 +151,15 @@ XCopyArea( srcPtr = &srcRect; SetRect(&srcRect, (short) (srcDraw->xOff + src_x), (short) (srcDraw->yOff + src_y), - (short) (srcDraw->xOff + src_x + width ), + (short) (srcDraw->xOff + src_x + width), (short) (srcDraw->yOff + src_y + height)); - if (tkPictureIsOpen ) { + if (tkPictureIsOpen) { dstPtr = &srcRect; } else { dstPtr = &dstRect; SetRect(&dstRect, (short) (dstDraw->xOff + dest_x), (short) (dstDraw->yOff + dest_y), - (short) (dstDraw->xOff + dest_x + width ), + (short) (dstDraw->xOff + dest_x + width), (short) (dstDraw->yOff + dest_y + height)); } TkMacOSXSetUpClippingRgn(dst); @@ -145,14 +178,15 @@ XCopyArea( * In this case, would have also clipped to the srcRect * ClipRect(&srcRect); */ + GetPortBounds(dstPort,&clpRect); dstPtr = &srcRect; ClipRect(&clpRect); } - if (!gc->clip_mask ) { + if (!gc->clip_mask) { } else if (((TkpClipMask*)gc->clip_mask)->type == TKP_CLIP_REGION) { RgnHandle clipRgn = (RgnHandle) - ((TkpClipMask*)gc->clip_mask)->value.region; + ((TkpClipMask*)gc->clip_mask)->value.region; int xOffset, yOffset; if (tmpRgn == NULL) { @@ -170,8 +204,8 @@ XCopyArea( OffsetRgn(clipRgn, -xOffset, -yOffset); } } - srcBit = GetPortBitMapForCopyBits( srcPort ); - dstBit = GetPortBitMapForCopyBits( dstPort ); + srcBit = GetPortBitMapForCopyBits(srcPort); + dstBit = GetPortBitMapForCopyBits(dstPort); tmode = srcCopy; CopyBits(srcBit, dstBit, srcPtr, dstPtr, tmode, NULL); @@ -225,7 +259,7 @@ XCopyPlane( CGrafPtr saveWorld; GDHandle saveDevice; RGBColor macColor; - TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask; + TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask; short tmode; srcPort = TkMacOSXGetDrawablePort(src); @@ -241,8 +275,8 @@ XCopyPlane( TkMacOSXSetUpClippingRgn(dst); - srcBit = GetPortBitMapForCopyBits ( srcPort ); - dstBit = GetPortBitMapForCopyBits ( dstPort ); + srcBit = GetPortBitMapForCopyBits(srcPort); + dstBit = GetPortBitMapForCopyBits(dstPort); SetRect(&srcRect, (short) (srcDraw->xOff + src_x), (short) (srcDraw->yOff + src_y), (short) (srcDraw->xOff + src_x + width), @@ -255,6 +289,7 @@ XCopyPlane( * clipping for color bitmaps. * To circumvent this problem, we clip to the whole window */ + Rect clpRect; GetPortBounds(dstPort,&clpRect); ClipRect(&clpRect); @@ -262,9 +297,9 @@ XCopyPlane( } else { dstPtr = &dstRect; SetRect(&dstRect, (short) (dstDraw->xOff + dest_x), - (short) (dstDraw->yOff + dest_y), - (short) (dstDraw->xOff + dest_x + width), - (short) (dstDraw->yOff + dest_y + height)); + (short) (dstDraw->yOff + dest_y), + (short) (dstDraw->xOff + dest_x + width), + (short) (dstDraw->yOff + dest_y + height)); } tmode = srcOr; tmode = srcCopy + transparent; @@ -274,10 +309,10 @@ XCopyPlane( } if (clipPtr == NULL || clipPtr->type == TKP_CLIP_REGION) { - /* * Case 1: opaque bitmaps. */ + TkSetMacColor(gc->background, &macColor); RGBBackColor(&macColor); tmode = srcCopy; @@ -289,6 +324,7 @@ XCopyPlane( * Case 2: transparent bitmaps. If it's color we ignore * the forecolor. */ + pm = GetPortPixMap(srcPort); if (GetPixDepth(pm) == 1) { tmode = srcOr; @@ -300,9 +336,10 @@ XCopyPlane( /* * Case 3: two arbitrary bitmaps. */ + tmode = srcCopy; mskPort = TkMacOSXGetDrawablePort(clipPtr->value.pixmap); - mskBit = GetPortBitMapForCopyBits ( mskPort ); + mskBit = GetPortBitMapForCopyBits(mskPort); CopyDeepMask(srcBit, mskBit, dstBit, srcPtr, srcPtr, dstPtr, tmode, NULL); } @@ -368,7 +405,7 @@ TkPutImage( /* Image from XGetImage, copy from containing GWorld directly */ GWorldPtr srcPort = TkMacOSXGetDrawablePort((Drawable)image->obdata); CopyBits(GetPortBitMapForCopyBits(srcPort), - GetPortBitMapForCopyBits (destPort), + GetPortBitMapForCopyBits(destPort), &srcRect, &destRect, srcCopy, NULL); } else if (image->depth == 1) { @@ -403,12 +440,15 @@ TkPutImage( bitmap.baseAddr = newData; bitmap.rowBytes = image->bytes_per_line; } - destBits = GetPortBitMapForCopyBits ( destPort ); + destBits = GetPortBitMapForCopyBits(destPort); CopyBits(&bitmap, destBits, &srcRect, &destRect, srcCopy, NULL); } else { - /* Color image */ + /* + * Color image + */ + PixMap pixmap; pixmap.bounds.left = 0; @@ -430,7 +470,7 @@ TkPutImage( pixmap.baseAddr = image->data; pixmap.rowBytes = image->bytes_per_line | 0x8000; - CopyBits((BitMap *) &pixmap, GetPortBitMapForCopyBits ( destPort ), + CopyBits((BitMap *) &pixmap, GetPortBitMapForCopyBits(destPort), &srcRect, &destRect, srcCopy, NULL); } @@ -477,15 +517,31 @@ XFillRectangles( SetGWorld(destPort, NULL); TkMacOSXSetUpClippingRgn(d); + if (useCGDrawing) { + CGContextRef outContext; + CGRect rect; + + TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); - TkMacOSXSetUpGraphicsPort(gc, destPort); + for (i = 0; i < n_rectangles; i++) { + rect = CGRectMake((float)(macWin->xOff + rectangles[i].x), + (float)(macWin->yOff + rectangles[i].y), + (float)rectangles[i].width, + (float)rectangles[i].height); + + CGContextFillRect(outContext, rect); + } + TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + } else { + TkMacOSXSetUpGraphicsPort(gc, destPort); - for (i = 0; i < n_rectangles; i++) { - theRect.left = (short) (macWin->xOff + rectangles[i].x); - theRect.top = (short) (macWin->yOff + rectangles[i].y); - theRect.right = (short) (theRect.left + rectangles[i].width); - theRect.bottom = (short) (theRect.top + rectangles[i].height); - FillCRect(&theRect, gPenPat); + for (i = 0; i < n_rectangles; i++) { + theRect.left = (short) (macWin->xOff + rectangles[i].x); + theRect.top = (short) (macWin->yOff + rectangles[i].y); + theRect.right = (short) (theRect.left + rectangles[i].width); + theRect.bottom = (short) (theRect.top + rectangles[i].height); + FillCRect(&theRect, gPenPat); + } } SetGWorld(saveWorld, saveDevice); @@ -539,13 +595,18 @@ XDrawLines( TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); CGContextBeginPath(outContext); - CGContextMoveToPoint(outContext, (float) points[0].x, - (float) points[0].y); - if (mode == CoordModeOrigin) { - for (i = 1; i < npoints; i++) { + CGContextMoveToPoint(outContext, (float)(macWin->xOff + points[0].x), + (float)(macWin->yOff + points[0].y)); + + for (i = 1; i < npoints; i++) { + if(mode==CoordModeOrigin) { CGContextAddLineToPoint(outContext, - (float) points[i].x, - (float) points[i].y); + (float) (macWin->xOff + points[i].x), + (float) (macWin->yOff + points[i].y)); + } else { + CGContextAddLineToPoint(outContext, + (float)(macWin->xOff + points[i].x), + (float)(macWin->yOff + points[i].y)); } } @@ -585,7 +646,7 @@ XDrawLines( * None. * * Side effects: - * Renders a series of connected lines. + * Renders a series of unconnected lines. * *---------------------------------------------------------------------- */ @@ -617,16 +678,17 @@ void XDrawSegments( TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); - CGContextBeginPath(outContext); for (i = 0; i < nsegments; i++) { + CGContextBeginPath(outContext); CGContextMoveToPoint(outContext, - (float) segments[i].x1, - (float) segments[i].y1); + (float)(macWin->xOff + segments[i].x1), + (float)(macWin->yOff + segments[i].y1)); CGContextAddLineToPoint (outContext, - (float) segments[i].x2, - (float) segments[i].y2); + (float)(macWin->xOff + segments[i].x2), + (float)(macWin->yOff + segments[i].y2)); + CGContextStrokePath(outContext); + } - CGContextStrokePath(outContext); TkMacOSXReleaseCGContext(macWin, destPort, &outContext); } else { TkMacOSXSetUpGraphicsPort(gc, destPort); @@ -693,18 +755,20 @@ XFillPolygon( TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); CGContextBeginPath(outContext); - CGContextMoveToPoint(outContext, (float) (points[0].x), - (float) (points[0].y)); + CGContextMoveToPoint(outContext, (float) (macWin->xOff + points[0].x), + (float) (macWin->yOff + points[0].y)); for (i = 1; i < npoints; i++) { if (mode == CoordModePrevious) { - CGContextAddLineToPoint(outContext, (float) points[i].x, + CGContextAddLineToPoint(outContext, (float)points[i].x, (float) points[i].y); } else { + CGContextAddLineToPoint(outContext, + (float)(macWin->xOff + points[i].x), + (float)(macWin->yOff + points[i].y)); } } - //CGContextStrokePath(outContext); - CGContextFillPath(outContext); + CGContextEOFillPath(outContext); TkMacOSXReleaseCGContext(macWin, destPort, &outContext); } else { TkMacOSXSetUpGraphicsPort(gc, destPort); @@ -772,19 +836,31 @@ XDrawRectangle( SetGWorld(destPort, NULL); TkMacOSXSetUpClippingRgn(d); + if (useCGDrawing) { + CGContextRef outContext; + CGRect rect; + + TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); - TkMacOSXSetUpGraphicsPort(gc, destPort); + rect = CGRectMake((float) ((float) macWin->xOff + (float) x), + (float) ((float) macWin->yOff + (float) y), + (float) width, + (float) height); + CGContextStrokeRect(outContext, rect); + TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + } else { + TkMacOSXSetUpGraphicsPort(gc, destPort); - theRect.left = (short) (macWin->xOff + x); - theRect.top = (short) (macWin->yOff + y); - theRect.right = (short) (theRect.left + width); - theRect.bottom = (short) (theRect.top + height); + theRect.left = (short) (macWin->xOff + x); + theRect.top = (short) (macWin->yOff + y); + theRect.right = (short) (theRect.left + width); + theRect.bottom = (short) (theRect.top + height); - ShowPen(); - PenPixPat(gPenPat); - FrameRect(&theRect); - HidePen(); - + ShowPen(); + PenPixPat(gPenPat); + FrameRect(&theRect); + HidePen(); + } SetGWorld(saveWorld, saveDevice); } @@ -823,7 +899,7 @@ XDrawRectangles( int nRects) { MacDrawable *macWin = (MacDrawable *) drawable; - Rect rect; + Rect theRect; CGrafPtr saveWorld; GDHandle saveDevice; GWorldPtr destPort; @@ -838,21 +914,36 @@ XDrawRectangles( TkMacOSXSetUpClippingRgn(drawable); - TkMacOSXSetUpGraphicsPort(gc, destPort); + if (useCGDrawing) { + CGContextRef outContext; + CGRect rect; + TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); - ShowPen(); - PenPixPat(gPenPat); + for (i = 0, rectPtr = rectArr; i < nRects; i++, rectPtr++) { + rect = CGRectMake((float) ((float) macWin->xOff + + (float) rectPtr->x), + (float) ((float) macWin->yOff + (float) rectPtr->y), + (float) rectPtr->width, + (float) rectPtr->height); + CGContextStrokeRect(outContext, rect); + } + TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + } else { + TkMacOSXSetUpGraphicsPort(gc, destPort); - for (i = 0, rectPtr = rectArr; i < nRects;i++, rectPtr++ ) { - rect.left = (short) (macWin->xOff + rectPtr->x); - rect.top = (short) (macWin->yOff + rectPtr->y); - rect.right = (short) (rect.left + rectPtr->width); - rect.bottom = (short) (rect.top + rectPtr->height); - FrameRect(&rect); - } - HidePen(); + ShowPen(); + PenPixPat(gPenPat); + for (i = 0, rectPtr = rectArr; i < nRects;i++, rectPtr++) { + theRect.left = (short) (macWin->xOff + rectPtr->x); + theRect.top = (short) (macWin->yOff + rectPtr->y); + theRect.right = (short) (theRect.left + rectPtr->width); + theRect.bottom = (short) (theRect.top + rectPtr->height); + FrameRect(&theRect); + } + HidePen(); + } SetGWorld(saveWorld, saveDevice); } @@ -890,10 +981,6 @@ XDrawArc( CGrafPtr saveWorld; GDHandle saveDevice; GWorldPtr destPort; - float fX = (float) x, - fY = (float) y, - fWidth = (float) width, - fHeight = (float) height; if (width == 0 || height == 0) { return; @@ -909,13 +996,20 @@ XDrawArc( if (useCGDrawing) { CGContextRef outContext; - CGAffineTransform transform; - int clockwise = angle1 ? 0 : 1; + CGRect boundingRect; + int clockwise; + float a,b; + CGPoint center; + float arc1, arc2; + + if (angle2 > 0) { + clockwise = 1; + } else { + clockwise = 0; + } TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); - CGContextBeginPath(outContext); - /* * If we are drawing an oval, we have to squash the coordinate * system before drawing, since CGContextAddArcToPoint only draws @@ -923,17 +1017,24 @@ XDrawArc( */ CGContextSaveGState(outContext); - transform = CGAffineTransformMakeTranslation((float) (x + width/2), - (float) (y + height/2)); - transform = CGAffineTransformScale(transform, 1.0, fHeight/fWidth); - CGContextConcatCTM(outContext, transform); - - CGContextAddArc(outContext, 0.0, 0.0, - (float) width/2, - (float) angle1, (float) angle2, clockwise); - - CGContextRestoreGState(outContext); - + boundingRect = CGRectMake( (float)(macWin->xOff + x), + (float)(macWin->yOff + y), + (float)(width), + (float)(height)); + + center = CGPointMake(CGRectGetMidX(boundingRect), + CGRectGetMidY(boundingRect)); + a = CGRectGetWidth(boundingRect)/2; + b = CGRectGetHeight(boundingRect)/2; + + CGContextTranslateCTM(outContext, center.x, center.y); + CGContextBeginPath(outContext); + CGContextScaleCTM(outContext, a, b); + arc1 = radians(-(angle1/64)); + arc2 = radians(-(angle2/64)) + arc1; + CGContextAddArc(outContext, 0.0, 0.0, 1, arc1, arc2, clockwise); + + CGContextRestoreGState(outContext); CGContextStrokePath(outContext); TkMacOSXReleaseCGContext(macWin, destPort, &outContext); } else { @@ -1003,23 +1104,66 @@ XDrawArcs( SetGWorld(destPort, NULL); TkMacOSXSetUpClippingRgn(d); + if (useCGDrawing) { + CGContextRef outContext; - TkMacOSXSetUpGraphicsPort(gc, destPort); + TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); + for (i=0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) { + CGRect boundingRect; + int clockwise; + float a,b, arc1, arc2; + CGPoint center; + + if (arcPtr[i].angle2 > 0) { + clockwise = 1; + } else { + clockwise = 0; + } - ShowPen(); - PenPixPat(gPenPat); - for (i = 0, arcPtr = arcArr;i < nArcs;i++, arcPtr++ ) { - rect.left = (short) (macWin->xOff + arcPtr->x); - rect.top = (short) (macWin->yOff + arcPtr->y); - rect.right = (short) (rect.left + arcPtr->width); - rect.bottom = (short) (rect.top + arcPtr->height); - start = (short) (90 - (arcPtr->angle1 / 64)); - extent = (short) (-(arcPtr->angle2 / 64)); - FrameArc(&rect, start, extent); - } - HidePen(); + /* + * If we are drawing an oval, we have to squash the coordinate + * system before drawing, since CGContextAddArcToPoint only draws + * circles. + */ + CGContextSaveGState(outContext); + CGContextBeginPath(outContext); + boundingRect = CGRectMake( (float)(macWin->xOff + arcPtr[i].x), + (float)(macWin->yOff + arcPtr[i].y), + (float)arcPtr[i].width, + (float)arcPtr[i].height); + + center = CGPointMake(CGRectGetMidX(boundingRect), + CGRectGetMidY(boundingRect)); + a = CGRectGetWidth(boundingRect)/2; + b = CGRectGetHeight(boundingRect)/2; + + CGContextTranslateCTM(outContext, center.x, center.y); + CGContextScaleCTM(outContext, a, b); + arc1 = radians(-(arcPtr[i].angle1/64)); + arc2 = radians(-(arcPtr[i].angle2/64)) + arc1; + CGContextAddArc(outContext, 0.0, 0.0, 1, arc1, arc2, clockwise); + CGContextRestoreGState(outContext); + CGContextStrokePath(outContext); + } + TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + } else { + TkMacOSXSetUpGraphicsPort(gc, destPort); + + ShowPen(); + PenPixPat(gPenPat); + for (i = 0, arcPtr = arcArr;i < nArcs;i++, arcPtr++) { + rect.left = (short) (macWin->xOff + arcPtr->x); + rect.top = (short) (macWin->yOff + arcPtr->y); + rect.right = (short) (rect.left + arcPtr->width); + rect.bottom = (short) (rect.top + arcPtr->height); + start = (short) (90 - (arcPtr->angle1 / 64)); + extent = (short) (-(arcPtr->angle2 / 64)); + FrameArc(&rect, start, extent); + } + HidePen(); + } SetGWorld(saveWorld, saveDevice); } @@ -1070,16 +1214,65 @@ XFillArc( TkMacOSXSetUpClippingRgn(d); - TkMacOSXSetUpGraphicsPort(gc, destPort); + if (useCGDrawing) { + CGContextRef outContext; + CGRect boundingRect; + int clockwise; + float a,b; + CGPoint center; + + if (angle2 > 0) { + clockwise = 1; + } else { + clockwise = 0; + } + + TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); + + boundingRect = CGRectMake((float) (macWin->xOff + x), + (float) (macWin->yOff + y), + (float) width, + (float) height); + center = CGPointMake(CGRectGetMidX(boundingRect), + CGRectGetMidY(boundingRect)); + a = CGRectGetWidth(boundingRect)/2; + b = CGRectGetHeight(boundingRect)/2; + + if (gc->arc_mode == ArcChord) { + float arc1, arc2; + + CGContextBeginPath(outContext); + CGContextTranslateCTM(outContext, center.x, center.y); + CGContextScaleCTM(outContext, a, b); + arc1 = radians(-(angle1/64)); + arc2 = radians(-(angle2/64)) + arc1; + CGContextAddArc(outContext, 0.0, 0.0, 1, arc1, arc2, clockwise); + CGContextFillPath(outContext); + } else if (gc->arc_mode == ArcPieSlice) { + float arc1, arc2; + + CGContextTranslateCTM(outContext, center.x, center.y); + CGContextScaleCTM(outContext,a,b); + arc1 = radians(-(angle1/64)); + arc2 = radians(-(angle2/64)) + arc1; + CGContextAddArc(outContext, 0.0, 0.0, 1, arc1, arc2, clockwise); + CGContextAddLineToPoint(outContext, 0.0f, 0.0f); + CGContextClosePath(outContext); + CGContextFillPath(outContext); + } + + TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + } else { + TkMacOSXSetUpGraphicsPort(gc, destPort); - theRect.left = (short) (macWin->xOff + x); - theRect.top = (short) (macWin->yOff + y); - theRect.right = (short) (theRect.left + width); - theRect.bottom = (short) (theRect.top + height); - start = (short) (90 - (angle1 / 64)); - extent = (short) (- (angle2 / 64)); + theRect.left = (short) (macWin->xOff + x); + theRect.top = (short) (macWin->yOff + y); + theRect.right = (short) (theRect.left + width); + theRect.bottom = (short) (theRect.top + height); + start = (short) (90 - (angle1 / 64)); + extent = (short) (- (angle2 / 64)); - if (gc->arc_mode == ArcChord) { + if (gc->arc_mode == ArcChord) { boxWidth = theRect.right - theRect.left; boxHeight = theRect.bottom - theRect.top; angle = -(angle1/64.0)*PI/180.0; @@ -1095,26 +1288,26 @@ XFillArc( center2[0] = vertex[0] + cos2*boxWidth/2.0; center2[1] = vertex[1] + sin2*boxHeight/2.0; - polygon = OpenPoly(); - MoveTo((short) ((theRect.left + theRect.right)/2), - (short) ((theRect.top + theRect.bottom)/2)); + polygon = OpenPoly(); + MoveTo((short) ((theRect.left + theRect.right)/2), + (short) ((theRect.top + theRect.bottom)/2)); - LineTo((short) (center1[0] + 0.5), (short) (center1[1] + 0.5)); - LineTo((short) (center2[0] + 0.5), (short) (center2[1] + 0.5)); - ClosePoly(); + LineTo((short) (center1[0] + 0.5), (short) (center1[1] + 0.5)); + LineTo((short) (center2[0] + 0.5), (short) (center2[1] + 0.5)); + ClosePoly(); - ShowPen(); - FillCArc(&theRect, start, extent, gPenPat); - FillCPoly(polygon, gPenPat); - HidePen(); + ShowPen(); + FillCArc(&theRect, start, extent, gPenPat); + FillCPoly(polygon, gPenPat); + HidePen(); - KillPoly(polygon); - } else { - ShowPen(); - FillCArc(&theRect, start, extent, gPenPat); - HidePen(); + KillPoly(polygon); + } else { + ShowPen(); + FillCArc(&theRect, start, extent, gPenPat); + HidePen(); + } } - SetGWorld(saveWorld, saveDevice); } @@ -1162,50 +1355,139 @@ XFillArcs( TkMacOSXSetUpClippingRgn(d); - TkMacOSXSetUpGraphicsPort(gc, destPort); + if (useCGDrawing) { + CGContextRef outContext; + + TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); + for (i = 0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) { + CGRect boundingRect; + int clockwise = arcPtr[i].angle1; + float a,b; + CGPoint center; + + if (arcPtr[i].angle2 > 0) { + clockwise = 1; + } else { + clockwise = 0; + } - for (i = 0, arcPtr = arcArr;i<nArcs;i++, arcPtr++ ) { - rect.left = (short) (macWin->xOff + arcPtr->x); - rect.top = (short) (macWin->yOff + arcPtr->y); - rect.right = (short) (rect.left + arcPtr->width); - rect.bottom = (short) (rect.top + arcPtr->height); - start = (short) (90 - (arcPtr->angle1 / 64)); - extent = (short) (- (arcPtr->angle2 / 64)); + /* + * If we are drawing an oval, we have to squash the coordinate + * system before drawing, since CGContextAddArcToPoint only draws + * circles. + */ + + if (gc->arc_mode == ArcChord) { + + CGContextBeginPath(outContext); + boundingRect = CGRectMake((float)(macWin->xOff + arcPtr[i].x), + (float)(macWin->yOff + arcPtr[i].y), + (float)arcPtr[i].width, + (float)arcPtr[i].height); + center = CGPointMake(CGRectGetMidX(boundingRect), + CGRectGetMidY(boundingRect)); + a = CGRectGetWidth(boundingRect)/2.0; + b = CGRectGetHeight(boundingRect)/2.0; + + angle = -(arcPtr->angle1/64.0)*PI/180.0; + sin1 = sin(angle); + cos1 = cos(angle); + angle -= (arcPtr->angle2/64.0)*PI/180.0; + sin2 = sin(angle); + cos2 = cos(angle); + vertex[0] = (CGRectGetMinX(boundingRect) + + CGRectGetMaxX(boundingRect))/2.0; + vertex[1] = (CGRectGetMaxY(boundingRect) + + CGRectGetMinY(boundingRect))/2.0; + center1[0] = vertex[0] + cos1*a; + center1[1] = vertex[1] + sin1*b; + center2[0] = vertex[0] + cos2*a; + center2[1] = vertex[1] + sin2*b; + + CGContextScaleCTM(outContext, a, b); + + CGContextBeginPath(outContext); + CGContextMoveToPoint(outContext, (float) vertex[0], + (float) vertex[1]); + CGContextAddLineToPoint(outContext, + (float) (center1[0] + 0.5), + (float) (center1[1] + 0.5)); + CGContextAddLineToPoint(outContext, + (float) (center2[0] + 0.5), + (float) (center2[1] + 0.5)); + CGContextFillPath(outContext); + } else if (gc->arc_mode == ArcPieSlice) { + float arc1, arc2; + CGContextBeginPath(outContext); + boundingRect = CGRectMake((float)(macWin->xOff + arcPtr[i].x), + (float)(macWin->yOff + arcPtr[i].y), + (float)arcPtr[i].width, + (float)arcPtr[i].height); + center = CGPointMake(CGRectGetMidX(boundingRect), + CGRectGetMidY(boundingRect)); + a = CGRectGetWidth(boundingRect)/2; + b = CGRectGetHeight(boundingRect)/2; + + CGContextTranslateCTM(outContext, center.x, center.y); + CGContextScaleCTM(outContext, a, b); + arc1 = radians(-(arcPtr[i].angle1/64)); + arc2 = radians(-(arcPtr[i].angle2/64)) + arc1; + CGContextAddArc(outContext, 0.0, 0.0, 1, + arc1, arc2, clockwise); + CGContextAddLineToPoint(outContext, 0.0f, 0.0f); + CGContextClosePath(outContext); + CGContextFillPath(outContext); + } + } + + TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + } else { + + TkMacOSXSetUpGraphicsPort(gc, destPort); - if (gc->arc_mode == ArcChord) { - boxWidth = rect.right - rect.left; - boxHeight = rect.bottom - rect.top; - angle = -(arcPtr->angle1/64.0)*PI/180.0; - sin1 = sin(angle); - cos1 = cos(angle); - angle -= (arcPtr->angle2/64.0)*PI/180.0; - sin2 = sin(angle); - cos2 = cos(angle); - vertex[0] = (rect.left + rect.right)/2.0; - vertex[1] = (rect.top + rect.bottom)/2.0; - center1[0] = vertex[0] + cos1*boxWidth/2.0; - center1[1] = vertex[1] + sin1*boxHeight/2.0; - center2[0] = vertex[0] + cos2*boxWidth/2.0; - center2[1] = vertex[1] + sin2*boxHeight/2.0; + for (i = 0, arcPtr = arcArr;i<nArcs;i++, arcPtr++) { + rect.left = (short) (macWin->xOff + arcPtr->x); + rect.top = (short) (macWin->yOff + arcPtr->y); + rect.right = (short) (rect.left + arcPtr->width); + rect.bottom = (short) (rect.top + arcPtr->height); + start = (short) (90 - (arcPtr->angle1 / 64)); + extent = (short) (- (arcPtr->angle2 / 64)); + + if (gc->arc_mode == ArcChord) { + boxWidth = rect.right - rect.left; + boxHeight = rect.bottom - rect.top; + angle = -(arcPtr->angle1/64.0)*PI/180.0; + sin1 = sin(angle); + cos1 = cos(angle); + angle -= (arcPtr->angle2/64.0)*PI/180.0; + sin2 = sin(angle); + cos2 = cos(angle); + vertex[0] = (rect.left + rect.right)/2.0; + vertex[1] = (rect.top + rect.bottom)/2.0; + center1[0] = vertex[0] + cos1*boxWidth/2.0; + center1[1] = vertex[1] + sin1*boxHeight/2.0; + center2[0] = vertex[0] + cos2*boxWidth/2.0; + center2[1] = vertex[1] + sin2*boxHeight/2.0; - polygon = OpenPoly(); - MoveTo((short) ((rect.left + rect.right)/2), - (short) ((rect.top + rect.bottom)/2)); + polygon = OpenPoly(); + MoveTo((short) ((rect.left + rect.right)/2), + (short) ((rect.top + rect.bottom)/2)); - LineTo((short) (center1[0] + 0.5), (short) (center1[1] + 0.5)); - LineTo((short) (center2[0] + 0.5), (short) (center2[1] + 0.5)); - ClosePoly(); + LineTo((short) (center1[0] + 0.5), (short) (center1[1] + 0.5)); + LineTo((short) (center2[0] + 0.5), (short) (center2[1] + 0.5)); + ClosePoly(); - ShowPen(); - FillCArc(&rect, start, extent, gPenPat); - FillCPoly(polygon, gPenPat); - HidePen(); + ShowPen(); + FillCArc(&rect, start, extent, gPenPat); + FillCPoly(polygon, gPenPat); + HidePen(); - KillPoly(polygon); - } else { - ShowPen(); - FillCArc(&rect, start, extent, gPenPat); - HidePen(); + KillPoly(polygon); + } else { + ShowPen(); + FillCArc(&rect, start, extent, gPenPat); + HidePen(); + } } } SetGWorld(saveWorld, saveDevice); @@ -1389,7 +1671,6 @@ TkMacOSXSetUpGraphicsPort( PenSize(gc->line_width, gc->line_width); } if (gc->line_style != LineSolid) { - unsigned char *p = (unsigned char *) &(gc->dashes); /* * Here the dash pattern should be set in the drawing, * environment, but I don't know how to do that for the Mac. @@ -1408,9 +1689,9 @@ TkMacOSXSetUpGraphicsPort( * url: http://purl.oclc.org/net/nijtmans/ * * FIXME: - * This is not possible with QuickDraw line drawing, we either - * have to convert all line drawings to regions, or, on Mac OS X - * we can use CG to draw our lines instead of QuickDraw. + * This is not possible with QuickDraw line drawing. As of + * Tk 8.4.7 we have a complete set of drawing routines using + * CG, so there is no reason to support this here. */ } } @@ -1441,43 +1722,54 @@ TkMacOSXSetUpCGContext( CGContextRef outContext; OSStatus err; Rect boundsRect; - CGAffineTransform coordsTransform; + CGAffineTransform coordsTransform; + static RgnHandle clipRgn = NULL; err = QDBeginCGContext(destPort, contextPtr); outContext = *contextPtr; - - CGContextSaveGState(outContext); - + + /* + * Now clip the CG Context to the port. Note, we have already + * set up the port with our clip region, so we can just get + * the clip back out of there. If we use the macWin->clipRgn + * directly at this point, we get some odd drawing effects. + * + * We also have to intersect our clip region with the port + * visible region so we don't overwrite the window decoration. + */ + + if (!clipRgn) { + clipRgn = NewRgn(); + } + GetPortBounds(destPort, &boundsRect); - CGContextResetCTM(outContext); - coordsTransform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0, - (float)(boundsRect.bottom - boundsRect.top)); - CGContextConcatCTM(outContext, coordsTransform); + RectRgn(clipRgn, &boundsRect); + SectRegionWithPortClipRegion(destPort, clipRgn); + SectRegionWithPortVisibleRegion(destPort, clipRgn); + ClipCGContextToRegion(outContext, &boundsRect, clipRgn); + SetEmptyRgn(clipRgn); - if (macWin->clipRgn != NULL) { - ClipCGContextToRegion(outContext, &boundsRect, macWin->clipRgn); - } else { - RgnHandle clipRgn = NewRgn(); - GetPortClipRegion(destPort, clipRgn); - ClipCGContextToRegion(outContext, &boundsRect, - clipRgn); - DisposeRgn(clipRgn); - } + /* + * Note: You have to call SyncCGContextOriginWithPort + * AFTER all the clip region manipulations. + */ + + SyncCGContextOriginWithPort(outContext, destPort); - /* Now offset the CTM to the subwindow offset */ + coordsTransform = CGAffineTransformMake(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, + (float) (boundsRect.bottom - boundsRect.top)); + CGContextConcatCTM(outContext, coordsTransform); - CGContextTranslateCTM(outContext, macWin->xOff, macWin->yOff); + /* Now offset the CTM to the subwindow offset */ if (TkSetMacColor(gc->foreground, &macColor) == true) { - CGContextSetRGBStrokeColor(outContext, RGBFLOATRED(macColor), - RGBFLOATGREEN(macColor), - RGBFLOATBLUE(macColor), 1.0); - } - if (TkSetMacColor(gc->background, &macColor) == true) { CGContextSetRGBFillColor(outContext, RGBFLOATRED(macColor), - RGBFLOATGREEN(macColor), - RGBFLOATBLUE(macColor), 1.0); + RGBFLOATGREEN(macColor), + RGBFLOATBLUE(macColor), 1.0f); + CGContextSetRGBStrokeColor(outContext, RGBFLOATRED(macColor), + RGBFLOATGREEN(macColor), + RGBFLOATBLUE(macColor), 1.0f); } if(gc->function == GXxor) { @@ -1485,30 +1777,44 @@ TkMacOSXSetUpCGContext( CGContextSetLineWidth(outContext, (float) gc->line_width); - if (gc->line_style != LineSolid) { - unsigned char *p = (unsigned char *) &(gc->dashes); + /* When should we antialias? */ + if (gc->line_width < tkMacOSXCGAntiAliasLimit) { + CGContextSetShouldAntialias(outContext, 0); + } else { + CGContextSetShouldAntialias(outContext, 1); + } + + if (gc->line_style != LineSolid) { + int num = 0; + char *p = &(gc->dashes); + float dashOffset = (float) gc->dash_offset; + float lengths[10]; + + while (p[num] != '\0') { + lengths[num] = (float) (p[num]); + num++; + } + CGContextSetLineDash(outContext, dashOffset, lengths, num); + } + + if (gc->cap_style == CapButt) { /* - * Here the dash pattern should be set in the drawing, - * environment, but I don't know how to do that for the Mac. - * - * p[] is an array of unsigned chars containing the dash list. - * A '\0' indicates the end of this list. - * - * Someone knows how to implement this? If you have a more - * complete implementation of SetUpGraphicsPort() for - * the Mac (or for Windows), please let me know. - * - * Jan Nijtmans - * CMG Arnhem, B.V. - * email: j.nijtmans@chello.nl (private) - * jan.nijtmans@cmg.nl (work) - * url: http://purl.oclc.org/net/nijtmans/ - * - * FIXME: - * This is not possible with QuickDraw line drawing, we either - * have to convert all line drawings to regions, or, on Mac OS X - * we can use CG to draw our lines instead of QuickDraw. + * What about CapNotLast, CapProjecting? */ + + CGContextSetLineCap(outContext, kCGLineCapButt); + } else if (gc->cap_style == CapRound) { + CGContextSetLineCap(outContext, kCGLineCapRound); + } else if (gc->cap_style == CapProjecting) { + CGContextSetLineCap(outContext, kCGLineCapSquare); + } + + if (gc->join_style == JoinMiter) { + CGContextSetLineJoin(outContext, kCGLineJoinMiter); + } else if (gc->join_style == JoinRound) { + CGContextSetLineJoin(outContext, kCGLineJoinRound); + } else if (gc->join_style == JoinBevel) { + CGContextSetLineJoin(outContext, kCGLineJoinBevel); } } @@ -1518,10 +1824,8 @@ TkMacOSXReleaseCGContext( CGrafPtr destPort, CGContextRef *outContext) { - CGContextResetCTM(*outContext); - CGContextRestoreGState(*outContext); + CGContextSynchronize(*outContext); QDEndCGContext(destPort, outContext); - } /* @@ -1617,7 +1921,7 @@ TkMacOSXMakeStippleMap( destPort = TkMacOSXGetDrawablePort(drawable); - GetPortBounds ( destPort, &portRect ); + GetPortBounds (destPort, &portRect); width = portRect.right - portRect.left; height = portRect.bottom - portRect.top; @@ -1640,7 +1944,7 @@ TkMacOSXMakeStippleMap( bounds.right = j + stippleWidth; bounds.bottom = i + stippleHeight; - CopyBits(GetPortBitMapForCopyBits ( destPort ), bitmapPtr, + CopyBits(GetPortBitMapForCopyBits(destPort), bitmapPtr, &portRect, &bounds, srcCopy, NULL); } } @@ -1716,7 +2020,8 @@ TkpDrawHighlightBorder ( } else { TkDrawInsetFocusHighlight (tkwin, bgGC, highlightWidth, drawable, 0); if (fgGC != bgGC) { - TkDrawInsetFocusHighlight (tkwin, fgGC, highlightWidth - 1, drawable, 0); + TkDrawInsetFocusHighlight (tkwin, fgGC, highlightWidth - 1, + drawable, 0); } } } diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index df7f255..07127eb 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -10,11 +10,14 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXInit.c,v 1.5 2004/02/16 00:19:42 wolfsuit Exp $ + * RCS: @(#) $Id: tkMacOSXInit.c,v 1.6 2004/11/11 01:24:32 das Exp $ */ #include "tkInt.h" #include "tkMacOSXInt.h" +#include "tclInt.h" +#include <sys/stat.h> +#include <mach-o/dyld.h> /* * The Init script (common to Windows and Unix platforms) is @@ -23,6 +26,15 @@ #include "tkInitScript.h" /* + * Define the following to 0 to not attempt to use an undocumented SPI + * to notify the window server that an unbundled executable is a full + * GUI application after loading Tk. + */ +#ifndef MAC_OSX_TK_USE_CPS_SPI +#define MAC_OSX_TK_USE_CPS_SPI 1 +#endif + +/* * The following structures are used to map the script/language codes of a * font to the name that should be passed to Tcl_GetEncoding() to obtain * the encoding for that font. The set of numeric constants is fixed and @@ -72,6 +84,11 @@ static Map scriptMap[] = { Tcl_Encoding TkMacOSXCarbonEncoding = NULL; +/* + * If the App is in an App package, then we want to add the Scripts + * directory to the auto_path. + */ +static char scriptPath[PATH_MAX + 1] = ""; /* *---------------------------------------------------------------------- @@ -95,30 +112,28 @@ int TkpInit(interp) Tcl_Interp *interp; { - char tkLibPath[1024]; - int result; - static int menusInitialized = false; - static int carbonEncodingInitialized = false; + static char tkLibPath[PATH_MAX + 1]; + static int tkMacOSXInitialized = false; /* * Since it is possible for TkInit to be called multiple times - * and we don't want to do the menu initialization multiple times + * and we don't want to do the initialization multiple times * we protect against doing it more than once. */ - if (menusInitialized == false) { - menusInitialized = true; + if (tkMacOSXInitialized == false) { + CFStringEncoding encoding; + char *encodingStr = NULL; + int i; + + tkMacOSXInitialized = true; + Tk_MacOSXSetupTkNotifier(); TkMacOSXInitAppleEvents(interp); TkMacOSXInitCarbonEvents(interp); TkMacOSXInitMenus(interp); TkMacOSXUseAntialiasedText(interp, TRUE); - } - - if (carbonEncodingInitialized == false) { - CFStringEncoding encoding; - char *encodingStr = NULL; - int i; + TkMacOSXInitCGDrawing(interp, TRUE, 3); encoding = CFStringGetSystemEncoding(); @@ -136,20 +151,112 @@ TkpInit(interp) if (TkMacOSXCarbonEncoding == NULL) { TkMacOSXCarbonEncoding = Tcl_GetEncoding (NULL, NULL); } - } + + /* + * When Tk is in a framework, force tcl_findLibrary to look in the + * framework scripts directory. + * FIXME: Should we come up with a more generic way of doing this? + */ + + Tcl_MacOSXOpenVersionedBundleResources(interp, + "com.tcltk.tklibrary", TK_VERSION, 1, 1024, tkLibPath); + + /* + * If we don't have a TTY and stdin is a special character file of length 0, + * (e.g. /dev/null, which is what Finder sets when double clicking Wish) + * then use the Tk based console interpreter. + */ - /* - * When Tk is in a framework, force tcl_findLibrary to look in the - * framework scripts directory. - * FIXME: Should we come up with a more generic way of doing this? - */ - - result = Tcl_MacOSXOpenVersionedBundleResources(interp, - "com.tcltk.tklibrary", TK_VERSION, 1, 1024, tkLibPath); - - if (result != TCL_ERROR) { + if (!isatty(0)) { + struct stat st; + if (fstat(0, &st) || (S_ISCHR(st.st_mode) && st.st_blocks == 0)) { + Tk_InitConsoleChannels(interp); + Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN)); + Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT)); + Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR)); + if (Tk_CreateConsoleWindow(interp) == TCL_OK) { + /* Only show the console if we don't have a startup script */ + if (Tcl_GetStartupScript(NULL) == NULL) { + Tcl_Eval(interp, "console show"); + } + } + } + } +#if MAC_OSX_TK_USE_CPS_SPI + /* + * If we are loaded into an executable that is not a bundled application, + * the window server does not let us come to the foreground. + * For such an executable, we attempt to use an undocumented SPI to + * notify the window server that we are now a full GUI application. + */ + { + /* Check whether we are a bundled executable: */ + int bundledExecutable = 0; + CFBundleRef bundleRef = CFBundleGetMainBundle(); + CFURLRef bundleUrl = NULL; + if (bundleRef) { + bundleUrl = CFBundleCopyBundleURL(bundleRef); + } + if (bundleUrl) { + /* + * A bundled executable is two levels down from its main bundle + * directory (e.g. Wish.app/Contents/MacOS/Wish), whereas + * an unbundled executable's main bundle directory is just + * the directory containing the executable. + * So to check whether we are bundled, we delete the last three + * path components of the executable's url and compare the + * resulting url with the main bundle url. + */ + int j = 3; + CFURLRef url = CFBundleCopyExecutableURL(bundleRef); + while (url && j--) { + CFURLRef parent = CFURLCreateCopyDeletingLastPathComponent(NULL, url); + CFRelease(url); + url = parent; + } + if (url) { + bundledExecutable = CFEqual(bundleUrl, url); + CFRelease(url); + } + CFRelease(bundleUrl); + } + + /* If we are not a bundled executable, attempt to use the CPS SPI: */ + if (!bundledExecutable) { + /* + * Load the CPS SPI symbol dynamically, so that we don't break + * if it every disappears or changes its name. + */ + OSErr (*cpsEnableForegroundOperation)(ProcessSerialNumberPtr) = NULL; + NSSymbol nsSymbol; + if(NSIsSymbolNameDefinedWithHint( + "_CPSEnableForegroundOperation", "CoreGraphics")) { + nsSymbol = NSLookupAndBindSymbolWithHint( + "_CPSEnableForegroundOperation", "CoreGraphics"); + if(nsSymbol) { + cpsEnableForegroundOperation = NSAddressOfSymbol(nsSymbol); + } + } + if (cpsEnableForegroundOperation) { + ProcessSerialNumber psn = { 0, kCurrentProcess }; + /* + * Let the window server know that we are a foregroundable app + */ + cpsEnableForegroundOperation(&psn); + } + } + } +#endif /* MAC_OSX_TK_USE_CPS_SPI */ + } + + if (tkLibPath[0] != '\0') { Tcl_SetVar(interp, "tk_library", tkLibPath, TCL_GLOBAL_ONLY); } + + if (scriptPath[0] != '\0') { + Tcl_SetVar(interp, "auto_path", scriptPath, + TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT|TCL_APPEND_VALUE); + } return Tcl_Eval(interp, initScript); } @@ -221,3 +328,59 @@ TkpDisplayWarning(msg, title) Tcl_WriteChars(errChannel, "\n", 1); } } + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXDefaultStartupScript -- + * + * + * On MacOS X, we look for a file in the Resources/Scripts + * directory called AppMain.tcl and if found, we set argv[1] to + * that, so that the rest of the code will find it, and add the + * Scripts folder to the auto_path. If we don't find the startup + * script, we just bag it, assuming the user is starting up some + * other way. + * + * Results: + * None. + * + * Side effects: + * Tcl_SetStartupScript() called when AppMain.tcl found. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXDefaultStartupScript(void) +{ + CFBundleRef bundleRef; + + bundleRef = CFBundleGetMainBundle(); + + if (bundleRef != NULL) { + CFURLRef appMainURL; + appMainURL = CFBundleCopyResourceURL(bundleRef, + CFSTR("AppMain"), + CFSTR("tcl"), + CFSTR("Scripts")); + + if (appMainURL != NULL) { + CFURLRef scriptFldrURL; + char startupScript[PATH_MAX + 1]; + + if (CFURLGetFileSystemRepresentation (appMainURL, true, + startupScript, PATH_MAX)) { + Tcl_SetStartupScript(Tcl_NewStringObj(startupScript, -1), NULL); + scriptFldrURL = CFURLCreateCopyDeletingLastPathComponent( + NULL, appMainURL); + if (scriptFldrURL != NULL) { + CFURLGetFileSystemRepresentation(scriptFldrURL, + true, scriptPath, PATH_MAX); + CFRelease(scriptFldrURL); + } + } + CFRelease(appMainURL); + } + } +} diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index df1089b..978f12a 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXInt.h,v 1.4 2004/02/16 00:19:42 wolfsuit Exp $ + * RCS: @(#) $Id: tkMacOSXInt.h,v 1.5 2004/11/11 01:24:32 das Exp $ */ #ifndef _TKMACINT @@ -151,12 +151,9 @@ extern TkMacOSXWindowList *tkMacOSXWindowListPtr; extern Tcl_Encoding TkMacOSXCarbonEncoding; extern int TkMacOSXUseAntialiasedText(Tcl_Interp *interp, int enable); - -/* - * FIXME: Put this into the decls file? - */ - extern void TkMacOSXInitCarbonEvents (Tcl_Interp *interp); +extern int TkMacOSXInitCGDrawing(Tcl_Interp *interp, int enable, int antiAlias); +extern void TkMacOSXDefaultStartupScript(void); #include "tkIntPlatDecls.h" diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index 7ad48b4..09126b8 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXMenu.c,v 1.15 2004/09/03 14:09:05 dkf Exp $ + * RCS: @(#) $Id: tkMacOSXMenu.c,v 1.16 2004/11/11 01:24:32 das Exp $ */ #include "tkMacOSXInt.h" #include "tkMenubutton.h" @@ -141,9 +141,6 @@ typedef struct TopLevelMenubarList { #define CASCADE_CMD (0x1b) /* The special command char for cascade * menus. */ -#define SEPARATOR_TEXT "\p(-" - /* The text for a menu separator. */ - #define MENUBAR_REDRAW_PENDING 1 #define SCREEN_MARGIN 5 @@ -1079,7 +1076,9 @@ ReconfigureIndividualMenu( */ if (mePtr->type == SEPARATOR_ENTRY) { - AppendMenu(macMenuHdl, SEPARATOR_TEXT); + AppendMenuItemTextWithCFString (macMenuHdl, NULL, + kMenuItemAttrSeparator | kMenuItemAttrDisabled, + 0, NULL); } else { Tcl_DString itemTextDString; int destWrote; @@ -1087,13 +1086,12 @@ ReconfigureIndividualMenu( GetEntryText(mePtr, &itemTextDString); cf = CFStringCreateWithCString(NULL, Tcl_DStringValue(&itemTextDString), kCFStringEncodingUTF8); - AppendMenu(macMenuHdl, "\px"); if (cf != NULL) { - SetMenuItemTextWithCFString(macMenuHdl, base + index, cf); + AppendMenuItemTextWithCFString (macMenuHdl, cf, 0, 0, NULL); CFRelease(cf); } else { cf = CFSTR ("<Error>"); - SetMenuItemTextWithCFString(macMenuHdl, base + index, cf); + AppendMenuItemTextWithCFString (macMenuHdl, cf, 0, 0, NULL); } Tcl_DStringFree(&itemTextDString); @@ -2103,6 +2101,7 @@ EventuallyInvokeMenu (ClientData data) code = TkInvokeMenu(realData->menuPtr->interp, realData->menuPtr, realData->index); + if (code != TCL_OK && code != TCL_CONTINUE && code != TCL_BREAK) { Tcl_AddErrorInfo(realData->menuPtr->interp, "\n (menu invoke)"); diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index cab8a93..168ef73 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -117,6 +117,7 @@ TkMacOSXProcessMouseEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) int status,err; MouseEventData mouseEventData, * medPtr = &mouseEventData; KeyMap keyMap; + long modif; switch (eventPtr->eKind) { case kEventMouseUp: @@ -140,19 +141,21 @@ TkMacOSXProcessMouseEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) } medPtr->state = 0; GetKeys(keyMap); - if (keyMap[1] & 2) { + modif = EndianS32_BtoN(*(long*)(&keyMap[1])); + + if (modif & 2) { medPtr->state |= LockMask; } - if (keyMap[1] & 1) { + if (modif & 1) { medPtr->state |= ShiftMask; } - if (keyMap[1] & 8) { + if (modif & 8) { medPtr->state |= ControlMask; } - if (keyMap[1] & 32768) { + if (modif & 32768) { medPtr->state |= Mod1Mask; /* command key */ } - if (keyMap[1] & 4) { + if (modif & 4) { medPtr->state |= Mod2Mask; /* option key */ } if (eventPtr->eKind == kEventMouseDown @@ -381,7 +384,7 @@ TkMacOSXProcessMouseEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) TkMacOSXPreprocessMenu(); TkMacOSXHandleMenuSelect(MenuSelect(where), - theKeys[1] & 4); + EndianS32_BtoN(*(long*)(&theKeys[1])) & 4); Tcl_SetServiceMode(oldMode); return true; /* TODO: may not be on event on queue. */ } @@ -678,30 +681,33 @@ TkMacOSXButtonKeyState() { unsigned int state = 0; KeyMap theKeys; + long modif; if (Button() & !gEatButtonUp) { state |= Button1Mask; } GetKeys(theKeys); + + modif = EndianS32_BtoN(*(long*)(&theKeys[1])); - if (theKeys[1] & 2) { + if (modif & 2) { state |= LockMask; } - if (theKeys[1] & 1) { + if (modif & 1) { state |= ShiftMask; } - if (theKeys[1] & 8) { + if (modif & 8) { state |= ControlMask; } - if (theKeys[1] & 32768) { + if (modif & 32768) { state |= Mod1Mask; /* command key */ } - if (theKeys[1] & 4) { + if (modif & 4) { state |= Mod2Mask; /* option key */ } diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 20b4506..f1f4cb1 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXSubwindows.c,v 1.5 2004/03/21 04:07:12 wolfsuit Exp $ + * RCS: @(#) $Id: tkMacOSXSubwindows.c,v 1.6 2004/11/11 01:24:32 das Exp $ */ #include "tkInt.h" @@ -611,7 +611,7 @@ XMoveWindow( UpdateOffsets(macWin->winPtr, deltaX, deltaY); TkMacOSXWinBounds(macWin->winPtr, &bounds); InvalWindowRect(GetWindowFromPort(destPort),&bounds); - GenerateConfigureNotify(macWin->winPtr, 0); + GenerateConfigureNotify(macWin->winPtr, 0); } } diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index c53f404..47c038a 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXWm.c,v 1.14 2004/10/05 22:04:44 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXWm.c,v 1.15 2004/11/11 01:24:32 das Exp $ */ #include <Carbon/Carbon.h> @@ -86,6 +86,11 @@ static int WmAspectCmd _ANSI_ARGS_((Tk_Window tkwin, static int WmAttributesCmd _ANSI_ARGS_((Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +static void WmAttrGetModifiedStatus(WindowRef macWindow, Tcl_Obj + *result); +static void WmAttrGetTitlePath(WindowRef macWindow, Tcl_Obj + *result); +static void WmAttrGetAlpha(WindowRef macWindow, Tcl_Obj *result); static int WmClientCmd _ANSI_ARGS_((Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); @@ -762,74 +767,215 @@ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - char buf[TCL_INTEGER_SPACE]; int i; + int index; WindowRef macWindow; - + Tcl_Obj *result = NULL; + const char *optionTable[] = { + "-modified", + "-titlepath", + "-alpha", + (char *)NULL + }; + enum optionIdx { + WmAttrModifiedIdx, + WmAttrTitlePathIdx, + WmAttrAlphaIdx, + }; + + /* Must have objc >= 3 at this point. */ if (objc < 3) { -configArgs: Tcl_WrongNumArgs(interp, 1, objv, - "attributes window ?-modified ?bool?? ?-titlepath ?path??"); - return TCL_ERROR; + "attributes window ?-modified ?bool?? ?-titlepath ?path?? ?-alpha ?double??"); + return TCL_ERROR; } + macWindow = GetWindowFromPort(TkMacOSXGetDrawablePort(winPtr->window)); + if (objc == 3) { - FSSpec spec; - sprintf(buf, "%d", (IsWindowModified(macWindow) == true)); - Tcl_AppendResult(interp, "-modified ", buf, (char *) NULL); - if (GetWindowProxyFSSpec(macWindow, &spec) == noErr) { - Tcl_AppendResult(interp, " -titlepath", (char *) NULL); - /* Need to get the path from the spec */ - Tcl_AppendElement(interp, "<read_unimplemented>"); - } else { - Tcl_AppendResult(interp, " -titlepath {}", (char *) NULL); - } + result = Tcl_NewObj(); + Tcl_AppendToObj(result, "-modified ", -1); + WmAttrGetModifiedStatus(macWindow, result); + Tcl_AppendToObj(result, " -titlepath ", -1); + WmAttrGetTitlePath(macWindow, result); + Tcl_AppendToObj(result, " -alpha ", -1); + WmAttrGetAlpha(macWindow, result); + Tcl_SetObjResult(interp, result); return TCL_OK; } + if (objc == 4) { + if (Tcl_GetIndexFromObj(interp, objv[3], optionTable, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + result = Tcl_NewObj(); + switch (index) { + case WmAttrModifiedIdx: + WmAttrGetModifiedStatus(macWindow, result); + break; + case WmAttrTitlePathIdx: + WmAttrGetTitlePath(macWindow, result); + break; + case WmAttrAlphaIdx: + WmAttrGetAlpha(macWindow, result); + break; + } + Tcl_SetObjResult(interp, result); + return TCL_OK; + } + + if ( (objc - 3) % 2 != 0 ) { + Tcl_WrongNumArgs(interp, 3, objv, + "?-modified ?bool?? ?-titlepath ?path?? ?-alpha ?double??"); + return TCL_ERROR; + } for (i = 3; i < objc; i += 2) { - int length; - char *argPtr = Tcl_GetStringFromObj(objv[i], &length); - if ((length < 2) || (*argPtr != '-')) { - goto configArgs; - } - if (strncmp(argPtr, "-modified", length) == 0) { - int boolean; - if (i < objc - 1) { - if (Tcl_GetBooleanFromObj(interp, objv[i+1], &boolean) != TCL_OK) { - return TCL_ERROR; - } - SetWindowModified(macWindow, boolean); - } - } else if (strncmp(argPtr, "-titlepath", length) == 0) { - if (i < objc - 1) { - OSErr err; - FSSpec spec; - FSRef ref; - Boolean isDirectory; - err = FSPathMakeRef(Tcl_GetStringFromObj(objv[i+1], NULL), &ref, &isDirectory); + int boolean; + OSErr err; + FSRef ref; + AliasHandle alias; + Boolean isDirectory; + double dval; + + if (Tcl_GetIndexFromObj(interp, objv[i], optionTable, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch (index) { + case WmAttrModifiedIdx: + if (Tcl_GetBooleanFromObj(interp, objv[i+1], &boolean) != + TCL_OK) { + return TCL_ERROR; + } + result = objv[i+1]; + SetWindowModified(macWindow, boolean); + break; + case WmAttrTitlePathIdx: + err = FSPathMakeRef( + Tcl_GetStringFromObj(objv[i+1], NULL), + &ref, &isDirectory); if (err == noErr) { - err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, - &spec, NULL); - if (err == noErr) { - if (SetWindowProxyFSSpec(macWindow,&spec) != noErr) { - Tcl_AppendResult(interp, "couldn't set window proxy title path", - (char *) NULL); - return TCL_ERROR; - } - } + err = FSNewAlias(NULL, &ref, &alias); } - } - } else { - goto configArgs; - } - if (i == objc - 2) { - /* Want to return last result */ - Tcl_SetObjResult(interp, objv[i+1]); - } + if (err == noErr) { + err = SetWindowProxyAlias(macWindow, alias); + } + if (err != noErr) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("couldn't set window proxy title path", + -1)); + return TCL_ERROR; + } else { + result = objv[i+1]; + } + break; + case WmAttrAlphaIdx: + if (Tcl_GetDoubleFromObj(interp, objv[i+1], &dval) != + TCL_OK) { + return TCL_ERROR; + } + /* + * The user should give (transparent) 0 .. 1.0 (opaque) + */ + if (dval < 0.0) { + dval = 0.0; + } else if (dval > 1.0) { + dval = 1.0; + } + result = Tcl_NewDoubleObj(dval); + SetWindowAlpha(macWindow, dval); + break; + } } + Tcl_SetObjResult(interp, result); return TCL_OK; } + +/* + *---------------------------------------------------------------------- + * WmAttrGetModifiedStatus -- + * + * Helper procedure to retrieve the -modified option for the wm + * attributes command. + * + * Results: + * Nothing. + * + * Side effects: + * Appends the modified status of the given window to the Tcl_Obj + * passed in. + * + *---------------------------------------------------------------------- + */ +static void WmAttrGetModifiedStatus(WindowRef macWindow, Tcl_Obj *result) +{ + Tcl_AppendObjToObj(result, Tcl_NewBooleanObj( + (IsWindowModified(macWindow) == true))); +} + +/* + *---------------------------------------------------------------------- + * WmAttrGetTitlePath -- + * + * Helper procedure to retrieve the -titlepath option for the wm + * attributes command. + * + * Results: + * Nothing. + * + * Side effects: + * Appends the proxy file path of the given window to the Tcl_Obj + * passed in. + * + *---------------------------------------------------------------------- + */ +static void WmAttrGetTitlePath(WindowRef macWindow, Tcl_Obj *result) +{ + FSRef ref; + AliasHandle alias; + Boolean wasChanged; + UInt8 path[2048]; + OSStatus err; + err = GetWindowProxyAlias(macWindow, &alias); + if (err == noErr) { + err = FSResolveAlias(NULL, alias, &ref, &wasChanged); + } + if (err == noErr) { + err = FSRefMakePath(&ref, path, 2048); + } + if (err == noErr) { + Tcl_AppendToObj(result, path, -1); + } else { + Tcl_AppendToObj(result, "{}", -1); + } +} + +/* + *---------------------------------------------------------------------- + * WmAttrGetAlpha -- + * + * Helper procedure to retrieve the -alpha option for the wm + * attributes command. + * + * Results: + * Nothing. + * + * Side effects: + * Appends the alpha value of the given window to the Tcl_Obj + * passed in. + * + *---------------------------------------------------------------------- + */ +static void WmAttrGetAlpha(WindowRef macWindow, Tcl_Obj *result) +{ + float fval; + if (GetWindowAlpha(macWindow, &fval) != noErr) { + fval = 1.0; + } + Tcl_AppendObjToObj(result, Tcl_NewDoubleObj(fval)); +} + /* *---------------------------------------------------------------------- * @@ -1451,16 +1597,16 @@ Tcl_Obj *CONST objv[]; /* Argument objects. */ wmPtr->hints.flags &= ~IconPixmapHint; } else { OSErr err; - FSSpec spec; + AliasHandle alias; FSRef ref; Boolean isDirectory; err = FSPathMakeRef(Tcl_GetStringFromObj(objv[3], NULL), &ref, &isDirectory); if (err == noErr) { - err = FSGetCatalogInfo (&ref, kFSCatInfoNone, NULL, NULL, &spec, NULL); + err = FSNewAlias(NULL, &ref, &alias); if (err == noErr) { WindowRef macWin = GetWindowFromPort(TkMacOSXGetDrawablePort(winPtr->window)); - SetWindowProxyFSSpec(macWin, &spec); + SetWindowProxyAlias(macWin, alias); return TCL_OK; } } |