Subversion Repositories spk

Rev

Rev 247 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "../StdAfx.h"
#include "MainGui.h"
#include "ModSelector.h"
#include "PackageBrowser.h"
#include "InstallPackageDialog.h"
#include "CompareList.h"
#include "EditGlobals.h"
#include "EditWares.h"
#include "CommandSlots.h"
#include "DownloadPackageList.h"
#include "FileLog.h"
#include "MessageBoxDetails.h"
#include <shellapi.h>

using System::Configuration::ApplicationSettingsBase;

#undef GetEnvironmentVariable

enum {LISTGROUP_INSTALLED, LISTGROUP_SHIP, LISTGROUP_FAKE, LISTGROUP_LIBRARY, LISTGROUP_MOD, LISTGROUP_MODADDON, LISTGROUP_MODS, LISTGROUP_ARCHIVE};

namespace PluginManager {

        void MainGui::OpenDirectoryControl()
        {
                DirectoryControl ^dialog = gcnew DirectoryControl(m_pPackages, m_pDirList, m_pRemovedDirList);
                if (dialog->ShowDialog(this) == System::Windows::Forms::DialogResult::OK)
                {
                        Utils::WStringList *dirs = dialog->directories();
                        Utils::WStringList *removed = dialog->removeDirectories();

                        // check if the current directory has been remove
                        bool isRemoved = m_pPackages->IsLoaded() && removed->contains(m_pPackages->getCurrentDirectory(), true);

                        // add all removed directories to list
                        m_pRemovedDirList->clear();
                        for (auto itr = removed->begin(); itr != removed->end(); itr++)
                                m_pRemovedDirList->pushBack(m_pPackages->getProperDir((*itr)->str), (*itr)->data);

                        bool changed = false;

                        Utils::WString current;
                        if (ComboDir->SelectedIndex == (ComboDir->Items->Count - 1))
                                current = _WS(ComboDir->Text);
                        else
                                current = m_pDirList->get(ComboDir->SelectedIndex)->str;

                        // remove any directories from main list that are not removed
                        for (int i = m_pDirList->size() - 1; i >= 0; --i)
                        {
                                Utils::WString dir = m_pDirList->get(i)->str;
                                if (m_pRemovedDirList->contains(dir))
                                {
                                        m_pDirList->removeAt(i);
                                        changed = true;
                                }
                        }

                        // now add any remaining directories
                        for (auto itr = dirs->begin(); itr != dirs->end(); itr++)
                        {
                                Utils::WString dir = m_pPackages->getProperDir((*itr)->str);
                                if (!m_pDirList->contains(dir))
                                {
                                        int lang = m_pPackages->getGameLanguage(dir);
                                        if(lang > 0)
                                                m_pDirList->pushBack(dir, Utils::WString::Number(lang) + L"|" + (*itr)->data);
                                        else
                                                m_pDirList->pushBack(dir, (*itr)->data);
                                        changed = true;
                                }
                        }

                        if (isRemoved)
                                ComboDir->SelectedIndex = ComboDir->Items->Count - 1;
                        else if (changed)
                                UpdateDirList(current);
                }
        }

        void MainGui::AboutDialog()
        {
                CBaseFile *pm = m_pPackages->findScriptByAuthor(L"PluginManager");
                System::String ^scriptVer = "None";
                if (pm)
                {
                        scriptVer = _US(pm->version());
                        if (!pm->creationDate().empty())
                                scriptVer += " (" + _US(pm->creationDate()) + ")";
                }
                About ^about = gcnew About(GetVersionString(), PMLDATE, scriptVer, m_bAdvanced);
                about->ShowDialog(this);
        }


        void MainGui::CheckProtectedDir()
        {
                if (!m_pPackages || !m_pPackages->IsLoaded())
                        return;

                Utils::WString dir = m_pPackages->getCurrentDirectory();
                if(!dir.empty())
                {
                        m_bDirLocked = false;

                        // write a file in the directory
                        String ^sDir = _US(dir.findReplace(L"/", L"\\"));
                        bool written = true;
                        StreamWriter ^sw = nullptr;
                        try {
                                sw = System::IO::File::CreateText(sDir + "\\checklock.xpmtest");
                                sw->WriteLine("can write");
                        }       
                        catch (System::Exception ^) {
                                written = false;
                        }
                        finally {
                                if ( sw )
                                        delete (IDisposable ^)sw;
                        }

                        // check its there
                        if ( written ) {
                                written = false;
                                cli::array<String ^> ^dirList = IO::Directory::GetFiles(sDir, "*.xpmtest");
                                if ( dirList && dirList->Length ) {
                                        for ( int i = 0; i < dirList->Length; i++ ) {
                                                if ( IO::FileInfo(dirList[i]).Name == "checklock.xpmtest" ) {
                                                        written = true;
                                                        break;
                                                }
                                        }
                                }
                        }

                        // remove it
                        if ( !IO::File::Exists(sDir + "\\checklock.xpmtest") )
                                written = false;
                        else {
                                try {
                                        IO::File::Delete(sDir + "\\checklock.xpmtest");
                                        if ( IO::File::Exists(sDir + "\\checklock.xpmtest") )
                                                written = false;
                                }
                                catch (System::Exception ^) {
                                        written = false;
                                }
                        }

                        if ( !written ) {
                                MessageBox::Show(this, _US(Utils::WString::Format(CLanguages::Instance()->findText(LS_STARTUP, LANGSTARTUP_LOCKEDDIR), dir.c_str())), _US(CLanguages::Instance()->findText(LS_STARTUP, LANGSTARTUP_LOCKEDDIR_TITLE)), MessageBoxButtons::OK, MessageBoxIcon::Error);
                                m_bDirLocked = true;
                        }
                        else {
                                dir = dir.findReplace(L"/", L"\\");
                                bool found = false;

                                String ^folder = Environment::GetFolderPath(Environment::SpecialFolder::ProgramFiles);
                                if ( dir.contains(_WS(folder)) )
                                        found = true;
                                else {
                                        folder = Environment::GetEnvironmentVariable("ProgramFiles(x86)");
                                        if ( dir.contains(_WS(folder)) )
                                                found = true;
                                }
                                if ( !found ) {
                                        folder = Environment::GetEnvironmentVariable("ProgramFiles");
                                        if ( dir.contains(_WS(folder)) )
                                                found = true;
                                }

                                if ( found ) {
                                        if ( !m_pPackages->IsSupressProtectedWarning() ) {
                                                if ( MessageBox::Show(this, "WARNING: The game directory:\n" + _US(dir) + "\n\nIs in a protected directory (" + _US(CFileIO(dir).dir().tokens(L"/", 1, 2).findReplace(L"/", L"\\")) + ")\n\nThis might cause problems with installing anything, its better to move to game elsewhere, or you may need to run the Plugin Manager with admin access rights\n\nWould you like to surpress this warning in the future?", "Protected Directory", MessageBoxButtons::YesNo, MessageBoxIcon::Warning) == Windows::Forms::DialogResult::Yes ) {
                                                        m_pPackages->SurpressProtectedWarning();
                                                }
                                        }
                                }
                        }
                }
        }

        void MainGui::UpdateDirList(const Utils::WString &current)
        {
                System::String ^checkCurrent = ComboDir->Text;
                System::String ^selected = nullptr;
                bool foundCurrent = false;

                ComboDir->Items->Clear();

                if (m_pDirList && !m_pDirList->empty())
                {
                        for(auto itr = m_pDirList->begin(); itr != m_pDirList->end(); itr++)
                        {
                                if (CDirIO((*itr)->str).exists())
                                {
                                        System::String ^str;
                                        if ((*itr)->data.contains(L"|"))
                                                str = _US((*itr)->str + L" [" + (*itr)->data.tokens(L"|", 2) + L"] (Language: " + CPackages::ConvertLanguage((*itr)->data.token(L"|", 1).toInt())  + L")");
                                        else
                                                str = _US((*itr)->str + L" [" + (*itr)->data + L"]");
                                        ComboDir->Items->Add(str);

                                        if (!current.empty() && current.Compare((*itr)->str))
                                                selected = str;

                                        if (!foundCurrent && System::String::Compare(str, checkCurrent) == 0)
                                                foundCurrent = true;
                                }
                        }
                }

                ComboDir->Items->Add("-- None --");
                if (selected && selected->Length > 0)
                        ComboDir->Text = selected;
                else if (current == L"-- None --")
                        ComboDir->Text = "-- None --";
                else if(!foundCurrent || !ComboDir->Text || ComboDir->Text->Length < 1)
                        ComboDir->Text = ComboDir->Items[0]->ToString();

                this->UpdateRunButton();
        }

        void MainGui::UpdateRunButton()
        {
                if (!m_pPackages || !m_pPackages->IsLoaded())
                {
                        ButRun->Visible = false;
                        return;
                }

                ButRun->Text = "Run: " + _US(m_pPackages->getGameName());
                ButRun->Visible = true;
                
                Utils::WString exe = m_pPackages->GetGameExe()->gameRunExe(m_pPackages->getCurrentDirectory());
                if ( CFileIO(exe).exists() )
                {
                        exe = exe.findReplace(L"/", L"\\");

                        System::Drawing::Icon ^myIcon;
                        SHFILEINFO *shinfo = new SHFILEINFO();

                        if ( FAILED(SHGetFileInfo(exe.c_str(), 0, shinfo, sizeof(shinfo), SHGFI_ICON | SHGFI_LARGEICON)) )
                        {
                                if ( FAILED(SHGetFileInfo(exe.c_str(), 0, shinfo, sizeof(shinfo), SHGFI_ICON | SHGFI_SMALLICON)))
                                {
                                        System::ComponentModel::ComponentResourceManager^  resources = (gcnew System::ComponentModel::ComponentResourceManager(MainGui::typeid));
                                        this->ButRun->Image = (cli::safe_cast<System::Drawing::Image^  >(resources->GetObject(L"ButRun.Image")));
                                }
                                else
                                {
                                        myIcon = System::Drawing::Icon::FromHandle(IntPtr(shinfo->hIcon));
                                        ButRun->Image = myIcon->ToBitmap();
                                }
                        }
                        else
                        {
                                myIcon = System::Drawing::Icon::FromHandle(IntPtr(shinfo->hIcon));
                                ButRun->Image = myIcon->ToBitmap();
                        }

                        delete shinfo;
                }
        }

