/* UMark
 * Copyright (C)2003-2005 Jeffrey Bakker

 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
   ___________________________________ .. .
 */

/*****
	The following block defines the source of a PERL script used to
	collect system information. This script has to be generated and
	deleted before and after use respectively, to ensure the script
	does not get modified by users (for cheat protection purposes).
**/

/***** BEGIN PERL BLOCK ******************************************************/
#define _SYSTEM_INFO_PL "#!/usr/bin/perl -w\n\
# obtains system info\n\
use strict;\n\
use Digest::MD5 'md5_hex';\n\
\n\
use constant STR_MAP => 0;\n\
use constant STR_BOT => 1;\n\
use constant STR_DTL => 2;\n\
use constant STR_RES => 3;\n\
use constant STR_MIN => 4;\n\
use constant STR_AVG => 5;\n\
use constant STR_MAX => 6;\n\
use constant STR_SCR => 7;\n\
use constant STR_VER => 8;\n\
use constant STR_TYP => 9;\n\
\n\
my $ulogpath = shift or die \"Error: no input file.\\n\";\n\
\n\
my $i;\n\
my $benchtype;\n\
my $AUID = md5_hex(\"UMark for Linux\");\n\
my $EHSH = md5_hex(\"UMark for Linux\");\n\
\n\
chomp(my $os_versn = `uname -s -r`);\n\
\n\
# collect various system information\n\
chomp(my @cpuinfo = `cat /proc/cpuinfo`);\n\
chomp(my @pciinfo = `cat /proc/pci`);\n\
chomp(my @glxinfo = `glxinfo`);\n\
chomp(my @meminfo = `free -m`);\n\
\n\
# collect specific cpu info\n\
(my $cpu_mhzs = $cpuinfo[6]) =~ s/cpu MHz.*: //g;\n\
(my $cpu_vend = $cpuinfo[1]) =~ s/vendor_id.*: //g;\n\
(my $cpu_modl = $cpuinfo[4]) =~ s/model name.*: //g;\n\
\n\
# find the number of processors\n\
my $a_size = @cpuinfo;\n\
my $num_cpus;\n\
\n\
$num_cpus = $a_size / 19;\n\
$num_cpus = sprintf(\"%%d\", $num_cpus);\n\
\n\
# round off MHz to an integer value\n\
$cpu_mhzs = sprintf(\"%%d\", $cpu_mhzs);\n\
\n\
# formulate CPU name\n\
#my $cpu_name = $cpu_vend . \" \" . $cpu_modl;\n\
my $cpu_name = $cpu_modl;\n\
\n\
\n\
# collect video information\n\
my $vid_card;\n\
my $vid_drvr;\n\
\n\
foreach my $line (@pciinfo)\n\
{\n\
	if($line =~ m/VGA compatible controller/)\n\
	{\n\
		($vid_card = $line) =~ s/VGA compatible controller://g;\n\
		chop $vid_card;\n\
	}\n\
}\n\
$vid_card =~ s/^\\s{0,}//g;\n\
\n\
foreach my $line (@glxinfo)\n\
{\n\
	if($line =~ m/OpenGL version string:/)\n\
	{\n\
		($vid_drvr = $line) =~ s/OpenGL version string://g;\n\
		chomp $vid_drvr;\n\
	}\n\
}\n\
$vid_drvr =~ s/^\\s{0,}//g;\n\
\n\
\n\
# collect memory information\n\
(my $mem = $meminfo[1]) =~ s/Mem:\\s{0,}(\\d{0,}).*/$1/g;\n\
(my $swp = $meminfo[3]) =~ s/Swap:\\s{0,}(\\d{0,}).*/$1/g;\n\
\n\
# collect scores for form submission\n\
open(UMTMP_LOG, \"<$ulogpath/Benchmark/UMTMP_LOG\") or die \"$1: cannot read $ulogpath/Benchmark/UMTMP_LOG\";\n\
\n\
my @scores = <UMTMP_LOG>;\n\
chomp @scores;\n\
close(UMTMP_LOG);\n\
\n\
print <<'_HTML_';\n\
\n\
<html>\n\
<head>\n\
<title>UMark Results</title>\n\
<link rel=\"stylesheet\" type=\"text/css\" href=\"html/umarks.css\">\n\
</head>\n\
</body>\n\
\n\
<div id=\"headbg\"></div>\n\
<div id=\"header\"></div>\n\
<div id=\"banner\"></div>\n\
<div id=\"neck\">Offline UMark Results</div>\n\
\n\
<div id=\"login\">\n\
<form action=\"http://unrealmark.net/results_linux.php\" method=\"post\">\n\
<input type=\"hidden\" name=\"system_config\"\n\
_HTML_\n\
\n\
print \" value=\\\"\";\n\
\n\
print \"$os_versn|$num_cpus|$cpu_mhzs|$cpu_name|$vid_card|$vid_drvr|$mem|$swp\\\">\\n\";\n\
print \"<input type=\\\"hidden\\\" name=\\\"auth_id\\\" value=\\\"$AUID\\\">\\n\";\n\
print \"<input type=\\\"hidden\\\" name=\\\"exe_hash\\\" value=\\\"$EHSH\\\">\\n\";\n\
\n\
#TODO: count num_maps and post each map\n\
my $mapnum;\n\
my @map;\n\
for($i = 0; $i < @scores; $i++)\n\
{\n\
	@map = split(/\\|/, $scores[$i]);\n\
	$mapnum = $i + 1;\n\
	print \"<input type=\\\"hidden\\\" name=\\\"umark_map$mapnum\\\" \";\n\
	print \"value=\\\"$map[STR_MAP]|$map[STR_BOT]|$map[STR_DTL]|$map[STR_RES]|$map[STR_MIN]|$map[STR_AVG]|$map[STR_MAX]|$map[STR_SCR]|$map[STR_VER]|$map[STR_TYP]|\\\">\\n\";\n\
\n\
	$benchtype = $map[STR_TYP];\n\
}\n\
\n\
my $ini_file_name;\n\
my $ini_user_name;\n\
\n\
if($map[STR_DTL] eq \"Low\")\n\
{\n\
	$ini_file_name = \"UMarkPerformance.ini\";\n\
	$ini_user_name = \"UMarkPerformanceUser.ini\";\n\
}\n\
elsif($map[STR_DTL] eq \"High\")\n\
{\n\
	$ini_file_name = \"UMarkQuality.ini\";\n\
	$ini_user_name = \"UMarkQualityUser.ini\";\n\
}\n\
else\n\
{\n\
	$ini_file_name = \"N/A\";\n\
	$ini_user_name = \"N/A\";\n\
}\n\
(my $ini_file_hash = `md5sum $ulogpath/Benchmark/Stuff/$ini_file_name -t`) =~ s/(.{32}).*/$1/;\n\
(my $ini_user_hash = `md5sum $ulogpath/Benchmark/Stuff/$ini_user_name -t`) =~ s/(.{32}).*/$1/;\n\
\n\
chomp $ini_file_hash;\n\
chomp $ini_user_hash;\n\
\n\
print \"<input type=\\\"hidden\\\" name=\\\"ini_hash\\\" value=\\\"$ini_file_hash\\\">\\n\";\n\
print \"<input type=\\\"hidden\\\" name=\\\"usr_hash\\\" value=\\\"$ini_user_hash\\\">\\n\";\n\
print \"<input type=\\\"hidden\\\" name=\\\"num_maps\\\" value=\\\"$mapnum\\\">\\n\";\n\
\n\
print <<'_HTML_';\n\
\n\
<table cellpadding=\"0\">\n\
<tr>\n\
<td><input type=\"text\" name=\"uname\" maxlength=\"40\" style=\"width: 92px;\"></td>\n\
<td><input type=\"password\" name=\"passwd\" maxlength=\"50\" style=\"width: 92px;\"></td>\n\
<td><input type=\"submit\" value=\"Submit Score\" style=\"width: 92px;\"></td>\n\
</tr><tr>\n\
<td>username</td>\n\
<td>password</td>\n\
<td><a href=\"http://unrealmark.net/register.php\">register</a></td>\n\
</tr></table>\n\
</form>\n\
</div>\n\
\n\
<div id=\"content\">\n\
<div id=\"title\"><img src=\"html/results.png\" alt=\"UMark Results\"></div>\n\
<table class=\"info\" cellspacing=\"0\">\n\
<tr>\n\
<td class=\"ul\"></td>\n\
<td class=\"uc\"></td>\n\
<td class=\"ur\"></td>\n\
</tr><tr>\n\
<td class=\"ml\"></td>\n\
<td class=\"mc\">\n\
\n\
_HTML_\n\
\n\
print \"<h2 align=\\\"center\\\">$benchtype Benchmark</h2>\\n\";\n\
\n\
print \"<h2 style=\\\"margin-bottom: 0px;\\\">System</h2>\";\n\
print \"OS Version: $os_versn<br>\\n\";\n\
print \"Processors: $num_cpus<br>\\nCPU Speed: ~$cpu_mhzs MHz<br>\\nCPU Name: $cpu_name<br>\\n\";\n\
print \"Video Card: $vid_card<br>\\n\";\n\
print \"OpenGL Driver: $vid_drvr<br>\\n\";\n\
print \"Memory: $mem MB<br>\\n\";\n\
print \"Swap File: $swp MB<br><br>\\n\";\n\
\n\
my $total;\n\
\n\
foreach my $line (@scores)\n\
{\n\
	my $highest;\n\
	my $hundred;\n\
	my @calchis;\n\
	my @percent;\n\
	my @map = split(/\\|/, $line);\n\
\n\
	$calchis[0] = $map[STR_MIN];\n\
	$calchis[1] = $map[STR_AVG];\n\
	$calchis[2] = $map[STR_MAX];\n\
	$calchis[3] = $map[STR_SCR];\n\
\n\
	for($i = 0; $i <= 3; $i++)\n\
	{\n\
		if($i == 0)\n\
		{\n\
			$highest = $calchis[$i];\n\
		}\n\
\n\
		if($calchis[$i] > $highest)\n\
		{\n\
			$highest = $calchis[$i];\n\
		}\n\
	}\n\
	for($i = 0; $i <= 3; $i++)\n\
	{\n\
		$hundred = $highest / 100;\n\
		$percent[$i] = $calchis[$i] / $hundred;\n\
	}\n\
\n\
	print \"<h2 style=\\\"margin-bottom: 0px;\\\">$map[STR_MAP]</h2>\\n<b>Build $map[STR_VER]</b><br><br>\\n\";\n\
	print \"Bots: $map[STR_BOT]<br>\\nDetail: $map[STR_DTL]<br>\\nResolution: $map[STR_RES]<br><br>\\n\";\n\
\n\
	print \"<div id=\\\"results\\\">\\n\";\n\
	print \"<div id=\\\"bar\\\" style=\\\"width: $percent[0]%\\\">Min $map[STR_MIN]</div>\\n\";\n\
	print \"<div id=\\\"bar\\\" style=\\\"width: $percent[1]%\\\">Avg $map[STR_AVG]</div>\\n\";\n\
	print \"<div id=\\\"bar\\\" style=\\\"width: $percent[2]%\\\">Max $map[STR_MAX]</div>\\n\";\n\
	print \"<div id=\\\"bar\\\" style=\\\"width: $percent[3]%\\\">Score $map[STR_SCR]</div>\\n\";\n\
	print \"</div>\\n\\n\";\n\
\n\
	$total += $map[STR_SCR];\n\
}\n\
\n\
my $totsize = length($total);\n\
\n\
print \"<center>\\n\";\n\
for($i = 0; $i <= $totsize -1; $i++)\n\
{\n\
	print \"<img src=\\\"html/0\";\n\
	print substr($total,$i,1);\n\
	print \".png\\\">\\n\";\n\
}\n\
print \"<h1 style=\\\"margin-bottom: 24px;\\\">$total UMarks</h1>\\n</center>\\n\";\n\
\n\
print <<'_HTML_';\n\
\n\
</td>\n\
<td class=\"mr\"></td>\n\
</tr><tr>\n\
<td class=\"ll\"></td>\n\
<td class=\"lc\"></td>\n\
<td class=\"lr\"></td>\n\
</tr></table>\n\
<div id=\"foot\">UMark &copy;2004 Jeffrey Bakker. Unreal&#174; Tournament 2004 &copy;2004 Epic games, Inc.</div>\n\
</div>\n\
</body>\n\
</html>\n\
\n\
_HTML_\n"
/***** END PERL BLOCK ********************************************************/


