Index: AE/Installer/trunk/source/about.cpp
===================================================================
--- AE/Installer/trunk/source/about.cpp	(revision 482)
+++ AE/Installer/trunk/source/about.cpp	(revision 487)
@@ -1,32 +1,17 @@
-/////////////////////////////////////////////////////////////////////////////
-// Name:        about_window.cpp
-// Purpose:     
-// Author:      
-// Modified by: 
-// Created:     08/05/2009 11:10:32
-// RCS-ID:      
-// Copyright:   
-// Licence:     
-/////////////////////////////////////////////////////////////////////////////
-
-// For compilers that support precompilation, includes "wx/wx.h".
-#include "wx/wxprec.h"
-
-#ifdef __BORLANDC__
-#pragma hdrstop
-#endif
-
-#ifndef WX_PRECOMP
-#include "wx/wx.h"
-#endif
+/***************************************************************************\
+| Project: AE Installer														|
+| By: Gumby & Iritscen														|
+| File: About.cpp															|
+| Function: Handles the About window!										|
+| Created: 08/05/2009 11:10:32												|
+\***************************************************************************/
 
 ////@begin includes
 ////@end includes
-
+#include "globals.h"
 #include "about.h"
 
 ////@begin XPM images
 ////@end XPM images
-
 
 /*
@@ -126,5 +111,20 @@
     itemPanel3->SetSizer(itemBoxSizer4);
 	
-    wxStaticText* itemStaticText5 = new wxStaticText( itemPanel3, wxID_STATIC, _("Mod Installer v1.0.1\nby Gumby and Iritscen\n\nAE credited to:\nEdT: BGI troops, additional weapons\ngeyser: Original creator\nGumby: Installer and Framework\nIritscen: Installer (Mac)\nLoser: Improved animation and AI\nNeo: OniSplit, documenting Oni, tech support\nONIrules: Additional weapons\nParadox: Documenting of Oni\nRossyMiles: Daodan DLL port to C\nSFeLi: Original Daodan DLL\nssg: Documenting Oni"), wxDefaultPosition, wxDefaultSize, wxNO_BORDER );
+	string aboutText = "AE/Mod Installer v";
+	aboutText = aboutText + INSTALLER_VERSION;
+	aboutText = aboutText + "\nby Gumby and Iritscen\n\n" +
+							"AE credited to:\n" +
+							"EdT: BGI troops, additional weapons\n" +
+							"geyser: Original AE framework\n" +
+							"Gumby: General AE framework, Windows Installer, add'l Daodan DLL coding\n" +
+							"Iritscen: Mac port of Installer & add'l Installer coding\n" +
+							"Loser: Improved combat animation and AI\n" +
+							"Neo: OniSplit, documenting Oni, tech support\n" +
+							"ONIrules: Additional weapons\n" +
+							"Paradox: Documenting of Oni\n" +
+							"RossyMiles: Daodan DLL port to C\n" +
+							"SFeLi: Original asm Daodan DLL\n" +
+							"ssg: Documenting Oni's game data";
+    wxStaticText* itemStaticText5 = new wxStaticText( itemPanel3, wxID_STATIC, _(aboutText.c_str()), wxDefaultPosition, wxDefaultSize, wxNO_BORDER );
     itemBoxSizer4->Add(itemStaticText5, 0, wxALIGN_LEFT|wxALL, 5);
 	
Index: AE/Installer/trunk/source/about.h
===================================================================
--- AE/Installer/trunk/source/about.h	(revision 482)
+++ AE/Installer/trunk/source/about.h	(revision 487)
@@ -1,16 +1,12 @@
-/////////////////////////////////////////////////////////////////////////////
-// Name:        about_window.h
-// Purpose:     
-// Author:      
-// Modified by: 
-// Created:     08/05/2009 11:10:32
-// RCS-ID:      
-// Copyright:   
-// Licence:     
-/////////////////////////////////////////////////////////////////////////////
+/***************************************************************************\
+| Project: AE Installer														|
+| By: Gumby & Iritscen														|
+| File: About.h																|
+| Function: Handles the About window!										|
+| Created: 08/05/2009 11:10:32												|
+\***************************************************************************/
 
 #ifndef _ABOUT_H_
 #define _ABOUT_H_
-
 
 /*!
Index: AE/Installer/trunk/source/aeinstallerapp.cpp
===================================================================
--- AE/Installer/trunk/source/aeinstallerapp.cpp	(revision 482)
+++ AE/Installer/trunk/source/aeinstallerapp.cpp	(revision 487)
@@ -1,34 +1,24 @@
-/////////////////////////////////////////////////////////////////////////////
-// Name:        aeinstallerapp.cpp
-// Purpose:     
-// Author:      
-// Modified by: 
-// Created:     07/05/2009 17:23:39
-// RCS-ID:      
-// Copyright:   
-// Licence:     
-/////////////////////////////////////////////////////////////////////////////
+/***************************************************************************\
+| Project: AE Installer														|
+| By: Gumby & Iritscen														|
+| File: AEInstallerApp.cpp													|
+| Function: Sets up the main application window.							|
+| Created: 07/05/2009 17:23:39												|
+\***************************************************************************/
+
+#include "boost/filesystem.hpp"
+#include "boost/lexical_cast.hpp" // int -> string
 #include "boost/thread.hpp"
-#include <boost/thread/mutex.hpp>
+#include "boost/thread/mutex.hpp"
 #include <fstream>
-#include "boost/filesystem.hpp" // includes all needed Boost.Filesystem declarations
-#include "boost/lexical_cast.hpp" //int -> string
-using namespace boost::filesystem; 
-// For compilers that support precompilation, includes "wx/wx.h".
-#include "wx/wxprec.h"
-
-#ifdef __BORLANDC__
-#pragma hdrstop
-#endif
-
-#ifndef WX_PRECOMP
-#include "wx/wx.h"
-#endif
+#include <string>
+#include "installer.h"
+#include "aeinstallerapp.h"
 
 ////@begin includes
 ////@end includes
 
-#include "aeinstallerapp.h"
-#include <string>
+Install_info_cfg currentAE, updateAE;
+MainWindow* TheWindow;
 
 ////@begin XPM images
@@ -88,4 +78,7 @@
  */
 
+/* The OnInit() routine is used to check whether the Installer has the software *\
+|  it needs to install mods, whether there is an available update, and whether	 |
+\* the user has globalized yet, to allow mods to be installed.					*/
 bool AEInstallerApp::OnInit()
 {    
@@ -93,5 +86,4 @@
 	// Remove the comment markers above and below this block
 	// to make permanent changes to the code.
-	
 #if wxUSE_XPM
 	wxImage::AddHandler(new wxXPMHandler);
@@ -111,98 +103,161 @@
 	TheWindow = mainWindow;
 	
+	// Anything after this is done after the window appears...
+	
+	if (!CheckForRequiredSoftware())
+	{
+		TheWindow->Close(); // CheckForRequiredSoftware() will have notified the user of what they are missing, so we just quit now
+		return true;
+	}
+	
+	bool installerJustUpdated = false;
+	int updateStatus = GetUpdateStatus(&currentAE, &updateAE, &installerJustUpdated);
+	if (updateStatus) // otherwise there's no update
+	{
+		string updateMsg = "An update for the Anniversary Edition is available.\n"; // for some reason we can't set the initial value while using the '+' operator...
+		updateMsg = updateMsg + "Do you wish to update to Edition version " + updateAE.AEVersion + "?\n" +
+						        "(Current version is " + currentAE.AEVersion + ")\n"; // ...so tack the rest on in a second command
+		wxMessageDialog* updateNotification;
+		
+		switch (updateStatus) // for the meanings of these return values, see the comments preceding installer.cpp's GetUpdateStatus()
+		{
+			case UPDATE_LOG_READ_ERR:
+			{
+				if (exists("Update.log")) remove("Update.log");
+				ofstream logfile("Update.log");
+				logfile << "Error: A necessary .cfg file could not be read.";
+			} // brackets are needed due to the initialization of the ofstream; silly C!
+				break;
+			case UPDATE_MNTH_REQD_ERR:
+				updateMsg = "There is a patch in the updates/ folder, but it patches the\n";
+				updateMsg = updateMsg + updateAE.AEVersion.substr(0, updateAE.AEVersion.length() - 1) + " release; it cannot update this version of the Edition.";
+				updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxOK | wxICON_EXCLAMATION, wxDefaultPosition);
+				updateNotification->ShowModal();
+				break;
+			case UPDATE_SIMP_AVAIL: // there's an update with no globalization or Installer strings attached
+				updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition);
+				if (updateNotification->ShowModal() == wxID_YES)
+					ProcessAEUpdate(&currentAE, &updateAE, &installerJustUpdated);
+				break;
+			case UPDATE_GLOB_AVAIL:	// there's an update with globalization strings attached
+				updateMsg = updateMsg + "**Note that the update requires you to reglobalize, which will take 5-20 minutes.**\n" +
+										"Before clicking Yes, MAKE SURE you have backed up any mods not installed through\n " +
+										"the Installer, such as plug-ins or direct OniSplit imports.";
+				updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition);
+				if (updateNotification->ShowModal() == wxID_YES)
+					ProcessAEUpdate(&currentAE, &updateAE, &installerJustUpdated);
+				break;
+			case UPDATE_INST_AVAIL: // there's an update with Installer strings attached (globalization is irrelevant while the Installer is not yet updated)
+				updateMsg = updateMsg + "**Note that the update requires the Installer to update itself.**\n" +
+										"If you click Yes, the Installer will quit and re-launch itself, then\n" +
+										"you will be prompted to begin the installation.";
+				updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition);
+				updateNotification->ShowModal();
+				if (updateNotification->ShowModal() == wxID_YES)
+				{
+					if (ProcessInstallerUpdate(&currentAE, &updateAE)) // there's an intentional logic gap here: if the user clicks "Yes"...
+					{												   // ...and then ProcessInstallerUpdate has an error and returns false, the logic gap results...
+						TheWindow->Close();							   // ...in the code continuing to execute down through case UPDATE_INST_REPL_ERR
+						return true;
+					}
+				}
+				else
+					break;
+			case UPDATE_INST_REPL_ERR: // the Installer replacement failed, user has to do it :-(
+				updateMsg = "The Installer replacement process failed for some reason.\n";
+				updateMsg = updateMsg + "Please quit, go into the folder Edition/Updates/" + strEUFN + "/install/ and drag the Installer to Edition/install/, " +
+										"replacing the current Installer application, then launch the new version.";
+				updateNotification = new wxMessageDialog(TheWindow, updateMsg.c_str(), "AE Installer Alert", wxOK | wxICON_EXCLAMATION, wxDefaultPosition);
+				updateNotification->ShowModal();
+				TheWindow->Close();
+				return true;
+		}
+	}
+
+	CheckForGlobalization(false); // function will prompt user and initiate globalization if not done already
+	
+	return true;
+}
+
+bool CheckForRequiredSoftware(void)
+{
 #ifdef WIN32
-	 HKEY hKey;
-	 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\.NETFramework\\policy\\v2.0", 0L, KEY_READ , &hKey) == ERROR_SUCCESS) {
-		 wxMessageDialog* MonoDialogOfDeath = new wxMessageDialog(TheWindow, "You don't have .NET 2.0 installed! .NET is a framework required by the Edition. You can download it from:\nhttp://gumby.oni2.net/dotnet\nPlease install .NET 2.0, then open this Installer again. \n\nWould you like to open the download webpage?",  "AE Installer Alert",  wxYES_NO | wxICON_EXCLAMATION	, wxDefaultPosition);
-		 if(MonoDialogOfDeath->ShowModal() == wxID_YES) {
+	// test for .NET 2.0 or higher
+	HKEY hKey;
+	if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\.NETFramework\\policy\\v2.0", 0L, KEY_READ , &hKey) == ERROR_SUCCESS)
+	{
+		string dotnetMsg = "You don't have .NET 2.0 installed! .NET is a framework required by the Edition.\n";
+		dotnetMsg = dotnetMsg + "You can download it from:\n" +
+								"http://gumby.oni2.net/dotnet\n" +
+								"Please install .NET 2.0, then open this Installer again.\n\n" +
+								"Would you like to open the download webpage?";
+		wxMessageDialog* DotNetDialogOfDeath = new wxMessageDialog(TheWindow, dotnetMsg.c_str(), "AE Installer Alert",
+																 wxYES_NO | wxICON_EXCLAMATION	, wxDefaultPosition);
+		if (DotNetDialogOfDeath->ShowModal() == wxID_YES)
 			system("start http://www.microsoft.com/downloads/details.aspx?familyid=0856eacb-4362-4b0d-8edd-aab15c5e04f5");
-		 }
 		RegCloseKey(hKey);
-		TheWindow->Close();
-	 }
-#else
-	// test for the third-party mono framework, because without it, on Mac, we are up a creek
-	char monoCommand[300] = "which mono >> ";
-	strcat(monoCommand, escapePath(system_complete("mono_check.log").string()).c_str());
-	system(monoCommand);
-	fstream file;
-	file.open("mono_check.log");
-	string line;
-	int line_count = 0;
-	while (!file.eof())
-	{
-		line_count++;
-		getline(file, line);
-	}
-	file.close();
-	remove("mono_check.log");
-	
-	if (line_count <= 1) // this means that "which mono" returned nothing -- abort! abort! abort!
-	{
-		wxMessageDialog* MonoDialogOfDeath = new wxMessageDialog(TheWindow, "You don't have 'mono' installed! 'mono' is a command-line tool required by the Edition. You can download it from:\nhttp://www.go-mono.com/mono-downloads/download.html (OS X 10.4+) or\nhttp://edt.oni2.net/AE/MonoFramework10.3.dmg (OS X 10.3)\n\nPlease install 'mono', then open this Installer again.",  "AE Installer Alert",  wxOK | wxICON_EXCLAMATION	, wxDefaultPosition);
+		return false;
+	}
+#else // on Mac...
+	// test for the third-party "mono" framework, because without it, we are up a creek
+	FILE *fWhichMono = NULL;
+	char chrWhichMono[32];
+	fWhichMono = popen("which mono", "r");
+	fgets(chrWhichMono, sizeof(chrWhichMono), fWhichMono);
+	pclose(fWhichMono);
+	string strWhichMono = (string)chrWhichMono;
+	string::size_type loc = strWhichMono.find("mono", 0);
+	
+	if (loc == string::npos) // this means that "which mono" did not return a path leading to the mono binary -- abort! abort! abort!
+	{
+		string monoMsg = "You don't have 'mono' installed! 'mono' is a command-line tool required by the Edition.\n";
+		monoMsg = monoMsg + "You can download it from: http://www.go-mono.com/mono-downloads/download.html (OS X 10.4+)\n" +
+							"or http://edt.oni2.net/AE/MonoFramework10.3.dmg (OS X 10.3)\n\n" +
+							"Please install 'mono', then open this Installer again.";
+		wxMessageDialog* MonoDialogOfDeath = new wxMessageDialog(TheWindow, monoMsg.c_str(), "AE Installer Alert", wxOK | wxICON_EXCLAMATION, wxDefaultPosition);
 		MonoDialogOfDeath->ShowModal();
-		TheWindow->Close();
-		return true; // it's quittin' time, Joe
-	}
-#endif
-
-	//anything after this is done after the window appears...
-
-	if ( !exists("../GameDataFolder") )
-	{
-		wxMessageDialog* YesNoDialog = new wxMessageDialog(TheWindow, 		"You haven't globalized yet! \nYou must globalize to use the Anniversary Edition framework. \nWould you like to globalize now? (This could take a while...)\n(Selecting \"No\" will exit this program...)",  "AE Installer Alert",  wxYES_NO | wxICON_EXCLAMATION	, wxDefaultPosition);
-
+		return false; // it's quittin' time, Joe
+	}
+#endif
+	return true;
+}
+
+bool CheckForGlobalization(bool justDoIt)
+{
+	if (!exists("../GameDataFolder"))
+	{
+		string globMsg = "You haven't globalized yet!\n";
+		globMsg = globMsg + "You must globalize to use the Anniversary Edition framework.\n" +
+							"Would you like to globalize now? (This could take a while...)\n" +
+							"(Selecting \"No\" will exit this program...)";
+		wxMessageDialog* YesNoDialog = new wxMessageDialog(TheWindow, globMsg.c_str(), "AE Installer Alert", wxYES_NO | wxICON_EXCLAMATION, wxDefaultPosition);
+		
 		if (YesNoDialog->ShowModal() == wxID_NO) // if the user said no...
+		{
 			TheWindow->Close();
-		else
-		{
-
-
+			return true;
+		}
+	}
+	else if (!justDoIt)
+		return false;
+	// Code below this point runs if user clicks "Yes" or if they are never asked but justDoIt is true
 #ifdef WIN32
-			boost::thread thrd3(globalize2);
-		//globalizeData();
-		//boost::thread::create_thread(&globalizeData);
-		//	 boost::thread_group Tg;
-		// Tg.create_thread( &globalizeData(), this );
-#else
-						TheWindow->InstallButton->Disable();
-			TheWindow->ReglobalizeButton->Disable();
-			globalizeData();
-						TheWindow->InstallButton->Enable();
-			TheWindow->ReglobalizeButton->Enable();
-#endif
-		
-
-		}
-	}
-
+	boost::thread thrd3(globalize2);
+#else // cannot use multi-threading in Mac build
+	TheWindow->InstallButton->Disable();
+	TheWindow->ReglobalizeButton->Disable();
+	globalizeData();
+	TheWindow->InstallButton->Enable();
+	TheWindow->ReglobalizeButton->Enable();
+#endif
+	
 	return true;
 }
 
-
-void setStatusArea( string s ) {
+void setStatusArea(string s)
+{
 	wxString wxs(s.c_str(), wxConvUTF8);
 	
-	TheWindow->StatusArea->SetStatusText(  wxs );
-	//TheWindow->StatusArea->SetStatusText(s.c_str());
-	//StatusArea->SetStatusText(_(s.c_str()));
-	//(*TheStatusBar)->SetStatusText(_(s.c_str()));
-	//AEInstallerApp::
-	//	TheWindow->StatusArea->SetStatusText("hi");
-	//mainWindow
-	//itemFrame1->StatusArea->SetStatusText(_"lol");
-	//MainWindow.StatusArea->SetStatusText("hi");
-	// class AbstractStatusNotifier { public: virtual void NotifyStatus(const wxString &statusString) = 0; };
-	//class StatusBarStatusNotifier : public AbstractStatusNotifier { wxStatusBar *statusbar; StatusBarStatusNotifier(wxStatusBar *bar) : statusbar(bar) { } ;
-	//void NotifyStatus(const wxString &status) { statusbar->SetStatus(status); } }
-	
-	
-	//MainWindow::StatusArea->
-	//MainWindow::MainWindow().SetSize(MainWindow::MainWindow().GetRect().GetWidth(), MainWindow::MainWindow().GetRect().GetHeight()+1);
-	
-	//MainWindow::StatusBar->SetLabel("Importing Files...");
-	//StatusBar->SetLabel(s);
-	//->SetLabel(s);
-	
+	TheWindow->StatusArea->SetStatusText(wxs);
 }
 
@@ -218,11 +273,9 @@
 	////@end AEInstallerApp cleanup
 }
-void doglobalizeData() {
-	//TheWindow->Disable();
+void doglobalizeData()
+{
 	globalizeData();
 #ifdef WIN32
 	while(1) Sleep(-1);
 #endif
-	//TheWindow->Enable();
-	//setStatusArea((string)"Test1");
-}
+}
Index: AE/Installer/trunk/source/aeinstallerapp.h
===================================================================
--- AE/Installer/trunk/source/aeinstallerapp.h	(revision 482)
+++ AE/Installer/trunk/source/aeinstallerapp.h	(revision 487)
@@ -1,12 +1,9 @@
-/////////////////////////////////////////////////////////////////////////////
-// Name:        main.h
-// Purpose:     
-// Author:      
-// Modified by: 
-// Created:     07/05/2009 17:23:39
-// RCS-ID:      
-// Copyright:   
-// Licence:     
-/////////////////////////////////////////////////////////////////////////////
+/***************************************************************************\
+| Project: AE Installer														|
+| By: Gumby & Iritscen														|
+| File: AEInstallerApp.h													|
+| Function: Sets up the main application window.							|
+| Created: 07/05/2009 17:23:39												|
+\***************************************************************************/
 
 #ifndef _AEINSTALLERAPP_H_
@@ -19,9 +16,8 @@
 
 ////@begin includes
+#include "wx/app.h"
 #include "wx/image.h"
 #include "main_window.h"
 ////@end includes
-
-string escapePath(string input);
 
 /*!
@@ -82,5 +78,6 @@
 #endif
     // _AEINSTALLERAPP_H_
-int globalizeData(void);
+
 void globalize2(void);
-MainWindow* TheWindow;
+bool CheckForRequiredSoftware(void);
+void doglobalizeData(void);
Index: AE/Installer/trunk/source/app_resources.cpp
===================================================================
--- AE/Installer/trunk/source/app_resources.cpp	(revision 482)
+++ AE/Installer/trunk/source/app_resources.cpp	(revision 487)
@@ -1,27 +1,14 @@
-/////////////////////////////////////////////////////////////////////////////
-// Name:        
-// Purpose:     
-// Author:      
-// Modified by: 
-// Created:     06/05/2009 08:47:16
-// RCS-ID:      
-// Copyright:   
-// Licence:     
-/////////////////////////////////////////////////////////////////////////////
+/***************************************************************************\
+| Project: AE Installer														|
+| By: Gumby & Iritscen														|
+| File: App_Resources.cpp													|
+| Function: Creates the menubar and loads image resources into memory.		|
+| Created: 06/05/2009 08:47:16												|
+\***************************************************************************/
 
-// For compilers that support precompilation, includes "wx/wx.h".
-#include "wx/wxprec.h"
-
-#ifdef __BORLANDC__
-#pragma hdrstop
-#endif
-
-#ifndef WX_PRECOMP
-#include "wx/wx.h"
-#endif
 
 ////@begin includes
 ////@end includes
-
+#include "globals.h"
 #include "app_resources.h"
 
Index: AE/Installer/trunk/source/app_resources.h
===================================================================
--- AE/Installer/trunk/source/app_resources.h	(revision 482)
+++ AE/Installer/trunk/source/app_resources.h	(revision 487)
@@ -1,12 +1,10 @@
-/////////////////////////////////////////////////////////////////////////////
-// Name:        
-// Purpose:     
-// Author:      
-// Modified by: 
-// Created:     06/05/2009 08:47:17
-// RCS-ID:      
-// Copyright:   
-// Licence:     
-/////////////////////////////////////////////////////////////////////////////
+/***************************************************************************\
+| Project: AE Installer														|
+| By: Gumby & Iritscen														|
+| File: App_Resources.h														|
+| Function: Creates menubar and loads image resources into memory.			|
+| Created: 06/05/2009 08:47:17												|
+\***************************************************************************/
+
 
 #ifndef _APP_RESOURCES_H_
