Code::Blocks  SVN r11506
pipedprocess.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  *
5  * $Revision: 11282 $
6  * $Id: pipedprocess.cpp 11282 2018-01-31 23:48:23Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/pipedprocess.cpp $
8  */
9 
10 #include "sdk_precomp.h"
11 
12 #ifndef CB_PRECOMP
13  #include <wx/app.h> // wxWakeUpIdle
14  #include "pipedprocess.h" // class' header file
15  #include "sdk_events.h"
16  #include "globals.h"
17 #endif
18 
19 // The following class is created to override wxTextStream::ReadLine()
21 {
22  protected:
24  public:
25 #if wxUSE_UNICODE
26  cbTextInputStream(wxInputStream& s, const wxString &sep=wxT(" \t"), wxMBConv& conv = wxConvLocal )
27  : wxTextInputStream(s, sep, conv),
28  m_allowMBconversion(true)
29  {
30  memset((void*)m_lastBytes, 0, 10);
31  }
32 #else
33  cbTextInputStream(wxInputStream& s, const wxString &sep=wxT(" \t") )
35  {
36  memset((void*)m_lastBytes, 0, 10);
37  }
38 #endif
40 
41 
42  // The following function was copied verbatim from wxTextStream::NextChar()
43  // The only change, is the removal of the MB2WC function
44  // With PipedProcess we work with compilers/debuggers which (usually) don't
45  // send us unicode (at least GDB).
47  {
48  #if wxUSE_UNICODE
49  wxChar wbuf[2];
50  memset((void*)m_lastBytes, 0, 10);
51  for (size_t inlen = 0; inlen < 9; inlen++)
52  {
53  // actually read the next character
54  m_lastBytes[inlen] = m_input.GetC();
55 
56  if (m_input.LastRead() <= 0)
57  return wxEOT;
58  if (m_allowMBconversion)
59  {
60  int retlen = (int) m_conv->MB2WC(wbuf, m_lastBytes, 2); // returns -1 for failure
61  if (retlen >= 0) // res == 0 could happen for '\0' char
62  return wbuf[0];
63  }
64  else
65  return m_lastBytes[inlen]; // C::B fix (?)
66  }
67  // there should be no encoding which requires more than nine bytes for one character...
68  return wxEOT;
69  #else
70  m_lastBytes[0] = m_input.GetC();
71 
72  if (m_input.LastRead() <= 0)
73  return wxEOT;
74 
75  return m_lastBytes[0];
76  #endif
77  }
78 
79  // The following function was copied verbatim from wxTextStream::ReadLine()
80  // The only change, is the addition of m_input.CanRead() in the while()
82  {
83  wxString line;
84 
85  while ( m_input.CanRead() && !m_input.Eof() )
86  {
87  wxChar c = NextChar();
88  if (m_input.LastRead() <= 0)
89  break;
90 
91  if ( !m_input )
92  break;
93 
94  if (EatEOL(c))
95  break;
96 
97  line += c;
98  }
99  return line;
100  }
101 };
102 
103 int idTimerPollProcess = wxNewId();
104 
105 BEGIN_EVENT_TABLE(PipedProcess, wxProcess)
106  EVT_TIMER(idTimerPollProcess, PipedProcess::OnTimer)
107  EVT_IDLE(PipedProcess::OnIdle)
108 END_EVENT_TABLE()
109 
110 // class constructor
111 PipedProcess::PipedProcess(PipedProcess** pvThis, wxEvtHandler* parent, int id, bool pipe,
112  const wxString& dir, int index)
113  : wxProcess(parent, id),
114  m_Parent(parent),
115  m_Id(id),
116  m_Pid(0),
117  m_Index(index),
118  m_Stopped(false),
119  m_pvThis(pvThis)
120 {
121  const wxString &unixDir = UnixFilename(dir);
122  if (!unixDir.empty())
123  wxSetWorkingDirectory(unixDir);
124  if (pipe)
125  Redirect();
126 }
127 
128 // class destructor
130 {
131  // insert your code here
132 }
133 
134 int PipedProcess::Launch(const wxString& cmd, cb_unused unsigned int pollingInterval)
135 {
136  m_Stopped = false;
137  m_Pid = wxExecute(cmd, wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER, this);
138  if (m_Pid)
139  {
140 // m_timerPollProcess.SetOwner(this, idTimerPollProcess);
141 // m_timerPollProcess.Start(pollingInterval);
142  }
143  return m_Pid;
144 }
145 
147 {
148  //Manager::Get()->GetLogManager()->Log(m_PageIndex, cmd);
149  wxOutputStream* pOut = GetOutputStream();
150  if (pOut)
151  {
152  wxTextOutputStream sin(*pOut);
153  wxString msg = text + _T('\n');
154  sin.WriteString(msg);
155  }
156 }
157 
159 {
160  m_Stopped = true;
161  char buf[4096];
162  if ( IsErrorAvailable() )
163  {
164  wxInputStream *in = GetErrorStream();
165  while (in->Read(&buf, sizeof(buf)).LastRead())
166  ;
167  }
168  if ( IsInputAvailable() )
169  {
171  while (in->Read(&buf, sizeof(buf)).LastRead())
172  ;
173  }
174 }
175 
177 {
178  if (IsErrorAvailable())
179  {
180  cbTextInputStream serr(*GetErrorStream());
181 
182  wxString msg;
183  msg << serr.ReadLine();
184 
185  if (m_Stopped)
186  return true;
187 
189  event.SetString(msg);
190  event.SetX(m_Index);
191  wxPostEvent(m_Parent, event);
192 
193  return true;
194  }
195 
196  if (IsInputAvailable())
197  {
199 
200  wxString msg;
201  msg << sout.ReadLine();
202 
203  if (m_Stopped)
204  return true;
205 
207  event.SetString(msg);
208  event.SetX(m_Index);
209  wxPostEvent(m_Parent, event);
210 
211  return true;
212  }
213 
214  return false;
215 }
216 
217 void PipedProcess::OnTerminate(int /*pid*/, int status)
218 {
219  // show the rest of the output
220  while ( HasInput() )
221  ;
222 
224  event.SetInt(status);
225  event.SetX(m_Index);
226  wxPostEvent(m_Parent, event);
227 
228  if (m_pvThis)
229  *m_pvThis = nullptr;
230  delete this;
231 }
232 
233 void PipedProcess::OnTimer(cb_unused wxTimerEvent& event)
234 {
235  wxWakeUpIdle();
236 }
237 
238 void PipedProcess::OnIdle(cb_unused wxIdleEvent& event)
239 {
240  while ( HasInput() )
241  ;
242 }
virtual void WriteString(const wxString &string)
int wxNewId()
wxTextInputStream(wxInputStream &stream, const wxString &sep=" \", const wxMBConv &conv=wxConvAuto())
EVTIMPORT const wxEventType cbEVT_PIPEDPROCESS_STDOUT
Definition: sdk_events.cpp:121
void wxWakeUpIdle()
#define _T(string)
EVTIMPORT const wxEventType cbEVT_PIPEDPROCESS_TERMINATED
Definition: sdk_events.cpp:123
cbTextInputStream(wxInputStream &s, const wxString &sep=wxT(" \), wxMBConv &conv=wxConvLocal)
#define wxT(string)
bool empty() const
A generic Code::Blocks event.
Definition: sdk_events.h:20
wxUSE_UNICODE_dependent wxChar
virtual void SendString(const wxString &text)
DLLIMPORT wxString UnixFilename(const wxString &filename, wxPathFormat format=wxPATH_NATIVE)
Definition: globals.cpp:228
void wxPostEvent(wxEvtHandler *dest, const wxEvent &event)
bool wxSetWorkingDirectory(const wxString &dir)
void OnTerminate(int pid, int status) override
wxString ReadLine()
static const wxString sep
virtual int Launch(const wxString &cmd, unsigned int pollingInterval=100)
virtual void OnTimer(wxTimerEvent &event)
virtual bool HasInput()
const wxInputStream & GetInputStream() const
void ForfeitStreams()
~PipedProcess() override
virtual void OnIdle(wxIdleEvent &event)
EVTIMPORT const wxEventType cbEVT_PIPEDPROCESS_STDERR
Definition: sdk_events.cpp:122
long wxExecute(const wxString &command, int flags=wxEXEC_ASYNC, wxProcess *callback=NULL, const wxExecuteEnv *env=NULL)