]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/standalone/wxwin/configtool.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / configtool / standalone / wxwin / configtool.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 // configtool.cpp :
27 //
28 //===========================================================================
29 //#####DESCRIPTIONBEGIN####
30 //
31 // Author(s):   julians, jld
32 // Contact(s):  julians, jld
33 // Date:        2000/08/24
34 // Version:     $Id$
35 // Purpose:
36 // Description: Implementation file for the ConfigTool application 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 "configtool.h"
56 #endif
57
58 // Includes other headers for precompiled compilation
59 #include "ecpch.h"
60
61 #ifdef __BORLANDC__
62     #pragma hdrstop
63 #endif
64
65 #include "eCosSocket.h"
66 #include "eCosTestPlatform.h"
67
68 #include "wx/splash.h"
69 #include "wx/cshelp.h"
70 #include "wx/image.h"
71 #include "wx/filesys.h"
72 #include "wx/fs_zip.h"
73 #include "wx/config.h"
74 #include "wx/cmdline.h"
75 #include "wx/process.h"
76 #include "wx/mimetype.h"
77 #include "wx/txtstrm.h"
78 #include "wx/wfstream.h"
79 #include "wx/fs_mem.h"
80
81 #include "configtool.h"
82 #include "configtoolview.h"
83 #include "configtree.h"
84 #include "mainwin.h"
85 #include "outputwin.h"
86 #include "configtooldoc.h"
87 #include "aboutdlg.h"
88 #include "shortdescrwin.h"
89 #include "conflictwin.h"
90 #include "propertywin.h"
91 #include "symbols.h"
92 #include "build.hxx"
93 #include "Subprocess.h"
94
95 // ----------------------------------------------------------------------------
96 // resources
97 // ----------------------------------------------------------------------------
98 // the application icon
99 #if defined(__WXGTK__) || defined(__WXMOTIF__)
100     #include "bitmaps/configtool.xpm"
101 #endif
102
103 // Create a new application object.
104 IMPLEMENT_APP(ecApp)
105
106 BEGIN_EVENT_TABLE(ecApp, wxApp)
107 // Don't handle automatically, or it will bypass more specific processing.
108 //    EVT_MENU(ecID_WHATS_THIS, ecApp::OnWhatsThis)
109 END_EVENT_TABLE()
110
111 bool ecApp::sm_arMounted[26]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
112
113 static const wxCmdLineEntryDesc sg_cmdLineDesc[] =
114 {
115 /*
116     { wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" },
117     { wxCMD_LINE_SWITCH, "q", "quiet",   "be quiet" },
118
119     { wxCMD_LINE_OPTION, "o", "output",  "output file" },
120     { wxCMD_LINE_OPTION, "i", "input",   "input dir" },
121     { wxCMD_LINE_OPTION, "s", "size",    "output block size", wxCMD_LINE_VAL_NUMBER },
122     { wxCMD_LINE_OPTION, "d", "date",    "output file date", wxCMD_LINE_VAL_DATE },
123 */
124     { wxCMD_LINE_SWITCH, "h", "help",   "displays help on the command line parameters" },
125     { wxCMD_LINE_SWITCH, "e", "edit-only",    "edit save file only" },
126     { wxCMD_LINE_SWITCH, "v", "version",    "print version" },
127     { wxCMD_LINE_SWITCH, "c", "compile-help",    "compile online help only" },
128
129     { wxCMD_LINE_PARAM,  NULL, NULL, "input file 1", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
130     { wxCMD_LINE_PARAM,  NULL, NULL, "input file 2", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
131
132     { wxCMD_LINE_NONE }
133 };
134
135 ecApp::ecApp()
136 {
137     m_docManager = NULL;
138     m_mainFrame = NULL;
139     m_currentDoc = NULL;
140     m_whatsThisMenu = new wxMenu;
141     m_whatsThisMenu->Append(ecID_WHATS_THIS, _("&What's This?"));
142     m_helpFile = wxEmptyString;
143     m_splashScreen = NULL;
144     m_pipedProcess = NULL;
145     m_valuesLocked = 0;
146     m_helpController = NULL;
147     m_fileSystem = new wxFileSystem;
148 #if wxUSE_STREAMS && wxUSE_ZIPSTREAM && wxUSE_ZLIB
149     m_zipHandler = new wxZipFSHandler;
150 #endif
151 }
152
153 ecApp::~ecApp()
154 {
155     delete m_whatsThisMenu;
156     delete m_fileSystem;
157 }
158
159 // 'Main program' equivalent: the program execution "starts" here
160 bool ecApp::OnInit()
161 {
162     wxLog::SetTimestamp(NULL);
163
164     wxHelpProvider::Set(new wxSimpleHelpProvider);
165     //wxHelpProvider::Set(new wxHelpControllerHelpProvider(& m_helpController));
166
167     wxImage::AddHandler(new wxPNGHandler);
168     wxImage::AddHandler(new wxGIFHandler);
169
170     // Required for advanced HTML help
171 #if wxUSE_STREAMS && wxUSE_ZIPSTREAM && wxUSE_ZLIB
172     wxFileSystem::AddHandler(m_zipHandler);
173 #endif
174
175     // Mandatory initialisation for Tcl 8.4
176     Tcl_FindExecutable(argv[0]);
177
178     wxString currentDir = wxGetCwd();
179
180     // Use argv to get current app directory
181     m_appDir = wxFindAppPath(argv[0], currentDir, wxT("CONFIGTOOLDIR"));
182     
183     // If the development version, go up a directory.
184 #ifdef __WXMSW__
185     if ((m_appDir.Right(5).CmpNoCase("DEBUG") == 0) ||
186         (m_appDir.Right(11).CmpNoCase("DEBUGSTABLE") == 0) ||
187         (m_appDir.Right(7).CmpNoCase("RELEASE") == 0) ||
188         (m_appDir.Right(13).CmpNoCase("RELEASESTABLE") == 0)
189         )
190         m_appDir = wxPathOnly(m_appDir);
191 #endif
192
193 // Install default platform definitions if no platforms defined
194 #ifdef __WXMSW__
195     wxConfig config (wxGetApp().GetSettings().GetConfigAppName());
196     if (! config.Exists (wxT("Platforms")))
197     {
198         wxFileName platforms (m_appDir, wxT("platforms.reg"));
199         platforms.Normalize();
200         if (platforms.FileExists())
201             wxExecute (wxT("regedit /s \"") + platforms.GetFullPath() + wxT("\""), wxEXEC_SYNC);
202     }
203 #endif
204 #ifdef __WXGTK__
205     wxFileName config (wxFileName::GetHomeDir(), wxEmptyString);
206     config.AppendDir(wxT(".eCosPlatforms"));
207     if (! config.DirExists())
208     {
209         wxFileName platforms (m_appDir, wxT("platforms.tar"));
210         platforms.Normalize();
211         if (platforms.FileExists())
212             wxExecute (wxT("tar -C ") + wxFileName::GetHomeDir() + wxT(" -xf ") + platforms.GetFullPath(), wxEXEC_SYNC);
213     }
214 #endif
215
216     CeCosSocket::Init();
217     CeCosTestPlatform::Load();
218
219     // Load resources from binary resources archive, or failing that, from
220     // Windows resources or plain files
221     LoadResources();
222
223     wxGetEnv(wxT("PATH"), & m_strOriginalPath);
224
225     // Create a document manager
226     m_docManager = new wxDocManager;
227
228     // Create a template relating documents to their views
229     wxDocTemplate* templ = new wxDocTemplate(m_docManager, "Configtool", "*.ecc", "", "ecc", "Configtool Doc", "Configtool View",
230         CLASSINFO(ecConfigToolDoc), CLASSINFO(ecConfigToolView));
231
232     // If we've only got one window, we only get to edit
233     // one document at a time.
234     m_docManager->SetMaxDocsOpen(1);
235     
236     // Initialize config settings
237     m_settings.Init();
238
239     // Let wxWindows know what the app name is
240     SetAppName(m_settings.GetAppName());
241
242     InitializeWindowSettings(TRUE /* beforeWindowConstruction */) ;
243
244     // Load config settings
245     m_settings.LoadConfig();
246
247     // Set the default directory for opening/saving files
248     if (!m_settings.m_lastFilename.IsEmpty())
249         templ->SetDirectory(wxPathOnly(m_settings.m_lastFilename));
250
251     // Parse the command-line parameters and options
252     wxCmdLineParser parser(sg_cmdLineDesc, argc, argv);
253     int res;
254     {
255         wxLogNull log;
256         res = parser.Parse();
257     }
258     if (res == -1 || res > 0 || parser.Found(wxT("h")))
259     {
260 #ifdef __WXGTK__
261         wxLog::SetActiveTarget(new wxLogStderr);
262 #endif
263         parser.Usage();
264         return FALSE;
265     }
266     if (parser.Found(wxT("v")))
267     {
268 #ifdef __WXGTK__
269         wxLog::SetActiveTarget(new wxLogStderr);
270 #endif
271         wxString msg;
272         msg.Printf(wxT("eCos Configuration Tool (c) Red Hat, 2001 Version %s, %s"), ecCONFIGURATION_TOOL_VERSION, __DATE__);
273         wxLogMessage(msg);
274         return FALSE;
275     }
276
277 /*
278 #ifdef __WXMSW__
279     wxBitmap bitmap(wxBITMAP(splash));
280 #else
281     wxBitmap bitmap;
282     if (wxFileExists("splash16.png"))
283         bitmap.LoadFile("splash16.png", wxBITMAP_TYPE_PNG);
284 #endif
285 */
286
287     //    wxYieldIfNeeded();
288
289     // create the main application window
290     ecMainFrame *frame = new ecMainFrame(m_docManager, GetSettings().GetAppName(),
291         wxPoint(GetSettings().m_frameSize.x, GetSettings().m_frameSize.y),
292         wxSize(GetSettings().m_frameSize.width, GetSettings().m_frameSize.height));
293
294     m_mainFrame = frame;
295     SetTopWindow(frame);
296     frame->Show(TRUE);
297     SendIdleEvents(); // Otherwise UI updates aren't done, because it's busy loading the repository
298 #ifdef __WXMSW__
299     ::UpdateWindow((HWND) frame->GetHWND());
300 #endif
301
302     InitializeWindowSettings(FALSE /* beforeWindowConstruction */) ;
303
304     if (m_splashScreenBitmap.Ok() && GetSettings().m_showSplashScreen)
305     {
306         m_splashScreen = new ecSplashScreen(m_splashScreenBitmap, wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT,
307             5000, NULL, -1, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxFRAME_FLOAT_ON_PARENT|wxSTAY_ON_TOP);
308     }
309
310     //    if (m_splashScreen)
311     //        m_splashScreen->Raise();
312
313     wxYieldIfNeeded();
314
315     if (parser.Found(wxT("e")))
316         GetSettings().m_editSaveFileOnly = TRUE;
317
318     // If in --compile-help (-c) mode, then exit immediately after recompiling help file
319     bool compileHelpOnly = parser.Found(wxT("c"));
320
321     wxString filenameToOpen1, filenameToOpen2;
322     if (parser.GetParamCount() > 0)
323     {
324         wxString tmpSaveFile;
325
326         filenameToOpen1 = parser.GetParam(0);
327
328         if (parser.GetParamCount() > 1)
329             filenameToOpen2 = parser.GetParam(1);
330
331         bool gotRepository = FALSE;
332         bool gotSavefile = FALSE;
333
334         wxString repositoryDir, saveFile;
335
336         // Might be e.g. . or .. in path, or relative path
337         filenameToOpen1 = wxGetRealPath(currentDir, filenameToOpen1);
338
339         if (parser.GetParamCount() > 1)
340             filenameToOpen2 = wxGetRealPath(currentDir, filenameToOpen2);
341
342         wxString path1, name1, ext1;
343         wxSplitPath(filenameToOpen1, & path1, & name1, & ext1);
344
345         wxString path2, name2, ext2;
346         wxSplitPath(filenameToOpen2, & path2, & name2, & ext2);
347
348         // Look at the first file
349         if (ext1 == "ecc" || ext1 == "ECC")
350         {
351             if (wxFileExists(filenameToOpen1))
352             {
353                 gotSavefile = TRUE;
354                 saveFile = filenameToOpen1;
355             }
356             else
357             {
358                 wxString msg;
359                 msg.Printf("%s is not a valid file.", (const wxChar*) filenameToOpen1);
360                 wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
361                 return FALSE;
362             }
363         }
364         else if (wxDirExists(filenameToOpen1) && FindSaveFileInDir(filenameToOpen1, tmpSaveFile))
365         {
366             saveFile = tmpSaveFile;
367             gotSavefile = TRUE;
368         }
369         else if ((name1 == wxT("ecos") && ext1 == wxT("db") && wxFileExists(filenameToOpen1)) || wxDirExists(filenameToOpen1))
370         {
371             // It's a repository (we hope).
372             if (name1 == wxT("ecos") && ext1 == wxT("db"))
373             {
374                 // Go two steps up
375                 filenameToOpen1 = wxPathOnly(filenameToOpen1);
376                 filenameToOpen1 = wxPathOnly(filenameToOpen1);
377             }
378             else
379             {
380                 // If it's the packages directory, we need to strip off
381                 // a directory
382                 wxString eccPath(filenameToOpen1 + wxString(wxFILE_SEP_PATH) + wxT("ecc"));
383
384                 // Don't strip off ecc if it's the CVS repository (with ecc below it)
385                 if (name1 == wxT("packages") || (name1 == wxT("ecc") && !wxDirExists(eccPath)))
386                     filenameToOpen1 = wxPathOnly(filenameToOpen1);
387             }
388
389             repositoryDir = filenameToOpen1;
390             gotRepository = TRUE;
391         }
392         else
393         {
394             wxString msg;
395             msg.Printf("%s is neither a project file nor a valid repository.", (const wxChar*) filenameToOpen1);
396             wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
397             return FALSE;
398         }
399
400         // Look at the second file, if any
401         if (parser.GetParamCount() > 1)
402         {
403             if (ext2 == "ecc" || ext2 == "ECC")
404             {
405                 if (wxFileExists(filenameToOpen2))
406                 {
407                     if (gotSavefile)
408                     {
409                         wxString msg;
410                         msg.Printf("%s is a second save file -- please supply only one.", (const wxChar*) filenameToOpen2);
411                         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
412                         return FALSE;
413                     }
414                     
415                     gotSavefile = TRUE;
416                     saveFile = filenameToOpen2;
417                 }
418                 else
419                 {
420                     wxString msg;
421                     msg.Printf("%s is not a valid file.", (const wxChar*) filenameToOpen2);
422                     wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
423                     return FALSE;
424                 }
425             }
426             else if (!gotSavefile && wxDirExists(filenameToOpen2) && FindSaveFileInDir(filenameToOpen2, tmpSaveFile))
427             {
428                 saveFile = tmpSaveFile;
429                 gotSavefile = TRUE;
430             }
431             else if ((name2 == wxT("ecos") && ext2 == wxT("db") && wxFileExists(filenameToOpen2)) || wxDirExists(filenameToOpen2))
432             {
433                 if (gotRepository)
434                 {
435                     wxString msg;
436                     msg.Printf("%s is a second repository -- please supply only one.", (const wxChar*) filenameToOpen2);
437                     wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
438                     return FALSE;
439                 }           
440                 
441                 // It's a repository (we hope).
442                 if (name1 == wxT("ecos") && ext1 == wxT("db"))
443                 {
444                     // Go two steps up
445                     filenameToOpen2 = wxPathOnly(filenameToOpen2);
446                     filenameToOpen2 = wxPathOnly(filenameToOpen2);
447                 }
448                 else
449                 {
450                     // If it's the packages directory, we need to strip off
451                     // a directory
452                     wxString eccPath(filenameToOpen2 + wxString(wxFILE_SEP_PATH) + wxT("ecc"));
453                     
454                     // Don't strip off ecc if it's the CVS repository (with ecc below it)
455                     if (name2 == wxT("packages") || (name2 == wxT("ecc") && !wxDirExists(eccPath)))
456                         filenameToOpen2 = wxPathOnly(filenameToOpen2);
457                 }
458                 
459                 repositoryDir = filenameToOpen2;
460                 gotRepository = TRUE;
461             }
462             else
463             {
464                 wxString msg;
465                 msg.Printf("%s is neither a project file nor a valid repository.", (const wxChar*) filenameToOpen2);
466                 wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
467                 return FALSE;
468             }
469         }
470         
471         // Now we have looked at the two files and decided what they are; let's
472         // act on it.
473
474         if (gotRepository)
475         {
476             GetSettings().m_strRepository = repositoryDir;
477         }
478
479         if (!gotSavefile)
480         {
481             // See if there's a save file in the current dir
482             if (FindSaveFileInDir(currentDir, saveFile))
483                 gotSavefile = TRUE;
484         }
485
486         if (gotSavefile)
487         {
488             // The repository will be loaded from m_strRepository, possibly set above.
489             m_docManager->CreateDocument(saveFile, wxDOC_SILENT);
490         }
491         else
492         {
493             // Create a new file
494             m_docManager->CreateDocument(wxString(""), wxDOC_NEW);
495         }
496
497         if (compileHelpOnly)
498         {
499             if (!gotRepository)
500             {
501                 wxString msg;
502                 msg.Printf(wxT("Please specify a repository when using the --compile-help option."));
503                 wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
504                 return FALSE;
505             }
506             ecConfigToolDoc* doc = wxGetApp().GetConfigToolDoc();
507             if (doc)
508             {
509                 if (!doc->RebuildHelpIndex(TRUE))
510                 {
511                     wxString msg;
512                     msg.Printf(wxT("Sorry, there was a problem compiling the help index."));
513                     wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
514                     return FALSE;
515                 }
516             }
517             else
518             {
519                 wxString msg;
520                 msg.Printf(wxT("Sorry, there was no current document when compiling the help index."));
521                 wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
522                 return FALSE;
523             }
524
525             // Return FALSE in order to quit the application
526             return FALSE;
527         }
528     }
529     else
530     {
531         if (GetSettings().m_strRepository.IsEmpty()) // first invocation by this user
532         {
533             // we have no clues as to the location of the repository so
534             // test for ../../packages relative to the configtool location
535             wxFileName repository = wxFileName (m_appDir, wxEmptyString);
536             repository.Normalize(); // remove trailing "./" if present
537             repository.RemoveDir (repository.GetDirCount()-1);
538             repository.RemoveDir (repository.GetDirCount()-1);
539             repository.AppendDir (wxT("packages"));
540             if (repository.DirExists()) // we've found a repository
541             {
542                 repository.RemoveDir (repository.GetDirCount()-1);
543                 GetSettings().m_strRepository = repository.GetFullPath();
544             }
545         }
546         m_docManager->CreateDocument(wxString(""), wxDOC_NEW);
547     }
548
549     return TRUE;
550 }
551
552 // Load resources from disk
553 bool ecApp::LoadResources()
554 {
555     wxFileSystem::AddHandler(new wxMemoryFSHandler);
556
557 //    LoadBitmapResource(m_splashScreenBitmap, wxT("splash16.png"), wxBITMAP_TYPE_PNG, FALSE);
558
559 //    wxBitmap bitmap1, bitmap2, bitmap3;
560 //    LoadBitmapResource(bitmap1, wxT("ecoslogo.png"), wxBITMAP_TYPE_PNG, TRUE);
561 //    LoadBitmapResource(bitmap2, wxT("ecoslogosmall.png"), wxBITMAP_TYPE_PNG, TRUE);
562 //    LoadBitmapResource(bitmap3, wxT("rhlogo.png"), wxBITMAP_TYPE_PNG, TRUE);
563
564 //    wxString aboutText;
565 //    LoadTextResource(aboutText, wxT("about.htm"), TRUE);
566
567 //    VersionStampSplashScreen();
568
569     return TRUE;
570 }
571
572 // Load resources from zip resource file or disk
573 bool ecApp::LoadBitmapResource(wxBitmap& bitmap, const wxString& filename, int bitmapType, bool addToMemoryFS)
574 {
575     wxString archive(GetFullAppPath(wxT("configtool.bin")));
576
577 #if wxUSE_STREAMS && wxUSE_ZIPSTREAM && wxUSE_ZLIB
578     wxFSFile* file = m_fileSystem->OpenFile(archive + wxString(wxT("#zip:")) + filename);
579     if (file)
580     {
581         wxInputStream* stream = file->GetStream();
582         
583         wxImage image(* stream, bitmapType);
584         bitmap = image.ConvertToBitmap();
585         
586         delete file;
587     }
588 #endif
589
590 #ifdef __WXMSW__
591     if (!bitmap.Ok())
592         bitmap.LoadFile(filename, wxBITMAP_TYPE_BMP_RESOURCE);
593 #endif
594
595     if (!bitmap.Ok() && wxFileExists(GetFullAppPath(filename)))
596         bitmap.LoadFile(GetFullAppPath(filename), bitmapType);
597
598
599     if (bitmap.Ok() && addToMemoryFS)
600         wxMemoryFSHandler::AddFile(filename, bitmap, bitmapType);
601
602     return bitmap.Ok();
603 }
604
605 // Load resources from zip resource file or disk
606 bool ecApp::LoadTextResource(wxString& text, const wxString& filename, bool addToMemoryFS)
607 {
608     wxString archive(GetFullAppPath(wxT("configtool.bin")));
609
610     bool success = FALSE;
611
612 #if wxUSE_STREAMS && wxUSE_ZIPSTREAM && wxUSE_ZLIB
613     wxFSFile* file = m_fileSystem->OpenFile(archive + wxString(wxT("#zip:")) + filename);
614     if (file)
615     {
616         wxInputStream* stream = file->GetStream();
617
618         char* buf = text.GetWriteBuf(stream->GetSize() + 1);
619         stream->Read((void*) buf, stream->GetSize());
620         buf[stream->GetSize()] = 0;
621         text.UngetWriteBuf();
622
623         success = TRUE;
624         
625         delete file;
626     }
627 #endif
628
629     if (!success && wxFileExists(GetFullAppPath(filename)))
630     {
631         wxFileInputStream str(GetFullAppPath(filename));
632
633         char* buf = text.GetWriteBuf(str.GetSize() + 1);
634         str.Read((void*) buf, str.GetSize());
635         buf[str.GetSize()] = 0;
636         text.UngetWriteBuf();
637
638         success = TRUE;
639     }
640
641     if (success && addToMemoryFS)
642         wxMemoryFSHandler::AddFile(filename, text);
643
644     return success;
645 }
646
647 // Get a text resource from the memory filesystem
648 bool ecApp::GetMemoryTextResource(const wxString& filename, wxString& text)
649 {
650     wxString s(wxString(wxT("memory:")) + filename);
651     wxFSFile* file = wxGetApp().GetFileSystem()->OpenFile(s);
652     if (file)
653     {
654         wxInputStream* stream = file->GetStream();
655
656         char* buf = text.GetWriteBuf(stream->GetSize() + 1);
657         stream->Read((void*) buf, stream->GetSize());
658         buf[stream->GetSize()] = 0;
659         text.UngetWriteBuf();
660
661         delete file;
662         return TRUE;
663     }
664     else
665         return FALSE;
666 }
667
668 // Version-stamp the splash screen
669 bool ecApp::VersionStampSplashScreen()
670 {
671     if (m_splashScreenBitmap.Ok())
672     {
673         wxMemoryDC dc;
674         dc.SelectObject(m_splashScreenBitmap);
675
676         wxColour textColour(19, 49, 4);
677         dc.SetTextForeground(textColour);
678         dc.SetBackgroundMode(wxTRANSPARENT);
679         dc.SetFont(wxFont(11, wxSWISS, wxNORMAL, wxBOLD, FALSE));
680
681         // Bottom left of area to start drawing at
682
683         wxString verString;
684         verString.Printf("%s", ecCONFIGURATION_TOOL_VERSION);
685
686         int x = 339; int y = 231;
687 #ifdef __WXMSW__
688         y += 5; // For some reason
689 #endif
690         int w, h;
691         dc.GetTextExtent(verString, & w, & h);
692         dc.DrawText(verString, x, y - h);
693
694         dc.SelectObject(wxNullBitmap);
695
696         return TRUE;
697     }
698     else
699         return FALSE;
700 }
701
702 // Initialize window settings object
703 bool ecApp::InitializeWindowSettings(bool beforeWindowConstruction)
704 {
705     wxWindowSettings& settings = GetSettings().m_windowSettings;
706     ecMainFrame* frame = GetMainFrame();
707
708     if (beforeWindowConstruction)
709     {
710         settings.Add(wxT("Configuration"));       
711         settings.Add(wxT("Short Description"));
712         settings.Add(wxT("Output"));
713         settings.Add(wxT("Properties"));
714         settings.Add(wxT("Conflicts"));
715     }
716     else
717     {
718         wxArrayPtrVoid arr;
719         arr.Add(frame->GetTreeCtrl());
720         arr.Add(frame->GetValueWindow());
721         settings.SetWindows(wxT("Configuration"), arr);
722
723         settings.SetWindow(wxT("Short Description"), frame->GetShortDescriptionWindow());
724         settings.SetWindow(wxT("Output"), frame->GetOutputWindow());
725         settings.SetWindow(wxT("Properties"), frame->GetPropertyListWindow());
726         settings.SetWindow(wxT("Conflicts"), frame->GetConflictsWindow());
727     }
728
729     return TRUE;
730 }
731
732
733 bool ecApp::InitializeHelpController()
734 {
735     if (m_helpController)
736         delete m_helpController;
737     m_helpController = new wxHelpController;
738
739     if (!m_helpController->Initialize(GetHelpFile()))
740     {
741         // TODO
742         return FALSE;
743     }
744     else
745     {
746         // Tell the help controller where the repository documentation is.
747         // For now, just keep this to myself since it uses hacks to wxWin
748         ecConfigToolDoc* doc = GetConfigToolDoc();
749
750         // No longer using relative paths
751 #if 0
752         if (doc)
753         {
754             wxString htmlDir = wxString(doc->GetRepository()) + wxString(wxT("/doc/html"));
755             if (!wxDirExists(htmlDir))
756                 htmlDir = wxString(doc->GetRepository()) + wxString(wxT("/doc"));
757
758             htmlDir += wxString(wxT("/"));
759
760             wxGetApp().GetHelpController().SetBookBasePath(htmlDir);
761         }
762 #endif
763         return TRUE;
764     }
765 }
766
767 // Check if there is a (unique) .ecc file in dir
768 bool ecApp::FindSaveFileInDir(const wxString& dir, wxString& saveFile)
769 {
770     wxDir fileFind;
771     
772     if (!fileFind.Open(dir))
773         return FALSE;
774     
775     wxString wildcard = wxT(".ecc");   
776     wxString filename;
777
778     bool found = fileFind.GetFirst (& filename, wildcard);
779     if (found)
780     {
781         // Fail if there was more than one matching file.
782         wxString filename2;
783         if (fileFind.GetNext (& filename2))
784             return FALSE;
785         else
786         {
787             saveFile = dir + wxString(wxFILE_SEP_PATH) + filename;
788             return TRUE;
789         }
790     }
791     return FALSE;
792 }
793
794 int ecApp::OnExit(void)
795 {
796 /*
797     if (m_helpController)
798     {
799         delete m_helpController;
800         m_helpController = NULL;
801     }
802 */
803
804     if (m_splashScreen)
805     {
806         m_splashScreen->Destroy();
807         m_splashScreen = NULL;
808     }
809
810     m_settings.SaveConfig();
811
812     {
813         wxConfig config(wxGetApp().GetSettings().GetConfigAppName());
814         if (config.HasGroup(wxT("FileHistory")))
815             config.DeleteGroup(wxT("FileHistory"));
816         config.SetPath(wxT("FileHistory/"));
817         m_docManager->FileHistorySave(config);
818     }
819
820     delete m_docManager;
821
822     return 0;
823 }
824
825 // Prepend the current program directory to the name
826 wxString ecApp::GetFullAppPath(const wxString& filename) const
827 {
828     wxString path(m_appDir);
829     if (path.Last() != '\\' && path.Last() != '/' && filename[0] != '\\' && filename[0] != '/')
830 #ifdef __WXGTK__
831         path += '/';
832 #else
833         path += '\\';
834 #endif
835     path += filename;
836     
837     return path;
838 }
839
840 // Are we running in 32K colours or more?
841 bool ecApp::GetHiColour() const
842 {
843     static bool hiColour = (wxDisplayDepth() >= 16) ;
844     return hiColour;
845 }
846
847 // General handler for 'What's this?'
848 void ecApp::OnWhatsThis(wxCommandEvent& event)
849 {
850     wxObject* obj = event.GetEventObject();
851     wxWindow* win = NULL;
852
853     if (obj->IsKindOf(CLASSINFO(wxMenu)))
854     {
855         win = ((wxMenu*) obj)->GetInvokingWindow();
856     }
857     else if (obj->IsKindOf(CLASSINFO(wxWindow)))
858     {
859         win = (wxWindow*) obj;
860     }
861
862     wxWindow* subjectOfHelp = win;
863     bool eventProcessed = FALSE;
864     wxPoint pt = wxGetMousePosition();
865
866     while (subjectOfHelp && !eventProcessed)
867     {
868         wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), pt) ;
869         helpEvent.SetEventObject(this);
870         eventProcessed = win->GetEventHandler()->ProcessEvent(helpEvent);
871         
872         // Go up the window hierarchy until the event is handled (or not).
873         // I.e. keep submitting ancestor windows until one is recognised
874         // by the app code that processes the ids and displays help.
875         subjectOfHelp = subjectOfHelp->GetParent();
876     }
877     // wxGetApp().GetHelpController().DisplayTextPopup(GetHelpText(), wxGetMousePosition());
878 }
879
880 // Log to output window
881 void ecApp::Log(const wxString& msg)
882 {
883     ecMainFrame* frame = (ecMainFrame*) GetTopWindow();
884     if (frame)
885     {
886         frame->GetOutputWindow()->AppendText(msg /* + wxT("\n") */ );
887         if ((msg == wxEmptyString) || (msg.Last() != wxT('\n')))
888             frame->GetOutputWindow()->AppendText(wxT("\n"));
889
890 //        frame->GetOutputWindow()->ShowPosition(frame->GetOutputWindow()->GetLastPosition());
891     }
892 }
893
894 void ecApp::SetStatusText(const wxString& text, bool clearFailingRulesPane)
895 {
896     ecMainFrame* mainFrame = GetMainFrame();
897     if(mainFrame)
898     {
899         mainFrame->GetStatusBar()->SetStatusText(text, ecStatusPane);
900         if (clearFailingRulesPane)
901             mainFrame->GetStatusBar()->SetStatusText(wxT(""), ecFailRulePane);
902 #ifdef __WXMSW__
903         ::UpdateWindow((HWND) mainFrame->GetHWND());
904         //wxYield();
905 #endif
906     }
907 }
908
909 // Config tree control
910 ecConfigTreeCtrl* ecApp::GetTreeCtrl() const
911 {
912     return GetMainFrame()->GetTreeCtrl();
913 }
914
915 // MLT window
916 ecMemoryLayoutWindow* ecApp::GetMLTWindow() const
917 {
918     return GetMainFrame()->GetMemoryLayoutWindow();
919 }
920
921 // Get active document
922 ecConfigToolDoc* ecApp::GetConfigToolDoc() const
923 {
924     if (m_currentDoc)
925         return m_currentDoc;
926
927     if (!m_docManager)
928         return NULL;
929
930     return wxDynamicCast(m_docManager->GetCurrentDocument(), ecConfigToolDoc);
931 }
932
933 bool ecApp::Launch(const wxString & strFileName,const wxString &strViewer)
934 {
935     bool ok = FALSE;
936     wxString cmd;
937
938     if (!strViewer.IsEmpty())
939     {
940         cmd = strViewer + wxString(wxT(" ")) + strFileName ;
941     }
942     else
943     {
944         wxString path, filename, ext;
945         wxSplitPath(strFileName, & path, & filename, & ext);
946         
947         wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(ext);
948         if ( !ft )
949         {
950             wxLogError(_T("Impossible to determine the file type for extension '%s'"),
951                 ext.c_str());
952             return FALSE;
953         }
954
955         bool ok = ft->GetOpenCommand(&cmd,
956             wxFileType::MessageParameters(strFileName, _T("")));
957         delete ft;
958         
959         if (!ok)
960         {
961             // TODO: some kind of configuration dialog here.
962             wxMessageBox(_("Could not determine the command for opening this file."),
963                 wxGetApp().GetSettings().GetAppName(), wxOK|wxICON_EXCLAMATION);
964             return FALSE;
965         }
966     }        
967
968     ok = (wxExecute(cmd, FALSE) != 0);
969     
970     return ok;
971
972 #if 0    
973     bool rc=false;
974     
975     if(!strViewer.IsEmpty())//use custom editor
976     {
977         CString strCmdline(strViewer);
978         
979         TCHAR *pszCmdLine=strCmdline.GetBuffer(strCmdline.GetLength());
980         GetShortPathName(pszCmdLine,pszCmdLine,strCmdline.GetLength());
981         strCmdline.ReleaseBuffer();
982         
983         strCmdline+=_TCHAR(' ');
984         strCmdline+=strFileName;
985         PROCESS_INFORMATION pi;
986         STARTUPINFO si;
987         
988         si.cb = sizeof(STARTUPINFO); 
989         si.lpReserved = NULL; 
990         si.lpReserved2 = NULL; 
991         si.cbReserved2 = 0; 
992         si.lpDesktop = NULL; 
993         si.dwFlags = 0; 
994         si.lpTitle=NULL;
995         
996         if(CreateProcess(
997             NULL, // app name
998             //strCmdline.GetBuffer(strCmdline.GetLength()),    // command line
999             strCmdline.GetBuffer(strCmdline.GetLength()),    // command line
1000             NULL, // process security
1001             NULL, // thread security
1002             TRUE, // inherit handles
1003             0,
1004             NULL, // environment
1005             NULL, // current dir
1006             &si, // startup info
1007             &pi)){
1008             CloseHandle(pi.hProcess);
1009             CloseHandle(pi.hThread);
1010             rc=true;
1011         } else {
1012             CUtils::MessageBoxF(_T("Failed to invoke %s.\n"),strCmdline);
1013         }
1014         strCmdline.ReleaseBuffer();
1015     } else {// Use association
1016         TCHAR szExe[MAX_PATH];
1017         HINSTANCE h=FindExecutable(strFileName,_T("."),szExe);
1018         if(int(h)<=32){
1019             CString str;
1020             switch(int(h)){
1021             case 0:  str=_T("The system is out of memory or resources.");break;
1022             case 31: str=_T("There is no association for the specified file type.");break;
1023             case ERROR_FILE_NOT_FOUND: str=_T("The specified file was not found.");break;
1024             case ERROR_PATH_NOT_FOUND: str=_T("The specified path was not found.");break;
1025             case ERROR_BAD_FORMAT:     str=_T("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).");break;
1026             default: break;
1027             }
1028             CUtils::MessageBoxF(_T("Failed to open document %s.\r\n%s"),strFileName,str);
1029         } else {
1030             
1031             SHELLEXECUTEINFO sei = {sizeof(sei), 0, AfxGetMainWnd()->GetSafeHwnd(), _T("open"),
1032                 strFileName, NULL, NULL, SW_SHOWNORMAL, AfxGetInstanceHandle( )};
1033             
1034             sei.hInstApp=0;
1035             HINSTANCE hInst=ShellExecute(AfxGetMainWnd()->GetSafeHwnd(),_T("open"), strFileName, NULL, _T("."), 0)/*ShellExecuteEx(&sei)*/;
1036             if(int(hInst)<=32/*sei.hInstApp==0*/)
1037             {
1038                 CString str;
1039                 switch(int(hInst))
1040                 {
1041                 case 0 : str=_T("The operating system is out of memory or resources. ");break;
1042                 case ERROR_FILE_NOT_FOUND : str=_T("The specified file was not found. ");break;
1043                 case ERROR_PATH_NOT_FOUND : str=_T("The specified path was not found. ");break;
1044                 case ERROR_BAD_FORMAT : str=_T("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image). ");break;
1045                 case SE_ERR_ACCESSDENIED : str=_T("The operating system denied access to the specified file. ");break;
1046                 case SE_ERR_ASSOCINCOMPLETE : str=_T("The filename association is incomplete or invalid. ");break;
1047                 case SE_ERR_DDEBUSY : str=_T("The DDE transaction could not be completed because other DDE transactions were being processed. ");break;
1048                 case SE_ERR_DDEFAIL : str=_T("The DDE transaction failed. ");break;
1049                 case SE_ERR_DDETIMEOUT : str=_T("The DDE transaction could not be completed because the request timed out. ");break;
1050                 case SE_ERR_DLLNOTFOUND : str=_T("The specified dynamic-link library was not found. ");break;
1051                     //case SE_ERR_FNF : str=_T("The specified file was not found. ");break;
1052                 case SE_ERR_NOASSOC : str=_T("There is no application associated with the given filename extension. ");break;
1053                 case SE_ERR_OOM : str=_T("There was not enough memory to complete the operation. ");break;
1054                     //case SE_ERR_PNF : str=_T("The specified path was not found. ");break;
1055                 case SE_ERR_SHARE : str=_T("A sharing violation occurred. ");break;
1056                 default: str=_T("An unexpected error occurred");break;
1057                 }
1058                 CUtils::MessageBoxF(_T("Failed to open document %s using %s.\r\n%s"),strFileName,szExe,str);
1059             } else {
1060                 rc=true;
1061             }
1062         }
1063     }
1064     return rc;
1065 #endif
1066 }
1067
1068 bool ecApp::PrepareEnvironment(bool bWithBuildTools, wxString* cmdLine)
1069 {
1070 #ifdef __WXMSW__
1071     // Under Windows we can set variables.
1072     ecConfigToolDoc *pDoc = GetConfigToolDoc();
1073     
1074     wxSetEnv(wxT("PATH"), m_strOriginalPath);
1075     
1076     const wxString strPrefix(pDoc->GetCurrentTargetPrefix());
1077     ecFileName strBinDir;
1078     bool rc = FALSE;
1079
1080     rc=(! bWithBuildTools) || GetSettings().m_arstrBinDirs.Find(strPrefix, strBinDir);
1081     if(!rc)
1082     {
1083         // Use fallback of previously-entered build tools directory, if available
1084         if (!GetSettings().m_buildToolsDir.IsEmpty())
1085         {
1086             strBinDir = GetSettings().m_buildToolsDir ;
1087             rc = TRUE;
1088         }
1089         else
1090         {
1091             wxCommandEvent event;
1092             GetMainFrame()->OnBuildToolsPath(event);
1093             rc = GetSettings().m_arstrBinDirs.Find(strPrefix, strBinDir);
1094         }
1095     }
1096     
1097     if (rc)
1098     {
1099         ecFileName strUserBinDir(GetSettings().m_userToolsDir);
1100         if(strUserBinDir.IsEmpty())
1101         {
1102             if ( 1 == GetSettings().m_userToolPaths.GetCount() )
1103             {
1104                 GetSettings().m_userToolsDir = GetSettings().m_userToolPaths[0];
1105             } else
1106             {
1107                 wxCommandEvent event;
1108                 GetMainFrame()->OnUserToolsPath(event);
1109             }
1110             strUserBinDir = GetSettings().m_userToolsDir;
1111         }
1112         if ( !strUserBinDir.IsEmpty() )
1113         {
1114             // calculate the directory of the host tools from this application's module name
1115             ecFileName strHostToolsBinDir(this->argv[0]);
1116             strHostToolsBinDir = strHostToolsBinDir.Head ();
1117             
1118             // tools directories are in the order host-tools, user-tools, comp-tools, install/bin (if present), contrib-tools (if present) on the path
1119             const ecFileName strContribBinDir(strUserBinDir, wxT("..\\contrib\\bin"));
1120             ecFileName strUsrBinDir(strUserBinDir, wxT("..\\usr\\bin"));
1121             const ecFileName strInstallBinDir(pDoc->GetInstallTree (), wxT("bin"));
1122
1123             // In case strUserBinDir is e.g. c:\program files\red hat\cygwin-00r1\usertools\h-i686-pc-cygwin\bin
1124             if (!strUsrBinDir.IsDir ())
1125                 strUsrBinDir = ecFileName(strUserBinDir + _T("..\\..\\..\\H-i686-pc-cygwin\\bin"));
1126
1127             if (
1128                 (strUsrBinDir.IsDir ()     && ! ecUtils::AddToPath (strUsrBinDir)) || 
1129                 (strContribBinDir.IsDir () && ! ecUtils::AddToPath (strContribBinDir)) || 
1130                 (strInstallBinDir.IsDir () && ! ecUtils::AddToPath (strInstallBinDir)) || 
1131                 (bWithBuildTools && ! ecUtils::AddToPath (strBinDir)) || 
1132                 ! ecUtils::AddToPath (strUserBinDir) || 
1133                 ! ecUtils::AddToPath (strHostToolsBinDir))
1134             {
1135                 wxString msg;
1136                 msg.Printf(wxT("Failed to set PATH environment variable"));
1137                 wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1138                 rc = FALSE;
1139             } else
1140             {
1141                 if(!wxSetEnv(_T("MAKE_MODE"),_T("unix")))
1142                 {
1143                     wxString msg;
1144                     msg.Printf(wxT("Failed to set MAKE_MODE environment variable"));
1145                     wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
1146                     rc = FALSE;
1147                 } else
1148                 {
1149                     // Remove from the environment
1150                     wxUnsetEnv(wxT("GDBTK_LIBRARY"));
1151                     wxUnsetEnv(wxT("GCC_EXEC_PREFIX"));
1152
1153                     // Useful for ecosconfig
1154                     wxSetEnv(wxT("ECOS_REPOSITORY"), pDoc->GetPackagesDir());
1155
1156                     // Mount /ecos-x so we can access these in text mode
1157                     if (! pDoc->GetBuildTree().IsEmpty() && wxIsalpha(pDoc->GetBuildTree()[0]))
1158                         CygMount(pDoc->GetBuildTree()[0]);
1159                     if (! pDoc->GetInstallTree().IsEmpty() && wxIsalpha(pDoc->GetInstallTree()[0]))
1160                         CygMount(pDoc->GetInstallTree()[0]);
1161                     if (! pDoc->GetRepository().IsEmpty() && wxIsalpha(pDoc->GetRepository()[0]))
1162                         CygMount(pDoc->GetRepository()[0]);
1163                 }
1164             }
1165         }
1166     }
1167     return rc;
1168 #else
1169     wxASSERT ( cmdLine != NULL );
1170
1171     (* cmdLine) = wxEmptyString;
1172
1173     // Under Unix we need to build up a command line to set variables and invoke make
1174     ecConfigToolDoc *pDoc = GetConfigToolDoc();
1175     
1176     const wxString strPrefix(pDoc->GetCurrentTargetPrefix());
1177     ecFileName strBinDir;
1178     bool rc = FALSE;
1179
1180     rc=(! bWithBuildTools) || GetSettings().m_arstrBinDirs.Find(strPrefix, strBinDir);
1181     if(!rc)
1182     {
1183         // Use fallback of previously-entered build tools directory, if available
1184         if (!GetSettings().m_buildToolsDir.IsEmpty())
1185         {
1186             strBinDir = GetSettings().m_buildToolsDir ;
1187             rc = TRUE;
1188         }
1189         else
1190         {
1191             wxCommandEvent event;
1192             GetMainFrame()->OnBuildToolsPath(event);
1193             rc = GetSettings().m_arstrBinDirs.Find(strPrefix, strBinDir);
1194         }
1195     }
1196     
1197     if (rc)
1198     {
1199         if (!strBinDir.IsEmpty())
1200         {
1201             (* cmdLine) += wxString(wxT("export PATH=")) + wxString(strBinDir) + wxT(":$PATH; ");
1202             
1203             // Also set the path
1204             wxString oldPath(wxGetenv(wxT("PATH")));
1205             wxString path(strBinDir);
1206             if (!oldPath.IsEmpty())
1207             {
1208                 path += wxT(":");
1209                 path += oldPath;
1210             }
1211             wxSetEnv(wxT("PATH"), path);
1212         }
1213         (* cmdLine) += wxString(wxT("unset GDBTK_LIBRARY; ")) ;
1214         wxUnsetEnv(wxT("GDBTK_LIBRARY"));
1215         
1216         (* cmdLine) += wxString(wxT("unset GCC_EXEC_PREFIX; ")) ;
1217         wxUnsetEnv(wxT("GCC_EXEC_PREFIX"));
1218         
1219         (* cmdLine) += wxString(wxT("export ECOS_REPOSITORY=")) + wxString(pDoc->GetPackagesDir()) + wxT("; ");
1220         wxSetEnv(wxT("ECOS_REPOSITORY"), pDoc->GetPackagesDir());
1221         
1222 #if 0
1223         ecFileName strUserBinDir(GetSettings().m_userToolsDir);
1224         if(strUserBinDir.IsEmpty())
1225         {
1226             if ( 1 == GetSettings().m_userToolPaths.GetCount() )
1227             {
1228                 GetSettings().m_userToolsDir = GetSettings().m_userToolPaths[0];
1229             } else
1230             {
1231                 wxCommandEvent event;
1232                 GetMainFrame()->OnUserToolsPath(event);
1233             }
1234             strUserBinDir = GetSettings().m_userToolsDir;
1235         }
1236         if ( !strUserBinDir.IsEmpty() )
1237         {
1238             // calculate the directory of the host tools from this application's module name
1239             ecFileName strHostToolsBinDir(this->argv[0]);
1240             strHostToolsBinDir = strHostToolsBinDir.Head ();
1241             
1242             // tools directories are in the order host-tools, user-tools, comp-tools, install/bin (if present), contrib-tools (if present) on the path
1243             
1244             // TODO: is this right? Assuming that the user tools are already in the user's path.
1245             // const ecFileName strContribBinDir(strUserBinDir, wxT("..\\contrib\\bin"));
1246             // const ecFileName strUsrBinDir(strUserBinDir, wxT("..\\usr\\bin"));
1247             const ecFileName strInstallBinDir(pDoc->GetInstallTree (), wxT("bin"));
1248             
1249             (* cmdLine) += wxString(wxT("export PATH=")) + wxString(strInstallBinDir) + wxT(":$PATH; ");
1250             (* cmdLine) += wxString(wxT("unset GDBTK_LIBRARY; ")) ;
1251             (* cmdLine) += wxString(wxT("unset GCC_EXEC_PREFIX; ")) ;
1252             (* cmdLine) += wxString(wxT("export ECOS_REPOSITORY=")) + wxString(pDoc->GetPackagesDir()) + wxT("; ");
1253         }
1254 #endif
1255     }
1256     return rc;
1257 #endif
1258 }
1259
1260 void ecApp::CygMount(wxChar c)
1261 {
1262     // May not be alpha if it's e.g. a UNC network path
1263     if (!wxIsalpha(c))
1264         return;
1265     
1266     c = wxTolower(c);
1267     
1268     if(!sm_arMounted[c-_TCHAR('a')])
1269     {
1270         sm_arMounted[c-wxChar('a')]=true;
1271         wxString strCmd;
1272         String strOutput;
1273         
1274         strCmd.Printf(wxT("mount -t -u %c: /ecos-%c"),c,c);
1275         CSubprocess sub;
1276         sub.Run(strOutput,strCmd);
1277     }
1278
1279
1280     // Doing it with wxExecute results in a flashing DOS box unfortunately
1281 #if 0
1282     wxASSERT(wxIsalpha(c));
1283     c = wxTolower(c);
1284     if(!sm_arMounted[c-wxChar('a')])
1285     {
1286         sm_arMounted[c-wxChar('a')] = TRUE;
1287         wxString strCmd;
1288         
1289         strCmd.Printf(wxT("mount.exe %c: /%c"),c,c);
1290
1291         wxExecute(strCmd, TRUE);
1292     }
1293 #endif
1294 }
1295
1296 // Fiddling directly with the registry DOESN'T WORK because Cygwin mount tables
1297 // get out of synch with the registry
1298 void ecApp::CygMountText(wxChar c)
1299 {
1300     wxASSERT(wxIsalpha(c));
1301     c = wxTolower(c);
1302 //    if(!sm_arMounted[c-wxChar('a')])
1303     {
1304 //        sm_arMounted[c-wxChar('a')] = TRUE;
1305
1306 #if 0        
1307         wxString strCmd;
1308         
1309         strCmd.Printf(wxT("mount.exe %c: /ecos-%c"),c,c);
1310
1311         wxExecute(strCmd, TRUE);
1312 #else
1313         wxString key, value;
1314         key.Printf(wxT("/ecos-%c"), c);
1315         value.Printf(wxT("%c:"), c);
1316
1317         // Mount by fiddling with registry instead, so we don't see ugly flashing windows
1318 #ifdef __WXMSW__
1319         HKEY hKey = 0;
1320         if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Cygnus Solutions\\Cygwin\\mounts v2",
1321             0, KEY_READ, &hKey))
1322         {
1323             DWORD disposition;
1324             HKEY hSubKey = 0;
1325
1326             if (ERROR_SUCCESS == RegCreateKeyEx(hKey, key, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
1327                 NULL, & hSubKey, & disposition))
1328             {
1329                 RegSetValueEx(hSubKey, "native", 0, REG_SZ, (unsigned char*) (const wxChar*) value, value.Length() + 1);
1330                 RegCloseKey(hSubKey);
1331             }
1332             
1333             RegCloseKey(hKey);
1334         }
1335 #endif
1336
1337 #endif
1338     }
1339 }
1340
1341 void ecApp::Build(const wxString &strWhat /*=wxT("")*/ )
1342 {
1343     if (m_pipedProcess)
1344         return;
1345
1346     ecConfigToolDoc* pDoc = GetConfigToolDoc();
1347     if (!pDoc)
1348         return;
1349
1350     if (!wxGetApp().GetMainFrame()->GetOutputWindow()->IsShown())
1351     {
1352         wxGetApp().GetMainFrame()->ToggleWindow(ecID_TOGGLE_OUTPUT);
1353     }
1354     if (!pDoc->GetDocumentSaved())
1355     {
1356         pDoc->SaveAs();
1357     }
1358 /*
1359     if (pDoc->IsModified() && !wxDirExists(pDoc->GetBuildTree()))
1360     {
1361         pDoc->SaveAs();
1362     }
1363 */
1364 //    if ( !(pDoc->IsModified() || !wxDirExists(pDoc->GetBuildTree())) ) // verify the save worked
1365     if ( pDoc->GetDocumentSaved() )
1366     {
1367         //wxString strCmd (wxT("c:\\bin\\testmake.bat"));
1368         wxString strCmd (wxT("make"));
1369         if(!strWhat.IsEmpty())
1370         {
1371             strCmd += wxT(' ');
1372             strCmd += strWhat;
1373         }
1374
1375         if(!GetSettings().m_strMakeOptions.IsEmpty())
1376         {
1377             strCmd += wxT(' ');
1378             strCmd += GetSettings().m_strMakeOptions;
1379         }
1380         strCmd += wxT(" --directory ");
1381
1382         // Quoting the name may not mix with the 'sh' command on Unix, so only do it
1383         // under Windows where it's more likely there will be spaces needing quoting.
1384 #ifdef __WXMSW__
1385         wxString buildDir(pDoc->GetBuildTree());
1386
1387 #if ecUSE_ECOS_X_NOTATION
1388         std::string cPath = cygpath(std::string(pDoc->GetBuildTree()));
1389         buildDir = cPath.c_str();
1390 #endif
1391         strCmd += wxString(wxT("\"")) + buildDir + wxString(wxT("\""));
1392 #else
1393         strCmd += wxString(pDoc->GetBuildTree()) ;
1394 #endif
1395
1396         wxString variableSettings;
1397
1398         if (PrepareEnvironment(TRUE, & variableSettings))
1399         {
1400 #ifdef __WXMSW__
1401             // strCmd is all we need
1402 #else
1403             // strCmd has to invoke a shell with variables and make invocation
1404             strCmd = wxString(wxT("sh -c \"")) + variableSettings + strCmd + wxString(wxT("\""));
1405 #endif
1406             // Output the command so we know what we're doing
1407             Log(strCmd);
1408             Log(wxT("\n"));
1409
1410             // No: pass --directory
1411             // wxSetWorkingDirectory(pDoc->GetBuildTree());
1412
1413             m_pipedProcess = new ecPipedProcess;
1414             long pid = wxExecute(strCmd, FALSE, m_pipedProcess);
1415             if ( pid )
1416             {
1417                 m_pipedProcess->SetPid(pid);
1418                 // wxLogStatus(_T("Process %ld (%s) launched."), pid, cmd.c_str());
1419             }
1420             else
1421             {
1422                 wxLogError(_T("Execution of '%s' failed."), strCmd.c_str());
1423                 
1424                 delete m_pipedProcess;
1425                 m_pipedProcess  = NULL;
1426             }
1427         }
1428
1429 #if 0        
1430         if(PrepareEnvironment())
1431         {
1432             m_strBuildTarget=strWhat;
1433             SetThermometerMax(250); // This is just a guess.  The thread we are about to spawn will work out the correct answer
1434             m_nLogicalLines=0;
1435             UpdateThermometer(0);
1436             CloseHandle(CreateThread(NULL, 0, ThreadFunc, this, 0 ,&m_dwThreadId));
1437             CString strMsg;
1438             strMsg.Format(_T("Building %s"),strWhat);
1439             SetIdleMessage(strMsg);
1440             
1441             SetTimer(42,1000,0); // This timer checks for process completion
1442             SetCurrentDirectory(pDoc->BuildTree());
1443             m_sp.Run(SubprocessOutputFunc, this, strCmd, false);
1444             SetIdleMessage();
1445         }
1446 #endif
1447     }
1448 #if 0
1449     
1450     if(pDoc->IsModified()||pDoc->BuildTree().IsEmpty()){
1451         SendMessage (WM_COMMAND, ID_FILE_SAVE);
1452     }
1453     
1454     if(!(pDoc->IsModified()||pDoc->BuildTree().IsEmpty())){ // verify the save worked
1455         CString strCmd (_T("make"));
1456         if(!strWhat.IsEmpty()){
1457             strCmd+=_TCHAR(' ');
1458             strCmd+=strWhat;
1459         }
1460         if(!GetApp()->m_strMakeOptions.IsEmpty()){
1461             strCmd+=_TCHAR(' ');
1462             strCmd+=GetApp()->m_strMakeOptions;
1463         }
1464         
1465         if(PrepareEnvironment()){
1466             m_strBuildTarget=strWhat;
1467             SetThermometerMax(250); // This is just a guess.  The thread we are about to spawn will work out the correct answer
1468             m_nLogicalLines=0;
1469             UpdateThermometer(0);
1470             CloseHandle(CreateThread(NULL, 0, ThreadFunc, this, 0 ,&m_dwThreadId));
1471             CString strMsg;
1472             strMsg.Format(_T("Building %s"),strWhat);
1473             SetIdleMessage(strMsg);
1474             
1475             SetTimer(42,1000,0); // This timer checks for process completion
1476             SetCurrentDirectory(pDoc->BuildTree());
1477             m_sp.Run(SubprocessOutputFunc, this, strCmd, false);
1478             SetIdleMessage();
1479         }
1480     }
1481 #endif
1482 }
1483
1484 void ecApp::OnProcessTerminated(wxProcess* process)
1485 {
1486     m_pipedProcess = NULL;
1487 }
1488
1489 // ----------------------------------------------------------------------------
1490 // ecPipedProcess
1491 // ----------------------------------------------------------------------------
1492
1493 bool ecPipedProcess::HasInput()
1494 {
1495     bool hasInput = FALSE;
1496
1497     wxInputStream& is = *GetInputStream();
1498     if ( IsInputAvailable() )
1499     {
1500         wxTextInputStream tis(is);
1501
1502         // this assumes that the output is always line buffered
1503         wxString msg;
1504         msg << tis.ReadLine();
1505
1506         wxGetApp().Log(msg);
1507
1508         hasInput = TRUE;
1509     }
1510
1511     wxInputStream& es = *GetErrorStream();
1512     if ( IsErrorAvailable() )
1513     {
1514         wxTextInputStream tis(es);
1515
1516         // this assumes that the output is always line buffered
1517         wxString msg;
1518         msg << tis.ReadLine();
1519
1520         wxGetApp().Log(msg);
1521
1522         hasInput = TRUE;
1523     }
1524
1525     return hasInput;
1526 }
1527
1528 void ecPipedProcess::OnTerminate(int pid, int status)
1529 {
1530     // show the rest of the output
1531     while ( HasInput() )
1532         ;
1533
1534     wxGetApp().OnProcessTerminated(this);
1535
1536     //wxLogStatus(m_parent, _T("Process %u ('%s') terminated with exit code %d."),
1537     //            pid, m_cmd.c_str(), status);
1538
1539     // we're not needed any more
1540     delete this;
1541 }
1542
1543 void ecPingTimer::Notify()
1544 {
1545     static bool s_inNotify = FALSE;
1546
1547     if (s_inNotify)
1548         return;
1549
1550     s_inNotify = TRUE;
1551
1552     // On Windows, simply having the timer going will ping the message queue
1553     // and cause idle processing to happen.
1554     // On Unix, this doesn't happen so we have to do the processing explicitly.
1555 #ifdef __WXMSW__
1556     // Nothing to do
1557 #else
1558     // Get some input
1559     if ( wxGetApp().m_pipedProcess )
1560         while (wxGetApp().m_pipedProcess->HasInput())
1561         {
1562             // Loop while there is still input
1563         }
1564 #endif
1565
1566     s_inNotify = FALSE;
1567 }
1568