summaryrefslogtreecommitdiff
path: root/pkg/osx/LauncherManager.m
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/osx/LauncherManager.m')
-rw-r--r--pkg/osx/LauncherManager.m338
1 files changed, 338 insertions, 0 deletions
diff --git a/pkg/osx/LauncherManager.m b/pkg/osx/LauncherManager.m
new file mode 100644
index 00000000..ae91ef4d
--- /dev/null
+++ b/pkg/osx/LauncherManager.m
@@ -0,0 +1,338 @@
+/* ... */
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 Simon Howard
+//
+// This program 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.
+//
+// This program 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 this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+
+#include <AppKit/AppKit.h>
+#include "Execute.h"
+#include "LauncherManager.h"
+#include "config.h"
+
+@implementation LauncherManager
+
+// Save configuration. Invoked when we launch the game or quit.
+
+- (void) saveConfig
+{
+ NSUserDefaults *defaults;
+
+ // Save IWAD configuration and selected IWAD.
+
+ [self->iwadController saveConfig];
+
+ // Save command line arguments.
+
+ defaults = [NSUserDefaults standardUserDefaults];
+ [defaults setObject:[self->commandLineArguments stringValue]
+ forKey:@"command_line_args"];
+}
+
+// Load configuration, invoked on startup.
+
+- (void) setConfig
+{
+ NSUserDefaults *defaults;
+ NSString *args;
+
+ defaults = [NSUserDefaults standardUserDefaults];
+
+ args = [defaults stringForKey:@"command_line_args"];
+
+ if (args != nil)
+ {
+ [self->commandLineArguments setStringValue:args];
+ }
+}
+
+// Get the next command line argument from the command line.
+// The position counter used to iterate over arguments is in 'pos'.
+// The index of the argument that was found is saved in arg_pos.
+
+static NSString *GetNextArgument(NSString *commandLine, int *pos, int *arg_pos)
+{
+ NSRange arg_range;
+
+ // Skip past any whitespace
+
+ while (*pos < [commandLine length]
+ && isspace([commandLine characterAtIndex: *pos]))
+ {
+ ++*pos;
+ }
+
+ if (*pos >= [commandLine length])
+ {
+ *arg_pos = *pos;
+ return nil;
+ }
+
+ // We are at the start of the argument. This may be a quoted
+ // string argument, or a "normal" one.
+
+ if ([commandLine characterAtIndex: *pos] == '\"')
+ {
+ // Quoted string, skip past first quote
+
+ ++*pos;
+
+ // Save start position:
+
+ *arg_pos = *pos;
+
+ while (*pos < [commandLine length]
+ && [commandLine characterAtIndex: *pos] != '\"')
+ {
+ ++*pos;
+ }
+
+ // Unexpected end of string?
+
+ if (*pos >= [commandLine length])
+ {
+ return nil;
+ }
+
+ arg_range = NSMakeRange(*arg_pos, *pos - *arg_pos);
+
+ // Skip past last quote
+
+ ++*pos;
+ }
+ else
+ {
+ // Normal argument
+
+ // Save position:
+
+ *arg_pos = *pos;
+
+ // Read until end:
+
+ while (*pos < [commandLine length]
+ && !isspace([commandLine characterAtIndex: *pos]))
+ {
+ ++*pos;
+ }
+
+ arg_range = NSMakeRange(*arg_pos, *pos - *arg_pos);
+ }
+
+ return [commandLine substringWithRange: arg_range];
+}
+
+// Given the specified command line argument, find the index
+// to insert the new file within the command line. Returns -1 if the
+// argument is not already within the arguments string.
+
+static int GetFileInsertIndex(NSString *commandLine, NSString *needle)
+{
+ NSString *arg;
+ int arg_pos;
+ int pos;
+
+ pos = 0;
+
+ // Find the command line parameter we are searching
+ // for (-merge, -deh, etc)
+
+ for (;;)
+ {
+ arg = GetNextArgument(commandLine, &pos, &arg_pos);
+
+ // Searched to end of string and never found?
+
+ if (arg == nil)
+ {
+ return -1;
+ }
+
+ if (![arg caseInsensitiveCompare: needle])
+ {
+ break;
+ }
+ }
+
+ // Now skip over existing files. For example, if we
+ // have -file foo.wad bar.wad, the new file should be appended
+ // to the end of the list.
+
+ for (;;)
+ {
+ arg = GetNextArgument(commandLine, &pos, &arg_pos);
+
+ // If we search to the end of the string now, it is fine;
+ // the new string should be added to the end of the command
+ // line. Otherwise, if we find an argument that begins
+ // with '-', it is a new command line parameter and the end
+ // of the list.
+
+ if (arg == nil || [arg characterAtIndex: 0] == '-')
+ {
+ break;
+ }
+ }
+
+ // arg_pos should now contain the offset to insert the new filename.
+
+ return arg_pos;
+}
+
+// Given the specified string, append a filename, quoted if necessary.
+
+static NSString *AppendQuotedFilename(NSString *str, NSString *fileName)
+{
+ int i;
+
+ // Search the filename for spaces, and quote if necessary.
+
+ for (i=0; i<[fileName length]; ++i)
+ {
+ if (isspace([fileName characterAtIndex: i]))
+ {
+ str = [str stringByAppendingString: @" \""];
+ str = [str stringByAppendingString: fileName];
+ str = [str stringByAppendingString: @"\" "];
+
+ return str;
+ }
+ }
+
+ str = [str stringByAppendingString: @" "];
+ str = [str stringByAppendingString: fileName];
+
+ return str;
+}
+
+// Clear out the existing command line options.
+// Invoked before the first file is added.
+
+- (void) clearCommandLine
+{
+ [self->commandLineArguments setStringValue: @""];
+}
+
+// Add a file to the command line to load with the game.
+
+- (void) addFileToCommandLine: (NSString *) fileName
+ forArgument: (NSString *) arg
+{
+ NSString *commandLine;
+ int insert_pos;
+
+ // Get the current command line
+
+ commandLine = [self->commandLineArguments stringValue];
+
+ // Find the location to insert the new filename:
+
+ insert_pos = GetFileInsertIndex(commandLine, arg);
+
+ // If position < 0, we should add the new argument and filename
+ // to the end. Otherwise, append the new filename to the existing
+ // list of files.
+
+ if (insert_pos < 0)
+ {
+ commandLine = [commandLine stringByAppendingString: @" "];
+ commandLine = [commandLine stringByAppendingString: arg];
+ commandLine = AppendQuotedFilename(commandLine, fileName);
+ }
+ else
+ {
+ NSString *start;
+ NSString *end;
+
+ // Divide existing command line in half:
+
+ start = [commandLine substringToIndex: insert_pos];
+ end = [commandLine substringFromIndex: insert_pos];
+
+ // Construct new command line:
+
+ commandLine = AppendQuotedFilename(start, fileName);
+ commandLine = [commandLine stringByAppendingString: @" "];
+ commandLine = [commandLine stringByAppendingString: end];
+ }
+
+ [self->commandLineArguments setStringValue: commandLine];
+}
+
+- (void) launch: (id)sender
+{
+ NSString *iwad;
+ NSString *args;
+
+ [self saveConfig];
+
+ iwad = [self->iwadController getIWADLocation];
+ args = [self->commandLineArguments stringValue];
+
+ if (iwad == nil)
+ {
+ NSRunAlertPanel(@"No IWAD selected",
+ @"You have not selected an IWAD (game) file.\n\n"
+ "You must configure and select a valid IWAD file "
+ "in order to launch the game.",
+ @"OK", nil, nil);
+ return;
+ }
+
+ ExecuteProgram(PACKAGE_TARNAME, [iwad UTF8String],
+ [args UTF8String]);
+ [NSApp terminate:sender];
+}
+
+// Invoked when the "Setup Tool" button is clicked, to run the setup tool:
+
+- (void) runSetup: (id)sender
+{
+ [self saveConfig];
+
+ [self->iwadController setEnvironment];
+ ExecuteProgram("chocolate-setup", NULL, NULL);
+}
+
+// Invoked when the "Terminal" option is selected from the menu, to open
+// a terminal window.
+
+- (void) openTerminal: (id) sender
+{
+ char *doomwadpath;
+
+ [self saveConfig];
+
+ doomwadpath = [self->iwadController doomWadPath];
+
+ OpenTerminalWindow(doomwadpath);
+
+ free(doomwadpath);
+}
+
+- (void) awakeFromNib
+{
+ [self->packageLabel setStringValue: @PACKAGE_STRING];
+ [self->launcherWindow setTitle: @PACKAGE_NAME " Launcher"];
+ [self->launcherWindow center];
+ [self->launcherWindow setDefaultButtonCell: [self->launchButton cell]];
+ [self setConfig];
+}
+
+@end
+