]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/common/win32/CTCommonDoc.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / configtool / common / win32 / CTCommonDoc.cpp
1 //####COPYRIGHTBEGIN####
2 //                                                                          
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
8 // This program is free software; you can redistribute it and/or modify it 
9 // under the terms of the GNU General Public License as published by the Free 
10 // Software Foundation; either version 2 of the License, or (at your option) 
11 // any later version.
12 // 
13 // This program is distributed in the hope that it will be useful, but WITHOUT 
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
15 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
16 // more details.
17 // 
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc., 
20 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 //
22 // ----------------------------------------------------------------------------
23 //                                                                          
24 //####COPYRIGHTEND####
25 #include "stdafx.h"
26
27 #include "ConfigToolDoc.h"
28
29 #ifdef PLUGIN
30   #include "CTMain.h"
31   #include "Project.h"
32   #include "ProjectManager.h"
33 #else
34   #include "MainFrm.h"
35 #endif
36
37 #include "CTUtils.h"
38 #include "CdlPackagesDialog.h"
39 #include "ConfigItem.h"
40 #include "ConfigTool.h"
41 #include "ControlView.h"
42 #include "FailingRulesDialog.h"
43 #include "FolderDialog.h"
44 #include "IdleMessage.h"
45 #include "MLTView.h"
46 #include "NotePage.h"
47 #include "RegionGeneralPage.h"
48 #include "RegKeyEx.h"
49 #include "RulesView.h"
50 #include "SectionGeneralPage.h"
51 #include "SectionRelocationPage.h"
52
53 #include <htmlhelp.h>
54 #include <shlobj.h>
55
56 #define INCLUDEFILE <string>
57 #include "IncludeSTL.h"
58 #define INCLUDEFILE "build.hxx"
59 #include "IncludeSTL.h"
60
61 #ifdef _DEBUG
62   #define new DEBUG_NEW
63   #undef THIS_FILE
64   static char THIS_FILE[] = __FILE__;
65 #endif
66
67 const CFileName &CConfigToolDoc::DefaultExternalBrowser()
68 {
69   static bool bFirstTime=true;
70   if(bFirstTime){
71     const CFileName strFile(CFileName::GetTempPath()+_T("index.html"));
72     CFile f;
73     if(f.Open(strFile,CFile::modeCreate|CFile::modeWrite)){
74       f.Close();
75       bool rc=((int)FindExecutable(strFile,_T("."),m_strDefaultExternalBrowser.GetBuffer(MAX_PATH))>32);
76       m_strDefaultExternalBrowser.ReleaseBuffer();
77       if(!rc){
78         m_strDefaultExternalBrowser=_T("");
79       }
80       ::DeleteFile(strFile);
81     }
82     bFirstTime=false;
83   }
84   return m_strDefaultExternalBrowser;
85 }
86
87 CFileName CConfigToolDoc::m_strDefaultExternalBrowser;
88
89 void CConfigToolDoc::CheckRadios()
90 {
91   for(int nItem=0;nItem<ItemCount();nItem++){
92     CConfigItem *pItem=Item(nItem);
93     if(pItem->HasRadio () && pItem==pItem->FirstRadio()){
94       CString strMsg;
95       CConfigItem *pFirstSet=NULL;
96       for(CConfigItem *pSibItem=pItem;pSibItem;pSibItem=pSibItem->NextRadio()){
97         if(pSibItem->IsEnabled ()){
98           if(pFirstSet){
99             strMsg+=_T(" ");
100             strMsg+=pSibItem->Macro ();
101           } else {
102             pFirstSet=pSibItem;
103           }
104         }
105       }
106       if(!strMsg.IsEmpty()){
107         CConfigTool::Log(_T("%s, multiple radio buttons are set: %s%s"),
108           pItem->Macro(),pFirstSet->Macro(),strMsg);
109       } else if(!pFirstSet){
110         CConfigTool::Log(_T("%s, no radio buttons are set"),pItem->Macro());
111       }
112     }
113   }
114 }
115
116 // Find the ConfigItem referencing the given CdlValuable
117 CConfigItem * CConfigToolDoc::Find (CdlValuable v)
118 {
119   for(int nItem=0;nItem<ItemCount();nItem++){
120     CConfigItem *pItem=Item(nItem);
121     if(v==pItem->GetCdlValuable()){
122       return pItem;
123     }
124   }
125   return NULL;
126 }
127
128 CConfigItem * CConfigToolDoc::Find(const CString & strWhat,WhereType where)
129 {
130   for(int nItem=0;nItem<ItemCount();nItem++){
131     CConfigItem *pItem=Item(nItem);
132     if(0==pItem->StringValue(where).Compare(strWhat)){
133       return pItem;
134     }
135   }
136   return NULL;
137 }
138
139 void CConfigToolDoc::OnMLTNewRegion() 
140 {
141   // create the property sheet
142   
143   CPropertySheet prsRegionSheet (IDS_NEW_REGION_SHEET_TITLE, CConfigTool::GetMLTView());
144   
145   // add the property pages
146   
147   CRegionGeneralPage prpGeneral;
148   CNotePage prpNote;
149   
150   prsRegionSheet.AddPage (&prpGeneral);
151   prsRegionSheet.AddPage (&prpNote);
152   
153   // setup initial values
154   
155   prpGeneral.m_strRegionName = _T("");
156   prpGeneral.m_dwRegionStartAddress = 0;
157   prpGeneral.m_dwRegionSize = 0;
158   
159   // show property sheet
160   
161   if (prsRegionSheet.DoModal () == IDOK)
162   {
163     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)))
164       ErrorBox (IDS_ERR_MEMMAP_REGION_CREATE, IDS_ERR_MEMMAP_BASE + nErrorCode);
165     else // no errors
166     {
167       SetModifiedFlag ();
168       UpdateAllViews (NULL, MemLayoutChanged);
169     }
170   }             
171 }
172
173 void CConfigToolDoc::ErrorBox (UINT uIDSIntro, UINT uIDSError)
174 {
175   CString strIntro, strError;
176   strIntro.LoadString (uIDSIntro);
177   strError.LoadString (uIDSError);
178   AfxMessageBox (strIntro + _T("\n\n") + strError);
179 }
180
181 void CConfigToolDoc::OnMLTNewSection() 
182 {
183   // create the property sheet
184   
185   CPropertySheet prsSectionSheet (IDS_NEW_SECTION_SHEET_TITLE, CConfigTool::GetMLTView());
186   
187   // add the property pages
188   
189   CSectionGeneralPage prpGeneral;
190   CSectionRelocationPage prpRelocation;
191   CNotePage prpNote;
192   
193   prsSectionSheet.AddPage (&prpGeneral);
194   prsSectionSheet.AddPage (&prpRelocation);
195   prsSectionSheet.AddPage (&prpNote);
196   
197   // initialise for a new section
198   
199   prpGeneral.m_bNameLinkerDefined = TRUE;
200   prpGeneral.m_strNameLinker = _T("");
201   prpRelocation.m_bRelocates = FALSE;
202   prpRelocation.m_bNewSection = TRUE;
203   
204   // show property sheet
205   
206   if (prsSectionSheet.DoModal () == IDOK)
207   {
208     mem_anchor initial_anchor, final_anchor;
209     mem_address initial_address;
210     CString strInitialRelativeName = _T("");
211     
212     if (prpGeneral.m_bFinalAbsolute) // final location is an absolute location
213       final_anchor = absolute;
214     else // final location is a relative location
215       final_anchor = relative;
216     
217     if (prpRelocation.m_bRelocates) // if the section relocates
218     {
219       if (prpRelocation.m_bInitialAbsolute) // initial location is an absolute location
220       {
221         initial_anchor = absolute;
222       }
223       else // initial location is a relative location
224       {
225         strInitialRelativeName = prpRelocation.m_strInitialRelativeName;
226         initial_anchor = relative;
227       }
228       initial_address = prpRelocation.m_dwInitialAddress;
229     }
230     else
231     {
232       strInitialRelativeName = prpGeneral.m_strFinalRelativeName;
233       initial_anchor = final_anchor;
234       initial_address = prpGeneral.m_dwFinalAddress;
235     }
236     
237     
238     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)))
239       ErrorBox (IDS_ERR_MEMMAP_SECTION_CREATE, IDS_ERR_MEMMAP_BASE + nErrorCode);
240     else // no errors
241     {
242       SetModifiedFlag ();
243       UpdateAllViews (NULL, MemLayoutChanged);
244     }
245   }             
246 }
247
248 void CConfigToolDoc::OnMLTDelete() 
249 {
250   if (strSelectedSection != _T("")) // a section is selected
251   {
252     if (MemoryMap.delete_memory_section (CUtils::UnicodeToStdStr(strSelectedSection)))
253     {
254       strSelectedSection = _T("");
255       SetModifiedFlag ();
256       UpdateAllViews (NULL, MemLayoutChanged);
257     }
258     else
259       AfxMessageBox (_T("Could not delete memory section.\n\nMake sure there are no other sections defined relative to this one."));
260   }
261   else if (strSelectedRegion != _T("")) // a region is selected
262   {
263     if (MemoryMap.delete_memory_region (CUtils::UnicodeToStdStr(strSelectedRegion)))
264     {
265       strSelectedRegion = _T("");
266       SetModifiedFlag ();
267       UpdateAllViews (NULL, MemLayoutChanged);
268     }
269     else
270       AfxMessageBox (_T("Could not delete memory region.\n\nMake sure it is not in use.")); // FIXME
271   }
272 }
273
274 void CConfigToolDoc::ShowRegionProperties()
275 {
276   // create the property sheet
277   
278   CString strTitle;
279   strTitle.LoadString (IDS_REGION_PROPERTIES_SHEET_TITLE);
280   CPropertySheet prsRegionSheet (strSelectedRegion + _T(" - ") + strTitle, CConfigTool::GetMLTView());
281   
282   // add the property pages
283   
284   CRegionGeneralPage prpGeneral;
285   CNotePage prpNote;
286   
287   prsRegionSheet.AddPage (&prpGeneral);
288   prsRegionSheet.AddPage (&prpNote);
289   
290   // set up property sheet values
291   
292   mem_type type;
293   std::string note;
294   MemoryMap.get_memory_region (CUtils::UnicodeToStdStr(strSelectedRegion), &prpGeneral.m_dwRegionStartAddress, &prpGeneral.m_dwRegionSize, &type, &note);
295   prpGeneral.m_strRegionName = strSelectedRegion;
296   prpGeneral.m_bRegionReadOnly = (type == read_only);
297   prpNote.m_strNote = note.c_str ();
298   
299   // show property sheet
300   
301   if (prsRegionSheet.DoModal () == IDOK)
302   {
303     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)))
304       ErrorBox (IDS_ERR_MEMMAP_REGION_MODIFY, IDS_ERR_MEMMAP_BASE + nErrorCode);
305     else // no errors
306     {
307       SetModifiedFlag ();
308       UpdateAllViews (NULL, MemLayoutChanged);
309     }
310   }             
311 }
312
313 void CConfigToolDoc::ShowSectionProperties()
314 {
315   // create the property sheet
316   
317   CString strTitle;
318   strTitle.LoadString (IDS_SECTION_PROPERTIES_SHEET_TITLE);
319   CPropertySheet prsSectionSheet (strSelectedSection + _T(" - ") + strTitle, CConfigTool::GetMLTView());
320   
321   // add the property pages
322   
323   CSectionGeneralPage prpGeneral;
324   CSectionRelocationPage prpRelocation;
325   CNotePage prpNote;
326   
327   prsSectionSheet.AddPage (&prpGeneral);
328   prsSectionSheet.AddPage (&prpRelocation);
329   prsSectionSheet.AddPage (&prpNote);
330   
331   // setup initial values
332   
333   std::list <mem_section>::iterator section = MemoryMap.find_memory_section (CUtils::UnicodeToStdStr(strSelectedSection));
334   prpGeneral.m_bNameLinkerDefined = (section->linker_defined);
335   if (prpGeneral.m_bNameLinkerDefined)
336     prpGeneral.m_strNameLinker = section->name.c_str ();
337   else
338   {
339     prpGeneral.m_strNameUser = section->name.c_str ();
340     prpGeneral.m_dwSectionSize = section->size;
341   }
342   
343   prpGeneral.m_bFinalAbsolute = (section->final_location->anchor == absolute);
344   if (prpGeneral.m_bFinalAbsolute)
345     prpGeneral.m_dwFinalAddress = section->final_location->address;
346   else
347   {
348     prpGeneral.m_strFinalRelativeName = MemoryMap.find_preceding_section (section, false)->name.c_str ();
349     prpGeneral.m_dwAlignment = section->alignment;
350   }
351   
352   prpRelocation.m_bRelocates = section->relocates;
353   if (prpRelocation.m_bRelocates)
354   {
355     prpRelocation.m_bInitialAbsolute = (section->initial_location->anchor == absolute);
356     if (prpRelocation.m_bInitialAbsolute)
357       prpRelocation.m_dwInitialAddress = section->initial_location->address;
358     else
359       prpRelocation.m_strInitialRelativeName = MemoryMap.find_preceding_section (section, true)->name.c_str ();
360   }
361   
362   prpNote.m_strNote = section->note.c_str ();
363   
364   // show property sheet
365   
366   if (prsSectionSheet.DoModal () == IDOK)
367   {
368     mem_anchor initial_anchor, final_anchor;
369     mem_address initial_address;
370     CString strInitialRelativeName = _T("");
371     
372     if (prpGeneral.m_bFinalAbsolute) // final location is an absolute location
373       final_anchor = absolute;
374     else // final location is a relative location
375       final_anchor = relative;
376     
377     if (prpRelocation.m_bRelocates) // if the section relocates
378     {
379       if (prpRelocation.m_bInitialAbsolute) // initial location is an absolute location
380       {
381         initial_anchor = absolute;
382       }
383       else // initial location is a relative location
384       {
385         strInitialRelativeName = prpRelocation.m_strInitialRelativeName;
386         initial_anchor = relative;
387       }
388       initial_address = prpRelocation.m_dwInitialAddress;
389     }
390     else
391     {
392       strInitialRelativeName = prpGeneral.m_strFinalRelativeName;
393       initial_anchor = final_anchor;
394       initial_address = prpGeneral.m_dwFinalAddress;
395     }
396     
397     
398     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)))
399       ErrorBox (IDS_ERR_MEMMAP_SECTION_MODIFY, IDS_ERR_MEMMAP_BASE + nErrorCode);
400     else // no errors
401     {
402       SetModifiedFlag ();
403       UpdateAllViews (NULL, MemLayoutChanged);
404     }
405   }             
406 }
407
408 void CConfigToolDoc::OnMLTProperties() 
409 {
410   if (strSelectedRegion != _T(""))
411     ShowRegionProperties ();
412   else if (strSelectedSection != _T(""))
413     ShowSectionProperties ();
414 }
415
416 // Choose a default Hal.  Do this using clues the installer may have helpfully left behind (PR 18050)
417 // or else if there is only one possible choice, by choosing that one :-).
418 /*
419 void CConfigToolDoc::ChooseDefaultHal()
420 {
421 bool bFound=false;
422 // Has the installer told us?
423 LPCTSTR pszRegPath=_T("SOFTWARE\\Red Hat\\eCos\\1.2.8");
424 HKEY hKey;
425 if(ERROR_SUCCESS==RegOpenKeyEx (HKEY_LOCAL_MACHINE, pszRegPath, 0L, KEY_READ, &hKey)){
426 DWORD dwSizePath=MAX_PATH;
427 CString str;
428 PTCHAR psz=str.GetBuffer(dwSizePath);
429 if(ERROR_SUCCESS==RegQueryValueEx(hKey, _T("Default Architecture"), NULL, NULL, (LPBYTE)psz, &dwSizePath)){
430 str.MakeLower();
431 for(int nItem=0;nItem<ItemCount();nItem++){
432 CConfigItem *pItem=Item(nItem);
433 if(pItem->m_pTarget){
434 CString strTarget(pItem->m_pTarget->Name());
435 strTarget.MakeLower();
436 if(-1!=str.Find(strTarget)){
437 bFound=true;
438 dwSizePath=MAX_PATH;
439 if(ERROR_SUCCESS==::RegQueryValueEx(hKey, _T("Default Build Tools Path"), NULL, NULL, (LPBYTE)psz, &dwSizePath)){
440 pItem->m_pTarget->SetBinDir(psz);
441 for(CConfigItem *pSib=pItem->FirstRadio();pSib;pSib=pSib->NextRadio()){
442 pSib->SetValue((ItemIntegerType) (pSib==pItem));
443 }
444 //                            pItem->EnableAncestors();
445 }
446 break;
447 }
448 }
449 }
450 }
451 RegCloseKey(hKey);
452 }
453
454   if(!bFound){
455   // No - choose the Hal according to toolchain
456   for(int nItem=0;nItem<ItemCount();nItem++){
457   CConfigItem *pItem=Item(nItem);
458   if(pItem->m_pTarget){
459   CString strTarget(pItem->m_pTarget->Name());
460   strTarget.MakeLower();
461   for(int j=0;j<m_arstrToolChainPaths.GetSize();j++){
462   CString strTools(m_arstrToolChainPaths[j]);
463   strTools.MakeLower();
464   if(-1!=strTools.Find(strTarget)){
465   for(CConfigItem *pSib=pItem->FirstRadio();pSib;pSib=pSib->NextRadio()){
466   pSib->SetValue((ItemIntegerType) (pSib==pItem));
467   }
468   return;
469   }
470   }
471   }
472   }
473   }
474   }
475 */
476
477 bool CConfigToolDoc::SetValue (CConfigItem &ti, double dValue, CdlTransaction transaction/*=NULL*/)
478 {
479   ASSERT (ti.Type () == CConfigItem::Double);
480   
481   // test if the new double value is in range
482   const CdlValuable valuable = ti.GetCdlValuable();
483   CdlListValue list_value;
484   CdlEvalContext context (NULL, ti.GetCdlItem (), ti.GetCdlItem ()->get_property (CdlPropertyId_LegalValues));
485   valuable->get_legal_values ()->eval (context, list_value);
486   if (! list_value.is_member (dValue))
487   {
488     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?"),
489       CUtils::DoubleToStr (dValue), ti.Macro ()))
490       return false;
491   }
492   
493   if (! ti.SetValue (dValue,transaction))
494     return false;
495   
496   SetModifiedFlag ();
497   return true;
498 }
499 bool CConfigToolDoc::SetValue(CConfigItem &ti,const CString &strValue, CdlTransaction transaction/*=NULL*/)
500 {
501   // warn the user if a modified memory layout is about to be discarded
502   if (MemoryMap.map_modified () && (ti.Macro () == _T("CYG_HAL_STARTUP")) &&
503     (IDCANCEL == CUtils::MessageBoxFT (MB_OKCANCEL, _T("Changes to the current memory layout will be lost."))))
504     return false;
505   
506   bool rc=false;
507   switch(ti.Type()){
508                 case CConfigItem::None:
509       break;
510     case CConfigItem::Enum:
511     case CConfigItem::String:
512       rc=ti.SetValue(strValue,transaction);
513       break;
514     case CConfigItem::Integer:
515       {
516         ItemIntegerType n;
517         rc=CUtils::StrToItemIntegerType(strValue,n) && SetValue(ti,n,transaction);
518       }
519       break;
520     case CConfigItem::Double:
521       {
522         double dValue;
523         rc = CUtils::StrToDouble (strValue, dValue) && SetValue (ti, dValue,transaction);
524       }
525       break;
526     default:
527       ASSERT(FALSE);
528       break;
529       
530   }
531   if(rc){
532     SetModifiedFlag();
533     UpdateAllViews (NULL, CConfigToolDoc::ValueChanged, (CObject *)&ti);
534   }
535   return rc;
536 }
537
538 // Look in registry to match prefixes CYGPKG_HAL_ and CYGHWR_HAL_:
539 //
540 bool CConfigToolDoc::GetRunPlatform(CString &strTarget)
541 {
542   CRegKeyEx k1(HKEY_CURRENT_USER,_T("Software\\Red Hat\\eCos\\Platforms"), KEY_READ);
543   CString strKey;
544   for(int i=0;k1.QueryKey(i,strKey);i++){
545     CRegKeyEx k2((HKEY)k1,strKey,KEY_READ);
546     // Subkeys' names are the target image names [one of which we aim to return]
547     // Subkeys's values of interest are:
548     //      Prefix  String
549     //      Sim     DWORD  [optional]
550     //      Macro   String 
551     DWORD dwSim=0;
552     CString strPrefix,strMacro;
553     k2.QueryValue(_T("Sim"),dwSim);
554     k2.QueryValue(_T("Prefix"),strPrefix);
555     k2.QueryValue(_T("Macro"),strMacro);
556
557     CConfigItem *pItem=Find(_T("CYGPKG_HAL_")+strMacro);
558     if(pItem && pItem->IsEnabled()){
559       // We have found what we are looking for - probably
560       pItem=Find(_T("CYGHWR_HAL_")+strMacro+_T("_STARTUP"));
561       if(pItem){
562         // Two platforms apply - choose this one only if the ram startup attribute fits
563         if( (dwSim==0) == (0==pItem->StringValue().CompareNoCase(_T("ram"))) ) {
564           strTarget=strKey;
565         }
566       } else {
567         // Only one platform applies
568         strTarget=strKey;
569       }
570       
571     }
572   }
573   return !strTarget.IsEmpty();
574 }
575
576 bool CConfigToolDoc::SetEnabled(CConfigItem &ti, bool bEnabled, CdlTransaction transaction/*=NULL*/)
577 {
578   const bool bStatus = ti.SetEnabled (bEnabled,transaction);
579   
580   if (bStatus) {
581     SetModifiedFlag();
582     UpdateAllViews (NULL, CConfigToolDoc::ValueChanged, (CObject *) &ti);
583   }
584   return bStatus;
585 }
586
587 void CConfigToolDoc::AddContents (const CdlContainer container, CConfigItem *pParent)
588 {
589   
590   // determine the container contents
591   
592   const std::vector<CdlNode>& contents = container->get_contents ();
593   std::vector<CdlNode>::const_iterator node_i;
594   for (node_i = contents.begin (); node_i != contents.end (); node_i++)
595   {
596     const CdlNode node = * node_i;
597     const CdlPackage pkg = dynamic_cast<CdlPackage> (node);
598     const CdlComponent comp = dynamic_cast<CdlComponent> (node);
599     const CdlOption opt = dynamic_cast<CdlOption> (node);
600     const CdlContainer contnr = dynamic_cast<CdlContainer> (node);
601     
602     // if the node in the container is a package, component or option
603     // then it is visible and should be added to the tree
604     if  (0 != pkg) // the node is a package
605     {
606       CConfigItem * pItem = AddItem (pkg, pParent); // add the package
607       AddContents (pkg, pItem); // add the package contents
608     }
609     else if (0 != comp) // the node is a component
610     {
611       CConfigItem * pItem = AddItem (comp, pParent); // add the component
612       AddContents (comp, pItem); // add the component contents
613     }
614     else if (0 != opt) // the node is an option
615       AddItem (opt, pParent); // add the option
616     
617     else if (0 != contnr) // if the node is a container
618       AddContents (contnr, pParent); // add the container contents
619     
620     // ignore nodes of any other class
621   }
622 }
623
624 // Three hack functions.
625
626 const CString CConfigToolDoc::CurrentPlatform()
627 {
628 /*
629 for(int nItem=0;nItem<ItemCount();nItem++){
630 CConfigItem *pItem=Item(nItem);
631 if(pItem->IsEnabled() && !pItem->Platform().IsEmpty()){
632 return pItem->Platform();
633 }
634 }
635   */
636   return _T("");
637 }
638
639 // a trivial CDL parse error handler
640 void CConfigToolDoc::CdlParseErrorHandler (std::string message)
641 {
642   CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
643   pDoc->m_strCdlErrorMessage = message.c_str ();
644   TRACE (_T("CdlParseError: %s\n"), pDoc->m_strCdlErrorMessage);
645   CConfigTool::Log (CUtils::StripExtraWhitespace (pDoc->m_strCdlErrorMessage)); // display the message in the output window
646 };
647
648 // a trivial CDL parse warning handler
649 void CConfigToolDoc::CdlParseWarningHandler (std::string message)
650 {
651   CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
652   pDoc->m_strCdlErrorMessage = message.c_str ();
653   TRACE (_T("CdlParseWarning: %s\n"), pDoc->m_strCdlErrorMessage);
654   CConfigTool::Log (CUtils::StripExtraWhitespace (pDoc->m_strCdlErrorMessage)); // display the message in the output window
655 };
656
657 // a trivial CDL load error handler
658 void CConfigToolDoc::CdlLoadErrorHandler (std::string message)
659 {
660   CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
661   pDoc->m_strCdlErrorMessage = message.c_str ();
662   TRACE (_T("CdlLoadError: %s\n"), pDoc->m_strCdlErrorMessage);
663   CConfigTool::Log (CUtils::StripExtraWhitespace (pDoc->m_strCdlErrorMessage)); // display the message in the output window
664 };
665
666 // a trivial CDL load warning handler
667 void CConfigToolDoc::CdlLoadWarningHandler (std::string message)
668 {
669   CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
670   pDoc->m_strCdlErrorMessage = message.c_str ();
671   TRACE (_T("CdlLoadWarning: %s\n"), pDoc->m_strCdlErrorMessage);
672   CConfigTool::Log (CUtils::StripExtraWhitespace (pDoc->m_strCdlErrorMessage)); // display the message in the output window
673 };
674
675 CdlInferenceCallbackResult CConfigToolDoc::CdlGlobalInferenceHandler(CdlTransaction transaction)
676 {
677   CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
678   pDoc->m_ConflictsOutcome=NotDone;  // prepare for the case that there are no solutions
679   CdlInferenceCallbackResult rc=CdlInferenceCallbackResult_Continue;
680   /*
681   std::list<CdlConflict>conflicts1(transaction->get_global_conflicts_with_solutions());
682   const std::vector<CdlConflict>&conflicts2=transaction->get_resolved_conflicts();
683         for (unsigned int i = 0; i < conflicts2.size (); i++) {
684                 conflicts1.push_back(conflicts2 [i]);
685         }
686   if(conflicts1.size()>0){
687     CFailingRulesDialog dlg(conflicts1,transaction,&pDoc->m_arConflictsOfInterest);
688     rc=(IDOK==dlg.DoModal())?CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel;
689     pDoc->m_ConflictsOutcome=(CdlInferenceCallbackResult_Continue==rc)?OK:Cancel;
690   }
691   */
692   const std::list<CdlConflict>& conflicts=pDoc->GetCdlConfig()->get_all_conflicts();  
693   CFailingRulesDialog dlg(conflicts,transaction,&pDoc->m_arConflictsOfInterest);
694   rc=(IDOK==dlg.DoModal())?CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel;
695   pDoc->m_ConflictsOutcome=(CdlInferenceCallbackResult_Continue==rc)?OK:Cancel;
696
697   return rc;
698 }
699
700 CdlInferenceCallbackResult CConfigToolDoc::CdlInferenceHandler (CdlTransaction transaction)
701 {
702   CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
703   CdlInferenceCallbackResult rc=CdlInferenceCallbackResult_Continue;
704   const std::list<CdlConflict>&conflicts=transaction->get_new_conflicts();
705   if((pDoc->m_nRuleChecking&Immediate) && conflicts.size()>0){
706     if(pDoc->m_nRuleChecking&SuggestFixes){
707       std::list<CdlConflict> s_conflicts;
708       for (std::list<CdlConflict>::const_iterator conf_i= conflicts.begin (); conf_i != conflicts.end (); conf_i++) { // for each conflict
709         if((*conf_i)->has_known_solution()){
710           s_conflicts.push_back(*conf_i);
711         }
712       }
713       if(s_conflicts.size()>0){
714         CFailingRulesDialog dlg(s_conflicts,transaction);
715         return(IDOK==dlg.DoModal()?CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel);
716       }
717     } 
718     CString strMsg;
719     if(1==conflicts.size()){
720       strMsg=(_T("There is 1 unresolved conflict."));
721     } else {
722       strMsg.Format(_T("There are %d unresolved conflict%s."),conflicts.size(),1==conflicts.size()?_T(""):_T("s"));
723     }
724     rc=(IDYES==CUtils::MessageBoxFT(MB_YESNO|MB_DEFBUTTON2,_T("%s  Make the change anyway?"),strMsg))?CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel;
725   }
726   return rc;
727 }
728
729
730 // a CDL transaction handler to refresh the configuration tree
731 void CConfigToolDoc::CdlTransactionHandler (const CdlTransactionCallback & data)
732 {
733 static int nNesting=0;
734 TRACE(_T("Transaction handler: nesting level=%d\n"),nNesting++);
735   CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
736   std::vector<CdlValuable>::const_iterator val_i;
737   std::vector<CdlNode>::const_iterator node_i;
738   std::list<CdlConflict>::const_iterator conf_i;
739   CControlView *pControlView=CConfigTool::GetControlView();
740   for (val_i = data.value_changes.begin(); val_i != data.value_changes.end(); val_i++)
741   {
742     const CString strName((*val_i)->get_name().c_str());
743     TRACE(_T("%s %s : value change\n"), CString ((*val_i)->get_class_name().c_str()), strName);
744     pControlView->Refresh(strName);
745     if (strName==_T("CYGHWR_MEMORY_LAYOUT")){               // the memory layout has changed...
746       pDoc->SwitchMemoryLayout (false); // ...so display a new one
747     }
748   }
749   for (node_i = data.active_changes.begin(); node_i != data.active_changes.end(); node_i++)
750   {
751     const CString strName((*node_i)->get_name().c_str());
752     TRACE(_T("%s %s : this has become active or inactive\n"), CString ((*node_i)->get_class_name().c_str()),
753       CString ((*node_i)->get_name().c_str()));
754     if (! dynamic_cast<CdlInterface> (*node_i)){ // if not an interface node
755       pControlView->Refresh(strName);
756     }
757   }
758   for (val_i = data.legal_values_changes.begin(); val_i != data.legal_values_changes.end(); val_i++)
759   {
760     const CString strName((*node_i)->get_class_name().c_str());
761     TRACE(_T("%s %s : the legal_values list has changed, a new widget may be needed.\n"),
762       CString ((*val_i)->get_class_name().c_str()), strName);               
763   }
764   
765   for (val_i = data.value_source_changes.begin(); val_i != data.value_source_changes.end(); val_i++)
766   {
767     const CString strName((*val_i)->get_name().c_str());
768     CdlValueSource source = (*val_i)->get_source();
769     TRACE(_T("%s %s : the value source has changed to %s\n"),
770       CString ((*val_i)->get_class_name().c_str()), strName,
771       CString ((CdlValueSource_Default  == source) ? "default"  :
772     (CdlValueSource_Inferred == source) ? "inferred" :
773     (CdlValueSource_Wizard   == source) ? "wizard"   : "user"));
774     pControlView->Refresh (strName);
775   }
776
777   pDoc->UpdateFailingRuleCount();
778 nNesting--;
779 }
780
781 // Three hack functions.
782
783 const CString CConfigToolDoc::CurrentMemoryLayout ()
784 {
785   const CConfigItem * pItem = Find (_T("CYGHWR_MEMORY_LAYOUT"));
786 #ifdef _DEBUG
787   if(NULL==pItem){
788     TRACE(_T("Warning - CurrentMemoryLayout() returning NULL\n"));
789   }
790 #endif
791   return pItem ? pItem->StringValue () : _T("");
792 }
793
794 const CString CConfigToolDoc::CurrentTestingIdentifier ()
795 {
796   // use the CDL target as the default testing identifier
797   // override in the forthcoming testing identifier dialog as necessary
798   return GetCdlConfig()->get_hardware ().c_str ();
799
800 //  const CConfigItem * pItem = Find (_T("CYGTST_TESTING_IDENTIFIER"));
801 //#ifdef _DEBUG
802 //  if(NULL==pItem){
803 //    TRACE(_T("Warning - CurrentTestingIdentifier() returning NULL\n"));
804 //  }
805 //#endif
806 //  return pItem ? pItem->StringValue () : _T("");
807 }
808
809 const CString CConfigToolDoc::CurrentStartup()
810 {
811   const CConfigItem * pItem = Find (_T("CYG_HAL_STARTUP"));
812 #ifdef _DEBUG
813   if(NULL==pItem){
814     TRACE(_T("Warning - CurrentStartup() returning NULL\n"));
815   }
816 #endif
817   return pItem ? pItem->StringValue () : _T("");
818   
819   /*
820   for(int nItem=0;nItem<ItemCount();nItem++){
821                 CConfigItem *pItem=Item(nItem);
822     const CString strName(pItem->Name());
823     if(0==strName.Compare(_T("Startup type")) && pItem->IsEnabled()){
824     return pItem->StringValue();
825     }
826     }
827     return _T("ram"); // FIXME - assume ram startup for now if no startup item
828   */
829 }
830
831 void CConfigToolDoc::UpdateFailingRuleCount()
832 {
833   int nCount=0;
834   if (GetCdlConfig ()){
835     // if configuration information
836     
837     // calculate the number of conflicts
838     nCount =
839       //                GetCdlConfig ()->get_structural_conflicts ().size () +    ignore for now
840       GetCdlConfig ()->get_all_conflicts ().size ();
841     
842     // update the conflicts view
843     if (CConfigTool::GetRulesView ()) {
844       CConfigTool::GetRulesView ()->FillRules ();
845     }
846   }
847   if(CConfigTool::GetMain()){
848     CConfigTool::GetMain()->SetFailRulePane(nCount);
849   }
850 }
851
852 void CConfigToolDoc::LogConflicts (const std::list<CdlConflict> & conflicts)
853 {
854   std::list<CdlConflict>::const_iterator conf_i;
855   for (conf_i = conflicts.begin (); conf_i != conflicts.end (); conf_i++) // for each conflict
856   {
857     CString strExplain = (* conf_i)->get_explanation ().c_str (); // get the conflict explanation
858     CConfigTool::Log (CUtils::StripExtraWhitespace (strExplain)); // display the message in the output window
859   }
860 }
861
862 CString CConfigToolDoc::GetPackageName (const CString & strAlias)
863 {
864   const std::vector<std::string> & packages = m_CdlPkgData->get_packages ();
865   std::vector<std::string>::const_iterator package_i;
866   for (package_i = packages.begin (); package_i != packages.end (); package_i++)
867   {
868     const std::vector<std::string> & aliases = m_CdlPkgData->get_package_aliases (* package_i);
869     CString strPackageAlias = aliases [0].c_str ();
870     if (aliases.size () && (0 == strAlias.Compare (strPackageAlias)))
871       return package_i->c_str ();
872   }
873   return _T("");
874 }
875
876 void CConfigToolDoc::DeleteContents() 
877 {
878   TRACE(_T("###DeleteContents()\n"));
879 #ifndef PLUGIN
880   CDocument::DeleteContents();
881 #endif
882   
883   RemoveAllItems();
884   TRACE(_T("###DeleteContents done\n"));
885 }
886
887 void CConfigToolDoc::SelectPackages ()
888 {
889   CCdlPackagesDialog dlg;
890   // This map holds the CConfigItem pointers for the packages loaded before the dialog is invoked.
891   // We cannot use Find(), which traverses all items - potentially those that have been removed
892   CMapStringToPtr arLoadedPackages;
893
894   // generate the contents of the add/remove list boxes
895   const std::vector<std::string> & packages = m_CdlPkgData->get_packages ();
896   std::vector<std::string>::const_iterator package_i;
897   for (package_i = packages.begin (); package_i != packages.end (); package_i++)
898   {
899     //          if (! m_CdlPkgData->is_hardware_package (* package_i)) // do not list hardware packages
900     {
901       const std::vector<std::string> & aliases = m_CdlPkgData->get_package_aliases (* package_i);
902       CString strMacroName = package_i->c_str ();
903       
904       // use the first alias (if any) as the package identifier
905       CString strPackageName = aliases.size () ? aliases [0].c_str () : strMacroName;
906       CConfigItem * pItem = Find (strMacroName);
907       if (pItem) // if the package is loaded
908       {
909         arLoadedPackages.SetAt(strMacroName,pItem);
910         // pass the currently selected package version string to the dialog box
911         const CdlValuable valuable = pItem->GetCdlValuable();
912         dlg.Insert (strPackageName, TRUE, NULL, valuable ? (LPCTSTR) CString (valuable->get_value ().c_str ()) : NULL);
913       }
914       else
915       {
916         // pass version string of the most latest version to the dialog box
917         dlg.Insert (strPackageName, FALSE, NULL, (LPCTSTR) CString (m_CdlPkgData->get_package_versions (* package_i) [0].c_str ()));
918       }
919     }
920   }
921   
922   if (IDOK == dlg.DoModal ())
923   {
924     bool bChanged = false; // until proved otherwise
925
926     // determine whether each package has changed loaded/unloaded state
927     for (package_i = packages.begin (); package_i != packages.end (); package_i++)
928       //                        if (! m_CdlPkgData->is_hardware_package (* package_i)) // do not check hardware packages
929     {
930       const std::vector<std::string> & aliases = m_CdlPkgData->get_package_aliases (* package_i);
931       CString strMacroName = package_i->c_str ();
932       
933       // use the first alias (if any) as the package identifier
934       CString strPackageName = aliases.size () ? aliases [0].c_str () : strMacroName;
935       
936       CConfigItem *pItem=NULL;
937       bool bPreviouslyLoaded=arLoadedPackages.Lookup(strMacroName,(void *&)pItem);
938       bool bNowLoaded=dlg.IsAdded (strPackageName);
939       
940       // unload packages which are no longer required before
941       // loading new ones to avoid potential duplicate macro definitions
942       if (! bNowLoaded && bPreviouslyLoaded){
943         // The package was loaded but should now be unloaded:
944         bChanged|=pItem->Unload();
945       } else if (bNowLoaded) {// if the package should be loaded
946         const CString strVersion(dlg.GetVersion (strPackageName));
947         if (bPreviouslyLoaded) { // if the package is already loaded
948           CdlTransactionCallback::set_callback_fn (NULL); // avoid value refresh attempts during load/unload
949           bChanged|=pItem->ChangeVersion(strVersion);
950           CdlTransactionCallback::set_callback_fn (CdlTransactionHandler); // restore value refresh
951         } else {
952           // the package was not loaded but should now be loaded
953           TRACE (_T("Loading package %s\n"), strMacroName);
954           try
955           {
956             GetCdlConfig()->load_package (CUtils::UnicodeToStdStr(strMacroName), CUtils::UnicodeToStdStr (strVersion), CConfigToolDoc::CdlParseErrorHandler, CConfigToolDoc::CdlParseWarningHandler);
957             bChanged=true;
958           }
959           catch (CdlStringException exception)
960           {
961             CUtils::MessageBoxF(_T("Error loading package %s:\n\n%s"), strMacroName, CString (exception.get_message ().c_str ()));
962           }
963           catch (...)
964           {
965             CUtils::MessageBoxF(_T("Error loading package %s."), strMacroName);
966           }
967         }
968       }                         
969     }
970     
971     if (bChanged) {// at least one package was loaded, unloaded or changed version
972       SetModifiedFlag();
973       RegenerateData();
974     }
975   }
976 }
977
978 bool CConfigToolDoc::SetValue(CConfigItem &ti,ItemIntegerType nValue, CdlTransaction transaction/*=NULL*/)
979 {
980   switch(ti.Type()){
981                 case CConfigItem::Enum:
982     case CConfigItem::Integer:
983       //                case CConfigItem::Boolean:
984       //                case CConfigItem::Radio:
985       break;
986     case CConfigItem::None:
987     case CConfigItem::String:
988     default:
989       ASSERT(FALSE);
990       break;
991   }
992   
993   bool rc=false;
994   bool bChangingMemmap=MemoryMap.map_modified () && ((ti.Macro ().Compare (_T ("CYG_HAL_STARTUP")) == 0));
995   
996   if(nValue==ti.Value()){
997     return true;
998   }
999   
1000   // test if the new integer value is in range
1001   if (CConfigItem::Integer == ti.Type ())
1002         {
1003     const CdlValuable valuable = ti.GetCdlValuable();
1004     CdlListValue list_value;
1005     CdlEvalContext context (NULL, ti.GetCdlItem (), ti.GetCdlItem ()->get_property (CdlPropertyId_LegalValues));
1006     valuable->get_legal_values ()->eval (context, list_value);
1007     if (! list_value.is_member ((cdl_int) nValue))
1008     {
1009       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?"),
1010         CUtils::IntToStr (nValue, CConfigTool::GetConfigToolDoc ()->m_bHex), ti.Macro ()))
1011         goto Exit;
1012     };
1013         }
1014   
1015   //    if(!ti.CanSetValue(nValue))
1016   //    {
1017   //        if(bInteractive){
1018   //                    CString strExplanation;
1019   //                    if(CConfigItem::Integer==ti.Type()){
1020   //                            strExplanation.Format(_T(" [value must lie in the range %d..%d]"),
1021   //                                    CUtils::IntToStr(ti.Min(),m_bHex), 
1022   //                    CUtils::IntToStr(ti.Max()),m_bHex);
1023   //                    }
1024   //                    CUtils::MessageBoxF(
1025   //                            _T("Cannot set '%s' to %s%s"),
1026   //                            ti.ItemNameOrMacro(), CUtils::IntToStr(nValue,m_bHex), strExplanation);
1027   //        }
1028   //            goto Exit;
1029   //    }
1030   
1031   // warn the user if the current memory layout has been changed and will be lost
1032   // this will happen when the layout has been modified and the target-platform-startup is changed
1033   
1034   if (bChangingMemmap && IDCANCEL==CUtils::MessageBoxFT(MB_OKCANCEL,_T("Changes to the current memory layout will be lost."))){
1035     goto Exit;
1036   }
1037   
1038   // Save state
1039   if(!ti.SetValue(nValue,transaction)){
1040     // CanSetValue above should have caught this
1041     CUtils::MessageBoxF(_T("Cannot set '%s' to %d"),ti.ItemNameOrMacro(), nValue);
1042     goto Exit;
1043   } 
1044   
1045   rc=true;
1046 Exit:
1047   if(rc){
1048     SetModifiedFlag();
1049     UpdateFailingRuleCount ();
1050     UpdateAllViews (NULL, CConfigToolDoc::ValueChanged, (CObject *)&ti);
1051     // switch to new memory layout when target, platform or startup changes
1052     // but ignore cases where a target or platform is being deactivated (PR 19363)
1053     
1054     //          if (((CurrentTarget () != pOldTarget) || (CurrentPlatform () != strOldPlatform) || (ti.Name ().Compare (_T ("Startup type")) == 0)) &&
1055     //                  ((ti.Type () != CConfigItem::Radio) || (nValue)))
1056     //                  SwitchMemoryLayout ((CurrentTarget () != pOldTarget) || (CurrentPlatform () != strOldPlatform));
1057   }
1058   return rc;
1059 }
1060
1061 bool CConfigToolDoc::OpenRepository(LPCTSTR pszRepository/*=NULL*/,bool bPromptInitially/*=false*/)
1062 {
1063   if(!m_bRepositoryOpen){
1064     CWaitCursor wait;
1065     CIdleMessage IM(_T("Opening repository"));
1066     UpdateFailingRuleCount();
1067     
1068     CFileName strNewRepository;
1069     while(!m_bRepositoryOpen){
1070       
1071       if(bPromptInitially){
1072         CFolderDialog dlg(/*BOOL bAllowCreation=*/false);
1073         dlg.m_strDesc=_T("Please specify the root of the eCos repository tree.");
1074         dlg.m_strTitle=_T("Choose folder for eCos repository");
1075         dlg.m_strFolder=strNewRepository;
1076         CConfigTool::DismissSplash();
1077         if(IDCANCEL==dlg.DoModal()){
1078           return false;
1079         }
1080         strNewRepository=dlg.m_strFolder;
1081       } else {
1082         // Use what came in as parameter or what was found in registry
1083         strNewRepository=pszRepository?pszRepository:m_strRepository;
1084         bPromptInitially=true;
1085       }
1086       
1087       IM.Set (_T("Opening repository ") + (CString) strNewRepository);
1088       
1089       CdlPackagesDatabase NewCdlPkgData = NULL;
1090       CdlInterpreter      NewCdlInterp  = NULL;
1091       CdlConfiguration    NewCdlConfig  = NULL;
1092       CFileName strNewPackagesDir;
1093       
1094       EnableCallbacks(false); // disable transaction callbacks until the config tree is regenerated
1095       
1096       if(OpenRepository(strNewRepository,NewCdlPkgData,NewCdlInterp,NewCdlConfig,strNewPackagesDir)){
1097         // Success
1098         
1099         // select the "default" template if it exists
1100         // otherwise select the first available template
1101         std::string default_template = "default";
1102         if (! NewCdlPkgData->is_known_template (default_template))
1103         {
1104           const std::vector<std::string>& templates = NewCdlPkgData->get_templates ();
1105           if (templates.size () != 0)
1106             default_template = templates [0];
1107         }
1108         
1109         m_template_version = "";
1110         try
1111         {
1112           const std::vector<std::string>& template_versions = NewCdlPkgData->get_template_versions (default_template);
1113           NewCdlConfig->set_template (default_template, template_versions [0], &CdlParseErrorHandler, &CdlParseWarningHandler);
1114           m_template_version = template_versions [0];
1115         }
1116         catch (CdlStringException exception) {
1117           CUtils::MessageBoxF(_T("Error loading package template '%s':\n\n%s"), CString (default_template.c_str ()), CString (exception.get_message ().c_str ()));
1118         }
1119         catch (...) {
1120           CUtils::MessageBoxF(_T("Error loading package template '%s'."), CString (default_template.c_str ()));
1121         }
1122         
1123         // check the configuration
1124         ASSERT (NewCdlConfig->check_this (cyg_extreme));
1125         
1126         // use the new package database, interpreter and configuration
1127         deleteZ(m_CdlConfig); // delete the previous configuration
1128         deleteZ(m_CdlInterp); // delete the previous interpreter
1129         deleteZ(m_CdlPkgData); // delete the previous package database
1130         
1131         m_CdlPkgData = NewCdlPkgData;
1132         m_CdlInterp  = NewCdlInterp;
1133         m_CdlConfig  = NewCdlConfig;
1134         
1135         // save the repository location
1136         
1137         SetRepository(strNewRepository);
1138         m_strPackagesDir = strNewPackagesDir;
1139         
1140 #ifndef PLUGIN
1141         // clear the previously specified document file name (if any),
1142         // OnNewDocument() calls DeleteContents() so must be called
1143         // before AddAllItems()
1144         CDocument::OnNewDocument ();
1145 #endif
1146         
1147         // generate the CConfigItems from their CDL descriptions
1148         AddAllItems ();
1149         
1150         m_bRepositoryOpen=true;
1151       } else {
1152         // failure
1153         deleteZ(NewCdlConfig);
1154         deleteZ(NewCdlInterp);
1155         deleteZ(NewCdlPkgData);
1156         
1157       }
1158       
1159       // install a transaction handler callback function now that the tree exists
1160       EnableCallbacks(true);
1161     }
1162     
1163     }
1164     return m_bRepositoryOpen;
1165 }
1166
1167 // Helper fn for namesake above
1168 bool CConfigToolDoc::OpenRepository (const CFileName strNewRepository,CdlPackagesDatabase &NewCdlPkgData,CdlInterpreter &NewCdlInterp,CdlConfiguration &NewCdlConfig,CFileName &strNewPackagesDir)
1169 {
1170   bool rc=false;
1171   TRACE(_T("###Open repository %s\n"),strNewRepository);
1172   if(!strNewRepository.IsEmpty()){
1173     // Now strNewRepository is guaranteed non-empty, but does it exist?
1174     if(!strNewRepository.IsDir()) {
1175       CUtils::MessageBoxF(_T("Cannot open repository - the folder %s does not exist"), strNewRepository);
1176     } else {
1177     
1178       // Ok so it exists, but does it look right?
1179       strNewPackagesDir=strNewRepository+_T("ecc");
1180       if(!strNewPackagesDir.IsDir()){
1181         strNewPackagesDir=strNewRepository+_T("packages");
1182       }
1183     
1184       if(!strNewPackagesDir.IsDir()){
1185         // Don't mention the ecc\ attempt
1186         CUtils::MessageBoxF(_T("%s does not seem to be a source repository: the folder %s does not exist"),
1187           strNewRepository,strNewPackagesDir);
1188       } else {
1189       
1190         const CFileName strDatabase = strNewPackagesDir + _T("ecos.db");
1191         if(!strDatabase.Exists()) {
1192           CUtils::MessageBoxF(_T("%s does not seem to be a source repository: %s does not exist"), strNewRepository, strDatabase);
1193         } else {
1194         
1195           // create a CDL repository, interpreter and configuration
1196         
1197           try {// create a new package database, interpreter and configuration
1198             NewCdlPkgData = CdlPackagesDatabaseBody::make (CUtils::UnicodeToStdStr(strNewPackagesDir), &CdlParseErrorHandler, &CdlParseWarningHandler);
1199             NewCdlInterp = CdlInterpreterBody::make ();
1200             NewCdlConfig = CdlConfigurationBody::make ("eCos", NewCdlPkgData, NewCdlInterp);
1201           }
1202           catch (CdlStringException exception) {
1203             CUtils::MessageBoxF(_T("Error opening eCos repository:\n\n%s"), CString (exception.get_message ().c_str ()));
1204             return false;
1205           }
1206           catch (...) {
1207             CUtils::MessageBoxF(_T("Error opening eCos repository."));
1208             return false;
1209           }
1210         
1211           // select the default target if specified in the registry
1212           // otherwise select the first available target
1213           std::string default_hardware = CUtils::UnicodeToStdStr (GetDefaultHardware ());
1214           if (! NewCdlPkgData->is_known_target (default_hardware)) {
1215             const std::vector<std::string>& targets = NewCdlPkgData->get_targets ();
1216             if (targets.size () == 0){
1217               CUtils::MessageBoxF (_T("Error opening eCos repository:\n\nno hardware templates"));
1218               return false;
1219             } else {
1220               default_hardware = targets [0];
1221             }
1222           }
1223         
1224           try {
1225             m_strCdlErrorMessage = _T("");
1226             NewCdlConfig->set_hardware (default_hardware, &CdlParseErrorHandler, &CdlParseWarningHandler);
1227           }
1228           catch (CdlStringException exception) {
1229             if (m_strCdlErrorMessage.IsEmpty ())
1230             {
1231               CUtils::MessageBoxF (_T("Error loading the default hardware template '%s':\n\n%s"), CString (default_hardware.c_str ()), CString (exception.get_message ().c_str ()));
1232             }
1233             else // report the most recent parser message in the message box since there may be no output pane in which to view it
1234             {
1235               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);
1236             }
1237             return false;
1238           }
1239           catch (...) {
1240             CUtils::MessageBoxF (_T("Error loading the default hardware template '%s':\n\n%s"), CString (default_hardware.c_str ()), m_strCdlErrorMessage);
1241             return false;
1242           }
1243           rc=true;
1244         }
1245       }
1246     }
1247   }
1248   return rc;
1249 }    
1250
1251 void CConfigToolDoc::CloseRepository()
1252 {
1253   if(m_bRepositoryOpen){
1254     // delete the libCDL objects with the document
1255     EnableCallbacks(false); // first disable the transaction handler
1256     deleteZ(m_CdlConfig);
1257     deleteZ(m_CdlInterp);
1258     deleteZ(m_CdlPkgData);
1259     m_bRepositoryOpen=false;
1260   }
1261 }
1262
1263 void CConfigToolDoc::SelectTemplate (std::string NewTemplate, std::string NewTemplateVersion)
1264 {
1265   if ((NewTemplate != m_CdlConfig->get_template()) || (NewTemplateVersion != m_template_version)){
1266
1267     CWaitCursor wait; // this may take a little while
1268     RemoveAllItems();
1269     m_template_version = "";
1270     try
1271     {
1272       m_CdlConfig->set_template (NewTemplate, NewTemplateVersion, CdlParseErrorHandler, CdlParseWarningHandler);
1273       m_template_version = NewTemplateVersion;
1274     }
1275     catch (CdlStringException exception)
1276     {
1277       CUtils::MessageBoxF(_T("Error loading package template '%s':\n\n%s"), CString (NewTemplate.c_str ()), CString (exception.get_message ().c_str ()));
1278     }
1279     catch (...)
1280     {
1281       CUtils::MessageBoxF(_T("Error loading package template '%s'."), CString (NewTemplate.c_str ()));
1282     }
1283     RegenerateData();  
1284
1285     if (!GetPathName().IsEmpty()){ // not a new document
1286       CopyMLTFiles (); // copy new MLT files to the build tree as necessary
1287     }
1288     SetModifiedFlag();
1289   }
1290 }
1291
1292 void CConfigToolDoc::RegenerateData()
1293 {
1294   CWaitCursor wait; // This may take a little while
1295   AddAllItems (); // regenerate all the config items since the topology may have changed
1296   if (m_strLinkerScriptFolder.IsEmpty ())
1297   {
1298     CUtils::MessageBoxF(_T("The eCos linker script macro CYGBLD_LINKER_SCRIPT is not defined."));
1299   }
1300   if (m_strMemoryLayoutFolder.IsEmpty ())
1301   {
1302     CUtils::MessageBoxF(_T("The eCos memory layout macro CYGHWR_MEMORY_LAYOUT is not defined."));
1303   }
1304   SwitchMemoryLayout (true); // the hardware template may have changed
1305   UpdateBuildInfo();
1306   CConfigTool::GetControlView()->SelectItem(Item(0));
1307 }
1308
1309 void CConfigToolDoc::SelectHardware (std::string NewTemplate)
1310 {
1311   const std::string OldTemplate=m_CdlConfig->get_hardware();
1312   if (NewTemplate != OldTemplate){
1313     RemoveAllItems();
1314
1315     try
1316     {
1317       m_CdlConfig->set_hardware (NewTemplate, CdlParseErrorHandler, CdlParseWarningHandler);
1318     }
1319     catch (CdlStringException exception)
1320     {
1321       CUtils::MessageBoxF(_T("Error loading hardware template '%s':\n\n%s"), CString (NewTemplate.c_str ()), CString (exception.get_message ().c_str ()));
1322       m_CdlConfig->set_hardware (OldTemplate, CdlParseErrorHandler, CdlParseWarningHandler);
1323     }
1324     catch (...)
1325     {
1326       CUtils::MessageBoxF(_T("Error loading hardware template '%s'."), CString (NewTemplate.c_str ()));
1327       m_CdlConfig->set_hardware (OldTemplate, CdlParseErrorHandler, CdlParseWarningHandler);
1328     }
1329   
1330     RegenerateData();
1331     //EnableCallbacks(true); // re-enable the transaction handler
1332     if (!GetPathName().IsEmpty()){
1333       CopyMLTFiles (); // copy new MLT files to the build tree as necessary
1334     }
1335     SetModifiedFlag();
1336   }
1337 }
1338
1339 bool CConfigToolDoc::SaveMemoryMap()
1340 {
1341   const CString strSuffix(_T("mlt_") + CurrentMemoryLayout ());
1342   const CFileName strMLTInstallPkgconfDir(InstallTree() + _T("include\\pkgconf"));
1343   bool rc=false;
1344   if(strMLTInstallPkgconfDir.CreateDirectory(true)){
1345     const CString strMLTInstallBase(strMLTInstallPkgconfDir+CFileName(strSuffix));
1346     const CFileName strMLTDir (MLTDir());
1347     if(strMLTDir.CreateDirectory (true)){
1348       const CString strMLTBase (strMLTDir + CFileName (strSuffix));
1349       TRACE(_T("Saving memory layout to %s\n"), strMLTBase + _T(".mlt"));
1350       if(MemoryMap.save_memory_layout (strMLTBase + _T(".mlt"))){
1351         TRACE(_T("Exporting memory layout to %s\n"), strMLTInstallPkgconfDir);
1352         rc=MemoryMap.export_files (strMLTInstallBase + _T(".ldi"), strMLTInstallBase + _T(".h"));
1353       }
1354     }
1355   }    
1356   return rc;
1357 }
1358
1359 bool CConfigToolDoc::CopyMLTFiles()
1360 {
1361   // copy default MLT files for the selected target/platform from the repository if they do not already exist
1362
1363   TRACE (_T("Looking for MLT files at %s\n"), PackagesDir() + m_strMemoryLayoutFolder + _T("include\\pkgconf\\mlt_*.*"));
1364   const CFileName strInstallDestination(InstallTree () + _T("include\\pkgconf"));
1365   const CFileName strMLTDestination (MLTDir ());
1366   TRACE (_T("Copying .ldi and .h files to %s\n"), strInstallDestination);
1367   TRACE (_T("Copying .mlt files to %s\n"), strMLTDestination);
1368   bool rc=strInstallDestination.CreateDirectory (true) && strMLTDestination.CreateDirectory (true);
1369   if(rc){
1370     CFileFind ffFileFind;
1371     BOOL bLastFile = ffFileFind.FindFile (PackagesDir() + m_strMemoryLayoutFolder + _T("\\include\\pkgconf\\mlt_*.*"));
1372     while (bLastFile)
1373     {
1374       bLastFile = ffFileFind.FindNextFile ();
1375       if (_T(".mlt") == ffFileFind.GetFileName ().Right (4)) // if a .mlt file
1376       {
1377         if (! CFileName (strMLTDestination, CFileName (ffFileFind.GetFileName ())).Exists ())
1378         {
1379           if(!CUtils::CopyFile (ffFileFind.GetFilePath (), strMLTDestination + CFileName (ffFileFind.GetFileName ()))){
1380             return false; // message already emitted
1381           }
1382         }
1383       }
1384       else // a .h or .ldi file
1385       {
1386         if (! CFileName (strInstallDestination, CFileName (ffFileFind.GetFileName ())).Exists () && 
1387           !CUtils::CopyFile (ffFileFind.GetFilePath (), strInstallDestination + CFileName (ffFileFind.GetFileName ()))){
1388           return false; // message already emitted
1389         }
1390       }
1391     }
1392   }
1393   return rc; //FIXME
1394 }
1395
1396 CString CConfigToolDoc::GetDefaultHardware ()
1397 {
1398   CString strKey = _T("SOFTWARE\\Red Hat\\eCos");
1399   CString strVersionKey = _T("");
1400   CString rc = _T("");
1401   TCHAR pszBuffer [MAX_PATH + 1];
1402   HKEY hKey;
1403   LONG lStatus;
1404   
1405   // get the greatest eCos version subkey
1406   if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, strKey, 0L, KEY_READ, &hKey))
1407   {
1408     DWORD dwIndex = 0;
1409     while (ERROR_SUCCESS == RegEnumKey (hKey, dwIndex++, (LPTSTR) pszBuffer, sizeof (pszBuffer)))
1410     {
1411       if (strVersionKey.Compare (pszBuffer) < 0)
1412         strVersionKey = pszBuffer;
1413     }
1414     RegCloseKey (hKey);
1415     if (! strVersionKey.IsEmpty ())
1416     {
1417       TRACE (_T("CConfigToolDoc::GetDefaultHardware(): version subkey = '%s'\n"), strVersionKey);
1418       
1419       // get the default hardware value
1420       strKey +=  _T("\\") + strVersionKey;
1421       if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, strKey, 0L, KEY_READ, &hKey))
1422       {
1423         DWORD dwBufferSize = sizeof (pszBuffer);
1424         lStatus = RegQueryValueEx (hKey, _T("Default Hardware"), NULL, NULL, (LPBYTE) pszBuffer, &dwBufferSize);
1425         RegCloseKey (hKey);
1426         if (ERROR_SUCCESS == lStatus)
1427         {
1428           TRACE (_T("CConfigToolDoc::GetDefaultHardware(): default hardware = '%s'\n"), pszBuffer);
1429           rc=pszBuffer;
1430         }
1431       }
1432     }
1433   }
1434   return rc;
1435 }
1436
1437 CConfigItem * CConfigToolDoc::AddItem (const CdlUserVisible vitem, CConfigItem * pParent)
1438 {
1439   CConfigItem * pItem = new CConfigItem (pParent, vitem);
1440
1441   m_arItem.Add(pItem);
1442   pItem->m_strDesc = CUtils::StripExtraWhitespace (CString (vitem->get_description ().c_str ()));
1443
1444   if (vitem->get_name () == "CYGHWR_MEMORY_LAYOUT")
1445   {
1446     ASSERT (m_strMemoryLayoutFolder.IsEmpty ());
1447     m_strMemoryLayoutFolder = vitem->get_owner ()->get_directory().c_str ();
1448     m_strMemoryLayoutFolder.Replace(_TCHAR('/'),_TCHAR('\\'));
1449     TRACE (_T("Found memory layout folder: %s\n"), m_strMemoryLayoutFolder);
1450   }
1451   
1452   if (vitem->get_name () == "CYGBLD_LINKER_SCRIPT")
1453   {
1454     ASSERT (m_strLinkerScriptFolder.IsEmpty ());
1455     m_strLinkerScriptFolder = vitem->get_owner ()->get_directory().c_str ();
1456     m_strLinkerScriptFolder.Replace(_TCHAR('/'),_TCHAR('\\'));
1457     TRACE (_T("Found linker script folder: %s\n"), m_strLinkerScriptFolder);
1458     
1459     // the CDL hardware template name will eventually become the target name,
1460     // but for now we must deduce the target name from the linker script file name
1461     
1462     const CdlValuable valuable = dynamic_cast<CdlValuable> (vitem);
1463     CFileName strLinkerScript (m_strPackagesDir, m_strLinkerScriptFolder, CString (valuable->get_value ().c_str ()));
1464     strLinkerScript.Replace (_TCHAR('/'), _TCHAR('\\'));
1465     if(!strLinkerScript.Exists ()){
1466         CConfigTool::Log(_T("%s does not exist\n"),strLinkerScript);
1467     }
1468     TRACE (_T("Target '%s' selected\n"), strLinkerScript.Tail ().Root (), pItem->Macro());
1469     //CFileName strBinDir = AfxGetApp () -> GetProfileString (CUtils::LoadString (IDS_KEY_TOOLS_DIR), pTarget->Name (), _T(""));
1470     //if (! strBinDir.IsEmpty () && strBinDir.IsDir ())
1471     //{
1472     //  pTarget->SetBinDir (strBinDir);
1473     //}
1474   }     
1475   
1476   //TRACE(_T("Created new item from cdl: "));
1477   //pItem->DumpItem();
1478   return pItem;
1479 }
1480
1481 void CConfigToolDoc::AddAllItems ()
1482 {
1483   // remove any old items and packages
1484   DeleteContents ();
1485   if(NULL!=CConfigTool::GetControlView()){ // may not be the case for plugin
1486
1487     // add the root item
1488     CConfigItem * pItem = new CConfigItem (NULL, NULL);
1489     m_arItem.Add(pItem);
1490     pItem->m_strDesc = _T("The root node for all configurable items");
1491   
1492     // add the remaining items using their CDL descriptions
1493     m_strMemoryLayoutFolder = _T("");
1494     m_strLinkerScriptFolder = _T("");
1495     AddContents (m_CdlConfig, FirstItem ());
1496   
1497     // check that exactly one radio button in each group is enabled
1498     CheckRadios ();
1499   
1500     // update the rules (conflicts) view
1501     UpdateFailingRuleCount ();
1502   
1503     if(NULL==CConfigTool::GetRulesView() || !CConfigTool::GetRulesView()->IsWindowVisible()){
1504       // log all conflicts
1505       //        LogConflicts (m_CdlConfig->get_structural_conflicts ()); // relating to package availability - ignore for now
1506       LogConflicts (m_CdlConfig->get_all_conflicts ());
1507     }
1508
1509     CConfigTool::GetControlView()->SelectItem(Item(0));
1510     UpdateAllViews (NULL, SelChanged, (CObject *)Item(0)); // refresh the display
1511     if(ItemCount()>0){
1512       CConfigTool::GetControlView()->GetTreeCtrl().Expand(Item(0)->HItem(),TVE_EXPAND);
1513     }
1514     CConfigTool::GetControlView()->SetFocus();
1515   }
1516 }
1517
1518 const CFileName CConfigToolDoc::CurrentLinkerScript()
1519 {
1520   const CConfigItem * pItem = Find (_T("CYGBLD_LINKER_SCRIPT"));
1521   return pItem ? CFileName (m_strPackagesDir, m_strLinkerScriptFolder, pItem->StringValue ()) : _T("");
1522 }
1523
1524 bool CConfigToolDoc::GenerateHeaders()
1525 {
1526 // Copy non-config header files from the repository to the
1527 // install tree for plugin only. The make system used by
1528 // the standalone config tool does this for us.
1529 #ifdef PLUGIN
1530   typedef std::vector<CdlBuildInfo_Loadable> EntriesArray;
1531   const EntriesArray &arEntries=BuildInfo().entries;
1532   typedef std::vector<CdlBuildInfo_Header> HeaderArray;
1533   for(EntriesArray::size_type j=0;j<arEntries.size();j++){
1534     const CdlBuildInfo_Loadable &e=arEntries[j];
1535     const CFileName strDir(CUtils::WPath(e.directory));
1536     const HeaderArray &arHeaders=e.headers;
1537     for(HeaderArray::size_type i=0;i<arHeaders.size();i++){
1538       const CdlBuildInfo_Header &h=arHeaders[i];
1539       const CFileName strSource(PackagesDir()+strDir+CUtils::WPath(h.source));
1540       const CFileName strDest(HeadersDir()/*+CUtils::WPath(e.directory)*/+CUtils::WPath(h.destination));
1541     
1542       if(!strDest.Head().CreateDirectory(true)){
1543         CUtils::MessageBoxF(_T("Failed to create %s - %s"),strDest.Head(),CUtils::GetLastErrorMessageString());
1544         return false;
1545       }
1546       if(!CUtils::CopyFile(strSource,strDest)){ 
1547         return false; // message already emitted
1548       }
1549     }
1550   }
1551 #endif
1552
1553   // Generate headers
1554   try {
1555     CFileName strPkfConfDir(InstallTree()+_T("include\\pkgconf"));
1556     if(!strPkfConfDir.CreateDirectory()){
1557       CUtils::MessageBoxF(_T("Failed to create %s - %s"),strPkfConfDir,CUtils::GetLastErrorMessageString());
1558       return false;
1559     }
1560     GetCdlConfig()->generate_config_headers(CUtils::UnicodeToStdStr(strPkfConfDir.ShortName()));
1561   }
1562   catch (CdlInputOutputException e) {
1563     const CString strMsg(e.get_message().c_str());
1564     TRACE(_T("!!! Exception thrown calling generate_config_headers - %s"),strMsg);
1565     CUtils::MessageBoxF(_T("Failed to generate header files - %s"),strMsg);
1566     return false;
1567   }
1568   return true;
1569 }
1570
1571 const CFileName CConfigToolDoc::MLTDir ()
1572 {
1573         CString strPathName (GetPathName ());
1574         ASSERT (! strPathName.IsEmpty ());
1575         return strPathName.Left (strPathName.ReverseFind (_TCHAR('.'))) + _T("_mlt");
1576 }
1577
1578 bool CConfigToolDoc::UpdateBuildInfo(bool bFirstTime)
1579 {
1580   try {
1581     GetCdlConfig()->get_build_info(m_BuildInfo);
1582     #ifdef PLUGIN
1583     // FIXME: this means anything not mentioned by AddFile in our scan below will be removed - including user-added items
1584     m_peCosProject->ClearItemFlags();    
1585     m_peCosProject->UpdateeCosProject(bFirstTime);
1586     m_peCosProject->RemoveAllUnflaggedItems();
1587     #else
1588     UNUSED_ALWAYS(bFirstTime);
1589     generate_build_tree (GetCdlConfig(), CUtils::UnicodeToStdStr(BuildTree()), CUtils::UnicodeToStdStr(InstallTree()));
1590     #endif
1591     return true;
1592   }
1593   catch(...){
1594     return false;
1595   }
1596 }
1597
1598 void CConfigToolDoc::RemoveAllItems()
1599 {
1600   for(int nItem=0;nItem<ItemCount();nItem++){
1601     CConfigItem *pItem=Item(nItem);
1602     deleteZ(pItem);
1603   }
1604   m_arItem.RemoveAll();
1605
1606   UpdateAllViews(NULL,Clear,0);
1607 }
1608
1609 void CConfigToolDoc::EnableCallbacks (bool bEnable/*=true*/)
1610 {
1611   CdlTransactionCallback::set_callback_fn(bEnable?&CdlTransactionHandler:0);
1612   CdlTransactionBody::set_inference_callback_fn(bEnable?&CdlInferenceHandler:0);
1613   CdlTransactionBody::set_inference_override(CdlValueSource_Invalid);
1614 }
1615
1616 int CConfigToolDoc::GetTestExeNames (CFileNameArray &arTestExes,CFileNameArray &arMissing)
1617 {
1618   arTestExes.RemoveAll();
1619   arMissing.RemoveAll();
1620   
1621   typedef std::vector<CdlBuildInfo_Loadable> EntriesArray;
1622   const EntriesArray &arEntries=BuildInfo().entries;
1623   for(EntriesArray::size_type j=0;j<arEntries.size();j++){
1624     const CdlBuildInfo_Loadable &e=arEntries[j];
1625     CStringArray ar;
1626     int n=CUtils::Chop(CString(get_tests(GetCdlConfig(),e).c_str()),ar);
1627     for(int i=0;i<n;i++){
1628       CFileName strFile;
1629       strFile.Format(_T("%s\\tests\\%s\\%s.exe"),InstallTree(),CString(e.directory.c_str()),ar[i]); 
1630       strFile.Replace(_TCHAR('/'),_TCHAR('\\'));
1631       if(strFile.Exists()){
1632         arTestExes.Add(strFile);
1633       } else {
1634         arMissing.Add(strFile);
1635       }
1636     }
1637   }
1638   return arTestExes.GetSize();
1639 }
1640
1641 CConfigToolDoc::GlobalConflictOutcome CConfigToolDoc::ResolveGlobalConflicts(CPtrArray *parConflictsOfInterest)
1642 {
1643   m_ConflictsOutcome=NotDone;
1644   m_arConflictsOfInterest.RemoveAll();
1645   if(parConflictsOfInterest){
1646     m_arConflictsOfInterest.Copy(*parConflictsOfInterest);
1647   }
1648   CdlInferenceCallback fn=CdlTransactionBody::get_inference_callback_fn();
1649   CdlTransactionBody::set_inference_callback_fn(CdlGlobalInferenceHandler);
1650   GetCdlInterpreter()->get_toplevel()->resolve_all_conflicts();
1651   CdlTransactionBody::set_inference_callback_fn(fn);
1652   if(NotDone==m_ConflictsOutcome){
1653     // No solutions were available, but we'll run the dialog anyway
1654     const std::list<CdlConflict>& conflicts=GetCdlConfig()->get_all_conflicts();  
1655     CFailingRulesDialog dlg(conflicts,NULL,&m_arConflictsOfInterest);
1656     m_ConflictsOutcome=(IDOK==dlg.DoModal())?OK:Cancel;
1657   }
1658   return m_ConflictsOutcome;
1659 }
1660
1661 bool CConfigToolDoc::CheckConflictsBeforeSave()
1662 {
1663   if(GetCdlInterpreter()->get_toplevel()->get_all_conflicts().size()>0){
1664     if(Deferred&m_nRuleChecking){
1665       if((SuggestFixes&m_nRuleChecking)&&(Cancel==ResolveGlobalConflicts())){
1666         return false;
1667       }
1668       int nConflicts=GetCdlInterpreter()->get_toplevel()->get_all_conflicts().size();
1669       switch(nConflicts){
1670       case 0:
1671         break;
1672       case 1:
1673         if(IDNO==CUtils::MessageBoxFT(MB_YESNO|MB_DEFBUTTON2,_T("There is 1 unresolved conflict.  Save anyway?"))){
1674           return false;
1675         }
1676       default:
1677         if(IDNO==CUtils::MessageBoxFT(MB_YESNO|MB_DEFBUTTON2,_T("There are %d unresolved conflicts.  Save anyway?"),nConflicts)){
1678           return false;
1679         }
1680       }
1681     }
1682   }
1683   return true;
1684 }
1685
1686 BOOL CConfigToolDoc::IsModified() 
1687
1688   return m_bModified || MemoryMap.map_modified();
1689 }
1690
1691 void CConfigToolDoc::OnFileExport()
1692 {
1693   CFileDialog dlg (FALSE, _T("ecm"), NULL, OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, _T("eCos Minimal Configuration (*.ecm)|*.ecm||"), AfxGetMainWnd ());
1694   TCHAR szBuffer [MAX_PATH * 16] = _T("");
1695   dlg.m_ofn.lpstrFile = szBuffer;
1696   dlg.m_ofn.nMaxFile = MAX_PATH * 16;
1697   dlg.m_ofn.lpstrTitle = _T("Export eCos Minimal Configuration");
1698   if (IDOK == dlg.DoModal ()) {
1699     try {
1700       TRACE (_T("Exporting eCos minimal configuration '%s'\n"), dlg.GetPathName ());
1701       m_CdlConfig->save (CUtils::UnicodeToStdStr (dlg.GetPathName ()), /* minimal = */ true);
1702     }
1703     catch (CdlStringException exception) {
1704       CUtils::MessageBoxF (_T("Error exporting eCos minimal configuration:\n\n%s"), CString (exception.get_message ().c_str ()));
1705     }
1706     catch (...) {
1707       CUtils::MessageBoxF (_T("Error exporting eCos minimal configuration."));
1708     }
1709   }
1710 }
1711
1712 void CConfigToolDoc::OnFileImport()
1713 {
1714   CFileDialog dlg (TRUE, _T("ecm"), NULL, OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, _T("eCos Minimal Configurations (*.ecm)|*.ecm||"), AfxGetMainWnd ());
1715   TCHAR szBuffer [MAX_PATH * 16] = _T("");
1716   dlg.m_ofn.lpstrFile = szBuffer;
1717   dlg.m_ofn.nMaxFile = MAX_PATH * 16;
1718   dlg.m_ofn.lpstrTitle = _T("Import eCos Minimal Configuration");
1719   if (IDOK == dlg.DoModal ()) {
1720     try {
1721       TRACE (_T("Importing eCos minimal configuration '%s'\n"), dlg.GetPathName ());
1722       m_CdlConfig->add (CUtils::UnicodeToStdStr (dlg.GetPathName ()), CConfigToolDoc::CdlParseErrorHandler, CConfigToolDoc::CdlParseWarningHandler);
1723     }
1724     catch (CdlStringException exception) {
1725       CUtils::MessageBoxF (_T("Error importing eCos minimal configuration:\n\n%s"), CString (exception.get_message ().c_str ()));
1726     }
1727     catch (...) {
1728       CUtils::MessageBoxF (_T("Error importing eCos minimal configuration."));
1729     }
1730
1731     CWaitCursor wait;
1732     AddAllItems (); // regenerate all the config items since the topology may have changed
1733     if (m_strLinkerScriptFolder.IsEmpty ()) {
1734       CUtils::MessageBoxF (_T("The eCos linker script macro CYGBLD_LINKER_SCRIPT is not defined."));
1735     }
1736     if (m_strMemoryLayoutFolder.IsEmpty ()) {
1737       CUtils::MessageBoxF (_T("The eCos memory layout macro CYGHWR_MEMORY_LAYOUT is not defined."));
1738     }
1739     SwitchMemoryLayout (true); // the hardware template may have changed
1740     UpdateBuildInfo ();
1741     CConfigTool::GetControlView()->SelectItem (Item (0));
1742     SetModifiedFlag ();
1743   }
1744 }
1745
1746 bool CConfigToolDoc::QualifyDocURL(CString &strURL)
1747 {
1748   if(-1==strURL.Find(_T("://"))){
1749     strURL.Replace(_TCHAR('/'),_TCHAR('\\'));
1750     if (! CFileName (strURL).IsFile ()) { // if not an absolute filepath
1751       strURL = DocBase () + CFileName (strURL); // prepend the doc directory path
1752     }
1753     strURL=_T("file://")+strURL;
1754   }
1755
1756   if(0==strURL.Find(_T("file://"))){
1757     CFileName strFile(strURL.Right(strURL.GetLength()-7));
1758     int nIndex=strFile.ReverseFind(_TCHAR('#'));
1759     if(-1!=nIndex){
1760       strFile=strFile.Left(nIndex);
1761     }
1762     strFile.Replace(_TCHAR('/'),_TCHAR('\\'));
1763     if(!strFile.Exists()){
1764       CUtils::MessageBoxF(_T("Cannot locate the file %s"),strFile);
1765       return false;
1766     }
1767   }
1768   return true;
1769 }
1770
1771 bool CConfigToolDoc::NewMemoryLayout (const CString &strPrefix)
1772 {
1773   CFileName strFileName = CurrentLinkerScript ();
1774   TRACE(_T("Reading linker-defined memory sections from %s\n"), strFileName);
1775   MemoryMap.new_memory_layout (); // delete the old memory layout regardless
1776   if (! strFileName.IsEmpty ())
1777     MemoryMap.import_linker_defined_sections (strFileName); // read the linker-defined section names from the repository (failure is silent)
1778
1779   CString strMemoryLayoutFileName = strPrefix + _T("\\mlt_") + CurrentMemoryLayout () + _T(".mlt");
1780   TRACE(_T("Reading memory layout from %s\n"), strMemoryLayoutFileName);
1781   MemoryMap.load_memory_layout (strMemoryLayoutFileName); // load the new memory layout (failure is silent)
1782   strSelectedSection = _T("");
1783   strSelectedRegion = _T("");
1784   UpdateAllViews (NULL, MemLayoutChanged);
1785   return true; // FIXME
1786 }
1787
1788 void CConfigToolDoc::SetPathName( LPCTSTR pszPath, BOOL bAddToMRU /*= TRUE*/ )
1789 {
1790   if(_TCHAR('\0')==*pszPath){ // called like this after failed saves to put things back as they were
1791           // CDocument::SetPathName would assert given an empty string
1792           m_strPathName = _T("");
1793 #ifndef PLUGIN
1794     SetTitle(_T("Untitled"));
1795 #endif
1796     m_strBuildTree   = _T("");
1797     m_strInstallTree = _T("");
1798   } else {
1799 #ifdef PLUGIN
1800     m_strPathName = CFileName (pszPath);
1801 #else
1802     CDocument::SetPathName (pszPath, bAddToMRU);
1803 #endif
1804     CString strFolder (pszPath);
1805     strFolder = strFolder.Left (strFolder.ReverseFind (_TCHAR('.'))); // extract folder from file path
1806     m_strBuildTree   = CFileName(strFolder + _T("_build")); 
1807     m_strInstallTree = CFileName(strFolder + _T("_install")); 
1808   }
1809 }
1810
1811 bool CConfigToolDoc::ShowHtmlHelp (LPCTSTR pszURL)
1812 {
1813
1814   HWND hwndCaller=AfxGetMainWnd()->CWnd::GetDesktopWindow()->GetSafeHwnd();
1815   bool rc=false;
1816   const CFileName strFile(HTMLHelpLinkFileName());
1817   CStdioFile f;
1818   if(!CFileName(CConfigTool::strHelpFile).Exists()) {
1819     CUtils::MessageBoxF(_T("Cannot display help - %s does not exist\n"),CConfigTool::strHelpFile);
1820   } else if(!f.Open(strFile,CFile::typeText|CFile::modeCreate|CFile::modeWrite)){
1821     CUtils::MessageBoxF(_T("Cannot display help - error creating %s\n"),strFile);
1822   } else {
1823     CString str;
1824     str.Format(_T("<meta HTTP-EQUIV=\"refresh\" CONTENT=\"0;URL=%s\">"),pszURL);
1825     f.WriteString(str);
1826     f.Close();
1827     if(0==HtmlHelp(hwndCaller, CConfigTool::strHelpFile, HH_DISPLAY_TOPIC, 0)){
1828       CUtils::MessageBoxF(_T("Cannot display %s"),pszURL);
1829     } else {
1830       // FIXME: Do this the first time only?
1831       HH_WINTYPE WinType;
1832       HWND wnd;
1833       HH_WINTYPE *pWinType=NULL;
1834       wnd = HtmlHelp(hwndCaller, CConfigTool::strHelpFile+_T(">mainwin"), HH_GET_WIN_TYPE, (DWORD) &pWinType);
1835       WinType=*pWinType;
1836       WinType.hwndCaller=hwndCaller;
1837       WinType.fsWinProperties|=HHWIN_PROP_TRACKING;
1838       WinType.idNotify = ID_HHNOTIFICATION;
1839       wnd = HtmlHelp(hwndCaller, CConfigTool::strHelpFile, HH_SET_WIN_TYPE, (DWORD) &WinType);
1840       rc=true;
1841     }
1842     //::DeleteFile(strFile);
1843   }
1844   return rc;
1845 }
1846
1847 const CString CConfigToolDoc::HTMLHelpLinkFileName()
1848 {
1849   return CFileName(CConfigTool::strHelpFile).Head()+"link2.htm";
1850 }