        void MainGui::_DisplayPackages(CBaseFile *currentParent, ListViewGroup ^useGroup)
        {
                CLinkList<CBaseFile> packageList;

                for ( CBaseFile *p = m_pPackages->FirstPackage(); p; p = m_pPackages->NextPackage() )
                {
                        if ( p->author().Compare(L"PluginManager") )
                                continue;
                        // if thier parent is a library dont add unless top level
                        if ( currentParent && p->GetParent() && p->GetParent()->GetType() == TYPE_SPK && ((CSpkFile *)p->GetParent())->IsLibrary() )
                                continue;
                        else if ( p->GetParent() == currentParent )
                                packageList.push_back(p);
                        // add any mod addons as the top level
                        else if ( p->GetParent() && p->GetParent()->IsMod() && !currentParent && p->GetParent() == m_pPackages->GetEnabledMod() )
                                packageList.push_back(p);
                        // if thier parent is a library add at top level
                        else if ( !currentParent && p->GetParent() && p->GetParent()->GetType() == TYPE_SPK && ((CSpkFile *)p->GetParent())->IsLibrary() )
                                packageList.push_back(p);
                }

                array<SortPackage ^> ^aPackages = gcnew array<SortPackage ^>(packageList.size());
                array<System::String ^> ^aNames = gcnew array<System::String ^>(packageList.size());

                int i = 0;
                for ( CBaseFile *p = packageList.First(); p; p = packageList.Next(), i++ )
                {
                        aPackages[i] = gcnew SortPackage(p);
                        if ( m_iSortingColumn == SORT_AUTHOR ) // sort by author
                                aNames[i] = _US(p->author())->ToLower();
                        else if ( m_iSortingColumn == SORT_VERSION ) // sort by author
                                aNames[i] = _US(p->version())->ToLower();
                        else if ( m_iSortingColumn == SORT_CREATED ) // sort by author
                                aNames[i] = _US(p->creationDate().token(L"/", 3) + p->creationDate().token(L"/", 2) + p->creationDate().token(L"/", 1));
                        else if ( m_iSortingColumn == SORT_ENABLE ) // sort by author
                        {
                                if ( p->IsEnabled() )
                                        aNames[i] = _US(Utils::WString::Number(1));
                                else
                                        aNames[i] = _US(Utils::WString::Number(0));
                        }
                        else if ( m_iSortingColumn == SORT_SIGNED ) // sort by author
                        {
                                if ( p->IsEnabled() )
                                        aNames[i] = _US(Utils::WString::Number(1));
                                else
                                        aNames[i] = _US(Utils::WString::Number(0));
                        }
                        else if ( m_iSortingColumn == SORT_TYPE ) // sort by type
                        {
                                if ( p->GetType() == TYPE_XSP )
                                        aNames[i] = "Ship";
                                else if ( p->GetType() == TYPE_ARCHIVE )
                                        aNames[i] = "- Archive -";
                                else if ( p->GetType() == TYPE_SPK )
                                        aNames[i] = _US(((CSpkFile *)p)->scriptTypeString(m_pPackages->GetLanguage()));
                                else
                                        aNames[i] = "";
                        }
                        else
                                aNames[i] = _US(p->name(m_pPackages->GetLanguage()))->ToLower();
                }

                Array::Sort(aNames, aPackages);

                // now display
                for ( i = 0; i < aPackages->Length; i++ )
                {
                        CBaseFile *p = (m_bSortingAsc) ? aPackages[i]->Package : aPackages[(aPackages->Length - 1 - i)]->Package;
                        Utils::WString name;
                        if ( p->GetType() == TYPE_ARCHIVE )
                                name = CFileIO(p->filename()).filename();
                        else
                                name = p->name(m_pPackages->GetLanguage());

                        int indent = 0;
                        CBaseFile *parent = p;

                        if ( p->GetParent() && p->GetParent()->GetType() == TYPE_SPK && ((CSpkFile *)p->GetParent())->IsLibrary() )
                                indent = 0;
                        else
                        {
                                while ( parent->GetParent() )
                                {
                                        parent = parent->GetParent();
                                        ++indent;
                                }

                                if ( p->GetParent() && p->GetParent() == m_pPackages->GetEnabledMod() )
                                        --indent;
                        }

                        ListViewItem ^item = gcnew ListViewItem(_US(name));
                        item->UseItemStyleForSubItems = false;
                        item->IndentCount = (indent * 2);
                        item->SubItems->Add(_US(p->author()));
                        item->SubItems->Add(_US(p->version()));
                        item->SubItems->Add(_US(p->creationDate()));
                        if ( p->GetType() == TYPE_XSP )
                                item->SubItems->Add("Ship");
                        else if ( p->GetType() == TYPE_ARCHIVE )
                                item->SubItems->Add("- Archive -");
                        else if ( p->GetType() == TYPE_SPK )
                        {
                                CSpkFile *spk = (CSpkFile *)p;
                                item->SubItems->Add(_US(spk->scriptTypeString(m_pPackages->GetLanguage())));
                        }
                        else
                                item->SubItems->Add("");

                        if ( p->IsEnabled() ) {
                                item->SubItems->Add("Yes");
                                item->SubItems[item->SubItems->Count - 1]->ForeColor = Color::Green;
                        }
                        else {
                                item->SubItems->Add("No");
                                item->SubItems[item->SubItems->Count - 1]->ForeColor = Color::Red;
                        }
                        if ( p->IsSigned() )
                                item->SubItems->Add("Yes");
                        else
                                item->SubItems->Add("No");
                        item->Tag = _US(Utils::WString::Number(p->GetNum()));

                        ListPackages->Items->Add(item);

                        if ( useGroup )
                                item->Group = useGroup;
                        else
                        {
                                int addGroup = LISTGROUP_INSTALLED;
                                if ( p->GetParent() && p->GetParent() == m_pPackages->GetEnabledMod() )
                                        addGroup = LISTGROUP_MODADDON;
                                if (p->IsMod())
                                        addGroup = p->IsEnabled() ? LISTGROUP_MOD : LISTGROUP_MODS;
                                else if ( p->GetType() == TYPE_SPK && ((CSpkFile *)p)->IsLibrary() )
                                        addGroup = LISTGROUP_LIBRARY;
                                else if ( p->GetType() == TYPE_SPK && ((CSpkFile *)p)->IsFakePatch() )
                                        addGroup = LISTGROUP_FAKE;
                                else if ( p->GetType() == TYPE_XSP )
                                        addGroup = LISTGROUP_SHIP;
                                else if ( p->GetType() == TYPE_ARCHIVE )
                                        addGroup = LISTGROUP_ARCHIVE;

                                item->Group = ListPackages->Groups[addGroup];
                        }

                        Utils::WString groupName = _WS(item->Group->Header);
                        if ( groupName.contains(L" ["))
                        {
                                int enabled = groupName.token(L" [", 2).token(L"/", 1).toInt();
                                int total = groupName.token(L" [", 2).token(L"/", 2).token(L"]", 1).toInt() + 1;
                                if ( p->IsEnabled() ) ++enabled;
                                groupName = groupName.token(L" [", 1) + L" [" + Utils::WString::Number(enabled) + L"/" + Utils::WString::Number(total) + L"]";
                        }
                        else
                        {
                                if ( p->IsEnabled() )
                                        groupName = groupName + L" [1/1]";
                                else
                                        groupName = groupName + L" [0/1]";
                        }
                        item->Group->Header = _US(groupName);

                        // get the icon
                        item->ImageIndex = -1;
                        if ( p->icon() )
                                PluginManager::DisplayListIcon(p, ListPackages, item);

                        if ( item->ImageIndex == -1 )
                        {
                                if ( p->GetType() == TYPE_XSP )
                                        item->ImageKey = "ship";
                                else if ( p->GetType() == TYPE_ARCHIVE )
                                        item->ImageKey = "archive";
                                else if ( p->GetType() == TYPE_SPK && ((CSpkFile *)p)->IsLibrary() )
                                        item->ImageKey = "library";
                                else if ( p->IsFakePatch() )
                                        item->ImageKey = "fake";
                                else
                                        item->ImageKey = "package";
                        }

                        // check for any children
                        this->_DisplayPackages(p, item->Group);
                }
        }

        void MainGui::AddIconToPackages(String ^icon)
        {
                int index = this->imageList1->Images->IndexOfKey(icon + ".png");
                if ( index != -1 )
                {
                        ListPackages->SmallImageList->Images->Add(icon, this->imageList1->Images[index]);
                        ListPackages->LargeImageList->Images->Add(icon, this->imageList1->Images[index]);
                }
        }

        void MainGui::UpdatePackages()
        {
                ListPackages->Items->Clear();
                ListPackages->Groups->Clear();
                ListPackages->SmallImageList = gcnew ImageList();
                ListPackages->LargeImageList = gcnew ImageList();
                ListPackages->LargeImageList->ImageSize = System::Drawing::Size(32, 32);
                ListPackages->LargeImageList->ColorDepth = Windows::Forms::ColorDepth::Depth32Bit;
                ListPackages->SmallImageList->ImageSize = System::Drawing::Size(16, 16);
                ListPackages->SmallImageList->ColorDepth = Windows::Forms::ColorDepth::Depth32Bit;

                if (m_pPackages && m_pPackages->IsLoaded())
                {
                        int index = this->imageList1->Images->IndexOfKey("package.png");
                        if (index != -1)
                        {
                                ListPackages->SmallImageList->Images->Add("package", this->imageList1->Images[index]);
                                ListPackages->LargeImageList->Images->Add("package", this->imageList1->Images[index]);
                        }
                        index = this->imageList1->Images->IndexOfKey("ship.png");
                        if (index != -1)
                        {
                                ListPackages->SmallImageList->Images->Add("ship", this->imageList1->Images[index]);
                                ListPackages->LargeImageList->Images->Add("ship", this->imageList1->Images[index]);
                        }
                        index = this->imageList1->Images->IndexOfKey("fake.png");
                        if (index != -1)
                        {
                                ListPackages->SmallImageList->Images->Add("fake", this->imageList1->Images[index]);
                                ListPackages->LargeImageList->Images->Add("fake", this->imageList1->Images[index]);
                        }
                        index = this->imageList1->Images->IndexOfKey("library.png");
                        if (index != -1)
                        {
                                ListPackages->SmallImageList->Images->Add("library", this->imageList1->Images[index]);
                                ListPackages->LargeImageList->Images->Add("library", this->imageList1->Images[index]);
                        }

                        index = this->imageList1->Images->IndexOfKey("archive.png");
                        if (index != -1)
                        {
                                ListPackages->SmallImageList->Images->Add("archive", this->imageList1->Images[index]);
                                ListPackages->LargeImageList->Images->Add("archive", this->imageList1->Images[index]);
                        }

                        AddIconToPackages("tick");
                        AddIconToPackages("no");

                        ListViewGroup ^group = gcnew ListViewGroup("Installed Scripts", HorizontalAlignment::Left);
                        ListPackages->Groups->Add(group);
                        ListViewGroup ^shipGroup = gcnew ListViewGroup("Installed Ships", HorizontalAlignment::Left);
                        ListPackages->Groups->Add(shipGroup);
                        ListViewGroup ^fakeGroup = gcnew ListViewGroup("Fake Patches", HorizontalAlignment::Left);
                        ListPackages->Groups->Add(fakeGroup);
                        ListViewGroup ^libGroup = gcnew ListViewGroup("Script Libraries", HorizontalAlignment::Left);
                        ListPackages->Groups->Add(libGroup);
                        ListViewGroup ^activeModGroup = gcnew ListViewGroup("Current Active Mod", HorizontalAlignment::Left);
                        ListPackages->Groups->Add(activeModGroup);
                        ListViewGroup ^modGroup = gcnew ListViewGroup("Current Mod Addons", HorizontalAlignment::Left);
                        ListPackages->Groups->Add(modGroup);
                        ListViewGroup ^availModGroup = gcnew ListViewGroup("Available Mods", HorizontalAlignment::Left);
                        ListPackages->Groups->Add(availModGroup);
                        ListViewGroup ^arcGroup = gcnew ListViewGroup("Installed Archives", HorizontalAlignment::Left);
                        ListPackages->Groups->Add(arcGroup);

                        // sort the items
                        m_pPackages->AssignPackageNumbers();
                        this->_DisplayPackages(NULL, nullptr);

                        PackageListSelected(ListPackages, gcnew System::EventArgs());

                        // update the status bar
                        LabelStatus->Text = "Plugins Available: " + (m_pPackages->countPackages(TYPE_BASE, false) - m_pPackages->CountBuiltInPackages(false)) + " (" + (m_pPackages->countPackages(TYPE_BASE, true) - m_pPackages->CountBuiltInPackages(true)) + " Enabled)";
                }
                else
                        LabelStatus->Text = "No current directory";

                ListPackages->AutoResizeColumns(ColumnHeaderAutoResizeStyle::HeaderSize);
        }

        void MainGui::StartCheckTimer()
        {
                System::Windows::Forms::Timer ^timer = gcnew System::Windows::Forms::Timer();
                timer->Interval = 5000;
                timer->Tick += gcnew System::EventHandler(this, &MainGui::TimerEvent_CheckFile);
                timer->Start();
        }


        //
        // Update Controls
        // Updates any additional controls, ie adding columns to package list
        //
        void MainGui::UpdateControls()
        {
                // Package List Columns
                int csize = ListPackages->Width - 200 - 5;
                int psize = ((csize * 7) / 10);
                int asize = ((csize * 3) / 10);
                if ( psize < 60 ) psize = 60;
                if ( asize < 60 ) asize = 60;
                ListPackages->Columns->Clear();
                ListPackages->Columns->Add("Package", psize, HorizontalAlignment::Left);
                ListPackages->Columns->Add("Author", asize, HorizontalAlignment::Left);
                ListPackages->Columns->Add("Version", 60, HorizontalAlignment::Right);
                ListPackages->Columns->Add("Updated", 80, HorizontalAlignment::Left);
                ListPackages->Columns->Add("Type", 100, HorizontalAlignment::Left);
                ListPackages->Columns->Add("Enabled", 60, HorizontalAlignment::Right);
                ListPackages->Columns->Add("Signed", 60, HorizontalAlignment::Right);
                ListPackages->FullRowSelect = true;
                ListPackages->Focus();

                if ( m_pPackages->IsVanilla() )
                        m_pMenuBar->Vanilla();
                else
                        m_pMenuBar->Modified();

                // enable/disable if directory is loaded
                bool isLoaded = m_pPackages && m_pPackages->IsLoaded();
                GroupPackages->Enabled = isLoaded;
                m_pMenuBar->SetLoaded(isLoaded);
        }

        //
        // Install a package
        // Called from either install button, or from command line
        //
        bool MainGui::InstallPackage(System::String ^file, bool straightAway, bool builtin, bool background)
        {
                bool errored = false;

                if ( file->Length )
                {
                        int error = INSTALLERR_NONE;
                        CBaseFile *package = m_pPackages->openPackage(_WS(file), &error, 0, SPKREAD_NODATA, READFLAG_NOUNCOMPRESS);
                        if ( error == INSTALLERR_NOMULTI )
                        {
                                CLinkList<CBaseFile> erroredList;
                                m_pPackages->prepareMultiPackage(_WS(file), &erroredList, &error, 0);
                                if ( erroredList.size() )
                                {
                                        System::String ^modified;
                                        for ( CBaseFile *p = erroredList.First(); p; p = erroredList.Next() )
                                        {
                                                p->SetOverrideFiles(builtin);
                                                if ( m_pPackages->PrepareInstallPackage(p, false, false, IC_MODIFIED) != INSTALLCHECK_OK )
                                                {
                                                        modified += _US(p->getFullPackageName(m_pPackages->GetLanguage()));
                                                        modified += "\n";
                                                        errored = true;
                                                }
                                        }

                                        if ( errored )
                                                this->DisplayMessageBox(false, "Installing", "Currently in Vanilla Mode, Package is not an Vanilla Package\n\n" + modified + "\nSwitch to modified mode if you wish to install this package", MessageBoxButtons::OK, MessageBoxIcon::Question);
                                }
                        }
                        else if ( !package )
                        {
                                System::String ^errorStr;
                                switch ( error )
                                {
                                        case INSTALLERR_OLD:
                                                errorStr = "File is in old format no longer supported";
                                                break;
                                        case INSTALLERR_NOEXIST:
                                                errorStr = "file doesn't exist";
                                                break;
                                        case INSTALLERR_INVALID:
                                                errorStr = "Invalid package file";
                                                break;
                                        case INSTALLERR_NOSHIP:
                                                errorStr = "Ship Packages are currently not supported";
                                                break;
                                        case INSTALLERR_VERSION:
                                                errorStr = "Package file was created in a newer version, unable to open";
                                                break;

                                        default:
                                                errorStr = "Unknown Error";
                                }

                                if ( !builtin )
                                        this->DisplayMessageBox(false, "Open Package Error", "Error Opening: " + file + "\n" + errorStr, MessageBoxButtons::OK, MessageBoxIcon::Stop);
                                errored = true;
                        }
                        else
                        {
                                if ( builtin )
                                {
                                        package->SetOverrideFiles(builtin);
                                        if ( m_pPackages->PrepareInstallPackage(package, false, false, IC_WRONGGAME|IC_WRONGVERSION|IC_OLDVERSION) != INSTALLCHECK_OK )
                                                errored = true;
                                }
                                else
                                {
                                        int errorNum = m_pPackages->PrepareInstallPackage(package, false, false, IC_ALL);
                                        if ( errorNum != INSTALLCHECK_OK )
                                        {
                                                if ( errorNum == INSTALLCHECK_NOSHIP )
                                                {
                                                        this->DisplayMessageBox(false, "No Ships", "Ships are not supported for " + _US(m_pPackages->getGameName()), MessageBoxButtons::OK, MessageBoxIcon::Stop);
                                                        errored = true;
                                                }
                                                else if ( m_pPackages->PrepareInstallPackage(package, false, false, IC_MODIFIED) != INSTALLCHECK_OK )
                                                {
                                                        this->DisplayMessageBox(false, "Installing", "Currently in Vanilla Mode, Package is not an Vanilla Package\n" + _US(package->name(m_pPackages->GetLanguage())) + "\n\nSwitch to modified mode if you wish to install this package", MessageBoxButtons::OK, MessageBoxIcon::Question);
                                                        errored = true;
                                                }
                                        }

                                        // check for compatabilities
                                        CLinkList<CBaseFile> packages;
                                        Utils::WStringList list;
                                        int compat = m_pPackages->checkCompatabilityAgainstPackages(package, &list, &packages);
                                        if ( compat )
                                        {
                                                String ^message = "Conflicts with:\n";
                                                for ( CBaseFile *p = packages.First(); p; p = packages.Next() )
                                                        message += _US(p->getFullPackageName(m_pPackages->GetLanguage())) + "\n";

                                                String^ details = "Package Conflicts:\n";
                                                for (CBaseFile* p = packages.First(); p; p = packages.Next())
                                                        details += _US(p->getFullPackageName(m_pPackages->GetLanguage())) + "\n";
                                                details += "File Conflicts:\n";
                                                for (auto itr = list.begin(); itr != list.end(); itr++)
                                                        details += _US((*itr)->str + " <> " + (*itr)->data) + "\n";
                                                MessageBoxDetails^ msgBox = gcnew MessageBoxDetails("Potential Incomatability Found", _US(package->getFullPackageName(m_pPackages->GetLanguage())) + ":\nIncompatabilities found with installed fake patches\n" + message + "\n\nDo you still wish to install ? ", details, true);
                                                msgBox->SetOkText("Yes");
                                                msgBox->SetCancelText("No");
                                                int height = 200 + (packages.size() * 20);
                                                msgBox->Height = height > 600 ? 600: height;
                                                msgBox->Width = 650;

                                                System::Windows::Forms::DialogResult res = msgBox->ShowDialog(this);
                                                delete msgBox;
                                                if (res != Windows::Forms::DialogResult::OK)
                                                {
                                                        m_pPackages->RemovePreparedInstall(package);
                                                        errored = true;
                                                }
                                        }
                                }

                                // not installing
                                if ( errored )
                                {
                                        delete package;
                                        package = NULL;
                                }
                        }
                }

                if ( errored )
                {
                        this->Enabled= true;
                        this->ProgressBar->Hide();
                        return false;
                }

                // start installing
                if ( straightAway )
                        return this->StartInstalling(builtin, background);

                return true;
        }