#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <sys/stat.h>
#include <gtk/gtk.h>
#include <stdio.h>

#include "callbacks.h"
#include "interface.h"
#include "support.h"


#define	DTL_LO	2
#define	DTL_HI	3
#define	DTL_CR	0
#define	DTL_CS	1

#define AUGMENT 0x3a

/* resolution */
enum
{
	RES_640	= 0,
	RES_800,
	RES_1024,
	RES_1280,
	RES_1600
};
/* presets */
enum
{
	PRE_BM	= 1,
	PRE_FB,
	PRE_DM,
	PRE_D4,
	PRE_DE,
	PRE_EG,
	PRE_U3,
	PRE_U4,
	PRE_TD
};
/* columns */
enum
{
	COL_MAP	= 0,
	COL_BOT,
	COL_DTL,
	COL_RES,
	COL_MIN,
	COL_AVG,
	COL_MAX,
	COL_SCR,
	COL_VER,
	COL_TYP
};
/* results */
struct UResults
{
	char	Map[44];
	int	Bot;
	int	Res;
	int	Dtl;
	double	Min;
	double	Avg;
	double	Max;
	double	Scr;
	int	Ver;
	int	Typ;
};


/* additional dialogs */
GtkWidget*	UMsgBox;
GtkWidget*	ConfBox;
GtkWidget*	AboutBox;
GtkWidget*	PresetsBox;
GtkWidget*	ResultsBox;


/* main window data */
gboolean	run_batch	= TRUE;
gboolean	fullscreen	= TRUE;
gboolean	res640x480	= FALSE;
gboolean	res800x600	= FALSE;
gboolean	res1024x768	= FALSE;
gboolean	res1280x1024	= FALSE;
gboolean	res1600x1200	= FALSE;

gboolean	dotimedemo	= FALSE;

gchar*		Command;
gchar*		inifile	= "";
gchar*		iniuser = "";
gchar*		strres	= "";
gchar*		strdtl	= "";
gchar*		map	= "";
gchar*		utver	= "";	/* ut2003, ut2004, etc */
gchar*		utdir	= "";	/* ut200x install dir */
gchar*		utpath	= "";	/* $HOME/.ut200x */
gchar*		bswitch = "";


gchar*		instdir1;
gchar*		instdir2;
gchar*		instdir3;
gchar*		instdir4;

gint		builds[4];
gint		build = 0;
gint		numbots	= 12;
gint		detail	= DTL_CR;

/* presets data */
gint		presetchosen	= 0;


/* gtktreeview */
/*GtkListStore	*lsBatchList;
*/
GtkListStore	*lsResultList;


/*** error messages **********************************************************/
void
umark_message_dialog(gchar* message)
{
	GtkLabel	*label;

	UMsgBox = create_MsgDlg();
	label = GTK_LABEL( lookup_widget(GTK_WIDGET(UMsgBox), "lblMsgDlg") );

	gtk_label_set_text(label, message);
	gtk_dialog_run(GTK_DIALOG(UMsgBox));

	gtk_widget_destroy(GTK_WIDGET(UMsgBox));
}


/*** init dialog *************************************************************/
static GtkTreeModel *
create_fill_resultlist(void)
{
	GtkListStore	*store;
	GtkTreeIter	iter;

	store = gtk_list_store_new(10, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_INT, G_TYPE_STRING);

	return GTK_TREE_MODEL(store);
}

static GtkWidget*
create_model_resultlist(GtkWidget *TVRL)
{
	GtkTreeSelection	*selection;

	GtkTreeViewColumn	*col;
	GtkCellRenderer		*renderer;
	GtkTreeModel		*model;
	GtkWidget		*view;

	view = TVRL; /* gtk_tree_view_new(); */

	renderer = gtk_cell_renderer_text_new();
	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
							-1,
							"Map",
							renderer,
							"text", COL_MAP,
							NULL);

	col = gtk_tree_view_column_new();
	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
							-1,
							"Bots",
							renderer,
							"text", COL_BOT,
							NULL);

	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
							-1,
							"Detail",
							renderer,
							"text", COL_DTL,
							NULL);

	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
							-1,
							"Resolution",
							renderer,
							"text", COL_RES,
							NULL);

	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
							-1,
							"Min FPS",
							renderer,
							"text", COL_MIN,
							NULL);

	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
							-1,
							"Avg FPS",
							renderer,
							"text", COL_AVG,
							NULL);

	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
							-1,
							"Max FPS",
							renderer,
							"text", COL_MAX,
							NULL);

	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
							-1,
							"Score",
							renderer,
							"text", COL_SCR,
							NULL);

	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
							-1,
							"Build",
							renderer,
							"text", COL_VER,
							NULL);

	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
							-1,
							"Type",
							renderer,
							"text", COL_TYP,
							NULL);

	model = create_fill_resultlist();

	selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(view) );
	gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);

	gtk_tree_view_set_model(GTK_TREE_VIEW(view), model);
	g_object_unref(model);

	return view;
}


/*** benchmark options *******************************************************/
void
on_spnbots_changed                     (GtkEditable     *editable,
                                        gpointer         user_data)
{
	/* FIXME: now crashes after choosing flyby, it now calls this function twice */

	if(numbots == 1 && atoi(gtk_entry_get_text(GTK_ENTRY(editable))) < 1)
	{
		gchar*		FlybyMsg;

		FlybyMsg = "With Zero bots selected, flyby benchmark is enabled. However, not all maps support automated flyby paths. Run the flyby preset tests to use supported maps.";
/*		umark_message_dialog(FlybyMsg);
*/	}
	numbots = atoi(gtk_entry_get_text(GTK_ENTRY(editable)));
}


