|
|
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:
1.1.1.6 root 8: #include "SDL.h"
9: #include "SDLMain.h"
10: #include <sys/param.h> /* for MAXPATHLEN */
11: #include <unistd.h>
12:
13: // for Hatari
1.1 root 14:
15: #include "dialog.h"
16: #include "floppy.h"
17: #include "reset.h"
18: #include "screenSnapShot.h"
19: #include "memorySnapShot.h"
20: #include "sound.h"
1.1.1.7 root 21: #include "screen.h"
22: #include "PrefsController.h"
23: #include "Shared.h"
1.1.1.6 root 24: #include "video.h"
25: #include "avi_record.h"
1.1.1.7 root 26: #include "../debug/debugui.h"
27: #include "clocks_timings.h"
1.1.1.6 root 28:
29: // for Hatari
30:
31:
32: /* For some reaon, Apple removed setAppleMenu from the headers in 10.4,
33: but the method still is there and works. To avoid warnings, we declare
34: it ourselves here. */
35: @interface NSApplication(SDL_Missing_Methods)
36: - (void)setAppleMenu:(NSMenu *)menu;
37: @end
38:
39: /* Use this flag to determine whether we use SDLMain.nib or not */
40: #define SDL_USE_NIB_FILE 1
41:
42: /* Use this flag to determine whether we use CPS (docking) or not */
43: #define SDL_USE_CPS 1
44: #ifdef SDL_USE_CPS
45: /* Portions of CPS.h */
46: typedef struct CPSProcessSerNum
47: {
48: UInt32 lo;
49: UInt32 hi;
50: } CPSProcessSerNum;
51:
52: extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
53: extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
54: extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
55:
56: #endif /* SDL_USE_CPS */
1.1 root 57:
58: static int gArgc;
59: static char **gArgv;
60: static BOOL gFinderLaunch;
1.1.1.6 root 61: static BOOL gCalledAppMainline = FALSE;
62:
63: static NSString *getApplicationName(void)
64: {
65: const NSDictionary *dict;
66: NSString *appName = 0;
1.1 root 67:
1.1.1.6 root 68: /* Determine the application name */
69: dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
70: if (dict)
71: appName = [dict objectForKey: @"CFBundleName"];
72:
73: if (![appName length])
74: appName = [[NSProcessInfo processInfo] processName];
75:
76: return appName;
77: }
78:
79: #if SDL_USE_NIB_FILE
80: /* A helper category for NSString */
81: @interface NSString (ReplaceSubString)
82: - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString;
1.1 root 83: @end
1.1.1.6 root 84: #endif
1.1 root 85:
1.1.1.6 root 86: @interface NSApplication (SDLApplication)
87: @end
88:
89: @implementation NSApplication (SDLApplication)
1.1 root 90: /* Invoked from the Quit menu item */
91: - (void)terminate:(id)sender
92: {
93: /* Post a SDL_QUIT event */
94: SDL_Event event;
95: event.type = SDL_QUIT;
96: SDL_PushEvent(&event);
97: }
98: @end
99:
100: /* The main class of the application, the application's delegate */
101: @implementation SDLMain
102:
1.1.1.7 root 103:
1.1.1.6 root 104: /* Set the working directory to the .app's parent directory */
105: - (void) setupWorkingDirectory:(BOOL)shouldChdir
106: {
107: if (shouldChdir)
108: {
109: char parentdir[MAXPATHLEN];
110: CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
111: CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url);
112: if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) {
113: chdir(parentdir); /* chdir to the binary app's parent */
114: }
115: CFRelease(url);
116: CFRelease(url2);
117: }
118: }
119:
120: #if SDL_USE_NIB_FILE
121:
122: /* Fix menu to contain the real app name instead of "SDL App" */
123: - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName
124: {
125: NSRange aRange;
126: NSEnumerator *enumerator;
127: NSMenuItem *menuItem;
128:
129: aRange = [[aMenu title] rangeOfString:@"SDL App"];
130: if (aRange.length != 0)
131: [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]];
132:
133: enumerator = [[aMenu itemArray] objectEnumerator];
134: while ((menuItem = [enumerator nextObject]))
135: {
136: aRange = [[menuItem title] rangeOfString:@"SDL App"];
137: if (aRange.length != 0)
138: [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]];
139: if ([menuItem hasSubmenu])
140: [self fixMenu:[menuItem submenu] withAppName:appName];
141: }
142: }
143:
144: #else
145:
146: static void setApplicationMenu(void)
147: {
148: /* warning: this code is very odd */
149: NSMenu *appleMenu;
150: NSMenuItem *menuItem;
151: NSString *title;
152: NSString *appName;
153:
154: appName = getApplicationName();
155: appleMenu = [[NSMenu alloc] initWithTitle:@""];
156:
157: /* Add menu items */
158: title = [@"About " stringByAppendingString:appName];
159: [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
160:
161: [appleMenu addItem:[NSMenuItem separatorItem]];
162:
163: title = [@"Hide " stringByAppendingString:appName];
164: [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
165:
166: menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
167: [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
168:
169: [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
170:
171: [appleMenu addItem:[NSMenuItem separatorItem]];
172:
173: title = [@"Quit " stringByAppendingString:appName];
174: [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
175:
176:
177: /* Put menu into the menubar */
178: menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
179: [menuItem setSubmenu:appleMenu];
180: [[NSApp mainMenu] addItem:menuItem];
181:
182: /* Tell the application object that this is now the application menu */
183: [NSApp setAppleMenu:appleMenu];
184:
185: /* Finally give up our references to the objects */
186: [appleMenu release];
187: [menuItem release];
188: }
189:
190: /* Create a window menu */
191: static void setupWindowMenu(void)
192: {
193: NSMenu *windowMenu;
194: NSMenuItem *windowMenuItem;
195: NSMenuItem *menuItem;
196:
197: windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
198:
199: /* "Minimize" item */
200: menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
201: [windowMenu addItem:menuItem];
202: [menuItem release];
203:
204: /* Put menu into the menubar */
205: windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
206: [windowMenuItem setSubmenu:windowMenu];
207: [[NSApp mainMenu] addItem:windowMenuItem];
208:
209: /* Tell the application object that this is now the window menu */
210: [NSApp setWindowsMenu:windowMenu];
211:
212: /* Finally give up our references to the objects */
213: [windowMenu release];
214: [windowMenuItem release];
215: }
216:
217: /* Replacement for NSApplicationMain */
218: static void CustomApplicationMain (int argc, char **argv)
219: {
220: NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
221: SDLMain *sdlMain;
222:
223: /* Ensure the application object is initialised */
224: [NSApplication sharedApplication];
225:
226: #ifdef SDL_USE_CPS
227: {
228: CPSProcessSerNum PSN;
229: /* Tell the dock about us */
230: if (!CPSGetCurrentProcess(&PSN))
231: if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
232: if (!CPSSetFrontProcess(&PSN))
233: [NSApplication sharedApplication];
234: }
235: #endif /* SDL_USE_CPS */
236:
237: /* Set up the menubar */
238: [NSApp setMainMenu:[[NSMenu alloc] init]];
239: setApplicationMenu();
240: setupWindowMenu();
241:
242: /* Create SDLMain and make it the app delegate */
243: sdlMain = [[SDLMain alloc] init];
244: [NSApp setDelegate:sdlMain];
245:
246: /* Start the main event loop */
247: [NSApp run];
248:
249: [sdlMain release];
250: [pool release];
251: }
252:
253: #endif
254:
255:
256: /*
257: * Catch document open requests...this lets us notice files when the app
258: * was launched by double-clicking a document, or when a document was
259: * dragged/dropped on the app's icon. You need to have a
260: * CFBundleDocumentsType section in your Info.plist to get this message,
261: * apparently.
262: *
263: * Files are added to gArgv, so to the app, they'll look like command line
264: * arguments. Previously, apps launched from the finder had nothing but
265: * an argv[0].
266: *
267: * This message may be received multiple times to open several docs on launch.
268: *
269: * This message is ignored once the app's mainline has been called.
270: */
271: - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
272: {
273: const char *temparg;
274: size_t arglen;
275: char *arg;
276: char **newargv;
277:
278: if (!gFinderLaunch) /* MacOS is passing command line args. */
279: return FALSE;
280:
281: if (gCalledAppMainline) /* app has started, ignore this document. */
282: return FALSE;
283:
284: temparg = [filename UTF8String];
285: arglen = SDL_strlen(temparg) + 1;
286: arg = (char *) SDL_malloc(arglen);
287: if (arg == NULL)
288: return FALSE;
289:
290: newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2));
291: if (newargv == NULL)
292: {
293: SDL_free(arg);
294: return FALSE;
295: }
296: gArgv = newargv;
297:
298: SDL_strlcpy(arg, temparg, arglen);
299: gArgv[gArgc++] = arg;
300: gArgv[gArgc] = NULL;
301: return TRUE;
302: }
303:
304:
305: /* Called when the internal event loop has just started running */
306: - (void) applicationDidFinishLaunching: (NSNotification *) note
307: {
308: int status;
309:
310: /* Set the working directory to the .app's parent directory */
311: [self setupWorkingDirectory:gFinderLaunch];
312:
313: #if SDL_USE_NIB_FILE
314: /* Set the main menu to contain the real app name instead of "SDL App" */
315: [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()];
316: #endif
317:
318: /* Hand off to main application code */
319: gCalledAppMainline = TRUE;
320: status = SDL_main (gArgc, gArgv);
321:
322: /* We're done, thank you for playing */
323: exit(status);
324: }
325:
326: // Hatari Stuff
1.1 root 327: - (IBAction)prefsMenu:(id)sender
328: {
329: static int in_propdialog = 0;
1.1.1.6 root 330:
1.1 root 331: if (in_propdialog)
332: return;
333: ++in_propdialog;
1.1.1.6 root 334: Dialog_DoProperty();
1.1 root 335: --in_propdialog;
336: }
337:
1.1.1.9 ! root 338: - (IBAction) openPreferences:(id)sender
! 339: {
! 340: [[PrefsController prefs] loadPrefs:sender];
! 341: }
! 342:
! 343:
1.1.1.6 root 344: - (IBAction)debugUI:(id)sender
345: {
1.1.1.8 root 346: DebugUI(REASON_USER);
1.1.1.6 root 347: }
348:
1.1 root 349: - (IBAction)warmReset:(id)sender
350: {
351: int b;
1.1.1.6 root 352:
353: b = NSRunAlertPanel (
354: NSLocalizedStringFromTable(@"Warm reset",@"Localizable",@"comment"),
355: NSLocalizedStringFromTable(@"Really reset the emulator?",@"Localizable",@"comment"),
356: NSLocalizedStringFromTable(@"OK",@"Localizable",@"comment"),
357: NSLocalizedStringFromTable(@"Cancel",@"Localizable",@"comment"), nil);
1.1 root 358: //printf("b=%i\n",b);
359: if (b == 1)
360: Reset_Warm();
361: }
362:
363: - (IBAction)coldReset:(id)sender
364: {
365: int b;
1.1.1.6 root 366:
367: b = NSRunAlertPanel (
368: NSLocalizedStringFromTable(@"Cold reset!",@"Localizable",@"comment"),
369: NSLocalizedStringFromTable(@"Really reset the emulator?",@"Localizable",@"comment") ,
370: NSLocalizedStringFromTable(@"OK",@"Localizable",@"comment"),
371: NSLocalizedStringFromTable(@"Cancel",@"Localizable",@"comment"), nil);
1.1 root 372: //printf("b=%i\n",b);
373: if (b == 1)
374: Reset_Cold();
375: }
376:
377: - (IBAction)insertDiskA:(id)sender
378: {
1.1.1.6 root 379: NSString *path = nil;
380: NSOpenPanel *openPanel = [ NSOpenPanel openPanel ];
381:
382: if ( [ openPanel runModalForDirectory:nil
383: file:@"SavedGame" types:nil ] )
384: {
385: path = [ [ openPanel filenames ] objectAtIndex:0 ];
386: }
387:
1.1 root 388: if (path != nil)
389: {
390: // Make a non-const C string out of it
1.1.1.6 root 391: const char* constSzPath = [path cStringUsingEncoding:NSASCIIStringEncoding];
1.1 root 392: size_t cbPath = strlen(constSzPath) + 1;
393: char szPath[cbPath];
1.1.1.6 root 394: strncpy(szPath, constSzPath, cbPath);
1.1.1.3 root 395:
396: Floppy_SetDiskFileName(0, szPath, NULL);
397: Floppy_InsertDiskIntoDrive(0);
1.1 root 398: }
399: }
400:
401: - (IBAction)insertDiskB:(id)sender
402: {
1.1.1.6 root 403: NSString *path = nil;
404: NSOpenPanel *openPanel = [ NSOpenPanel openPanel ];
405:
406: if ( [ openPanel runModalForDirectory:nil
407: file:@"SavedGame" types:nil ] )
408: {
409: path = [ [ openPanel filenames ] objectAtIndex:0 ];
410: }
411:
1.1 root 412: if (path != nil)
413: {
414: // Make a non-const C string out of it
1.1.1.6 root 415: const char* constSzPath = [path cStringUsingEncoding:NSASCIIStringEncoding];
1.1 root 416: size_t cbPath = strlen(constSzPath) + 1;
417: char szPath[cbPath];
418: strncpy(szPath, constSzPath, cbPath);
1.1.1.6 root 419:
1.1.1.3 root 420: Floppy_SetDiskFileName(1, szPath, NULL);
421: Floppy_InsertDiskIntoDrive(1);
1.1 root 422: }
423: }
424:
425: /*-----------------------------------------------------------------------*/
426: /*
1.1.1.6 root 427: Controls the enabled state of the menu items
428: */
1.1 root 429: - (BOOL)validateMenuItem:(NSMenuItem*)item
430: {
431: if (item == beginCaptureAnim)
432: {
1.1.1.6 root 433: return !Avi_AreWeRecording();
1.1 root 434: }
435: if (item == endCaptureAnim)
436: {
1.1.1.6 root 437: return Avi_AreWeRecording();
1.1 root 438: }
439: if (item == beginCaptureSound)
440: {
441: return !Sound_AreWeRecording();
442: }
443: if (item == endCaptureSound)
444: {
445: return Sound_AreWeRecording();
446: }
447:
448: return YES;
449: }
450:
1.1.1.7 root 451: - (NSString*)displayFileSelection:(const char*)pathInParams preferredFileName:(NSString*)preferredFileName allowedExtensions:(NSArray*)allowedExtensions
1.1 root 452: {
1.1.1.7 root 453:
1.1 root 454: // Get the path from the user settings
1.1.1.7 root 455: NSString *preferredPath = [[NSString stringWithCString:(pathInParams) encoding:NSASCIIStringEncoding] stringByAbbreviatingWithTildeInPath];
456:
1.1 root 457: // Determine the directory and filename
458: NSString *directoryToOpen;
459: NSString *fileToPreselect;
460: if ((preferredPath != nil) && ([preferredPath length] > 0))
461: {
462: // There is existing path: we will open its directory with its file pre-selected.
463: directoryToOpen = [preferredPath stringByDeletingLastPathComponent];
464: fileToPreselect = [preferredPath lastPathComponent];
465: }
466: else
467: {
468: // Currently no path: we will open the user's directory with no file selected.
469: directoryToOpen = [@"~" stringByExpandingTildeInPath];
1.1.1.7 root 470: fileToPreselect = preferredFileName;
1.1 root 471: }
1.1.1.7 root 472:
1.1 root 473: // Create and configure a SavePanel for choosing what file to write
474: NSSavePanel *savePanel = [NSSavePanel savePanel];
1.1.1.7 root 475: [savePanel setAllowedFileTypes:allowedExtensions];
1.1 root 476: [savePanel setExtensionHidden:NO];
1.1.1.7 root 477: NSString* extensionList = [allowedExtensions componentsJoinedByString:@" or a ."];
1.1 root 478:
1.1.1.7 root 479: [savePanel setMessage:[NSString stringWithFormat:@"Please specify a .%@ file",extensionList]]; // TODO: Move to localizable resources
1.1 root 480: // Run the SavePanel, then check if the user clicked OK and selected at least one file
1.1.1.6 root 481: if (NSFileHandlingPanelOKButton == [savePanel runModalForDirectory:directoryToOpen file:fileToPreselect] )
1.1.1.7 root 482: return [[savePanel URL] path];
483: return nil;
484: }
485:
486: - (IBAction)captureScreen:(id)sender
487: {
488: GuiOsx_Pause();
489: ScreenSnapShot_SaveScreen();
490: GuiOsx_Resume();
491: }
492:
493: - (IBAction)captureAnimation:(id)sender
494: {
495: GuiOsx_Pause();
496: if(!Avi_AreWeRecording()) {
497: NSString* path = [self displayFileSelection:ConfigureParams.Video.AviRecordFile preferredFileName:@"hatari.avi"
498: allowedExtensions:[NSArray arrayWithObjects:@"avi", nil]];
1.1 root 499:
1.1.1.7 root 500: if(path) {
501: GuiOsx_ExportPathString(path, ConfigureParams.Video.AviRecordFile, sizeof(ConfigureParams.Video.AviRecordFile));
502: Avi_StartRecording ( ConfigureParams.Video.AviRecordFile , ConfigureParams.Screen.bCrop ,
503: ConfigureParams.Video.AviRecordFps == 0 ?
504: ClocksTimings_GetVBLPerSec ( ConfigureParams.System.nMachineType , nScreenRefreshRate ) :
505: (Uint32)ConfigureParams.Video.AviRecordFps << CLOCKS_TIMINGS_SHIFT_VBL ,
506: 1 << CLOCKS_TIMINGS_SHIFT_VBL ,
507: ConfigureParams.Video.AviRecordVcodec );
508: }
1.1.1.6 root 509:
1.1.1.7 root 510: } else {
511: Avi_StopRecording();
1.1.1.6 root 512: }
1.1.1.7 root 513: GuiOsx_Resume();
514: }
1.1 root 515:
1.1.1.7 root 516: - (IBAction)endCaptureAnimation:(id)sender
517: {
518: //?
519: }
520:
521: - (IBAction)captureSound:(id)sender
522: {
523: GuiOsx_Pause();
524: NSString* path = [self displayFileSelection:ConfigureParams.Sound.szYMCaptureFileName preferredFileName:@"hatari.wav"
525: allowedExtensions:[NSArray arrayWithObjects:@"ym", @"wav", nil]];
526: if(path) {
527: GuiOsx_ExportPathString(path, ConfigureParams.Sound.szYMCaptureFileName, sizeof(ConfigureParams.Sound.szYMCaptureFileName));
528: Sound_BeginRecording(ConfigureParams.Sound.szYMCaptureFileName);
529: }
1.1.1.5 root 530: GuiOsx_Resume();
1.1 root 531: }
532:
533: - (IBAction)endCaptureSound:(id)sender
534: {
1.1.1.5 root 535: GuiOsx_Pause();
1.1 root 536: Sound_EndRecording();
1.1.1.5 root 537: GuiOsx_Resume();
1.1 root 538: }
539:
540: - (IBAction)saveMemorySnap:(id)sender
541: {
1.1.1.5 root 542: GuiOsx_Pause();
1.1 root 543:
1.1.1.7 root 544: NSString* path = [self displayFileSelection:ConfigureParams.Memory.szMemoryCaptureFileName preferredFileName:@"hatari.sav"
545: allowedExtensions:[NSArray arrayWithObjects:@"sav",nil]];
546: if(path) {
1.1 root 547: GuiOsx_ExportPathString(path, ConfigureParams.Memory.szMemoryCaptureFileName, sizeof(ConfigureParams.Memory.szMemoryCaptureFileName));
1.1.1.2 root 548: MemorySnapShot_Capture(ConfigureParams.Memory.szMemoryCaptureFileName, TRUE);
1.1.1.6 root 549: }
1.1.1.7 root 550:
1.1.1.5 root 551: GuiOsx_Resume();
1.1 root 552: }
553:
554: - (IBAction)restoreMemorySnap:(id)sender
555: {
1.1.1.5 root 556: GuiOsx_Pause();
1.1 root 557:
558: // Create and configure an OpenPanel
1.1.1.6 root 559: NSOpenPanel *openPanel = [NSOpenPanel openPanel];
1.1 root 560:
561: // Get the path from the user settings
1.1.1.6 root 562: NSString *oldPath = [NSString stringWithCString:(ConfigureParams.Memory.szMemoryCaptureFileName) encoding:NSASCIIStringEncoding];
1.1 root 563:
564: // Determine the directory and filename
565: NSString *directoryToOpen;
566: NSString *fileToPreselect;
567: if ((oldPath != nil) && ([oldPath length] > 0))
568: {
569: // There is existing path: we will open its directory with its file pre-selected.
570: directoryToOpen = [oldPath stringByDeletingLastPathComponent];
571: fileToPreselect = [oldPath lastPathComponent];
572: }
573: else
574: {
575: // Currently no path: we will open the user's directory with no file selected.
576: directoryToOpen = [@"~" stringByExpandingTildeInPath];
577: fileToPreselect = nil;
578: }
1.1.1.6 root 579:
1.1 root 580: // Run the OpenPanel, then check if the user clicked OK and selected at least one file
1.1.1.6 root 581: if ( (NSOKButton == [openPanel runModalForDirectory:directoryToOpen file:fileToPreselect types:nil] )
1.1 root 582: && ([[openPanel filenames] count] > 0) )
583: {
584: // Get the path to the selected file
585: NSString *path = [[openPanel filenames] objectAtIndex:0];
586:
587: // Perform the memory snapshot load
1.1.1.6 root 588: MemorySnapShot_Restore([path cStringUsingEncoding:NSASCIIStringEncoding], TRUE);
589: }
590:
1.1.1.5 root 591: GuiOsx_Resume();
1.1 root 592: }
593:
594: - (IBAction)doFullScreen:(id)sender
595: {
596: // 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.
597: // Therefore we simulate the fullscreen key press instead
598:
599: SDL_KeyboardEvent event;
1.1.1.6 root 600: event.type = SDL_KEYDOWN;
601: event.which = 0;
602: event.state = SDL_PRESSED;
603: event.keysym.sym = SDLK_F11;
604: SDL_PushEvent((SDL_Event*)&event); // Send the F11 key press
605: event.type = SDL_KEYUP;
606: event.state = SDL_RELEASED;
607: SDL_PushEvent((SDL_Event*)&event); // Send the F11 key release
1.1 root 608: }
609:
1.1.1.9 ! root 610:
1.1 root 611: - (IBAction)help:(id)sender
612: {
1.1.1.8 root 613: [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://hatari.tuxfamily.org/docs.html"]];
1.1 root 614: }
615:
616:
1.1.1.9 ! root 617: - (IBAction)openConfig:(id)sender
! 618: {
! 619: BOOL applyChanges = true;
! 620: NSString *ConfigFile = [NSString stringWithCString:(sConfigFileName) encoding:NSASCIIStringEncoding];
! 621: NSOpenPanel *openPanel = [ NSOpenPanel openPanel ];
! 622:
! 623: CNF_PARAMS CurrentParams;
! 624:
! 625:
! 626: // Backup of configuration settings to CurrentParams (which we will only
! 627: // commit back to the configuration settings if choosing user confirm)
! 628: CurrentParams = ConfigureParams;
! 629:
! 630: GuiOsx_Pause();
! 631:
! 632: if ( [ openPanel runModalForDirectory:nil file:ConfigFile types:nil ] )
! 633: {
! 634: ConfigFile = [ [ openPanel filenames ] objectAtIndex:0 ];
! 635: }
! 636: else
! 637: {
! 638: ConfigFile = nil;
! 639: }
! 640:
! 641: //[openPanel release];
! 642:
! 643: if (ConfigFile != nil)
! 644: {
! 645: // Make a non-const C string out of it
! 646: const char* constSzPath = [ConfigFile cStringUsingEncoding:NSASCIIStringEncoding];
! 647: size_t cbPath = strlen(constSzPath) + 1;
! 648: char szPath[cbPath];
! 649: strncpy(szPath, constSzPath, cbPath);
! 650:
! 651: // Load the config into ConfigureParams
! 652: Configuration_Load(szPath);
! 653: strcpy(sConfigFileName,szPath);
! 654: // Refresh all the controls to match ConfigureParams
! 655:
! 656: if (Change_DoNeedReset(&CurrentParams, &ConfigureParams))
! 657: {
! 658: applyChanges = ( 0 == NSRunAlertPanel (
! 659: NSLocalizedStringFromTable(@"Reset the emulator",@"Localizable",@"comment"),
! 660: NSLocalizedStringFromTable(@"Must be reset",@"Localizable",@"comment"),
! 661: NSLocalizedStringFromTable(@"Don't reset",@"Localizable",@"comment"),
! 662: NSLocalizedStringFromTable(@"Reset",@"Localizable",@"comment"), nil) );
! 663: }
! 664:
! 665: // Commit the new configuration
! 666: if (applyChanges)
! 667: {
! 668: Change_CopyChangedParamsToConfiguration(&CurrentParams, &ConfigureParams, false);
! 669: }
! 670: else
! 671: {
! 672: ConfigureParams = CurrentParams;
! 673: }
! 674:
! 675:
! 676: }
! 677:
! 678: GuiOsx_Resume();
! 679: //[ConfigFile release];
1.1 root 680: }
681:
1.1.1.9 ! root 682:
1.1.1.6 root 683: - (IBAction)saveConfig:(id)sender {
1.1 root 684: }
685:
686: @end
687:
688:
689: @implementation NSString (ReplaceSubString)
690:
691: - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
692: {
693: unsigned int bufferSize;
694: unsigned int selfLen = [self length];
695: unsigned int aStringLen = [aString length];
696: unichar *buffer;
697: NSRange localRange;
698: NSString *result;
699:
700: bufferSize = selfLen + aStringLen - aRange.length;
1.1.1.6 root 701: buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar));
1.1 root 702:
703: /* Get first part into buffer */
704: localRange.location = 0;
705: localRange.length = aRange.location;
706: [self getCharacters:buffer range:localRange];
707:
708: /* Get middle part into buffer */
709: localRange.location = 0;
710: localRange.length = aStringLen;
711: [aString getCharacters:(buffer+aRange.location) range:localRange];
712:
713: /* Get last part into buffer */
714: localRange.location = aRange.location + aRange.length;
715: localRange.length = selfLen - localRange.location;
716: [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
717:
718: /* Build output string */
719: result = [NSString stringWithCharacters:buffer length:bufferSize];
720:
721: NSDeallocateMemoryPages(buffer, bufferSize);
722:
723: return result;
724: }
725:
726: @end
727:
728:
729:
730: #ifdef main
731: # undef main
732: #endif
733:
734:
735: /* Main entry point to executable - should *not* be SDL_main! */
736: int main (int argc, char **argv)
737: {
738: /* Copy the arguments into a global variable */
739: /* This is passed if we are launched by double-clicking */
740: if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
1.1.1.6 root 741: gArgv = (char **) SDL_malloc(sizeof (char *) * 2);
742: gArgv[0] = argv[0];
743: gArgv[1] = NULL;
1.1 root 744: gArgc = 1;
1.1.1.6 root 745: gFinderLaunch = YES;
1.1 root 746: } else {
1.1.1.6 root 747: int i;
1.1 root 748: gArgc = argc;
1.1.1.6 root 749: gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1));
750: for (i = 0; i <= argc; i++)
751: gArgv[i] = argv[i];
752: gFinderLaunch = NO;
1.1 root 753: }
754:
1.1.1.6 root 755: #if SDL_USE_NIB_FILE
1.1.1.7 root 756: NSApplicationMain (argc, (const char**)argv);
1.1.1.6 root 757: #else
758: CustomApplicationMain (argc, argv);
759: #endif
1.1 root 760: return 0;
761: }
1.1.1.6 root 762:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.