Index: AE/Installer/trunk/source/globals.h
===================================================================
--- AE/Installer/trunk/source/globals.h	(revision 487)
+++ AE/Installer/trunk/source/globals.h	(revision 487)
@@ -0,0 +1,104 @@
+/***************************************************************************\
+| Project: AE Installer														|
+| By: Gumby & Iritscen														|
+| File: Globals.h															|
+| Function: Contains most of the includes needed by the source, and some	|
+|			defines, structs, and prototypes that help bridge certain		|
+|			source files that need to talk to each other.					|
+| Created: 04/11/2009 21:05:00												|
+\***************************************************************************/
+
+
+#pragma mark INCLUDES
+#include <fstream>
+#include <string>
+#include <stdio.h>
+#include <iostream>
+#include <cctype>
+#include <vector>
+#include <errno.h>
+#include <sstream>
+#include "boost/thread.hpp"
+#include "boost/tokenizer.hpp"
+#include "boost/lexical_cast.hpp" // int -> string
+#include "boost/algorithm/string.hpp"
+#include "boost/filesystem.hpp" // includes all needed Boost.Filesystem declarations
+using namespace boost::filesystem;
+using namespace std;
+#ifdef WIN32
+#include <windows.h>
+#else // assume we're on Mac
+#include <stdlib.h>
+#include <dirent.h>
+#endif
+#include "wx/wxprec.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#pragma mark DEFINES
+#define INSTALLER_VERSION		 "1.1" // only place we need to change this
+#define UPDATE_LOG_READ_ERR		-1
+#define UPDATE_INST_REPL_ERR	-2
+#define UPDATE_MNTH_REQD_ERR	-3
+#define UPDATE_NO_UPD_AVAIL		 0
+#define UPDATE_SIMP_AVAIL		 1
+#define UPDATE_GLOB_AVAIL		 2
+#define UPDATE_INST_AVAIL		 3
+#define UPDATE_CONT_UPD			 4
+
+#pragma mark STRUCTS
+struct ModPackage
+{
+	bool	isInstalled; // replace with function 
+	string	name;
+	string	modStringName;
+	int	modStringVersion;
+	bool	hasOnis;
+	bool	hasDeltas;
+	bool	hasBSL;
+	bool	hasAddon;
+	bool	hasDats;
+	string	category;
+	string	creator;
+	bool	isEngine;
+	string	readme;
+	bool	globalNeeded;
+	ModPackage();
+	
+	bool operator < (const ModPackage &fs) const
+	{ return (name < fs.name);}
+	
+	bool operator > (const ModPackage &fs) const
+	{ return (name > fs.name);}
+	
+	bool operator == (const ModPackage &fs) const
+	{ return (name == fs.name);}
+};
+
+struct Install_info_cfg
+{
+	string AEVersion, InstallerVersion, DaodanVersion, OniSplitVersion, WinGUIVersion, MacGUIVersion;
+	bool patch, globalizationRequired;
+	vector<string> deleteList;
+	
+	Install_info_cfg();
+};
+
+
+#pragma mark PROTOTYPES
+void recompileAll(vector<string>);
+int globalizeData(void);
+bool CheckForGlobalization(bool);
+int GetUpdateStatus(Install_info_cfg *, Install_info_cfg *, bool *);
+bool ProcessInstallerUpdate(Install_info_cfg *, Install_info_cfg *);
+bool ProcessAEUpdate(Install_info_cfg *, Install_info_cfg *, bool *);
+void callRefreshMods(void);
+string escapePath(string input);
+void setStatusArea(string);
+void setProgressBar(int);
+void copy_directory(const path &from_dir_ph, const path &to_dir_ph);
+void copy(const path &from_file_ph, const path &to_file_ph);
Index: AE/Installer/trunk/source/installer.cpp
===================================================================
--- AE/Installer/trunk/source/installer.cpp	(revision 482)
+++ AE/Installer/trunk/source/installer.cpp	(revision 487)
@@ -1,151 +1,51 @@
-/*
- AE/Mod Installer
- by Gumby and Iritscen
-*/
+/***************************************************************************\
+| Project: AE Installer														|
+| By: Gumby & Iritscen														|
+| File: Installer.cpp														|
+| Function: Contains the real meat of the installation process. Mm, beefy.	|
+| Created: 24/05/2009 19:39:00												|
+\***************************************************************************/
+
+// TODO: Load credits from text resource file
+// TODO: Clear mod info fields when mod is de-selected
 
 #define DEBUG
-#include <stdio.h>
-//#include <conio.h>
-//#include <process.h>
-#include <string>
-#include <iostream>
-#include <cctype>
-#include <vector>
-#include <fstream>
-#include <errno.h>
-#include <sstream>
-
-#include "boost/filesystem.hpp" // includes all needed Boost.Filesystem declarations
-
+
+#include "boost/date_time/gregorian/gregorian.hpp"
+#include "boost/date_time/date_parsing.hpp"
+#include "boost/date_time/posix_time/posix_time.hpp"
 #include "installer.h"
-
-#ifdef WIN32
-#include <windows.h>
-#else // assume we're on Mac
-#include <stdlib.h>
-#include <dirent.h>
-#endif
-
-//const string strInstallerVersion = "1.0";
-const bool SPLIT = 1;
-const bool NOT_SPLIT = 0;
-bool splitInstances = SPLIT;
-
-#ifdef WIN32
-const string strOniSplit = "Onisplit.exe";
-string strImportOption = "-import:nosep";
-const char* strClsCmd = "cls";
-const char* strPauseCmd = "PAUSE";
-#else // set up Mac equivalents since we're in Mac OS
-const string strOniSplit = "mono Onisplit.exe";
-string strImportOption = "-import:sep";
-const char* strClsCmd = "clear";
-const char* strPauseCmd = "read -n 1 -p \"Press any key to continue\"";
-#endif
-
-using namespace boost::filesystem; 
-using namespace std;
-
-
-/*
- int main(void)
- {
- if ( exists( "../../GameDataFolder/level0_Final.sep" ) ) splitInstances = NOT_SPLIT;
- else splitInstances = NOT_SPLIT;
- //	SetConsoleTitle("AE Installer"); windows junk, convert to SDL
- #ifdef WIN32	
- system("color 0A"); 
- #endif
- cout << "\nWelcome to the AE installer!\n";
- cout << "\nWhat would you like to do?\n";
- 
- return mainMenu();
- }
- */
-
-
-
-int mainMenu(void)
-{
-	char choice = '0';
-	bool exit = false;
+#include "aeinstallerapp.h"
+
+using namespace boost::gregorian;
+using namespace boost::posix_time;
+
+// externs declared in installer.h
+string strInstallCfg = "../GameDataFolder/Add.cfg";
+string strEUFN = "Edition"; // GetUpdateStatus() may set this to "Edition-patch" later, but this is the assumed name of the new Edition folder in Updates/
+
+int globalizeData(void)
+{
+	busy = 1;
+	using boost::lexical_cast;
+	using boost::bad_lexical_cast;
+	using namespace boost::gregorian;
+	using namespace boost::posix_time;
+	ptime start_time(second_clock::local_time());
+	
+	setStatusArea("Globalizing!");
 	int err = 0;
-	do
-	{
-		if( exists( "../GameDataFolder" ) ) {
-			cout << "\n1. Add new packages\n";
-			cout << "2. Remove packages\n";
-			cout << "3. See what is installed\n";
-			cout << "4. Globalize data\n";
-			cout << "5. About AE\n";
-			cout << "6. Quit\n\n";
-			
-			choice = cin.get();
-			cin.ignore(128, '\n');
-			switch(choice)
-			{
-				case '1':
-					err = installPackages();
-					break;
-				case '2':
-					err = uninstallPackages();
-					break;
-				case '3':
-					err = listInstalledPackages();
-					break;
-				case '4':
-					err = globalizeData();
-					break;
-				case '5':
-					err = printInstallerInfo();
-					break;
-				case '6':
-					exit = true;
-					break;
-				default:
-					cout << "Please choose one of the above numbers, and press Enter.\n\n";
-			}
-			if (err) // if something fatal happened
-				exit = true;
-		}
-		else {
-			cout << "\n1. Globalize data\n";
-			cout << "2. About AE\n";
-			cout << "3. Quit\n\n";
-			
-			choice = cin.get();
-			cin.ignore(128, '\n');
-			switch(choice)
-			{
-				case '1':
-					err = globalizeData();
-					break;
-				case '2':
-					err = printInstallerInfo();
-					break;
-				case '3':
-					exit = true;
-					break;
-				default:
-					cout << "Please choose one of the above numbers, and press Enter.\n\n";
-			}
-			if (err) // if something fatal happened
-				exit = true;
-		}
-	} while(!exit);
-	
-	return err;
-}
-
-int globalizeData(void)
-{
-	int err = 0;
-	
-	try {
-		int levels[15] = {0, 1, 2, 3, 4, 6, 8, 9, 10, 11, 12, 13, 14, 18, 19}; // the levels Oni has
-		char choice = 0;
-		
-		//SetCurrentDirectory("C:/Program Files/Oni/edition/install");
-		char levelnum[3];
+	int parts_done = 0;
+	remove("Globalize.log");
+	ofstream logfile("Globalize.log");
+	logfile << "Globalization started " << to_simple_string(start_time) << endl;
+	
+	try {  // the levels Oni has...probably should have made a string array. Oops.
+		char levels_cstr[15][3] = {"0", "1", "2", "3", "4", "6", "8", "9", "10", "11", "12", "13", "14", "18", "19"};
+		vector<string> levels;
+		for (int f = 0; f < 15; f++) {
+			levels.push_back(levels_cstr[f]);
+		}
+
 		path Characters = "../GameDataFolder/level0_Characters";
 		path Particles = "../GameDataFolder/level0_Particles";
@@ -156,24 +56,40 @@
 		path TRAC = Animations / "level0_TRAC";
 		path TRAM = Animations / "level0_TRAM";
-		/*
-		 if (exists("../GameDataFolder/"))
-		 {
-		 //cout << "\nIt looks like you've already globalized Oni's data.\nDo you want to re-globalize?\n(This will erase existing mods installed to the AE's game data.)"
-		 //	 << "\n1. Re-globalize"
-		 //	 << "\n2. Return to main menu\n";
-		 //choice = cin.get();
-		 cin.ignore(128, '\n');
-		 if (choice == '1')
-		 remove_all("../GameDataFolder"); // remove AE GDF
-		 if (choice == '2')
-		 return 0;
-		 }
-		 */
+		
+		vector<path> GDFPaths;
+		GDFPaths.push_back(Particles);
+		GDFPaths.push_back(Textures);
+		GDFPaths.push_back(Sounds);
+		GDFPaths.push_back(TRAC);
+		GDFPaths.push_back(TRAM);
+		
+		path VanillaCharacters = "VanillaDats/level0_Final/level0_Characters/level0_Characters.oni";
+		path VanillaParticles = "VanillaDats/level0_Final/level0_Particles/level0_Particles.oni";
+		path VanillaTextures  = "VanillaDats/level0_Final/level0_Textures/level0_Textures.oni";
+		path VanillaSounds = "VanillaDats/level0_Final/level0_Sounds/level0_Sounds.oni";
+		path VanillaAnimations = "VanillaDats/level0_Final/level0_Animations/level0_Animations.oni";
+		path VanillaTRAC = "VanillaDats/level0_Final/level0_Animations/level0_TRAC.oni";
+		path VanillaTRAM = "VanillaDats/level0_Final/level0_Animations/level0_TRAM.oni";
+		
+		vector<path> VanillaPaths;
+		
+		VanillaPaths.push_back(VanillaParticles);
+		VanillaPaths.push_back(VanillaTextures);
+		VanillaPaths.push_back(VanillaSounds);
+		VanillaPaths.push_back(VanillaTRAC);
+		VanillaPaths.push_back(VanillaTRAM);
+		
+		setStatusArea("Removing old GameDataFolder...\n");
+		logfile <<  "Removing old GameDataFolder...\n";
+		remove_all( "../GameDataFolder/" );
+		setStatusArea("Creating needed directories...");
+		logfile <<  "Creating needed directories...\n";
 		create_directory( "../GameDataFolder/" );
+		
 		create_directory( "packages" );
-		if (exists("packages/VanillaDats")) remove_all("packages/VanillaDats");
-		create_directory( "packages/VanillaDats" );
-		
-		create_directory( "packages/VanillaDats/level0_Final/" );
+		
+		if (exists("VanillaDats")) remove_all("VanillaDats"); 
+		create_directory( "VanillaDats" );
+		create_directory( "VanillaDats/level0_Final/" );
 		create_directory( Characters );
 		create_directory( Particles );
@@ -184,318 +100,229 @@
 		create_directory( TRAC );
 		create_directory( TRAM );
+		int num_levels = 0;
+		for(int i = 1; i < 15; i++)
+		{
+			if (exists("../../GameDataFolder/level" + levels[i] + "_Final.dat")) {
+				num_levels++;
+				
+			}
+		}
+		logfile << "Exporting and moving...\n\n";
+		int total_steps =  8 + 2 * num_levels;
 		
 		for(int i = 0; i < 15; i++)
-		{
-			sprintf(levelnum,"%d",levels[i]); // int to char array
-			exists("../../GameDataFolder/level" + (string)levelnum + "_Final");
-			system((strOniSplit + " -export ../GameDataFolder/level" + (string)levelnum + "_Final ../../GameDataFolder/level" + (string)levelnum + "_Final.dat").c_str());
-			
-			create_directory( "packages/VanillaDats/level" + (string)levelnum + "_Final" ); //remember to cast your arrays as strings :)
-			create_directory( "packages/VanillaDats/level" + (string)levelnum + "_Final/level" + (string)levelnum + "_Final" );
-			
-			directory_iterator end_iter;
-			for ( directory_iterator dir_itr( "../GameDataFolder/level" + (string)levelnum + "_Final" ); dir_itr != end_iter; ++dir_itr )
-			{
-				//cout << dir_itr->path().filename();
-				if ( is_regular_file( dir_itr->status() ) )
+		{			
+			if (exists("../../GameDataFolder/level" + levels[i] + "_Final.dat")) {
+				logfile << "level" << levels[i] << "_Final\n";
+				logfile << "\tExporting level" << levels[i] << "_Final.dat\n";
+				setStatusArea("Step " + lexical_cast<std::string>(parts_done + 1) + "/" + lexical_cast<std::string>(total_steps) + " exporting level" + levels[i]+"_Final.dat");
+				create_directory( "../GameDataFolder/level" + levels[i] + "_Final" ); 
+				system((strOniSplit + " -export ../GameDataFolder/level" + levels[i] + "_Final ../../GameDataFolder/level" + levels[i] + "_Final.dat").c_str());
+				create_directory( "VanillaDats/level" + levels[i] + "_Final" ); 
+				create_directory( "VanillaDats/level" + levels[i] + "_Final/level" + levels[i] + "_Final" );
+				
+				//Moves the AKEV and other files into a safe directory so that level specific textures are not globalized...
+				if ( strcmp(levels[i].c_str(), "0") ){
+					create_directory( "../GameDataFolder/level" + levels[i] + "_Final/AKEV" ); 
+					system((strOniSplit + " -move:overwrite ../GameDataFolder/level" + levels[i] + "_Final/AKEV ../GameDataFolder/level" + levels[i] + "_Final/AKEV*.oni").c_str());
+					
+				}
+				
+				directory_iterator end_iter;
+				for ( directory_iterator dir_itr( "../GameDataFolder/level" + levels[i] + "_Final" ); dir_itr != end_iter; ++dir_itr )
 				{
+					if ( is_regular_file( dir_itr->status() ) )
+					{
+						if ( dir_itr->path().filename().substr(0,8) == "TXMPfail" || 
+							dir_itr->path().filename().substr(0,9) == "TXMPlevel" ||
+							( dir_itr->path().filename().substr(0,4) == "TXMP" && dir_itr->path().filename().find("intro")!=string::npos) ||
+							dir_itr->path().filename().substr(0,4) == "TXMB" || 
+							dir_itr->path().filename() == "M3GMpowerup_lsi.oni" ||
+							dir_itr->path().filename() == "TXMPlsi_icon.oni" ||
+							( dir_itr->path().filename().substr(0,4) == "TXMB" && dir_itr->path().filename().find("splash_screen.oni")!=string::npos)	)
+						{
+							cout <<dir_itr->path().filename() << "\n";
+							create_directory( dir_itr->path().parent_path() / "NoGlobal");	
+							if(!exists( dir_itr->path().parent_path() / "NoGlobal" / dir_itr->filename())) rename(dir_itr->path(), dir_itr->path().parent_path() / "NoGlobal" /
+																												  dir_itr->filename());
+							else remove(dir_itr->path());
+						}
+						else if (dir_itr->path().filename().substr(0,4) == "TRAC"
+								 ) {
+							cout <<dir_itr->path().filename() << "\n";
+							if(!exists( TRAC / dir_itr->filename())) rename(dir_itr->path(), TRAC / dir_itr->filename());
+							else remove(dir_itr->path());
+						}
+						else if (dir_itr->path().filename().substr(0,4) == "TRAM") {
+							cout <<dir_itr->path().filename() << "\n";
+							if(!exists( TRAM / dir_itr->filename())) rename(dir_itr->path(), TRAM / dir_itr->filename());
+							else remove(dir_itr->path());
+						}
+						else if (dir_itr->path().filename().substr(0,4) == "ONSK" ||
+								 dir_itr->path().filename().substr(0,4) == "TXMP") {
+							cout <<dir_itr->path().filename() << "\n";\
+							create_directory( dir_itr->path().parent_path() / "TexFix");	
+							if(!exists( Textures / dir_itr->filename())) rename(dir_itr->path(), Textures / dir_itr->filename());
+						}
+						else if (dir_itr->path().filename().substr(0,4) == "ONCC" 
+								 || dir_itr->path().filename().substr(0,4) == "TRBS"
+								 || dir_itr->path().filename().substr(0,4) == "ONCV"
+								 || dir_itr->path().filename().substr(0,4) == "ONVL"
+								 || dir_itr->path().filename().substr(0,4) == "TRMA"
+								 || dir_itr->path().filename().substr(0,4) == "TRSC"
+								 || dir_itr->path().filename().substr(0,4) == "TRAS") {
+							cout <<dir_itr->path().filename() << "\n";
+							if(!exists( Characters / dir_itr->filename())) rename(dir_itr->path(), Characters / dir_itr->filename());
+							else remove(dir_itr->path());
+						}
+						else if (dir_itr->path().filename().substr(0,4) == "OSBD"
+								 || dir_itr->path().filename().substr(0,4) == "SNDD") {
+							cout << dir_itr->path().filename() << "\n";
+							if(!exists( Sounds / dir_itr->filename())) rename(dir_itr->path(), Sounds / dir_itr->filename());
+							else remove(dir_itr->path());
+						}
+						else if (dir_itr->path().filename().substr(0,5) == "BINA3"
+								 || dir_itr->path().filename().substr(0,10) == "M3GMdebris"
+								 || dir_itr->path().filename() == "M3GMtoxic_bubble.oni"
+								 || dir_itr->path().filename().substr(0,8) == "M3GMelec"
+								 || dir_itr->path().filename().substr(0,7) == "M3GMrat"
+								 || dir_itr->path().filename().substr(0,7) == "M3GMjet"
+								 || dir_itr->path().filename().substr(0,9) == "M3GMbomb_"
+								 || dir_itr->path().filename() == "M3GMbarab_swave.oni"
+								 || dir_itr->path().filename() == "M3GMbloodyfoot.oni"
+								 ){
+							cout <<dir_itr->path().filename() << "\n";
+							if(!exists( Particles / dir_itr->filename())) rename(dir_itr->path(), Particles / dir_itr->filename());
+							else remove(dir_itr->path());
+						}
+						else if (dir_itr->path().filename().substr(0,4) == "AGDB"
+								 || dir_itr->path().filename().substr(0,4) == "TRCM") {
+							cout <<dir_itr->path().filename() << "\n";
+							
+							if(!exists( Archive / dir_itr->filename())) rename(dir_itr->path(), Archive / dir_itr->filename());
+							else remove(dir_itr->path());
+						}
+						else if (dir_itr->path().filename().substr(0,4) == "ONWC") { //fix for buggy ONWC overriding
+							cout <<dir_itr->path().filename() << "\n";
+							
+							if(!exists( "VanillaDats/level0_Final/level0_Final/" +  dir_itr->filename()))
+								rename(dir_itr->path(), "VanillaDats/level0_Final/level0_Final/" +  dir_itr->filename());
+							else remove(dir_itr->path());
+						}
+						
+						if (exists(dir_itr->path())) {
+							
+						}
+						else {
+							//logfile << "\tMoved file: " << dir_itr->path().filename() << "\n";
+						}
+					}
 					
-					if ( dir_itr->path().filename().substr(0,8) == "TXMPfail" || 
-						dir_itr->path().filename().substr(0,9) == "TXMPlevel" ||
-						( dir_itr->path().filename().substr(0,4) == "TXMP" && dir_itr->path().filename().find("intro")!=string::npos) ||
-						dir_itr->path().filename().substr(0,4) == "TXMB" || 
-						dir_itr->path().filename() == "M3GMpowerup_lsi.oni" ||
-						dir_itr->path().filename() == "TXMPlsi_icon.oni" ||
-						( dir_itr->path().filename().substr(0,4) == "TXMB" && dir_itr->path().filename().find("splash_screen.oni")!=string::npos)	)
-					{
-						cout <<dir_itr->path().filename() << "\n";
-						create_directory( dir_itr->path().parent_path() / "NoGlobal");	
-						if(!exists( dir_itr->path().parent_path() / "NoGlobal" / dir_itr->filename())) rename(dir_itr->path(), dir_itr->path().parent_path() / "NoGlobal" /
-																											  dir_itr->filename());
-						else remove(dir_itr->path());
-					}
-					else if (dir_itr->path().filename().substr(0,4) == "TRAC") {
-						cout <<dir_itr->path().filename() << "\n";
-						if(!exists( TRAC / dir_itr->filename())) rename(dir_itr->path(), TRAC / dir_itr->filename());
-						else remove(dir_itr->path());
-					}
-					else if (dir_itr->path().filename().substr(0,4) == "TRAM") {
-						cout <<dir_itr->path().filename() << "\n";
-						if(!exists( TRAM / dir_itr->filename())) rename(dir_itr->path(), TRAM / dir_itr->filename());
-						else remove(dir_itr->path());
-					}
-					else if (dir_itr->path().filename().substr(0,4) == "ONSK" ||
-							 dir_itr->path().filename().substr(0,4) == "TXMP") {
-						cout <<dir_itr->path().filename() << "\n";\
-						create_directory( dir_itr->path().parent_path() / "TexFix");	
-						if(!exists( Textures / dir_itr->filename())) rename(dir_itr->path(), Textures / dir_itr->filename());
-						//rename(dir_itr->path(), dir_itr->path().parent_path() / "TexFix" / dir_itr->filename());
-					}
-					else if (dir_itr->path().filename().substr(0,4) == "ONCC" 
-							 || dir_itr->path().filename().substr(0,4) == "TRBS"
-							 || dir_itr->path().filename().substr(0,4) == "TRMA"
-							 || dir_itr->path().filename().substr(0,4) == "TRSC"
-							 || dir_itr->path().filename().substr(0,4) == "TRAS") {
-						cout <<dir_itr->path().filename() << "\n";
-						if(!exists( Characters / dir_itr->filename())) rename(dir_itr->path(), Characters / dir_itr->filename());
-						else remove(dir_itr->path());
-					}
-					else if (dir_itr->path().filename().substr(0,4) == "OSBD"
-							 || dir_itr->path().filename().substr(0,4) == "SNDD") {
-						cout << dir_itr->path().filename() << "\n";
-						if(!exists( Sounds / dir_itr->filename())) rename(dir_itr->path(), Sounds / dir_itr->filename());
-						else remove(dir_itr->path());
-					}
-					else if (dir_itr->path().filename().substr(0,5) == "BINA3"
-							 || dir_itr->path().filename().substr(0,10) == "M3GMdebris"
-							 || dir_itr->path().filename() == "M3GMtoxic_bubble.oni"
-							 || dir_itr->path().filename().substr(0,8) == "M3GMelec"
-							 || dir_itr->path().filename().substr(0,7) == "M3GMrat"
-							 || dir_itr->path().filename().substr(0,7) == "M3GMjet"
-							 || dir_itr->path().filename().substr(0,9) == "M3GMbomb_"
-							 || dir_itr->path().filename() == "M3GMbarab_swave.oni"
-							 || dir_itr->path().filename() == "M3GMbloodyfoot.oni"
-							 ){
-						cout <<dir_itr->path().filename() << "\n";
-						if(!exists( Particles / dir_itr->filename())) rename(dir_itr->path(), Particles / dir_itr->filename());
-						else remove(dir_itr->path());
-					}
-					else if (dir_itr->path().filename().substr(0,4) == "AGDB"
-							 || dir_itr->path().filename().substr(0,4) == "TRCM") {
-						cout <<dir_itr->path().filename() << "\n";
-						
-						if(!exists( Archive / dir_itr->filename())) rename(dir_itr->path(), Archive / dir_itr->filename());
-						else remove(dir_itr->path());
-					}
-				}
+					
+					
+				}
+				
+				logfile << "\tCleaning up TXMPs...\n";
+				system( (strOniSplit + " -move:delete " + Textures.string() + " ../GameDataFolder/level" + levels[i] + "_Final/TXMP*.oni").c_str());
 				
 				
-			}
-			system( (strOniSplit + " -move:delete " + Textures.string() + " ../GameDataFolder/level" + (string)levelnum + "_Final/TXMP*.oni").c_str());
-			
-		}
-		
+				if ( strcmp(levels[i].c_str(), "0") ){
+					system((strOniSplit + " -move:overwrite ../GameDataFolder/level" + levels[i] + "_Final ../GameDataFolder/level" + levels[i] + "_Final/AKEV/AKEV*.oni").c_str());
+					remove(  "../GameDataFolder/level" + levels[i] + "_Final/AKEV" );
+				}
+				
+				parts_done++;
+				
+				setProgressBar( (int)(1000 * (float)(parts_done) / (float)(total_steps) )); 
+				
+			}
+		}
+		logfile << "Reimporting levels\n";
 		for (int i = 0; i < 15; i++)
 		{
-			sprintf(levelnum,"%d",levels[i]);
-			system( (strOniSplit + " " + strImportOption + " ../GameDataFolder/level" + levelnum + "_Final packages/VanillaDats/level" + levelnum + "_Final/level"
-					 + levelnum + "_Final/level" + levelnum + "_Final.oni").c_str());
-		}
-		path VanillaCharacters = "packages/VanillaDats/level0_Final/level0_Characters/level0_Characters.oni";
-		path VanillaParticles = "packages/VanillaDats/level0_Final/level0_Particles/level0_Particles.oni";
-		path VanillaTextures  = "packages/VanillaDats/level0_Final/level0_Textures/level0_Textures.oni";
-		path VanillaSounds = "packages/VanillaDats/level0_Final/level0_Sounds/level0_Sounds.oni";
-		path VanillaAnimations = "packages/VanillaDats/level0_Final/level0_Animations/level0_Animations.oni";
-		path VanillaTRAC = "packages/VanillaDats/level0_Final/level0_Animations/level0_TRAC.oni";
-		path VanillaTRAM = "packages/VanillaDats/level0_Final/level0_Animations/level0_TRAM.oni";
-		create_directory( VanillaCharacters.parent_path() );
+			logfile << "\tReimporting level" << levels[i] << "_Final.oni\n";
+			setStatusArea("Step " + lexical_cast<std::string>(parts_done + 1) + "/" + lexical_cast<std::string>(total_steps) + " reimporting level" + levels[i]+"_Final.oni");
+			logfile << (strOniSplit + " " + strImportOption + " ../GameDataFolder/level" + levels[i] + "_Final VanillaDats/level" + levels[i] + "_Final/level" 
+						+ levels[i] + "_Final/level" + levels[i] + "_Final.oni >> Globalize.log").c_str() << '\n';
+			string sys_str = (strOniSplit + " " + strImportOption + " ../GameDataFolder/level" + levels[i] + "_Final VanillaDats/level" + levels[i] + "_Final/level"
+							  + levels[i] + "_Final/level" + levels[i] + "_Final.oni");
+			system(sys_str.c_str() );
+			setProgressBar( (int)(1000 * (float)(parts_done) / (float)(total_steps) ));
+			parts_done++;
+		}
 		create_directory( VanillaParticles.parent_path() );
 		create_directory( VanillaTextures.parent_path() );
 		create_directory( VanillaSounds.parent_path() );
 		create_directory( VanillaAnimations.remove_filename() );
-		system((strOniSplit + " " + strImportOption + " " + Characters.string() + " " + VanillaCharacters.string()).c_str());
-		system((strOniSplit + " " + strImportOption + " " + Particles.string() + " " + VanillaParticles.string()).c_str());
-		system((strOniSplit + " " + strImportOption + " " + Textures.string() + " " + VanillaTextures.string()).c_str());
-		//system((strOniSplit	+ " " + strImportOption + (string)" " + Animations.string() + (string)" " + VanillaAnimations.string()).c_str());
-		system((strOniSplit + " " + strImportOption + " " + TRAC.string() + " " + VanillaTRAC.string()).c_str());
-		system((strOniSplit + " " + strImportOption + " " + Sounds.string() + " " + VanillaSounds.string()).c_str());
-		system((strOniSplit + " " + strImportOption + " " + TRAM.string() + " " + VanillaTRAM.string()).c_str());
-		
-		create_directory("../GameDataFolder/IGMD");
+		
+		for(unsigned int j = 0; j < GDFPaths.size(); j++) {
+			logfile << "\tReimporting " << GDFPaths[j].filename() << ".oni\n";
+			setStatusArea("Step " + lexical_cast<std::string>(parts_done + 1) + "/" + lexical_cast<std::string>(total_steps) + ": reimporting " + GDFPaths[j].filename() );
+			system((strOniSplit + " " + strImportOption + " " + GDFPaths[j].string() + " " + VanillaPaths[j].string()).c_str());
+			parts_done++;
+			setProgressBar( (int)(1000 * (float)(parts_done) / (float)(total_steps) )); 
+		}
+		logfile << "\nMoving level0_Characters\n";
+		setStatusArea("Step " + lexical_cast<std::string>(parts_done + 1) + "/" + lexical_cast<std::string>(total_steps) + ": moving level0_Characters" );	
+		copy((path)"../GameDataFolder/level0_Characters", (path)("VanillaDats/level0_Final"));
+		GDFPaths.push_back( Characters );
+		for(int i = 0; i < GDFPaths.size(); i++) 
+		{
+			directory_iterator end_iter;
+			for ( directory_iterator dir_itr( GDFPaths[i] ); dir_itr != end_iter; ++dir_itr )
+			{
+				try 
+				{
+					rename(dir_itr->path(), "../GameDataFolder/level0_Final/" + dir_itr->path().filename() );
+				}
+				catch(exception &ex) {
+					
+				}
+			}
+		}
+
+		create_directory((path)"../GameDataFolder/IGMD");
 		copy((path)"packages/VanillaBSL/IGMD", (path)"../GameDataFolder");
-	}
-	catch (exception ex) {
-		cout << ex.what();
-	}
+		setProgressBar( 1000 );
+		
+		if(exists("../../persist.dat"))
+			if(!exists("../persist.dat")) 
+			
+			//TODO: Concatenate level0 Dirs.
+			
+				copy("../../persist.dat","..");
+		if(exists("../../key_config.txt"))
+			if(!exists("../key_config.txt"))
+				copy("../../key_config.txt",".."); 
+		
+#ifndef WIN32
+		/* On Mac only, set the current GDF to the AE GDF by writing to Oni's global preferences file (thankfully a standard OS X ".plist" XML file).
+		 Tests for presence of prefs with [ -f ] before doing anything so it doesn't create a partial prefs file -- just in case user has never
+		 run Oni before :-p */
+		string fullAEpath = escapePath(system_complete(".").parent_path().parent_path().string()); // get full path for edition/
+		char prefsCommand[300] = "[ -f ~/Library/Preferences/com.godgames.oni.plist ] && defaults write com.godgames.oni RetailInstallationPath -string '";
+		strcat(prefsCommand, fullAEpath.c_str()); // get path of Edition/ folder (Oni wants the folder that *contains* the GDF)
+		strcat(prefsCommand, "'"); // path string is enclosed in single quotes to avoid the need to escape UNIX-unfriendly characters
+		system(prefsCommand);
+#endif
+		
+		setStatusArea((string)"Done! Now select your mod packages and click install.");
+	}
+	catch (exception & ex) {
+		setStatusArea("Warning, handled exception: " + (string)ex.what());
+	}
+	
+	ptime end_time(second_clock::local_time());
+	time_period total_time (start_time, end_time);
+	logfile << "\n\nGlobalization ended " << to_simple_string(end_time) << "\nThe process took " << total_time.length();
+	logfile.close();
+	busy = 0;
 	return err;
 }
 