void
on_version_changed                     (GtkComboBox     *combobox,
                                        gpointer         user_data)
{

/*
default paths:

Demo
2206 /usr/local/games/ut2003_demo/ut2003_demo symlink ut2003_demo config $HOME/.ut2003
3334 /usr/local/games/ut2004demo/ut2004-demo symlink ut2004 config $HOME/.ut2004demo

Retail
2107 /usr/local/games/ut2003/ut2003 symlink ut2003 config $HOME/.ut2003
3186 /usr/local/games/ut2004//ut2004 symlink ut2004 config $HOME/.ut2004
*/
	GtkWidget	*UMarkDialog;
	GtkComboBox	*cbMaps;
	GtkTreeModel	*cbTmod;

	FILE		*MapList;
	gchar		*lcurmap;
	gchar		*MapPath;
	gchar		*LogPath;
	char		buffer;

	gchar		*umarkrc;
	gchar		*line;
	gint		lnum;
	FILE		*RCFILE;

	/* set game paths */
	GtkWidget *W = GTK_BIN(combobox)->child;
	utver = (gchar *)gtk_entry_get_text( GTK_ENTRY(W) );
	if(strcmp(utver, "Uninitialized") == 0)
	{
		return;
	}

	/* game config home paths */
	if(strcmp(utver, "ut2003_demo") == 0)
	{
		utpath = g_strdup_printf("%s/.%s", getenv("HOME"), "ut2003");
	}
	else
	if(strcmp(utver, "ut2004-demo") == 0)
	{
		utpath = g_strdup_printf("%s/.%s", getenv("HOME"), "ut2004demo");
	}
	else
	utpath = g_strdup_printf("%s/.%s", getenv("HOME"), utver);

	/* game install paths */
	umarkrc = g_strdup_printf("%s/.umarkrc", getenv("HOME"));
	if((RCFILE = fopen(umarkrc, "r")) == NULL)
	{
		gchar* FOpenErrMsg = "Could not find the UMark config file. Please run the UMark/install_umark_data.sh script.";
		umark_message_dialog(FOpenErrMsg);
	}
	else
	{
		line = "";
		lnum = 0;

		while((buffer = getc(RCFILE)) != EOF)
		{
			if(buffer == '\n')
			{
				if(lnum == 0 && strcmp(line, "n/a|n/a") != 0)
				{
					instdir1 = line;
				}
				else
				if(lnum == 1 && strcmp(line, "n/a|n/a") != 0)
				{
					instdir2 = line;
				}
				else
				if(lnum == 2 && strcmp(line, "n/a|n/a") != 0)
				{
					instdir3 = line;
				}
				else
				if(lnum == 3 && strcmp(line, "n/a|n/a") != 0)
				{
					instdir4 = line;
				}
				line = "";
				lnum++;
			}
			else
			if(buffer == '|')
			{
				builds[lnum] = atoi(line);
				line = "";
			}
			else
			{
				line = g_strdup_printf("%s%c", line, buffer);
			}
		}
		fclose(RCFILE);
	}

	if(strcmp(utver, "ut2003") == 0)
	{
		utdir = instdir1;
		build = builds[0];
	}
	else
	if(strcmp(utver, "ut2004") == 0)
	{
		utdir = instdir2;
		build = builds[1];

		utver = g_strdup_printf("%s/%s", utdir, utver);
	}
	else
	if(strcmp(utver, "ut2003_demo") == 0)
	{
		utdir = instdir3;
		build = builds[2];
	}
	else
	if(strcmp(utver, "ut2004-demo") == 0)
	{
		utdir = instdir4;
		build = builds[3];

		utver = g_strdup_printf("%s/%s", utdir, utver);
	}

/** TEST
	GtkWidget* FOpenErrBox;
	FOpenErrBox = gnome_ok_dialog(utdir);
	gtk_widget_show(FOpenErrBox);
**/

	UMarkDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(combobox)));
	cbMaps = GTK_COMBO_BOX(lookup_widget(UMarkDialog , "CmbMaps"));
	cbTmod = GTK_TREE_MODEL(gtk_combo_box_get_model(cbMaps));

	if(dotimedemo)
	{
		dotimedemo = !dotimedemo;
		on_chkTimeDemo_clicked(GTK_BUTTON(lookup_widget(UMarkDialog, "chkTimeDemo")), user_data);
		return;
	}

/*	g_object_set(GTK_WIDGET(cbMaps), "appears-as-list", TRUE, NULL);
*/	gtk_list_store_clear(GTK_LIST_STORE(cbTmod));

	MapPath = g_strdup_printf("ls -1 %s/Maps | grep \"AS-\\|BR-\\|CTF-\\|DM-\\|DOM-\\|MOV-\\|ONS-\" >%s/Benchmark/.UMMAP_LST", utdir, utpath);
	system(MapPath);
	g_free(MapPath);
	MapPath = g_strdup_printf("%s/Benchmark/.UMMAP_LST", utpath);
	MapList = fopen(MapPath, "r");

	lcurmap = "";

	while((buffer = getc(MapList)) != EOF)
	{
		if(buffer != '\n')
		{
			lcurmap = g_strdup_printf("%s%c", lcurmap, buffer); /* TODO: find a better way to append */
		}
		else
		{
			gtk_combo_box_append_text(GTK_COMBO_BOX(cbMaps), lcurmap);
			g_free(lcurmap);
			lcurmap = "";
		}
	}
	fclose(MapList);
	remove(MapPath);
	g_free(MapPath);

/*
	if(strcmp(map,"") != 0)
	{
		g_free(map);
		map = "";
	}
*/
}


void
on_chkfullscr_toggled                   (GtkToggleButton *togglebutton,
                                        gpointer         user_data)
{
	fullscreen = !fullscreen;
}


void
on_maps_changed                        (GtkComboBox     *combobox,
                                        gpointer         user_data)
{
/*	if(strcmp(map,"") != 0)
	{
		g_free(map);
	}
*/
	GtkWidget* W = GTK_BIN(combobox)->child;
	map = (gchar *)gtk_entry_get_text( GTK_ENTRY(W) );
}


/*** benchmarking code *******************************************************/
gboolean
foreach_batchlist_benchmark(	GtkTreeModel	*model,
				GtkTreePath	*path,
				GtkTreeIter	*iter,
				gpointer	user_data)
{
	GtkWidget	*UMarkDialog;
	gchar*		rm_file;

	gtk_tree_model_get(model, iter, 0, &map, -1);

	run_batch = TRUE;

	if(dotimedemo)
	{
		rm_file = g_strdup_printf("%s/Benchmark/benchmark.log", utpath);
	}
	else
	{
		rm_file = g_strdup_printf("%s/Benchmark/lowframerate.log", utpath);
	}
	remove(rm_file);
	g_free(rm_file);
	run_benchmark();

/*	g_free(map);
*/
	return FALSE;
}

void
on_btnbenchmark_clicked                (GtkButton       *button,
                                        gpointer         user_data)
{
	gint	res;
	gchar*	rm_file;

/*	GtkProgressBar	*pBar; */
	GtkWidget	*UMarkDialog;
	GtkListStore	*lsBatchList;
	GtkTreeIter	iter;

	UMarkDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	lsBatchList = GTK_LIST_STORE( gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(UMarkDialog , "tvBatchList"))) );
/*	pBar = GTK_PROGRESS_BAR(lookup_widget(UMarkDialog, "batchprogress")); */

	run_batch = FALSE;
	gboolean res_check = FALSE;

	bswitch = "1";

	if(res640x480)   res_check = TRUE;
	if(res800x600)   res_check = TRUE;
	if(res1024x768)  res_check = TRUE;
	if(res1280x1024) res_check = TRUE;
	if(res1600x1200) res_check = TRUE;

	if(!res_check)
	{
		gchar* BenchErrBox = "Please select a resolution in which to run the benchmark.";
		umark_message_dialog(BenchErrBox);
		return;
	}

	if(strcmp(utver,"ut2003") == 0 || strcmp(utver,"ut2003_demo") == 0)
	{
		bswitch = "true";
	}
	else
	if(strcmp(utver,"ut2004") == 0)
	{
		bswitch = "1";
	}

	/* run the benchmark for each resolution selected */
	for(res = RES_640; res <= RES_1600; res++)
	{
		switch(res)
		{
			case RES_640:  if(res640x480)   strres = "-640x480";   break;
			case RES_800:  if(res800x600)   strres = "-800x600";   break;
			case RES_1024: if(res1024x768)  strres = "-1024x768";  break;
			case RES_1280: if(res1280x1024) strres = "-1280x1024"; break;
			case RES_1600: if(res1600x1200) strres = "-1600x1200"; break;
		}

		if(strres != "")
		{
/*			gtk_progress_bar_set_fraction(pBar, 0.0); */
			gtk_tree_model_foreach(GTK_TREE_MODEL(lsBatchList), foreach_batchlist_benchmark, NULL);

			if(!run_batch)
			{
				if(strcmp(map,"") == 0)
				{
					gchar* BenchErrBox = "You must select a map to benchmark.";
					umark_message_dialog(BenchErrBox);
					return;
				}

				/* clear previous log entries */
				if(dotimedemo)
				{
					rm_file = g_strdup_printf("%s/Benchmark/benchmark.log", utpath);
				}
				else
				{
					rm_file = g_strdup_printf("%s/Benchmark/lowframerate.log", utpath);
				}
				remove(rm_file);
				g_free(rm_file);

				run_benchmark();
			}
		}
		strres = "";
	}
	ResultsBox = create_ResultsDlg();
	create_model_resultlist(lookup_widget( GTK_WIDGET(ResultsBox), "tvResults") );

	read_results_log(button);
	gtk_widget_show(ResultsBox);
}


