From da00a8bb164dd1f58dd0bb211475538a375867b4 Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Fri, 12 Jul 2002 18:15:49 +0000
Subject: [PATCH] added and documented wxProcess::Open()

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@16152 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/process.tex | 37 ++++++++++++++++++++++++++
 include/wx/process.h      | 56 +++++++++++++++++++++++++++++++--------
 src/common/process.cpp    | 18 +++++++++++--
 3 files changed, 98 insertions(+), 13 deletions(-)

diff --git a/docs/latex/wx/process.tex b/docs/latex/wx/process.tex
index f8475c9e63..98e90695dc 100644
--- a/docs/latex/wx/process.tex
+++ b/docs/latex/wx/process.tex
@@ -45,6 +45,8 @@ for explicit destruction.}
 
 \func{}{wxProcess}{\param{wxEvtHandler *}{ parent = NULL}, \param{int}{ id = -1}}
 
+\func{}{wxProcess}{\param{int }{flags}}
+
 Constructs a process object. {\it id} is only used in the case you want to
 use wxWindows events. It identifies this object, or another window that will
 receive the event.
@@ -53,12 +55,20 @@ If the {\it parent} parameter is different from NULL, it will receive
 a wxEVT\_END\_PROCESS notification event (you should insert EVT\_END\_PROCESS
 macro in the event table of the parent to handle it) with the given {\it id}.
 
+The second constructor creates an object without any associated parent (and
+hence no id neither) but allows to specify the {\it flags} which can have the
+value of {\tt wxPROCESS\_DEFAULT} or {\tt wxPROCESS\_REDIRECT}. Specifying the
+former value has no particular effect while using the latter one is equivalent
+to calling \helpref{Redirect}{wxprocessredirect}.
+
 \wxheading{Parameters}
 
 \docparam{parent}{The event handler parent.}
 
 \docparam{id}{id of an event.}
 
+\docparam{flags}{either {\tt wxPROCESS\_DEFAULT} or {\tt wxPROCESS\_REDIRECT}}
+
 \membersection{wxProcess::\destruct{wxProcess}}
 
 \func{}{\destruct{wxProcess}}{\void}
@@ -184,6 +194,33 @@ It raises a wxWindows event when it isn't overridden.
 
 \docparam{status}{The exit code of the process.}
 
+\membersection{wxProcess::Open}\label{wxprocessopen}
+
+\func{static wxProcess *}{Open}{\param{const wxString\& }{cmd}}
+
+This static method replaces the standard {\tt popen()} function: it launches
+the process specified by the {\it cmd} parameter and returns the wxProcess
+object which can be used to retrieve the streams connected to the standard
+input, output and error output of the child process.
+
+If the process couldn't be launched, {\tt NULL} is returned. Note that in any
+case the returned pointer should {\bf not} be deleted, rather the process
+object will be destroyed automatically when the child process terminates. This
+does mean that the child process should be told to quit before the main program
+exits to avoid memory leaks.
+
+\wxheading{Parameters}
+
+\docparam{cmd}{The command to execute, including optional arguments.}
+
+\wxheading{Return value}
+
+A pointer to new wxProcess object or {\tt NULL} on error.
+
+\wxheading{See also}
+
+\helpref{wxExecute}{wxexecute}
+
 \membersection{wxProcess::Redirect}\label{wxprocessredirect}
 
 \func{void}{Redirect}{\void}
diff --git a/include/wx/process.h b/include/wx/process.h
index 91c71032eb..67ac9c258f 100644
--- a/include/wx/process.h
+++ b/include/wx/process.h
@@ -24,6 +24,16 @@
 
 #include "wx/utils.h"       // for wxSignal
 
+// the wxProcess creation flags
+enum
+{
+    // no redirection
+    wxPROCESS_DEFAULT = 0,
+
+    // redirect the IO of the child process
+    wxPROCESS_REDIRECT = 1
+};
+
 // ----------------------------------------------------------------------------
 // A wxProcess object should be passed to wxExecute - than its OnTerminate()
 // function will be called when the process terminates.
