diff options
Diffstat (limited to 'code/macosx/Q3Controller.m')
-rwxr-xr-x | code/macosx/Q3Controller.m | 870 |
1 files changed, 435 insertions, 435 deletions
diff --git a/code/macosx/Q3Controller.m b/code/macosx/Q3Controller.m index 7839d59..6ddf9d5 100755 --- a/code/macosx/Q3Controller.m +++ b/code/macosx/Q3Controller.m @@ -1,435 +1,435 @@ -/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#import "Q3Controller.h"
-
-#import <Foundation/Foundation.h>
-#import <AppKit/AppKit.h>
-
-#include "client.h"
-#include "macosx_local.h"
-//#include "GameRanger SDK/gameranger.h"
-#ifdef OMNI_TIMER
-#import "macosx_timers.h"
-#endif
-
-#define MAX_ARGC 1024
-
-static qboolean Sys_IsProcessingTerminationRequest = qfalse;
-static void Sys_CreatePathToFile(NSString *path, NSDictionary *attributes);
-
-@interface Q3Controller (Private)
-- (void)quakeMain;
-@end
-
-@implementation Q3Controller
-
-#ifndef DEDICATED
-
-- (void)applicationDidFinishLaunching:(NSNotification *)notification;
-{
- NS_DURING {
- [self quakeMain];
- } NS_HANDLER {
- Sys_Error("%@", [localException reason]);
- } NS_ENDHANDLER;
- Sys_Quit();
-}
-
-- (void)applicationDidUnhide:(NSNotification *)notification;
-{
- // Don't reactivate the game if we are asking whether to quit
- if (Sys_IsProcessingTerminationRequest)
- return;
-
- if (!Sys_Unhide())
- // Didn't work -- hide again so we should get another chance to unhide later
- [NSApp hide: nil];
-}
-
-- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
-{
- int choice;
-
- if (!Sys_IsHidden) {
- // We're terminating via -terminate:
- return NSTerminateNow;
- }
-
- // Avoid reactivating GL when we unhide due to this panel
- Sys_IsProcessingTerminationRequest = qtrue;
- choice = NSRunAlertPanel(nil, @"Quit without saving?", @"Don't Quit", @"Quit", nil);
- Sys_IsProcessingTerminationRequest = qfalse;
-
- if (choice == NSAlertAlternateReturn)
- return NSTerminateNow;
-
- // Make sure we get re-hidden
- [NSApp hide:nil];
-
- return NSTerminateCancel;
-}
-
-// Actions
-
-- (IBAction)paste:(id)sender;
-{
- int shiftWasDown, insertWasDown;
- unsigned int currentTime;
-
- currentTime = Sys_Milliseconds();
- // Save the original keyboard state
- shiftWasDown = keys[K_SHIFT].down;
- insertWasDown = keys[K_INS].down;
- // Fake a Shift-Insert keyboard event
- keys[K_SHIFT].down = qtrue;
- Sys_QueEvent(currentTime, SE_KEY, K_INS, qtrue, 0, NULL);
- Sys_QueEvent(currentTime, SE_KEY, K_INS, qfalse, 0, NULL);
- // Restore the original keyboard state
- keys[K_SHIFT].down = shiftWasDown;
- keys[K_INS].down = insertWasDown;
-}
-
-extern void CL_Quit_f(void);
-
-
-- (IBAction)requestTerminate:(id)sender;
-{
- Com_Quit_f();
- // UI_QuitMenu();
-}
-
-- (void)showBanner;
-{
- static BOOL hasShownBanner = NO;
-
- if (!hasShownBanner) {
- cvar_t *showBanner;
-
- hasShownBanner = YES;
- showBanner = Cvar_Get("cl_showBanner", "1", 0);
- if (showBanner->integer != 0) {
- NSPanel *splashPanel;
- NSImage *bannerImage;
- NSRect bannerRect;
- NSImageView *bannerImageView;
-
- bannerImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForImageResource:@"banner.jpg"]];
- bannerRect = NSMakeRect(0.0, 0.0, [bannerImage size].width, [bannerImage size].height);
-
- splashPanel = [[NSPanel alloc] initWithContentRect:bannerRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
-
- bannerImageView = [[NSImageView alloc] initWithFrame:bannerRect];
- [bannerImageView setImage:bannerImage];
- [splashPanel setContentView:bannerImageView];
- [bannerImageView release];
-
- [splashPanel center];
- [splashPanel setHasShadow:YES];
- [splashPanel orderFront: nil];
- [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.5]];
- [splashPanel close];
-
- [bannerImage release];
- }
- }
-}
-
-// Services
-
-- (void)connectToServer:(NSPasteboard *)pasteboard userData:(NSString *)data error:(NSString **)error;
-{
- NSArray *pasteboardTypes;
-
- pasteboardTypes = [pasteboard types];
- if ([pasteboardTypes containsObject:NSStringPboardType]) {
- NSString *requestedServer;
-
- requestedServer = [pasteboard stringForType:NSStringPboardType];
- if (requestedServer) {
- Cbuf_AddText(va("connect %s\n", [requestedServer cString]));
- return;
- }
- }
- *error = @"Unable to connect to server: could not find string on pasteboard";
-}
-
-- (void)performCommand:(NSPasteboard *)pasteboard userData:(NSString *)data error:(NSString **)error;
-{
- NSArray *pasteboardTypes;
-
- pasteboardTypes = [pasteboard types];
- if ([pasteboardTypes containsObject:NSStringPboardType]) {
- NSString *requestedCommand;
-
- requestedCommand = [pasteboard stringForType:NSStringPboardType];
- if (requestedCommand) {
- Cbuf_AddText(va("%s\n", [requestedCommand cString]));
- return;
- }
- }
- *error = @"Unable to perform command: could not find string on pasteboard";
-}
-
-#endif
-
-- (void)quakeMain;
-{
- NSAutoreleasePool *pool;
- int argc = 0;
- const char *argv[MAX_ARGC];
- NSProcessInfo *processInfo;
- NSArray *arguments;
- unsigned int argumentIndex, argumentCount;
- NSFileManager *defaultManager;
- unsigned int commandLineLength;
- NSString *installationPathKey, *installationPath;
- char *cmdline;
- BOOL foundDirectory;
- NSString *appName, *demoAppName, *selectButton;
- int count = 0;
- pool = [[NSAutoreleasePool alloc] init];
-
- [NSApp setServicesProvider:self];
-
- processInfo = [NSProcessInfo processInfo];
- arguments = [processInfo arguments];
- argumentCount = [arguments count];
- for (argumentIndex = 0; argumentIndex < argumentCount; argumentIndex++) {
- NSString *arg;
-
- arg = [arguments objectAtIndex:argumentIndex];
- // Don't pass the Process Serial Number command line arg that the Window Server/Finder invokes us with
- if ([arg hasPrefix: @"-psn_"])
- continue;
-
- argv[argc++] = strdup([arg cString]);
- }
-
- // Figure out where the level data is stored.
- installationPathKey = @"RetailInstallationPath";
-
- installationPath = [[NSUserDefaults standardUserDefaults] objectForKey:installationPathKey];
- if (!installationPath) {
- // Default to the directory containing the executable (which is where most users will want to put it
- installationPath = [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent];
- }
-
-#if !defined(DEDICATED)
- appName = [[[NSBundle mainBundle] infoDictionary] objectForKey: @"CFBundleName"];
-#else
- // We are hard coding the app name here since the dedicated server is a tool, not a app bundle and does not have access to the Info.plist that the client app does. Suck.
- appName = @"Quake3";
-#endif
- demoAppName = appName;
-
- while (YES) {
- NSString *dataPath;
- NSOpenPanel *openPanel;
- int result;
-
- foundDirectory = NO;
- defaultManager = [NSFileManager defaultManager];
- //NSLog(@"Candidate installation path = %@", installationPath);
- dataPath = [installationPath stringByAppendingPathComponent: @"baseq3"];
-
- if ([defaultManager fileExistsAtPath: dataPath]) {
- // Check that the data directory contains at least one .pk3 file. We don't know what it will be named, so don't hard code a name (for example it might be named 'french.pk3' for a French release
- NSArray *files;
- unsigned int fileIndex;
-
- files = [defaultManager directoryContentsAtPath: dataPath];
- fileIndex = [files count];
- while (fileIndex--) {
- if ([[files objectAtIndex: fileIndex] hasSuffix: @"pk3"]) {
- //NSLog(@"Found %@.", [files objectAtIndex: fileIndex]);
- foundDirectory = YES;
- break;
- }
- }
- }
-
- if (foundDirectory)
- break;
-
-#ifdef DEDICATED
- break;
-#warning TJW: We are hard coding the app name and default domain here since the dedicated server is a tool, not a app bundle and does not have access to the Info.plist that the client app does. Suck.
- NSLog(@"Unable to determine installation directory. Please move the executable into the '%@' installation directory or add a '%@' key in the 'Q3DedicatedServer' defaults domain.", appName, installationPathKey, [[NSBundle mainBundle] bundleIdentifier]);
- Sys_Quit();
- exit(1);
-#else
- selectButton = @"Select Retail Installation...";
-
- result = NSRunAlertPanel(demoAppName, @"You need to select the installation directory for %@ (not any directory inside of it -- the installation directory itself).", selectButton, @"Quit", nil, appName);
- switch (result) {
- case NSAlertDefaultReturn:
- break;
- default:
- Sys_Quit();
- break;
- }
-
- openPanel = [NSOpenPanel openPanel];
- [openPanel setAllowsMultipleSelection:NO];
- [openPanel setCanChooseDirectories:YES];
- [openPanel setCanChooseFiles:NO];
- result = [openPanel runModalForDirectory:nil file:nil];
- if (result == NSOKButton) {
- NSArray *filenames;
-
- filenames = [openPanel filenames];
- if ([filenames count] == 1) {
- installationPath = [filenames objectAtIndex:0];
- [[NSUserDefaults standardUserDefaults] setObject:installationPath forKey:installationPathKey];
- [[NSUserDefaults standardUserDefaults] synchronize];
- }
- }
-#endif
- }
-
- // Create the application support directory if it doesn't exist already
- do {
- NSArray *results;
- NSString *libraryPath, *homePath, *filePath;
- NSDictionary *attributes;
-
- results = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
- if (![results count])
- break;
-
- libraryPath = [results objectAtIndex: 0];
- homePath = [libraryPath stringByAppendingPathComponent: @"Application Support"];
- homePath = [homePath stringByAppendingPathComponent: appName];
- filePath = [homePath stringByAppendingPathComponent: @"foo"];
-
- attributes = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithUnsignedInt: 0750], NSFilePosixPermissions, nil];
- NS_DURING {
- Sys_CreatePathToFile(filePath, attributes);
- Sys_SetDefaultHomePath([homePath fileSystemRepresentation]);
- } NS_HANDLER {
- NSLog(@"Exception: %@", localException);
-#ifndef DEDICATED
- NSRunAlertPanel(nil, @"Unable to create '%@'. Please make sure that you have permission to write to this folder and re-run the game.", @"OK", nil, nil, homePath);
-#endif
- Sys_Quit();
- } NS_ENDHANDLER;
- } while(0);
-
- // Provoke the CD scanning code into looking up the CD.
- Sys_CheckCD();
-
- // Let the filesystem know where our local install is
- Sys_SetDefaultInstallPath([installationPath cString]);
-
- cmdline = NULL;
-#if 0
- if (GRCheckFileForCmd()) {
- GRGetWaitingCmd();
- if (GRHasProperty( 'Exec' )) {
- NSString *cfgPath, *grCfg;
- cfgPath = [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent];
- cfgPath = [cfgPath stringByAppendingPathComponent: [NSString stringWithCString: GRGetPropertyStr( 'Exec' )]];
- grCfg = [NSString stringWithContentsOfFile: cfgPath];
- cmdline = malloc(strlen([grCfg cString])+1);
- [grCfg getCString: cmdline];
- }
- }
-#endif
- if (!cmdline) {
- // merge the command line, this is kinda silly
- for (commandLineLength = 1, argumentIndex = 1; argumentIndex < argc; argumentIndex++)
- commandLineLength += strlen(argv[argumentIndex]) + 1;
- cmdline = malloc(commandLineLength);
- *cmdline = '\0';
- for (argumentIndex = 1; argumentIndex < argc; argumentIndex++) {
- if (argumentIndex > 1)
- strcat(cmdline, " ");
- strcat(cmdline, argv[argumentIndex]);
- }
- }
- Com_Printf("command line: %s\n", cmdline);
-
- Com_Init(cmdline);
-
-#ifndef DEDICATED
- [NSApp activateIgnoringOtherApps:YES];
-#endif
-
- while (1) {
- Com_Frame();
-
- if ((count & 15)==0) {
- // We should think about doing this less frequently than every frame
- [pool release];
- pool = [[NSAutoreleasePool alloc] init];
- }
- }
-
- [pool release];
-}
-
-@end
-
-
-
-// Creates any directories needed to be able to create a file at the specified path. Raises an exception on failure.
-static void Sys_CreatePathToFile(NSString *path, NSDictionary *attributes)
-{
- NSArray *pathComponents;
- unsigned int dirIndex, dirCount;
- unsigned int startingIndex;
- NSFileManager *manager;
-
- manager = [NSFileManager defaultManager];
- pathComponents = [path pathComponents];
- dirCount = [pathComponents count] - 1;
-
- startingIndex = 0;
- for (dirIndex = startingIndex; dirIndex < dirCount; dirIndex++) {
- NSString *partialPath;
- BOOL fileExists;
-
- partialPath = [NSString pathWithComponents:[pathComponents subarrayWithRange:NSMakeRange(0, dirIndex + 1)]];
-
- // Don't use the 'fileExistsAtPath:isDirectory:' version since it doesn't traverse symlinks
- fileExists = [manager fileExistsAtPath:partialPath];
- if (!fileExists) {
- if (![manager createDirectoryAtPath:partialPath attributes:attributes]) {
- [NSException raise:NSGenericException format:@"Unable to create a directory at path: %@", partialPath];
- }
- } else {
- NSDictionary *attributes;
-
- attributes = [manager fileAttributesAtPath:partialPath traverseLink:YES];
- if (![[attributes objectForKey:NSFileType] isEqualToString: NSFileTypeDirectory]) {
- [NSException raise:NSGenericException format:@"Unable to write to path \"%@\" because \"%@\" is not a directory",
- path, partialPath];
- }
- }
- }
-}
-
-#ifdef DEDICATED
-void S_ClearSoundBuffer( void ) {
-}
-#endif
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#import "Q3Controller.h" + +#import <Foundation/Foundation.h> +#import <AppKit/AppKit.h> + +#include "client.h" +#include "macosx_local.h" +//#include "GameRanger SDK/gameranger.h" +#ifdef OMNI_TIMER +#import "macosx_timers.h" +#endif + +#define MAX_ARGC 1024 + +static qboolean Sys_IsProcessingTerminationRequest = qfalse; +static void Sys_CreatePathToFile(NSString *path, NSDictionary *attributes); + +@interface Q3Controller (Private) +- (void)quakeMain; +@end + +@implementation Q3Controller + +#ifndef DEDICATED + +- (void)applicationDidFinishLaunching:(NSNotification *)notification; +{ + NS_DURING { + [self quakeMain]; + } NS_HANDLER { + Sys_Error("%@", [localException reason]); + } NS_ENDHANDLER; + Sys_Quit(); +} + +- (void)applicationDidUnhide:(NSNotification *)notification; +{ + // Don't reactivate the game if we are asking whether to quit + if (Sys_IsProcessingTerminationRequest) + return; + + if (!Sys_Unhide()) + // Didn't work -- hide again so we should get another chance to unhide later + [NSApp hide: nil]; +} + +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; +{ + int choice; + + if (!Sys_IsHidden) { + // We're terminating via -terminate: + return NSTerminateNow; + } + + // Avoid reactivating GL when we unhide due to this panel + Sys_IsProcessingTerminationRequest = qtrue; + choice = NSRunAlertPanel(nil, @"Quit without saving?", @"Don't Quit", @"Quit", nil); + Sys_IsProcessingTerminationRequest = qfalse; + + if (choice == NSAlertAlternateReturn) + return NSTerminateNow; + + // Make sure we get re-hidden + [NSApp hide:nil]; + + return NSTerminateCancel; +} + +// Actions + +- (IBAction)paste:(id)sender; +{ + int shiftWasDown, insertWasDown; + unsigned int currentTime; + + currentTime = Sys_Milliseconds(); + // Save the original keyboard state + shiftWasDown = keys[K_SHIFT].down; + insertWasDown = keys[K_INS].down; + // Fake a Shift-Insert keyboard event + keys[K_SHIFT].down = qtrue; + Sys_QueEvent(currentTime, SE_KEY, K_INS, qtrue, 0, NULL); + Sys_QueEvent(currentTime, SE_KEY, K_INS, qfalse, 0, NULL); + // Restore the original keyboard state + keys[K_SHIFT].down = shiftWasDown; + keys[K_INS].down = insertWasDown; +} + +extern void CL_Quit_f(void); + + +- (IBAction)requestTerminate:(id)sender; +{ + Com_Quit_f(); + // UI_QuitMenu(); +} + +- (void)showBanner; +{ + static BOOL hasShownBanner = NO; + + if (!hasShownBanner) { + cvar_t *showBanner; + + hasShownBanner = YES; + showBanner = Cvar_Get("cl_showBanner", "1", 0); + if (showBanner->integer != 0) { + NSPanel *splashPanel; + NSImage *bannerImage; + NSRect bannerRect; + NSImageView *bannerImageView; + + bannerImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForImageResource:@"banner.jpg"]]; + bannerRect = NSMakeRect(0.0, 0.0, [bannerImage size].width, [bannerImage size].height); + + splashPanel = [[NSPanel alloc] initWithContentRect:bannerRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]; + + bannerImageView = [[NSImageView alloc] initWithFrame:bannerRect]; + [bannerImageView setImage:bannerImage]; + [splashPanel setContentView:bannerImageView]; + [bannerImageView release]; + + [splashPanel center]; + [splashPanel setHasShadow:YES]; + [splashPanel orderFront: nil]; + [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.5]]; + [splashPanel close]; + + [bannerImage release]; + } + } +} + +// Services + +- (void)connectToServer:(NSPasteboard *)pasteboard userData:(NSString *)data error:(NSString **)error; +{ + NSArray *pasteboardTypes; + + pasteboardTypes = [pasteboard types]; + if ([pasteboardTypes containsObject:NSStringPboardType]) { + NSString *requestedServer; + + requestedServer = [pasteboard stringForType:NSStringPboardType]; + if (requestedServer) { + Cbuf_AddText(va("connect %s\n", [requestedServer cString])); + return; + } + } + *error = @"Unable to connect to server: could not find string on pasteboard"; +} + +- (void)performCommand:(NSPasteboard *)pasteboard userData:(NSString *)data error:(NSString **)error; +{ + NSArray *pasteboardTypes; + + pasteboardTypes = [pasteboard types]; + if ([pasteboardTypes containsObject:NSStringPboardType]) { + NSString *requestedCommand; + + requestedCommand = [pasteboard stringForType:NSStringPboardType]; + if (requestedCommand) { + Cbuf_AddText(va("%s\n", [requestedCommand cString])); + return; + } + } + *error = @"Unable to perform command: could not find string on pasteboard"; +} + +#endif + +- (void)quakeMain; +{ + NSAutoreleasePool *pool; + int argc = 0; + const char *argv[MAX_ARGC]; + NSProcessInfo *processInfo; + NSArray *arguments; + unsigned int argumentIndex, argumentCount; + NSFileManager *defaultManager; + unsigned int commandLineLength; + NSString *installationPathKey, *installationPath; + char *cmdline; + BOOL foundDirectory; + NSString *appName, *demoAppName, *selectButton; + int count = 0; + pool = [[NSAutoreleasePool alloc] init]; + + [NSApp setServicesProvider:self]; + + processInfo = [NSProcessInfo processInfo]; + arguments = [processInfo arguments]; + argumentCount = [arguments count]; + for (argumentIndex = 0; argumentIndex < argumentCount; argumentIndex++) { + NSString *arg; + + arg = [arguments objectAtIndex:argumentIndex]; + // Don't pass the Process Serial Number command line arg that the Window Server/Finder invokes us with + if ([arg hasPrefix: @"-psn_"]) + continue; + + argv[argc++] = strdup([arg cString]); + } + + // Figure out where the level data is stored. + installationPathKey = @"RetailInstallationPath"; + + installationPath = [[NSUserDefaults standardUserDefaults] objectForKey:installationPathKey]; + if (!installationPath) { + // Default to the directory containing the executable (which is where most users will want to put it + installationPath = [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent]; + } + +#if !defined(DEDICATED) + appName = [[[NSBundle mainBundle] infoDictionary] objectForKey: @"CFBundleName"]; +#else + // We are hard coding the app name here since the dedicated server is a tool, not a app bundle and does not have access to the Info.plist that the client app does. Suck. + appName = @"Quake3"; +#endif + demoAppName = appName; + + while (YES) { + NSString *dataPath; + NSOpenPanel *openPanel; + int result; + + foundDirectory = NO; + defaultManager = [NSFileManager defaultManager]; + //NSLog(@"Candidate installation path = %@", installationPath); + dataPath = [installationPath stringByAppendingPathComponent: @"baseq3"]; + + if ([defaultManager fileExistsAtPath: dataPath]) { + // Check that the data directory contains at least one .pk3 file. We don't know what it will be named, so don't hard code a name (for example it might be named 'french.pk3' for a French release + NSArray *files; + unsigned int fileIndex; + + files = [defaultManager directoryContentsAtPath: dataPath]; + fileIndex = [files count]; + while (fileIndex--) { + if ([[files objectAtIndex: fileIndex] hasSuffix: @"pk3"]) { + //NSLog(@"Found %@.", [files objectAtIndex: fileIndex]); + foundDirectory = YES; + break; + } + } + } + + if (foundDirectory) + break; + +#ifdef DEDICATED + break; +#warning TJW: We are hard coding the app name and default domain here since the dedicated server is a tool, not a app bundle and does not have access to the Info.plist that the client app does. Suck. + NSLog(@"Unable to determine installation directory. Please move the executable into the '%@' installation directory or add a '%@' key in the 'Q3DedicatedServer' defaults domain.", appName, installationPathKey, [[NSBundle mainBundle] bundleIdentifier]); + Sys_Quit(); + exit(1); +#else + selectButton = @"Select Retail Installation..."; + + result = NSRunAlertPanel(demoAppName, @"You need to select the installation directory for %@ (not any directory inside of it -- the installation directory itself).", selectButton, @"Quit", nil, appName); + switch (result) { + case NSAlertDefaultReturn: + break; + default: + Sys_Quit(); + break; + } + + openPanel = [NSOpenPanel openPanel]; + [openPanel setAllowsMultipleSelection:NO]; + [openPanel setCanChooseDirectories:YES]; + [openPanel setCanChooseFiles:NO]; + result = [openPanel runModalForDirectory:nil file:nil]; + if (result == NSOKButton) { + NSArray *filenames; + + filenames = [openPanel filenames]; + if ([filenames count] == 1) { + installationPath = [filenames objectAtIndex:0]; + [[NSUserDefaults standardUserDefaults] setObject:installationPath forKey:installationPathKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; + } + } +#endif + } + + // Create the application support directory if it doesn't exist already + do { + NSArray *results; + NSString *libraryPath, *homePath, *filePath; + NSDictionary *attributes; + + results = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); + if (![results count]) + break; + + libraryPath = [results objectAtIndex: 0]; + homePath = [libraryPath stringByAppendingPathComponent: @"Application Support"]; + homePath = [homePath stringByAppendingPathComponent: appName]; + filePath = [homePath stringByAppendingPathComponent: @"foo"]; + + attributes = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithUnsignedInt: 0750], NSFilePosixPermissions, nil]; + NS_DURING { + Sys_CreatePathToFile(filePath, attributes); + Sys_SetDefaultHomePath([homePath fileSystemRepresentation]); + } NS_HANDLER { + NSLog(@"Exception: %@", localException); +#ifndef DEDICATED + NSRunAlertPanel(nil, @"Unable to create '%@'. Please make sure that you have permission to write to this folder and re-run the game.", @"OK", nil, nil, homePath); +#endif + Sys_Quit(); + } NS_ENDHANDLER; + } while(0); + + // Provoke the CD scanning code into looking up the CD. + Sys_CheckCD(); + + // Let the filesystem know where our local install is + Sys_SetDefaultInstallPath([installationPath cString]); + + cmdline = NULL; +#if 0 + if (GRCheckFileForCmd()) { + GRGetWaitingCmd(); + if (GRHasProperty( 'Exec' )) { + NSString *cfgPath, *grCfg; + cfgPath = [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent]; + cfgPath = [cfgPath stringByAppendingPathComponent: [NSString stringWithCString: GRGetPropertyStr( 'Exec' )]]; + grCfg = [NSString stringWithContentsOfFile: cfgPath]; + cmdline = malloc(strlen([grCfg cString])+1); + [grCfg getCString: cmdline]; + } + } +#endif + if (!cmdline) { + // merge the command line, this is kinda silly + for (commandLineLength = 1, argumentIndex = 1; argumentIndex < argc; argumentIndex++) + commandLineLength += strlen(argv[argumentIndex]) + 1; + cmdline = malloc(commandLineLength); + *cmdline = '\0'; + for (argumentIndex = 1; argumentIndex < argc; argumentIndex++) { + if (argumentIndex > 1) + strcat(cmdline, " "); + strcat(cmdline, argv[argumentIndex]); + } + } + Com_Printf("command line: %s\n", cmdline); + + Com_Init(cmdline); + +#ifndef DEDICATED + [NSApp activateIgnoringOtherApps:YES]; +#endif + + while (1) { + Com_Frame(); + + if ((count & 15)==0) { + // We should think about doing this less frequently than every frame + [pool release]; + pool = [[NSAutoreleasePool alloc] init]; + } + } + + [pool release]; +} + +@end + + + +// Creates any directories needed to be able to create a file at the specified path. Raises an exception on failure. +static void Sys_CreatePathToFile(NSString *path, NSDictionary *attributes) +{ + NSArray *pathComponents; + unsigned int dirIndex, dirCount; + unsigned int startingIndex; + NSFileManager *manager; + + manager = [NSFileManager defaultManager]; + pathComponents = [path pathComponents]; + dirCount = [pathComponents count] - 1; + + startingIndex = 0; + for (dirIndex = startingIndex; dirIndex < dirCount; dirIndex++) { + NSString *partialPath; + BOOL fileExists; + + partialPath = [NSString pathWithComponents:[pathComponents subarrayWithRange:NSMakeRange(0, dirIndex + 1)]]; + + // Don't use the 'fileExistsAtPath:isDirectory:' version since it doesn't traverse symlinks + fileExists = [manager fileExistsAtPath:partialPath]; + if (!fileExists) { + if (![manager createDirectoryAtPath:partialPath attributes:attributes]) { + [NSException raise:NSGenericException format:@"Unable to create a directory at path: %@", partialPath]; + } + } else { + NSDictionary *attributes; + + attributes = [manager fileAttributesAtPath:partialPath traverseLink:YES]; + if (![[attributes objectForKey:NSFileType] isEqualToString: NSFileTypeDirectory]) { + [NSException raise:NSGenericException format:@"Unable to write to path \"%@\" because \"%@\" is not a directory", + path, partialPath]; + } + } + } +} + +#ifdef DEDICATED +void S_ClearSoundBuffer( void ) { +} +#endif |