|
|
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: #import "SDL.h"
9: #import "SDLMain.h"
10: #import <sys/param.h> /* for MAXPATHLEN */
11: #import <unistd.h>
12:
13: /* Use this flag to determine whether we use SDLMain.nib or not */
14: #define SDL_USE_NIB_FILE 0
15:
16:
17: static int gArgc;
18: static char **gArgv;
19: static BOOL gFinderLaunch;
20:
21: #if SDL_USE_NIB_FILE
22: /* A helper category for NSString */
23: @interface NSString (ReplaceSubString)
24: - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString;
25: @end
26: #else
27: /* An internal Apple class used to setup Apple menus */
28: @interface NSAppleMenuController:NSObject {}
29: - (void)controlMenu:(NSMenu *)aMenu;
30: @end
31: #endif
32:
33: @interface SDLApplication : NSApplication
34: @end
35:
36: @implementation SDLApplication
37: /* Invoked from the Quit menu item */
38: - (void)terminate:(id)sender
39: {
40: /* Post a SDL_QUIT event */
41: SDL_Event event;
42: event.type = SDL_QUIT;
43: SDL_PushEvent(&event);
44: }
45: @end
46:
47:
48: /* The main class of the application, the application's delegate */
49: @implementation SDLMain
50:
51: /* Set the working directory to the .app's parent directory */
52: - (void) setupWorkingDirectory:(BOOL)shouldChdir
53: {
54: char parentdir[MAXPATHLEN];
55: char *c;
56:
57: strncpy ( parentdir, gArgv[0], sizeof(parentdir) );
58: c = (char*) parentdir;
59:
60: while (*c != '\0') /* go to end */
61: c++;
62:
63: while (*c != '/') /* back up to parent */
64: c--;
65:
66: *c++ = '\0'; /* cut off last part (binary name) */
67:
68: if (shouldChdir)
69: {
70: assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */
71: assert ( chdir ("../../../") == 0 ); /* chdir to the .app's parent */
72: }
73: }
74:
75: #if SDL_USE_NIB_FILE
76:
77: /* Fix menu to contain the real app name instead of "SDL App" */
78: - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName
79: {
80: NSRange aRange;
81: NSEnumerator *enumerator;
82: NSMenuItem *menuItem;
83:
84: aRange = [[aMenu title] rangeOfString:@"SDL App"];
85: if (aRange.length != 0)
86: [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]];
87:
88: enumerator = [[aMenu itemArray] objectEnumerator];
89: while ((menuItem = [enumerator nextObject]))
90: {
91: aRange = [[menuItem title] rangeOfString:@"SDL App"];
92: if (aRange.length != 0)
93: [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]];
94: if ([menuItem hasSubmenu])
95: [self fixMenu:[menuItem submenu] withAppName:appName];
96: }
97: [ aMenu sizeToFit ];
98: }
99:
100: #else
101:
102: void setupAppleMenu(void)
103: {
104: /* warning: this code is very odd */
105: NSAppleMenuController *appleMenuController;
106: NSMenu *appleMenu;
107: NSMenuItem *appleMenuItem;
108:
109: appleMenuController = [[NSAppleMenuController alloc] init];
110: appleMenu = [[NSMenu alloc] initWithTitle:@""];
111: appleMenuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
112:
113: [appleMenuItem setSubmenu:appleMenu];
114:
115: /* yes, we do need to add it and then remove it --
116: if you don't add it, it doesn't get displayed
117: if you don't remove it, you have an extra, titleless item in the menubar
118: when you remove it, it appears to stick around
119: very, very odd */
120: [[NSApp mainMenu] addItem:appleMenuItem];
121: [appleMenuController controlMenu:appleMenu];
122: [[NSApp mainMenu] removeItem:appleMenuItem];
123: [appleMenu release];
124: [appleMenuItem release];
125: }
126:
127: /* Create a window menu */
128: void setupWindowMenu(void)
129: {
130: NSMenu *windowMenu;
131: NSMenuItem *windowMenuItem;
132: NSMenuItem *menuItem;
133:
134:
135: windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
136:
137: /* "Minimize" item */
138: menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
139: [windowMenu addItem:menuItem];
140: [menuItem release];
141:
142: /* Put menu into the menubar */
143: windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
144: [windowMenuItem setSubmenu:windowMenu];
145: [[NSApp mainMenu] addItem:windowMenuItem];
146:
147: /* Tell the application object that this is now the window menu */
148: [NSApp setWindowsMenu:windowMenu];
149:
150: /* Finally give up our references to the objects */
151: [windowMenu release];
152: [windowMenuItem release];
153: }
154:
155: extern char **environ;
156:
157: /* Replacement for NSApplicationMain */
158: void CustomApplicationMain (argc, argv)
159: {
160: NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
161: SDLMain *sdlMain;
162:
163: /* Ensure the application object is initialised */
164: [SDLApplication sharedApplication];
165:
166: /* Set up the menubar */
167: [NSApp setMainMenu:[[NSMenu alloc] init]];
168: setupAppleMenu();
169: setupWindowMenu();
170:
171: /* Create SDLMain and make it the app delegate */
172: sdlMain = [[SDLMain alloc] init];
173: [NSApp setDelegate:sdlMain];
174:
175: /* Start the main event loop */
176: [NSApp run];
177:
178: [sdlMain release];
179: [pool release];
180: }
181:
182: #endif
183:
184: /* Called when the internal event loop has just started running */
185: - (void) applicationDidFinishLaunching: (NSNotification *) note
186: {
187: int status;
188:
189: /* Set the working directory to the .app's parent directory */
190: [self setupWorkingDirectory:gFinderLaunch];
191:
192: #if SDL_USE_NIB_FILE
193: /* Set the main menu to contain the real app name instead of "SDL App" */
194: [self fixMenu:[NSApp mainMenu] withAppName:[[NSProcessInfo processInfo] processName]];
195: #endif
196:
197: /* Hand off to main application code */
198: status = SDL_main_env (gArgc, gArgv, environ);
199:
200: /* We're done, thank you for playing */
201: exit(status);
202: }
203: @end
204:
205:
206: @implementation NSString (ReplaceSubString)
207:
208: - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
209: {
210: unsigned int bufferSize;
211: unsigned int selfLen = [self length];
212: unsigned int aStringLen = [aString length];
213: unichar *buffer;
214: NSRange localRange;
215: NSString *result;
216:
217: bufferSize = selfLen + aStringLen - aRange.length;
218: buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
219:
220: /* Get first part into buffer */
221: localRange.location = 0;
222: localRange.length = aRange.location;
223: [self getCharacters:buffer range:localRange];
224:
225: /* Get middle part into buffer */
226: localRange.location = 0;
227: localRange.length = aStringLen;
228: [aString getCharacters:(buffer+aRange.location) range:localRange];
229:
230: /* Get last part into buffer */
231: localRange.location = aRange.location + aRange.length;
232: localRange.length = selfLen - localRange.location;
233: [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
234:
235: /* Build output string */
236: result = [NSString stringWithCharacters:buffer length:bufferSize];
237:
238: NSDeallocateMemoryPages(buffer, bufferSize);
239:
240: return result;
241: }
242:
243: @end
244:
245:
246:
247: #ifdef main
248: # undef main
249: #endif
250:
251:
252: /* Main entry point to executable - should *not* be SDL_main! */
253: int main (int argc, char **argv)
254: {
255:
256: /* Copy the arguments into a global variable */
257: int i;
258:
259: /* This is passed if we are launched by double-clicking */
260: if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
261: gArgc = 1;
262: gFinderLaunch = YES;
263: } else {
264: gArgc = argc;
265: gFinderLaunch = NO;
266: }
267: gArgv = (char**) malloc (sizeof(*gArgv) * (gArgc+1));
268: assert (gArgv != NULL);
269: for (i = 0; i < gArgc; i++)
270: gArgv[i] = argv[i];
271: gArgv[i] = NULL;
272:
273: #if SDL_USE_NIB_FILE
274: [SDLApplication poseAsClass:[NSApplication class]];
275: NSApplicationMain (argc, argv);
276: #else
277: CustomApplicationMain (argc, argv);
278: #endif
279: return 0;
280: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.