@@ -32,10 +42,27 @@
 class WXDLLEXPORT wxProcess : public wxEvtHandler
 {
 public:
+    // kill the process with the given PID
+    static wxKillError Kill(int pid, wxSignal sig = wxSIGTERM);
+
+    // test if the given process exists
+    static bool Exists(int pid);
+
+    // this function replaces the standard popen() one: it launches a process
+    // asynchronously and allows the caller to get the streams connected to its
+    // std{in|out|err}
+    //
+    // on error NULL is returned, in any case the process object will be
+    // deleted automatically when the process terminates and should *not* be
+    // deleted by the caller
+    static wxProcess *Open(const wxString& cmd);
+
+
+    // ctors
     wxProcess(wxEvtHandler *parent = (wxEvtHandler *) NULL, int id = -1)
-        { Init(parent, id, FALSE); }
-    wxProcess(wxEvtHandler *parent, bool redirect)
-        { Init(parent, -1, redirect); }
+        { Init(parent, id, wxPROCESS_DEFAULT); }
+
+    wxProcess(int flags) { Init(NULL, -1, flags); }
 
     virtual ~wxProcess();
 
@@ -62,23 +89,30 @@ public:
     void CloseOutput() { delete m_outputStream; m_outputStream = NULL; }
 
     // implementation only (for wxExecute)
-    void SetPipeStreams(wxInputStream *inStream,
-                        wxOutputStream *outStream,
+    //
+    // NB: the streams passed here should correspond to the child process
+    //     stdout, stdin and stderr and here the normal naming convention is
+    //     used unlike elsewhere in this class
+    void SetPipeStreams(wxInputStream *outStream,
+                        wxOutputStream *inStream,
                         wxInputStream *errStream);
 #endif // wxUSE_STREAMS
 
-    // kill the process with the given PID
-    static wxKillError Kill(int pid, wxSignal sig = wxSIGTERM);
-
-    // test if the given process exists
-    static bool Exists(int pid);
+    // for backwards compatibility only, don't use
+#if WXWIN_COMPATIBILITY_2_2
+    wxProcess(wxEvtHandler *parent, bool redirect)
+        { Init(parent, -1, redirect ? wxPROCESS_REDIRECT : wxPROCESS_DEFAULT); }
+#endif // WXWIN_COMPATIBILITY_2_2
 
 protected:
-    void Init(wxEvtHandler *parent, int id, bool redirect);
+    void Init(wxEvtHandler *parent, int id, int flags);
 
     int m_id;
 
 #if wxUSE_STREAMS
+    // these streams are connected to stdout, stderr and stdin of the child
+    // process respectively (yes, m_inputStream corresponds to stdout -- very
+    // confusing but too late to change now)
     wxInputStream  *m_inputStream,
                    *m_errorStream;
     wxOutputStream *m_outputStream;
diff --git a/src/common/process.cpp b/src/common/process.cpp
index 05e24ffb20..d98c7178ef 100644
--- a/src/common/process.cpp
+++ b/src/common/process.cpp
@@ -47,13 +47,13 @@ IMPLEMENT_DYNAMIC_CLASS(wxProcessEvent, wxEvent)
 // wxProcess creation
 // ----------------------------------------------------------------------------
 
-void wxProcess::Init(wxEvtHandler *parent, int id, bool redirect)
+void wxProcess::Init(wxEvtHandler *parent, int id, int flags)
 {
     if ( parent )
         SetNextHandler(parent);
 
     m_id         = id;
-    m_redirect   = redirect;
+    m_redirect   = (flags & wxPROCESS_REDIRECT) != 0;
 
 #if wxUSE_STREAMS
     m_inputStream  = NULL;
@@ -62,6 +62,20 @@ void wxProcess::Init(wxEvtHandler *parent, int id, bool redirect)
 #endif // wxUSE_STREAMS
 }
 
+/* static */
+wxProcess *wxProcess::Open(const wxString& cmd)
+{
+    wxProcess *process = new wxProcess(wxPROCESS_REDIRECT);
+    if ( !wxExecute(cmd, wxEXEC_ASYNC, process) )
+    {
+        // couldn't launch the process
+        delete process;
+        return NULL;
+    }
+
+    return process;
+}
+
 // ----------------------------------------------------------------------------
 // wxProcess termination
 // ----------------------------------------------------------------------------
-- 
2.50.0