        void MainGui::DoUninstall()
        {
                m_pPi = gcnew PackageInstalled("Uninstall Packages");

                CLinkList<CBaseFile> packageList;
                CLinkList<CBaseFile> disableList;

                if ( m_pPackages->uninstallPreparedPackages(m_pFileErrors, 0, &packageList, &disableList) )
                {
                        Utils::WString sDisplay;
                        Utils::WString sAfterText;
                        for ( CBaseFile *p = packageList.First(); p; p = packageList.Next() )
                        {
                                sAfterText = m_pPackages->getUninstallAfterText(p);
                                m_pPi->AddPackageWithGroup(_US(p->name(m_pPackages->GetLanguage())), _US(p->author()), _US(p->version()), (sAfterText.empty() ? "Uninstalled" : _US(sAfterText)), "Uninstalled");
                                sDisplay = p->getFullPackageName(m_pPackages->GetLanguage());
                                delete p;
                        }
                        for ( CBaseFile *p = disableList.First(); p; p = disableList.Next() )
                                m_pPi->AddPackageWithGroup(_US(p->name(m_pPackages->GetLanguage())), _US(p->author()), _US(p->version()), "Disabled", "Dependants Disabled");
                        packageList.clear();                    

                        if ( m_pPi->PackageCount() == 1 )
                        {
                                if ( sAfterText.empty() )
                                        this->DisplayMessageBox(true, "Uninstalled", "Package Uninstalled\n" + _US(sDisplay), MessageBoxButtons::OK, MessageBoxIcon::Information);
                                else
                                        this->DisplayMessageBox(true, "Uninstalled", "Package Uninstalled\n" + _US(sDisplay) + "\n\n" + _US(sAfterText), MessageBoxButtons::OK, MessageBoxIcon::Information);
                        }
                        else
                                m_bDisplayDialog = true;
                }
                else
                        this->DisplayMessageBox(true, "Uninstall Error", "Error Uninstalling", MessageBoxButtons::OK, MessageBoxIcon::Stop);
        }

        void MainGui::DoDisable()
        {
                CLinkList<CBaseFile> packageList;

                System::String ^display;
                m_pPi = gcnew PackageInstalled("Enabled/Disabled Packages");

                if ( m_pPackages->GetNumPackagesInDisabledQueue() )
                {
                        if ( m_pPackages->disablePreparedPackages(0, 0, &packageList) )
                        {
                                for ( CBaseFile *p = packageList.First(); p; p = packageList.Next() )
                                {
                                        m_pPi->AddPackageWithGroup(_US(p->name(m_pPackages->GetLanguage())), _US(p->author()), _US(p->version()), "Disabled", "Disabled Packages");
                                        display = L"Package Disabled\n\n" + _US(p->getFullPackageName(m_pPackages->GetLanguage()));
                                }
                        }
                        else
                                this->DisplayMessageBox(true, "Disable Error", "Error Disabling packages", MessageBoxButtons::OK, MessageBoxIcon::Stop);
                }

                packageList.clear();
                if ( m_pPackages->GetNumPackagesInEnabledQueue() )
                {
                        if ( m_pPackages->enablePreparedPackages(0, 0, &packageList) )
                        {
                                for ( CBaseFile *p = packageList.First(); p; p = packageList.Next() )
                                {
                                        m_pPi->AddPackageWithGroup(_US(p->name(m_pPackages->GetLanguage())), _US(p->author()), _US(p->version()), "Enabled", "Enable Packages");
                                        display = L"Package Enabled\n\n" + _US(p->getFullPackageName(m_pPackages->GetLanguage()));
                                }
                        }
                        else
                                this->DisplayMessageBox(true, "Enable Error", "Error Enabling packages", MessageBoxButtons::OK, MessageBoxIcon::Stop);
                }

                if ( m_pPi->PackageCount() == 1 )
                        this->DisplayMessageBox(true, "Packages Enabled/Disabled", display, MessageBoxButtons::OK, MessageBoxIcon::Information);
                else
                {
                        m_bDisplayDialog = true;
                }
        }

        void MainGui::DoInstall(bool builtin, bool frombackground)
        {
                CLinkList<CBaseFile> erroredPackages;
                CLinkList<CBaseFile> installedPackages;
                if ( m_pPackages->installPreparedPackages(m_pFileErrors, 0, &erroredPackages, &installedPackages) )
                {
                        if ( !builtin )
                        {
                                if ( installedPackages.size() == 1 && erroredPackages.size() == 0 )
                                {
                                        CBaseFile *p = installedPackages.Front()->Data();
                                        Utils::WString packageName = p->getFullPackageName(m_pPackages->GetLanguage());
                                        Utils::WString afterText = m_pPackages->getInstallAfterText(p);
                                        if (afterText.empty())
                                                this->DisplayMessageBox(frombackground, "Installed", "Package: " + _US(packageName) + " installed!\n\n", MessageBoxButtons::OK, MessageBoxIcon::Information);
                                        else
                                        {
                                                afterText = afterText.stripHtml();
                                                this->DisplayMessageBox(frombackground, "Installed", "Package: " + _US(packageName) + " installed!\n\n" + _US(afterText), MessageBoxButtons::OK, MessageBoxIcon::Information);
                                        }
                                }
                                else
                                {
                                        m_pPi = gcnew PackageInstalled("Packages Installed");

                                        for ( CListNode<CBaseFile> *node = installedPackages.Front(); node; node = node->next() )
                                        {
                                                CBaseFile *p = node->Data();
                                                Utils::WString packageName = p->getFullPackageName(m_pPackages->GetLanguage());
                                                Utils::WString afterText = m_pPackages->getInstallAfterText(p);

                                                if (afterText.empty())
                                                        afterText = L"Installed";
                                                m_pPi->AddPackage(_US(packageName), _US(p->author()), _US(p->version()), _US(afterText));
                                        }
                                        for ( CListNode<CBaseFile> *node = erroredPackages.Front(); node; node = node->next() )
                                        {
                                                CBaseFile *p = node->Data();
                                                Utils::WString packageName = p->getFullPackageName(m_pPackages->GetLanguage());
                                                m_pPi->AddPackage(_US(packageName), _US(p->author()), _US(p->version()), "Failed to Install");
                                        }

                                        m_bDisplayDialog = true;
                                }
                        }
                }
                // no packages were installed
                else 
                {
                        if ( !builtin )
                        {
                                if ( erroredPackages.size() == 1 )
                                {
                                        CBaseFile *p = erroredPackages.Front()->Data();
                                        Utils::WString packageName = p->getFullPackageName(m_pPackages->GetLanguage());
                                        this->DisplayMessageBox(frombackground, "Error Installing", "Package: " + _US(packageName) + " failed to install!\nError: " + _US(CBaseFile::ErrorString(p->lastError(), p->lastErrorString())) + "\n", MessageBoxButtons::OK, MessageBoxIcon::Error);
                                }
                                else
                                {
                                        m_pPi = gcnew PackageInstalled("Packages Failed To Install");

                                        for ( CListNode<CBaseFile> *node = erroredPackages.Front(); node; node = node->next() )
                                        {
                                                CBaseFile *p = node->Data();
                                                Utils::WString packageName = p->getFullPackageName(m_pPackages->GetLanguage());
                                                m_pPi->AddPackage(_US(packageName), _US(p->author()), _US(p->version()), "Failed: " + _US(CBaseFile::ErrorString(p->lastError(), p->lastErrorString())));
                                        }

                                        m_bDisplayDialog = true;
                                }
                        }
                }

                if ( !frombackground )
                        this->Background_Finished();
        }

        void MainGui::ClearSelectedItems()
        {
                for ( int i = 0; i < this->ListPackages->Items->Count; i++ )
                        this->ListPackages->Items[i]->Selected = false;
                PackageListSelected(ListPackages, gcnew System::EventArgs());
        }

        void MainGui::FindPackages()
        {
                if (m_lAvailablePackages)
                        m_lAvailablePackages->clear();
                if (!m_lAvailablePackages)
                        m_lAvailablePackages = new CLinkList<CBaseFile>;

                String ^curDir = System::IO::FileInfo(System::Windows::Forms::Application::ExecutablePath).DirectoryName;
                m_pPackages->updateFoundPackages(_WS(curDir));

                // find packages from registry key
                RegistryKey ^searchKey = Registry::CurrentUser->OpenSubKey("Software\\Egosoft\\SuperBox");
                if (searchKey)
                {
                        String ^dir = System::Convert::ToString(searchKey->GetValue("Addons"));
                        if (dir)
                                m_pPackages->addFoundPackages(_WS(dir));
                }

                // find packages from DVD
                cli::array<IO::DriveInfo ^> ^Drives = IO::DriveInfo::GetDrives();
                if (Drives)
                {
                        for (int i = 0; i < Drives->Length; i++)
                        {
                                IO::DriveInfo ^info = Drives[i];
                                if (info->DriveType != IO::DriveType::CDRom)
                                        continue;
                                if (info->IsReady)
                                        m_pPackages->addFoundPackages(_WS(info->RootDirectory + "XPluginManager"));
                        }
                }

                for (auto p = m_pPackages->getFoundPackageList()->First(); p; p = m_pPackages->getFoundPackageList()->Next())
                        m_lAvailablePackages->push_back(p);

                int num = 0;
                for (CBaseFile *p = m_lAvailablePackages->First(); p; p = m_lAvailablePackages->Next())
                {
                        p->SetNum(num);
                        ++num;
                }
        }


