]> git.kernelconcepts.de Git - karo-tx-redboot.git/blobdiff - tools/src/tools/configtool/standalone/wxwin/configtooldoc.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / configtool / standalone / wxwin / configtooldoc.cpp
diff --git a/tools/src/tools/configtool/standalone/wxwin/configtooldoc.cpp b/tools/src/tools/configtool/standalone/wxwin/configtooldoc.cpp
new file mode 100644 (file)
index 0000000..952ea14
--- /dev/null
@@ -0,0 +1,2330 @@
+//####COPYRIGHTBEGIN####
+//
+// ----------------------------------------------------------------------------
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
+// Copyright (C) 2003 John Dallaway
+//
+// This program is part of the eCos host tools.
+//
+// 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.
+//
+// ----------------------------------------------------------------------------
+//
+//####COPYRIGHTEND####
+// configtooldoc.cpp :
+//
+//===========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):   julians, jld
+// Contact(s):  julians, jld
+// Date:        2000/10/05
+// Version:     $Id$
+// Purpose:
+// Description: Implementation file for the ecConfigToolDoc class
+// Requires:
+// Provides:
+// See also:
+// Known bugs:
+// Usage:
+//
+//####DESCRIPTIONEND####
+//
+//===========================================================================
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+#ifdef __GNUG__
+#pragma implementation "configtooldoc.h"
+#endif
+
+// Includes other headers for precompiled compilation
+#include "ecpch.h"
+
+#include "wx/config.h"
+#include "wx/textfile.h"
+#include "wx/process.h"
+#include "wx/mimetype.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifdef __WXMSW__
+#include <windows.h>
+#ifndef __CYGWIN__
+#include <shlobj.h>
+#endif
+#include "wx/msw/winundef.h"
+#ifdef CreateDirectory
+#undef CreateDirectory
+#endif
+#endif
+
+#include "configtooldoc.h"
+#include "configtoolview.h"
+#include "configtree.h"
+#include "mainwin.h"
+#include "ecutils.h"
+#include "filename.h"
+#include "choosereposdlg.h"
+#include "packagesdlg.h"
+#include "conflictsdlg.h"
+#include "conflictwin.h"
+#include "mltwin.h"
+#include "build.hxx"
+#include "platformeditordlg.h"
+#include "runtestsdlg.h"
+#include "propertywin.h"
+#include "docsystem.h"
+
+IMPLEMENT_DYNAMIC_CLASS(ecConfigToolDoc, wxDocument)
+
+ecConfigToolDoc::ecConfigToolDoc()
+{
+    m_bRepositoryOpen = FALSE;
+    m_CdlPkgData = NULL;
+    m_CdlInterp = NULL;
+    m_CdlConfig = NULL;
+    m_ConflictsOutcome = OK;
+    m_strRepository = wxGetApp().GetSettings().m_strRepository;
+}
+
+ecConfigToolDoc::~ecConfigToolDoc()
+{
+    wxGetApp().m_currentDoc = NULL;
+    wxGetApp().GetSettings().m_strRepository = m_strRepository;
+
+    CloseRepository();
+
+    // Delete remaining items -- most (if not all) should already
+    // have been deleted via the tree item client data
+    DeleteItems();
+}
+
+void ecConfigToolDoc::DeleteItems()
+{
+    // Delete any remaining items
+    wxNode* node = m_items.First();
+    while (node)
+    {
+        ecConfigItem* item = wxDynamicCast(node->Data(), ecConfigItem);
+        wxNode* next = node->Next();
+
+        // Note: automatically removes itself from this list in ~ecConfigItem
+        delete item;
+        node = next;
+    }
+}
+
+bool ecConfigToolDoc::OnCloseDocument()
+{
+    if (wxDocument::OnCloseDocument())
+    {
+        DeleteItems();
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+
+bool ecConfigToolDoc::Save()
+{
+    bool ret = FALSE;
+
+    if (!IsModified() && m_savedYet) return TRUE;
+    if (m_documentFile == wxT("") || !m_savedYet)
+        ret = SaveAs();
+    else
+        ret = OnSaveDocument(m_documentFile);
+    if ( ret )
+        SetDocumentSaved(TRUE);
+    return ret;
+}
+
+
+bool ecConfigToolDoc::OnCreate(const wxString& path, long flags)
+{
+    wxGetApp().m_currentDoc = this;
+
+    if (flags & wxDOC_NEW)
+    {
+        m_bRepositoryOpen = FALSE;
+
+        bool prompt = FALSE;
+        if (flags & ecDOC_PROMPT_FOR_REPOSITORY)
+            prompt = TRUE;
+
+        if(!OpenRepository(wxEmptyString, prompt))
+        {
+            wxGetApp().m_currentDoc = NULL;
+            return FALSE;
+        }
+
+        Modify(FALSE);
+        SetDocumentSaved(FALSE);
+
+        wxString rootName(wxT("untitled"));
+        wxStripExtension(rootName);
+        SetFilename(wxGetApp().GetSettings().GenerateFilename(rootName));
+    }
+
+    // Creates the view, so do any view updating after this
+    bool success = wxDocument::OnCreate(path, flags);
+
+    if (success)
+    {
+        if (flags & wxDOC_NEW)
+        {
+            wxBusyCursor wait;
+
+            ecConfigToolHint hint(NULL, ecSelChanged);
+            UpdateAllViews (NULL, & hint);
+
+            SetFilename(GetFilename(), TRUE);
+
+            // load the memory layout for the default target-platform-startup from the current repository
+
+            // TODO
+            // m_memoryMap.set_map_size (0xFFFFFFFF); // set the maximum memory map size
+            // NewMemoryLayout (CFileName (m_strPackagesDir, m_strMemoryLayoutFolder, _T("include\\pkgconf")));
+
+            // Why should we generate the names at this point, when we only have a temporary filename?
+            // Don't do it!
+#if 0
+            wxGetApp().SetStatusText(wxT("Updating build information..."), FALSE);
+            UpdateBuildInfo();
+#endif
+        }
+    }
+    return success;
+}
+
+bool ecConfigToolDoc::OnSaveDocument(const wxString& filename)
+{
+    wxBusyCursor cursor;
+
+    const wxString strOldPath(GetFilename());
+
+#if 0
+    bool bSaveAs=(filename!=strOldPath);
+    if(!IsModified() && wxFileExists(filename))
+    {
+        return TRUE;
+    }
+#endif
+
+    bool rc=FALSE;
+    if (CheckConflictsBeforeSave())
+    { // errors already emitted
+
+        const wxString strPathName(filename);
+
+        wxString str;
+        str.Printf(_("Saving configuration %s"), (const wxChar*) filename);
+
+        /* TODO
+        CIdleMessage IM(str);
+        if(CConfigTool::GetCellView()){
+        CConfigTool::GetCellView()->CancelCellEdit();
+        }
+        */
+
+        // check the configuration
+
+        wxASSERT (m_CdlConfig->check_this (cyg_extreme));
+
+        // save the configuration
+
+        try
+        {
+            m_CdlConfig->save ((const wxChar*) filename);
+            rc=TRUE;
+        }
+
+        catch (CdlStringException exception)
+        {
+            wxString msg;
+            msg.Printf(_("Error saving eCos configuration:\n\n%s"), exception.get_message ().c_str ());
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+        }
+
+        catch (...)
+        {
+            wxString msg;
+            msg.Printf(_("Error saving eCos configuration"));
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+        }
+
+        if(rc){
+            rc=FALSE;
+            SetFilename (filename); // called to ensure that MLTDir() will work in this function TODO??
+
+            // save the memory layout files to the build tree and copy to the install tree
+            /* TODO
+            if (bSaveAs || MemoryMap.map_modified ()) {
+            SaveMemoryMap();
+            }
+            */
+
+            ecConfigToolHint hint(NULL, ecAllSaved);
+            UpdateAllViews (NULL, & hint);
+
+            wxASSERT( !m_strBuildTree.IsEmpty() );
+            wxASSERT( !m_strInstallTree.IsEmpty() );
+
+            ecFileName buildFilename(m_strBuildTree);
+            ecFileName installFilename(m_strInstallTree);
+
+            if (!wxGetApp().GetSettings().m_editSaveFileOnly)
+            {
+                if (!buildFilename.CreateDirectory(FALSE) || !installFilename.CreateDirectory(FALSE))
+                {
+                    wxString msg;
+                    msg.Printf(_("Failed to save %s"), (const wxChar*) filename);
+                    
+                    wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION);
+                    rc = FALSE;
+                }
+                else if (GenerateHeaders() && CopyMLTFiles())
+                {
+                    // in each case errors already emitted
+                    // copy new MLT files to the build tree as necessary
+                    rc=generate_build_tree (GetCdlConfig(), ecUtils::UnicodeToStdStr(m_strBuildTree), ecUtils::UnicodeToStdStr(m_strInstallTree));
+                    rc = TRUE;
+                }
+            }
+            else
+            {
+                rc = TRUE;
+            }
+        }
+    }
+    if(rc)
+    {
+        Modify(FALSE);
+        SetDocumentSaved(TRUE);
+        SetFilename(filename);
+        wxGetApp().GetSettings().m_lastFilename = filename;
+    } else
+    {
+        SetFilename(strOldPath);
+    }
+    wxGetApp().GetMainFrame()->UpdateFrameTitle();
+    return rc;
+}
+
+// Can we generate the build tree yet?
+bool ecConfigToolDoc::CanGenerateBuildTree()
+{
+    if (m_strBuildTree.IsEmpty() || m_strInstallTree.IsEmpty() )
+        return FALSE;
+
+    int nCount=0;
+    if (GetCdlConfig ())
+    {
+        // calculate the number of conflicts
+        int nCount = GetCdlConfig ()->get_all_conflicts ().size ();
+
+        if (nCount > 0)
+            return FALSE;
+    }
+    else
+        return FALSE;
+
+    return TRUE;
+}
+
+// A standalone method for generating a build tree without saving first
+bool ecConfigToolDoc::GenerateBuildTree()
+{
+    wxBusyCursor wait;
+    if (CanGenerateBuildTree())
+    {
+        ecFileName buildFilename(m_strBuildTree);
+        ecFileName installFilename(m_strInstallTree);
+        
+        if (!buildFilename.CreateDirectory() || !installFilename.CreateDirectory())
+        {
+            wxString msg;
+            msg.Printf(_("Failed to create build tree"));
+            
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION);
+            return FALSE;
+        }
+        else if (GenerateHeaders() && CopyMLTFiles())
+        {
+            // in each case errors already emitted
+            // copy new MLT files to the build tree as necessary
+            bool rc = generate_build_tree (GetCdlConfig(), ecUtils::UnicodeToStdStr(m_strBuildTree), ecUtils::UnicodeToStdStr(m_strInstallTree));
+            rc = TRUE;
+        }
+
+    }
+    else
+        return FALSE;
+    return TRUE;
+}
+
+bool ecConfigToolDoc::OnOpenDocument(const wxString& filename)
+{
+    wxGetApp().GetSettings().m_lastFilename = filename;
+
+    wxBusyCursor cursor;
+
+    bool rc=FALSE; // Assume the worst
+    CdlInterpreter NewCdlInterp = NULL;
+    CdlConfiguration NewCdlConfig = NULL;
+
+    // We have to open the repository or m_CdlPkgData and co. won't be set
+    if (!OpenRepository())
+        return FALSE;
+
+    wxString str;
+    str.Printf(_("Opening save file %s"), (const wxChar*) filename);
+    wxGetApp().SetStatusText(str);
+
+    EnableCallbacks(FALSE);
+
+    try
+    {
+        NewCdlInterp = CdlInterpreterBody::make ();
+        NewCdlConfig = CdlConfigurationBody::load ((const wxChar*) filename, m_CdlPkgData, NewCdlInterp, &CdlLoadErrorHandler, &CdlLoadWarningHandler);
+        rc = TRUE;
+    }
+    catch (CdlStringException exception)
+    {
+        wxString msg;
+        msg.Printf(_("Error opening eCos configuration:\n\n%s"), exception.get_message ().c_str ());
+        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+    }
+    catch (...)
+    {
+        wxString msg;
+        msg.Printf(_("Error opening eCos configuration"));
+        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+    }
+
+    if (rc)
+    {
+        rc=FALSE;
+        // check the new configuration
+
+        wxASSERT (NewCdlConfig->check_this (cyg_extreme));
+
+        // switch to the new configuration
+
+        delete m_CdlConfig;
+        delete m_CdlInterp;
+        m_CdlInterp = NewCdlInterp;
+        m_CdlConfig = NewCdlConfig;
+        //SetPathName (lpszPathName, TRUE); // called to ensure that MLTDir() will work in this function
+
+        AddAllItems (); // must precede NewMemoryLayout() [CurrentLinkerScript() calls Find()]
+
+        // load the memory layout from the build tree
+        // TODO
+        NewMemoryLayout (MLTDir ());
+
+        UpdateFailingRuleCount();
+
+        SetFilename(filename);
+
+       // UpdateBuildInfo(); // Don't create directories on opening file
+
+        rc = TRUE;
+
+
+        ecConfigToolHint hint(NULL, ecFilenameChanged);
+        UpdateAllViews (NULL, & hint);
+    }
+
+    // re-enable the transaction callback
+    EnableCallbacks(TRUE);
+
+    SetDocumentSaved(TRUE); // Necessary or it will pop up the Save As dialog
+
+    wxGetApp().SetStatusText(wxEmptyString, FALSE);
+
+    return rc;
+}
+
+void ecConfigToolDoc::AddAllItems()
+{
+    ecConfigTreeCtrl* treeCtrl = wxGetApp().GetMainFrame()->GetTreeCtrl();
+    // Ensure there's no dangling pointer
+    wxGetApp().GetMainFrame()->GetPropertyListWindow()->Fill(NULL);
+
+    treeCtrl->DeleteAllItems();
+
+    m_strMemoryLayoutFolder = wxT("");
+    m_strLinkerScriptFolder = wxT("");
+
+    // Add the root item
+    ecConfigItem* item = NULL;
+    wxTreeItemId rootId = treeCtrl->AddRoot(_(""), -1, -1, new ecTreeItemData(item = new ecConfigItem(NULL, _("Configuration"), ecContainer)));
+    item->SetTreeItem(rootId);
+    item->UpdateTreeItem(* treeCtrl);
+    item->SetDescription(_("The root node for all configurable items"));
+    m_items.Append(item);
+
+    AddContents(m_CdlConfig, item);
+    treeCtrl->Expand(rootId);
+
+    // check that exactly one radio button in each group is enabled
+    CheckRadios ();
+
+    // update the rules (conflicts) view
+    UpdateFailingRuleCount ();
+
+    if( ! wxGetApp().GetMainFrame() || ! wxGetApp().GetMainFrame()->GetConflictsWindow() ||
+        ! wxGetApp().GetMainFrame()->GetConflictsWindow()->IsShown())
+    {
+        // log all conflicts
+        //     LogConflicts (m_CdlConfig->get_structural_conflicts ()); // relating to package availability - ignore for now
+        LogConflicts (m_CdlConfig->get_all_conflicts ());
+    }
+
+    wxGetApp().GetTreeCtrl()->SelectItem(wxGetApp().GetTreeCtrl()->GetRootItem());
+    //ecConfigToolHint hint(item, ecValueChanged);
+    ecConfigToolHint hint(NULL, ecSelChanged);
+
+    UpdateAllViews (NULL, & hint);
+
+    if(GetItems().Number()>0){
+        wxGetApp().GetTreeCtrl()->Expand(rootId);
+    }
+    wxGetApp().GetTreeCtrl()->SetFocus();
+}
+
+void ecConfigToolDoc::AddContents (const CdlContainer container, ecConfigItem *pParent)
+{
+    // determine the container contents
+
+    const std::vector<CdlNode>& contents = container->get_contents ();
+    std::vector<CdlNode>::const_iterator node_i;
+    for (node_i = contents.begin (); node_i != contents.end (); node_i++)
+    {
+        const CdlNode node = * node_i;
+        const CdlPackage pkg = dynamic_cast<CdlPackage> (node);
+        const CdlComponent comp = dynamic_cast<CdlComponent> (node);
+        const CdlOption opt = dynamic_cast<CdlOption> (node);
+        const CdlContainer contnr = dynamic_cast<CdlContainer> (node);
+
+        // if the node in the container is a package, component or option
+        // then it is visible and should be added to the tree
+        if  (0 != pkg) // the node is a package
+        {
+            ecConfigItem * pItem = AddItem (pkg, pParent); // add the package
+            AddContents (pkg, pItem); // add the package contents
+        }
+        else if (0 != comp) // the node is a component
+        {
+            ecConfigItem * pItem = AddItem (comp, pParent); // add the component
+            AddContents (comp, pItem); // add the component contents
+        }
+        else if (0 != opt) // the node is an option
+            AddItem (opt, pParent); // add the option
+
+        else if (0 != contnr) // if the node is a container
+            AddContents (contnr, pParent); // add the container contents
+
+        // ignore nodes of any other class
+    }
+}
+
+ecConfigItem * ecConfigToolDoc::AddItem (const CdlUserVisible vitem, ecConfigItem * pParent)
+{
+    ecConfigItem * pItem = new ecConfigItem (pParent, vitem);
+
+    m_items.Append(pItem);
+
+    if (vitem->get_name () == "CYGHWR_MEMORY_LAYOUT")
+    {
+        wxASSERT (m_strMemoryLayoutFolder.IsEmpty ());
+        m_strMemoryLayoutFolder = vitem->get_owner ()->get_directory().c_str ();
+#ifdef __WXMSW__
+        m_strMemoryLayoutFolder.Replace(wxT("/"),wxT("\\"));
+#endif
+        //TRACE (_T("Found memory layout folder: %s\n"), m_strMemoryLayoutFolder);
+    }
+
+    if (vitem->get_name () == "CYGBLD_LINKER_SCRIPT")
+    {
+        wxASSERT (m_strLinkerScriptFolder.IsEmpty ());
+        m_strLinkerScriptFolder = vitem->get_owner ()->get_directory().c_str ();
+#ifdef __WXMSW__
+        m_strLinkerScriptFolder.Replace(wxT("/"),wxT("\\"));
+#endif
+        //TRACE (_T("Found linker script folder: %s\n"), m_strLinkerScriptFolder);
+
+        // the CDL hardware template name will eventually become the target name,
+        // but for now we must deduce the target name from the linker script file name
+
+        const CdlValuable valuable = dynamic_cast<CdlValuable> (vitem);
+        ecFileName strLinkerScript (m_strPackagesDir, m_strLinkerScriptFolder, wxString (valuable->get_value ().c_str ()));
+
+#ifdef __WXMSW__
+        strLinkerScript.Replace (wxT("/"), wxT("\\"));
+#endif
+
+        if(!strLinkerScript.Exists ()){
+            wxString msg;
+            msg.Printf(wxT("%s does not exist\n"), (const wxChar*) strLinkerScript);
+            wxGetApp().Log(msg);
+        }
+        //TRACE (_T("Target '%s' selected\n"), strLinkerScript.Tail ().Root (), pItem->Macro());
+    }
+
+    //TRACE(_T("Created new item from cdl: "));
+    //pItem->DumpItem();
+    return pItem;
+}
+
+void ecConfigToolDoc::CheckRadios()
+{
+    int nItem;
+    for(nItem=0; nItem < GetItems().Number() ; nItem++)
+    {
+        ecConfigItem *pItem=(ecConfigItem*) GetItems()[nItem];
+
+        if(pItem->HasRadio () && pItem==pItem->FirstRadio())
+        {
+            wxString strMsg;
+            ecConfigItem *pFirstSet=NULL;
+            ecConfigItem *pSibItem;
+
+            for ( pSibItem=pItem; pSibItem; pSibItem = pSibItem->NextRadio() )
+            {
+                if(pSibItem->IsEnabled ())
+                {
+                    if(pFirstSet)
+                    {
+                        strMsg += wxT(" ");
+                        strMsg += pSibItem->GetMacro ();
+                    } else
+                    {
+                        pFirstSet = pSibItem;
+                    }
+                }
+            }
+
+            if ( !strMsg.IsEmpty() )
+            {
+                wxString msg2;
+                msg2.Printf(_("%s, multiple radio buttons are set: %s%s"),
+                    (const wxChar*) pItem->GetMacro(), (const wxChar*) pFirstSet->GetMacro(), (const wxChar*) strMsg);
+                wxGetApp().Log(msg2);
+            } else if ( !pFirstSet )
+            {
+                wxString msg2;
+                msg2.Printf(_("%s, no radio buttons are set"), (const wxChar*) pItem->GetMacro());
+                wxGetApp().Log(msg2);
+            }
+        }
+    }
+}
+
+// Find the ecConfigItem referencing the given CdlValuable
+ecConfigItem * ecConfigToolDoc::Find (CdlValuable v)
+{
+    int nItem;
+    for (nItem=0 ; nItem < m_items.Number() ; nItem++)
+    {
+        ecConfigItem *pItem = (ecConfigItem*) m_items[nItem];
+        if( v == pItem->GetCdlValuable() )
+        {
+            return pItem;
+        }
+    }
+    return NULL;
+}
+
+ecConfigItem * ecConfigToolDoc::Find(const wxString & strWhat, ecWhereType where)
+{
+    int nItem;
+    for (nItem=0 ; nItem < m_items.Number() ; nItem++)
+    {
+        ecConfigItem *pItem = (ecConfigItem*) m_items[nItem];
+        if (pItem->StringValue(where) == strWhat)
+        {
+            return pItem;
+        }
+    }
+    return NULL;
+}
+
+// a trivial CDL load error handler
+void ecConfigToolDoc::CdlLoadErrorHandler (std::string message)
+{
+    wxGetApp().Log(message.c_str());
+};
+
+// a trivial CDL load warning handler
+void ecConfigToolDoc::CdlLoadWarningHandler (std::string message)
+{
+    wxGetApp().Log(message.c_str());
+};
+
+// a trivial CDL parse error handler
+void ecConfigToolDoc::CdlParseErrorHandler (std::string message)
+{
+    wxGetApp().Log(message.c_str());
+};
+
+// a trivial CDL parse warning handler
+void ecConfigToolDoc::CdlParseWarningHandler (std::string message)
+{
+    wxGetApp().Log(message.c_str());
+};
+
+
+void ecConfigToolDoc::CloseRepository()
+{
+    if(m_bRepositoryOpen){
+        // delete the libCDL objects with the document
+        EnableCallbacks(FALSE); // first disable the transaction handler
+        delete m_CdlConfig; m_CdlConfig = NULL;
+        delete m_CdlInterp; m_CdlInterp = NULL;
+        delete m_CdlPkgData; m_CdlPkgData = NULL;
+        m_bRepositoryOpen=FALSE;
+    }
+}
+
+bool ecConfigToolDoc::OpenRepository(const wxString& pszRepository /* = wxEmptyString */, bool bPromptInitially/* =FALSE */)
+{
+    ecMainFrame* mainFrame = wxGetApp().GetMainFrame();
+    if(!m_bRepositoryOpen)
+    {
+        UpdateFailingRuleCount();
+
+        ecFileName strNewRepository;
+        while(!m_bRepositoryOpen)
+        {
+            if(bPromptInitially)
+            {
+                ecChooseRepositoryDialog dlg(wxGetApp().GetTopWindow());
+
+                if(wxID_CANCEL==dlg.ShowModal()){
+                    wxGetApp().SetStatusText(wxEmptyString);
+                    return FALSE;
+                }
+#ifdef __WXMSW__
+                // Ensure display gets updated
+                ::UpdateWindow((HWND) mainFrame->GetHWND());
+                //wxYield();
+#endif
+                strNewRepository=dlg.GetFolder();
+            } else
+            {
+                // Use what came in as parameter or what was found in registry
+                if (!pszRepository.IsEmpty())
+                    strNewRepository = pszRepository;
+                else
+                    strNewRepository = m_strRepository;
+
+                bPromptInitially=TRUE;
+            }
+            wxString str;
+            if (strNewRepository.IsEmpty())
+                str.Printf(_("Opening repository..."));
+            else
+                str.Printf(_("Opening repository %s..."), (const wxChar*) strNewRepository);
+            wxGetApp().SetStatusText(str);
+
+            CdlPackagesDatabase NewCdlPkgData = NULL;
+            CdlInterpreter      NewCdlInterp  = NULL;
+            CdlConfiguration    NewCdlConfig  = NULL;
+            wxString strNewPackagesDir;
+
+            EnableCallbacks(FALSE); // disable transaction callbacks until the config tree is regenerated
+
+            wxBusyCursor wait;
+            if(OpenRepository(strNewRepository,NewCdlPkgData,NewCdlInterp,NewCdlConfig,strNewPackagesDir))
+            {
+                // select the "default" template if it exists
+                // otherwise select the first available template
+
+                std::string default_template = "default";
+                if (! NewCdlPkgData->is_known_template (default_template))
+                {
+                    const std::vector<std::string>& templates = NewCdlPkgData->get_templates ();
+                    if (templates.size () != 0)
+                        default_template = templates [0];
+                }
+
+                m_templateVersion = "";
+                try
+                {
+                    const std::vector<std::string>& template_versions = NewCdlPkgData->get_template_versions (default_template);
+                    NewCdlConfig->set_template (default_template, template_versions [0], &CdlParseErrorHandler, &CdlParseWarningHandler);
+                    m_templateVersion = template_versions [0].c_str();
+                }
+                catch (CdlStringException exception) {
+                    wxString msg;
+                    msg.Printf(_("Error loading package template '%s':\n\n%s"), default_template.c_str (), exception.get_message ().c_str ());
+                    wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+                }
+                catch (...) {
+                    wxString msg;
+                    msg.Printf(_("Error loading package template '%s'."), default_template.c_str ());
+                    wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+                }
+
+                // check the configuration
+                wxASSERT (NewCdlConfig->check_this (cyg_extreme));
+
+                // use the new package database, interpreter and configuration
+                delete m_CdlConfig; // delete the previous configuration
+                delete m_CdlInterp; // delete the previous interpreter
+                delete m_CdlPkgData; // delete the previous package database
+
+                m_CdlPkgData = NewCdlPkgData;
+                m_CdlInterp  = NewCdlInterp;
+                m_CdlConfig  = NewCdlConfig;
+
+                // save the repository location
+
+                SetRepository(strNewRepository);
+                m_strPackagesDir = strNewPackagesDir;
+
+                // clear the previously specified document file name (if any),
+                // OnNewDocument() calls DeleteContents() so must be called
+                // before AddAllItems()
+
+                wxDocument::OnNewDocument ();
+
+                // generate the CConfigItems from their CDL descriptions
+                AddAllItems ();
+
+                m_bRepositoryOpen=TRUE;
+
+                // Rebuild help index if it needs building
+                RebuildHelpIndex(FALSE);
+
+            } else {
+                // failure
+                delete NewCdlConfig; NewCdlConfig = NULL;
+                delete NewCdlInterp; NewCdlInterp = NULL;
+                delete NewCdlPkgData; NewCdlPkgData = NULL;
+
+            }
+
+            // install a transaction handler callback function now that the tree exists
+            EnableCallbacks(TRUE);
+        }
+
+    }
+    wxGetApp().SetStatusText(wxEmptyString, FALSE);
+    return m_bRepositoryOpen;
+}
+
+// Find a valid repository given a directory name
+bool ecConfigToolDoc::FindRepository (ecFileName& repositoryIn, ecFileName& repositoryOut) const
+{
+    if (repositoryIn.IsEmpty())
+       return FALSE;
+    
+    if (ecFileName(repositoryIn + wxT("ecos.db")).Exists())
+    {
+       repositoryOut = repositoryIn;
+       repositoryIn = wxPathOnly(repositoryIn);
+       return TRUE;
+    }
+    else if (ecFileName(ecFileName(repositoryIn) + ecFileName(wxT("ecc")) + wxT("ecos.db")).Exists())
+    {
+       repositoryOut = repositoryIn + wxT("ecc");
+       return TRUE;
+    }
+    else if (ecFileName(ecFileName(repositoryIn) + ecFileName(wxT("packages")) + wxT("ecos.db")).Exists())
+    {
+       repositoryOut = repositoryIn + wxT("packages");
+       return TRUE;
+    }
+    else
+    {
+       return FALSE;
+    }
+}
+
+
+bool ecConfigToolDoc::OpenRepository (ecFileName& strNewRepository, CdlPackagesDatabase &NewCdlPkgData,CdlInterpreter &NewCdlInterp,CdlConfiguration &NewCdlConfig, wxString &strNewPackagesDir)
+{
+    bool rc=FALSE;
+
+    if (strNewRepository.IsEmpty())
+        return FALSE;
+
+    ecFileName strNewPackagesDir1;
+    if (!FindRepository(strNewRepository, strNewPackagesDir1))
+    {
+        wxString msg;
+        msg.Printf(_("%s does not seem to be a source repository."),
+                    (const wxChar*) strNewRepository);
+        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+    } else
+    {
+                strNewPackagesDir = strNewPackagesDir1;
+
+                const wxString strDatabase = strNewPackagesDir + wxString(wxFILE_SEP_PATH) + wxT("ecos.db");
+                if(!wxFileExists(strDatabase))
+                {
+                    wxString msg;
+                    msg.Printf(_("%s does not seem to be a source repository: %s does not exist"), (const wxChar*) strNewRepository, (const wxChar*) strDatabase);
+                    wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+                } else
+               {
+
+                    // create a CDL repository, interpreter and configuration
+                    try {// create a new package database, interpreter and configuration
+                        NewCdlPkgData = CdlPackagesDatabaseBody::make ((const wxChar*) strNewPackagesDir, &CdlParseErrorHandler, &CdlParseWarningHandler);
+                        NewCdlInterp = CdlInterpreterBody::make ();
+                        NewCdlConfig = CdlConfigurationBody::make ("eCos", NewCdlPkgData, NewCdlInterp);
+                    }
+                    catch (CdlStringException exception)
+                    {
+                        wxString msg;
+                        msg.Printf(_("Error opening eCos repository:\n\n%s"), exception.get_message ().c_str ());
+                        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+                        return FALSE;
+                    }
+                    catch (...)
+                    {
+                        wxString msg;
+                        msg.Printf(_("Error opening eCos repository."));
+                        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+                        return FALSE;
+                    }
+
+                    // select the default target if specified in the registry
+                    // otherwise select the first available target
+                    wxString default_hardware = GetDefaultHardware ();
+
+                    if (! NewCdlPkgData->is_known_target ((const wxChar*) default_hardware)) {
+                        const std::vector<std::string>& targets = NewCdlPkgData->get_targets ();
+                        if (targets.size () == 0)
+                        {
+                            wxString msg;
+                            msg.Printf(_("Error opening eCos repository:\n\nno hardware templates"));
+                            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+                            return FALSE;
+                        } else {
+                            default_hardware = targets [0].c_str();
+                        }
+                    }
+
+                    try {
+                        m_strCdlErrorMessage = wxT("");
+                        NewCdlConfig->set_hardware ((const wxChar*) default_hardware, &CdlParseErrorHandler, &CdlParseWarningHandler);
+                    }
+                    catch (CdlStringException exception) {
+                        if (m_strCdlErrorMessage.IsEmpty ())
+                        {
+                            wxString msg;
+                            msg.Printf(_("Error loading the default hardware template '%s':\n\n%s"), default_hardware.c_str (), exception.get_message ().c_str ());
+                            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+                        }
+                        else // report the most recent parser message in the message box since there may be no output pane in which to view it
+                        {
+                            wxString msg;
+                            msg.Printf(_("Error loading the default hardware template '%s':\n\n%s\n\nParser message:\n\n%s"), default_hardware.c_str (), exception.get_message ().c_str (), (const wxChar*) m_strCdlErrorMessage);
+                            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+                        }
+                        return FALSE;
+                    }
+                    catch (...) {
+                        wxString msg;
+                        msg.Printf(_("Error loading the default hardware template '%s':\n\n%s"), default_hardware.c_str (), (const wxChar*) m_strCdlErrorMessage);
+                        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+                        return FALSE;
+                    }
+                    rc=TRUE;
+                }
+    }
+
+    return rc;
+}
+
+void ecConfigToolDoc::SelectTemplate (const wxString& newTemplate, const wxString& newTemplateVersion)
+{
+    if ((newTemplate != m_CdlConfig->get_template().c_str()) || (newTemplateVersion != m_templateVersion)){
+
+        wxBusyCursor wait; // this may take a little while
+        DeleteItems();
+
+        m_templateVersion = wxT("");
+        try
+        {
+            m_CdlConfig->set_template (newTemplate.c_str(), newTemplateVersion.c_str(), CdlParseErrorHandler, CdlParseWarningHandler);
+            m_templateVersion = newTemplateVersion;
+        }
+        catch (CdlStringException exception)
+        {
+            wxString msg;
+            msg.Printf(wxT("Error loading package template '%s':\n\n%s"), (const wxChar*) newTemplate.c_str (), (const wxChar*) exception.get_message ().c_str ());
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+        }
+        catch (...)
+        {
+            wxString msg;
+            msg.Printf(wxT("Error loading package template '%s'."), (const wxChar*) newTemplate.c_str ());
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+        }
+        RegenerateData();
+
+        if (!GetFilename().IsEmpty())
+        { // not a new document
+#if 0 // TODO
+            CopyMLTFiles (); // copy new MLT files to the build tree as necessary
+#endif
+        }
+        Modify(TRUE);
+        wxGetApp().GetMainFrame()->UpdateFrameTitle();
+    }
+}
+
+void ecConfigToolDoc::RegenerateData()
+{
+    wxBusyCursor wait; // This may take a little while
+    AddAllItems (); // regenerate all the config items since the topology may have changed
+    if (m_strLinkerScriptFolder.IsEmpty ())
+    {
+        wxMessageBox(_("The eCos linker script macro CYGBLD_LINKER_SCRIPT is not defined."), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+    }
+    if (m_strMemoryLayoutFolder.IsEmpty ())
+    {
+        wxMessageBox(_("The eCos memory layout macro CYGHWR_MEMORY_LAYOUT is not defined."), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+    }
+    // TODO
+#if 0
+    SwitchMemoryLayout (TRUE); // the hardware template may have changed
+#endif
+
+    if (GetDocumentSaved() && !wxGetApp().GetSettings().m_editSaveFileOnly)
+        UpdateBuildInfo();
+    
+    // TODO
+    // CConfigTool::GetControlView()->SelectItem(Item(0));
+}
+
+void ecConfigToolDoc::SelectHardware (const wxString& newTemplate)
+{
+    const std::string OldTemplate=m_CdlConfig->get_hardware();
+    if (newTemplate != OldTemplate.c_str()){
+        DeleteItems();
+
+        try
+        {
+            m_CdlConfig->set_hardware (newTemplate.c_str(), CdlParseErrorHandler, CdlParseWarningHandler);
+        }
+        catch (CdlStringException exception)
+        {
+            wxString msg;
+            msg.Printf(_("Error loading hardware template '%s':\n\n%s"), (const wxChar*) newTemplate, (const wxChar*) exception.get_message ().c_str ());
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+            m_CdlConfig->set_hardware (OldTemplate, CdlParseErrorHandler, CdlParseWarningHandler);
+        }
+        catch (...)
+        {
+            wxString msg;
+            msg.Printf(_("Error loading hardware template '%s'."), (const wxChar*) newTemplate);
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+            m_CdlConfig->set_hardware (OldTemplate, CdlParseErrorHandler, CdlParseWarningHandler);
+        }
+
+        RegenerateData();
+
+        // TODO
+#if 0
+        if (!GetFilename().IsEmpty())
+        {
+            CopyMLTFiles (); // copy new MLT files to the build tree as necessary
+        }
+#endif
+
+        Modify(TRUE);
+        wxGetApp().GetMainFrame()->UpdateFrameTitle();
+    }
+}
+
+void ecConfigToolDoc::SelectPackages ()
+{
+    // Crashes the Cygwin 1.0 compiler
+#ifndef __CYGWIN10__
+    ecPackagesDialog dlg(wxGetApp().GetTopWindow());
+
+    // This map holds the ecConfigItem pointers for the packages loaded before the dialog is invoked.
+    // We cannot use Find(), which traverses all items - potentially those that have been removed
+    wxHashTable arLoadedPackages(wxKEY_STRING);
+
+    wxBeginBusyCursor();
+
+    // generate the contents of the add/remove list boxes
+    const std::vector<std::string> & packages = m_CdlPkgData->get_packages ();
+    std::vector<std::string>::const_iterator package_i;
+    for (package_i = packages.begin (); package_i != packages.end (); package_i++)
+    {
+        //             if (! m_CdlPkgData->is_hardware_package (* package_i)) // do not list hardware packages
+        {
+            const std::vector<std::string> & aliases = m_CdlPkgData->get_package_aliases (* package_i);
+            wxString strMacroName = package_i->c_str ();
+
+            // use the first alias (if any) as the package identifier
+            wxString strPackageName = aliases.size () ? aliases [0].c_str () : strMacroName.c_str();
+            ecConfigItem * pItem = Find (strMacroName);
+            if (pItem) // if the package is loaded
+            {
+                arLoadedPackages.Put(strMacroName, pItem);
+                // pass the currently selected package version string to the dialog box
+                const CdlValuable valuable = pItem->GetCdlValuable();
+                dlg.Insert (strPackageName, TRUE, wxEmptyString, valuable ? wxString (valuable->get_value ().c_str ()) : wxString());
+            }
+            else
+            {
+                // pass version string of the most latest version to the dialog box
+                dlg.Insert (strPackageName, FALSE, wxEmptyString, wxString (m_CdlPkgData->get_package_versions (* package_i) [0].c_str ()));
+            }
+        }
+    }
+
+    wxEndBusyCursor();
+
+    if (wxID_OK == dlg.ShowModal ())
+    {
+        bool bChanged = FALSE; // until proved otherwise
+
+        // determine whether each package has changed loaded/unloaded state
+        for (package_i = packages.begin (); package_i != packages.end (); package_i++)
+            //                 if (! m_CdlPkgData->is_hardware_package (* package_i)) // do not check hardware packages
+        {
+            const std::vector<std::string> & aliases = m_CdlPkgData->get_package_aliases (* package_i);
+            wxString strMacroName = package_i->c_str ();
+
+            // use the first alias (if any) as the package identifier
+            wxString strPackageName = aliases.size () ? aliases [0].c_str () : strMacroName.c_str();
+
+            ecConfigItem *pItem = (ecConfigItem *) arLoadedPackages.Get(strMacroName);
+            //bool bPreviouslyLoaded=arLoadedPackages.Lookup(strMacroName,(void *&)pItem);
+            bool bPreviouslyLoaded = (pItem != NULL);
+            bool bNowLoaded=dlg.IsAdded (strPackageName);
+
+            // unload packages which are no longer required before
+            // loading new ones to avoid potential duplicate macro definitions
+            if (! bNowLoaded && bPreviouslyLoaded){
+                // The package was loaded but should now be unloaded:
+                bChanged|=pItem->Unload();
+            } else if (bNowLoaded) {// if the package should be loaded
+                const wxString strVersion(dlg.GetVersion (strPackageName));
+                if (bPreviouslyLoaded) { // if the package is already loaded
+                    CdlTransactionCallback::set_callback_fn (NULL); // avoid value refresh attempts during load/unload
+                    bChanged|=pItem->ChangeVersion(strVersion);
+                    CdlTransactionCallback::set_callback_fn (CdlTransactionHandler); // restore value refresh
+                } else {
+                    // the package was not loaded but should now be loaded
+                    //TRACE (_T("Loading package %s\n"), strMacroName);
+                    try
+                    {
+                        GetCdlConfig()->load_package (ecUtils::UnicodeToStdStr(strMacroName), ecUtils::UnicodeToStdStr (strVersion), ecConfigToolDoc::CdlParseErrorHandler, ecConfigToolDoc::CdlParseWarningHandler);
+                        bChanged=true;
+                    }
+                    catch (CdlStringException exception)
+                    {
+                        wxString msg;
+                        msg.Printf(_("Error loading package %s:\n\n%s"), (const wxChar*) strMacroName, (const wxChar*) exception.get_message ().c_str ());
+                        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+                    }
+                    catch (...)
+                    {
+                        wxString msg;
+                        msg.Printf(_("Error loading package %s"), (const wxChar*) strMacroName);
+                        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+                    }
+                }
+            }
+        }
+
+        if (bChanged) {// at least one package was loaded, unloaded or changed version
+            Modify(TRUE);
+            wxGetApp().GetMainFrame()->UpdateFrameTitle();
+            RegenerateData();
+        }
+    }
+#endif
+}
+
+
+bool ecConfigToolDoc::UpdateBuildInfo(bool WXUNUSED(bFirstTime))
+{
+    try {
+        GetCdlConfig()->get_build_info(m_BuildInfo);
+        generate_build_tree (GetCdlConfig(), ecUtils::UnicodeToStdStr(GetBuildTree()), ecUtils::UnicodeToStdStr(GetInstallTree()));
+        return TRUE;
+    }
+    catch(...){
+        return FALSE;
+    }
+}
+
+wxString ecConfigToolDoc::GetDefaultHardware ()
+{
+#ifdef __WXMSW__
+    // get the greatest eCos version subkey
+    wxConfig config(wxT("eCos"), wxEmptyString, wxEmptyString, wxEmptyString, wxCONFIG_USE_GLOBAL_FILE);
+
+    wxString versionKey(wxT(""));
+    wxString key(wxT(""));
+    long index;
+    bool bMore = config.GetFirstGroup(key, index);
+    while (bMore)
+    {
+        if (wxIsdigit(key.GetChar(0)) && versionKey.CompareTo(key) < 0)
+            versionKey = key;
+
+        bMore = config.GetNextGroup(key, index);
+    }
+
+    if (!versionKey.IsEmpty())
+    {
+        wxString defaultHardware;
+        wxString defaultHardwareKey(versionKey + wxString(wxT("/")) + wxString(wxT("Default Hardware")));
+        if (config.Read(defaultHardwareKey, & defaultHardware))
+        {
+            return defaultHardware;
+        }
+    }
+    return wxEmptyString;
+#else
+    // For other platforms, simply rely on Cdl to get the default hardware.
+    return wxEmptyString;
+#endif
+}
+
+void ecConfigToolDoc::EnableCallbacks (bool bEnable/*=TRUE*/)
+{
+    CdlTransactionCallback::set_callback_fn(bEnable?&CdlTransactionHandler:0);
+    CdlTransactionBody::set_inference_callback_fn(bEnable?&CdlInferenceHandler:0);
+    CdlTransactionBody::set_inference_override(CdlValueSource_Invalid);
+}
+
+CdlInferenceCallbackResult ecConfigToolDoc::CdlGlobalInferenceHandler(CdlTransaction transaction)
+{
+    CdlInferenceCallbackResult rc=CdlInferenceCallbackResult_Continue;
+
+    ecConfigToolDoc *pDoc = wxGetApp().GetConfigToolDoc();
+    pDoc->m_ConflictsOutcome=NotDone;  // prepare for the case that there are no solutions
+
+    const std::list<CdlConflict>& conflicts=pDoc->GetCdlConfig()->get_all_conflicts();
+    ecResolveConflictsDialog dlg(wxGetApp().GetTopWindow(), conflicts, transaction, &pDoc->m_arConflictsOfInterest);
+
+    rc = (wxID_OK == dlg.ShowModal()) ? CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel;
+    pDoc->m_ConflictsOutcome=(CdlInferenceCallbackResult_Continue==rc)?OK:Cancel;
+
+    return rc;
+}
+
+CdlInferenceCallbackResult ecConfigToolDoc::CdlInferenceHandler (CdlTransaction transaction)
+{
+    CdlInferenceCallbackResult rc=CdlInferenceCallbackResult_Continue;
+
+    ecConfigToolDoc *pDoc=wxGetApp().GetConfigToolDoc();
+    const std::list<CdlConflict>&conflicts=transaction->get_new_conflicts();
+    if ((wxGetApp().GetSettings().m_nRuleChecking & ecSettings::Immediate) && conflicts.size()>0)
+    {
+        if (wxGetApp().GetSettings().m_nRuleChecking & ecSettings::SuggestFixes)
+        {
+            std::list<CdlConflict> s_conflicts;
+            for (std::list<CdlConflict>::const_iterator conf_i= conflicts.begin (); conf_i != conflicts.end (); conf_i++) { // for each conflict
+                if((*conf_i)->has_known_solution()){
+                    s_conflicts.push_back(*conf_i);
+                }
+            }
+            if(s_conflicts.size()>0)
+            {
+                wxGetApp().LockValues();
+
+                ecResolveConflictsDialog dlg(wxGetApp().GetTopWindow(), s_conflicts, transaction);
+                int ret = dlg.ShowModal() ;
+
+                wxGetApp().UnlockValues();
+
+                return (wxID_OK == ret ? CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel);
+            }
+        }
+
+        wxGetApp().LockValues();
+
+        wxString strMsg;
+        if(1==conflicts.size()){
+            strMsg=wxT("There is 1 unresolved conflict. Make the change anyway?");
+        } else {
+            strMsg.Printf(_("There are %d unresolved conflict%s. Make the change anyway?"), conflicts.size(), (const wxChar*) (1==conflicts.size()? wxT(""):wxT("s")) );
+        }
+        rc = (wxYES == wxMessageBox(strMsg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxYES_NO)) ? CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel;
+
+        wxGetApp().UnlockValues();
+
+    }
+    return rc;
+}
+
+
+// a CDL transaction handler to refresh the configuration tree
+void ecConfigToolDoc::CdlTransactionHandler (const CdlTransactionCallback & data)
+{
+    static int nNesting=0;
+    //TRACE(_T("Transaction handler: nesting level=%d\n"),nNesting++);
+    ecConfigToolDoc *pDoc = wxGetApp().GetConfigToolDoc();
+
+    std::vector<CdlValuable>::const_iterator val_i;
+    std::vector<CdlNode>::const_iterator node_i;
+    std::list<CdlConflict>::const_iterator conf_i;
+    ecConfigToolView *pControlView = (ecConfigToolView*) pDoc->GetFirstView();
+
+    for (val_i = data.value_changes.begin(); val_i != data.value_changes.end(); val_i++)
+    {
+        const wxString strName((*val_i)->get_name().c_str());
+        //TRACE(_T("%s %s : value change\n"), wxString ((*val_i)->get_class_name().c_str()), strName);
+        pControlView->Refresh(strName);
+        if (strName==wxT("CYGHWR_MEMORY_LAYOUT")){               // the memory layout has changed...
+            // TODO
+            // pDoc->SwitchMemoryLayout (FALSE); // ...so display a new one
+        }
+    }
+    for (node_i = data.active_changes.begin(); node_i != data.active_changes.end(); node_i++)
+    {
+        const wxString strName((*node_i)->get_name().c_str());
+        //TRACE(_T("%s %s : this has become active or inactive\n"), CString ((*node_i)->get_class_name().c_str()),
+        //    CString ((*node_i)->get_name().c_str()));
+        if (! dynamic_cast<CdlInterface> (*node_i)){ // if not an interface node
+            pControlView->Refresh(strName);
+        }
+    }
+    for (val_i = data.legal_values_changes.begin(); val_i != data.legal_values_changes.end(); val_i++)
+    {
+        const wxString strName((*node_i)->get_class_name().c_str());
+        //TRACE(_T("%s %s : the legal_values list has changed, a new widget may be needed.\n"),
+        //    CString ((*val_i)->get_class_name().c_str()), strName);
+    }
+
+    for (val_i = data.value_source_changes.begin(); val_i != data.value_source_changes.end(); val_i++)
+    {
+        const wxString strName((*val_i)->get_name().c_str());
+        CdlValueSource source = (*val_i)->get_source();
+/*
+        TRACE(_T("%s %s : the value source has changed to %s\n"),
+            CString ((*val_i)->get_class_name().c_str()), strName,
+            CString ((CdlValueSource_Default  == source) ? "default"  :
+        (CdlValueSource_Inferred == source) ? "inferred" :
+        (CdlValueSource_Wizard   == source) ? "wizard"   : "user"));
+*/
+        pControlView->Refresh (strName);
+    }
+
+    pDoc->UpdateFailingRuleCount();
+    nNesting--;
+}
+
+bool ecConfigToolDoc::ShowURL(const wxString& strURL1)
+{
+    bool rc = TRUE;
+
+    wxString strURL(strURL1);
+
+/*
+    if(!QualifyDocURL(strURL)){
+        return FALSE; // error message already output
+    }
+*/
+
+    switch (wxGetApp().GetSettings().m_eUseCustomBrowser)
+    {
+    case ecInternal:
+        rc = ShowInternalHtmlHelp(strURL);
+        break;
+    case ecAssociatedExternal:
+        {
+            rc = ShowExternalHtmlHelp(strURL);
+        }
+
+        break;
+    case ecCustomExternal:
+        QualifyDocURL(strURL, FALSE);
+        wxGetApp().Launch(strURL, wxGetApp().GetSettings().m_strBrowser);
+        break;
+    default:
+        wxASSERT(FALSE);
+    }
+    return rc;
+}
+
+bool ecConfigToolDoc::ShowExternalHtmlHelp (const wxString& strURL)
+{
+#if defined(__WXMSW__) || defined(__WXGTK__)
+
+    wxString url;
+
+    wxString sep(wxFILE_SEP_PATH);
+    wxString docDir(wxString(m_strRepository) + sep + wxString(wxT("doc")));
+    if (wxDirExists(docDir + sep + wxT("html")))
+        docDir += sep + wxT("html") ;
+
+    if (strURL.Left(7) == wxT("http://") || strURL.Left(7) == wxT("file://"))
+        url = strURL;
+    else
+    {
+       if (wxIsAbsolutePath(strURL))
+           url = strURL;
+       else
+            url = docDir + sep + strURL;
+    }
+
+    wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(wxT("html"));
+    if ( !ft )
+    {
+        wxLogError(_T("Impossible to determine the file type for extension html"));
+        return FALSE;
+    }
+
+    wxString cmd;
+    bool ok = ft->GetOpenCommand(&cmd,
+                                 wxFileType::MessageParameters(url, _T("")));
+    delete ft;
+
+    if (!ok)
+    {
+        // TODO: some kind of configuration dialog here.
+        wxMessageBox(_("Could not determine the command for running the browser."),
+                  wxGetApp().GetSettings().GetAppName(), wxOK|wxICON_EXCLAMATION);
+        return FALSE;
+    }
+
+    // Remove spurious file:// if added
+#ifdef __WXMSW__
+    if (strURL.Left(7) == wxT("http://"))
+        cmd.Replace(wxT("file://"), wxT(""));
+#endif
+
+    ok = (wxExecute(cmd, FALSE) != 0);
+
+    return ok;
+
+    // Old code using MS HTML Help
+#elif 0
+    HWND hwndCaller = ::GetDesktopWindow();
+
+    wxString helpFile(wxGetApp().GetHelpFile());
+    bool rc = FALSE;
+    const ecFileName strFile(HTMLHelpLinkFileName());
+    if (wxFileExists(strFile))
+        wxRemoveFile(strFile);
+
+    wxTextFile f(strFile);
+    if(!ecFileName(helpFile).Exists())
+    {
+        wxString msg;
+        msg.Printf(_("Cannot display help - %s does not exist"), (const wxChar*) helpFile);
+        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+    } else if (!f.Create())
+    {
+        wxString msg;
+        msg.Printf(_("Cannot display help - error creating %s"), (const wxChar*) strFile);
+        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+    } else
+    {
+        wxString str;
+        str.Printf(_T("<meta HTTP-EQUIV=\"refresh\" CONTENT=\"0;URL=%s\">"), (const wxChar*) strURL);
+        f.AddLine(str);
+        f.Write();
+        f.Close();
+        if(0==HtmlHelp(hwndCaller, wxGetApp().GetHelpFile(), HH_DISPLAY_TOPIC, 0))
+        {
+            wxString msg;
+            msg.Printf(_("Cannot display %s"), (const wxChar*) strURL);
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+        }
+#if 0
+        else
+        {
+            // JACS: I don't think we need to do this. Even on the MFC version, the notification
+            // callback didn't do anything interesting.
+#define ID_HHNOTIFICATION               55017
+
+            // FIXME: Do this the first time only?
+            HH_WINTYPE WinType;
+            HWND wnd;
+            HH_WINTYPE *pWinType=NULL;
+            wxString s = wxGetApp().GetHelpFile() + wxT(">mainwin");
+            wnd = HtmlHelp(hwndCaller, s, HH_GET_WIN_TYPE, (DWORD) &pWinType);
+            WinType=*pWinType;
+            WinType.hwndCaller=hwndCaller;
+            WinType.fsWinProperties|=HHWIN_PROP_TRACKING;
+            WinType.idNotify = ID_HHNOTIFICATION;
+            wnd = HtmlHelp(hwndCaller, wxGetApp().GetHelpFile(), HH_SET_WIN_TYPE, (DWORD) &WinType);
+            rc = TRUE;
+        }
+#endif
+        //wxRemoveFile(strFile);
+    }
+    return rc;
+
+#else
+    wxMessageBox(_("Sorry, ShowHtmlHelp not yet implemented"), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+    return FALSE;
+#endif
+}
+
+bool ecConfigToolDoc::ShowInternalHtmlHelp (const wxString& strURL)
+{
+#if defined(__WXMSW__) || defined(__WXGTK__)
+
+    wxString url(strURL);
+
+    wxString sep(wxFILE_SEP_PATH);
+    wxString docDir(wxString(m_strRepository) + sep + wxString(wxT("doc")));
+    if (wxDirExists(docDir + sep + wxT("html")))
+        docDir += sep + wxT("html") ;
+
+    url = docDir + sep + ecHtmlIndexer::Redirect(docDir, url);
+
+#if 0
+    if (strURL.Left(7) == wxT("http://") || strURL.Left(7) == wxT("file://"))
+        url = strURL;
+    else
+        url = docDir + sep + strURL;
+#endif
+
+    //url = url.Mid(docDir.Length() + 1);
+
+    if (wxGetApp().HasHelpController())
+    {
+        return wxGetApp().GetHelpController().Display(url);
+    }
+    else
+        return FALSE;
+
+    // Old code using MS HTML Help
+#elif 0
+    HWND hwndCaller = ::GetDesktopWindow();
+
+    wxString helpFile(wxGetApp().GetHelpFile());
+    bool rc = FALSE;
+    const ecFileName strFile(HTMLHelpLinkFileName());
+    if (wxFileExists(strFile))
+        wxRemoveFile(strFile);
+
+    wxTextFile f(strFile);
+    if(!ecFileName(helpFile).Exists())
+    {
+        wxString msg;
+        msg.Printf(_("Cannot display help - %s does not exist"), (const wxChar*) helpFile);
+        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+    } else if (!f.Create())
+    {
+        wxString msg;
+        msg.Printf(_("Cannot display help - error creating %s"), (const wxChar*) strFile);
+        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+    } else
+    {
+        wxString str;
+        str.Printf(_T("<meta HTTP-EQUIV=\"refresh\" CONTENT=\"0;URL=%s\">"), (const wxChar*) strURL);
+        f.AddLine(str);
+        f.Write();
+        f.Close();
+        if(0==HtmlHelp(hwndCaller, wxGetApp().GetHelpFile(), HH_DISPLAY_TOPIC, 0))
+        {
+            wxString msg;
+            msg.Printf(_("Cannot display %s"), (const wxChar*) strURL);
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+        }
+    }
+    return rc;
+
+#else
+    wxMessageBox(_("Sorry, ShowHtmlHelp not yet implemented"), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+    return FALSE;
+#endif
+}
+
+const wxString ecConfigToolDoc::HTMLHelpLinkFileName()
+{
+    return ecFileName(wxGetApp().GetHelpFile()).Head() + wxT("link2.htm");
+}
+
+bool ecConfigToolDoc::QualifyDocURL(wxString &strURL, bool prefix)
+{
+    if(-1==strURL.Find(wxT("://")))
+    {
+#ifdef __WXMSW__
+        strURL.Replace(wxT("/"), wxT("\\"));
+#endif
+        wxString originalURL(strURL);
+
+        if (! ecFileName (strURL).IsFile ())
+        { // if not an absolute filepath
+            strURL = GetDocBase () + ecFileName (originalURL); // prepend the doc directory path
+        }
+        if (!wxFileExists(strURL))
+            strURL = GetDocBase() + ecFileName(wxT("html")) + ecFileName(originalURL);
+
+        if (prefix)
+            strURL = wxT("file://") + strURL;
+    }
+
+    if(0==strURL.Find(wxT("file://")))
+    {
+        ecFileName strFile(strURL.Right(strURL.Length()-7));
+        int nIndex=strFile.Find(wxT('#'), TRUE);
+
+        if ( -1 != nIndex )
+        {
+            strFile=strFile.Left(nIndex);
+        }
+#ifdef __WXMSW__
+        strFile.Replace(wxT("/"), wxT("\\"));
+#endif
+
+        if(!strFile.Exists())
+        {
+            wxString msg;
+            msg.Printf(_("Cannot locate the file %s"), (const wxChar*) strFile);
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxID_OK);
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+wxString ecConfigToolDoc::GetPackageName (const wxString & strAlias)
+{
+    const std::vector<std::string> & packages = m_CdlPkgData->get_packages ();
+    std::vector<std::string>::const_iterator package_i;
+    for (package_i = packages.begin (); package_i != packages.end (); package_i++)
+    {
+        const std::vector<std::string> & aliases = m_CdlPkgData->get_package_aliases (* package_i);
+        wxString strPackageAlias = aliases [0].c_str ();
+        if (aliases.size () && (strAlias == strPackageAlias))
+            return package_i->c_str ();
+    }
+    return wxEmptyString;
+}
+
+const wxString ecConfigToolDoc::GetCurrentTargetPrefix()
+{
+    ecConfigItem *pItem = Find(wxT("CYGBLD_GLOBAL_COMMAND_PREFIX"));
+    if (pItem)
+        return pItem->StringValue();
+    else
+        return wxT("");
+}
+
+ecConfigToolDoc::GlobalConflictOutcome ecConfigToolDoc::ResolveGlobalConflicts(wxList *parConflictsOfInterest)
+{
+    m_ConflictsOutcome=NotDone;
+    m_arConflictsOfInterest.Clear();
+    if(parConflictsOfInterest)
+    {
+        wxNode* node = parConflictsOfInterest->First();
+        while (node)
+        {
+            wxObject* obj = (wxObject*) node->Data();
+            m_arConflictsOfInterest.Append(obj);
+            node = node->Next();
+        }
+    }
+    CdlInferenceCallback fn=CdlTransactionBody::get_inference_callback_fn();
+    CdlTransactionBody::set_inference_callback_fn(CdlGlobalInferenceHandler);
+    GetCdlInterpreter()->get_toplevel()->resolve_all_conflicts();
+    CdlTransactionBody::set_inference_callback_fn(fn);
+    if(NotDone==m_ConflictsOutcome){
+        // No solutions were available, but we'll run the dialog anyway
+        const std::list<CdlConflict>& conflicts=GetCdlConfig()->get_all_conflicts();
+        ecResolveConflictsDialog dlg(wxGetApp().GetTopWindow(), conflicts, NULL, &m_arConflictsOfInterest);
+        m_ConflictsOutcome = (wxID_OK == dlg.ShowModal())?OK:Cancel;
+    }
+    return m_ConflictsOutcome;
+}
+
+bool ecConfigToolDoc::CheckConflictsBeforeSave()
+{
+    if (GetCdlInterpreter()->get_toplevel()->get_all_conflicts().size()>0)
+    {
+        if(ecSettings::Deferred & wxGetApp().GetSettings().m_nRuleChecking)
+        {
+            if ((ecSettings::SuggestFixes & wxGetApp().GetSettings().m_nRuleChecking) &&
+                (Cancel==ResolveGlobalConflicts()))
+            {
+                return FALSE;
+            }
+            int nConflicts = GetCdlInterpreter()->get_toplevel()->get_all_conflicts().size();
+            switch (nConflicts)
+            {
+            case 0:
+                break;
+            case 1:
+                {
+                    wxString msg;
+                    msg.Printf(_("There is 1 unresolved conflict. Save anyway?"));
+                    if (wxNO == wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxYES_NO))
+                    {
+                        return FALSE;
+                    }
+                }
+            default:
+                {
+                    wxString msg;
+                    msg.Printf(_("There are %d unresolved conflicts. Save anyway?"), nConflicts);
+                    if (wxNO == wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxYES_NO))
+                    {
+                        return FALSE;
+                    }
+                }
+            }
+        }
+    }
+    return TRUE;
+}
+
+void ecConfigToolDoc::UpdateFailingRuleCount()
+{
+    int nCount=0;
+    if (GetCdlConfig ())
+    {
+        // if configuration information
+
+        // calculate the number of conflicts
+        nCount = GetCdlConfig ()->get_all_conflicts ().size ();
+            //         GetCdlConfig ()->get_structural_conflicts ().size () +    ignore for now
+
+        // update the conflicts view
+        if (wxGetApp().GetMainFrame() && wxGetApp().GetMainFrame()->GetConflictsWindow())
+        {
+            wxGetApp().GetMainFrame()->GetConflictsWindow()->FillRules ();
+        }
+    }
+
+    if (wxGetApp().GetMainFrame())
+    {
+        wxGetApp().GetMainFrame()->SetFailRulePane(nCount);
+    }
+}
+
+void ecConfigToolDoc::LogConflicts (const std::list<CdlConflict> & conflicts)
+{
+    std::list<CdlConflict>::const_iterator conf_i;
+    for (conf_i = conflicts.begin (); conf_i != conflicts.end (); conf_i++) // for each conflict
+    {
+        wxString strExplain = (* conf_i)->get_explanation ().c_str (); // get the conflict explanation
+        wxGetApp().Log (ecUtils::StripExtraWhitespace (strExplain)); // display the message in the output window
+    }
+}
+
+bool ecConfigToolDoc::SetValue (ecConfigItem &ti, double dValue, CdlTransaction transaction/*=NULL*/)
+{
+    wxASSERT (ti.GetOptionType () == ecDouble);
+
+    // test if the new double value is in range
+    const CdlValuable valuable = ti.GetCdlValuable();
+    CdlListValue list_value;
+    CdlEvalContext context (NULL, ti.GetCdlItem (), ti.GetCdlItem ()->get_property (CdlPropertyId_LegalValues));
+    valuable->get_legal_values ()->eval (context, list_value);
+    if (! list_value.is_member (dValue))
+    {
+        if ( dValue == valuable->get_double_value(CdlValueSource_Current) )
+            return FALSE;
+
+        wxString msg;
+        msg.Printf(_("%s is not a legal value for %s.\n\nDo you want to use this value anyway?"),
+            (const wxChar*) ecUtils::DoubleToStr (dValue), (const wxChar*) ti.GetMacro ());
+
+        if (wxNO == wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_QUESTION|wxYES_NO))
+            return FALSE;
+    }
+
+    if (! ti.SetValue (dValue,transaction))
+        return FALSE;
+
+    Modify(TRUE);
+    wxGetApp().GetMainFrame()->UpdateFrameTitle();
+
+    // NB UpdateAllViews isn't in the MFC Configtool for double (though it is for the
+    // other types of value). In theory this should lead to a display inconsistency in the MFC tool.
+    ecConfigToolHint hint(& ti, ecValueChanged);
+    UpdateAllViews (NULL, & hint);
+
+    return TRUE;
+}
+
+bool ecConfigToolDoc::SetValue(ecConfigItem &ti, const wxString &strValue, CdlTransaction transaction/*=NULL*/)
+{
+    // TODO
+#if 0
+    // warn the user if a modified memory layout is about to be discarded
+    if (MemoryMap.map_modified () && (ti.Macro () == _T("CYG_HAL_STARTUP")) &&
+        (IDCANCEL == CUtils::MessageBoxFT (MB_OKCANCEL, _T("Changes to the current memory layout will be lost."))))
+        return false;
+#endif
+
+    bool rc = FALSE;
+
+    switch(ti.GetOptionType())
+    {
+    case ecOptionTypeNone:
+        break;
+    case ecEnumerated:
+    case ecString:
+        rc = ti.SetValue(strValue, transaction);
+        break;
+    case ecLong:
+        {
+            long n;
+            rc = ecUtils::StrToItemIntegerType(strValue,n) && SetValue(ti,n,transaction);
+        }
+        break;
+    case ecDouble:
+        {
+            double dValue;
+            rc = ecUtils::StrToDouble (strValue, dValue) && SetValue (ti, dValue,transaction);
+        }
+        break;
+    default:
+        wxASSERT(FALSE);
+        break;
+
+    }
+    if(rc){
+        Modify(TRUE);
+        wxGetApp().GetMainFrame()->UpdateFrameTitle();
+
+        ecConfigToolHint hint(& ti, ecValueChanged);
+        UpdateAllViews (NULL, & hint);
+    }
+    return rc;
+}
+
+bool ecConfigToolDoc::SetValue(ecConfigItem &ti, long nValue, CdlTransaction transaction/*=NULL*/)
+{
+    switch(ti.GetOptionType())
+    {
+    case ecEnumerated:
+    case ecLong:
+        break;
+    case ecOptionTypeNone:
+    case ecString:
+    default:
+        wxASSERT(FALSE);
+        break;
+    }
+
+    bool rc = FALSE;
+
+    // TODO
+#if 0
+    bool bChangingMemmap = MemoryMap.map_modified () && ((ti.Macro ().Compare (_T ("CYG_HAL_STARTUP")) == 0));
+#endif
+
+    if(nValue==ti.Value())
+    {
+        return TRUE;
+    }
+
+    // test if the new integer value is in range
+    if (ecLong == ti.GetOptionType ())
+    {
+        const CdlValuable valuable = ti.GetCdlValuable();
+        CdlListValue list_value;
+        CdlEvalContext context (NULL, ti.GetCdlItem (), ti.GetCdlItem ()->get_property (CdlPropertyId_LegalValues));
+        valuable->get_legal_values ()->eval (context, list_value);
+        if (! list_value.is_member ((cdl_int) nValue))
+        {
+            if (nValue == (long) valuable->get_integer_value (CdlValueSource_Current))
+                goto Exit;
+
+            wxString msg;
+            msg.Printf(_("%s is not a legal value for %s.\n\nDo you want to use this value anyway?"),
+                (const wxChar*) ecUtils::IntToStr (nValue, wxGetApp().GetSettings().m_bHex), (const wxChar*) ti.GetMacro ());
+            if (wxNO == wxMessageBox (msg, wxGetApp().GetSettings().GetAppName(), wxICON_QUESTION|wxYES_NO))
+                goto Exit;
+        };
+    }
+
+    // TODO
+#if 0
+    // warn the user if the current memory layout has been changed and will be lost
+    // this will happen when the layout has been modified and the target-platform-startup is changed
+
+    if (bChangingMemmap && IDCANCEL==CUtils::MessageBoxFT(MB_OKCANCEL,_T("Changes to the current memory layout will be lost."))){
+        goto Exit;
+    }
+#endif
+
+    // Save state
+    if(!ti.SetValue(nValue,transaction)){
+        // CanSetValue above should have caught this
+        wxString msg;
+        msg.Printf(_("Cannot set '%s' to %d"), (const wxChar*) ti.GetItemNameOrMacro(), nValue);
+        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+        goto Exit;
+    }
+
+    rc = TRUE;
+Exit:
+    if(rc)
+    {
+        Modify(TRUE);
+        wxGetApp().GetMainFrame()->UpdateFrameTitle();
+
+        UpdateFailingRuleCount ();
+
+        ecConfigToolHint hint(& ti, ecValueChanged);
+        UpdateAllViews (NULL, & hint);
+    }
+    return rc;
+}
+
+bool ecConfigToolDoc::SetEnabled(ecConfigItem &ti, bool bEnabled, CdlTransaction transaction/*=NULL*/)
+{
+    const bool bStatus = ti.SetEnabled (bEnabled, transaction);
+
+    if (bStatus)
+    {
+        Modify(TRUE);
+        ecConfigToolHint hint(& ti, ecValueChanged);
+        UpdateAllViews (NULL, & hint);
+    }
+    return bStatus;
+}
+
+const ecFileName ecConfigToolDoc::CurrentLinkerScript()
+{
+    const ecConfigItem * pItem = Find (wxT("CYGBLD_LINKER_SCRIPT"));
+    return pItem ? ecFileName (m_strPackagesDir, m_strLinkerScriptFolder, pItem->StringValue ()) : ecFileName(wxT(""));
+}
+
+
+bool ecConfigToolDoc::GenerateHeaders()
+{
+    wxString sep(wxFILE_SEP_PATH);
+
+    // Generate headers
+    try {
+        ecFileName strPkfConfDir(GetInstallTree());
+        strPkfConfDir += ecFileName(wxT("include"));
+        strPkfConfDir += ecFileName(wxT("pkgconf"));
+        if ( !strPkfConfDir.CreateDirectory())
+        {
+            wxString msg;
+            msg.Printf(_("Failed to create %s"), (const wxChar*) strPkfConfDir);
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION);
+            return FALSE;
+        }
+        GetCdlConfig()->generate_config_headers(ecUtils::UnicodeToStdStr(strPkfConfDir.ShortName()));
+    }
+    catch (CdlInputOutputException e) {
+        const wxString strMsg(e.get_message().c_str());
+        // TRACE(_T("!!! Exception thrown calling generate_config_headers - %s"),strMsg);
+        wxString msg;
+        msg.Printf(_("Failed to generate header files - %s"), (const wxChar*) strMsg);
+        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION);
+        return FALSE;
+    }
+    return TRUE;
+}
+
+const ecFileName ecConfigToolDoc::MLTDir ()
+{
+    wxString strPathName (GetFilename ());
+    wxASSERT (! strPathName.IsEmpty ());
+    return strPathName.Left (strPathName.Find (wxT('.'), TRUE)) + wxT("_mlt");
+}
+
+int ecConfigToolDoc::GetTestExeNames (wxArrayString& arTestExes, wxArrayString& arMissing)
+{
+    arTestExes.Clear();
+    arMissing.Clear();
+    typedef std::vector<CdlBuildInfo_Loadable> EntriesArray;
+    const EntriesArray &arEntries=GetBuildInfo().entries;
+    for(EntriesArray::size_type j=0;j<arEntries.size();j++)
+    {
+        const CdlBuildInfo_Loadable &e=arEntries[j];
+        wxArrayString ar;
+        int n = ecUtils::Chop(wxString(get_tests(GetCdlConfig(),e).c_str()),ar);
+        int i;
+        for (i=0;i<n;i++)
+        {
+            wxString strFile;
+            strFile += GetInstallTree();
+            strFile += wxFILE_SEP_PATH;
+            strFile += wxT("tests");
+            strFile += wxFILE_SEP_PATH;
+            strFile += e.directory.c_str();
+            strFile += wxFILE_SEP_PATH;
+            strFile += ar[i];
+
+            // Some tests accidentally specify .c
+//            wxStripExtension(strFile);
+
+#ifdef __WXMSW__
+//            strFile += wxT(".exe");
+            strFile.Replace(wxT("/"),wxT("\\"));
+#endif
+
+            if (wxFileExists(strFile))
+            {
+                arTestExes.Add(strFile);
+            } else
+            {
+                arMissing.Add(strFile);
+            }
+        }
+    }
+    return arTestExes.Count();
+}
+
+bool ecConfigToolDoc::SaveMemoryMap()
+{
+    // TODO
+#if 0
+    wxString sep(wxFILE_SEP_PATH);
+
+    const wxString strSuffix(wxT("mlt_") + CurrentMemoryLayout ());
+    ecFileName strMLTInstallPkgconfDir(GetInstallTree());
+    strMLTInstallPkgconfDir = strMLTInstallPkgconfDir + ecFileName(wxT("include"));
+    strMLTInstallPkgconfDir = strMLTInstallPkgconfDir + ecFileName(wxT("pkgconf"));
+
+    bool rc=false;
+    if(strMLTInstallPkgconfDir.CreateDirectory(true)){
+        const wxString strMLTInstallBase(strMLTInstallPkgconfDir+ecFileName(strSuffix));
+        const ecFileName strMLTDir (MLTDir());
+
+        if(strMLTDir.CreateDirectory (TRUE))
+        {
+            const wxString strMLTBase (strMLTDir + ecFileName (strSuffix));
+            // TRACE(_T("Saving memory layout to %s\n"), strMLTBase + _T(".mlt"));
+            if(MemoryMap.save_memory_layout (strMLTBase + _T(".mlt"))){
+                // TRACE(_T("Exporting memory layout to %s\n"), strMLTInstallPkgconfDir);
+                rc=MemoryMap.export_files (strMLTInstallBase + _T(".ldi"), strMLTInstallBase + _T(".h"));
+            }
+        }
+    }
+    return rc;
+#else
+    return FALSE;
+#endif
+}
+
+bool ecConfigToolDoc::CopyMLTFiles()
+{
+    wxString sep(wxFILE_SEP_PATH);
+
+    // copy default MLT files for the selected target/platform from the repository if they do not already exist
+
+    // TRACE (_T("Looking for MLT files at %s\n"), PackagesDir() + m_strMemoryLayoutFolder + _T("include\\pkgconf\\mlt_*.*"));
+    const ecFileName strInstallDestination(GetInstallTree () + sep + wxString(wxT("include")) + sep + wxT("pkgconf"));
+    const ecFileName strMLTDestination (MLTDir ());
+    // TRACE (_T("Copying .ldi and .h files to %s\n"), strInstallDestination);
+    // TRACE (_T("Copying .mlt files to %s\n"), strMLTDestination);
+    bool rc=strInstallDestination.CreateDirectory ( TRUE ) && strMLTDestination.CreateDirectory ( TRUE );
+    if (rc)
+    {
+        wxDir ffFileFind;
+        wxString fileName;
+        wxString path = GetPackagesDir();
+        path += sep;
+        path += m_strMemoryLayoutFolder;
+        path += sep;
+        path += wxString(wxT("include"));
+        path += sep;
+        path += wxString(wxT("pkgconf"));
+
+        if (!ffFileFind.Open(path))
+            return FALSE;
+
+        ecFileName wildcard = wxT("mlt_*.*");
+
+        //bool bLastFile = ffFileFind.FindFile (PackagesDir() + m_strMemoryLayoutFolder + wxT("\\include\\pkgconf\\mlt_*.*"));
+        bool bLastFile = ffFileFind.GetFirst (& fileName, wildcard);
+        while (bLastFile)
+        {
+            wxString fullPath = path + sep + fileName;
+
+            if (wxT(".mlt") == fileName.Right (4)) // if a .mlt file
+            {
+                if (! ecFileName (strMLTDestination, ecFileName (fileName)).Exists ())
+                {
+                    if (!wxCopyFile (fullPath, strMLTDestination + ecFileName (fileName)))
+                    {
+                        return FALSE; // message already emitted
+                    }
+                }
+            }
+            else // a .h or .ldi file
+            {
+                if (!ecFileName (strInstallDestination, ecFileName (fileName)).Exists () &&
+                    !wxCopyFile (fullPath, strInstallDestination + ecFileName (fileName))){
+                    return FALSE; // message already emitted
+                }
+            }
+            bLastFile = ffFileFind.GetNext(& fileName);
+        }
+    }
+    return rc; //FIXME
+}
+
+const wxString ecConfigToolDoc::CurrentMemoryLayout ()
+{
+    const ecConfigItem * pItem = Find (wxT("CYGHWR_MEMORY_LAYOUT"));
+
+    wxString str;
+    if (pItem)
+        str = pItem->StringValue ();
+    return str;
+}
+
+bool ecConfigToolDoc::ExportFile()
+{
+    wxFileDialog dialog(wxGetApp().GetTopWindow(), _("Export eCos Minimal Configuration"),
+        wxT(""), wxT(""), wxT("eCos Minimal Configuration (*.ecm)|*.ecm"), wxSAVE|wxOVERWRITE_PROMPT|wxHIDE_READONLY);
+
+    if (dialog.ShowModal() == wxID_OK)
+    {
+        try {
+            m_CdlConfig->save (ecUtils::UnicodeToStdStr (dialog.GetPath()), /* minimal = */ true);
+        }
+        catch (CdlStringException exception)
+        {
+            wxString msg;
+            wxString err(exception.get_message ().c_str ());
+            msg.Printf(_("Error exporting eCos minimal configuration:\n\n%s"), (const wxChar*) err );
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+            return FALSE;
+        }
+        catch (...)
+        {
+            wxString msg;
+            msg.Printf(_("Error exporting eCos minimal configuration"));
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+bool ecConfigToolDoc::ImportFile()
+{
+    wxFileDialog dialog(wxGetApp().GetTopWindow(), _("Import eCos Minimal Configuration"),
+        wxT(""), wxT(""), wxT("eCos Minimal Configuration (*.ecm)|*.ecm"), wxOPEN|wxFILE_MUST_EXIST|wxHIDE_READONLY);
+
+    if (dialog.ShowModal() == wxID_OK)
+    {
+        try {
+            m_CdlConfig->add (ecUtils::UnicodeToStdStr (dialog.GetPath ()), ecConfigToolDoc::CdlParseErrorHandler, ecConfigToolDoc::CdlParseWarningHandler);
+        }
+        catch (CdlStringException exception)
+        {
+            wxString msg;
+            wxString err(exception.get_message ().c_str ());
+            msg.Printf(_("Error importing eCos minimal configuration:\n\n%s"), (const wxChar*) err );
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+            return FALSE;
+        }
+        catch (...)
+        {
+            wxString msg;
+            msg.Printf(_("Error importing eCos minimal configuration"));
+            wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+            return FALSE;
+        }
+
+        wxBusyCursor wait;
+
+        AddAllItems (); // regenerate all the config items since the topology may have changed
+
+        if (m_strLinkerScriptFolder.IsEmpty ())
+        {
+            wxMessageBox(_("The eCos linker script macro CYGBLD_LINKER_SCRIPT is not defined."), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+        }
+        if (m_strMemoryLayoutFolder.IsEmpty ())
+        {
+            wxMessageBox(_("The eCos memory layout macro CYGHWR_MEMORY_LAYOUT is not defined."), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
+        }
+        SwitchMemoryLayout (TRUE); // the hardware template may have changed
+        UpdateBuildInfo ();
+        wxGetApp().GetTreeCtrl()->SelectItem (wxGetApp().GetTreeCtrl()->GetRootItem());
+        Modify(TRUE);
+
+    }
+    return TRUE;
+}
+
+bool ecConfigToolDoc::SwitchMemoryLayout (bool bNewTargetPlatform)
+{
+    bool rc = TRUE;
+    if (bNewTargetPlatform && ! m_strBuildTree.IsEmpty ()) // the user has changed target/platform within a build tree
+    {
+        // copy default MLT save files for the selected target/platform from the repository to the build tree if they do not already exist
+        CopyMLTFiles();
+    }
+
+    if (m_strBuildTree.IsEmpty ()) // load the memory layout from the repository
+    {
+        wxString sep(wxFILE_SEP_PATH);
+        wxString filename(m_strPackagesDir);
+        filename += sep;
+        filename += m_strMemoryLayoutFolder;
+        filename += sep;
+        filename += wxT("include");
+        filename += sep;
+        filename += wxT("pkgconf");
+
+        rc = NewMemoryLayout (ecFileName (filename));
+    }
+    else // load the memory layout from the build tree
+    {
+        rc = NewMemoryLayout (MLTDir ());
+    }
+
+    return TRUE; // FIXME
+}
+
+bool ecConfigToolDoc::NewMemoryLayout (const wxString &strPrefix)
+{
+    // TODO
+#if ecUSE_MLT
+    ecFileName strFileName = CurrentLinkerScript ();
+    wxString sep(wxFILE_SEP_PATH);
+
+    m_memoryMap.new_memory_layout (); // delete the old memory layout regardless
+    if (! strFileName.IsEmpty ())
+        m_memoryMap.import_linker_defined_sections (strFileName); // read the linker-defined section names from the repository (failure is silent)
+
+    wxString strMemoryLayoutFileName = strPrefix + sep + wxString(wxT("mlt_")) + CurrentMemoryLayout () + wxT(".mlt");
+
+    m_memoryMap.load_memory_layout (strMemoryLayoutFileName); // load the new memory layout (failure is silent)
+    m_strSelectedSection = wxT("");
+    m_strSelectedRegion = wxT("");
+
+    wxGetApp().GetMLTWindow()->RefreshMLT();
+
+    // ecConfigToolHint hint(NULL, ecMemLayoutChanged);
+    // UpdateAllViews (NULL, & hint);
+#endif
+
+    return TRUE; // FIXME
+}
+
+void ecConfigToolDoc::RunTests()
+{
+    wxString strTarget(GetCdlConfig()->get_hardware ().c_str ());
+    wxArrayString ar;
+    wxArrayString arTestsMissing;
+    int nTests;
+    wxGetApp().GetSettings().GetRunTestsSettings().m_strTarget = strTarget;
+
+    {
+        wxBusyCursor busy;
+
+        GetCdlConfig()->get_build_info(m_BuildInfo);
+        if (NULL==CeCosTestPlatform::Get(strTarget))
+        {
+            wxString msg;
+            msg.Printf(_("%s is not a recognized platform - do you wish to add it?"), (const wxChar*) strTarget);
+            if (wxNO == wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_QUESTION|wxYES_NO))
+                return;
+            
+            ecPlatformEditorDialog dlg(wxGetApp().GetTopWindow());
+            
+            dlg.m_strPlatform = strTarget;
+            dlg.m_strPrefix = GetCurrentTargetPrefix();
+            dlg.m_strCaption=_("New Platform");
+            if(wxID_CANCEL == dlg.ShowModal())
+            {
+                return;
+            }
+            CeCosTestPlatform::Add(CeCosTestPlatform(dlg.m_strPlatform,dlg.m_strPrefix,dlg.m_strPrompt,dlg.m_strGDB,dlg.m_bServerSideGdb,dlg.m_strInferior));
+            CeCosTestPlatform::Save();
+        }
+        
+        nTests = GetTestExeNames(ar, arTestsMissing);
+    }
+
+    const CeCosTestPlatform * etPlatform = CeCosTestPlatform::Get(strTarget);
+    wxASSERT (NULL != etPlatform);
+
+    if (-1 != wxString (etPlatform->GdbCmds ()).Find (wxT("cyg_test_is_simulator=1")))
+    {   // if a simulator target, disable 'reset hardware' message box
+        wxGetApp().GetSettings().GetRunTestsSettings().m_nReset = RESET_NONE ;
+    }
+
+    // TODO: I think the remote controls was something that wasn't quite implemented in the MFC tool.
+    // It's in the properties dialog, but not used.
+    // sheet.HideRemoteControls();
+    if (arTestsMissing.Count() > 0)
+    {
+        wxString msg;
+        msg.Printf(_("Not all tests are built. Do you wish to build them now?"));
+        if (wxYES == wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_QUESTION|wxYES_NO))
+        {
+            wxGetApp().Build(wxT("tests"));
+            return;
+        }
+    }
+    wxString shellCommands;
+    // Don't know why we passed TRUE (no build tools) but we need build tools for gdb
+    if (wxGetApp().PrepareEnvironment(TRUE /* FALSE */, & shellCommands))
+    {
+        ecRunTestsDialog dialog(wxGetApp().GetTopWindow());
+        int i;
+        for ( i = 0 ; i < nTests; i++)
+        {
+            dialog.Populate(ar[i], TRUE);
+        }
+        for ( i = 0 ; i < arTestsMissing.Count(); i++)
+        {
+            dialog.Populate(arTestsMissing[i], FALSE);
+        }
+
+        dialog.ShowModal();
+    }
+}
+
+// Rebuild the .hhc, .hhp, .hhk files and reinitialize the help controller
+bool ecConfigToolDoc::RebuildHelpIndex(bool force)
+{
+    ecHtmlIndexer indexer(FALSE /* useRelativeURLs */ );
+
+    wxString docDir = GetRepository() ;
+
+    wxString projectFile;
+    if (!indexer.IndexDocs(docDir, projectFile, force))
+    {
+        wxMessageBox("Sorry, could not index documentation.");
+        return FALSE;
+    }
+    else
+    {
+        // Now we need to reset the help controller.
+        wxGetApp().SetHelpFile(projectFile);
+        wxGetApp().InitializeHelpController();
+        return TRUE;
+    }
+}
+