/*
* This file is part of Code::Blocks Studio, an open-source cross-platform IDE
* Copyright (C) 2003  Yiannis An. Mandravellos
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* Contact e-mail: Yiannis An. Mandravellos <mandrav@codeblocks.org>
* Program URL   : http://www.codeblocks.org
*
* $Id: compileroptionsdlg.cpp,v 1.43.2.1 2005/10/25 07:59:01 mandrav Exp $
* $Date: 2005/10/25 07:59:01 $
*/

#include <sdk.h>
#include "compileroptionsdlg.h"
#include "compilergcc.h"
#include "advancedcompileroptionsdlg.h"
#include <wx/xrc/xmlres.h>
#include <manager.h>
#include <configmanager.h>
#include <messagemanager.h>
#include <projectmanager.h>
#include <customvars.h>
#include "editpathdlg.h"

BEGIN_EVENT_TABLE(CompilerOptionsDlg, wxDialog)
    EVT_UPDATE_UI(			XRCID("btnEditDir"),	    CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnDelDir"),	        CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("spnDirs"),	        CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnEditVar"),		CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnDeleteVar"),		CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("cmbCompilerPolicy"),	CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("cmbLinkerPolicy"),	CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("cmbIncludesPolicy"),	CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("cmbLibDirsPolicy"),	CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnSetDefaultCompiler"),	CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnAddCompiler"),	CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnRenameCompiler"),	CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnDelCompiler"),	CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnResetCompiler"),	CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnAddLib"),	        CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnEditLib"),	    CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnDelLib"),	        CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("spnLibs"),	        CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("txtMasterPath"),		CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnMasterPath"),		CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnExtraAdd"),	    CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnExtraEdit"),	    CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnExtraDelete"),	CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("txtCcompiler"),		CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnCcompiler"),		CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("txtCPPcompiler"),	CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnCPPcompiler"),	CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("txtLinker"),			CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnLinker"),			CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("txtLibLinker"),		CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnLibLinker"),		CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("txtDebugger"),		CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnDebugger"),		CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("txtResComp"),		CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnResComp"),		CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("txtMake"),			CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("btnMake"),			CompilerOptionsDlg::OnUpdateUI)
    EVT_UPDATE_UI(			XRCID("cmbCompiler"),		CompilerOptionsDlg::OnUpdateUI)
    //
	EVT_TREE_SEL_CHANGED(	XRCID("tcScope"),			CompilerOptionsDlg::OnTreeSelectionChange)
	EVT_TREE_SEL_CHANGING(	XRCID("tcScope"),			CompilerOptionsDlg::OnTreeSelectionChanging)
	EVT_COMBOBOX(			XRCID("cmbCategory"), 		CompilerOptionsDlg::OnCategoryChanged)
	EVT_COMBOBOX(			XRCID("cmbCompiler"), 		CompilerOptionsDlg::OnCompilerChanged)
	EVT_LISTBOX_DCLICK(		XRCID("lstVars"),			CompilerOptionsDlg::OnEditVarClick)
	EVT_BUTTON(				XRCID("btnSetDefaultCompiler"),	CompilerOptionsDlg::OnSetDefaultCompilerClick)
	EVT_BUTTON(				XRCID("btnAddCompiler"),	CompilerOptionsDlg::OnAddCompilerClick)
	EVT_BUTTON(				XRCID("btnRenameCompiler"),	CompilerOptionsDlg::OnEditCompilerClick)
	EVT_BUTTON(				XRCID("btnDelCompiler"),	CompilerOptionsDlg::OnRemoveCompilerClick)
	EVT_BUTTON(				XRCID("btnResetCompiler"),	CompilerOptionsDlg::OnResetCompilerClick)
	EVT_BUTTON(				XRCID("btnAddDir"),	        CompilerOptionsDlg::OnAddDirClick)
	EVT_BUTTON(				XRCID("btnEditDir"),	    CompilerOptionsDlg::OnEditDirClick)
	EVT_BUTTON(				XRCID("btnDelDir"),	        CompilerOptionsDlg::OnRemoveDirClick)
    EVT_BUTTON(			    XRCID("btnAddLib"),	        CompilerOptionsDlg::OnAddLibClick)
    EVT_BUTTON(			    XRCID("btnEditLib"),	    CompilerOptionsDlg::OnEditLibClick)
    EVT_BUTTON(			    XRCID("btnDelLib"),	        CompilerOptionsDlg::OnRemoveLibClick)
    EVT_BUTTON(			    XRCID("btnExtraAdd"),	    CompilerOptionsDlg::OnAddExtraPathClick)
    EVT_BUTTON(			    XRCID("btnExtraEdit"),	    CompilerOptionsDlg::OnEditExtraPathClick)
    EVT_BUTTON(			    XRCID("btnExtraDelete"),	CompilerOptionsDlg::OnRemoveExtraPathClick)
    EVT_SPIN_UP(			XRCID("spnLibs"),	        CompilerOptionsDlg::OnMoveLibUpClick)
    EVT_SPIN_DOWN(			XRCID("spnLibs"),	        CompilerOptionsDlg::OnMoveLibDownClick)
    EVT_SPIN_UP(			XRCID("spnDirs"),	        CompilerOptionsDlg::OnMoveDirUpClick)
    EVT_SPIN_DOWN(			XRCID("spnDirs"),	        CompilerOptionsDlg::OnMoveDirDownClick)
	EVT_BUTTON(				XRCID("btnAddVar"),			CompilerOptionsDlg::OnAddVarClick)
	EVT_BUTTON(				XRCID("btnEditVar"),		CompilerOptionsDlg::OnEditVarClick)
	EVT_BUTTON(				XRCID("btnDeleteVar"),		CompilerOptionsDlg::OnRemoveVarClick)
	EVT_BUTTON(				XRCID("btnMasterPath"),		CompilerOptionsDlg::OnMasterPathClick)
	EVT_BUTTON(				XRCID("btnAutoDetect"),		CompilerOptionsDlg::OnAutoDetectClick)
	EVT_BUTTON(				XRCID("btnCcompiler"),		CompilerOptionsDlg::OnSelectProgramClick)
	EVT_BUTTON(				XRCID("btnCPPcompiler"),	CompilerOptionsDlg::OnSelectProgramClick)
	EVT_BUTTON(				XRCID("btnLinker"),		    CompilerOptionsDlg::OnSelectProgramClick)
	EVT_BUTTON(				XRCID("btnLibLinker"),		CompilerOptionsDlg::OnSelectProgramClick)
	EVT_BUTTON(				XRCID("btnDebugger"),		CompilerOptionsDlg::OnSelectProgramClick)
	EVT_BUTTON(				XRCID("btnResComp"),		CompilerOptionsDlg::OnSelectProgramClick)
	EVT_BUTTON(				XRCID("btnMake"),		    CompilerOptionsDlg::OnSelectProgramClick)
	EVT_BUTTON(				XRCID("btnAdvanced"),		CompilerOptionsDlg::OnAdvancedClick)
	EVT_CHAR_HOOK(CompilerOptionsDlg::OnMyCharHook)
END_EVENT_TABLE()

CompilerOptionsDlg::CompilerOptionsDlg(wxWindow* parent, CompilerGCC* compiler, cbProject* project, ProjectBuildTarget* target)
	: m_Compiler(compiler),
	m_InitialCompilerIdx(0),
	m_pProject(project),
	m_pTarget(target),
	m_BuildingTree(false)
{
	wxXmlResource::Get()->LoadDialog(this, parent, _T("dlgCompilerOptions"));

	DoFillCompilerSets();
	DoFillCompilerPrograms();
	DoFillOthers();
	DoFillCategories();
	DoFillTree(project, target);
	DoFillVars();

    wxTreeCtrl* tree = XRCCTRL(*this, "tcScope", wxTreeCtrl);
    wxSizer* sizer = tree->GetContainingSizer();
    if (!project)
    {
        // global settings
        SetTitle(_("Compiler Settings"));
        sizer->Show(tree,false);
        sizer->Remove(tree);
        wxNotebook* nb = XRCCTRL(*this, "nbMain", wxNotebook);
        nb->DeletePage(3); // remove "Commands" page
	}
	else
	{
        m_InitialCompilerIdx = project->GetCompilerIndex();
        // project settings
        SetTitle(_("Project's Build options"));

        wxNotebook* nb = XRCCTRL(*this, "nbMain", wxNotebook);
        nb->DeletePage(6); // remove "Other" page
        nb->DeletePage(4); // remove "Programs" page

        // remove "Compiler" buttons
        wxWindow* win = XRCCTRL(*this, "btnAddCompiler", wxButton);
        wxSizer* sizer2 = win->GetContainingSizer();
        sizer2->Clear(true);
        sizer2->RecalcSizes();
        sizer2->Layout();
    }
    sizer->Layout();
    Layout();
    GetSizer()->Layout();
    GetSizer()->SetSizeHints(this);
    this->SetSize(-1, -1, 0, 0);
    this->CenterOnScreen();
}