void
run_benchmark()
{
	/* .ini files and exec files need to be moved to the ut home dirs */

	strdtl = "";

	switch(detail)
	{
		case DTL_LO: strdtl = g_strdup_printf(" -ini=%s/System/UMarkPerformance.ini -userini=%s/System/UMarkPerformanceUser.ini", utpath, utpath); break;
		case DTL_HI: strdtl = g_strdup_printf(" -ini=%s/System/UMarkQuality.ini -userini=%s/System/UMarkQualityUser.ini", utpath, utpath); break;
		case DTL_CS: strdtl = g_strdup_printf(" -ini=%s -userini=%s", inifile, iniuser); break;
		default	: break;
	}
	if(dotimedemo)
	{
		gchar	*tdfile;
		FILE	*UMarkTime;

		/* TODO: Timedemos are also currently only tested in UT2004 */

		/* create UMarkTime.txt file */
		tdfile = g_strdup_printf("%s/Benchmark/Stuff/UMarkTime.txt", utpath);

		if((UMarkTime = fopen(tdfile, "w")) == NULL)
		{
			umark_message_dialog(tdfile);
			return;
		}
		fprintf(UMarkTime, "demoplay %s?timedemo\nship\nstat fps", map);
		fclose(UMarkTime);

		if(build >= 3000)
		{
			Command = g_strdup_printf("%s -exitafterdemo -benchmark -nosound -seconds=77 -exec=%s/Benchmark/Stuff/UMarkTime.txt", utver, utpath);
		}
		else
		{
			Command = g_strdup_printf("%s -exitafterdemo -benchmark -nosound -exec=%s/Benchmark/Stuff/UMarkTime.txt", utver, utpath);
		}
		presetchosen = PRE_TD;
	}
	else
	if(numbots == 0)
	{
		Command = g_strdup_printf("%s %s?game=engine.gameinfo -benchmark -seconds=77 -nosound -exec=%s/Benchmark/Stuff/UMarkFly.txt %s %s",
					utver, map, utpath, strdtl, strres);
	}
	else
	{
		Command = g_strdup_printf("%s %s?spectatoronly=%s?numbots=%d?quickstart=%s?attractcam=%s -benchmark -seconds=77 -nosound -exec=%s/Benchmark/Stuff/UMarkBot.txt %s %s",
					utver, map, bswitch, numbots, bswitch, bswitch, utpath, strdtl, strres);
	}

	if(!fullscreen)
	{
		Command = g_strconcat(Command, " -windowed", NULL);
	}


/* TEST
	gchar* test = g_strdup_printf("Executing: %s", Command);
	umark_message_dialog(test);
	g_free(test);
*/

	system(Command);

	if(dotimedemo)
	{
		write_log_td();
	}
	else
	{
		write_log();
	}
}


void
write_log()
{
	int	lines;
	char	buffer;
	FILE*	UTLog;
	FILE*	UMarkLog;

	gchar*	logfile_name;
	gchar*	umarklog_name;
	gchar*	logdetail;
	gchar*	logres;
	gchar*	btype;

	lines = 0;

	logfile_name = g_strdup_printf("%s/Benchmark/lowframerate.log", utpath);
	umarklog_name = g_strdup_printf("%s/Benchmark/UMTMP_LOG", utpath);

	if((UTLog = fopen(logfile_name, "r")) == NULL)
	{
		umark_message_dialog(logfile_name);
		return;
	}
	if((UMarkLog = fopen(umarklog_name, "a")) == NULL)
	{
		umark_message_dialog(umarklog_name);
		return;
	}
	g_free(logfile_name);
	g_free(umarklog_name);

	// detail level string
	switch(detail)
	{
		case DTL_LO :	logdetail = "Low"; break;
		case DTL_HI :	logdetail = "High"; break;
		case DTL_CS :	logdetail = "Custom"; break;
		default	:	logdetail = "Current"; break;
	}

	// resolution string
	if(strcmp(strres, "-640x480") == 0)
	{
		logres = "640x480";
	}
	else
	if(strcmp(strres, "-800x600") == 0)
	{
		logres = "800x600";
	}
	else
	if(strcmp(strres, "-1024x768") == 0)
	{
		logres = "1024x768";
	}
	else
	if(strcmp(strres, "-1280x1024") == 0)
	{
		logres = "1280x1024";
	}
	else
	if(strcmp(strres, "-1600x1200") == 0)
	{
		logres = "1600x1200";
	}

	switch(presetchosen)
	{
		case PRE_BM: btype = "UT2003 Botmatch"; break;
		case PRE_FB: btype = "UT2003 Flyby"; break;
		case PRE_DM: btype = "UT2003 Demo"; break;
		case PRE_D4: btype = "UT2004 Demo"; break;
		case PRE_DE: btype = "DE Bonus Pack"; break;
		case PRE_EG: btype = "Epic Bonus Pack"; break;
		case PRE_U3: btype = "UMark 2003"; break;
		case PRE_U4: btype = "UMark 2004"; break;
		default: btype = "Custom";
	}

	// read lowframerate.log and write a reformatted umark temp log
	while((buffer = getc(UTLog)) != EOF)
	{
		if(buffer == '\n') lines++;

		if(lines == 0)
		{
			if(buffer != '\n' && buffer != '\r')
			{
				putc(buffer, UMarkLog);
			}
		}
		else
		if(lines == 3)
		{
			/* do nothing */
		}
		else
		if(lines == 1 && buffer == '\n')
		{
			fprintf(UMarkLog, "|%d|%s|%s|", numbots, logdetail, logres);
		}
		else
		{
			switch(buffer)
			{
				case  'c':
				case  'e':
				case  'f':
				case  'o':
				case  'p':
				case  'r':
				case  's':
				case  'S':
				case  '=':
				case '\r':
				case  ' ': break;
				case  '/':
				case '\n': putc('|', UMarkLog); break;
				default  : putc(buffer, UMarkLog); break;
			}
		}
	}
	fprintf(UMarkLog, "%d|%s\n", build, btype);

	fclose(UTLog);
	fclose(UMarkLog);
}


void
write_log_td()
{
	char	buffer;
	FILE*	UTLog;
	FILE*	UMarkLog;

	gchar*	logfile_name;
	gchar*	umarklog_name;
	gchar*	logdetail;
	gchar*	logres;
	gchar*	btype;

	logfile_name = g_strdup_printf("%s/Benchmark/benchmark.log", utpath);
	umarklog_name = g_strdup_printf("%s/Benchmark/UMTMP_LOG", utpath);

	if((UTLog = fopen(logfile_name, "r")) == NULL)
	{
		umark_message_dialog(logfile_name);
		return;
	}
	if((UMarkLog = fopen(umarklog_name, "a")) == NULL)
	{
		umark_message_dialog(umarklog_name);
		return;
	}
	g_free(logfile_name);
	g_free(umarklog_name);

	// detail level string
	switch(detail)
	{
		case DTL_LO :	logdetail = "Low"; break;
		case DTL_HI :	logdetail = "High"; break;
		case DTL_CS :	logdetail = "Custom"; break;
		default	:	logdetail = "Current"; break;
	}

	// resolution string
	if(strcmp(strres, "-640x480") == 0)
	{
		logres = "640x480";
	}
	else
	if(strcmp(strres, "-800x600") == 0)
	{
		logres = "800x600";
	}
	else
	if(strcmp(strres, "-1024x768") == 0)
	{
		logres = "1024x768";
	}
	else
	if(strcmp(strres, "-1280x1024") == 0)
	{
		logres = "1280x1024";
	}
	else
	if(strcmp(strres, "-1600x1200") == 0)
	{
		logres = "1600x1200";
	}
	btype = "Timedemo";

	fprintf(UMarkLog, "%s|-1|%s|%s|-1|-1|-1|", map, logdetail, logres);

	// read benchmark.log and write a reformatted umark temp log
	while((buffer = getc(UTLog)) != ' ')
	{
		putc(buffer, UMarkLog);
	}
	fprintf(UMarkLog, "|%d|%s\n", build, btype);

	fclose(UTLog);
	fclose(UMarkLog);
}


