| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575 | 
							- /////////////////////////////////////////////////////////////////////////////
 
- // Name:        exec.cpp
 
- // Purpose:     exec sample demonstrates wxExecute and related functions
 
- // Author:      Vadim Zeitlin
 
- // Modified by:
 
- // Created:     15.01.00
 
- // Copyright:   (c) Vadim Zeitlin
 
- // Licence:     wxWindows licence
 
- /////////////////////////////////////////////////////////////////////////////
 
- // ============================================================================
 
- // declarations
 
- // ============================================================================
 
- // ----------------------------------------------------------------------------
 
- // headers
 
- // ----------------------------------------------------------------------------
 
- // For compilers that support precompilation, includes "wx/wx.h".
 
- #include "wx/wxprec.h"
 
- #ifdef __BORLANDC__
 
-     #pragma hdrstop
 
- #endif
 
- // for all others, include the necessary headers (this file is usually all you
 
- // need because it includes almost all "standard" wxWidgets headers
 
- #ifndef WX_PRECOMP
 
-     #include "wx/app.h"
 
-     #include "wx/log.h"
 
-     #include "wx/frame.h"
 
-     #include "wx/panel.h"
 
-     #include "wx/timer.h"
 
-     #include "wx/utils.h"
 
-     #include "wx/menu.h"
 
-     #include "wx/msgdlg.h"
 
-     #include "wx/textdlg.h"
 
-     #include "wx/filedlg.h"
 
-     #include "wx/choicdlg.h"
 
-     #include "wx/button.h"
 
-     #include "wx/checkbox.h"
 
-     #include "wx/stattext.h"
 
-     #include "wx/textctrl.h"
 
-     #include "wx/listbox.h"
 
-     #include "wx/sizer.h"
 
- #endif
 
- #include "wx/txtstrm.h"
 
- #include "wx/numdlg.h"
 
- #include "wx/textdlg.h"
 
- #include "wx/ffile.h"
 
- #include "wx/scopedptr.h"
 
- #include "wx/stopwatch.h"
 
- #include "wx/process.h"
 
- #include "wx/mimetype.h"
 
- #ifdef __WINDOWS__
 
-     #include "wx/dde.h"
 
- #endif // __WINDOWS__
 
- #ifndef wxHAS_IMAGES_IN_RESOURCES
 
-     #include "../sample.xpm"
 
- #endif
 
- // ----------------------------------------------------------------------------
 
- // the usual application and main frame classes
 
- // ----------------------------------------------------------------------------
 
- // Define a new application type, each program should derive a class from wxApp
 
- class MyApp : public wxApp
 
- {
 
- public:
 
-     // override base class virtuals
 
-     // ----------------------------
 
-     // this one is called on application startup and is a good place for the app
 
-     // initialization (doing it here and not in the ctor allows to have an error
 
-     // return: if OnInit() returns false, the application terminates)
 
-     virtual bool OnInit();
 
- };
 
- // Define an array of process pointers used by MyFrame
 
- class MyPipedProcess;
 
- WX_DEFINE_ARRAY_PTR(MyPipedProcess *, MyPipedProcessesArray);
 
- class MyProcess;
 
- WX_DEFINE_ARRAY_PTR(MyProcess *, MyProcessesArray);
 
- // Define a new frame type: this is going to be our main frame
 
- class MyFrame : public wxFrame
 
- {
 
- public:
 
-     // ctor and dtor
 
-     MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
 
-     virtual ~MyFrame();
 
-     // event handlers (these functions should _not_ be virtual)
 
-     void OnQuit(wxCommandEvent& event);
 
-     void OnKill(wxCommandEvent& event);
 
-     void OnClear(wxCommandEvent& event);
 
-     void OnBeginBusyCursor(wxCommandEvent& event);
 
-     void OnEndBusyCursor(wxCommandEvent& event);
 
-     void OnSyncExec(wxCommandEvent& event);
 
-     void OnAsyncExec(wxCommandEvent& event);
 
-     void OnShell(wxCommandEvent& event);
 
-     void OnExecWithRedirect(wxCommandEvent& event);
 
-     void OnExecWithPipe(wxCommandEvent& event);
 
-     void OnPOpen(wxCommandEvent& event);
 
-     void OnFileExec(wxCommandEvent& event);
 
-     void OnFileLaunch(wxCommandEvent& event);
 
-     void OnOpenURL(wxCommandEvent& event);
 
-     void OnShowCommandForExt(wxCommandEvent& event);
 
-     void OnAbout(wxCommandEvent& event);
 
-     // polling output of async processes
 
-     void OnIdleTimer(wxTimerEvent& event);
 
-     void OnIdle(wxIdleEvent& event);
 
-     // for MyPipedProcess
 
-     void OnProcessTerminated(MyPipedProcess *process);
 
-     wxListBox *GetLogListBox() const { return m_lbox; }
 
-     // for MyProcess
 
-     void OnAsyncTermination(MyProcess *process);
 
-     // timer updating a counter in the background
 
-     void OnBgTimer(wxTimerEvent& event);
 
- private:
 
-     void ShowOutput(const wxString& cmd,
 
-                     const wxArrayString& output,
 
-                     const wxString& title);
 
-     int GetExecFlags() const;
 
-     void DoAsyncExec(const wxString& cmd);
 
-     void AddAsyncProcess(MyProcess *process) { m_allAsync.push_back(process); }
 
-     void AddPipedProcess(MyPipedProcess *process);
 
-     void RemovePipedProcess(MyPipedProcess *process);
 
-     // the PID of the last process we launched asynchronously
 
-     long m_pidLast;
 
-     // last command we executed
 
-     wxString m_cmdLast;
 
- #ifdef __WINDOWS__
 
-     void OnDDEExec(wxCommandEvent& event);
 
-     void OnDDERequest(wxCommandEvent& event);
 
-     bool GetDDEServer();
 
-     // last params of a DDE transaction
 
-     wxString m_server,
 
-              m_topic,
 
-              m_cmdDde;
 
- #endif // __WINDOWS__
 
-     wxListBox *m_lbox;
 
-     // array of running processes with redirected IO
 
-     MyPipedProcessesArray m_running;
 
-     // array of all asynchrously running processes
 
-     MyProcessesArray m_allAsync;
 
-     // the idle event wake up timer
 
-     wxTimer m_timerIdleWakeUp;
 
-     // a background timer allowing to easily check visually whether the
 
-     // messages are processed or not
 
-     wxTimer m_timerBg;
 
-     // any class wishing to process wxWidgets events must use this macro
 
-     wxDECLARE_EVENT_TABLE();
 
- };
 
- // ----------------------------------------------------------------------------
 
- // MyPipeFrame: allows the user to communicate with the child process
 
- // ----------------------------------------------------------------------------
 
- class MyPipeFrame : public wxFrame
 