        bool MainGui::StartInstalling(bool builtin, bool background, bool archive)
        {
                // no packages to install
                if (!m_pPackages->GetNumPackagesInQueue())
                {
                        this->Enabled = true;
                        this->ProgressBar->Hide();
                        return false;
                }

                // clear selected
                this->ClearSelectedItems();

                bool hasArchive = false;
                auto list = m_pPackages->GetInstallPackageList();
                for (auto itr = list->Front(); itr; itr = itr->next()) {
                        if (itr->Data()->GetType() == TYPE_ARCHIVE) {
                                hasArchive = true;
                                break;
                        }
                }

                // lets install them now
                CLinkList<CBaseFile> lCheckPackages;
                if ( m_pPackages->CheckPreparedInstallRequired(&lCheckPackages) )
                {
                        CLinkList<CBaseFile> *installRequired = new CLinkList<CBaseFile>();
                        for ( CListNode<CBaseFile> *pNode = lCheckPackages.Front(); pNode; pNode = pNode->next() )
                        {
                                CBaseFile *package = pNode->Data();
                                CSpkFile *spk = (CSpkFile *)package;

                                if (m_pPackages->findAllNeededDependacies(package, *m_lAvailablePackages, installRequired, false, true))
                                {
                                        bool added = false;
                                        for (auto itr = installRequired->Front(); itr; itr = itr->next())
                                        {
                                                if (itr->Data() == package || (itr->Data()->name().Compare(package->name()) && itr->Data()->author().Compare(package->author())))
                                                {
                                                        added = true;
                                                        break;
                                                }
                                        }
                                        if (!added)
                                                installRequired->push_back(package);
                                        continue;
                                }

                                Utils::WStringList missingList;
                                if ( m_pPackages->getMissingDependacies(package, &missingList) )
                                {
                                        Utils::WString requires;
                                        for (auto itr = missingList.begin(); itr != missingList.end(); itr++)
                                        {
                                                Utils::WString name = (*itr)->str;;
                                                Utils::WString author = (*itr)->data;
                                                Utils::WString version;
                                                if (name.contains(L"|"))
                                                {
                                                        version = name.token(L"|", 2);
                                                        name = name.token(L"|", 1);
                                                }

                                                if (!version.empty())
                                                        requires += name + L" V" + version + L" by " + author;
                                                else
                                                        requires += name + L" by " + author;
                                                requires += L"\n";
                                        }

                                        std::vector<const SAvailablePackage*> downloads;
                                        if (m_pPackages->getDownloadableDependacies(package, downloads) >= missingList.size())
                                        {
                                                if (this->DisplayMessageBox(false, "Installing", "Missing Package for " + _US(package->name(m_pPackages->GetLanguage())) + "\nRequires:\n" + _US(requires) + "\n\nDo you want to download them?", MessageBoxButtons::YesNo, MessageBoxIcon::Question) == System::Windows::Forms::DialogResult::Yes)
                                                {
                                                        CheckUpdate^ update = gcnew CheckUpdate(m_pPackages, this->imageList1);
                                                        update->SetDownloader();
                                                        if (downloads.size() == 1)
                                                                update->OnePackage(downloads.front());
                                                        else
                                                        {
                                                                for (auto itr = downloads.begin(); itr != downloads.end(); itr++)
                                                                        update->AddPackage(*itr);
                                                        }
                                                        if (update->ShowDialog(this) == Windows::Forms::DialogResult::OK)
                                                        {
                                                                FindPackages();
                                                                for (CListNode<CBaseFile>* pNode = lCheckPackages.Front(); pNode; pNode = pNode->next())
                                                                        m_pPackages->PrepareInstallPackage(pNode->Data(), false, false, IC_ALL);
                                                                return StartInstalling(builtin, background);
                                                        }
                                                }
                                        }
                                        else
                                                this->DisplayMessageBox(false, "Installing", "Missing Package for " + _US(package->name(m_pPackages->GetLanguage())) + "\nRequires:\n" + _US(requires), MessageBoxButtons::OK, MessageBoxIcon::Exclamation);
                                }
                        }

                        bool restart = false;
                        if (installRequired->size())
                        {
                                bool errored = false;
                                for (auto itr = installRequired->Front(); itr; itr = itr->next())
                                {
                                        CBaseFile *package = NULL;
                                        int error = 0;
                                        if (CFileIO::Exists(itr->Data()->filename()))
                                                if (!this->InstallPackage(_US(itr->Data()->filename()), false, builtin, background))
                                                        errored = true;
                                }
                                if (!errored)
                                        restart = true;
                        }

                        delete installRequired;
                        lCheckPackages.MemoryClear();
                        if(restart)
                                return StartInstalling(builtin, background);
                }

                // no packages to install
                if ( !m_pPackages->GetNumPackagesInQueue() )
                {
                        this->Enabled = true;
                        this->ProgressBar->Hide();
                        return false;
                }

                ProgressBar->Show();
                this->Enabled = false;

                if ( builtin )
                {
                        if ( background )
                                this->StartBackground(MGUI_BACKGROUND_INSTALLBUILTIN);
                        else
                                this->DoInstall(builtin, false);
                }
                else if ( archive && hasArchive)
                {
                        if ( background )
                                this->StartBackground(MGUI_BACKGROUND_INSTALL);
                        else
                                this->DoInstall(false, false);
                }
                else
                {
                        InstallPackageDialog ^installDialog = gcnew InstallPackageDialog(m_pPackages);
                        if ( installDialog->ShowDialog(this) == System::Windows::Forms::DialogResult::OK )
                        {
                                // no packages to install
                                if ( !m_pPackages->GetNumPackagesInQueue() )
                                {
                                        this->Enabled = true;
                                        this->ProgressBar->Hide();
                                        return false;
                                }
                                if ( background )
                                        this->StartBackground(MGUI_BACKGROUND_INSTALL);
                                else
                                        this->DoInstall(false, false);
                        }
                        else
                        {
                                m_pPackages->RemovePreparedInstall(NULL);
                                this->Enabled = true;
                                this->ProgressBar->Hide();
                                return false;
                        }
                }
                return true;
        }

        bool MainGui::StartBackground(int type, System::String ^info)
        {
                if ( backgroundWorker1->IsBusy )
                        return false;
                if ( m_bRunningBackground )
                        return false;

                m_sBackgroundInfo = info;
                return this->StartBackground(type);
        }

        bool MainGui::StartBackground(int type)
        {
                if ( backgroundWorker1->IsBusy )
                        return false;
                if ( m_bRunningBackground )
                        return false;

                m_iBackgroundTask = type;

                backgroundWorker1->RunWorkerAsync();
                m_bRunningBackground = true;
                return true;
        }

        void MainGui::CloseCurrentDirectory()
        {
                if (m_pPackages->IsLoaded())
                {
                        if (m_pPackages->closeDir(0, 0, true))
                        {
                                // write the modname
                                if (!m_pPackages->getModKey().empty())
                                        PluginManager::WriteRegistryValue(m_pPackages->getModKey(), m_pPackages->selectedModName());
                                m_pPackages->Reset();
                        }
                        else
                        {
                                this->DisplayMessageBox(true, "Error", "unable to close directory", MessageBoxButtons::OK, MessageBoxIcon::Error);
                                return;
                        }
                }

                m_pPackages->Reset();
        }

        void MainGui::ChangeDirectory(const Utils::WString &dir)
        {
                if ( m_pPackages->isCurrentDir(dir) )
                        return;

                CloseCurrentDirectory();

                if ( m_pPackages->read(dir, 0) )
                {
                        //if ( m_iSaveGameManager == 1 )
                                //m_pPackages->RestoreSaves();
                        m_pPackages->UpdatePackages();
                        m_pPackages->ReadGameLanguage(true);
                        System::String ^mod = PluginManager::ReadRegistryValue(m_pPackages->getModKey());
                        m_pPackages->setMod(_WS(mod));
                        if(m_lAvailablePackages)
                                m_lAvailablePackages->clear();
                        this->FindPackages();
                }
                else
                {
                        this->DisplayMessageBox(true, "Error", "unable to open new directory", MessageBoxButtons::OK, MessageBoxIcon::Error);
                        this->CloseCurrentDirectory();
                }
        }

        CBaseFile *MainGui::FindPackageFromList(ListViewItem ^item)
        {
                if ( !item )
                        return NULL;

                System::String ^sNum = System::Convert::ToString(item->Tag);
                int iNum = _WS(sNum).toInt();

                CBaseFile *p = m_pPackages->GetPackageAt(iNum);
                return p;
        }

        void MainGui::FindPackagesOnline()
        {
                Utils::WStringList servers;
                m_pPackages->findAllServers(&servers);
                if ( servers.empty() )
                {
                        MessageBox::Show(this, "Found now web address to check for packages", "No Web Address", MessageBoxButtons::OK, MessageBoxIcon::Warning);
                        return;
                }

                DownloadPackageList ^dpl = gcnew DownloadPackageList(m_pPackages, &servers);
                dpl->ShowDialog(this);

                if ( m_pPackages->AnyAvailablePackages() )
                        MessageBox::Show(this, "Package update completed\n" + m_pPackages->getAvailablePackageList()->size() + " packages have been added to the package browser", "Found Packages", MessageBoxButtons::OK, MessageBoxIcon::Information);
                else
                        MessageBox::Show(this, "Unable to find any packages\n", "No Packages Found", MessageBoxButtons::OK, MessageBoxIcon::Warning);
        }

        //
        // Event Handlers
        //
        void MainGui::SetupEventHandlers()
        {
                // setup Event Handlers
                ButClose->Click += gcnew EventHandler(this, &PluginManager::MainGui::ClosedEvent);
                ButInstall->Click += gcnew EventHandler(this, &PluginManager::MainGui::InstallEvent);
                ButUninstall->Click += gcnew EventHandler(this, &PluginManager::MainGui::UninstallEvent);
                ButDisable->Click += gcnew EventHandler(this, &PluginManager::MainGui::DisableEvent);
                ListPackages->SelectedIndexChanged += gcnew EventHandler(this, &PluginManager::MainGui::PackageListSelected);
                ListPackages->ColumnClick  += gcnew ColumnClickEventHandler(this, &PluginManager::MainGui::PackageListSort);
                ComboDir->SelectedIndexChanged += gcnew EventHandler(this, &PluginManager::MainGui::ChangeDirectoryEvent);


                // background worker
                backgroundWorker1->DoWork += gcnew DoWorkEventHandler( this, &MainGui::Background_DoWork );
                backgroundWorker1->RunWorkerCompleted += gcnew RunWorkerCompletedEventHandler( this, &MainGui::Background_Finished );
                backgroundWorker1->ProgressChanged += gcnew ProgressChangedEventHandler( this, &MainGui::Background_Progress );

                // auto update
                backgroundUpdater->DoWork += gcnew DoWorkEventHandler( this, &MainGui::Updater_DoWork );
                backgroundUpdater->RunWorkerCompleted += gcnew RunWorkerCompletedEventHandler( this, &MainGui::Updater_Finished );
        }

        void MainGui::PackageListSort(System::Object ^Sender, ColumnClickEventArgs ^E)
        {
                if ( E->Column != m_iSortingColumn )
                {
                        m_iSortingColumn = E->Column;
                        m_bSortingAsc = true;
                }
                else
                        m_bSortingAsc = !m_bSortingAsc;
                this->UpdatePackages();
        }

        void MainGui::PackageListSelected(System::Object ^Sender, System::EventArgs ^E)
        {
                // is there any selected items
                this->PictureDisplay->Image = nullptr;
                this->PanelDisplay->Hide();
                TextDesc->Text = "";
                bool buttonEnabled = false;
                if ( ListPackages->SelectedItems->Count )
                {
                        buttonEnabled = true;

                        ListView::SelectedListViewItemCollection^ selected = this->ListPackages->SelectedItems;
                        System::Collections::IEnumerator^ myEnum = selected->GetEnumerator();
                        while ( myEnum->MoveNext() )
                        {
                                CBaseFile *p = this->FindPackageFromList(safe_cast<ListViewItem ^>(myEnum->Current));
                                if ( p )
                                {
                                        if ( p->IsEnabled() )
                                                ButDisable->Text = "Disable";
                                        else
                                                ButDisable->Text = "Enable";
                                        if ( !p->description().empty() )        TextDesc->Text = _US(p->description().findReplace(L"<br>", L"\n").stripHtml());

                                        this->PictureDisplay->Show();
                                        bool addedIcon = false;
                                        C_File *picFile = p->GetFirstFile(FILETYPE_ADVERT);
                                        if ( picFile )
                                        {
                                                System::String ^pic = _US(picFile->filePointer());
                                                if ( System::IO::File::Exists(pic) )
                                                {
                                                        Bitmap ^myBitmap = gcnew Bitmap(pic);
                                                        if ( myBitmap )
                                                        {
                                                                this->PictureDisplay->Image = dynamic_cast<Image ^>(myBitmap);
                                                                addedIcon = true;
                                                        }
                                                }
                                        }

                                        if ( !addedIcon )
                                        {
        
                                                System::ComponentModel::ComponentResourceManager^  resources = (gcnew System::ComponentModel::ComponentResourceManager(MainGui::typeid));
                                                this->PictureDisplay->Image = (cli::safe_cast<System::Drawing::Image^  >(resources->GetObject(L"PictureDisplay.Image")));
                                        }

                                        if ( p->GetType() != TYPE_ARCHIVE )
                                                this->PanelDisplay->Show();
                                }       
                        }                               
                }

                // enable/disable the buttons connected to the package list
                ButUninstall->Enabled = buttonEnabled;
                ButDisable->Enabled = buttonEnabled;
        }

        bool MainGui::EnablePackage(CBaseFile *p)
        {
                if ( !m_pPackages->PrepareEnablePackage(p) )
                {
                        if ( m_pPackages->GetError() == PKERR_NOPARENT )
                                this->DisplayMessageBox(false, "Enable Error", "Error enabling package\n" + _US(p->getFullPackageName(m_pPackages->GetLanguage())) + "\n\nParent mod is not enabled", MessageBoxButtons::OK, MessageBoxIcon::Warning);
                        else if ( m_pPackages->GetError() == PKERR_MODIFIED )
                                this->DisplayMessageBox(false, "Enable Error", "Error enabling package\n" + _US(p->getFullPackageName(m_pPackages->GetLanguage())) + "\n\nPackage is modified and game is currently set to vanilla\nSwitch to modified mode to enable", MessageBoxButtons::OK, MessageBoxIcon::Warning);
                        else if ( m_pPackages->GetError() == PKERR_MISSINGDEP )
                        {
                                Utils::WStringList depList;
                                m_pPackages->getMissingDependacies(p, &depList, true);
                                Utils::WString sDep;
                                for(auto itr = depList.begin(); itr != depList.end(); itr++)
                                {
                                        if ( (*itr)->str.contains(L"|") )
                                                sDep = (*itr)->str.token(L"|", 1) + L" V" + (*itr)->str.token(L"|", 2) + L" by " + (*itr)->data + L"\n";
                                        else
                                                sDep = (*itr)->str + L" by " + (*itr)->data + L"\n";
                                }
                                this->DisplayMessageBox(false, "Enable Error", "Error enabling package\n" + _US(p->getFullPackageName(m_pPackages->GetLanguage())) + "\n\nMissing Enabled Dependacies:\n" + _US(sDep), MessageBoxButtons::OK, MessageBoxIcon::Warning);
                        }
                        else
                                this->DisplayMessageBox(false, "Enable Error", "Error enabling package\n" + _US(p->getFullPackageName(m_pPackages->GetLanguage())) + "\n\nUnknown Error", MessageBoxButtons::OK, MessageBoxIcon::Warning);
                        return false;
                }
                return true;
        }

        void MainGui::DisableList(ArrayList ^List)
        {
                bool skipShips = false;
                int count = 0;

                for ( int i = 0; i < List->Count; i++ )
                {
                        CBaseFile *p = this->FindPackageFromList(cli::safe_cast<ListViewItem ^>(List[i]));
                        if ( p )
                        {
                                if ( p->IsEnabled() )
                                {
                                        if ( p->GetType() == TYPE_SPK && ((CSpkFile *)p)->IsLibrary() )
                                        {
                                                if ( this->DisplayMessageBox(false, "Disable Library", "Package: " + _US(p->getFullPackageName(m_pPackages->GetLanguage())) + "\nThis is a library package and might be required for other installed packages\nDo you still wish to disable it?", MessageBoxButtons::YesNo, MessageBoxIcon::Question) == System::Windows::Forms::DialogResult::No )
                                                        continue;
                                        }
                                        if ( p->GetType() == TYPE_XSP )
                                        {
                                                if ( !this->DisplayTip(TIPSECTION_YESNO, TIP_SHIPDISABLE) )
                                                        skipShips = true;

                                                if ( skipShips )
                                                        continue;
                                        }

                                        m_pPackages->PrepareDisablePackage(p);
                                        ++count;
                                }
                                else
                                {
                                        this->EnablePackage(p);
                                        ++count;
                                }
                        }
                }

                if ( count )
                {
                        this->Enabled = false;
                        this->StartBackground(MGUI_BACKGROUND_DISABLE);
                }
        }

