diff --git a/build/Xcode/MacMain.m b/build/Xcode/MacMain.m index 943840698..4ecf882d2 100644 --- a/build/Xcode/MacMain.m +++ b/build/Xcode/MacMain.m @@ -1,282 +1,166 @@ -// Mac OS X SDL Code -// Used to register our program, import SDL, and hand off the rest of the code to the game -// No support for Mac OS Leopard or higher as of yet... +/* 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 + */ -#import -#import // Needed -#import // for MAXPATHLEN +#import +#import +#import /* for MAXPATHLEN */ #import @interface SDLMain : NSObject @end -// To avoid warnings, we declare -// it ourselves here. -@interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; -@end - -// Used to determine whether we use SDLMain.nib or not, in this case -// we want to use our own interface file instead, to be changed later.. -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#if 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; // See if the app had been launched by the finder +static BOOL gFinderLaunch; -static void addArgument(const char *value) -{ - if(!gArgc) - gArgv = (char **)malloc(sizeof(*gArgv)); - else - gArgv = (char **)realloc(gArgv, sizeof(*gArgv) * (gArgc + 1)); - gArgc++; - gArgv[gArgc - 1] = (char *)malloc(sizeof(char) * (strlen(value) + 1)); - strcpy(gArgv[gArgc - 1], value); -} - -static NSString *getApplicationName(void) -{ - NSDictionary *dict; - NSString *appName = NULL; - - // Determine the application name - dict = ( 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; +/* An internal Apple class used to setup Apple menus */ +@interface NSAppleMenuController:NSObject {} +- (void)controlMenu:(NSMenu *)aMenu; @end -#endif @interface SDLApplication : NSApplication @end @implementation SDLApplication -// Invoked from the Quit menu item +/* Invoked from the Quit menu item */ - (void)terminate:(id)sender { - (void)sender; - // Post a SDL_QUIT event + /* 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 + +/* The main class of the application, the application's delegate */ @implementation SDLMain -// Set the working directory to the .app's parent directory +/* Set the working directory to the .app's parent directory */ - (void) setupWorkingDirectory:(BOOL)shouldChdir { + char parentdir[MAXPATHLEN]; + char *c; + + strncpy ( parentdir, gArgv[0], sizeof(parentdir) ); + c = (char*) parentdir; + + while (*c != '\0') /* go to end */ + c++; + + while (*c != '/') /* back up to parent */ + c--; + + *c++ = '\0'; /* cut off last part (binary name) */ + if (shouldChdir) { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) - { - assert ( chdir (parentdir) == 0 ); // chdir to the binary app's parent - } - CFRelease(url); - CFRelease(url2); + assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ + assert ( chdir ("../../../") == 0 ); /* chdir to the .app's parent */ } - } -#if SDL_USE_NIB_FILE - -// Fix menu to contain the real app name instead of "SDL App" -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with: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]; - } - [ aMenu sizeToFit ]; -} - -#else - -static void setApplicationMenu(void) +void setupAppleMenu(void) { /* warning: this code is very odd */ + NSAppleMenuController *appleMenuController; NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; + NSMenuItem *appleMenuItem; - appName = getApplicationName(); + appleMenuController = [[NSAppleMenuController alloc] init]; appleMenu = [[NSMenu alloc] initWithTitle:@""]; + appleMenuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + + [appleMenuItem setSubmenu:appleMenu]; - // Add menu items - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - 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 + /* yes, we do need to add it and then remove it -- + if you don't add it, it doesn't get displayed + if you don't remove it, you have an extra, titleless item in the menubar + when you remove it, it appears to stick around + very, very odd */ + [[NSApp mainMenu] addItem:appleMenuItem]; + [appleMenuController controlMenu:appleMenu]; + [[NSApp mainMenu] removeItem:appleMenuItem]; [appleMenu release]; - [menuItem release]; + [appleMenuItem release]; } -// Create a window menu -static void setupWindowMenu(void) +/* Create a window menu */ +void setupWindowMenu(void) { - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; + NSMenu *windowMenu; + NSMenuItem *windowMenuItem; + NSMenuItem *menuItem; + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - // "Minimize" item + + /* "Minimize" item */ menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [windowMenu addItem:menuItem]; [menuItem release]; - - // Put menu into the menubar + + /* 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 + + /* Tell the application object that this is now the window menu */ [NSApp setWindowsMenu:windowMenu]; - // Finally give up our references to the objects + /* Finally give up our references to the objects */ [windowMenu release]; [windowMenuItem release]; } -// Replacement for NSApplicationMain -static void CustomApplicationMain (int argc, char **argv) +/* Replacement for NSApplicationMain */ +void CustomApplicationMain (int argc, char** argv) { - (void)argc; - (void)argv; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SDLMain *sdlMain; - // Ensure the application object is initialised + /* Ensure the application object is initialised */ [SDLApplication sharedApplication]; - -#if SDL_USE_CPS - { - CPSProcessSerNum PSN; - // Tell the dock about us - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [SDLApplication sharedApplication]; - } -#endif // SDL_USE_CPS - - // Set up the menubar + + /* Set up the menubar */ [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); + setupAppleMenu(); setupWindowMenu(); - - // Create SDLMain and make it the app delegate + + /* Create SDLMain and make it the app delegate */ sdlMain = [[SDLMain alloc] init]; [NSApp setDelegate:sdlMain]; - - // Start the main event loop + + /* Start the main event loop */ [NSApp run]; - + [sdlMain release]; [pool release]; } -#endif +/* Called when the internal event loop has just started running */ +- (void) applicationDidFinishLaunching: (NSNotification *) note +{ + int status; + + /* Set the working directory to the .app's parent directory */ + [self setupWorkingDirectory:gFinderLaunch]; + + /* Hand off to main application code */ + status = SDL_main (gArgc, gArgv); + + /* We're done, thank you for playing */ + exit(status); +} - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { - (void)theApplication; - //addArgument("-iwad"); - //addArgument([filename cString]); // Deprecated in Mac OS Leopard - return YES; -} - -// Called when the internal event loop has just started running -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ - (void)note; - int status; - - // Set the working directory to the .app's parent directory - [self setupWorkingDirectory:gFinderLaunch]; - -#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 - - //setenv("SRB2PATH", [[[NSBundle mainBundle] resourcePath] cString], 1); // Deprecated Mac OS Leopard - - // Hand off to main application code - status = SDL_main (gArgc, gArgv); - - // We're done, thanks for playing - exit(status); + printf("Requested opening file\n"); + return NO; } @end @@ -294,27 +178,27 @@ static void CustomApplicationMain (int argc, char **argv) bufferSize = selfLen + aStringLen - aRange.length; buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - // Get first part into buffer + + /* Get first part into buffer */ localRange.location = 0; localRange.length = aRange.location; [self getCharacters:buffer range:localRange]; - - // Get middle part into buffer + + /* Get middle part into buffer */ localRange.location = 0; localRange.length = aStringLen; [aString getCharacters:(buffer+aRange.location) range:localRange]; - // Get last part into buffer + /* 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 + + /* Build output string */ result = [NSString stringWithCharacters:buffer length:bufferSize]; - + NSDeallocateMemoryPages(buffer, bufferSize); - + return result; } @@ -327,27 +211,28 @@ static void CustomApplicationMain (int argc, char **argv) #endif -// Main entry point to the game - shouldn't be SDL_main +/* Main entry point to executable - should *not* be SDL_main! */ int main (int argc, char **argv) { - // Copy the arguments into a global variable - - // This is passed if we are launched by double-clicking + /* Copy the arguments into a global variable */ + int i; + + /* This is passed if we are launched by double-clicking */ if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { gArgc = 1; - gFinderLaunch = YES; + gFinderLaunch = YES; } else { gArgc = argc; - gFinderLaunch = NO; + gFinderLaunch = NO; } - gArgv = argv; + gArgv = (char**) malloc (sizeof(*gArgv) * (gArgc+1)); + assert (gArgv != NULL); + for (i = 0; i < gArgc; i++) + gArgv[i] = argv[i]; + gArgv[i] = NULL; -#if SDL_USE_NIB_FILE - [SDLApplication poseAsClass:[NSApplication class]]; - NSApplicationMain (argc, argv); -#else CustomApplicationMain (argc, argv); -#endif + return 0; }