-int installPackages(void)
-{
-	bool installed_something = 0;
-	int err = 0;
-	ModPackage package;
-	vector<string> installed_packages;
-	vector<ModPackage> packages; 
-	vector<ModPackage>::iterator iter;
-	vector<string> installString;
-	
-	iter = packages.begin();
-	packages = getPackages();
-	vector<string> installedMods = getInstallString();
-	
-	if (packages.empty())
-	{
-		cout << "Error: You have no packages!\n";
-		return 0;
-	}
-	
-	cout << "Detecting installed packages...\n";
-	
-	int index = 1;
-	char choice = '0';
-	
-	for (vector<ModPackage>::iterator package_iter = packages.begin(); package_iter != packages.end(); ++package_iter)
-	{
-		if (!binary_search(installedMods.begin(), installedMods.end(), package_iter->modStringName))
-		{ //package_iter->isInstalled :< I forgot about this...
-			//cout << index << " ";
-			system(strClsCmd);
-			cout << (*package_iter).name << "\n";
-			for (int character = 1; character <= (*package_iter).name.length() - 1; character++) cout << '-';
-			cout << "\n"
-			<< (*package_iter).readme << "\n\n"
-			<< "Please enter a number choice\n"
-			<< " 1. Add\n"
-			<< " 2. Don't Add\n"
-			<< "";
-			index++;
-			choice = 0;
-			
-			do
-			{
-				choice = cin.get();
-				cin.ignore(1280, '\n');
-			} while(choice == 0);
-			
-			if (choice == '1')
-			{
-				cout << "\nInstalling...\n\n";
-				if (package_iter->hasOnis || (package_iter->hasDeltas /*(*package_iter).isUnpacked */ ))
-				{
-					installed_something = 1;
-					installedMods.push_back(package_iter->modStringName);
-					system(strPauseCmd);
-				}
-			}
-		}
-	}
-	if (index == 1)
-	{
-		cout << "Warning: All packages are already installed\n";
-		//would you like to recombine your data?
-		return 0;
-	}
-	if (installed_something == 0)
-	{
-		cout << "Warning: You didn't add anything!\n";
-		//would you like to recombine your data?
-		return 0;
-	}
-	
-	sort(installedMods.begin(), installedMods.end());
-	//system(Onisplit.c_str());
-	recompileAll(installedMods);
-	system(strPauseCmd);
-	
-	return err;
-}
-
-int uninstallPackages(void)
-{
-	int err = 0;
-	ModPackage package;
-	vector<string> installed_packages;
-	vector<ModPackage> packages; 
-	vector<ModPackage>::iterator iter;
-	vector<string> installString;
-	
-	iter = packages.begin();
-	packages = getPackages();
-	
-	
-	cout << "Detecting installed packages...\n";
-	
-	vector<string> installedMods = getInstallString();
-	
-	if (packages.empty())
-	{
-		cout << "Error: You have no packages!\n";
-		return 0;
-	}
-	
-	int index = 0;
-	int uninstalled_something = 0;
-	char choice = '0';
-	
-	for (vector<ModPackage>::iterator package_iter = packages.begin(); package_iter != packages.end(); ++package_iter)
-	{
-		if (binary_search(installedMods.begin(), installedMods.end(), package_iter->modStringName))
-		{ //package_iter->isInstalled :< I forgot about this...
-			//cout << index << " ";
-			system(strClsCmd);
-			cout << (*package_iter).name << "\n";
-			for (int character = 1; character <= (*package_iter).name.length() - 1; character++) cout << '-';
-			cout << "\n"
-			<< (*package_iter).readme << "\n\n"
-			<< "Please enter a number choice\n"
-			<< " 1. Remove\n"
-			<< " 2. Don't Remove\n"
-			<< "";
-			
-			choice = 0;
-			
-			do
-			{
-				choice = cin.get();
-				cin.ignore(1280, '\n');
-			} while(choice == 0);
-			
-			if (choice == '1')
-			{
-				cout << "\nUninstalling...\n\n";
-				installedMods.erase( installedMods.begin() + (index) );
-				system(strPauseCmd);
-				uninstalled_something = 1; 
-				
-			}
-			else {
-				index++;
-			}
-		}
-	}
-	if ( uninstalled_something == 0 )
-	{
-		if (index == 0) //bad practice, I need to implement a second vector or something. Meh.
-		{
-			cout << "\nWarning: You have no installed packages!";
-		}
-		else
-		{
-			cout << "\nWarning: You didn't remove anything!";
-		}
-		//would you like to recombine your data?
-		return 0;
-		
-	}	
-	sort(installedMods.begin(), installedMods.end());
-	//system(Onisplit.c_str());
-	recompileAll(installedMods);
-	system(strPauseCmd);
-	
-	return err;
-}
-
-int listInstalledPackages(void)
-{
-	cout << "\nThis feature not yet implemented.\n\n";
-	
-	return 0;
-}
-
-int printInstallerInfo(void)
-{
-	cout << "\nAE/Mod Installer\n";
-	cout << "version " << strInstallerVersion << "\n";
-	cout << "by Gumby & Iritscen\n";
-	cout << "see http://oni.bungie.org/community/forums for more info\n\n";
-	
-	return 0;
-}
-
-vector<ModPackage> getPackages(void)
+vector<ModPackage> getPackages(string packageDir)
 {
 	vector<ModPackage> packages;
-	packages.reserve(65536); // come on, we shouldn't need this much space...right?!
+	packages.reserve(256);
 	fstream file;
 	string filename = "\0";
@@ -504,13 +331,10 @@
 	try
 	{
-		directory_iterator end_iter;
-		for (directory_iterator dir_itr("./packages"); dir_itr != end_iter; ++dir_itr)
+		for (directory_iterator dir_itr(packageDir), end_itr; dir_itr != end_itr; ++dir_itr)
 		{
 			file.open((dir_itr->path().string() + "/" + MODINFO_CFG).c_str());
-			//cout << filename << "\n";
 			
 			if(!file.fail())
 			{
-				//cout << dir_itr->path().string() + MODINFO_CFG;
 				//would prefer to push a pointer to a package, but this will do for now
 				packages.push_back(fileToModPackage(file));
@@ -519,4 +343,5 @@
 			file.clear();
 		}
+		sort(packages.begin(), packages.end());
 	}
 	catch (const std::exception & ex)
@@ -559,15 +384,13 @@
 		vector<string>::iterator iter;
 		tokenize(line, tokens);					//string to vector of "words"
-		if (tokens.capacity() >= 2) {			//make sure they are using enough stuff
+		if (tokens.capacity() >= 3) {			//make sure they are using enough stuff
 			iter = tokens.begin();				//what word we are on, starts at first word
-			/*
+			/* TODO: Get this "required Installer version" code working
 			 if (!AEInstallVersion.compare(*iter))
 			 If mod is too old, skip this mod.
 			 */
 			/*else*/if (!NameOfMod.compare(*iter))  {	//if it contains the name
-				for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {	//interates through the words, ends if it reaches the end of the line or a "//" comment
-					if (ARROW.compare(*iter) && NameOfMod.compare(*iter)) {			//ignores "->" and "NameOfMod"
-						//cout << *iter; 
-						//cout << " ";
+				for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {	// iterates through the words, ends if it reaches the end of the line or a "//" comment
+					if (ARROW.compare(*iter) && NameOfMod.compare(*iter)) {			// ignores "->" and "NameOfMod"
 						package.name += *iter + " ";
 					}
@@ -583,9 +406,9 @@
 			else if (!HasOnis.compare(*iter)) {
 				iter++; iter++;  
-				if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasOnis = 1; //Gotta love c++'s lack of a standard case-insensitive
-				else if (!HasBSL.compare(*iter)) { // string comparer...I know my implementation here sucks. I need to change it to check each character one by one. At the moment,
-				iter++; iter++;}  // using "YFR" would probably set it off. :<
-				
-				if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasBSL = 1;
+				if ( boost::iequals(*iter, "Yes")) package.hasOnis = 1;
+			}	
+			else if (!HasBSL.compare(*iter)) {
+				if(toupper((*iter)[0]) == 'Y' && toupper((*iter)[1]) == 'E' && toupper((*iter)[2]) == 'S') package.hasBSL = true;
+				else if ( boost::iequals(*iter, "Addon")) package.hasAddon = true;
 			}
 			else if (!HasDeltas.compare(*iter)) {
@@ -604,11 +427,9 @@
 				iter++; iter++;  
 				if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.globalNeeded = 1;
-				else if (toupper((*iter)[0]) + toupper((*iter)[1]) == 'N' + 'O') package.globalNeeded = 1; //Really the only place where checking for "No" is important atm.
+				else if (toupper((*iter)[0]) + toupper((*iter)[1]) == 'N' + 'O') package.globalNeeded = 1; // only place where checking for "No" is important atm.
 			}
 			else if (!Category.compare(*iter))  {	
-				for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {	//interates through the words, ends if it reaches the end of the line or a "//" comment
-					if (ARROW.compare(*iter) && Category.compare(*iter)) {			//ignores "->" and "Category"
-						//cout << *iter; 
-						//cout << " ";
+				for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {	// iterates through the words, ends if it reaches end of line or a "//" comment
+					if (ARROW.compare(*iter) && Category.compare(*iter)) {			// ignores "->" and "Category"
 						package.category += *iter + " ";
 					}
@@ -616,8 +437,6 @@
 			}
 			else if (!Creator.compare(*iter))  {	//if it contains the name
-				for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {	//interates through the words, ends if it reaches the end of the line or a "//" comment
-					if (ARROW.compare(*iter) && Creator.compare(*iter)) {			//ignores "->" and "Category"
-						//cout << *iter; 
-						//cout << " ";
+				for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {	// iterates through the words, ends if it reaches end of line or a "//" comment
+					if (ARROW.compare(*iter) && Creator.compare(*iter)) {			// ignores "->" and "Creator"
 						package.creator += *iter + " ";
 					}
@@ -625,6 +444,6 @@
 			}
 			else if (!Readme.compare(*iter))  {	//if it contains the name
-				for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {	//interates through the words, ends if it reaches the end of the line or a "//" comment
-					if (ARROW.compare(*iter) && Readme.compare(*iter)) {			//ignores "->" and "Category"
+				for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {	// iterates through the words, ends if it reaches end of line or a "//" comment
+					if (ARROW.compare(*iter) && Readme.compare(*iter)) {			// ignores "->" and "Readme"
 						if(!(*iter).compare("\\n")) package.readme += '\n';
 						else package.readme += *iter + " ";
@@ -635,29 +454,35 @@
 		
 	}
-	package.doOutput();
+
 	return package;
 }
 
 void recompileAll(vector<string> installedMods)
-{
-#ifdef WIN32
-	RedirectIOToConsole(); 
-	HWND hWnd = GetConsoleWindow(); 
-	ShowWindow( hWnd, SW_HIDE ); 
-#endif
-	setStatusArea("Importing levels...");
-	//setStatusArea("Recompiling Data...");
-	path vanilla_dir = "./packages/VanillaDats/";
+{try {
+	busy = 1;
+	using namespace boost::gregorian;
+	using namespace boost::posix_time;
+	using boost::lexical_cast;
+	using boost::bad_lexical_cast;
+	path vanilla_dir = "./VanillaDats/";
 	string importCommand = "";
-	char statusString[128];
 	int numberOfDats = 0;
 	int j = 1;
 	string datString;
+		
+	setStatusArea("Importing levels...");
+	
 	std::stringstream out;
 	
-	
+	ptime start_time(second_clock::local_time());
 	clearOldDats();
-	remove("Onisplit.log");
-	if(splitInstances == SPLIT){
+	
+	if(exists("Install.log")) remove("Install.log");
+	ofstream logfile("Install.log");
+	logfile << "Mod Installation started " << to_simple_string(start_time) << endl;
+	logfile.close();
+	
+	if(splitInstances == true)
+	{
 		recursive_directory_iterator end_iter;
 		
@@ -672,15 +497,16 @@
 				}
 			}
-			catch(exception ex) {
+			catch(exception & ex) {
+				remove("Install.log");
+				ofstream logfile("Install.log");
 				
-			}
-		}
-		
-		//recursive_directory_iterator end_iter;
-		
-		
-		out << numberOfDats;
-		datString = out.str();
+				logfile << "Warning, exception " << ex.what() << "!";
+				setStatusArea("Warning, exception " + (string)ex.what() + "!");
+				logfile.close();	
+			}
+		}
 		try {
+			out << numberOfDats;
+			datString = out.str();
 			for ( recursive_directory_iterator dir_itr( vanilla_dir );
 				 dir_itr != end_iter;
@@ -692,38 +518,37 @@
 					{
 						importCommand = strOniSplit + " " + strImportOption + " " + dir_itr->path().parent_path().string() + '/' + dir_itr->path().filename();
-						for (int i = 0; i < installedMods.size(); ++i) {
+						for (unsigned int i = 0; i < installedMods.size(); ++i) {
 							if (exists("packages/" + installedMods[i] + "/oni/" + dir_itr->path().parent_path().filename() + '/' + dir_itr->path().filename()  ))
 								importCommand += " packages/" + installedMods[i] + "/oni/" + dir_itr->path().parent_path().filename() + '/' + dir_itr->path().filename();
-							
-							//else cout << " packages/VanillaDats/" + installedMods[i] + "/oni/";
 						}
-						importCommand += " ../GameDataFolder/" + dir_itr->path().filename() + ".dat >> Onisplit.log";
+						importCommand += " ../GameDataFolder/" + dir_itr->path().filename() + ".dat >> Install.log";
 						
-						sprintf(statusString,"%d/%i\0",j,numberOfDats);	
+						
 						setProgressBar( (int)(1000 * (float)(j-1) / (float)numberOfDats) ); //100% * dat we're on / total dats
-						setStatusArea("Importing " +  dir_itr->path().filename() + " " + statusString);
+						setStatusArea("Step " + lexical_cast<std::string>(j) + '/' + lexical_cast<std::string>(numberOfDats)+ ": Importing " +  dir_itr->path().filename() + " ");
 						
 						system(importCommand.c_str());
-						//Sleep(1000);
-						//cout << importCommand << "\n";
-						j++;
-						
+						j++;						
 					}
 				}
 				catch ( const std::exception & ex )
 				{
-					cout << "Warning, exception " << ex.what() << "!";
-				}
-			}
-			
+					remove("Install.log");
+					ofstream logfile("Install.log");
+					logfile << "Warning, exception " << ex.what() << "!";
+					setStatusArea("Warning, exception " + (string)ex.what() + "!");
+					logfile.close();	
+				}
+			}
 		}
 		catch( const std::exception & ex ) {
-			cout << "Warning, exception " << ex.what() << "!\n"
-			<< "You probably need to re-globalize.";
-			//create_directory( "./packages/VanillaDats" );
-		}
-		
-	}
-	else if(splitInstances == NOT_SPLIT){
+			remove("Install.log");
+			ofstream logfile("Install.log");
+			logfile << "Warning, exception " << ex.what() << "!";
+			setStatusArea("Warning, exception " + (string)ex.what() + "!");
+			logfile.close();
+		}
+	}
+	else if(splitInstances == false){
 		directory_iterator end_iter;
 		
@@ -732,11 +557,8 @@
 			 ++dir_itr )
 		{
-			
 			if ( is_directory( dir_itr->status() ) )
 			{
 				numberOfDats++;
 			}
-			
-			
 		}
 		
@@ -752,18 +574,14 @@
 				if ( is_directory( dir_itr->status() ) )
 				{
-					importCommand = strOniSplit + " " + strImportOption + " " + vanilla_dir.string() + dir_itr->path().filename() + " " + "../GameDataFolder/" + dir_itr->path().filename()
-					+ ".dat";
-					for (int i = 0; i < installedMods.size(); ++i) {
+					importCommand = strOniSplit + " " + strImportOption + " " + vanilla_dir.string() + dir_itr->path().filename() + " ";
+					for (unsigned int i = 0; i < installedMods.size(); ++i) {
 						if (exists("packages/" + installedMods[i] + "/oni/" + dir_itr->path().filename()  ))
 							importCommand += " packages/" + installedMods[i] + "/oni/" + dir_itr->path().filename();
 					}
-					importCommand += " ../GameDataFolder/" + dir_itr->path().filename() + ".dat";
+					importCommand += " ../GameDataFolder/" + dir_itr->path().filename() + ".dat >> Install.log";
 					
-					sprintf(statusString,"%d/%i\0",j,numberOfDats);	
 					setProgressBar( (int)(1000 * (float)(j-1) / (float)numberOfDats) ); //100% * dat we're on / total dats
-					setStatusArea("Importing " +  dir_itr->path().filename() + " " + statusString);
-					
+					setStatusArea("Step " + lexical_cast<std::string>(j) + '/' + lexical_cast<std::string>(numberOfDats)+ ": Importing " +  dir_itr->path().filename() + " ");
 					system(importCommand.c_str());
-					
 					j++;
 				}
@@ -771,19 +589,123 @@
 			catch ( const std::exception & ex )
 			{
-				cout << "Warning, something odd happened!\n";
-			}
-		}
-	}
+				remove("Install.log");
+				ofstream logfile("Install.log");
+				logfile << "Warning, exception " << ex.what() << "!";
+				setStatusArea("Warning, exception " + (string)ex.what() + "!");
+				logfile.close();
+			}
+		}
+	}
+	
+	vector<string> BSLfolders;
+	vector<string> skippedfolders;
+
+	ofstream BSLlog("BSL.log");
+	for ( directory_iterator dir_itr( "../GameDataFolder/IGMD/" ), end_itr;
+		 dir_itr != end_itr;
+		 ++dir_itr ) {
+		if( exists(dir_itr->path().string() + "/ignore.txt") ){
+			BSLfolders.push_back(dir_itr->path().filename());
+			skippedfolders.push_back(dir_itr->path().filename());
+		}
+	}
+	
+	for (int i = installedMods.size() - 1; i >= 0; i--) {							//Iterates through the installed mods (backwards :P)
+		for (unsigned int j = 0; j < globalPackages.size(); ++j) {				//looking in the global packages
+			if (globalPackages[j].modStringName == installedMods[i]) {	//for a mod that has BSL in it
+				if(!(globalPackages[j].hasAddon || globalPackages[j].hasBSL)) break; //skip non-BSL
+				if( exists( "packages/" + globalPackages[j].modStringName + "/BSL/" ) ) {
+					copyBSL("packages/" + globalPackages[j].modStringName + "/BSL", BSLfolders, globalPackages[j] );
+					BSLlog << "Copied " <<  globalPackages[j].modStringName << "!\n";
+				}
+			}
+		}
+	}
+	
+	ModPackage emptyPackage;
+	emptyPackage.modStringName = "VanillaBSL";
+	emptyPackage.hasBSL = 1;
+	copyBSL("packages/VanillaBSL/IGMD", BSLfolders, emptyPackage);
+	BSLlog.close();
+	
+	logfile << "Writing config file";
 	writeInstalledMods(installedMods);
 	setProgressBar(1000);
-	setStatusArea("Done!");
-	sleep(1000);
+	
+	string finallyDone = "Done! You can now play Oni.";
+	setStatusArea(finallyDone);
+	
+	ptime end_time(second_clock::local_time());
+	time_period total_time (start_time, end_time);
+	ofstream logfile2("Install.log", ios::app | ios::ate);
+	string outstring = (string)"\n\nGlobalization ended " + to_simple_string(end_time) + "\nThe process took ";// + (string)total_time.length();
+	
+	logfile2 << "\nInstallation ended " << to_simple_string(end_time) << "\nThe process took " << total_time.length();
+	logfile2.close();
+	
+	Sleep(1000);
 	setProgressBar(0);
-	
-}
+}
+	catch(exception & ex) {
+		remove("Install.log"); //why did we do this? :|
+		ofstream logfile("Install.log");
+		logfile << "Warning, exception " << ex.what() << "!";
+		setStatusArea("Warning, exception " + (string)ex.what() + "!");
+		logfile.close();
+	}
+	busy = 0;
+}
+
+void copyBSL(string copypath, vector<string>& BSLfolders, ModPackage pkg)
+{
+	ofstream BSLlog("BSL2.log", ios::app );
+	
+	try {
+		for ( directory_iterator dir_itr( copypath ), end_itr;
+			 dir_itr != end_itr;
+			 ++dir_itr ) {
+			
+			if ( is_directory( dir_itr->path() ) && dir_itr->path().string() != ".svn" ) {  
+				BSLlog << "Testing " << dir_itr->path().string() << " HasBSL: " << pkg.hasBSL << " HasAddon: " << pkg.hasAddon << "\n";
+				int skip_folder = 0;
+				
+				for(unsigned int k = 0; k < BSLfolders.size(); k++)		{//iterate through already found BSL folders	
+					BSLlog << "testing " << dir_itr->path().filename() << " vs " << BSLfolders[k] << "\n";
+					if(dir_itr->path().filename() == BSLfolders[k]) {
+						skip_folder = 1;
+						BSLlog << "skipping " << BSLfolders[k] << " in " << pkg.modStringName << "\n";
+						break;
+					}
+				}
+				if (!skip_folder && !exists("../GameDataFolder/IGMD/" + dir_itr->path().filename() + "/ignore.txt")) {
+					remove_all( "../GameDataFolder/IGMD/" + dir_itr->path().filename() );
+					Sleep(100);
+					create_directory( "../GameDataFolder/IGMD/" + dir_itr->path().filename());
+					BSLlog << "Copied " << dir_itr->path().string() << " in " << pkg.modStringName << "!\n";
+					for ( directory_iterator bsl_itr( dir_itr->path() );
+						 bsl_itr != end_itr;
+						 bsl_itr++ ) {
+						if ( bsl_itr->path().extension() == ".bsl" ) {
+							copy_file(bsl_itr->path(),  "../GameDataFolder/IGMD/" + dir_itr->path().filename() + "/" + bsl_itr->path().filename()); 
+						}
+					}
+					BSLfolders.push_back( dir_itr->path().filename() ); //add back check for addon
+					BSLlog << "Pushing " << dir_itr->path().filename() << "\n" ;
+				}
+			}
+		}
+	}
+	catch ( const std::exception & ex )
+	{
+		setStatusArea("Warning, exception " + (string)ex.what() + "!");
+		while(1) Sleep(1000);
+	}
+	BSLlog.close();
+	
+}
+
 
 void writeInstalledMods(vector<string> installedMods)
-{
-	
+{	
 	if ( exists( strInstallCfg ) )
 	{
@@ -805,12 +727,9 @@
 	file.close();
 	file.clear();
-	
 }
 
 vector<string> getInstallString(string Cfg)
 {
-	//system(strPauseCmd);
-	vector<string> returnval;
-	
+	vector<string> returnval;	
 	string line;
 	fstream file;
@@ -830,4 +749,691 @@
 }
 
+/* GetUpdateStatus determines whether there is an update available. It is called once, *\
+|  on launch, by AEInstallerApp::OnInit(), and not only passes back a #defined result	|
+|  code, but also oversees the setting of data in the global structures	currentAE and	|
+|  updateAE, which tell the Installer all the version information it needs to know.		|
+|					---Return Values---													|
+|  UPDATE_LOG_READ_ERR		-- A log file could not be opened							|
+|  UPDATE_INST_REPL_ERR		-- The Installer self-updating process failed				|
+|  UPDATE_MNTH_REQD_ERR		-- The update is a patch, and the monthly release it		|
+|							   patches is not installed									|
+|  UPDATE_NO_UPD_AVAIL		-- Either there isn't an update in place, or it's not		|
+|							   newer than what's installed								|
+|  UPDATE_SIMP_AVAIL		-- An update is available									|
+|  UPDATE_GLOB_AVAIL		-- An update is available that requires re-globalization	|
+|							   afterwards (because of some notable change in the AE)	|
+|  UPDATE_INST_AVAIL		-- An update is available that first requires the			|
+|							   Installer to be replaced (when the new Installer			|
+|							   launches, this function will be called again but will	|
+|							   return UPDATE_SIMP_AVAIL or UPDATE_GLOB_AVAIL)			|
+\* UPDATE_CONT_UPD			-- Currently unused										   */
+int GetUpdateStatus(Install_info_cfg *currentAE, Install_info_cfg *updateAE, bool *installerJustUpdated)
+{
+	fstream currentAECfg, updateAECfg, updateLog;
+	string strInstaller = "Installer";
+	string strBeing = "being";
+	string strWas = "was"; // lol
+#ifdef WIN32
+	string strInstallerName = "AEInstaller.exe";
+#else
+	string strInstallerName = "Installer.app";
+#endif
+	
+	// Try to get current AE's version info; if it doesn't exist, then the default version data for 2009-07 remains in place
+	if (exists("packages/Globalize/Install_Info.cfg"))
+	{
+		currentAECfg.open("packages/Globalize/Install_Info.cfg");
+		if (!currentAECfg.fail())
+		{
+			if (!ReadInstallInfoCfg(&currentAECfg, currentAE))
+				return UPDATE_LOG_READ_ERR;
+			
+			currentAECfg.close();
+			currentAECfg.clear();
+		}
+		else
+			return UPDATE_LOG_READ_ERR;
+	}
+	
+	// Is there an update folder, and is it a monthly release or a patch?
+	if (!exists("../updates/Edition"))
+	{
+		strEUFN = "Edition-patch";
+		if (!exists("../updates/Edition-patch"))
+			return UPDATE_NO_UPD_AVAIL;
+	}
+	
+	// Unlike the current AE's version info, we *need* to find the update's version info or we won't continue
+	string updateCfgPath = ("../updates/" + strEUFN + "/install/packages/Globalize/Install_Info.cfg");
+	updateAECfg.open(updateCfgPath.c_str());
+	if (!updateAECfg.fail())
+	{
+		if (!ReadInstallInfoCfg(&updateAECfg, updateAE))
+			return UPDATE_LOG_READ_ERR;
+		
+		updateAECfg.close();
+		updateAECfg.clear();
+	}
+	else
+		return UPDATE_LOG_READ_ERR;
+
+	// Now we check for an Installer update in progress
+	if (exists("Update.log"))
+	{
+		updateLog.open("Update.log");
+		if (!updateLog.fail())
+		{
+			vector<string> lines; 
+			string line;
+			int num_lines = 0;
+			bool readingInstallerVersion = false, doneReadingFile = false;
+			
+			while (!updateLog.eof() && !doneReadingFile)
+			{
+				getline(updateLog, line);
+				lines.push_back(line);
+				num_lines++;
+				vector<string> tokens;
+				vector<string>::iterator iter;
+				tokenize(line, tokens);
+				iter = tokens.begin();
+				if (!readingInstallerVersion && tokens.capacity() >= 4)
+				{
+					if (!strInstaller.compare(*iter))
+					{
+						if (!strBeing.compare(*++iter))
+							readingInstallerVersion = true;
+						else if (!strWas.compare(*iter))
+							*installerJustUpdated = true; // our third indirect return value after currentAE and updateAE
+					}
+				}
+				else if (readingInstallerVersion && tokens.capacity() >= 3)
+				{
+					readingInstallerVersion = false;
+					string installerVersion = INSTALLER_VERSION;
+					if (installerVersion.compare(*iter)) // then the shell script-powered replacement failed
+						return UPDATE_INST_REPL_ERR;
+					else
+					{
+						updateLog.close();
+						updateLog.clear();
+						Sleep(1000);
+						remove("Update.log");
+						ofstream newUpdateLog("Update.log");
+						if (!newUpdateLog.fail())
+						{
+							// Write over old log with updated information
+							ptime startTime(second_clock::local_time());
+							string strStartTime = to_simple_string(startTime);
+							string newUpdateLine = installerVersion + " on " + strStartTime;
+							for (int a = 0; a < lines.capacity() - 2; a++) // if there were even lines in the log before this at all
+							{
+								newUpdateLog << lines[a].c_str();
+								newUpdateLog << "\n";
+							}
+							newUpdateLog << "Installer was updated to:\n";
+							newUpdateLog << newUpdateLine.c_str();
+							*installerJustUpdated = true; // this value is indirectly returned to AEInstallerAp::OnInit()
+							doneReadingFile = true;
+							newUpdateLog.close();
+							newUpdateLog.clear();
+							//return UPDATE_CONT_UPD; // as noted above, we are not using this return value; in fact, we want...
+							//							 ...the code to continue running down through the Edition version check
+						}
+						else
+							return UPDATE_LOG_READ_ERR;
+					}
+				}
+			}
+			updateLog.close();
+			updateLog.clear();
+		}
+		else
+			return UPDATE_LOG_READ_ERR;
+	}
+	
+	if (updateAE->AEVersion.compare(currentAE->AEVersion) >= 1) // is the release update newer than what's installed?
+	{
+		if (!strEUFN.compare("Edition-patch")) // if update is a patch...
+		{
+			if (currentAE->AEVersion.compare(updateAE->AEVersion.substr(0, updateAE->AEVersion.length() - 1))) // ...is it for a different month?
+				return UPDATE_MNTH_REQD_ERR;
+		}
+		string strNewInstallerPath = "../updates/" + strEUFN + "/install/" + strInstallerName;
+		string installerVersion = INSTALLER_VERSION;
+		if (updateAE->InstallerVersion.compare(installerVersion) >= 1)
+		{
+			if (exists(strNewInstallerPath))
+				return UPDATE_INST_AVAIL;
+		}
+		else if (updateAE->globalizationRequired)
+			return UPDATE_GLOB_AVAIL;
+		else
+			return UPDATE_SIMP_AVAIL;
+	}
+	else
+		return UPDATE_NO_UPD_AVAIL;
+	
+	return UPDATE_NO_UPD_AVAIL;
+}
+
+bool ReadInstallInfoCfg(fstream *fileHandler, Install_info_cfg *info_cfg)
+{
+	vector<string> tokens;
+	vector<string>::iterator iter;
+	string line;
+	string strAEVersion = "AE_Version";
+	string strInstallerVersion = "Installer_Version";
+	string strDaodanVersion = "Daodan_Version";
+	string strOniSplitVersion = "OniSplit_Version";
+	string strGUIWinVersion = "GUI_Win_Version";
+	string strGUIMacVersion = "GUI_Mac_Version";
+	string strReglobalize = "Reglobalize";
+	string strDeleteList = "Delete_List";
+	string strArrow = "->";
+	string strDoubleSlash = "//";
+	string strYes = "Yes"; // this is getting silly
+	
+	while (getline(*fileHandler, line))
+	{
+		tokenize(line, tokens);
+		iter = tokens.begin();
+		
+		if (tokens.size() >= 3)
+		{
+			if (!strAEVersion.compare(*iter))
+			{
+				if (!strArrow.compare(*++iter))
+					info_cfg->AEVersion = *++iter;
+				else
+					return false;
+			}
+			else if (!strInstallerVersion.compare(*iter))
+			{
+				if (!strArrow.compare(*++iter))
+					info_cfg->InstallerVersion = *++iter;
+				else
+					return false;
+			}
+			else if (!strDaodanVersion.compare(*iter))
+			{
+				if (!strArrow.compare(*++iter))
+					info_cfg->DaodanVersion = *++iter;
+				else
+					return false;
+			}
+			else if (!strOniSplitVersion.compare(*iter))
+			{
+				if (!strArrow.compare(*++iter))
+					info_cfg->OniSplitVersion = *++iter;
+				else
+					return false;
+			}
+			else if (!strGUIWinVersion.compare(*iter))
+			{
+				if (!strArrow.compare(*++iter))
+					info_cfg->WinGUIVersion = *++iter;
+				else
+					return false;
+			}
+			else if (!strGUIMacVersion.compare(*iter))
+			{
+				if (!strArrow.compare(*++iter))
+					info_cfg->MacGUIVersion = *++iter;
+				else
+					return false;
+			}
+			else if (!strReglobalize.compare(*iter))
+			{
+				if (!strArrow.compare(*++iter))
+				{
+					if (!strYes.compare(*++iter))
+						info_cfg->globalizationRequired = true;
+				}
+				else
+					return false;
+			}
+			else if (!strDeleteList.compare(*iter))
+			{
+				// We need to perform a totally customized parsing process on this data
+				if (!strArrow.compare(*++iter))
+				{
+					vector<string> tokens2;
+					tokenize(line, tokens2, ","); // the paths on this line are comma-delimited, so we parse it again
+					vector<string>::iterator iter2 = tokens2.begin();
+					string finalPath = "";
+					for (; iter2 != tokens2.end(); iter2++)
+					{
+						finalPath = finalPath + *iter2;
+						
+						string::size_type loc = finalPath.find("->", 0); // the first word will have "Delete_List ->" at the front, so let's cut that off
+						if (loc != string::npos)
+							finalPath = finalPath.substr(loc + 3, finalPath.size());
+						
+						// If a path has '//' in it, it must contain some optional comments that were at the end of the Delete_List line
+						loc = finalPath.find("//", 0);
+						if (loc != string::npos)
+							finalPath = finalPath.substr(0, loc);
+						
+						// Trim a single space if it exists at the start or finish; putting more than one space after a comma will break this
+						if (finalPath.at(0) == ' ')
+							finalPath = finalPath.substr(1, finalPath.size());
+						if (finalPath.at(finalPath.size() - 1) == ' ')
+							finalPath = finalPath.substr(0, finalPath.size() - 1);
+
+						// If the tokenized path ends with a '\', then we assume it was followed by a comma
+						if (finalPath.at(finalPath.size() - 1) == '\\')
+						{
+							finalPath = finalPath.substr(0, finalPath.size() - 1); // clip the '\' off the end of the string now that it served its purpose...
+							finalPath = finalPath + ","; // ...and add the actual comma back at the end
+						}
+						else // we can add the path to deleteList, and clear the path; otherwise it will be added to on the next iteration
+						{
+							if (StringIsLegalPathForDeletion(finalPath)) // ...and it's not violating any of our security rules as to what can be deleted...
+								info_cfg->deleteList.push_back(finalPath); // ...then add it to our deleteList in memory
+							finalPath.clear(); // clear the token we were building up before the next pass
+						}
+					}
+				}
+				else
+					return false;
+			}
+		}
+		tokens.clear();
+	}
+	
+	return true;
+}
+
+// TODO: Fix security holes here
+/* There is currently a security hole in this function; the first occurrence of a '.' not followed by a second '.' will prevent the function from
+ noticing an actual occurrence of '..' later in the string; iow, it only looks after the first period it finds for a second period.
+ A second hole is that the last slash will be trimmed from the path, but one could still use ".//" and it would get past this function, and
+ possibly be interpreted by the Boost file functions as "the current directory". Iow, both of these checks need to be iterative, not one-time.
+ Not too concerned about this at the moment, as only we of the AE Team are supplying the install_info file that this function is connected to. -I */
+
+/* This function serves as a barrier against the Installer deleting files it shouldn't. *\
+|  It tests for each of the following conditions in the path it is passed:				 |
+|   A. '..' as the whole path or '/..', '\..' anywhere in the path						 |
+|	 Reason: Moving up from the parent directory, the Edition folder, would allow one	 |
+|	 to delete anything on the hard drive, so all "parent path" references are illegal.	 |
+|   B. '/' at the beginning of the path													 |
+|	 Reason: In Unix, this means the path starts from root level, as opposed to the		 |
+|	 directory we will evaluate these paths as being relative to, which is Edition/.	 |
+|   C. '.' as the whole path															 |
+|	 Reason: This would mean "the Edition folder", which is not allowed to be deleted.	 |
+|   D. 'GameDataFolder' at the end of the path											 |
+|	 Reason: We don't allow the entire GDF to be deleted, only specific files in it.	 |
+|   E. '*' anywhere in the path															 |
+|	 Reason: We don't want this interpreted as a wildcard; it's best to only delete		 |
+*\	 files by name.																		*/
+bool StringIsLegalPathForDeletion(string word)
+{
+	string::size_type loc1, loc2;
+	
+	// Trim ending slashes in order to simplify the test
+	// Note that we're only altering the local copy of the string here
+	loc1 = word.find_last_of("\\", word.size());
+	if (loc1 == word.size() - 1)
+		word.resize(word.size() - 1);
+	loc1 = word.find_last_of("/", word.size());
+	if (loc1 == word.size() - 1)
+		word.resize(word.size() - 1);
+	
+	// Test B
+	loc1 = word.find_first_of("\\", 0);
+	if (loc1 == 0)
+		return false; // path begins with a slash, meaning root level of HD in Unix, an illegal path
+	loc1 = word.find_first_of("/", 0);
+	if (loc1 == 0)
+		return false; // path begins with a slash, meaning root level of HD in Unix, an illegal path
+	
+	// Test E
+	loc1 = word.find("*", 0);
+	if (loc1 != string::npos) // if we found our character before reaching the end of the string
+		return false; // path cannot contain the '*' character
+	
+	// Tests A (part 1) and C
+	loc1 = word.find(".", 0);
+	if (loc1 != string::npos)
+	{
+		if (word.size() == 1)
+			return false; // path cannot be simply '.', referring to Edition folder itself
+		loc2 = word.find(".", loc1 + 1);
+		if (loc2 == loc1 + 1) // make sure this second period comes after the first one
+			if (word.size() == 2)
+				return false; // not allowed to reference a parent directory
+	}
+	
+	// Test A (part 2)
+	loc1 = word.find("/..", 0);
+	if (loc1 != string::npos)
+		return false; // not allowed to reference a parent directory
+	loc1 = word.find("\\..", 0);
+	if (loc1 != string::npos)
+		return false; // not allowed to reference a parent directory
+	
+	// Test D
+	loc1 = word.find("GameDataFolder", 0);
+	if (loc1 == word.size() - 14) // if "GameDataFolder" is the last 14 characters of the string...
+		return false; // not allowed to delete the GDF
+
+	return true;
+}
+
+bool ProcessInstallerUpdate(Install_info_cfg *currentAE, Install_info_cfg *updateAE)
+{
+	ofstream file;
+	string shellScript;
+	
+	ptime startTime(second_clock::local_time());
+	string strStartTime = to_simple_string(startTime);
+	string progressMsg = "Installer being updated to:\n" +
+						 updateAE->InstallerVersion + " on " + strStartTime;
+	file.open("Update.log");
+	if (!file.fail())
+		file << progressMsg.c_str();
+	file.close();
+	file.clear();
+	
+	string popenCommand = "../updates/" + strEUFN + "/install/";
+#ifdef WIN32
+	// TODO: Fill in Windows equivalent of code below :-3
+#else
+	// We can't just use '~' to mean "the home directory" because we need to check the path in C...
+	// ...so we actually get the current user's shortname and manually construct the path to home
+	FILE *fUserName = NULL;
+	char chrUserName[32];
+	fUserName = popen("whoami", "r");
+	fgets(chrUserName, sizeof(chrUserName), fUserName);
+	pclose(fUserName);
+	string strUserName = (string)chrUserName; // stringsblaaarrrgggghhhh
+	int endOfName = strUserName.find("\n", 0);
+	string pathToTrash = "/Users/" + strUserName.substr(0, endOfName) + "/.Trash/";
+	tm tmStartTime = to_tm(startTime);
+	pathToTrash = pathToTrash + "Old_Edition_files_" + currentAE->AEVersion + "_" + boost::lexical_cast<string>(tmStartTime.tm_hour) + "-" +
+	boost::lexical_cast<string>(tmStartTime.tm_min) + "-" + boost::lexical_cast<string>(tmStartTime.tm_sec); // lol
+	create_directory(pathToTrash);
+	// The script takes as a parameter the path the old Installer should go to, in quotes
+	popenCommand = "bash " + popenCommand + "replace_installer.sh " + pathToTrash + "/Installer.app";
+				   
+#endif
+	file.close();
+	file.clear();
+	popen(popenCommand.c_str(), "r");
+	
+	return true; // returning 'true' tells the Installer to quit itself ASAP so it can be replaced by the process that is now running
+}
+
+bool ProcessAEUpdate(Install_info_cfg *currentAE, Install_info_cfg *updateAE, bool *installerJustUpdated)
+{
+	fstream file;
+	string line;
+	vector<string> tokens, updateStarted;
+	string strInstaller = "Installer";
+	string strWas = "was";
+	string strPathToEUFN = ("../updates/" + strEUFN + "/"); // strEUFN is set by GetUpdateStatus()
+	string strPathToEUFNInstall = ("../updates/" + strEUFN + "/install/");
+	string strPathToEUFNPackages = ("../updates/" + strEUFN + "/install/packages/");
+	string strPathToPackages = "packages/";
+	string strGlobalize = "Globalize/";
+	string strOniSplit = "OniSplit.exe";
+	string strDaodan = "binkw32.dll";
+	string strWinGUI = "onisplit_gui.exe";
+	string strWinGUILang = "ospgui_lang.ini";
+	string strMacGUI = "AETools.app";
+#ifdef WIN32
+	string strOniApp = "Oni.exe";
+#else
+	string strOniApp = "Oni.app";
+#endif
+	bool needNewTrashDir = false;
+	bool readingVerAndDate = false;
+	
+	// TODO: Fill in Windows equivalent of code below
+#ifdef WIN32
+	string strTrashDir = "%RECYCLE%";
+#else
+	FILE *fUserName = NULL;
+	char chrUserName[32];
+	fUserName = popen("whoami", "r");
+	fgets(chrUserName, sizeof(chrUserName), fUserName);
+	pclose(fUserName);
+	string strUserName = (string)chrUserName; // stringsblaaarrrgggghhhh
+	int endOfName = strUserName.find("\n", 0);
+	string strTrashDir = "/Users/" + strUserName.substr(0, endOfName) + "/.Trash/";
+#endif
+	
+	// Write to log that we are beginning the update process
+	ptime startTime(second_clock::local_time());
+	string strStartTime = to_simple_string(startTime);
+	string progressMsg = "\nEdition being updated to:\n" +
+						 updateAE->AEVersion + " on " + strStartTime;
+	file.open("Update.log");
+	if (!file.fail())
+		file << progressMsg.c_str();
+	
+	if (*installerJustUpdated) // then we want to know what folder in the Trash the Installer was placed in...
+	{
+		while (!file.eof()) // ...so we read the log to get the timestamp so we know the name of the folder that should be in the Trash
+		{
+			getline(file, line);
+			tokenize(line, tokens);
+			
+			if (tokens.capacity() >= 4)
+				if (!strInstaller.compare(tokens[0]))
+					if (!strWas.compare(tokens[1]))
+						readingVerAndDate = true;
+			if (readingVerAndDate && tokens.capacity() >= 3)
+				tokenize(tokens[2], updateStarted, "-");
+		}
+		if (updateStarted.capacity() < 3)
+			needNewTrashDir = true;
+		else
+		{
+			strTrashDir = strTrashDir + "Old_Edition_files_" + currentAE->AEVersion + "-" +
+						  updateStarted[0] + "-" + updateStarted[1] + "-" + updateStarted[2] + "/";
+			if (!exists(strTrashDir))
+				needNewTrashDir = true;
+		}
+	}
+	
+	if (!*installerJustUpdated || needNewTrashDir) // prepare a new directory for deleted files to go to
+	{
+		tm tmStartTime = to_tm(startTime);
+		strTrashDir = strTrashDir + "Old_Edition_files_" + currentAE->AEVersion + "_" + boost::lexical_cast<string>(tmStartTime.tm_hour) + "-" +
+					  boost::lexical_cast<string>(tmStartTime.tm_min) + "-" + boost::lexical_cast<string>(tmStartTime.tm_sec) + "/";
+		create_directory(strTrashDir);
+	}
+	file.close();
+	file.clear();
+
+	// Special code to replace our special files -- the Oni app, OniSplit, the Daodan DLL, and the GUI for OniSplit
+	if (exists(strPathToEUFN + strOniApp))
+	{
+		if (exists(strOniApp))
+			rename((path)strOniApp, (path)(strTrashDir + strOniApp));
+		rename((path)(strPathToEUFN + strOniApp), (path)strOniApp);
+	}
+	if (updateAE->OniSplitVersion.compare(currentAE->OniSplitVersion) >= 1)
+	{
+		if (exists(strPathToEUFNInstall + strOniSplit))
+		{
+			if (exists(strOniSplit))
+				rename((path)strOniSplit, (path)(strTrashDir + strOniSplit));
+			rename((path)(strPathToEUFNInstall + strOniSplit), (path)strOniSplit);
+		}
+	}
+#ifdef WIN32
+	if (updateAE->DaodanVersion.compare(currentAE->DaodanVersion) >= 1)
+	{
+		if (exists(strPathToEUFN + strDaodan))
+		{
+			if (exists(("../" + strDaodan)))
+				rename((path)("../" + strDaodan), (path)(strTrashDir + strDaodan));
+			rename((path)(strPathToEUFN + strDaodan), (path)("../" + strDaodan));
+		}
+	}
+	if (updateAE->WinGUIVersion.compare(currentAE->WinGUIVersion) >= 1)
+	{
+		if (exists(strPathToEUFNInstall + strWinGUI))
+		{
+			if (exists((path)strWinGUI))
+				rename((path)strWinGUI, (path)strcat(strTrashDir, strWinGUI));
+			if (exists(strWinGUILang))
+				rename((path)strWinGUILang, (path)strcat(strTrashDir, strWinGUILang));
+			rename((path)(strPathToEUFNInstall + strWinGUI), (path)strWinGUI);
+			rename((path)(strPathToEUFNInstall + strWinGUILang), (path)strWinGUILang);
+		}
+	}
+#else
+	if (updateAE->MacGUIVersion.compare(currentAE->MacGUIVersion) >= 1)
+	{
+		if (exists(strPathToEUFN + strMacGUI))
+		{
+			if (exists(("../" + strMacGUI)))
+				rename((path)("../" + strMacGUI), (path)(strTrashDir + strMacGUI));
+			rename((path)(strPathToEUFN + strMacGUI), (path)("../" + strMacGUI));
+		}
+	}
+#endif
+	
+	// Now we trash whatever's in DeleteList; this allows us to clear out obsolete files in the previous AE install
+	// Before moving a file to the Trash, we need to make sure each of the file's parent paths exists in the Trash...
+	// ...so we iterate through the hierarchy of the file path, checking for each one and creating it if necessary
+	for (vector<string>::iterator iter = updateAE->deleteList.begin(); iter != updateAE->deleteList.end(); iter++)
+	{
+		string thePath = *iter;
+		if (exists((path)("../" + thePath)))
+		{
+			string aParentPath;
+			string::size_type curPos = thePath.find("/", 0);
+			if (curPos != string::npos)
+				aParentPath = thePath.substr(0, curPos);
+			string::size_type lastPos = curPos;
+			while (curPos != string::npos && curPos < thePath.size())
+			{
+				aParentPath = aParentPath + thePath.substr(lastPos, curPos - lastPos);
+				if (!exists(strTrashDir + aParentPath))
+					create_directory(strTrashDir + aParentPath);
+				lastPos = curPos + 1;
+				curPos = thePath.find("/", lastPos);
+				aParentPath = aParentPath + "/";
+			}
+			rename((path)("../" + thePath), (path)(strTrashDir + thePath));
+		}
+	}
+	
+	// Now we crawl the update's package folders for newer versions and move them over, trashing ones that are already present
+	vector<ModPackage> updatePackages, currentPackages;
+	bool matchFound;
+	updatePackages.reserve(256);
+	currentPackages.reserve(256);
+	
+	currentPackages = getPackages();
+	updatePackages = getPackages(strPathToEUFNPackages);
+
+	for (vector<ModPackage>::iterator iter1 = updatePackages.begin(); iter1 != updatePackages.end(); iter1++)
+	{
+		matchFound = false;
+		for (vector<ModPackage>::iterator iter2 = currentPackages.begin(); iter2 != currentPackages.end(); iter2++)
+		{
+			if (!iter1->modStringName.compare(iter2->modStringName))
+			{
+				matchFound = true;
+				if (iter1->modStringVersion > iter2->modStringVersion)
+				{
+					rename((path)(strPathToPackages + iter2->modStringName), (path)(strTrashDir + iter2->modStringName));
+					rename((path)(strPathToEUFNPackages + iter1->modStringName), (path)(strPathToPackages + iter1->modStringName));
+				}
+			}
+		}
+		if (!matchFound) // then there's no old package in the way, so just move in the one from the update
+			rename((path)(strPathToEUFNPackages + iter1->modStringName), (path)(strPathToPackages + iter1->modStringName));
+	}
+	
+	// Next, we get a list of which files and folders in the update's Globalize folder to move over; all files not starting with '.' will be moved...
+	// ...and folders which do not exist in the current AE will be created there
+	vector<string> foldersToMake, filesToMove;
+	string thePath;
+	for (recursive_directory_iterator dir_itr(strPathToEUFNPackages + strGlobalize), end_itr; dir_itr != end_itr; ++dir_itr)
+	{
+		thePath = dir_itr->path().string();
+		MakePathLocalToGlobalize(&thePath);
+		if (is_regular_file(dir_itr->status()))
+		{
+			if (dir_itr->filename().at(0) != '.') // skip over dot-files, which are invisible in Unix
+				filesToMove.push_back(thePath);
+		}
+		else if (is_directory(dir_itr->status()))
+		{
+			if (!exists(strPathToPackages + strGlobalize + thePath))
+				foldersToMake.push_back(thePath);
+		}
+	}
+	// Sort the foldersToMake strings by length, which is a fast solution to the problem of "How do we make sure we create folder 'parent/'...
+	// ...before folder 'parent/child/'"?
+	sort(foldersToMake.begin(), foldersToMake.end(), SortBySize); // SortBySize is a custom comparison function found later in this source file
+	// First make the folders that don't exist in the current AE, so all the files have a place to go
+	for (vector<string>::iterator iter = foldersToMake.begin(); iter != foldersToMake.end(); iter++)
+	{
+		create_directory(strPathToPackages + strGlobalize + *iter);
+	}
+	for (vector<string>::iterator iter = filesToMove.begin(); iter != filesToMove.end(); iter++)
+	{
+		if (exists(strPathToPackages + strGlobalize + *iter))
+			rename((path)(strPathToPackages + strGlobalize + *iter), (path)(strTrashDir + *iter));
+		rename((path)(strPathToEUFNPackages + strGlobalize + *iter), (path)(strPathToPackages + strGlobalize + *iter));
+	}
+	
+	// Clean up after ourselves, trashing any packages or programs in the update package that are not newer than the current AE
+	create_directory(strTrashDir + "Unneeded update files");
+	rename((path)strPathToEUFN, (path)(strTrashDir + "Unneeded update files/" + strEUFN));
+	
+	// Write to log that we are finished with update
+	ptime end_time(second_clock::local_time());
+	string progressMsg2 = "Edition was updated to:\n" +
+						  updateAE->AEVersion + " on " + to_simple_string(end_time);
+	
+	file.open("Update.log");
+	
+	if(!file.fail())
+		file.write(progressMsg2.c_str(), sizeof(progressMsg2.c_str()));
+	
+	file.close();
+	file.clear();
+	
+	if (updateAE->globalizationRequired)
+		CheckForGlobalization(true); // the 'true' value forces re-globalization
+	
+	globalPackages = getPackages(); // refresh the list in memory
+	
+	// TODO: Refresh the packages list in the window
+
+	return true;
+}
+
+/* MakePathLocalToGlobalize is a function used once by ProcessAEUpdate() that takes a file in an	\
+|  update's Globalize folder and changes its path, originally relative to the Installer, to be		|
+|  relative to the structure of the Globalize folder; this makes it easier to have the Installer	|
+\  move said file from an update's Globalize folder to the current Globalize folder.               */
+void MakePathLocalToGlobalize(string *installerBasedPath)
+{
+	int deleteToHere = 0;
+	deleteToHere = installerBasedPath->find("Globalize/");
+	if (deleteToHere != 0)
+	{
+		deleteToHere += strlen("Globalize/");
+		installerBasedPath->erase(0, deleteToHere);
+	}
+}
+
+/* SortBySize is a custom comparison function that we call when using the C++ sort() function in \
+\  ProcessAEUpdate() on some strings that we want to sort by length.							*/
+bool SortBySize(string a, string b)
+{
+	return (a.size() < b.size());
+}
+
 //stolen token function...
 void tokenize(const string& str, vector<string>& tokens, const string& delimiters)
@@ -855,5 +1461,4 @@
 		 ++dir_itr_gdf )
 	{
-		//cout << dir_itr_gdf->path().extension() << "\n";
 		if ( dir_itr_gdf->path().extension() == ".dat" || dir_itr_gdf->path().extension() == ".raw" || dir_itr_gdf->path().extension() == ".sep" ) {
 			remove( dir_itr_gdf->path() );
@@ -863,2 +1468,165 @@
 	
 }
+
+// this function copies files and directories. If copying a 
+// directory to a directory, it copies recursively. 
+
+//pardon the mess, I did this at midnight, and had to fix a bug
+void copy( const path & from_ph, 
+		  const path & to_ph ) 
+{ 
+	cout << to_ph.string() << "\n";
+	// Make sure that the destination, if it exists, is a directory 
+	if((exists(to_ph) && !is_directory(to_ph)) || (!exists(from_ph))) cout << "error";
+	if(!is_directory(from_ph)) 
+	{ 
+		
+		if(exists(to_ph)) 
+		{ 
+			copy_file(from_ph,to_ph/from_ph.filename()); 
+		} 
+		else 
+		{ 
+			try{
+				
+				copy_file(from_ph,to_ph);
+			}
+			catch (exception ex){
+				cout << from_ph.string() << " to " << to_ph.string() << "\n";
+			}
+		}
+		
+	} 
+	else if(from_ph.filename() != ".svn")
+	{ 
+		path destination; 
+		if(!exists(to_ph)) 
+		{ 
+			destination=to_ph; 
+		} 
+		else 
+		{ 
+			destination=to_ph/from_ph.filename(); 
+		} 
+		
+		for(directory_iterator i(from_ph); i!=directory_iterator(); ++i) 
+		{ 
+			//the idiot who coded this in the first place (not me)
+			//forgot to make a new directory. Exception city. x_x
+			create_directory(destination); 
+			copy(*i,destination/i->filename()); 
+		} 
+	} 
+} 
+
+void copy_directory( const path &from_dir_ph, 
+					const path &to_dir_ph) 
+{ 
+	if(!exists(from_dir_ph) || !is_directory(from_dir_ph) 
+	   || exists(to_dir_ph)) 
+		cout << !exists(from_dir_ph) << " " << !is_directory(from_dir_ph) 
+		<< " " << exists(to_dir_ph);
+	
+# ifdef BOOST_POSIX 
+	struct stat from_stat; 
+	if ( (::stat( from_dir_ph.string().c_str(), &from_stat ) != 0) 
+		|| ::mkdir(to_dir_ph.native_directory_string().c_str(), 
+				   from_stat.st_mode)!=0) 
+# endif 
+		} 
+
+string escapePath(string input)
+{
+	string output;
+	string escape_me = "& ;()|<>\"'\\#*?$";
+	for (unsigned int i = 0; i < input.size(); i++)
+	{
+		for (unsigned int j = 0; j < escape_me.size(); j++)
+			if (input[i] == escape_me[j])
+				output += '\\';
+		output += input[i];
+	}
+	return output;
+}
+
+Install_info_cfg::Install_info_cfg()
+{
+	AEVersion = "2009-07b";
+	InstallerVersion = "1.0.1";
+	DaodanVersion = "1.0";
+	OniSplitVersion = "0.9.38.0";
+	WinGUIVersion = "0";
+	MacGUIVersion = "0";
+	patch = false;
+	globalizationRequired = false;
+	deleteList.reserve(255);
+}
+
+ModPackage::ModPackage()
+{
+	isInstalled = true; // replace with function 
+	name = "";
+	modStringName = "";
+	modStringVersion = 0;
+	hasOnis = false;
+	hasDeltas = false;
+	hasBSL = false;
+	hasAddon = false;
+	hasDats = false;
+	category = "";
+	creator = "";
+	isEngine = false;
+	readme = "";
+	globalNeeded = true;
+}
+
+void Sleep(int ms)
+{
+	sleep(ms / 1000);
+}
+
+#ifdef WIN32
+
+void RedirectIOToConsole()
+{
+	int hConHandle;	
+	long lStdHandle;
+	CONSOLE_SCREEN_BUFFER_INFO coninfo;
+	FILE *fp;
+	
+	// allocate a console for this app
+	AllocConsole();
+	
+	// set the screen buffer to be big enough to let us scroll text
+	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), 
+							   &coninfo);
+	coninfo.dwSize.Y = MAX_CONSOLE_LINES;
+	SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), 
+							   coninfo.dwSize);
+	
+	// redirect unbuffered STDOUT to the console
+	lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
+	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
+	fp = _fdopen( hConHandle, "w" );
+	*stdout = *fp;
+	setvbuf( stdout, NULL, _IONBF, 0 );
+	
+	// redirect unbuffered STDIN to the console
+	lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
+	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
+	fp = _fdopen( hConHandle, "r" );
+	*stdin = *fp;
+	setvbuf( stdin, NULL, _IONBF, 0 );
+	
+	// redirect unbuffered STDERR to the console
+	lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
+	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
+	fp = _fdopen( hConHandle, "w" );
+	*stderr = *fp;
+	setvbuf( stderr, NULL, _IONBF, 0 );
+	
+	// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog 
+	// point to console as well
+	ios::sync_with_stdio();
+}
+#endif
Index: AE/Installer/trunk/source/installer.h
===================================================================
--- AE/Installer/trunk/source/installer.h	(revision 482)
+++ AE/Installer/trunk/source/installer.h	(revision 487)
@@ -1,317 +1,70 @@
- #pragma once 
-/* AE/Mod Installer header file */
+/***************************************************************************\
+| Project: AE Installer														|
+| By: Gumby & Iritscen														|
+| File: Installer.h															|
+| Function: Contains the real meat of the installation process.				|
+| Created: 24/05/2009 19:39:00												|
+\***************************************************************************/
+
 #ifndef DOUBLE_HEADER
 #define DOUBLE_HEADER
 
-
 #include <string>
 #include <vector>
+#include <iostream>
+#include "globals.h"
+#ifdef WIN32
+#ifndef __GUICON_H__
+#define __GUICON_H__
+#endif
 #include <fstream>
+#include <windows.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <io.h>
 
-using namespace std;
+void RedirectIOToConsole();
+// maximum mumber of lines the output console should have
+static const WORD MAX_CONSOLE_LINES = 500;
+#endif
 
+
+#pragma mark GLOBALS
 static string SLASHSLASH = "//";
 static string DIRSLASH = "\\";
-string strInstallCfg = "../GameDataFolder/Add.cfg";
-static string strInstallerVersion = "1.0";
+extern bool busy;
+extern string strInstallCfg;// = "../GameDataFolder/Add.cfg";
+extern Install_info_cfg currentAE, updateAE;
+extern bool splitInstances;
+extern string strImportOption;
+extern string strOniSplit;
+extern vector<ModPackage> globalPackages;
+extern string strEUFN; // I don't mind long variable names, but even I think strEditionUpdateFolderName is a bit much
+#ifndef WIN32
+void Sleep(int ms); // crudely converts the Windows sleep() call, which operates in ms, to the Mac sleep() call that operates in seconds
+#endif
 
-#define STRUCT_DEFS 
-struct ModPackage
-{
-	bool	isInstalled; //replace with function 
-	string	name;
-	string	modStringName;
-	int	modStringVersion;
-	bool	hasOnis;
-	bool	hasDeltas;
-	bool	hasBSL;
-	bool	hasAddon;
-	bool	hasDats;
-	string	category;
-	string	creator;
-	bool	isEngine;
-	string	readme;
-	bool	globalNeeded;
-	ModPackage();
 
-	void doOutput()
-	{
-		cout << "Mod: " << name; cout << "\n"; // remove this when done
-		cout << "	String: " << modStringName << " v." << modStringVersion << "\n";
-		cout << "	Category: " << category << "\n";
-		cout << "	Creator: " << creator << "\n";
-		cout << "	HasOnis: " << hasOnis << "\n";
-		cout << "	HasBSL: " << hasBSL << "\n";
-		cout << "	HasDeltas: " << hasDeltas << "\n";
-		cout << "	HasDats: " << hasDats << "\n";
-		cout << "	IsEngine: " << isEngine << "\n";
-		cout << "	GlobalNeeded: " << globalNeeded << "\n";
-		cout << "	Readme: " << readme << "\n";
-		cout << "\n";
-	}
-
-	     bool operator < (const ModPackage &fs) const
-     { return (name < fs.name);}
-
-     bool operator > (const ModPackage &fs) const
-     { return (name > fs.name);}
-
-     bool operator == (const ModPackage &fs) const
-     { return (name == fs.name);}
-};
-
-#define METHOD_DEFS 
-// Initialization to default values
-ModPackage::ModPackage()
-{
-	isInstalled = true; // replace with function 
-	name = "";
-	modStringName = "";
-	modStringVersion = 0;
-	hasOnis = false;
-	hasDeltas = false;
-	hasBSL = false;
-	hasAddon = false;
-	hasDats = false;
-	category = "";
-	creator = "";
-	isEngine = false;
-	readme = "";
-	globalNeeded = true;
-	//		void doOutput() const
-	//		{ };
-}
-
-#define FUNCTION_PROTOTYPES 
+#pragma mark PROTOTYPES
 int mainMenu(void);
-int globalizeData(void);
+vector<string> getInstallString(string = strInstallCfg);
 int installPackages(void);
 int uninstallPackages(void);
 int listInstalledPackages(void);
 int printInstallerInfo(void);
-vector<ModPackage> getPackages(void);
 ModPackage fileToModPackage(fstream&);
-void recompileAll(vector<string>);
-vector<string> getInstallString(string = strInstallCfg);
+bool StringIsLegalPathForDeletion(string);
+vector<ModPackage> getPackages(string packageDir = "./packages");
+void MakePathLocalToGlobalize(string*);
+bool SortBySize(string, string);
 void tokenize(const string&, vector<string>&, const string& delimiters = " ");
-//bool getDirectoryContents(char , char &);
 void clearOldDats(void);
 void writeInstalledMods( vector<string> );
-void setStatusArea( string );
-void setProgressBar( int );
-
 void copyBSL( string, vector<string>&, ModPackage );
-
-//New copy(path, path) function. Too lazy to implement my own, this is basically how I would have done it though.
-//No, really. :)
-//Move to utilities.cpp when the time comes.
-using namespace boost::filesystem; 
-using namespace std;
-
-void copy_directory( const path & from_dir_ph, 
-					const path & to_dir_ph ); 
-
-void copy( const path & from_file_ph, 
-		  const path & to_file_ph ); 
-
-
-// this function copies files and directories. If copying a 
-// directory to a directory, it copies recursively. 
-
-//pardon the mess, I did this at midnight, and had to fix a bug
-void copy( const path & from_ph, 
-		  const path & to_ph ) 
-{ 
-	cout << to_ph.string() << "\n";
-	// Make sure that the destination, if it exists, is a directory 
-	if((exists(to_ph) && !is_directory(to_ph)) || (!exists(from_ph))) cout << "error";
-	if(!is_directory(from_ph)) 
-	{ 
-		
-		if(exists(to_ph)) 
-		{ 
-			copy_file(from_ph,to_ph/from_ph.filename()); 
-		} 
-		else 
-		{ 
-			try{
-				
-				copy_file(from_ph,to_ph);
-			}
-			catch (exception ex){
-				cout << from_ph.string() << " to " << to_ph.string() << "\n";
-			}
-		}
-		
-	} 
-	else if(from_ph.filename() != ".svn")
-	{ 
-		path destination; 
-		if(!exists(to_ph)) 
-		{ 
-			destination=to_ph; 
-		} 
-		else 
-		{ 
-			destination=to_ph/from_ph.filename(); 
-		} 
-		//not sure what this did, its going away though. probably error checking ;)
-		//copy_directory(from_ph,destination); 
-		
-		for(directory_iterator i(from_ph); i!=directory_iterator(); ++i) 
-		{ 
-			//the idiot who coded this in the first place (not me)
-			//forgot to make a new directory. Exception city. x_x
-			create_directory(destination); 
-			copy(*i,destination/i->filename()); 
-		} 
-	} 
-} 
-
-void copy_directory( const path &from_dir_ph, 
-					const path &to_dir_ph) 
-{ 
-	if(!exists(from_dir_ph) || !is_directory(from_dir_ph) 
-	   || exists(to_dir_ph)) 
-		cout << !exists(from_dir_ph) << " " << !is_directory(from_dir_ph) 
-		<< " " << exists(to_dir_ph);
-	//boost::throw_exception( filesystem_error( 
-	//"boost::filesystem::copy_directory", 
-	//from_dir_ph, to_dir_ph, boost::system::error_code() )); 
-	
-# ifdef BOOST_POSIX 
-	struct stat from_stat; 
-	if ( (::stat( from_dir_ph.string().c_str(), &from_stat ) != 0) 
-		|| ::mkdir(to_dir_ph.native_directory_string().c_str(), 
-				   from_stat.st_mode)!=0) 
-# endif 
-		//	boost::throw_exception( filesystem_error( 
-		//	//"boost::filesystem::copy_directory", 
-		//	from_dir_ph, to_dir_ph, boost::system::error_code())); 
-		} 
-
-#endif
-
-#ifdef WIN32
-
-#ifndef __GUICON_H__
-
-#define __GUICON_H__
-
-
-
-void RedirectIOToConsole();
-
-
-
-#endif
+bool ReadInstallInfoCfg(fstream *, Install_info_cfg *);
 
 /* End of File */
 
-
-#include <windows.h>
-
-#include <stdio.h>
-
-#include <fcntl.h>
-
-#include <io.h>
-
-#include <iostream>
-
-#include <fstream>
-
-#ifndef _USE_OLD_IOSTREAMS
-
-using namespace std;
+//End of File
 
 #endif
-
-// maximum mumber of lines the output console should have
-
-static const WORD MAX_CONSOLE_LINES = 500;
-
-
-void RedirectIOToConsole()
-
-{
-	
-	int hConHandle;
-	
-	long lStdHandle;
-	
-	CONSOLE_SCREEN_BUFFER_INFO coninfo;
-	
-	FILE *fp;
-	
-	// allocate a console for this app
-	
-	AllocConsole();
-	
-	// set the screen buffer to be big enough to let us scroll text
-	
-	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), 
-							   
-							   &coninfo);
-	
-	coninfo.dwSize.Y = MAX_CONSOLE_LINES;
-	
-	SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), 
-							   
-							   coninfo.dwSize);
-	
-	// redirect unbuffered STDOUT to the console
-	
-	lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
-	
-	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
-	
-	fp = _fdopen( hConHandle, "w" );
-	
-	*stdout = *fp;
-	
-	setvbuf( stdout, NULL, _IONBF, 0 );
-	
-	// redirect unbuffered STDIN to the console
-	
-	lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
-	
-	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
-	
-	fp = _fdopen( hConHandle, "r" );
-	
-	*stdin = *fp;
-	
-	setvbuf( stdin, NULL, _IONBF, 0 );
-	
-	// redirect unbuffered STDERR to the console
-	
-	lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
-	
-	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
-	
-	fp = _fdopen( hConHandle, "w" );
-	
-	*stderr = *fp;
-	
-	setvbuf( stderr, NULL, _IONBF, 0 );
-	
-	
-	// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog 
-	
-	// point to console as well
-	
-	ios::sync_with_stdio();
-	
-}
-
-
-
-//End of File
-
-
-
-
-
-
-#endif
Index: AE/Installer/trunk/source/main_window.cpp
===================================================================
--- AE/Installer/trunk/source/main_window.cpp	(revision 482)
+++ AE/Installer/trunk/source/main_window.cpp	(revision 487)
@@ -1,986 +1,22 @@
+/***************************************************************************\
+| Project: AE Installer														|
+| By: Gumby & Iritscen														|
+| File: Main_Window.cpp														|
+| Function: Handles the GUI.												|
+| Created: 07/05/2009 20:38:25												|
+\***************************************************************************/
+
 #ifndef NTDDI_VERSION           
 #define NTDDI_VERSION NTDDI_WIN7
 #endif
 #ifdef WIN32
- #include <windows.h>
+#include <windows.h>
 #include <shobjidl.h>
 HWND Handle;
-
 ITaskbarList *pTaskbarList;
 ITaskbarList3 *pTaskbarList3;
 #endif
 
-/*
- AE/Mod Installer
- by Gumby and Iritscen
-*/
-
-// To-do: - Load credits from text resource file
-//		  - Institute lots of checks into file-handling
-//		  - Clear mod info fields when mod is de-selected
-
-#define DEBUG
-#include <stdio.h>
-//#include <conio.h>
-//#include <process.h>
-#include <string>
-#include <iostream>
-#include <cctype>
-#include <vector>
-#include <fstream>
-#include <errno.h>
-#include <sstream>
-
-#include "boost/filesystem.hpp" // includes all needed Boost.Filesystem declarations
-#include "boost/lexical_cast.hpp" //int -> string
-#include "boost/algorithm/string.hpp"
-#include "installer.h"
-
-#ifdef WIN32
-#include <windows.h>
-#else // assume we're on Mac
-#include <stdlib.h>
-#include <dirent.h>
-#endif
-
-
-const bool SPLIT = 1;
-const bool NOT_SPLIT = 0;
-bool splitInstances = SPLIT;
-bool busy = 0;
-#ifdef WIN32
-const string strOniSplit = "Onisplit.exe";
-string strImportOption = "-import:nosep";
-const char* strClsCmd = "cls";
-const char* strPauseCmd = "PAUSE";
-#else // set up Mac equivalents since we're in Mac OS
-const string strOniSplit = "mono Onisplit.exe";
-string strImportOption = "-import:sep";
-const char* strClsCmd = "clear";
-const char* strPauseCmd = "read -n 1 -p \"Press any key to continue\"";
-void Sleep(int ms) { sleep( ms / 1000 ); }
-#endif
-
-using namespace boost::filesystem; 
-using namespace std;
-
-
-vector<string> globalInstalledMods;
-vector<ModPackage> globalPackages;
-
-
-#include "boost/date_time/gregorian/gregorian.hpp"
-#include "boost/date_time/date_parsing.hpp"
-#include "boost/date_time/posix_time/posix_time.hpp" 
-
-string escapePath(string input) {
-	
-	string output;
-	string escape_me = "& ;()|<>\"'\\#*?$";
-	for(unsigned int i = 0; i < input.size(); i++)  {
-		for(unsigned int j = 0; j < escape_me.size(); j++) if (input[i] == escape_me[j]) output += '\\';
-		output += input[i];
-	}
-	return output;
-}
-
-int globalizeData(void)
-{
-	busy = 1;
-	using boost::lexical_cast;
-	using boost::bad_lexical_cast;
-	// using namespace boost::posix_time;
-	using namespace boost::gregorian;
-	using namespace boost::posix_time;
-	ptime start_time(second_clock::local_time());
-
-	setStatusArea("Globalizing!");
-	int err = 0;
-	int parts_done = 0;
-	char Step_x_x[300];
-	//char levels[i][5];
-	remove("Globalize.log");
-	ofstream logfile("Globalize.log");
-	logfile << "Globalization started " << to_simple_string(start_time) << endl;
-	try {
-
-		char levels_cstr[15][3] = {"0", "1", "2", "3", "4", "6", "8", "9", "10", "11", "12", "13", "14", "18", "19"}; // the levels Oni has...probably should have made a string array. Oops.
-		//const vector<double> ck(cv, &cv[CvSize]);
-		vector<string> levels;
-		for (int f = 0; f < 15; f++) {
-			levels.push_back(levels_cstr[f]);
-		}
-		char choice = 0;
-
-		//SetCurrentDirectory("C:/Program Files/Oni/edition/install");
-		///char levels[i][3];
-		path Characters = "../GameDataFolder/level0_Characters";
-		path Particles = "../GameDataFolder/level0_Particles";
-		path Archive = "../GameDataFolder/Archive";
-		path Textures  = "../GameDataFolder/level0_Textures";
-		path Sounds = "../GameDataFolder/level0_Sounds";
-		path Animations = "../GameDataFolder/level0_Animations";
-		path TRAC = Animations / "level0_TRAC";
-		path TRAM = Animations / "level0_TRAM";
-
-		vector<path> GDFPaths;
-		//GDFPaths.push_back(Characters);
-		GDFPaths.push_back(Particles);
-		GDFPaths.push_back(Textures);
-		GDFPaths.push_back(Sounds);
-		GDFPaths.push_back(TRAC);
-		GDFPaths.push_back(TRAM);
-
-
-		path VanillaCharacters = "VanillaDats/level0_Final/level0_Characters/level0_Characters.oni";
-		path VanillaParticles = "VanillaDats/level0_Final/level0_Particles/level0_Particles.oni";
-		path VanillaTextures  = "VanillaDats/level0_Final/level0_Textures/level0_Textures.oni";
-		path VanillaSounds = "VanillaDats/level0_Final/level0_Sounds/level0_Sounds.oni";
-		path VanillaAnimations = "VanillaDats/level0_Final/level0_Animations/level0_Animations.oni";
-		path VanillaTRAC = "VanillaDats/level0_Final/level0_Animations/level0_TRAC.oni";
-		path VanillaTRAM = "VanillaDats/level0_Final/level0_Animations/level0_TRAM.oni";
-
-		vector<path> VanillaPaths;
-
-		//VanillaPaths.push_back(VanillaCharacters);
-		VanillaPaths.push_back(VanillaParticles);
-		VanillaPaths.push_back(VanillaTextures);
-		VanillaPaths.push_back(VanillaSounds);
-		VanillaPaths.push_back(VanillaTRAC);
-		VanillaPaths.push_back(VanillaTRAM);
-
-		/*
-		if (exists("../GameDataFolder/"))
-		{
-		//cout << "\nIt looks like you've already globalized Oni's data.\nDo you want to re-globalize?\n(This will erase existing mods installed to the AE's game data.)"
-		//	 << "\n1. Re-globalize"
-		//	 << "\n2. Return to main menu\n";
-		//choice = cin.get();
-		cin.ignore(128, '\n');
-		if (choice == '1')
-		remove_all("../GameDataFolder"); // remove AE GDF
-		if (choice == '2')
-		return 0;
-		}
-		*/
-		setStatusArea("Removing old GameDataFolder...\n");
-		logfile <<  "Removing old GameDataFolder...\n";
-		remove_all( "../GameDataFolder/" );
-		setStatusArea("Creating needed directories...");
-		logfile <<  "Creating needed directories...\n";
-		create_directory( "../GameDataFolder/" );
-
-		create_directory( "packages" );
-
-		if (exists("VanillaDats")) remove_all("VanillaDats"); 
-		create_directory( "VanillaDats" );
-		create_directory( "VanillaDats/level0_Final/" );
-		//blah blah finish this.
-		//logfile <<  "VanillaDats/level0_Final/ created";
-		create_directory( Characters );
-		create_directory( Particles );
-		create_directory( Archive );
-		create_directory( Textures );
-		create_directory( Sounds );
-		create_directory( Animations );
-		create_directory( TRAC );
-		create_directory( TRAM );
-		int num_levels = 0;
-		for(int i = 1; i < 15; i++)
-		{
-			if (exists("../../GameDataFolder/level" + levels[i] + "_Final.dat")) {
-				num_levels++;
-
-			}
-		}
-		logfile << "Exporting and moving...\n\n";
-		int total_steps =  8 + 2 * num_levels;
-	
-		for(int i = 0; i < 15; i++)
-		{
-
-			//printf(levels[i],"%d",levels[i]); // int to char array
-
-			if (exists("../../GameDataFolder/level" + levels[i] + "_Final.dat")) {
-				logfile << "level" << levels[i] << "_Final\n";
-				logfile << "\tExporting level" << levels[i] << "_Final.dat\n";
-				//printf(Step_x_x,"Step %d/%d: exporting level%d_final.dat", parts_done + 1,, levels[i]); setStatusArea((string)Step_x_x);
-				setStatusArea("Step " + lexical_cast<std::string>(parts_done + 1) + "/" + lexical_cast<std::string>(total_steps) + " exporting level" + levels[i]+"_Final.dat");
-				create_directory( "../GameDataFolder/level" + levels[i] + "_Final" ); 
-				//				setStatusArea(strOniSplit + " -export ../GameDataFolder/level" + levels[i] + "_Final ../../GameDataFolder/level" + levels[i] + "_Final.dat");
-				system((strOniSplit + " -export ../GameDataFolder/level" + levels[i] + "_Final ../../GameDataFolder/level" + levels[i] + "_Final.dat").c_str());
-				create_directory( "VanillaDats/level" + levels[i] + "_Final" ); 
-				create_directory( "VanillaDats/level" + levels[i] + "_Final/level" + levels[i] + "_Final" );
-				
-				//Moves the AKEV and other files into a safe directory so that level specific textures are not globalized...
-				if ( strcmp(levels[i].c_str(), "0") ){
-					create_directory( "../GameDataFolder/level" + levels[i] + "_Final/AKEV" ); 
-					system((strOniSplit + " -move:overwrite ../GameDataFolder/level" + levels[i] + "_Final/AKEV ../GameDataFolder/level" + levels[i] + "_Final/AKEV*.oni").c_str());
-
-				}
-
-				directory_iterator end_iter;
-				for ( directory_iterator dir_itr( "../GameDataFolder/level" + levels[i] + "_Final" ); dir_itr != end_iter; ++dir_itr )
-				{
-					//cout << dir_itr->path().filename();
-					if ( is_regular_file( dir_itr->status() ) )
-					{
-						if ( dir_itr->path().filename().substr(0,8) == "TXMPfail" || 
-							dir_itr->path().filename().substr(0,9) == "TXMPlevel" ||
-							( dir_itr->path().filename().substr(0,4) == "TXMP" && dir_itr->path().filename().find("intro")!=string::npos) ||
-							dir_itr->path().filename().substr(0,4) == "TXMB" || 
-							dir_itr->path().filename() == "M3GMpowerup_lsi.oni" ||
-							dir_itr->path().filename() == "TXMPlsi_icon.oni" ||
-							( dir_itr->path().filename().substr(0,4) == "TXMB" && dir_itr->path().filename().find("splash_screen.oni")!=string::npos)	)
-						{
-							cout <<dir_itr->path().filename() << "\n";
-							create_directory( dir_itr->path().parent_path() / "NoGlobal");	
-							if(!exists( dir_itr->path().parent_path() / "NoGlobal" / dir_itr->filename())) rename(dir_itr->path(), dir_itr->path().parent_path() / "NoGlobal" /
-								dir_itr->filename());
-							else remove(dir_itr->path());
-						}
-						else if (dir_itr->path().filename().substr(0,4) == "TRAC"
-							) {
-								cout <<dir_itr->path().filename() << "\n";
-								if(!exists( TRAC / dir_itr->filename())) rename(dir_itr->path(), TRAC / dir_itr->filename());
-								else remove(dir_itr->path());
-						}
-						else if (dir_itr->path().filename().substr(0,4) == "TRAM") {
-							cout <<dir_itr->path().filename() << "\n";
-							if(!exists( TRAM / dir_itr->filename())) rename(dir_itr->path(), TRAM / dir_itr->filename());
-							else remove(dir_itr->path());
-						}
-						else if (dir_itr->path().filename().substr(0,4) == "ONSK" ||
-							dir_itr->path().filename().substr(0,4) == "TXMP") {
-								cout <<dir_itr->path().filename() << "\n";\
-									create_directory( dir_itr->path().parent_path() / "TexFix");	
-								if(!exists( Textures / dir_itr->filename())) rename(dir_itr->path(), Textures / dir_itr->filename());
-								//rename(dir_itr->path(), dir_itr->path().parent_path() / "TexFix" / dir_itr->filename());
-						}
-						else if (dir_itr->path().filename().substr(0,4) == "ONCC" 
-							|| dir_itr->path().filename().substr(0,4) == "TRBS"
-							|| dir_itr->path().filename().substr(0,4) == "ONCV"
-							|| dir_itr->path().filename().substr(0,4) == "ONVL"
-							|| dir_itr->path().filename().substr(0,4) == "TRMA"
-							|| dir_itr->path().filename().substr(0,4) == "TRSC"
-							|| dir_itr->path().filename().substr(0,4) == "TRAS") {
-								cout <<dir_itr->path().filename() << "\n";
-								if(!exists( Characters / dir_itr->filename())) rename(dir_itr->path(), Characters / dir_itr->filename());
-								else remove(dir_itr->path());
-						}
-						else if (dir_itr->path().filename().substr(0,4) == "OSBD"
-							|| dir_itr->path().filename().substr(0,4) == "SNDD") {
-								cout << dir_itr->path().filename() << "\n";
-								if(!exists( Sounds / dir_itr->filename())) rename(dir_itr->path(), Sounds / dir_itr->filename());
-								else remove(dir_itr->path());
-						}
-						else if (dir_itr->path().filename().substr(0,5) == "BINA3"
-							|| dir_itr->path().filename().substr(0,10) == "M3GMdebris"
-							|| dir_itr->path().filename() == "M3GMtoxic_bubble.oni"
-							|| dir_itr->path().filename().substr(0,8) == "M3GMelec"
-							|| dir_itr->path().filename().substr(0,7) == "M3GMrat"
-							|| dir_itr->path().filename().substr(0,7) == "M3GMjet"
-							|| dir_itr->path().filename().substr(0,9) == "M3GMbomb_"
-							|| dir_itr->path().filename() == "M3GMbarab_swave.oni"
-							|| dir_itr->path().filename() == "M3GMbloodyfoot.oni"
-							){
-								cout <<dir_itr->path().filename() << "\n";
-								if(!exists( Particles / dir_itr->filename())) rename(dir_itr->path(), Particles / dir_itr->filename());
-								else remove(dir_itr->path());
-						}
-						else if (dir_itr->path().filename().substr(0,4) == "AGDB"
-							|| dir_itr->path().filename().substr(0,4) == "TRCM") {
-								cout <<dir_itr->path().filename() << "\n";
-
-								if(!exists( Archive / dir_itr->filename())) rename(dir_itr->path(), Archive / dir_itr->filename());
-								else remove(dir_itr->path());
-						}
-						else if (dir_itr->path().filename().substr(0,4) == "ONWC") { //fix for buggy ONWC overriding
-								cout <<dir_itr->path().filename() << "\n";
-
-								if(!exists( "VanillaDats/level0_Final/level0_Final/" +  dir_itr->filename())) rename(dir_itr->path(), "VanillaDats/level0_Final/level0_Final/" +  dir_itr->filename());
-								else remove(dir_itr->path());
-						}
-
-						if (exists(dir_itr->path())) {
-
-						}
-						else {
-							logfile << "\tMoved file: " << dir_itr->path().filename() << "\n";
-						}
-					}
-
-
-
-				}
-				
-				logfile << "\tCleaning up TXMPs...\n";
-				system( (strOniSplit + " -move:delete " + Textures.string() + " ../GameDataFolder/level" + levels[i] + "_Final/TXMP*.oni").c_str());
-				
-
-				if ( strcmp(levels[i].c_str(), "0") ){
-					system((strOniSplit + " -move:overwrite ../GameDataFolder/level" + levels[i] + "_Final ../GameDataFolder/level" + levels[i] + "_Final/AKEV/AKEV*.oni").c_str());
-					remove(  "../GameDataFolder/level" + levels[i] + "_Final/AKEV" );
-				}
-
-				parts_done++;
-
-				setProgressBar( (int)(1000 * (float)(parts_done) / (float)(total_steps) )); 
-
-			}
-		}
-		logfile << "Reimporting levels\n";
-		for (int i = 0; i < 15; i++)
-		{
-			logfile << "\tReimporting level" << levels[i] << "_Final.oni\n";
-			//printf(levels[i],"%d",levels[i]);
-			//printf(Step_x_x,"Step %d/%d: reimporting level", parts_done + 1, 7 + 2 * num_levels); setStatusArea((string)Step_x_x + levels[i] + (string)"_Final.dat");
-			setStatusArea("Step " + lexical_cast<std::string>(parts_done + 1) + "/" + lexical_cast<std::string>(total_steps) + " reimporting level" + levels[i]+"_Final.oni");
-			logfile << (strOniSplit + " " + strImportOption + " ../GameDataFolder/level" + levels[i] + "_Final VanillaDats/level" + levels[i] + "_Final/level" 
-				+ levels[i] + "_Final/level" + levels[i] + "_Final.oni >> Globalize.log").c_str() << '\n';
-			string sys_str = (strOniSplit + " " + strImportOption + " ../GameDataFolder/level" + levels[i] + "_Final VanillaDats/level" + levels[i] + "_Final/level"
-				+ levels[i] + "_Final/level" + levels[i] + "_Final.oni");
-				system(sys_str.c_str() );
-			setProgressBar( (int)(1000 * (float)(parts_done) / (float)(total_steps) ));
-			parts_done++;
-		}
-		//create_directory( VanillaCharacters.parent_path() );
-		create_directory( VanillaParticles.parent_path() );
-		create_directory( VanillaTextures.parent_path() );
-		create_directory( VanillaSounds.parent_path() );
-		create_directory( VanillaAnimations.remove_filename() );
-
-		for(unsigned int j = 0; j < GDFPaths.size(); j++) {
-			logfile << "\tReimporting " << GDFPaths[j].filename() << ".oni\n";
-			setStatusArea("Step " + lexical_cast<std::string>(parts_done + 1) + "/" + lexical_cast<std::string>(total_steps) + ": reimporting " + GDFPaths[j].filename() );
-			system((strOniSplit + " " + strImportOption + " " + GDFPaths[j].string() + " " + VanillaPaths[j].string()).c_str());
-			parts_done++;
-			setProgressBar( (int)(1000 * (float)(parts_done) / (float)(total_steps) )); 
-		}
-		logfile << "\nMoving level0_Characters\n";
-		setStatusArea("Step " + lexical_cast<std::string>(parts_done + 1) + "/" + lexical_cast<std::string>(total_steps) + ": moving level0_Characters" );	
-		copy((path)"../GameDataFolder/level0_Characters", (path)("VanillaDats/level0_Final"));
-		GDFPaths.push_back( Characters );
-		for(int i = 0; i < GDFPaths.size(); i++) 
-		{
-			directory_iterator end_iter;
-			for ( directory_iterator dir_itr( GDFPaths[i] ); dir_itr != end_iter; ++dir_itr )
-			{
-				try 
-				{
-
-
-					rename(dir_itr->path(), "../GameDataFolder/level0_Final/" + dir_itr->path().filename() );
-				}
-				catch(exception &ex) {
-
-				}
-			}
-		}
-		/*
-		printf(Step_x_x,"Step %d/%d: reimporting level0_Characters", parts_done,7 + 2 * num_levels); setStatusArea((string)Step_x_x);setProgressBar( (int)(1000 * (float)(parts_done) / (float)(7 + 2 * num_levels) )); 
-		system((strOniSplit + " " + strImportOption + " " + Characters.string() + " " + VanillaCharacters.string()).c_str());
-		parts_done++; printf(Step_x_x,"Step %d/%d: reimporting level0_Particles", parts_done,7 + 2 * num_levels); setStatusArea((string)Step_x_x);setProgressBar( (int)(1000 * (float)(parts_done) / (float)(7 + 2 * num_levels) )); 
-		system((strOniSplit + " " + strImportOption + " " + Particles.string() + " " + VanillaParticles.string()).c_str());
-		parts_done++; printf(Step_x_x,"Step %d/%d: reimporting level0_Textures", parts_done,7 + 2 * num_levels); setStatusArea((string)Step_x_x);setProgressBar( (int)(1000 * (float)(parts_done) / (float)(7 + 2 * num_levels) )); 
-		system((strOniSplit + " " + strImportOption + " " + Textures.string() + " " + VanillaTextures.string()).c_str());
-		//system((strOniSplit	+ " " + strImportOption + (string)" " + Animations.string() + (string)" " + VanillaAnimations.string()).c_str());
-		parts_done++; printf(Step_x_x,"Step %d/%d: reimporting level0_TRAC", parts_done,7 + 2 * num_levels); setStatusArea((string)Step_x_x);setProgressBar( (int)(1000 * (float)(parts_done) / (float)(7 + 2 * num_levels) )); 
-		system((strOniSplit + " " + strImportOption + " " + TRAC.string() + " " + VanillaTRAC.string()).c_str());
-		parts_done++; printf(Step_x_x,"Step %d/%d: reimporting level0_Sounds", parts_done,7 + 2 * num_levels); setStatusArea((string)Step_x_x);setProgressBar( (int)(1000 * (float)(parts_done) / (float)(7 + 2 * num_levels) )); 
-		system((strOniSplit + " " + strImportOption + " " + Sounds.string() + " " + VanillaSounds.string()).c_str());
-		parts_done++; printf(Step_x_x,"Step %d/%d: reimporting level0_TRAM", parts_done,7 + 2 * num_levels); setStatusArea((string)Step_x_x);setProgressBar( (int)(1000 * (float)(parts_done) / (float)(7 + 2 * num_levels) )); 
-		system((strOniSplit + " " + strImportOption + " " + TRAM.string() + " " + VanillaTRAM.string()).c_str()); 
-		//parts_done++; setStatusArea((string)"Copying level scripts...");setProgressBar( (int)(1000 * (float)(parts_done) / (float)(7 + 2 * num_levels) )); 
-		if (exists("../GameDataFolder/IGMD")) remove_all("../GameDataFolder/IGMD");
-		*/
-		create_directory((path)"../GameDataFolder/IGMD");
-		copy((path)"packages/VanillaBSL/IGMD", (path)"../GameDataFolder");
-		setProgressBar( 1000 );
-
-		if(exists("../../persist.dat")) if(!exists("../persist.dat")) 
-		
-			//TODO: Concactate level0 Dirs.
-
-			copy("../../persist.dat","..");
-		if(exists("../../key_config.txt"))if(!exists("../key_config.txt"))
-			copy("../../key_config.txt",".."); 
-		
-#ifndef WIN32
-		/* On Mac only, set the current GDF to the AE GDF by writing to Oni's global preferences file (thankfully a standard OS X ".plist" XML file).
-		   Tests for presence of prefs with [ -f ] before doing anything so it doesn't create a partial prefs file -- just in case user has never
-		   run Oni before :-p */
-		string fullAEpath = escapePath(system_complete(".").parent_path().parent_path().string()); // get full path for edition/
-		char prefsCommand[300] = "[ -f ~/Library/Preferences/com.godgames.oni.plist ] && defaults write com.godgames.oni RetailInstallationPath -string '";
-		strcat(prefsCommand, fullAEpath.c_str()); // get path of edition/ folder (Oni wants the folder that *contains* the GDF)
-		strcat(prefsCommand, "'"); // path string is enclosed in single quotes to avoid the need to escape UNIX-unfriendly characters
-		system(prefsCommand);
-		
-#endif
-		
-		
-		setStatusArea((string)"Done! Now select your mod packages and click install.");
-		//	while(1) Sleep(-1);
-
-	}
-	catch (exception & ex) {
-		setStatusArea("Warning, handled exception: " + (string)ex.what());
-	}
-
-	ptime end_time(second_clock::local_time());
-	time_period total_time (start_time, end_time);
-	logfile << "\n\nGlobalization ended " << to_simple_string(end_time) << "\nThe process took " << total_time.length();
-	//total_time.length().hours();
-	logfile.close();
-	busy = 0;
-	return err;
-}
-
-
-vector<ModPackage> getPackages(void)
-{
-	vector<ModPackage> packages;
-	packages.reserve(65536); // come on, we shouldn't need this much space...right?!
-	fstream file;
-	string filename = "\0";
-	string MODINFO_CFG = "Mod_Info.cfg";
-
-	try
-	{
-		for (directory_iterator dir_itr("./packages"), end_itr; dir_itr != end_itr; ++dir_itr)
-		{
-			file.open((dir_itr->path().string() + "/" + MODINFO_CFG).c_str());
-			//cout << filename << "\n";
-
-			if(!file.fail())
-			{
-				//cout << dir_itr->path().string() + MODINFO_CFG;
-				//would prefer to push a pointer to a package, but this will do for now
-				packages.push_back(fileToModPackage(file));
-			}	
-			file.close();
-			file.clear();
-		}
-		sort(packages.begin(), packages.end());
-	}
-	catch (const std::exception & ex)
-	{
-		cout << "Warning, something odd happened!\n";
-	}
-
-	return packages;
-}
-
-ModPackage fileToModPackage(fstream &file)
-{
-	/*
-	This converts a file to a ModPackage struct.
-
-	A few notes...
-	"iter" is the current word we are on. I should have named it "token" or something, but I don't have multiple iterators, so its ok.
-	I refer to (*iter) at the beginning of each if statement block. I could probably store it as a variable, but I'm pretty sure that dereferencing a pointer\iterator isn't much
-	slower than reading a variable.
-	*/
-	ModPackage package;
-	string line;
-	static string NameOfMod = "NameOfMod";	//used for comparing to the current token...
-	//I could have done it in reverse (*iter).compare("ModString") or  
-	static string ARROW = "->";				//did something like "ModString".compare(*iter), and it would have been
-	static string ModString = "ModString";	//functionably the same. 
-	static string HasOnis = "HasOnis";
-	static string HasDeltas = "HasDeltas";
-	static string HasBSL = "HasBSL";
-	static string HasDats = "HasDats";
-	static string IsEngine = "IsEngine";
-	static string Readme = "Readme";
-	static string GlobalNeeded = "GlobalNeeded";
-	static string Category = "Category";
-	static string Creator = "Creator";
-	while (! file.eof() )
-	{
-		getline (file,line);
-		vector<string> tokens; 
-		vector<string>::iterator iter;
-		tokenize(line, tokens);					//string to vector of "words"
-		if (tokens.capacity() >= 2) {			//make sure they are using enough stuff
-			iter = tokens.begin();				//what word we are on, starts at first word
-			/*
-			if (!AEInstallVersion.compare(*iter))
-			If mod is too old, skip this mod.
-			*/
-			/*else*/if (!NameOfMod.compare(*iter))  {	//if it contains the name
-				for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {	//interates through the words, ends if it reaches the end of the line or a "//" comment
-					if (ARROW.compare(*iter) && NameOfMod.compare(*iter)) {			//ignores "->" and "NameOfMod"
-						//cout << *iter; 
-						//cout << " ";
-						package.name += *iter + " ";
-					}
-				}
-
-			}
-			else if (!ModString.compare(*iter)) {
-				iter++; iter++;
-				package.modStringName = *iter;
-				iter++;
-				package.modStringVersion = atoi((*iter).c_str());
-			}
-			else if (!HasOnis.compare(*iter)) {
-				iter++; iter++;  
-				if ( boost::iequals(*iter, "Yes")) package.hasOnis = 1;
-			}	
-			else if (!HasBSL.compare(*iter)) { // string comparer...I know my implementation here sucks. I need to change it to check each character one by one. At the moment,
-				iter++; iter++;  // using "YFR" would probably set it off. :<
-				if ( boost::iequals(*iter, "Yes")) package.hasBSL = 1;
-				else if ( boost::iequals(*iter, "Addon")) package.hasAddon = 1;
-			}
-			else if (!HasDeltas.compare(*iter)) {
-				iter++; iter++;  
-				if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasDeltas = 1;
-			}
-			else if (!HasDats.compare(*iter)) {
-				iter++; iter++;  
-				if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasDats = 1;
-			}
-			else if (!IsEngine.compare(*iter)) {
-				iter++; iter++;  
-				if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.isEngine = 1;
-			}
-			else if (!GlobalNeeded.compare(*iter)) {
-				iter++; iter++;  
-				if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.globalNeeded = 1;
-				else if (toupper((*iter)[0]) + toupper((*iter)[1]) == 'N' + 'O') package.globalNeeded = 1; //Really the only place where checking for "No" is important atm.
-			}
-			else if (!Category.compare(*iter))  {	
-				for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {	//interates through the words, ends if it reaches the end of the line or a "//" comment
-					if (ARROW.compare(*iter) && Category.compare(*iter)) {			//ignores "->" and "Category"
-						//cout << *iter; 
-						//cout << " ";
-						package.category += *iter + " ";
-					}
-			}
-		}
-		else if (!Creator.compare(*iter))  {	//if it contains the name
-			for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {	//interates through the words, ends if it reaches the end of the line or a "//" comment
-				if (ARROW.compare(*iter) && Creator.compare(*iter)) {			//ignores "->" and "Category"
-					//cout << *iter; 
-					//cout << " ";
-					package.creator += *iter + " ";
-				}
-			}
-		}
-		else if (!Readme.compare(*iter))  {	//if it contains the name
-			for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {	//interates through the words, ends if it reaches the end of the line or a "//" comment
-				if (ARROW.compare(*iter) && Readme.compare(*iter)) {			//ignores "->" and "Category"
-					if(!(*iter).compare("\\n")) package.readme += '\n';
-					else package.readme += *iter + " ";
-				}
-			}
-		}
-	}
-
-}
-package.doOutput();
-return package;
-}
-
-void recompileAll(vector<string> installedMods)
-{try {
-	busy = 1;
-	using namespace boost::gregorian;
-	using namespace boost::posix_time;
-	using boost::lexical_cast;
-	using boost::bad_lexical_cast;
-		path vanilla_dir = "./VanillaDats/";
-	string importCommand = "";
-	char statusString[128];
-	int numberOfDats = 0;
-	int j = 1;
-	string datString;
-	
-
-	setStatusArea("Importing levels...");
-	//setStatusArea("Recompiling Data...");
-
-	std::stringstream out;
-
-	ptime start_time(second_clock::local_time());
-	clearOldDats();
-	
-	if(exists("Install.log")) remove("Install.log");
-	ofstream logfile("Install.log");
-	logfile << "Mod Installation started " << to_simple_string(start_time) << endl;
-	logfile.close();
-
-
-	if(splitInstances == SPLIT){
-		recursive_directory_iterator end_iter;
-
-		for ( recursive_directory_iterator dir_itr( vanilla_dir );
-			dir_itr != end_iter;
-			++dir_itr )
-		{
-			try{
-				if ( is_directory( dir_itr->status() ) &&  dir_itr.level() == 1)
-				{
-					numberOfDats++;
-				}
-			}
-			catch(exception & ex) {
-					remove("Install.log");
-					ofstream logfile("Install.log");
-
-
-					logfile << "Warning, exception " << ex.what() << "!";
-					setStatusArea("Warning, exception " + (string)ex.what() + "!");
-					logfile.close();	
-			}
-		}
-		try {
-		//recursive_directory_iterator end_iter;
-		
-
-		out << numberOfDats;
-		datString = out.str();
-			for ( recursive_directory_iterator dir_itr( vanilla_dir );
-				dir_itr != end_iter;
-				++dir_itr )
-			{
-				try
-				{
-					if ( is_directory( dir_itr->status() ) &&  dir_itr.level() == 1)
-					{
-						importCommand = strOniSplit + " " + strImportOption + " " + dir_itr->path().parent_path().string() + '/' + dir_itr->path().filename();
-						for (unsigned int i = 0; i < installedMods.size(); ++i) {
-							if (exists("packages/" + installedMods[i] + "/oni/" + dir_itr->path().parent_path().filename() + '/' + dir_itr->path().filename()  ))
-								importCommand += " packages/" + installedMods[i] + "/oni/" + dir_itr->path().parent_path().filename() + '/' + dir_itr->path().filename();
-
-							//else cout << " VanillaDats/" + installedMods[i] + "/oni/";
-						}
-						importCommand += " ../GameDataFolder/" + dir_itr->path().filename() + ".dat >> Install.log";
-
-						
-						setProgressBar( (int)(1000 * (float)(j-1) / (float)numberOfDats) ); //100% * dat we're on / total dats
-						setStatusArea("Step " + lexical_cast<std::string>(j) + '/' + lexical_cast<std::string>(numberOfDats)+ ": Importing " +  dir_itr->path().filename() + " ");
-
-						system(importCommand.c_str());
-						//Sleep(1000);
-						//cout << importCommand << "\n";
-						j++;
-
-					}
-				}
-				catch ( const std::exception & ex )
-				{
-
-					remove("Install.log");
-					ofstream logfile("Install.log");
-
-
-					logfile << "Warning, exception " << ex.what() << "!";
-					setStatusArea("Warning, exception " + (string)ex.what() + "!");
-					logfile.close();	
-				}
-			}
-
-		}
-		catch( const std::exception & ex ) {
-
-			remove("Install.log");
-			ofstream logfile("Install.log");
-
-
-			logfile << "Warning, exception " << ex.what() << "!";
-			setStatusArea("Warning, exception " + (string)ex.what() + "!");
-			logfile.close();
-		}
-
-	}
-	else if(splitInstances == NOT_SPLIT){
-		directory_iterator end_iter;
-
-		for ( directory_iterator dir_itr( vanilla_dir );
-			dir_itr != end_iter;
-			++dir_itr )
-		{
-
-			if ( is_directory( dir_itr->status() ) )
-			{
-				numberOfDats++;
-			}
-
-
-		}
-
-		out << numberOfDats;
-		datString = out.str();
-
-		for ( directory_iterator dir_itr( vanilla_dir );
-			dir_itr != end_iter;
-			++dir_itr )
-		{
-			try
-			{
-				if ( is_directory( dir_itr->status() ) )
-				{
-					importCommand = strOniSplit + " " + strImportOption + " " + vanilla_dir.string() + dir_itr->path().filename() + " ";
-					for (unsigned int i = 0; i < installedMods.size(); ++i) {
-						if (exists("packages/" + installedMods[i] + "/oni/" + dir_itr->path().filename()  ))
-							importCommand += " packages/" + installedMods[i] + "/oni/" + dir_itr->path().filename();
-					}
-					importCommand += " ../GameDataFolder/" + dir_itr->path().filename() + ".dat >> Install.log";
-
-
-					setProgressBar( (int)(1000 * (float)(j-1) / (float)numberOfDats) ); //100% * dat we're on / total dats
-					setStatusArea("Step " + lexical_cast<std::string>(j) + '/' + lexical_cast<std::string>(numberOfDats)+ ": Importing " +  dir_itr->path().filename() + " ");
-
-					system(importCommand.c_str());
-
-					j++;
-				}
-			}
-			catch ( const std::exception & ex )
-			{
-
-				remove("Install.log");
-				ofstream logfile("Install.log");
-
-
-				logfile << "Warning, exception " << ex.what() << "!";
-				setStatusArea("Warning, exception " + (string)ex.what() + "!");
-				logfile.close();
-			}}
-	}
-
-
-
-	
-
-
-
-
-		
-		
-		vector<string> BSLfolders;
-		vector<string> skippedfolders;
-
-		
-ofstream BSLlog("BSL.log");
-		for ( directory_iterator dir_itr( "../GameDataFolder/IGMD/" ), end_itr;
-			dir_itr != end_itr;
-			++dir_itr ) {
-				if( exists(dir_itr->path().string() + "/ignore.txt") ){
-					BSLfolders.push_back(dir_itr->path().filename());
-					skippedfolders.push_back(dir_itr->path().filename());
-				}
-		}
-
-		for (int i = installedMods.size() - 1; i >= 0; i--) {							//Iterates through the installed mods (backwards :P)
-			for (unsigned int j = 0; j < globalPackages.size(); ++j) {				//looking in the global packages
-				if (globalPackages[j].modStringName == installedMods[i]) {	//for a mod that has BSL in it
-				/*BSLlog << "Testing " << globalPackages[j].modStringName << "\n"
-						<< "HasBSL: " << globalPackages[j].hasBSL << "\n"
-						<< "HasAddon: " << globalPackages[j].hasAddon << "\n";*/
-					if(!(globalPackages[j].hasAddon || globalPackages[j].hasBSL)) break; //skip non-BSL
-					if( exists( "packages/" + globalPackages[j].modStringName + "/BSL/" ) ) {
-					copyBSL("packages/" + globalPackages[j].modStringName + "/BSL", BSLfolders, globalPackages[j] );
-					BSLlog << "Copied " <<  globalPackages[j].modStringName << "!\n";
-					}
-
-				}
-
-			}
-		}
-
-		ModPackage emptyPackage;
-		emptyPackage.modStringName = "VanillaBSL";
-		emptyPackage.hasBSL = 1;
-		copyBSL("packages/VanillaBSL/IGMD", BSLfolders, emptyPackage);
-		BSLlog.close();
-	
-
-	logfile << "Writing config file";
-	writeInstalledMods(installedMods);
-	setProgressBar(1000);
-	
-	string finallyDone = "Done! You can now play Oni.";
-	
-
-	
-	setStatusArea(finallyDone);
-
-	ptime end_time(second_clock::local_time());
-	time_period total_time (start_time, end_time);
-
-
-	ofstream logfile2("Install.log", ios::app | ios::ate);
-	string outstring = (string)"\n\nGlobalization ended " + to_simple_string(end_time) + "\nThe process took ";// + (string)total_time.length();
-
-	logfile2 << "\nInstallation ended " << to_simple_string(end_time) << "\nThe process took " << total_time.length();
-
-	//logfile2.write(outstring.c_str(), outstring.length());
-	logfile2.close();
-
-	//total_time.length().hours();
-
-	Sleep(1000);
-	setProgressBar(0);
-
-	}
-	catch(exception & ex) {
-		remove("Install.log"); //why did we do this? :|
-		ofstream logfile("Install.log");
-
-
-		logfile << "Warning, exception " << ex.what() << "!";
-		setStatusArea("Warning, exception " + (string)ex.what() + "!");
-		logfile.close();	
-	}
-	busy = 0;
-}
-
-void copyBSL(string copypath, vector<string>& BSLfolders, ModPackage pkg) {
-
-	ofstream BSLlog("BSL2.log", ios::app );
-	
-	try {
-		for ( directory_iterator dir_itr( copypath ), end_itr;
-			dir_itr != end_itr;
-			++dir_itr ) {
-
-				if ( is_directory( dir_itr->path() ) && dir_itr->path().string() != ".svn" ) {  
-					BSLlog << "Testing " << dir_itr->path().string() << " HasBSL: " << pkg.hasBSL << " HasAddon: " << pkg.hasAddon << "\n";
-					int skip_folder = 0;
-
-					for(unsigned int k = 0; k < BSLfolders.size(); k++)		{//iterate through already found BSL folders	
-						BSLlog << "testing " << dir_itr->path().filename() << " vs " << BSLfolders[k] << "\n";
-						if(dir_itr->path().filename() == BSLfolders[k]) {
-							skip_folder = 1;
-							BSLlog << "skipping " << BSLfolders[k] << " in " << pkg.modStringName << "\n";
-							break;
-						}
-					}
-					if (!skip_folder && !exists("../GameDataFolder/IGMD/" + dir_itr->path().filename() + "/ignore.txt")) {
-						remove_all( "../GameDataFolder/IGMD/" + dir_itr->path().filename() );
-						Sleep(100);
-						create_directory( "../GameDataFolder/IGMD/" + dir_itr->path().filename());
-						BSLlog << "Copied " << dir_itr->path().string() << " in " << pkg.modStringName << "!\n";
-						for ( directory_iterator bsl_itr( dir_itr->path() );
-							bsl_itr != end_itr;
-							bsl_itr++ ) {
-								if ( bsl_itr->path().extension() == ".bsl" ) {
-									copy_file(bsl_itr->path(),  "../GameDataFolder/IGMD/" + dir_itr->path().filename() + "/" + bsl_itr->path().filename()); 
-								}
-						}
-						BSLfolders.push_back( dir_itr->path().filename() ); //add back check for addon
-						BSLlog << "Pushing " << dir_itr->path().filename() << "\n" ;
-					}
-				}
-		}
-	}
-	catch ( const std::exception & ex )
-	{
-		setStatusArea("Warning, exception " + (string)ex.what() + "!");
-		while(1) Sleep(1000);
-	}
-	BSLlog.close();
-	
-}
-
-
-void writeInstalledMods(vector<string> installedMods)
-{
-
-	if ( exists( strInstallCfg ) )
-	{
-		remove( strInstallCfg );
-	}
-
-	ofstream file(strInstallCfg.c_str());
-
-	vector<string>list = installedMods;
-	vector<string>::iterator begin_iter = list.begin(); 
-	vector<string>::iterator end_iter = list.end();
-
-	sort( list.begin(), list.end() );
-
-	for( ; begin_iter != end_iter; ++begin_iter) {
-		file << *begin_iter << " ";
-	}
-
-	file.close();
-	file.clear();
-
-}
-
-vector<string> getInstallString(string Cfg)
-{
-	//system(strPauseCmd);
-	vector<string> returnval;
-
-	string line;
-	fstream file;
-
-	if (exists( Cfg ))
-	{
-		file.open(Cfg.c_str());
-		getline(file, line);
-		tokenize(line, returnval);
-		file.close();
-		file.clear();
-		sort(returnval.begin(), returnval.end());
-	}
-	else cout << "fail";
-
-	return returnval;
-}
-
-//stolen token function...
-void tokenize(const string& str, vector<string>& tokens, const string& delimiters)
-{
-	// Skip delimiters at beginning.
-	string::size_type lastPos = str.find_first_not_of(delimiters, 0);
-	// Find first "non-delimiter".
-	string::size_type pos     = str.find_first_of(delimiters, lastPos);
-
-	while (string::npos != pos || string::npos != lastPos)
-	{
-		// Found a token, add it to the vector.
-		tokens.push_back(str.substr(lastPos, pos - lastPos));
-		// Skip delimiters.  Note the "not_of"
-		lastPos = str.find_first_not_of(delimiters, pos);
-		// Find next "non-delimiter"
-		pos = str.find_first_of(delimiters, lastPos);
-	}
-}
-
-void clearOldDats(void) {
-	directory_iterator end_iter_gdf;
-	for ( directory_iterator dir_itr_gdf( "../GameDataFolder" );
-		dir_itr_gdf != end_iter_gdf;
-		++dir_itr_gdf )
-	{
-		//cout << dir_itr_gdf->path().extension() << "\n";
-		if ( dir_itr_gdf->path().extension() == ".dat" || dir_itr_gdf->path().extension() == ".raw" || dir_itr_gdf->path().extension() == ".sep" ) {
-			remove( dir_itr_gdf->path() );
-		}
-
-	}
-
-}
-
-#include "boost/thread.hpp"
 #include <boost/thread/mutex.hpp>
-
-/////////////////////////////////////////////////////////////////////////////
-// Name:        main_window.cpp
-// Purpose:     
-// Author:      
-// Modified by: 
-// Created:     07/05/2009 20:38:25
-// RCS-ID:      
-// Copyright:   
-// Licence:     
-/////////////////////////////////////////////////////////////////////////////
-
 // For compilers that support precompilation, includes "wx/wx.h".
 #include "wx/wxprec.h"
@@ -996,7 +32,7 @@
 ////@begin includes
 #include "about.h"
+#include "main_window.h"
+#include "installer.h"
 ////@end includes
-
-#include "main_window.h"
 
 ////@begin XPM images
@@ -1008,6 +44,17 @@
 ////@end XPM images
 
-//#define wxDebug 1;
-//#define wxUSE_UNICODE 1;
+bool busy = false;
+vector<string> globalInstalledMods;
+vector<ModPackage> globalPackages;
+// Variable declarations
+#ifdef WIN32
+bool splitInstances = true;
+string strImportOption = "-import:nosep";
+string strOniSplit = "Onisplit.exe";
+#else
+bool splitInstances = false;
+string strImportOption = "-import:sep";
+string strOniSplit = "mono Onisplit.exe";
+#endif
 
 /*
@@ -1093,5 +140,4 @@
 }
 
-
 /*
 * MainWindow destructor
@@ -1103,5 +149,4 @@
 	////@end MainWindow destruction
 }
-
 
 /*
@@ -1129,7 +174,5 @@
     ReglobalizeButton = NULL;
 	////@end MainWindow member initialisation
-
-}
-
+}
 
 /*
@@ -1169,5 +212,4 @@
     itemMenu42->Append(wxID_OPTIONS, _("Show Advanced Options..."), wxEmptyString, wxITEM_CHECK);
     menuBar->Append(itemMenu42, _("Options"));
-    wxMenu* itemMenu44 = new wxMenu;
 #ifdef WIN32
 	itemMenu44->Append(wxID_ABOUT, _("About"), wxEmptyString, wxITEM_NORMAL);
@@ -1242,5 +284,6 @@
     StatusArea->SetName(_T("StatusArea"));
     StatusArea->SetFieldsCount(1);
-    StatusArea->SetStatusText(_("AE Installer v1.0.1"), 0);
+	string versionText = "AE Installer v" + (string)INSTALLER_VERSION;
+    StatusArea->SetStatusText(versionText.c_str(), 0);
     itemBoxSizer2->Add(StatusArea, 0, wxGROW|wxALL, 0);
 
@@ -1312,31 +355,4 @@
 	::CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList, (void **)&pTaskbarList);
 #endif
-
-
-	/*if ( exists( "../../GameDataFolder/level0_Final.sep" ) ) {
-		strImportOption = "-import:sep";
-		splitInstances = NOT_SPLIT;
-	}
-	else {
-		strImportOption = "-import:nosep";
-		splitInstances = SPLIT;
-	}*/
-	
-
-#ifndef WIN32
-		strImportOption = "-import:sep";
-		splitInstances = NOT_SPLIT;
-#else
-		strImportOption = "-import:nosep";
-		splitInstances = SPLIT;
-#endif
-
-#ifndef WIN32
-	strImportOption = "-import:sep";
-	splitInstances = NOT_SPLIT;
-#else
-	strImportOption = "-import:nosep";
-	splitInstances = SPLIT;
-#endif
 	
 	globalPackages = getPackages();
@@ -1352,14 +368,8 @@
 	OptionsPanel->Hide();
 	
-//#ifndef WIN32
-//	itemMenu37->Append(wxID_ABOUT, _("About"), wxEmptyString, wxITEM_NORMAL);
-	
-//#endif
-	
-	if(splitInstances == SPLIT) SeperatedRadio->SetValue(true);
+	if(splitInstances) SeperatedRadio->SetValue(true);
 	else CompleteRadio->SetValue(true);
 	if(strImportOption == "-import:nosep") NoSepRadio->SetValue(true);
 	else SepRadio->SetValue(true);
-
 
 #ifdef WIN32
@@ -1368,8 +378,5 @@
 	ShowWindow( hWnd, SW_HIDE ); 
 #endif
-
-	//MainWindow::SetSize(MainWindow::GetRect().GetWidth(), MainWindow::GetRect().GetHeight()-OptionsPanel->GetRect().GetHeight() );
-}
-
+}
 
 /*
@@ -1382,19 +389,13 @@
 	case wxCHK_UNCHECKED:
 		for(unsigned int i = 0; i < globalPackages.size(); i++) Mods_CheckboxList->Check(i, false);
-		//SelectAll->Set3StateValue(wxCHK_CHECKED);
 		break;
 	case wxCHK_CHECKED:
 		for(unsigned int i = 0; i < globalPackages.size(); i++) Mods_CheckboxList->Check(i, true);
-		//SelectAll->Set3StateValue(wxCHK_UNCHECKED);
 		break;
 	case wxCHK_UNDETERMINED:
 		for(unsigned int i = 0; i < globalPackages.size(); i++) Mods_CheckboxList->Check(i, false);
-		//SelectAll->Set3StateValue(wxCHK_CHECKED);
 		break;
-
-	}
-
-}
-
+	}
+}
 
 /*
@@ -1404,5 +405,4 @@
 void MainWindow::ModList_OnCreate( wxWindowCreateEvent& event )
 {
-
 
 }
@@ -1457,5 +457,4 @@
 wxIcon MainWindow::GetIconResource( const wxString& name )
 {
-
 	// Icon retrieval
 	////@begin MainWindow icon retrieval
@@ -1470,5 +469,4 @@
 }
 
-
 /*
 * wxEVT_COMMAND_LISTBOX_SELECTED event handler for Mods_CheckboxList1
@@ -1477,12 +475,8 @@
 void MainWindow::OnModsCheckboxList1Selected( wxCommandEvent& event )
 {
-	//event.GetSelection
 	titleText->SetValue(globalPackages[event.GetSelection()].name.c_str());
 	creatorText->SetValue(globalPackages[event.GetSelection()].creator.c_str());
 	descriptionText->SetValue(globalPackages[event.GetSelection()].readme.c_str());
-
-	//creatorText->Refresh();
-}
-
+}
 
 /*
@@ -1519,6 +513,5 @@
 		this->SetSize(this->GetRect().GetWidth(), this->GetRect().GetHeight()-OptionsPanel->GetRect().GetHeight());}
 	else {
-//		Uncomment this when we release, it gets annoying if you are testing globalization a lot ;)
-		wxMessageDialog* YesNoDialog = new wxMessageDialog(this, 			"WARNING: These options are for advanced users only, use with caution.",
+		wxMessageDialog* YesNoDialog = new wxMessageDialog(this, "WARNING: These options are for advanced users only, use with caution.",
 														   "AE Installer Alert",  wxOK | wxICON_EXCLAMATION	, wxDefaultPosition);
 		YesNoDialog->ShowModal();
@@ -1529,5 +522,4 @@
 }
 
-
 /*
 * wxEVT_COMMAND_MENU_SELECTED event handler for wxID_EXIT
@@ -1539,9 +531,7 @@
 }
 
-
 /*
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for Install_Button
 */