void
read_results_log(GtkButton *button)
{
	FILE		*UMTmpLog;
	gchar		*umarklog;
	gchar		*strtmp;
	char		buffer;
	int		colnum;

	gint		itmp;
	gdouble		dtmp;

	GtkWidget	*ResultsDialog;
	GtkListStore	*lsResultList;
	GtkTreeIter	iter;

	ResultsDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	lsResultList = GTK_LIST_STORE(gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(ResultsBox , "tvResults")) ));

	umarklog = g_strdup_printf("%s/Benchmark/UMTMP_LOG", utpath);
	if((UMTmpLog = fopen(umarklog, "r")) == NULL)
	{
		gchar* FOpenErrBox = "ERROR: Could not read the UMTMP_LOG file.";
		umark_message_dialog(FOpenErrBox);
		return;
	}

	gtk_list_store_clear(GTK_LIST_STORE(lsResultList));
	strtmp = "";
	colnum = 0;

	gtk_list_store_append(lsResultList, &iter);

	while(( buffer = getc(UMTmpLog) ) != EOF)
	{
		if(buffer == '\n')
		{
			gtk_list_store_set(lsResultList, &iter, COL_TYP, strtmp, -1);

			/* new map in log */
			gtk_list_store_append (lsResultList, &iter);
			strtmp = "";
			colnum = 0;
		}
		else
		if(buffer == '|')
		{
			/* next column in log */
			switch(colnum)
			{
				case COL_VER:
				case COL_BOT: gtk_list_store_set(lsResultList, &iter, colnum, atoi(strtmp), -1); break;
				case COL_MIN:
				case COL_AVG:
				case COL_MAX:
				case COL_SCR: gtk_list_store_set(lsResultList, &iter, colnum, g_strtod(strtmp, NULL), -1); break;
				default: gtk_list_store_set(lsResultList, &iter, colnum, strtmp, -1);
			}
			strtmp = "";
			colnum++;
		}
		else
		{
			strtmp = g_strdup_printf("%s%c", strtmp, buffer); /* TODO: use a better method for appending */
		}
	}
	fclose(UMTmpLog);
	g_free(umarklog);

	gtk_list_store_remove(lsResultList, &iter);
}


void
on_btnresults_clicked                  (GtkButton       *button,
                                        gpointer         user_data)
{
	ResultsBox = create_ResultsDlg();
	create_model_resultlist(lookup_widget( GTK_WIDGET(ResultsBox), "tvResults") );

/* TEST
	read_results_log(button);
*/
	gtk_widget_show(ResultsBox);
}


void
on_btnabout_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
	AboutBox = create_AboutDlg();
	gtk_widget_show(AboutBox);
}


void
on_btnquit_clicked                     (GtkButton       *button,
                                        gpointer         user_data)
{
	/* TODO: free up unfreed non-constant assigned gchar* variables */
	if(strcmp(utdir, "") != 0)	g_free(utdir);
	if(strcmp(utpath, "") != 0)	g_free(utpath);

	gtk_main_quit();
}


/*** resolution checkboxes ***************************************************/
void
on_chkres640_toggled                   (GtkToggleButton *togglebutton,
                                        gpointer         user_data)
{
	res640x480 = !res640x480;
}


void
on_chkres800_toggled                   (GtkToggleButton *togglebutton,
                                        gpointer         user_data)
{
	res800x600 = !res800x600;
}


void
on_chkres1024_toggled                  (GtkToggleButton *togglebutton,
                                        gpointer         user_data)
{
	res1024x768 = !res1024x768;
}


void
on_chkres1280_toggled                  (GtkToggleButton *togglebutton,
                                        gpointer         user_data)
{
	res1280x1024 = !res1280x1024;
}


void
on_chkres1600_toggled                  (GtkToggleButton *togglebutton,
                                        gpointer         user_data)
{
	res1600x1200 = !res1600x1200;
}


/*** detail selection ********************************************************/
void
on_raddtllow_clicked                   (GtkButton       *button,
                                        gpointer         user_data)
{
	detail = DTL_LO;
}


void
on_raddtlhigh_clicked                  (GtkButton       *button,
                                        gpointer         user_data)
{
	detail = DTL_HI;
}


void
on_raddtlcurrent_clicked               (GtkButton       *button,
                                        gpointer         user_data)
{
	detail = DTL_CR;
}


void
on_raddtlcustom_clicked                (GtkButton       *button,
                                        gpointer         user_data)
{
	detail = DTL_CS;
}

/*
void
on_fileentryini_changed                (GtkEditable     *editable,
                                        gpointer         user_data)
{
	inifile = (gchar *)gtk_entry_get_text(GTK_ENTRY(editable));
}
*/

void
on_btnarrow_clicked                   (GtkButton       *button,
                                        gpointer         user_data)
{
	on_btnadd_clicked(button, user_data);
}

/*** batch map list controls *************************************************/
void
on_btnpreset_clicked                   (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget	*UMarkDialog;
	GtkListStore	*lsBatchList;
	GtkTreeIter	iter;

	presetchosen = -1;
	PresetsBox = create_PresetDlg();

	if(gtk_dialog_run(GTK_DIALOG(PresetsBox)) == GTK_RESPONSE_OK)
	{
		UMarkDialog = GTK_WIDGET( gtk_widget_get_toplevel(GTK_WIDGET(button)) );
		lsBatchList = GTK_LIST_STORE(gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(UMarkDialog , "tvBatchList")) ));

		if(presetchosen == 0)
		{
			return;
		}

		if(presetchosen < 0)
		{
			gtk_list_store_clear(GTK_LIST_STORE(lsBatchList));
		}

		if(presetchosen == PRE_BM || presetchosen == -PRE_BM)
		{
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Antalus", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "BR-Anubis", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Asbestos", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-Citadel", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Inferno", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DOM-Suntemple", -1);
		}
		if(presetchosen == PRE_FB || presetchosen == -PRE_FB)
		{
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Antalus", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Asbestos", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-Citadel", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-Face3", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Inferno", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Phobos2", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DOM-Suntemple", -1);
		}
		if(presetchosen == PRE_DM || presetchosen == -PRE_DM)
		{
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Antalus", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "BR-Anubis", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Asbestos", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-Citadel", -1);
		}
		if(presetchosen == PRE_D4 || presetchosen == -PRE_D4)
		{
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "AS-Convoy", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "BR-Colossus", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-BridgeOfFate", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Rankin", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "ONS-Torlan", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-FaceClassic", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "ONS-Primeval", -1);
		}
		if(presetchosen == PRE_DE || presetchosen == -PRE_DE)
		{
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-DE-ElecFields", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-DE-GrendelKeep", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-DE-LavaGiant2", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-DE-Ironic", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-DE-Osiris2", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "BR-DE-ElecFields", -1);
		}
		if(presetchosen == PRE_EG || presetchosen == -PRE_EG)
		{
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-IronDeity", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-IceTomb", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "BR-Canyon", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DOM-Junkyard", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Rustatorium", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-1on1-Crash", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-1on1-Mixer", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Injector", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-Avaris", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-DoubleDamage", -1);
		}
		if(presetchosen == PRE_U3 || presetchosen == -PRE_U3)
		{
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "BR-IceFields", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Inferno", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-Maul", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-Magma", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DOM-Ruination", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "BR-Slaughterhouse", -1);
		}
		if(presetchosen == PRE_U4 || presetchosen == -PRE_U4)
		{
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "AS-FallenCity", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "BR-Slaughterhouse", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "CTF-MoonDragon", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DM-Inferno", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "DOM-Ruination", -1);
			gtk_list_store_append(lsBatchList, &iter);
			gtk_list_store_set(lsBatchList, &iter, 0, "ONS-Dawn", -1);
		}
	}
	gtk_widget_destroy(PresetsBox);
}


void
on_btnmoveup_clicked                   (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget	*UMarkDialog;
	GtkListStore	*lsBatchList;
	GtkTreeIter	iter;

	GtkTreeSelection *select;

	UMarkDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	lsBatchList = GTK_LIST_STORE(gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(UMarkDialog , "tvBatchList")) ));

	select = gtk_tree_view_get_selection(GTK_TREE_VIEW(lookup_widget(UMarkDialog , "tvBatchList")));
	gtk_tree_selection_get_selected(select, (GtkTreeModel **)&lsBatchList, &iter);

	gtk_list_store_move_after(lsBatchList, &iter, NULL);
}


void
on_btnmovedown_clicked                 (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget	*UMarkDialog;
	GtkListStore	*lsBatchList;
	GtkTreeIter	iter;

	GtkTreeSelection *select;

	UMarkDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	lsBatchList = GTK_LIST_STORE(gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(UMarkDialog , "tvBatchList")) ));

	select = gtk_tree_view_get_selection(GTK_TREE_VIEW(lookup_widget(UMarkDialog , "tvBatchList")));
	gtk_tree_selection_get_selected(select, (GtkTreeModel **)&lsBatchList, &iter);

	gtk_list_store_move_before(lsBatchList, &iter, NULL);
}


void
on_btnadd_clicked                      (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget	*UMarkDialog;
	GtkListStore	*lsBatchList;
	GtkTreeIter	iter;

	UMarkDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	lsBatchList = GTK_LIST_STORE(gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(UMarkDialog , "tvBatchList")) ));

	gtk_list_store_append(lsBatchList, &iter);
	gtk_list_store_set(lsBatchList, &iter, 0, map, -1);

	presetchosen = 0;
}


void
on_btnremove_clicked                   (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget	*UMarkDialog;
	GtkListStore	*lsBatchList;
	GtkTreeIter	iter;

	GtkTreeSelection *select;

	UMarkDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	lsBatchList = GTK_LIST_STORE(gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(UMarkDialog , "tvBatchList")) ));

	select = gtk_tree_view_get_selection(GTK_TREE_VIEW(lookup_widget(UMarkDialog , "tvBatchList")));
	gtk_tree_selection_get_selected(select, (GtkTreeModel **)&lsBatchList, &iter);
	gtk_list_store_remove(GTK_LIST_STORE(lsBatchList), &iter);

	presetchosen = 0;
}


