aboutsummaryrefslogtreecommitdiffstats
path: root/code/macosx/Q3Controller.m
diff options
context:
space:
mode:
authorzakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea>2005-08-26 17:39:27 +0000
committerzakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea>2005-08-26 17:39:27 +0000
commit6bf20c78f5b69d40bcc4931df93d29198435ab67 (patch)
treee3eda937a05d7db42de725b7013bd0344b987f34 /code/macosx/Q3Controller.m
parent872d4d7f55af706737ffb361bb76ad13e7496770 (diff)
downloadioquake3-aero-6bf20c78f5b69d40bcc4931df93d29198435ab67.tar.gz
ioquake3-aero-6bf20c78f5b69d40bcc4931df93d29198435ab67.zip
newlines fixed
git-svn-id: svn://svn.icculus.org/quake3/trunk@6 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'code/macosx/Q3Controller.m')
-rwxr-xr-xcode/macosx/Q3Controller.m870
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