        void MainGui::DisableEvent(System::Object ^Sender, System::EventArgs ^E)
        {
                if ( !ListPackages->SelectedItems->Count )
                        return;

                bool skipShips = false;

                ListView::SelectedListViewItemCollection^ selected = this->ListPackages->SelectedItems;
                System::Collections::IEnumerator^ myEnum = selected->GetEnumerator();
                int count = 0;
                ArrayList ^List = gcnew ArrayList();

                while ( myEnum->MoveNext() )
                        List->Add(safe_cast<ListViewItem ^>(myEnum->Current));

                if ( List->Count )
                        this->DisableList(List);
        }

        void MainGui::PackageBrowserEvent(System::Object ^Sender, System::EventArgs ^E)
        {
                this->Enabled = false;
                PackageBrowser ^mod = gcnew PackageBrowser(m_pPackages, m_lAvailablePackages, this->imageList1, this);
                if ( !mod->AnyPackages() )
                {
                        System::String ^game = _US(m_pPackages->getGameName());
                        this->DisplayMessageBox(false, "No Available Packages", "No available packages found for " + game, MessageBoxButtons::OK, MessageBoxIcon::Exclamation);

                        this->Enabled = true;
                        return;
                }

                if ( m_bDirLocked ) {
                        this->DisplayLocked(false);
                        this->Enabled = true;
                        return;
                }

                mod->SetExperimental(m_bExperimental);
                mod->SetCheat(m_bCheat);
                mod->SetShips(m_bShips);
                if ( m_pPackages->IsVanilla() )
                        mod->SetSigned(true);
                else
                        mod->SetSigned(m_bSigned);
                mod->SetDownload(m_bDownloadable);
                mod->UpdatePackages();
                System::Windows::Forms::DialogResult result = mod->ShowDialog(this);

                m_bDownloadable = mod->IsDownload();
                m_bCheat = mod->IsCheat();
                m_bExperimental = mod->IsExperimental();
                m_bShips = mod->IsShips();
                m_bSigned = mod->IsSigned();

                bool doenable = true;
                CBaseFile *p = mod->SelectedMod();
                if ( result == System::Windows::Forms::DialogResult::OK )
                {
                        if ( p )
                        {
                                if ( this->InstallPackage(_US(p->filename()), true, false, true) )
                                        doenable = false;
                        }
                }
                else if ( result == System::Windows::Forms::DialogResult::Yes )
                        this->StartInstalling(false, true);

                this->Enabled = doenable;
        }

        void MainGui::CloseEvent(System::Object ^Sender, FormClosingEventArgs ^E)
        {
                int h = this->Size.Height;
                int w = this->Size.Width;
        }

        void MainGui::DisplayLocked(bool inthread) 
        {
                this->DisplayMessageBox(inthread, "Directory Locked", "The current directory is locked and unable to make any changes\nYou may need to adjust the directory permissions", MessageBoxButtons::OK, MessageBoxIcon::Error);
        }

        void MainGui::OpenModSelecter()
        {
                if (m_pPackages->IsVanilla())
                {
                        this->DisplayMessageBox(false, "Mod Selector", "Currently in Vanilla Mode, You can only enable mods when in Modified Mode\n\nSwitch to modified mode if you wish to install mods", MessageBoxButtons::OK, MessageBoxIcon::Question);
                        return;
                }
                this->Enabled = false;
                ModSelector ^mod = gcnew ModSelector(m_pPackages, this->imageList1);

                if (!mod->AnyPackages())
                {
                        this->DisplayMessageBox(false, "Mod Selector", "No available mods have been found", MessageBoxButtons::OK, MessageBoxIcon::Warning);
                        this->Enabled = true;
                        return;
                }

                if (m_bDirLocked) {
                        this->DisplayLocked(false);
                        this->Enabled = true;
                        return;
                }

                if (!m_bModSelectorDetails)
                {
                        mod->HideDetails();
                        mod->Update();
                }

                System::Windows::Forms::DialogResult result = mod->ShowDialog(this);
                m_bModSelectorDetails = mod->ShowingDetails();

                // install the selected mod
                bool reEnable = true;

                CBaseFile *p = mod->SelectedMod();
                if (result == System::Windows::Forms::DialogResult::OK)
                {
                        if (p)
                        {
                                // from file
                                if (p->GetNum() < 0)
                                {
                                        if (m_pPackages->GetEnabledMod())
                                                m_pPackages->disablePackage(m_pPackages->GetEnabledMod(), 0, 0);
                                        if (this->InstallPackage(_US(p->filename()), true, false, true))
                                                reEnable = false;
                                }
                                // otherwise just enable it
                                else
                                {
                                        if (this->EnablePackage(p))
                                        {
                                                this->StartBackground(MGUI_BACKGROUND_DISABLE);
                                                reEnable = false;
                                        }
                                }
                        }
                }

                // install downloaded mods
                else if (result == Windows::Forms::DialogResult::Yes)
                        this->StartInstalling(false, true);

                // remove the current mod
                else if (result == System::Windows::Forms::DialogResult::Abort)
                {
                        if (m_pPackages->GetEnabledMod())
                        {
                                CBaseFile *mod = m_pPackages->GetEnabledMod();
                                Utils::WString message = mod->getFullPackageName(m_pPackages->GetLanguage());
                                m_pPackages->disablePackage(m_pPackages->GetEnabledMod(), 0, 0);
                                this->DisplayMessageBox(false, "Mod Disabed", _US(message) + " has been disabled\nYour game is no longer using any mods\n", MessageBoxButtons::OK, MessageBoxIcon::Exclamation);
                        }
                }

                // uninstall the selected mod
                else if (result == System::Windows::Forms::DialogResult::Retry)
                {
                        if (p && p->GetNum() >= 0)
                        {
                                m_pPackages->PrepareUninstallPackage(p);
                                if (m_pPackages->GetNumPackagesInQueue())
                                {
                                        reEnable = false;
                                        this->StartBackground(MGUI_BACKGROUND_UNINSTALL);
                                }
                        }
                }

                if (reEnable)
                        this->Enabled = true;

                mod->RemovePackages();
                this->UpdatePackages();
        }

        void MainGui::ModSelectorEvent(System::Object ^Sender, System::EventArgs ^E)
        {
                OpenModSelecter();
        }

        void MainGui::UninstallList(ArrayList ^List)
        {
                bool skipShips = false;

                for ( int i = 0; i < List->Count; i++ )
                {
                        CBaseFile *p = this->FindPackageFromList(safe_cast<ListViewItem ^>(List[i]));
                        if ( p )
                        {
                                if ( p->GetType() == TYPE_XSP )
                                {
                                        if ( !this->DisplayTip(TIPSECTION_YESNO, TIP_SHIPUNINSTALL) )
                                                skipShips = true;

                                        if ( skipShips )
                                                continue;
                                }

                                // display uninstall text
                                Utils::WString beforeText = m_pPackages->getUninstallBeforeText(p);
                                if ( !beforeText.empty() ) {
                                        if ( this->DisplayMessageBox(false, "Uninstall Package", _US(p->getFullPackageName(m_pPackages->GetLanguage()) + "\n" + beforeText + "\n\nDo you want to uninstall this package?"), MessageBoxButtons::YesNo, MessageBoxIcon::Question) != System::Windows::Forms::DialogResult::Yes )
                                                continue;
                                }

                                m_pPackages->PrepareUninstallPackage(p);
                        }
                }

                if ( m_pPackages->GetNumPackagesInQueue() )
                {
                        this->Enabled = false;
                        this->StartBackground(MGUI_BACKGROUND_UNINSTALL);
                }
        }
        void MainGui::UninstallEvent(System::Object ^Sender, System::EventArgs ^E)
        {
                if ( !ListPackages->SelectedItems->Count )
                        return;

                ArrayList ^List = gcnew ArrayList();

                ListView::SelectedListViewItemCollection^ selected = this->ListPackages->SelectedItems;
                System::Collections::IEnumerator^ myEnum = selected->GetEnumerator();

                while ( myEnum->MoveNext() )
                        List->Add(safe_cast<ListViewItem ^>(myEnum->Current));

                this->UninstallList(List);
        }

        void MainGui::ModifiedEvent(System::Object ^Sender, System::EventArgs ^E)
        {
                if ( m_bDirLocked ) {
                        this->DisplayLocked(false);
                        return;
                }
                if ( m_pPackages->IsVanilla() )
                {
                        this->Enabled = false;
                        if ( this->DisplayMessageBox(false, "Modified Mode", "Enabling modified mode will allow you to use any modified content\nThis will however mark any games you save as modified and you will be unable to participate in Uplink\nAny current save games wil also be backed up and kept seperate from your modified save games\n\nDo you wish to enable modified mode?", MessageBoxButtons::YesNo, MessageBoxIcon::Question) == System::Windows::Forms::DialogResult::Yes )
                        {
                                if ( m_iSaveGameManager == 1 )
                                {
                                        m_pPackages->backupSaves(true);
                                        m_pPackages->restoreSaves(false);
                                }
                                m_pPackages->SetVanilla(false);
                                m_pMenuBar->Modified();
                                m_pPackages->PrepareEnableLibrarys();
                                m_pPackages->PrepareEnableFromVanilla();
                                this->StartBackground(MGUI_BACKGROUND_DISABLE);
                        }
                        else
                                this->Enabled = true;
                }
        }

        void MainGui::VanillaEvent(System::Object ^Sender, System::EventArgs ^E)
        {
                if ( m_bDirLocked ) {
                        this->DisplayLocked(false);
                        return;
                }
                if ( !m_pPackages->IsVanilla() )
                {
                        this->Enabled = false;
                        if ( this->DisplayMessageBox(false, "Vanilla Mode", "Switching back to vanilla mode you will no longer be able to use any modifying packages, these will be disabled\nYour current save games will be backed up as modified saves, and any vanilla save games will be restored\n\nDo you wish to go back to Vanilla?", MessageBoxButtons::YesNo, MessageBoxIcon::Question) == System::Windows::Forms::DialogResult::Yes )
                        {
                                if ( m_iSaveGameManager == 1 )
                                {
                                        m_pPackages->backupSaves(false);
                                        m_pPackages->restoreSaves(true);
                                }
                                m_pPackages->SetVanilla(true);
                                m_pMenuBar->Vanilla();
                                m_pPackages->PrepareDisableForVanilla();
                                this->StartBackground(MGUI_BACKGROUND_DISABLE);
                        }
                        else
                                this->Enabled = true;
                }
        }

        void MainGui::InstallEvent(System::Object ^Sender, System::EventArgs ^E)
        {
                if ( m_bDirLocked ) {
                        this->DisplayLocked(false);
                        return;
                }

                OpenFileDialog ^ofd = gcnew OpenFileDialog();
                ofd->Filter = "All (*.spk, *.xsp)|*.spk;*.xsp|Package Files (*.spk)|*.spk|Ship Files (*.xsp)|*.xsp";
                ofd->FilterIndex = 1;
                ofd->RestoreDirectory = true;
                ofd->Multiselect = true;

                this->Enabled = false;
                if ( ofd->ShowDialog(this) == System::Windows::Forms::DialogResult::OK )
                {
                        bool anytoinstall = false;
                        array<System::String ^> ^fileArray = ofd->FileNames;
                        for ( int i = 0; i < fileArray->Length; i++ )
                        {
                                System::String ^file = fileArray[i];
                                if ( this->InstallPackage(file, false, false, true) )
                                        anytoinstall = true;
                        }

                        if ( anytoinstall )
                                this->StartInstalling(false, true);
                }
                else
                {
                        ProgressBar->Hide();
                        this->Enabled = true;
                }
        }

        void MainGui::CheckUnusedShared()
        {
                if ( m_pPackages->AnyUnusedShared() )
                {
                        if ( this->DisplayMessageBox(false, "Remove Shared Files", "You have some unused shared files, would you like to remove these?", MessageBoxButtons::YesNo, MessageBoxIcon::Question) == System::Windows::Forms::DialogResult::Yes)
                                m_pPackages->removeUnusedSharedFiles();
                }
        }

        void MainGui::ChangeDirectoryEvent(System::Object ^Sender, System::EventArgs ^E)
        {
                if (ComboDir->SelectedIndex == (ComboDir->Items->Count - 1))
                {
                        if (m_pPackages && m_pPackages->IsLoaded())
                        {
                                this->Enabled = false;
                                ProgressBar->Show();
                                this->CheckUnusedShared();
                                this->StartBackground(MGUI_BACKGROUND_CLOSEDIR, "");
                        }
                }
                else if (ComboDir->SelectedIndex >= 0)
                {
                        Utils::WString dir = m_pDirList->get(ComboDir->SelectedIndex)->str;
                        if (!m_pPackages->isCurrentDir(dir))
                        {
                                this->Enabled = false;
                                ProgressBar->Show();
                                this->CheckUnusedShared();
                                this->StartBackground(MGUI_BACKGROUND_CHANGEDIR, _US(dir));
                        }
                }
        }

        void MainGui::Background_DoWork(System::Object ^Sender, DoWorkEventArgs ^E)
        {
                m_bDisplayMessage = false;
                m_bDisplayDialog = false;

                switch ( m_iBackgroundTask )
                {
                        case MGUI_BACKGROUND_INSTALL:
                                this->DoInstall(false, true);
                                break;
                        case MGUI_BACKGROUND_INSTALLBUILTIN:
                                this->DoInstall(true, true);
                                break;
                        case MGUI_BACKGROUND_UNINSTALL:
                                this->DoUninstall();
                                break;
                        case MGUI_BACKGROUND_DISABLE:
                                this->DoDisable();
                                break;
                        case MGUI_BACKGROUND_CLOSEDIR:
                                this->CloseCurrentDirectory();
                                break;
                        case MGUI_BACKGROUND_CHANGEDIR:
                                this->ChangeDirectory(_WS(m_sBackgroundInfo));
                                break;
                }
        }