- {
 
- public:
 
-     MyPipeFrame(wxFrame *parent,
 
-                 const wxString& cmd,
 
-                 wxProcess *process);
 
- protected:
 
-     void OnTextEnter(wxCommandEvent& WXUNUSED(event)) { DoSend(); }
 
-     void OnBtnSend(wxCommandEvent& WXUNUSED(event)) { DoSend(); }
 
-     void OnBtnSendFile(wxCommandEvent& WXUNUSED(event));
 
-     void OnBtnGet(wxCommandEvent& WXUNUSED(event)) { DoGet(); }
 
-     void OnBtnClose(wxCommandEvent& WXUNUSED(event)) { DoClose(); }
 
-     void OnClose(wxCloseEvent& event);
 
-     void OnProcessTerm(wxProcessEvent& event);
 
-     void DoSend()
 
-     {
 
-         wxString s(m_textOut->GetValue());
 
-         s += wxT('\n');
 
-         m_out.Write(s.c_str(), s.length());
 
-         m_textOut->Clear();
 
-         DoGet();
 
-     }
 
-     void DoGet();
 
-     void DoClose();
 
- private:
 
-     void DoGetFromStream(wxTextCtrl *text, wxInputStream& in);
 
-     void DisableInput();
 
-     void DisableOutput();
 
-     wxProcess *m_process;
 
-     wxOutputStream &m_out;
 
-     wxInputStream &m_in,
 
-                   &m_err;
 
-     wxTextCtrl *m_textOut,
 
-                *m_textIn,
 
-                *m_textErr;
 
-     wxDECLARE_EVENT_TABLE();
 
- };
 
- // ----------------------------------------------------------------------------
 
- // wxProcess-derived classes
 
- // ----------------------------------------------------------------------------
 
- // This is the handler for process termination events
 
- class MyProcess : public wxProcess
 
- {
 
- public:
 
-     MyProcess(MyFrame *parent, const wxString& cmd)
 
-         : wxProcess(parent), m_cmd(cmd)
 
-     {
 
-         m_parent = parent;
 
-     }
 
-     // instead of overriding this virtual function we might as well process the
 
-     // event from it in the frame class - this might be more convenient in some
 
-     // cases
 
-     virtual void OnTerminate(int pid, int status);
 
- protected:
 
-     MyFrame *m_parent;
 
-     wxString m_cmd;
 
- };
 
- // A specialization of MyProcess for redirecting the output
 
- class MyPipedProcess : public MyProcess
 
- {
 
- public:
 
-     MyPipedProcess(MyFrame *parent, const wxString& cmd)
 
-         : MyProcess(parent, cmd)
 
-         {
 
-             Redirect();
 
-         }
 
-     virtual void OnTerminate(int pid, int status);
 
-     virtual bool HasInput();
 
- };
 
- // A version of MyPipedProcess which also sends input to the stdin of the
 
- // child process
 
- class MyPipedProcess2 : public MyPipedProcess
 
- {
 
- public:
 
-     MyPipedProcess2(MyFrame *parent, const wxString& cmd, const wxString& input)
 
-         : MyPipedProcess(parent, cmd), m_input(input)
 
-         {
 
-         }
 
-     virtual bool HasInput();
 
- private:
 
-     wxString m_input;
 
- };
 
- // ----------------------------------------------------------------------------
 
- // constants
 
- // ----------------------------------------------------------------------------
 
- // IDs for the controls and the menu commands
 
- enum
 
- {
 
-     // timer ids
 
-     Exec_TimerIdle = 10,
 
-     Exec_TimerBg,
 
-     // menu items
 
-     Exec_Kill = 100,
 
-     Exec_ClearLog,
 
-     Exec_BeginBusyCursor,
 
-     Exec_EndBusyCursor,
 
-     Exec_SyncExec = 200,
 
-     Exec_AsyncExec,
 
-     Exec_Shell,
 
-     Exec_POpen,
 
-     Exec_OpenFile,
 
-     Exec_ShowCommandForExt,
 
-     Exec_LaunchFile,
 
-     Exec_OpenURL,
 
-     Exec_DDEExec,
 
-     Exec_DDERequest,
 
-     Exec_Redirect,
 
-     Exec_Pipe,
 
-     Exec_Flags_HideConsole,
 
-     Exec_Flags_ShowConsole,
 
-     Exec_Flags_NoEvents,
 
-     Exec_About = wxID_ABOUT,
 
-     Exec_Quit = wxID_EXIT,
 
-     // control ids
 
-     Exec_Btn_Send = 1000,
 
-     Exec_Btn_SendFile,
 
-     Exec_Btn_Get,
 
-     Exec_Btn_Close
 
- };
 
- static const wxChar *DIALOG_TITLE = wxT("Exec sample");
 
- // ----------------------------------------------------------------------------
 
- // event tables and other macros for wxWidgets
 
- // ----------------------------------------------------------------------------
 
- // 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.
 
- wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
 
-     EVT_MENU(Exec_Quit,  MyFrame::OnQuit)
 
-     EVT_MENU(Exec_Kill,  MyFrame::OnKill)
 
-     EVT_MENU(Exec_ClearLog,  MyFrame::OnClear)
 
-     EVT_MENU(Exec_BeginBusyCursor,  MyFrame::OnBeginBusyCursor)
 
-     EVT_MENU(Exec_EndBusyCursor,  MyFrame::OnEndBusyCursor)
 
-     EVT_MENU(Exec_SyncExec, MyFrame::OnSyncExec)
 
-     EVT_MENU(Exec_AsyncExec, MyFrame::OnAsyncExec)
 
-     EVT_MENU(Exec_Shell, MyFrame::OnShell)
 
-     EVT_MENU(Exec_Redirect, MyFrame::OnExecWithRedirect)
 
-     EVT_MENU(Exec_Pipe, MyFrame::OnExecWithPipe)
 
-     EVT_MENU(Exec_POpen, MyFrame::OnPOpen)
 
-     EVT_MENU(Exec_OpenFile, MyFrame::OnFileExec)
 
-     EVT_MENU(Exec_ShowCommandForExt, MyFrame::OnShowCommandForExt)
 
-     EVT_MENU(Exec_LaunchFile, MyFrame::OnFileLaunch)
 
-     EVT_MENU(Exec_OpenURL, MyFrame::OnOpenURL)
 
- #ifdef __WINDOWS__
 
-     EVT_MENU(Exec_DDEExec, MyFrame::OnDDEExec)
 
-     EVT_MENU(Exec_DDERequest, MyFrame::OnDDERequest)
 
- #endif // __WINDOWS__
 
-     EVT_MENU(Exec_About, MyFrame::OnAbout)
 
-     EVT_IDLE(MyFrame::OnIdle)
 
-     EVT_TIMER(Exec_TimerIdle, MyFrame::OnIdleTimer)
 
-     EVT_TIMER(Exec_TimerBg, MyFrame::OnBgTimer)
 
- wxEND_EVENT_TABLE()
 
- wxBEGIN_EVENT_TABLE(MyPipeFrame, wxFrame)
 
-     EVT_BUTTON(Exec_Btn_Send, MyPipeFrame::OnBtnSend)
 
-     EVT_BUTTON(Exec_Btn_SendFile, MyPipeFrame::OnBtnSendFile)
 