CompilerOptionsDlg::~CompilerOptionsDlg()
{
	//dtor
}

void CompilerOptionsDlg::DoFillCompilerSets()
{
    wxComboBox* cmb = XRCCTRL(*this, "cmbCompiler", wxComboBox);
    cmb->Clear();
    for (unsigned int i = 0; i < CompilerFactory::Compilers.GetCount(); ++i)
    {
        cmb->Append(CompilerFactory::Compilers[i]->GetName());
    }

	int compilerIdx = CompilerFactory::GetDefaultCompilerIndex();
    if (m_pTarget)
        compilerIdx = m_pTarget->GetCompilerIndex();
    else if (m_pProject)
        compilerIdx = m_pProject->GetCompilerIndex();

	if (!CompilerFactory::CompilerIndexOK(compilerIdx))
        compilerIdx = 0;
    m_Options = CompilerFactory::Compilers[compilerIdx]->GetOptions();
    cmb->SetSelection(compilerIdx);
    m_LastCompilerIdx = compilerIdx;
}

void CompilerOptionsDlg::DoFillCompilerPrograms()
{
    if (m_pProject)
        return; // no "Programs" page

    int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
/*
//    Manager::Get()->GetMessageManager()->DebugLog("compilerIdx=%d, m_LastCompilerIdx=%d", compilerIdx, m_LastCompilerIdx);
    if (compilerIdx != m_LastCompilerIdx)
    {
        // compiler changed; check for changes and update as needed
        DoSaveCompilerPrograms();
    }
    m_LastCompilerIdx = compilerIdx;
*/
    const CompilerPrograms& progs = CompilerFactory::Compilers[compilerIdx]->GetPrograms();

    XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->SetValue(CompilerFactory::Compilers[compilerIdx]->GetMasterPath());
    XRCCTRL(*this, "txtCcompiler", wxTextCtrl)->SetValue(progs.C);
    XRCCTRL(*this, "txtCPPcompiler", wxTextCtrl)->SetValue(progs.CPP);
    XRCCTRL(*this, "txtLinker", wxTextCtrl)->SetValue(progs.LD);
    XRCCTRL(*this, "txtLibLinker", wxTextCtrl)->SetValue(progs.LIB);
    XRCCTRL(*this, "txtDebugger", wxTextCtrl)->SetValue(progs.DBG);
    XRCCTRL(*this, "txtResComp", wxTextCtrl)->SetValue(progs.WINDRES);
    XRCCTRL(*this, "txtMake", wxTextCtrl)->SetValue(progs.MAKE);

    XRCCTRL(*this, "lstExtraPaths", wxListBox)->Clear();
    const wxArrayString& extraPaths = CompilerFactory::Compilers[compilerIdx]->GetExtraPaths();
    for (unsigned int i = 0; i < extraPaths.GetCount(); ++i)
    {
        XRCCTRL(*this, "lstExtraPaths", wxListBox)->Append(extraPaths[i]);
    }
}

void CompilerOptionsDlg::DoFillVars(CustomVars* vars)
{
	wxListBox* lst = XRCCTRL(*this, "lstVars", wxListBox);
	if (!lst)
        return;
	lst->Clear();
	if (!vars)
        vars = GetCustomVars();
    if (!vars)
        return;
	const VarsArray& varsarr = vars->GetVars();
	//Manager::Get()->GetMessageManager()->DebugLog("[0x%8.8x] Current var count is %d (0x%8.8x)", m_Compiler, vars.GetCount(), &vars);
	for (unsigned int i = 0; i < varsarr.GetCount(); ++i)
	{
		Var* v = &varsarr[i];
		if (!v->builtin)
		{
            wxString text = v->name + _T(" = ") + v->value;
            lst->Append(text, static_cast<void*>(v));
		}
	}
}

void CompilerOptionsDlg::DoFillOthers()
{
    wxTextCtrl* txt = XRCCTRL(*this, "txtConsoleShell", wxTextCtrl);
    if (txt)
    {
        txt->SetValue(ConfigManager::Get()->Read(_T("/compiler_gcc/console_shell"), DEFAULT_CONSOLE_SHELL));
#ifdef __WXMSW__
        // under win32, this option is not needed, so disable it
        txt->Enable(false);
#endif
    }
    wxSpinCtrl* spn = XRCCTRL(*this, "spnMaxErrors", wxSpinCtrl);
    if (spn)
    {
        spn->SetRange(0, 1000);
        spn->SetValue(ConfigManager::Get()->Read(_T("/compiler_gcc/max_reported_errors"), 50));
    }
}

void CompilerOptionsDlg::DoFillTree(cbProject* focusProject, ProjectBuildTarget* focusTarget)
{
	m_BuildingTree = true;
	wxTreeCtrl* tc = XRCCTRL(*this, "tcScope", wxTreeCtrl);
	tc->DeleteAllItems();

	wxTreeItemId root;
	ScopeTreeData* selected = 0L;
	wxTreeItemId selectedItem;

	if (!focusProject)
	{
        // global settings
        root = tc->AddRoot(_("Global options"), -1, -1);
        selectedItem = root;
    }
    else
    {
        // project settings
        ScopeTreeData* data = new ScopeTreeData(focusProject, 0L);
        root = tc->AddRoot(focusProject->GetTitle(), -1, -1, data);
        selectedItem = root;
        selected = data;
        for (int x = 0; x < focusProject->GetBuildTargetsCount(); ++x)
        {
            ProjectBuildTarget* target = focusProject->GetBuildTarget(x);
            data = new ScopeTreeData(focusProject, target);
            wxTreeItemId targetItem = tc->AppendItem(root, target->GetTitle(), -1, -1, data);
            if (target == focusTarget)
            {
                selected = data;
                selectedItem = targetItem;
            }
        }
    }
    tc->Expand(root);
    int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
    DoLoadOptions(compilerIdx, selected);
    tc->SelectItem(selectedItem);
    m_BuildingTree = false;
}

void CompilerOptionsDlg::DoFillCategories()
{
	wxComboBox* cmb = XRCCTRL(*this, "cmbCategory", wxComboBox);
	cmb->Clear();
	cmb->Append(_("<All categories>"));

	for (unsigned int i = 0; i < m_Options.GetCount(); ++i)
	{
		CompOption* copt = m_Options.GetOption(i);
		if (cmb->FindString(copt->category) == -1)
			cmb->Append(copt->category);
	}
	cmb->SetSelection(0);
}