-
 
 struct recompile
@@ -1555,5 +545,4 @@
 		
 	}
-
 	vector<string> thePackages;
 };
@@ -1565,9 +554,6 @@
 }
 
-
-
 void MainWindow::OnInstallButtonClick( wxCommandEvent& event )
 {
-
 	vector<string> localPackages;
 	localPackages.push_back("00000Globalize");
@@ -1576,7 +562,4 @@
 		sort(localPackages.begin(), localPackages.end());
 		localPackages[0] = "Globalize";
-		//MainWindow::MainWindow().Hide();	
-		//	boost::thread thrd2(recompileAll(localPackages) );
-		//MainWindow::MainWindow().Show();
 		this->InstallButton->Disable();
 		this->ReglobalizeButton->Disable();
@@ -1587,46 +570,23 @@
 		recompileAll(localPackages);
 #endif
-
 		this->InstallButton->Enable();
 		this->ReglobalizeButton->Enable();
 	}
-
-
-}
-
-/*void setStatusArea( string s ) {
-//TheStatusBar = MainWindow::StatusArea;
-(**TheStatusBar).SetStatusText(_(s.c_str()), 0);
-
-//MainWindow::MainWindow().SetSize(MainWindow::MainWindow().GetRect().GetWidth(), MainWindow::MainWindow().GetRect().GetHeight()+1);
-
-//MainWindow::StatusBar->SetLabel("Importing Files...");
-//StatusBar->SetLabel(s);
-//->SetLabel(s);
-
-}*/
-
-void setProgressBar( int i ) {
-	//TheProgressBar->SetValue(
+}
+
+void setProgressBar( int i )
+{
 #ifdef WIN32
-	
-
-
 if (SUCCEEDED(pTaskbarList->QueryInterface(IID_ITaskbarList3, (void **)&pTaskbarList3)))
 {
-	
 	pTaskbarList3->SetProgressValue(Handle,i, 1000);
-	if ( i == 0 ) {
-
-	pTaskbarList3->SetProgressState(Handle,TBPF_NOPROGRESS);
-	}
-}
-
-
+	if ( i == 0 )
+	{
+		pTaskbarList3->SetProgressState(Handle,TBPF_NOPROGRESS);
+	}
+}
 #endif
 	TheProgressBar->SetValue(i);
