Annotation of sbbs/src/conio/sdlmain.m, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.