home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / utils / emulator / src / emulator.cpp < prev    next >
C/C++ Source or Header  |  2002-07-14  |  19KB  |  602 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        emulator.cpp
  3. // Purpose:     Emulator wxWindows sample
  4. // Author:      Julian Smart
  5. // Modified by:
  6. // Created:     04/01/98
  7. // RCS-ID:      $Id: emulator.cpp,v 1.5 2002/07/13 12:14:07 GD Exp $
  8. // Copyright:   (c) Julian Smart
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. #ifdef __GNUG__
  17.     #pragma implementation "emulator.h"
  18. #endif
  19.  
  20. // ----------------------------------------------------------------------------
  21. // headers
  22. // ----------------------------------------------------------------------------
  23.  
  24. // For compilers that support precompilation, includes "wx/wx.h".
  25. #include "wx/wxprec.h"
  26.  
  27. #ifdef __BORLANDC__
  28.     #pragma hdrstop
  29. #endif
  30.  
  31. // for all others, include the necessary headers (this file is usually all you
  32. // need because it includes almost all "standard" wxWindows headers)
  33. #ifndef WX_PRECOMP
  34.     #include "wx/wx.h"
  35. #endif
  36.  
  37. #include "wx/confbase.h"
  38. #include "wx/fileconf.h"
  39. #include "wx/cmdline.h"
  40. #include "wx/image.h"
  41.  
  42. #ifdef __WXX11__    
  43. #include "wx/x11/reparent.h"
  44. #endif
  45.  
  46. #include "emulator.h"
  47.  
  48. // ----------------------------------------------------------------------------
  49. // resources
  50. // ----------------------------------------------------------------------------
  51.  
  52. // the application icon (under Windows and OS/2 it is in resources)
  53. #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
  54.     #include "emulator.xpm"
  55. #endif
  56.  
  57. // ----------------------------------------------------------------------------
  58. // event tables and other macros for wxWindows
  59. // ----------------------------------------------------------------------------
  60.  
  61. // the event tables connect the wxWindows events with the functions (event
  62. // handlers) which process them. It can be also done at run-time, but for the
  63. // simple menu events like this the static method is much simpler.
  64. BEGIN_EVENT_TABLE(wxEmulatorFrame, wxFrame)
  65.     EVT_MENU(Emulator_Quit,  wxEmulatorFrame::OnQuit)
  66.     EVT_MENU(Emulator_About, wxEmulatorFrame::OnAbout)
  67.     EVT_CLOSE(wxEmulatorFrame::OnCloseWindow)
  68. END_EVENT_TABLE()
  69.  
  70. // Create a new application object: this macro will allow wxWindows to create
  71. // the application object during program execution (it's better than using a
  72. // static object for many reasons) and also declares the accessor function
  73. // wxGetApp() which will return the reference of the right type (i.e. wxEmulatorApp and
  74. // not wxApp)
  75. IMPLEMENT_APP(wxEmulatorApp)
  76.  
  77. static const wxCmdLineEntryDesc sg_cmdLineDesc[] =
  78. {
  79.     { wxCMD_LINE_OPTION, "u", "use-display",   "display number to use (default 100)" },
  80.  
  81.     { wxCMD_LINE_SWITCH, "h", "help",   "displays help on the command line parameters" },
  82.     { wxCMD_LINE_SWITCH, "v", "version",    "print version" },
  83.  
  84.     { wxCMD_LINE_PARAM,  NULL, NULL, "config file 1", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
  85.  
  86.     { wxCMD_LINE_NONE }
  87. };
  88.  
  89.  
  90. // ============================================================================
  91. // implementation
  92. // ============================================================================
  93.  
  94. // ----------------------------------------------------------------------------
  95. // the application class
  96. // ----------------------------------------------------------------------------
  97.  
  98. wxEmulatorApp::wxEmulatorApp()
  99. {
  100.     m_xnestWindow = NULL;
  101.     m_containerWindow = NULL;
  102.     m_displayNumber = wxT("100");
  103.     m_xnestPID = 0;
  104.  
  105. }
  106.  
  107. // 'Main program' equivalent: the program execution "starts" here
  108. bool wxEmulatorApp::OnInit()
  109. {
  110.     wxLog::SetTimestamp(NULL);
  111.     wxInitAllImageHandlers();
  112.  
  113.     wxString currentDir = wxGetCwd();
  114.  
  115.     // Use argv to get current app directory
  116.     m_appDir = wxFindAppPath(argv[0], currentDir, wxT("WXEMUDIR"));
  117.     
  118.     // If the development version, go up a directory.
  119. #ifdef __WXMSW__
  120.     if ((m_appDir.Right(5).CmpNoCase("DEBUG") == 0) ||
  121.         (m_appDir.Right(11).CmpNoCase("DEBUGSTABLE") == 0) ||
  122.         (m_appDir.Right(7).CmpNoCase("RELEASE") == 0) ||
  123.         (m_appDir.Right(13).CmpNoCase("RELEASESTABLE") == 0)
  124.         )
  125.         m_appDir = wxPathOnly(m_appDir);
  126. #endif
  127.  
  128.     // Parse the command-line parameters and options
  129.     wxCmdLineParser parser(sg_cmdLineDesc, argc, argv);
  130.     int res;
  131.     {
  132.         wxLogNull log;
  133.         res = parser.Parse();
  134.     }
  135.     if (res == -1 || res > 0 || parser.Found(wxT("h")))
  136.     {
  137. #ifdef __X__
  138.         wxLog::SetActiveTarget(new wxLogStderr);
  139. #endif
  140.         parser.Usage();
  141.         return FALSE;
  142.     }
  143.     if (parser.Found(wxT("v")))
  144.     {
  145. #ifdef __X__
  146.         wxLog::SetActiveTarget(new wxLogStderr);
  147. #endif
  148.         wxString msg;
  149.         msg.Printf(wxT("wxWindows PDA Emulator (c) Julian Smart, 2002 Version %.2f, %s"), wxEMULATOR_VERSION, __DATE__);
  150.         wxLogMessage(msg);
  151.         return FALSE;
  152.     }
  153.     if (parser.Found(wxT("u"), & m_displayNumber))
  154.     {
  155.         // Should only be number, so strip out anything before
  156.         // and including a : character
  157.         if (m_displayNumber.Find(wxT(':')) != -1)
  158.         {
  159.             m_displayNumber = m_displayNumber.AfterFirst(wxT(':'));
  160.         }
  161.     }
  162.     if (parser.GetParamCount() == 0)
  163.     {
  164.         m_emulatorInfo.m_emulatorFilename = wxT("default.wxe");
  165.     }
  166.     else if (parser.GetParamCount() > 0)
  167.     {
  168.         m_emulatorInfo.m_emulatorFilename = parser.GetParam(0);
  169.     }
  170.  
  171.     // Load the emulation info
  172.     if (!LoadEmulator(m_appDir))
  173.     {
  174.         //wxMessageBox(wxT("Sorry, could not load this emulator. Please check bitmaps are valid."));
  175.         return FALSE;        
  176.     }
  177.     
  178.     // create the main application window
  179.     wxEmulatorFrame *frame = new wxEmulatorFrame(_T("wxEmulator"),
  180.                                  wxPoint(50, 50), wxSize(450, 340));
  181.                                 
  182.     frame->SetStatusText(m_emulatorInfo.m_emulatorTitle, 0);
  183.  
  184.     wxString sizeStr;
  185.     sizeStr.Printf(wxT("Screen: %dx%d"), (int) m_emulatorInfo.m_emulatorScreenSize.x,
  186.             (int) m_emulatorInfo.m_emulatorScreenSize.y);
  187.     frame->SetStatusText(sizeStr, 1);
  188.  
  189.     m_containerWindow = new wxEmulatorContainer(frame, -1);
  190.  
  191.     frame->SetClientSize(m_emulatorInfo.m_emulatorDeviceSize.x,
  192.                          m_emulatorInfo.m_emulatorDeviceSize.y);
  193.     
  194.     // and show it (the frames, unlike simple controls, are not shown when
  195.     // created initially)
  196.     frame->Show(TRUE);
  197.     
  198. #ifdef __WXX11__    
  199.     m_xnestWindow = new wxAdoptedWindow;
  200.  
  201.     wxString cmd;
  202.     cmd.Printf(wxT("Xnest :%s -geometry %dx%d"),
  203.         m_displayNumber.c_str(),
  204.         (int) m_emulatorInfo.m_emulatorScreenSize.x,
  205.         (int) m_emulatorInfo.m_emulatorScreenSize.y);
  206.  
  207.     // Asynchronously executes Xnest
  208.     m_xnestPID = wxExecute(cmd);
  209.     if (0 == m_xnestPID)
  210.     {
  211.         frame->Destroy();
  212.         wxMessageBox(wxT("Sorry, could not run Xnest. Please check your PATH."));
  213.         return FALSE;
  214.     }
  215.     
  216.     wxReparenter reparenter;
  217.     if (!reparenter.WaitAndReparent(m_containerWindow, m_xnestWindow, wxT("Xnest")))
  218.     {
  219.         wxMessageBox(wxT("Sorry, could not reparent Xnest.."));
  220.         frame->Destroy();
  221.         return FALSE;
  222.     }
  223.  
  224. #endif
  225.     m_containerWindow->DoResize();
  226.  
  227.     // success: wxApp::OnRun() will be called which will enter the main message
  228.     // loop and the application will run. If we returned FALSE here, the
  229.     // application would exit immediately.
  230.     return TRUE;
  231. }
  232.  
  233. // Prepend the current program directory to the name
  234. wxString wxEmulatorApp::GetFullAppPath(const wxString& filename) const
  235. {
  236.     wxString path(m_appDir);
  237.     if (path.Last() != '\\' && path.Last() != '/' && filename[0] != '\\' && filename[0] != '/')
  238. #ifdef __X__
  239.         path += '/';
  240. #else
  241.         path += '\\';
  242. #endif
  243.     path += filename;
  244.     
  245.     return path;
  246. }
  247.  
  248.  
  249. // Load the specified emulator.
  250. // For now, hard-wired. TODO: make this configurable
  251. bool wxEmulatorApp::LoadEmulator(const wxString& appDir)
  252. {
  253.     // Load config file and bitmaps
  254.     return m_emulatorInfo.Load(appDir);
  255. }
  256.  
  257. // ----------------------------------------------------------------------------
  258. // main frame
  259. // ----------------------------------------------------------------------------
  260.  
  261. // frame constructor
  262. wxEmulatorFrame::wxEmulatorFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
  263.        : wxFrame(NULL, -1, title, pos, size)
  264. {
  265.     // set the frame icon
  266.     SetIcon(wxICON(emulator));
  267.  
  268. #if wxUSE_MENUS
  269.     // create a menu bar
  270.     wxMenu *menuFile = new wxMenu;
  271.  
  272.     // the "About" item should be in the help menu
  273.     wxMenu *helpMenu = new wxMenu;
  274.     helpMenu->Append(Emulator_About, _T("&About...\tF1"), _T("Show about dialog"));
  275.  
  276.     menuFile->Append(Emulator_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
  277.  
  278.     // now append the freshly created menu to the menu bar...
  279.     wxMenuBar *menuBar = new wxMenuBar();
  280.     menuBar->Append(menuFile, _T("&File"));
  281.     menuBar->Append(helpMenu, _T("&Help"));
  282.  
  283.     // ... and attach this menu bar to the frame
  284.     SetMenuBar(menuBar);
  285. #endif // wxUSE_MENUS
  286.  
  287. #if wxUSE_STATUSBAR
  288.     // create a status bar just for fun (by default with 1 pane only)
  289.     CreateStatusBar(2);
  290. #endif // wxUSE_STATUSBAR
  291. }
  292.  
  293.  
  294. // event handlers
  295.  
  296. void wxEmulatorFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
  297. {
  298.     // TRUE is to force the frame to close
  299.     Close(TRUE);
  300. }
  301.  
  302. void wxEmulatorFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
  303. {
  304.     wxString msg;
  305.     msg.Printf( _T("wxEmulator is an environment for testing embedded X11 apps.\n"));
  306.  
  307.     wxMessageBox(msg, _T("About wxEmulator"), wxOK | wxICON_INFORMATION, this);
  308. }
  309.  
  310. void wxEmulatorFrame::OnCloseWindow(wxCloseEvent& event)
  311. {
  312. #ifdef __WXX11__
  313.     if (wxGetApp().m_xnestWindow)
  314.     {
  315.         wxGetApp().m_xnestWindow->SetHandle((WXWindow) NULL);
  316.     }
  317. #endif
  318.     this->Destroy();
  319.     if (wxGetApp().m_xnestPID > 0)
  320.     {
  321.         wxKill(wxGetApp().m_xnestPID);
  322.         wxGetApp().m_xnestPID = 0;
  323.     }
  324. }
  325.  
  326. IMPLEMENT_CLASS(wxEmulatorContainer, wxWindow)
  327.  
  328. BEGIN_EVENT_TABLE(wxEmulatorContainer, wxWindow)
  329.     EVT_SIZE(wxEmulatorContainer::OnSize)
  330.     EVT_PAINT(wxEmulatorContainer::OnPaint)
  331.     EVT_ERASE_BACKGROUND(wxEmulatorContainer::OnEraseBackground)
  332. END_EVENT_TABLE()
  333.  
  334. wxEmulatorContainer::wxEmulatorContainer(wxWindow* parent, wxWindowID id):
  335.     wxWindow(parent, id, wxDefaultPosition, wxDefaultSize)
  336. {
  337. }
  338.  
  339. void wxEmulatorContainer::OnSize(wxSizeEvent& event)
  340. {
  341.     DoResize();
  342. }
  343.  
  344. void wxEmulatorContainer::DoResize()
  345. {
  346.     wxSize sz = GetClientSize();
  347.     if (wxGetApp().m_xnestWindow
  348. #ifdef __WXX11__
  349.         && wxGetApp().m_xnestWindow->GetMainWindow()
  350. #endif
  351.         )
  352.     {
  353.         int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x;
  354.         int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y;
  355.         
  356.         int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0));
  357.         int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0));
  358.         
  359.         x += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.x;
  360.         y += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.y;
  361.         
  362.         wxGetApp().m_xnestWindow->Move(x, y);
  363.     }
  364.     Refresh();
  365. }
  366.  
  367. void wxEmulatorContainer::OnPaint(wxPaintEvent& event)
  368. {
  369.     wxPaintDC dc(this);
  370.     
  371.     wxSize sz = GetClientSize();
  372.     if (wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.Ok())
  373.     {
  374.         int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x;
  375.         int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y;
  376.         
  377.         int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0));
  378.         int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0));
  379.         
  380.         dc.DrawBitmap(wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap, x, y);
  381.     }
  382. }
  383.  
  384. void wxEmulatorContainer::OnEraseBackground(wxEraseEvent& event)
  385. {
  386.     wxDC* dc = NULL;
  387.     
  388.     if (event.GetDC())
  389.     {
  390.         dc = event.GetDC();
  391.     }
  392.     else
  393.     {
  394.         dc = new wxClientDC(this);
  395.     }
  396.     
  397.     dc->SetBackground(wxBrush(wxGetApp().m_emulatorInfo.m_emulatorBackgroundColour, wxSOLID));
  398.     dc->Clear();
  399.     
  400.     if (!event.GetDC())
  401.         delete dc;
  402. }
  403.  
  404. // Information about the emulator decorations
  405.  
  406. void wxEmulatorInfo::Copy(const wxEmulatorInfo& info)
  407. {
  408.     m_emulatorFilename = info.m_emulatorFilename;
  409.     m_emulatorTitle = info.m_emulatorTitle;
  410.     m_emulatorDescription = info.m_emulatorDescription;
  411.     m_emulatorScreenPosition = info.m_emulatorScreenPosition;
  412.     m_emulatorScreenSize = info.m_emulatorScreenSize;
  413.     m_emulatorBackgroundBitmap = info.m_emulatorBackgroundBitmap;
  414.     m_emulatorBackgroundBitmapName = info.m_emulatorBackgroundBitmapName;
  415.     m_emulatorBackgroundColour = info.m_emulatorBackgroundColour;
  416.     m_emulatorDeviceSize = info.m_emulatorDeviceSize;
  417. }
  418.  
  419. // Initialisation
  420. void wxEmulatorInfo::Init()
  421. {
  422.     m_emulatorDeviceSize = wxSize(260, 340);
  423.     m_emulatorScreenSize = wxSize(240, 320);
  424. }
  425.  
  426. // Loads bitmaps
  427. bool wxEmulatorInfo::Load(const wxString& appDir)
  428. {
  429.     // Try to find absolute path
  430.     wxString absoluteConfigPath = m_emulatorFilename;
  431.     if (!wxIsAbsolutePath(absoluteConfigPath))
  432.     {
  433.         wxString currDir = wxGetCwd();
  434.         absoluteConfigPath = currDir + wxString(wxFILE_SEP_PATH) + m_emulatorFilename;
  435.         if (!wxFileExists(absoluteConfigPath))
  436.         {
  437.             absoluteConfigPath = appDir + wxString(wxFILE_SEP_PATH) + m_emulatorFilename;
  438.         }
  439.     }
  440.     if (!wxFileExists(absoluteConfigPath))
  441.     {
  442.         wxString str;
  443.         str.Printf(wxT("Could not find config file %s"), absoluteConfigPath.c_str()), 
  444.         wxMessageBox(str);
  445.         return FALSE;
  446.     }
  447.  
  448.     wxString rootPath = wxPathOnly(absoluteConfigPath);
  449.  
  450.     {
  451.         wxFileConfig config(wxT("wxEmulator"), wxT("wxWindows"),
  452.             absoluteConfigPath, wxEmptyString, wxCONFIG_USE_LOCAL_FILE);
  453.  
  454.         config.Read(wxT("/General/title"), & m_emulatorTitle);
  455.         config.Read(wxT("/General/description"), & m_emulatorDescription);
  456.         config.Read(wxT("/General/backgroundBitmap"), & m_emulatorBackgroundBitmapName);
  457.  
  458.         wxString colString;
  459.         if (config.Read(wxT("/General/backgroundColour"), & colString) ||
  460.             config.Read(wxT("/General/backgroundColor"), & colString)
  461.            )
  462.         {
  463.             m_emulatorBackgroundColour = wxHexStringToColour(colString);
  464.         }
  465.  
  466.         int x = 0, y = 0, w = 0, h = 0, dw = 0, dh = 0;
  467.         config.Read(wxT("/General/screenX"), & x);
  468.         config.Read(wxT("/General/screenY"), & y);
  469.         config.Read(wxT("/General/screenWidth"), & w);
  470.         config.Read(wxT("/General/screenHeight"), & h);
  471.         if (config.Read(wxT("/General/deviceWidth"), & dw) && config.Read(wxT("/General/deviceHeight"), & dh))
  472.         {
  473.             m_emulatorDeviceSize = wxSize(dw, dh);
  474.         }
  475.  
  476.         m_emulatorScreenPosition = wxPoint(x, y);
  477.         m_emulatorScreenSize = wxSize(w, h);
  478.     }
  479.     
  480.     if (!m_emulatorBackgroundBitmapName.IsEmpty())
  481.     {
  482.         wxString absoluteBackgroundBitmapName = rootPath + wxString(wxFILE_SEP_PATH) + m_emulatorBackgroundBitmapName;
  483.         if (!wxFileExists(absoluteBackgroundBitmapName))
  484.         {
  485.             wxString str;
  486.             str.Printf(wxT("Could not find bitmap %s"), absoluteBackgroundBitmapName.c_str()), 
  487.             wxMessageBox(str);
  488.             return FALSE;
  489.         }
  490.         
  491.         wxBitmapType type = wxDetermineImageType(m_emulatorBackgroundBitmapName);
  492.         if (type == wxBITMAP_TYPE_INVALID)
  493.             return FALSE;
  494.         
  495.         if (!m_emulatorBackgroundBitmap.LoadFile(m_emulatorBackgroundBitmapName, type))
  496.         {
  497.             wxString str;
  498.             str.Printf(wxT("Could not load bitmap file %s"), m_emulatorBackgroundBitmapName.c_str()), 
  499.             wxMessageBox(str);
  500.             return FALSE;
  501.         }
  502.         m_emulatorDeviceSize = wxSize(m_emulatorBackgroundBitmap.GetWidth(),
  503.             m_emulatorBackgroundBitmap.GetHeight());
  504.     }
  505.     return TRUE;
  506. }
  507.  
  508. // Returns the image type, or -1, determined from the extension.
  509. wxBitmapType wxDetermineImageType(const wxString& filename)
  510. {
  511.     wxString path, name, ext;
  512.  
  513.     wxSplitPath(filename, & path, & name, & ext);
  514.  
  515.     ext.MakeLower();
  516.     if (ext == "jpg" || ext == "jpeg")
  517.         return wxBITMAP_TYPE_JPEG;
  518.     if (ext == "gif")
  519.         return wxBITMAP_TYPE_GIF;
  520.     if (ext == "bmp")
  521.         return wxBITMAP_TYPE_BMP;
  522.     if (ext == "png")
  523.         return wxBITMAP_TYPE_PNG;
  524.     if (ext == "pcx")
  525.         return wxBITMAP_TYPE_PCX;
  526.     if (ext == "tif" || ext == "tiff")
  527.         return wxBITMAP_TYPE_TIF;
  528.     
  529.     return wxBITMAP_TYPE_INVALID;
  530. }
  531.  
  532. // Convert a colour to a 6-digit hex string
  533. wxString wxColourToHexString(const wxColour& col)
  534. {
  535.     wxString hex;
  536.  
  537.     hex += wxDecToHex(col.Red());
  538.     hex += wxDecToHex(col.Green());
  539.     hex += wxDecToHex(col.Blue());
  540.  
  541.     return hex;
  542. }
  543.  
  544. // Convert 6-digit hex string to a colour
  545. wxColour wxHexStringToColour(const wxString& hex)
  546. {
  547.     unsigned int r = 0;
  548.     unsigned int g = 0;
  549.     unsigned int b = 0;
  550.     r = wxHexToDec(hex.Mid(0, 2));
  551.     g = wxHexToDec(hex.Mid(2, 2));
  552.     b = wxHexToDec(hex.Mid(4, 2));
  553.  
  554.     return wxColour(r, g, b);
  555. }
  556.  
  557. // Find the absolute path where this application has been run from.
  558. // argv0 is wxTheApp->argv[0]
  559. // cwd is the current working directory (at startup)
  560. // appVariableName is the name of a variable containing the directory for this app, e.g.
  561. // MYAPPDIR. This is checked first.
  562.  
  563. wxString wxFindAppPath(const wxString& argv0, const wxString& cwd, const wxString& appVariableName)
  564. {
  565.     wxString str;
  566.  
  567.     // Try appVariableName
  568.     if (!appVariableName.IsEmpty())
  569.     {
  570.         str = wxGetenv(appVariableName);
  571.         if (!str.IsEmpty())
  572.             return str;
  573.     }
  574.  
  575.     if (wxIsAbsolutePath(argv0))
  576.         return wxPathOnly(argv0);
  577.     else
  578.     {
  579.         // Is it a relative path?
  580.         wxString currentDir(cwd);
  581.         if (currentDir.Last() != wxFILE_SEP_PATH)
  582.             currentDir += wxFILE_SEP_PATH;
  583.  
  584.         str = currentDir + argv0;
  585.         if (wxFileExists(str))
  586.             return wxPathOnly(str);
  587.     }
  588.  
  589.     // OK, it's neither an absolute path nor a relative path.
  590.     // Search PATH.
  591.  
  592.     wxPathList pathList;
  593.     pathList.AddEnvList(wxT("PATH"));
  594.     str = pathList.FindAbsoluteValidPath(argv0);
  595.     if (!str.IsEmpty())
  596.         return wxPathOnly(str);
  597.  
  598.     // Failed
  599.     return wxEmptyString;
  600. }
  601.  
  602.