Subversion Repositories Games.Rick Dangerous

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 pmbaty 1
// osx-sdlmain.m -- main entry point for our Cocoaized SDL app
2 pmbaty 2
 
4 pmbaty 3
#import <Cocoa/Cocoa.h>
4
#include "string.h"
2 pmbaty 5
#include "SDL.h"
6
 
7
 
4 pmbaty 8
// global variables used in this module only
9
static int global_argc = 0;
10
static char **global_argv = NULL;
11
static BOOL has_app_started = FALSE;
2 pmbaty 12
 
13
 
4 pmbaty 14
@interface SDLMainAppDelegate : NSObject
15
- (void) applicationDidFinishLaunching: (NSNotification *) notification;
16
- (BOOL) application: (NSApplication *) the_app openFile: (NSString *) filename;
17
@end
2 pmbaty 18
 
4 pmbaty 19
@interface NSApplication (SDL_Missing_Methods)
20
// for some reaon, Apple removed setAppleMenu from the headers in 10.4, but the method still is there and works. To avoid warnings, we declare it ourselves here
21
- (void) setAppleMenu: (NSMenu *) menu;
2 pmbaty 22
@end
23
 
24
@interface NSApplication (SDLApplication)
4 pmbaty 25
- (void) quitMenuCommand: (id) sender;
26
- (void) fullscreenMenuCommand: (id) sender;
27
- (void) visitwebsiteMenuCommand: (id) sender;
2 pmbaty 28
@end
29
 
4 pmbaty 30
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
31
 
2 pmbaty 32
@implementation NSApplication (SDLApplication)
4 pmbaty 33
 
34
- (void) quitMenuCommand: (id) sender
2 pmbaty 35
{
4 pmbaty 36
   // this functin is invoked when the Quit menu item is clicked
2 pmbaty 37
 
4 pmbaty 38
   SDL_Event event;
39
   event.type = SDL_QUIT;
40
   SDL_PushEvent (&event); // post a SDL_QUIT event
2 pmbaty 41
}
42
 
43
 
4 pmbaty 44
- (void) fullscreenMenuCommand: (id) sender
2 pmbaty 45
{
4 pmbaty 46
    // this functin is invoked when the Enter Full Screen menu item is clicked
47
 
48
    SDL_Event event;
2 pmbaty 49
 
4 pmbaty 50
    event.type = SDL_KEYDOWN;
51
    event.key.keysym.sym = SDLK_LALT;
52
    SDL_PushEvent (&event); // post a SDL_KEY event that simulates pressing the left ALT key
53
    event.type = SDL_KEYDOWN;
54
    event.key.keysym.sym = SDLK_RETURN;
55
    SDL_PushEvent (&event); // post a SDL_KEY event that simulates pressing the main ENTER key
56
    event.type = SDL_KEYUP;
57
    event.key.keysym.sym = SDLK_RETURN;
58
    SDL_PushEvent (&event); // post a SDL_KEY event that simulates releasing the main ENTER key
59
    event.type = SDL_KEYUP;
60
    event.key.keysym.sym = SDLK_LALT;
61
    SDL_PushEvent (&event); // post a SDL_KEY event that simulates releasing the left ALT key
2 pmbaty 62
}
63
 
4 pmbaty 64
- (void) visitwebsiteMenuCommand: (id) sender
2 pmbaty 65
{
4 pmbaty 66
   // this functin is invoked when the Visit Website menu item is clicked
2 pmbaty 67
 
4 pmbaty 68
   [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: @"http://www.pmbaty.com/rick/"]]; // visit the website!
69
}
2 pmbaty 70
 
4 pmbaty 71
@end
2 pmbaty 72
 
4 pmbaty 73
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 pmbaty 74
 
4 pmbaty 75
@implementation SDLMainAppDelegate
2 pmbaty 76
 
4 pmbaty 77
- (void) applicationDidFinishLaunching: (NSNotification *) notification
78
{
79
   // this function is called when the internal event loop has just started running
2 pmbaty 80
 
4 pmbaty 81
   int status;
2 pmbaty 82
 
4 pmbaty 83
   has_app_started = TRUE; // remember the app has started (so we can no longer change argc and argv)
84
   status = SDL_main (global_argc, global_argv); // only now that we know Cocoa has finished its business, we can run SDL_main() and pass it our command-line arguments
2 pmbaty 85
 
4 pmbaty 86
   exit (status); // when SDL_main returns, we can tell Cocoa to quit
2 pmbaty 87
}
88
 