-     EVT_BUTTON(Exec_Btn_Get, MyPipeFrame::OnBtnGet)
 
-     EVT_BUTTON(Exec_Btn_Close, MyPipeFrame::OnBtnClose)
 
-     EVT_TEXT_ENTER(wxID_ANY, MyPipeFrame::OnTextEnter)
 
-     EVT_CLOSE(MyPipeFrame::OnClose)
 
-     EVT_END_PROCESS(wxID_ANY, MyPipeFrame::OnProcessTerm)
 
- wxEND_EVENT_TABLE()
 
- // 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. MyApp and
 
- // not wxApp)
 
- IMPLEMENT_APP(MyApp)
 
- // ============================================================================
 
- // implementation
 
- // ============================================================================
 
- // ----------------------------------------------------------------------------
 
- // the application class
 
- // ----------------------------------------------------------------------------
 
- // `Main program' equivalent: the program execution "starts" here
 
- bool MyApp::OnInit()
 
- {
 
-     if ( !wxApp::OnInit() )
 
-         return false;
 
-     // Create the main application window
 
-     MyFrame *frame = new MyFrame(wxT("Exec wxWidgets sample"),
 
-                                  wxDefaultPosition, wxSize(500, 140));
 
-     // Show it
 
-     frame->Show(true);
 
-     // success: wxApp::OnRun() will be called which will enter the main message
 
-     // loop and the application will run. If we returned false here, the
 
-     // application would exit immediately.
 
-     return true;
 
- }
 
- // ----------------------------------------------------------------------------
 
- // main frame
 
- // ----------------------------------------------------------------------------
 
- #ifdef __VISUALC__
 
- #pragma warning(disable: 4355) // this used in base member initializer list
 
- #endif
 
- // frame constructor
 
- MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
 
-        : wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size),
 
-          m_timerIdleWakeUp(this, Exec_TimerIdle),
 
-          m_timerBg(this, Exec_TimerBg)
 
- {
 
-     SetIcon(wxICON(sample));
 
-     m_pidLast = 0;
 
- #ifdef __WXMAC__
 
-     // we need this in order to allow the about menu relocation, since ABOUT is
 
-     // not the default id of the about menu
 
-     wxApp::s_macAboutMenuItemId = Exec_About;
 
- #endif
 
-     // create a menu bar
 
-     wxMenu *menuFile = new wxMenu(wxEmptyString, wxMENU_TEAROFF);
 
-     menuFile->Append(Exec_Kill, wxT("&Kill process...\tCtrl-K"),
 
-                      wxT("Kill a process by PID"));
 
-     menuFile->AppendSeparator();
 
-     menuFile->Append(Exec_OpenFile, wxT("Open &file...\tCtrl-F"),
 
-                      wxT("Launch the command to open this kind of files"));
 
-     menuFile->Append(Exec_ShowCommandForExt,
 
-                      "Show association for extension...\tShift-Ctrl-A",
 
-                      "Show the command associated with the given extension");
 
-     menuFile->Append(Exec_LaunchFile, wxT("La&unch file...\tShift-Ctrl-F"),
 
-                      wxT("Launch the default application associated with the file"));
 
-     menuFile->Append(Exec_OpenURL, wxT("Open &URL...\tCtrl-U"),
 
-                      wxT("Launch the default browser with the given URL"));
 
-     menuFile->AppendSeparator();
 
-     menuFile->Append(Exec_BeginBusyCursor, wxT("Show &busy cursor\tCtrl-C"));
 
-     menuFile->Append(Exec_EndBusyCursor, wxT("Show &normal cursor\tShift-Ctrl-C"));
 
-     menuFile->AppendSeparator();
 
-     menuFile->Append(Exec_ClearLog, wxT("&Clear log\tCtrl-L"),
 
-                      wxT("Clear the log window"));
 
-     menuFile->AppendSeparator();
 
-     menuFile->Append(Exec_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program"));
 
-     wxMenu *flagsMenu = new wxMenu;
 
-     flagsMenu->AppendCheckItem(Exec_Flags_HideConsole, "Always &hide console");
 
-     flagsMenu->AppendCheckItem(Exec_Flags_ShowConsole, "Always &show console");
 
-     flagsMenu->AppendCheckItem(Exec_Flags_NoEvents, "Disable &events",
 
-                                "This flag is valid for sync execution only");
 
-     wxMenu *execMenu = new wxMenu;
 
-     execMenu->AppendSubMenu(flagsMenu, "Execution flags");
 
-     execMenu->AppendSeparator();
 
-     execMenu->Append(Exec_SyncExec, wxT("Sync &execution...\tCtrl-E"),
 
-                      wxT("Launch a program and return when it terminates"));
 
-     execMenu->Append(Exec_AsyncExec, wxT("&Async execution...\tCtrl-A"),
 
-                      wxT("Launch a program and return immediately"));
 
-     execMenu->Append(Exec_Shell, wxT("Execute &shell command...\tCtrl-S"),
 
-                      wxT("Launch a shell and execute a command in it"));
 
-     execMenu->AppendSeparator();
 
-     execMenu->Append(Exec_Redirect, wxT("Capture command &output...\tCtrl-O"),
 
-                      wxT("Launch a program and capture its output"));
 
-     execMenu->Append(Exec_Pipe, wxT("&Pipe through command..."),
 
-                      wxT("Pipe a string through a filter"));
 
-     execMenu->Append(Exec_POpen, wxT("&Open a pipe to a command...\tCtrl-P"),
 
-                      wxT("Open a pipe to and from another program"));
 
- #ifdef __WINDOWS__
 
-     execMenu->AppendSeparator();
 
-     execMenu->Append(Exec_DDEExec, wxT("Execute command via &DDE...\tCtrl-D"));
 
-     execMenu->Append(Exec_DDERequest, wxT("Send DDE &request...\tCtrl-R"));
 
- #endif
 
-     wxMenu *helpMenu = new wxMenu(wxEmptyString, wxMENU_TEAROFF);
 
-     helpMenu->Append(Exec_About, wxT("&About\tF1"), wxT("Show about dialog"));
 
-     // now append the freshly created menu to the menu bar...
 
-     wxMenuBar *menuBar = new wxMenuBar();
 
-     menuBar->Append(menuFile, wxT("&File"));
 
-     menuBar->Append(execMenu, wxT("&Exec"));
 
-     menuBar->Append(helpMenu, wxT("&Help"));
 
-     // ... and attach this menu bar to the frame
 
-     SetMenuBar(menuBar);
 
-     // create the listbox in which we will show misc messages as they come
 
-     m_lbox = new wxListBox(this, wxID_ANY);
 
-     wxFont font(12, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL,
 
-                 wxFONTWEIGHT_NORMAL);
 
-     if ( font.IsOk() )
 
-         m_lbox->SetFont(font);
 
- #if wxUSE_STATUSBAR
 
-     // create a status bar just for fun (by default with 1 pane only)
 
-     CreateStatusBar(2);
 
-     SetStatusText(wxT("Welcome to wxWidgets exec sample!"));
 
- #endif // wxUSE_STATUSBAR
 
-     m_timerBg.Start(1000);
 
- }
 
- MyFrame::~MyFrame()
 
- {
 
-     // any processes left until now must be deleted manually: normally this is
 
-     // done when the associated process terminates but it must be still running
 
-     // if this didn't happen until now
 
-     for ( size_t n = 0; n < m_allAsync.size(); n++ )
 
-     {
 
-         delete m_allAsync[n];
 
-     }
 
- }
 
- // ----------------------------------------------------------------------------
 
- // event handlers: file and help menu
 
- // ----------------------------------------------------------------------------
 
- void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     // true is to force the frame to close
 
-     Close(true);
 
- }
 