void
on_btnclear_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget	*UMarkDialog;
	GtkListStore	*lsBatchList;

	UMarkDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	lsBatchList = GTK_LIST_STORE(gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(UMarkDialog , "tvBatchList")) ));

	gtk_list_store_clear(GTK_LIST_STORE(lsBatchList));

	presetchosen = 0;
}


void
on_btnloadlist_clicked                 (GtkButton       *button,
                                        gpointer         user_data)
{
	char	buffer;
	gchar	*listfile;
	gchar	*lcurmap;

	GtkWidget *OpenDlg;
	FILE *MapList;

	GtkWidget	*UMarkDialog;
	GtkListStore	*lsBatchList;
	GtkTreeIter	iter;

	UMarkDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	lsBatchList = GTK_LIST_STORE(gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(UMarkDialog , "tvBatchList")) ));

	OpenDlg = gtk_file_chooser_dialog_new(
		"Open Map List", NULL,
		GTK_FILE_CHOOSER_ACTION_OPEN,
		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
		GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
		NULL);

	if(gtk_dialog_run(GTK_DIALOG(OpenDlg)) == GTK_RESPONSE_ACCEPT)
	{
		listfile = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(OpenDlg));

		if((MapList = fopen(listfile, "r")) == NULL)
		{
			gchar* FOpenErrBox = "ERROR: Could not open the file.";
			umark_message_dialog(FOpenErrBox);
			return;
		}
		lcurmap = "";

		while((buffer = getc(MapList)) != EOF)
		{
			if(buffer != '\n')
			{
				lcurmap = g_strdup_printf("%s%c", lcurmap, buffer);
			}
			else
			{
				gtk_list_store_append(lsBatchList, &iter);
				gtk_list_store_set(lsBatchList, &iter, 0, lcurmap, -1);

				g_free(lcurmap);
				lcurmap = "";
			}
		}
		fclose(MapList);
		g_free(listfile);
	}
	gtk_widget_destroy(OpenDlg);

	presetchosen = 0;
}


gboolean
foreach_batchlist_save(	GtkTreeModel	*model,
			GtkTreePath	*path,
			GtkTreeIter	*iter,
			gpointer	user_data)
{
	gchar	*lcurmap;

	gtk_tree_model_get(model, iter, 0, &lcurmap, -1);
	fprintf(user_data, "%s\n", lcurmap);
	g_free(lcurmap);

	return FALSE;
}


void
on_btnsavelist_clicked                 (GtkButton       *button,
                                        gpointer         user_data)
{
	gchar		*lcurmap;
	gchar		*listfile;
	FILE		*MapList;
	GtkWidget	*SaveDlg;

	GtkWidget	*UMarkDialog;
	GtkListStore	*lsBatchList;
	GtkTreeModel	*tmBatchList;
	GtkTreePath	*tpBatchList;

	UMarkDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	tmBatchList = gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(UMarkDialog, "tvBatchList")) );

/*	TODO: rows, not columns
	if(gtk_tree_model_get_n_columns(tmBatchList) == 0)
	{
		GtkWidget* BlErrBox;
		BlErrBox = gnome_ok_dialog("There are no maps in the list to save.");
		gtk_widget_show(BlErrBox);

		return;
	}
*/
	SaveDlg = gtk_file_chooser_dialog_new(
		"Save Map List", NULL,
		GTK_FILE_CHOOSER_ACTION_SAVE,
		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
		GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
		NULL);

	if(gtk_dialog_run(GTK_DIALOG(SaveDlg)) == GTK_RESPONSE_ACCEPT)
	{
		listfile = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(SaveDlg));

		if((MapList = fopen(listfile, "w")) == NULL)
		{
			gchar* FOpenErrBox = "ERROR: Could not open the file.";
			umark_message_dialog(FOpenErrBox);
			return;
		}
		gtk_tree_model_foreach(GTK_TREE_MODEL(tmBatchList), foreach_batchlist_save, MapList);

		fclose(MapList);
		g_free(listfile);
	}
	gtk_widget_destroy(SaveDlg);
}


/*** results dialog controls *************************************************/
/*
void
compare_foreach_pass_highest		(GtkTreeModel	*model,
					 GtkTreePath	*path,
					 GtkTreeIter	*iter,
					 gpointer	data)
{
	gdouble fps;

	gtk_tree_model_get(model, iter, COL_MAP, &fps, -1);

	if(fps > *data)
	{
		*data = fps;
	}

}


void
compare_foreach_pass_hundred		(GtkTreeModel	*model,
					 GtkTreePath	*path,
					 GtkTreeIter	*iter,
					 gpointer	data)
{

}
*/

void
on_btncompare_clicked                  (GtkButton       *button,
                                        gpointer         user_data)
{
	gdouble *highest;
	gdouble *hundred;
	gdouble	*percent;

	highest = malloc(sizeof(gdouble));
	hundred = malloc(sizeof(gdouble));
	percent = malloc(sizeof(gdouble));

	struct UResults Rlt;
	struct UResults *pRlt;

	pRlt = &Rlt;

	GtkTreeSelection *selection;

	GtkWidget	*ResultsDialog;
	GtkListStore	*lsResultList;
	GtkTreeIter	iter;

	ResultsDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	lsResultList = GTK_LIST_STORE(gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(ResultsDialog , "tvResults")) ));
	selection = GTK_TREE_SELECTION( gtk_tree_view_get_selection(GTK_TREE_VIEW(lookup_widget(ResultsDialog , "tvResults"))) );	

	/* TODO: use gtk_tree_selection_selected_foreach(selection, func, FILEPOINTER) */

/*	gtk_tree_selection_selected_foreach(selection, compare_foreach_pass_highest, highest);
	gtk_tree_selection_selected_foreach(selection, compare_foreach_pass_hundred, hundred);
*/

	gtk_tree_selection_selected_foreach(selection, compare_foreach_pass_one, NULL);


/*	gchar	*test;
	test = g_strdup_printf("Highest is %.6f", highest);
	umark_message_dialog(test);
	g_free(test);
*/
}


void
compare_foreach_pass_one		(GtkTreeModel	*model,
					 GtkTreePath	*path,
					 GtkTreeIter	*iter,
					 gpointer	data)
{
	gchar* mapname;

	gtk_tree_model_get(model, iter, COL_MAP, &mapname, -1);
	umark_message_dialog(mapname);

	g_free(mapname);
}


void
on_btnsubmit_clicked                   (GtkButton       *button,
                                        gpointer         user_data)
{
	/* TODO: output UMTMP_LOG and delete after calling UMPRL_TMP */
	gchar	*vbrowser;
	gchar	*perlexec;
	gchar	*perlfile;
	FILE	*PERLFILE;

	perlfile = g_strdup_printf("%s/Benchmark/UMPRL_TMP", utpath);
	PERLFILE = fopen(perlfile, "w");

	fprintf(PERLFILE, _SYSTEM_INFO_PL);
	fclose(PERLFILE);

	perlexec = g_strdup_printf("perl %s %s >%s/Benchmark/UMTMP_HTM", perlfile, utpath, utpath);
	system(perlexec);
	g_free(perlexec);
	remove(perlfile);

	vbrowser = g_strdup_printf("%s %s/Benchmark/UMTMP_HTM &", "mozilla", utpath);
	system(vbrowser);
	g_free(vbrowser);
	g_free(perlfile);

	/* TODO: delete html file after viewing in HTML viewer */
/*	system("echo '<html></html>' >UMTMP_HTM");
*/
}


