home *** CD-ROM | disk | FTP | other *** search
- /*
- * Ghostview.c -- Ghostview widget.
- * Copyright (C) 1992 Timothy O. Theisen
- *
- * This program 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 program 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 program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Tim Theisen Systems Programmer
- * Internet: tim@cs.wisc.edu Department of Computer Sciences
- * UUCP: uwvax!tim University of Wisconsin-Madison
- * Phone: (608)262-0438 1210 West Dayton Street
- * FAX: (608)262-9777 Madison, WI 53706
- */
-
- #include <X11/IntrinsicP.h>
- #include <X11/StringDefs.h>
- #include <X11/Xatom.h>
- #include <X11/Xproto.h>
- #include <X11/Xos.h>
- #include "GhostviewP.h"
- #include <ctype.h>
-
- #ifndef XlibSpecificationRelease
- typedef char *XPointer;
- #endif
-
- #include <signal.h>
- #ifdef SIGNALRETURNSINT
- #define SIGVAL int
- #else
- #define SIGVAL void
- #endif
-
- #ifdef NON_BLOCKING_IO
- #include <fcntl.h>
- /* if POSIX O_NONBLOCK is not available, use O_NDELAY */
- #if !defined(O_NONBLOCK) && defined(O_NDELAY)
- #define O_NONBLOCK O_NDELAY
- #endif
- #endif
-
- #include <errno.h>
- /* BSD 4.3 errno.h does not declare errno */
- extern int errno;
- /* Both error returns are checked for non-blocking I/O. */
- /* Manufacture the other error code if only one exists. */
- #if !defined(EWOULDBLOCK) && defined(EAGAIN)
- #define EWOULDBLOCK EAGAIN
- #endif
- #if !defined(EAGAIN) && defined(EWOULDBLOCK)
- #define EAGAIN EWOULDBLOCK
- #endif
-
- #ifndef VMS
- /* GV_BUFSIZ is set to the minimum POSIX PIPE_BUF to ensure that
- * nonblocking writes to ghostscript will work properly.
- */
- #define GV_BUFSIZ 512
- #else /* VMS */
- /*
- ** GV_BUFSIZ is the maximum length line we can handle, so we up it to 1024
- */
- #define GV_BUFSIZ 1024
- #endif /* VMS */
-
- static void ComputeXdpi();
- static void ComputeYdpi();
-
- static XtResource resources[] = {
- #define offset(field) XtOffsetOf(GhostviewRec, ghostview.field)
- { XtNarguments, XtCArguments, XtRString, sizeof(String),
- offset(arguments), XtRString, (XtPointer)NULL },
- { XtNbottomMargin, XtCMargin, XtRInt, sizeof(int),
- offset(bottom_margin), XtRImmediate, (XtPointer)0 },
- { XtNbusyCursor, XtCCursor, XtRCursor, sizeof(XtPointer),
- offset(busy_cursor), XtRString, "watch" },
- { XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer),
- offset(callback), XtRCallback, (XtPointer)NULL },
- { XtNcursor, XtCCursor, XtRCursor, sizeof(XtPointer),
- offset(cursor), XtRString, "crosshair" },
- { XtNfilename, XtCFilename, XtRString, sizeof(String),
- offset(filename), XtRString, (XtPointer)NULL },
- { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
- offset(foreground), XtRString, XtDefaultForeground},
- { XtNinterpreter, XtCInterpreter, XtRString, sizeof(String),
- offset(interpreter), XtRString, "gs" },
- { XtNleftMargin, XtCMargin, XtRInt, sizeof(int),
- offset(left_margin), XtRImmediate, (XtPointer)0 },
- { XtNllx, XtCBoundingBox, XtRInt, sizeof(int),
- offset(llx), XtRImmediate, (XtPointer)0 },
- { XtNlly, XtCBoundingBox, XtRInt, sizeof(int),
- offset(lly), XtRImmediate, (XtPointer)0 },
- { XtNmessageCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
- offset(message_callback), XtRCallback, (XtPointer)NULL },
- { XtNorientation, XtCOrientation, XtRPageOrientation,
- sizeof(XtPageOrientation), offset(orientation), XtRImmediate,
- (XtPointer)XtPageOrientationPortrait },
- { XtNoutputCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
- offset(output_callback), XtRCallback, (XtPointer)NULL },
- { XtNpalette, XtCPalette, XtRPalette, sizeof(XtPalette),
- offset(palette), XtRImmediate, (XtPointer)XtPaletteColor },
- { XtNquiet, XtCQuiet, XtRBoolean, sizeof(Boolean),
- offset(quiet), XtRImmediate, (XtPointer)True },
- { XtNrightMargin, XtCMargin, XtRInt, sizeof(int),
- offset(right_margin), XtRImmediate, (XtPointer)0 },
- { XtNsafer, XtCSafer, XtRBoolean, sizeof(Boolean),
- offset(safer), XtRImmediate, (XtPointer)True },
- { XtNtopMargin, XtCMargin, XtRInt, sizeof(int),
- offset(top_margin), XtRImmediate, (XtPointer)0 },
- { XtNuseBackingPixmap, XtCUseBackingPixmap, XtRBoolean, sizeof(Boolean),
- offset(use_bpixmap), XtRImmediate, (XtPointer)True },
- { XtNurx, XtCBoundingBox, XtRInt, sizeof(int),
- offset(urx), XtRImmediate, (XtPointer)612 },
- { XtNury, XtCBoundingBox, XtRInt, sizeof(int),
- offset(ury), XtRImmediate, (XtPointer)792 },
- { XtNxdpi, XtCResolution, XtRFloat, sizeof(float),
- offset(xdpi), XtRCallProc, (XtPointer)ComputeXdpi },
- { XtNydpi, XtCResolution, XtRFloat, sizeof(float),
- offset(ydpi), XtRCallProc, (XtPointer)ComputeYdpi },
- #undef offset
- };
-
- static void Message();
- static void Notify();
- static void Input();
- static void Output();
-
- static void ClassInitialize();
- static void ClassPartInitialize();
- static void Initialize();
- static void Realize();
- static void Destroy();
- static void Resize();
- static Boolean SetValues();
- static XtGeometryResult QueryGeometry();
-
- static void Layout();
- static Boolean ComputeSize();
- static void ChangeSize();
- static Boolean Setup();
- static void StartInterpreter();
- static void StopInterpreter();
- static void InterpreterFailed();
-
- static XtActionsRec actions[] =
- {
- {"message", Message},
- {"notify", Notify},
- };
-
- /* notify takes zero to four parameters. The first two give the width and
- * height of the zoom requested in the default user coordinate system.
- * If they are omitted, a default value of 72 is provided. If the second
- * parameter is omitted, the zoom area is assumed to be a square.
- * The next two parameters give the desired resolution of the zoom window.
- * If they are omitted, a default value of 300 is provided. If the four
- * parameter is omitted, the y resolution is assumed to be equal to the
- * x resolution.
- */
- static char translations[] =
- "<Message>: message() \n\
- <Btn1Down>: notify(72) \n\
- <Btn2Down>: notify(108) \n\
- <Btn3Down>: notify(144) \n\
- ";
-
- GhostviewClassRec ghostviewClassRec = {
- { /* core fields */
- /* superclass */ (WidgetClass) &coreClassRec,
- /* class_name */ "Ghostview",
- /* widget_size */ sizeof(GhostviewRec),
- /* class_initialize */ ClassInitialize,
- /* class_part_initialize */ ClassPartInitialize,
- /* class_inited */ FALSE,
- /* initialize */ Initialize,
- /* initialize_hook */ NULL,
- /* realize */ Realize,
- /* actions */ actions,
- /* num_actions */ XtNumber(actions),
- /* resources */ resources,
- /* num_resources */ XtNumber(resources),
- /* xrm_class */ NULLQUARK,
- /* compress_motion */ TRUE,
- /* compress_exposure */ TRUE,
- /* compress_enterleave */ TRUE,
- /* visible_interest */ FALSE,
- /* destroy */ Destroy,
- /* resize */ Resize,
- /* expose */ NULL,
- /* set_values */ SetValues,
- /* set_values_hook */ NULL,
- /* set_values_almost */ XtInheritSetValuesAlmost,
- /* get_values_hook */ NULL,
- /* accept_focus */ NULL,
- /* version */ XtVersion,
- /* callback_private */ NULL,
- /* tm_table */ translations,
- /* query_geometry */ QueryGeometry,
- /* display_accelerator */ XtInheritDisplayAccelerator,
- /* extension */ NULL
- },
- { /* ghostview fields */
- /* ghostview */ NULL,
- /* gv_colors */ NULL,
- /* next */ NULL,
- /* page */ NULL,
- /* done */ NULL
- }
- };
-
- WidgetClass ghostviewWidgetClass = (WidgetClass)&ghostviewClassRec;
-
- /* Procedures that compute the default xdpi and ydpi from display parameters */
-
- static void
- ComputeXdpi(w, offset, value)
- Widget w;
- int offset;
- XrmValue *value;
- {
- static float xdpi;
- xdpi = 25.4 * WidthOfScreen(XtScreen(w)) / WidthMMOfScreen(XtScreen(w));
- value->addr = (XtPointer) &xdpi;
- }
-
- static void
- ComputeYdpi(w, offset, value)
- Widget w;
- int offset;
- XrmValue *value;
- {
- static float ydpi;
- ydpi = 25.4 * HeightOfScreen(XtScreen(w)) / HeightMMOfScreen(XtScreen(w));
- value->addr = (XtPointer) &ydpi;
- }
-
- /* Message action routine.
- * Passes ghostscript message events back to application via
- * the message callback. It also marks the interpreter as
- * being not busy at the end of page, and stops the interpreter
- * when it send a "done" message.
- */
- static void
- Message(w, event, params, num_params)
- Widget w;
- XEvent *event;
- String *params; /* unused */
- Cardinal *num_params; /* unused */
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- GhostviewWidgetClass gvc = (GhostviewWidgetClass) XtClass(w);
-
- gvw->ghostview.mwin = event->xclient.data.l[0];
- if (event->xclient.message_type ==
- XmuInternAtom(XtDisplay(w), gvc->ghostview_class.page)) {
- gvw->ghostview.busy = False;
- XDefineCursor(XtDisplay(gvw), XtWindow(gvw), gvw->ghostview.cursor);
- XtCallCallbackList(w, gvw->ghostview.message_callback, "Page");
- } else if (event->xclient.message_type ==
- XmuInternAtom(XtDisplay(w), gvc->ghostview_class.done)) {
- StopInterpreter(w);
- XtCallCallbackList(w, gvw->ghostview.message_callback, "Done");
- }
- }
-
- /* Notify action routine.
- * Calculates where the user clicked in the default user coordinate system.
- * Call the callbacks with the point of click and size of zoom window
- * requested.
- */
- static void
- Notify(w, event, params, num_params)
- Widget w;
- XEvent *event;
- String *params;
- Cardinal *num_params;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- GhostviewReturnStruct ret_val;
-
- /* notify takes zero to four parameters. The first two give the width and
- * height of the zoom requested in the default user coordinate system.
- * If they are omitted, a default value of 72 is provided. If the second
- * parameter is omitted, the zoom area is assumed to be a square.
- * The next two parameters give the desired resolution of the zoom window.
- * If they are omitted, a default value of 300 is provided. If the four
- * parameter is omitted, the y resolution is assumed to be equal to the
- * x resolution.
- */
- switch (*num_params) {
- case 0:
- ret_val.width = ret_val.height = 72;
- ret_val.xdpi = ret_val.ydpi = 300;
- break;
- case 1:
- ret_val.width = ret_val.height = atoi(params[0]);
- ret_val.xdpi = ret_val.ydpi = 300;
- break;
- case 2:
- ret_val.width = atoi(params[0]);
- ret_val.height = atoi(params[1]);
- ret_val.xdpi = ret_val.ydpi = 300;
- break;
- case 3:
- ret_val.width = atoi(params[0]);
- ret_val.height = atoi(params[1]);
- ret_val.xdpi = ret_val.ydpi = atoi(params[2]);
- break;
- default:
- ret_val.width = atoi(params[0]);
- ret_val.height = atoi(params[1]);
- ret_val.xdpi = atoi(params[2]);
- ret_val.ydpi = atoi(params[3]);
- break;
- }
-
- switch (gvw->ghostview.orientation) {
- case XtPageOrientationPortrait:
- ret_val.psx = gvw->ghostview.llx +
- event->xbutton.x * 72.0 / gvw->ghostview.xdpi;
- ret_val.psy = gvw->ghostview.ury -
- event->xbutton.y * 72.0 / gvw->ghostview.ydpi;
- break;
- case XtPageOrientationLandscape:
- ret_val.psx = gvw->ghostview.llx +
- event->xbutton.y * 72.0 / gvw->ghostview.ydpi;
- ret_val.psy = gvw->ghostview.lly +
- event->xbutton.x * 72.0 / gvw->ghostview.xdpi;
- break;
- case XtPageOrientationUpsideDown:
- ret_val.psx = gvw->ghostview.urx -
- event->xbutton.x * 72.0 / gvw->ghostview.xdpi;
- ret_val.psy = gvw->ghostview.lly +
- event->xbutton.y * 72.0 / gvw->ghostview.ydpi;
- break;
- case XtPageOrientationSeascape:
- ret_val.psx = gvw->ghostview.urx -
- event->xbutton.y * 72.0 / gvw->ghostview.ydpi;
- ret_val.psy = gvw->ghostview.ury -
- event->xbutton.x * 72.0 / gvw->ghostview.xdpi;
- break;
- }
- XtCallCallbackList(w, gvw->ghostview.callback, (XtPointer) &ret_val);
- }
-
- #ifndef SEEK_SET
- #define SEEK_SET 0
- #endif
-
- static Boolean broken_pipe = False;
-
- static SIGVAL
- CatchPipe(i)
- int i;
- {
- broken_pipe = True;
- #ifdef SIGNALRETURNSINT
- return 0;
- #endif
- }
-
- #ifndef VMS
-
- /* Input - Feed data to ghostscript's stdin.
- * Write bytes to ghostscript using non-blocking I/O.
- * Also, pipe signals are caught during writing. The return
- * values are checked and the appropriate action is taken. I do
- * this at this low level, because it may not be appropriate for
- * SIGPIPE to be caught for the overall application.
- */
-
- static void
- Input(client_data, source, id)
- XtPointer client_data;
- int *source;
- XtInputId *id;
- {
- Widget w = (Widget) client_data;
- GhostviewWidget gvw = (GhostviewWidget) w;
- int bytes_written;
- SIGVAL (*oldsig)();
-
- oldsig = signal(SIGPIPE, CatchPipe);
-
- #ifdef NON_BLOCKING_IO
- do {
- #endif
-
- if (gvw->ghostview.buffer_bytes_left == 0) {
-
- /* Get a new section if required */
- if (gvw->ghostview.ps_input && gvw->ghostview.bytes_left == 0) {
- struct record_list *ps_old = gvw->ghostview.ps_input;
- gvw->ghostview.ps_input = ps_old->next;
- if (ps_old->close) fclose(ps_old->fp);
- XtFree((char *)ps_old);
- }
-
- /* Have to seek at the beginning of each section */
- if (gvw->ghostview.ps_input &&
- gvw->ghostview.ps_input->seek_needed) {
- if (gvw->ghostview.ps_input->len > 0)
- fseek(gvw->ghostview.ps_input->fp,
- gvw->ghostview.ps_input->begin, SEEK_SET);
- gvw->ghostview.ps_input->seek_needed = False;
- gvw->ghostview.bytes_left = gvw->ghostview.ps_input->len;
- }
-
- if (gvw->ghostview.bytes_left > GV_BUFSIZ) {
- gvw->ghostview.buffer_bytes_left =
- fread(gvw->ghostview.input_buffer,
- sizeof (char), GV_BUFSIZ,
- gvw->ghostview.ps_input->fp);
- } else if (gvw->ghostview.bytes_left > 0) {
- gvw->ghostview.buffer_bytes_left =
- fread(gvw->ghostview.input_buffer,
- sizeof (char), gvw->ghostview.bytes_left,
- gvw->ghostview.ps_input->fp);
- } else {
- gvw->ghostview.buffer_bytes_left = 0;
- }
- if (gvw->ghostview.bytes_left > 0 &&
- gvw->ghostview.buffer_bytes_left == 0) {
- InterpreterFailed(w); /* Error occurred */
- }
- gvw->ghostview.input_buffer_ptr = gvw->ghostview.input_buffer;
- gvw->ghostview.bytes_left -= gvw->ghostview.buffer_bytes_left;
- }
-
- if (gvw->ghostview.buffer_bytes_left > 0) {
- bytes_written = write(gvw->ghostview.interpreter_input,
- gvw->ghostview.input_buffer_ptr,
- gvw->ghostview.buffer_bytes_left);
-
- if (broken_pipe) {
- broken_pipe = False;
- InterpreterFailed(w); /* Something bad happened */
- } else if (bytes_written == -1) {
- if ((errno != EWOULDBLOCK) && (errno != EAGAIN)) {
- InterpreterFailed(w); /* Something bad happened */
- }
- } else {
- gvw->ghostview.buffer_bytes_left -= bytes_written;
- gvw->ghostview.input_buffer_ptr += bytes_written;
- }
- }
- #ifdef NON_BLOCKING_IO
- } while(gvw->ghostview.ps_input &&
- gvw->ghostview.buffer_bytes_left == 0);
- #endif
- signal(SIGPIPE, oldsig);
- if (gvw->ghostview.ps_input == NULL &&
- gvw->ghostview.buffer_bytes_left == 0) {
- if (gvw->ghostview.interpreter_input_id != None) {
- XtRemoveInput(gvw->ghostview.interpreter_input_id);
- gvw->ghostview.interpreter_input_id = None;
- }
- }
- }
-
- /* Output - receive I/O from ghostscript's stdout and stderr.
- * Pass this to the application via the output_callback. */
- static void
- Output(client_data, source, id)
- XtPointer client_data;
- int *source;
- XtInputId *id;
- {
- Widget w = (Widget) client_data;
- GhostviewWidget gvw = (GhostviewWidget) w;
- char buf[GV_BUFSIZ+1];
- int bytes = 0;
-
- if (*source == gvw->ghostview.interpreter_output) {
- bytes = read(gvw->ghostview.interpreter_output, buf, GV_BUFSIZ);
- if (bytes == 0) { /* EOF occurred */
- close(gvw->ghostview.interpreter_output);
- gvw->ghostview.interpreter_output = -1;
- XtRemoveInput(gvw->ghostview.interpreter_output_id);
- return;
- } else if (bytes == -1) {
- InterpreterFailed(w); /* Something bad happened */
- return;
- }
- } else if (*source == gvw->ghostview.interpreter_error) {
- bytes = read(gvw->ghostview.interpreter_error, buf, GV_BUFSIZ);
- if (bytes == 0) { /* EOF occurred */
- close(gvw->ghostview.interpreter_error);
- gvw->ghostview.interpreter_error = -1;
- XtRemoveInput(gvw->ghostview.interpreter_error_id);
- return;
- } else if (bytes == -1) {
- InterpreterFailed(w); /* Something bad happened */
- return;
- }
- }
- if (bytes > 0) {
- buf[bytes] = '\0';
- XtCallCallbackList(w, gvw->ghostview.output_callback, (XtPointer) buf);
- }
- }
-
- #endif /* VMS */
-
- /* Register the type converter required for the PageOrientation. */
- /* Register the type converter required for the Palette. */
- /* This routine is called exactly once. */
- static void
- ClassInitialize()
- {
- XtSetTypeConverter(XtRString, XtRPageOrientation,
- XmuCvtStringToPageOrientation, NULL, 0,
- XtCacheAll, NULL);
- XtSetTypeConverter(XtRString, XtRPalette,
- XmuCvtStringToPalette, NULL, 0,
- XtCacheAll, NULL);
- }
-
- /* Get atoms needed to communicate with ghostscript. */
- /* This routine is called once per display. */
- static void
- ClassPartInitialize(class)
- WidgetClass class;
- {
- GhostviewWidgetClass gvc = (GhostviewWidgetClass)class;
- gvc->ghostview_class.ghostview = XmuMakeAtom("GHOSTVIEW");
- gvc->ghostview_class.gv_colors = XmuMakeAtom("GHOSTVIEW_COLORS");
- gvc->ghostview_class.next = XmuMakeAtom("NEXT");
- gvc->ghostview_class.page = XmuMakeAtom("PAGE");
- gvc->ghostview_class.done = XmuMakeAtom("DONE");
- }
-
- /* Initialize private state. */
-
- static void
- Initialize(request, new, args, num_args)
- Widget request, new;
- ArgList args; /* unused */
- Cardinal *num_args; /* unused */
- {
- XGCValues values;
- XtGCMask mask;
- GhostviewWidget ngvw = (GhostviewWidget) new;
- GhostviewWidget rgvw = (GhostviewWidget) request;
-
- values.foreground = new->core.background_pixel;
- mask = GCForeground;
- ngvw->ghostview.gc = XtGetGC(new, mask, &values);
- ngvw->ghostview.mwin = None;
- ngvw->ghostview.disable_start = False;
- ngvw->ghostview.interpreter_pid = -1;
- ngvw->ghostview.input_buffer = NULL;
- ngvw->ghostview.bytes_left = 0;
- #ifndef VMS
- ngvw->ghostview.input_buffer_ptr = NULL;
- ngvw->ghostview.buffer_bytes_left = 0;
- #endif
- ngvw->ghostview.ps_input = NULL;
- ngvw->ghostview.interpreter_input = -1;
- ngvw->ghostview.interpreter_output = -1;
- #ifndef VMS
- ngvw->ghostview.interpreter_error = -1;
- ngvw->ghostview.interpreter_input_id = None;
- ngvw->ghostview.interpreter_output_id = None;
- ngvw->ghostview.interpreter_error_id = None;
- #else /* VMS */
- memset(ngvw->ghostview.interpreter_input_iosb, 0, 8);
- memset(ngvw->ghostview.interpreter_output_iosb, 0, 8);
- ngvw->ghostview.output_buffer = NULL;
- #endif /* VMS */
- ngvw->ghostview.gs_width = 0;
- ngvw->ghostview.gs_height = 0;
- ngvw->ghostview.changed = False;
- ngvw->ghostview.busy = False;
-
- /* Compute window size */
- Layout(new, (rgvw->core.width == 0), (rgvw->core.height == 0));
- }
-
- /* Create Window and start interpreter if needed */
- static void
- Realize(w, valueMask, attributes)
- Widget w;
- Mask *valueMask;
- XSetWindowAttributes *attributes;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
-
- if (gvw->ghostview.cursor != None) {
- attributes->cursor = gvw->ghostview.cursor;
- *valueMask |= CWCursor;
- }
-
- XtCreateWindow(w, (unsigned int) InputOutput, (Visual *) CopyFromParent,
- *valueMask, attributes);
-
- Setup(w);
- }
-
- /* Destroy routine: kill the interpreter and release the GC */
- static void
- Destroy(w)
- Widget w;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
-
- StopInterpreter(w);
- XtReleaseGC(w, gvw->ghostview.gc);
- if (gvw->ghostview.input_buffer) XtFree(gvw->ghostview.input_buffer);
- #ifdef VMS
- if (gvw->ghostview.output_buffer) XtFree(gvw->ghostview.output_buffer);
- #endif /* VMS */
- if (gvw->core.background_pixmap != XtUnspecifiedPixmap)
- XFreePixmap(XtDisplay(w), gvw->core.background_pixmap);
- }
-
- /* Process resize request. Requested size cannot be changed.
- * NOTE: This routine may be called before the widget is realized.
- * (It was a surprise to me.)
- * If the widget is realized, start a new interpreter by calling Setup().
- * If Setup() actually started a new interpreter and it is taking input
- * from stdin, send a refresh message to the application. This is the
- * only way that the application can be notified that it needs to resend
- * the input because someone forced a new window size on the widget.
- */
- static void
- Resize(w)
- Widget w;
- {
- Layout(w, False, False);
- if (!XtIsRealized(w)) return;
- if (Setup(w)) {
- GhostviewWidget gvw = (GhostviewWidget) w;
- if (gvw->ghostview.filename == NULL) {
- XtCallCallbackList(w, gvw->ghostview.message_callback, "Refresh");
- }
- }
- }
-
- /* SetValues routine. Set new private state, based on changed values
- * in the widget. Always returns False, because redisplay is never needed.
- */
- static Boolean
- SetValues(current, request, new)
- Widget current, request, new;
- {
- GhostviewWidget cgvw = (GhostviewWidget) current;
- GhostviewWidget rgvw = (GhostviewWidget) request;
- GhostviewWidget ngvw = (GhostviewWidget) new;
- String cfilename;
- String rfilename;
- String carguments;
- String rarguments;
-
- cfilename = cgvw->ghostview.filename;
- if (cfilename == NULL) cfilename = "(null)";
- rfilename = rgvw->ghostview.filename;
- if (rfilename == NULL) rfilename = "(null)";
- carguments = cgvw->ghostview.arguments;
- if (carguments == NULL) carguments = "(null)";
- rarguments = rgvw->ghostview.arguments;
- if (rarguments == NULL) rarguments = "(null)";
-
- if (XtIsRealized(new) && !ngvw->ghostview.busy &&
- (cgvw->ghostview.cursor != ngvw->ghostview.cursor)) {
- XDefineCursor(XtDisplay(new), XtWindow(new), ngvw->ghostview.cursor);
- }
- if (XtIsRealized(new) && ngvw->ghostview.busy &&
- (cgvw->ghostview.busy_cursor != ngvw->ghostview.busy_cursor)) {
- XDefineCursor(XtDisplay(new), XtWindow(new),
- ngvw->ghostview.busy_cursor);
- }
- if (cgvw->core.background_pixel != rgvw->core.background_pixel) {
- XGCValues values;
- XtGCMask mask;
-
- XtReleaseGC(current, cgvw->ghostview.gc);
- values.foreground = new->core.background_pixel;
- mask = GCForeground;
- ngvw->ghostview.gc = XtGetGC(new, mask, &values);
- }
- if ((cgvw->core.width != rgvw->core.width) ||
- (cgvw->core.height != rgvw->core.height) ||
- (cgvw->core.background_pixel != rgvw->core.background_pixel) ||
- (cgvw->ghostview.foreground != rgvw->ghostview.foreground) ||
- (cgvw->ghostview.palette != rgvw->ghostview.palette) ||
- strcmp(cgvw->ghostview.interpreter, rgvw->ghostview.interpreter) ||
- strcmp(carguments, rarguments) ||
- (cgvw->ghostview.quiet != rgvw->ghostview.quiet) ||
- (cgvw->ghostview.safer != rgvw->ghostview.safer) ||
- strcmp(cfilename, rfilename) ||
- (cgvw->ghostview.orientation != rgvw->ghostview.orientation) ||
- (cgvw->ghostview.use_bpixmap != rgvw->ghostview.use_bpixmap) ||
- (cgvw->ghostview.xdpi != rgvw->ghostview.xdpi) ||
- (cgvw->ghostview.ydpi != rgvw->ghostview.ydpi) ||
- (cgvw->ghostview.bottom_margin != rgvw->ghostview.bottom_margin) ||
- (cgvw->ghostview.left_margin != rgvw->ghostview.left_margin) ||
- (cgvw->ghostview.right_margin != rgvw->ghostview.right_margin) ||
- (cgvw->ghostview.top_margin != rgvw->ghostview.top_margin) ||
- (cgvw->ghostview.llx != rgvw->ghostview.llx) ||
- (cgvw->ghostview.lly != rgvw->ghostview.lly) ||
- (cgvw->ghostview.urx != rgvw->ghostview.urx) ||
- (cgvw->ghostview.ury != rgvw->ghostview.ury)) {
-
- ngvw->ghostview.changed = True;
- Layout(new, True, True);
- }
-
- if (ngvw->ghostview.changed && XtIsRealized(current)) Setup(new);
- return(False);
- }
-
- /* Function Name: QueryGeometry
- * Description: This tells the parent what size we would like to be
- * given certain constraints.
- * Arguments: w - the widget.
- * intended - what the parent intends to do with us.
- * requested - what we want to happen.
- */
-
- static XtGeometryResult
- QueryGeometry(w, intended, requested)
- Widget w;
- XtWidgetGeometry *intended, *requested;
- {
- Dimension new_width, new_height;
- Boolean change, width_req, height_req;
-
- width_req = intended->request_mode & CWWidth;
- height_req = intended->request_mode & CWHeight;
-
- if (width_req)
- new_width = intended->width;
- else
- new_width = w->core.width;
-
- if (height_req)
- new_height = intended->height;
- else
- new_height = w->core.height;
-
- requested->request_mode = 0;
-
- /*
- * We only care about our height and width.
- */
-
- if (!width_req && !height_req)
- return(XtGeometryYes);
-
- change = ComputeSize(w, !width_req, !height_req, &new_width, &new_height);
-
- requested->request_mode |= CWWidth;
- requested->width = new_width;
- requested->request_mode |= CWHeight;
- requested->height = new_height;
-
- if (change)
- return(XtGeometryAlmost);
- return(XtGeometryYes);
- }
-
- /* Layout the widget. */
-
- static void
- Layout(w, xfree, yfree)
- Widget w;
- Boolean xfree, yfree;
- {
- Dimension width = w->core.width;
- Dimension height = w->core.height;
- Boolean different_size = ComputeSize(w, xfree, yfree, &width, &height);
- if (different_size) ChangeSize(w, width, height);
- }
-
- /* Compute new size of window, sets xdpi and ydpi if necessary.
- * returns True if new window size is different */
- static Boolean
- ComputeSize(w, xfree, yfree, width, height)
- Widget w;
- Boolean xfree, yfree; /* Am I allowed to change width or height */
- Dimension *width, *height;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- Dimension new_width = *width;
- Dimension new_height = *height;
- float newxdpi, newydpi;
- Boolean change;
-
- if (xfree && yfree) {
- /* width and height can be changed, calculate window size according */
- /* to xpdi and ydpi */
- switch (gvw->ghostview.orientation) {
- case XtPageOrientationPortrait:
- case XtPageOrientationUpsideDown:
- new_width = (gvw->ghostview.urx - gvw->ghostview.llx) / 72.0 *
- gvw->ghostview.xdpi + 0.5;
- new_height = (gvw->ghostview.ury - gvw->ghostview.lly) / 72.0 *
- gvw->ghostview.ydpi + 0.5;
- break;
- case XtPageOrientationLandscape:
- case XtPageOrientationSeascape:
- new_width = (gvw->ghostview.ury - gvw->ghostview.lly) / 72.0 *
- gvw->ghostview.xdpi + 0.5;
- new_height = (gvw->ghostview.urx - gvw->ghostview.llx) / 72.0 *
- gvw->ghostview.ydpi + 0.5;
- break;
- }
- } else if (xfree) {
- /* height is fixed. Preserve aspect ratio by recomputing */
- /* ydpi and xdpi */
- switch (gvw->ghostview.orientation) {
- case XtPageOrientationPortrait:
- case XtPageOrientationUpsideDown:
- newydpi = gvw->core.height * 72.0 /
- (gvw->ghostview.ury - gvw->ghostview.lly);
- newxdpi = newydpi * gvw->ghostview.xdpi / gvw->ghostview.ydpi;
- gvw->ghostview.xdpi = newxdpi;
- gvw->ghostview.ydpi = newydpi;
- new_width = (gvw->ghostview.urx - gvw->ghostview.llx) / 72.0 *
- gvw->ghostview.xdpi + 0.5;
- break;
- case XtPageOrientationLandscape:
- case XtPageOrientationSeascape:
- newydpi = gvw->core.height * 72.0 /
- (gvw->ghostview.urx - gvw->ghostview.llx);
- newxdpi = newydpi * gvw->ghostview.xdpi / gvw->ghostview.ydpi;
- gvw->ghostview.xdpi = newxdpi;
- gvw->ghostview.ydpi = newydpi;
- new_width = (gvw->ghostview.ury - gvw->ghostview.lly) / 72.0 *
- gvw->ghostview.xdpi + 0.5;
- break;
- }
- } else if (yfree) {
- /* width is fixed. Preserve aspect ratio by recomputing */
- /* xdpi and ydpi */
- switch (gvw->ghostview.orientation) {
- case XtPageOrientationPortrait:
- case XtPageOrientationUpsideDown:
- newxdpi = gvw->core.width * 72.0 /
- (gvw->ghostview.urx - gvw->ghostview.llx);
- newydpi = newxdpi * gvw->ghostview.ydpi / gvw->ghostview.xdpi;
- gvw->ghostview.xdpi = newxdpi;
- gvw->ghostview.ydpi = newydpi;
- new_height = (gvw->ghostview.ury - gvw->ghostview.lly) / 72.0 *
- gvw->ghostview.ydpi + 0.5;
- break;
- case XtPageOrientationLandscape:
- case XtPageOrientationSeascape:
- newxdpi = gvw->core.width * 72.0 /
- (gvw->ghostview.ury - gvw->ghostview.lly);
- newydpi = newxdpi * gvw->ghostview.ydpi / gvw->ghostview.xdpi;
- gvw->ghostview.xdpi = newxdpi;
- gvw->ghostview.ydpi = newydpi;
- new_height = (gvw->ghostview.urx - gvw->ghostview.llx) / 72.0 *
- gvw->ghostview.ydpi + 0.5;
- break;
- }
- } else {
- /* height and width are fixed. Just have to live with it. */
- switch (gvw->ghostview.orientation) {
- case XtPageOrientationPortrait:
- case XtPageOrientationUpsideDown:
- gvw->ghostview.xdpi = gvw->core.width * 72.0 /
- (gvw->ghostview.urx - gvw->ghostview.llx);
- gvw->ghostview.ydpi = gvw->core.height * 72.0 /
- (gvw->ghostview.ury - gvw->ghostview.lly);
- break;
- case XtPageOrientationLandscape:
- case XtPageOrientationSeascape:
- gvw->ghostview.xdpi = gvw->core.width * 72.0 /
- (gvw->ghostview.ury - gvw->ghostview.lly);
- gvw->ghostview.ydpi = gvw->core.height * 72.0 /
- (gvw->ghostview.urx - gvw->ghostview.llx);
- break;
- }
- }
-
- change = (new_width != *width) || (new_height != *height);
- *width = new_width;
- *height = new_height;
- return (change);
- }
-
- /* Function Name: ChangeSize.
- * Description: Request a size change.
- * Arguments: w - the widget to try change the size of.
- */
-
- static void
- ChangeSize(w, width, height)
- Widget w;
- Dimension width, height;
- {
- XtWidgetGeometry request, reply;
- Boolean changed = False;
-
- request.request_mode = CWWidth | CWHeight;
- request.width = width;
- request.height = height;
-
- switch ( XtMakeGeometryRequest(w, &request, &reply) ) {
- case XtGeometryYes:
- changed = True;
- break;
- case XtGeometryNo:
- break;
- case XtGeometryAlmost:
- ComputeSize(w, (request.height != reply.height),
- (request.width != reply.width),
- &(reply.width), &(reply.height));
- request = reply;
- switch (XtMakeGeometryRequest(w, &request, &reply) ) {
- case XtGeometryYes:
- changed = True;
- break;
- case XtGeometryNo:
- break;
- case XtGeometryAlmost:
- request = reply;
- ComputeSize(w, FALSE, FALSE, &(request.width), &(request.height));
- request.request_mode = CWWidth | CWHeight;
- XtMakeGeometryRequest(w, &request, &reply);
- changed = True;
- break;
- }
- break;
- }
-
- /* If success, setup the widet for the new size. */
- if (changed && XtIsRealized(w)) Setup(w);
- }
-
- /* Catch the alloc error when there is not enough resources for the
- * backing pixmap. Automatically shut off backing pixmap and let the
- * user know when this happens.
- */
- static Boolean alloc_error;
- static XErrorHandler oldhandler;
-
- static int
- catch_alloc (dpy, err)
- Display *dpy;
- XErrorEvent *err;
- {
- if (err->error_code == BadAlloc) {
- alloc_error = True;
- }
- if (alloc_error) return 0;
- return oldhandler(dpy, err);
- }
-
- /* Setup - sets up the backing pixmap, and GHOSTVIEW property and
- * starts interpreter if needed.
- * NOTE: the widget must be realized before calling Setup().
- * Returns True if a new interpreter was started, False otherwise.
- */
-
- static Boolean
- Setup(w)
- Widget w;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- GhostviewWidgetClass gvc = (GhostviewWidgetClass) XtClass(w);
- char buf[GV_BUFSIZ];
- Pixmap bpixmap;
- XSetWindowAttributes xswa;
-
- if (!gvw->ghostview.changed &&
- (gvw->core.width == gvw->ghostview.gs_width) &&
- (gvw->core.height == gvw->ghostview.gs_height)) return False;
-
- StopInterpreter(w);
-
- if ((gvw->core.width != gvw->ghostview.gs_width) ||
- (gvw->core.height != gvw->ghostview.gs_height) ||
- (!gvw->ghostview.use_bpixmap)) {
- if (gvw->core.background_pixmap != XtUnspecifiedPixmap) {
- XFreePixmap(XtDisplay(w), gvw->core.background_pixmap);
- gvw->core.background_pixmap = XtUnspecifiedPixmap;
- XSetWindowBackgroundPixmap(XtDisplay(w), XtWindow(w), None);
- }
- }
-
- if (gvw->ghostview.use_bpixmap) {
- if (gvw->core.background_pixmap == XtUnspecifiedPixmap) {
- /* Get a Backing Pixmap, but be ready for the BadAlloc. */
- XSync(XtDisplay(w), False); /* Get to known state */
- oldhandler = XSetErrorHandler(catch_alloc);
- alloc_error = False;
- bpixmap = XCreatePixmap(XtDisplay(w), XtWindow(w),
- gvw->core.width, gvw->core.height,
- gvw->core.depth);
- XSync(XtDisplay(w), False); /* Force the error */
- if (alloc_error) {
- XtCallCallbackList(w, gvw->ghostview.message_callback,
- "BadAlloc");
- if (bpixmap != None) {
- XFreePixmap(XtDisplay(w), bpixmap);
- XSync(XtDisplay(w), False); /* Force the error */
- bpixmap = None;
- }
- }
- oldhandler = XSetErrorHandler(oldhandler);
- if (bpixmap != None) {
- gvw->core.background_pixmap = bpixmap;
- XSetWindowBackgroundPixmap(XtDisplay(w), XtWindow(w),
- gvw->core.background_pixmap);
- }
- } else {
- bpixmap = gvw->core.background_pixmap;
- }
- } else {
- if (gvw->core.background_pixmap != XtUnspecifiedPixmap) {
- XFreePixmap(XtDisplay(w), gvw->core.background_pixmap);
- gvw->core.background_pixmap = XtUnspecifiedPixmap;
- XSetWindowBackgroundPixmap(XtDisplay(w), XtWindow(w), None);
- }
- bpixmap = None;
- }
-
- if (bpixmap != None) {
- xswa.backing_store = NotUseful;
- XChangeWindowAttributes(XtDisplay(w), XtWindow(w),
- CWBackingStore, &xswa);
- } else {
- xswa.backing_store = Always;
- XChangeWindowAttributes(XtDisplay(w), XtWindow(w),
- CWBackingStore, &xswa);
- }
-
- gvw->ghostview.gs_width = gvw->core.width;
- gvw->ghostview.gs_height = gvw->core.height;
-
- sprintf(buf, "%d %d %d %d %d %d %g %g %d %d %d %d",
- bpixmap, gvw->ghostview.orientation,
- gvw->ghostview.llx, gvw->ghostview.lly,
- gvw->ghostview.urx, gvw->ghostview.ury,
- gvw->ghostview.xdpi, gvw->ghostview.ydpi,
- gvw->ghostview.left_margin, gvw->ghostview.bottom_margin,
- gvw->ghostview.right_margin, gvw->ghostview.top_margin);
- XChangeProperty(XtDisplay(w), XtWindow(w),
- XmuInternAtom(XtDisplay(w), gvc->ghostview_class.ghostview),
- XA_STRING, 8, PropModeReplace,
- (unsigned char *)buf, strlen(buf));
-
- sprintf(buf, "%s %d %d",
- gvw->ghostview.palette == XtPaletteMonochrome ? "Monochrome" :
- gvw->ghostview.palette == XtPaletteGrayscale ? "Grayscale" :
- gvw->ghostview.palette == XtPaletteColor ? "Color" : "?",
- gvw->ghostview.foreground, gvw->core.background_pixel);
- XChangeProperty(XtDisplay(w), XtWindow(w),
- XmuInternAtom(XtDisplay(w), gvc->ghostview_class.gv_colors),
- XA_STRING, 8, PropModeReplace,
- (unsigned char *)buf, strlen(buf));
-
- XSync(XtDisplay(w), False); /* Be sure to update properties */
- StartInterpreter(w);
- return True;
- }
-
- #ifndef VMS
-
- /* This routine starts the interpreter. It sets the DISPLAY and
- * GHOSTVIEW environment variables. The GHOSTVIEW environment variable
- * contains the Window that ghostscript should write on.
- *
- * This routine also opens pipes for stdout and stderr and initializes
- * application input events for them. If input to ghostscript is not
- * from a file, a pipe for stdin is created. This pipe is setup for
- * non-blocking I/O so that the user interface never "hangs" because of
- * a write to ghostscript.
- */
- static void
- StartInterpreter(w)
- Widget w;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- int std_in[2];
- int std_out[2];
- int std_err[2];
- char buf[GV_BUFSIZ];
- #define NUM_ARGS 100
- char *argv[NUM_ARGS];
- char *arguments = NULL;
- char *cptr;
- int argc = 0;
- int ret;
-
- StopInterpreter(w);
-
- /* Clear the window before starting a new interpreter. */
- if (gvw->core.background_pixmap != XtUnspecifiedPixmap) {
- XFillRectangle(XtDisplay(w), gvw->core.background_pixmap,
- gvw->ghostview.gc,
- 0, 0, gvw->core.width, gvw->core.height);
- }
- XClearArea(XtDisplay(w), XtWindow(w),
- 0, 0, gvw->core.width, gvw->core.height, False);
-
- if (gvw->ghostview.disable_start) return;
-
- argv[argc++] = gvw->ghostview.interpreter;
- argv[argc++] = "-sDEVICE=x11";
- argv[argc++] = "-dNOPAUSE";
- if (gvw->ghostview.quiet) argv[argc++] = "-dQUIET";
- if (gvw->ghostview.safer) argv[argc++] = "-dSAFER";
- if (gvw->ghostview.arguments) {
- cptr = arguments = XtNewString(gvw->ghostview.arguments);
- while (isspace(*cptr)) cptr++;
- while (*cptr) {
- argv[argc++] = cptr;
- while (*cptr && !isspace(*cptr)) cptr++;
- if (*cptr) *cptr++ = '\0';
- if (argc + 2 >= NUM_ARGS) {
- fprintf(stderr, "Too many arguments to interpreter.\n");
- exit(1);
- }
- while (isspace(*cptr)) cptr++;
- }
- }
- argv[argc++] = "-";
- argv[argc++] = NULL;
-
- if (gvw->ghostview.filename == NULL) {
- ret = pipe(std_in);
- if (ret == -1) {
- perror("Could not create pipe");
- exit(1);
- }
- } else if (strcmp(gvw->ghostview.filename, "-")) {
- std_in[0] = open(gvw->ghostview.filename, O_RDONLY, 0);
- }
- ret = pipe(std_out);
- if (ret == -1) {
- perror("Could not create pipe");
- exit(1);
- }
- ret = pipe(std_err);
- if (ret == -1) {
- perror("Could not create pipe");
- exit(1);
- }
-
- gvw->ghostview.changed = False;
- gvw->ghostview.busy = True;
- XDefineCursor(XtDisplay(gvw), XtWindow(gvw), gvw->ghostview.busy_cursor);
- #if defined(SYSV) || defined(USG)
- #define vfork fork
- #endif
- gvw->ghostview.interpreter_pid = vfork();
-
- if (gvw->ghostview.interpreter_pid == 0) { /* child */
- close(std_out[0]);
- close(std_err[0]);
- dup2(std_out[1], 1);
- close(std_out[1]);
- dup2(std_err[1], 2);
- close(std_err[1]);
- sprintf(buf, "%d", XtWindow(w));
- setenv("GHOSTVIEW", buf, True);
- setenv("DISPLAY", XDisplayString(XtDisplay(w)), True);
- if (gvw->ghostview.filename == NULL) {
- close(std_in[1]);
- dup2(std_in[0], 0);
- close(std_in[0]);
- } else if (strcmp(gvw->ghostview.filename, "-")) {
- dup2(std_in[0], 0);
- close(std_in[0]);
- }
- execvp(argv[0], argv);
- sprintf(buf, "Exec of %s failed", argv[0]);
- perror(buf);
- _exit(1);
- } else {
- if (gvw->ghostview.filename == NULL) {
- #ifdef NON_BLOCKING_IO
- int result;
- #endif
- close(std_in[0]);
-
- #ifdef NON_BLOCKING_IO
- result = fcntl(std_in[1], F_GETFL, 0);
- result = result | O_NONBLOCK;
- result = fcntl(std_in[1], F_SETFL, result);
- #endif
- gvw->ghostview.interpreter_input = std_in[1];
- gvw->ghostview.interpreter_input_id = None;
- } else if (strcmp(gvw->ghostview.filename, "-")) {
- close(std_in[0]);
- }
- close(std_out[1]);
- gvw->ghostview.interpreter_output = std_out[0];
- gvw->ghostview.interpreter_output_id =
- XtAppAddInput(XtWidgetToApplicationContext(w), std_out[0],
- (XtPointer)XtInputReadMask, Output, (XtPointer)w);
- close(std_err[1]);
- gvw->ghostview.interpreter_error = std_err[0];
- gvw->ghostview.interpreter_error_id =
- XtAppAddInput(XtWidgetToApplicationContext(w), std_err[0],
- (XtPointer)XtInputReadMask, Output, (XtPointer)w);
- }
- if (arguments) XtFree(arguments);
- }
-
- /* Stop the interperter, if present, and remove any Input sources. */
- /* Also reset the busy state. */
- static void
- StopInterpreter(w)
- Widget w;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- if (gvw->ghostview.interpreter_pid >= 0) {
- kill(gvw->ghostview.interpreter_pid, SIGTERM);
- wait(0);
- gvw->ghostview.interpreter_pid = -1;
- }
- if (gvw->ghostview.interpreter_input >= 0) {
- close(gvw->ghostview.interpreter_input);
- gvw->ghostview.interpreter_input = -1;
- if (gvw->ghostview.interpreter_input_id != None) {
- XtRemoveInput(gvw->ghostview.interpreter_input_id);
- gvw->ghostview.interpreter_input_id = None;
- }
- while (gvw->ghostview.ps_input) {
- struct record_list *ps_old = gvw->ghostview.ps_input;
- gvw->ghostview.ps_input = ps_old->next;
- if (ps_old->close) fclose(ps_old->fp);
- XtFree((char *)ps_old);
- }
- }
- if (gvw->ghostview.interpreter_output >= 0) {
- close(gvw->ghostview.interpreter_output);
- gvw->ghostview.interpreter_output = -1;
- XtRemoveInput(gvw->ghostview.interpreter_output_id);
- }
- if (gvw->ghostview.interpreter_error >= 0) {
- close(gvw->ghostview.interpreter_error);
- gvw->ghostview.interpreter_error = -1;
- XtRemoveInput(gvw->ghostview.interpreter_error_id);
- }
- gvw->ghostview.busy = False;
- XDefineCursor(XtDisplay(gvw), XtWindow(gvw), gvw->ghostview.cursor);
- }
-
- #endif /* VMS */
-
- /* The interpeter failed, Stop what's left and notify application */
- static void
- InterpreterFailed(w)
- Widget w;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- StopInterpreter(w);
- XtCallCallbackList(w, gvw->ghostview.message_callback, "Failed");
- }
-
- /*
- * Public Routines
- */
-
- /* GhostviewDisableInterpreter:
- * Stop any interpreter and disable new ones from starting.
- */
- void
- GhostviewDisableInterpreter(w)
- Widget w;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- gvw->ghostview.disable_start = True;
- if (XtIsRealized(w)) StopInterpreter(w);
- }
-
- /* GhostviewDisableInterpreter:
- * Allow an interpreter to start and start one if the widget is
- * currently realized.
- */
- void
- GhostviewEnableInterpreter(w)
- Widget w;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- gvw->ghostview.disable_start = False;
- if (XtIsRealized(w)) StartInterpreter(w);
- }
-
- /* GhostviewIsInterpreterReady:
- * Returns True if the interpreter is ready for new input.
- */
- Boolean
- GhostviewIsInterpreterReady(w)
- Widget w;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- return gvw->ghostview.interpreter_pid != -1 &&
- !gvw->ghostview.busy &&
- gvw->ghostview.ps_input == NULL;
- }
-
- /* GhostviewIsInterpreterRunning:
- * Returns True if the interpreter is running.
- */
- Boolean
- GhostviewIsInterpreterRunning(w)
- Widget w;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- return gvw->ghostview.interpreter_pid != -1;
- }
-
- /* GhostviewGetBackingPixmap:
- * Returns the current backing pixmap.
- */
- Pixmap
- GhostviewGetBackingPixmap(w)
- Widget w;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- if (gvw->core.background_pixmap != XtUnspecifiedPixmap)
- return(gvw->core.background_pixmap);
- else
- return(None);
- }
-
- #ifndef VMS
-
- /* GhostviewSendPS:
- * Queue a portion of a PostScript file for output to ghostscript.
- * fp: FILE * of the file in question. NOTE: if you have several
- * Ghostview widgets reading from the same file. You must open
- * a unique FILE * for each widget.
- * SendPS does not actually send the PostScript, it merely queues it
- * for output.
- * begin: position in file (returned from ftell()) to start.
- * len: number of bytes to write.
- *
- * If an interpreter is not running, nothing is queued and
- * False is returned.
- */
- Boolean
- GhostviewSendPS(w, fp, begin, len, close)
- Widget w;
- FILE *fp;
- long begin;
- unsigned int len;
- Bool close;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- struct record_list *ps_new;
-
- if (gvw->ghostview.interpreter_input < 0) return False;
- ps_new = (struct record_list *) XtMalloc(sizeof (struct record_list));
- ps_new->fp = fp;
- ps_new->begin = begin;
- ps_new->len = len;
- ps_new->seek_needed = True;
- ps_new->close = close;
- ps_new->next = NULL;
-
- if (gvw->ghostview.input_buffer == NULL) {
- gvw->ghostview.input_buffer = XtMalloc(GV_BUFSIZ);
- }
-
- if (gvw->ghostview.ps_input == NULL) {
- gvw->ghostview.input_buffer_ptr = gvw->ghostview.input_buffer;
- gvw->ghostview.bytes_left = len;
- gvw->ghostview.buffer_bytes_left = 0;
- gvw->ghostview.ps_input = ps_new;
- gvw->ghostview.interpreter_input_id =
- XtAppAddInput(XtWidgetToApplicationContext(w),
- gvw->ghostview.interpreter_input,
- (XtPointer)XtInputWriteMask, Input, (XtPointer)w);
- } else {
- struct record_list *p = gvw->ghostview.ps_input;
- while (p->next != NULL) {
- p = p->next;
- }
- p->next = ps_new;
- }
- return True;
- }
-
- #endif /* VMS */
-
- /* GhostviewNextPage:
- * Tell ghostscript to start the next page.
- * Returns False if ghostscript is not running, or not ready to start
- * another page.
- * If another page is started. Sets the busy flag and cursor.
- */
- Boolean
- GhostviewNextPage(w)
- Widget w;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- GhostviewWidgetClass gvc = (GhostviewWidgetClass) XtClass(w);
- XEvent event;
-
- if (gvw->ghostview.interpreter_pid < 0) return False;
- if (gvw->ghostview.mwin == None) return False;
-
- if (!gvw->ghostview.busy) {
- gvw->ghostview.busy = True;
- XDefineCursor(XtDisplay(gvw), XtWindow(gvw),
- gvw->ghostview.busy_cursor);
-
- event.xclient.type = ClientMessage;
- event.xclient.display = XtDisplay(w);
- event.xclient.window = gvw->ghostview.mwin;
- event.xclient.message_type =
- XmuInternAtom(XtDisplay(w), gvc->ghostview_class.next);
- event.xclient.format = 32;
- XSendEvent(XtDisplay(w), gvw->ghostview.mwin, False, 0, &event);
- XFlush(XtDisplay(w)); /* And push it out */
- return True;
- } else {
- return False;
- }
- }
-
- #define done(type, value) \
- { \
- if (toVal->addr != NULL) { \
- if (toVal->size < sizeof(type)) { \
- toVal->size = sizeof(type); \
- return False; \
- } \
- *(type*)(toVal->addr) = (value); \
- } \
- else { \
- static type static_val; \
- static_val = (value); \
- toVal->addr = (XPointer)&static_val; \
- } \
- toVal->size = sizeof(type); \
- return True; \
- }
-
- /* PageOrienation Conversion Routine.
- * Returns True if Conversion is successful.
- */
- Boolean
- XmuCvtStringToPageOrientation(dpy, args, num_args, fromVal, toVal, data)
- Display *dpy;
- XrmValue *args; /* unused */
- Cardinal *num_args; /* unused */
- XrmValue *fromVal;
- XrmValue *toVal;
- XtPointer *data; /* unused */
- {
- static XrmQuark XrmQEportrait;
- static XrmQuark XrmQElandscape;
- static XrmQuark XrmQEupsideDown;
- static XrmQuark XrmQEseascape;
- static int haveQuarks;
- XrmQuark q;
- char *str = (XPointer) fromVal->addr;
- char lowerName[1000];
-
- if (str == NULL) return False;
-
- if (!haveQuarks) {
- XrmQEportrait = XrmStringToQuark(XtEportrait);
- XrmQElandscape = XrmStringToQuark(XtElandscape);
- XrmQEupsideDown = XrmStringToQuark(XtEupsideDown);
- XrmQEseascape = XrmStringToQuark(XtEseascape);
- haveQuarks = 1;
- }
-
- XmuCopyISOLatin1Lowered(lowerName, str);
-
- q = XrmStringToQuark(lowerName);
-
- if (q == XrmQEportrait)
- done(XtPageOrientation, XtPageOrientationPortrait);
- if (q == XrmQElandscape)
- done(XtPageOrientation, XtPageOrientationLandscape);
- if (q == XrmQEupsideDown)
- done(XtPageOrientation, XtPageOrientationUpsideDown);
- if (q == XrmQEseascape)
- done(XtPageOrientation, XtPageOrientationSeascape);
-
- XtDisplayStringConversionWarning(dpy, str, XtRPageOrientation);
- return False;
- }
-
- /* Palette Conversion Routine.
- * Returns True if Conversion is successful.
- */
- Boolean
- XmuCvtStringToPalette(dpy, args, num_args, fromVal, toVal, data)
- Display *dpy;
- XrmValue *args; /* unused */
- Cardinal *num_args; /* unused */
- XrmValue *fromVal;
- XrmValue *toVal;
- XtPointer *data; /* unused */
- {
- static XrmQuark XrmQEmonochrome;
- static XrmQuark XrmQEgrayscale;
- static XrmQuark XrmQEcolor;
- static int haveQuarks;
- XrmQuark q;
- char *str = (XPointer) fromVal->addr;
- char lowerName[1000];
-
- if (str == NULL) return False;
-
- if (!haveQuarks) {
- XrmQEmonochrome = XrmStringToQuark(XtEmonochrome);
- XrmQEgrayscale = XrmStringToQuark(XtEgrayscale);
- XrmQEcolor = XrmStringToQuark(XtEcolor);
- haveQuarks = 1;
- }
-
- XmuCopyISOLatin1Lowered(lowerName, str);
-
- q = XrmStringToQuark(lowerName);
-
- if (q == XrmQEmonochrome)
- done(XtPalette, XtPaletteMonochrome);
- if (q == XrmQEgrayscale)
- done(XtPalette, XtPaletteGrayscale);
- if (q == XrmQEcolor)
- done(XtPalette, XtPaletteColor);
-
- XtDisplayStringConversionWarning(dpy, str, XtRPalette);
- return False;
- }
-
- #ifdef VMS
-
- /*
- ** VMS specific include files
- */
- #include <descrip.h>
- #include <ssdef.h>
- #include <clidef.h>
- #include <lnmdef.h>
- #include <iodef.h>
- #include <dvidef.h>
- #include "vms_types.h"
-
- #define ERR_SIGNAL(s) if(!((s) & 1))lib$signal((s), 0, 0)
- #define XtEFN 23
-
- struct g_l_i
- {
- GhostviewWidget w;
- struct g_l_i *next;
- };
-
- typedef struct g_l_i GhostListItem, *GLI_p;
-
- static GhostListItem glhead = {(GhostviewWidget) -1, NULL};
- static GLI_p GL = &glhead;
- static size_t GLI_Size = sizeof(GhostListItem);
- static XtInputId EventId;
-
- /*
- ** This routine is passed to XtAppAddInput(). It is called whenever the event
- ** flag number XtEFN is set and the Xt main loop becomes idle. It clears the
- ** event flag and then scans all the ghostview widgets for completed I/O
- ** requests, processing each as they are found. We have to do them all because
- ** there is no way to have Xt dispatch them individually without a window of
- ** vulnerability that can cause missed events, or by using a separate event
- ** flag for each I/O stream. Event flags are, unfortunately, a limited
- ** resource.
- */
- static Boolean
- IOProcess()
- {
- GhostviewWidget gvw;
- GLI_p cur;
-
- /*
- ** Before we process any I/O's, clear the event flag.
- */
- sys$clref(XtEFN);
- /*
- ** Scan all the ghostview widgets and check for completed I/O's
- */
- for(cur = GL->next; cur; cur = cur->next){
- /*
- ** Get the widget and check for I/O complete on either mailbox.
- */
- gvw = cur->w;
- if(gvw->ghostview.interpreter_input_iosb[0])Input(gvw);
- if(gvw->ghostview.interpreter_output_iosb[0])Output(gvw);
- }
- }
-
- /*
- ** This is an AST routine. It is called asynchronously whenever one of our
- ** mailbox I/O's completes.
- */
- static void
- IOComplete(client_data)
- XtPointer client_data;
- {
- /*
- ** Set the event flag to tell Xt to call IOProcess.
- */
- sys$setef(XtEFN);
- }
-
- static void
- GLInsert(w)
- GhostviewWidget w;
- {
- GLI_p new;
- int first;
-
- /*
- ** Insert this widget after the list head
- */
- first = (GL->next == NULL);
- new = XtMalloc(GLI_Size);
- new->w = w;
- new->next = GL->next;
- GL->next = new;
- /*
- ** If this is the first item on the list, call XtAppAddInput()
- */
- if(first)EventId = XtAppAddInput(XtWidgetToApplicationContext(w), XtEFN, 0,
- IOProcess, 0);
- }
-
- static void
- GLRemove(w)
- GhostviewWidget w;
- {
- GLI_p prev, cur;
- int last = 0;
-
- /*
- ** Find and remove this widget from the list.
- */
- prev = GL;
- cur = prev->next;
- while(cur && cur->w != w){
- prev = cur;
- cur = cur->next;
- }
- if(cur){
- prev->next = cur->next;
- XtFree(cur);
- last = (GL->next == NULL);
- }
- /*
- ** If this was the last item on the list, call XtRemoveInput()
- */
- if(last)XtRemoveInput(EventId);
- }
-
- /* Input - Feed data to ghostscript's stdin.
- * Write bytes to ghostscript using non-blocking I/O.
- * Also, pipe signals are caught during writing. The return
- * values are checked and the appropriate action is taken. I do
- * this at this low level, because it may not be appropriate for
- * SIGPIPE to be caught for the overall application.
- */
-
- static void
- Input(gvw)
- GhostviewWidget gvw;
- {
- int stat, bbytes;
- char *ch;
-
- /*
- ** Check for error on previous I/O.
- */
- stat = gvw->ghostview.interpreter_input_iosb[0];
- if(stat != SS$_NORMAL){
- InterpreterFailed(gvw);
- } else {
-
- /* Get a new section if required */
-
- if (gvw->ghostview.ps_input && gvw->ghostview.bytes_left == 0) {
- struct record_list *ps_old = gvw->ghostview.ps_input;
- gvw->ghostview.ps_input = ps_old->next;
- if (ps_old->close) fclose(ps_old->fp);
- XtFree((char *)ps_old);
- }
- if(gvw->ghostview.ps_input){
- /* Have to seek at the beginning of each section */
- if (gvw->ghostview.ps_input->seek_needed) {
- if (gvw->ghostview.ps_input->len > 0)
- fseek(gvw->ghostview.ps_input->fp,
- gvw->ghostview.ps_input->begin, SEEK_SET);
- gvw->ghostview.ps_input->seek_needed = False;
- gvw->ghostview.bytes_left = gvw->ghostview.ps_input->len;
- }
- /*
- ** Read a line from the file.
- */
- ch = fgets(gvw->ghostview.input_buffer, GV_BUFSIZ,
- gvw->ghostview.ps_input->fp);
- if(!ch){
- /*
- ** Error, EOF when there's supposed to be data left.
- */
- InterpreterFailed(gvw);
- } else {
- /*
- ** Write it to the mailbox.
- */
- bbytes = strlen(gvw->ghostview.input_buffer);
- gvw->ghostview.bytes_left -= bbytes;
- stat = sys$qio(0, (short)gvw->ghostview.interpreter_input,
- IO$_WRITEVBLK, &gvw->ghostview.interpreter_input_iosb,
- IOComplete, 0, gvw->ghostview.input_buffer, bbytes,
- 0, 0, 0, 0);
- ERR_SIGNAL(stat);
- }
- }
- }
- }
-
- /* Output - receive I/O from ghostscript's stdout and stderr.
- * Pass this to the application via the output_callback. */
- static void
- Output(gvw)
- GhostviewWidget gvw;
- {
- char buf[GV_BUFSIZ+1];
- int bytes, stat;
-
- stat = gvw->ghostview.interpreter_output_iosb[0];
- bytes = gvw->ghostview.interpreter_output_iosb[1];
- if (stat == SS$_NORMAL) {
- /*
- ** Got a message. If line complete, pass to the output_callback.
- **
- ** HACK ALERT, if bytes is -1 nothing happens, but an I/O is queued.
- ** This is our first time code, since Xt doesn't queue the I/O for us
- ** under VMS, just watches for completion. In StartInterpreter We setup
- ** an IOSB with a success status and -1 bytes so Xt will call us the
- ** first time to get the I/O queued.
- */
- if (bytes == 0) {
- strcpy(buf, "\n");
- } else if (bytes == 1) {
- buf[0] = gvw->ghostview.output_buffer[0];
- buf[1] = '\0';
- } else if (bytes > 1) {
- /*
- ** Copy the message to a local buffer and pass it to the callback.
- */
- memcpy(buf, gvw->ghostview.output_buffer, bytes);
- buf[bytes] = '\0';
- }
- if(bytes >= 0)XtCallCallbackList(gvw, gvw->ghostview.output_callback,
- (XtPointer) buf);
- /*
- ** Queue a new read to the mailbox
- */
- stat = sys$qio(0, (short)gvw->ghostview.interpreter_output,
- IO$_READVBLK, &gvw->ghostview.interpreter_output_iosb, IOComplete,
- 0, gvw->ghostview.output_buffer, GV_BUFSIZ, 0, 0, 0, 0);
- ERR_SIGNAL(stat);
- } else {
- InterpreterFailed(gvw); /* Something bad happened */
- }
- }
-
- /* This routine starts the interpreter. It sets the DISPLAY and
- * GHOSTVIEW environment variables. The GHOSTVIEW environment variable
- * contains the Window that ghostscript should write on.
- *
- * This routine also opens pipes for stdout and stderr and initializes
- * application input events for them. If input to ghostscript is not
- * from a file, a pipe for stdin is created. This pipe is setup for
- * non-blocking I/O so that the user interface never "hangs" because of
- * a write to ghostscript.
- */
- static void
- StartInterpreter(w)
- Widget w;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- char buf[GV_BUFSIZ];
- char cmd[512];
- int ret;
- short ch1, ch2;
- char in_mbx_name[65], out_mbx_name[65];
- long pid, nowait = CLI$M_NOWAIT;
- const $DESCRIPTOR(ghostview_desc, "GHOSTVIEW");
- const $DESCRIPTOR(display_desc, "DECW$DISPLAY");
- const $DESCRIPTOR(lnt_desc, "LNM$PROCESS");
- $DESCRIPTOR(in_desc, "");
- $DESCRIPTOR(out_desc, "");
- $DESCRIPTOR(lnm_desc, "");
- $DESCRIPTOR(cmd_desc, cmd);
- ITEM_LIST_3_T(gv_list, 1) = {{{0, LNM$_STRING, buf, NULL}}, 0};
- ITEM_LIST_3_T(dis_list, 1) = {{{0, LNM$_STRING, NULL, NULL}}, 0};
- ITEM_LIST_3_T(dvi_list, 1) = {{{64, DVI$_DEVNAM, NULL, NULL}}, 0};
- IOSB_GET_T dvi_iosb;
-
- /*
- ** Stop interpreter if running
- */
- StopInterpreter(w);
- /*
- ** Clear the window before starting a new interpreter.
- */
- if (gvw->core.background_pixmap != XtUnspecifiedPixmap) {
- XFillRectangle(XtDisplay(w), gvw->core.background_pixmap,
- gvw->ghostview.gc,
- 0, 0, gvw->core.width, gvw->core.height);
- }
- XClearArea(XtDisplay(w), XtWindow(w),
- 0, 0, gvw->core.width, gvw->core.height, False);
- /*
- ** Check for disabled.
- */
- if (gvw->ghostview.disable_start) return;
- /*
- ** Build Ghostscript startup command
- */
- strcpy(cmd, gvw->ghostview.interpreter);
- strcat(cmd, " \"-sDEVICE=x11\" \"-dNOPAUSE\" ");
- if (gvw->ghostview.quiet) strcat(cmd, "\"-dQUIET\" ");
- if (gvw->ghostview.safer) strcat(cmd, "\"-dSAFER\" ");
- if (gvw->ghostview.arguments) {
- strcat(cmd, gvw->ghostview.arguments);
- strcat(cmd, " ");
- }
- strcat(cmd, "\"-\" ");
-
- /*
- ** Determine input source.
- */
- if (gvw->ghostview.filename == NULL) {
- /*
- ** Create a mailbox to feed input to Ghostscript and get its name.
- */
- ret = sys$crembx(0, &ch1, GV_BUFSIZ, GV_BUFSIZ, 0, 0, 0, 0);
- ERR_SIGNAL(ret);
- dvi_list.item[0].buffer_p = in_mbx_name;
- ret = sys$getdvi(0, ch1, 0, &dvi_list, &dvi_iosb, 0, 0, 0);
- ERR_SIGNAL(ret); ERR_SIGNAL(dvi_iosb.status);
- in_mbx_name[64] = '\0';
- in_desc.dsc$a_pointer = in_mbx_name;
- in_desc.dsc$w_length = strlen(in_mbx_name);
- } else {
- /*
- ** Set up file name to give Ghostscript as standard input.
- */
- in_desc.dsc$a_pointer = gvw->ghostview.filename;
- in_desc.dsc$w_length = strlen(gvw->ghostview.filename);
- }
- /*
- ** Create mailbox to receive Ghostscript's output
- */
- ret = sys$crembx(0, &ch2, GV_BUFSIZ, GV_BUFSIZ, 0, 0, 0, 0);
- ERR_SIGNAL(ret);
- dvi_list.item[0].buffer_p = out_mbx_name;
- ret = sys$getdvi(0, ch2, 0, &dvi_list, &dvi_iosb, 0, 0, 0);
- ERR_SIGNAL(ret); ERR_SIGNAL(dvi_iosb.status);
- out_mbx_name[64] = '\0';
- out_desc.dsc$a_pointer = out_mbx_name;
- out_desc.dsc$w_length = strlen(out_mbx_name);
- /*
- ** Create GHOSTVIEW and DECW$DISPLAY logical names.
- **
- ** We use CRELNM rather than LIB$SET_LOGICAL because we want these to be
- ** user mode and go away when the program exits. It doesn't matter that we
- ** may set them multiple times, as with the mailbox logicals, since once
- ** Ghostscript starts we don't need them any more.
- */
- sprintf(buf, "%d", XtWindow(w));
- gv_list.item[0].buffer_size = strlen(buf);
- ret = sys$crelnm(0, &lnt_desc, &ghostview_desc, 0, &gv_list);
- ERR_SIGNAL(ret);
- dis_list.item[0].buffer_p = XDisplayString(XtDisplay(w));
- dis_list.item[0].buffer_size = strlen(dis_list.item[0].buffer_p);
- ret = sys$crelnm(0, &lnt_desc, &display_desc, 0, &dis_list);
- ERR_SIGNAL(ret);
- /*
- ** Spawn Ghostscript process
- */
- gvw->ghostview.changed = False;
- gvw->ghostview.busy = True;
- cmd_desc.dsc$w_length = strlen(cmd);
- ret = lib$spawn(&cmd_desc, &in_desc, &out_desc, &nowait, 0, &pid, 0, 0,
- 0, 0, 0, 0, 0);
- ERR_SIGNAL(ret);
- XDefineCursor(XtDisplay(gvw), XtWindow(gvw), gvw->ghostview.busy_cursor);
- /*
- ** Everything worked, initialize IOSBs and save info about interpretter.
- */
- gvw->ghostview.interpreter_pid = pid;
- if (gvw->ghostview.filename == NULL) {
- gvw->ghostview.interpreter_input = ch1;
- gvw->ghostview.interpreter_input_iosb[0] = 0;
- }
- gvw->ghostview.interpreter_output = ch2;
- if (gvw->ghostview.output_buffer == NULL) {
- gvw->ghostview.output_buffer = XtMalloc(GV_BUFSIZ);
- }
- GLInsert(gvw);
- /*
- ** Fake a completed I/O so Output will get called to queue the first I/O.
- */
- gvw->ghostview.interpreter_output_iosb[0] = SS$_NORMAL;
- gvw->ghostview.interpreter_output_iosb[1] = -1;
- IOComplete();
- }
-
- /* Stop the interperter, if present, and remove any Input sources. */
- /* Also reset the busy state. */
- static void
- StopInterpreter(w)
- Widget w;
- {
- int ret;
-
- GhostviewWidget gvw = (GhostviewWidget) w;
- if (gvw->ghostview.interpreter_pid >= 0) {
- ret = sys$delprc(&gvw->ghostview.interpreter_pid, 0);
- if(ret != SS$_NORMAL && ret != SS$_NONEXPR)lib$signal(ret, 0, 0);
- gvw->ghostview.interpreter_pid = -1;
- }
- if (gvw->ghostview.interpreter_input >= 0) {
- (void) sys$dassgn(gvw->ghostview.interpreter_input);
- gvw->ghostview.interpreter_input = -1;
- while (gvw->ghostview.ps_input) {
- struct record_list *ps_old = gvw->ghostview.ps_input;
- gvw->ghostview.ps_input = ps_old->next;
- if (ps_old->close) fclose(ps_old->fp);
- XtFree((char *)ps_old);
- }
- }
- if (gvw->ghostview.interpreter_output >= 0) {
- (void) sys$dassgn(gvw->ghostview.interpreter_output);
- gvw->ghostview.interpreter_output = -1;
- }
- gvw->ghostview.busy = False;
- XDefineCursor(XtDisplay(gvw), XtWindow(gvw), gvw->ghostview.cursor);
- GLRemove(gvw);
- }
-
- /* GhostviewSendPS:
- * Queue a portion of a PostScript file for output to ghostscript.
- * fp: FILE * of the file in question. NOTE: if you have several
- * Ghostview widgets reading from the same file. You must open
- * a unique FILE * for each widget.
- * SendPS does not actually send the PostScript, it merely queues it
- * for output.
- * begin: position in file (returned from ftell()) to start.
- * len: number of bytes to write.
- *
- * If an interpreter is not running, nothing is queued and
- * False is returned.
- */
- Boolean
- GhostviewSendPS(w, fp, begin, len, close)
- Widget w;
- FILE *fp;
- long begin;
- unsigned int len;
- Bool close;
- {
- GhostviewWidget gvw = (GhostviewWidget) w;
- struct record_list *ps_new;
-
- if (gvw->ghostview.interpreter_input < 0) return False;
- if(len != 0){
- ps_new = (struct record_list *) XtMalloc(sizeof (struct record_list));
- ps_new->fp = fp;
- ps_new->begin = begin;
- ps_new->len = len;
- ps_new->seek_needed = True;
- ps_new->close = close;
- ps_new->next = NULL;
-
- if (gvw->ghostview.input_buffer == NULL) {
- gvw->ghostview.input_buffer = XtMalloc(GV_BUFSIZ);
- }
-
- if (gvw->ghostview.ps_input == NULL) {
- gvw->ghostview.bytes_left = len;
- gvw->ghostview.ps_input = ps_new;
- /*
- ** Fake a completed I/O so Input will get called to queue the
- ** first I/O.
- */
- gvw->ghostview.interpreter_input_iosb[0] = SS$_NORMAL;
- gvw->ghostview.interpreter_input_iosb[1] = -1;
- IOComplete();
- } else {
- struct record_list *p = gvw->ghostview.ps_input;
- while (p->next != NULL) {
- p = p->next;
- }
- p->next = ps_new;
- }
- }
- return True;
- }
- #endif /* VMS */
-