X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0470b3826a114b510bb4937daa137ee061541b04..c5453c7956e115a1e7290f01cbbd730a5d8f3448:/utils/emulator/src/emulator.cpp?ds=sidebyside diff --git a/utils/emulator/src/emulator.cpp b/utils/emulator/src/emulator.cpp index bf43a462ce..41ef3eec8f 100644 --- a/utils/emulator/src/emulator.cpp +++ b/utils/emulator/src/emulator.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // Name: emulator.cpp -// Purpose: Emulator wxWindows sample +// Purpose: Emulator wxWidgets sample // Author: Julian Smart // Modified by: // Created: 04/01/98 @@ -13,10 +13,6 @@ // declarations // ============================================================================ -#ifdef __GNUG__ - #pragma implementation "emulator.h" -#endif - // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- @@ -29,12 +25,19 @@ #endif // for all others, include the necessary headers (this file is usually all you -// need because it includes almost all "standard" wxWindows headers) +// need because it includes almost all "standard" wxWidgets headers) #ifndef WX_PRECOMP #include "wx/wx.h" #endif -#ifdef __WXX11__ +#include "wx/confbase.h" +#include "wx/fileconf.h" +#include "wx/cmdline.h" +#include "wx/image.h" +#include "wx/file.h" +#include "wx/filename.h" + +#ifdef __WXX11__ #include "wx/x11/reparent.h" #endif @@ -45,29 +48,43 @@ // ---------------------------------------------------------------------------- // the application icon (under Windows and OS/2 it is in resources) -#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__) - #include "mondrian.xpm" +#ifndef wxHAS_IMAGES_IN_RESOURCES + #include "emulator.xpm" #endif // ---------------------------------------------------------------------------- -// event tables and other macros for wxWindows +// event tables and other macros for wxWidgets // ---------------------------------------------------------------------------- -// the event tables connect the wxWindows events with the functions (event +// the event tables connect the wxWidgets events with the functions (event // handlers) which process them. It can be also done at run-time, but for the // simple menu events like this the static method is much simpler. BEGIN_EVENT_TABLE(wxEmulatorFrame, wxFrame) EVT_MENU(Emulator_Quit, wxEmulatorFrame::OnQuit) EVT_MENU(Emulator_About, wxEmulatorFrame::OnAbout) + EVT_CLOSE(wxEmulatorFrame::OnCloseWindow) END_EVENT_TABLE() -// Create a new application object: this macro will allow wxWindows to create +// Create a new application object: this macro will allow wxWidgets to create // the application object during program execution (it's better than using a // static object for many reasons) and also declares the accessor function // wxGetApp() which will return the reference of the right type (i.e. wxEmulatorApp and // not wxApp) IMPLEMENT_APP(wxEmulatorApp) +static const wxCmdLineEntryDesc sg_cmdLineDesc[] = +{ + { wxCMD_LINE_OPTION, "u", "use-display", "display number to use (default 100)" }, + + { wxCMD_LINE_SWITCH, "h", "help", "displays help on the command line parameters" }, + { wxCMD_LINE_SWITCH, "v", "version", "print version" }, + + { wxCMD_LINE_PARAM, NULL, NULL, "config file 1", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, + + wxCMD_LINE_DESC_END +}; + + // ============================================================================ // implementation // ============================================================================ @@ -80,89 +97,163 @@ wxEmulatorApp::wxEmulatorApp() { m_xnestWindow = NULL; m_containerWindow = NULL; + m_displayNumber = wxT("100"); + m_xnestPID = 0; + } // 'Main program' equivalent: the program execution "starts" here bool wxEmulatorApp::OnInit() { +#if wxUSE_LOG + wxLog::DisableTimestamp(); +#endif // wxUSE_LOG wxInitAllImageHandlers(); - // create the main application window - wxEmulatorFrame *frame = new wxEmulatorFrame(_T("wxEmulator"), - wxPoint(50, 50), wxSize(450, 340)); - - m_containerWindow = new wxEmulatorContainer(frame, -1); + wxString currentDir = wxGetCwd(); + + // Use argv to get current app directory + m_appDir = wxFindAppPath(argv[0], currentDir, wxT("WXEMUDIR")); + + // If the development version, go up a directory. +#ifdef __WXMSW__ + if ((m_appDir.Right(5).CmpNoCase(wxT("DEBUG")) == 0) || + (m_appDir.Right(11).CmpNoCase(wxT("DEBUGSTABLE")) == 0) || + (m_appDir.Right(7).CmpNoCase(wxT("RELEASE")) == 0) || + (m_appDir.Right(13).CmpNoCase(wxT("RELEASESTABLE")) == 0) + ) + m_appDir = wxPathOnly(m_appDir); +#endif + + // Parse the command-line parameters and options + wxCmdLineParser parser(sg_cmdLineDesc, argc, argv); + int res; + { + wxLogNull log; + res = parser.Parse(); + } + if (res == -1 || res > 0 || parser.Found(wxT("h"))) + { +#ifdef __X__ + wxLog::SetActiveTarget(new wxLogStderr); +#endif + parser.Usage(); + return false; + } + if (parser.Found(wxT("v"))) + { +#ifdef __X__ + wxLog::SetActiveTarget(new wxLogStderr); +#endif + wxString msg; + msg.Printf(wxT("wxWidgets PDA Emulator (c) Julian Smart, 2002 Version %.2f, %s"), wxEMULATOR_VERSION, __DATE__); + wxLogMessage(msg); + return false; + } + if (parser.Found(wxT("u"), & m_displayNumber)) + { + // Should only be number, so strip out anything before + // and including a : character + if (m_displayNumber.Find(wxT(':')) != -1) + { + m_displayNumber = m_displayNumber.AfterFirst(wxT(':')); + } + } + if (parser.GetParamCount() == 0) + { + m_emulatorInfo.m_emulatorFilename = wxT("default.wxe"); + } + else if (parser.GetParamCount() > 0) + { + m_emulatorInfo.m_emulatorFilename = parser.GetParam(0); + } // Load the emulation info - if (!LoadEmulator()) + if (!LoadEmulator(m_appDir)) { - frame->Destroy(); - wxMessageBox(wxT("Sorry, could not load this emulator. Please check bitmaps are valid.")); - return FALSE; + //wxMessageBox(wxT("Sorry, could not load this emulator. Please check bitmaps are valid.")); + return false; } - - if (m_emulatorInfo.m_emulatorBackgroundBitmap.Ok()) - frame->SetClientSize(m_emulatorInfo.m_emulatorBackgroundBitmap.GetWidth(), - m_emulatorInfo.m_emulatorBackgroundBitmap.GetHeight()); - + + // create the main application window + wxEmulatorFrame *frame = new wxEmulatorFrame(wxT("wxEmulator"), + wxPoint(50, 50), wxSize(450, 340)); + +#if wxUSE_STATUSBAR + frame->SetStatusText(m_emulatorInfo.m_emulatorTitle, 0); + + wxString sizeStr; + sizeStr.Printf(wxT("Screen: %dx%d"), (int) m_emulatorInfo.m_emulatorScreenSize.x, + (int) m_emulatorInfo.m_emulatorScreenSize.y); + frame->SetStatusText(sizeStr, 1); +#endif // wxUSE_STATUSBAR + + m_containerWindow = new wxEmulatorContainer(frame, wxID_ANY); + + frame->SetClientSize(m_emulatorInfo.m_emulatorDeviceSize.x, + m_emulatorInfo.m_emulatorDeviceSize.y); + // and show it (the frames, unlike simple controls, are not shown when // created initially) - frame->Show(TRUE); - -#ifdef __WXX11__ + frame->Show(true); + +#ifdef __WXX11__ m_xnestWindow = new wxAdoptedWindow; wxString cmd; - // cmd.Printf(wxT("Xnest :100 -geometry %dx%d+50+50"), - cmd.Printf(wxT("Xnest :100 -geometry %dx%d"), - (int) m_emulatorInfo.m_emulatorScreenSize.x, (int) m_emulatorInfo.m_emulatorScreenSize.y); - - // Asynchronously executes Xnest - if (0 == wxExecute(cmd)) + cmd.Printf(wxT("Xnest :%s -geometry %dx%d"), + m_displayNumber.c_str(), + (int) m_emulatorInfo.m_emulatorScreenSize.x, + (int) m_emulatorInfo.m_emulatorScreenSize.y); + + // Asynchronously executes Xnest + m_xnestPID = wxExecute(cmd); + if (0 == m_xnestPID) { frame->Destroy(); wxMessageBox(wxT("Sorry, could not run Xnest. Please check your PATH.")); - return FALSE; + return false; } - + wxReparenter reparenter; if (!reparenter.WaitAndReparent(m_containerWindow, m_xnestWindow, wxT("Xnest"))) { wxMessageBox(wxT("Sorry, could not reparent Xnest..")); frame->Destroy(); - return FALSE; + return false; } - m_containerWindow->DoResize(); #endif + m_containerWindow->DoResize(); // success: wxApp::OnRun() will be called which will enter the main message - // loop and the application will run. If we returned FALSE here, the + // loop and the application will run. If we returned false here, the // application would exit immediately. - return TRUE; + return true; } -// Load the specified emulator. -// For now, hard-wired. TODO: make this configurable -bool wxEmulatorApp::LoadEmulator() +// Prepend the current program directory to the name +wxString wxEmulatorApp::GetFullAppPath(const wxString& filename) const { - m_emulatorInfo.m_emulatorTitle = wxT("iPAQ Emulator"); - - m_emulatorInfo.m_emulatorDescription = wxT("No description yet"); - - // The offset from the top-left of the main emulator - // bitmap and the virtual screen (where Xnest is - // positioned) - m_emulatorInfo.m_emulatorScreenPosition = wxPoint(56, 69); + wxString path(m_appDir); + if (path.Last() != '\\' && path.Last() != '/' && filename[0] != '\\' && filename[0] != '/') +#ifdef __X__ + path += '/'; +#else + path += '\\'; +#endif + path += filename; - // The emulated screen size - m_emulatorInfo.m_emulatorScreenSize = wxSize(240, 320); + return path; +} - m_emulatorInfo.m_emulatorBackgroundBitmapName = wxT("ipaq01.jpg"); - m_emulatorInfo.m_emulatorBackgroundColour = * wxBLACK; - - return m_emulatorInfo.Load(); +// Load the specified emulator. +// For now, hard-wired. TODO: make this configurable +bool wxEmulatorApp::LoadEmulator(const wxString& appDir) +{ + // Load config file and bitmaps + return m_emulatorInfo.Load(appDir); } // ---------------------------------------------------------------------------- @@ -170,11 +261,12 @@ bool wxEmulatorApp::LoadEmulator() // ---------------------------------------------------------------------------- // frame constructor -wxEmulatorFrame::wxEmulatorFrame(const wxString& title, const wxPoint& pos, const wxSize& size) - : wxFrame(NULL, -1, title, pos, size) +wxEmulatorFrame::wxEmulatorFrame(const wxString& title, + const wxPoint& pos, const wxSize& size) + : wxFrame(NULL, wxID_ANY, title, pos, size) { // set the frame icon - SetIcon(wxICON(mondrian)); + SetIcon(wxICON(emulator)); #if wxUSE_MENUS // create a menu bar @@ -182,14 +274,14 @@ wxEmulatorFrame::wxEmulatorFrame(const wxString& title, const wxPoint& pos, cons // the "About" item should be in the help menu wxMenu *helpMenu = new wxMenu; - helpMenu->Append(Emulator_About, _T("&About...\tF1"), _T("Show about dialog")); + helpMenu->Append(Emulator_About, wxT("&About\tF1"), wxT("Show about dialog")); - menuFile->Append(Emulator_Quit, _T("E&xit\tAlt-X"), _T("Quit this program")); + menuFile->Append(Emulator_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program")); // now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar(); - menuBar->Append(menuFile, _T("&File")); - menuBar->Append(helpMenu, _T("&Help")); + menuBar->Append(menuFile, wxT("&File")); + menuBar->Append(helpMenu, wxT("&Help")); // ... and attach this menu bar to the frame SetMenuBar(menuBar); @@ -198,7 +290,6 @@ wxEmulatorFrame::wxEmulatorFrame(const wxString& title, const wxPoint& pos, cons #if wxUSE_STATUSBAR // create a status bar just for fun (by default with 1 pane only) CreateStatusBar(2); - SetStatusText(_T("Welcome to wxWindows!")); #endif // wxUSE_STATUSBAR } @@ -207,16 +298,32 @@ wxEmulatorFrame::wxEmulatorFrame(const wxString& title, const wxPoint& pos, cons void wxEmulatorFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { - // TRUE is to force the frame to close - Close(TRUE); + // true is to force the frame to close + Close(true); } void wxEmulatorFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { wxString msg; - msg.Printf( _T("wxEmulator is an environment for testing embedded X11 apps.\n")); + msg.Printf( wxT("wxEmulator is an environment for testing embedded X11 apps.\n")); - wxMessageBox(msg, _T("About wxEmulator"), wxOK | wxICON_INFORMATION, this); + wxMessageBox(msg, wxT("About wxEmulator"), wxOK | wxICON_INFORMATION, this); +} + +void wxEmulatorFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event)) +{ +#ifdef __WXX11__ + if (wxGetApp().m_xnestWindow) + { + wxGetApp().m_xnestWindow->SetHandle((WXWindow) NULL); + } +#endif + this->Destroy(); + if (wxGetApp().m_xnestPID > 0) + { + wxKill(wxGetApp().m_xnestPID); + wxGetApp().m_xnestPID = 0; + } } IMPLEMENT_CLASS(wxEmulatorContainer, wxWindow) @@ -232,7 +339,7 @@ wxEmulatorContainer::wxEmulatorContainer(wxWindow* parent, wxWindowID id): { } -void wxEmulatorContainer::OnSize(wxSizeEvent& event) +void wxEmulatorContainer::OnSize(wxSizeEvent& WXUNUSED(event)) { DoResize(); } @@ -240,44 +347,47 @@ void wxEmulatorContainer::OnSize(wxSizeEvent& event) void wxEmulatorContainer::DoResize() { wxSize sz = GetClientSize(); - if (wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.Ok() && - wxGetApp().m_xnestWindow) + if (wxGetApp().m_xnestWindow +#ifdef __WXX11__ + && wxGetApp().m_xnestWindow->X11GetMainWindow() +#endif + ) { - int bitmapWidth = wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.GetWidth(); - int bitmapHeight = wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.GetHeight(); - - int x = wxMax(0, (int) ((sz.x - bitmapWidth)/2.0)); - int y = wxMax(0, (int) ((sz.y - bitmapHeight)/2.0)); - + int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x; + int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y; + + int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0)); + int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0)); + x += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.x; y += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.y; - + wxGetApp().m_xnestWindow->Move(x, y); } Refresh(); } -void wxEmulatorContainer::OnPaint(wxPaintEvent& event) +void wxEmulatorContainer::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); - + wxSize sz = GetClientSize(); - if (wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.Ok()) + if (wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.IsOk()) { - int bitmapWidth = wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.GetWidth(); - int bitmapHeight = wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.GetHeight(); - - int x = wxMax(0, (int) ((sz.x - bitmapWidth)/2.0)); - int y = wxMax(0, (int) ((sz.y - bitmapHeight)/2.0)); - + int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x; + int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y; + + int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0)); + int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0)); + dc.DrawBitmap(wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap, x, y); } } void wxEmulatorContainer::OnEraseBackground(wxEraseEvent& event) { - wxDC* dc = NULL; - + wxDC* dc wxDUMMY_INITIALIZE(NULL); + if (event.GetDC()) { dc = event.GetDC(); @@ -286,10 +396,10 @@ void wxEmulatorContainer::OnEraseBackground(wxEraseEvent& event) { dc = new wxClientDC(this); } - + dc->SetBackground(wxBrush(wxGetApp().m_emulatorInfo.m_emulatorBackgroundColour, wxSOLID)); dc->Clear(); - + if (!event.GetDC()) delete dc; } @@ -298,6 +408,7 @@ void wxEmulatorContainer::OnEraseBackground(wxEraseEvent& event) void wxEmulatorInfo::Copy(const wxEmulatorInfo& info) { + m_emulatorFilename = info.m_emulatorFilename; m_emulatorTitle = info.m_emulatorTitle; m_emulatorDescription = info.m_emulatorDescription; m_emulatorScreenPosition = info.m_emulatorScreenPosition; @@ -305,49 +416,193 @@ void wxEmulatorInfo::Copy(const wxEmulatorInfo& info) m_emulatorBackgroundBitmap = info.m_emulatorBackgroundBitmap; m_emulatorBackgroundBitmapName = info.m_emulatorBackgroundBitmapName; m_emulatorBackgroundColour = info.m_emulatorBackgroundColour; + m_emulatorDeviceSize = info.m_emulatorDeviceSize; } // Initialisation void wxEmulatorInfo::Init() { + m_emulatorDeviceSize = wxSize(260, 340); + m_emulatorScreenSize = wxSize(240, 320); } // Loads bitmaps -bool wxEmulatorInfo::Load() +bool wxEmulatorInfo::Load(const wxString& appDir) { - if (m_emulatorBackgroundBitmapName.IsEmpty()) - return FALSE; - - // TODO: prepend current directory if relative name - int type = wxDetermineImageType(m_emulatorBackgroundBitmapName); - if (type == -1) - return FALSE; - - return m_emulatorBackgroundBitmap.LoadFile(m_emulatorBackgroundBitmapName, type); + // Try to find absolute path + wxString absoluteConfigPath = m_emulatorFilename; + if ( !::wxIsAbsolutePath(absoluteConfigPath) ) + { + wxString currDir = wxGetCwd(); + absoluteConfigPath = currDir + wxString(wxFILE_SEP_PATH) + m_emulatorFilename; + if ( !wxFile::Exists(absoluteConfigPath) ) + { + absoluteConfigPath = appDir + wxString(wxFILE_SEP_PATH) + + m_emulatorFilename; + } + } + + if ( !wxFile::Exists(absoluteConfigPath) ) + { + wxString str; + str.Printf( wxT("Could not find config file %s"), + absoluteConfigPath.c_str() ); + + wxMessageBox(str); + return false; + } + + wxString rootPath = wxPathOnly(absoluteConfigPath); + + { + wxFileConfig config(wxT("wxEmulator"), wxT("wxWidgets"), + absoluteConfigPath, wxEmptyString, wxCONFIG_USE_LOCAL_FILE); + + config.Read(wxT("/General/title"), & m_emulatorTitle); + config.Read(wxT("/General/description"), & m_emulatorDescription); + config.Read(wxT("/General/backgroundBitmap"), & m_emulatorBackgroundBitmapName); + + wxString colString; + if (config.Read(wxT("/General/backgroundColour"), & colString) || + config.Read(wxT("/General/backgroundColor"), & colString) + ) + { + m_emulatorBackgroundColour = wxHexStringToColour(colString); + } + + int x = 0, y = 0, w = 0, h = 0, dw = 0, dh = 0; + config.Read(wxT("/General/screenX"), & x); + config.Read(wxT("/General/screenY"), & y); + config.Read(wxT("/General/screenWidth"), & w); + config.Read(wxT("/General/screenHeight"), & h); + if (config.Read(wxT("/General/deviceWidth"), & dw) && config.Read(wxT("/General/deviceHeight"), & dh)) + { + m_emulatorDeviceSize = wxSize(dw, dh); + } + + m_emulatorScreenPosition = wxPoint(x, y); + m_emulatorScreenSize = wxSize(w, h); + } + + if (!m_emulatorBackgroundBitmapName.empty()) + { + wxString absoluteBackgroundBitmapName = rootPath + wxString(wxFILE_SEP_PATH) + m_emulatorBackgroundBitmapName; + if ( !wxFile::Exists(absoluteBackgroundBitmapName) ) + { + wxString str; + str.Printf( wxT("Could not find bitmap %s"), + absoluteBackgroundBitmapName.c_str() ); + wxMessageBox(str); + return false; + } + + wxBitmapType type = wxDetermineImageType(m_emulatorBackgroundBitmapName); + if (type == wxBITMAP_TYPE_INVALID) + return false; + + if (!m_emulatorBackgroundBitmap.LoadFile(m_emulatorBackgroundBitmapName, type)) + { + wxString str; + str.Printf( wxT("Could not load bitmap file %s"), + m_emulatorBackgroundBitmapName.c_str() ); + wxMessageBox(str); + return false; + } + + m_emulatorDeviceSize = wxSize(m_emulatorBackgroundBitmap.GetWidth(), + m_emulatorBackgroundBitmap.GetHeight()); + } + return true; } // Returns the image type, or -1, determined from the extension. -int wxDetermineImageType(const wxString& filename) +wxBitmapType wxDetermineImageType(const wxString& filename) { wxString path, name, ext; - wxSplitPath(filename, & path, & name, & ext); + wxFileName::SplitPath(filename, & path, & name, & ext); ext.MakeLower(); - if (ext == "jpg" || ext == "jpeg") + if (ext == wxT("jpg") || ext == wxT("jpeg")) return wxBITMAP_TYPE_JPEG; - else if (ext == "gif") + if (ext == wxT("gif")) return wxBITMAP_TYPE_GIF; - else if (ext == "bmp") + if (ext == wxT("bmp")) return wxBITMAP_TYPE_BMP; - else if (ext == "png") + if (ext == wxT("png")) return wxBITMAP_TYPE_PNG; - else if (ext == "pcx") + if (ext == wxT("pcx")) return wxBITMAP_TYPE_PCX; - else if (ext == "tif" || ext == "tiff") - return wxBITMAP_TYPE_TIF; - else - return -1; + if (ext == wxT("tif") || ext == wxT("tiff")) + return wxBITMAP_TYPE_TIFF; + + return wxBITMAP_TYPE_INVALID; +} + +// Convert a colour to a 6-digit hex string +wxString wxColourToHexString(const wxColour& col) +{ + wxString hex; + + hex += wxDecToHex(col.Red()); + hex += wxDecToHex(col.Green()); + hex += wxDecToHex(col.Blue()); + + return hex; +} + +// Convert 6-digit hex string to a colour +wxColour wxHexStringToColour(const wxString& hex) +{ + unsigned char r = (unsigned char)wxHexToDec(hex.Mid(0, 2)); + unsigned char g = (unsigned char)wxHexToDec(hex.Mid(2, 2)); + unsigned char b = (unsigned char)wxHexToDec(hex.Mid(4, 2)); + + return wxColour(r, g, b); } +// Find the absolute path where this application has been run from. +// argv0 is wxTheApp->argv[0] +// cwd is the current working directory (at startup) +// appVariableName is the name of a variable containing the directory for this app, e.g. +// MYAPPDIR. This is checked first. + +wxString wxFindAppPath(const wxString& argv0, const wxString& cwd, const wxString& appVariableName) +{ + wxString str; + + // Try appVariableName + if (!appVariableName.empty()) + { + str = wxGetenv(appVariableName); + if (!str.empty()) + return str; + } + + if (wxIsAbsolutePath(argv0)) + return wxPathOnly(argv0); + else + { + // Is it a relative path? + wxString currentDir(cwd); + if (!wxEndsWithPathSeparator(currentDir)) + currentDir += wxFILE_SEP_PATH; + + str = currentDir + argv0; + if ( wxFile::Exists(str) ) + return wxPathOnly(str); + } + + // OK, it's neither an absolute path nor a relative path. + // Search PATH. + + wxPathList pathList; + pathList.AddEnvList(wxT("PATH")); + str = pathList.FindAbsoluteValidPath(argv0); + if (!str.empty()) + return wxPathOnly(str); + + // Failed + return wxEmptyString; +}