home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / xcode / SDLMain.m < prev    next >
Encoding:
Text File  |  2007-06-04  |  11.6 KB  |  393 lines

  1. /*   SDLMain.m - main entry point for our Cocoa-ized SDL app
  2.        Initial Version: Darrell Walisser <dwaliss1@purdue.edu>
  3.        Non-NIB-Code & other changes: Max Horn <max@quendi.de>
  4.  
  5.     Feel free to customize this file to suit your needs
  6. */
  7.  
  8. #import "SDL.h"
  9. #import "SDLMain.h"
  10. #import <sys/param.h> /* for MAXPATHLEN */
  11. #import <unistd.h>
  12.  
  13. /* For some reaon, Apple removed setAppleMenu from the headers in 10.4,
  14.  but the method still is there and works. To avoid warnings, we declare
  15.  it ourselves here. */
  16. @interface NSApplication(SDL_Missing_Methods)
  17. - (void)setAppleMenu:(NSMenu *)menu;
  18. @end
  19.  
  20. /* Use this flag to determine whether we use SDLMain.nib or not */
  21. #define        SDL_USE_NIB_FILE    0
  22.  
  23. /* Use this flag to determine whether we use CPS (docking) or not */
  24. #define        SDL_USE_CPS        1
  25. #ifdef SDL_USE_CPS
  26. /* Portions of CPS.h */
  27. typedef struct CPSProcessSerNum
  28. {
  29.     UInt32        lo;
  30.     UInt32        hi;
  31. } CPSProcessSerNum;
  32.  
  33. extern OSErr    CPSGetCurrentProcess( CPSProcessSerNum *psn);
  34. extern OSErr     CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
  35. extern OSErr    CPSSetFrontProcess( CPSProcessSerNum *psn);
  36.  
  37. #endif /* SDL_USE_CPS */
  38.  
  39. static int    gArgc;
  40. static char  **gArgv;
  41. static BOOL   gFinderLaunch;
  42. static BOOL   gCalledAppMainline = FALSE;
  43.  
  44. static NSString *getApplicationName(void)
  45. {
  46.     NSDictionary *dict;
  47.     NSString *appName = 0;
  48.  
  49.     /* Determine the application name */
  50.     dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
  51.     if (dict)
  52.         appName = [dict objectForKey: @"CFBundleName"];
  53.     
  54.     if (![appName length])
  55.         appName = [[NSProcessInfo processInfo] processName];
  56.  
  57.     return appName;
  58. }
  59.  
  60. #if SDL_USE_NIB_FILE
  61. /* A helper category for NSString */
  62. @interface NSString (ReplaceSubString)
  63. - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString;
  64. @end
  65. #endif
  66.  
  67. @interface SDLApplication : NSApplication
  68. @end
  69.  
  70. @implementation SDLApplication
  71. /* Invoked from the Quit menu item */
  72. - (void)terminate:(id)sender
  73. {
  74.     /* Post a SDL_QUIT event */
  75.     SDL_Event event;
  76.     event.type = SDL_QUIT;
  77.     SDL_PushEvent(&event);
  78. }
  79.  
  80. // ADDED SO IT DOESN'T BEEP BECAUSE WE ENABLE SDL_ENABLEAPPEVENTS
  81. - (void)sendEvent:(NSEvent *)anEvent
  82. {
  83.     if( NSKeyDown == [anEvent type] || NSKeyUp == [anEvent type] ) {
  84.         if( [anEvent modifierFlags] & NSCommandKeyMask ) 
  85.             [super sendEvent: anEvent];
  86.     } else 
  87.         [super sendEvent: anEvent];
  88. }
  89. @end
  90.  
  91. /* The main class of the application, the application's delegate */
  92. @implementation SDLMain
  93.  
  94. /* Set the working directory to the .app's parent directory */
  95. - (void) setupWorkingDirectory:(BOOL)shouldChdir
  96. {
  97.     if (shouldChdir)
  98.     {
  99.         char parentdir[MAXPATHLEN];
  100.         CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
  101.         CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url);
  102.         if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) {
  103.             assert ( chdir (parentdir) == 0 );   /* chdir to the binary app's parent */
  104.         }
  105.         CFRelease(url);
  106.         CFRelease(url2);
  107.     }
  108.  
  109. }
  110.  
  111. #if SDL_USE_NIB_FILE
  112.  
  113. /* Fix menu to contain the real app name instead of "SDL App" */
  114. - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName
  115. {
  116.     NSRange aRange;
  117.     NSEnumerator *enumerator;
  118.     NSMenuItem *menuItem;
  119.  
  120.     aRange = [[aMenu title] rangeOfString:@"SDL App"];
  121.     if (aRange.length != 0)
  122.         [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]];
  123.  
  124.     enumerator = [[aMenu itemArray] objectEnumerator];
  125.     while ((menuItem = [enumerator nextObject]))
  126.     {
  127.         aRange = [[menuItem title] rangeOfString:@"SDL App"];
  128.         if (aRange.length != 0)
  129.             [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]];
  130.         if ([menuItem hasSubmenu])
  131.             [self fixMenu:[menuItem submenu] withAppName:appName];
  132.     }
  133.     [ aMenu sizeToFit ];
  134. }
  135.  
  136. #else
  137.  
  138. static void setApplicationMenu(void)
  139. {
  140.     /* warning: this code is very odd */
  141.     NSMenu *appleMenu;
  142.     NSMenuItem *menuItem;
  143.     NSString *title;
  144.     NSString *appName;
  145.     
  146.     appName = getApplicationName();
  147.     appleMenu = [[NSMenu alloc] initWithTitle:@""];
  148.     
  149.     /* Add menu items */
  150.     title = [@"About " stringByAppendingString:appName];
  151.     [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
  152.  
  153.     [appleMenu addItem:[NSMenuItem separatorItem]];
  154.  
  155.     title = [@"Hide " stringByAppendingString:appName];
  156.     [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
  157.  
  158.     menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
  159.     [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
  160.  
  161.     [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
  162.  
  163.     [appleMenu addItem:[NSMenuItem separatorItem]];
  164.  
  165.     title = [@"Quit " stringByAppendingString:appName];
  166.     [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
  167.  
  168.     
  169.     /* Put menu into the menubar */
  170.     menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
  171.     [menuItem setSubmenu:appleMenu];
  172.     [[NSApp mainMenu] addItem:menuItem];
  173.  
  174.     /* Tell the application object that this is now the application menu */
  175.     [NSApp setAppleMenu:appleMenu];
  176.  
  177.     /* Finally give up our references to the objects */
  178.     [appleMenu release];
  179.     [menuItem release];
  180. }
  181.  
  182. /* Create a window menu */
  183. static void setupWindowMenu(void)
  184. {
  185.     NSMenu      *windowMenu;
  186.     NSMenuItem  *windowMenuItem;
  187.     NSMenuItem  *menuItem;
  188.  
  189.     windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
  190.     
  191.     /* "Minimize" item */
  192.     menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
  193.     [windowMenu addItem:menuItem];
  194.     [menuItem release];
  195.     
  196.     /* Put menu into the menubar */
  197.     windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
  198.     [windowMenuItem setSubmenu:windowMenu];
  199.     [[NSApp mainMenu] addItem:windowMenuItem];
  200.     
  201.     /* Tell the application object that this is now the window menu */
  202.     [NSApp setWindowsMenu:windowMenu];
  203.  
  204.     /* Finally give up our references to the objects */
  205.     [windowMenu release];
  206.     [windowMenuItem release];
  207. }
  208.  
  209. /* Replacement for NSApplicationMain */
  210. static void CustomApplicationMain (int argc, char **argv)
  211. {
  212.     NSAutoreleasePool    *pool = [[NSAutoreleasePool alloc] init];
  213.     SDLMain                *sdlMain;
  214.  
  215.     /* Ensure the application object is initialised */
  216.     [SDLApplication sharedApplication];
  217.     
  218. #ifdef SDL_USE_CPS
  219.     {
  220.         CPSProcessSerNum PSN;
  221.         /* Tell the dock about us */
  222.         if (!CPSGetCurrentProcess(&PSN))
  223.             if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
  224.                 if (!CPSSetFrontProcess(&PSN))
  225.                     [SDLApplication sharedApplication];
  226.     }
  227. #endif /* SDL_USE_CPS */
  228.  
  229.     /* Set up the menubar */
  230.     [NSApp setMainMenu:[[NSMenu alloc] init]];
  231.     setApplicationMenu();
  232.     setupWindowMenu();
  233.  
  234.     /* Create SDLMain and make it the app delegate */
  235.     sdlMain = [[SDLMain alloc] init];
  236.     [NSApp setDelegate:sdlMain];
  237.     
  238.     /* Start the main event loop */
  239.     [NSApp run];
  240.     
  241.     [sdlMain release];
  242.     [pool release];
  243. }
  244.  
  245. #endif
  246.  
  247.  
  248. /*
  249.  * Catch document open requests...this lets us notice files when the app
  250.  *  was launched by double-clicking a document, or when a document was
  251.  *  dragged/dropped on the app's icon. You need to have a
  252.  *  CFBundleDocumentsType section in your Info.plist to get this message,
  253.  *  apparently.
  254.  *
  255.  * Files are added to gArgv, so to the app, they'll look like command line
  256.  *  arguments. Previously, apps launched from the finder had nothing but
  257.  *  an argv[0].
  258.  *
  259.  * This message may be received multiple times to open several docs on launch.
  260.  *
  261.  * This message is ignored once the app's mainline has been called.
  262.  */
  263. - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
  264. {
  265.     const char *temparg;
  266.     size_t arglen;
  267.     char *arg;
  268.     char **newargv;
  269.  
  270.     if (!gFinderLaunch)  /* MacOS is passing command line args. */
  271.         return FALSE;
  272.  
  273.     if (gCalledAppMainline)  /* app has started, ignore this document. */
  274.         return FALSE;
  275.  
  276.     temparg = [filename UTF8String];
  277.     arglen = SDL_strlen(temparg) + 1;
  278.     arg = (char *) SDL_malloc(arglen);
  279.     if (arg == NULL)
  280.         return FALSE;
  281.  
  282.     newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2));
  283.     if (newargv == NULL)
  284.     {
  285.         SDL_free(arg);
  286.         return FALSE;
  287.     }
  288.     gArgv = newargv;
  289.  
  290.     SDL_strlcpy(arg, temparg, arglen);
  291.     gArgv[gArgc++] = arg;
  292.     gArgv[gArgc] = NULL;
  293.     return TRUE;
  294. }
  295.  
  296.  
  297. /* Called when the internal event loop has just started running */
  298. - (void) applicationDidFinishLaunching: (NSNotification *) note
  299. {
  300.     int status;
  301.  
  302.     /* Set the working directory to the .app's parent directory */
  303.     [self setupWorkingDirectory:gFinderLaunch];
  304.  
  305. #if SDL_USE_NIB_FILE
  306.     /* Set the main menu to contain the real app name instead of "SDL App" */
  307.     [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()];
  308. #endif
  309.  
  310.     /* Hand off to main application code */
  311.     gCalledAppMainline = TRUE;
  312.     status = SDL_main (gArgc, gArgv);
  313.  
  314.     /* We're done, thank you for playing */
  315.     exit(status);
  316. }
  317. @end
  318.  
  319.  
  320. @implementation NSString (ReplaceSubString)
  321.  
  322. - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
  323. {
  324.     unsigned int bufferSize;
  325.     unsigned int selfLen = [self length];
  326.     unsigned int aStringLen = [aString length];
  327.     unichar *buffer;
  328.     NSRange localRange;
  329.     NSString *result;
  330.  
  331.     bufferSize = selfLen + aStringLen - aRange.length;
  332.     buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
  333.     
  334.     /* Get first part into buffer */
  335.     localRange.location = 0;
  336.     localRange.length = aRange.location;
  337.     [self getCharacters:buffer range:localRange];
  338.     
  339.     /* Get middle part into buffer */
  340.     localRange.location = 0;
  341.     localRange.length = aStringLen;
  342.     [aString getCharacters:(buffer+aRange.location) range:localRange];
  343.      
  344.     /* Get last part into buffer */
  345.     localRange.location = aRange.location + aRange.length;
  346.     localRange.length = selfLen - localRange.location;
  347.     [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
  348.     
  349.     /* Build output string */
  350.     result = [NSString stringWithCharacters:buffer length:bufferSize];
  351.     
  352.     NSDeallocateMemoryPages(buffer, bufferSize);
  353.     
  354.     return result;
  355. }
  356.  
  357. @end
  358.  
  359.  
  360.  
  361. #ifdef main
  362. #  undef main
  363. #endif
  364.  
  365.  
  366. /* Main entry point to executable - should *not* be SDL_main! */
  367. int main (int argc, char **argv)
  368. {
  369.     /* Copy the arguments into a global variable */
  370.     /* This is passed if we are launched by double-clicking */
  371.     if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
  372.         gArgv = (char **) SDL_malloc(sizeof (char *) * 2);
  373.         gArgv[0] = argv[0];
  374.         gArgv[1] = NULL;
  375.         gArgc = 1;
  376.         gFinderLaunch = YES;
  377.     } else {
  378.         int i;
  379.         gArgc = argc;
  380.         gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1));
  381.         for (i = 0; i <= argc; i++)
  382.             gArgv[i] = argv[i];
  383.         gFinderLaunch = NO;
  384.     }
  385.  
  386. #if SDL_USE_NIB_FILE
  387.     [SDLApplication poseAsClass:[NSApplication class]];
  388.     NSApplicationMain (argc, argv);
  389. #else
  390.     CustomApplicationMain (argc, argv);
  391. #endif
  392.     return 0;
  393. }