~ubuntu-branches/ubuntu/utopic/hedgewars/utopic

« back to all changes in this revision

Viewing changes to hedgewars/sdlmain/SDLMain.m

  • Committer: Package Import Robot
  • Author(s): Gianfranco Costamagna
  • Date: 2014-01-02 12:37:23 UTC
  • mfrom: (19.1.5 sid)
  • Revision ID: package-import@ubuntu.com-20140102123723-6pdhmyj8tb5y8xbg
Tags: 0.9.20.3-1
New upstream minor release, suitable for unstable

Show diffs side-by-side

added added

removed removed

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