]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/standalone/wxwin/configtooldoc.cpp
94eb56eea6f8773dee1233f925a16ec4ea43c94c
[karo-tx-redboot.git] / tools / src / tools / configtool / standalone / wxwin / configtooldoc.cpp
1 //####COPYRIGHTBEGIN####
2 //
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 // Copyright (C) 2003 John Dallaway
6 //
7 // This program is part of the eCos host tools.
8 //
9 // This program is free software; you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License as published by the Free
11 // Software Foundation; either version 2 of the License, or (at your option)
12 // any later version.
13 //
14 // This program is distributed in the hope that it will be useful, but WITHOUT
15 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17 // more details.
18 //
19 // You should have received a copy of the GNU General Public License along with
20 // this program; if not, write to the Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 //
23 // ----------------------------------------------------------------------------
24 //
25 //####COPYRIGHTEND####
26 // configtooldoc.cpp :
27 //
28 //===========================================================================
29 //#####DESCRIPTIONBEGIN####
30 //
31 // Author(s):   julians, jld
32 // Contact(s):  julians, jld
33 // Date:        2000/10/05
34 // Version:     $Id$
35 // Purpose:
36 // Description: Implementation file for the ecConfigToolDoc class
37 // Requires:
38 // Provides:
39 // See also:
40 // Known bugs:
41 // Usage:
42 //
43 //####DESCRIPTIONEND####
44 //
45 //===========================================================================
46
47 // ============================================================================
48 // declarations
49 // ============================================================================
50
51 // ----------------------------------------------------------------------------
52 // headers
53 // ----------------------------------------------------------------------------
54 #ifdef __GNUG__
55 #pragma implementation "configtooldoc.h"
56 #endif
57
58 // Includes other headers for precompiled compilation
59 #include "ecpch.h"
60
61 #include "wx/config.h"
62 #include "wx/textfile.h"
63 #include "wx/process.h"
64 #include "wx/mimetype.h"
65
66 #ifdef __BORLANDC__
67 #pragma hdrstop
68 #endif
69
70 #ifdef __WXMSW__
71 #include <windows.h>
72 #ifndef __CYGWIN__
73 #include <shlobj.h>
74 #endif
75 #include "wx/msw/winundef.h"
76 #if defined(CreateDirectory) && !defined(__CYGWIN__)
77 #undef CreateDirectory
78 #endif
79 #endif
80
81 #include "configtooldoc.h"
82 #include "configtoolview.h"
83 #include "configtree.h"
84 #include "mainwin.h"
85 #include "ecutils.h"
86 #include "filename.h"
87 #include "choosereposdlg.h"
88 #include "packagesdlg.h"
89 #include "conflictsdlg.h"
90 #include "conflictwin.h"
91 #include "mltwin.h"
92 #include "build.hxx"
93 #include "platformeditordlg.h"
94 #include "runtestsdlg.h"
95 #include "propertywin.h"
96 #include "docsystem.h"
97
98 IMPLEMENT_DYNAMIC_CLASS(ecConfigToolDoc, wxDocument)
99
100 ecConfigToolDoc::ecConfigToolDoc()
101 {
102     m_bRepositoryOpen = FALSE;
103     m_CdlPkgData = NULL;
104     m_CdlInterp = NULL;
105     m_CdlConfig = NULL;
106     m_ConflictsOutcome = OK;
107     m_strRepository = wxGetApp().GetSettings().m_strRepository;
108 }
109
110 ecConfigToolDoc::~ecConfigToolDoc()
111 {
112     wxGetApp().m_currentDoc = NULL;
113     wxGetApp().GetSettings().m_strRepository = m_strRepository;
114
115     CloseRepository();
116
117     // Delete remaining items -- most (if not all) should already
118     // have been deleted via the tree item client data
119     DeleteItems();
120 }
121
122 void ecConfigToolDoc::DeleteItems()
123 {
124     // Delete any remaining items
125     wxNode* node = m_items.First();
126     while (node)
127     {
128         ecConfigItem* item = wxDynamicCast(node->Data(), ecConfigItem);
129         wxNode* next = node->Next();
130
131         // Note: automatically removes itself from this list in ~ecConfigItem
132         delete item;
133         node = next;
134     }
135 }
136
137 bool ecConfigToolDoc::OnCloseDocument()
138 {
139     if (wxDocument::OnCloseDocument())
140     {
141         DeleteItems();
142         return TRUE;
143     }
144     else
145     {
146         return FALSE;
147     }
148 }
149
150 bool ecConfigToolDoc::Save()
151 {
152     bool ret = FALSE;
153
154     if (!IsModified() && m_savedYet) return TRUE;
155     if (m_documentFile == wxT("") || !m_savedYet)
156         ret = SaveAs();
157     else
158         ret = OnSaveDocument(m_documentFile);
159     if ( ret )
160         SetDocumentSaved(TRUE);
161     return ret;
162 }
163
164
165 bool ecConfigToolDoc::OnCreate(const wxString& path, long flags)
166 {
167     wxGetApp().m_currentDoc = this;
168
169     if (flags & wxDOC_NEW)
170     {
171         m_bRepositoryOpen = FALSE;
172
173         bool prompt = FALSE;
174         if (flags & ecDOC_PROMPT_FOR_REPOSITORY)
175             prompt = TRUE;
176
177         if(!OpenRepository(wxEmptyString, prompt))
178         {
179             wxGetApp().m_currentDoc = NULL;
180             return FALSE;
181         }
182
183         Modify(FALSE);
184         SetDocumentSaved(FALSE);
185
186         wxString rootName(wxT("untitled"));
187         wxStripExtension(rootName);
188         SetFilename(wxGetApp().GetSettings().GenerateFilename(rootName));
189     }
190
191     // Creates the view, so do any view updating after this
192     bool success = wxDocument::OnCreate(path, flags);
193
194     if (success)
195     {
196         if (flags & wxDOC_NEW)
197         {
198             wxBusyCursor wait;
199
200             ecConfigToolHint hint(NULL, ecSelChanged);
201             UpdateAllViews (NULL, & hint);
202
203             SetFilename(GetFilename(), TRUE);
204
205             // load the memory layout for the default target-platform-startup from the current repository
206
207             // TODO
208             // m_memoryMap.set_map_size (0xFFFFFFFF); // set the maximum memory map size
209             // NewMemoryLayout (CFileName (m_strPackagesDir, m_strMemoryLayoutFolder, _T("include\\pkgconf")));
210
211             // Why should we generate the names at this point, when we only have a temporary filename?
212             // Don't do it!
213 #if 0
214             wxGetApp().SetStatusText(wxT("Updating build information..."), FALSE);
215             UpdateBuildInfo();
216 #endif
217         }
218     }
219     return success;
220 }
221
222 bool ecConfigToolDoc::OnSaveDocument(const wxString& filename)
223 {
224     wxBusyCursor cursor;
225
226     const wxString strOldPath(GetFilename());
227
228 #if 0
229     bool bSaveAs=(filename!=strOldPath);
230     if(!IsModified() && wxFileExists(filename))
231     {
232         return TRUE;
233     }
234 #endif
235
236     bool rc=FALSE;
237     if (CheckConflictsBeforeSave())
238     { // errors already emitted
239
240         const wxString strPathName(filename);
241
242         wxString str;
243         str.Printf(_("Saving configuration %s"), (const wxChar*) filename);
244
245         /* TODO
246         CIdleMessage IM(str);
247         if(CConfigTool::GetCellView()){
248         CConfigTool::GetCellView()->CancelCellEdit();
249         }
250         */
251
252         // check the configuration
253
254         wxASSERT (m_CdlConfig->check_this (cyg_extreme));
255
256         // save the configuration
257
258         try
259         {
260             m_CdlConfig->save ((const wxChar*) filename);
261             rc=TRUE;
262         }
263
264         catch (CdlStringException exception)
265         {
266             wxString msg;
267             msg.Printf(_("Error saving eCos configuration:\n\n%s"), exception.get_message ().c_str ());
268             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
269         }
270
271         catch (...)
272         {
273             wxString msg;
274             msg.Printf(_("Error saving eCos configuration"));
275             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
276         }
277
278         if(rc){
279             rc=FALSE;
280             SetFilename (filename); // called to ensure that MLTDir() will work in this function TODO??
281
282             // save the memory layout files to the build tree and copy to the install tree
283             /* TODO
284             if (bSaveAs || MemoryMap.map_modified ()) {
285             SaveMemoryMap();
286             }
287             */
288
289             ecConfigToolHint hint(NULL, ecAllSaved);
290             UpdateAllViews (NULL, & hint);
291
292             wxASSERT( !m_strBuildTree.IsEmpty() );
293             wxASSERT( !m_strInstallTree.IsEmpty() );
294
295             ecFileName buildFilename(m_strBuildTree);
296             ecFileName installFilename(m_strInstallTree);
297
298             if (!wxGetApp().GetSettings().m_editSaveFileOnly)
299             {
300                 if (!buildFilename.CreateDirectory(FALSE) || !installFilename.CreateDirectory(FALSE))
301                 {
302                     wxString msg;
303                     msg.Printf(_("Failed to save %s"), (const wxChar*) filename);
304                     
305                     wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION);
306                     rc = FALSE;
307                 }
308                 else if (GenerateHeaders() && CopyMLTFiles())
309                 {
310                     // in each case errors already emitted
311                     // copy new MLT files to the build tree as necessary
312                     rc=generate_build_tree (GetCdlConfig(), ecUtils::UnicodeToStdStr(m_strBuildTree), ecUtils::UnicodeToStdStr(m_strInstallTree));
313                     rc = TRUE;
314                 }
315             }
316             else
317             {
318                 rc = TRUE;
319             }
320         }
321     }
322     if(rc)
323     {
324         Modify(FALSE);
325         SetDocumentSaved(TRUE);
326         SetFilename(filename);
327         wxGetApp().GetSettings().m_lastFilename = filename;
328     } else
329     {
330         SetFilename(strOldPath);
331     }
332     wxGetApp().GetMainFrame()->UpdateFrameTitle();
333     return rc;
334 }
335
336 // Can we generate the build tree yet?
337 bool ecConfigToolDoc::CanGenerateBuildTree()
338 {
339     if (m_strBuildTree.IsEmpty() || m_strInstallTree.IsEmpty() )
340         return FALSE;
341
342     int nCount=0;
343     if (GetCdlConfig ())
344     {
345         // calculate the number of conflicts
346         int nCount = GetCdlConfig ()->get_all_conflicts ().size ();
347
348         if (nCount > 0)
349             return FALSE;
350     }
351     else
352         return FALSE;
353
354     return TRUE;
355 }
356
357 // A standalone method for generating a build tree without saving first
358 bool ecConfigToolDoc::GenerateBuildTree()
359 {
360     wxBusyCursor wait;
361     if (CanGenerateBuildTree())
362     {
363         ecFileName buildFilename(m_strBuildTree);
364         ecFileName installFilename(m_strInstallTree);
365         
366         if (!buildFilename.CreateDirectory() || !installFilename.CreateDirectory())
367         {
368             wxString msg;
369             msg.Printf(_("Failed to create build tree"));
370             
371             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION);
372             return FALSE;
373         }
374         else if (GenerateHeaders() && CopyMLTFiles())
375         {
376             // in each case errors already emitted
377             // copy new MLT files to the build tree as necessary
378             bool rc = generate_build_tree (GetCdlConfig(), ecUtils::UnicodeToStdStr(m_strBuildTree), ecUtils::UnicodeToStdStr(m_strInstallTree));
379             rc = TRUE;
380         }
381
382     }
383     else
384         return FALSE;
385     return TRUE;
386 }
387
388 bool ecConfigToolDoc::OnOpenDocument(const wxString& filename)
389 {
390     wxGetApp().GetSettings().m_lastFilename = filename;
391
392     wxBusyCursor cursor;
393
394     bool rc=FALSE; // Assume the worst
395     CdlInterpreter NewCdlInterp = NULL;
396     CdlConfiguration NewCdlConfig = NULL;
397
398     // We have to open the repository or m_CdlPkgData and co. won't be set
399     if (!OpenRepository())
400         return FALSE;
401
402     wxString str;
403     str.Printf(_("Opening save file %s"), (const wxChar*) filename);
404     wxGetApp().SetStatusText(str);
405
406     EnableCallbacks(FALSE);
407
408     try
409     {
410         NewCdlInterp = CdlInterpreterBody::make ();
411         NewCdlConfig = CdlConfigurationBody::load ((const wxChar*) filename, m_CdlPkgData, NewCdlInterp, &CdlLoadErrorHandler, &CdlLoadWarningHandler);
412         rc = TRUE;
413     }
414     catch (CdlStringException exception)
415     {
416         wxString msg;
417         msg.Printf(_("Error opening eCos configuration:\n\n%s"), exception.get_message ().c_str ());
418         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
419     }
420     catch (...)
421     {
422         wxString msg;
423         msg.Printf(_("Error opening eCos configuration"));
424         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
425     }
426
427     if (rc)
428     {
429         rc=FALSE;
430         // check the new configuration
431
432         wxASSERT (NewCdlConfig->check_this (cyg_extreme));
433
434         // switch to the new configuration
435
436         delete m_CdlConfig;
437         delete m_CdlInterp;
438         m_CdlInterp = NewCdlInterp;
439         m_CdlConfig = NewCdlConfig;
440         //SetPathName (lpszPathName, TRUE); // called to ensure that MLTDir() will work in this function
441
442         AddAllItems (); // must precede NewMemoryLayout() [CurrentLinkerScript() calls Find()]
443
444         // load the memory layout from the build tree
445         // TODO
446         NewMemoryLayout (MLTDir ());
447
448         UpdateFailingRuleCount();
449
450         SetFilename(filename);
451
452         // UpdateBuildInfo(); // Don't create directories on opening file
453
454         rc = TRUE;
455
456
457         ecConfigToolHint hint(NULL, ecFilenameChanged);
458         UpdateAllViews (NULL, & hint);
459     }
460
461     // re-enable the transaction callback
462     EnableCallbacks(TRUE);
463
464     SetDocumentSaved(TRUE); // Necessary or it will pop up the Save As dialog
465
466     wxGetApp().SetStatusText(wxEmptyString, FALSE);
467
468     return rc;
469 }
470
471 void ecConfigToolDoc::AddAllItems()
472 {
473     ecConfigTreeCtrl* treeCtrl = wxGetApp().GetMainFrame()->GetTreeCtrl();
474     // Ensure there's no dangling pointer
475     wxGetApp().GetMainFrame()->GetPropertyListWindow()->Fill(NULL);
476
477     treeCtrl->DeleteAllItems();
478
479     m_strMemoryLayoutFolder = wxT("");
480     m_strLinkerScriptFolder = wxT("");
481
482     // Add the root item
483     ecConfigItem* item = NULL;
484     wxTreeItemId rootId = treeCtrl->AddRoot(_(""), -1, -1, new ecTreeItemData(item = new ecConfigItem(NULL, _("Configuration"), ecContainer)));
485     item->SetTreeItem(rootId);
486     item->UpdateTreeItem(* treeCtrl);
487     item->SetDescription(_("The root node for all configurable items"));
488     m_items.Append(item);
489
490     AddContents(m_CdlConfig, item);
491     treeCtrl->Expand(rootId);
492
493     // check that exactly one radio button in each group is enabled
494     CheckRadios ();
495
496     // update the rules (conflicts) view
497     UpdateFailingRuleCount ();
498
499     if( ! wxGetApp().GetMainFrame() || ! wxGetApp().GetMainFrame()->GetConflictsWindow() ||
500         ! wxGetApp().GetMainFrame()->GetConflictsWindow()->IsShown())
501     {
502         // log all conflicts
503         //      LogConflicts (m_CdlConfig->get_structural_conflicts ()); // relating to package availability - ignore for now
504         LogConflicts (m_CdlConfig->get_all_conflicts ());
505     }
506
507     wxGetApp().GetTreeCtrl()->SelectItem(wxGetApp().GetTreeCtrl()->GetRootItem());
508     //ecConfigToolHint hint(item, ecValueChanged);
509     ecConfigToolHint hint(NULL, ecSelChanged);
510
511     UpdateAllViews (NULL, & hint);
512
513     if(GetItems().Number()>0){
514         wxGetApp().GetTreeCtrl()->Expand(rootId);
515     }
516     wxGetApp().GetTreeCtrl()->SetFocus();
517 }
518
519 void ecConfigToolDoc::AddContents (const CdlContainer container, ecConfigItem *pParent)
520 {
521     // determine the container contents
522
523     const std::vector<CdlNode>& contents = container->get_contents ();
524     std::vector<CdlNode>::const_iterator node_i;
525     for (node_i = contents.begin (); node_i != contents.end (); node_i++)
526     {
527         const CdlNode node = * node_i;
528         const CdlPackage pkg = dynamic_cast<CdlPackage> (node);
529         const CdlComponent comp = dynamic_cast<CdlComponent> (node);
530         const CdlOption opt = dynamic_cast<CdlOption> (node);
531         const CdlContainer contnr = dynamic_cast<CdlContainer> (node);
532
533         // if the node in the container is a package, component or option
534         // then it is visible and should be added to the tree
535         if  (0 != pkg) // the node is a package
536         {
537             ecConfigItem * pItem = AddItem (pkg, pParent); // add the package
538             AddContents (pkg, pItem); // add the package contents
539         }
540         else if (0 != comp) // the node is a component
541         {
542             ecConfigItem * pItem = AddItem (comp, pParent); // add the component
543             AddContents (comp, pItem); // add the component contents
544         }
545         else if (0 != opt) // the node is an option
546             AddItem (opt, pParent); // add the option
547
548         else if (0 != contnr) // if the node is a container
549             AddContents (contnr, pParent); // add the container contents
550
551         // ignore nodes of any other class
552     }
553 }
554
555 ecConfigItem * ecConfigToolDoc::AddItem (const CdlUserVisible vitem, ecConfigItem * pParent)
556 {
557     ecConfigItem * pItem = new ecConfigItem (pParent, vitem);
558
559     m_items.Append(pItem);
560
561     if (vitem->get_name () == "CYGHWR_MEMORY_LAYOUT")
562     {
563         wxASSERT (m_strMemoryLayoutFolder.IsEmpty ());
564         m_strMemoryLayoutFolder = vitem->get_owner ()->get_directory().c_str ();
565 #ifdef __WXMSW__
566         m_strMemoryLayoutFolder.Replace(wxT("/"),wxT("\\"));
567 #endif
568         //TRACE (_T("Found memory layout folder: %s\n"), m_strMemoryLayoutFolder);
569     }
570
571     if (vitem->get_name () == "CYGBLD_LINKER_SCRIPT")
572     {
573         wxASSERT (m_strLinkerScriptFolder.IsEmpty ());
574         m_strLinkerScriptFolder = vitem->get_owner ()->get_directory().c_str ();
575 #ifdef __WXMSW__
576         m_strLinkerScriptFolder.Replace(wxT("/"),wxT("\\"));
577 #endif
578         //TRACE (_T("Found linker script folder: %s\n"), m_strLinkerScriptFolder);
579
580         // the CDL hardware template name will eventually become the target name,
581         // but for now we must deduce the target name from the linker script file name
582
583         const CdlValuable valuable = dynamic_cast<CdlValuable> (vitem);
584         ecFileName strLinkerScript (m_strPackagesDir, m_strLinkerScriptFolder, wxString (valuable->get_value ().c_str ()));
585
586 #ifdef __WXMSW__
587         strLinkerScript.Replace (wxT("/"), wxT("\\"));
588 #endif
589
590         if(!strLinkerScript.Exists ()){
591             wxString msg;
592             msg.Printf(wxT("%s does not exist\n"), (const wxChar*) strLinkerScript);
593             wxGetApp().Log(msg);
594         }
595         //TRACE (_T("Target '%s' selected\n"), strLinkerScript.Tail ().Root (), pItem->Macro());
596     }
597
598     //TRACE(_T("Created new item from cdl: "));
599     //pItem->DumpItem();
600     return pItem;
601 }
602
603 void ecConfigToolDoc::CheckRadios()
604 {
605     int nItem;
606     for(nItem=0; nItem < GetItems().Number() ; nItem++)
607     {
608         ecConfigItem *pItem=(ecConfigItem*) GetItems()[nItem];
609
610         if(pItem->HasRadio () && pItem==pItem->FirstRadio())
611         {
612             wxString strMsg;
613             ecConfigItem *pFirstSet=NULL;
614             ecConfigItem *pSibItem;
615
616             for ( pSibItem=pItem; pSibItem; pSibItem = pSibItem->NextRadio() )
617             {
618                 if(pSibItem->IsEnabled ())
619                 {
620                     if(pFirstSet)
621                     {
622                         strMsg += wxT(" ");
623                         strMsg += pSibItem->GetMacro ();
624                     } else
625                     {
626                         pFirstSet = pSibItem;
627                     }
628                 }
629             }
630
631             if ( !strMsg.IsEmpty() )
632             {
633                 wxString msg2;
634                 msg2.Printf(_("%s, multiple radio buttons are set: %s%s"),
635                     (const wxChar*) pItem->GetMacro(), (const wxChar*) pFirstSet->GetMacro(), (const wxChar*) strMsg);
636                 wxGetApp().Log(msg2);
637             } else if ( !pFirstSet )
638             {
639                 wxString msg2;
640                 msg2.Printf(_("%s, no radio buttons are set"), (const wxChar*) pItem->GetMacro());
641                 wxGetApp().Log(msg2);
642             }
643         }
644     }
645 }
646
647 // Find the ecConfigItem referencing the given CdlValuable
648 ecConfigItem * ecConfigToolDoc::Find (CdlValuable v)
649 {
650     int nItem;
651     for (nItem=0 ; nItem < m_items.Number() ; nItem++)
652     {
653         ecConfigItem *pItem = (ecConfigItem*) m_items[nItem];
654         if( v == pItem->GetCdlValuable() )
655         {
656             return pItem;
657         }
658     }
659     return NULL;
660 }
661
662 ecConfigItem * ecConfigToolDoc::Find(const wxString & strWhat, ecWhereType where)
663 {
664     int nItem;
665     for (nItem=0 ; nItem < m_items.Number() ; nItem++)
666     {
667         ecConfigItem *pItem = (ecConfigItem*) m_items[nItem];
668         if (pItem->StringValue(where) == strWhat)
669         {
670             return pItem;
671         }
672     }
673     return NULL;
674 }
675
676 // a trivial CDL load error handler
677 void ecConfigToolDoc::CdlLoadErrorHandler (std::string message)
678 {
679     wxGetApp().Log(message.c_str());
680 };
681
682 // a trivial CDL load warning handler
683 void ecConfigToolDoc::CdlLoadWarningHandler (std::string message)
684 {
685     wxGetApp().Log(message.c_str());
686 };
687
688 // a trivial CDL parse error handler
689 void ecConfigToolDoc::CdlParseErrorHandler (std::string message)
690 {
691     wxGetApp().Log(message.c_str());
692 };
693
694 // a trivial CDL parse warning handler
695 void ecConfigToolDoc::CdlParseWarningHandler (std::string message)
696 {
697     wxGetApp().Log(message.c_str());
698 };
699
700
701 void ecConfigToolDoc::CloseRepository()
702 {
703     if(m_bRepositoryOpen){
704         // delete the libCDL objects with the document
705         EnableCallbacks(FALSE); // first disable the transaction handler
706         delete m_CdlConfig; m_CdlConfig = NULL;
707         delete m_CdlInterp; m_CdlInterp = NULL;
708         delete m_CdlPkgData; m_CdlPkgData = NULL;
709         m_bRepositoryOpen=FALSE;
710     }
711 }
712
713 bool ecConfigToolDoc::OpenRepository(const wxString& pszRepository /* = wxEmptyString */, bool bPromptInitially/* =FALSE */)
714 {
715     ecMainFrame* mainFrame = wxGetApp().GetMainFrame();
716     if(!m_bRepositoryOpen)
717     {
718         UpdateFailingRuleCount();
719
720         ecFileName strNewRepository;
721         while(!m_bRepositoryOpen)
722         {
723             if(bPromptInitially)
724             {
725                 ecChooseRepositoryDialog dlg(wxGetApp().GetTopWindow());
726
727                 if(wxID_CANCEL==dlg.ShowModal()){
728                     wxGetApp().SetStatusText(wxEmptyString);
729                     return FALSE;
730                 }
731 #ifdef __WXMSW__
732                 // Ensure display gets updated
733                 ::UpdateWindow((HWND) mainFrame->GetHWND());
734                 //wxYield();
735 #endif
736                 strNewRepository=dlg.GetFolder();
737             } else
738             {
739                 // Use what came in as parameter or what was found in registry
740                 if (!pszRepository.IsEmpty())
741                     strNewRepository = pszRepository;
742                 else
743                     strNewRepository = m_strRepository;
744
745                 bPromptInitially=TRUE;
746             }
747             wxString str;
748             if (strNewRepository.IsEmpty())
749                 str.Printf(_("Opening repository..."));
750             else
751                 str.Printf(_("Opening repository %s..."), (const wxChar*) strNewRepository);
752             wxGetApp().SetStatusText(str);
753
754             CdlPackagesDatabase NewCdlPkgData = NULL;
755             CdlInterpreter      NewCdlInterp  = NULL;
756             CdlConfiguration    NewCdlConfig  = NULL;
757             wxString strNewPackagesDir;
758
759             EnableCallbacks(FALSE); // disable transaction callbacks until the config tree is regenerated
760
761             wxBusyCursor wait;
762             if(OpenRepository(strNewRepository,NewCdlPkgData,NewCdlInterp,NewCdlConfig,strNewPackagesDir))
763             {
764                 // select the "default" template if it exists
765                 // otherwise select the first available template
766
767                 std::string default_template = "default";
768                 if (! NewCdlPkgData->is_known_template (default_template))
769                 {
770                     const std::vector<std::string>& templates = NewCdlPkgData->get_templates ();
771                     if (templates.size () != 0)
772                         default_template = templates [0];
773                 }
774
775                 m_templateVersion = "";
776                 try
777                 {
778                     const std::vector<std::string>& template_versions = NewCdlPkgData->get_template_versions (default_template);
779                     NewCdlConfig->set_template (default_template, template_versions [0], &CdlParseErrorHandler, &CdlParseWarningHandler);
780                     m_templateVersion = template_versions [0].c_str();
781                 }
782                 catch (CdlStringException exception) {
783                     wxString msg;
784                     msg.Printf(_("Error loading package template '%s':\n\n%s"), default_template.c_str (), exception.get_message ().c_str ());
785                     wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
786                 }
787                 catch (...) {
788                     wxString msg;
789                     msg.Printf(_("Error loading package template '%s'."), default_template.c_str ());
790                     wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
791                 }
792
793                 // check the configuration
794                 wxASSERT (NewCdlConfig->check_this (cyg_extreme));
795
796                 // use the new package database, interpreter and configuration
797                 delete m_CdlConfig; // delete the previous configuration
798                 delete m_CdlInterp; // delete the previous interpreter
799                 delete m_CdlPkgData; // delete the previous package database
800
801                 m_CdlPkgData = NewCdlPkgData;
802                 m_CdlInterp  = NewCdlInterp;
803                 m_CdlConfig  = NewCdlConfig;
804
805                 // save the repository location
806
807                 SetRepository(strNewRepository);
808                 m_strPackagesDir = strNewPackagesDir;
809
810                 // clear the previously specified document file name (if any),
811                 // OnNewDocument() calls DeleteContents() so must be called
812                 // before AddAllItems()
813
814                 wxDocument::OnNewDocument ();
815
816                 // generate the CConfigItems from their CDL descriptions
817                 AddAllItems ();
818
819                 m_bRepositoryOpen=TRUE;
820
821                 // Rebuild help index if it needs building
822                 RebuildHelpIndex(FALSE);
823
824             } else {
825                 // failure
826                 delete NewCdlConfig; NewCdlConfig = NULL;
827                 delete NewCdlInterp; NewCdlInterp = NULL;
828                 delete NewCdlPkgData; NewCdlPkgData = NULL;
829
830             }
831
832             // install a transaction handler callback function now that the tree exists
833             EnableCallbacks(TRUE);
834         }
835
836     }
837     wxGetApp().SetStatusText(wxEmptyString, FALSE);
838     return m_bRepositoryOpen;
839 }
840
841 // Find a valid repository given a directory name
842 bool ecConfigToolDoc::FindRepository (ecFileName& repositoryIn, ecFileName& repositoryOut) const
843 {
844     if (repositoryIn.IsEmpty())
845         return FALSE;
846     
847     if (ecFileName(repositoryIn + wxT("ecos.db")).Exists())
848     {
849         repositoryOut = repositoryIn;
850         repositoryIn = wxPathOnly(repositoryIn);
851         return TRUE;
852     }
853     else if (ecFileName(ecFileName(repositoryIn) + ecFileName(wxT("ecc")) + wxT("ecos.db")).Exists())
854     {
855         repositoryOut = repositoryIn + wxT("ecc");
856         return TRUE;
857     }
858     else if (ecFileName(ecFileName(repositoryIn) + ecFileName(wxT("packages")) + wxT("ecos.db")).Exists())
859     {
860         repositoryOut = repositoryIn + wxT("packages");
861         return TRUE;
862     }
863     else
864     {
865         return FALSE;
866     }
867 }
868
869
870 bool ecConfigToolDoc::OpenRepository (ecFileName& strNewRepository, CdlPackagesDatabase &NewCdlPkgData,CdlInterpreter &NewCdlInterp,CdlConfiguration &NewCdlConfig, wxString &strNewPackagesDir)
871 {
872     bool rc=FALSE;
873
874     if (strNewRepository.IsEmpty())
875         return FALSE;
876
877     ecFileName strNewPackagesDir1;
878     if (!FindRepository(strNewRepository, strNewPackagesDir1))
879     {
880         wxString msg;
881         msg.Printf(_("%s does not seem to be a source repository."),
882                     (const wxChar*) strNewRepository);
883         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
884     } else
885     {
886                 strNewPackagesDir = strNewPackagesDir1;
887
888                 const wxString strDatabase = strNewPackagesDir + wxString(wxFILE_SEP_PATH) + wxT("ecos.db");
889                 if(!wxFileExists(strDatabase))
890                 {
891                     wxString msg;
892                     msg.Printf(_("%s does not seem to be a source repository: %s does not exist"), (const wxChar*) strNewRepository, (const wxChar*) strDatabase);
893                     wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
894                 } else
895                 {
896
897                     // create a CDL repository, interpreter and configuration
898                     try {// create a new package database, interpreter and configuration
899                         NewCdlPkgData = CdlPackagesDatabaseBody::make ((const wxChar*) strNewPackagesDir, &CdlParseErrorHandler, &CdlParseWarningHandler);
900                         NewCdlInterp = CdlInterpreterBody::make ();
901                         NewCdlConfig = CdlConfigurationBody::make ("eCos", NewCdlPkgData, NewCdlInterp);
902                     }
903                     catch (CdlStringException exception)
904                     {
905                         wxString msg;
906                         msg.Printf(_("Error opening eCos repository:\n\n%s"), exception.get_message ().c_str ());
907                         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
908                         return FALSE;
909                     }
910                     catch (...)
911                     {
912                         wxString msg;
913                         msg.Printf(_("Error opening eCos repository."));
914                         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
915                         return FALSE;
916                     }
917
918                     // select the default target if specified in the registry
919                     // otherwise select the first available target
920                     wxString default_hardware = GetDefaultHardware ();
921
922                     if (! NewCdlPkgData->is_known_target ((const wxChar*) default_hardware)) {
923                         const std::vector<std::string>& targets = NewCdlPkgData->get_targets ();
924                         if (targets.size () == 0)
925                         {
926                             wxString msg;
927                             msg.Printf(_("Error opening eCos repository:\n\nno hardware templates"));
928                             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
929                             return FALSE;
930                         } else {
931                             default_hardware = targets [0].c_str();
932                         }
933                     }
934
935                     try {
936                         m_strCdlErrorMessage = wxT("");
937                         NewCdlConfig->set_hardware ((const wxChar*) default_hardware, &CdlParseErrorHandler, &CdlParseWarningHandler);
938                     }
939                     catch (CdlStringException exception) {
940                         if (m_strCdlErrorMessage.IsEmpty ())
941                         {
942                             wxString msg;
943                             msg.Printf(_("Error loading the default hardware template '%s':\n\n%s"), default_hardware.c_str (), exception.get_message ().c_str ());
944                             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
945                         }
946                         else // report the most recent parser message in the message box since there may be no output pane in which to view it
947                         {
948                             wxString msg;
949                             msg.Printf(_("Error loading the default hardware template '%s':\n\n%s\n\nParser message:\n\n%s"), default_hardware.c_str (), exception.get_message ().c_str (), (const wxChar*) m_strCdlErrorMessage);
950                             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
951                         }
952                         return FALSE;
953                     }
954                     catch (...) {
955                         wxString msg;
956                         msg.Printf(_("Error loading the default hardware template '%s':\n\n%s"), default_hardware.c_str (), (const wxChar*) m_strCdlErrorMessage);
957                         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
958                         return FALSE;
959                     }
960                     rc=TRUE;
961                 }
962     }
963
964     return rc;
965 }
966
967 void ecConfigToolDoc::SelectTemplate (const wxString& newTemplate, const wxString& newTemplateVersion)
968 {
969     if ((newTemplate != m_CdlConfig->get_template().c_str()) || (newTemplateVersion != m_templateVersion)){
970
971         wxBusyCursor wait; // this may take a little while
972         DeleteItems();
973
974         m_templateVersion = wxT("");
975         try
976         {
977             m_CdlConfig->set_template (newTemplate.c_str(), newTemplateVersion.c_str(), CdlParseErrorHandler, CdlParseWarningHandler);
978             m_templateVersion = newTemplateVersion;
979         }
980         catch (CdlStringException exception)
981         {
982             wxString msg;
983             msg.Printf(wxT("Error loading package template '%s':\n\n%s"), (const wxChar*) newTemplate.c_str (), (const wxChar*) exception.get_message ().c_str ());
984             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
985         }
986         catch (...)
987         {
988             wxString msg;
989             msg.Printf(wxT("Error loading package template '%s'."), (const wxChar*) newTemplate.c_str ());
990             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
991         }
992         RegenerateData();
993
994         if (!GetFilename().IsEmpty())
995         { // not a new document
996 #if 0 // TODO
997             CopyMLTFiles (); // copy new MLT files to the build tree as necessary
998 #endif
999         }
1000         Modify(TRUE);
1001         wxGetApp().GetMainFrame()->UpdateFrameTitle();
1002     }
1003 }
1004
1005 void ecConfigToolDoc::RegenerateData()
1006 {
1007     wxBusyCursor wait; // This may take a little while
1008     AddAllItems (); // regenerate all the config items since the topology may have changed
1009     if (m_strLinkerScriptFolder.IsEmpty ())
1010     {
1011         wxMessageBox(_("The eCos linker script macro CYGBLD_LINKER_SCRIPT is not defined."), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1012     }
1013     if (m_strMemoryLayoutFolder.IsEmpty ())
1014     {
1015         wxMessageBox(_("The eCos memory layout macro CYGHWR_MEMORY_LAYOUT is not defined."), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1016     }
1017     // TODO
1018 #if 0
1019     SwitchMemoryLayout (TRUE); // the hardware template may have changed
1020 #endif
1021
1022     if (GetDocumentSaved() && !wxGetApp().GetSettings().m_editSaveFileOnly)
1023         UpdateBuildInfo();
1024     
1025     // TODO
1026     // CConfigTool::GetControlView()->SelectItem(Item(0));
1027 }
1028
1029 void ecConfigToolDoc::SelectHardware (const wxString& newTemplate)
1030 {
1031     const std::string OldTemplate=m_CdlConfig->get_hardware();
1032     if (newTemplate != OldTemplate.c_str()){
1033         DeleteItems();
1034
1035         try
1036         {
1037             m_CdlConfig->set_hardware (newTemplate.c_str(), CdlParseErrorHandler, CdlParseWarningHandler);
1038         }
1039         catch (CdlStringException exception)
1040         {
1041             wxString msg;
1042             msg.Printf(_("Error loading hardware template '%s':\n\n%s"), (const wxChar*) newTemplate, (const wxChar*) exception.get_message ().c_str ());
1043             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1044             m_CdlConfig->set_hardware (OldTemplate, CdlParseErrorHandler, CdlParseWarningHandler);
1045         }
1046         catch (...)
1047         {
1048             wxString msg;
1049             msg.Printf(_("Error loading hardware template '%s'."), (const wxChar*) newTemplate);
1050             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1051             m_CdlConfig->set_hardware (OldTemplate, CdlParseErrorHandler, CdlParseWarningHandler);
1052         }
1053
1054         RegenerateData();
1055
1056         // TODO
1057 #if 0
1058         if (!GetFilename().IsEmpty())
1059         {
1060             CopyMLTFiles (); // copy new MLT files to the build tree as necessary
1061         }
1062 #endif
1063
1064         Modify(TRUE);
1065         wxGetApp().GetMainFrame()->UpdateFrameTitle();
1066     }
1067 }
1068
1069 void ecConfigToolDoc::SelectPackages ()
1070 {
1071     // Crashes the Cygwin 1.0 compiler
1072 #ifndef __CYGWIN10__
1073     ecPackagesDialog dlg(wxGetApp().GetTopWindow());
1074
1075     // This map holds the ecConfigItem pointers for the packages loaded before the dialog is invoked.
1076     // We cannot use Find(), which traverses all items - potentially those that have been removed
1077     wxHashTable arLoadedPackages(wxKEY_STRING);
1078
1079     wxBeginBusyCursor();
1080
1081     // generate the contents of the add/remove list boxes
1082     const std::vector<std::string> & packages = m_CdlPkgData->get_packages ();
1083     std::vector<std::string>::const_iterator package_i;
1084     for (package_i = packages.begin (); package_i != packages.end (); package_i++)
1085     {
1086         //              if (! m_CdlPkgData->is_hardware_package (* package_i)) // do not list hardware packages
1087         {
1088             const std::vector<std::string> & aliases = m_CdlPkgData->get_package_aliases (* package_i);
1089             wxString strMacroName = package_i->c_str ();
1090
1091             // use the first alias (if any) as the package identifier
1092             wxString strPackageName = aliases.size () ? aliases [0].c_str () : strMacroName.c_str();
1093             ecConfigItem * pItem = Find (strMacroName);
1094             if (pItem) // if the package is loaded
1095             {
1096                 arLoadedPackages.Put(strMacroName, pItem);
1097                 // pass the currently selected package version string to the dialog box
1098                 const CdlValuable valuable = pItem->GetCdlValuable();
1099                 dlg.Insert (strPackageName, TRUE, wxEmptyString, valuable ? wxString (valuable->get_value ().c_str ()) : wxString());
1100             }
1101             else
1102             {
1103                 // pass version string of the most latest version to the dialog box
1104                 dlg.Insert (strPackageName, FALSE, wxEmptyString, wxString (m_CdlPkgData->get_package_versions (* package_i) [0].c_str ()));
1105             }
1106         }
1107     }
1108
1109     wxEndBusyCursor();
1110
1111     if (wxID_OK == dlg.ShowModal ())
1112     {
1113         bool bChanged = FALSE; // until proved otherwise
1114
1115         // determine whether each package has changed loaded/unloaded state
1116         for (package_i = packages.begin (); package_i != packages.end (); package_i++)
1117             //                  if (! m_CdlPkgData->is_hardware_package (* package_i)) // do not check hardware packages
1118         {
1119             const std::vector<std::string> & aliases = m_CdlPkgData->get_package_aliases (* package_i);
1120             wxString strMacroName = package_i->c_str ();
1121
1122             // use the first alias (if any) as the package identifier
1123             wxString strPackageName = aliases.size () ? aliases [0].c_str () : strMacroName.c_str();
1124
1125             ecConfigItem *pItem = (ecConfigItem *) arLoadedPackages.Get(strMacroName);
1126             //bool bPreviouslyLoaded=arLoadedPackages.Lookup(strMacroName,(void *&)pItem);
1127             bool bPreviouslyLoaded = (pItem != NULL);
1128             bool bNowLoaded=dlg.IsAdded (strPackageName);
1129
1130             // unload packages which are no longer required before
1131             // loading new ones to avoid potential duplicate macro definitions
1132             if (! bNowLoaded && bPreviouslyLoaded){
1133                 // The package was loaded but should now be unloaded:
1134                 bChanged|=pItem->Unload();
1135             } else if (bNowLoaded) {// if the package should be loaded
1136                 const wxString strVersion(dlg.GetVersion (strPackageName));
1137                 if (bPreviouslyLoaded) { // if the package is already loaded
1138                     CdlTransactionCallback::set_callback_fn (NULL); // avoid value refresh attempts during load/unload
1139                     bChanged|=pItem->ChangeVersion(strVersion);
1140                     CdlTransactionCallback::set_callback_fn (CdlTransactionHandler); // restore value refresh
1141                 } else {
1142                     // the package was not loaded but should now be loaded
1143                     //TRACE (_T("Loading package %s\n"), strMacroName);
1144                     try
1145                     {
1146                         GetCdlConfig()->load_package (ecUtils::UnicodeToStdStr(strMacroName), ecUtils::UnicodeToStdStr (strVersion), ecConfigToolDoc::CdlParseErrorHandler, ecConfigToolDoc::CdlParseWarningHandler);
1147                         bChanged=true;
1148                     }
1149                     catch (CdlStringException exception)
1150                     {
1151                         wxString msg;
1152                         msg.Printf(_("Error loading package %s:\n\n%s"), (const wxChar*) strMacroName, (const wxChar*) exception.get_message ().c_str ());
1153                         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1154                     }
1155                     catch (...)
1156                     {
1157                         wxString msg;
1158                         msg.Printf(_("Error loading package %s"), (const wxChar*) strMacroName);
1159                         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1160                     }
1161                 }
1162             }
1163         }
1164
1165         if (bChanged) {// at least one package was loaded, unloaded or changed version
1166             Modify(TRUE);
1167             wxGetApp().GetMainFrame()->UpdateFrameTitle();
1168             RegenerateData();
1169         }
1170     }
1171 #endif
1172 }
1173
1174
1175 bool ecConfigToolDoc::UpdateBuildInfo(bool WXUNUSED(bFirstTime))
1176 {
1177     try {
1178         GetCdlConfig()->get_build_info(m_BuildInfo);
1179         generate_build_tree (GetCdlConfig(), ecUtils::UnicodeToStdStr(GetBuildTree()), ecUtils::UnicodeToStdStr(GetInstallTree()));
1180         return TRUE;
1181     }
1182     catch(...){
1183         return FALSE;
1184     }
1185 }
1186
1187 wxString ecConfigToolDoc::GetDefaultHardware ()
1188 {
1189 #ifdef __WXMSW__
1190     // get the greatest eCos version subkey
1191     wxConfig config(wxT("eCos"), wxEmptyString, wxEmptyString, wxEmptyString, wxCONFIG_USE_GLOBAL_FILE);
1192
1193     wxString versionKey(wxT(""));
1194     wxString key(wxT(""));
1195     long index;
1196     bool bMore = config.GetFirstGroup(key, index);
1197     while (bMore)
1198     {
1199         if (wxIsdigit(key.GetChar(0)) && versionKey.CompareTo(key) < 0)
1200             versionKey = key;
1201
1202         bMore = config.GetNextGroup(key, index);
1203     }
1204
1205     if (!versionKey.IsEmpty())
1206     {
1207         wxString defaultHardware;
1208         wxString defaultHardwareKey(versionKey + wxString(wxT("/")) + wxString(wxT("Default Hardware")));
1209         if (config.Read(defaultHardwareKey, & defaultHardware))
1210         {
1211             return defaultHardware;
1212         }
1213     }
1214     return wxEmptyString;
1215 #else
1216     // For other platforms, simply rely on Cdl to get the default hardware.
1217     return wxEmptyString;
1218 #endif
1219 }
1220
1221 void ecConfigToolDoc::EnableCallbacks (bool bEnable/*=TRUE*/)
1222 {
1223     CdlTransactionCallback::set_callback_fn(bEnable?&CdlTransactionHandler:0);
1224     CdlTransactionBody::set_inference_callback_fn(bEnable?&CdlInferenceHandler:0);
1225     CdlTransactionBody::set_inference_override(CdlValueSource_Invalid);
1226 }
1227
1228 CdlInferenceCallbackResult ecConfigToolDoc::CdlGlobalInferenceHandler(CdlTransaction transaction)
1229 {
1230     CdlInferenceCallbackResult rc=CdlInferenceCallbackResult_Continue;
1231
1232     ecConfigToolDoc *pDoc = wxGetApp().GetConfigToolDoc();
1233     pDoc->m_ConflictsOutcome=NotDone;  // prepare for the case that there are no solutions
1234
1235     const std::list<CdlConflict>& conflicts=pDoc->GetCdlConfig()->get_all_conflicts();
1236     ecResolveConflictsDialog dlg(wxGetApp().GetTopWindow(), conflicts, transaction, &pDoc->m_arConflictsOfInterest);
1237
1238     rc = (wxID_OK == dlg.ShowModal()) ? CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel;
1239     pDoc->m_ConflictsOutcome=(CdlInferenceCallbackResult_Continue==rc)?OK:Cancel;
1240
1241     return rc;
1242 }
1243
1244 CdlInferenceCallbackResult ecConfigToolDoc::CdlInferenceHandler (CdlTransaction transaction)
1245 {
1246     CdlInferenceCallbackResult rc=CdlInferenceCallbackResult_Continue;
1247
1248     ecConfigToolDoc *pDoc=wxGetApp().GetConfigToolDoc();
1249     const std::list<CdlConflict>&conflicts=transaction->get_new_conflicts();
1250     if ((wxGetApp().GetSettings().m_nRuleChecking & ecSettings::Immediate) && conflicts.size()>0)
1251     {
1252         if (wxGetApp().GetSettings().m_nRuleChecking & ecSettings::SuggestFixes)
1253         {
1254             std::list<CdlConflict> s_conflicts;
1255             for (std::list<CdlConflict>::const_iterator conf_i= conflicts.begin (); conf_i != conflicts.end (); conf_i++) { // for each conflict
1256                 if((*conf_i)->has_known_solution()){
1257                     s_conflicts.push_back(*conf_i);
1258                 }
1259             }
1260             if(s_conflicts.size()>0)
1261             {
1262                 wxGetApp().LockValues();
1263
1264                 ecResolveConflictsDialog dlg(wxGetApp().GetTopWindow(), s_conflicts, transaction);
1265                 int ret = dlg.ShowModal() ;
1266
1267                 wxGetApp().UnlockValues();
1268
1269                 return (wxID_OK == ret ? CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel);
1270             }
1271         }
1272
1273         wxGetApp().LockValues();
1274
1275         wxString strMsg;
1276         if(1==conflicts.size()){
1277             strMsg=wxT("There is 1 unresolved conflict. Make the change anyway?");
1278         } else {
1279             strMsg.Printf(_("There are %d unresolved conflict%s. Make the change anyway?"), conflicts.size(), (const wxChar*) (1==conflicts.size()? wxT(""):wxT("s")) );
1280         }
1281         rc = (wxYES == wxMessageBox(strMsg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxYES_NO)) ? CdlInferenceCallbackResult_Continue:CdlInferenceCallbackResult_Cancel;
1282
1283         wxGetApp().UnlockValues();
1284
1285     }
1286     return rc;
1287 }
1288
1289
1290 // a CDL transaction handler to refresh the configuration tree
1291 void ecConfigToolDoc::CdlTransactionHandler (const CdlTransactionCallback & data)
1292 {
1293     static int nNesting=0;
1294     //TRACE(_T("Transaction handler: nesting level=%d\n"),nNesting++);
1295     ecConfigToolDoc *pDoc = wxGetApp().GetConfigToolDoc();
1296
1297     std::vector<CdlValuable>::const_iterator val_i;
1298     std::vector<CdlNode>::const_iterator node_i;
1299     std::list<CdlConflict>::const_iterator conf_i;
1300     ecConfigToolView *pControlView = (ecConfigToolView*) pDoc->GetFirstView();
1301
1302     for (val_i = data.value_changes.begin(); val_i != data.value_changes.end(); val_i++)
1303     {
1304         const wxString strName((*val_i)->get_name().c_str());
1305         //TRACE(_T("%s %s : value change\n"), wxString ((*val_i)->get_class_name().c_str()), strName);
1306         pControlView->Refresh(strName);
1307         if (strName==wxT("CYGHWR_MEMORY_LAYOUT")){               // the memory layout has changed...
1308             // TODO
1309             // pDoc->SwitchMemoryLayout (FALSE); // ...so display a new one
1310         }
1311     }
1312     for (node_i = data.active_changes.begin(); node_i != data.active_changes.end(); node_i++)
1313     {
1314         const wxString strName((*node_i)->get_name().c_str());
1315         //TRACE(_T("%s %s : this has become active or inactive\n"), CString ((*node_i)->get_class_name().c_str()),
1316         //    CString ((*node_i)->get_name().c_str()));
1317         if (! dynamic_cast<CdlInterface> (*node_i)){ // if not an interface node
1318             pControlView->Refresh(strName);
1319         }
1320     }
1321     for (val_i = data.legal_values_changes.begin(); val_i != data.legal_values_changes.end(); val_i++)
1322     {
1323         const wxString strName((*node_i)->get_class_name().c_str());
1324         //TRACE(_T("%s %s : the legal_values list has changed, a new widget may be needed.\n"),
1325         //    CString ((*val_i)->get_class_name().c_str()), strName);
1326     }
1327
1328     for (val_i = data.value_source_changes.begin(); val_i != data.value_source_changes.end(); val_i++)
1329     {
1330         const wxString strName((*val_i)->get_name().c_str());
1331         CdlValueSource source = (*val_i)->get_source();
1332 /*
1333         TRACE(_T("%s %s : the value source has changed to %s\n"),
1334             CString ((*val_i)->get_class_name().c_str()), strName,
1335             CString ((CdlValueSource_Default  == source) ? "default"  :
1336         (CdlValueSource_Inferred == source) ? "inferred" :
1337         (CdlValueSource_Wizard   == source) ? "wizard"   : "user"));
1338 */
1339         pControlView->Refresh (strName);
1340     }
1341
1342     pDoc->UpdateFailingRuleCount();
1343     nNesting--;
1344 }
1345
1346 bool ecConfigToolDoc::ShowURL(const wxString& strURL1)
1347 {
1348     bool rc = TRUE;
1349
1350     wxString strURL(strURL1);
1351
1352 /*
1353     if(!QualifyDocURL(strURL)){
1354         return FALSE; // error message already output
1355     }
1356 */
1357
1358     switch (wxGetApp().GetSettings().m_eUseCustomBrowser)
1359     {
1360     case ecInternal:
1361         rc = ShowInternalHtmlHelp(strURL);
1362         break;
1363     case ecAssociatedExternal:
1364         {
1365             rc = ShowExternalHtmlHelp(strURL);
1366         }
1367
1368         break;
1369     case ecCustomExternal:
1370         QualifyDocURL(strURL, FALSE);
1371         wxGetApp().Launch(strURL, wxGetApp().GetSettings().m_strBrowser);
1372         break;
1373     default:
1374         wxASSERT(FALSE);
1375     }
1376     return rc;
1377 }
1378
1379 bool ecConfigToolDoc::ShowExternalHtmlHelp (const wxString& strURL)
1380 {
1381 #if defined(__WXMSW__) || defined(__WXGTK__)
1382
1383     wxString url;
1384
1385     wxString sep(wxFILE_SEP_PATH);
1386     wxString docDir(wxString(m_strRepository) + sep + wxString(wxT("doc")));
1387     if (wxDirExists(docDir + sep + wxT("html")))
1388         docDir += sep + wxT("html") ;
1389
1390     if (strURL.Left(7) == wxT("http://") || strURL.Left(7) == wxT("file://"))
1391         url = strURL;
1392     else
1393     {
1394         if (wxIsAbsolutePath(strURL))
1395             url = strURL;
1396         else
1397             url = docDir + sep + strURL;
1398     }
1399
1400     wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(wxT("html"));
1401     if ( !ft )
1402     {
1403         wxLogError(_T("Impossible to determine the file type for extension html"));
1404         return FALSE;
1405     }
1406
1407     wxString cmd;
1408     bool ok = ft->GetOpenCommand(&cmd,
1409                                  wxFileType::MessageParameters(url, _T("")));
1410     delete ft;
1411
1412     if (!ok)
1413     {
1414         // TODO: some kind of configuration dialog here.
1415         wxMessageBox(_("Could not determine the command for running the browser."),
1416                    wxGetApp().GetSettings().GetAppName(), wxOK|wxICON_EXCLAMATION);
1417         return FALSE;
1418     }
1419
1420     // Remove spurious file:// if added
1421 #ifdef __WXMSW__
1422     if (strURL.Left(7) == wxT("http://"))
1423         cmd.Replace(wxT("file://"), wxT(""));
1424 #endif
1425
1426     ok = (wxExecute(cmd, FALSE) != 0);
1427
1428     return ok;
1429
1430     // Old code using MS HTML Help
1431 #elif 0
1432     HWND hwndCaller = ::GetDesktopWindow();
1433
1434     wxString helpFile(wxGetApp().GetHelpFile());
1435     bool rc = FALSE;
1436     const ecFileName strFile(HTMLHelpLinkFileName());
1437     if (wxFileExists(strFile))
1438         wxRemoveFile(strFile);
1439
1440     wxTextFile f(strFile);
1441     if(!ecFileName(helpFile).Exists())
1442     {
1443         wxString msg;
1444         msg.Printf(_("Cannot display help - %s does not exist"), (const wxChar*) helpFile);
1445         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1446     } else if (!f.Create())
1447     {
1448         wxString msg;
1449         msg.Printf(_("Cannot display help - error creating %s"), (const wxChar*) strFile);
1450         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1451     } else
1452     {
1453         wxString str;
1454         str.Printf(_T("<meta HTTP-EQUIV=\"refresh\" CONTENT=\"0;URL=%s\">"), (const wxChar*) strURL);
1455         f.AddLine(str);
1456         f.Write();
1457         f.Close();
1458         if(0==HtmlHelp(hwndCaller, wxGetApp().GetHelpFile(), HH_DISPLAY_TOPIC, 0))
1459         {
1460             wxString msg;
1461             msg.Printf(_("Cannot display %s"), (const wxChar*) strURL);
1462             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1463         }
1464 #if 0
1465         else
1466         {
1467             // JACS: I don't think we need to do this. Even on the MFC version, the notification
1468             // callback didn't do anything interesting.
1469 #define ID_HHNOTIFICATION               55017
1470
1471             // FIXME: Do this the first time only?
1472             HH_WINTYPE WinType;
1473             HWND wnd;
1474             HH_WINTYPE *pWinType=NULL;
1475             wxString s = wxGetApp().GetHelpFile() + wxT(">mainwin");
1476             wnd = HtmlHelp(hwndCaller, s, HH_GET_WIN_TYPE, (DWORD) &pWinType);
1477             WinType=*pWinType;
1478             WinType.hwndCaller=hwndCaller;
1479             WinType.fsWinProperties|=HHWIN_PROP_TRACKING;
1480             WinType.idNotify = ID_HHNOTIFICATION;
1481             wnd = HtmlHelp(hwndCaller, wxGetApp().GetHelpFile(), HH_SET_WIN_TYPE, (DWORD) &WinType);
1482             rc = TRUE;
1483         }
1484 #endif
1485         //wxRemoveFile(strFile);
1486     }
1487     return rc;
1488
1489 #else
1490     wxMessageBox(_("Sorry, ShowHtmlHelp not yet implemented"), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1491     return FALSE;
1492 #endif
1493 }
1494
1495 bool ecConfigToolDoc::ShowInternalHtmlHelp (const wxString& strURL)
1496 {
1497 #if defined(__WXMSW__) || defined(__WXGTK__)
1498
1499     wxString url(strURL);
1500
1501     wxString sep(wxFILE_SEP_PATH);
1502     wxString docDir(wxString(m_strRepository) + sep + wxString(wxT("doc")));
1503     if (wxDirExists(docDir + sep + wxT("html")))
1504         docDir += sep + wxT("html") ;
1505
1506     url = docDir + sep + ecHtmlIndexer::Redirect(docDir, url);
1507
1508 #if 0
1509     if (strURL.Left(7) == wxT("http://") || strURL.Left(7) == wxT("file://"))
1510         url = strURL;
1511     else
1512         url = docDir + sep + strURL;
1513 #endif
1514
1515     //url = url.Mid(docDir.Length() + 1);
1516
1517     if (wxGetApp().HasHelpController())
1518     {
1519         return wxGetApp().GetHelpController().Display(url);
1520     }
1521     else
1522         return FALSE;
1523
1524     // Old code using MS HTML Help
1525 #elif 0
1526     HWND hwndCaller = ::GetDesktopWindow();
1527
1528     wxString helpFile(wxGetApp().GetHelpFile());
1529     bool rc = FALSE;
1530     const ecFileName strFile(HTMLHelpLinkFileName());
1531     if (wxFileExists(strFile))
1532         wxRemoveFile(strFile);
1533
1534     wxTextFile f(strFile);
1535     if(!ecFileName(helpFile).Exists())
1536     {
1537         wxString msg;
1538         msg.Printf(_("Cannot display help - %s does not exist"), (const wxChar*) helpFile);
1539         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1540     } else if (!f.Create())
1541     {
1542         wxString msg;
1543         msg.Printf(_("Cannot display help - error creating %s"), (const wxChar*) strFile);
1544         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1545     } else
1546     {
1547         wxString str;
1548         str.Printf(_T("<meta HTTP-EQUIV=\"refresh\" CONTENT=\"0;URL=%s\">"), (const wxChar*) strURL);
1549         f.AddLine(str);
1550         f.Write();
1551         f.Close();
1552         if(0==HtmlHelp(hwndCaller, wxGetApp().GetHelpFile(), HH_DISPLAY_TOPIC, 0))
1553         {
1554             wxString msg;
1555             msg.Printf(_("Cannot display %s"), (const wxChar*) strURL);
1556             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1557         }
1558     }
1559     return rc;
1560
1561 #else
1562     wxMessageBox(_("Sorry, ShowHtmlHelp not yet implemented"), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1563     return FALSE;
1564 #endif
1565 }
1566
1567 const wxString ecConfigToolDoc::HTMLHelpLinkFileName()
1568 {
1569     return ecFileName(wxGetApp().GetHelpFile()).Head() + wxT("link2.htm");
1570 }
1571
1572 bool ecConfigToolDoc::QualifyDocURL(wxString &strURL, bool prefix)
1573 {
1574     if(-1==strURL.Find(wxT("://")))
1575     {
1576 #ifdef __WXMSW__
1577         strURL.Replace(wxT("/"), wxT("\\"));
1578 #endif
1579         wxString originalURL(strURL);
1580
1581         if (! ecFileName (strURL).IsFile ())
1582         { // if not an absolute filepath
1583             strURL = GetDocBase () + ecFileName (originalURL); // prepend the doc directory path
1584         }
1585         if (!wxFileExists(strURL))
1586             strURL = GetDocBase() + ecFileName(wxT("html")) + ecFileName(originalURL);
1587
1588         if (prefix)
1589             strURL = wxT("file://") + strURL;
1590     }
1591
1592     if(0==strURL.Find(wxT("file://")))
1593     {
1594         ecFileName strFile(strURL.Right(strURL.Length()-7));
1595         int nIndex=strFile.Find(wxT('#'), TRUE);
1596
1597         if ( -1 != nIndex )
1598         {
1599             strFile=strFile.Left(nIndex);
1600         }
1601 #ifdef __WXMSW__
1602         strFile.Replace(wxT("/"), wxT("\\"));
1603 #endif
1604
1605         if(!strFile.Exists())
1606         {
1607             wxString msg;
1608             msg.Printf(_("Cannot locate the file %s"), (const wxChar*) strFile);
1609             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxID_OK);
1610             return FALSE;
1611         }
1612     }
1613     return TRUE;
1614 }
1615
1616 wxString ecConfigToolDoc::GetPackageName (const wxString & strAlias)
1617 {
1618     const std::vector<std::string> & packages = m_CdlPkgData->get_packages ();
1619     std::vector<std::string>::const_iterator package_i;
1620     for (package_i = packages.begin (); package_i != packages.end (); package_i++)
1621     {
1622         const std::vector<std::string> & aliases = m_CdlPkgData->get_package_aliases (* package_i);
1623         wxString strPackageAlias = aliases [0].c_str ();
1624         if (aliases.size () && (strAlias == strPackageAlias))
1625             return package_i->c_str ();
1626     }
1627     return wxEmptyString;
1628 }
1629
1630 const wxString ecConfigToolDoc::GetCurrentTargetPrefix()
1631 {
1632     ecConfigItem *pItem = Find(wxT("CYGBLD_GLOBAL_COMMAND_PREFIX"));
1633     if (pItem)
1634         return pItem->StringValue();
1635     else
1636         return wxT("");
1637 }
1638
1639 ecConfigToolDoc::GlobalConflictOutcome ecConfigToolDoc::ResolveGlobalConflicts(wxList *parConflictsOfInterest)
1640 {
1641     m_ConflictsOutcome=NotDone;
1642     m_arConflictsOfInterest.Clear();
1643     if(parConflictsOfInterest)
1644     {
1645         wxNode* node = parConflictsOfInterest->First();
1646         while (node)
1647         {
1648             wxObject* obj = (wxObject*) node->Data();
1649             m_arConflictsOfInterest.Append(obj);
1650             node = node->Next();
1651         }
1652     }
1653     CdlInferenceCallback fn=CdlTransactionBody::get_inference_callback_fn();
1654     CdlTransactionBody::set_inference_callback_fn(CdlGlobalInferenceHandler);
1655     GetCdlInterpreter()->get_toplevel()->resolve_all_conflicts();
1656     CdlTransactionBody::set_inference_callback_fn(fn);
1657     if(NotDone==m_ConflictsOutcome){
1658         // No solutions were available, but we'll run the dialog anyway
1659         const std::list<CdlConflict>& conflicts=GetCdlConfig()->get_all_conflicts();
1660         ecResolveConflictsDialog dlg(wxGetApp().GetTopWindow(), conflicts, NULL, &m_arConflictsOfInterest);
1661         m_ConflictsOutcome = (wxID_OK == dlg.ShowModal())?OK:Cancel;
1662     }
1663     return m_ConflictsOutcome;
1664 }
1665
1666 bool ecConfigToolDoc::CheckConflictsBeforeSave()
1667 {
1668     if (GetCdlInterpreter()->get_toplevel()->get_all_conflicts().size()>0)
1669     {
1670         if(ecSettings::Deferred & wxGetApp().GetSettings().m_nRuleChecking)
1671         {
1672             if ((ecSettings::SuggestFixes & wxGetApp().GetSettings().m_nRuleChecking) &&
1673                 (Cancel==ResolveGlobalConflicts()))
1674             {
1675                 return FALSE;
1676             }
1677             int nConflicts = GetCdlInterpreter()->get_toplevel()->get_all_conflicts().size();
1678             switch (nConflicts)
1679             {
1680             case 0:
1681                 break;
1682             case 1:
1683                 {
1684                     wxString msg;
1685                     msg.Printf(_("There is 1 unresolved conflict. Save anyway?"));
1686                     if (wxNO == wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxYES_NO))
1687                     {
1688                         return FALSE;
1689                     }
1690                 }
1691             default:
1692                 {
1693                     wxString msg;
1694                     msg.Printf(_("There are %d unresolved conflicts. Save anyway?"), nConflicts);
1695                     if (wxNO == wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxYES_NO))
1696                     {
1697                         return FALSE;
1698                     }
1699                 }
1700             }
1701         }
1702     }
1703     return TRUE;
1704 }
1705
1706 void ecConfigToolDoc::UpdateFailingRuleCount()
1707 {
1708     int nCount=0;
1709     if (GetCdlConfig ())
1710     {
1711         // if configuration information
1712
1713         // calculate the number of conflicts
1714         nCount = GetCdlConfig ()->get_all_conflicts ().size ();
1715             //          GetCdlConfig ()->get_structural_conflicts ().size () +    ignore for now
1716
1717         // update the conflicts view
1718         if (wxGetApp().GetMainFrame() && wxGetApp().GetMainFrame()->GetConflictsWindow())
1719         {
1720             wxGetApp().GetMainFrame()->GetConflictsWindow()->FillRules ();
1721         }
1722     }
1723
1724     if (wxGetApp().GetMainFrame())
1725     {
1726         wxGetApp().GetMainFrame()->SetFailRulePane(nCount);
1727     }
1728 }
1729
1730 void ecConfigToolDoc::LogConflicts (const std::list<CdlConflict> & conflicts)
1731 {
1732     std::list<CdlConflict>::const_iterator conf_i;
1733     for (conf_i = conflicts.begin (); conf_i != conflicts.end (); conf_i++) // for each conflict
1734     {
1735         wxString strExplain = (* conf_i)->get_explanation ().c_str (); // get the conflict explanation
1736         wxGetApp().Log (ecUtils::StripExtraWhitespace (strExplain)); // display the message in the output window
1737     }
1738 }
1739
1740 bool ecConfigToolDoc::SetValue (ecConfigItem &ti, double dValue, CdlTransaction transaction/*=NULL*/)
1741 {
1742     wxASSERT (ti.GetOptionType () == ecDouble);
1743
1744     // test if the new double value is in range
1745     const CdlValuable valuable = ti.GetCdlValuable();
1746     CdlListValue list_value;
1747     CdlEvalContext context (NULL, ti.GetCdlItem (), ti.GetCdlItem ()->get_property (CdlPropertyId_LegalValues));
1748     valuable->get_legal_values ()->eval (context, list_value);
1749     if (! list_value.is_member (dValue))
1750     {
1751         if ( dValue == valuable->get_double_value(CdlValueSource_Current) )
1752             return FALSE;
1753
1754         wxString msg;
1755         msg.Printf(_("%s is not a legal value for %s.\n\nDo you want to use this value anyway?"),
1756             (const wxChar*) ecUtils::DoubleToStr (dValue), (const wxChar*) ti.GetMacro ());
1757
1758         if (wxNO == wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_QUESTION|wxYES_NO))
1759             return FALSE;
1760     }
1761
1762     if (! ti.SetValue (dValue,transaction))
1763         return FALSE;
1764
1765     Modify(TRUE);
1766     wxGetApp().GetMainFrame()->UpdateFrameTitle();
1767
1768     // NB UpdateAllViews isn't in the MFC Configtool for double (though it is for the
1769     // other types of value). In theory this should lead to a display inconsistency in the MFC tool.
1770     ecConfigToolHint hint(& ti, ecValueChanged);
1771     UpdateAllViews (NULL, & hint);
1772
1773     return TRUE;
1774 }
1775
1776 bool ecConfigToolDoc::SetValue(ecConfigItem &ti, const wxString &strValue, CdlTransaction transaction/*=NULL*/)
1777 {
1778     // TODO
1779 #if 0
1780     // warn the user if a modified memory layout is about to be discarded
1781     if (MemoryMap.map_modified () && (ti.Macro () == _T("CYG_HAL_STARTUP")) &&
1782         (IDCANCEL == CUtils::MessageBoxFT (MB_OKCANCEL, _T("Changes to the current memory layout will be lost."))))
1783         return false;
1784 #endif
1785
1786     bool rc = FALSE;
1787
1788     switch(ti.GetOptionType())
1789     {
1790     case ecOptionTypeNone:
1791         break;
1792     case ecEnumerated:
1793     case ecString:
1794         rc = ti.SetValue(strValue, transaction);
1795         break;
1796     case ecLong:
1797         {
1798             long n;
1799             rc = ecUtils::StrToItemIntegerType(strValue,n) && SetValue(ti,n,transaction);
1800         }
1801         break;
1802     case ecDouble:
1803         {
1804             double dValue;
1805             rc = ecUtils::StrToDouble (strValue, dValue) && SetValue (ti, dValue,transaction);
1806         }
1807         break;
1808     default:
1809         wxASSERT(FALSE);
1810         break;
1811
1812     }
1813     if(rc){
1814         Modify(TRUE);
1815         wxGetApp().GetMainFrame()->UpdateFrameTitle();
1816
1817         ecConfigToolHint hint(& ti, ecValueChanged);
1818         UpdateAllViews (NULL, & hint);
1819     }
1820     return rc;
1821 }
1822
1823 bool ecConfigToolDoc::SetValue(ecConfigItem &ti, long nValue, CdlTransaction transaction/*=NULL*/)
1824 {
1825     switch(ti.GetOptionType())
1826     {
1827     case ecEnumerated:
1828     case ecLong:
1829         break;
1830     case ecOptionTypeNone:
1831     case ecString:
1832     default:
1833         wxASSERT(FALSE);
1834         break;
1835     }
1836
1837     bool rc = FALSE;
1838
1839     // TODO
1840 #if 0
1841     bool bChangingMemmap = MemoryMap.map_modified () && ((ti.Macro ().Compare (_T ("CYG_HAL_STARTUP")) == 0));
1842 #endif
1843
1844     if(nValue==ti.Value())
1845     {
1846         return TRUE;
1847     }
1848
1849     // test if the new integer value is in range
1850     if (ecLong == ti.GetOptionType ())
1851     {
1852         const CdlValuable valuable = ti.GetCdlValuable();
1853         CdlListValue list_value;
1854         CdlEvalContext context (NULL, ti.GetCdlItem (), ti.GetCdlItem ()->get_property (CdlPropertyId_LegalValues));
1855         valuable->get_legal_values ()->eval (context, list_value);
1856         if (! list_value.is_member ((cdl_int) nValue))
1857         {
1858             if (nValue == (long) valuable->get_integer_value (CdlValueSource_Current))
1859                 goto Exit;
1860
1861             wxString msg;
1862             msg.Printf(_("%s is not a legal value for %s.\n\nDo you want to use this value anyway?"),
1863                 (const wxChar*) ecUtils::IntToStr (nValue, wxGetApp().GetSettings().m_bHex), (const wxChar*) ti.GetMacro ());
1864             if (wxNO == wxMessageBox (msg, wxGetApp().GetSettings().GetAppName(), wxICON_QUESTION|wxYES_NO))
1865                 goto Exit;
1866         };
1867     }
1868
1869     // TODO
1870 #if 0
1871     // warn the user if the current memory layout has been changed and will be lost
1872     // this will happen when the layout has been modified and the target-platform-startup is changed
1873
1874     if (bChangingMemmap && IDCANCEL==CUtils::MessageBoxFT(MB_OKCANCEL,_T("Changes to the current memory layout will be lost."))){
1875         goto Exit;
1876     }
1877 #endif
1878
1879     // Save state
1880     if(!ti.SetValue(nValue,transaction)){
1881         // CanSetValue above should have caught this
1882         wxString msg;
1883         msg.Printf(_("Cannot set '%s' to %d"), (const wxChar*) ti.GetItemNameOrMacro(), nValue);
1884         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1885         goto Exit;
1886     }
1887
1888     rc = TRUE;
1889 Exit:
1890     if(rc)
1891     {
1892         Modify(TRUE);
1893         wxGetApp().GetMainFrame()->UpdateFrameTitle();
1894
1895         UpdateFailingRuleCount ();
1896
1897         ecConfigToolHint hint(& ti, ecValueChanged);
1898         UpdateAllViews (NULL, & hint);
1899     }
1900     return rc;
1901 }
1902
1903 bool ecConfigToolDoc::SetEnabled(ecConfigItem &ti, bool bEnabled, CdlTransaction transaction/*=NULL*/)
1904 {
1905     const bool bStatus = ti.SetEnabled (bEnabled, transaction);
1906
1907     if (bStatus)
1908     {
1909         Modify(TRUE);
1910         ecConfigToolHint hint(& ti, ecValueChanged);
1911         UpdateAllViews (NULL, & hint);
1912     }
1913     return bStatus;
1914 }
1915
1916 const ecFileName ecConfigToolDoc::CurrentLinkerScript()
1917 {
1918     const ecConfigItem * pItem = Find (wxT("CYGBLD_LINKER_SCRIPT"));
1919     return pItem ? ecFileName (m_strPackagesDir, m_strLinkerScriptFolder, pItem->StringValue ()) : ecFileName(wxT(""));
1920 }
1921
1922
1923 bool ecConfigToolDoc::GenerateHeaders()
1924 {
1925     wxString sep(wxFILE_SEP_PATH);
1926
1927     // Generate headers
1928     try {
1929         ecFileName strPkfConfDir(GetInstallTree());
1930         strPkfConfDir += ecFileName(wxT("include"));
1931         strPkfConfDir += ecFileName(wxT("pkgconf"));
1932         if ( !strPkfConfDir.CreateDirectory())
1933         {
1934             wxString msg;
1935             msg.Printf(_("Failed to create %s"), (const wxChar*) strPkfConfDir);
1936             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION);
1937             return FALSE;
1938         }
1939         GetCdlConfig()->generate_config_headers(ecUtils::UnicodeToStdStr(strPkfConfDir.ShortName()));
1940     }
1941     catch (CdlInputOutputException e) {
1942         const wxString strMsg(e.get_message().c_str());
1943         // TRACE(_T("!!! Exception thrown calling generate_config_headers - %s"),strMsg);
1944         wxString msg;
1945         msg.Printf(_("Failed to generate header files - %s"), (const wxChar*) strMsg);
1946         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION);
1947         return FALSE;
1948     }
1949     return TRUE;
1950 }
1951
1952 const ecFileName ecConfigToolDoc::MLTDir ()
1953 {
1954     wxString strPathName (GetFilename ());
1955     wxASSERT (! strPathName.IsEmpty ());
1956     return strPathName.Left (strPathName.Find (wxT('.'), TRUE)) + wxT("_mlt");
1957 }
1958
1959 int ecConfigToolDoc::GetTestExeNames (wxArrayString& arTestExes, wxArrayString& arMissing)
1960 {
1961     arTestExes.Clear();
1962     arMissing.Clear();
1963     typedef std::vector<CdlBuildInfo_Loadable> EntriesArray;
1964     const EntriesArray &arEntries=GetBuildInfo().entries;
1965     for(EntriesArray::size_type j=0;j<arEntries.size();j++)
1966     {
1967         const CdlBuildInfo_Loadable &e=arEntries[j];
1968         wxArrayString ar;
1969         int n = ecUtils::Chop(wxString(get_tests(GetCdlConfig(),e).c_str()),ar);
1970         int i;
1971         for (i=0;i<n;i++)
1972         {
1973             wxString strFile;
1974             strFile += GetInstallTree();
1975             strFile += wxFILE_SEP_PATH;
1976             strFile += wxT("tests");
1977             strFile += wxFILE_SEP_PATH;
1978             strFile += e.directory.c_str();
1979             strFile += wxFILE_SEP_PATH;
1980             strFile += ar[i];
1981
1982             // Some tests accidentally specify .c
1983 //            wxStripExtension(strFile);
1984
1985 #ifdef __WXMSW__
1986 //            strFile += wxT(".exe");
1987             strFile.Replace(wxT("/"),wxT("\\"));
1988 #endif
1989
1990             if (wxFileExists(strFile))
1991             {
1992                 arTestExes.Add(strFile);
1993             } else
1994             {
1995                 arMissing.Add(strFile);
1996             }
1997         }
1998     }
1999     return arTestExes.Count();
2000 }
2001
2002 bool ecConfigToolDoc::SaveMemoryMap()
2003 {
2004     // TODO
2005 #if 0
2006     wxString sep(wxFILE_SEP_PATH);
2007
2008     const wxString strSuffix(wxT("mlt_") + CurrentMemoryLayout ());
2009     ecFileName strMLTInstallPkgconfDir(GetInstallTree());
2010     strMLTInstallPkgconfDir = strMLTInstallPkgconfDir + ecFileName(wxT("include"));
2011     strMLTInstallPkgconfDir = strMLTInstallPkgconfDir + ecFileName(wxT("pkgconf"));
2012
2013     bool rc=false;
2014     if(strMLTInstallPkgconfDir.CreateDirectory(true)){
2015         const wxString strMLTInstallBase(strMLTInstallPkgconfDir+ecFileName(strSuffix));
2016         const ecFileName strMLTDir (MLTDir());
2017
2018         if(strMLTDir.CreateDirectory (TRUE))
2019         {
2020             const wxString strMLTBase (strMLTDir + ecFileName (strSuffix));
2021             // TRACE(_T("Saving memory layout to %s\n"), strMLTBase + _T(".mlt"));
2022             if(MemoryMap.save_memory_layout (strMLTBase + _T(".mlt"))){
2023                 // TRACE(_T("Exporting memory layout to %s\n"), strMLTInstallPkgconfDir);
2024                 rc=MemoryMap.export_files (strMLTInstallBase + _T(".ldi"), strMLTInstallBase + _T(".h"));
2025             }
2026         }
2027     }
2028     return rc;
2029 #else
2030     return FALSE;
2031 #endif
2032 }
2033
2034 bool ecConfigToolDoc::CopyMLTFiles()
2035 {
2036     wxString sep(wxFILE_SEP_PATH);
2037
2038     // copy default MLT files for the selected target/platform from the repository if they do not already exist
2039
2040     // TRACE (_T("Looking for MLT files at %s\n"), PackagesDir() + m_strMemoryLayoutFolder + _T("include\\pkgconf\\mlt_*.*"));
2041     const ecFileName strInstallDestination(GetInstallTree () + sep + wxString(wxT("include")) + sep + wxT("pkgconf"));
2042     const ecFileName strMLTDestination (MLTDir ());
2043     // TRACE (_T("Copying .ldi and .h files to %s\n"), strInstallDestination);
2044     // TRACE (_T("Copying .mlt files to %s\n"), strMLTDestination);
2045     bool rc=strInstallDestination.CreateDirectory ( TRUE ) && strMLTDestination.CreateDirectory ( TRUE );
2046     if (rc)
2047     {
2048         wxDir ffFileFind;
2049         wxString fileName;
2050         wxString path = GetPackagesDir();
2051         path += sep;
2052         path += m_strMemoryLayoutFolder;
2053         path += sep;
2054         path += wxString(wxT("include"));
2055         path += sep;
2056         path += wxString(wxT("pkgconf"));
2057
2058         if (!ffFileFind.Open(path))
2059             return FALSE;
2060
2061         ecFileName wildcard = wxT("mlt_*.*");
2062
2063         //bool bLastFile = ffFileFind.FindFile (PackagesDir() + m_strMemoryLayoutFolder + wxT("\\include\\pkgconf\\mlt_*.*"));
2064         bool bLastFile = ffFileFind.GetFirst (& fileName, wildcard);
2065         while (bLastFile)
2066         {
2067             wxString fullPath = path + sep + fileName;
2068
2069             if (wxT(".mlt") == fileName.Right (4)) // if a .mlt file
2070             {
2071                 if (! ecFileName (strMLTDestination, ecFileName (fileName)).Exists ())
2072                 {
2073                     if (!wxCopyFile (fullPath, strMLTDestination + ecFileName (fileName)))
2074                     {
2075                         return FALSE; // message already emitted
2076                     }
2077                 }
2078             }
2079             else // a .h or .ldi file
2080             {
2081                 if (!ecFileName (strInstallDestination, ecFileName (fileName)).Exists () &&
2082                     !wxCopyFile (fullPath, strInstallDestination + ecFileName (fileName))){
2083                     return FALSE; // message already emitted
2084                 }
2085             }
2086             bLastFile = ffFileFind.GetNext(& fileName);
2087         }
2088     }
2089     return rc; //FIXME
2090 }
2091
2092 const wxString ecConfigToolDoc::CurrentMemoryLayout ()
2093 {
2094     const ecConfigItem * pItem = Find (wxT("CYGHWR_MEMORY_LAYOUT"));
2095
2096     wxString str;
2097     if (pItem)
2098         str = pItem->StringValue ();
2099     return str;
2100 }
2101
2102 bool ecConfigToolDoc::ExportFile()
2103 {
2104     wxFileDialog dialog(wxGetApp().GetTopWindow(), _("Export eCos Minimal Configuration"),
2105         wxT(""), wxT(""), wxT("eCos Minimal Configuration (*.ecm)|*.ecm"), wxSAVE|wxOVERWRITE_PROMPT|wxHIDE_READONLY);
2106
2107     if (dialog.ShowModal() == wxID_OK)
2108     {
2109         try {
2110             m_CdlConfig->save (ecUtils::UnicodeToStdStr (dialog.GetPath()), /* minimal = */ true);
2111         }
2112         catch (CdlStringException exception)
2113         {
2114             wxString msg;
2115             wxString err(exception.get_message ().c_str ());
2116             msg.Printf(_("Error exporting eCos minimal configuration:\n\n%s"), (const wxChar*) err );
2117             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
2118             return FALSE;
2119         }
2120         catch (...)
2121         {
2122             wxString msg;
2123             msg.Printf(_("Error exporting eCos minimal configuration"));
2124             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
2125             return FALSE;
2126         }
2127     }
2128     return TRUE;
2129 }
2130
2131 bool ecConfigToolDoc::ImportFile()
2132 {
2133     wxFileDialog dialog(wxGetApp().GetTopWindow(), _("Import eCos Minimal Configuration"),
2134         wxT(""), wxT(""), wxT("eCos Minimal Configuration (*.ecm)|*.ecm"), wxOPEN|wxFILE_MUST_EXIST|wxHIDE_READONLY);
2135
2136     if (dialog.ShowModal() == wxID_OK)
2137     {
2138         try {
2139             m_CdlConfig->add (ecUtils::UnicodeToStdStr (dialog.GetPath ()), ecConfigToolDoc::CdlParseErrorHandler, ecConfigToolDoc::CdlParseWarningHandler);
2140         }
2141         catch (CdlStringException exception)
2142         {
2143             wxString msg;
2144             wxString err(exception.get_message ().c_str ());
2145             msg.Printf(_("Error importing eCos minimal configuration:\n\n%s"), (const wxChar*) err );
2146             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
2147             return FALSE;
2148         }
2149         catch (...)
2150         {
2151             wxString msg;
2152             msg.Printf(_("Error importing eCos minimal configuration"));
2153             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
2154             return FALSE;
2155         }
2156
2157         wxBusyCursor wait;
2158
2159         AddAllItems (); // regenerate all the config items since the topology may have changed
2160
2161         if (m_strLinkerScriptFolder.IsEmpty ())
2162         {
2163             wxMessageBox(_("The eCos linker script macro CYGBLD_LINKER_SCRIPT is not defined."), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
2164         }
2165         if (m_strMemoryLayoutFolder.IsEmpty ())
2166         {
2167             wxMessageBox(_("The eCos memory layout macro CYGHWR_MEMORY_LAYOUT is not defined."), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
2168         }
2169         SwitchMemoryLayout (TRUE); // the hardware template may have changed
2170         UpdateBuildInfo ();
2171         wxGetApp().GetTreeCtrl()->SelectItem (wxGetApp().GetTreeCtrl()->GetRootItem());
2172         Modify(TRUE);
2173
2174     }
2175     return TRUE;
2176 }
2177
2178 bool ecConfigToolDoc::SwitchMemoryLayout (bool bNewTargetPlatform)
2179 {
2180     bool rc = TRUE;
2181     if (bNewTargetPlatform && ! m_strBuildTree.IsEmpty ()) // the user has changed target/platform within a build tree
2182     {
2183         // copy default MLT save files for the selected target/platform from the repository to the build tree if they do not already exist
2184         CopyMLTFiles();
2185     }
2186
2187     if (m_strBuildTree.IsEmpty ()) // load the memory layout from the repository
2188     {
2189         wxString sep(wxFILE_SEP_PATH);
2190         wxString filename(m_strPackagesDir);
2191         filename += sep;
2192         filename += m_strMemoryLayoutFolder;
2193         filename += sep;
2194         filename += wxT("include");
2195         filename += sep;
2196         filename += wxT("pkgconf");
2197
2198         rc = NewMemoryLayout (ecFileName (filename));
2199     }
2200     else // load the memory layout from the build tree
2201     {
2202         rc = NewMemoryLayout (MLTDir ());
2203     }
2204
2205     return TRUE; // FIXME
2206 }
2207
2208 bool ecConfigToolDoc::NewMemoryLayout (const wxString &strPrefix)
2209 {
2210     // TODO
2211 #if ecUSE_MLT
2212     ecFileName strFileName = CurrentLinkerScript ();
2213     wxString sep(wxFILE_SEP_PATH);
2214
2215     m_memoryMap.new_memory_layout (); // delete the old memory layout regardless
2216     if (! strFileName.IsEmpty ())
2217         m_memoryMap.import_linker_defined_sections (strFileName); // read the linker-defined section names from the repository (failure is silent)
2218
2219     wxString strMemoryLayoutFileName = strPrefix + sep + wxString(wxT("mlt_")) + CurrentMemoryLayout () + wxT(".mlt");
2220
2221     m_memoryMap.load_memory_layout (strMemoryLayoutFileName); // load the new memory layout (failure is silent)
2222     m_strSelectedSection = wxT("");
2223     m_strSelectedRegion = wxT("");
2224
2225     wxGetApp().GetMLTWindow()->RefreshMLT();
2226
2227     // ecConfigToolHint hint(NULL, ecMemLayoutChanged);
2228     // UpdateAllViews (NULL, & hint);
2229 #endif
2230
2231     return TRUE; // FIXME
2232 }
2233
2234 void ecConfigToolDoc::RunTests()
2235 {
2236     wxString strTarget(GetCdlConfig()->get_hardware ().c_str ());
2237     wxArrayString ar;
2238     wxArrayString arTestsMissing;
2239     int nTests;
2240     wxGetApp().GetSettings().GetRunTestsSettings().m_strTarget = strTarget;
2241
2242     {
2243         wxBusyCursor busy;
2244
2245         GetCdlConfig()->get_build_info(m_BuildInfo);
2246         if (NULL==CeCosTestPlatform::Get(strTarget))
2247         {
2248             wxString msg;
2249             msg.Printf(_("%s is not a recognized platform - do you wish to add it?"), (const wxChar*) strTarget);
2250             if (wxNO == wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_QUESTION|wxYES_NO))
2251                 return;
2252             
2253             ecPlatformEditorDialog dlg(wxGetApp().GetTopWindow());
2254             
2255             dlg.m_strPlatform = strTarget;
2256             dlg.m_strPrefix = GetCurrentTargetPrefix();
2257             dlg.m_strCaption=_("New Platform");
2258             if(wxID_CANCEL == dlg.ShowModal())
2259             {
2260                 return;
2261             }
2262             CeCosTestPlatform::Add(CeCosTestPlatform(dlg.m_strPlatform,dlg.m_strPrefix,dlg.m_strPrompt,dlg.m_strGDB,dlg.m_bServerSideGdb,dlg.m_strInferior));
2263             CeCosTestPlatform::Save();
2264         }
2265         
2266         nTests = GetTestExeNames(ar, arTestsMissing);
2267     }
2268
2269     const CeCosTestPlatform * etPlatform = CeCosTestPlatform::Get(strTarget);
2270     wxASSERT (NULL != etPlatform);
2271
2272     if (-1 != wxString (etPlatform->GdbCmds ()).Find (wxT("cyg_test_is_simulator=1")))
2273     {   // if a simulator target, disable 'reset hardware' message box
2274         wxGetApp().GetSettings().GetRunTestsSettings().m_nReset = RESET_NONE ;
2275     }
2276
2277     // TODO: I think the remote controls was something that wasn't quite implemented in the MFC tool.
2278     // It's in the properties dialog, but not used.
2279     // sheet.HideRemoteControls();
2280     if (arTestsMissing.Count() > 0)
2281     {
2282         wxString msg;
2283         msg.Printf(_("Not all tests are built. Do you wish to build them now?"));
2284         if (wxYES == wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_QUESTION|wxYES_NO))
2285         {
2286             wxGetApp().Build(wxT("tests"));
2287             return;
2288         }
2289     }
2290     wxString shellCommands;
2291     // Don't know why we passed TRUE (no build tools) but we need build tools for gdb
2292     if (wxGetApp().PrepareEnvironment(TRUE /* FALSE */, & shellCommands))
2293     {
2294         ecRunTestsDialog dialog(wxGetApp().GetTopWindow());
2295         int i;
2296         for ( i = 0 ; i < nTests; i++)
2297         {
2298             dialog.Populate(ar[i], TRUE);
2299         }
2300         for ( i = 0 ; i < arTestsMissing.Count(); i++)
2301         {
2302             dialog.Populate(arTestsMissing[i], FALSE);
2303         }
2304
2305         dialog.ShowModal();
2306     }
2307 }
2308
2309 // Rebuild the .hhc, .hhp, .hhk files and reinitialize the help controller
2310 bool ecConfigToolDoc::RebuildHelpIndex(bool force)
2311 {
2312     ecHtmlIndexer indexer(FALSE /* useRelativeURLs */ );
2313
2314     wxString docDir = GetRepository() ;
2315
2316     wxString projectFile;
2317     if (!indexer.IndexDocs(docDir, projectFile, force))
2318     {
2319         wxMessageBox("Sorry, could not index documentation.");
2320         return FALSE;
2321     }
2322     else
2323     {
2324         // Now we need to reset the help controller.
2325         wxGetApp().SetHelpFile(projectFile);
2326         wxGetApp().InitializeHelpController();
2327         return TRUE;
2328     }
2329 }
2330