1 /* SDLMain.m - main entry point for our Cocoa-ized SDL app
2 Initial Version: Darrell Walisser <dwaliss1@purdue.edu>
3 Non-NIB-Code & other changes: Max Horn <max@quendi.de>
5 Feel free to customize this file to suit your needs
10 #import <sys/param.h> /* for MAXPATHLEN */
13 /* Use this flag to determine whether we use SDLMain.nib or not */
14 #define SDL_USE_NIB_FILE 0
19 static BOOL gFinderLaunch;
22 /* A helper category for NSString */
23 @interface NSString (ReplaceSubString)
24 - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString;
27 /* An internal Apple class used to setup Apple menus */
28 @interface NSAppleMenuController:NSObject {}
29 - (void)controlMenu:(NSMenu *)aMenu;
33 @interface SDLApplication : NSApplication
36 @implementation SDLApplication
37 /* Invoked from the Quit menu item */
38 - (void)terminate:(id)sender
40 /* Post a SDL_QUIT event */
42 event.type = SDL_QUIT;
43 SDL_PushEvent(&event);
48 /* The main class of the application, the application's delegate */
49 @implementation SDLMain
51 /* Set the working directory to the .app's parent directory */
52 - (void) setupWorkingDirectory:(BOOL)shouldChdir
54 char parentdir[MAXPATHLEN];
57 strncpy ( parentdir, gArgv[0], sizeof(parentdir) );
58 c = (char*) parentdir;
60 while (*c != '\0') /* go to end */
63 while (*c != '/') /* back up to parent */
66 *c++ = '\0'; /* cut off last part (binary name) */
70 assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */
71 assert ( chdir ("../../../") == 0 ); /* chdir to the .app's parent */
77 /* Fix menu to contain the real app name instead of "SDL App" */
78 - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName
81 NSEnumerator *enumerator;
84 aRange = [[aMenu title] rangeOfString:@"SDL App"];
85 if (aRange.length != 0)
86 [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]];
88 enumerator = [[aMenu itemArray] objectEnumerator];
89 while ((menuItem = [enumerator nextObject]))
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];
102 void setupAppleMenu(void)
104 /* warning: this code is very odd */
105 NSAppleMenuController *appleMenuController;
107 NSMenuItem *appleMenuItem;
109 appleMenuController = [[NSAppleMenuController alloc] init];
110 appleMenu = [[NSMenu alloc] initWithTitle:@""];
111 appleMenuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
113 [appleMenuItem setSubmenu:appleMenu];
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
120 [[NSApp mainMenu] addItem:appleMenuItem];
121 [appleMenuController controlMenu:appleMenu];
122 [[NSApp mainMenu] removeItem:appleMenuItem];
124 [appleMenuItem release];
127 /* Create a window menu */
128 void setupWindowMenu(void)
131 NSMenuItem *windowMenuItem;
132 NSMenuItem *menuItem;
135 windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
137 /* "Minimize" item */
138 menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
139 [windowMenu addItem:menuItem];
142 /* Put menu into the menubar */
143 windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
144 [windowMenuItem setSubmenu:windowMenu];
145 [[NSApp mainMenu] addItem:windowMenuItem];
147 /* Tell the application object that this is now the window menu */
148 [NSApp setWindowsMenu:windowMenu];
150 /* Finally give up our references to the objects */
151 [windowMenu release];
152 [windowMenuItem release];
155 /* Replacement for NSApplicationMain */
156 void CustomApplicationMain (argc, argv)
158 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
161 /* Ensure the application object is initialised */
162 [SDLApplication sharedApplication];
164 /* Set up the menubar */
165 [NSApp setMainMenu:[[NSMenu alloc] init]];
167 /* TODO: Disabled because breaks on tiger */
168 /* setupWindowMenu(); */
170 /* Create SDLMain and make it the app delegate */
171 sdlMain = [[SDLMain alloc] init];
172 [NSApp setDelegate:sdlMain];
174 /* Start the main event loop */
183 /* Called when the internal event loop has just started running */
184 - (void) applicationDidFinishLaunching: (NSNotification *) note
188 /* Set the working directory to the .app's parent directory */
189 [self setupWorkingDirectory:gFinderLaunch];
192 /* Set the main menu to contain the real app name instead of "SDL App" */
193 [self fixMenu:[NSApp mainMenu] withAppName:[[NSProcessInfo processInfo] processName]];
196 /* Hand off to main application code */
197 status = SDL_main (gArgc, gArgv);
199 /* We're done, thank you for playing */
205 @implementation NSString (ReplaceSubString)
207 - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
209 unsigned int bufferSize;
210 unsigned int selfLen = [self length];
211 unsigned int aStringLen = [aString length];
216 bufferSize = selfLen + aStringLen - aRange.length;
217 buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
219 /* Get first part into buffer */
220 localRange.location = 0;
221 localRange.length = aRange.location;
222 [self getCharacters:buffer range:localRange];
224 /* Get middle part into buffer */
225 localRange.location = 0;
226 localRange.length = aStringLen;
227 [aString getCharacters:(buffer+aRange.location) range:localRange];
229 /* Get last part into buffer */
230 localRange.location = aRange.location + aRange.length;
231 localRange.length = selfLen - localRange.location;
232 [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
234 /* Build output string */
235 result = [NSString stringWithCharacters:buffer length:bufferSize];
237 NSDeallocateMemoryPages(buffer, bufferSize);
251 /* Main entry point to executable - should *not* be SDL_main! */
252 int main (int argc, char **argv)
255 /* Copy the arguments into a global variable */
258 /* This is passed if we are launched by double-clicking */
259 if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
266 gArgv = (char**) malloc (sizeof(*gArgv) * (gArgc+1));
267 assert (gArgv != NULL);
268 for (i = 0; i < gArgc; i++)
273 [SDLApplication poseAsClass:[NSApplication class]];
274 NSApplicationMain (argc, argv);
276 CustomApplicationMain (argc, argv);