1 #ifndef lint
RCSid()2 static char *RCSid() { return RCSid("$Id: gpexecute.c,v 1.17 2010/08/31 12:57:32 mikulik Exp $"); }
3 #endif
4
5 /* GNUPLOT - gpexecute.c */
6
7 /*[
8 * Permission to use, copy, and distribute this software and its
9 * documentation for any purpose with or without fee is hereby granted,
10 * provided that the above copyright notice appear in all copies and
11 * that both that copyright notice and this permission notice appear
12 * in supporting documentation.
13 *
14 * Permission to modify the software is granted, but not the right to
15 * distribute the complete modified source code. Modifications are to
16 * be distributed as patches to the released version. Permission to
17 * distribute binaries produced by compiling modified sources is granted,
18 * provided you
19 * 1. distribute the corresponding source modifications from the
20 * released version in the form of a patch file along with the binaries,
21 * 2. add special version identification to distinguish your version
22 * in addition to the base release version number,
23 * 3. provide your name and address as the primary contact for the
24 * support of your modified version, and
25 * 4. retain our contact information in regard to use of the base
26 * software.
27 * Permission to distribute the released version of the source code along
28 * with corresponding source modifications in the form of a patch file is
29 * granted with same provisions 2 through 4 for binary distributions.
30 *
31 * This software is provided "as is" without express or implied warranty
32 * to the extent permitted by applicable law.
33 ]*/
34
35 /*
36 * AUTHORS
37 *
38 * Original Software (October 1999 - January 2000):
39 * Pieter-Tjerk de Boer <ptdeboer@cs.utwente.nl>
40 * Petr Mikulik <mikulik@physics.muni.cz>
41 * Johannes Zellner <johannes@zellner.org>
42 */
43
44 #include "gpexecute.h"
45
46 #include "stdfn.h"
47
48 #ifdef OS2_IPC
49 # include <stdio.h>
50 #endif
51
52 #ifdef PIPE_IPC
53 # include <unistd.h> /* open(), write() */
54 # include <stdlib.h>
55 # include <assert.h>
56 # include <errno.h>
57 int pipe_died = 0;
58 #endif /* PIPE_IPC */
59
60 #ifdef WIN_IPC
61 # include <stdlib.h>
62 # include <assert.h>
63 # include "mouse.h" /* do_event() */
64 #endif
65
66 #if defined(PIPE_IPC) /* || defined(WIN_IPC) */
67 static gpe_fifo_t *gpe_init __PROTO((void));
68 static void gpe_push __PROTO((gpe_fifo_t ** base, struct gp_event_t * ge));
69 static struct gp_event_t *gpe_front __PROTO((gpe_fifo_t ** base));
70 static int gpe_pop __PROTO((gpe_fifo_t ** base));
71 #endif /* PIPE_IPC || WIN_IPC */
72
73 /*
74 * gp_execute functions
75 */
76
77 #ifdef OS2_IPC
78 char mouseShareMemName[40];
79 PVOID input_from_PM_Terminal;
80 /* pointer to shared memory for storing the command to be executed */
81 HEV semInputReady = 0;
82 /* handle to event semaphore (post an event to gnuplot that the shared
83 memory contains a command to be executed) */
84 int pausing = 0;
85 /* avoid passing data back to gnuplot in `pause' mode */
86 /* gplt_x11.c */
87 ULONG ppidGnu = 0;
88
89
90 /*
91 * Let the command in the shared memory be executed.
92 */
93 void
gp_post_shared_mem()94 gp_post_shared_mem()
95 {
96 APIRET rc;
97 if (semInputReady == 0) { /* but it must be open for the first time */
98 char semInputReadyName[40];
99 sprintf(semInputReadyName, "\\SEM32\\GP%i_Input_Ready", (int) ppidGnu);
100 DosOpenEventSem(semInputReadyName, &semInputReady);
101 }
102 rc = DosPostEventSem(semInputReady);
103 DosSleep(10);
104 /* dirty trick: wait a little bit; otherwise problems to
105 * distinguish mouse button down and up, for instance
106 * (info sent to shared memory was too fast; maybe a blocking
107 * semaphore would help, but no fun to implement it...)
108 &*/
109 }
110
111 /* Copy the command (given by the input string) to the shared memory
112 * and let gnuplot execute it.
113 * If this routine is called during a 'pause', then the command is
114 * ignored (shared memory is cleared). Needed for actions launched by a
115 * hotkey.
116 * Firstly, the command is copied from shared memory to clipboard
117 * if this option is set on.
118 * Secondly, gnuplot is informed that shared memory contains a command
119 * by posting semInputReady event semaphore.
120 *
121 * OS/2 specific: if (!s), then the command has been already sprintf'ed to
122 * the shared memory.
123 */
124 void
gp_execute(char * s)125 gp_execute(char *s)
126 {
127 if (input_from_PM_Terminal == NULL)
128 return;
129 if (s) /* copy the command to shared memory */
130 strcpy(input_from_PM_Terminal, s);
131 if (((char *) input_from_PM_Terminal)[0] == 0)
132 return;
133 if (pausing) { /* no communication during pause */
134 /* DosBeep(440,111); */
135 ((char *) input_from_PM_Terminal)[0] = 0;
136 return;
137 }
138 gp_post_shared_mem();
139 }
140
141 #endif /* OS2_IPC */
142
143 #if defined(PIPE_IPC) /* || defined(WIN_IPC) */
144
145 int buffered_output_pending = 0;
146
147 static gpe_fifo_t *
gpe_init()148 gpe_init()
149 {
150 gpe_fifo_t *base = malloc(sizeof(gpe_fifo_t));
151 /* fprintf(stderr, "(gpe_init) \n"); */
152 assert(base);
153 base->next = (gpe_fifo_t *) 0;
154 base->prev = (gpe_fifo_t *) 0;
155 return base;
156 }
157
158 static void
gpe_push(gpe_fifo_t ** base,struct gp_event_t * ge)159 gpe_push(gpe_fifo_t ** base, struct gp_event_t *ge)
160 {
161 buffered_output_pending++;
162 if ((*base)->prev) {
163 gpe_fifo_t *new = malloc(sizeof(gpe_fifo_t));
164 /* fprintf(stderr, "(gpe_push) \n"); */
165 assert(new);
166 (*base)->prev->next = new;
167 new->prev = (*base)->prev;
168 (*base)->prev = new;
169 new->next = (gpe_fifo_t *) 0;
170 } else {
171 /* first element, this is the case, if the pipe isn't clogged */
172 (*base)->next = (gpe_fifo_t *) 0; /* tail */
173 (*base)->prev = (*base); /* points to itself */
174 }
175 (*base)->prev->ge = *ge;
176 }
177
178 static struct gp_event_t *
gpe_front(gpe_fifo_t ** base)179 gpe_front(gpe_fifo_t ** base)
180 {
181 return &((*base)->ge);
182 }
183
184 static int
gpe_pop(gpe_fifo_t ** base)185 gpe_pop(gpe_fifo_t ** base)
186 {
187 buffered_output_pending--;
188 if ((*base)->prev == (*base)) {
189 (*base)->prev = (gpe_fifo_t *) 0;
190 return 0;
191 } else {
192 gpe_fifo_t *save = *base;
193 /* fprintf(stderr, "(gpe_pop) \n"); */
194 (*base)->next->prev = (*base)->prev;
195 (*base) = (*base)->next;
196 free(save);
197 return 1;
198 }
199 }
200 #endif /* PIPE_IPC || WIN_IPC */
201
202 #ifdef PIPE_IPC
203 RETSIGTYPE
pipe_died_handler(int signum)204 pipe_died_handler(int signum)
205 {
206 (void) signum; /* avoid -Wunused warning. */
207 /* fprintf(stderr, "\n*******(pipe_died_handler)*******\n"); */
208 close(1);
209 pipe_died = 1;
210 }
211 #endif /* PIPE_IPC */
212
213 void
gp_exec_event(char type,int mx,int my,int par1,int par2,int winid)214 gp_exec_event(char type, int mx, int my, int par1, int par2, int winid)
215 {
216 struct gp_event_t ge;
217 #if defined(PIPE_IPC) /* || defined(WIN_IPC) */
218 static struct gpe_fifo_t *base = (gpe_fifo_t *) 0;
219 #endif
220
221 ge.type = type;
222 ge.mx = mx;
223 ge.my = my;
224 ge.par1 = par1;
225 ge.par2 = par2;
226 ge.winid = winid;
227 #ifdef PIPE_IPC
228 if (pipe_died)
229 return;
230 #endif
231 /* HBB 20010218: commented this out for WIN_IPC. We don't actually use the stack,
232 * there */
233 #if defined(PIPE_IPC) /* || defined(WIN_IPC) */
234 if (!base) {
235 base = gpe_init();
236 }
237 if (GE_pending != type) {
238 gpe_push(&base, &ge);
239 } else if (!buffered_output_pending) {
240 return;
241 }
242 #endif
243 #ifdef WIN_IPC
244 do_event(&ge);
245 return;
246 #endif
247 #ifdef PIPE_IPC
248 do {
249 int status = write(1, gpe_front(&base), sizeof(ge));
250 if (-1 == status) {
251 switch (errno) {
252 case EAGAIN:
253 /* do nothing */
254 FPRINTF((stderr, "(gp_exec_event) EAGAIN\n"));
255 break;
256 default:
257 FPRINTF((stderr, "(gp_exec_event) errno = %d\n", errno));
258 break;
259 }
260 break;
261 }
262 } while (gpe_pop(&base));
263 #endif /* PIPE_IPC */
264
265 #ifdef OS2_IPC /* OS/2 communication via shared memory; coded according to gp_execute() */
266 if (input_from_PM_Terminal == NULL)
267 return;
268 ((char *) input_from_PM_Terminal)[0] = '%'; /* flag that passing gp_event_t */
269 memcpy(((char *) input_from_PM_Terminal) + 1, &ge, sizeof(ge)); /* copy the command to shared memory */
270 if (pausing) { /* no communication during pause */
271 /* DosBeep(440,111); */
272 ((char *) input_from_PM_Terminal)[0] = 0;
273 return;
274 }
275 gp_post_shared_mem();
276 #endif
277 }
278