diff options
Diffstat (limited to 'macosx/tkMacOSXInit.c')
-rw-r--r-- | macosx/tkMacOSXInit.c | 350 |
1 files changed, 185 insertions, 165 deletions
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index 85d4aa5..524306e 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -1,17 +1,17 @@ -/* +/* * tkMacOSXInit.c -- * - * This file contains Mac OS X -specific interpreter initialization - * functions. + * This file contains Mac OS X -specific interpreter initialization + * functions. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. - * Copyright (c) 2005-2006 Daniel A. Steffen <das@users.sourceforge.net> + * Copyright (c) 2005-2007 Daniel A. Steffen <das@users.sourceforge.net> * * 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.3.2.20 2006/11/24 19:04:07 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXInit.c,v 1.3.2.21 2007/04/29 02:26:49 das Exp $ */ #include "tkMacOSXInt.h" @@ -40,13 +40,13 @@ /* * 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 + * the encoding for that font. The set of numeric constants is fixed and * defined by Apple. */ typedef struct Map { CFStringEncoding numKey; - char *strKey; + const char *strKey; } Map; static Map scriptMap[] = { @@ -82,7 +82,7 @@ static Map scriptMap[] = { {smEastEurRoman, "macCentEuro"}, {smVietnamese, "macVietnam"}, {smExtArabic, "macSindhi"}, - {0, NULL} + {0, NULL} }; Tcl_Encoding TkMacOSXCarbonEncoding = NULL; @@ -93,79 +93,60 @@ Tcl_Encoding TkMacOSXCarbonEncoding = NULL; */ static char scriptPath[PATH_MAX + 1] = ""; + /* *---------------------------------------------------------------------- * * TkpInit -- * - * Performs Mac-specific interpreter initialization related to the - * tk_library variable. + * Performs Mac-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. + * 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. + * Sets "tk_library" Tcl variable, runs "tk.tcl" script. * *---------------------------------------------------------------------- */ int -TkpInit(interp) - Tcl_Interp *interp; +TkpInit( + Tcl_Interp *interp) { static char tkLibPath[PATH_MAX + 1]; - static int tkMacOSXInitialized = false; + static int tkMacOSXInitialized = 0; Tk_MacOSXSetupTkNotifier(); - /* + /* * Since it is possible for TkInit to be called multiple times - * and we don't want to do the initialization multiple times + * and we don't want to do the following initialization multiple times * we protect against doing it more than once. */ - if (tkMacOSXInitialized == false) { + if (!tkMacOSXInitialized) { + int bundledExecutable = 0; + CFBundleRef bundleRef; + CFURLRef bundleUrl = NULL; CFStringEncoding encoding; - char *encodingStr = NULL; + const char *encodingStr = NULL; int i; - tkMacOSXInitialized = true; - - TkMacOSXInitAppleEvents(interp); - TkMacOSXInitCarbonEvents(interp); - TkMacOSXInitMenus(interp); - TkMacOSXUseAntialiasedText(interp, TRUE); - TkMacOSXInitCGDrawing(interp, TRUE, 0); - TkMacOSXInitKeyboard(interp); - - encoding = CFStringGetSystemEncoding(); - - for (i = 0; scriptMap[i].strKey != NULL; i++) { - if (scriptMap[i].numKey == encoding) { - encodingStr = scriptMap[i].strKey; - break; - } - } - if (encodingStr == NULL) { - encodingStr = "macRoman"; - } - - TkMacOSXCarbonEncoding = Tcl_GetEncoding (NULL, encodingStr); - if (TkMacOSXCarbonEncoding == NULL) { - TkMacOSXCarbonEncoding = Tcl_GetEncoding (NULL, NULL); - } + tkMacOSXInitialized = 1; /* - * When Tk is in a framework, force tcl_findLibrary to look in the + * 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? */ #ifdef TK_FRAMEWORK if (Tcl_MacOSXOpenVersionedBundleResources(interp, - "com.tcltk.tklibrary", TK_FRAMEWORK_VERSION, 1, PATH_MAX, tkLibPath) != TCL_OK) + "com.tcltk.tklibrary", TK_FRAMEWORK_VERSION, 1, PATH_MAX, + tkLibPath) != TCL_OK) #endif { /* Tk.framework not found, check if resource file is open */ @@ -181,12 +162,13 @@ TkpInit(interp) char fileName[L_tmpnam + 15]; uint32_t i, n; - /* Get resource data from __tk_rsrc section of tk library file */ + /* Get resource data from __tk_rsrc section of tk dylib file*/ n = _dyld_image_count(); for (i = 0; i < n; i++) { image = _dyld_get_image_header(i); if (image) { - data = getsectdatafromheader(image, SEG_TEXT, "__tk_rsrc", &size); + data = getsectdatafromheader(image, SEG_TEXT, + "__tk_rsrc", (void*)&size); if (data) { data += _dyld_get_image_vmaddr_slide(i); break; @@ -194,26 +176,32 @@ TkpInit(interp) } } while (data) { - OSStatus err; FSRef ref; SInt16 refNum; - /* Write resource data to temporary file and open it */ + /* + * Write resource data to temporary file and open it. + */ + strcpy(fileName, P_tmpdir); if (fileName[strlen(fileName) - 1] != '/') { strcat(fileName, "/"); } strcat(fileName, "tkMacOSX_XXXXXX"); fd = mkstemp(fileName); - if (fd == -1) break; + if (fd == -1) { + break; + } fcntl(fd, F_SETFD, FD_CLOEXEC); - if (write(fd, data, size) == -1) break; - err = FSPathMakeRef((unsigned char*)fileName, &ref, NULL); - if (err != noErr) break; - err = FSOpenResourceFile(&ref, 0, NULL, fsRdPerm, &refNum); -#ifdef TK_MAC_DEBUG - if (err != noErr) fprintf(stderr,"FSOpenResourceFile error %ld\n",err); -#endif + if (write(fd, data, size) == -1) { + break; + } + if(ChkErr(FSPathMakeRef, (unsigned char*)fileName, &ref, + NULL) != noErr) { + break; + } + ChkErr(FSOpenResourceFile, &ref, 0, NULL, fsRdPerm, + &refNum); break; } if (fd != -1) { @@ -225,6 +213,100 @@ TkpInit(interp) } /* + * 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, notify the window server that + * we are now a full GUI application. + */ + + /* Check whether we are a bundled executable: */ + bundleRef = CFBundleGetMainBundle(); + 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, notify the window server that + * we are a foregroundable app. */ + if (!bundledExecutable) { + OSStatus err = procNotFound; + ProcessSerialNumber psn = { 0, kCurrentProcess }; + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + if (1 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030 + && TransformProcessType != NULL +#endif + ) { + err = ChkErr(TransformProcessType, &psn, + kProcessTransformToForegroundApplication); + } +#endif +#if MAC_OSX_TK_USE_CPS_SPI + if (err != noErr) { + /* + * When building or running on 10.2 or when the above fails, + * attempt to use undocumented CPS SPI to notify the window + * server. Load the SPI symbol dynamically, so that we don't + * break if it ever disappears or changes its name. + */ + TkMacOSXInitNamedSymbol(CoreGraphics, OSStatus, + CPSEnableForegroundOperation, ProcessSerialNumberPtr); + if (CPSEnableForegroundOperation) { + ChkErr(CPSEnableForegroundOperation, &psn); + } + } +#endif /* MAC_OSX_TK_USE_CPS_SPI */ + } + + TkMacOSXInitAppleEvents(interp); + TkMacOSXInitCarbonEvents(interp); + TkMacOSXInitMenus(interp); + TkMacOSXUseAntialiasedText(interp, TRUE); + TkMacOSXInitCGDrawing(interp, TRUE, 0); + TkMacOSXInitKeyboard(interp); + + encoding = CFStringGetSystemEncoding(); + + for (i = 0; scriptMap[i].strKey != NULL; i++) { + if (scriptMap[i].numKey == encoding) { + encodingStr = scriptMap[i].strKey; + break; + } + } + if (encodingStr == NULL) { + encodingStr = "macRoman"; + } + + TkMacOSXCarbonEncoding = Tcl_GetEncoding(NULL, encodingStr); + if (TkMacOSXCarbonEncoding == NULL) { + TkMacOSXCarbonEncoding = Tcl_GetEncoding(NULL, NULL); + } + + /* * 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. @@ -232,18 +314,22 @@ TkpInit(interp) 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)); + /* * Only show the console if we don't have a startup script * and tcl_interactive hasn't been set already. */ + if (TclGetStartupScriptFileName() == NULL) { - CONST char *intvar = - Tcl_GetVar(interp, "tcl_interactive", TCL_GLOBAL_ONLY); + const char *intvar = Tcl_GetVar(interp, + "tcl_interactive", TCL_GLOBAL_ONLY); + if (intvar == NULL) { Tcl_SetVar(interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY); @@ -254,74 +340,6 @@ TkpInit(interp) } } } - - /* - * 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, 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, notify the window server - * that we are a foregroundable app. */ - if (!bundledExecutable) { - OSStatus err = procNotFound; - ProcessSerialNumber psn = { 0, kCurrentProcess }; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 - if (TransformProcessType != NULL) { - err = TransformProcessType(&psn, - kProcessTransformToForegroundApplication); - } -#endif -#if MAC_OSX_TK_USE_CPS_SPI - if (err != noErr) { - /* - * When building or running on 10.2 or when the above - * fails, attempt to use undocumented CPS SPI to notify - * the window server. Load the SPI symbol dynamically, so - * that we don't break if it ever disappears or changes - * its name. - */ - TkMacOSXInitNamedSymbol(CoreGraphics, OSErr, - CPSEnableForegroundOperation, ProcessSerialNumberPtr); - if (CPSEnableForegroundOperation) { - CPSEnableForegroundOperation(&psn); - } - } -#endif /* MAC_OSX_TK_USE_CPS_SPI */ - } - } } if (tkLibPath[0] != '\0') { @@ -341,25 +359,25 @@ TkpInit(interp) * * 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. + * 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. + * Returns the application name in the given Tcl_DString. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ void -TkpGetAppName(interp, namePtr) - Tcl_Interp *interp; - Tcl_DString *namePtr; /* A previously initialized Tcl_DString. */ +TkpGetAppName( + Tcl_Interp *interp, + Tcl_DString *namePtr) /* A previously initialized Tcl_DString. */ { - CONST char *p, *name; + const char *p, *name; name = Tcl_GetVar(interp, "argv0", TCL_GLOBAL_ONLY); if ((name == NULL) || (*name == 0)) { @@ -378,22 +396,22 @@ TkpGetAppName(interp, namePtr) * * TkpDisplayWarning -- * - * This routines is called from Tk_Main to display warning - * messages that occur during startup. + * This routines is called from Tk_Main to display warning + * messages that occur during startup. * * Results: - * None. + * None. * * Side effects: - * Generates messages on stdout. + * Generates messages on stdout. * *---------------------------------------------------------------------- */ void -TkpDisplayWarning(msg, title) - CONST char *msg; /* Message to be displayed. */ - CONST char *title; /* Title of warning. */ +TkpDisplayWarning( + CONST char *msg, /* Message to be displayed. */ + CONST char *title) /* Title of warning. */ { Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR); if (errChannel) { @@ -410,18 +428,18 @@ TkpDisplayWarning(msg, title) * 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. + * 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. + * None. * * Side effects: - * TclSetStartupScriptFileName() called when AppMain.tcl found. + * TclSetStartupScriptFileName() called when AppMain.tcl found. * *---------------------------------------------------------------------- */ @@ -435,9 +453,9 @@ TkMacOSXDefaultStartupScript(void) if (bundleRef != NULL) { CFURLRef appMainURL; - appMainURL = CFBundleCopyResourceURL(bundleRef, - CFSTR("AppMain"), - CFSTR("tcl"), + appMainURL = CFBundleCopyResourceURL(bundleRef, + CFSTR("AppMain"), + CFSTR("tcl"), CFSTR("Scripts")); if (appMainURL != NULL) { @@ -450,7 +468,7 @@ TkMacOSXDefaultStartupScript(void) scriptFldrURL = CFURLCreateCopyDeletingLastPathComponent( NULL, appMainURL); if (scriptFldrURL != NULL) { - CFURLGetFileSystemRepresentation(scriptFldrURL, + CFURLGetFileSystemRepresentation(scriptFldrURL, true, (unsigned char*) scriptPath, PATH_MAX); CFRelease(scriptFldrURL); } @@ -466,23 +484,25 @@ TkMacOSXDefaultStartupScript(void) * TkMacOSXGetNamedSymbol -- * * - * Dynamically acquire address of a named symbol from a loaded - * dynamic library, so that we can use API that may not be - * available on all OS versions. - * If module is non-NULL and not the empty string, use twolevel - * namespace lookup. + * Dynamically acquire address of a named symbol from a loaded + * dynamic library, so that we can use API that may not be + * available on all OS versions. + * If module is non-NULL and not the empty string, use twolevel + * namespace lookup. * * Results: - * Address of given symbol or NULL if unavailable. + * Address of given symbol or NULL if unavailable. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ MODULE_SCOPE void* -TkMacOSXGetNamedSymbol(const char* module, const char* symbol) +TkMacOSXGetNamedSymbol( + const char* module, + const char* symbol) { NSSymbol nsSymbol = NULL; if (module && *module) { |