root / TUIO_CPP / SDLMain.m @ 91

View | Annotate | Download (9.3 KB)

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
6
#import <SDL.h>
7
#import <Cocoa/Cocoa.h>
8
#import <sys/param.h>
9
#import <unistd.h>
10
11
@interface SDLMain : NSObject
12
@end
13
14
/* For some reaon, Apple removed setAppleMenu from the headers in 10.4,
15
 but the method still is there and works. To avoid warnings, we declare
16
 it ourselves here. */
17
@interface NSApplication(SDL_Missing_Methods)
18
- (void)setAppleMenu:(NSMenu *)menu;
19
@end
20
21
/* Portions of CPS.h */
22
typedef struct CPSProcessSerNum
23
{
24
	UInt32		lo;
25
	UInt32		hi;
26
} CPSProcessSerNum;
27
28
extern OSErr	CPSGetCurrentProcess( CPSProcessSerNum *psn);
29
extern OSErr 	CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
30
extern OSErr	CPSSetFrontProcess( CPSProcessSerNum *psn);
31
32
static int    gArgc;
33
static char  **gArgv;
34
static BOOL   gFinderLaunch;
35
static BOOL   gCalledAppMainline = FALSE;
36
37
static NSString *getApplicationName(void)
38
{
39
    NSDictionary *dict;
40
    NSString *appName = 0;
41
42
    /* Determine the application name */
43
    dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
44
    if (dict)
45
        appName = [dict objectForKey: @"CFBundleName"];
46
    
47
    if (![appName length])
48
        appName = [[NSProcessInfo processInfo] processName];
49
50
    return appName;
51
}
52
53
@interface SDLApplication : NSApplication
54
@end
55
56
@implementation SDLApplication
57
/* Invoked from the Quit menu item */
58
- (void)terminate:(id)sender
59
{
60
    /* Post a SDL_QUIT event */
61
    SDL_Event event;
62
    event.type = SDL_QUIT;
63
    SDL_PushEvent(&event);
64
}
65
@end
66
67
/* The main class of the application, the application's delegate */
68
@implementation SDLMain
69
70
/* Set the working directory to the .app's parent directory */
71
- (void) setupWorkingDirectory:(BOOL)shouldChdir
72
{
73
    if (shouldChdir)
74
    {
75
        char parentdir[MAXPATHLEN];
76
		CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
77
		CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url);
78
		if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) {
79
	        assert ( chdir (parentdir) == 0 );   /* chdir to the binary app's parent */
80
		}
81
		CFRelease(url);
82
		CFRelease(url2);
83
	}
