Initial release of Maemo 5 port of gnuplot
[gnuplot] / src / gpexecute.c
1 #ifndef lint
2 static char *RCSid() { return RCSid("$Id: gpexecute.c,v 1.14.2.1 2009/02/19 21:17:54 sfeam 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
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
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 #ifdef GNUPMDRV
139     /* write the command to clipboard */
140     if (bSend2gp == TRUE)
141         TextToClipboard(input_from_PM_Terminal);
142 #endif
143     gp_post_shared_mem();
144 }
145
146 #endif /* OS2_IPC */
147
148 #if defined(PIPE_IPC) /* || defined(WIN_IPC) */
149
150 int buffered_output_pending = 0;
151
152 static gpe_fifo_t *
153 gpe_init()
154 {
155     gpe_fifo_t *base = malloc(sizeof(gpe_fifo_t));
156     /* fprintf(stderr, "(gpe_init) \n"); */
157     assert(base);
158     base->next = (gpe_fifo_t *) 0;
159     base->prev = (gpe_fifo_t *) 0;
160     return base;
161 }
162
163 static void
164 gpe_push(gpe_fifo_t ** base, struct gp_event_t *ge)
165 {
166     buffered_output_pending++;
167     if ((*base)->prev) {
168         gpe_fifo_t *new = malloc(sizeof(gpe_fifo_t));
169         /* fprintf(stderr, "(gpe_push) \n"); */
170         assert(new);
171         (*base)->prev->next = new;
172         new->prev = (*base)->prev;
173         (*base)->prev = new;
174         new->next = (gpe_fifo_t *) 0;
175     } else {
176         /* first element, this is the case, if the pipe isn't clogged */
177         (*base)->next = (gpe_fifo_t *) 0;       /* tail */
178         (*base)->prev = (*base);        /* points to itself */
179     }
180     (*base)->prev->ge = *ge;
181 }
182
183 static struct gp_event_t *
184 gpe_front(gpe_fifo_t ** base)
185 {
186     return &((*base)->ge);
187 }
188
189 static int
190 gpe_pop(gpe_fifo_t ** base)
191 {
192     buffered_output_pending--;
193     if ((*base)->prev == (*base)) {
194         (*base)->prev = (gpe_fifo_t *) 0;
195         return 0;
196     } else {
197         gpe_fifo_t *save = *base;
198         /* fprintf(stderr, "(gpe_pop) \n"); */
199         (*base)->next->prev = (*base)->prev;
200         (*base) = (*base)->next;
201         free(save);
202         return 1;
203     }
204 }
205 #endif /* PIPE_IPC || WIN_IPC */
206
207 #ifdef PIPE_IPC
208 RETSIGTYPE
209 pipe_died_handler(int signum)
210 {
211     (void) signum;              /* avoid -Wunused warning. */
212     /* fprintf(stderr, "\n*******(pipe_died_handler)*******\n"); */
213     close(1);
214     pipe_died = 1;
215 }
216 #endif /* PIPE_IPC */
217
218 void
219 gp_exec_event(char type, int mx, int my, int par1, int par2, int winid)
220 {
221     struct gp_event_t ge;
222 #if defined(PIPE_IPC) /* || defined(WIN_IPC) */
223     static struct gpe_fifo_t *base = (gpe_fifo_t *) 0;
224 #endif
225
226     ge.type = type;
227     ge.mx = mx;
228     ge.my = my;
229     ge.par1 = par1;
230     ge.par2 = par2;
231     ge.winid = winid;
232 #ifdef PIPE_IPC
233     if (pipe_died)
234         return;
235 #endif
236     /* HBB 20010218: commented this out for WIN_IPC. We don't actually use the stack,
237      * there */
238 #if defined(PIPE_IPC) /* || defined(WIN_IPC) */
239     if (!base) {
240         base = gpe_init();
241     }
242     if (GE_pending != type) {
243         gpe_push(&base, &ge);
244     } else if (!buffered_output_pending) {
245         return;
246     }
247 #endif
248 #ifdef WIN_IPC
249     /* FIXME HBB 20010216: this breaks the wgnuplot.exe+wgnuplot.dll type of
250      * compilation (for Win16). do_event is in the main program(mouse.c), but
251      * gpexecute is in the DLL --> can't reach it, from here. */
252     do_event(&ge);
253     return;
254 #endif
255 #ifdef PIPE_IPC
256     do {
257         int status = write(1, gpe_front(&base), sizeof(ge));
258         if (-1 == status) {
259             switch (errno) {
260             case EAGAIN:
261                 /* do nothing */
262                 break;
263             default:
264                 break;
265             }
266             break;
267         }
268     } while (gpe_pop(&base));
269 #endif /* PIPE_IPC */
270
271 #ifdef OS2_IPC                  /* OS/2 communication via shared memory; coded according to gp_execute() */
272     if (input_from_PM_Terminal == NULL)
273         return;
274     ((char *) input_from_PM_Terminal)[0] = '%'; /* flag that passing gp_event_t */
275     memcpy(((char *) input_from_PM_Terminal) + 1, &ge, sizeof(ge));     /* copy the command to shared memory */
276     if (pausing) {              /* no communication during pause */
277         /* DosBeep(440,111); */
278         ((char *) input_from_PM_Terminal)[0] = 0;
279         return;
280     }
281     gp_post_shared_mem();
282 #endif
283 }