|
|
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 Hatari ! 14: ! 15: #include "dialog.h" ! 16: #include "reset.h" ! 17: #include "screenSnapShot.h" ! 18: #include "memorySnapShot.h" ! 19: #include "video.h" ! 20: #include "avi_record.h" ! 21: ! 22: // for Hatari ! 23: ! 24: ! 25: /* For some reaon, Apple removed setAppleMenu from the headers in 10.4, ! 26: but the method still is there and works. To avoid warnings, we declare ! 27: it ourselves here. */ ! 28: @interface NSApplication(SDL_Missing_Methods) ! 29: - (void)setAppleMenu:(NSMenu *)menu; ! 30: @end ! 31: ! 32: /* Use this flag to determine whether we use SDLMain.nib or not */ ! 33: #define SDL_USE_NIB_FILE 1 ! 34: ! 35: /* Use this flag to determine whether we use CPS (docking) or not */ ! 36: #define SDL_USE_CPS 1 ! 37: #ifdef SDL_USE_CPS ! 38: /* Portions of CPS.h */ ! 39: typedef struct CPSProcessSerNum ! 40: { ! 41: UInt32 lo; ! 42: UInt32 hi; ! 43: } CPSProcessSerNum; ! 44: ! 45: extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); ! 46: extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); ! 47: extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); ! 48: ! 49: #endif /* SDL_USE_CPS */ ! 50: ! 51: static int gArgc; ! 52: static char **gArgv; ! 53: static BOOL gFinderLaunch; ! 54: static BOOL gCalledAppMainline = FALSE; ! 55: ! 56: static NSString *getApplicationName(void) ! 57: { ! 58: const NSDictionary *dict; ! 59: NSString *appName = 0; ! 60: ! 61: /* Determine the application name */ ! 62: dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); ! 63: if (dict) ! 64: appName = [dict objectForKey: @"CFBundleName"]; ! 65: ! 66: if (![appName length]) ! 67: appName = [[NSProcessInfo processInfo] processName]; ! 68: ! 69: return appName; ! 70: } ! 71: ! 72: #if SDL_USE_NIB_FILE ! 73: /* A helper category for NSString */ ! 74: @interface NSString (ReplaceSubString) ! 75: - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; ! 76: @end ! 77: #endif ! 78: ! 79: @interface NSApplication (SDLApplication) ! 80: @end ! 81: ! 82: @implementation NSApplication (SDLApplication) ! 83: /* Invoked from the Quit menu item */ ! 84: - (void)terminate:(id)sender ! 85: { ! 86: /* Post a SDL_QUIT event */ ! 87: SDL_Event event; ! 88: event.type = SDL_QUIT; ! 89: SDL_PushEvent(&event); ! 90: } ! 91: @end ! 92: ! 93: /* The main class of the application, the application's delegate */ ! 94: @implementation SDLMain ! 95: ! 96: /* Set the working directory to the .app's parent directory */ ! 97: - (void) setupWorkingDirectory:(BOOL)shouldChdir ! 98: { ! 99: if (shouldChdir) ! 100: { ! 101: char parentdir[MAXPATHLEN]; ! 102: CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); ! 103: CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); ! 104: if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) { ! 105: chdir(parentdir); /* chdir to the binary app's parent */ ! 106: } ! 107: CFRelease(url); ! 108: CFRelease(url2); ! 109: } ! 110: } ! 111: ! 112: #if SDL_USE_NIB_FILE ! 113: ! 114: /* Fix menu to contain the real app name instead of "SDL App" */ ! 115: - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName ! 116: { ! 117: NSRange aRange; ! 118: NSEnumerator *enumerator; ! 119: NSMenuItem *menuItem; ! 120: ! 121: aRange = [[aMenu title] rangeOfString:@"SDL App"]; ! 122: if (aRange.length != 0) ! 123: [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; ! 124: ! 125: enumerator = [[aMenu itemArray] objectEnumerator]; ! 126: while ((menuItem = [enumerator nextObject])) ! 127: { ! 128: aRange = [[menuItem title] rangeOfString:@"SDL App"]; ! 129: if (aRange.length != 0) ! 130: [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; ! 131: if ([menuItem hasSubmenu]) ! 132: [self fixMenu:[menuItem submenu] withAppName:appName]; ! 133: } ! 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: [NSApplication 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: [NSApplication 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: ! 318: // Hatari Stuff ! 319: - (IBAction)prefsMenu:(id)sender ! 320: { ! 321: static int in_propdialog = 0; ! 322: ! 323: if (in_propdialog) ! 324: return; ! 325: ++in_propdialog; ! 326: Dialog_DoProperty(); ! 327: --in_propdialog; ! 328: } ! 329: ! 330: - (IBAction)debugUI:(id)sender ! 331: { ! 332: DebugUI(); ! 333: } ! 334: ! 335: - (IBAction)warmReset:(id)sender ! 336: { ! 337: int b; ! 338: ! 339: b = NSRunAlertPanel ( ! 340: NSLocalizedStringFromTable(@"Warm reset",@"Localizable",@"comment"), ! 341: NSLocalizedStringFromTable(@"Really reset the emulator?",@"Localizable",@"comment"), ! 342: NSLocalizedStringFromTable(@"OK",@"Localizable",@"comment"), ! 343: NSLocalizedStringFromTable(@"Cancel",@"Localizable",@"comment"), nil); ! 344: //printf("b=%i\n",b); ! 345: if (b == 1) ! 346: Reset_Warm(); ! 347: } ! 348: ! 349: - (IBAction)coldReset:(id)sender ! 350: { ! 351: int b; ! 352: ! 353: b = NSRunAlertPanel ( ! 354: NSLocalizedStringFromTable(@"Cold reset!",@"Localizable",@"comment"), ! 355: NSLocalizedStringFromTable(@"Really reset the emulator?",@"Localizable",@"comment") , ! 356: NSLocalizedStringFromTable(@"OK",@"Localizable",@"comment"), ! 357: NSLocalizedStringFromTable(@"Cancel",@"Localizable",@"comment"), nil); ! 358: //printf("b=%i\n",b); ! 359: if (b == 1) ! 360: Reset_Cold(); ! 361: } ! 362: ! 363: - (IBAction)insertDiskA:(id)sender ! 364: { ! 365: NSString *path = nil; ! 366: NSOpenPanel *openPanel = [ NSOpenPanel openPanel ]; ! 367: ! 368: if ( [ openPanel runModalForDirectory:nil ! 369: file:@"SavedGame" types:nil ] ) ! 370: { ! 371: path = [ [ openPanel filenames ] objectAtIndex:0 ]; ! 372: } ! 373: ! 374: if (path != nil) ! 375: { ! 376: // Make a non-const C string out of it ! 377: const char* constSzPath = [path cStringUsingEncoding:NSASCIIStringEncoding]; ! 378: size_t cbPath = strlen(constSzPath) + 1; ! 379: char szPath[cbPath]; ! 380: strncpy(szPath, constSzPath, cbPath); ! 381: ! 382: // Floppy_SetDiskFileName(0, szPath, NULL); ! 383: // Floppy_InsertDiskIntoDrive(0); ! 384: } ! 385: } ! 386: ! 387: - (IBAction)insertDiskB:(id)sender ! 388: { ! 389: NSString *path = nil; ! 390: NSOpenPanel *openPanel = [ NSOpenPanel openPanel ]; ! 391: ! 392: if ( [ openPanel runModalForDirectory:nil ! 393: file:@"SavedGame" types:nil ] ) ! 394: { ! 395: path = [ [ openPanel filenames ] objectAtIndex:0 ]; ! 396: } ! 397: ! 398: if (path != nil) ! 399: { ! 400: // Make a non-const C string out of it ! 401: const char* constSzPath = [path cStringUsingEncoding:NSASCIIStringEncoding]; ! 402: size_t cbPath = strlen(constSzPath) + 1; ! 403: char szPath[cbPath]; ! 404: strncpy(szPath, constSzPath, cbPath); ! 405: ! 406: // Floppy_SetDiskFileName(1, szPath, NULL); ! 407: // Floppy_InsertDiskIntoDrive(1); ! 408: } ! 409: } ! 410: ! 411: /*-----------------------------------------------------------------------*/ ! 412: /* ! 413: Controls the enabled state of the menu items ! 414: */ ! 415: - (BOOL)validateMenuItem:(NSMenuItem*)item ! 416: { ! 417: if (item == beginCaptureAnim) ! 418: { ! 419: // return !Avi_AreWeRecording(); ! 420: } ! 421: if (item == endCaptureAnim) ! 422: { ! 423: // return Avi_AreWeRecording(); ! 424: } ! 425: if (item == beginCaptureSound) ! 426: { ! 427: // return !Sound_AreWeRecording(); ! 428: } ! 429: if (item == endCaptureSound) ! 430: { ! 431: // return Sound_AreWeRecording(); ! 432: } ! 433: ! 434: return YES; ! 435: } ! 436: ! 437: - (IBAction)captureScreen:(id)sender ! 438: { ! 439: GuiOsx_Pause(); ! 440: ScreenSnapShot_SaveScreen(); ! 441: GuiOsx_Resume(); ! 442: } ! 443: ! 444: - (IBAction)captureAnimation:(id)sender ! 445: { ! 446: GuiOsx_Pause(); ! 447: // Avi_StartRecording ( AviRecordFile , AviRecordDefaultCrop , nScreenRefreshRate , AviRecordDefaultVcodec ); ! 448: GuiOsx_Resume(); ! 449: } ! 450: ! 451: - (IBAction)endCaptureAnimation:(id)sender ! 452: { ! 453: GuiOsx_Pause(); ! 454: // Avi_StopRecording(); ! 455: GuiOsx_Resume(); ! 456: } ! 457: ! 458: - (IBAction)captureSound:(id)sender ! 459: { ! 460: GuiOsx_Pause(); ! 461: ! 462: // Get the path from the user settings ! 463: NSString *preferredPath = [[NSString stringWithCString:(ConfigureParams.Sound.szYMCaptureFileName) encoding:NSASCIIStringEncoding] stringByAbbreviatingWithTildeInPath]; ! 464: ! 465: // Determine the directory and filename ! 466: NSString *directoryToOpen; ! 467: NSString *fileToPreselect; ! 468: if ((preferredPath != nil) && ([preferredPath length] > 0)) ! 469: { ! 470: // There is existing path: we will open its directory with its file pre-selected. ! 471: directoryToOpen = [preferredPath stringByDeletingLastPathComponent]; ! 472: fileToPreselect = [preferredPath lastPathComponent]; ! 473: } ! 474: else ! 475: { ! 476: // Currently no path: we will open the user's directory with no file selected. ! 477: directoryToOpen = [@"~" stringByExpandingTildeInPath]; ! 478: fileToPreselect = @"hatari.wav"; ! 479: } ! 480: ! 481: // Create and configure a SavePanel for choosing what file to write ! 482: NSSavePanel *savePanel = [NSSavePanel savePanel]; ! 483: [savePanel setAllowedFileTypes:[NSArray arrayWithObjects:@"ym", @"wav", nil]]; ! 484: [savePanel setExtensionHidden:NO]; ! 485: [savePanel setMessage:@"Please specify an .ym or a .wav file."]; // TODO: Move to localizable resources ! 486: ! 487: // Run the SavePanel, then check if the user clicked OK and selected at least one file ! 488: if (NSFileHandlingPanelOKButton == [savePanel runModalForDirectory:directoryToOpen file:fileToPreselect] ) ! 489: { ! 490: // Get the path to the selected file ! 491: NSString *path = [savePanel filename]; ! 492: ! 493: // Store the path in the user settings ! 494: GuiOsx_ExportPathString(path, ConfigureParams.Sound.szYMCaptureFileName, sizeof(ConfigureParams.Sound.szYMCaptureFileName)); ! 495: ! 496: // Begin capture ! 497: // Sound_BeginRecording(ConfigureParams.Sound.szYMCaptureFileName); ! 498: } ! 499: ! 500: GuiOsx_Resume(); ! 501: } ! 502: ! 503: - (IBAction)endCaptureSound:(id)sender ! 504: { ! 505: GuiOsx_Pause(); ! 506: // Sound_EndRecording(); ! 507: GuiOsx_Resume(); ! 508: } ! 509: ! 510: - (IBAction)saveMemorySnap:(id)sender ! 511: { ! 512: GuiOsx_Pause(); ! 513: ! 514: // Get the path from the user settings ! 515: NSString *preferredPath = [[NSString stringWithCString:(ConfigureParams.Memory.szMemoryCaptureFileName) encoding:NSASCIIStringEncoding] stringByAbbreviatingWithTildeInPath]; ! 516: ! 517: // Determine the directory and filename ! 518: NSString *directoryToOpen; ! 519: NSString *fileToPreselect; ! 520: if ((preferredPath != nil) && ([preferredPath length] > 0)) ! 521: { ! 522: // There is existing path: we will open its directory with its file pre-selected. ! 523: directoryToOpen = [preferredPath stringByDeletingLastPathComponent]; ! 524: fileToPreselect = [preferredPath lastPathComponent]; ! 525: } ! 526: else ! 527: { ! 528: // Currently no path: we will open the user's directory with the default filename. ! 529: directoryToOpen = [@"~" stringByExpandingTildeInPath]; ! 530: fileToPreselect = @"hatari.sav"; ! 531: } ! 532: ! 533: // Create and configure a SavePanel for choosing what file to write ! 534: NSSavePanel *savePanel = [NSSavePanel savePanel]; ! 535: [savePanel setExtensionHidden:NO]; ! 536: ! 537: // Run the SavePanel, then check if the user clicked OK and selected at least one file ! 538: if (NSFileHandlingPanelOKButton == [savePanel runModalForDirectory:directoryToOpen file:fileToPreselect] ) ! 539: { ! 540: // Get the path to the selected file ! 541: NSString *path = [savePanel filename]; ! 542: ! 543: // Store the path in the user settings ! 544: GuiOsx_ExportPathString(path, ConfigureParams.Memory.szMemoryCaptureFileName, sizeof(ConfigureParams.Memory.szMemoryCaptureFileName)); ! 545: ! 546: // Perform the memory snapshot save ! 547: MemorySnapShot_Capture(ConfigureParams.Memory.szMemoryCaptureFileName, TRUE); ! 548: } ! 549: ! 550: GuiOsx_Resume(); ! 551: } ! 552: ! 553: - (IBAction)restoreMemorySnap:(id)sender ! 554: { ! 555: GuiOsx_Pause(); ! 556: ! 557: // Create and configure an OpenPanel ! 558: NSOpenPanel *openPanel = [NSOpenPanel openPanel]; ! 559: ! 560: // Get the path from the user settings ! 561: NSString *oldPath = [NSString stringWithCString:(ConfigureParams.Memory.szMemoryCaptureFileName) encoding:NSASCIIStringEncoding]; ! 562: ! 563: // Determine the directory and filename ! 564: NSString *directoryToOpen; ! 565: NSString *fileToPreselect; ! 566: if ((oldPath != nil) && ([oldPath length] > 0)) ! 567: { ! 568: // There is existing path: we will open its directory with its file pre-selected. ! 569: directoryToOpen = [oldPath stringByDeletingLastPathComponent]; ! 570: fileToPreselect = [oldPath lastPathComponent]; ! 571: } ! 572: else ! 573: { ! 574: // Currently no path: we will open the user's directory with no file selected. ! 575: directoryToOpen = [@"~" stringByExpandingTildeInPath]; ! 576: fileToPreselect = nil; ! 577: } ! 578: ! 579: // Run the OpenPanel, then check if the user clicked OK and selected at least one file ! 580: if ( (NSOKButton == [openPanel runModalForDirectory:directoryToOpen file:fileToPreselect types:nil] ) ! 581: && ([[openPanel filenames] count] > 0) ) ! 582: { ! 583: // Get the path to the selected file ! 584: NSString *path = [[openPanel filenames] objectAtIndex:0]; ! 585: ! 586: // Perform the memory snapshot load ! 587: MemorySnapShot_Restore([path cStringUsingEncoding:NSASCIIStringEncoding], TRUE); ! 588: } ! 589: ! 590: GuiOsx_Resume(); ! 591: } ! 592: ! 593: - (IBAction)doFullScreen:(id)sender ! 594: { ! 595: // A call to Screen_EnterFullScreen() would be required, but this causes a crash when using SDL runtime 1.2.11, probably due to conflicts between Cocoa and SDL. ! 596: // Therefore we simulate the fullscreen key press instead ! 597: ! 598: SDL_KeyboardEvent event; ! 599: event.type = SDL_KEYDOWN; ! 600: event.which = 0; ! 601: event.state = SDL_PRESSED; ! 602: event.keysym.sym = SDLK_F11; ! 603: SDL_PushEvent((SDL_Event*)&event); // Send the F11 key press ! 604: event.type = SDL_KEYUP; ! 605: event.state = SDL_RELEASED; ! 606: SDL_PushEvent((SDL_Event*)&event); // Send the F11 key release ! 607: } ! 608: ! 609: - (IBAction)help:(id)sender ! 610: { ! 611: [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://hatari.berlios.de/docs.html"]]; ! 612: } ! 613: ! 614: ! 615: - (IBAction)openConfig:(id)sender { ! 616: } ! 617: ! 618: - (IBAction)saveConfig:(id)sender { ! 619: } ! 620: ! 621: @end ! 622: ! 623: ! 624: @implementation NSString (ReplaceSubString) ! 625: ! 626: - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString ! 627: { ! 628: unsigned int bufferSize; ! 629: unsigned int selfLen = [self length]; ! 630: unsigned int aStringLen = [aString length]; ! 631: unichar *buffer; ! 632: NSRange localRange; ! 633: NSString *result; ! 634: ! 635: bufferSize = selfLen + aStringLen - aRange.length; ! 636: buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar)); ! 637: ! 638: /* Get first part into buffer */ ! 639: localRange.location = 0; ! 640: localRange.length = aRange.location; ! 641: [self getCharacters:buffer range:localRange]; ! 642: ! 643: /* Get middle part into buffer */ ! 644: localRange.location = 0; ! 645: localRange.length = aStringLen; ! 646: [aString getCharacters:(buffer+aRange.location) range:localRange]; ! 647: ! 648: /* Get last part into buffer */ ! 649: localRange.location = aRange.location + aRange.length; ! 650: localRange.length = selfLen - localRange.location; ! 651: [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; ! 652: ! 653: /* Build output string */ ! 654: result = [NSString stringWithCharacters:buffer length:bufferSize]; ! 655: ! 656: NSDeallocateMemoryPages(buffer, bufferSize); ! 657: ! 658: return result; ! 659: } ! 660: ! 661: @end ! 662: ! 663: ! 664: ! 665: #ifdef main ! 666: # undef main ! 667: #endif ! 668: ! 669: ! 670: /* Main entry point to executable - should *not* be SDL_main! */ ! 671: int main (int argc, char **argv) ! 672: { ! 673: /* Copy the arguments into a global variable */ ! 674: /* This is passed if we are launched by double-clicking */ ! 675: if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { ! 676: gArgv = (char **) SDL_malloc(sizeof (char *) * 2); ! 677: gArgv[0] = argv[0]; ! 678: gArgv[1] = NULL; ! 679: gArgc = 1; ! 680: gFinderLaunch = YES; ! 681: } else { ! 682: int i; ! 683: gArgc = argc; ! 684: gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); ! 685: for (i = 0; i <= argc; i++) ! 686: gArgv[i] = argv[i]; ! 687: gFinderLaunch = NO; ! 688: } ! 689: ! 690: #if SDL_USE_NIB_FILE ! 691: NSApplicationMain (argc, argv); ! 692: #else ! 693: CustomApplicationMain (argc, argv); ! 694: #endif ! 695: return 0; ! 696: } ! 697:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.