Initial release of Maemo 5 port of gnuplot
[gnuplot] / src / gpexecute.c
diff --git a/src/gpexecute.c b/src/gpexecute.c
new file mode 100644 (file)
index 0000000..6866c07
--- /dev/null
@@ -0,0 +1,283 @@
+#ifndef lint
+static char *RCSid() { return RCSid("$Id: gpexecute.c,v 1.14.2.1 2009/02/19 21:17:54 sfeam Exp $"); }
+#endif
+
+/* GNUPLOT - gpexecute.c */
+
+/*[
+ * Permission to use, copy, and distribute this software and its
+ * documentation for any purpose with or without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.
+ *
+ * Permission to modify the software is granted, but not the right to
+ * distribute the complete modified source code.  Modifications are to
+ * be distributed as patches to the released version.  Permission to
+ * distribute binaries produced by compiling modified sources is granted,
+ * provided you
+ *   1. distribute the corresponding source modifications from the
+ *    released version in the form of a patch file along with the binaries,
+ *   2. add special version identification to distinguish your version
+ *    in addition to the base release version number,
+ *   3. provide your name and address as the primary contact for the
+ *    support of your modified version, and
+ *   4. retain our contact information in regard to use of the base
+ *    software.
+ * Permission to distribute the released version of the source code along
+ * with corresponding source modifications in the form of a patch file is
+ * granted with same provisions 2 through 4 for binary distributions.
+ *
+ * This software is provided "as is" without express or implied warranty
+ * to the extent permitted by applicable law.
+]*/
+
+/*
+ * AUTHORS
+ *
+ *   Original Software (October 1999 - January 2000):
+ *     Pieter-Tjerk de Boer <ptdeboer@cs.utwente.nl>
+ *     Petr Mikulik <mikulik@physics.muni.cz>
+ *     Johannes Zellner <johannes@zellner.org>
+ */
+
+#include "gpexecute.h"
+
+#include "stdfn.h"
+
+#ifdef OS2_IPC
+# include <stdio.h>
+#endif
+
+#ifdef PIPE_IPC
+# include <unistd.h>   /* open(), write() */
+# include <stdlib.h>
+# include <assert.h>
+# include <errno.h>
+int pipe_died = 0;
+#endif /* PIPE_IPC */
+
+#ifdef WIN_IPC
+# include <stdlib.h>
+# include <assert.h>
+# include "mouse.h"    /* do_event() */
+#endif
+
+#if defined(PIPE_IPC) /* || defined(WIN_IPC) */
+static gpe_fifo_t *gpe_init __PROTO((void));
+static void gpe_push __PROTO((gpe_fifo_t ** base, struct gp_event_t * ge));
+static struct gp_event_t *gpe_front __PROTO((gpe_fifo_t ** base));
+static int gpe_pop __PROTO((gpe_fifo_t ** base));
+#endif /* PIPE_IPC || WIN_IPC */
+
+/*
+ * gp_execute functions
+ */
+
+#ifdef OS2_IPC
+char mouseShareMemName[40];
+PVOID input_from_PM_Terminal;
+  /* pointer to shared memory for storing the command to be executed */
+HEV semInputReady = 0;
+  /* handle to event semaphore (post an event to gnuplot that the shared
+     memory contains a command to be executed) */
+int pausing = 0;
+  /* avoid passing data back to gnuplot in `pause' mode */
+  /* gplt_x11.c */
+ULONG ppidGnu = 0;
+
+
+/*
+ * Let the command in the shared memory be executed.
+ */
+void
+gp_post_shared_mem()
+{
+    APIRET rc;
+    if (semInputReady == 0) {  /* but it must be open for the first time */
+       char semInputReadyName[40];
+       sprintf(semInputReadyName, "\\SEM32\\GP%i_Input_Ready", (int) ppidGnu);
+       DosOpenEventSem(semInputReadyName, &semInputReady);
+    }
+    rc = DosPostEventSem(semInputReady);
+    DosSleep(10);
+    /* dirty trick: wait a little bit; otherwise problems to
+     * distinguish mouse button down and up, for instance
+     * (info sent to shared memory was too fast; maybe a blocking
+     * semaphore would help, but no fun to implement it...)
+     &*/
+}
+
+/* Copy the command (given by the input string) to the shared memory
+ * and let gnuplot execute it.
+ * If this routine is called during a 'pause', then the command is
+ * ignored (shared memory is cleared). Needed for actions launched by a
+ * hotkey.
+ * Firstly, the command is copied from shared memory to clipboard
+ * if this option is set on.
+ * Secondly, gnuplot is informed that shared memory contains a command
+ * by posting semInputReady event semaphore.
+ *
+ * OS/2 specific: if (!s), then the command has been already sprintf'ed to
+ * the shared memory.
+ */
+void
+gp_execute(char *s)
+{
+    if (input_from_PM_Terminal == NULL)
+       return;
+    if (s)                     /* copy the command to shared memory */
+       strcpy(input_from_PM_Terminal, s);
+    if (((char *) input_from_PM_Terminal)[0] == 0)
+       return;
+    if (pausing) {             /* no communication during pause */
+       /* DosBeep(440,111); */
+       ((char *) input_from_PM_Terminal)[0] = 0;
+       return;
+    }
+#ifdef GNUPMDRV
+    /* write the command to clipboard */
+    if (bSend2gp == TRUE)
+       TextToClipboard(input_from_PM_Terminal);
+#endif
+    gp_post_shared_mem();
+}
+
+#endif /* OS2_IPC */
+
+#if defined(PIPE_IPC) /* || defined(WIN_IPC) */
+
+int buffered_output_pending = 0;
+
+static gpe_fifo_t *
+gpe_init()
+{
+    gpe_fifo_t *base = malloc(sizeof(gpe_fifo_t));
+    /* fprintf(stderr, "(gpe_init) \n"); */
+    assert(base);
+    base->next = (gpe_fifo_t *) 0;
+    base->prev = (gpe_fifo_t *) 0;
+    return base;
+}
+
+static void
+gpe_push(gpe_fifo_t ** base, struct gp_event_t *ge)
+{
+    buffered_output_pending++;
+    if ((*base)->prev) {
+       gpe_fifo_t *new = malloc(sizeof(gpe_fifo_t));
+       /* fprintf(stderr, "(gpe_push) \n"); */
+       assert(new);
+       (*base)->prev->next = new;
+       new->prev = (*base)->prev;
+       (*base)->prev = new;
+       new->next = (gpe_fifo_t *) 0;
+    } else {
+       /* first element, this is the case, if the pipe isn't clogged */
+       (*base)->next = (gpe_fifo_t *) 0;       /* tail */
+       (*base)->prev = (*base);        /* points to itself */
+    }
+    (*base)->prev->ge = *ge;
+}
+
+static struct gp_event_t *
+gpe_front(gpe_fifo_t ** base)
+{
+    return &((*base)->ge);
+}
+
+static int
+gpe_pop(gpe_fifo_t ** base)
+{
+    buffered_output_pending--;
+    if ((*base)->prev == (*base)) {
+       (*base)->prev = (gpe_fifo_t *) 0;
+       return 0;
+    } else {
+       gpe_fifo_t *save = *base;
+       /* fprintf(stderr, "(gpe_pop) \n"); */
+       (*base)->next->prev = (*base)->prev;
+       (*base) = (*base)->next;
+       free(save);
+       return 1;
+    }
+}
+#endif /* PIPE_IPC || WIN_IPC */
+
+#ifdef PIPE_IPC
+RETSIGTYPE
+pipe_died_handler(int signum)
+{
+    (void) signum;             /* avoid -Wunused warning. */
+    /* fprintf(stderr, "\n*******(pipe_died_handler)*******\n"); */
+    close(1);
+    pipe_died = 1;
+}
+#endif /* PIPE_IPC */
+
+void
+gp_exec_event(char type, int mx, int my, int par1, int par2, int winid)
+{
+    struct gp_event_t ge;
+#if defined(PIPE_IPC) /* || defined(WIN_IPC) */
+    static struct gpe_fifo_t *base = (gpe_fifo_t *) 0;
+#endif
+
+    ge.type = type;
+    ge.mx = mx;
+    ge.my = my;
+    ge.par1 = par1;
+    ge.par2 = par2;
+    ge.winid = winid;
+#ifdef PIPE_IPC
+    if (pipe_died)
+       return;
+#endif
+    /* HBB 20010218: commented this out for WIN_IPC. We don't actually use the stack,
+     * there */
+#if defined(PIPE_IPC) /* || defined(WIN_IPC) */
+    if (!base) {
+       base = gpe_init();
+    }
+    if (GE_pending != type) {
+       gpe_push(&base, &ge);
+    } else if (!buffered_output_pending) {
+       return;
+    }
+#endif
+#ifdef WIN_IPC
+    /* FIXME HBB 20010216: this breaks the wgnuplot.exe+wgnuplot.dll type of
+     * compilation (for Win16). do_event is in the main program(mouse.c), but
+     * gpexecute is in the DLL --> can't reach it, from here. */
+    do_event(&ge);
+    return;
+#endif
+#ifdef PIPE_IPC
+    do {
+       int status = write(1, gpe_front(&base), sizeof(ge));
+       if (-1 == status) {
+           switch (errno) {
+           case EAGAIN:
+               /* do nothing */
+               break;
+           default:
+               break;
+           }
+           break;
+       }
+    } while (gpe_pop(&base));
+#endif /* PIPE_IPC */
+
+#ifdef OS2_IPC                 /* OS/2 communication via shared memory; coded according to gp_execute() */
+    if (input_from_PM_Terminal == NULL)
+       return;
+    ((char *) input_from_PM_Terminal)[0] = '%';        /* flag that passing gp_event_t */
+    memcpy(((char *) input_from_PM_Terminal) + 1, &ge, sizeof(ge));    /* copy the command to shared memory */
+    if (pausing) {             /* no communication during pause */
+       /* DosBeep(440,111); */
+       ((char *) input_from_PM_Terminal)[0] = 0;
+       return;
+    }
+    gp_post_shared_mem();
+#endif
+}