- void MyFrame::OnClear(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     m_lbox->Clear();
 
- }
 
- void MyFrame::OnBeginBusyCursor(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     wxBeginBusyCursor();
 
- }
 
- void MyFrame::OnEndBusyCursor(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     wxEndBusyCursor();
 
- }
 
- void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     wxMessageBox(wxT("Exec wxWidgets Sample\n(c) 2000-2002 Vadim Zeitlin"),
 
-                  wxT("About Exec"), wxOK | wxICON_INFORMATION, this);
 
- }
 
- void MyFrame::OnKill(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     long pid = wxGetNumberFromUser(wxT("Please specify the process to kill"),
 
-                                    wxT("Enter PID:"),
 
-                                    wxT("Exec question"),
 
-                                    m_pidLast,
 
-                                    // we need the full unsigned int range
 
-                                    -INT_MAX, INT_MAX,
 
-                                    this);
 
-     if ( pid == -1 )
 
-     {
 
-         // cancelled
 
-         return;
 
-     }
 
-     m_pidLast = pid;
 
-     static const wxString signalNames[] =
 
-     {
 
-         wxT("Just test (SIGNONE)"),
 
-         wxT("Hangup (SIGHUP)"),
 
-         wxT("Interrupt (SIGINT)"),
 
-         wxT("Quit (SIGQUIT)"),
 
-         wxT("Illegal instruction (SIGILL)"),
 
-         wxT("Trap (SIGTRAP)"),
 
-         wxT("Abort (SIGABRT)"),
 
-         wxT("Emulated trap (SIGEMT)"),
 
-         wxT("FP exception (SIGFPE)"),
 
-         wxT("Kill (SIGKILL)"),
 
-         wxT("Bus (SIGBUS)"),
 
-         wxT("Segment violation (SIGSEGV)"),
 
-         wxT("System (SIGSYS)"),
 
-         wxT("Broken pipe (SIGPIPE)"),
 
-         wxT("Alarm (SIGALRM)"),
 
-         wxT("Terminate (SIGTERM)"),
 
-     };
 
-     static int s_sigLast = wxSIGNONE;
 
-     int sig = wxGetSingleChoiceIndex(wxT("How to kill the process?"),
 
-                                      wxT("Exec question"),
 
-                                      WXSIZEOF(signalNames), signalNames,
 
-                                      s_sigLast,
 
-                                      this);
 
-     switch ( sig )
 
-     {
 
-         default:
 
-             wxFAIL_MSG( wxT("unexpected return value") );
 
-             // fall through
 
-         case -1:
 
-             // cancelled
 
-             return;
 
-         case wxSIGNONE:
 
-         case wxSIGHUP:
 
-         case wxSIGINT:
 
-         case wxSIGQUIT:
 
-         case wxSIGILL:
 
-         case wxSIGTRAP:
 
-         case wxSIGABRT:
 
-         case wxSIGEMT:
 
-         case wxSIGFPE:
 
-         case wxSIGKILL:
 
-         case wxSIGBUS:
 
-         case wxSIGSEGV:
 
-         case wxSIGSYS:
 
-         case wxSIGPIPE:
 
-         case wxSIGALRM:
 
-         case wxSIGTERM:
 
-             break;
 
-     }
 
-     s_sigLast = sig;
 
-     if ( sig == wxSIGNONE )
 
-     {
 
-         // This simply calls Kill(wxSIGNONE) but using it is more convenient.
 
-         if ( wxProcess::Exists(pid) )
 
-         {
 
-             wxLogStatus(wxT("Process %ld is running."), pid);
 
-         }
 
-         else
 
-         {
 
-             wxLogStatus(wxT("No process with pid = %ld."), pid);
 
-         }
 
-     }
 
-     else // not SIGNONE
 
-     {
 
-         wxKillError rc = wxProcess::Kill(pid, (wxSignal)sig);
 
-         if ( rc == wxKILL_OK )
 
-         {
 
-             wxLogStatus(wxT("Process %ld killed with signal %d."), pid, sig);
 
-         }
 
-         else
 
-         {
 
-             static const wxChar *errorText[] =
 
-             {
 
-                 wxT(""), // no error
 
-                 wxT("signal not supported"),
 
-                 wxT("permission denied"),
 
-                 wxT("no such process"),
 
-                 wxT("unspecified error"),
 
-             };
 
-             wxLogStatus(wxT("Failed to kill process %ld with signal %d: %s"),
 
-                         pid, sig, errorText[rc]);
 
-         }
 
-     }
 
- }
 
- // ----------------------------------------------------------------------------
 
- // execution options dialog
 
- // ----------------------------------------------------------------------------
 
- enum ExecQueryDialogID
 
- {
 
-     TEXT_EXECUTABLE,
 
-     TEXT_CWD,
 
-     TEXT_ENVIRONMENT
 
- };
 
- class ExecQueryDialog : public wxDialog
 
- {
 
- public:
 
-     ExecQueryDialog(const wxString& cmd);
 
-     wxString GetExecutable() const
 
-     {
 
-         return m_executable->GetValue();
 
-     }
 
-     wxString GetWorkDir() const
 
-     {
 
-         return m_useCWD->GetValue() ? m_cwdtext->GetValue() : wxString();
 
-     }
 
-     void GetEnvironment(wxEnvVariableHashMap& env);
 
- private:
 
-     void OnUpdateWorkingDirectoryUI(wxUpdateUIEvent& event)
 
-     {
 
-         event.Enable(m_useCWD->GetValue());
 
-     }
 
-     void OnUpdateEnvironmentUI(wxUpdateUIEvent& event)
 
-     {
 
-         event.Enable(m_useEnv->GetValue());
 
-     }
 
-     wxTextCtrl* m_executable;
 
-     wxTextCtrl* m_cwdtext;
 
-     wxTextCtrl* m_envtext;
 
-     wxCheckBox* m_useCWD;
 
-     wxCheckBox* m_useEnv;
 
-     wxDECLARE_EVENT_TABLE();
 
- };
 
- wxBEGIN_EVENT_TABLE(ExecQueryDialog, wxDialog)
 
-     EVT_UPDATE_UI(TEXT_CWD, ExecQueryDialog::OnUpdateWorkingDirectoryUI)
 
