diff --git a/sc2/build/unix/build.config b/sc2/build/unix/build.config index 338d4bf21..1b8fd702d 100644 --- a/sc2/build/unix/build.config +++ b/sc2/build/unix/build.config @@ -593,7 +593,7 @@ uqm_install_osx() { $PREPROC_C -D__MACOSX__ -include $HEADER - | \ awk '(/'$HEADER_FILE'/ && $2 == 1) { print $3; exit }' | \ $SED 's/.Headers.*$/"/'` - cp -r "$FRAMEWORK" "$INSTROOT/Frameworks" + cp -a "$FRAMEWORK" "$INSTROOT/Frameworks" done # Install game content (it should probably make a zipfile) diff --git a/sc2/build/unix/config_proginfo_build b/sc2/build/unix/config_proginfo_build index 80984e60f..e265527ed 100644 --- a/sc2/build/unix/config_proginfo_build +++ b/sc2/build/unix/config_proginfo_build @@ -326,7 +326,7 @@ PROG_windres_VERSION='windres --version' ### Rez resource compiler (for MacOS X) ### PROG_Rez_NAME="Rez resource compiler (Apple Developer Tools)" -PROG_Rez_FILE="/Developer/Tools/Rez" +PROG_Rez_FILE="Rez" PROG_Rez_ACTION="" PROG_Rez_VERSION='' diff --git a/sc2/src/darwin/SDLMain.h b/sc2/src/darwin/SDLMain.h index 206cd7062..c56d90cbe 100644 --- a/sc2/src/darwin/SDLMain.h +++ b/sc2/src/darwin/SDLMain.h @@ -1,19 +1,16 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn - Feel free to customize this file to suit your needs + Feel free to customize this file to suit your needs */ -#import +#ifndef _SDLMain_h_ +#define _SDLMain_h_ -/* An internal Apple class used to setup Apple menus */ -@interface NSAppleMenuController:NSObject {} -- (void)controlMenu:(NSMenu *)aMenu; -@end +#import @interface SDLMain : NSObject @end -@interface SDLApplication : NSApplication -@end +#endif /* _SDLMain_h_ */ diff --git a/sc2/src/darwin/SDLMain.m b/sc2/src/darwin/SDLMain.m index 5a15162c4..2434f81aa 100644 --- a/sc2/src/darwin/SDLMain.m +++ b/sc2/src/darwin/SDLMain.m @@ -1,285 +1,381 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn - Feel free to customize this file to suit your needs - - Modified for use with The Ur-Quan Masters by Nicolas Simonds - + Feel free to customize this file to suit your needs */ -#import "port.h" -#import SDL_INCLUDE(SDL.h) -#import "SDLMain.h" -#import - /* for PATH_MAX */ -#import - /* for strrchr() */ -#import +#include "SDL.h" +#include "SDLMain.h" +#include /* for MAXPATHLEN */ +#include -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; +/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, + but the method still is there and works. To avoid warnings, we declare + it ourselves here. */ +@interface NSApplication(SDL_Missing_Methods) +- (void)setAppleMenu:(NSMenu *)menu; +@end -@implementation SDLApplication +/* Use this flag to determine whether we use SDLMain.nib or not */ +#define SDL_USE_NIB_FILE 0 + +/* Use this flag to determine whether we use CPS (docking) or not */ +#define SDL_USE_CPS 1 +#ifdef SDL_USE_CPS +/* Portions of CPS.h */ +typedef struct CPSProcessSerNum +{ + UInt32 lo; + UInt32 hi; +} CPSProcessSerNum; + +extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); +extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); +extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); + +#endif /* SDL_USE_CPS */ + +static int gArgc; +static char **gArgv; +static BOOL gFinderLaunch; +static BOOL gCalledAppMainline = FALSE; + +static NSString *getApplicationName(void) +{ + const NSDictionary *dict; + NSString *appName = 0; + + /* Determine the application name */ + dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); + if (dict) + appName = [dict objectForKey: @"CFBundleName"]; + + if (![appName length]) + appName = [[NSProcessInfo processInfo] processName]; + + return appName; +} + +#if SDL_USE_NIB_FILE +/* A helper category for NSString */ +@interface NSString (ReplaceSubString) +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; +@end +#endif + +@interface NSApplication (SDLApplication) +@end + +@implementation NSApplication (SDLApplication) /* Invoked from the Quit menu item */ - (void)terminate:(id)sender { - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent (&event); - (void) sender; /* Get rid of unused variable warning */ -} - -/* override NSApplication:sendEvent, to keep Cocoa from beeping on - non-command keystrokes */ -- (void)sendEvent:(NSEvent *)anEvent { - if (NSKeyDown == [anEvent type] || NSKeyUp == [anEvent type]) { - if ([anEvent modifierFlags] & NSCommandKeyMask) - [super sendEvent: anEvent]; - } else - [super sendEvent: anEvent]; + /* Post a SDL_QUIT event */ + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); } @end /* The main class of the application, the application's delegate */ @implementation SDLMain -static char * -basename (char *path) -{ - char *base; - - base = strrchr (path, '/'); - if (base == NULL) - return path; - - return (base + 1); -} - /* Set the working directory to the .app's parent directory */ - (void) setupWorkingDirectory:(BOOL)shouldChdir { - char origindir[PATH_MAX]; - char *c; - - if (!shouldChdir) - return; - - strncpy (origindir, gArgv[0], sizeof origindir); - origindir[sizeof origindir - 1] = '\0'; - - c = basename (origindir); - if (c == origindir) - strcpy (origindir, "."); - else - *c = '\0'; - - /* chdir to the binary app's point of origin */ - if (chdir (origindir) != 0) - abort (); - /* then chdir to the .app's parent */ - if ( chdir ("../Resources/") != 0 ) - abort(); + if (shouldChdir) + { + char parentdir[MAXPATHLEN]; + CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); + if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) { + chdir(parentdir); /* chdir to the binary app's parent */ + } + CFRelease(url); + CFRelease(url2); + } } -void -setupAppleMenu (void) +#if SDL_USE_NIB_FILE + +/* Fix menu to contain the real app name instead of "SDL App" */ +- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName { - NSMenu *appleMenu; + NSRange aRange; + NSEnumerator *enumerator; + NSMenuItem *menuItem; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; + aRange = [[aMenu title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - appName = [NSString stringWithUTF8String:basename (gArgv[0])]; - appleMenu = [[NSMenu alloc] initWithTitle:appName]; + enumerator = [[aMenu itemArray] objectEnumerator]; + while ((menuItem = [enumerator nextObject])) + { + aRange = [[menuItem title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; + if ([menuItem hasSubmenu]) + [self fixMenu:[menuItem submenu] withAppName:appName]; + } +} - /* Add menu items */ - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) - keyEquivalent:@"h"]; +#else - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" - action:@selector(hideOtherApplications:) - keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; +static void setApplicationMenu(void) +{ + /* warning: this code is very odd */ + NSMenu *appleMenu; + NSMenuItem *menuItem; + NSString *title; + NSString *appName; + + appName = getApplicationName(); + appleMenu = [[NSMenu alloc] initWithTitle:@""]; + + /* Add menu items */ + title = [@"About " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - [appleMenu addItemWithTitle:@"Show All" - action:@selector(unhideAllApplications:) - keyEquivalent:@""]; + [appleMenu addItem:[NSMenuItem separatorItem]]; - [appleMenu addItem:[NSMenuItem separatorItem]]; + title = [@"Hide " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) - keyEquivalent:@"q"]; + menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; + [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil - keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; + [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; + [appleMenu addItem:[NSMenuItem separatorItem]]; - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; + title = [@"Quit " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; + + + /* Put menu into the menubar */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:appleMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Tell the application object that this is now the application menu */ + [NSApp setAppleMenu:appleMenu]; + + /* Finally give up our references to the objects */ + [appleMenu release]; + [menuItem release]; } /* Create a window menu */ -void -setupWindowMenu (void) +static void setupWindowMenu(void) { - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; + NSMenu *windowMenu; + NSMenuItem *windowMenuItem; + NSMenuItem *menuItem; - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; + + /* "Minimize" item */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; + [windowMenu addItem:menuItem]; + [menuItem release]; + + /* Put menu into the menubar */ + windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; + [windowMenuItem setSubmenu:windowMenu]; + [[NSApp mainMenu] addItem:windowMenuItem]; + + /* Tell the application object that this is now the window menu */ + [NSApp setWindowsMenu:windowMenu]; - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" - action:@selector(performMiniaturize:) - keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" - action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; + /* Finally give up our references to the objects */ + [windowMenu release]; + [windowMenuItem release]; } /* Replacement for NSApplicationMain */ -void -CustomApplicationMain (int argc, char **argv) +static void CustomApplicationMain (int argc, char **argv) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SDLMain *sdlMain; - /* Ensure the application object is initialised */ - [SDLApplication sharedApplication]; + /* Ensure the application object is initialised */ + [NSApplication sharedApplication]; + +#ifdef SDL_USE_CPS + { + CPSProcessSerNum PSN; + /* Tell the dock about us */ + if (!CPSGetCurrentProcess(&PSN)) + if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) + if (!CPSSetFrontProcess(&PSN)) + [NSApplication sharedApplication]; + } +#endif /* SDL_USE_CPS */ - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setupAppleMenu (); - setupWindowMenu (); + /* Set up the menubar */ + [NSApp setMainMenu:[[NSMenu alloc] init]]; + setApplicationMenu(); + setupWindowMenu(); - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; - - (void) argc; /* Get rid of unused variable warning */ - (void) argv; /* Get rid of unused variable warning */ + /* Create SDLMain and make it the app delegate */ + sdlMain = [[SDLMain alloc] init]; + [NSApp setDelegate:sdlMain]; + + /* Start the main event loop */ + [NSApp run]; + + [sdlMain release]; + [pool release]; } +#endif + + +/* + * Catch document open requests...this lets us notice files when the app + * was launched by double-clicking a document, or when a document was + * dragged/dropped on the app's icon. You need to have a + * CFBundleDocumentsType section in your Info.plist to get this message, + * apparently. + * + * Files are added to gArgv, so to the app, they'll look like command line + * arguments. Previously, apps launched from the finder had nothing but + * an argv[0]. + * + * This message may be received multiple times to open several docs on launch. + * + * This message is ignored once the app's mainline has been called. + */ +- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename +{ + const char *temparg; + size_t arglen; + char *arg; + char **newargv; + + if (!gFinderLaunch) /* MacOS is passing command line args. */ + return FALSE; + + if (gCalledAppMainline) /* app has started, ignore this document. */ + return FALSE; + + temparg = [filename UTF8String]; + arglen = SDL_strlen(temparg) + 1; + arg = (char *) SDL_malloc(arglen); + if (arg == NULL) + return FALSE; + + newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); + if (newargv == NULL) + { + SDL_free(arg); + return FALSE; + } + gArgv = newargv; + + SDL_strlcpy(arg, temparg, arglen); + gArgv[gArgc++] = arg; + gArgv[gArgc] = NULL; + return TRUE; +} + + /* Called when the internal event loop has just started running */ - (void) applicationDidFinishLaunching: (NSNotification *) note { - int status; + int status; - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; + /* Set the working directory to the .app's parent directory */ + [self setupWorkingDirectory:gFinderLaunch]; - /* allow Cocoa to hear keystrokes like Command-Q, etc. */ - setenv ("SDL_ENABLEAPPEVENTS", "1", 1); +#if SDL_USE_NIB_FILE + /* Set the main menu to contain the real app name instead of "SDL App" */ + [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; +#endif - /* Hand off to main application code */ - status = SDL_main (gArgc, gArgv); + /* Hand off to main application code */ + gCalledAppMainline = TRUE; + status = SDL_main (gArgc, gArgv); - /* We're done, thank you for playing */ - exit (status); - - (void) note; /* Get rid of unused variable warning */ + /* We're done, thank you for playing */ + exit(status); } @end + @implementation NSString (ReplaceSubString) -- (NSString *) stringByReplacingRange:(NSRange)aRange with:(NSString *)aString +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString { - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; + unsigned int bufferSize; + unsigned int selfLen = [self length]; + unsigned int aStringLen = [aString length]; + unichar *buffer; + NSRange localRange; + NSString *result; - bufferSize = selfLen + aStringLen - aRange.length; - buffer = NSAllocateMemoryPages (bufferSize * sizeof (unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer + aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer + aRange.location+aStringLen) - range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages (buffer, bufferSize); - - return result; + bufferSize = selfLen + aStringLen - aRange.length; + buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar)); + + /* Get first part into buffer */ + localRange.location = 0; + localRange.length = aRange.location; + [self getCharacters:buffer range:localRange]; + + /* Get middle part into buffer */ + localRange.location = 0; + localRange.length = aStringLen; + [aString getCharacters:(buffer+aRange.location) range:localRange]; + + /* Get last part into buffer */ + localRange.location = aRange.location + aRange.length; + localRange.length = selfLen - localRange.location; + [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; + + /* Build output string */ + result = [NSString stringWithCharacters:buffer length:bufferSize]; + + NSDeallocateMemoryPages(buffer, bufferSize); + + return result; } @end + + #ifdef main # undef main #endif + /* Main entry point to executable - should *not* be SDL_main! */ -int -main (int argc, char **argv) +int main (int argc, char **argv) { - /* Copy the arguments into a global variable */ - int i; + /* Copy the arguments into a global variable */ + /* This is passed if we are launched by double-clicking */ + if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { + gArgv = (char **) SDL_malloc(sizeof (char *) * 2); + gArgv[0] = argv[0]; + gArgv[1] = NULL; + gArgc = 1; + gFinderLaunch = YES; + } else { + int i; + gArgc = argc; + gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); + for (i = 0; i <= argc; i++) + gArgv[i] = argv[i]; + gFinderLaunch = NO; + } - /* If we are launched by double-clicking, argv[1] is "-psn_ */ - if ( argc >= 2 && strncmp (argv[1], "-psn_", 5) == 0 ) { - gArgc = 1; - gFinderLaunch = YES; - } else { - gArgc = argc; - gFinderLaunch = NO; - } - gArgv = (char **) malloc (sizeof *gArgv * (gArgc + 1)); - if (gArgv == NULL) - abort (); - for (i = 0; i < gArgc; i++) - gArgv[i] = argv[i]; - gArgv[i] = NULL; - - CustomApplicationMain (argc, argv); - free (gArgv); - return 0; +#if SDL_USE_NIB_FILE + NSApplicationMain (argc, argv); +#else + CustomApplicationMain (argc, argv); +#endif + return 0; } -