        void MainGui::Background_Finished()
        {
                ProgressBar->Hide();

                if ( m_bDisplayMessage )
                        MessageBox::Show(this, m_sMessageText, m_sMessageTitle, m_messageButtons, m_messageIcon);

                if ( m_bDisplayDialog )
                {
                        if ( m_pPi->PackageCount() )
                        {
                                m_pPi->AdjustColumns();
                                m_pPi->ShowDialog(this);
                        }
                }

                m_bDisplayDialog = false;
                m_bDisplayMessage = false;

                if ( m_iBackgroundTask == MGUI_BACKGROUND_CHANGEDIR || m_iBackgroundTask == MGUI_BACKGROUND_CLOSEDIR)
                {
                        // switch the dir list
                        Utils::WString selectedDir;
                        if (ComboDir->SelectedIndex == ComboDir->Items->Count - 1)
                                selectedDir = _WS(ComboDir->Text);
                        else if (ComboDir->SelectedIndex >= 0)
                        {
                                Utils::WString dir = m_pDirList->get(ComboDir->SelectedIndex)->str;
                                selectedDir = dir;
                                if ( !dir.empty() )
                                {
                                        if ( (m_iBackgroundTask == MGUI_BACKGROUND_CHANGEDIR) && (dir.countToken(L" [")) )
                                                dir = dir.tokens(L" [", 1);
                                        if ( m_pDirList->findString(dir) )
                                        {
                                                Utils::WString data = m_pDirList->findString(dir);
                                                m_pDirList->remove(dir, false);
                                                m_pDirList->pushFront(dir, data);
                                        }
                                        else
                                        {
                                                int lang = m_pPackages->getGameLanguage(dir);
                                                if ( lang )
                                                        m_pDirList->pushFront(dir, Utils::WString::Number(lang) + L"|" + m_pPackages->getGameName(dir));
                                                else
                                                        m_pDirList->pushFront(dir, m_pPackages->getGameName(dir));
                                        }
                                }
                        }

                        this->UpdateDirList(selectedDir);
                        this->UpdateRunButton();
                }

                // display any files that failed
                if ( m_iBackgroundTask == MGUI_BACKGROUND_INSTALL )
                {
                        String ^files = "";
                        for(auto itr = m_pFileErrors->begin(); itr != m_pFileErrors->end(); itr++)
                        {
                                if ((*itr)->data.toInt() == SPKINSTALL_WRITEFILE_FAIL )
                                {
                                        files += "\n";
                                        files += _US((*itr)->str);
                                }
                        }

                        if ( files->Length )
                                MessageBox::Show(this, "These files failed to install\n" + files, "Failed Files", MessageBoxButtons::OK, MessageBoxIcon::Warning);
                }

                switch ( m_iBackgroundTask )
                {
                        case MGUI_BACKGROUND_CLOSEDIR:
                        case MGUI_BACKGROUND_CHANGEDIR:
                                this->UpdateControls();
                                this->UpdatePackages();
                                this->CheckProtectedDir();
                                m_bRunningBackground = false;
                                if ( this->UpdateBuiltInPackages() )
                                        return;
                                break;

                        case MGUI_BACKGROUND_INSTALL:
                        case MGUI_BACKGROUND_INSTALLBUILTIN:
                        case MGUI_BACKGROUND_UNINSTALL:
                        case MGUI_BACKGROUND_DISABLE:
                                this->UpdatePackages();
                                break;
                }

                m_iBackgroundTask = MGUI_BACKGROUND_NONE;

                this->Enabled = true;
                ProgressBar->Hide();
                m_bRunningBackground = false;
        }

        void MainGui::Background_Progress(System::Object ^Sender, ProgressChangedEventArgs ^E)
        {
                this->ProgressBar->Value = E->ProgressPercentage;
        }

        bool MainGui::UpdateBuiltInPackages()
        {
                // no current directory
                if (!m_pPackages || !m_pPackages->IsLoaded())
                        return false;

                // find all built-in packages
                System::String ^dir = ".\\Required";

                if ( System::IO::Directory::Exists(dir) ) 
                {
                        bool installing = false;
                        array <System::String ^> ^Files = System::IO::Directory::GetFiles(dir, "*.spk");

                        for ( int i = 0; i < Files->Length; i++ )
                        {
                                Utils::WString file = _WS(Files[i]);
                                int error;
                                CBaseFile *p = m_pPackages->openPackage(file, &error, 0, SPKREAD_NODATA);
                                if ( !p )
                                        continue;

                                if ( !((CSpkFile *)p)->IsLibrary() )
                                        continue;

                                if ( !p->CheckGameCompatability(m_pPackages->GetGame()) )
                                        continue;

                                // if its installed, check if we have a newer version
                                CBaseFile *check = m_pPackages->findSpkPackage(p->name(), p->author());
                                if ( check )
                                {
                                        if ( check->version().compareVersion(p->version()) != COMPARE_OLDER )
                                        {
                                                this->InstallPackage(Files[i], false, true, true);
                                                installing = true;
                                        }
                                }
                                else
                                {
                                        this->InstallPackage(Files[i], false, true, true);
                                        installing = true;
                                }

                                delete p;
                        }
                
                        if ( installing )
                                this->StartInstalling(true, true);
                        return installing;
                }

                return false;
        }

        ////
        // Auto Update
        ////
        void MainGui::AutoUpdate()
        {
                if ( !m_bAutoUpdate || !System::IO::File::Exists( ".\\AutoUpdater.exe") )
                        return;

                // load the dir list
                if ( !m_pUpdateList )
                {
                        m_pUpdateList = new Utils::WStringList;

                        // TODO: read addresses from data

                        // hardcoded address
                        m_pUpdateList->pushBack(L"http://xpluginmanager.co.uk/pmupdate.dat", L"");
                        if ( (int)PMLBETA )
                                m_pUpdateList->pushBack(L"http://xpluginmanager.co.uk/Beta/pmupdatebeta.dat", L"");
                }

                backgroundUpdater->RunWorkerAsync();
        }

        void MainGui::Updater_Finished(System::Object ^Sender, RunWorkerCompletedEventArgs ^E)
        {
                if ( !m_pUpdateList )
                        return;
                if (m_pUpdateList->empty())
                {
                        delete m_pUpdateList;
                        m_pUpdateList = nullptr;
                        return;
                }

                this->Enabled = false;

                Utils::WString server = (*m_pUpdateList)[0]->str;
                Utils::WString data = (*m_pUpdateList)[0]->data;

                m_pUpdateList->popFront();

                // lets check if we have an update
                if ( data.token(L" ", 1) != L"!ERROR!" )
                {
                        Utils::WString download;
                        Utils::WString message;

                        std::vector<Utils::WString> strs;
                        if(data.tokenise(L"\n", strs))
                        {
                                for (size_t i = 0; i < strs.size(); i++)
                                {
                                        Utils::WString cmd = strs[i].token(L":", 1);
                                        Utils::WString rest = strs[i].tokens(L":", 2);
                                        rest.removeFirstSpace();
                                        if ( cmd.Compare(L"SPKVERSION") )
                                        {
                                                float v = rest.token(L" ", 1).toFloat();
                                                if ( v > GetLibraryVersion() )
                                                {
                                                        message += L"New version of the SPK Libraries available\nCurrent = ";
                                                        message += Utils::WString::FromFloat(GetLibraryVersion(), 2);
                                                        message += L"\nNew Version = ";
                                                        message += Utils::WString::FromFloat(v, 2);
                                                        message += L"\n\n";

                                                        Utils::WString filename = rest.tokens(L" ", 2);
                                                        if ( download.empty() )
                                                                download = filename;
                                                        else
                                                        {
                                                                download += L"|";
                                                                download += filename;
                                                        }
                                                }
                                        }
                                        else if ( cmd.Compare(L"PMLVERSION") )
                                        {
                                                float v = rest.token(L" ", 1).toFloat();
                                                int beta = rest.token(L" ", 2).toInt();

                                                bool newVersion = false;
                                                // new version
                                                if ( v > (float)PMLVERSION )
                                                        newVersion = true;
                                                // same version, check beta/rc
                                                if ( v == (float)PMLVERSION )
                                                {
                                                        // newer beta version
                                                        if ( beta > (int)PMLBETA && (int)PMLBETA > 0 )
                                                                newVersion = true;
                                                        // current is beta, new is an RC
                                                        else if ( (int)PMLBETA > 0 && beta < 0 )
                                                                newVersion = true;
                                                        // current is rc, new is an rc
                                                        else if ( (int)PMLBETA < 0 && beta < 0 && beta < (int)PMLBETA )
                                                                newVersion = true;
                                                        // current is beta or rc, new is not, so its newer
                                                        else if ( (int)PMLBETA != 0 && beta == 0 )
                                                                newVersion = true;
                                                }

                                                if ( newVersion )
                                                {
                                                        message += L"New version of the ";
                                                        message += _WS(GetProgramName(m_bAdvanced));
                                                        message += L" available\nCurrent = ";
                                                        message += _WS(PluginManager::GetVersionString());
                                                        message += L"\nNew Version = ";
                                                        message += _WS(PluginManager::GetVersionString(v, beta));
                                                        message += L"\n\n";
                                                        if ( download.empty() )
                                                                download = rest.tokens(L" ", 3);
                                                        else
                                                        {
                                                                download += L"|";
                                                                download += rest.tokens(L" ", 3);
                                                        }
                                                }
                                        }
                                }
                        }

                        if ( !download.empty() && !message.empty() )
                        {
                                if ( this->DisplayMessageBox(false, "Updater", _US(message) + "Do You wish to download and install it?", MessageBoxButtons::YesNo, MessageBoxIcon::Question) == System::Windows::Forms::DialogResult::Yes )
                                {
                                        // absolute address
                                        Utils::WString downloadFile;

                                        std::vector<Utils::WString> strs;
                                        download.tokenise(L"\n", strs);

                                        for (size_t i = 0; i < strs.size(); i++ )
                                        {
                                                Utils::WString d = strs[i];
                                                // relative address
                                                if ( !d.left(7).Compare(L"http://") && !d.left(4).Compare(L"www.") )
                                                        d = server.remToken(L"/", server.countToken(L"/")) + L"/" + d;

                                                if ( downloadFile.empty() )
                                                        downloadFile = d;
                                                else
                                                {
                                                        downloadFile += L"|";
                                                        downloadFile += d;
                                                }
                                        }

                                        if ( !downloadFile.empty() )
                                        {
                                                m_sDownload = _US(downloadFile);
                                                this->Close();
                                                return;
                                        }
                                }
                        }
                }

                // otherwise, lets continue with the next server
                if (!m_pUpdateList->empty())
                        backgroundUpdater->RunWorkerAsync();
                else
                {
                        delete m_pUpdateList;
                        m_pUpdateList = NULL;
                }

                this->Enabled = true;
        }

        void MainGui::TimerEvent_CheckFile(System::Object ^Sender, System::EventArgs ^E)
        {
                if ( m_bRunningBackground )
                        return;

                System::String ^mydoc = Environment::GetFolderPath(Environment::SpecialFolder::Personal );

                bool anytoinstall = false;

                if ( System::IO::File::Exists(mydoc + "\\Egosoft\\pluginmanager_load.dat") )
                {
                        System::String ^lines = System::IO::File::ReadAllText(mydoc + "\\Egosoft\\pluginmanager_load.dat");
                        System::IO::File::Delete(mydoc + "\\Egosoft\\pluginmanager_load.dat");
                        if ( lines )
                        {
                                Utils::WString strLines = _WS(lines);
                                int num;
                                Utils::WString *aLines = strLines.tokenise(L"\n", &num);
                                if ( num && aLines )
                                {
                                        for ( int i = 0; i < num; i++ )
                                        {
                                                Utils::WString l = aLines[i];
                                                l = l.remove('\r');
                                                Utils::WString first = l.token(L":", 1);
                                                Utils::WString rest = l.tokens(L":", 2);
                                                rest.removeFirstSpace();

                                                if ( first.Compare(L"File") )
                                                {
                                                        if ( m_bDirLocked ) {
                                                                this->DisplayLocked(false);
                                                                return;
                                                        }
                                                        if ( this->InstallPackage(_US(rest), false, false, true) )
                                                                anytoinstall = true;
                                                }
                                        }

                                        CLEANSPLIT(aLines, num);
                                }
                        }
                }

                if ( anytoinstall )
                        this->StartInstalling(false, true);
        }

        void MainGui::Updater_DoWork(System::Object ^Sender, DoWorkEventArgs ^E)
        {
                if ( !m_pUpdateList )
                        return;
                if (m_pUpdateList->empty())
                {
                        delete m_pUpdateList;
                        m_pUpdateList = NULL;
                        return;
                }

                try 
                {
                        System::Net::WebClient ^Client = gcnew System::Net::WebClient();

                        System::IO::Stream ^strm = Client->OpenRead(_US(m_pUpdateList->front()));
                        System::IO::StreamReader ^sr = gcnew System::IO::StreamReader(strm);
                        System::String ^read = sr->ReadToEnd();
                        strm->Close();
                        sr->Close();
                        m_pUpdateList->changeData(m_pUpdateList->front(), _WS(read));
                }
                catch (System::Net::WebException ^ex)
                {
                        m_pUpdateList->changeData(m_pUpdateList->front(), _WS("!ERROR! " + ex->ToString()));
                        if ( ex->Status == System::Net::WebExceptionStatus::ConnectFailure )
                                m_pUpdateList->changeData(m_pUpdateList->front(), _WS("!ERROR! " + ex->ToString()));
                }
        }

        void MainGui::LaunchGame()
        {
                if ( !System::IO::File::Exists(".\\GameLauncher.exe") )
                        return;

                m_sRun = _US(m_pPackages->getGameRunExe());
                this->Close();
        }

        bool MainGui::DisplayTip(int tipsection, int tip)
        {
                if ( tipsection < 0 || tipsection >= MAXTIPS )
                        return false;

                STips ^tips = (STips ^)m_lTips[tipsection];
                if ( !(tips->iTips & tip) )
                {
                        System::String ^sTip = cli::safe_cast<System::String ^>(tips->sTips[(tip >> 1)]);

                        tips->iTips |= tip;

                        if ( this->DisplayMessageBox(false, "Plugin Manager Tip", sTip, MessageBoxButtons::YesNo, MessageBoxIcon::Question) == System::Windows::Forms::DialogResult::Yes )
                                return true;
                        else 
                                return false;
                }

                return true;
        }