-
-}
-
+}
 
 /*
@@ -1642,5 +602,4 @@
 }
 
-
 /*
 * wxEVT_COMMAND_MENU_SELECTED event handler for wxID_ABOUT
@@ -1651,11 +610,10 @@
 	////@begin wxEVT_COMMAND_MENU_SELECTED event handler for wxID_ABOUT in MainWindow.
     // Before editing this code, remove the block markers.
+	// TODO: Make About window work again!
     About* window = new About(this);
-    int returnValue = window->ShowModal();
     window->Destroy();
 	////@end wxEVT_COMMAND_MENU_SELECTED event handler for wxID_ABOUT in MainWindow. 
 }
 
-
 /*
 * wxEVT_COMMAND_RADIOBUTTON_SELECTED event handler for NoSep_RadioButton
@@ -1667,5 +625,4 @@
 }
 
-
 /*
 * wxEVT_COMMAND_RADIOBUTTON_SELECTED event handler for Sep_RadioButton
@@ -1677,5 +634,4 @@
 }
 
-
 /*
 * wxEVT_COMMAND_RADIOBUTTON_SELECTED event handler for Separated_RadioButton
@@ -1688,8 +644,6 @@
 void MainWindow::OnCompleteRadioButtonSelected( wxCommandEvent& event )
 {
-	splitInstances = NOT_SPLIT;
-
-}
-
+	splitInstances = false;
+}
 
 /*
@@ -1702,21 +656,16 @@
 }
 
-
 /*
 * wxEVT_COMMAND_MENU_SELECTED event handler for wxID_LOAD
 */
 
