00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 #import "SDL.h"
00009 #import "SDLMain.h"
00010 #import <sys/param.h> 
00011 #import <unistd.h>
00012 
00013 
00014 
00015 
00016 @interface NSApplication(SDL_Missing_Methods)
00017 - (void)setAppleMenu:(NSMenu *)menu;
00018 @end
00019 
00020 
00021 #define         SDL_USE_NIB_FILE        0
00022 
00023 
00024 #define         SDL_USE_CPS             1
00025 #ifdef SDL_USE_CPS
00026 
00027 typedef struct CPSProcessSerNum
00028 {
00029         UInt32          lo;
00030         UInt32          hi;
00031 } CPSProcessSerNum;
00032 
00033 extern OSErr    CPSGetCurrentProcess( CPSProcessSerNum *psn);
00034 extern OSErr    CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
00035 extern OSErr    CPSSetFrontProcess( CPSProcessSerNum *psn);
00036 
00037 #endif 
00038 
00039 static int    gArgc;
00040 static char  **gArgv;
00041 static BOOL   gFinderLaunch;
00042 static BOOL   gCalledAppMainline = FALSE;
00043 
00044 static NSString *getApplicationName(void)
00045 {
00046     NSDictionary *dict;
00047     NSString *appName = 0;
00048 
00049     
00050     dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
00051     if (dict)
00052         appName = [dict objectForKey: @"CFBundleName"];
00053     
00054     if (![appName length])
00055         appName = [[NSProcessInfo processInfo] processName];
00056 
00057     return appName;
00058 }
00059 
00060 #if SDL_USE_NIB_FILE
00061 
00062 @interface NSString (ReplaceSubString)
00063 - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString;
00064 @end
00065 #endif
00066 
00067 @interface SDLApplication : NSApplication
00068 @end
00069 
00070 @implementation SDLApplication
00071 
00072 - (void)terminate:(id)sender
00073 {
00074     
00075     SDL_Event event;
00076     event.type = SDL_QUIT;
00077     SDL_PushEvent(&event);
00078 }
00079 @end
00080 
00081 
00082 @implementation SDLMain
00083 
00084 
00085 - (void) setupWorkingDirectory:(BOOL)shouldChdir
00086 {
00087     if (shouldChdir)
00088     {
00089         char parentdir;
00090                 CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
00091                 CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url);
00092                 if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) {
00093                 assert ( chdir (parentdir) == 0 );   
00094                 }
00095                 CFRelease(url);
00096                 CFRelease(url2);
00097         }
00098 
00099 }
00100 
00101 #if SDL_USE_NIB_FILE
00102 
00103 
00104 - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName
00105 {
00106     NSRange aRange;
00107     NSEnumerator *enumerator;
00108     NSMenuItem *menuItem;
00109 
00110     aRange = [[aMenu title] rangeOfString:@"SDL App"];
00111     if (aRange.length != 0)
00112         [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]];
00113 
00114     enumerator = [[aMenu itemArray] objectEnumerator];
00115     while ((menuItem = [enumerator nextObject]))
00116     {
00117         aRange = [[menuItem title] rangeOfString:@"SDL App"];
00118         if (aRange.length != 0)
00119             [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]];
00120         if ([menuItem hasSubmenu])
00121             [self fixMenu:[menuItem submenu] withAppName:appName];
00122     }
00123     [ aMenu sizeToFit ];
00124 }
00125 
00126 #else
00127 
00128 static void setApplicationMenu(void)
00129 {
00130     
00131     NSMenu *appleMenu;
00132     NSMenuItem *menuItem;
00133     NSString *title;
00134     NSString *appName;
00135     
00136     appName = getApplicationName();
00137     appleMenu = [[NSMenu alloc] initWithTitle:@""];
00138     
00139     
00140     title = [@"About " stringByAppendingString:appName];
00141     [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
00142 
00143     [appleMenu addItem:[NSMenuItem separatorItem]];
00144 
00145     title = [@"Hide " stringByAppendingString:appName];
00146     [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
00147 
00148     menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
00149     [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
00150 
00151     [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
00152 
00153     [appleMenu addItem:[NSMenuItem separatorItem]];
00154 
00155     title = [@"Quit " stringByAppendingString:appName];
00156     [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
00157 
00158     
00159     
00160     menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
00161     [menuItem setSubmenu:appleMenu];
00162     [[NSApp mainMenu] addItem:menuItem];
00163 
00164     
00165     [NSApp setAppleMenu:appleMenu];
00166 
00167     
00168     [appleMenu release];
00169     [menuItem release];
00170 }
00171 
00172 
00173 static void setupWindowMenu(void)
00174 {
00175     NSMenu      *windowMenu;
00176     NSMenuItem  *windowMenuItem;
00177     NSMenuItem  *menuItem;
00178 
00179     windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
00180     
00181     
00182     menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
00183     [windowMenu addItem:menuItem];
00184     [menuItem release];
00185     
00186     
00187     windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
00188     [windowMenuItem setSubmenu:windowMenu];
00189     [[NSApp mainMenu] addItem:windowMenuItem];
00190     
00191     
00192     [NSApp setWindowsMenu:windowMenu];
00193 
00194     
00195     [windowMenu release];
00196     [windowMenuItem release];
00197 }
00198 
00199 
00200 static void CustomApplicationMain (int argc, char **argv)
00201 {
00202     NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];
00203     SDLMain                             *sdlMain;
00204 
00205     
00206     [SDLApplication sharedApplication];
00207     
00208 #ifdef SDL_USE_CPS
00209     {
00210         CPSProcessSerNum PSN;
00211         
00212         if (!CPSGetCurrentProcess(&PSN))
00213             if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
00214                 if (!CPSSetFrontProcess(&PSN))
00215                     [SDLApplication sharedApplication];
00216     }
00217 #endif 
00218 
00219     
00220     [NSApp setMainMenu:[[NSMenu alloc] init]];
00221     setApplicationMenu();
00222     setupWindowMenu();
00223 
00224     
00225     sdlMain = [[SDLMain alloc] init];
00226     [NSApp setDelegate:sdlMain];
00227     
00228     
00229     [NSApp run];
00230     
00231     [sdlMain release];
00232     [pool release];
00233 }
00234 
00235 #endif
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
00254 {
00255     const char *temparg;
00256     size_t arglen;
00257     char *arg;
00258     char **newargv;
00259 
00260     if (!gFinderLaunch)  
00261         return FALSE;
00262 
00263     if (gCalledAppMainline)  
00264         return FALSE;
00265 
00266     temparg = [filename UTF8String];
00267     arglen = SDL_strlen(temparg) + 1;
00268     arg = (char *) SDL_malloc(arglen);
00269     if (arg == NULL)
00270         return FALSE;
00271 
00272     newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2));
00273     if (newargv == NULL)
00274     {
00275         SDL_free(arg);
00276         return FALSE;
00277     }
00278     gArgv = newargv;
00279 
00280     SDL_strlcpy(arg, temparg, arglen);
00281     gArgv = arg;
00282     gArgv = NULL;
00283     return TRUE;
00284 }
00285 
00286 
00287 
00288 - (void) applicationDidFinishLaunching: (NSNotification *) note
00289 {
00290     int status;
00291 
00292     
00293     [self setupWorkingDirectory:gFinderLaunch];
00294 
00295 #if SDL_USE_NIB_FILE
00296     
00297     [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()];
00298 #endif
00299 
00300     
00301     gCalledAppMainline = TRUE;
00302     status = SDL_main (gArgc, gArgv);
00303 
00304     
00305     exit(status);
00306 }
00307 @end
00308 
00309 
00310 @implementation NSString (ReplaceSubString)
00311 
00312 - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
00313 {
00314     unsigned int bufferSize;
00315     unsigned int selfLen = [self length];
00316     unsigned int aStringLen = [aString length];
00317     unichar *buffer;
00318     NSRange localRange;
00319     NSString *result;
00320 
00321     bufferSize = selfLen + aStringLen - aRange.length;
00322     buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
00323     
00324     
00325     localRange.location = 0;
00326     localRange.length = aRange.location;
00327     [self getCharacters:buffer range:localRange];
00328     
00329     
00330     localRange.location = 0;
00331     localRange.length = aStringLen;
00332     [aString getCharacters:(buffer+aRange.location) range:localRange];
00333      
00334     
00335     localRange.location = aRange.location + aRange.length;
00336     localRange.length = selfLen - localRange.location;
00337     [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
00338     
00339     
00340     result = [NSString stringWithCharacters:buffer length:bufferSize];
00341     
00342     NSDeallocateMemoryPages(buffer, bufferSize);
00343     
00344     return result;
00345 }
00346 
00347 @end
00348 
00349 
00350 
00351 #ifdef main
00352 #  undef main
00353 #endif
00354 
00355 
00356 
00357 int main (int argc, char **argv)
00358 {
00359     
00360     
00361     if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
00362         gArgv = (char **) SDL_malloc(sizeof (char *) * 2);
00363         gArgv = argv;
00364         gArgv = NULL;
00365         gArgc = 1;
00366         gFinderLaunch = YES;
00367     } else {
00368         int i;
00369         gArgc = argc;
00370         gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1));
00371         for (i = 0; i <= argc; i++)
00372             gArgv[i] = argv[i];
00373         gFinderLaunch = NO;
00374     }
00375 
00376 #if SDL_USE_NIB_FILE
00377     [SDLApplication poseAsClass:[NSApplication class]];
00378     NSApplicationMain (argc, argv);
00379 #else
00380     CustomApplicationMain (argc, argv);
00381 #endif
00382     return 0;
00383 }