summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXInit.c
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/tkMacOSXInit.c')
-rw-r--r--macosx/tkMacOSXInit.c605
1 files changed, 316 insertions, 289 deletions
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c
index 38471ad..2bf1962 100644
--- a/macosx/tkMacOSXInit.c
+++ b/macosx/tkMacOSXInit.c
@@ -5,95 +5,175 @@
* functions.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
- * Copyright 2001, Apple Computer, Inc.
- * Copyright (c) 2005-2007 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2005-2009 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.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tkMacOSXPrivate.h"
-#include "tclInt.h" /* for Tcl{G,S}etStartupScriptFileName() */
+#include "tclInt.h" /* for Tcl_GetStartupScript() & Tcl_SetStartupScript() */
#include <sys/stat.h>
#include <sys/utsname.h>
-#include <mach-o/dyld.h>
-#include <mach-o/getsect.h>
+#include <dlfcn.h>
+#include <objc/objc-auto.h>
-/*
- * The Init script (common to Windows and Unix platforms) is
- * defined in tkInitScript.h
- */
-#include "tkInitScript.h"
+static char tkLibPath[PATH_MAX + 1] = "";
/*
- * 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.
+ * If the App is in an App package, then we want to add the Scripts directory
+ * to the auto_path.
*/
-#ifndef MAC_OSX_TK_USE_CPS_SPI
-#define MAC_OSX_TK_USE_CPS_SPI 1
+
+static char scriptPath[PATH_MAX + 1] = "";
+
+int tkMacOSXGCEnabled = 0;
+long tkMacOSXMacOSXVersion = 0;
+
+#pragma mark TKApplication(TKInit)
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+#define NSTextInputContextKeyboardSelectionDidChangeNotification @"NSTextInputContextKeyboardSelectionDidChangeNotification"
+static void keyboardChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
+ [[NSNotificationCenter defaultCenter] postNotificationName:NSTextInputContextKeyboardSelectionDidChangeNotification object:nil userInfo:nil];
+}
#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
- * defined by Apple.
- */
+@interface TKApplication(TKKeyboard)
+- (void)keyboardChanged:(NSNotification *)notification;
+@end
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+#define TKApplication_NSApplicationDelegate <NSApplicationDelegate>
+#else
+#define TKApplication_NSApplicationDelegate
+#endif
+@interface TKApplication(TKWindowEvent) TKApplication_NSApplicationDelegate
+- (void)_setupWindowNotifications;
+@end
-typedef struct Map {
- CFStringEncoding numKey;
- const char *strKey;
-} Map;
-
-static Map scriptMap[] = {
- {smRoman, "macRoman"},
- {smJapanese, "macJapan"},
- {smTradChinese, "macChinese"},
- {smKorean, "macKorean"},
- {smArabic, "macArabic"},
- {smHebrew, "macHebrew"},
- {smGreek, "macGreek"},
- {smCyrillic, "macCyrillic"},
- {smRSymbol, "macRSymbol"},
- {smDevanagari, "macDevanagari"},
- {smGurmukhi, "macGurmukhi"},
- {smGujarati, "macGujarati"},
- {smOriya, "macOriya"},
- {smBengali, "macBengali"},
- {smTamil, "macTamil"},
- {smTelugu, "macTelugu"},
- {smKannada, "macKannada"},
- {smMalayalam, "macMalayalam"},
- {smSinhalese, "macSinhalese"},
- {smBurmese, "macBurmese"},
- {smKhmer, "macKhmer"},
- {smThai, "macThailand"},
- {smLaotian, "macLaos"},
- {smGeorgian, "macGeorgia"},
- {smArmenian, "macArmenia"},
- {smSimpChinese, "macSimpChinese"},
- {smTibetan, "macTIbet"},
- {smMongolian, "macMongolia"},
- {smGeez, "macEthiopia"},
- {smEastEurRoman, "macCentEuro"},
- {smVietnamese, "macVietnam"},
- {smExtArabic, "macSindhi"},
- {0, NULL}
-};
-
-Tcl_Encoding TkMacOSXCarbonEncoding = NULL;
+@interface TKApplication(TKScrlbr)
+- (void)_setupScrollBarNotifications;
+@end
+
+@interface TKApplication(TKMenus)
+- (void)_setupMenus;
+@end
+
+@implementation TKApplication
+@end
+
+@implementation TKApplication(TKInit)
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+- (void)_postedNotification:(NSNotification *)notification {
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+}
+#endif
+- (void)_setupApplicationNotifications {
+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+#define observe(n, s) [nc addObserver:self selector:@selector(s) name:(n) object:nil]
+ observe(NSApplicationDidBecomeActiveNotification, applicationActivate:);
+ observe(NSApplicationDidResignActiveNotification, applicationDeactivate:);
+ observe(NSApplicationDidUnhideNotification, applicationShowHide:);
+ observe(NSApplicationDidHideNotification, applicationShowHide:);
+ observe(NSApplicationDidChangeScreenParametersNotification, displayChanged:);
+ observe(NSTextInputContextKeyboardSelectionDidChangeNotification, keyboardChanged:);
+#undef observe
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), NULL, &keyboardChanged, kTISNotifySelectedKeyboardInputSourceChanged, NULL, CFNotificationSuspensionBehaviorCoalesce);
+#endif
+}
+- (void)_setupEventLoop {
+ _running = 1;
+ if (!_appFlags._hasBeenRun) {
+ _appFlags._hasBeenRun = YES;
+ [self finishLaunching];
+ }
+ [self setWindowsNeedUpdate:YES];
+}
+- (void)_setup:(Tcl_Interp *)interp {
+ _eventInterp = interp;
+ _defaultMainMenu = nil;
+ [self _setupMenus];
+ [self setDelegate:self];
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(_postedNotification:) name:nil object:nil];
+#endif
+ [self _setupWindowNotifications];
+ [self _setupScrollBarNotifications];
+ [self _setupApplicationNotifications];
+}
+- (NSString *)tkFrameworkImagePath:(NSString*)image {
+ NSString *path = nil;
+ if (tkLibPath[0] != '\0') {
+ path = [[NSBundle bundleWithPath:[[NSString stringWithUTF8String:
+ tkLibPath] stringByAppendingString:@"/../.."]]
+ pathForImageResource:image];
+ }
+ if (!path) {
+ const char *tk_library = Tcl_GetVar2(_eventInterp, "tk_library", NULL,
+ TCL_GLOBAL_ONLY);
+ if (tk_library) {
+ NSFileManager *fm = [NSFileManager defaultManager];
+ path = [[NSString stringWithUTF8String:tk_library]
+ stringByAppendingFormat:@"/%@", image];
+ if (![fm isReadableFileAtPath:path]) {
+ path = [[NSString stringWithUTF8String:tk_library]
+ stringByAppendingFormat:@"/../macosx/%@", image];
+ if (![fm isReadableFileAtPath:path]) {
+ path = nil;
+ }
+ }
+ }
+ }
+#ifdef TK_MAC_DEBUG
+ if (!path && getenv("TK_SRCROOT")) {
+ path = [[NSString stringWithUTF8String:getenv("TK_SRCROOT")]
+ stringByAppendingFormat:@"/macosx/%@", image];
+ if (![[NSFileManager defaultManager] isReadableFileAtPath:path]) {
+ path = nil;
+ }
+ }
+#endif
+ return path;
+}
+@end
+#pragma mark -
+
/*
- * If the App is in an App package, then we want to add the Scripts
- * directory to the auto_path.
+ *----------------------------------------------------------------------
+ *
+ * DoWindowActivate --
+ *
+ * Idle handler that sets the application icon to the generic Tk icon.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
*/
-static char scriptPath[PATH_MAX + 1] = "";
-
-float tkMacOSXToolboxVersionNumber = 0;
+static void
+SetApplicationIcon(
+ ClientData clientData)
+{
+ NSString *path = [NSApp tkFrameworkImagePath:@"Tk.icns"];
+ if (path) {
+ NSImage *image = [[NSImage alloc] initWithContentsOfFile:path];
+ if (image) {
+ [NSApp setApplicationIconImage:image];
+ [image release];
+ }
+ }
+}
/*
*----------------------------------------------------------------------
@@ -104,8 +184,8 @@ float tkMacOSXToolboxVersionNumber = 0;
* 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.
@@ -117,137 +197,68 @@ int
TkpInit(
Tcl_Interp *interp)
{
- static char tkLibPath[PATH_MAX + 1];
static int initialized = 0;
- Tk_MacOSXSetupTkNotifier();
-
/*
- * Since it is possible for TkInit to be called multiple times
- * and we don't want to do the following initialization multiple times
- * we protect against doing it more than once.
+ * Since it is possible for TkInit to be called multiple times and we
+ * don't want to do the following initialization multiple times we protect
+ * against doing it more than once.
*/
if (!initialized) {
int bundledExecutable = 0;
CFBundleRef bundleRef;
CFURLRef bundleUrl = NULL;
- CFStringEncoding encoding;
- const char *encodingStr = NULL;
- int i;
struct utsname name;
- long osVersion = 0;
+ struct stat st;
initialized = 1;
-
+
/*
* Initialize/check OS version variable for runtime checks.
*/
-
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+# error Mac OS X 10.5 required
+#endif
+
if (!uname(&name)) {
- osVersion = strtol(name.release, NULL, 10) - 4;
+ tkMacOSXMacOSXVersion = (strtod(name.release, NULL) + 96) * 10;
}
- if (osVersion && osVersion < (MAC_OS_X_VERSION_MIN_REQUIRED-1000)/10) {
+ if (tkMacOSXMacOSXVersion &&
+ tkMacOSXMacOSXVersion/10 < MAC_OS_X_VERSION_MIN_REQUIRED/10) {
Tcl_Panic("Mac OS X 10.%d or later required !",
- (MAC_OS_X_VERSION_MIN_REQUIRED-1000)/10);
+ (MAC_OS_X_VERSION_MIN_REQUIRED/10)-100);
}
- TK_IF_MAC_OS_X_API (3, &kHIToolboxVersionNumber,
- tkMacOSXToolboxVersionNumber = kHIToolboxVersionNumber;
- ) TK_ELSE_MAC_OS_X (3,
- if (osVersion > 5) {
- tkMacOSXToolboxVersionNumber = INFINITY;
- } else if (osVersion >= 3) {
- static const float tbVersions[3] = {
- kHIToolboxVersionNumber10_3,
- kHIToolboxVersionNumber10_4,
- kHIToolboxVersionNumber10_5,
- };
-
- tkMacOSXToolboxVersionNumber = tbVersions[osVersion-3];
- }
- ) TK_ENDIF
+#ifdef TK_FRAMEWORK
/*
* 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)
-#endif
- {
- /* Tk.framework not found, check if resource file is open */
- Handle rsrc = Get1NamedResource('CURS', "\phand");
- if (rsrc) {
- ReleaseResource(rsrc);
- } else {
-#ifndef __LP64__
- const struct mach_header *image;
- char *data = NULL;
- uint32_t size;
- int fd = -1;
- char fileName[L_tmpnam + 15];
- uint32_t i, n;
-
- /* 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", (void*)&size);
- if (data) {
- data += _dyld_get_image_vmaddr_slide(i);
- break;
- }
- }
- }
- while (data) {
- FSRef ref;
- SInt16 refNum;
-
- /*
- * 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;
- }
- fcntl(fd, F_SETFD, FD_CLOEXEC);
- 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) {
- unlink(fileName);
- close(fd);
- }
-#endif /* __LP64__ */
- }
+ "com.tcltk.tklibrary", TK_FRAMEWORK_VERSION, 0, PATH_MAX,
+ tkLibPath) != TCL_OK) {
+ TkMacOSXDbgMsg("Tcl_MacOSXOpenVersionedBundleResources failed");
}
+#endif
- /*
- * 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.
- */
+ static NSAutoreleasePool *pool = nil;
+ if (!pool) {
+ pool = [NSAutoreleasePool new];
+ }
+ tkMacOSXGCEnabled = ([NSGarbageCollector defaultCollector] != nil);
+ [[NSUserDefaults standardUserDefaults] registerDefaults:
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:YES],
+ @"_NSCanWrapButtonTitles",
+ [NSNumber numberWithInt:-1],
+ @"NSStringDrawingTypesetterBehavior",
+ nil]];
+ [TKApplication sharedApplication];
+ [NSApp _setup:interp];
/* Check whether we are a bundled executable: */
bundleRef = CFBundleGetMainBundle();
@@ -264,11 +275,14 @@ TkpInit(
* 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);
+ CFURLRef parent =
+ CFURLCreateCopyDeletingLastPathComponent(NULL, url);
+
CFRelease(url);
url = parent;
}
@@ -279,68 +293,44 @@ TkpInit(
CFRelease(bundleUrl);
}
- /* If we are not a bundled executable, notify the window server that
- * we are a foregroundable app. */
if (!bundledExecutable) {
+ /*
+ * 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.
+ */
+
OSStatus err = procNotFound;
ProcessSerialNumber psn = { 0, kCurrentProcess };
- TK_IF_MAC_OS_X_API (3, TransformProcessType,
- err = ChkErr(TransformProcessType, &psn,
- kProcessTransformToForegroundApplication);
- ) TK_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 */
- }
+ err = ChkErr(TransformProcessType, &psn,
+ kProcessTransformToForegroundApplication);
- TkMacOSXInitAppleEvents(interp);
- TkMacOSXInitCarbonEvents(interp);
- TkMacOSXInitMenus(interp);
- TkMacOSXUseAntialiasedText(interp, TRUE);
- TkMacOSXInitCGDrawing(interp, TRUE, 0);
- TkMacOSXInitKeyboard(interp);
-
- encoding = CFStringGetSystemEncoding();
+ /*
+ * Set application icon to generic Tk icon, do it at idle time
+ * instead of now to ensure tk_library is setup.
+ */
- for (i = 0; scriptMap[i].strKey != NULL; i++) {
- if (scriptMap[i].numKey == encoding) {
- encodingStr = scriptMap[i].strKey;
- break;
- }
- }
- if (encodingStr == NULL) {
- encodingStr = "macRoman";
+ Tcl_DoWhenIdle(SetApplicationIcon, NULL);
}
- TkMacOSXCarbonEncoding = Tcl_GetEncoding(NULL, encodingStr);
- if (TkMacOSXCarbonEncoding == NULL) {
- TkMacOSXCarbonEncoding = Tcl_GetEncoding(NULL, NULL);
- }
+ [NSApp _setupEventLoop];
+ TkMacOSXInitAppleEvents(interp);
+ TkMacOSXUseAntialiasedText(interp, -1);
+ TkMacOSXInitCGDrawing(interp, TRUE, 0);
+ [pool drain];
+ pool = [NSAutoreleasePool new];
-#if 0
/*
- * FIXME: Close stdin & stdout for remote debugging otherwise we
- * will fight with gdb for stdin & stdout
+ * FIXME: Close stdin & stdout for remote debugging otherwise we will
+ * fight with gdb for stdin & stdout
*/
if (getenv("XCNOSTDIN") != NULL) {
close(0);
close(1);
}
-#endif
/*
* If we don't have a TTY and stdin is a special character file of
@@ -348,36 +338,36 @@ TkpInit(
* 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 (getenv("TK_CONSOLE") ||
+ (!isatty(0) && (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.
- */
+ /*
+ * 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);
+ if (Tcl_GetStartupScript(NULL) == NULL) {
+ const char *intvar = Tcl_GetVar(interp,
+ "tcl_interactive", TCL_GLOBAL_ONLY);
- if (intvar == NULL) {
- Tcl_SetVar(interp, "tcl_interactive", "1",
- TCL_GLOBAL_ONLY);
- }
- }
- if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) {
- return TCL_ERROR;
+ if (intvar == NULL) {
+ Tcl_SetVar(interp, "tcl_interactive", "1",
+ TCL_GLOBAL_ONLY);
}
}
+ if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
}
}
+ Tk_MacOSXSetupTkNotifier();
+
if (tkLibPath[0] != '\0') {
Tcl_SetVar(interp, "tk_library", tkLibPath, TCL_GLOBAL_ONLY);
}
@@ -387,7 +377,12 @@ TkpInit(
TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
}
- return Tcl_EvalEx(interp, initScript, -1, TCL_EVAL_GLOBAL);
+ Tcl_CreateObjCommand(interp, "::tk::mac::standardAboutPanel",
+ TkMacOSXStandardAboutPanelObjCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "::tk::mac::iconBitmap",
+ TkMacOSXIconBitmapObjCmd, NULL, NULL);
+
+ return TCL_OK;
}
/*
@@ -395,9 +390,9 @@ TkpInit(
*
* 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.
@@ -432,8 +427,8 @@ TkpGetAppName(
*
* 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.
@@ -446,10 +441,11 @@ TkpGetAppName(
void
TkpDisplayWarning(
- CONST char *msg, /* Message to be displayed. */
- CONST char *title) /* Title of warning. */
+ const char *msg, /* Message to be displayed. */
+ const char *title) /* Title of warning. */
{
Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR);
+
if (errChannel) {
Tcl_WriteChars(errChannel, title, -1);
Tcl_WriteChars(errChannel, ": ", 2);
@@ -463,19 +459,17 @@ TkpDisplayWarning(
*
* 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.
*
* Side effects:
- * TclSetStartupScriptFileName() called when AppMain.tcl found.
+ * Tcl_SetStartupScript() called when AppMain.tcl found.
*
*----------------------------------------------------------------------
*/
@@ -488,24 +482,21 @@ TkMacOSXDefaultStartupScript(void)
bundleRef = CFBundleGetMainBundle();
if (bundleRef != NULL) {
- CFURLRef appMainURL;
- appMainURL = CFBundleCopyResourceURL(bundleRef,
- CFSTR("AppMain"),
- CFSTR("tcl"),
- CFSTR("Scripts"));
+ CFURLRef appMainURL = CFBundleCopyResourceURL(bundleRef,
+ CFSTR("AppMain"), CFSTR("tcl"), CFSTR("Scripts"));
if (appMainURL != NULL) {
CFURLRef scriptFldrURL;
char startupScript[PATH_MAX + 1];
if (CFURLGetFileSystemRepresentation (appMainURL, true,
- (unsigned char*) startupScript, PATH_MAX)) {
- TclSetStartupScriptFileName(startupScript);
- scriptFldrURL = CFURLCreateCopyDeletingLastPathComponent(
- NULL, appMainURL);
+ (unsigned char *) startupScript, PATH_MAX)) {
+ Tcl_SetStartupScript(Tcl_NewStringObj(startupScript,-1), NULL);
+ scriptFldrURL = CFURLCreateCopyDeletingLastPathComponent(NULL,
+ appMainURL);
if (scriptFldrURL != NULL) {
- CFURLGetFileSystemRepresentation(scriptFldrURL,
- true, (unsigned char*) scriptPath, PATH_MAX);
+ CFURLGetFileSystemRepresentation(scriptFldrURL, true,
+ (unsigned char *) scriptPath, PATH_MAX);
CFRelease(scriptFldrURL);
}
}
@@ -519,12 +510,9 @@ 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.
*
* Results:
* Address of given symbol or NULL if unavailable.
@@ -540,19 +528,58 @@ TkMacOSXGetNamedSymbol(
const char* module,
const char* symbol)
{
- NSSymbol nsSymbol = NULL;
- if (module && *module) {
- if(NSIsSymbolNameDefinedWithHint(symbol, module)) {
- nsSymbol = NSLookupAndBindSymbolWithHint(symbol, module);
- }
- } else {
- if(NSIsSymbolNameDefined(symbol)) {
- nsSymbol = NSLookupAndBindSymbol(symbol);
- }
+ void *addr = dlsym(RTLD_NEXT, symbol);
+ if (!addr) {
+ (void) dlerror(); /* Clear dlfcn error state */
}
- if (nsSymbol) {
- return NSAddressOfSymbol(nsSymbol);
+ return addr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetStringObjFromCFString --
+ *
+ * Get a string object from a CFString as efficiently as possible.
+ *
+ * Results:
+ * New string object or NULL if conversion failed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE Tcl_Obj*
+TkMacOSXGetStringObjFromCFString(
+ CFStringRef str)
+{
+ Tcl_Obj *obj = NULL;
+ const char *c = CFStringGetCStringPtr(str, kCFStringEncodingUTF8);
+
+ if (c) {
+ obj = Tcl_NewStringObj(c, -1);
} else {
- return NULL;
+ CFRange all = CFRangeMake(0, CFStringGetLength(str));
+ CFIndex len;
+
+ if (CFStringGetBytes(str, all, kCFStringEncodingUTF8, 0, false, NULL,
+ 0, &len) > 0 && len < INT_MAX) {
+ obj = Tcl_NewObj();
+ Tcl_SetObjLength(obj, len);
+ CFStringGetBytes(str, all, kCFStringEncodingUTF8, 0, false,
+ (UInt8*) obj->bytes, len, NULL);
+ }
}
+ return obj;
}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */