]> git.saurik.com Git - wxWidgets.git/blame - samples/exec/exec.cpp
blind fix for gcc warning about ?: and different enums
[wxWidgets.git] / samples / exec / exec.cpp
CommitLineData
69c33c6c
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: exec.cpp
3// Purpose: exec sample demonstrates wxExecute and related functions
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 15.01.00
7// RCS-ID: $Id$
8// Copyright: (c) Vadim Zeitlin
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "exec.cpp"
22 #pragma interface "exec.cpp"
23#endif
24
25// For compilers that support precompilation, includes "wx/wx.h".
26#include "wx/wxprec.h"
27
28#ifdef __BORLANDC__
29 #pragma hdrstop
30#endif
31
32// for all others, include the necessary headers (this file is usually all you
33// need because it includes almost all "standard" wxWindows headers
34#ifndef WX_PRECOMP
35 #include "wx/app.h"
36 #include "wx/frame.h"
92a2a7eb
VZ
37 #include "wx/panel.h"
38
39 #include "wx/timer.h"
eb671557 40
69c33c6c 41 #include "wx/utils.h"
a8f0faf3 42 #include "wx/menu.h"
eb671557 43
a8f0faf3
GRG
44 #include "wx/msgdlg.h"
45 #include "wx/textdlg.h"
8ce88dfa 46 #include "wx/filedlg.h"
50567b69 47 #include "wx/choicdlg.h"
eb671557
VZ
48
49 #include "wx/button.h"
50 #include "wx/textctrl.h"
51 #include "wx/listbox.h"
52
53 #include "wx/sizer.h"
69c33c6c
VZ
54#endif
55
d8e41d42
VZ
56#include "wx/txtstrm.h"
57
69c33c6c
VZ
58#include "wx/process.h"
59
6ba63600
VZ
60#include "wx/mimetype.h"
61
d93c719a
VZ
62#ifdef __WINDOWS__
63 #include "wx/dde.h"
64#endif // __WINDOWS__
65
69c33c6c 66// ----------------------------------------------------------------------------
eb671557 67// the usual application and main frame classes
69c33c6c
VZ
68// ----------------------------------------------------------------------------
69
70// Define a new application type, each program should derive a class from wxApp
71class MyApp : public wxApp
72{
73public:
74 // override base class virtuals
75 // ----------------------------
76
77 // this one is called on application startup and is a good place for the app
78 // initialization (doing it here and not in the ctor allows to have an error
79 // return: if OnInit() returns false, the application terminates)
80 virtual bool OnInit();
81};
82
cd6ce4a9
VZ
83// Define an array of process pointers used by MyFrame
84class MyPipedProcess;
85WX_DEFINE_ARRAY(MyPipedProcess *, MyProcessesArray);
86
69c33c6c
VZ
87// Define a new frame type: this is going to be our main frame
88class MyFrame : public wxFrame
89{
90public:
91 // ctor(s)
92 MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
93
94 // event handlers (these functions should _not_ be virtual)
95 void OnQuit(wxCommandEvent& event);
96
50567b69
VZ
97 void OnKill(wxCommandEvent& event);
98
d8e41d42
VZ
99 void OnClear(wxCommandEvent& event);
100
69c33c6c
VZ
101 void OnSyncExec(wxCommandEvent& event);
102 void OnAsyncExec(wxCommandEvent& event);
103 void OnShell(wxCommandEvent& event);
d8e41d42 104 void OnExecWithRedirect(wxCommandEvent& event);
f6bcfd97
BP
105 void OnExecWithPipe(wxCommandEvent& event);
106
eb671557
VZ
107 void OnPOpen(wxCommandEvent& event);
108
6ba63600
VZ
109 void OnFileExec(wxCommandEvent& event);
110
69c33c6c
VZ
111 void OnAbout(wxCommandEvent& event);
112
cd6ce4a9 113 // polling output of async processes
92a2a7eb 114 void OnTimer(wxTimerEvent& event);
cd6ce4a9
VZ
115 void OnIdle(wxIdleEvent& event);
116
d8e41d42 117 // for MyPipedProcess
f6bcfd97 118 void OnProcessTerminated(MyPipedProcess *process);
d8e41d42
VZ
119 wxListBox *GetLogListBox() const { return m_lbox; }
120
69c33c6c 121private:
f6bcfd97
BP
122 void ShowOutput(const wxString& cmd,
123 const wxArrayString& output,
124 const wxString& title);
125
6ba63600
VZ
126 void DoAsyncExec(const wxString& cmd);
127
92a2a7eb
VZ
128 void AddAsyncProcess(MyPipedProcess *process)
129 {
130 if ( m_running.IsEmpty() )
131 {
132 // we want to start getting the timer events to ensure that a
133 // steady stream of idle events comes in -- otherwise we
134 // wouldn't be able to poll the child process input
135 m_timerIdleWakeUp.Start(100);
136 }
137 //else: the timer is already running
138
139 m_running.Add(process);
140 }
141
142 void RemoveAsyncProcess(MyPipedProcess *process)
143 {
144 m_running.Remove(process);
145
146 if ( m_running.IsEmpty() )
147 {
148 // we don't need to get idle events all the time any more
149 m_timerIdleWakeUp.Stop();
150 }
151 }
152
50567b69 153 // the PID of the last process we launched asynchronously
aec18ff7 154 long m_pidLast;
50567b69 155
ca289436 156 // last command we executed
69c33c6c
VZ
157 wxString m_cmdLast;
158
ca289436
VZ
159#ifdef __WINDOWS__
160 void OnDDEExec(wxCommandEvent& event);
161 void OnDDERequest(wxCommandEvent& event);
162
163 bool GetDDEServer();
164
165 // last params of a DDE transaction
166 wxString m_server,
167 m_topic,
168 m_cmdDde;
169#endif // __WINDOWS__
170
d8e41d42
VZ
171 wxListBox *m_lbox;
172
cd6ce4a9
VZ
173 MyProcessesArray m_running;
174
92a2a7eb
VZ
175 // the idle event wake up timer
176 wxTimer m_timerIdleWakeUp;
177
69c33c6c
VZ
178 // any class wishing to process wxWindows events must use this macro
179 DECLARE_EVENT_TABLE()
180};
181
eb671557
VZ
182// ----------------------------------------------------------------------------
183// MyPipeFrame: allows the user to communicate with the child process
184// ----------------------------------------------------------------------------
185
186class MyPipeFrame : public wxFrame
187{
188public:
189 MyPipeFrame(wxFrame *parent,
190 const wxString& cmd,
191 wxProcess *process);
192
193protected:
194 void OnTextEnter(wxCommandEvent& event) { DoSend(); }
195 void OnBtnSend(wxCommandEvent& event) { DoSend(); }
196 void OnBtnGet(wxCommandEvent& event) { DoGet(); }
197
198 void OnClose(wxCloseEvent& event);
199
7ca528cb
VZ
200 void OnProcessTerm(wxProcessEvent& event);
201
202 void DoSend()
203 {
204 m_out.WriteString(m_textIn->GetValue() + '\n');
205 m_textIn->Clear();
206
207 DoGet();
208 }
209
eb671557
VZ
210 void DoGet();
211
212private:
213 wxProcess *m_process;
214
215 wxTextInputStream m_in;
216 wxTextOutputStream m_out;
217
218 wxTextCtrl *m_textIn,
219 *m_textOut;
220
221 DECLARE_EVENT_TABLE()
222};
223
224// ----------------------------------------------------------------------------
225// wxProcess-derived classes
226// ----------------------------------------------------------------------------
227
69c33c6c
VZ
228// This is the handler for process termination events
229class MyProcess : public wxProcess
230{
231public:
d8e41d42 232 MyProcess(MyFrame *parent, const wxString& cmd)
69c33c6c
VZ
233 : wxProcess(parent), m_cmd(cmd)
234 {
235 m_parent = parent;
236 }
237
238 // instead of overriding this virtual function we might as well process the
239 // event from it in the frame class - this might be more convenient in some
240 // cases
241 virtual void OnTerminate(int pid, int status);
242
d8e41d42
VZ
243protected:
244 MyFrame *m_parent;
69c33c6c
VZ
245 wxString m_cmd;
246};
247
d8e41d42
VZ
248// A specialization of MyProcess for redirecting the output
249class MyPipedProcess : public MyProcess
250{
251public:
252 MyPipedProcess(MyFrame *parent, const wxString& cmd)
253 : MyProcess(parent, cmd)
254 {
cd6ce4a9 255 Redirect();
d8e41d42
VZ
256 }
257
258 virtual void OnTerminate(int pid, int status);
cd6ce4a9 259
f6bcfd97
BP
260 virtual bool HasInput();
261};
262
263// A version of MyPipedProcess which also sends input to the stdin of the
264// child process
265class MyPipedProcess2 : public MyPipedProcess
266{
267public:
268 MyPipedProcess2(MyFrame *parent, const wxString& cmd, const wxString& input)
269 : MyPipedProcess(parent, cmd), m_input(input)
270 {
271 }
272
273 virtual bool HasInput();
274
275private:
276 wxString m_input;
d8e41d42
VZ
277};
278
69c33c6c
VZ
279// ----------------------------------------------------------------------------
280// constants
281// ----------------------------------------------------------------------------
282
283// IDs for the controls and the menu commands
284enum
285{
286 // menu items
287 Exec_Quit = 100,
50567b69 288 Exec_Kill,
d8e41d42 289 Exec_ClearLog,
69c33c6c
VZ
290 Exec_SyncExec = 200,
291 Exec_AsyncExec,
292 Exec_Shell,
eb671557 293 Exec_POpen,
6ba63600 294 Exec_OpenFile,
d93c719a 295 Exec_DDEExec,
ca289436 296 Exec_DDERequest,
d8e41d42 297 Exec_Redirect,
f6bcfd97 298 Exec_Pipe,
eb671557
VZ
299 Exec_About = 300,
300
301 // control ids
302 Exec_Btn_Send = 1000,
303 Exec_Btn_Get
69c33c6c
VZ
304};
305
d93c719a
VZ
306static const wxChar *DIALOG_TITLE = _T("Exec sample");
307
69c33c6c
VZ
308// ----------------------------------------------------------------------------
309// event tables and other macros for wxWindows
310// ----------------------------------------------------------------------------
311
312// the event tables connect the wxWindows events with the functions (event
313// handlers) which process them. It can be also done at run-time, but for the
314// simple menu events like this the static method is much simpler.
315BEGIN_EVENT_TABLE(MyFrame, wxFrame)
316 EVT_MENU(Exec_Quit, MyFrame::OnQuit)
50567b69 317 EVT_MENU(Exec_Kill, MyFrame::OnKill)
d8e41d42 318 EVT_MENU(Exec_ClearLog, MyFrame::OnClear)
69c33c6c
VZ
319
320 EVT_MENU(Exec_SyncExec, MyFrame::OnSyncExec)
321 EVT_MENU(Exec_AsyncExec, MyFrame::OnAsyncExec)
322 EVT_MENU(Exec_Shell, MyFrame::OnShell)
d8e41d42 323 EVT_MENU(Exec_Redirect, MyFrame::OnExecWithRedirect)
f6bcfd97
BP
324 EVT_MENU(Exec_Pipe, MyFrame::OnExecWithPipe)
325
eb671557
VZ
326 EVT_MENU(Exec_POpen, MyFrame::OnPOpen)
327
6ba63600
VZ
328 EVT_MENU(Exec_OpenFile, MyFrame::OnFileExec)
329
5af4b77f 330#ifdef __WINDOWS__
d93c719a 331 EVT_MENU(Exec_DDEExec, MyFrame::OnDDEExec)
ca289436 332 EVT_MENU(Exec_DDERequest, MyFrame::OnDDERequest)
5af4b77f 333#endif // __WINDOWS__
eb671557 334
69c33c6c 335 EVT_MENU(Exec_About, MyFrame::OnAbout)
cd6ce4a9
VZ
336
337 EVT_IDLE(MyFrame::OnIdle)
92a2a7eb
VZ
338
339 EVT_TIMER(-1, MyFrame::OnTimer)
69c33c6c
VZ
340END_EVENT_TABLE()
341
eb671557
VZ
342BEGIN_EVENT_TABLE(MyPipeFrame, wxFrame)
343 EVT_BUTTON(Exec_Btn_Send, MyPipeFrame::OnBtnSend)
344 EVT_BUTTON(Exec_Btn_Get, MyPipeFrame::OnBtnGet)
345
346 EVT_TEXT_ENTER(-1, MyPipeFrame::OnTextEnter)
347
348 EVT_CLOSE(MyPipeFrame::OnClose)
7ca528cb
VZ
349
350 EVT_END_PROCESS(-1, MyPipeFrame::OnProcessTerm)
eb671557
VZ
351END_EVENT_TABLE()
352
69c33c6c
VZ
353// Create a new application object: this macro will allow wxWindows to create
354// the application object during program execution (it's better than using a
355// static object for many reasons) and also declares the accessor function
356// wxGetApp() which will return the reference of the right type (i.e. MyApp and
357// not wxApp)
358IMPLEMENT_APP(MyApp)
359
360// ============================================================================
361// implementation
362// ============================================================================
363
364// ----------------------------------------------------------------------------
365// the application class
366// ----------------------------------------------------------------------------
367
368// `Main program' equivalent: the program execution "starts" here
369bool MyApp::OnInit()
370{
371 // Create the main application window
372 MyFrame *frame = new MyFrame(_T("Exec wxWindows sample"),
373 wxDefaultPosition, wxSize(500, 140));
374
375 // Show it and tell the application that it's our main window
376 frame->Show(TRUE);
377 SetTopWindow(frame);
378
379 // success: wxApp::OnRun() will be called which will enter the main message
380 // loop and the application will run. If we returned FALSE here, the
381 // application would exit immediately.
382 return TRUE;
383}
384
385// ----------------------------------------------------------------------------
386// main frame
387// ----------------------------------------------------------------------------
388
389// frame constructor
390MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
92a2a7eb
VZ
391 : wxFrame((wxFrame *)NULL, -1, title, pos, size),
392 m_timerIdleWakeUp(this)
69c33c6c 393{
50567b69
VZ
394 m_pidLast = 0;
395
69c33c6c
VZ
396#ifdef __WXMAC__
397 // we need this in order to allow the about menu relocation, since ABOUT is
398 // not the default id of the about menu
399 wxApp::s_macAboutMenuItemId = Exec_About;
400#endif
401
69c33c6c
VZ
402 // create a menu bar
403 wxMenu *menuFile = new wxMenu(_T(""), wxMENU_TEAROFF);
50567b69
VZ
404 menuFile->Append(Exec_Kill, _T("&Kill process...\tCtrl-K"),
405 _T("Kill a process by PID"));
406 menuFile->AppendSeparator();
d8e41d42
VZ
407 menuFile->Append(Exec_ClearLog, _T("&Clear log\tCtrl-C"),
408 _T("Clear the log window"));
409 menuFile->AppendSeparator();
69c33c6c
VZ
410 menuFile->Append(Exec_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
411
412 wxMenu *execMenu = new wxMenu;
413 execMenu->Append(Exec_SyncExec, _T("Sync &execution...\tCtrl-E"),
414 _T("Launch a program and return when it terminates"));
415 execMenu->Append(Exec_AsyncExec, _T("&Async execution...\tCtrl-A"),
416 _T("Launch a program and return immediately"));
417 execMenu->Append(Exec_Shell, _T("Execute &shell command...\tCtrl-S"),
418 _T("Launch a shell and execute a command in it"));
f6bcfd97 419 execMenu->AppendSeparator();
d8e41d42
VZ
420 execMenu->Append(Exec_Redirect, _T("Capture command &output...\tCtrl-O"),
421 _T("Launch a program and capture its output"));
eb671557 422 execMenu->Append(Exec_Pipe, _T("&Pipe through command..."),
f6bcfd97 423 _T("Pipe a string through a filter"));
eb671557
VZ
424 execMenu->Append(Exec_POpen, _T("&Open a pipe to a command...\tCtrl-P"),
425 _T("Open a pipe to and from another program"));
69c33c6c 426
6ba63600
VZ
427 execMenu->AppendSeparator();
428 execMenu->Append(Exec_OpenFile, _T("Open &file...\tCtrl-F"),
429 _T("Launch the command to open this kind of files"));
d93c719a
VZ
430#ifdef __WINDOWS__
431 execMenu->AppendSeparator();
432 execMenu->Append(Exec_DDEExec, _T("Execute command via &DDE...\tCtrl-D"));
ca289436 433 execMenu->Append(Exec_DDERequest, _T("Send DDE &request...\tCtrl-R"));
d93c719a
VZ
434#endif
435
69c33c6c
VZ
436 wxMenu *helpMenu = new wxMenu(_T(""), wxMENU_TEAROFF);
437 helpMenu->Append(Exec_About, _T("&About...\tF1"), _T("Show about dialog"));
438
439 // now append the freshly created menu to the menu bar...
440 wxMenuBar *menuBar = new wxMenuBar();
441 menuBar->Append(menuFile, _T("&File"));
442 menuBar->Append(execMenu, _T("&Exec"));
443 menuBar->Append(helpMenu, _T("&Help"));
444
445 // ... and attach this menu bar to the frame
446 SetMenuBar(menuBar);
447
9121bed2 448 // create the listbox in which we will show misc messages as they come
d8e41d42 449 m_lbox = new wxListBox(this, -1);
8ce88dfa
VZ
450 wxFont font(12, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL,
451 wxFONTWEIGHT_NORMAL);
452 if ( font.Ok() )
453 m_lbox->SetFont(font);
9121bed2 454
69c33c6c
VZ
455#if wxUSE_STATUSBAR
456 // create a status bar just for fun (by default with 1 pane only)
e680a378 457 CreateStatusBar();
9121bed2 458 SetStatusText(_T("Welcome to wxWindows exec sample!"));
69c33c6c
VZ
459#endif // wxUSE_STATUSBAR
460}
461
50567b69
VZ
462// ----------------------------------------------------------------------------
463// event handlers: file and help menu
464// ----------------------------------------------------------------------------
69c33c6c
VZ
465
466void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
467{
468 // TRUE is to force the frame to close
469 Close(TRUE);
470}
471
d8e41d42
VZ
472void MyFrame::OnClear(wxCommandEvent& WXUNUSED(event))
473{
474 m_lbox->Clear();
475}
476
69c33c6c
VZ
477void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
478{
92a2a7eb 479