void
on_btnloadlog_clicked                  (GtkButton       *button,
                                        gpointer         user_data)
{
	char		*umarkfile;
	GtkWidget	*OpenDlg;
	GtkWidget	*ResultsDialog;
	GtkListStore	*lsResultList;
	GtkTreeIter	iter;

	ResultsDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	lsResultList = GTK_LIST_STORE(gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(ResultsDialog , "tvResults")) ));

	OpenDlg = gtk_file_chooser_dialog_new(
		"Open UMark File", NULL,
		GTK_FILE_CHOOSER_ACTION_OPEN,
		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
		GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
		NULL);

	if(gtk_dialog_run(GTK_DIALOG(OpenDlg)) == GTK_RESPONSE_ACCEPT)
	{
		umarkfile = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(OpenDlg));

		int	i,j;
		int	nrow;
		int	passes;

		FILE	*UMarks;
		gchar	*strTmp;

		struct	stat results;
		struct	UResults Rlt;
		struct	UResults *pRlt;

		pRlt = &Rlt;

		/* TODO: check if results.st_size % sizeof(struct UResults) == 0 */

		if(stat(umarkfile, &results) != 0)
		{
			gchar* FSizeErrBox = "ERROR: Could not read the file size.";
			umark_message_dialog(FSizeErrBox);
			return;
		}
		passes = results.st_size / sizeof(struct UResults);

		/* verify file is open */
		if((UMarks = fopen(umarkfile, "rb")) == NULL)
		{
			gchar* FOpenErrBox = "ERROR: Could not read the .umark file.";
			umark_message_dialog(FOpenErrBox);
			return;
		}
		gtk_list_store_clear(GTK_LIST_STORE(lsResultList));

		for(i = 0; i < passes; i++)
		{
			fread(&Rlt, sizeof(struct UResults), 1, UMarks);

			for(j = 0; j < 44; j++)
			{
				Rlt.Map[j] -= AUGMENT;
			}
			/* nrow = */

			gtk_list_store_append (lsResultList, &iter);

			gtk_list_store_set(lsResultList, &iter, COL_MAP, Rlt.Map, -1);
			gtk_list_store_set(lsResultList, &iter, COL_BOT, pRlt->Bot - AUGMENT, -1);

			switch(pRlt->Dtl - AUGMENT)
			{
				case 0: strTmp = "Low"; break;
				case 1: strTmp = "High"; break;
				case 2: strTmp = "Current"; break;
				case 3: strTmp = "Custom"; break;
				default: strTmp = "Error";
			}
			gtk_list_store_set(lsResultList, &iter, COL_DTL, strTmp, -1);

			switch(pRlt->Res - AUGMENT)
			{
				case RES_640 : strTmp = "640x480";	break;
				case RES_800 : strTmp = "800x600";	break;
				case RES_1024: strTmp = "1024x768";	break;
				case RES_1280: strTmp = "1280x1024";	break;
				case RES_1600: strTmp = "1600x1200";	break;
				default: strTmp = "Error";
			}
			gtk_list_store_set(lsResultList, &iter, COL_RES, strTmp, -1);

			gtk_list_store_set(lsResultList, &iter, COL_MIN, pRlt->Min - AUGMENT, -1);
			gtk_list_store_set(lsResultList, &iter, COL_AVG, pRlt->Avg - AUGMENT, -1);
			gtk_list_store_set(lsResultList, &iter, COL_MAX, pRlt->Max - AUGMENT, -1);
			gtk_list_store_set(lsResultList, &iter, COL_SCR, pRlt->Scr - AUGMENT, -1);
			gtk_list_store_set(lsResultList, &iter, COL_VER, pRlt->Ver - AUGMENT, -1);

			switch((pRlt->Typ - AUGMENT) +1)
			{
				case PRE_BM: strTmp = "UT2003 Botmatch"; break;
				case PRE_FB: strTmp = "UT2003 Flyby"; break;
				case PRE_DM: strTmp = "UT2003 Demo"; break;
				case PRE_D4: strTmp = "UT2004 Demo"; break;
				case PRE_DE: strTmp = "DE Bonus Pack"; break;
				case PRE_EG: strTmp = "Epic Bonus Pack"; break;
				case PRE_U3: strTmp = "UMark 2003"; break;
				case PRE_U4: strTmp = "UMark 2004"; break;
				case PRE_TD: strTmp = "Timedemo"; break;
				default: strTmp = "Custom";
			}
			gtk_list_store_set(lsResultList, &iter, COL_TYP, strTmp, -1);
		}
		fclose(UMarks);
		g_free(umarkfile);
	}
	gtk_widget_destroy(OpenDlg);
}


gboolean
foreach_results_save(	GtkTreeModel	*model,
			GtkTreePath	*path,
			GtkTreeIter	*iter,
			gpointer	user_data)
{
	gint	i;
	gchar	*strTmp;
	gchar	*MapName;

	struct	UResults Rlt;

	/* map */
	gtk_tree_model_get(model, iter, COL_MAP, &MapName, -1);
	for(i = 0; MapName[i] == '\0' || i < 44; i++)
	{
		Rlt.Map[i] = MapName[i] + AUGMENT;
	}

	/* bot */
	gtk_tree_model_get(model, iter, COL_BOT, &Rlt.Bot, -1);
	Rlt.Bot += AUGMENT;

	/* detail */
	gtk_tree_model_get(model, iter, COL_DTL, &strTmp, -1);

	if(strcmp(strTmp, "Low") == 0) Rlt.Dtl = 0;
	else
	if(strcmp(strTmp, "High") == 0) Rlt.Dtl = 1;
	else
	if(strcmp(strTmp, "Current") == 0) Rlt.Dtl = 2;
	else
	if(strcmp(strTmp, "Custom") == 0) Rlt.Dtl = 3;

	Rlt.Dtl += AUGMENT;
	g_free(strTmp);

	/* resolution */
	gtk_tree_model_get(model, iter, COL_RES, &strTmp, -1);

	if(strcmp(strTmp, "640x480") == 0) Rlt.Res = 0;
	else
	if(strcmp(strTmp, "800x600") == 0) Rlt.Res = 1;
	else
	if(strcmp(strTmp, "1024x768") == 0) Rlt.Res = 2;
	else
	if(strcmp(strTmp, "1280x1024") == 0) Rlt.Res = 3;
	else
	if(strcmp(strTmp, "1600x1200") == 0) Rlt.Res = 4;

	Rlt.Res += AUGMENT;
	g_free(strTmp);

	/* fps & version */
	gtk_tree_model_get(model, iter, COL_MIN, &Rlt.Min, -1);
	Rlt.Min += AUGMENT;
	gtk_tree_model_get(model, iter, COL_AVG, &Rlt.Avg, -1);
	Rlt.Avg += AUGMENT;
	gtk_tree_model_get(model, iter, COL_MAX, &Rlt.Max, -1);
	Rlt.Max += AUGMENT;
	gtk_tree_model_get(model, iter, COL_SCR, &Rlt.Scr, -1);
	Rlt.Scr += AUGMENT;
	gtk_tree_model_get(model, iter, COL_VER, &Rlt.Ver, -1);
	Rlt.Ver += AUGMENT;

	/* benchmark type */
	gtk_tree_model_get(model, iter, COL_TYP, &strTmp, -1);

	if(strcmp(strTmp, "UT2003 Botmatch") == 0) Rlt.Typ = 0;
	else
	if(strcmp(strTmp, "UT2003 Flyby") == 0) Rlt.Typ = 1;
	else
	if(strcmp(strTmp, "UT2003 Demo") == 0) Rlt.Typ = 2;
	else
	if(strcmp(strTmp, "UT2004 Demo") == 0) Rlt.Typ = 3;
	else
	if(strcmp(strTmp, "DE Bonus Back") == 0) Rlt.Typ = 4;
	else
	if(strcmp(strTmp, "Epic Bonus Pack") == 0) Rlt.Typ = 5;
	else
	if(strcmp(strTmp, "UMark 2003") == 0) Rlt.Typ = 6;
	else
	if(strcmp(strTmp, "UMark 2004") == 0) Rlt.Typ = 7;
	else
	if(strcmp(strTmp, "Timedemo") == 0) Rlt.Typ = 8;
	else	Rlt.Typ = 9;

	Rlt.Typ += AUGMENT;
	g_free(strTmp);

	fwrite(&Rlt, sizeof(struct UResults), 1, user_data);

	return FALSE;
}


void
on_btnsavelog_clicked                  (GtkButton       *button,
                                        gpointer         user_data)
{
	char		*umarkfile;
	GtkWidget	*SaveDlg;
	GtkWidget	*ResultsDialog;
	GtkListStore	*lsResultList;
	GtkTreeIter	*iter;

	ResultsDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	lsResultList = GTK_LIST_STORE(gtk_tree_view_get_model( GTK_TREE_VIEW(lookup_widget(ResultsDialog , "tvResults")) ));

/*	gtk_tree_model_get_iter_first(tmBatchList, iter);
*/
	SaveDlg = gtk_file_chooser_dialog_new(
		"Save UMark File", NULL,
		GTK_FILE_CHOOSER_ACTION_SAVE,
		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
		GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
		NULL);

	if(gtk_dialog_run(GTK_DIALOG(SaveDlg)) == GTK_RESPONSE_ACCEPT)
	{
		umarkfile = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(SaveDlg));

		FILE *UMarks;
		if((UMarks = fopen(umarkfile, "wb")) == NULL)
		{
			gchar* FOpenErrBox = "ERROR: Could not open the .umark file for writing.";
			umark_message_dialog(FOpenErrBox);
			return;
		}
		gtk_tree_model_foreach(GTK_TREE_MODEL(lsResultList), foreach_results_save, UMarks);

		fclose(UMarks);
		g_free(umarkfile);
	}
	gtk_widget_destroy(SaveDlg);
}


void
on_btndismissresults_clicked           (GtkButton       *button,
                                        gpointer         user_data)
{
	gchar	*rm_log;

	gtk_widget_destroy(ResultsBox);
	rm_log = g_strdup_printf("%s/Benchmark/UMTMP_LOG", utpath);

	remove(rm_log);
	g_free(rm_log);
}


/*** preset maps dialog ******************************************************/
void
on_radprebm_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
	presetchosen = PRE_BM;
}


void
on_radprefb_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
	presetchosen = PRE_FB;
}


void
on_radpredm_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
	presetchosen = PRE_DM;
}


void
on_radpred4_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
	presetchosen = PRE_D4;
}


void
on_radprede_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
	presetchosen = PRE_DE;
}


void
on_radpreeg_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
	presetchosen = PRE_EG;
}