        void MainGui::SetTipStrings(int section)
        {
                STips ^t = (STips ^)m_lTips[section];
                t->sTips = gcnew ArrayList();

                switch ( section )
                {
                        case TIPSECTION_YESNO:
                                t->sTips->Add("You are about to uninstall a ship, you need to make sure that there are no ships in the sector you was in when you saved, otherwise it could prevent the save from loading\n\nContinue Uninstalling Ship?");
                                t->sTips->Add("You are about to disable a ship, you need to make sure that there are no ships in the sector you was in when you saved, otherwise it could prevent the save from loading\n\nContinue Disabling Ship?");
                                break;
                }
        }

        void MainGui::SetSaveGameManager(int i) 
        { 
                m_iSaveGameManager = i; 
                if (m_iSaveGameManager != -1)
                {
                        if (m_pPackages && m_pPackages->IsLoaded())
                                m_pPackages->setSaveGameManager(m_iSaveGameManager == 1);
                }
        }


        System::Windows::Forms::DialogResult MainGui::DisplayMessageBox(bool inthread, System::String ^title, System::String ^text, MessageBoxButtons buttons, MessageBoxIcon icon)
        {
                if ( !inthread )
                        return MessageBox::Show(this, text, title, buttons, icon);
                else
                {
                        m_bDisplayMessage = true;
                        m_sMessageText = text;
                        m_sMessageTitle = title;
                        m_messageIcon = icon;
                        m_messageButtons = buttons;

                        return System::Windows::Forms::DialogResult::Abort;
                }
        }

        ListViewItem ^MainGui::FindSelectedItem()
        {
                Point ^mousePoint = this->ListPackages->PointToClient(this->contextMenuStrip1->MousePosition);
                return  this->ListPackages->GetItemAt(mousePoint->X, mousePoint->Y);
        }

        CBaseFile *MainGui::GetFileFromItem(ListViewItem ^item)
        {
                int num = System::Convert::ToInt32(item->Tag);
                return m_pPackages->GetPackageAt(num);
        }

        System::Void MainGui::OpenContextMenu(System::Object ^Sender, CancelEventArgs ^E)
        {
                m_pListItem = nullptr;
                E->Cancel = true;
                bool showSep = false;
                bool showSep2 = false;

                ListViewItem ^item = this->FindSelectedItem();
                CBaseFile *p = NULL;
                if ( item )
                                p = this->GetFileFromItem(item);

                this->emailAuthorToolStripMenuItem->Visible = false;
                this->visitForumPageToolStripMenuItem->Visible = false;
                this->visitWebSiteToolStripMenuItem->Visible = false;
                this->ContextDisable->Visible = false;
                this->ContextEnable->Visible = false;
                this->ContextName->Image = nullptr;
                this->UninstallSelectedContext->Visible = false;
                this->viewReadmeToolStripMenuItem->Visible = false;
                this->extrasToolStripMenuItem->Visible = false;
                this->checkForUpdatesToolStripMenuItem->Visible = false;

                if ( p  || this->ListPackages->SelectedItems->Count )
                {

                        if ( item && p )
                        {
                                m_pListItem = item;
                                this->ContextName->Text = item->Text;
                                if ( item->ImageIndex != -1 )
                                        this->ContextName->Image = this->ListPackages->LargeImageList->Images[item->ImageIndex];
                                else if ( item->ImageKey )
                                {
                                        int key = this->ListPackages->LargeImageList->Images->IndexOfKey(item->ImageKey);
                                        if ( key != -1 )
                                                this->ContextName->Image = this->ListPackages->LargeImageList->Images[key];
                                }
                                else if ( p->icon() )
                                        PluginManager::DisplayContextIcon(p, this->ContextName, nullptr);

                                this->uninstallToolStripMenuItem->Text = "Uninstall: " + item->Text;

                                this->viewReadmeToolStripMenuItem->DropDownItems->Clear();
                                if (p->countFiles(FILETYPE_README))
                                {
                                        for ( C_File *f = p->GetFirstFile(FILETYPE_README); f; f = p->GetNextFile(f) )
                                        {
                                                if ( f->baseName().token(L".", 1).isNumber() )
                                                {
                                                        if ( f->baseName().token(L".", 1).toInt() != m_pPackages->GetLanguage() )
                                                                continue;
                                                }
                                                if ( f->baseName().contains(L"-L") )
                                                {
                                                        int pos = f->baseName().findPos(L"-L");
                                                        int l = f->baseName().mid(pos + 2, 3).toInt();
                                                        if ( l != m_pPackages->GetLanguage() )
                                                                continue;
                                                }

                                                Windows::Forms::ToolStripMenuItem ^item = gcnew Windows::Forms::ToolStripMenuItem();
                                                item->Text = _US(f->filename());
                                                item->Image = this->viewReadmeToolStripMenuItem->Image;
                                                item->ImageScaling = ToolStripItemImageScaling::None;
                                                item->Click += gcnew System::EventHandler(this, &MainGui::RunItem);
                                                item->Tag = _US(f->filePointer());
                                                this->viewReadmeToolStripMenuItem->DropDownItems->Add(item);
                                        }

                                        if ( this->viewReadmeToolStripMenuItem->DropDownItems->Count )
                                        {
                                                this->viewReadmeToolStripMenuItem->Visible = true;
                                                showSep = true;
                                        }
                                }

                                this->extrasToolStripMenuItem->DropDownItems->Clear();
                                if (p->countFiles(FILETYPE_EXTRA))
                                {
                                        showSep = true;
                                        for ( C_File *f = p->GetFirstFile(FILETYPE_EXTRA); f; f = p->GetNextFile(f) )
                                        {
                                                if ( !f->dir().left(6).Compare(L"extras") )
                                                        continue;

                                                Windows::Forms::ToolStripMenuItem ^item = gcnew Windows::Forms::ToolStripMenuItem();
                                                item->Text = _US(f->filename());
                                                if ( this->imageList2->Images->IndexOfKey(_US(f->fileExt().lower())) > -1 )
                                                        item->Image = this->imageList2->Images[this->imageList2->Images->IndexOfKey(_US(f->fileExt().lower()))];
                                                else
                                                {
                                                        Utils::WString exe = f->filePointer();
                                                        exe = exe.findReplace(L"/", L"\\");

                                                        System::Drawing::Icon ^myIcon;
                                                        SHFILEINFO *shinfo = new SHFILEINFO();

                                                        if ( FAILED(SHGetFileInfo(exe.c_str(), 0, shinfo, sizeof(shinfo), SHGFI_ICON | SHGFI_LARGEICON)) )
                                                        {
                                                                if ( FAILED(SHGetFileInfo(exe.c_str(), 0, shinfo, sizeof(shinfo), SHGFI_ICON | SHGFI_SMALLICON)))
                                                                        item->Image = this->imageList2->Images[0];
                                                                else
                                                                {
                                                                        myIcon = System::Drawing::Icon::FromHandle(IntPtr(shinfo->hIcon));
                                                                        item->Image = myIcon->ToBitmap();
                                                                }
                                                        }
                                                        else
                                                        {
                                                                myIcon = System::Drawing::Icon::FromHandle(IntPtr(shinfo->hIcon));
                                                                item->Image = myIcon->ToBitmap();
                                                        }

                                                        delete shinfo;
                                                }
                                                item->ImageScaling = ToolStripItemImageScaling::None;
                                                item->Click += gcnew System::EventHandler(this, &MainGui::RunItem);
                                                item->Tag = _US(f->filePointer());
                                                this->extrasToolStripMenuItem->DropDownItems->Add(item);
                                        }
                                }

                                if ( this->extrasToolStripMenuItem->DropDownItems->Count )
                                        this->extrasToolStripMenuItem->Visible = true;

                                // email/website/forum
                                if ( !p->forumLink().empty() ) {
                                        Utils::WString web = p->forumLink();
                                        if ( web.isNumber() )
                                                web = Utils::WString(L"http://forum.egosoft.com/viewtopic.php?t=") + web; 

                                        this->visitForumPageToolStripMenuItem->Visible = true;
                                        if ( !web.isin(L"http://") )
                                                this->visitForumPageToolStripMenuItem->Tag = "http://" + _US(web);
                                        else
                                                this->visitForumPageToolStripMenuItem->Tag = _US(web);
                                        showSep2 = true;
                                }
                                if ( !p->email().empty() )
                                {
                                        this->emailAuthorToolStripMenuItem->Visible = true;
                                        this->emailAuthorToolStripMenuItem->Tag = "mailto://" + _US(p->email()) + "?subject=Re: " + _US(p->name().findReplace(L" ", L"%20"));
                                        showSep2 = true;
                                }
                                if ( !p->webSite().empty() ) {
                                        this->visitWebSiteToolStripMenuItem->Visible = true;
                                        if ( !p->webSite().isin(L"http://") ) 
                                                this->visitWebSiteToolStripMenuItem->Tag = "http://" + _US(p->webSite());
                                        else    
                                                this->visitWebSiteToolStripMenuItem->Tag = _US(p->webSite());
                                        showSep2 = true;
                                }

                                if ( !p->webAddress().empty() )
                                        this->checkForUpdatesToolStripMenuItem->Visible = true;
                        }
                        else
                                m_pListItem = nullptr;

                        if ( this->ListPackages->SelectedItems->Count > 1 || !p )
                        {
                                this->UninstallSelectedContext->Visible = true;
                                this->UninstallSelectedContext->Text = "Uninstall Selected (" + System::Convert::ToString(this->ListPackages->SelectedItems->Count) + " packages)";
                        }

                        if ( p )
                        {
                                if ( p->IsEnabled() )
                                        this->ContextDisable->Visible = true;
                                else
                                        this->ContextEnable->Visible = true;
                        }

                        if (p->IsMod())
                        {
                                this->UninstallSelectedContext->Visible = false;
                                this->uninstallToolStripMenuItem->Visible = false;
                                this->viewModSelectedToolStripMenuItem->Visible = true;
                                this->ContextDisable->Visible = false;
                                this->ContextEnable->Visible = false;
                        }
                        else 
                                this->viewModSelectedToolStripMenuItem->Visible = false;

                        this->ContextSeperator->Visible = showSep;
                        this->ContextSeperator2->Visible = showSep2;
                        E->Cancel = false;
                }
        }

        System::Void MainGui::ListPackages_DragOver(System::Object^  sender, System::Windows::Forms::DragEventArgs^  e)
        {
                e->Effect = DragDropEffects::None;

                if (e->Data->GetDataPresent(DataFormats::FileDrop)) 
                {
                        cli::array<String ^> ^a = (cli::array<String ^> ^)e->Data->GetData(DataFormats::FileDrop, false);
                        int i;
                        for(i = 0; i < a->Length; i++)
                        {
                                String ^s = a[i];
                                String ^ext = IO::FileInfo(s).Extension;
                                if ( String::Compare(IO::FileInfo(s).Extension, ".xsp", true) == 0 || String::Compare(IO::FileInfo(s).Extension, ".spk", true) == 0 )
                                {
                                        e->Effect = DragDropEffects::Copy;
                                        break;
                                }
                        }
                }
        }

        System::Void MainGui::ListPackages_DragDrop(System::Object^  sender, System::Windows::Forms::DragEventArgs^  e)
        {
                if (e->Data->GetDataPresent(DataFormats::FileDrop)) 
                {
                        cli::array<String ^> ^a = (cli::array<String ^> ^)e->Data->GetData(DataFormats::FileDrop, false);
                        int i;
                        for(i = 0; i < a->Length; i++)
                        {
                                String ^s = a[i];
                                String ^ext = IO::FileInfo(s).Extension;
                                if ( String::Compare(IO::FileInfo(s).Extension, ".xsp", true) == 0 || String::Compare(IO::FileInfo(s).Extension, ".spk", true) == 0 )
                                {
                                        if ( m_bDirLocked ) {
                                                this->DisplayLocked(false);
                                                return;
                                        }
                                        this->InstallPackage(s, false, false, true);
                                }
                        }

                        this->StartInstalling(false, true);
                }
        }

        bool MainGui::CheckAccessRights(String ^dir)
        {
                /*
                // check if already exists
                String ^file = dir + "\\accessrightscheck.dat";
                String ^writeStr = "testing file access";
                if ( IO::File::Exists(file) )
                {
                        // remove it
                        IO::File::Delete(file);
                        // still exists, cant delete it
                        if ( IO::File::Exists(file) )
                                return false;
                }

                IO::DirectoryInfo ^dInfo = gcnew IO::DirectoryInfo(dir);
                Security::AccessControl::DirectorySecurity ^dSecurity = dInfo->GetAccessControl();
                dSecurity->
                

                System::IO::FileStream ^writeStream = nullptr;
                IO::BinaryWriter ^writer = nullptr;
                try {
                         writeStream = gcnew System::IO::FileStream(file, System::IO::FileMode::Create);
                         writer = gcnew IO::BinaryWriter(writeStream);
                }
                catch (System::IO::IOException ^e)
                {
                        MessageBox::Show("Error: " + e->ToString(), "Error", MessageBoxButtons::OK, MessageBoxIcon::Warning);
                }
                catch (System::Exception ^e)
                {
                        MessageBox::Show("Error: " + e->ToString(), "Error", MessageBoxButtons::OK, MessageBoxIcon::Warning);
                }
                finally 
                {
                        writer->Write(writeStr);
                        writer->Close();
                        writeStream->Close();
                }

                // check if its written
                if ( !IO::File::Exists(file) )
                        return false;

                // remove the file again
                IO::File::Delete(file);
                if ( IO::File::Exists(file) )
                        return false;
*/
                return true;
        }

        System::Void MainGui::RunItem(System::Object ^sender, System::EventArgs ^e)
        {
                Windows::Forms::ToolStripMenuItem ^item = cli::safe_cast<ToolStripMenuItem ^>(sender);
                String ^file = Convert::ToString(item->Tag);

                if ( IO::File::Exists(file) )
                {
                        System::Diagnostics::Process::Start(file);
                }
        }

        void MainGui::RunFromToolItem(ToolStripMenuItem ^item)
        {
                if ( !item ) return;
                if ( !item->Tag ) return;

                String ^file = Convert::ToString(item->Tag);
                System::Diagnostics::Process::Start(file);
        }

        void MainGui::FakePatchControlDialog()
        {
                FakePatchControl ^fpc = gcnew FakePatchControl(m_pPackages);
                if ( fpc->ShowDialog(this) == Windows::Forms::DialogResult::OK )
                {
                        m_pPackages->applyFakePatchOrder(*fpc->GetPatchOrder());
                        m_pPackages->shuffleFakePatches(0);
                }
        }

