diff --git a/sc2/ChangeLog b/sc2/ChangeLog index c4665bf7a..a0d4d4edd 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,5 @@ Changes towards version 0.4: +- Cocoa hooks for MacOS X, from Nic - Corrected number for combat energy when outfitting starship. - SvdB - Added dumping planet info to uqmdebug.c - SvdB - Check language.txt for locale, from Zap diff --git a/sc2/build/unix/build_functions b/sc2/build/unix/build_functions index eb4a8fad9..3bf9096f9 100644 --- a/sc2/build/unix/build_functions +++ b/sc2/build/unix/build_functions @@ -105,9 +105,9 @@ build_rec_dependancies() { mv -f -- "$DEPEND_FILE".tmp "$DEPEND_FILE" } -# Output the .o file for a .c file. +# Output the .o file for a given .c or .m (Objective-C) file build_collect_o_files() { - eval echo "\$BUILD_WORK_ESC/\${${BUILD_PROJECT}_OBJS}\${1%.c}.o" + eval echo "\$BUILD_WORK_ESC/\${${BUILD_PROJECT}_OBJS}\${1%.[cm]}.o" } # Output the extra .o file with the complete path diff --git a/sc2/build/unix/config_proginfo b/sc2/build/unix/config_proginfo index e8aff3575..853437ad2 100644 --- a/sc2/build/unix/config_proginfo +++ b/sc2/build/unix/config_proginfo @@ -99,18 +99,27 @@ LIB_SDL_NAME="Simple DirectMedia Layer" case "$OSNAME" in FreeBSD) LIB_SDL_CFLAGS='$(sdl11-config --cflags)' ;; + Darwin) LIB_SDL_CFLAGS='-I/System/Library/Frameworks/SDL.framework/Headers + -I/Library/Frameworks/SDL.framework/Headers + -I$HOME/Library/Frameworks/SDL.framework/Headers' + ;; *) LIB_SDL_CFLAGS='$(sdl-config --cflags)' ;; esac case "$OSNAME" in FreeBSD) LIB_SDL_LDFLAGS='$(sdl11-config --libs)' ;; + Darwin) LIB_SDL_LDFLAGS='-framework SDL -framework Cocoa -lobjc' ;; *) LIB_SDL_LDFLAGS='$(sdl-config --libs)' ;; esac case "$OSNAME" in FreeBSD) LIB_SDL_VERSION='$(sdl11-config --version)' ;; + Darwin) LIB_SDL_VERSION=$(echo \ + "SDL_MAJOR_VERSION.SDL_MINOR_VERSION.SDL_PATCHLEVEL" | \ + gcc -E -include SDL_version.h $LIB_SDL_CFLAGS - | \ + tail -1 | tr -d ' ') ;; *) LIB_SDL_VERSION='$(sdl-config --version)' ;; esac case "$OSNAME" in - Darwin) + Disabled) LIB_SDL_DETECT="Darwin_SDL_detect SDL" Darwin_SDL_detect() { local LIB TEMP_LDFLAGS TEMP_CFLAGS @@ -135,15 +144,24 @@ LIB_SDL_mixer_CFLAGS="$LIB_SDL_CFLAGS" LIB_SDL_mixer_LDFLAGS="$LIB_SDL_LDFLAGS -lSDL_mixer" LIB_SDL_mixer_VERSION="" case "$OSNAME" in - Darwin) LIB_SDL_mixer_DETECT="Darwin_SDL_detect SDL_mixer" ;; + Disabled) LIB_SDL_mixer_DETECT="Darwin_SDL_detect SDL_mixer" ;; esac LIB_SDL_image_NAME="SDL_image" -LIB_SDL_image_CFLAGS="$LIB_SDL_CFLAGS" -LIB_SDL_image_LDFLAGS="$LIB_SDL_LDFLAGS -lSDL_image" +case "$OSNAME" in + Darwin) LIB_SDL_image_CFLAGS="-I/System/Library/Frameworks/SDL_image.framework/Headers + -I/Library/Frameworks/SDL_image.framework/Headers + -I$HOME/Library/Frameworks/SDL_image.framework/Headers" + ;; + *) LIB_SDL_image_CFLAGS="$LIB_SDL_CFLAGS" ;; +esac +case "$OSNAME" in + Darwin) LIB_SDL_image_LDFLAGS="-framework SDL_image" ;; + *) LIB_SDL_image_LDFLAGS="$LIB_SDL_LDFLAGS -lSDL_image" ;; +esac LIB_SDL_image_VERSION="" case "$OSNAME" in - Darwin) LIB_SDL_image_DETECT="Darwin_SDL_detect SDL_image" ;; + Disabled) LIB_SDL_image_DETECT="Darwin_SDL_detect SDL_image" ;; esac LIB_openal_NAME="OpenAL" diff --git a/sc2/src/Makeinfo b/sc2/src/Makeinfo index df83841a1..b05a3f504 100644 --- a/sc2/src/Makeinfo +++ b/sc2/src/Makeinfo @@ -1,4 +1,10 @@ uqm_SUBDIRS="sc2code getopt res" +case "$OSNAME" in + Darwin) + uqm_SUBDIRS="$uqm_SUBDIRS darwin" + ;; +esac + uqm_CFILES="options.c port.c starcon2.c" test_CFILES=test.c diff --git a/sc2/src/darwin/SDLMain.h b/sc2/src/darwin/SDLMain.h new file mode 100644 index 000000000..5dcc7329b --- /dev/null +++ b/sc2/src/darwin/SDLMain.h @@ -0,0 +1,11 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn + + Feel free to customize this file to suit your needs +*/ + +#import + +@interface SDLMain : NSObject +@end diff --git a/sc2/src/darwin/SDLMain.m b/sc2/src/darwin/SDLMain.m new file mode 100644 index 000000000..6cc9b3395 --- /dev/null +++ b/sc2/src/darwin/SDLMain.m @@ -0,0 +1,295 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn + + Feel free to customize this file to suit your needs + + Modified for use with The Ur-Quan Masters by Nicolas Simonds + +*/ + +#import "SDL.h" +#import "SDLMain.h" +#import + /* for PATH_MAX */ +#import + /* for strrchr() */ +#import + +static int gArgc; +static char **gArgv; +static BOOL gFinderLaunch; + +/* An internal Apple class used to setup Apple menus */ +@interface NSAppleMenuController:NSObject {} +- (void)controlMenu:(NSMenu *)aMenu; +@end + +@interface SDLApplication : NSApplication +@end + +@implementation SDLApplication +/* Invoked from the Quit menu item */ +- (void)terminate:(id)sender +{ + /* Post a SDL_QUIT event */ + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent (&event); + (void) sender; /* Get rid of unused variable warning */ +} + +/* override NSApplication:sendEvent, to keep Cocoa from beeping on + non-command keystrokes */ +- (void)sendEvent:(NSEvent *)anEvent { + if (NSKeyDown == [anEvent type] || NSKeyUp == [anEvent type]) { + if ([anEvent modifierFlags] & NSCommandKeyMask) + [super sendEvent: anEvent]; + } else + [super sendEvent: anEvent]; +} +@end + +/* The main class of the application, the application's delegate */ +@implementation SDLMain + +static char * +basename (char *path) +{ + char *base; + + base = strrchr (path, '/'); + if (base == NULL) + return path; + + return (base + 1); +} + +/* Set the working directory to the .app's parent directory */ +- (void) +setupWorkingDirectory:(BOOL)shouldChdir +{ + char origindir[PATH_MAX]; + char *c; + + if (!shouldChdir) + return; + + strncpy (origindir, gArgv[0], sizeof origindir); + origindir[sizeof origindir - 1] = '\0'; + + c = basename (origindir); + if (c == origindir) + strcpy (origindir, "."); + else + *c = '\0'; + + /* chdir to the binary app's point of origin */ + if (chdir (origindir) != 0) + abort (); + /* then chdir to the .app's parent */ + if (chdir ("../../../") != 0) + abort (); +} + +void +setupAppleMenu (void) +{ + NSMenu *appleMenu; + + NSMenuItem *menuItem; + NSString *title; + NSString *appName; + + appName = [NSString stringWithUTF8String:basename (gArgv[0])]; + appleMenu = [[NSMenu alloc] initWithTitle:appName]; + + /* Add menu items */ + title = [@"Hide " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(hide:) + keyEquivalent:@"h"]; + + menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" + action:@selector(hideOtherApplications:) + keyEquivalent:@"h"]; + [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; + + [appleMenu addItemWithTitle:@"Show All" + action:@selector(unhideAllApplications:) + keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Quit " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(terminate:) + keyEquivalent:@"q"]; + + /* Put menu into the menubar */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil + keyEquivalent:@""]; + [menuItem setSubmenu:appleMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Tell the application object that this is now the application menu */ + [NSApp setAppleMenu:appleMenu]; + + /* Finally give up our references to the objects */ + [appleMenu release]; + [menuItem release]; +} + +/* Create a window menu */ +void +setupWindowMenu (void) +{ + NSMenu *windowMenu; + NSMenuItem *windowMenuItem; + NSMenuItem *menuItem; + + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; + + /* "Minimize" item */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" + action:@selector(performMiniaturize:) + keyEquivalent:@"m"]; + [windowMenu addItem:menuItem]; + [menuItem release]; + + /* Put menu into the menubar */ + windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" + action:nil keyEquivalent:@""]; + [windowMenuItem setSubmenu:windowMenu]; + [[NSApp mainMenu] addItem:windowMenuItem]; + + /* Tell the application object that this is now the window menu */ + [NSApp setWindowsMenu:windowMenu]; + + /* Finally give up our references to the objects */ + [windowMenu release]; + [windowMenuItem release]; +} + +/* Replacement for NSApplicationMain */ +void +CustomApplicationMain (int argc, char **argv) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SDLMain *sdlMain; + + /* Ensure the application object is initialised */ + [SDLApplication sharedApplication]; + + /* Set up the menubar */ + [NSApp setMainMenu:[[NSMenu alloc] init]]; + setupAppleMenu (); + setupWindowMenu (); + + /* Create SDLMain and make it the app delegate */ + sdlMain = [[SDLMain alloc] init]; + [NSApp setDelegate:sdlMain]; + + /* Start the main event loop */ + [NSApp run]; + + [sdlMain release]; + [pool release]; + + (void) argc; /* Get rid of unused variable warning */ + (void) argv; /* Get rid of unused variable warning */ +} + +/* Called when the internal event loop has just started running */ +- (void) +applicationDidFinishLaunching: (NSNotification *) note +{ + int status; + + /* allow Cocoa to hear keystrokes like Command-Q, etc. */ + setenv ("SDL_ENABLEAPPEVENTS", "1", 1); + + /* Set the working directory to the .app's parent directory */ + [self setupWorkingDirectory:gFinderLaunch]; + + /* Hand off to main application code */ + status = SDL_main (gArgc, gArgv); + + /* We're done, thank you for playing */ + exit (status); + + (void) note; /* Get rid of unused variable warning */ +} +@end + +@implementation NSString (ReplaceSubString) + +- (NSString *) +stringByReplacingRange:(NSRange)aRange with:(NSString *)aString +{ + unsigned int bufferSize; + unsigned int selfLen = [self length]; + unsigned int aStringLen = [aString length]; + unichar *buffer; + NSRange localRange; + NSString *result; + + bufferSize = selfLen + aStringLen - aRange.length; + buffer = NSAllocateMemoryPages (bufferSize * sizeof (unichar)); + + /* Get first part into buffer */ + localRange.location = 0; + localRange.length = aRange.location; + [self getCharacters:buffer range:localRange]; + + /* Get middle part into buffer */ + localRange.location = 0; + localRange.length = aStringLen; + [aString getCharacters:(buffer + aRange.location) range:localRange]; + + /* Get last part into buffer */ + localRange.location = aRange.location + aRange.length; + localRange.length = selfLen - localRange.location; + [self getCharacters:(buffer + aRange.location+aStringLen) + range:localRange]; + + /* Build output string */ + result = [NSString stringWithCharacters:buffer length:bufferSize]; + + NSDeallocateMemoryPages (buffer, bufferSize); + + return result; +} + +@end + +#ifdef main +# undef main +#endif + +/* Main entry point to executable - should *not* be SDL_main! */ +int +main (int argc, char **argv) +{ + /* Copy the arguments into a global variable */ + int i; + + /* This is passed if we are launched by double-clicking */ + if (argc >= 2 && strcmp (argv[1], "-psn") == 0) { + gArgc = 1; + gFinderLaunch = YES; + } else { + gArgc = argc; + gFinderLaunch = NO; + } + gArgv = (char **) malloc (sizeof *gArgv * (gArgc + 1)); + if (gArgv == NULL) + abort (); + for (i = 0; i < gArgc; i++) + gArgv[i] = argv[i]; + gArgv[i] = NULL; + + CustomApplicationMain (argc, argv); + free (gArgv); + return 0; +} + +