-
-
-
-void MainWindow::refreshMods (vector<string> s) {
-
+// TODO: Make refreshMods actually refresh the list in the window of available mods so we can see any new package info and deleted mods are removed from the list
+void MainWindow::refreshMods (vector<string> s)
+{
 	Mods_CheckboxList->Clear();
-	//globalInstalledMods = getPackages();
 	for (unsigned int i = 0; i < globalPackages.size(); i++) {
 		Mods_CheckboxList->Append(globalPackages[i].name.c_str());
-		if( binary_search(s.begin(), s.end(), globalPackages[i].modStringName ) ) Mods_CheckboxList->Check(i);
-		//else Mods_CheckboxList->Check(i,0);
-
+		if( binary_search(s.begin(), s.end(), globalPackages[i].modStringName ) )
+			Mods_CheckboxList->Check(i);
 	}
 }
@@ -1738,8 +687,5 @@
 		refreshMods(getInstallString( string(openFileDialog->GetPath()) ));
 	}
-
-
-}
-
+}
 
 /*
@@ -1761,12 +707,4 @@
 	if ( openFileDialog->ShowModal() == wxID_OK )
 	{
-
-
-		//Mods_CheckboxList->
-
-
-
-		//
-
 		if ( exists( openFileDialog->GetPath().c_str() ) )
 		{
@@ -1789,13 +727,6 @@
 		file.close();
 		file.clear();
-
-		//SetCurrentFilename(openFileDialog->GetFilename());
-		//theText->LoadFile(openFileDialog->GetFilename());
-		//SetStatusText(GetCurrentFilename(), 0);
-		//SetStatusText(openFileDialog->GetDirectory(),1);
-	}
-}
-
-
+	}
+}
 
 /*
@@ -1805,16 +736,17 @@
 void MainWindow::OnReGlobalizeButtonClick( wxCommandEvent& event )
 {
-	wxMessageDialog* YesNoDialog = new wxMessageDialog(this, 			"WARNING: This will DELETE the Edition's GameDataFolder and recreate it from the vanilla Oni game data. \n Are you SURE you want to do this? ", "AE Installer Alert",  wxYES_NO | wxICON_EXCLAMATION	, wxDefaultPosition);
-
-	if (YesNoDialog->ShowModal() == wxID_NO) { //if the user said no...
-
-	}
-	else {
-	
+	string YesNoMsg = "WARNING: This will DELETE the Edition's GameDataFolder and recreate it from the vanilla Oni game data.\n";
+	YesNoMsg = YesNoMsg + "Are you SURE you want to do this?";
+	wxMessageDialog* YesNoDialog = new wxMessageDialog(this, YesNoMsg.c_str(), "AE Installer Alert",  wxYES_NO | wxICON_EXCLAMATION	, wxDefaultPosition);
+
+	if (YesNoDialog->ShowModal() == wxID_NO)
+	{
+		//if the user said no...
+	}
+	else
+	{
 		this->InstallButton->Disable();
 		this->ReglobalizeButton->Disable();
-
 #ifdef WIN32
-
 		boost::thread thrd2(globalizeData);
 		//globalizeData();
@@ -1825,22 +757,11 @@
 		globalizeData();
 #endif
-		
 		this->InstallButton->Enable();
 		this->ReglobalizeButton->Enable();
 	}
-
 }
 /*
 * wxEVT_COMMAND_RADIOBUTTON_SELECTED event handler for Separated_RadioButton
 */
