Mercurial > ecos
diff host/tools/configtool/common/win32/CTCommonDoc.cpp @ 76:435cced73e2f ecos-v1_3_1-release
eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
| author | jlarmour |
|---|---|
| date | Tue, 28 Mar 2000 14:10:45 +0000 |
| parents | |
| children | 59d97b6ba612 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/host/tools/configtool/common/win32/CTCommonDoc.cpp @@ -0,0 +1,1847 @@ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// 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#### +#include "stdafx.h" + +#include "ConfigToolDoc.h" + +#ifdef PLUGIN + #include "CTMain.h" + #include "Project.h" + #include "ProjectManager.h" +#else + #include "MainFrm.h" +#endif + +#include "CTUtils.h" +#include "CdlPackagesDialog.h" +#include "ConfigItem.h" +#include "ConfigTool.h" +#include "ControlView.h" +#include "FailingRulesDialog.h" +#include "FolderDialog.h" +#include "IdleMessage.h" +#include "MLTView.h" +#include "NotePage.h" +#include "RegionGeneralPage.h" +#include "RegKeyEx.h" +#include "RulesView.h" +#include "SectionGeneralPage.h" +#include "SectionRelocationPage.h" + +#include <htmlhelp.h> +#include <shlobj.h> + +#define INCLUDEFILE <string> +#include "IncludeSTL.h" +#define INCLUDEFILE "build.hxx" +#include "IncludeSTL.h" + +#ifdef _DEBUG + #define new DEBUG_NEW + #undef THIS_FILE + static char THIS_FILE[] = __FILE__; +#endif + +const CFileName &CConfigToolDoc::DefaultExternalBrowser() +{ + static bool bFirstTime=true; + if(bFirstTime){ + const CFileName strFile(CFileName::GetTempPath()+_T("index.html")); + CFile f; + if(f.Open(strFile,CFile::modeCreate|CFile::modeWrite)){ + f.Close(); + bool rc=((int)FindExecutable(strFile,_T("."),m_strDefaultExternalBrowser.GetBuffer(MAX_PATH))>32); + m_strDefaultExternalBrowser.ReleaseBuffer(); + if(!rc){ + m_strDefaultExternalBrowser=_T(""); + } + ::DeleteFile(strFile); + } + bFirstTime=false; + } + return m_strDefaultExternalBrowser; +} + +CFileName CConfigToolDoc::m_strDefaultExternalBrowser; + +void CConfigToolDoc::CheckRadios() +{ + for(int nItem=0;nItem<ItemCount();nItem++){ + CConfigItem *pItem=Item(nItem); + if(pItem->HasRadio () && pItem==pItem->FirstRadio()){ + CString strMsg; + CConfigItem *pFirstSet=NULL; + for(CConfigItem *pSibItem=pItem;pSibItem;pSibItem=pSibItem->NextRadio()){ + if(pSibItem->IsEnabled ()){ + if(pFirstSet){ + strMsg+=_T(" "); + strMsg+=pSibItem->Macro (); + } else { + pFirstSet=pSibItem; + } + } + } + if(!strMsg.IsEmpty()){ + CConfigTool::Log(_T("%s, multiple radio buttons are set: %s%s"), + pItem->Macro(),pFirstSet->Macro(),strMsg); + } else if(!pFirstSet){ + CConfigTool::Log(_T("%s, no radio buttons are set"),pItem->Macro()); + } + } + } +} + +// Find the ConfigItem referencing the given CdlValuable +CConfigItem * CConfigToolDoc::Find (CdlValuable v) +{ + for(int nItem=0;nItem<ItemCount();nItem++){ + CConfigItem *pItem=Item(nItem); + if(v==pItem->GetCdlValuable()){ + return pItem; + } + } + return NULL; +} + +CConfigItem * CConfigToolDoc::Find(const CString & strWhat,WhereType where) +{ + for(int nItem=0;nItem<ItemCount();nItem++){ + CConfigItem *pItem=Item(nItem); + if(0==pItem->StringValue(where).Compare(strWhat)){ + return pItem; + } + } + return NULL; +} + +void CConfigToolDoc::OnMLTNewRegion() +{ + // create the property sheet + + CPropertySheet prsRegionSheet (IDS_NEW_REGION_SHEET_TITLE, CConfigTool::GetMLTView()); + + // add the property pages + + CRegionGeneralPage prpGeneral; + CNotePage prpNote; + + prsRegionSheet.AddPage (&prpGeneral); + prsRegionSheet.AddPage (&prpNote); + + // setup initial values + + prpGeneral.m_strRegionName = _T(""); + prpGeneral.m_dwRegionStartAddress = 0; + prpGeneral.m_dwRegionSize = 0; + + // show property sheet + + if (prsRegionSheet.DoModal () == IDOK) + { + if (int nErrorCode = MemoryMap.create_memory_region (CUtils::UnicodeToStdStr(prpGeneral.m_strRegionName), prpGeneral.m_dwRegionStartAddress, prpGeneral.m_dwRegionSize, (prpGeneral.m_bRegionReadOnly ? read_only : read_write), CUtils::UnicodeToStdStr(prpNote.m_strNote))) + ErrorBox (IDS_ERR_MEMMAP_REGION_CREATE, IDS_ERR_MEMMAP_BASE + nErrorCode); + else // no errors + { + SetModifiedFlag (); + UpdateAllViews (NULL, MemLayoutChanged); + } + } +} + +void CConfigToolDoc::ErrorBox (UINT uIDSIntro, UINT uIDSError) +{ + CString strIntro, strError; + strIntro.LoadString (uIDSIntro); + strError.LoadString (uIDSError); + AfxMessageBox (strIntro + _T("\n\n") + strError); +} + +void CConfigToolDoc::OnMLTNewSection() +{ + // create the property sheet + + CPropertySheet prsSectionSheet (IDS_NEW_SECTION_SHEET_TITLE, CConfigTool::GetMLTView()); + + // add the property pages + + CSectionGeneralPage prpGeneral; + CSectionRelocationPage prpRelocation; + CNotePage prpNote; + + prsSectionSheet.AddPage (&prpGeneral); + prsSectionSheet.AddPage (&prpRelocation); + prsSectionSheet.AddPage (&prpNote); + + // initialise for a new section + + prpGeneral.m_bNameLinkerDefined = TRUE; + prpGeneral.m_strNameLinker = _T(""); + prpRelocation.m_bRelocates = FALSE; + prpRelocation.m_bNewSection = TRUE; + + // show property sheet + + if (prsSectionSheet.DoModal () == IDOK) + { + mem_anchor initial_anchor, final_anchor; + mem_address initial_address; + CString strInitialRelativeName = _T(""); + + if (prpGeneral.m_bFinalAbsolute) // final location is an absolute location + final_anchor = absolute; + else // final location is a relative location + final_anchor = relative; + + if (prpRelocation.m_bRelocates) // if the section relocates + { + if (prpRelocation.m_bInitialAbsolute) // initial location is an absolute location + { + initial_anchor = absolute; + } + else // initial location is a relative location + { + strInitialRelativeName = prpRelocation.m_strInitialRelativeName; + initial_anchor = relative; + } + initial_address = prpRelocation.m_dwInitialAddress; + } + else + { + strInitialRelativeName = prpGeneral.m_strFinalRelativeName; + initial_anchor = final_anchor; + initial_address = prpGeneral.m_dwFinalAddress; + } + + + if (int nErrorCode = MemoryMap.create_memory_section (CUtils::UnicodeToStdStr(prpGeneral.m_bNameLinkerDefined ? prpGeneral.m_strNameLinker : prpGeneral.m_strNameUser), prpGeneral.m_dwSectionSize, prpGeneral.m_dwAlignment, initial_anchor, CUtils::UnicodeToStdStr(strInitialRelativeName), initial_address, final_anchor, CUtils::UnicodeToStdStr(prpGeneral.m_strFinalRelativeName), prpGeneral.m_dwFinalAddress, prpRelocation.m_bRelocates, false, prpGeneral.m_bNameLinkerDefined, CUtils::UnicodeToStdStr(prpNote.m_strNote))) + ErrorBox (IDS_ERR_MEMMAP_SECTION_CREATE, IDS_ERR_MEMMAP_BASE + nErrorCode); + else // no errors + { + SetModifiedFlag (); + UpdateAllViews (NULL, MemLayoutChanged); + } + } +} + +void CConfigToolDoc::OnMLTDelete() +{ + if (strSelectedSection != _T("")) // a section is selected + { + if (MemoryMap.delete_memory_section (CUtils::UnicodeToStdStr(strSelectedSection))) + { + strSelectedSection = _T(""); + SetModifiedFlag (); + UpdateAllViews (NULL, MemLayoutChanged); + } + else + AfxMessageBox (_T("Could not delete memory section.\n\nMake sure there are no other sections defined relative to this one.")); + } + else if (strSelectedRegion != _T("")) // a region is selected + { + if (MemoryMap.delete_memory_region (CUtils::UnicodeToStdStr(strSelectedRegion))) + { + strSelectedRegion = _T(""); + SetModifiedFlag (); + UpdateAllViews (NULL, MemLayoutChanged); + } + else + AfxMessageBox (_T("Could not delete memory region.\n\nMake sure it is not in use.")); // FIXME + } +} + +void CConfigToolDoc::ShowRegionProperties() +{ + // create the property sheet + + CString strTitle; + strTitle.LoadString (IDS_REGION_PROPERTIES_SHEET_TITLE); + CPropertySheet prsRegionSheet (strSelectedRegion + _T(" - ") + strTitle, CConfigTool::GetMLTView()); + + // add the property pages + + CRegionGeneralPage prpGeneral; + CNotePage prpNote; + + prsRegionSheet.AddPage (&prpGeneral); + prsRegionSheet.AddPage (&prpNote); + + // set up property sheet values + + mem_type type; + std::string note; + MemoryMap.get_memory_region (CUtils::UnicodeToStdStr(strSelectedRegion), &prpGeneral.m_dwRegionStartAddress, &prpGeneral.m_dwRegionSize, &type, ¬e); + prpGeneral.m_strRegionName = strSelectedRegion; + prpGeneral.m_bRegionReadOnly = (type == read_only); + prpNote.m_strNote = note.c_str (); + + // show property sheet + + if (prsRegionSheet.DoModal () == IDOK) + { + if (int nErrorCode = MemoryMap.edit_memory_region (CUtils::UnicodeToStdStr(strSelectedRegion), CUtils::UnicodeToStdStr(prpGeneral.m_strRegionName), prpGeneral.m_dwRegionStartAddress, prpGeneral.m_dwRegionSize, (prpGeneral.m_bRegionReadOnly ? read_only : read_write), CUtils::UnicodeToStdStr(prpNote.m_strNote))) + ErrorBox (IDS_ERR_MEMMAP_REGION_MODIFY, IDS_ERR_MEMMAP_BASE + nErrorCode); + else // no errors + { + SetModifiedFlag (); + UpdateAllViews (NULL, MemLayoutChanged); + } + } +} + +void CConfigToolDoc::ShowSectionProperties() +{ + // create the property sheet + + CString strTitle; + strTitle.LoadString (IDS_SECTION_PROPERTIES_SHEET_TITLE); + CPropertySheet prsSectionSheet (strSelectedSection + _T(" - ") + strTitle, CConfigTool::GetMLTView()); + + // add the property pages + + CSectionGeneralPage prpGeneral; + CSectionRelocationPage prpRelocation; + CNotePage prpNote; + + prsSectionSheet.AddPage (&prpGeneral); + prsSectionSheet.AddPage (&prpRelocation); + prsSectionSheet.AddPage (&prpNote); + + // setup initial values + + std::list <mem_section>::iterator section = MemoryMap.find_memory_section (CUtils::UnicodeToStdStr(strSelectedSection)); + prpGeneral.m_bNameLinkerDefined = (section->linker_defined); + if (prpGeneral.m_bNameLinkerDefined) + prpGeneral.m_strNameLinker = section->name.c_str (); + else + { + prpGeneral.m_strNameUser = section->name.c_str (); + prpGeneral.m_dwSectionSize = section->size; + } + + prpGeneral.m_bFinalAbsolute = (section->final_location->anchor == absolute); + if (prpGeneral.m_bFinalAbsolute) + prpGeneral.m_dwFinalAddress = section->final_location->address; + else + { + prpGeneral.m_strFinalRelativeName = MemoryMap.find_preceding_section (section, false)->name.c_str (); + prpGeneral.m_dwAlignment = section->alignment; + } + + prpRelocation.m_bRelocates = section->relocates; + if (prpRelocation.m_bRelocates) + { + prpRelocation.m_bInitialAbsolute = (section->initial_location->anchor == absolute); + if (prpRelocation.m_bInitialAbsolute) + prpRelocation.m_dwInitialAddress = section->initial_location->address; + else + prpRelocation.m_strInitialRelativeName = MemoryMap.find_preceding_section (section, true)->name.c_str (); + } + + prpNote.m_strNote = section->note.c_str (); + + // show property sheet + + if (prsSectionSheet.DoModal () == IDOK) + { + mem_anchor initial_anchor, final_anchor; + mem_address initial_address; + CString strInitialRelativeName = _T(""); + + if (prpGeneral.m_bFinalAbsolute) // final location is an absolute location + final_anchor = absolute; + else // final location is a relative location + final_anchor = relative; + + if (prpRelocation.m_bRelocates) // if the section relocates + { + if (prpRelocation.m_bInitialAbsolute) // initial location is an absolute location + { + initial_anchor = absolute; + } + else // initial location is a relative location + { + strInitialRelativeName = prpRelocation.m_strInitialRelativeName; + initial_anchor = relative; + } + initial_address = prpRelocation.m_dwInitialAddress; + } + else + { + strInitialRelativeName = prpGeneral.m_strFinalRelativeName; + initial_anchor = final_anchor; + initial_address = prpGeneral.m_dwFinalAddress; + } + + + if (int nErrorCode = MemoryMap.edit_memory_section (CUtils::UnicodeToStdStr(strSelectedSection), CUtils::UnicodeToStdStr(prpGeneral.m_bNameLinkerDefined ? prpGeneral.m_strNameLinker : prpGeneral.m_strNameUser), prpGeneral.m_dwSectionSize, prpGeneral.m_dwAlignment, initial_anchor, CUtils::UnicodeToStdStr(strInitialRelativeName), initial_address, final_anchor, CUtils::UnicodeToStdStr(prpGeneral.m_strFinalRelativeName), prpGeneral.m_dwFinalAddress, prpRelocation.m_bRelocates, false, prpGeneral.m_bNameLinkerDefined, CUtils::UnicodeToStdStr(prpNote.m_strNote))) + ErrorBox (IDS_ERR_MEMMAP_SECTION_MODIFY, IDS_ERR_MEMMAP_BASE + nErrorCode); + else // no errors + { + SetModifiedFlag (); + UpdateAllViews (NULL, MemLayoutChanged); + } + } +} + +void CConfigToolDoc::OnMLTProperties() +{ + if (strSelectedRegion != _T("")) + ShowRegionProperties (); + else if (strSelectedSection != _T("")) + ShowSectionProperties (); +} + +// Choose a default Hal. Do this using clues the installer may have helpfully left behind (PR 18050) +// or else if there is only one possible choice, by choosing that one :-). +/* +void CConfigToolDoc::ChooseDefaultHal() +{ +bool bFound=false; +// Has the installer told us? +LPCTSTR pszRegPath=_T("SOFTWARE\\Red Hat\\eCos\\1.2.8"); +HKEY hKey; +if(ERROR_SUCCESS==RegOpenKeyEx (HKEY_LOCAL_MACHINE, pszRegPath, 0L, KEY_READ, &hKey)){ +DWORD dwSizePath=MAX_PATH; +CString str; +PTCHAR psz=str.GetBuffer(dwSizePath); +if(ERROR_SUCCESS==RegQueryValueEx(hKey, _T("Default Architecture"), NULL, NULL, (LPBYTE)psz, &dwSizePath)){ +str.MakeLower(); +for(int nItem=0;nItem<ItemCount();nItem++){ +CConfigItem *pItem=Item(nItem); +if(pItem->m_pTarget){ +CString strTarget(pItem->m_pTarget->Name()); +strTarget.MakeLower(); +if(-1!=str.Find(strTarget)){ +bFound=true; +dwSizePath=MAX_PATH; +if(ERROR_SUCCESS==::RegQueryValueEx(hKey, _T("Default Build Tools Path"), NULL, NULL, (LPBYTE)psz, &dwSizePath)){ +pItem->m_pTarget->SetBinDir(psz); +for(CConfigItem *pSib=pItem->FirstRadio();pSib;pSib=pSib->NextRadio()){ +pSib->SetValue((ItemIntegerType) (pSib==pItem)); +} +// pItem->EnableAncestors(); +} +break; +} +} +} +} +RegCloseKey(hKey); +} + + if(!bFound){ + // No - choose the Hal according to toolchain + for(int nItem=0;nItem<ItemCount();nItem++){ + CConfigItem *pItem=Item(nItem); + if(pItem->m_pTarget){ + CString strTarget(pItem->m_pTarget->Name()); + strTarget.MakeLower(); + for(int j=0;j<m_arstrToolChainPaths.GetSize();j++){ + CString strTools(m_arstrToolChainPaths[j]); + strTools.MakeLower(); + if(-1!=strTools.Find(strTarget)){ + for(CConfigItem *pSib=pItem->FirstRadio();pSib;pSib=pSib->NextRadio()){ + pSib->SetValue((ItemIntegerType) (pSib==pItem)); + } + return; + } + } + } + } + } + } +*/ + +bool CConfigToolDoc::SetValue (CConfigItem &ti, double dValue, CdlTransaction transaction/*=NULL*/) +{ + ASSERT (ti.Type () == CConfigItem::Double); + + // 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) || IDNO == CUtils::MessageBoxFT (MB_YESNO, _T("%s is not a legal value for %s.\n\nDo you want to use this value anyway?"), + CUtils::DoubleToStr (dValue), ti.Macro ())) + return false; + } + + if (! ti.SetValue (dValue,transaction)) + return false; + + SetModifiedFlag (); + return true; +} +bool CConfigToolDoc::SetValue(CConfigItem &ti,const CString &strValue, CdlTransaction transaction/*=NULL*/) +{ + // 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; + + bool rc=false; + switch(ti.Type()){ + case CConfigItem::None: + break; + case CConfigItem::Enum: + case CConfigItem::String: + rc=ti.SetValue(strValue,transaction); + break; + case CConfigItem::Integer: + { + ItemIntegerType n; + rc=CUtils::StrToItemIntegerType(strValue,n) && SetValue(ti,n,transaction); + } + break; + case CConfigItem::Double: + { + double dValue; + rc = CUtils::StrToDouble (strValue, dValue) && SetValue (ti, dValue,transaction); + } + break; + default: + ASSERT(FALSE); + break; + + } + if(rc){ + SetModifiedFlag(); + UpdateAllViews (NULL, CConfigToolDoc::ValueChanged, (CObject *)&ti); + } + return rc; +} + +// Look in registry to match prefixes CYGPKG_HAL_ and CYGHWR_HAL_: +// +bool CConfigToolDoc::GetRunPlatform(CString &strTarget) +{ + CRegKeyEx k1(HKEY_CURRENT_USER,_T("Software\\Red Hat\\eCos\\Platforms"), KEY_READ); + CString strKey; + for(int i=0;k1.QueryKey(i,strKey);i++){ + CRegKeyEx k2((HKEY)k1,strKey,KEY_READ); + // Subkeys' names are the target image names [one of which we aim to return] + // Subkeys's values of interest are: + // Prefix String + // Sim DWORD [optional] + // Macro String + DWORD dwSim=0; + CString strPrefix,strMacro; + k2.QueryValue(_T("Sim"),dwSim); + k2.QueryValue(_T("Prefix"),strPrefix); + k2.QueryValue(_T("Macro"),strMacro); + + CConfigItem *pItem=Find(_T("CYGPKG_HAL_")+strMacro); + if(pItem && pItem->IsEnabled()){ + // We have found what we are looking for - probably + pItem=Find(_T("CYGHWR_HAL_")+strMacro+_T("_STARTUP")); + if(pItem){ + // Two platforms apply - choose this one only if the ram startup attribute fits + if( (dwSim==0) == (0==pItem->StringValue().CompareNoCase(_T("ram"))) ) { + strTarget=strKey; + } + } else { + // Only one platform applies + strTarget=strKey; + } + + } + } + return !strTarget.IsEmpty(); +} + +bool CConfigToolDoc::SetEnabled(CConfigItem &ti, bool bEnabled, CdlTransaction transaction/*=NULL*/) +{ + const bool bStatus = ti.SetEnabled (bEnabled,transaction); + + if (bStatus) { + SetModifiedFlag(); + UpdateAllViews (NULL, CConfigToolDoc::ValueChanged, (CObject *) &ti); + } + return bStatus; +} + +void CConfigToolDoc::AddContents (const CdlContainer container, CConfigItem *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 + { + CConfigItem * pItem = AddItem (pkg, pParent); // add the package + AddContents (pkg, pItem); // add the package contents + } + else if (0 != comp) // the node is a component + { + CConfigItem * 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 + } +} + +// Three hack functions. + +const CString CConfigToolDoc::CurrentPlatform() +{ +/* +for(int nItem=0;nItem<ItemCount();nItem++){ +CConfigItem *pItem=Item(nItem); +if(pItem->IsEnabled() && !pItem->Platform().IsEmpty()){ +return pItem->Platform(); +} +} + */ + return _T(""); +} + +// a trivial CDL parse error handler +void CConfigToolDoc::CdlParseErrorHandler (std::string message) +{ + CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc(); + pDoc->m_strCdlErrorMessage = message.c_str (); + TRACE (_T("CdlParseError: %s\n"), pDoc->m_strCdlErrorMessage); + CConfigTool::Log (CUtils::StripExtraWhitespace (pDoc->m_strCdlErrorMessage)); // display the message in the output window +}; + +// a trivial CDL parse warning handler +void CConfigToolDoc::CdlParseWarningHandler (std::string message) +{ + CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc(); + pDoc->m_strCdlErrorMessage = message.c_str (); + TRACE (_T("CdlParseWarning: %s\n"), pDoc->m_strCdlErrorMessage); + CConfigTool::Log (CUtils::StripExtraWhitespace (pDoc->m_strCdlErrorMessage)); // display the message in the output window +}; + +// a trivial CDL load error handler +void CConfigToolDoc::CdlLoadErrorHandler (std::string message) +{ + CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc(); + pDoc->m_strCdlErrorMessage = message.c_str (); + TRACE (_T("CdlLoadError: %s\n"), pDoc->m_strCdlErrorMessage); + CConfigTool::Log (CUtils::StripExtraWhitespace (pDoc->m_strCdlErrorMessage)); // display the message in the output window +}; + +// a trivial CDL load warning handler +void CConfigToolDoc::CdlLoadWarningHandler (std::string message) +{ + CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc(); + pDoc->m_strCdlErrorMessage = message.c_str (); + TRACE (_T("CdlLoadWarning: %s\n"), pDoc->m_strCdlErrorMessage); + CConfigTool::Log (CUtils::StripExtraWhitespace (pDoc->m_strCdlErrorMessage)); // display the message in the output window +}; + +CdlInferenceCallbackResult CConfigToolDoc::CdlGlobalInferenceHandler(CdlTransaction transaction) +{ + CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc(); + pDoc->m_ConflictsOutcome=NotDone; // prepare for the case that there are no solutions + CdlInferenceCallbackResult rc=CdlInferenceCallbackResult_Continue; + /* + std::list<CdlConflict>conflicts1(transaction->get_global_conflicts_with_solutions()); + const std::vector<CdlConflict>&conflicts2=transaction->get_resolved_conflicts(); + for (unsigned int i = 0; i < conflicts2.size (); i++) { + conflicts1.push_back(conflicts2 [i]); + } + if(conflicts1.size()>0){ + CFailingRulesDialog dlg(conflicts1,transaction,&pDoc->m_arConflictsOfInterest); + rc=(IDOK==dlg.DoModal())?CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel; + pDoc->m_ConflictsOutcome=(CdlInferenceCallbackResult_Continue==rc)?OK:Cancel; + } + */ + const std::list<CdlConflict>& conflicts=pDoc->GetCdlConfig()->get_all_conflicts(); + CFailingRulesDialog dlg(conflicts,transaction,&pDoc->m_arConflictsOfInterest); + rc=(IDOK==dlg.DoModal())?CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel; + pDoc->m_ConflictsOutcome=(CdlInferenceCallbackResult_Continue==rc)?OK:Cancel; + + return rc; +} + +CdlInferenceCallbackResult CConfigToolDoc::CdlInferenceHandler (CdlTransaction transaction) +{ + CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc(); + CdlInferenceCallbackResult rc=CdlInferenceCallbackResult_Continue; + const std::list<CdlConflict>&conflicts=transaction->get_new_conflicts(); + if((pDoc->m_nRuleChecking&Immediate) && conflicts.size()>0){ + if(pDoc->m_nRuleChecking&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){ + CFailingRulesDialog dlg(s_conflicts,transaction); + return(IDOK==dlg.DoModal()?CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel); + } + } + CString strMsg; + if(1==conflicts.size()){ + strMsg=(_T("There is 1 unresolved conflict.")); + } else { + strMsg.Format(_T("There are %d unresolved conflict%s."),conflicts.size(),1==conflicts.size()?_T(""):_T("s")); + } + rc=(IDYES==CUtils::MessageBoxFT(MB_YESNO|MB_DEFBUTTON2,_T("%s Make the change anyway?"),strMsg))?CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel; + } + return rc; +} + + +// a CDL transaction handler to refresh the configuration tree +void CConfigToolDoc::CdlTransactionHandler (const CdlTransactionCallback & data) +{ +static int nNesting=0; +TRACE(_T("Transaction handler: nesting level=%d\n"),nNesting++); + CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc(); + std::vector<CdlValuable>::const_iterator val_i; + std::vector<CdlNode>::const_iterator node_i; + std::list<CdlConflict>::const_iterator conf_i; + CControlView *pControlView=CConfigTool::GetControlView(); + for (val_i = data.value_changes.begin(); val_i != data.value_changes.end(); val_i++) + { + const CString strName((*val_i)->get_name().c_str()); + TRACE(_T("%s %s : value change\n"), CString ((*val_i)->get_class_name().c_str()), strName); + pControlView->Refresh(strName); + if (strName==_T("CYGHWR_MEMORY_LAYOUT")){ // the memory layout has changed... + pDoc->SwitchMemoryLayout (false); // ...so display a new one + } + } + for (node_i = data.active_changes.begin(); node_i != data.active_changes.end(); node_i++) + { + const CString 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 CString 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 CString 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--; +} + +// Three hack functions. + +const CString CConfigToolDoc::CurrentMemoryLayout () +{ + const CConfigItem * pItem = Find (_T("CYGHWR_MEMORY_LAYOUT")); +#ifdef _DEBUG + if(NULL==pItem){ + TRACE(_T("Warning - CurrentMemoryLayout() returning NULL\n")); + } +#endif + return pItem ? pItem->StringValue () : _T(""); +} + +const CString CConfigToolDoc::CurrentTestingIdentifier () +{ + // use the CDL target as the default testing identifier + // override in the forthcoming testing identifier dialog as necessary + return GetCdlConfig()->get_hardware ().c_str (); + +// const CConfigItem * pItem = Find (_T("CYGTST_TESTING_IDENTIFIER")); +//#ifdef _DEBUG +// if(NULL==pItem){ +// TRACE(_T("Warning - CurrentTestingIdentifier() returning NULL\n")); +// } +//#endif +// return pItem ? pItem->StringValue () : _T(""); +} + +const CString CConfigToolDoc::CurrentStartup() +{ + const CConfigItem * pItem = Find (_T("CYG_HAL_STARTUP")); +#ifdef _DEBUG + if(NULL==pItem){ + TRACE(_T("Warning - CurrentStartup() returning NULL\n")); + } +#endif + return pItem ? pItem->StringValue () : _T(""); + + /* + for(int nItem=0;nItem<ItemCount();nItem++){ + CConfigItem *pItem=Item(nItem); + const CString strName(pItem->Name()); + if(0==strName.Compare(_T("Startup type")) && pItem->IsEnabled()){ + return pItem->StringValue(); + } + } + return _T("ram"); // FIXME - assume ram startup for now if no startup item + */ +} + +void CConfigToolDoc::UpdateFailingRuleCount() +{ + int nCount=0; + if (GetCdlConfig ()){ + // if configuration information + + // calculate the number of conflicts + nCount = + // GetCdlConfig ()->get_structural_conflicts ().size () + ignore for now + GetCdlConfig ()->get_all_conflicts ().size (); + + // update the conflicts view + if (CConfigTool::GetRulesView ()) { + CConfigTool::GetRulesView ()->FillRules (); + } + } + if(CConfigTool::GetMain()){ + CConfigTool::GetMain()->SetFailRulePane(nCount); + } +} + +void CConfigToolDoc::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 + { + CString strExplain = (* conf_i)->get_explanation ().c_str (); // get the conflict explanation + CConfigTool::Log (CUtils::StripExtraWhitespace (strExplain)); // display the message in the output window + } +} + +CString CConfigToolDoc::GetPackageName (const CString & 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); + CString strPackageAlias = aliases [0].c_str (); + if (aliases.size () && (0 == strAlias.Compare (strPackageAlias))) + return package_i->c_str (); + } + return _T(""); +} + +void CConfigToolDoc::DeleteContents() +{ + TRACE(_T("###DeleteContents()\n")); +#ifndef PLUGIN + CDocument::DeleteContents(); +#endif + + RemoveAllItems(); + TRACE(_T("###DeleteContents done\n")); +} + +void CConfigToolDoc::SelectPackages () +{ + CCdlPackagesDialog dlg; + // This map holds the CConfigItem pointers for the packages loaded before the dialog is invoked. + // We cannot use Find(), which traverses all items - potentially those that have been removed + CMapStringToPtr arLoadedPackages; + + // 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); + CString strMacroName = package_i->c_str (); + + // use the first alias (if any) as the package identifier + CString strPackageName = aliases.size () ? aliases [0].c_str () : strMacroName; + CConfigItem * pItem = Find (strMacroName); + if (pItem) // if the package is loaded + { + arLoadedPackages.SetAt(strMacroName,pItem); + // pass the currently selected package version string to the dialog box + const CdlValuable valuable = pItem->GetCdlValuable(); + dlg.Insert (strPackageName, TRUE, NULL, valuable ? (LPCTSTR) CString (valuable->get_value ().c_str ()) : NULL); + } + else + { + // pass version string of the most latest version to the dialog box + dlg.Insert (strPackageName, FALSE, NULL, (LPCTSTR) CString (m_CdlPkgData->get_package_versions (* package_i) [0].c_str ())); + } + } + } + + if (IDOK == dlg.DoModal ()) + { + 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); + CString strMacroName = package_i->c_str (); + + // use the first alias (if any) as the package identifier + CString strPackageName = aliases.size () ? aliases [0].c_str () : strMacroName; + + CConfigItem *pItem=NULL; + bool bPreviouslyLoaded=arLoadedPackages.Lookup(strMacroName,(void *&)pItem); + 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 CString strVersion(dlg.GetVersion (strPackageName)); + if (bPreviouslyLoaded) { // if the package is not already loaded + bChanged|=pItem->ChangeVersion(strVersion); + } else { + // the package was not loaded but should now be loaded + TRACE (_T("Loading package %s\n"), strMacroName); + try + { + GetCdlConfig()->load_package (CUtils::UnicodeToStdStr(strMacroName), CUtils::UnicodeToStdStr (strVersion), CConfigToolDoc::CdlParseErrorHandler, CConfigToolDoc::CdlParseWarningHandler); + bChanged=true; + } + catch (CdlStringException exception) + { + CUtils::MessageBoxF(_T("Error loading package %s:\n\n%s"), strMacroName, CString (exception.get_message ().c_str ())); + } + catch (...) + { + CUtils::MessageBoxF(_T("Error loading package %s."), strMacroName); + } + } + } + } + + if (bChanged) {// at least one package was loaded, unloaded or changed version + SetModifiedFlag(); + RegenerateData(); + } + } +} + +bool CConfigToolDoc::SetValue(CConfigItem &ti,ItemIntegerType nValue, CdlTransaction transaction/*=NULL*/) +{ + switch(ti.Type()){ + case CConfigItem::Enum: + case CConfigItem::Integer: + // case CConfigItem::Boolean: + // case CConfigItem::Radio: + break; + case CConfigItem::None: + case CConfigItem::String: + default: + ASSERT(FALSE); + break; + } + + bool rc=false; + bool bChangingMemmap=MemoryMap.map_modified () && ((ti.Macro ().Compare (_T ("CYG_HAL_STARTUP")) == 0)); + + if(nValue==ti.Value()){ + return true; + } + + // test if the new integer value is in range + if (CConfigItem::Integer == ti.Type ()) + { + 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==(ItemIntegerType) valuable->get_integer_value (CdlValueSource_Current) || IDNO == CUtils::MessageBoxFT (MB_YESNO, _T("%s is not a legal value for %s.\n\nDo you want to use this value anyway?"), + CUtils::IntToStr (nValue, CConfigTool::GetConfigToolDoc ()->m_bHex), ti.Macro ())) + goto Exit; + }; + } + + // if(!ti.CanSetValue(nValue)) + // { + // if(bInteractive){ + // CString strExplanation; + // if(CConfigItem::Integer==ti.Type()){ + // strExplanation.Format(_T(" [value must lie in the range %d..%d]"), + // CUtils::IntToStr(ti.Min(),m_bHex), + // CUtils::IntToStr(ti.Max()),m_bHex); + // } + // CUtils::MessageBoxF( + // _T("Cannot set '%s' to %s%s"), + // ti.ItemNameOrMacro(), CUtils::IntToStr(nValue,m_bHex), strExplanation); + // } + // goto Exit; + // } + + // 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; + } + + // Save state + if(!ti.SetValue(nValue,transaction)){ + // CanSetValue above should have caught this + CUtils::MessageBoxF(_T("Cannot set '%s' to %d"),ti.ItemNameOrMacro(), nValue); + goto Exit; + } + + rc=true; +Exit: + if(rc){ + SetModifiedFlag(); + UpdateFailingRuleCount (); + UpdateAllViews (NULL, CConfigToolDoc::ValueChanged, (CObject *)&ti); + // switch to new memory layout when target, platform or startup changes + // but ignore cases where a target or platform is being deactivated (PR 19363) + + // if (((CurrentTarget () != pOldTarget) || (CurrentPlatform () != strOldPlatform) || (ti.Name ().Compare (_T ("Startup type")) == 0)) && + // ((ti.Type () != CConfigItem::Radio) || (nValue))) + // SwitchMemoryLayout ((CurrentTarget () != pOldTarget) || (CurrentPlatform () != strOldPlatform)); + } + return rc; +} + +bool CConfigToolDoc::OpenRepository(LPCTSTR pszRepository/*=NULL*/,bool bPromptInitially/*=false*/) +{ + if(!m_bRepositoryOpen){ + CWaitCursor wait; + CIdleMessage IM(_T("Opening repository")); + UpdateFailingRuleCount(); + + CFileName strNewRepository; + while(!m_bRepositoryOpen){ + + if(bPromptInitially){ + CFolderDialog dlg(/*BOOL bAllowCreation=*/false); + dlg.m_strDesc=_T("Please specify the root of the eCos repository tree."); + dlg.m_strTitle=_T("Choose folder for eCos repository"); + dlg.m_strFolder=strNewRepository; + CConfigTool::DismissSplash(); + if(IDCANCEL==dlg.DoModal()){ + return false; + } + strNewRepository=dlg.m_strFolder; + } else { + // Use what came in as parameter or what was found in registry + strNewRepository=pszRepository?pszRepository:m_strRepository; + bPromptInitially=true; + } + + IM.Set (_T("Opening repository ") + (CString) strNewRepository); + + CdlPackagesDatabase NewCdlPkgData = NULL; + CdlInterpreter NewCdlInterp = NULL; + CdlConfiguration NewCdlConfig = NULL; + CFileName strNewPackagesDir; + + EnableCallbacks(false); // disable transaction callbacks until the config tree is regenerated + + if(OpenRepository(strNewRepository,NewCdlPkgData,NewCdlInterp,NewCdlConfig,strNewPackagesDir)){ + // Success + + // 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_template_version = ""; + 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_template_version = template_versions [0]; + } + catch (CdlStringException exception) { + CUtils::MessageBoxF(_T("Error loading package template '%s':\n\n%s"), CString (default_template.c_str ()), CString (exception.get_message ().c_str ())); + } + catch (...) { + CUtils::MessageBoxF(_T("Error loading package template '%s'."), CString (default_template.c_str ())); + } + + // check the configuration + ASSERT (NewCdlConfig->check_this (cyg_extreme)); + + // use the new package database, interpreter and configuration + deleteZ(m_CdlConfig); // delete the previous configuration + deleteZ(m_CdlInterp); // delete the previous interpreter + deleteZ(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; + +#ifndef PLUGIN + // clear the previously specified document file name (if any), + // OnNewDocument() calls DeleteContents() so must be called + // before AddAllItems() + CDocument::OnNewDocument (); +#endif + + // generate the CConfigItems from their CDL descriptions + AddAllItems (); + + m_bRepositoryOpen=true; + } else { + // failure + deleteZ(NewCdlConfig); + deleteZ(NewCdlInterp); + deleteZ(NewCdlPkgData); + + } + + // install a transaction handler callback function now that the tree exists + EnableCallbacks(true); + } + + } + return m_bRepositoryOpen; +} + +// Helper fn for namesake above +bool CConfigToolDoc::OpenRepository (const CFileName strNewRepository,CdlPackagesDatabase &NewCdlPkgData,CdlInterpreter &NewCdlInterp,CdlConfiguration &NewCdlConfig,CFileName &strNewPackagesDir) +{ + bool rc=false; + TRACE(_T("###Open repository %s\n"),strNewRepository); + if(!strNewRepository.IsEmpty()){ + // Now strNewRepository is guaranteed non-empty, but does it exist? + if(!strNewRepository.IsDir()) { + CUtils::MessageBoxF(_T("Cannot open repository - the folder %s does not exist"), strNewRepository); + } else { + + // Ok so it exists, but does it look right? + strNewPackagesDir=strNewRepository+_T("ecc"); + if(!strNewPackagesDir.IsDir()){ + strNewPackagesDir=strNewRepository+_T("packages"); + } + + if(!strNewPackagesDir.IsDir()){ + // Don't mention the ecc\ attempt + CUtils::MessageBoxF(_T("%s does not seem to be a source repository: the folder %s does not exist"), + strNewRepository,strNewPackagesDir); + } else { + + const CFileName strDatabase = strNewPackagesDir + _T("ecos.db"); + if(!strDatabase.Exists()) { + CUtils::MessageBoxF(_T("%s does not seem to be a source repository: %s does not exist"), strNewRepository, strDatabase); + } else { + + // create a CDL repository, interpreter and configuration + + try {// create a new package database, interpreter and configuration + NewCdlPkgData = CdlPackagesDatabaseBody::make (CUtils::UnicodeToStdStr(strNewPackagesDir)); + NewCdlInterp = CdlInterpreterBody::make (); + NewCdlConfig = CdlConfigurationBody::make ("eCos", NewCdlPkgData, NewCdlInterp); + } + catch (CdlStringException exception) { + CUtils::MessageBoxF(_T("Error opening eCos repository:\n\n%s"), CString (exception.get_message ().c_str ())); + return false; + } + catch (...) { + CUtils::MessageBoxF(_T("Error opening eCos repository.")); + return false; + } + + // select the default target if specified in the registry + // otherwise select the first available target + std::string default_hardware = CUtils::UnicodeToStdStr (GetDefaultHardware ()); + if (! NewCdlPkgData->is_known_target (default_hardware)) { + const std::vector<std::string>& targets = NewCdlPkgData->get_targets (); + if (targets.size () == 0){ + CUtils::MessageBoxF (_T("Error opening eCos repository:\n\nno hardware templates")); + return false; + } else { + default_hardware = targets [0]; + } + } + + try { + m_strCdlErrorMessage = _T(""); + NewCdlConfig->set_hardware (default_hardware, &CdlParseErrorHandler, &CdlParseWarningHandler); + } + catch (CdlStringException exception) { + if (m_strCdlErrorMessage.IsEmpty ()) + { + CUtils::MessageBoxF (_T("Error loading the default hardware template '%s':\n\n%s"), CString (default_hardware.c_str ()), CString (exception.get_message ().c_str ())); + } + else // report the most recent parser message in the message box since there may be no output pane in which to view it + { + CUtils::MessageBoxF (_T("Error loading the default hardware template '%s':\n\n%s\n\nParser message:\n\n%s"), CString (default_hardware.c_str ()), CString (exception.get_message ().c_str ()), m_strCdlErrorMessage); + } + return false; + } + catch (...) { + CUtils::MessageBoxF (_T("Error loading the default hardware template '%s':\n\n%s"), CString (default_hardware.c_str ()), m_strCdlErrorMessage); + return false; + } + rc=true; + } + } + } + } + return rc; +} + +void CConfigToolDoc::CloseRepository() +{ + if(m_bRepositoryOpen){ + // delete the libCDL objects with the document + EnableCallbacks(false); // first disable the transaction handler + deleteZ(m_CdlConfig); + deleteZ(m_CdlInterp); + deleteZ(m_CdlPkgData); + m_bRepositoryOpen=false; + } +} + +void CConfigToolDoc::SelectTemplate (std::string NewTemplate, std::string NewTemplateVersion) +{ + if ((NewTemplate != m_CdlConfig->get_template()) || (NewTemplateVersion != m_template_version)){ + + CWaitCursor wait; // this may take a little while + RemoveAllItems(); + m_template_version = ""; + try + { + m_CdlConfig->set_template (NewTemplate, NewTemplateVersion, CdlParseErrorHandler, CdlParseWarningHandler); + m_template_version = NewTemplateVersion; + } + catch (CdlStringException exception) + { + CUtils::MessageBoxF(_T("Error loading package template '%s':\n\n%s"), CString (NewTemplate.c_str ()), CString (exception.get_message ().c_str ())); + } + catch (...) + { + CUtils::MessageBoxF(_T("Error loading package template '%s'."), CString (NewTemplate.c_str ())); + } + RegenerateData(); + + if (!GetPathName().IsEmpty()){ // not a new document + CopyMLTFiles (); // copy new MLT files to the build tree as necessary + } + SetModifiedFlag(); + } +} + +void CConfigToolDoc::RegenerateData() +{ + CWaitCursor wait; // This may take a little while + AddAllItems (); // regenerate all the config items since the topology may have changed + if (m_strLinkerScriptFolder.IsEmpty ()) + { + CUtils::MessageBoxF(_T("The eCos linker script macro CYGBLD_LINKER_SCRIPT is not defined.")); + } + if (m_strMemoryLayoutFolder.IsEmpty ()) + { + CUtils::MessageBoxF(_T("The eCos memory layout macro CYGHWR_MEMORY_LAYOUT is not defined.")); + } + SwitchMemoryLayout (true); // the hardware template may have changed + UpdateBuildInfo(); + CConfigTool::GetControlView()->SelectItem(Item(0)); +} + +void CConfigToolDoc::SelectHardware (std::string NewTemplate) +{ + const std::string OldTemplate=m_CdlConfig->get_hardware(); + if (NewTemplate != OldTemplate){ + RemoveAllItems(); + + try + { + m_CdlConfig->set_hardware (NewTemplate, CdlParseErrorHandler, CdlParseWarningHandler); + } + catch (CdlStringException exception) + { + CUtils::MessageBoxF(_T("Error loading hardware template '%s':\n\n%s"), CString (NewTemplate.c_str ()), CString (exception.get_message ().c_str ())); + m_CdlConfig->set_hardware (OldTemplate, CdlParseErrorHandler, CdlParseWarningHandler); + } + catch (...) + { + CUtils::MessageBoxF(_T("Error loading hardware template '%s'."), CString (NewTemplate.c_str ())); + m_CdlConfig->set_hardware (OldTemplate, CdlParseErrorHandler, CdlParseWarningHandler); + } + + RegenerateData(); + //EnableCallbacks(true); // re-enable the transaction handler + if (!GetPathName().IsEmpty()){ + CopyMLTFiles (); // copy new MLT files to the build tree as necessary + } + SetModifiedFlag(); + } +} + +bool CConfigToolDoc::SaveMemoryMap() +{ + const CString strSuffix(_T("mlt_") + CurrentMemoryLayout ()); + const CFileName strMLTInstallPkgconfDir(InstallTree() + _T("include\\pkgconf")); + bool rc=false; + if(strMLTInstallPkgconfDir.CreateDirectory(true)){ + const CString strMLTInstallBase(strMLTInstallPkgconfDir+CFileName(strSuffix)); + const CFileName strMLTDir (MLTDir()); + if(strMLTDir.CreateDirectory (true)){ + const CString strMLTBase (strMLTDir + CFileName (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; +} + +bool CConfigToolDoc::CopyMLTFiles() +{ + // 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 CFileName strInstallDestination(InstallTree () + _T("include\\pkgconf")); + const CFileName 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){ + CFileFind ffFileFind; + BOOL bLastFile = ffFileFind.FindFile (PackagesDir() + m_strMemoryLayoutFolder + _T("\\include\\pkgconf\\mlt_*.*")); + while (bLastFile) + { + bLastFile = ffFileFind.FindNextFile (); + if (_T(".mlt") == ffFileFind.GetFileName ().Right (4)) // if a .mlt file + { + if (! CFileName (strMLTDestination, CFileName (ffFileFind.GetFileName ())).Exists ()) + { + if(!CUtils::CopyFile (ffFileFind.GetFilePath (), strMLTDestination + CFileName (ffFileFind.GetFileName ()))){ + return false; // message already emitted + } + } + } + else // a .h or .ldi file + { + if (! CFileName (strInstallDestination, CFileName (ffFileFind.GetFileName ())).Exists () && + !CUtils::CopyFile (ffFileFind.GetFilePath (), strInstallDestination + CFileName (ffFileFind.GetFileName ()))){ + return false; // message already emitted + } + } + } + } + return rc; //FIXME +} + +CString CConfigToolDoc::GetDefaultHardware () +{ + CString strKey = _T("SOFTWARE\\Red Hat\\eCos"); + CString strVersionKey = _T(""); + CString rc = _T(""); + TCHAR pszBuffer [MAX_PATH + 1]; + HKEY hKey; + LONG lStatus; + + // get the greatest eCos version subkey + if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, strKey, 0L, KEY_READ, &hKey)) + { + DWORD dwIndex = 0; + while (ERROR_SUCCESS == RegEnumKey (hKey, dwIndex++, (LPTSTR) pszBuffer, sizeof (pszBuffer))) + { + if (strVersionKey.Compare (pszBuffer) < 0) + strVersionKey = pszBuffer; + } + RegCloseKey (hKey); + if (! strVersionKey.IsEmpty ()) + { + TRACE (_T("CConfigToolDoc::GetDefaultHardware(): version subkey = '%s'\n"), strVersionKey); + + // get the default hardware value + strKey += _T("\\") + strVersionKey; + if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, strKey, 0L, KEY_READ, &hKey)) + { + DWORD dwBufferSize = sizeof (pszBuffer); + lStatus = RegQueryValueEx (hKey, _T("Default Hardware"), NULL, NULL, (LPBYTE) pszBuffer, &dwBufferSize); + RegCloseKey (hKey); + if (ERROR_SUCCESS == lStatus) + { + TRACE (_T("CConfigToolDoc::GetDefaultHardware(): default hardware = '%s'\n"), pszBuffer); + rc=pszBuffer; + } + } + } + } + return rc; +} + +CConfigItem * CConfigToolDoc::AddItem (const CdlUserVisible vitem, CConfigItem * pParent) +{ + CConfigItem * pItem = new CConfigItem (pParent, vitem); + + m_arItem.Add(pItem); + pItem->m_strDesc = CUtils::StripExtraWhitespace (CString (vitem->get_description ().c_str ())); + + if (vitem->get_name () == "CYGHWR_MEMORY_LAYOUT") + { + ASSERT (m_strMemoryLayoutFolder.IsEmpty ()); + m_strMemoryLayoutFolder = vitem->get_owner ()->get_directory().c_str (); + m_strMemoryLayoutFolder.Replace(_TCHAR('/'),_TCHAR('\\')); + TRACE (_T("Found memory layout folder: %s\n"), m_strMemoryLayoutFolder); + } + + if (vitem->get_name () == "CYGBLD_LINKER_SCRIPT") + { + ASSERT (m_strLinkerScriptFolder.IsEmpty ()); + m_strLinkerScriptFolder = vitem->get_owner ()->get_directory().c_str (); + m_strLinkerScriptFolder.Replace(_TCHAR('/'),_TCHAR('\\')); + 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); + CFileName strLinkerScript (m_strPackagesDir, m_strLinkerScriptFolder, CString (valuable->get_value ().c_str ())); + strLinkerScript.Replace (_TCHAR('/'), _TCHAR('\\')); + if(!strLinkerScript.Exists ()){ + CConfigTool::Log(_T("%s does not exist\n"),strLinkerScript); + } + TRACE (_T("Target '%s' selected\n"), strLinkerScript.Tail ().Root (), pItem->Macro()); + //CFileName strBinDir = AfxGetApp () -> GetProfileString (CUtils::LoadString (IDS_KEY_TOOLS_DIR), pTarget->Name (), _T("")); + //if (! strBinDir.IsEmpty () && strBinDir.IsDir ()) + //{ + // pTarget->SetBinDir (strBinDir); + //} + } + + //TRACE(_T("Created new item from cdl: ")); + //pItem->DumpItem(); + return pItem; +} + +void CConfigToolDoc::AddAllItems () +{ + // remove any old items and packages + DeleteContents (); + if(NULL!=CConfigTool::GetControlView()){ // may not be the case for plugin + + // add the root item + CConfigItem * pItem = new CConfigItem (NULL, NULL); + m_arItem.Add(pItem); + pItem->m_strDesc = _T("The root node for all configurable items"); + + // add the remaining items using their CDL descriptions + m_strMemoryLayoutFolder = _T(""); + m_strLinkerScriptFolder = _T(""); + AddContents (m_CdlConfig, FirstItem ()); + + // check that exactly one radio button in each group is enabled + CheckRadios (); + + // update the rules (conflicts) view + UpdateFailingRuleCount (); + + if(NULL==CConfigTool::GetRulesView() || !CConfigTool::GetRulesView()->IsWindowVisible()){ + // log all conflicts + // LogConflicts (m_CdlConfig->get_structural_conflicts ()); // relating to package availability - ignore for now + LogConflicts (m_CdlConfig->get_all_conflicts ()); + } + + CConfigTool::GetControlView()->SelectItem(Item(0)); + UpdateAllViews (NULL, SelChanged, (CObject *)Item(0)); // refresh the display + if(ItemCount()>0){ + CConfigTool::GetControlView()->GetTreeCtrl().Expand(Item(0)->HItem(),TVE_EXPAND); + } + CConfigTool::GetControlView()->SetFocus(); + } +} + +const CFileName CConfigToolDoc::CurrentLinkerScript() +{ + const CConfigItem * pItem = Find (_T("CYGBLD_LINKER_SCRIPT")); + return pItem ? CFileName (m_strPackagesDir, m_strLinkerScriptFolder, pItem->StringValue ()) : _T(""); +} + +bool CConfigToolDoc::GenerateHeaders() +{ +// Copy non-config header files from the repository to the +// install tree for plugin only. The make system used by +// the standalone config tool does this for us. +#ifdef PLUGIN + typedef std::vector<CdlBuildInfo_Loadable> EntriesArray; + const EntriesArray &arEntries=BuildInfo().entries; + typedef std::vector<CdlBuildInfo_Header> HeaderArray; + for(EntriesArray::size_type j=0;j<arEntries.size();j++){ + const CdlBuildInfo_Loadable &e=arEntries[j]; + const CFileName strDir(CUtils::WPath(e.directory)); + const HeaderArray &arHeaders=e.headers; + for(HeaderArray::size_type i=0;i<arHeaders.size();i++){ + const CdlBuildInfo_Header &h=arHeaders[i]; + const CFileName strSource(PackagesDir()+strDir+CUtils::WPath(h.source)); + const CFileName strDest(HeadersDir()/*+CUtils::WPath(e.directory)*/+CUtils::WPath(h.destination)); + + if(!strDest.Head().CreateDirectory(true)){ + CUtils::MessageBoxF(_T("Failed to create %s - %s"),strDest.Head(),CUtils::GetLastErrorMessageString()); + return false; + } + if(!CUtils::CopyFile(strSource,strDest)){ + return false; // message already emitted + } + } + } +#endif + + // Generate headers + try { + CFileName strPkfConfDir(InstallTree()+_T("include\\pkgconf")); + if(!strPkfConfDir.CreateDirectory()){ + CUtils::MessageBoxF(_T("Failed to create %s - %s"),strPkfConfDir,CUtils::GetLastErrorMessageString()); + return false; + } + GetCdlConfig()->generate_config_headers(CUtils::UnicodeToStdStr(strPkfConfDir.ShortName())); + } + catch (CdlInputOutputException e) { + const CString strMsg(e.get_message().c_str()); + TRACE(_T("!!! Exception thrown calling generate_config_headers - %s"),strMsg); + CUtils::MessageBoxF(_T("Failed to generate header files - %s"),strMsg); + return false; + } + return true; +} + +const CFileName CConfigToolDoc::MLTDir () +{ + CString strPathName (GetPathName ()); + ASSERT (! strPathName.IsEmpty ()); + return strPathName.Left (strPathName.ReverseFind (_TCHAR('.'))) + _T("_mlt"); +} + +bool CConfigToolDoc::UpdateBuildInfo(bool bFirstTime) +{ + try { + GetCdlConfig()->get_build_info(m_BuildInfo); + #ifdef PLUGIN + // FIXME: this means anything not mentioned by AddFile in our scan below will be removed - including user-added items + m_peCosProject->ClearItemFlags(); + m_peCosProject->UpdateeCosProject(bFirstTime); + m_peCosProject->RemoveAllUnflaggedItems(); + #else + UNUSED_ALWAYS(bFirstTime); + generate_build_tree (GetCdlConfig(), CUtils::UnicodeToStdStr(BuildTree()), CUtils::UnicodeToStdStr(InstallTree())); + #endif + return true; + } + catch(...){ + return false; + } +} + +void CConfigToolDoc::RemoveAllItems() +{ + for(int nItem=0;nItem<ItemCount();nItem++){ + CConfigItem *pItem=Item(nItem); + deleteZ(pItem); + } + m_arItem.RemoveAll(); + + UpdateAllViews(NULL,Clear,0); +} + +void CConfigToolDoc::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); +} + +int CConfigToolDoc::GetTestExeNames (CFileNameArray &arTestExes,CFileNameArray &arMissing) +{ + arTestExes.RemoveAll(); + arMissing.RemoveAll(); + + typedef std::vector<CdlBuildInfo_Loadable> EntriesArray; + const EntriesArray &arEntries=BuildInfo().entries; + for(EntriesArray::size_type j=0;j<arEntries.size();j++){ + const CdlBuildInfo_Loadable &e=arEntries[j]; + CStringArray ar; + int n=CUtils::Chop(CString(get_tests(GetCdlConfig(),e).c_str()),ar); + for(int i=0;i<n;i++){ + CFileName strFile; + strFile.Format(_T("%s\\tests\\%s\\%s.exe"),InstallTree(),CString(e.directory.c_str()),ar[i]); + strFile.Replace(_TCHAR('/'),_TCHAR('\\')); + if(strFile.Exists()){ + arTestExes.Add(strFile); + } else { + arMissing.Add(strFile); + } + } + } + return arTestExes.GetSize(); +} + +CConfigToolDoc::GlobalConflictOutcome CConfigToolDoc::ResolveGlobalConflicts(CPtrArray *parConflictsOfInterest) +{ + m_ConflictsOutcome=NotDone; + m_arConflictsOfInterest.RemoveAll(); + if(parConflictsOfInterest){ + m_arConflictsOfInterest.Copy(*parConflictsOfInterest); + } + 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(); + CFailingRulesDialog dlg(conflicts,NULL,&m_arConflictsOfInterest); + m_ConflictsOutcome=(IDOK==dlg.DoModal())?OK:Cancel; + } + return m_ConflictsOutcome; +} + +bool CConfigToolDoc::CheckConflictsBeforeSave() +{ + if(GetCdlInterpreter()->get_toplevel()->get_all_conflicts().size()>0){ + if(Deferred&m_nRuleChecking){ + if((SuggestFixes&m_nRuleChecking)&&(Cancel==ResolveGlobalConflicts())){ + return false; + } + int nConflicts=GetCdlInterpreter()->get_toplevel()->get_all_conflicts().size(); + switch(nConflicts){ + case 0: + break; + case 1: + if(IDNO==CUtils::MessageBoxFT(MB_YESNO|MB_DEFBUTTON2,_T("There is 1 unresolved conflict. Save anyway?"))){ + return false; + } + default: + if(IDNO==CUtils::MessageBoxFT(MB_YESNO|MB_DEFBUTTON2,_T("There are %d unresolved conflicts. Save anyway?"),nConflicts)){ + return false; + } + } + } + } + return true; +} + +BOOL CConfigToolDoc::IsModified() +{ + return m_bModified || MemoryMap.map_modified(); +} + +void CConfigToolDoc::OnFileExport() +{ + CFileDialog dlg (FALSE, _T("ecm"), NULL, OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, _T("eCos Minimal Configuration (*.ecm)|*.ecm||"), AfxGetMainWnd ()); + TCHAR szBuffer [MAX_PATH * 16] = _T(""); + dlg.m_ofn.lpstrFile = szBuffer; + dlg.m_ofn.nMaxFile = MAX_PATH * 16; + dlg.m_ofn.lpstrTitle = _T("Export eCos Minimal Configuration"); + if (IDOK == dlg.DoModal ()) { + try { + TRACE (_T("Exporting eCos minimal configuration '%s'\n"), dlg.GetPathName ()); + m_CdlConfig->save (CUtils::UnicodeToStdStr (dlg.GetPathName ()), /* minimal = */ true); + } + catch (CdlStringException exception) { + CUtils::MessageBoxF (_T("Error exporting eCos minimal configuration:\n\n%s"), CString (exception.get_message ().c_str ())); + } + catch (...) { + CUtils::MessageBoxF (_T("Error exporting eCos minimal configuration.")); + } + } +} + +void CConfigToolDoc::OnFileImport() +{ + CFileDialog dlg (TRUE, NULL, NULL, OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, _T("eCos Minimal Configurations (*.ecm)|*.ecm||"), AfxGetMainWnd ()); + TCHAR szBuffer [MAX_PATH * 16] = _T(""); + dlg.m_ofn.lpstrFile = szBuffer; + dlg.m_ofn.nMaxFile = MAX_PATH * 16; + dlg.m_ofn.lpstrTitle = _T("Import eCos Minimal Configuration"); + if (IDOK == dlg.DoModal ()) { + try { + TRACE (_T("Importing eCos minimal configuration '%s'\n"), dlg.GetPathName ()); + m_CdlConfig->add (CUtils::UnicodeToStdStr (dlg.GetPathName ()), CConfigToolDoc::CdlParseErrorHandler, CConfigToolDoc::CdlParseWarningHandler); + } + catch (CdlStringException exception) { + CUtils::MessageBoxF (_T("Error importing eCos minimal configuration:\n\n%s"), CString (exception.get_message ().c_str ())); + } + catch (...) { + CUtils::MessageBoxF (_T("Error importing eCos minimal configuration.")); + } + + CWaitCursor wait; + AddAllItems (); // regenerate all the config items since the topology may have changed + if (m_strLinkerScriptFolder.IsEmpty ()) { + CUtils::MessageBoxF (_T("The eCos linker script macro CYGBLD_LINKER_SCRIPT is not defined.")); + } + if (m_strMemoryLayoutFolder.IsEmpty ()) { + CUtils::MessageBoxF (_T("The eCos memory layout macro CYGHWR_MEMORY_LAYOUT is not defined.")); + } + SwitchMemoryLayout (true); // the hardware template may have changed + UpdateBuildInfo (); + CConfigTool::GetControlView()->SelectItem (Item (0)); + SetModifiedFlag (); + } +} + +bool CConfigToolDoc::QualifyDocURL(CString &strURL) +{ + if(-1==strURL.Find(_T("://"))){ + // Relative URL - qualify it as a file URL + strURL=DocBase()+CFileName(strURL); + strURL.Replace(_TCHAR('/'),_TCHAR('\\')); + strURL=_T("file://")+strURL; + } + + if(0==strURL.Find(_T("file://"))){ + CFileName strFile(strURL.Right(strURL.GetLength()-7)); + int nIndex=strFile.ReverseFind(_TCHAR('#')); + if(-1!=nIndex){ + strFile=strFile.Left(nIndex); + } + strFile.Replace(_TCHAR('/'),_TCHAR('\\')); + if(!strFile.Exists()){ + CUtils::MessageBoxF(_T("Cannot locate the file %s"),strFile); + return false; + } + } + return true; +} + +bool CConfigToolDoc::NewMemoryLayout (const CString &strPrefix) +{ + CFileName strFileName = CurrentLinkerScript (); + TRACE(_T("Reading linker-defined memory sections from %s\n"), strFileName); + MemoryMap.new_memory_layout (); // delete the old memory layout regardless + if (! strFileName.IsEmpty ()) + MemoryMap.import_linker_defined_sections (strFileName); // read the linker-defined section names from the repository (failure is silent) + + CString strMemoryLayoutFileName = strPrefix + _T("\\mlt_") + CurrentMemoryLayout () + _T(".mlt"); + TRACE(_T("Reading memory layout from %s\n"), strMemoryLayoutFileName); + MemoryMap.load_memory_layout (strMemoryLayoutFileName); // load the new memory layout (failure is silent) + strSelectedSection = _T(""); + strSelectedRegion = _T(""); + UpdateAllViews (NULL, MemLayoutChanged); + return true; // FIXME +} + +void CConfigToolDoc::SetPathName( LPCTSTR pszPath, BOOL bAddToMRU /*= TRUE*/ ) +{ + if(_TCHAR('\0')==*pszPath){ // called like this after failed saves to put things back as they were + // CDocument::SetPathName would assert given an empty string + m_strPathName = _T(""); +#ifndef PLUGIN + SetTitle(_T("Untitled")); +#endif + m_strBuildTree = _T(""); + m_strInstallTree = _T(""); + } else { +#ifdef PLUGIN + m_strPathName = CFileName (pszPath); +#else + CDocument::SetPathName (pszPath, bAddToMRU); +#endif + CString strFolder (pszPath); + strFolder = strFolder.Left (strFolder.ReverseFind (_TCHAR('.'))); // extract folder from file path + m_strBuildTree = CFileName(strFolder + _T("_build")); + m_strInstallTree = CFileName(strFolder + _T("_install")); + } +} + +bool CConfigToolDoc::ShowHtmlHelp (LPCTSTR pszURL) +{ + + HWND hwndCaller=AfxGetMainWnd()->CWnd::GetDesktopWindow()->GetSafeHwnd(); + bool rc=false; + const CFileName strFile(HTMLHelpLinkFileName()); + CStdioFile f; + if(!CFileName(CConfigTool::strHelpFile).Exists()) { + CUtils::MessageBoxF(_T("Cannot display help - %s does not exist\n"),CConfigTool::strHelpFile); + } else if(!f.Open(strFile,CFile::typeText|CFile::modeCreate|CFile::modeWrite)){ + CUtils::MessageBoxF(_T("Cannot display help - error creating %s\n"),strFile); + } else { + CString str; + str.Format(_T("<meta HTTP-EQUIV=\"refresh\" CONTENT=\"0;URL=%s\">"),pszURL); + f.WriteString(str); + f.Close(); + if(0==HtmlHelp(hwndCaller, CConfigTool::strHelpFile, HH_DISPLAY_TOPIC, 0)){ + CUtils::MessageBoxF(_T("Cannot display %s"),pszURL); + } else { + // FIXME: Do this the first time only? + HH_WINTYPE WinType; + HWND wnd; + HH_WINTYPE *pWinType=NULL; + wnd = HtmlHelp(hwndCaller, CConfigTool::strHelpFile+_T(">mainwin"), HH_GET_WIN_TYPE, (DWORD) &pWinType); + WinType=*pWinType; + WinType.hwndCaller=hwndCaller; + WinType.fsWinProperties|=HHWIN_PROP_TRACKING; + WinType.idNotify = ID_HHNOTIFICATION; + wnd = HtmlHelp(hwndCaller, CConfigTool::strHelpFile, HH_SET_WIN_TYPE, (DWORD) &WinType); + rc=true; + } + //::DeleteFile(strFile); + } + return rc; +} + +const CString CConfigToolDoc::HTMLHelpLinkFileName() +{ + return CFileName(CConfigTool::strHelpFile).Head()+"link2.htm"; +}
