--- hatari/src/gui-osx/SDLMain.m 2019/04/09 08:54:10 1.1.1.11 +++ hatari/src/gui-osx/SDLMain.m 2019/04/09 08:56:38 1.1.1.13 @@ -1,18 +1,10 @@ -// -// HatariAppDelegate.m -// Hatari -// -// Créé le 12/06/13 par Miguel Saro. -// Tout droits réservés, - Cocoa Pod -, 2013. -// - -/* 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 + 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 */ @@ -72,8 +64,8 @@ char szPath[FILENAME_MAX] ; // // Set the working directory to the .app's parent directory - (void) setupWorkingDirectory:(BOOL)shouldChdir { - if (shouldChdir) - chdir([[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] cStringUsingEncoding:NSASCIIStringEncoding]) ; + if (shouldChdir) + chdir([[[NSBundle mainBundle].bundlePath stringByDeletingLastPathComponent] cStringUsingEncoding:NSASCIIStringEncoding]) ; } @@ -94,40 +86,40 @@ char szPath[FILENAME_MAX] ; // */ - (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; -} + 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; @@ -138,7 +130,7 @@ char szPath[FILENAME_MAX] ; // //setenv ("SDL_ENABLEAPPEVENTS", "1", 1) ; // Hand off to main application code - + emulationPaused=NO; gCalledAppMainline = TRUE; status = SDL_main (gArgc, gArgv) ; @@ -146,7 +138,9 @@ char szPath[FILENAME_MAX] ; // exit(status) ; } +/*----------------------------------------------------------------------*/ // Hatari Stuff +/*----------------------------------------------------------------------*/ - (IBAction)prefsMenu:(id)sender { static int in_propdialog = 0; @@ -163,53 +157,56 @@ char szPath[FILENAME_MAX] ; // [[PrefsController prefs] loadPrefs:sender]; } // */ - +/*----------------------------------------------------------------------*/ - (IBAction)debugUI:(id)sender { DebugUI(REASON_USER); } - +/*----------------------------------------------------------------------*/ - (IBAction)warmReset:(id)sender { - if (NSRunAlertPanel (localize(@"Warm reset"), localize(@"Really reset the emulator?"), - localize(@"OK"), localize(@"Cancel"), nil) == NSAlertDefaultReturn ) + if ([NSApp myAlerte:NSInformationalAlertStyle Txt:localize(@"Warm reset!") firstB:localize(@"OK") alternateB:localize(@"Cancel") + otherB:nil informativeTxt:localize(@"Really reset the emulator?")] == NSAlertFirstButtonReturn ) Reset_Warm(); } - +/*----------------------------------------------------------------------*/ - (IBAction)coldReset:(id)sender { - if (NSRunAlertPanel (localize(@"Cold reset!"), localize(@"Really reset the emulator?"), - localize(@"OK"),localize(@"Cancel"), nil) == NSAlertDefaultReturn ) + if ([NSApp myAlerte:NSInformationalAlertStyle Txt:localize(@"Cold reset") firstB:localize(@"OK") alternateB:localize(@"Cancel") + otherB:nil informativeTxt:localize(@"Really reset the emulator?")] == NSAlertFirstButtonReturn ) Reset_Cold(); } - +/*----------------------------------------------------------------------*/ - (IBAction)insertDiskA:(id)sender { [self insertDisk:0] ; } - +/*----------------------------------------------------------------------*/ - (IBAction)insertDiskB:(id)sender { [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 = [NSApp hopenfile:NO defoDir:nil defoFile:@"" types:@[allF]] ; + if (aDisk.length == 0) return ; // user canceled [aDisk getCString:szPath maxLength:FILENAME_MAX-1 encoding:NSASCIIStringEncoding] ; Floppy_SetDiskFileName(disque, szPath, NULL) ; Floppy_InsertDiskIntoDrive(disque) ; } +/*----------------------------------------------------------------------*/ +- (IBAction)quit:(id)sender +{ + Main_RequestQuit(0) ; +} - -/*-----------------------------------------------------------------------*/ -/* - Controls the enabled state of the menu items - */ +/*----------------------------------------------------------------------*/ +/*Controls the enabled state of the menu items */ +/*----------------------------------------------------------------------*/ - (BOOL)validateMenuItem:(NSMenuItem*)item { if (item == beginCaptureAnim) @@ -232,6 +229,8 @@ char szPath[FILENAME_MAX] ; // return YES; } +/*----------------------------------------------------------------------*/ + - (NSString*)displayFileSelection:(const char*)pathInParams preferredFileName:(NSString*)preferredFileName allowedExtensions:(NSArray*)allowedExtensions { // BOOL test ; @@ -240,48 +239,47 @@ char szPath[FILENAME_MAX] ; // 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 + if ((preferredPath != nil) && (preferredPath.length > 0)) // Determine the directory and filename { - directoryToOpen = [preferredPath stringByDeletingLastPathComponent]; // Existing path: we use it - fileToPreselect = [preferredPath lastPathComponent]; + 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 ) + if (selectFile.length != 0 ) return selectFile ; - + return nil; } - +/*----------------------------------------------------------------------*/ - (IBAction)captureScreen:(id)sender { - GuiOsx_Pause(); + GuiOsx_Pause(false); ScreenSnapShot_SaveScreen(); GuiOsx_Resume(); } - +/*----------------------------------------------------------------------*/ - (IBAction)captureAnimation:(id)sender { - GuiOsx_Pause(); + GuiOsx_Pause(false); if(!Avi_AreWeRecording()) { - NSString* path = [self displayFileSelection:ConfigureParams.Video.AviRecordFile preferredFileName:@"hatari.avi" - allowedExtensions:[NSArray arrayWithObject:@"avi"]]; - + NSString* path = [self displayFileSelection:ConfigureParams.Video.AviRecordFile preferredFileName:@"hatari.avi" + allowedExtensions:@[@"avi"]]; + if(path) { GuiOsx_ExportPathString(path, ConfigureParams.Video.AviRecordFile, sizeof(ConfigureParams.Video.AviRecordFile)); Avi_StartRecording ( ConfigureParams.Video.AviRecordFile , ConfigureParams.Screen.bCrop , @@ -291,88 +289,87 @@ char szPath[FILENAME_MAX] ; // 1 << CLOCKS_TIMINGS_SHIFT_VBL , ConfigureParams.Video.AviRecordVcodec ); } - } else { Avi_StopRecording(); } GuiOsx_Resume(); } - +/*----------------------------------------------------------------------*/ - (IBAction)endCaptureAnimation:(id)sender { - GuiOsx_Pause(); + GuiOsx_Pause(false); Avi_StopRecording(); GuiOsx_Resume(); } - +/*----------------------------------------------------------------------*/ - (IBAction)captureSound:(id)sender { - GuiOsx_Pause(); - NSString* path = [self displayFileSelection:ConfigureParams.Sound.szYMCaptureFileName preferredFileName:@"hatari.wav" - allowedExtensions:[NSArray arrayWithObjects:@"ym", @"wav", nil]]; + GuiOsx_Pause(true); + NSString* path = [self displayFileSelection:ConfigureParams.Sound.szYMCaptureFileName preferredFileName:@"hatari.wav" + allowedExtensions:@[@"ym", @"wav"]]; if(path) { GuiOsx_ExportPathString(path, ConfigureParams.Sound.szYMCaptureFileName, sizeof(ConfigureParams.Sound.szYMCaptureFileName)); Sound_BeginRecording(ConfigureParams.Sound.szYMCaptureFileName); } GuiOsx_Resume(); } - +/*----------------------------------------------------------------------*/ - (IBAction)endCaptureSound:(id)sender { - GuiOsx_Pause(); + GuiOsx_Pause(false); Sound_EndRecording(); GuiOsx_Resume(); } - +/*----------------------------------------------------------------------*/ - (IBAction)saveMemorySnap:(id)sender { - GuiOsx_Pause(); + GuiOsx_Pause(true); - NSString* path = [self displayFileSelection:ConfigureParams.Memory.szMemoryCaptureFileName preferredFileName:@"hatari.sav" - allowedExtensions:[NSArray arrayWithObject:@"sav"]]; + NSString* path = [self displayFileSelection:ConfigureParams.Memory.szMemoryCaptureFileName preferredFileName:@"hatari.sav" + allowedExtensions:@[@"sav"]]; if(path) { GuiOsx_ExportPathString(path, ConfigureParams.Memory.szMemoryCaptureFileName, sizeof(ConfigureParams.Memory.szMemoryCaptureFileName)); MemorySnapShot_Capture(ConfigureParams.Memory.szMemoryCaptureFileName, TRUE); } - + GuiOsx_Resume(); } - +/*----------------------------------------------------------------------*/ - (IBAction)restoreMemorySnap:(id)sender { -NSString *directoryToOpen; -NSString *fileToPreselect; -NSString *oldPath ; -NSString *newPath ; + NSString *directoryToOpen; + NSString *fileToPreselect; + NSString *oldPath ; + NSString *newPath ; - GuiOsx_Pause(); + GuiOsx_Pause(true); // Get the path from the user settings oldPath = [NSString stringWithCString:(ConfigureParams.Memory.szMemoryCaptureFileName) encoding:NSASCIIStringEncoding]; - - if ((oldPath != nil) && ([oldPath length] > 0)) // Determine directory and filename - { directoryToOpen = [oldPath stringByDeletingLastPathComponent]; // existing path: we use it. - 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 - { directoryToOpen = [@"~" stringByExpandingTildeInPath]; // Currently no path: we use user's directory + { 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 + newPath = [NSApp hopenfile:NO defoDir:directoryToOpen defoFile:fileToPreselect types:@[@"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 + // 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; + memset(&event, 0, sizeof(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 @@ -381,100 +378,141 @@ NSString *newPath ; SDL_PushEvent((SDL_Event*)&event); // Send the F11 key release } - +/*----------------------------------------------------------------------*/ - (IBAction)help:(id)sender { NSString *the_help; - + the_help = [[NSBundle mainBundle] pathForResource:@"manual" ofType:@"html" inDirectory:@"HatariHelp"]; - - if (![[NSWorkspace sharedWorkspace] openFile:the_help withApplication:@"HelpViewer"]) - if (![[NSWorkspace sharedWorkspace] openFile:the_help withApplication:@"Help Viewer"]) - [[NSWorkspace sharedWorkspace] openFile:the_help]; -} + [[NSWorkspace sharedWorkspace] openFile:the_help]; +} +/*----------------------------------------------------------------------*/ - (IBAction)compat:(id)sender { -NSString *C_aide ; - - 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] ; -} + NSString *the_help ; + + the_help = [[NSBundle mainBundle] pathForResource:@"compatibility" ofType:@"html" inDirectory:@"HatariHelp"] ; -- (IBAction)openConfig:(id)sender -{ -BOOL applyChanges ; -NSString *ConfigFile, *newCfg ; -CNF_PARAMS CurrentParams; + [[NSWorkspace sharedWorkspace] openFile:the_help]; +} +/*----------------------------------------------------------------------*/ +- (IBAction)PauseMenu:(id)sender { + if(!emulationPaused) + { + GuiOsx_Pause(true); + emulationPaused=YES; + [pauseMenuItem setState:NSOnState]; + } + else + { + GuiOsx_Resume(); + emulationPaused=NO; + [pauseMenuItem setState:NSOffState]; + } +} +/*----------------------------------------------------------------------*/ +- (IBAction)openConfig:(id)sender +{ + BOOL applyChanges ; + NSString *ConfigFile, *newCfg ; + CNF_PARAMS CurrentParams; applyChanges = true ; - ConfigFile = [NSString stringWithCString:(sConfigFileName) encoding:NSASCIIStringEncoding]; - + ConfigFile = [NSString stringWithCString:(sConfigFileName) encoding:NSASCIIStringEncoding]; + // Backup of configuration settings to CurrentParams (which we will only // commit back to the configuration settings if choosing user confirm) CurrentParams = ConfigureParams; - - GuiOsx_Pause(); - - newCfg = [NSApp hopenfile:NO defoDir:nil defoFile:ConfigFile types:[NSArray arrayWithObject:@"cfg"] ] ; - - if ([newCfg length] != 0) - { + + GuiOsx_Pause(true); + + newCfg = [NSApp hopenfile:NO defoDir:nil defoFile:ConfigFile types:@[@"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) ; - // Refresh all the controls to match ConfigureParams + // Refresh all the controls to match ConfigureParams if (Change_DoNeedReset(&CurrentParams, &ConfigureParams)) - applyChanges = NSRunAlertPanel(localize(@"Reset the emulator"), localize(@"Must be reset"), - localize(@"Don't reset"), localize(@"Reset"), nil) == NSAlertAlternateReturn ; - + applyChanges = [NSApp myAlerte:NSInformationalAlertStyle Txt:localize(@"Reset the emulator") firstB:localize(@"Don't reset") + alternateB:localize(@"Reset") otherB:nil informativeTxt:@"" ] == NSAlertFirstButtonReturn ; if (applyChanges) - Change_CopyChangedParamsToConfiguration(&CurrentParams, &ConfigureParams, true); // Ok with Reset - else + Change_CopyChangedParamsToConfiguration(&CurrentParams, &ConfigureParams, true); // Ok with Reset + else ConfigureParams = CurrentParams; //Restore previous Params. - } ; - + } ; + 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() +{ + // OK for 10.9, but before ?? + NSOperatingSystemVersion systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; + int r=(systemVersion.majorVersion==10) && (systemVersion.minorVersion>=9); + + return r; +} +/*----------------------------------------------------------------------*/ +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 - // This is passed if we are launched by double-clicking - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - 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 + 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; + } #if SDL_USE_NIB_FILE - NSApplicationMain (argc, (const char**)argv); + NSApplicationMain (argc, (const char**)argv); #else - CustomApplicationMain (argc, argv); + CustomApplicationMain (argc, argv); #endif - return 0; -} // */ + return 0; +}