-
-/*void MainWindow::OnSeparatedRadioButtonSelected( wxCommandEvent& event )
-{
-////@begin wxEVT_COMMAND_RADIOBUTTON_SELECTED event handler for Separated_RadioButton in MainWindow.
-// Before editing this code, remove the block markers.
-event.Skip();
-////@end wxEVT_COMMAND_RADIOBUTTON_SELECTED event handler for Separated_RadioButton in MainWindow. 
-}*/
-
 
 /*
@@ -1850,5 +771,4 @@
 void MainWindow::OnSeperatedRadioButtonSelected( wxCommandEvent& event )
 {
-splitInstances = SPLIT;
-}
-
+	splitInstances = true;
+}
Index: AE/Installer/trunk/source/main_window.h
===================================================================
--- AE/Installer/trunk/source/main_window.h	(revision 482)
+++ AE/Installer/trunk/source/main_window.h	(revision 487)
@@ -1,28 +1,32 @@
+/***************************************************************************\
+| Project: AE Installer														|
+| By: Gumby & Iritscen														|
+| File: Main_Window.h														|
+| Function: Handles GUI.													|
+| Created: 07/05/2009 20:38:25												|
+\***************************************************************************/
 
-
-/////////////////////////////////////////////////////////////////////////////
-// Name:        main_window.h
-// Purpose:     
-// Author:      
-// Modified by: 
-// Created:     07/05/2009 20:38:25
-// RCS-ID:      
-// Copyright:   
-// Licence:     
-/////////////////////////////////////////////////////////////////////////////
 
 #ifndef _MAINWINDOW_H_
 #define _MAINWINDOW_H_
 
