source: abuse/trunk/osx/SDLMain.m @ 597

Last change on this file since 597 was 97, checked in by Sam Hocevar, 12 years ago
  • Updated the Mac OS X port, thanks to Julian Mayer.
File size: 7.5 KB
Line 
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>
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
17static int    gArgc;
18static char  **gArgv;
19static 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
102void 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 */
128void 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/* Replacement for NSApplicationMain */
156void CustomApplicationMain (argc, argv)
157{
158    NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];
159    SDLMain                             *sdlMain;
160
161    /* Ensure the application object is initialised */
162    [SDLApplication sharedApplication];
163   
164    /* Set up the menubar */
165    [NSApp setMainMenu:[[NSMenu alloc] init]];
166    setupAppleMenu();
167    setupWindowMenu();
168   
169    /* Create SDLMain and make it the app delegate */
170    sdlMain = [[SDLMain alloc] init];
171    [NSApp setDelegate:sdlMain];
172   
173    /* Start the main event loop */
174    [NSApp run];
175   
176    [sdlMain release];
177    [pool release];
178}
179
180#endif
181
182/* Called when the internal event loop has just started running */
183- (void) applicationDidFinishLaunching: (NSNotification *) note
184{
185    int status;
186
187    /* Set the working directory to the .app's parent directory */
188    [self setupWorkingDirectory:gFinderLaunch];
189
190#if SDL_USE_NIB_FILE
191    /* Set the main menu to contain the real app name instead of "SDL App" */
192    [self fixMenu:[NSApp mainMenu] withAppName:[[NSProcessInfo processInfo] processName]];
193#endif
194
195    /* Hand off to main application code */
196    status = SDL_main (gArgc, gArgv);
197
198    /* We're done, thank you for playing */
199    exit(status);
200}
201@end
202
203
204@implementation NSString (ReplaceSubString)
205
206- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
207{
208    unsigned int bufferSize;
209    unsigned int selfLen = [self length];
210    unsigned int aStringLen = [aString length];
211    unichar *buffer;
212    NSRange localRange;
213    NSString *result;
214
215    bufferSize = selfLen + aStringLen - aRange.length;
216    buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
217   
218    /* Get first part into buffer */
219    localRange.location = 0;
220    localRange.length = aRange.location;
221    [self getCharacters:buffer range:localRange];
222   
223    /* Get middle part into buffer */
224    localRange.location = 0;
225    localRange.length = aStringLen;
226    [aString getCharacters:(buffer+aRange.location) range:localRange];
227     
228    /* Get last part into buffer */
229    localRange.location = aRange.location + aRange.length;
230    localRange.length = selfLen - localRange.location;
231    [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
232   
233    /* Build output string */
234    result = [NSString stringWithCharacters:buffer length:bufferSize];
235   
236    NSDeallocateMemoryPages(buffer, bufferSize);
237   
238    return result;
239}
240
241@end
242
243
244
245#ifdef main
246#  undef main
247#endif
248
249
250/* Main entry point to executable - should *not* be SDL_main! */
251int main (int argc, char **argv)
252{
253
254    /* Copy the arguments into a global variable */
255    int i;
256   
257    /* This is passed if we are launched by double-clicking */
258    if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
259        gArgc = 1;
260        gFinderLaunch = YES;
261    } else {
262        gArgc = argc;
263        gFinderLaunch = NO;
264    }
265    gArgv = (char**) malloc (sizeof(*gArgv) * (gArgc+1));
266    assert (gArgv != NULL);
267    for (i = 0; i < gArgc; i++)
268        gArgv[i] = argv[i];
269    gArgv[i] = NULL;
270
271#if SDL_USE_NIB_FILE
272    [SDLApplication poseAsClass:[NSApplication class]];
273    NSApplicationMain (argc, argv);
274#else
275    CustomApplicationMain (argc, argv);
276#endif
277    return 0;
278}
Note: See TracBrowser for help on using the repository browser.