84
85
}
86
87
static void setApplicationMenu(void)
88
{
89
    /* warning: this code is very odd */
90
    NSMenu *appleMenu;
91
    NSMenuItem *menuItem;
92
    NSString *title;
93
    NSString *appName;
94
    
95
    appName = getApplicationName();
96
    appleMenu = [[NSMenu alloc] initWithTitle:@""];
97
    
98
    /* Add menu items */
99
    title = [@"About " stringByAppendingString:appName];
100
    [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
101
102
    [appleMenu addItem:[NSMenuItem separatorItem]];
103
104
    title = [@"Hide " stringByAppendingString:appName];
105
    [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
106
107
    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
108
    [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
109
110
    [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
111
112
    [appleMenu addItem:[NSMenuItem separatorItem]];
113
114
    title = [@"Quit " stringByAppendingString:appName];
115
    [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
116
117
    
118
    /* Put menu into the menubar */
119
    menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
120
    [menuItem setSubmenu:appleMenu];
121
    [[NSApp mainMenu] addItem:menuItem];
122
123
    /* Tell the application object that this is now the application menu */
124
    [NSApp setAppleMenu:appleMenu];
125
126
    /* Finally give up our references to the objects */
127
    [appleMenu release];
128
    [menuItem release];
129
}
130
131
/* Create a window menu */
132
static void setupWindowMenu(void)
133
{
134
    NSMenu      *windowMenu;
135
    NSMenuItem  *windowMenuItem;
136
    NSMenuItem  *menuItem;
137
138
    windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
139
    
140
    /* "Minimize" item */
141
    menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
142
    [windowMenu addItem:menuItem];
143
    [menuItem release];
144
    
145
    /* Put menu into the menubar */
146
    windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
147
    [windowMenuItem setSubmenu:windowMenu];
148
    [[NSApp mainMenu] addItem:windowMenuItem];
149
    
150
    /* Tell the application object that this is now the window menu */
151
    [NSApp setWindowsMenu:windowMenu];
152
153
    /* Finally give up our references to the objects */
154
    [windowMenu release];
155
    [windowMenuItem release];
156
}
157
158
/* Replacement for NSApplicationMain */
159
static void CustomApplicationMain (int argc, char **argv)
160
{
161
    NSAutoreleasePool	*pool = [[NSAutoreleasePool alloc] init];
162
    SDLMain				*sdlMain;
163
164
    /* Ensure the application object is initialised */
165
    [SDLApplication sharedApplication];
166
    
167
    {
168
        CPSProcessSerNum PSN;
169
        /* Tell the dock about us */
170
        if (!CPSGetCurrentProcess(&PSN))
171
            if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
172
                if (!CPSSetFrontProcess(&PSN))
173
                    [SDLApplication sharedApplication];
174
    }
175
176
    /* Set up the menubar */
177
    [NSApp setMainMenu:[[NSMenu alloc] init]];
178
    setApplicationMenu();
179
    setupWindowMenu();
180
181
    /* Create SDLMain and make it the app delegate */
182
    sdlMain = [[SDLMain alloc] init];
183
    [NSApp setDelegate:sdlMain];
184
    
185
    /* Start the main event loop */
186
    [NSApp run];
187
    
188
    [sdlMain release];
189
    [pool release];
190
}
191
192
/*
193
 * Catch document open requests...this lets us notice files when the app
194
 *  was launched by double-clicking a document, or when a document was
195
 *  dragged/dropped on the app's icon. You need to have a
196
 *  CFBundleDocumentsType section in your Info.plist to get this message,
197
 *  apparently.
198
 *
199
 * Files are added to gArgv, so to the app, they'll look like command line
200
 *  arguments. Previously, apps launched from the finder had nothing but
201
 *  an argv[0].
202
 *
203
 * This message may be received multiple times to open several docs on launch.
204
 *
205
 * This message is ignored once the app's mainline has been called.
206
 */
207
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
208
{
209
    const char *temparg;
210
    size_t arglen;
211
    char *arg;
212
    char **newargv;
213
214
    if (!gFinderLaunch)  /* MacOS is passing command line args. */
215
        return FALSE;
216
217
    if (gCalledAppMainline)  /* app has started, ignore this document. */
218
        return FALSE;
219
220
    temparg = [filename UTF8String];
221
    arglen = SDL_strlen(temparg) + 1;
222
    arg = (char *) SDL_malloc(arglen);
223
    if (arg == NULL)
224
        return FALSE;
225
226
    newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2));
227
    if (newargv == NULL)
228
    {
229
        SDL_free(arg);
230
        return FALSE;
231
    }
232
    gArgv = newargv;
233
234
    SDL_strlcpy(arg, temparg, arglen);
235
    gArgv[gArgc++] = arg;
236
    gArgv[gArgc] = NULL;
237
    return TRUE;
238
}
239
240
241
/* Called when the internal event loop has just started running */
242
- (void) applicationDidFinishLaunching: (NSNotification *) note
243
{
244
    int status;
245
246
    /* Set the working directory to the .app's parent directory */
247
    [self setupWorkingDirectory:gFinderLaunch];
248
249
    /* Hand off to main application code */
250
    gCalledAppMainline = TRUE;
251
    status = SDL_main (gArgc, gArgv);
252
253
    /* We're done, thank you for playing */
254
    exit(status);
255
}
256
@end
257
258
259
@implementation NSString (ReplaceSubString)
260
261
- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
262
{
263
    unsigned int bufferSize;
264
    unsigned int selfLen = [self length];
265
    unsigned int aStringLen = [aString length];
266
    unichar *buffer;
267
    NSRange localRange;
268
    NSString *result;
269
270
    bufferSize = selfLen + aStringLen - aRange.length;
271
    buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
272
    
273
    /* Get first part into buffer */
274
    localRange.location = 0;
275
    localRange.length = aRange.location;
276
    [self getCharacters:buffer range:localRange];
277
    
278
    /* Get middle part into buffer */
279
    localRange.location = 0;
280
    localRange.length = aStringLen;
281
    [aString getCharacters:(buffer+aRange.location) range:localRange];
282
     
283
    /* Get last part into buffer */
284
    localRange.location = aRange.location + aRange.length;
285
    localRange.length = selfLen - localRange.location;
286
    [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
287
    
288
    /* Build output string */
289
    result = [NSString stringWithCharacters:buffer length:bufferSize];
290
    
291
    NSDeallocateMemoryPages(buffer, bufferSize);
292
    
293
    return result;
294
}
295
296
@end
297
298
#ifdef main
299
#  undef main
300
#endif
301
302
/* Main entry point to executable - should *not* be SDL_main! */
303
int main (int argc, char **argv)
304
{
305
    /* Copy the arguments into a global variable */
306
    /* This is passed if we are launched by double-clicking */
307
    if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
308
        gArgv = (char **) SDL_malloc(sizeof (char *) * 2);
309
        gArgv[0] = argv[0];
310
        gArgv[1] = NULL;
311
        gArgc = 1;
312
        gFinderLaunch = YES;
313
    } else {
314
        int i;
315
        gArgc = argc;
316
        gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1));
317
        for (i = 0; i <= argc; i++)
318
            gArgv[i] = argv[i];
319
        gFinderLaunch = NO;
320
    }
321
322
    CustomApplicationMain (argc, argv);
323
    return 0;
324
}