-
 /*!
  * Includes
  */
-
+#pragma mark INCLUDES
 ////@begin includes
+#include "wx/bmpbuttn.h"
+#include "wx/checkbox.h"
+#include "wx/checklst.h"
 #include "wx/frame.h"
+#include "wx/gauge.h"
+#include "wx/generic/panelg.h"
+#include "wx/radiobut.h"
 #include "wx/splitter.h"
 #include "wx/statline.h"
 #include "wx/statusbr.h"
+#include "wx/textctrl.h"
+#include <vector>
+using namespace std;
 ////@end includes
 
@@ -39,5 +43,5 @@
  * Control identifiers
  */
-
+#pragma mark DEFINES
 ////@begin control identifiers
 #define ID_MAINWINDOW 10000
@@ -69,13 +73,9 @@
 ////@end control identifiers
 
-
 /*!
  * MainWindow class declaration
  */
 
-using namespace std;
-
-#include <vector>
-
+#pragma mark CLASS DECLARATIONS
 class MainWindow: public wxFrame
 {    
@@ -86,7 +86,9 @@
     /// Constructors
     MainWindow();
-    MainWindow( wxWindow* parent, wxWindowID id = SYMBOL_MAINWINDOW_IDNAME, const wxString& caption = SYMBOL_MAINWINDOW_TITLE, const wxPoint& pos = SYMBOL_MAINWINDOW_POSITION, const wxSize& size = SYMBOL_MAINWINDOW_SIZE, long style = SYMBOL_MAINWINDOW_STYLE );
+    MainWindow( wxWindow* parent, wxWindowID id = SYMBOL_MAINWINDOW_IDNAME, const wxString& caption = SYMBOL_MAINWINDOW_TITLE,
+			   const wxPoint& pos = SYMBOL_MAINWINDOW_POSITION, const wxSize& size = SYMBOL_MAINWINDOW_SIZE, long style = SYMBOL_MAINWINDOW_STYLE );
 
-    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_MAINWINDOW_IDNAME, const wxString& caption = SYMBOL_MAINWINDOW_TITLE, const wxPoint& pos = SYMBOL_MAINWINDOW_POSITION, const wxSize& size = SYMBOL_MAINWINDOW_SIZE, long style = SYMBOL_MAINWINDOW_STYLE );
+    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_MAINWINDOW_IDNAME, const wxString& caption = SYMBOL_MAINWINDOW_TITLE,
+				const wxPoint& pos = SYMBOL_MAINWINDOW_POSITION, const wxSize& size = SYMBOL_MAINWINDOW_SIZE, long style = SYMBOL_MAINWINDOW_STYLE );
 
     /// Destructor
@@ -190,3 +192,2 @@
 #endif
     // _MAINWINDOW_H_
-void doglobalizeData(void);
