Fixing Qt pipes.
[texmacs.git] / src / src / Plugins / Qt / qt_pipe_link.cpp
blob9416e0599272299014a1bdad8561e77d326bcb2d
2 /******************************************************************************
3 * MODULE : qt_pipe_link.cpp
4 * DESCRIPTION: TeXmacs links by pipes
5 * COPYRIGHT : (C) 2000 Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
12 #include "basic.hpp"
14 #if defined (QTTEXMACS) && (defined (__MINGW__) || defined (__MINGW32__) || defined (QTPIPES))
16 #include "tm_link.hpp"
17 #include "QTMPipeLink.hpp"
18 #include "hashset.hpp"
19 #include "iterator.hpp"
20 #include "timer.hpp"
22 #include <sys/types.h>
23 #include <signal.h>
24 #if defined(__MINGW__) || defined(__MINGW32__)
25 #else
26 # include <sys/wait.h>
27 #endif
29 hashset<pointer> pipe_link_set;
31 /******************************************************************************
32 * Definition of qt_pipe_link_rep class
33 ******************************************************************************/
35 struct qt_pipe_link_rep: tm_link_rep {
36 QTMPipeLink PipeLink;
38 public:
39 qt_pipe_link_rep (string cmd);
40 ~qt_pipe_link_rep ();
42 string start ();
43 void write (string s, int channel);
44 string& watch (int channel);
45 string read (int channel);
46 void listen (int msecs);
47 bool is_readable (int channel);
48 void interrupt ();
49 void stop ();
50 void feed (int channel);
53 qt_pipe_link_rep::qt_pipe_link_rep (string cmd) : PipeLink (cmd) {
54 PipeLink.feed_cmd = &feed_cmd;
55 pipe_link_set->insert ((pointer) this);
56 alive = false;
59 qt_pipe_link_rep::~qt_pipe_link_rep () {
60 stop ();
61 pipe_link_set->remove ((pointer) this);
64 /******************************************************************************
65 * Routines for qt_pipe_links
66 ******************************************************************************/
68 string
69 qt_pipe_link_rep::start () {
70 if (alive) return "busy";
71 if (DEBUG_AUTO) cerr << "TeXmacs] Launching '" << PipeLink.cmd << "'\n";
72 if (! PipeLink.launchCmd ()) {
73 if (DEBUG_AUTO) cerr << "TeXmacs] Error: cannot start '" << PipeLink.cmd << "'\n";
74 return "Error: cannot start application";
76 alive= true;
77 return "ok";
80 void
81 qt_pipe_link_rep::write (string s, int channel) {
82 if ((!alive) || (channel != LINK_IN)) return;
83 if (-1 == PipeLink.writeStdin (s)) {
84 cerr << "TeXmacs] Error: cannot write to '" << PipeLink.cmd << "'\n";
85 PipeLink.killProcess ();
89 void
90 qt_pipe_link_rep::feed (int channel) {
91 if ((!alive) || ((channel != LINK_OUT) && (channel != LINK_ERR))) return;
92 if (channel == LINK_OUT) PipeLink.feedBuf (QProcess::StandardOutput);
93 else PipeLink.feedBuf (QProcess::StandardError);
96 string&
97 qt_pipe_link_rep::watch (int channel) {
98 static string empty_string= "";
99 if (channel == LINK_OUT) return PipeLink.getOutbuf ();
100 else if (channel == LINK_ERR) return PipeLink.getErrbuf ();
101 else return empty_string;
104 string
105 qt_pipe_link_rep::read (int channel) {
106 if (channel == LINK_OUT) {
107 string r= PipeLink.getOutbuf ();
108 PipeLink.setOutbuf ("");
109 return r;
111 else if (channel == LINK_ERR) {
112 string r= PipeLink.getErrbuf ();
113 PipeLink.setErrbuf ("");
114 return r;
116 else return string("");
119 void
120 qt_pipe_link_rep::listen (int msecs) {
121 if (!alive) return;
122 time_t wait_until= texmacs_time () + msecs;
123 while ((PipeLink.getOutbuf() == "") && (PipeLink.getErrbuf() == "")) {
124 PipeLink.listenChannel (QProcess::StandardOutput, 0);
125 PipeLink.listenChannel (QProcess::StandardError, 0);
126 if (texmacs_time () - wait_until > 0) break;
130 bool
131 qt_pipe_link_rep::is_readable (int channel) {
132 if ((!alive) || ((channel != LINK_OUT) && (channel != LINK_ERR))) return false;
133 if (channel == LINK_OUT) PipeLink.listenChannel (QProcess::StandardOutput, 0);
134 else PipeLink.listenChannel (QProcess::StandardError, 0);
137 void
138 qt_pipe_link_rep::interrupt () {
139 if (!alive) return;
140 #if defined(__MINGW__) || defined(__MINGW32__)
141 // Not implemented
142 #else
143 ::killpg(PipeLink.pid (), SIGINT);
144 #endif
147 void
148 qt_pipe_link_rep::stop () {
149 PipeLink.killProcess ();
150 alive= false;
153 /******************************************************************************
154 * Main builder function for qt_pipe_links
155 ******************************************************************************/
157 tm_link
158 make_pipe_link (string cmd) {
159 return tm_new<qt_pipe_link_rep> (cmd);
162 /******************************************************************************
163 * Emergency exit for all pipes
164 ******************************************************************************/
166 void
167 close_all_pipes () {
168 iterator<pointer> it= iterate (pipe_link_set);
169 while (it->busy()) {
170 qt_pipe_link_rep* con= (qt_pipe_link_rep*) it->next();
171 if (con->alive) con->stop ();
175 void
176 process_all_pipes () {
177 iterator<pointer> it= iterate (pipe_link_set);
178 while (it->busy()) {
179 qt_pipe_link_rep* con= (qt_pipe_link_rep*) it->next();
180 if (con->alive) con->apply_command ();
184 #endif // defined (QTTEXMACS) && (defined (__MINGW__) || defined (__MINGW32__))