4 pmbaty 89
 
90
- (BOOL) application: (NSApplication *) the_app openFile: (NSString *) filename
2 pmbaty 91
{
4 pmbaty 92
    // this function catches document open requests and appends them to global argc and argv arrays, so they look like a command-line argument.
93
    // This lets us notice files when the app was launched by double-clicking a document, or when a document was dragged/dropped on the app's icon.
94
    // You need to have a CFBundleDocumentsType section in your Info.plist to get this message.
95
    // Once the app's main loop has started, this message can no longer be used (since it has already parsed its command-line arguments).
2 pmbaty 96
 
4 pmbaty 97
    char **new_argv;
2 pmbaty 98
 
4 pmbaty 99
    if (has_app_started)
100
        return (FALSE); // if the app has started, then argc and argv can no longer be modified
2 pmbaty 101
 
4 pmbaty 102
    // reallocate the global argv array to hold one parameter more
103
    new_argv = (char **) realloc (global_argv, (global_argc + 2) * sizeof (char *));
104
    if (new_argv == NULL)
105
        return (FALSE); // on realloc() failure, give up
106
    global_argv = new_argv;
107
    global_argc++;
108
 
109
    // now store the filename we're opening as a new command-line argument
110
    global_argv[global_argc - 1] = strdup ([filename UTF8String]);
111
    global_argv[global_argc] = NULL;
112
 
113
    return (TRUE); // message was handled successfully
2 pmbaty 114
}
4 pmbaty 115
@end
2 pmbaty 116
 
4 pmbaty 117
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 pmbaty 118
 
119
 
4 pmbaty 120
#ifdef main
121
#undef main
2 pmbaty 122
#endif
123
 
124
 
