diff options
Diffstat (limited to 'Build/source/texk/web2c/window/mftalk.c')
-rw-r--r-- | Build/source/texk/web2c/window/mftalk.c | 275 |
1 files changed, 275 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..880b0b8c34f --- /dev/null +++ b/Build/source/texk/web2c/window/mftalk.c @@ -0,0 +1,275 @@ +/* mftalk.c -- generic Metafont window server. + Copyright (C) 1994 Ralph Schleicher + Slightly modified for Web2c 7.0 by Karl Berry. + 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 (int sig); +static string app_type (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. */ + + +#include <mfdisplay.h> + +int +mf_mftalk_initscreen (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 (void) +{ + buf[0] = MF_FLUSH; + write (win, buf, sizeof (int)); +} + + +void +mf_mftalk_blankrectangle (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 (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 (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 */ |