-     EVT_UPDATE_UI(TEXT_ENVIRONMENT, ExecQueryDialog::OnUpdateEnvironmentUI)
 
- wxEND_EVENT_TABLE()
 
- ExecQueryDialog::ExecQueryDialog(const wxString& cmd)
 
-     : wxDialog(NULL, wxID_ANY, DIALOG_TITLE,
 
-                wxDefaultPosition, wxDefaultSize,
 
-                wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
 
- {
 
-     wxSizer* globalSizer = new wxBoxSizer(wxVERTICAL);
 
-     m_executable = new wxTextCtrl(this, TEXT_EXECUTABLE, wxString());
 
-     m_cwdtext = new wxTextCtrl(this, TEXT_CWD, wxString());
 
-     m_envtext = new wxTextCtrl(this, TEXT_ENVIRONMENT, wxString(),
 
-                                wxDefaultPosition, wxSize(300, 200),
 
-                                wxTE_MULTILINE|wxHSCROLL);
 
-     const wxSizerFlags flagsExpand = wxSizerFlags().Expand().Border();
 
-     globalSizer->Add(new wxStaticText(this, wxID_ANY, "Enter the command: "),
 
-                      flagsExpand);
 
-     globalSizer->Add(m_executable, flagsExpand);
 
-     m_useCWD = new wxCheckBox(this, wxID_ANY, "Working directory: ");
 
-     globalSizer->Add(m_useCWD, flagsExpand);
 
-     globalSizer->Add(m_cwdtext, flagsExpand);
 
-     m_useEnv = new wxCheckBox(this, wxID_ANY, "Environment: ");
 
-     globalSizer->Add(m_useEnv, flagsExpand);
 
-     globalSizer->Add(m_envtext, wxSizerFlags(flagsExpand).Proportion(1));
 
-     globalSizer->Add(CreateStdDialogButtonSizer(wxOK|wxCANCEL), flagsExpand);
 
-     SetSizerAndFit(globalSizer);
 
-     m_executable->SetValue(cmd);
 
-     m_cwdtext->SetValue(wxGetCwd());
 
-     wxEnvVariableHashMap env;
 
-     if ( wxGetEnvMap(&env) )
 
-     {
 
-         for ( wxEnvVariableHashMap::iterator it = env.begin();
 
-               it != env.end();
 
-               ++it )
 
-         {
 
-             m_envtext->AppendText(it->first + '=' + it->second + '\n');
 
-         }
 
-     }
 
-     m_useCWD->SetValue(false);
 
-     m_useEnv->SetValue(false);
 
- }
 
- void ExecQueryDialog::GetEnvironment(wxEnvVariableHashMap& env)
 
- {
 
-     env.clear();
 
-     if ( m_useEnv->GetValue() )
 
-     {
 
-         wxString name,
 
-                  value;
 
-         const int nb = m_envtext->GetNumberOfLines();
 
-         for ( int l = 0; l < nb; l++ )
 
-         {
 
-             const wxString line = m_envtext->GetLineText(l).Trim();
 
-             if ( !line.empty() )
 
-             {
 
-                 name = line.BeforeFirst('=', &value);
 
-                 if ( name.empty() )
 
-                 {
 
-                     wxLogWarning("Skipping invalid environment line \"%s\".", line);
 
-                     continue;
 
-                 }
 
-                 env[name] = value;
 
-             }
 
-         }
 
-     }
 
- }
 
- static bool QueryExec(wxString& cmd, wxExecuteEnv& env)
 
- {
 
-     ExecQueryDialog dialog(cmd);
 
-     if ( dialog.ShowModal() != wxID_OK )
 
-         return false;
 
-     cmd = dialog.GetExecutable();
 
-     env.cwd = dialog.GetWorkDir();
 
-     dialog.GetEnvironment(env.env);
 
-     return true;
 
- }
 
- // ----------------------------------------------------------------------------
 
- // event handlers: exec menu
 
- // ----------------------------------------------------------------------------
 
- int MyFrame::GetExecFlags() const
 
- {
 
-     wxMenuBar* const mbar = GetMenuBar();
 
-     int flags = 0;
 
-     if ( mbar->IsChecked(Exec_Flags_HideConsole) )
 
-         flags |= wxEXEC_HIDE_CONSOLE;
 
-     if ( mbar->IsChecked(Exec_Flags_ShowConsole) )
 
-         flags |= wxEXEC_SHOW_CONSOLE;
 
-     if ( mbar->IsChecked(Exec_Flags_NoEvents) )
 
-         flags |= wxEXEC_NOEVENTS;
 
-     return flags;
 
- }
 
- void MyFrame::DoAsyncExec(const wxString& cmd)
 
- {
 
-     MyProcess * const process = new MyProcess(this, cmd);
 
-     m_pidLast = wxExecute(cmd, wxEXEC_ASYNC | GetExecFlags(), process);
 
-     if ( !m_pidLast )
 
-     {
 
-         wxLogError(wxT("Execution of '%s' failed."), cmd.c_str());
 
-         delete process;
 
-     }
 
-     else
 
-     {
 
-         wxLogStatus(wxT("Process %ld (%s) launched."), m_pidLast, cmd.c_str());
 
-         m_cmdLast = cmd;
 
-         // the parent frame keeps track of all async processes as it needs to
 
-         // free them if we exit before the child process terminates
 
-         AddAsyncProcess(process);
 
-     }
 
- }
 
- void MyFrame::OnSyncExec(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     wxString cmd;
 
-     wxExecuteEnv env;
 
-     if ( !QueryExec(cmd, env) )
 
-         return;
 
-     wxLogStatus( wxT("'%s' is running please wait..."), cmd.c_str() );
 
-     int code = wxExecute(cmd, wxEXEC_SYNC | GetExecFlags(), NULL, &env);
 
-     wxLogStatus(wxT("Process '%s' terminated with exit code %d."),
 
-         cmd.c_str(), code);
 
-     m_cmdLast = cmd;
 
- }
 
- void MyFrame::OnAsyncExec(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     wxString cmd = wxGetTextFromUser(wxT("Enter the command: "),
 
-                                      DIALOG_TITLE,
 
-                                      m_cmdLast);
 
-     if ( !cmd )
 
-         return;
 
-     DoAsyncExec(cmd);
 
- }
 
- void MyFrame::OnShell(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     wxString cmd = wxGetTextFromUser(wxT("Enter the command: "),
 
-                                      DIALOG_TITLE,
 
-                                      m_cmdLast);
 
-     if ( !cmd )
 
-         return;
 
-     int code = wxShell(cmd);
 
-     wxLogStatus(wxT("Shell command '%s' terminated with exit code %d."),
 
-                 cmd.c_str(), code);
 
-     m_cmdLast = cmd;
 
- }
 
- void MyFrame::OnExecWithRedirect(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     if ( !m_cmdLast )
 
-     {
 
- #ifdef __WXMSW__
 
-         m_cmdLast = "type Makefile.in";
 
- #else
 
-         m_cmdLast = "cat -n Makefile";
 
- #endif
 
-     }
 
-     wxString cmd = wxGetTextFromUser(wxT("Enter the command: "),
 
-                                      DIALOG_TITLE,
 
-                                      m_cmdLast);
 
-     if ( !cmd )
 
-         return;
 
-     bool sync;
 
-     switch ( wxMessageBox(wxT("Execute it synchronously?"),
 
-                           wxT("Exec question"),
 
-                           wxYES_NO | wxCANCEL | wxICON_QUESTION, this) )
 
-     {
 
-         case wxYES:
 
-             sync = true;
 
-             break;
 
-         case wxNO:
 
-             sync = false;
 
-             break;
 
-         default:
 
-             return;
 
-     }
 
-     if ( sync )
 
-     {
 
-         wxLogStatus("\"%s\" is running please wait...", cmd);
 
-         wxStopWatch sw;
 
-         wxArrayString output, errors;
 
-         int code = wxExecute(cmd, output, errors);
 
-         wxLogStatus("Command \"%s\" terminated after %ldms; exit code %d.",
 
-                     cmd, sw.Time(), code);
 
-         ShowOutput(cmd, output, wxT("Output"));
 
-         ShowOutput(cmd, errors, wxT("Errors"));
 
-     }
 
-     else // async exec
 
-     {
 
-         MyPipedProcess *process = new MyPipedProcess(this, cmd);
 
-         if ( !wxExecute(cmd, wxEXEC_ASYNC, process) )
 
-         {
 
-             wxLogError(wxT("Execution of '%s' failed."), cmd.c_str());
 
-             delete process;
 
-         }
 
-         else
 
-         {
 
-             AddPipedProcess(process);
 
-         }
 
-     }
 
-     m_cmdLast = cmd;
 
- }
 
- void MyFrame::OnExecWithPipe(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     if ( !m_cmdLast )
 
-         m_cmdLast = wxT("tr [a-z] [A-Z]");
 
-     wxString cmd = wxGetTextFromUser(wxT("Enter the command: "),
 
-                                      DIALOG_TITLE,
 
-                                      m_cmdLast);
 
-     if ( !cmd )
 
-         return;
 
-     wxString input = wxGetTextFromUser(wxT("Enter the string to send to it: "),
 
-                                        DIALOG_TITLE);
 
-     if ( !input )
 
-         return;
 
-     // always execute the filter asynchronously
 
-     MyPipedProcess2 *process = new MyPipedProcess2(this, cmd, input);
 
-     long pid = wxExecute(cmd, wxEXEC_ASYNC, process);
 
-     if ( pid )
 
-     {
 
-         wxLogStatus(wxT("Process %ld (%s) launched."), pid, cmd.c_str());
 
-         AddPipedProcess(process);
 
-     }
 
-     else
 
-     {
 
-         wxLogError(wxT("Execution of '%s' failed."), cmd.c_str());
 
-         delete process;
 
-     }
 
-     m_cmdLast = cmd;
 
- }
 
- void MyFrame::OnPOpen(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     wxString cmd = wxGetTextFromUser(wxT("Enter the command to launch: "),
 
-                                      DIALOG_TITLE,
 
-                                      m_cmdLast);
 
-     if ( cmd.empty() )
 
-         return;
 
-     wxProcess *process = wxProcess::Open(cmd);
 
-     if ( !process )
 
-     {
 
-         wxLogError(wxT("Failed to launch the command."));
 
-         return;
 
-     }
 
-     wxLogVerbose(wxT("PID of the new process: %ld"), process->GetPid());
 
-     wxOutputStream *out = process->GetOutputStream();
 
-     if ( !out )
 
-     {
 
-         wxLogError(wxT("Failed to connect to child stdin"));
 
-         return;
 
-     }
 
-     wxInputStream *in = process->GetInputStream();
 
-     if ( !in )
 
-     {
 
-         wxLogError(wxT("Failed to connect to child stdout"));
 
-         return;
 
-     }
 
-     new MyPipeFrame(this, cmd, process);
 
- }
 
- static wxString gs_lastFile;
 
- static bool AskUserForFileName()
 
- {
 
-     wxString filename;
 
- #if wxUSE_FILEDLG
 
-     filename = wxLoadFileSelector(wxT("any"), wxEmptyString, gs_lastFile);
 
- #else // !wxUSE_FILEDLG
 
-     filename = wxGetTextFromUser(wxT("Enter the file name"), wxT("exec sample"),
 
-                                  gs_lastFile);
 
- #endif // wxUSE_FILEDLG/!wxUSE_FILEDLG
 
-     if ( filename.empty() )
 
-         return false;
 
-     gs_lastFile = filename;
 
-     return true;
 
- }
 
- void MyFrame::OnFileExec(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     if ( !AskUserForFileName() )
 
-         return;
 
-     wxString ext = gs_lastFile.AfterLast(wxT('.'));
 
-     wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(ext);
 
-     if ( !ft )
 
-     {
 
-         wxLogError(wxT("Impossible to determine the file type for extension '%s'"),
 
-                    ext.c_str());
 
-         return;
 
-     }
 
-     wxString cmd;
 
-     bool ok = ft->GetOpenCommand(&cmd,
 
-                                  wxFileType::MessageParameters(gs_lastFile));
 
-     delete ft;
 
-     if ( !ok )
 
-     {
 
-         wxLogError(wxT("Impossible to find out how to open files of extension '%s'"),
 
-                    ext.c_str());
 
-         return;
 
-     }
 
-     DoAsyncExec(cmd);
 
- }
 
- void MyFrame::OnShowCommandForExt(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     static wxString s_ext;
 
-     wxString ext = wxGetTextFromUser
 
-                    (
 
-                     "Enter the extension without leading dot",
 
-                     "Exec sample",
 
-                     s_ext,
 
-                     this
 
-                    );
 
-     if ( ext.empty() )
 
-         return;
 
-     s_ext = ext;
 
-     wxScopedPtr<wxFileType>
 
-         ft(wxTheMimeTypesManager->GetFileTypeFromExtension(ext));
 
-     if ( !ft )
 
-     {
 
-         wxLogError("Information for extension \"%s\" not found", ext);
 
-         return;
 
-     }
 
-     const wxString cmd = ft->GetOpenCommand("file." + ext);
 
-     if ( cmd.empty() )
 
-     {
 
-         wxLogWarning("Open command for extension \"%s\" not defined.", ext);
 
-         return;
 
-     }
 
-     wxLogMessage("Open command for files of extension \"%s\" is\n%s",
 
-                  ext, cmd);
 
- }
 
- void MyFrame::OnFileLaunch(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     if ( !AskUserForFileName() )
 
-         return;
 
-     if ( !wxLaunchDefaultApplication(gs_lastFile) )
 
-     {
 
-         wxLogError("Opening \"%s\" in default application failed.", gs_lastFile);
 
-     }
 
- }
 
- void MyFrame::OnOpenURL(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     static wxString s_url(wxT("http://www.wxwidgets.org/"));
 
-     wxString filename = wxGetTextFromUser
 
-                         (
 
-                             wxT("Enter the URL"),
 
-                             wxT("exec sample"),
 
-                             s_url,
 
-                             this
 
-                         );
 
-     if ( filename.empty() )
 
-         return;
 
-     s_url = filename;
 
-     if ( !wxLaunchDefaultBrowser(s_url) )
 
-     {
 
-         wxLogError(wxT("Failed to open URL \"%s\""), s_url.c_str());
 
-     }
 
- }
 
- // ----------------------------------------------------------------------------
 
- // DDE stuff
 
- // ----------------------------------------------------------------------------
 
- #ifdef __WINDOWS__
 
- bool MyFrame::GetDDEServer()
 
- {
 
-     wxString server = wxGetTextFromUser(wxT("Server to connect to:"),
 
-                                         DIALOG_TITLE, m_server);
 
-     if ( !server )
 
-         return false;
 
-     m_server = server;
 
-     wxString topic = wxGetTextFromUser(wxT("DDE topic:"), DIALOG_TITLE, m_topic);
 
-     if ( !topic )
 
-         return false;
 
-     m_topic = topic;
 
-     wxString cmd = wxGetTextFromUser(wxT("DDE command:"), DIALOG_TITLE, m_cmdDde);
 
-     if ( !cmd )
 
-         return false;
 
-     m_cmdDde = cmd;
 
-     return true;
 
- }
 
- void MyFrame::OnDDEExec(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     if ( !GetDDEServer() )
 
-         return;
 
-     wxDDEClient client;
 
-     wxConnectionBase *conn = client.MakeConnection(wxEmptyString, m_server, m_topic);
 
-     if ( !conn )
 
-     {
 
-         wxLogError(wxT("Failed to connect to the DDE server '%s'."),
 
-                    m_server.c_str());
 
-     }
 
-     else
 
-     {
 
-         if ( !conn->Execute(m_cmdDde) )
 
-         {
 
-             wxLogError(wxT("Failed to execute command '%s' via DDE."),
 
-                        m_cmdDde.c_str());
 
-         }
 
-         else
 
-         {
 
-             wxLogStatus(wxT("Successfully executed DDE command"));
 
-         }
 
-     }
 
- }
 
- void MyFrame::OnDDERequest(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     if ( !GetDDEServer() )
 
-         return;
 
-     wxDDEClient client;
 
-     wxConnectionBase *conn = client.MakeConnection(wxEmptyString, m_server, m_topic);
 
-     if ( !conn )
 
-     {
 
-         wxLogError(wxT("Failed to connect to the DDE server '%s'."),
 
-                    m_server.c_str());
 
-     }
 
-     else
 
-     {
 
-         if ( !conn->Request(m_cmdDde) )
 
-         {
 
-             wxLogError(wxT("Failed to  send request '%s' via DDE."),
 
-                        m_cmdDde.c_str());
 
-         }
 
-         else
 
-         {
 
-             wxLogStatus(wxT("Successfully sent DDE request."));
 
-         }
 
-     }
 
- }
 
- #endif // __WINDOWS__
 
- // ----------------------------------------------------------------------------
 
- // various helpers
 
- // ----------------------------------------------------------------------------
 
- // input polling
 
- void MyFrame::OnIdle(wxIdleEvent& event)
 
- {
 
-     size_t count = m_running.GetCount();
 
-     for ( size_t n = 0; n < count; n++ )
 
-     {
 
-         if ( m_running[n]->HasInput() )
 
-         {
 
-             event.RequestMore();
 
-         }
 
-     }
 
- }
 
- void MyFrame::OnIdleTimer(wxTimerEvent& WXUNUSED(event))
 
- {
 
-     wxWakeUpIdle();
 
- }
 
- void MyFrame::OnBgTimer(wxTimerEvent& WXUNUSED(event))
 
- {
 
-     static unsigned long s_ticks = 0;
 
-     SetStatusText(wxString::Format("%lu ticks", s_ticks++), 1);
 
- }
 
- void MyFrame::OnProcessTerminated(MyPipedProcess *process)
 
- {
 
-     RemovePipedProcess(process);
 
- }
 
- void MyFrame::OnAsyncTermination(MyProcess *process)
 
- {
 
-     m_allAsync.Remove(process);
 
-     delete process;
 
- }
 
- void MyFrame::AddPipedProcess(MyPipedProcess *process)
 
- {
 
-     if ( m_running.IsEmpty() )
 
-     {
 
-         // we want to start getting the timer events to ensure that a
 
-         // steady stream of idle events comes in -- otherwise we
 
-         // wouldn't be able to poll the child process input
 
-         m_timerIdleWakeUp.Start(100);
 
-     }
 
-     //else: the timer is already running
 
-     m_running.Add(process);
 
-     m_allAsync.Add(process);
 
- }
 
- void MyFrame::RemovePipedProcess(MyPipedProcess *process)
 
- {
 
-     m_running.Remove(process);
 
-     if ( m_running.IsEmpty() )
 
-     {
 
-         // we don't need to get idle events all the time any more
 
-         m_timerIdleWakeUp.Stop();
 
-     }
 
- }
 
- void MyFrame::ShowOutput(const wxString& cmd,
 
-                          const wxArrayString& output,
 
-                          const wxString& title)
 
- {
 
-     size_t count = output.GetCount();
 
-     if ( !count )
 
-         return;
 
-     m_lbox->Append(wxString::Format(wxT("--- %s of '%s' ---"),
 
-                                     title.c_str(), cmd.c_str()));
 
-     for ( size_t n = 0; n < count; n++ )
 
-     {
 
-         m_lbox->Append(output[n]);
 
-     }
 
-     m_lbox->Append(wxString::Format(wxT("--- End of %s ---"),
 
-                                     title.Lower().c_str()));
 
- }
 
- // ----------------------------------------------------------------------------
 
- // MyProcess
 
- // ----------------------------------------------------------------------------
 
- void MyProcess::OnTerminate(int pid, int status)
 
- {
 
-     wxLogStatus(m_parent, wxT("Process %u ('%s') terminated with exit code %d."),
 
-                 pid, m_cmd.c_str(), status);
 
-     m_parent->OnAsyncTermination(this);
 
- }
 
- // ----------------------------------------------------------------------------
 
- // MyPipedProcess
 
- // ----------------------------------------------------------------------------
 
- bool MyPipedProcess::HasInput()
 
- {
 
-     bool hasInput = false;
 
-     if ( IsInputAvailable() )
 
-     {
 
-         wxTextInputStream tis(*GetInputStream());
 
-         // this assumes that the output is always line buffered
 
-         wxString msg;
 
-         msg << m_cmd << wxT(" (stdout): ") << tis.ReadLine();
 
-         m_parent->GetLogListBox()->Append(msg);
 
-         hasInput = true;
 
-     }
 
-     if ( IsErrorAvailable() )
 
-     {
 
-         wxTextInputStream tis(*GetErrorStream());
 
-         // this assumes that the output is always line buffered
 
-         wxString msg;
 
-         msg << m_cmd << wxT(" (stderr): ") << tis.ReadLine();
 
-         m_parent->GetLogListBox()->Append(msg);
 
-         hasInput = true;
 
-     }
 
-     return hasInput;
 
- }
 
- void MyPipedProcess::OnTerminate(int pid, int status)
 
- {
 
-     // show the rest of the output
 
-     while ( HasInput() )
 
-         ;
 
-     m_parent->OnProcessTerminated(this);
 
-     MyProcess::OnTerminate(pid, status);
 
- }
 
- // ----------------------------------------------------------------------------
 
- // MyPipedProcess2
 
- // ----------------------------------------------------------------------------
 
- bool MyPipedProcess2::HasInput()
 
- {
 
-     if ( !m_input.empty() )
 
-     {
 
-         wxTextOutputStream os(*GetOutputStream());
 
-         os.WriteString(m_input);
 
-         CloseOutput();
 
-         m_input.clear();
 
-         // call us once again - may be we'll have output
 
-         return true;
 
-     }
 
-     return MyPipedProcess::HasInput();
 
- }
 
- // ============================================================================
 
- // MyPipeFrame implementation
 
- // ============================================================================
 
- MyPipeFrame::MyPipeFrame(wxFrame *parent,
 
-                          const wxString& cmd,
 
-                          wxProcess *process)
 
-            : wxFrame(parent, wxID_ANY, cmd),
 
-              m_process(process),
 
-              // in a real program we'd check that the streams are !NULL here
 
-              m_out(*process->GetOutputStream()),
 
-              m_in(*process->GetInputStream()),
 
-              m_err(*process->GetErrorStream())
 
- {
 
-     m_process->SetNextHandler(this);
 
-     wxPanel *panel = new wxPanel(this, wxID_ANY);
 
-     m_textOut = new wxTextCtrl(panel, wxID_ANY, wxEmptyString,
 
-                               wxDefaultPosition, wxDefaultSize,
 
-                               wxTE_PROCESS_ENTER);
 
-     m_textIn = new wxTextCtrl(panel, wxID_ANY, wxEmptyString,
 
-                                wxDefaultPosition, wxDefaultSize,
 
-                                wxTE_MULTILINE | wxTE_RICH);
 
-     m_textIn->SetEditable(false);
 
-     m_textErr = new wxTextCtrl(panel, wxID_ANY, wxEmptyString,
 
-                                wxDefaultPosition, wxDefaultSize,
 
-                                wxTE_MULTILINE | wxTE_RICH);
 
-     m_textErr->SetEditable(false);
 
-     wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
 
-     sizerTop->Add(m_textOut, 0, wxGROW | wxALL, 5);
 
-     wxSizer *sizerBtns = new wxBoxSizer(wxHORIZONTAL);
 
-     sizerBtns->
 
-         Add(new wxButton(panel, Exec_Btn_Send, wxT("&Send")), 0, wxALL, 5);
 
-     sizerBtns->
 
-         Add(new wxButton(panel, Exec_Btn_SendFile, wxT("&File...")), 0, wxALL, 5);
 
-     sizerBtns->
 
-         Add(new wxButton(panel, Exec_Btn_Get, wxT("&Get")), 0, wxALL, 5);
 
-     sizerBtns->
 
-         Add(new wxButton(panel, Exec_Btn_Close, wxT("&Close")), 0, wxALL, 5);
 
-     sizerTop->Add(sizerBtns, 0, wxCENTRE | wxALL, 5);
 
-     sizerTop->Add(m_textIn, 1, wxGROW | wxALL, 5);
 
-     sizerTop->Add(m_textErr, 1, wxGROW | wxALL, 5);
 
-     panel->SetSizer(sizerTop);
 
-     sizerTop->Fit(this);
 
-     Show();
 
- }
 
- void MyPipeFrame::OnBtnSendFile(wxCommandEvent& WXUNUSED(event))
 
- {
 
- #if wxUSE_FILEDLG
 
-     wxFileDialog filedlg(this, wxT("Select file to send"));
 
-     if ( filedlg.ShowModal() != wxID_OK )
 
-         return;
 
-     wxFFile file(filedlg.GetFilename(), wxT("r"));
 
-     wxString data;
 
-     if ( !file.IsOpened() || !file.ReadAll(&data) )
 
-         return;
 
-     // can't write the entire string at once, this risk overflowing the pipe
 
-     // and we would dead lock
 
-     size_t len = data.length();
 
-     const wxChar *pc = data.c_str();
 
-     while ( len )
 
-     {
 
-         const size_t CHUNK_SIZE = 4096;
 
-         m_out.Write(pc, len > CHUNK_SIZE ? CHUNK_SIZE : len);
 
-         // note that not all data could have been written as we don't block on
 
-         // the write end of the pipe
 
-         const size_t lenChunk = m_out.LastWrite();
 
-         pc += lenChunk;
 
-         len -= lenChunk;
 
-         DoGet();
 
-     }
 
- #endif // wxUSE_FILEDLG
 
- }
 
- void MyPipeFrame::DoGet()
 
- {
 
-     // we don't have any way to be notified when any input appears on the
 
-     // stream so we have to poll it :-(
 
-     DoGetFromStream(m_textIn, m_in);
 
-     DoGetFromStream(m_textErr, m_err);
 
- }
 
- void MyPipeFrame::DoGetFromStream(wxTextCtrl *text, wxInputStream& in)
 
- {
 
-     while ( in.CanRead() )
 
-     {
 
-         char buffer[4096];
 
-         buffer[in.Read(buffer, WXSIZEOF(buffer) - 1).LastRead()] = '\0';
 
-         text->AppendText(buffer);
 
-     }
 
- }
 
- void MyPipeFrame::DoClose()
 
- {
 
-     m_process->CloseOutput();
 
-     DisableInput();
 
- }
 
- void MyPipeFrame::DisableInput()
 
- {
 
-     m_textOut->SetEditable(false);
 
-     FindWindow(Exec_Btn_Send)->Disable();
 
-     FindWindow(Exec_Btn_SendFile)->Disable();
 
-     FindWindow(Exec_Btn_Close)->Disable();
 
- }
 
- void MyPipeFrame::DisableOutput()
 
- {
 
-     FindWindow(Exec_Btn_Get)->Disable();
 
- }
 
- void MyPipeFrame::OnClose(wxCloseEvent& event)
 
- {
 
-     if ( m_process )
 
-     {
 
-         // we're not interested in getting the process termination notification
 
-         // if we are closing it ourselves
 
-         wxProcess *process = m_process;
 
-         m_process = NULL;
 
-         process->SetNextHandler(NULL);
 
-         process->CloseOutput();
 
-     }
 
-     event.Skip();
 
- }
 
- void MyPipeFrame::OnProcessTerm(wxProcessEvent& WXUNUSED(event))
 
- {
 
-     DoGet();
 
-     wxDELETE(m_process);
 
-     wxLogWarning(wxT("The other process has terminated, closing"));
 
-     DisableInput();
 
-     DisableOutput();
 
- }
 
 
  |