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