void CompilerOptionsDlg::DoFillOptions()
{
	Disconnect(XRCID("lstCompilerOptions"), -1,
			wxEVT_COMMAND_CHECKLISTBOX_TOGGLED,
			(wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
			&CompilerOptionsDlg::OnOptionToggled);

	wxComboBox* cmb = XRCCTRL(*this, "cmbCategory", wxComboBox);
	wxString cat = cmb->GetValue();
	bool isAll = cmb->GetSelection() == 0;
	wxCheckListBox* list = XRCCTRL(*this, "lstCompilerOptions", wxCheckListBox);
	list->Clear();

	for (unsigned int i = 0; i < m_Options.GetCount(); ++i)
	{
		CompOption* copt = m_Options.GetOption(i);
		if (isAll || copt->category.Matches(cat))
		{
			list->Append(copt->name);
			list->Check(list->GetCount() - 1, copt->enabled);
//            Manager::Get()->GetMessageManager()->DebugLog("(FILL) option %s (0x%8.8x) %s", copt->option.c_str(), copt, copt->enabled ? "enabled" : "disabled");
		}
	}
	Connect(XRCID("lstCompilerOptions"), -1,
			wxEVT_COMMAND_CHECKLISTBOX_TOGGLED,
			(wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
			&CompilerOptionsDlg::OnOptionToggled);
}

void CompilerOptionsDlg::TextToOptions()
{
    // disable all options
	for (unsigned int n = 0; n < m_Options.GetCount(); ++n)
	{
        CompOption* copt = m_Options.GetOption(n);
        if (copt)
            copt->enabled = false;
	}

	wxString rest;

    int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
    Compiler* compiler = CompilerFactory::Compilers[compilerIdx];

	XRCCTRL(*this, "txtCompilerDefines", wxTextCtrl)->Clear();
	unsigned int i = 0;
	while (i < m_CompilerOptions.GetCount())
	{
		wxString opt = m_CompilerOptions.Item(i);
		opt.Trim(wxString::both);
		CompOption* copt = m_Options.GetOptionByOption(opt);
		if (copt)
		{
//            Manager::Get()->GetMessageManager()->DebugLog("Enabling option %s", copt->option.c_str());
			copt->enabled = true;
			m_CompilerOptions.RemoveAt(i, 1);
		}
		else if (opt.StartsWith(compiler->GetSwitches().defines, &rest))
		{
			// definition
			XRCCTRL(*this, "txtCompilerDefines", wxTextCtrl)->AppendText(rest);
			XRCCTRL(*this, "txtCompilerDefines", wxTextCtrl)->AppendText(_T("\n"));
			m_CompilerOptions.RemoveAt(i, 1);
		}
		else
			++i;
	}
	i = 0;
	while (i < m_LinkerOptions.GetCount())
	{
		wxString opt = m_LinkerOptions.Item(i);
		opt.Trim(wxString::both);
		CompOption* copt = m_Options.GetOptionByAdditionalLibs(opt);
		if (copt)
		{
//            Manager::Get()->GetMessageManager()->DebugLog("Enabling option %s", copt->option.c_str());
			copt->enabled = true;
			m_LinkerOptions.RemoveAt(i, 1);
		}
		else
            ++i;
	}

	XRCCTRL(*this, "lstLibs", wxListBox)->Clear();
	for (i = 0; i < m_LinkLibs.GetCount(); ++i)
	{
        XRCCTRL(*this, "lstLibs", wxListBox)->Append(m_LinkLibs[i]);
	}
	m_LinkLibs.Clear();
}

void CompilerOptionsDlg::OptionsToText()
{
	wxArrayString array;
	DoGetCompileOptions(array, XRCCTRL(*this, "txtCompilerDefines", wxTextCtrl));

    int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
    Compiler* compiler = CompilerFactory::Compilers[compilerIdx];

	for (unsigned int i = 0; i < array.GetCount(); ++i)
	{
		if (!array[i].IsEmpty())
		{
			if (array[i].StartsWith(_T("-")))
			{
                if (m_CompilerOptions.Index(array[i]) == wxNOT_FOUND)
                    m_CompilerOptions.Add(array[i]);
            }
			else
			{
                if (m_CompilerOptions.Index(compiler->GetSwitches().defines + array[i]) == wxNOT_FOUND)
                    m_CompilerOptions.Add(compiler->GetSwitches().defines + array[i]);
            }
		}
	}

	for (unsigned int i = 0; i < m_Options.GetCount(); ++i)
	{
		CompOption* copt = m_Options.GetOption(i);
		if (copt->enabled)
		{
			m_CompilerOptions.Insert(copt->option, 0);
			if (!copt->additionalLibs.IsEmpty())
			{
                if (m_LinkerOptions.Index(copt->additionalLibs) == wxNOT_FOUND)
                    m_LinkerOptions.Insert(copt->additionalLibs, 0);
            }
        }
        else
        {
            // for disabled options, remove relative text option *and*
            // relative linker option
            int idx = m_CompilerOptions.Index(copt->option);
            if (idx != wxNOT_FOUND)
                m_CompilerOptions.RemoveAt(idx, 1);
            idx = m_LinkerOptions.Index(copt->additionalLibs);
            if (idx != wxNOT_FOUND)
                m_LinkerOptions.RemoveAt(idx, 1);
        }
	}

	// linker options and libs
	wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
	for (int i = 0; i < lstLibs->GetCount(); ++i)
        m_LinkLibs.Add(lstLibs->GetString(i));
}

void CompilerOptionsDlg::DoFillCompileOptions(const wxArrayString& array, wxTextCtrl* control)
{
	control->Clear();
	int count = array.GetCount();
	for (int i = 0; i < count; ++i)
	{
        if (!array[i].IsEmpty())
        {
            control->AppendText(array[i]);
            control->AppendText(_T('\n'));
        }
    }
}

void CompilerOptionsDlg::DoFillCompileDirs(const wxArrayString& array, wxListBox* control)
{
	control->Clear();
	int count = array.GetCount();
	for (int i = 0; i < count; ++i)
	{
        if (!array[i].IsEmpty())
            control->Append(array[i]);
    }
}

void CompilerOptionsDlg::DoGetCompileOptions(wxArrayString& array, wxTextCtrl* control)
{
/* NOTE (mandrav#1#): Under Gnome2, wxTextCtrl::GetLineLength() returns always 0,
                      so wxTextCtrl::GetLineText() is always empty...
                      Now, we 're breaking up by newlines. */    array.Clear();
#if 1
    wxString tmp = control->GetValue();
    int nl = tmp.Find(_T('\n'));
    wxString line;
    if (nl == -1)
    {
        line = tmp;
        tmp = _T("");
    }
    else
        line = tmp.Left(nl);
    while (nl != -1 || !line.IsEmpty())
    {
//        Manager::Get()->GetMessageManager()->DebugLog("%s text=%s", control->GetName().c_str(), line.c_str());
        if (!line.IsEmpty())
        {
            // just to make sure..
            line.Replace(_T("\r"), _T(" "), true); // remove CRs
            line.Replace(_T("\n"), _T(" "), true); // remove LFs
            array.Add(line.Strip(wxString::both));
        }
        tmp.Remove(0, nl + 1);
        nl = tmp.Find(_T('\n'));
        if (nl == -1)
        {
            line = tmp;
            tmp = _T("");
        }
        else
            line = tmp.Left(nl);
    }
#else
	int count = control->GetNumberOfLines();
	for (int i = 0; i < count; ++i)
	{
        wxString tmp = control->GetLineText(i);
        if (!tmp.IsEmpty())
        {
            tmp.Replace(_T("\r"), _T(" "), true); // remove CRs
            tmp.Replace(_T("\n"), _T(" "), true); // remove LFs
            array.Add(tmp.Strip(wxString::both));
        }
    }
#endif
}

void CompilerOptionsDlg::DoGetCompileDirs(wxArrayString& array, wxListBox* control)
{
    array.Clear();
	int count = control->GetCount();
	for (int i = 0; i < count; ++i)
	{
        wxString tmp = control->GetString(i);
        if (!tmp.IsEmpty())
            array.Add(tmp);
    }
}

void CompilerOptionsDlg::DoLoadOptions(int compilerIdx, ScopeTreeData* data)
{
	if (!data)
	{
		// global options
        Compiler* compiler = CompilerFactory::Compilers[compilerIdx];

		m_IncludeDirs = compiler->GetIncludeDirs();
		m_ResDirs = compiler->GetResourceIncludeDirs();
		m_LibDirs = compiler->GetLibDirs();
		m_CompilerOptions = compiler->GetCompilerOptions();
		m_LinkerOptions = compiler->GetLinkerOptions();
		m_LinkLibs = compiler->GetLinkLibs();
		m_CommandsAfterBuild = compiler->GetCommandsAfterBuild();
		m_CommandsBeforeBuild = compiler->GetCommandsBeforeBuild();
		m_AlwaysUsePre = compiler->GetAlwaysRunPreBuildSteps();
		m_AlwaysUsePost = compiler->GetAlwaysRunPostBuildSteps();

        wxComboBox* cmb = XRCCTRL(*this, "cmbLogging", wxComboBox);
        if (cmb)
            cmb->SetSelection((int)compiler->GetSwitches().logging);
        cmb = XRCCTRL(*this, "cmbBuildMethod", wxComboBox);
        if (cmb)
            cmb->SetSelection((int)compiler->GetSwitches().buildMethod);
	}
	else
	{
		if (!data->GetTarget())
		{
			// project options
			m_pTarget = 0;
			cbProject* project = data->GetProject();
			m_IncludeDirs = project->GetIncludeDirs();
			m_ResDirs = project->GetResourceIncludeDirs();
			m_LibDirs = project->GetLibDirs();
			m_CompilerOptions = project->GetCompilerOptions();
			m_LinkerOptions = project->GetLinkerOptions();
			m_LinkLibs = project->GetLinkLibs();
			m_CommandsAfterBuild = project->GetCommandsAfterBuild();
			m_CommandsBeforeBuild = project->GetCommandsBeforeBuild();
			m_AlwaysUsePre = project->GetAlwaysRunPreBuildSteps();
			m_AlwaysUsePost = project->GetAlwaysRunPostBuildSteps();
		}
		else
		{
			// target options
			ProjectBuildTarget* target = data->GetTarget();
			m_pTarget = target;
			m_IncludeDirs = target->GetIncludeDirs();
			m_ResDirs = target->GetResourceIncludeDirs();
			m_LibDirs = target->GetLibDirs();
			m_CompilerOptions = target->GetCompilerOptions();
			m_LinkerOptions = target->GetLinkerOptions();
			m_LinkLibs = target->GetLinkLibs();
			m_CommandsAfterBuild = target->GetCommandsAfterBuild();
			m_CommandsBeforeBuild = target->GetCommandsBeforeBuild();
			m_AlwaysUsePre = target->GetAlwaysRunPreBuildSteps();
			m_AlwaysUsePost = target->GetAlwaysRunPostBuildSteps();
			XRCCTRL(*this, "cmbCompilerPolicy", wxComboBox)->SetSelection(target->GetOptionRelation(ortCompilerOptions));
			XRCCTRL(*this, "cmbLinkerPolicy", wxComboBox)->SetSelection(target->GetOptionRelation(ortLinkerOptions));
			XRCCTRL(*this, "cmbIncludesPolicy", wxComboBox)->SetSelection(target->GetOptionRelation(ortIncludeDirs));
			XRCCTRL(*this, "cmbLibDirsPolicy", wxComboBox)->SetSelection(target->GetOptionRelation(ortLibDirs));
			XRCCTRL(*this, "cmbResDirsPolicy", wxComboBox)->SetSelection(target->GetOptionRelation(ortResDirs));
		}
	}
	TextToOptions();

    DoFillVars();
	DoFillOptions();
	DoFillCompileDirs(m_IncludeDirs, XRCCTRL(*this, "lstIncludeDirs", wxListBox));
	DoFillCompileDirs(m_LibDirs, XRCCTRL(*this, "lstLibDirs", wxListBox));
	DoFillCompileDirs(m_ResDirs, XRCCTRL(*this, "lstResDirs", wxListBox));
	DoFillCompileOptions(m_CompilerOptions, XRCCTRL(*this, "txtCompilerOptions", wxTextCtrl));
	DoFillCompileOptions(m_LinkerOptions, XRCCTRL(*this, "txtLinkerOptions", wxTextCtrl));

    // only if "Commands" page exists
	if (XRCCTRL(*this, "txtCmdBefore", wxTextCtrl))
	{
        DoFillCompileOptions(m_CommandsBeforeBuild, XRCCTRL(*this, "txtCmdBefore", wxTextCtrl));
        DoFillCompileOptions(m_CommandsAfterBuild, XRCCTRL(*this, "txtCmdAfter", wxTextCtrl));
        XRCCTRL(*this, "chkAlwaysRunPre", wxCheckBox)->SetValue(m_AlwaysUsePre);
        XRCCTRL(*this, "chkAlwaysRunPost", wxCheckBox)->SetValue(m_AlwaysUsePost);
    }
}

void CompilerOptionsDlg::DoSaveOptions(int compilerIdx, ScopeTreeData* data)
{
    // only if "Commands" page exists
	if (XRCCTRL(*this, "txtCmdBefore", wxTextCtrl))
	{
        m_AlwaysUsePre = XRCCTRL(*this, "chkAlwaysRunPre", wxCheckBox)->GetValue();
        m_AlwaysUsePost = XRCCTRL(*this, "chkAlwaysRunPost", wxCheckBox)->GetValue();
        DoGetCompileOptions(m_CommandsBeforeBuild, XRCCTRL(*this, "txtCmdBefore", wxTextCtrl));
        DoGetCompileOptions(m_CommandsAfterBuild, XRCCTRL(*this, "txtCmdAfter", wxTextCtrl));
	}
	DoGetCompileDirs(m_IncludeDirs, XRCCTRL(*this, "lstIncludeDirs", wxListBox));
	DoGetCompileDirs(m_LibDirs, XRCCTRL(*this, "lstLibDirs", wxListBox));
	DoGetCompileDirs(m_ResDirs, XRCCTRL(*this, "lstResDirs", wxListBox));
	DoGetCompileOptions(m_CompilerOptions, XRCCTRL(*this, "txtCompilerOptions", wxTextCtrl));
	DoGetCompileOptions(m_LinkerOptions, XRCCTRL(*this, "txtLinkerOptions", wxTextCtrl));
    OptionsToText();

	if (!data)
	{
		// global options
        Compiler* compiler = CompilerFactory::Compilers[compilerIdx];

		compiler->SetIncludeDirs(m_IncludeDirs);
		compiler->SetLibDirs(m_LibDirs);
		compiler->SetResourceIncludeDirs(m_ResDirs);
		compiler->SetCompilerOptions(m_CompilerOptions);
		compiler->SetLinkerOptions(m_LinkerOptions);
		compiler->SetLinkLibs(m_LinkLibs);
		compiler->SetCommandsBeforeBuild(m_CommandsBeforeBuild);
		compiler->SetCommandsAfterBuild(m_CommandsAfterBuild);
		compiler->SetAlwaysRunPreBuildSteps(m_AlwaysUsePre);
		compiler->SetAlwaysRunPostBuildSteps(m_AlwaysUsePost);

        wxComboBox* cmb = XRCCTRL(*this, "cmbLogging", wxComboBox);
        if (cmb)
        {
            CompilerSwitches switches = compiler->GetSwitches();
            switches.logging = (CompilerLoggingType)cmb->GetSelection();
            compiler->SetSwitches(switches);
        }
        cmb = XRCCTRL(*this, "cmbBuildMethod", wxComboBox);
        if (cmb)
        {
            CompilerSwitches switches = compiler->GetSwitches();
            switches.buildMethod = (CompilerBuildMethod)cmb->GetSelection();
            compiler->SetSwitches(switches);
        }
	}
	else
	{
		if (!data->GetTarget())
		{
			// project options
			cbProject* project = data->GetProject();
			project->SetIncludeDirs(m_IncludeDirs);
			project->SetResourceIncludeDirs(m_ResDirs);
			project->SetLibDirs(m_LibDirs);
			project->SetCompilerOptions(m_CompilerOptions);
			project->SetLinkerOptions(m_LinkerOptions);
			project->SetLinkLibs(m_LinkLibs);
			project->SetCommandsBeforeBuild(m_CommandsBeforeBuild);
			project->SetCommandsAfterBuild(m_CommandsAfterBuild);
            project->SetAlwaysRunPreBuildSteps(m_AlwaysUsePre);
            project->SetAlwaysRunPostBuildSteps(m_AlwaysUsePost);
		}
		else
		{
			// target options
			ProjectBuildTarget* target = data->GetTarget();
			target->SetIncludeDirs(m_IncludeDirs);
			target->SetResourceIncludeDirs(m_ResDirs);
			target->SetLibDirs(m_LibDirs);
			target->SetCompilerOptions(m_CompilerOptions);
			target->SetLinkerOptions(m_LinkerOptions);
			target->SetLinkLibs(m_LinkLibs);
            target->SetOptionRelation(ortCompilerOptions, OptionsRelation(XRCCTRL(*this, "cmbCompilerPolicy", wxComboBox)->GetSelection()));
            target->SetOptionRelation(ortLinkerOptions, OptionsRelation(XRCCTRL(*this, "cmbLinkerPolicy", wxComboBox)->GetSelection()));
            target->SetOptionRelation(ortIncludeDirs, OptionsRelation(XRCCTRL(*this, "cmbIncludesPolicy", wxComboBox)->GetSelection()));
            target->SetOptionRelation(ortLibDirs, OptionsRelation(XRCCTRL(*this, "cmbLibDirsPolicy", wxComboBox)->GetSelection()));
            target->SetOptionRelation(ortResDirs, OptionsRelation(XRCCTRL(*this, "cmbResDirsPolicy", wxComboBox)->GetSelection()));
			target->SetCommandsBeforeBuild(m_CommandsBeforeBuild);
			target->SetCommandsAfterBuild(m_CommandsAfterBuild);
            target->SetAlwaysRunPreBuildSteps(m_AlwaysUsePre);
            target->SetAlwaysRunPostBuildSteps(m_AlwaysUsePost);
		}
	}
}

void CompilerOptionsDlg::DoMakeRelative(wxFileName& path)
{
    // NOTE: this function is not currently used

	wxTreeCtrl* tc = XRCCTRL(*this, "tcScope", wxTreeCtrl);
	ScopeTreeData* data = (ScopeTreeData*)tc->GetItemData(tc->GetSelection());
	if (data && data->GetProject())
	{
        path.MakeRelativeTo(data->GetProject()->GetBasePath());
    }
}

void CompilerOptionsDlg::DoSaveCompilerPrograms(int compilerIdx)
{
    if (m_pProject || // no "Programs" page
        !CompilerFactory::CompilerIndexOK(compilerIdx))
    {
        return;
    }
    CompilerPrograms progs;
    wxString masterPath = XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->GetValue();
    progs.C = XRCCTRL(*this, "txtCcompiler", wxTextCtrl)->GetValue();
    progs.CPP = XRCCTRL(*this, "txtCPPcompiler", wxTextCtrl)->GetValue();
    progs.LD = XRCCTRL(*this, "txtLinker", wxTextCtrl)->GetValue();
    progs.LIB = XRCCTRL(*this, "txtLibLinker", wxTextCtrl)->GetValue();
    progs.WINDRES = XRCCTRL(*this, "txtResComp", wxTextCtrl)->GetValue();
    progs.MAKE = XRCCTRL(*this, "txtMake", wxTextCtrl)->GetValue();
    progs.DBG = XRCCTRL(*this, "txtDebugger", wxTextCtrl)->GetValue();
    CompilerFactory::Compilers[compilerIdx]->SetPrograms(progs);
    CompilerFactory::Compilers[compilerIdx]->SetMasterPath(masterPath);
    CompilerFactory::Compilers[compilerIdx]->SetOptions(m_Options);
}

// events

void CompilerOptionsDlg::OnTreeSelectionChange(wxTreeEvent& event)
{
	if (m_BuildingTree)
		return;
	wxTreeCtrl* tc = XRCCTRL(*this, "tcScope", wxTreeCtrl);
	ScopeTreeData* data = (ScopeTreeData*)tc->GetItemData(event.GetItem());
	if (!data)
        return;
    int compilerIdx = data->GetTarget() ? data->GetTarget()->GetCompilerIndex() :
                        (data->GetProject() ? data->GetProject()->GetCompilerIndex() :
                        XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection());
    XRCCTRL(*this, "cmbCompiler", wxComboBox)->SetSelection(compilerIdx);
    CompilerChanged(data);
    m_pTarget = data->GetTarget();
//	DoLoadOptions(compilerIdx, data);
}

void CompilerOptionsDlg::OnTreeSelectionChanging(wxTreeEvent& event)
{
	if (m_BuildingTree)
		return;
	wxTreeCtrl* tc = XRCCTRL(*this, "tcScope", wxTreeCtrl);
	ScopeTreeData* data = (ScopeTreeData*)tc->GetItemData(event.GetOldItem());
	if (!data)
        return;
    int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
	DoSaveOptions(compilerIdx, data);
}

void CompilerOptionsDlg::OnCompilerChanged(wxCommandEvent& event)
{
	wxTreeCtrl* tc = XRCCTRL(*this, "tcScope", wxTreeCtrl);
	ScopeTreeData* data = tc ? (ScopeTreeData*)tc->GetItemData(tc->GetSelection()) : 0;
	DoSaveCompilerPrograms(m_LastCompilerIdx);
	DoSaveOptions(m_LastCompilerIdx, data);
    CompilerChanged(data);
}

void CompilerOptionsDlg::CompilerChanged(ScopeTreeData* data)
{
    int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();

    if (data)
    {
        if (data->GetTarget())
             data->GetTarget()->SetCompilerIndex(compilerIdx);
        else if (data->GetProject())
            data->GetProject()->SetCompilerIndex(compilerIdx);
    }
    else if (m_pProject)
        m_pProject->SetCompilerIndex(compilerIdx);

    m_Options = CompilerFactory::Compilers[compilerIdx]->GetOptions();
    DoFillCompilerPrograms();
    DoFillCategories();
    DoFillOptions();

	if (m_BuildingTree)
		return;
	DoLoadOptions(compilerIdx, data);
	m_LastCompilerIdx = compilerIdx;

	// this relies on GetCustomVars(), which relies on m_LastCompilerIdx
	DoFillVars();
}

void CompilerOptionsDlg::UpdateCompilerForTargets(int compilerIdx)
{
    int ret = wxMessageBox(_("You have changed the compiler used for the project.\n"
                            "Do you want to use the same compiler for all the project's build targets too?"),
                            _("Question"),
                            wxICON_QUESTION | wxYES_NO);
    if (ret == wxYES)
    {
        for (int i = 0; i < m_pProject->GetBuildTargetsCount(); ++i)
        {
            ProjectBuildTarget* target = m_pProject->GetBuildTarget(i);
            target->SetCompilerIndex(compilerIdx);
        }
    }
}

void CompilerOptionsDlg::AutoDetectCompiler()
{
    wxComboBox* cmb = XRCCTRL(*this, "cmbCompiler", wxComboBox);
    int compilerIdx = cmb->GetSelection();
    Compiler* compiler = CompilerFactory::Compilers[compilerIdx];
    wxString backup = XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->GetValue();

    wxArrayString empty;
    compiler->SetExtraPaths(empty);

    switch (compiler->AutoDetectInstallationDir())
    {
        case adrDetected:
        {
            wxString msg;
            msg.Printf(_("Auto-detected installation path of \"%s\"\nin \"%s\""), compiler->GetName().c_str(), compiler->GetMasterPath().c_str());
            wxMessageBox(msg);
        }
        break;

        case adrGuessed:
        {
            wxString msg;
            msg.Printf(_("Could not auto-detect installation path of \"%s\"...\n"
                        "Do you want to use this compiler's default installation directory?"),
                        compiler->GetName().c_str());
            if (wxMessageBox(msg, _("Confirmation"), wxICON_QUESTION | wxYES_NO) == wxNO)
                compiler->SetMasterPath(backup);
        }
        break;
    }
    XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->SetValue(compiler->GetMasterPath());
    XRCCTRL(*this, "lstExtraPaths", wxListBox)->Clear();
    const wxArrayString& extraPaths = CompilerFactory::Compilers[compilerIdx]->GetExtraPaths();
    for (unsigned int i = 0; i < extraPaths.GetCount(); ++i)
    {
        XRCCTRL(*this, "lstExtraPaths", wxListBox)->Append(extraPaths[i]);
    }
}

wxListBox* CompilerOptionsDlg::GetDirsListBox()
{
    wxNotebook* nb = XRCCTRL(*this, "nbDirs", wxNotebook);
    if (!nb)
        return 0;
    switch (nb->GetSelection())
    {
        case 0: // compiler dirs
            return XRCCTRL(*this, "lstIncludeDirs", wxListBox);
        case 1: // linker dirs
            return XRCCTRL(*this, "lstLibDirs", wxListBox);
        case 2: // resource compiler dirs
            return XRCCTRL(*this, "lstResDirs", wxListBox);
        default: break;
    }
    return 0;
}

CustomVars* CompilerOptionsDlg::GetCustomVars()
{
	wxTreeCtrl* tc = XRCCTRL(*this, "tcScope", wxTreeCtrl);
    ScopeTreeData* data = tc ? (ScopeTreeData*)tc->GetItemData(tc->GetSelection()) : 0;
    CustomVars* vars = 0;
    if (!data)
        vars = GetCustomVars(0);
    else
    {
        if (data->GetTarget())
            vars = &data->GetTarget()->GetCustomVars();
        else
            vars = &m_pProject->GetCustomVars();
    }
    return vars;
}

CustomVars* CompilerOptionsDlg::GetCustomVars(CompileOptionsBase* base)
{
	if (base)
        return &base->GetCustomVars();
    Compiler* compiler = CompilerFactory::Compilers[m_LastCompilerIdx];
    return compiler ? &compiler->GetCustomVars() : 0;
}

void CompilerOptionsDlg::OnCategoryChanged(wxCommandEvent& event)
{
	DoFillOptions();
}

void CompilerOptionsDlg::OnOptionToggled(wxCommandEvent& event)
{
	wxCheckListBox* list = XRCCTRL(*this, "lstCompilerOptions", wxCheckListBox);
	int sel = event.GetInt();
	CompOption* copt = m_Options.GetOptionByName(list->GetString(sel));
	if (copt)
	{
		copt->enabled = list->IsChecked(sel);
//        Manager::Get()->GetMessageManager()->DebugLog("option %s (0x%8.8x) %s", copt->option.c_str(), copt, copt->enabled ? "enabled" : "disabled");
    }
}

void CompilerOptionsDlg::OnAddDirClick(wxCommandEvent& event)
{
    /*wxString path = ChooseDirectory(this,
                                    _("Select directory"),
                                    m_pProject ? m_pProject->GetBasePath() : "",
                                    m_pProject ? m_pProject->GetBasePath() : "",
                                    true,
                                    true);*/

    EditPathDlg dlg(this,
            m_pProject ? m_pProject->GetBasePath() : _T(""),
            m_pProject ? m_pProject->GetBasePath() : _T(""),
            _("Add directory"));

    if (dlg.ShowModal() == wxID_OK)
    {
        wxString path = dlg.GetPath();

        wxListBox* control = GetDirsListBox();
        if (control)
            control->Append(path);
    }
}

void CompilerOptionsDlg::OnEditDirClick(wxCommandEvent& event)
{
    wxListBox* control = GetDirsListBox();
    if (!control || control->GetSelection() < 0)
        return;

    wxFileName dir(control->GetString(control->GetSelection()) + wxFileName::GetPathSeparator());
//    if (m_pProject)
//        dir.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, m_pProject->GetBasePath());
//    Manager::Get()->GetMessageManager()->DebugLog(dir.GetFullPath());
    wxString initial = _T("");

    // This path may not exist, but if using EditPathDlg, you still want it
    // displayed
    initial = dir.GetPath(wxPATH_GET_VOLUME);

    /*wxString path = ChooseDirectory(this,
                                    _("Select directory"),
                                    initial,
                                    m_pProject ? m_pProject->GetBasePath() : "",
                                    true,
                                    true);*/

    EditPathDlg dlg(this,
            initial,
            m_pProject ? m_pProject->GetBasePath() : _T(""),
            _("Edit directory"));

    if (dlg.ShowModal() == wxID_OK)
    {
        wxString path = dlg.GetPath();

        control->SetString(control->GetSelection(), path);
    }
}

void CompilerOptionsDlg::OnRemoveDirClick(wxCommandEvent& event)
{
    wxListBox* control = GetDirsListBox();
    if (!control || control->GetSelection() < 0)
        return;
	if (wxMessageBox(_("Remove '")+control->GetStringSelection()+_("' from the list?"),
					_("Confirmation"),
					wxOK | wxCANCEL | wxICON_QUESTION) == wxOK)
	{
        control->Delete(control->GetSelection());
    }
}

void CompilerOptionsDlg::OnAddVarClick(wxCommandEvent& event)
{
	const wxString title = _("Add variable");
	wxString name = wxGetTextFromUser(_("Please enter the name for the new variable:"), title);
	if (name.IsEmpty())
		return;
	wxString value = wxGetTextFromUser(_("Please enter value for the new variable:"), title);
    CustomVars* vars = GetCustomVars();
    if (vars)
    {
        vars->Add(name, value);
        DoFillVars(vars);
    }
}

void CompilerOptionsDlg::OnEditVarClick(wxCommandEvent& event)
{
	const wxString title = _("Edit variable");
	int sel = XRCCTRL(*this, "lstVars", wxListBox)->GetSelection();
	if (sel == -1)
		return;

	Var* var = static_cast<Var*>(XRCCTRL(*this, "lstVars", wxListBox)->GetClientData(sel));
	if (!var)
		return;

	wxString value = wxGetTextFromUser(_("Please edit the variable value:"), title, var->value);
	if (!value.IsEmpty() && value != var->value)
	{
		var->value = value;
        CustomVars* vars = GetCustomVars();
        if (vars)
            vars->SetModified(true);
		XRCCTRL(*this, "lstVars", wxListBox)->SetString(sel, var->name + _T(" = ") + var->value);
	}
}

void CompilerOptionsDlg::OnRemoveVarClick(wxCommandEvent& event)
{
	int sel = XRCCTRL(*this, "lstVars", wxListBox)->GetSelection();
	if (sel == -1)
		return;
	if (wxMessageBox(_("Are you sure you want to delete this variable?"),
					_("Confirmation"),
					wxOK | wxCANCEL | wxICON_QUESTION) == wxOK)
	{
		Var* var = static_cast<Var*>(XRCCTRL(*this, "lstVars", wxListBox)->GetClientData(sel));
		if (var)
		{
            CustomVars* vars = GetCustomVars();
            if (vars)
            {
    			vars->DeleteVar(var);
                DoFillVars(vars);
            }
		}
	}
}

void CompilerOptionsDlg::OnSetDefaultCompilerClick(wxCommandEvent& event)
{
    wxComboBox* cmb = XRCCTRL(*this, "cmbCompiler", wxComboBox);
    int idx = cmb->GetSelection();
    CompilerFactory::SetDefaultCompilerIndex(idx);
    wxString msg;
    msg.Printf(_("%s is now selected as the default compiler for new projects"), CompilerFactory::GetDefaultCompiler()->GetName().c_str());
    wxMessageBox(msg);
}

void CompilerOptionsDlg::OnAddCompilerClick(wxCommandEvent& event)
{
    wxComboBox* cmb = XRCCTRL(*this, "cmbCompiler", wxComboBox);
    int idx = cmb->GetSelection();
	wxString value = wxGetTextFromUser(_("Please enter the new compiler's name:"), _("Add new compiler"), _("Copy of ") + CompilerFactory::Compilers[idx]->GetName());
	if (!value.IsEmpty())
	{
        // make a copy of current compiler
        int newIdx = CompilerFactory::CreateCompilerCopy(CompilerFactory::Compilers[idx]);
        Compiler* newC = CompilerFactory::Compilers[newIdx];
        // and change its name
        newC->SetName(value);

        cmb->Append(value);
        cmb->SetSelection(cmb->GetCount() - 1);
        // refresh settings in dialog
        DoFillCompilerPrograms();
        DoFillCategories();
        DoFillOptions();
        DoLoadOptions(newIdx, 0);
        m_LastCompilerIdx = newIdx;
        wxMessageBox(_("The new compiler has been added! Don't forget to update the \"Programs\" page..."));
    }
}

void CompilerOptionsDlg::OnEditCompilerClick(wxCommandEvent& event)
{
    wxComboBox* cmb = XRCCTRL(*this, "cmbCompiler", wxComboBox);
	wxString value = wxGetTextFromUser(_("Please edit the compiler's name:"), _("Rename compiler"), cmb->GetValue());
	if (!value.IsEmpty())
	{
        int idx = cmb->GetSelection();
        CompilerFactory::Compilers[idx]->SetName(value);
#ifndef __WXGTK__
        cmb->SetString(idx, value);
#else
	#warning wxComboBox::SetString() not implemented: CompilerOptionsDlg::OnEditCompilerClick() is not updating correctly...
#endif
        cmb->SetSelection(idx);
    }
}

void CompilerOptionsDlg::OnRemoveCompilerClick(wxCommandEvent& event)
{
	if (wxMessageBox(_("Are you sure you want to remove this compiler?"),
					_("Confirmation"),
					wxOK | wxCANCEL | wxICON_QUESTION | wxNO_DEFAULT) == wxOK)
    {
        wxComboBox* cmb = XRCCTRL(*this, "cmbCompiler", wxComboBox);
        int compilerIdx = cmb->GetSelection();
        CompilerFactory::RemoveCompiler(CompilerFactory::Compilers[compilerIdx]);
        cmb->Delete(compilerIdx);
        while (compilerIdx >= cmb->GetCount())
            --compilerIdx;
        cmb->SetSelection(compilerIdx);

        DoFillCompilerPrograms();
        DoFillCategories();
        DoFillOptions();
        m_LastCompilerIdx = compilerIdx;
        DoLoadOptions(compilerIdx, 0);
    }
}

void CompilerOptionsDlg::OnResetCompilerClick(wxCommandEvent& event)
{
	if (wxMessageBox(_("Reset this compiler's settings to the defaults?"),
					_("Confirmation"),
					wxOK | wxCANCEL | wxICON_QUESTION | wxNO_DEFAULT) == wxOK)
	if (wxMessageBox(_("Reset this compiler's settings to the defaults?\n"
	                   "\nAre you REALLY sure?"),
					_("Confirmation"),
					wxOK | wxCANCEL | wxICON_QUESTION | wxNO_DEFAULT) == wxOK)
    {
        wxComboBox* cmb = XRCCTRL(*this, "cmbCompiler", wxComboBox);
        int compilerIdx = cmb->GetSelection();
        CompilerFactory::Compilers[compilerIdx]->Reset();
        // run auto-detection
        AutoDetectCompiler();
        CompilerFactory::SaveSettings();
        // refresh settings in dialog
        DoFillCompilerPrograms();
        DoFillCategories();
        DoFillOptions();
        DoLoadOptions(compilerIdx, 0);
    }
}

void CompilerOptionsDlg::OnAddLibClick(wxCommandEvent& event)
{
    /*int compilerIdx = m_pTarget ? m_pTarget->GetCompilerIndex()
                                : (m_pProject ? m_pProject->GetCompilerIndex()
                                              : XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection());*/
    wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
    /*LinkLibDlg dlg(this, m_pProject, m_pTarget, CompilerFactory::Compilers[compilerIdx], "");*/

    EditPathDlg dlg(this,
            _T(""),
            m_pProject ? m_pProject->GetBasePath() : _T(""),
            _("Add library"),
            _("Choose library to link"),
            false,
            true,
            _("Library files (*.a, *.lib)|*.a;*.lib|All files (*)|*"));

    if (dlg.ShowModal() == wxID_OK)
    {
        wxArrayString paths = GetArrayFromString(dlg.GetPath());
        for (unsigned int i = 0; i < paths.GetCount(); ++i)
            lstLibs->Append(paths[i]);
    }
}

void CompilerOptionsDlg::OnEditLibClick(wxCommandEvent& event)
{
    /*int compilerIdx = m_pTarget ? m_pTarget->GetCompilerIndex()
                                : (m_pProject ? m_pProject->GetCompilerIndex()
                                              : XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection());*/
    wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);

    /*LinkLibDlg dlg(this, m_pProject, m_pTarget, CompilerFactory::Compilers[compilerIdx], lstLibs->GetStringSelection());*/

    EditPathDlg dlg(this,
            lstLibs->GetStringSelection(),
            m_pProject ? m_pProject->GetBasePath() : _T(""),
            _("Edit library"),
            _("Choose library to link"),
            false,
            false,
            _("Library files (*.a, *.lib)|*.a;*.lib|All files (*)|*"));

    if (dlg.ShowModal() == wxID_OK)
    {
        /*lstLibs->SetString(lstLibs->GetSelection(), dlg.GetLib());*/
        lstLibs->SetString(lstLibs->GetSelection(), dlg.GetPath());
    }
}

void CompilerOptionsDlg::OnRemoveLibClick(wxCommandEvent& event)
{
    wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
    if (!lstLibs || lstLibs->GetSelection() < 0)
        return;
    if (wxMessageBox(_("Remove library '")+lstLibs->GetStringSelection()+_("' from the list?"), _("Confirmation"), wxICON_QUESTION | wxOK | wxCANCEL) == wxOK)
        lstLibs->Delete(lstLibs->GetSelection());
}

void CompilerOptionsDlg::OnAddExtraPathClick(wxCommandEvent& event)
{
    wxString path = ChooseDirectory(this,
                                    _("Select directory"),
                                    _T(""),
                                    _T(""),
                                    true,
                                    true);
    if (path.IsEmpty())
        return;

    wxListBox* control = XRCCTRL(*this, "lstExtraPaths", wxListBox);
    if (control)
    {
        int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
        Compiler* compiler = CompilerFactory::Compilers[compilerIdx];
        wxArrayString extraPaths = CompilerFactory::Compilers[compilerIdx]->GetExtraPaths();
        if (extraPaths.Index(path) != wxNOT_FOUND)
        {
            wxMessageBox(_("Path already in extra paths list!"), _("Warning"), wxICON_WARNING);
            return;
        }
        extraPaths.Add(path);
        compiler->SetExtraPaths(extraPaths);
        control->Append(path);
    }
}

void CompilerOptionsDlg::OnEditExtraPathClick(wxCommandEvent& event)
{
    wxListBox* control = XRCCTRL(*this, "lstExtraPaths", wxListBox);
    if (!control || control->GetSelection() < 0)
        return;

    wxFileName dir(control->GetString(control->GetSelection()) + wxFileName::GetPathSeparator());
    wxString initial = _T("");
    if (dir.DirExists())
        initial = dir.GetPath(wxPATH_GET_VOLUME);

    wxString path = ChooseDirectory(this,
                                    _("Select directory"),
                                    initial,
                                    _T(""),
                                    true,
                                    true);
    if (path.IsEmpty())
        return;

    int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
    Compiler* compiler = CompilerFactory::Compilers[compilerIdx];
    wxArrayString extraPaths = CompilerFactory::Compilers[compilerIdx]->GetExtraPaths();
    if (extraPaths.Index(path) != wxNOT_FOUND)
    {
        wxMessageBox(_("Path already in extra paths list!"), _("Warning"), wxICON_WARNING);
        return;
    }
    extraPaths[control->GetSelection()] = path;
    compiler->SetExtraPaths(extraPaths);
    control->SetString(control->GetSelection(), path);
}

void CompilerOptionsDlg::OnRemoveExtraPathClick(wxCommandEvent& event)
{
    wxListBox* control = XRCCTRL(*this, "lstExtraPaths", wxListBox);
    if (!control || control->GetSelection() < 0)
        return;

    int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
    Compiler* compiler = CompilerFactory::Compilers[compilerIdx];
    wxArrayString extraPaths = CompilerFactory::Compilers[compilerIdx]->GetExtraPaths();
    extraPaths.RemoveAt(control->GetSelection());
    compiler->SetExtraPaths(extraPaths);
    control->Delete(control->GetSelection());
}

void CompilerOptionsDlg::OnMoveLibUpClick(wxSpinEvent& event)
{
    wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
    if (lstLibs->GetSelection() <= 0)
        return;
    int sel = lstLibs->GetSelection();
    wxString lib = lstLibs->GetStringSelection();
    lstLibs->Delete(sel);
    lstLibs->InsertItems(1, &lib, sel - 1);
    lstLibs->SetSelection(sel - 1);
    if (m_pProject)
        m_pProject->SetModified(true);
}

void CompilerOptionsDlg::OnMoveLibDownClick(wxSpinEvent& event)
{
    wxListBox* lstLibs = XRCCTRL(*this, "lstLibs", wxListBox);
    if (lstLibs->GetSelection() == lstLibs->GetCount() - 1)
        return;
    int sel = lstLibs->GetSelection();
    wxString lib = lstLibs->GetStringSelection();
    lstLibs->Delete(sel);
    lstLibs->InsertItems(1, &lib, sel + 1);
    lstLibs->SetSelection(sel + 1);
    if (m_pProject)
        m_pProject->SetModified(true);
}

void CompilerOptionsDlg::OnMoveDirUpClick(wxSpinEvent& event)
{
    wxListBox* lst = GetDirsListBox();
    if (!lst || lst->GetSelection() <= 0)
        return;
    int sel = lst->GetSelection();
    wxString lib = lst->GetStringSelection();
    lst->Delete(sel);
    lst->InsertItems(1, &lib, sel - 1);
    lst->SetSelection(sel - 1);
    if (m_pProject)
        m_pProject->SetModified(true);
}

void CompilerOptionsDlg::OnMoveDirDownClick(wxSpinEvent& event)
{
    wxListBox* lst = GetDirsListBox();
    if (!lst || lst->GetSelection() == lst->GetCount() - 1)
        return;
    int sel = lst->GetSelection();
    wxString lib = lst->GetStringSelection();
    lst->Delete(sel);
    lst->InsertItems(1, &lib, sel + 1);
    lst->SetSelection(sel + 1);
    if (m_pProject)
        m_pProject->SetModified(true);
}

void CompilerOptionsDlg::OnMasterPathClick(wxCommandEvent& event)
{
    wxString path = ChooseDirectory(this,
                                    _("Select directory"),
                                    XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->GetValue());
    if (path.IsEmpty())
        return;
    if (!path.IsEmpty())
    {
        XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->SetValue(path);
        int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
        DoSaveCompilerPrograms(compilerIdx);
    }
}

void CompilerOptionsDlg::OnAutoDetectClick(wxCommandEvent& event)
{
    AutoDetectCompiler();
}

void CompilerOptionsDlg::OnSelectProgramClick(wxCommandEvent& event)
{
    // see who called us
    wxTextCtrl* obj = 0L;
    if (event.GetId() == XRCID("btnCcompiler"))
        obj = XRCCTRL(*this, "txtCcompiler", wxTextCtrl);
    else if (event.GetId() == XRCID("btnCPPcompiler"))
        obj = XRCCTRL(*this, "txtCPPcompiler", wxTextCtrl);
    else if (event.GetId() == XRCID("btnLinker"))
        obj = XRCCTRL(*this, "txtLinker", wxTextCtrl);
    else if (event.GetId() == XRCID("btnLibLinker"))
        obj = XRCCTRL(*this, "txtLibLinker", wxTextCtrl);
    else if (event.GetId() == XRCID("btnDebugger"))
        obj = XRCCTRL(*this, "txtDebugger", wxTextCtrl);
    else if (event.GetId() == XRCID("btnResComp"))
        obj = XRCCTRL(*this, "txtResComp", wxTextCtrl);
    else if (event.GetId() == XRCID("btnMake"))
        obj = XRCCTRL(*this, "txtMake", wxTextCtrl);

    if (!obj)
        return; // called from invalid caller

    // common part follows
    wxFileDialog* dlg = new wxFileDialog(this,
                            _("Select file"),
                            XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->GetValue() + _T("/bin"),
                            obj->GetValue(),
                            _("Executable files (*.exe)|*.exe"),
                            wxOPEN | wxFILE_MUST_EXIST);
    dlg->SetFilterIndex(0);

    if (dlg->ShowModal() != wxID_OK)
        return;
    wxFileName fname(dlg->GetPath());
    obj->SetValue(fname.GetFullName());
    int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
    DoSaveCompilerPrograms(compilerIdx);
}

void CompilerOptionsDlg::OnAdvancedClick(wxCommandEvent& event)
{
	if (wxMessageBox(_("The compiler's advanced settings, need command-line "
                        "compiler knowledge to be tweaked.\nIf you don't know "
                        "*exactly* what you 're doing, it is suggested to "
                        "NOT tamper with the advanced settings...\n\n"
                        "Are you sure you want to edit the advanced settings?"),
					_("Warning"),
					wxOK | wxCANCEL | wxICON_WARNING) == wxOK)
    {
        wxComboBox* cmb = XRCCTRL(*this, "cmbCompiler", wxComboBox);
        int compilerIdx = cmb->GetSelection();
        AdvancedCompilerOptionsDlg dlg(this, compilerIdx);
        dlg.ShowModal();
    }
}

void CompilerOptionsDlg::OnUpdateUI(wxUpdateUIEvent& event)
{
    wxListBox* control = GetDirsListBox();
    if (control)
    {
        // add/edit/delete dir
        bool en = control->GetSelection() >= 0;
        XRCCTRL(*this, "btnEditDir", wxButton)->Enable(en);
        XRCCTRL(*this, "btnDelDir", wxButton)->Enable(en);

        // moveup/movedown dir
        XRCCTRL(*this, "spnDirs", wxSpinButton)->Enable(en);
    }

    // add/edit/delete/moveup/movedown lib
    bool en = XRCCTRL(*this, "lstLibs", wxListBox)->GetSelection() >= 0;
    XRCCTRL(*this, "btnEditLib", wxButton)->Enable(en);
    XRCCTRL(*this, "btnDelLib", wxButton)->Enable(en);
    XRCCTRL(*this, "spnLibs", wxSpinButton)->Enable(en);

    // add/edit/delete vars
    if (XRCCTRL(*this, "lstVars", wxListBox))
    {
        en = XRCCTRL(*this, "lstVars", wxListBox)->GetSelection() >= 0;
        XRCCTRL(*this, "btnEditVar", wxButton)->Enable(en);
        XRCCTRL(*this, "btnDeleteVar", wxButton)->Enable(en);
    }

    // policies
	wxTreeCtrl* tc = XRCCTRL(*this, "tcScope", wxTreeCtrl);
	ScopeTreeData* data = (ScopeTreeData*)tc->GetItemData(tc->GetSelection());
	en = (data && data->GetTarget());
    XRCCTRL(*this, "cmbCompilerPolicy", wxComboBox)->Enable(en);
    XRCCTRL(*this, "cmbLinkerPolicy", wxComboBox)->Enable(en);
    XRCCTRL(*this, "cmbIncludesPolicy", wxComboBox)->Enable(en);
    XRCCTRL(*this, "cmbLibDirsPolicy", wxComboBox)->Enable(en);
    XRCCTRL(*this, "cmbResDirsPolicy", wxComboBox)->Enable(en);

    // compiler set buttons
    if (XRCCTRL(*this, "btnAddCompiler", wxButton)) // only if exist
    {
        en = !data; // global options selected
        int idx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
        int count = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetCount(); // compilers count
        XRCCTRL(*this, "btnSetDefaultCompiler", wxButton)->Enable(CompilerFactory::GetDefaultCompilerIndex() != idx);
        XRCCTRL(*this, "btnAddCompiler", wxButton)->Enable(en);
        XRCCTRL(*this, "btnRenameCompiler", wxButton)->Enable(en && count);
        XRCCTRL(*this, "btnDelCompiler", wxButton)->Enable(en &&
                                                        CompilerFactory::CompilerIndexOK(idx) &&
                                                        CompilerFactory::Compilers[idx]->GetParentID() != -1);
        XRCCTRL(*this, "btnResetCompiler", wxButton)->Enable(en &&
                                                        CompilerFactory::CompilerIndexOK(idx) &&
                                                        CompilerFactory::Compilers[idx]->GetParentID() == -1);
    }

    // compiler programs
    if (XRCCTRL(*this, "txtMasterPath", wxTextCtrl)) // "Programs" page exists?
    {
        en = !data; // global options selected
        int extraSel = XRCCTRL(*this, "lstExtraPaths", wxListBox)->GetSelection();
        XRCCTRL(*this, "txtMasterPath", wxTextCtrl)->Enable(en);
        XRCCTRL(*this, "btnMasterPath", wxButton)->Enable(en);
        XRCCTRL(*this, "btnExtraAdd", wxButton)->Enable(en);
        XRCCTRL(*this, "btnExtraEdit", wxButton)->Enable(en && extraSel != -1);
        XRCCTRL(*this, "btnExtraDelete", wxButton)->Enable(en && extraSel != -1);
        XRCCTRL(*this, "txtCcompiler", wxTextCtrl)->Enable(en);
        XRCCTRL(*this, "btnCcompiler", wxButton)->Enable(en);
        XRCCTRL(*this, "txtCPPcompiler", wxTextCtrl)->Enable(en);
        XRCCTRL(*this, "btnCPPcompiler", wxButton)->Enable(en);
        XRCCTRL(*this, "txtLinker", wxTextCtrl)->Enable(en);
        XRCCTRL(*this, "btnLinker", wxButton)->Enable(en);
        XRCCTRL(*this, "txtLibLinker", wxTextCtrl)->Enable(en);
        XRCCTRL(*this, "btnLibLinker", wxButton)->Enable(en);
        XRCCTRL(*this, "txtDebugger", wxTextCtrl)->Enable(en);
        XRCCTRL(*this, "btnDebugger", wxButton)->Enable(en);
        XRCCTRL(*this, "txtResComp", wxTextCtrl)->Enable(en);
        XRCCTRL(*this, "btnResComp", wxButton)->Enable(en);
        XRCCTRL(*this, "txtMake", wxTextCtrl)->Enable(en);
        XRCCTRL(*this, "btnMake", wxButton)->Enable(en);
        XRCCTRL(*this, "cmbCompiler", wxComboBox)->Enable(en);
    }
}

void CompilerOptionsDlg::EndModal(int retCode)
{
	wxTreeCtrl* tc = XRCCTRL(*this, "tcScope", wxTreeCtrl);
	ScopeTreeData* data = (ScopeTreeData*)tc->GetItemData(tc->GetSelection());
    int compilerIdx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
	DoSaveOptions(compilerIdx, data);
	CompilerFactory::SaveSettings();

    // compiler set
    int idx = XRCCTRL(*this, "cmbCompiler", wxComboBox)->GetSelection();
    if (m_pProject && !data->GetTarget() && idx != m_InitialCompilerIdx)
    {
        m_pProject->SetCompilerIndex(idx);
        UpdateCompilerForTargets(idx);
        wxMessageBox(_("You changed the compiler used for this project.\n"
                        "It is recommended that you fully rebuild your project, "
                        "otherwise linking errors might occur..."),
                        _("Notice"),
                        wxICON_EXCLAMATION);
    }

    if (!m_pProject)
    {
        // only do it for global compiler options
        // why does it crash for project compiler options???
        DoSaveCompilerPrograms(idx);
    }

	//others
    wxTextCtrl* txt = XRCCTRL(*this, "txtConsoleShell", wxTextCtrl);
    if (txt)
        ConfigManager::Get()->Write(_T("/compiler_gcc/console_shell"), txt->GetValue());
    wxSpinCtrl* spn = XRCCTRL(*this, "spnMaxErrors", wxSpinCtrl);
    if (spn)
        ConfigManager::Get()->Write(_T("/compiler_gcc/max_reported_errors"), spn->GetValue());

	wxDialog::EndModal(retCode);
}

void CompilerOptionsDlg::OnMyCharHook(wxKeyEvent& event)
{
    wxWindow* focused = wxWindow::FindFocus();
    if(!focused)
        { event.Skip();return; }
    int keycode = event.GetKeyCode();
    int id = focused->GetId();

    int myid = 0;
    unsigned int myidx = 0;

    const wxChar* str_libs[3] = { _T("btnEditLib"),_T("btnAddLib"),_T("btnDelLib") };
    const wxChar* str_dirs[3] = { _T("btnEditDir"),_T("btnAddDir"),_T("btnDelDir") };
    const wxChar* str_vars[3] = { _T("btnEditVar"),_T("btnAddVar"),_T("btnDeleteVar") };
    const wxChar* str_xtra[3] = { _T("btnExtraEdit"),_T("btnExtraAdd"),_T("btnExtraDelete") };

    if(keycode == WXK_RETURN || keycode == WXK_NUMPAD_ENTER)
        { myidx = 0; } // Edit
    else if(keycode == WXK_INSERT || keycode == WXK_NUMPAD_INSERT)
        { myidx = 1; } // Add
    else if(keycode == WXK_DELETE || keycode == WXK_NUMPAD_DELETE)
        { myidx = 2; } // Delete
    else
        { event.Skip();return; }

    if(     id == XRCID("lstLibs")) // Link libraries
        { myid =  wxXmlResource::GetXRCID(str_libs[myidx]); }
    else if(id == XRCID("lstIncludeDirs") || id == XRCID("lstLibDirs") || id == XRCID("lstResDirs")) // Directories
        { myid =  wxXmlResource::GetXRCID(str_dirs[myidx]); }
    else if(id == XRCID("lstVars")) // Custom Vars
        { myid =  wxXmlResource::GetXRCID(str_vars[myidx]); }
    else if(id == XRCID("lstExtraPaths")) // Extra Paths
        { myid =  wxXmlResource::GetXRCID(str_xtra[myidx]); }
    else
        myid = 0;

    // Generate the event
    if(myid == 0)
        event.Skip();
    else
    {
        wxCommandEvent newevent(wxEVT_COMMAND_BUTTON_CLICKED,myid);
        this->ProcessEvent(newevent);
    }
}


syntax highlighted by Code2HTML, v. 0.9.1