void
on_radpreu3_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
	presetchosen = PRE_U3;
}


void
on_radpreu4_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
	presetchosen = PRE_U4;
}


void
on_BtnPresetUse_clicked                (GtkButton       *button,
                                        gpointer         user_data)
{
	presetchosen = 0 - presetchosen;
	gtk_widget_hide(PresetsBox);
}


void
on_BtnPresetAdd_clicked                (GtkButton       *button,
                                        gpointer         user_data)
{
	if(presetchosen == -1) presetchosen = 1;

	/* add preset to existing list */
	gtk_widget_hide(PresetsBox);
}


void
on_BtnPresetCancel_clicked             (GtkButton       *button,
                                        gpointer         user_data)
{
	presetchosen = 0;
	gtk_widget_hide(PresetsBox);
}

void
on_btnMsgOK_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
	gtk_widget_hide(GTK_WIDGET(UMsgBox));
}


void
on_chkTimeDemo_clicked                 (GtkButton       *button,
                                        gpointer         user_data)
{
	/* TODO: disable for non-retail versions */

	dotimedemo = !dotimedemo;

	if(build == 0)
	{
		return;
	}
	if(dotimedemo)
	{
		/* get demo directory into map list */
		GtkWidget	*UMarkDialog;
		GtkComboBox	*cbMaps;
		GtkTreeModel	*cbTmod;

		FILE		*MapList;
		gchar		*lcurmap;
		gchar		*MapPath;
		gchar		*LogPath;
		char		buffer;

		UMarkDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
		cbMaps = GTK_COMBO_BOX(lookup_widget(UMarkDialog , "CmbMaps"));
		cbTmod = GTK_TREE_MODEL(gtk_combo_box_get_model(cbMaps));

/*		g_object_set(GTK_WIDGET(cbMaps), "appears-as-list", TRUE, NULL);
*/		gtk_list_store_clear(GTK_LIST_STORE(cbTmod));

		if(build >= 3000)
		{
			MapPath = g_strdup_printf("ls -1 %s/Demos | sed -e 's/.demo4//g' >%s/Benchmark/.UMMAP_LST", utdir, utpath);
		}
		else
		{
			MapPath = g_strdup_printf("ls -1 %s/System/*.dem | sed -e 's/.dem//g' >%s/Benchmark/.UMMAP_LST", utdir, utpath);
		}
		system(MapPath);
		g_free(MapPath);
		MapPath = g_strdup_printf("%s/Benchmark/.UMMAP_LST", utpath);
		MapList = fopen(MapPath, "r");

		lcurmap = "";

		while((buffer = getc(MapList)) != EOF)
		{
			if(buffer != '\n')
			{
				lcurmap = g_strdup_printf("%s%c", lcurmap, buffer); /* TODO: find a better way to append */
			}
			else
			{
				gtk_combo_box_append_text(GTK_COMBO_BOX(cbMaps), lcurmap);
				g_free(lcurmap);
				lcurmap = "";
			}
		}
		fclose(MapList);
		remove(MapPath);
		g_free(MapPath);
	}
	else
	{
		/* place maps back into map list */
		GtkWidget	*UMarkDialog;
		GtkComboBox	*cbMaps;
		GtkTreeModel	*cbTmod;

		FILE		*MapList;
		gchar		*lcurmap;
		gchar		*MapPath;
		gchar		*LogPath;
		char		buffer;

		UMarkDialog = GTK_WIDGET(gtk_widget_get_toplevel(GTK_WIDGET(button)));
		cbMaps = GTK_COMBO_BOX(lookup_widget(UMarkDialog , "CmbMaps"));
		cbTmod = GTK_TREE_MODEL(gtk_combo_box_get_model(cbMaps));

/*		g_object_set(GTK_WIDGET(cbMaps), "appears-as-list", TRUE, NULL);
*/		gtk_list_store_clear(GTK_LIST_STORE(cbTmod));

		MapPath = g_strdup_printf("ls -1 %s/Maps | grep \"AS-\\|BR-\\|CTF-\\|DM-\\|DOM-\\|MOV-\\|ONS-\" >%s/Benchmark/.UMMAP_LST", utdir, utpath);
		system(MapPath);
		g_free(MapPath);
		MapPath = g_strdup_printf("%s/Benchmark/.UMMAP_LST", utpath);
		MapList = fopen(MapPath, "r");

		lcurmap = "";

		while((buffer = getc(MapList)) != EOF)
		{
			if(buffer != '\n')
			{
				lcurmap = g_strdup_printf("%s%c", lcurmap, buffer); /* TODO: find a better way to append */
			}
			else
			{
				gtk_combo_box_append_text(GTK_COMBO_BOX(cbMaps), lcurmap);
				g_free(lcurmap);
				lcurmap = "";
			}
		}
		fclose(MapList);
		remove(MapPath);
		g_free(MapPath);
	}
}


void
on_btnUMarkConf_clicked                (GtkButton       *button,
                                        gpointer         user_data)
{
	ConfBox = create_UMarkConfDlg();
/*
FIXME: garbage characters on choosing ini files, then reopening dialog and clicking OK without changing
** (umark:29584): CRITICAL **: file pango-layout.c: line 1769 (pango_layout_get_cursor_pos): assertion `index >= 0 && index <= layout->length' failed
*/
	gtk_entry_set_text(GTK_ENTRY( lookup_widget(ConfBox, "entryIniFile") ), inifile);
	gtk_entry_set_text(GTK_ENTRY( lookup_widget(ConfBox, "entryIniUser") ), iniuser);

	if(gtk_dialog_run(GTK_DIALOG(ConfBox)) == GTK_RESPONSE_CANCEL)
	{
		inifile = "";
		iniuser = "";
	}
	gtk_widget_destroy(ConfBox);

	umark_message_dialog(inifile);
	umark_message_dialog(iniuser);
}


/*** ini configuration dialog ************************************************/
void
on_btnConfCancel_clicked               (GtkButton       *button,
                                        gpointer         user_data)
{
	gtk_widget_hide(ConfBox);
}


void
on_btnConfOK_clicked                   (GtkButton       *button,
                                        gpointer         user_data)
{
	gtk_widget_hide(ConfBox);
}


void
on_entryIniFile_changed                (GtkEditable     *editable,
                                        gpointer         user_data)
{
	inifile = (gchar *)gtk_entry_get_text(GTK_ENTRY(editable));
}


void
on_btnBrowseIni_clicked                (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget	*ConfDlg;
	GtkWidget	*OpenDlg;
	gchar		*browse_inifile;

	OpenDlg = gtk_file_chooser_dialog_new(
		"Open Ini File", NULL,
		GTK_FILE_CHOOSER_ACTION_OPEN,
		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
		GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
		NULL);

	ConfDlg = GTK_WIDGET( gtk_widget_get_toplevel(GTK_WIDGET(button)) );

	if(gtk_dialog_run(GTK_DIALOG(OpenDlg)) == GTK_RESPONSE_ACCEPT)
	{
		browse_inifile = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(OpenDlg));

		gtk_entry_set_text(GTK_ENTRY( lookup_widget(ConfDlg, "entryIniFile") ), browse_inifile);
		inifile = g_strdup(browse_inifile);

		umark_message_dialog(inifile);
		g_free(browse_inifile);
	}
	gtk_widget_destroy(OpenDlg);
}


void
on_entryIniUser_changed                (GtkEditable     *editable,
                                        gpointer         user_data)
{
	iniuser = (gchar *)gtk_entry_get_text(GTK_ENTRY(editable));
}


void
on_btnBrowseUser_clicked               (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget	*ConfDlg;
	GtkWidget	*OpenDlg;
	gchar		*browse_iniuser;

	OpenDlg = gtk_file_chooser_dialog_new(
		"Open User Ini", NULL,
		GTK_FILE_CHOOSER_ACTION_OPEN,
		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
		GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
		NULL);

	ConfDlg = GTK_WIDGET( gtk_widget_get_toplevel(GTK_WIDGET(button)) );

	if(gtk_dialog_run(GTK_DIALOG(OpenDlg)) == GTK_RESPONSE_ACCEPT)
	{
		browse_iniuser = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(OpenDlg));

		gtk_entry_set_text(GTK_ENTRY( lookup_widget(ConfDlg, "entryIniUser") ), browse_iniuser);
		iniuser = g_strdup(browse_iniuser);

		umark_message_dialog(iniuser);
		g_free(browse_iniuser);	
	}
	gtk_widget_destroy(OpenDlg);
}


/*** about dialog ************************************************************/
void
on_btnAboutDocs_clicked                (GtkButton       *button,
                                        gpointer         user_data)
{
	system("mozilla http://www.unrealmark.net/docs.php &");
}


void
on_btnAboutOnline_clicked              (GtkButton       *button,
                                        gpointer         user_data)
{
	system("mozilla http://www.unrealmark.net/login.php &");
}


void
on_btnAboutUpdates_clicked             (GtkButton       *button,
                                        gpointer         user_data)
{
	system("mozilla http://www.unrealmark.net &");
}


void
on_btnCloseAbout_clicked               (GtkButton       *button,
                                        gpointer         user_data)
{
	gtk_widget_destroy(AboutBox);
}