4 pmbaty 125
int main (int argc, char **argv)
2 pmbaty 126
{
4 pmbaty 127
   // OS/X program entrypoint
2 pmbaty 128
 
4 pmbaty 129
   SDLMainAppDelegate *sdlmain_delegate;
130
   NSAutoreleasePool *pool;
131
   NSMenu *submenu;
132
   NSMenuItem *menu_item;
133
   const NSDictionary *infoplist_dict;
134
   NSString *application_name;
135
   int arg_index;
2 pmbaty 136
 
4 pmbaty 137
   // copy the program arguments into global variables (discard arguments 1-n if we were launched by double-clicking)
138
   if ((argc >= 2) && (strncmp (argv[1], "-psn", 4) == 0))
139
      global_argc = 1; // we were launched by Finder, ignore all arguments except the executable name
140
   else
141
      global_argc = argc; // we were NOT launched by Finder (most probably by a shell), copy all arguments
142
   global_argv = (char **) malloc ((global_argc + 1) * sizeof (char *));
143
   for (arg_index = 0; arg_index < global_argc; arg_index++)
144
      global_argv[arg_index] = argv[arg_index];
145
   global_argv[arg_index] = NULL;
2 pmbaty 146
 
4 pmbaty 147
   // allocate an autorelease pool and start Cocoa
148
   pool = [[NSAutoreleasePool alloc] init];
2 pmbaty 149
 
4 pmbaty 150
   // ensure the application object is initialised (FIXME: is this necessary ?)
151
   [NSApplication sharedApplication];
2 pmbaty 152
 
4 pmbaty 153
   // figure out the application name, either from the Info.plist, or from the process name
154
   application_name = NULL;
155
   infoplist_dict = (const NSDictionary *) CFBundleGetInfoDictionary (CFBundleGetMainBundle ()); // try to get the bundle's Info.plist
156
   if (infoplist_dict)
157
      application_name = [infoplist_dict objectForKey: @"CFBundleName"]; // if it has, read the CFBundleName key value from it
158
   if ((application_name == NULL) || ([application_name length] == 0))
159
      application_name = [[NSProcessInfo processInfo] processName]; // else, or if the bundle name is empty, use the process name
2 pmbaty 160
 
4 pmbaty 161
   // create the application menu and populate it
162
   [NSApp setMainMenu: [[NSMenu alloc] init]];
2 pmbaty 163
 
4 pmbaty 164
   // create the [AppName] menu
165
   submenu = [[NSMenu alloc] initWithTitle: @""];
166
   [submenu addItemWithTitle: [@"About " stringByAppendingString: application_name] action: @selector(orderFrontStandardAboutPanel:) keyEquivalent: @""];
167
   [submenu addItem: [NSMenuItem separatorItem]];
168
   [submenu addItemWithTitle: [@"Hide " stringByAppendingString: application_name] action: @selector(hide:) keyEquivalent: @"h"];
169
   [[submenu addItemWithTitle: @"Hide Others" action: @selector(hideOtherApplications:) keyEquivalent: @"h"] setKeyEquivalentModifierMask: (NSAlternateKeyMask|NSCommandKeyMask)];
170
   [submenu addItemWithTitle: @"Show All" action: @selector(unhideAllApplications:) keyEquivalent: @""];
171
   [submenu addItem: [NSMenuItem separatorItem]];
172
   [submenu addItemWithTitle: [@"Quit " stringByAppendingString: application_name] action: @selector(quitMenuCommand:) keyEquivalent: @"q"];
2 pmbaty 173
 
4 pmbaty 174
   // put the [AppName] menu in the menubar
175
   menu_item = [[NSMenuItem alloc] initWithTitle: @"" action: nil keyEquivalent: @""];
176
   [menu_item setSubmenu: submenu];
177
   [[NSApp mainMenu] addItem: menu_item]; // put menu into the menubar
178
   [NSApp setAppleMenu: submenu]; // tell the application object that this is now the application menu
179
   [menu_item release]; // finally give up our references to the objects
180
   [submenu release]; // finally give up our references to the objects
2 pmbaty 181
 
4 pmbaty 182
   // create a [Window] menu
183
   submenu = [[NSMenu alloc] initWithTitle: @"Window"];
184
   menu_item = [[NSMenuItem alloc] initWithTitle: @"Minimize" action: @selector(performMiniaturize:) keyEquivalent: @"m"];
185
   [submenu addItem: menu_item];
186
   menu_item = [[NSMenuItem alloc] initWithTitle: @"Enter Full Screen" action: @selector(fullscreenMenuCommand:) keyEquivalent: @"f"];
187
   [submenu addItem: menu_item];
188
   [menu_item release];
2 pmbaty 189
 
4 pmbaty 190
   // put the [Window] menu in the menubar
191
   menu_item = [[NSMenuItem alloc] initWithTitle: @"Window" action: nil keyEquivalent: @""];
192
   [menu_item setSubmenu: submenu];
193
   [[NSApp mainMenu] addItem: menu_item]; // put menu into the menubar
194
   [NSApp setWindowsMenu: submenu]; // tell the application object that this is now the window menu
195
   [menu_item release]; // finally give up our references to the objects
196
   [submenu release]; // finally give up our references to the objects
2 pmbaty 197
 
4 pmbaty 198
   // create a [Help] menu
199
   submenu = [[NSMenu alloc] initWithTitle: @"Help"];
200
   [submenu addItem: [NSMenuItem separatorItem]];
201
   menu_item = [[NSMenuItem alloc] initWithTitle: @"How to play" action: @selector(visitwebsiteMenuCommand:) keyEquivalent: @"?"];
202
   [submenu addItem: menu_item];
203
   menu_item = [[NSMenuItem alloc] initWithTitle: @"Visit Website" action: @selector(visitwebsiteMenuCommand:) keyEquivalent: @"w"];
204
   [submenu addItem: menu_item];
205
   [menu_item release];
2 pmbaty 206
 
4 pmbaty 207
   // put the [Help] menu in the menubar
208
   menu_item = [[NSMenuItem alloc] initWithTitle: @"Help" action: nil keyEquivalent: @""];
209
   [menu_item setSubmenu: submenu];
210
   [[NSApp mainMenu] addItem: menu_item]; // put menu into the menubar
211
   [NSApp setHelpMenu: submenu]; // tell the application object that this is now the help menu
212
   [menu_item release]; // finally give up our references to the objects
213
   [submenu release]; // finally give up our references to the objects
2 pmbaty 214
 
4 pmbaty 215
   // create the SDLMain object and make it the app delegate
216
   sdlmain_delegate = [[SDLMainAppDelegate alloc] init];
217
   [NSApp setDelegate: (id) sdlmain_delegate];
2 pmbaty 218
 
4 pmbaty 219
   // start the Cocoa event loop
220
   [NSApp run];
2 pmbaty 221
 
4 pmbaty 222
   // finally give up our references to the objects when the Cocoa event loop exits
223
   [sdlmain_delegate release];
224
   [pool release];
2 pmbaty 225
 
4 pmbaty 226
   return (0); // e finita la comedia!
2 pmbaty 227
}