summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/window/mftalk.c
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
committerKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
commit487ca4806cc046076293cf6cc5fbba0db282bac7 (patch)
tree847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/web2c/window/mftalk.c
parenta3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff)
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/window/mftalk.c')
-rw-r--r--Build/source/texk/web2c/window/mftalk.c273
1 files changed, 273 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/window/mftalk.c b/Build/source/texk/web2c/window/mftalk.c
new file mode 100644
index 00000000000..25554e05831
--- /dev/null
+++ b/Build/source/texk/web2c/window/mftalk.c
@@ -0,0 +1,273 @@
+/* mftalk.c -- generic Metafont window server.
+ Copyright (C) 1994 Ralph Schleicher
+ Slightly modified for Web2c 7.0 by kb@mail.tug.org.
+ Further modifications for Web2C 7.2 by Mathias.Herberts@irisa.fr */
+
+/* This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Please remember the following for porting to UNIX:
+
+ pid = fork ();
+ if (pid == 0)
+ execve (...); pid = spawnve (mode, ...);
+ else if (pid == -1) if (pid == -1)
+ error (); error ();
+ else else
+ success (); success ();
+
+ Spawnve(2) has many different modes and a `session' is indicated by
+ running on an extra terminal. */
+
+
+#define EXTERN extern
+#include "../mfd.h"
+
+#ifdef MFTALKWIN
+
+#undef input
+#undef output
+#undef read
+#undef write
+#ifdef OS2
+#include <sys/param.h>
+#include <process.h>
+extern int close (int);
+extern int pipe (int *);
+extern int read (int, void *, size_t);
+extern int setmode (int, int);
+extern int write (int, const void *, size_t);
+#endif
+#include <fcntl.h>
+#include <signal.h>
+#include <kpathsea/variable.h>
+#include "mftalk.h"
+
+/* We use SIGCHLD, but fall back on SIGCLD if that's all we have. */
+#if !defined (SIGCHLD) && defined (SIGCLD)
+#define SIGCHLD SIGCLD
+#endif
+
+#define fatal(func, cond) do { if (cond) FATAL_PERROR ("perror"); } while (0)
+
+static RETSIGTYPE child_died P1H(int sig);
+static string app_type P2H(char *prog, int *app);
+
+static int pid = -1; /* Process ID of our child. */
+static int win = -1; /* Write handle to the `window'. */
+static int buf[8]; /* Temporary buffer. */
+static RETSIGTYPE (*old) (); /* Old signal handler. */
+
+
+boolean
+mf_mftalk_initscreen P1H(void)
+{
+ int app; /* Client application type. */
+ char *prog, *name; /* Client program name. */
+ /* Size of METAFONT window. */
+ char height[MAX_INT_LENGTH], width[MAX_INT_LENGTH];
+ /* Inherited pipe handles. */
+ char input[MAX_INT_LENGTH], output[MAX_INT_LENGTH];
+ char parent[MAX_INT_LENGTH]; /* My own process ID. */
+ int sc_pipe[2]; /* Server->Client pipe. */
+ int cs_pipe[2]; /* Client->Server pipe. */
+ int res, ack; /* Wait until child is ready. */
+
+ prog = kpse_var_value ("MFTALK");
+ if (prog == NULL)
+ prog = "mftalk.exe";
+
+ name = app_type (prog, &app);
+ if (!name)
+ return 0;
+
+ if (pipe (sc_pipe) == -1)
+ return 0;
+ if (pipe (cs_pipe) == -1)
+ {
+ close (sc_pipe[0]);
+ close (sc_pipe[1]);
+ return 0;
+ }
+#ifdef OS2
+ fatal (setmode, setmode (sc_pipe[0], O_BINARY) == -1);
+ fatal (setmode, setmode (sc_pipe[1], O_BINARY) == -1);
+ fatal (setmode, setmode (cs_pipe[0], O_BINARY) == -1);
+ fatal (setmode, setmode (cs_pipe[1], O_BINARY) == -1);
+#endif
+
+ old = signal (SIGCHLD, child_died);
+ fatal (old, old == SIG_ERR);
+
+ sprintf (height, "-h%d", screendepth);
+ sprintf (width, "-w%d", screenwidth);
+ sprintf (input, "-i%d", sc_pipe[0]);
+ sprintf (output, "-o%d", cs_pipe[1]);
+ sprintf (parent, "-p%d", getpid ());
+
+#ifdef OS2
+ pid = spawnl (app, name, prog, height, width, input, output, parent, NULL);
+#else
+ pid = fork ();
+ if (pid == 0)
+ {
+ fatal (close, close (0) == -1);
+ fatal (dup, dup (sc_pipe[0]) != 0);
+ fatal (close, close (sc_pipe[0]) == -1);
+ fatal (close, close (sc_pipe[1]) == -1);
+ fatal (close, close (1) == -1);
+ fatal (dup, dup (cs_pipe[1]) != 1);
+ fatal (close, close (cs_pipe[0]) == -1);
+ fatal (close, close (cs_pipe[1]) == -1);
+
+ /* We still pass the file handles as parameters for
+ * backward compatibility. instead of sc_pipe[0] and
+ * cs_pipe[1] we just pass 0 (stdin) and 1 (stdout).
+ */
+
+ sprintf (input, "-i0");
+ sprintf (output, "-o1");
+
+ execl (name, prog, height, width, input, output, parent, NULL);
+ }
+#endif /* not OS2 */
+ switch (pid)
+ {
+ case -1:
+ failure:
+ fatal (close, close (sc_pipe[0]) == -1);
+ fatal (close, close (sc_pipe[1]) == -1);
+ fatal (close, close (cs_pipe[0]) == -1);
+ fatal (close, close (cs_pipe[1]) == -1);
+ fatal (signal, signal (SIGCHLD, old) == SIG_ERR);
+ break;
+ default:
+ res = read (cs_pipe[0], &ack, sizeof (int));
+ if (res != sizeof (int) || ack != MF_ACK)
+ goto failure;
+ fatal (close, close (cs_pipe[0]) == -1);
+ win = sc_pipe[1];
+ break;
+ }
+
+ return (win == -1) ? 0 : 1;
+}
+
+
+void
+mf_mftalk_updatescreen P1H(void)
+{
+ buf[0] = MF_FLUSH;
+ write (win, buf, sizeof (int));
+}
+
+
+void
+mf_mftalk_blankrectangle P4C(screencol, left,
+ screencol, right,
+ screenrow, top,
+ screenrow, bottom)
+{
+ buf[0] = MF_RECT;
+ buf[1] = MF_WHITE;
+ buf[2] = left;
+ buf[3] = bottom;
+ buf[4] = right;
+ buf[5] = top;
+
+ write (win, buf, 6 * sizeof (int));
+}
+
+
+void
+mf_mftalk_paintrow P4C(screenrow, row,
+ pixelcolor, init_color,
+ transspec, transition_vector,
+ screencol, vector_size)
+{
+ buf[0] = MF_LINE;
+ buf[1] = init_color == 0 ? MF_WHITE : MF_BLACK;
+ buf[2] = *transition_vector++;
+ buf[3] = row;
+ buf[4] = --vector_size;
+
+ write (win, buf, 5 * sizeof (int));
+ write (win, transition_vector, vector_size * sizeof (int));
+}
+
+
+static string
+app_type P2C(string, prog, int *, app)
+{
+#ifdef OS2
+ int res, app;
+
+ res = DosSearchPath (0x02 | 0x01, "PATH", prog, buf, len);
+ if (res != 0)
+ return -1;
+
+ res = DosQueryAppType (buf, &app);
+ if (res != 0)
+ return -1;
+
+ switch (app & 0x07) /* Quick guess. */
+ {
+ case 0x00: return (P_SESSION | P_DEFAULT);
+ case 0x01: return (P_SESSION | P_FULLSCREEN);
+ case 0x02: return (P_SESSION | P_WINDOWED);
+ case 0x03: return (P_PM);
+ }
+#endif /* OS2 */
+
+ *app = 0; /* Irrelevant. */
+ return prog;
+}
+
+
+static RETSIGTYPE
+child_died (int sig)
+{
+#ifdef OS2
+ fatal (signal, signal (sig, SIG_ACK) == SIG_ERR);
+#endif
+ fatal (signal, signal (sig, SIG_IGN) == SIG_ERR);
+
+ if (pid == -1 || kill (-pid, 0) == 0) /* This was not our child. */
+ {
+ if (old != SIG_IGN)
+ {
+ fatal (signal, signal (sig, old) == SIG_ERR);
+ fatal (raise, raise (sig) == -1);
+ }
+ fatal (signal, signal (sig, child_died) == SIG_ERR);
+ }
+ else
+ {
+ close (win); /* This may fail. */
+ win = -1;
+
+ pid = -1;
+
+ screenstarted = false; /* METAFONT variables. */
+ screenOK = false;
+
+ fatal (signal, signal (sig, old) == SIG_ERR);
+ }
+}
+
+#else /* !MFTALKWIN */
+
+int mftalk_dummy;
+
+#endif /* !MFTALKWIN */