--- hatari/src/gui-osx/SDLMain.m 2019/04/01 07:13:37 1.1.1.2 +++ hatari/src/gui-osx/SDLMain.m 2019/04/09 08:55:22 1.1.1.12 @@ -1,451 +1,499 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app +/* + SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn - - Feb-Mar 2006, Sˇbastien Molines - Added prefs & create floppy - June 2006, Sˇbastien Molines - Added capture and memory snapshot + Modifications for Hatari by Miguel Saro and Jerome Vernet Feel free to customize this file to suit your needs */ +/* Use this flag to determine whether we use SDLMain.nib or not */ +#define SDL_USE_NIB_FILE 1 + +/* Use this flag to determine whether we use CPS (docking) or not */ +#define SDL_USE_CPS 1 + #import "SDL.h" #import "SDLMain.h" -#import "SDL_events.h" -#import "Shared.h" -#import /* for MAXPATHLEN */ +#import // for MAXPATHLEN #import -#include "dialog.h" -#include "floppy.h" -#include "reset.h" -#include "screenSnapShot.h" -#include "memorySnapShot.h" -#include "sound.h" - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; +// for Hatari +#import "dialog.h" +#import "floppy.h" +#import "reset.h" +#import "screenSnapShot.h" +#import "memorySnapShot.h" +#import "sound.h" +#import "screen.h" +#import "PrefsController.h" +#import "Shared.h" +#import "video.h" +#import "avi_record.h" +#import "debugui.h" +#import "clocks_timings.h" +#import "change.h" -@interface SDLApplication : NSApplication -@end -@implementation SDLApplication -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); +#ifdef 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 = NO ; +static BOOL gCalledAppMainline = NO ; + + +// The main class of the application, the application's delegate +// +@implementation HatariAppDelegate + +char szPath[FILENAME_MAX] ; // for general use + +// Set the working directory to the .app's parent directory +- (void) setupWorkingDirectory:(BOOL)shouldChdir +{ + if (shouldChdir) + chdir([[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] cStringUsingEncoding:NSASCIIStringEncoding]) ; } -@end -/* The main class of the application, the application's delegate */ -@implementation SDLMain +/* + * Catch document open requests...this lets us notice files when the app + * was launched by double-clicking a document, or when a document was + * dragged/dropped on the app's icon. You need to have a + * CFBundleDocumentsType section in your Info.plist to get this message, + * apparently. + * + * Files are added to gArgv, so to the app, they'll look like command line + * arguments. Previously, apps launched from the finder had nothing but + * an argv[0]. + * + * This message may be received multiple times to open several docs on launch. + * + * This message is ignored once the app's mainline has been called. + */ +- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename +{ + const char *temparg; + size_t arglen; + char *arg; + char **newargv; + + if (!gFinderLaunch) // MacOS is passing command line args. + return FALSE; + + if (gCalledAppMainline) // app has started, ignore this document. + return FALSE; + + temparg = [filename UTF8String] ; + arglen = SDL_strlen(temparg) + 1 ; + arg = (char *) SDL_malloc(arglen) ; + if (arg == NULL) + return FALSE; + + newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)) ; + if (newargv == NULL) + { + SDL_free(arg); + return FALSE; + } + gArgv = newargv ; + + SDL_strlcpy(arg, temparg, arglen) ; + gArgv[gArgc++] = arg ; + gArgv[gArgc] = NULL ; + return TRUE; +} + + +// 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]; + + //setenv ("SDL_ENABLEAPPEVENTS", "1", 1) ; + + // Hand off to main application code + + gCalledAppMainline = TRUE; + status = SDL_main (gArgc, gArgv) ; + + // We're done, thank you for playing + exit(status) ; +} +// Hatari Stuff - (IBAction)prefsMenu:(id)sender { static int in_propdialog = 0; - + if (in_propdialog) - return; - ++in_propdialog; - Dialog_DoProperty(); + return ; + ++in_propdialog ; + Dialog_DoProperty() ; --in_propdialog; } +/*- (IBAction) openPreferences:(id)sender +{ + [[PrefsController prefs] loadPrefs:sender]; +} // */ + + +- (IBAction)debugUI:(id)sender +{ + DebugUI(REASON_USER); +} + - (IBAction)warmReset:(id)sender { - int b; - - b = NSRunAlertPanel (@"Warm reset!", - @"Really reset the emulator? All current work will be lost. Click Cancel to continue without reset.", - @"OK", @"Cancel", nil); - //printf("b=%i\n",b); - if (b == 1) + if ([NSApp myAlerte:NSInformationalAlertStyle Txt:localize(@"Warm reset!") firstB:localize(@"OK") alternateB:localize(@"Cancel") + otherB:nil informativeTxt:localize(@"Really reset the emulator?")] == NSAlertDefaultReturn) Reset_Warm(); -} +} - (IBAction)coldReset:(id)sender { - int b; - - b = NSRunAlertPanel (@"Cold reset!", - @"Really reset the emulator? All current work will be lost. Click Cancel to continue without reset.", - @"OK", @"Cancel", nil); - //printf("b=%i\n",b); - if (b == 1) + if ([NSApp myAlerte:NSInformationalAlertStyle Txt:localize(@"Cold reset") firstB:localize(@"OK") alternateB:localize(@"Cancel") + otherB:nil informativeTxt:localize(@"Really reset the emulator?")] == NSAlertDefaultReturn) Reset_Cold(); } - (IBAction)insertDiskA:(id)sender { - NSString *path = nil; - NSOpenPanel *openPanel = [ NSOpenPanel openPanel ]; - - if ( [ openPanel runModalForDirectory:nil - file:@"SavedGame" types:nil ] ) { - - path = [ [ openPanel filenames ] objectAtIndex:0 ]; - } - - if (path != nil) - { - // Make a non-const C string out of it - const char* constSzPath = [path cString]; - size_t cbPath = strlen(constSzPath) + 1; - char szPath[cbPath]; - strncpy(szPath, constSzPath, cbPath); - - Floppy_InsertDiskIntoDrive(0, szPath, cbPath); - } + [self insertDisk:0] ; } - (IBAction)insertDiskB:(id)sender { - NSString *path = nil; - NSOpenPanel *openPanel = [ NSOpenPanel openPanel ]; - - if ( [ openPanel runModalForDirectory:nil - file:@"SavedGame" types:nil ] ) { - - path = [ [ openPanel filenames ] objectAtIndex:0 ]; - } - - if (path != nil) - { - // Make a non-const C string out of it - const char* constSzPath = [path cString]; - size_t cbPath = strlen(constSzPath) + 1; - char szPath[cbPath]; - strncpy(szPath, constSzPath, cbPath); - - Floppy_InsertDiskIntoDrive(1, szPath, cbPath); - } + [self insertDisk:1] ; } +- (void)insertDisk:(int)disque +{ + NSString *aDisk ; + + aDisk = [NSApp hopenfile:NO defoDir:nil defoFile:@"" types:[NSArray arrayWithObjects:allF,nil]] ; + if ([aDisk length] == 0) return ; // user canceled + + [aDisk getCString:szPath maxLength:FILENAME_MAX-1 encoding:NSASCIIStringEncoding] ; + Floppy_SetDiskFileName(disque, szPath, NULL) ; + Floppy_InsertDiskIntoDrive(disque) ; +} + + /*-----------------------------------------------------------------------*/ /* - Controls the enabled state of the menu items -*/ + Controls the enabled state of the menu items + */ - (BOOL)validateMenuItem:(NSMenuItem*)item { if (item == beginCaptureAnim) { - return !ScreenSnapShot_AreWeRecording(); + return !Avi_AreWeRecording() ; } if (item == endCaptureAnim) { - return ScreenSnapShot_AreWeRecording(); + return Avi_AreWeRecording() ; } if (item == beginCaptureSound) { - return !Sound_AreWeRecording(); + return !Sound_AreWeRecording() ; } if (item == endCaptureSound) { - return Sound_AreWeRecording(); + return Sound_AreWeRecording() ; } return YES; } +- (NSString*)displayFileSelection:(const char*)pathInParams preferredFileName:(NSString*)preferredFileName allowedExtensions:(NSArray*)allowedExtensions +{ + // BOOL test ; + NSString *directoryToOpen; + NSString *fileToPreselect; + NSString *preferredPath; + NSString *extensionText; + NSString *selectFile; + + // Get the path from the user settings + preferredPath = [[NSString stringWithCString:pathInParams encoding:NSASCIIStringEncoding] stringByAbbreviatingWithTildeInPath]; + + if ((preferredPath != nil) && ([preferredPath length] > 0)) // Determine the directory and filename + { + directoryToOpen = [preferredPath stringByDeletingLastPathComponent]; // Existing path: we use it + fileToPreselect = [preferredPath lastPathComponent]; + } + else + { + directoryToOpen = [@"~" stringByExpandingTildeInPath]; // No path: we use the user's directory + fileToPreselect = preferredFileName; + } ; + + if(bInFullScreen) + Screen_ReturnFromFullScreen(); + // SavePanel for choosing what file to write + extensionText = [NSString stringWithFormat:localize(@"Please specify a .%@ file"), [allowedExtensions componentsJoinedByString:localize(@" or a .")] ]; + + selectFile = [NSApp hsavefile:YES defoDir:directoryToOpen defoFile:fileToPreselect types:allowedExtensions titre:extensionText ] ; + if ([selectFile length] != 0 ) + return selectFile ; + + return nil; +} + - (IBAction)captureScreen:(id)sender { - GuiOsx_PauseAndSwitchToCocoaUI(); + GuiOsx_Pause(); ScreenSnapShot_SaveScreen(); - GuiOsx_ResumeFromCocoaUI(); + GuiOsx_Resume(); } - (IBAction)captureAnimation:(id)sender { - GuiOsx_PauseAndSwitchToCocoaUI(); - ScreenSnapShot_BeginRecording(DialogParams.Screen.bCaptureChange, 25); - GuiOsx_ResumeFromCocoaUI(); + GuiOsx_Pause(); + if(!Avi_AreWeRecording()) { + NSString* path = [self displayFileSelection:ConfigureParams.Video.AviRecordFile preferredFileName:@"hatari.avi" + allowedExtensions:[NSArray arrayWithObject:@"avi"]]; + + if(path) { + GuiOsx_ExportPathString(path, ConfigureParams.Video.AviRecordFile, sizeof(ConfigureParams.Video.AviRecordFile)); + Avi_StartRecording ( ConfigureParams.Video.AviRecordFile , ConfigureParams.Screen.bCrop , + ConfigureParams.Video.AviRecordFps == 0 ? + ClocksTimings_GetVBLPerSec ( ConfigureParams.System.nMachineType , nScreenRefreshRate ) : + (Uint32)ConfigureParams.Video.AviRecordFps << CLOCKS_TIMINGS_SHIFT_VBL , + 1 << CLOCKS_TIMINGS_SHIFT_VBL , + ConfigureParams.Video.AviRecordVcodec ); + } + } else { + Avi_StopRecording(); + } + GuiOsx_Resume(); } - (IBAction)endCaptureAnimation:(id)sender { - GuiOsx_PauseAndSwitchToCocoaUI(); - ScreenSnapShot_EndRecording(); - GuiOsx_ResumeFromCocoaUI(); + GuiOsx_Pause(); + Avi_StopRecording(); + GuiOsx_Resume(); } - (IBAction)captureSound:(id)sender { - GuiOsx_PauseAndSwitchToCocoaUI(); - - // Get the path from the user settings - NSString *preferredPath = [[NSString stringWithCString:(ConfigureParams.Sound.szYMCaptureFileName)] stringByAbbreviatingWithTildeInPath]; - - // Determine the directory and filename - NSString *directoryToOpen; - NSString *fileToPreselect; - if ((preferredPath != nil) && ([preferredPath length] > 0)) - { - // There is existing path: we will open its directory with its file pre-selected. - directoryToOpen = [preferredPath stringByDeletingLastPathComponent]; - fileToPreselect = [preferredPath lastPathComponent]; - } - else - { - // Currently no path: we will open the user's directory with no file selected. - directoryToOpen = [@"~" stringByExpandingTildeInPath]; - fileToPreselect = @"hatari.wav"; - } - - // Create and configure a SavePanel for choosing what file to write - NSSavePanel *savePanel = [NSSavePanel savePanel]; - [savePanel setAllowedFileTypes:[NSArray arrayWithObjects:@"ym", @"wav", nil]]; - [savePanel setExtensionHidden:NO]; - [savePanel setMessage:@"Please specify an .ym or a .wav file."]; // TODO: Move to localizable resources - - // Run the SavePanel, then check if the user clicked OK and selected at least one file - if (NSFileHandlingPanelOKButton == [savePanel runModalForDirectory:directoryToOpen file:fileToPreselect] ) - { - // Get the path to the selected file - NSString *path = [savePanel filename]; - - // Store the path in the user settings + GuiOsx_Pause(); + NSString* path = [self displayFileSelection:ConfigureParams.Sound.szYMCaptureFileName preferredFileName:@"hatari.wav" + allowedExtensions:[NSArray arrayWithObjects:@"ym", @"wav", nil]]; + if(path) { GuiOsx_ExportPathString(path, ConfigureParams.Sound.szYMCaptureFileName, sizeof(ConfigureParams.Sound.szYMCaptureFileName)); - - // Begin capture Sound_BeginRecording(ConfigureParams.Sound.szYMCaptureFileName); - } - - GuiOsx_ResumeFromCocoaUI(); + } + GuiOsx_Resume(); } - (IBAction)endCaptureSound:(id)sender { - GuiOsx_PauseAndSwitchToCocoaUI(); + GuiOsx_Pause(); Sound_EndRecording(); - GuiOsx_ResumeFromCocoaUI(); + GuiOsx_Resume(); } - (IBAction)saveMemorySnap:(id)sender { - GuiOsx_PauseAndSwitchToCocoaUI(); + GuiOsx_Pause(); - // Get the path from the user settings - NSString *preferredPath = [[NSString stringWithCString:(ConfigureParams.Memory.szMemoryCaptureFileName)] stringByAbbreviatingWithTildeInPath]; - - // Determine the directory and filename - NSString *directoryToOpen; - NSString *fileToPreselect; - if ((preferredPath != nil) && ([preferredPath length] > 0)) - { - // There is existing path: we will open its directory with its file pre-selected. - directoryToOpen = [preferredPath stringByDeletingLastPathComponent]; - fileToPreselect = [preferredPath lastPathComponent]; - } - else - { - // Currently no path: we will open the user's directory with the default filename. - directoryToOpen = [@"~" stringByExpandingTildeInPath]; - fileToPreselect = @"hatari.sav"; - } - - // Create and configure a SavePanel for choosing what file to write - NSSavePanel *savePanel = [NSSavePanel savePanel]; - [savePanel setExtensionHidden:NO]; - - // Run the SavePanel, then check if the user clicked OK and selected at least one file - if (NSFileHandlingPanelOKButton == [savePanel runModalForDirectory:directoryToOpen file:fileToPreselect] ) - { - // Get the path to the selected file - NSString *path = [savePanel filename]; - - // Store the path in the user settings + NSString* path = [self displayFileSelection:ConfigureParams.Memory.szMemoryCaptureFileName preferredFileName:@"hatari.sav" + allowedExtensions:[NSArray arrayWithObject:@"sav"]]; + if(path) { GuiOsx_ExportPathString(path, ConfigureParams.Memory.szMemoryCaptureFileName, sizeof(ConfigureParams.Memory.szMemoryCaptureFileName)); - - // Perform the memory snapshot save MemorySnapShot_Capture(ConfigureParams.Memory.szMemoryCaptureFileName, TRUE); - } + } - GuiOsx_ResumeFromCocoaUI(); + GuiOsx_Resume(); } - (IBAction)restoreMemorySnap:(id)sender { - GuiOsx_PauseAndSwitchToCocoaUI(); + NSString *directoryToOpen; + NSString *fileToPreselect; + NSString *oldPath ; + NSString *newPath ; - // Create and configure an OpenPanel - NSOpenPanel *openPanel = [NSOpenPanel openPanel]; + GuiOsx_Pause(); // Get the path from the user settings - NSString *oldPath = [NSString stringWithCString:(ConfigureParams.Memory.szMemoryCaptureFileName)]; + oldPath = [NSString stringWithCString:(ConfigureParams.Memory.szMemoryCaptureFileName) encoding:NSASCIIStringEncoding]; - // Determine the directory and filename - NSString *directoryToOpen; - NSString *fileToPreselect; - if ((oldPath != nil) && ([oldPath length] > 0)) - { - // There is existing path: we will open its directory with its file pre-selected. - directoryToOpen = [oldPath stringByDeletingLastPathComponent]; - fileToPreselect = [oldPath lastPathComponent]; - } + if ((oldPath != nil) && ([oldPath length] > 0)) // Determine directory and filename + { directoryToOpen = [oldPath stringByDeletingLastPathComponent]; // existing path: we use it. + fileToPreselect = [oldPath lastPathComponent]; } else - { - // Currently no path: we will open the user's directory with no file selected. - directoryToOpen = [@"~" stringByExpandingTildeInPath]; - fileToPreselect = nil; - } - - // Run the OpenPanel, then check if the user clicked OK and selected at least one file - if ( (NSOKButton == [openPanel runModalForDirectory:directoryToOpen file:fileToPreselect types:nil] ) - && ([[openPanel filenames] count] > 0) ) - { - // Get the path to the selected file - NSString *path = [[openPanel filenames] objectAtIndex:0]; - - // Perform the memory snapshot load - MemorySnapShot_Restore([path cString], TRUE); - } - - GuiOsx_ResumeFromCocoaUI(); + { directoryToOpen = [@"~" stringByExpandingTildeInPath]; // Currently no path: we use user's directory + fileToPreselect = nil; } ; + + newPath = [NSApp hopenfile:NO defoDir:directoryToOpen defoFile:fileToPreselect types:[NSArray arrayWithObject:@"sav"] ] ; + if ([newPath length] != 0) // Perform the memory snapshot load + MemorySnapShot_Restore([newPath cStringUsingEncoding:NSASCIIStringEncoding], TRUE); + + GuiOsx_Resume(); } - (IBAction)doFullScreen:(id)sender { - // 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. + // 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. // Therefore we simulate the fullscreen key press instead - + SDL_KeyboardEvent event; - event.type = SDL_KEYDOWN; - event.which = 0; - event.state = SDL_PRESSED; - event.keysym.sym = SDLK_F11; - SDL_PushEvent((SDL_Event*)&event); // Send the F11 key press - event.type = SDL_KEYUP; - event.state = SDL_RELEASED; - SDL_PushEvent((SDL_Event*)&event); // Send the F11 key release + memset(&event, 0, sizeof(event)); + event.type = SDL_KEYDOWN; + event.state = SDL_PRESSED; + event.keysym.sym = SDLK_F11; + SDL_PushEvent((SDL_Event*)&event); // Send the F11 key press + event.type = SDL_KEYUP; + event.state = SDL_RELEASED; + SDL_PushEvent((SDL_Event*)&event); // Send the F11 key release } + - (IBAction)help:(id)sender { - [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://hatari.sourceforge.net/"]]; - /* - NSRunAlertPanel (@"Help", - @"Sorry, there is no built-in help available.\n\nPlease visit http://hatari.sourceforge.net/ for more information.\n\n", - @"OK", nil, nil); - */ -} + NSString *the_help; + the_help = [[NSBundle mainBundle] pathForResource:@"manual" ofType:@"html" inDirectory:@"HatariHelp"]; -/* 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) - { - assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ - assert ( chdir ("../../../") == 0 ); /* chdir to the .app's parent */ - } + if (![[NSWorkspace sharedWorkspace] openFile:the_help withApplication:@"HelpViewer"]) + if (![[NSWorkspace sharedWorkspace] openFile:the_help withApplication:@"Help Viewer"]) + [[NSWorkspace sharedWorkspace] openFile:the_help]; } +- (IBAction)compat:(id)sender +{ + NSString *C_aide ; -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note + C_aide = [[NSBundle mainBundle] pathForResource:@"compatibility" ofType:@"html" inDirectory:@"HatariHelp"] ; + + if (![[NSWorkspace sharedWorkspace] openFile:C_aide withApplication:@"HelpViewer"]) + if (![[NSWorkspace sharedWorkspace] openFile:C_aide withApplication:@"Help Viewer"]) + [[NSWorkspace sharedWorkspace] openFile:C_aide] ; +} + +- (IBAction)openConfig:(id)sender { - int status; + BOOL applyChanges ; + NSString *ConfigFile, *newCfg ; + CNF_PARAMS CurrentParams; - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; + applyChanges = true ; + ConfigFile = [NSString stringWithCString:(sConfigFileName) encoding:NSASCIIStringEncoding]; - /* Hand off to main application code */ - status = SDL_main (gArgc, gArgv); + // Backup of configuration settings to CurrentParams (which we will only + // commit back to the configuration settings if choosing user confirm) + CurrentParams = ConfigureParams; - /* We're done, thank you for playing */ - exit(status); -} + GuiOsx_Pause(); -@end + newCfg = [NSApp hopenfile:NO defoDir:nil defoFile:ConfigFile types:[NSArray arrayWithObject:@"cfg"] ] ; + if ([newCfg length] != 0) + { + [newCfg getCString:szPath maxLength:FILENAME_MAX-1 encoding:NSASCIIStringEncoding] ; // get Cstring szPath + Configuration_Load(szPath) ; // Load the config into ConfigureParams + strcpy(sConfigFileName,szPath) ; -@implementation NSString (ReplaceSubString) + // Refresh all the controls to match ConfigureParams + if (Change_DoNeedReset(&CurrentParams, &ConfigureParams)) + applyChanges = [NSApp myAlerte:NSInformationalAlertStyle Txt:localize(@"Reset the emulator") firstB:localize(@"Don't reset") + alternateB:localize(@"Reset") otherB:nil informativeTxt:@"" ] == NSAlertAlternateReturn ; + if (applyChanges) + Change_CopyChangedParamsToConfiguration(&CurrentParams, &ConfigureParams, true); // Ok with Reset + else + ConfigureParams = CurrentParams; //Restore previous Params. + } ; -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* 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 */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; + GuiOsx_Resume(); +} + + +- (IBAction)saveConfig:(id)sender { } @end +static int IsRootCwd() +{ + char buf[MAXPATHLEN]; + char *cwd = getcwd(buf, sizeof (buf)); + return (cwd && (strcmp(cwd, "/") == 0)); +} + +static int IsTenPointNineOrLater() +{ + /* Gestalt() is deprecated in 10.8 ... TODO: replace with better test? */ + SInt32 major, minor; + Gestalt(gestaltSystemVersionMajor, &major); + Gestalt(gestaltSystemVersionMinor, &minor); + return ( ((major << 16) | minor) >= ((10 << 16) | 9) ); +} +static int IsFinderLaunch(const int argc, char **argv) +{ + /* -psn_XXX is passed if we are launched from Finder in 10.8 and earlier */ + if (argc >= 2 && strncmp(argv[1], "-psn", 4) == 0) { + return 1; + } + if (IsTenPointNineOrLater() && argc == 1 && IsRootCwd()) { + /* we might still be launched from the Finder; on 10.9+, you might not + get the -psn command line anymore. Check version, if there's no + command line, and if our current working directory is "/". */ + return 1; + } + return 0; /* not a Finder launch. */ +} #ifdef main # undef main #endif - -/* Main entry point to executable - should *not* 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 + if (IsFinderLaunch(argc, argv)) { + gArgv = (char **) SDL_malloc(sizeof (char *) * 2); + gArgv[0] = argv[0]; + gArgv[1] = NULL; + gArgc = 1; + gFinderLaunch = YES; + } else { + int i; + gArgc = argc; + gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); + for (i = 0; i <= argc; i++) + gArgv[i] = argv[i]; + gFinderLaunch = NO; + } - /* 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; - } else { - gArgc = argc; - gFinderLaunch = NO; - } - gArgv = (char**) malloc (sizeof(*gArgv) * (gArgc+1)); - assert (gArgv != NULL); - for (i = 0; i < gArgc; i++) - gArgv[i] = argv[i]; - gArgv[i] = NULL; - - [SDLApplication poseAsClass:[NSApplication class]]; - NSApplicationMain (argc, (const char**)argv); - - return 0; +#if SDL_USE_NIB_FILE + NSApplicationMain (argc, (const char**)argv); +#else + CustomApplicationMain (argc, argv); +#endif + return 0; }