Mercurial > ecos
diff host/tools/configtool/standalone/wxwin/configtool.cpp @ 160:0d0f03f76f6a
Merge from eCos master repository on 2001-06-01-18:52:13-BST
| author | jlarmour |
|---|---|
| date | Fri, 01 Jun 2001 22:16:29 +0000 |
| parents | |
| children | 0d2b193a635f |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/host/tools/configtool/standalone/wxwin/configtool.cpp @@ -0,0 +1,1193 @@ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This program is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +// configtool.cpp : +// +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): julians +// Contact(s): julians +// Date: 2000/08/24 +// Version: $Id: configtool.cpp,v 1.34 2001/05/02 10:36:15 julians Exp $ +// Purpose: +// Description: Implementation file for the ConfigTool application class +// Requires: +// Provides: +// See also: +// Known bugs: +// Usage: +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- +#ifdef __GNUG__ + #pragma implementation "configtool.h" +#endif + +// Includes other headers for precompiled compilation +#include "ecpch.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#include "eCosSocket.h" +#include "eCosTestPlatform.h" + +#include "wx/splash.h" +#include "wx/cshelp.h" +#include "wx/image.h" +#include "wx/filesys.h" +#include "wx/fs_zip.h" +#include "wx/config.h" +#include "wx/cmdline.h" +#include "wx/process.h" +#include "wx/mimetype.h" +#include "wx/txtstrm.h" + +#include "configtool.h" +#include "configtoolview.h" +#include "configtree.h" +#include "mainwin.h" +#include "outputwin.h" +#include "configtooldoc.h" +#include "aboutdlg.h" +#include "shortdescrwin.h" +#include "conflictwin.h" +#include "propertywin.h" + +// ---------------------------------------------------------------------------- +// resources +// ---------------------------------------------------------------------------- +// the application icon +#if defined(__WXGTK__) || defined(__WXMOTIF__) + #include "bitmaps/configtool.xpm" +#endif + +// Create a new application object. +IMPLEMENT_APP(ecApp) + +BEGIN_EVENT_TABLE(ecApp, wxApp) +// Don't handle automatically, or it will bypass more specific processing. +// EVT_MENU(ecID_WHATS_THIS, ecApp::OnWhatsThis) +END_EVENT_TABLE() + +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}; + +static const wxCmdLineEntryDesc sg_cmdLineDesc[] = +{ +/* + { wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" }, + { wxCMD_LINE_SWITCH, "q", "quiet", "be quiet" }, + + { wxCMD_LINE_OPTION, "o", "output", "output file" }, + { wxCMD_LINE_OPTION, "i", "input", "input dir" }, + { wxCMD_LINE_OPTION, "s", "size", "output block size", wxCMD_LINE_VAL_NUMBER }, + { wxCMD_LINE_OPTION, "d", "date", "output file date", wxCMD_LINE_VAL_DATE }, +*/ + + { wxCMD_LINE_PARAM, NULL, NULL, "input file 1", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, + { wxCMD_LINE_PARAM, NULL, NULL, "input file 2", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, + + { wxCMD_LINE_NONE } +}; + +ecApp::ecApp() +{ + m_docManager = NULL; + m_mainFrame = NULL; + m_currentDoc = NULL; + m_whatsThisMenu = new wxMenu; + m_whatsThisMenu->Append(ecID_WHATS_THIS, _("&What's This?")); + m_helpFile = wxEmptyString; + m_splashScreen = NULL; + m_pipedProcess = NULL; + m_valuesLocked = 0; + m_helpController = NULL; +} + +ecApp::~ecApp() +{ + delete m_whatsThisMenu; +} + +// 'Main program' equivalent: the program execution "starts" here +bool ecApp::OnInit() +{ + wxLog::SetTimestamp(NULL); + + CeCosSocket::Init(); + CeCosTestPlatform::Load(); + + wxHelpProvider::Set(new wxSimpleHelpProvider); + //wxHelpProvider::Set(new wxHelpControllerHelpProvider(& m_helpController)); + + wxImage::AddHandler(new wxPNGHandler); + wxImage::AddHandler(new wxGIFHandler); + + // Required for advanced HTML help +#if wxUSE_STREAMS && wxUSE_ZIPSTREAM && wxUSE_ZLIB + wxFileSystem::AddHandler(new wxZipFSHandler); +#endif + + wxString currentDir = wxGetCwd(); + + // Use argv to get current app directory + m_appDir = wxFindAppPath(argv[0], currentDir, wxT("CONFIGTOOLDIR")); + + // If the development version, go up a directory. +#ifdef __WXMSW__ + if ((m_appDir.Right(5).CmpNoCase("DEBUG") == 0) || + (m_appDir.Right(11).CmpNoCase("DEBUGSTABLE") == 0) || + (m_appDir.Right(7).CmpNoCase("RELEASE") == 0) || + (m_appDir.Right(13).CmpNoCase("RELEASESTABLE") == 0) + ) + m_appDir = wxPathOnly(m_appDir); +#endif + + wxGetEnv(wxT("PATH"), & m_strOriginalPath); + + // Create a document manager + m_docManager = new wxDocManager; + + // Create a template relating documents to their views + (void) new wxDocTemplate(m_docManager, "Configtool", "*.ecc", "", "ecc", "Configtool Doc", "Configtool View", + CLASSINFO(ecConfigToolDoc), CLASSINFO(ecConfigToolView)); + + // If we've only got one window, we only get to edit + // one document at a time. + m_docManager->SetMaxDocsOpen(1); + + // Initialize config settings + m_settings.Init(); + + // Let wxWindows know what the app name is + SetAppName(m_settings.GetAppName()); + + InitializeWindowSettings(TRUE /* beforeWindowConstruction */) ; + + // Load config settings + m_settings.LoadConfig(); + +#ifdef __WXMSW__ + wxBitmap bitmap(wxBITMAP(splash)); +#else + wxBitmap bitmap; + if (wxFileExists("splash16.png")) + bitmap.LoadFile("splash16.png", wxBITMAP_TYPE_PNG); +#endif + if (bitmap.Ok() && GetSettings().m_showSplashScreen) + { + m_splashScreen = new ecSplashScreen(bitmap, wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT, + 6000, NULL, -1, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxFRAME_FLOAT_ON_PARENT|wxSTAY_ON_TOP); + } + + wxYieldIfNeeded(); + + // create the main application window + ecMainFrame *frame = new ecMainFrame(m_docManager, GetSettings().GetAppName(), + wxPoint(GetSettings().m_frameSize.x, GetSettings().m_frameSize.y), + wxSize(GetSettings().m_frameSize.width, GetSettings().m_frameSize.height)); + +#if 0 + // TODO: eCos.hhp/hhc/hhk will eventually be generated as the app starts up. + if ( !GetHelpController().Initialize(GetFullAppPath(wxT("eCos"))) ) + { + //wxMessageBox(_("Cannot initialize the help system, aborting.")); + //return FALSE; + } +#endif + + m_mainFrame = frame; + SetTopWindow(frame); + frame->Show(TRUE); + SendIdleEvents(); // Otherwise UI updates aren't done, because it's busy loading the repository + + InitializeWindowSettings(FALSE /* beforeWindowConstruction */) ; + + if (m_splashScreen) + m_splashScreen->Raise(); + + wxYieldIfNeeded(); + + // Parse the command-line parameters and options + wxCmdLineParser parser(sg_cmdLineDesc, argc, argv); + int res = parser.Parse(); + if (res == -1 || res > 0) + { + parser.Usage(); + return FALSE; + } + wxString filenameToOpen1, filenameToOpen2; + if (parser.GetParamCount() > 0) + { + wxString tmpSaveFile; + + filenameToOpen1 = parser.GetParam(0); + + if (parser.GetParamCount() > 1) + filenameToOpen2 = parser.GetParam(1); + + bool gotRepository = FALSE; + bool gotSavefile = FALSE; + + wxString repositoryDir, saveFile; + + // Might be e.g. . or .. in path, or relative path + filenameToOpen1 = wxGetRealPath(currentDir, filenameToOpen1); + + if (parser.GetParamCount() > 1) + filenameToOpen2 = wxGetRealPath(currentDir, filenameToOpen2); + + wxString path1, name1, ext1; + wxSplitPath(filenameToOpen1, & path1, & name1, & ext1); + + wxString path2, name2, ext2; + wxSplitPath(filenameToOpen2, & path2, & name2, & ext2); + + // Look at the first file + if (ext1 == "ecc" || ext1 == "ECC") + { + if (wxFileExists(filenameToOpen1)) + { + gotSavefile = TRUE; + saveFile = filenameToOpen1; + } + else + { + wxString msg; + msg.Printf("%s is not a valid file.", (const wxChar*) filenameToOpen1); + wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK); + return FALSE; + } + } + else if (wxDirExists(filenameToOpen1) && FindSaveFileInDir(filenameToOpen1, tmpSaveFile)) + { + saveFile = tmpSaveFile; + gotSavefile = TRUE; + } + else if ((name1 == wxT("ecos") && ext1 == wxT("db") && wxFileExists(filenameToOpen1)) || wxDirExists(filenameToOpen1)) + { + // It's a repository (we hope). + if (name1 == wxT("ecos") && ext1 == wxT("db")) + { + // Go two steps up + filenameToOpen1 = wxPathOnly(filenameToOpen1); + filenameToOpen1 = wxPathOnly(filenameToOpen1); + } + else + { + // If it's the packages directory, we need to strip off + // a directory + wxString eccPath(filenameToOpen1 + wxString(wxFILE_SEP_PATH) + wxT("ecc")); + + // Don't strip off ecc if it's the CVS repository (with ecc below it) + if (name1 == wxT("packages") || (name1 == wxT("ecc") && !wxDirExists(eccPath))) + filenameToOpen1 = wxPathOnly(filenameToOpen1); + } + + repositoryDir = filenameToOpen1; + gotRepository = TRUE; + } + else + { + wxString msg; + msg.Printf("%s is neither a project file nor a valid repository.", (const wxChar*) filenameToOpen1); + wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK); + return FALSE; + } + + // Look at the second file, if any + if (parser.GetParamCount() > 1) + { + if (ext2 == "ecc" || ext2 == "ECC") + { + if (wxFileExists(filenameToOpen2)) + { + if (gotSavefile) + { + wxString msg; + msg.Printf("%s is a second save file -- please supply only one.", (const wxChar*) filenameToOpen2); + wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK); + return FALSE; + } + + gotSavefile = TRUE; + saveFile = filenameToOpen2; + } + else + { + wxString msg; + msg.Printf("%s is not a valid file.", (const wxChar*) filenameToOpen2); + wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK); + return FALSE; + } + } + else if (!gotSavefile && wxDirExists(filenameToOpen2) && FindSaveFileInDir(filenameToOpen2, tmpSaveFile)) + { + saveFile = tmpSaveFile; + gotSavefile = TRUE; + } + else if ((name2 == wxT("ecos") && ext2 == wxT("db") && wxFileExists(filenameToOpen2)) || wxDirExists(filenameToOpen2)) + { + if (gotRepository) + { + wxString msg; + msg.Printf("%s is a second repository -- please supply only one.", (const wxChar*) filenameToOpen2); + wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK); + return FALSE; + } + + // It's a repository (we hope). + if (name1 == wxT("ecos") && ext1 == wxT("db")) + { + // Go two steps up + filenameToOpen2 = wxPathOnly(filenameToOpen2); + filenameToOpen2 = wxPathOnly(filenameToOpen2); + } + else + { + // If it's the packages directory, we need to strip off + // a directory + wxString eccPath(filenameToOpen2 + wxString(wxFILE_SEP_PATH) + wxT("ecc")); + + // Don't strip off ecc if it's the CVS repository (with ecc below it) + if (name2 == wxT("packages") || (name2 == wxT("ecc") && !wxDirExists(eccPath))) + filenameToOpen2 = wxPathOnly(filenameToOpen2); + } + + repositoryDir = filenameToOpen2; + gotRepository = TRUE; + } + else + { + wxString msg; + msg.Printf("%s is neither a project file nor a valid repository.", (const wxChar*) filenameToOpen2); + wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK); + return FALSE; + } + } + + // Now we have looked at the two files and decided what they are; let's + // act on it. + + if (gotRepository) + { + GetSettings().m_strRepository = repositoryDir; + } + + if (!gotSavefile) + { + // See if there's a save file in the current dir + if (FindSaveFileInDir(currentDir, saveFile)) + gotSavefile = TRUE; + } + + if (gotSavefile) + { + // The repository will be loaded from m_strRepository, possibly set above. + m_docManager->CreateDocument(saveFile, wxDOC_SILENT); + } + else + { + // Create a new file + m_docManager->CreateDocument(wxString(""), wxDOC_NEW); + } + } + else + { + m_docManager->CreateDocument(wxString(""), wxDOC_NEW); + } + + return TRUE; +} + +// Initialize window settings object +bool ecApp::InitializeWindowSettings(bool beforeWindowConstruction) +{ + wxWindowSettings& settings = GetSettings().m_windowSettings; + ecMainFrame* frame = GetMainFrame(); + + if (beforeWindowConstruction) + { + settings.Add(wxT("Configuration")); + settings.Add(wxT("Short Description")); + settings.Add(wxT("Output")); + settings.Add(wxT("Properties")); + settings.Add(wxT("Conflicts")); + } + else + { + wxArrayPtrVoid arr; + arr.Add(frame->GetTreeCtrl()); + arr.Add(frame->GetValueWindow()); + settings.SetWindows(wxT("Configuration"), arr); + + settings.SetWindow(wxT("Short Description"), frame->GetShortDescriptionWindow()); + settings.SetWindow(wxT("Output"), frame->GetOutputWindow()); + settings.SetWindow(wxT("Properties"), frame->GetPropertyListWindow()); + settings.SetWindow(wxT("Conflicts"), frame->GetConflictsWindow()); + } + + return TRUE; +} + + +bool ecApp::InitializeHelpController() +{ + if (m_helpController) + delete m_helpController; + m_helpController = new wxHelpController; + + if (!m_helpController->Initialize(GetHelpFile())) + { + // TODO + return FALSE; + } + else + { + // Tell the help controller where the repository documentation is. + // For now, just keep this to myself since it uses hacks to wxWin + ecConfigToolDoc* doc = GetConfigToolDoc(); + + // No longer using relative paths +#if 0 + if (doc) + { + wxString htmlDir = wxString(doc->GetRepository()) + wxString(wxT("/doc/html")); + if (!wxDirExists(htmlDir)) + htmlDir = wxString(doc->GetRepository()) + wxString(wxT("/doc")); + + htmlDir += wxString(wxT("/")); + + wxGetApp().GetHelpController().SetBookBasePath(htmlDir); + } +#endif + return TRUE; + } +} + +// Check if there is a (unique) .ecc file in dir +bool ecApp::FindSaveFileInDir(const wxString& dir, wxString& saveFile) +{ + wxDir fileFind; + + if (!fileFind.Open(dir)) + return FALSE; + + wxString wildcard = wxT(".ecc"); + wxString filename; + + bool found = fileFind.GetFirst (& filename, wildcard); + if (found) + { + // Fail if there was more than one matching file. + wxString filename2; + if (fileFind.GetNext (& filename2)) + return FALSE; + else + { + saveFile = dir + wxString(wxFILE_SEP_PATH) + filename; + return TRUE; + } + } + return FALSE; +} + +int ecApp::OnExit(void) +{ +/* + if (m_helpController) + { + delete m_helpController; + m_helpController = NULL; + } +*/ + + if (m_splashScreen) + { + m_splashScreen->Destroy(); + m_splashScreen = NULL; + } + + m_settings.SaveConfig(); + + { + wxConfig config(wxGetApp().GetSettings().GetConfigAppName(), wxT("Red Hat")); + m_docManager->FileHistorySave(config); + } + + delete m_docManager; + + return 0; +} + +// Prepend the current program directory to the name +wxString ecApp::GetFullAppPath(const wxString& filename) const +{ + wxString path(m_appDir); + if (path.Last() != '\\' && path.Last() != '/' && filename[0] != '\\' && filename[0] != '/') +#ifdef __WXGTK__ + path += '/'; +#else + path += '\\'; +#endif + path += filename; + + return path; +} + +// Are we running in 32K colours or more? +bool ecApp::GetHiColour() const +{ + static bool hiColour = (wxDisplayDepth() >= 16) ; + return hiColour; +} + +// General handler for 'What's this?' +void ecApp::OnWhatsThis(wxCommandEvent& event) +{ + wxObject* obj = event.GetEventObject(); + wxWindow* win = NULL; + + if (obj->IsKindOf(CLASSINFO(wxMenu))) + { + win = ((wxMenu*) obj)->GetInvokingWindow(); + } + else if (obj->IsKindOf(CLASSINFO(wxWindow))) + { + win = (wxWindow*) obj; + } + + wxWindow* subjectOfHelp = win; + bool eventProcessed = FALSE; + wxPoint pt = wxGetMousePosition(); + + while (subjectOfHelp && !eventProcessed) + { + wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), pt) ; + helpEvent.SetEventObject(this); + eventProcessed = win->GetEventHandler()->ProcessEvent(helpEvent); + + // Go up the window hierarchy until the event is handled (or not). + // I.e. keep submitting ancestor windows until one is recognised + // by the app code that processes the ids and displays help. + subjectOfHelp = subjectOfHelp->GetParent(); + } + // wxGetApp().GetHelpController().DisplayTextPopup(GetHelpText(), wxGetMousePosition()); +} + +// Log to output window +void ecApp::Log(const wxString& msg) +{ + ecMainFrame* frame = (ecMainFrame*) GetTopWindow(); + if (frame) + { + // TODO is SetInsertionPointEnd necessary? + frame->GetOutputWindow()->SetInsertionPointEnd(); + frame->GetOutputWindow()->AppendText(msg /* + wxT("\n") */ ); + if ((msg == wxEmptyString) || (msg.Last() != wxT('\n'))) + frame->GetOutputWindow()->AppendText(wxT("\n")); + } +} + +void ecApp::SetStatusText(const wxString& text, bool clearFailingRulesPane) +{ + ecMainFrame* mainFrame = GetMainFrame(); + if(mainFrame) + { + mainFrame->GetStatusBar()->SetStatusText(text, ecStatusPane); + if (clearFailingRulesPane) + mainFrame->GetStatusBar()->SetStatusText(wxT(""), ecFailRulePane); +#ifdef __WXMSW__ + wxYield(); +#endif + } +} + +// Config tree control +ecConfigTreeCtrl* ecApp::GetTreeCtrl() const +{ + return GetMainFrame()->GetTreeCtrl(); +} + +// MLT window +ecMemoryLayoutWindow* ecApp::GetMLTWindow() const +{ + return GetMainFrame()->GetMemoryLayoutWindow(); +} + +// Get active document +ecConfigToolDoc* ecApp::GetConfigToolDoc() const +{ + if (m_currentDoc) + return m_currentDoc; + + if (!m_docManager) + return NULL; + + return wxDynamicCast(m_docManager->GetCurrentDocument(), ecConfigToolDoc); +} + +bool ecApp::Launch(const wxString & strFileName,const wxString &strViewer) +{ + bool ok = FALSE; + wxString cmd; + + if (!strViewer.IsEmpty()) + { + cmd = strViewer + wxString(wxT(" ")) + strFileName ; + } + else + { + wxString path, filename, ext; + wxSplitPath(strFileName, & path, & filename, & ext); + + wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(ext); + if ( !ft ) + { + wxLogError(_T("Impossible to determine the file type for extension '%s'"), + ext.c_str()); + return FALSE; + } + + bool ok = ft->GetOpenCommand(&cmd, + wxFileType::MessageParameters(strFileName, _T(""))); + delete ft; + + if (!ok) + { + // TODO: some kind of configuration dialog here. + wxMessageBox(_("Could not determine the command for opening this file."), + wxGetApp().GetSettings().GetAppName(), wxOK|wxICON_EXCLAMATION); + return FALSE; + } + } + + ok = (wxExecute(cmd, FALSE) != 0); + + return ok; + +#if 0 + bool rc=false; + + if(!strViewer.IsEmpty())//use custom editor + { + CString strCmdline(strViewer); + + TCHAR *pszCmdLine=strCmdline.GetBuffer(strCmdline.GetLength()); + GetShortPathName(pszCmdLine,pszCmdLine,strCmdline.GetLength()); + strCmdline.ReleaseBuffer(); + + strCmdline+=_TCHAR(' '); + strCmdline+=strFileName; + PROCESS_INFORMATION pi; + STARTUPINFO si; + + si.cb = sizeof(STARTUPINFO); + si.lpReserved = NULL; + si.lpReserved2 = NULL; + si.cbReserved2 = 0; + si.lpDesktop = NULL; + si.dwFlags = 0; + si.lpTitle=NULL; + + if(CreateProcess( + NULL, // app name + //strCmdline.GetBuffer(strCmdline.GetLength()), // command line + strCmdline.GetBuffer(strCmdline.GetLength()), // command line + NULL, // process security + NULL, // thread security + TRUE, // inherit handles + 0, + NULL, // environment + NULL, // current dir + &si, // startup info + &pi)){ + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + rc=true; + } else { + CUtils::MessageBoxF(_T("Failed to invoke %s.\n"),strCmdline); + } + strCmdline.ReleaseBuffer(); + } else {// Use association + TCHAR szExe[MAX_PATH]; + HINSTANCE h=FindExecutable(strFileName,_T("."),szExe); + if(int(h)<=32){ + CString str; + switch(int(h)){ + case 0: str=_T("The system is out of memory or resources.");break; + case 31: str=_T("There is no association for the specified file type.");break; + case ERROR_FILE_NOT_FOUND: str=_T("The specified file was not found.");break; + case ERROR_PATH_NOT_FOUND: str=_T("The specified path was not found.");break; + case ERROR_BAD_FORMAT: str=_T("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).");break; + default: break; + } + CUtils::MessageBoxF(_T("Failed to open document %s.\r\n%s"),strFileName,str); + } else { + + SHELLEXECUTEINFO sei = {sizeof(sei), 0, AfxGetMainWnd()->GetSafeHwnd(), _T("open"), + strFileName, NULL, NULL, SW_SHOWNORMAL, AfxGetInstanceHandle( )}; + + sei.hInstApp=0; + HINSTANCE hInst=ShellExecute(AfxGetMainWnd()->GetSafeHwnd(),_T("open"), strFileName, NULL, _T("."), 0)/*ShellExecuteEx(&sei)*/; + if(int(hInst)<=32/*sei.hInstApp==0*/) + { + CString str; + switch(int(hInst)) + { + case 0 : str=_T("The operating system is out of memory or resources. ");break; + case ERROR_FILE_NOT_FOUND : str=_T("The specified file was not found. ");break; + case ERROR_PATH_NOT_FOUND : str=_T("The specified path was not found. ");break; + case ERROR_BAD_FORMAT : str=_T("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image). ");break; + case SE_ERR_ACCESSDENIED : str=_T("The operating system denied access to the specified file. ");break; + case SE_ERR_ASSOCINCOMPLETE : str=_T("The filename association is incomplete or invalid. ");break; + case SE_ERR_DDEBUSY : str=_T("The DDE transaction could not be completed because other DDE transactions were being processed. ");break; + case SE_ERR_DDEFAIL : str=_T("The DDE transaction failed. ");break; + case SE_ERR_DDETIMEOUT : str=_T("The DDE transaction could not be completed because the request timed out. ");break; + case SE_ERR_DLLNOTFOUND : str=_T("The specified dynamic-link library was not found. ");break; + //case SE_ERR_FNF : str=_T("The specified file was not found. ");break; + case SE_ERR_NOASSOC : str=_T("There is no application associated with the given filename extension. ");break; + case SE_ERR_OOM : str=_T("There was not enough memory to complete the operation. ");break; + //case SE_ERR_PNF : str=_T("The specified path was not found. ");break; + case SE_ERR_SHARE : str=_T("A sharing violation occurred. ");break; + default: str=_T("An unexpected error occurred");break; + } + CUtils::MessageBoxF(_T("Failed to open document %s using %s.\r\n%s"),strFileName,szExe,str); + } else { + rc=true; + } + } + } + return rc; +#endif +} + +bool ecApp::PrepareEnvironment(bool bWithBuildTools, wxString* cmdLine) +{ +#ifdef __WXMSW__ + // Under Windows we can set variables. + ecConfigToolDoc *pDoc = GetConfigToolDoc(); + + wxSetEnv(wxT("PATH"), m_strOriginalPath); + + const wxString strPrefix(pDoc->GetCurrentTargetPrefix()); + ecFileName strBinDir; + bool rc = FALSE; + + rc=(! bWithBuildTools) || GetSettings().m_arstrBinDirs.Find(strPrefix, strBinDir); + if(!rc){ + wxCommandEvent event; + GetMainFrame()->OnBuildToolsPath(event); + rc = GetSettings().m_arstrBinDirs.Find(strPrefix, strBinDir); + } + + if (rc) + { + ecFileName strUserBinDir(GetSettings().m_userToolsDir); + if(strUserBinDir.IsEmpty()) + { + if ( 1 == GetSettings().m_userToolPaths.GetCount() ) + { + GetSettings().m_userToolsDir = GetSettings().m_userToolPaths[0]; + } else + { + wxCommandEvent event; + GetMainFrame()->OnUserToolsPath(event); + } + strUserBinDir = GetSettings().m_userToolsDir; + } + if ( !strUserBinDir.IsEmpty() ) + { + // calculate the directory of the host tools from this application's module name + ecFileName strHostToolsBinDir(this->argv[0]); + strHostToolsBinDir = strHostToolsBinDir.Head (); + + // tools directories are in the order host-tools, user-tools, comp-tools, install/bin (if present), contrib-tools (if present) on the path + const ecFileName strContribBinDir(strUserBinDir, wxT("..\\contrib\\bin")); + ecFileName strUsrBinDir(strUserBinDir, wxT("..\\usr\\bin")); + const ecFileName strInstallBinDir(pDoc->GetInstallTree (), wxT("bin")); + + // In case strUserBinDir is e.g. c:\program files\red hat\cygwin-00r1\usertools\h-i686-pc-cygwin\bin + if (!strUsrBinDir.IsDir ()) + strUsrBinDir = ecFileName(strUserBinDir + _T("..\\..\\..\\H-i686-pc-cygwin\\bin")); + + if ( + (strUsrBinDir.IsDir () && ! ecUtils::AddToPath (strUsrBinDir)) || + (strContribBinDir.IsDir () && ! ecUtils::AddToPath (strContribBinDir)) || + (strInstallBinDir.IsDir () && ! ecUtils::AddToPath (strInstallBinDir)) || + (bWithBuildTools && ! ecUtils::AddToPath (strBinDir)) || + ! ecUtils::AddToPath (strUserBinDir) || + ! ecUtils::AddToPath (strHostToolsBinDir)) + { + wxString msg; + msg.Printf(wxT("Failed to set PATH environment variable")); + wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK); + rc = FALSE; + } else + { + if(!wxSetEnv(_T("MAKE_MODE"),_T("unix"))) + { + wxString msg; + msg.Printf(wxT("Failed to set MAKE_MODE environment variable")); + wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK); + rc = FALSE; + } else + { + // Remove from the environment + wxUnsetEnv(wxT("GDBTK_LIBRARY")); + wxUnsetEnv(wxT("GCC_EXEC_PREFIX")); + + // Useful for ecosconfig + wxSetEnv(wxT("ECOS_REPOSITORY"), pDoc->GetPackagesDir()); + + if (! pDoc->GetBuildTree().IsEmpty()) + CygMount(pDoc->GetBuildTree()[0]); + if (! pDoc->GetInstallTree().IsEmpty()) + CygMount(pDoc->GetInstallTree()[0]); + if (! pDoc->GetRepository().IsEmpty()) + CygMount(pDoc->GetRepository()[0]); + } + } + } + } + return rc; +#else + wxASSERT ( cmdLine != NULL ); + + (* cmdLine) = wxEmptyString; + + // Under Unix we need to build up a command line to set variables and invoke make + ecConfigToolDoc *pDoc = GetConfigToolDoc(); + + const wxString strPrefix(pDoc->GetCurrentTargetPrefix()); + ecFileName strBinDir; + bool rc = FALSE; + + rc=(! bWithBuildTools) || GetSettings().m_arstrBinDirs.Find(strPrefix, strBinDir); + if(!rc){ + wxCommandEvent event; + GetMainFrame()->OnBuildToolsPath(event); + rc = GetSettings().m_arstrBinDirs.Find(strPrefix, strBinDir); + } + + if (rc) + { + if (!strBinDir.IsEmpty()) + { + (* cmdLine) += wxString(wxT("export PATH=")) + strBinDir + wxT(":$PATH; "); + + // Also set the path + wxString oldPath(wxGetenv(wxT("PATH"))); + wxString path(strBinDir); + if (!oldPath.IsEmpty()) + path += oldPath; + wxSetEnv(wxT("PATH"), path); + } + (* cmdLine) += wxString(wxT("unset GDBTK_LIBRARY; ")) ; + wxUnsetEnv(wxT("GDBTK_LIBRARY")); + + (* cmdLine) += wxString(wxT("unset GCC_EXEC_PREFIX; ")) ; + wxUnsetEnv(wxT("GCC_EXEC_PREFIX")); + + (* cmdLine) += wxString(wxT("export ECOS_REPOSITORY=")) + pDoc->GetPackagesDir()+ wxT("; "); + wxSetEnv(wxT("ECOS_REPOSITORY"), pDoc->GetPackagesDir()); + +#if 0 + ecFileName strUserBinDir(GetSettings().m_userToolsDir); + if(strUserBinDir.IsEmpty()) + { + if ( 1 == GetSettings().m_userToolPaths.GetCount() ) + { + GetSettings().m_userToolsDir = GetSettings().m_userToolPaths[0]; + } else + { + wxCommandEvent event; + GetMainFrame()->OnUserToolsPath(event); + } + strUserBinDir = GetSettings().m_userToolsDir; + } + if ( !strUserBinDir.IsEmpty() ) + { + // calculate the directory of the host tools from this application's module name + ecFileName strHostToolsBinDir(this->argv[0]); + strHostToolsBinDir = strHostToolsBinDir.Head (); + + // tools directories are in the order host-tools, user-tools, comp-tools, install/bin (if present), contrib-tools (if present) on the path + + // TODO: is this right? Assuming that the user tools are already in the user's path. + // const ecFileName strContribBinDir(strUserBinDir, wxT("..\\contrib\\bin")); + // const ecFileName strUsrBinDir(strUserBinDir, wxT("..\\usr\\bin")); + const ecFileName strInstallBinDir(pDoc->GetInstallTree (), wxT("bin")); + + (* cmdLine) += wxString(wxT("export PATH=")) + strInstallBinDir + wxT(":$PATH; "); + (* cmdLine) += wxString(wxT("unset GDBTK_LIBRARY; ")) ; + (* cmdLine) += wxString(wxT("unset GCC_EXEC_PREFIX; ")) ; + (* cmdLine) += wxString(wxT("export ECOS_REPOSITORY=")) + pDoc->GetPackagesDir()+ wxT("; "); + } +#endif + } + return rc; +#endif +} + +void ecApp::CygMount(wxChar c) +{ + wxASSERT(wxIsalpha(c)); + c = wxTolower(c); + if(!sm_arMounted[c-wxChar('a')]) + { + sm_arMounted[c-wxChar('a')] = TRUE; + wxString strCmd; + + strCmd.Printf(wxT("mount.exe %c: /%c"),c,c); + + wxExecute(strCmd, TRUE); + } +} + +void ecApp::Build(const wxString &strWhat /*=wxT("")*/ ) +{ + if (m_pipedProcess) + return; + + ecConfigToolDoc* pDoc = GetConfigToolDoc(); + if (!pDoc) + return; + + if (!wxGetApp().GetMainFrame()->GetOutputWindow()->IsShown()) + { + wxGetApp().GetMainFrame()->ToggleWindow(ecID_TOGGLE_OUTPUT); + } + if (!pDoc->GetDocumentSaved()) + { + pDoc->SaveAs(); + } +/* + if (pDoc->IsModified() && !wxDirExists(pDoc->GetBuildTree())) + { + pDoc->SaveAs(); + } +*/ +// if ( !(pDoc->IsModified() || !wxDirExists(pDoc->GetBuildTree())) ) // verify the save worked + if ( pDoc->GetDocumentSaved() ) + { + //wxString strCmd (wxT("c:\\bin\\testmake.bat")); + wxString strCmd (wxT("make")); + if(!strWhat.IsEmpty()) + { + strCmd += wxT(' '); + strCmd += strWhat; + } + + if(!GetSettings().m_strMakeOptions.IsEmpty()) + { + strCmd += wxT(' '); + strCmd += GetSettings().m_strMakeOptions; + } + strCmd += wxT(" --directory "); + strCmd += pDoc->GetBuildTree(); + + wxString variableSettings; + + if (PrepareEnvironment(TRUE, & variableSettings)) + { +#ifdef __WXMSW__ + // strCmd is all we need +#else + // strCmd has to invoke a shell with variables and make invocation + strCmd = wxString(wxT("sh -c \"")) + variableSettings + strCmd + wxString(wxT("\"")); +#endif + // Output the command so we know what we're doing + Log(strCmd); + Log(wxT("\n")); + + // No: pass --directory + // wxSetWorkingDirectory(pDoc->GetBuildTree()); + + m_pipedProcess = new ecPipedProcess; + int pid = wxExecute(strCmd, FALSE, m_pipedProcess); + if ( pid ) + { + // wxLogStatus(_T("Process %ld (%s) launched."), pid, cmd.c_str()); + } + else + { + wxLogError(_T("Execution of '%s' failed."), strCmd.c_str()); + + delete m_pipedProcess; + m_pipedProcess = NULL; + } + } + +#if 0 + if(PrepareEnvironment()) + { + m_strBuildTarget=strWhat; + SetThermometerMax(250); // This is just a guess. The thread we are about to spawn will work out the correct answer + m_nLogicalLines=0; + UpdateThermometer(0); + CloseHandle(CreateThread(NULL, 0, ThreadFunc, this, 0 ,&m_dwThreadId)); + CString strMsg; + strMsg.Format(_T("Building %s"),strWhat); + SetIdleMessage(strMsg); + + SetTimer(42,1000,0); // This timer checks for process completion + SetCurrentDirectory(pDoc->BuildTree()); + m_sp.Run(SubprocessOutputFunc, this, strCmd, false); + SetIdleMessage(); + } +#endif + } +#if 0 + + if(pDoc->IsModified()||pDoc->BuildTree().IsEmpty()){ + SendMessage (WM_COMMAND, ID_FILE_SAVE); + } + + if(!(pDoc->IsModified()||pDoc->BuildTree().IsEmpty())){ // verify the save worked + CString strCmd (_T("make")); + if(!strWhat.IsEmpty()){ + strCmd+=_TCHAR(' '); + strCmd+=strWhat; + } + if(!GetApp()->m_strMakeOptions.IsEmpty()){ + strCmd+=_TCHAR(' '); + strCmd+=GetApp()->m_strMakeOptions; + } + + if(PrepareEnvironment()){ + m_strBuildTarget=strWhat; + SetThermometerMax(250); // This is just a guess. The thread we are about to spawn will work out the correct answer + m_nLogicalLines=0; + UpdateThermometer(0); + CloseHandle(CreateThread(NULL, 0, ThreadFunc, this, 0 ,&m_dwThreadId)); + CString strMsg; + strMsg.Format(_T("Building %s"),strWhat); + SetIdleMessage(strMsg); + + SetTimer(42,1000,0); // This timer checks for process completion + SetCurrentDirectory(pDoc->BuildTree()); + m_sp.Run(SubprocessOutputFunc, this, strCmd, false); + SetIdleMessage(); + } + } +#endif +} + +void ecApp::OnProcessTerminated(wxProcess* process) +{ + m_pipedProcess = NULL; +} + +// ---------------------------------------------------------------------------- +// ecPipedProcess +// ---------------------------------------------------------------------------- + +bool ecPipedProcess::HasInput() +{ + bool hasInput = FALSE; + + wxInputStream& is = *GetInputStream(); + if ( !is.Eof() ) + { + wxTextInputStream tis(is); + + // this assumes that the output is always line buffered + wxString msg; + msg << tis.ReadLine(); + + wxGetApp().Log(msg); + + hasInput = TRUE; + } + + wxInputStream& es = *GetErrorStream(); + if ( !es.Eof() ) + { + wxTextInputStream tis(es); + + // this assumes that the output is always line buffered + wxString msg; + msg << tis.ReadLine(); + + wxGetApp().Log(msg); + + hasInput = TRUE; + } + + return hasInput; +} + +void ecPipedProcess::OnTerminate(int pid, int status) +{ + // show the rest of the output + while ( HasInput() ) + ; + + wxGetApp().OnProcessTerminated(this); + + //wxLogStatus(m_parent, _T("Process %u ('%s') terminated with exit code %d."), + // pid, m_cmd.c_str(), status); + + // we're not needed any more + delete this; +} + +void ecPingTimer::Notify() +{ + static bool s_inNotify = FALSE; + + if (s_inNotify) + return; + + s_inNotify = TRUE; + + // On Windows, simply having the timer going will ping the message queue + // and cause idle processing to happen. + // On Unix, this doesn't happen so we have to do the processing explicitly. +#ifdef __WXMSW__ + // Nothing to do +#else + // Get some input + if ( wxGetApp().m_pipedProcess ) + while (wxGetApp().m_pipedProcess->HasInput()) + { + // Loop while there is still input + } +#endif + + s_inNotify = FALSE; +} +