        void MainGui::CheckFakePatchCompatability()
        {
                Utils::WStringList errorList;
                int count = 0;
                int packageCount = 0;
                for ( CBaseFile *p = m_pPackages->GetFirstPackage(); p; p = m_pPackages->GetNextPackage(p) )
                {
                        if ( !p->IsEnabled() ) continue;
                        if ( !p->AnyFileType(FILETYPE_MOD) ) continue;

                        Utils::WString packageName = p->getFullPackageName(m_pPackages->GetLanguage());

                        // compare this file against all other packages
                        for ( CBaseFile *comparePackage = m_pPackages->GetNextPackage(p); comparePackage; comparePackage = m_pPackages->GetNextPackage(comparePackage) )
                        {
                                if ( comparePackage == p ) continue; // dont include the same package
                                if ( !comparePackage->IsEnabled() ) continue;
                                if ( !comparePackage->AnyFileType(FILETYPE_MOD) ) continue;

                                Utils::WStringList list;
                                if ( m_pPackages->checkCompatabilityBetweenMods(p, comparePackage, &list) )
                                {
                                        Utils::WString package2Name = comparePackage->getFullPackageName(m_pPackages->GetLanguage());
                                        for(auto itr = list.begin(); itr != list.end(); itr++)
                                        {
                                                errorList.pushBack((*itr)->str + L" (" + packageName + L")", (*itr)->data + L" (" + package2Name + L")");
                                                ++count;
                                        }
                                        ++packageCount;
                                }
                        }
                }

                if ( count )
                {
                        if ( MessageBox::Show(this, "Found incompatability between fake patches\n" + count + " errors found\n\nDo you wish to view the errors?", "Fake Patch Compatability", MessageBoxButtons::YesNo, MessageBoxIcon::Information) == Windows::Forms::DialogResult::Yes )
                        {
                                CompareList ^cl = gcnew CompareList("Fake Patch Incompatabilities");
                                cl->AddStringList(errorList);
                                cl->ShowDialog(this);
                        }
                }
                else
                        MessageBox::Show(this, "No incompatabilities found between fake patches", "Fake Patch Compatability", MessageBoxButtons::OK, MessageBoxIcon::Information);
        }

        void MainGui::EditWaresDialog()
        {
                if ( m_bDirLocked ) {
                        this->DisplayLocked(false);
                        return;
                }

                EditWares ^edit = gcnew EditWares(m_pPackages);

                if ( edit->ShowDialog(this) == Windows::Forms::DialogResult::OK )
                {
                }
        }

        void MainGui::CommandSlotsDialog()
        {
                CommandSlots ^slots = gcnew CommandSlots(m_pPackages);

                slots->ShowDialog(this);
        }

        void MainGui::EditGlobalsDialog()
        {
                if ( m_pPackages->IsVanilla() ) {
                        this->DisplayMessageBox(false, "Edit Globals", "Currently in Vanilla Mode, Cant change globals without being modified\n\nSwitch to modified mode if you wish to edit globals", MessageBoxButtons::OK, MessageBoxIcon::Question);
                        return;
                }
                if ( m_bDirLocked ) {
                        this->DisplayLocked(false);
                        return;
                }

                //load globals
                Utils::WStringList globals;
                m_pPackages->readGlobals(globals);

                EditGlobals ^edit = gcnew EditGlobals(&globals);

                // make our saved changes
                auto& packageGlobals = m_pPackages->getGlobals();
                for(auto itr = packageGlobals.begin(); itr != packageGlobals.end(); itr++)
                        edit->SetEditedItem(_US((*itr)->str), _US((*itr)->data));

                if ( edit->ShowDialog(this) == Windows::Forms::DialogResult::OK )
                {
                        // compare whats different and save
                        packageGlobals.clear();
                        for (auto itr = edit->GetSavedSettings()->begin(); itr != edit->GetSavedSettings()->end(); itr++)
                                packageGlobals.pushBack((*itr)->str, (*itr)->data);
                }
        }

        void MainGui::ViewFileLog()
        {
                if ( m_pFileErrors->empty() )
                        MessageBox::Show(this, "No messages to view in file log", "Empty File Log", MessageBoxButtons::OK, MessageBoxIcon::Warning);
                else
                {
                        FileLog ^log = gcnew FileLog;
                        for(auto itr = m_pFileErrors->begin(); itr != m_pFileErrors->end(); itr++)
                        {
                                bool add = true;
                                String ^status = "Unknown Error";
                                switch((*itr)->data.token(L" ", 1).toInt())
                                {
                                        case SPKINSTALL_CREATEDIRECTORY:
                                                status = "Created Directory";
                                                break;
                                        case SPKINSTALL_CREATEDIRECTORY_FAIL:
                                                status = "Failed to create Directory";
                                                break;
                                        case SPKINSTALL_WRITEFILE:
                                                status = "File Written";
                                                break;
                                        case SPKINSTALL_WRITEFILE_FAIL:
                                                status = "Failed to Write File";
                                                break;
                                        case SPKINSTALL_DELETEFILE:
                                                status = "Deleted File";
                                                break;
                                        case SPKINSTALL_DELETEFILE_FAIL:
                                                status = "Failed to Delete File";
                                                break;
                                        case SPKINSTALL_SKIPFILE:
                                                status = "File Skipped";
                                                break;
                                        case SPKINSTALL_REMOVEDIR:
                                                status = "Removed Directory";
                                                break;
                                        case SPKINSTALL_ENABLEFILE:
                                                status = "Enabled File";
                                                break;
                                        case SPKINSTALL_DISABLEFILE:
                                                status = "Disabled File";
                                                break;
                                        case SPKINSTALL_ENABLEFILE_FAIL:
                                                status = "Failed to Enable File";
                                                break;
                                        case SPKINSTALL_DISABLEFILE_FAIL:
                                                status = "Failed to Disable File";
                                                break;
                                        case SPKINSTALL_UNINSTALL_MOVE:
                                                status = "Moved Uninstall File";
                                                break;
                                        case SPKINSTALL_UNINSTALL_COPY:
                                                status = "Copied Uninstall File";
                                                break;
                                        case SPKINSTALL_UNINSTALL_MOVE_FAIL:
                                                status = "Failed to move uninstall file";
                                                break;
                                        case SPKINSTALL_UNINSTALL_COPY_FAIL:
                                                status = "Failed to copy uninstall file";
                                                break;
                                        case SPKINSTALL_UNINSTALL_REMOVE:
                                                status = "Removed uninstall file";
                                                break;
                                        case SPKINSTALL_UNINSTALL_REMOVE_FAIL:
                                                status = "Failed to remove uninstall file";
                                                break;
                                        case SPKINSTALL_ORIGINAL_BACKUP:
                                                status = "Backed up Original";
                                                break;
                                        case SPKINSTALL_ORIGINAL_RESTORE:
                                                status = "Restored Original";
                                                break;
                                        case SPKINSTALL_ORIGINAL_BACKUP_FAIL:
                                                status = "Failed to Backup Original";
                                                break;
                                        case SPKINSTALL_ORIGINAL_RESTORE_FAIL:
                                                status = "Failed to restore Original";
                                                break;
                                        case SPKINSTALL_FAKEPATCH:
                                                status = "Adjusting Fakepatch";
                                                break;
                                        case SPKINSTALL_FAKEPATCH_FAIL:
                                                status = "Failed to adjust Fakepatch";
                                                break;
                                        case SPKINSTALL_AUTOTEXT:
                                                status = "Adjusting Text File";
                                                break;
                                        case SPKINSTALL_AUTOTEXT_FAIL:
                                                status = "Failed to adjust Text File";
                                                break;
                                        case SPKINSTALL_MISSINGFILE:
                                                status = "Missing File";
                                                break;
                                        case SPKINSTALL_SHARED:
                                                status = "Shared File";
                                                break;
                                        case SPKINSTALL_SHARED_FAIL:
                                                status = "Shared File Failed";
                                                break;
                                        case SPKINSTALL_ORPHANED:
                                                status = "File Orphaned";
                                                break;
                                        case SPKINSTALL_ORPHANED_FAIL:
                                                status = "Failed to Orphan file";
                                                break;
                                        case SPKINSTALL_UNCOMPRESS_FAIL:
                                                status = "Failed to Uncompress";
                                                break;
                                }

                                if ( add )
                                {
                                        if ((*itr)->data.countToken(L" ") > 1 )
                                                log->AddItem(_US((*itr)->str.findReplace(L"~", L" => ")), status, _US(SPK::ConvertTimeString((long)(*itr)->data.token(L" ", 2).toLong())));
                                        else
                                                log->AddItem(_US((*itr)->str.findReplace(L"~", L" => ")), status, nullptr);
                                }
                        }
                        if ( log->ShowDialog(this) == Windows::Forms::DialogResult::Cancel )
                        {
                                if ( MessageBox::Show(this, "Are you sure you want to clear the file log?", "Clear File Log", MessageBoxButtons::YesNo, MessageBoxIcon::Question) == Windows::Forms::DialogResult::Yes )
                                {
                                        m_pFileErrors->clear();
                                        MessageBox::Show(this, "The file log has been cleared", "File Log Cleared", MessageBoxButtons::OK, MessageBoxIcon::Information);
                                }
                        }

                }
        }

        void MainGui::VerifyInstalledFiles()
        {
                Utils::WStringList missing;
                int amount = m_pPackages->verifyInstalledFiles(&missing);
                if ( !amount )
                        MessageBox::Show(this, "All files are currently installed", "Verifying Installed Files", MessageBoxButtons::OK, MessageBoxIcon::Information);
                else
                {
                        String ^text;
                        for(auto itr = missing.begin(); itr != missing.end(); itr++)
                        {
                                text += _US((*itr)->str);
                                text += "\n\t";
                                text += _US((*itr)->data.findReplace(L"\n", L"\t\n"));
                                text += "\n\n";
                        }
                        MessageBoxDetails::Show(this, "Verifing Installed Files", "Missing files detected\nAmount = " + amount, text, false, 600);
                }
        }

        void MainGui::ExportPackageList()
        {
                bool enabled = false;
                if ( MessageBox::Show(this, "Do you only want to export enabled packages?", "Only Enabled", MessageBoxButtons::YesNo, MessageBoxIcon::Question) == Windows::Forms::DialogResult::Yes )
                        enabled =true;
                SaveFileDialog ^ofd = gcnew SaveFileDialog();
                ofd->Filter = "Log Files (*.log)|*.log";
                ofd->FilterIndex = 1;
                ofd->RestoreDirectory = true;
                ofd->AddExtension =  true;
                ofd->Title = "Select the file to save the package list to";
                if ( ofd->ShowDialog(this) == Windows::Forms::DialogResult::OK )
                {
                        if ( IO::File::Exists(ofd->FileName) )
                                IO::File::Delete(ofd->FileName);
                        
                        StreamWriter ^sw = File::CreateText(ofd->FileName);
                        try 
                        {
                                for ( CBaseFile *package = m_pPackages->FirstPackage(); package; package = m_pPackages->NextPackage() )
                                {
                                        if ( enabled && !package->IsEnabled() ) continue;
                                        Utils::WString line = package->name() + L" :: " + package->author() + L" :: " + package->version() + L" :: " + package->creationDate() + L" :: ";
                                                
                                        if ( package->GetType() == TYPE_XSP )
                                                line += L"Ship :: ";
                                        else if ( package->GetType() == TYPE_ARCHIVE )
                                                line += L"- Archive - :: ";
                                        else if ( package->GetType() == TYPE_SPK ) {
                                                Utils::WString type = ((CSpkFile *)package)->scriptTypeString(m_pPackages->GetLanguage());
                                                if ( !type.empty() ) line += type + L" :: ";
                                        }

                                        line = line + ((package->IsEnabled()) ? L"Yes" : L"No") + L" :: " + ((package->IsSigned()) ? L"Yes" : L"No");
                                        sw->WriteLine(_US(line));
                                }
                        }
                        finally
                        {
                                if ( sw )
                                        delete (IDisposable ^)sw;
                        }                               

                        if ( IO::File::Exists(ofd->FileName) )
                        {
                                if ( enabled )
                                        MessageBox::Show(this, "Enabled Packages have been saved to:\n" + ofd->FileName, "Package List Saved", MessageBoxButtons::OK, MessageBoxIcon::Information);
                                else
                                        MessageBox::Show(this, "Complete Package List has been saved to:\n" + ofd->FileName, "Package List Saved", MessageBoxButtons::OK, MessageBoxIcon::Information);
                        }
                        else
                                MessageBox::Show(this, "There was an error writing file:\n" + ofd->FileName, "File Write Error", MessageBoxButtons::OK, MessageBoxIcon::Error);
                }
        }
        System::Void MainGui::MainGui_Shown(System::Object^  sender, System::EventArgs^  e)
        {
                if (m_pDirList->empty())
                {
                        if (MessageBox::Show(this, "You currently have no directories added, would you like to add them now?", "No Game Directories", MessageBoxButtons::YesNo, MessageBoxIcon::Question) == Windows::Forms::DialogResult::Yes)
                                this->OpenDirectoryControl();
                }
        }
        
        System::Void MainGui::MainGui_Load(System::Object^  sender, System::EventArgs^  e)
        {
                
                if ( m_iSaveGameManager == -1 )
                {
                        m_iSaveGameManager = 0;
                        /*
                        if ( MessageBox::Show(this, "The save game manager will keep seperate save games for each directory and keeps vanilla and modified save games seperate\n\nDo you want to enable the save game manager?", "Save Game Manager", MessageBoxButtons::YesNo, MessageBoxIcon::Question) == Windows::Forms::DialogResult::Yes )
                        {
                                m_iSaveGameManager = 1;
                                this->PrepareSaveGameManager();
                        }
                        else
                                m_iSaveGameManager = 0;
                        */
                }
                m_pMenuBar->SetSaveGameManager((m_iSaveGameManager == 1) ? true : false);

                // auto update
                if (m_iSizeX != -1 && m_iSizeY != -1)
                        this->Size = System::Drawing::Size(m_iSizeX, m_iSizeY);

                this->UpdateBuiltInPackages();
                this->AutoUpdate();
        }
        System::Void MainGui::viewModSelectedToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e)
        {               
                this->OpenModSelecter();
        }
}