diff -N -u ghostview-1.3/Dir.c ghostview-1.4/Dir.c --- ghostview-1.3/Dir.c Wed Apr 15 09:15:45 1992 +++ ghostview-1.4/Dir.c Thu Oct 1 14:04:22 1992 @@ -120,7 +120,7 @@ return 1; } - (void) fstat(dirp->dd_fd, &statBuf); + (void) stat(".", &statBuf); dir->mtime = statBuf.st_mtime; (void) readdir(dirp); /* throw away "." */ diff -N -u ghostview-1.3/Ghostview.ad ghostview-1.4/Ghostview.ad --- ghostview-1.3/Ghostview.ad Fri May 8 10:01:36 1992 +++ ghostview-1.4/Ghostview.ad Thu Oct 1 14:08:39 1992 @@ -36,6 +36,7 @@ *quit.Label: Quit *fileButton.Label: File *open.Label: Open... +*reopen.Label: Reopen *printwhole.Label: Print... *printmarked.Label: Print marked pages... *save.Label: Save marked pages... @@ -138,6 +139,7 @@ C: GhostviewCenter() \n\ Q: GhostviewQuit() \n\ O: GhostviewOpen() \n\ + R: GhostviewReopen() \n\ S: GhostviewSave() \n\ ShiftP: GhostviewPrintWhole() \n\ P: GhostviewPrintMarked() \n\ @@ -150,7 +152,6 @@ F: GhostviewNext() \n\ Next: GhostviewNext() \n\ period: GhostviewShow() \n\ - R: GhostviewShow() \n\ CtrlL: GhostviewShow() \n\ M: GhostviewMark() \n\ N: GhostviewUnmark() \n\ @@ -180,6 +181,7 @@ C: GhostviewCenter() \n\ Q: GhostviewQuit() \n\ O: GhostviewOpen() \n\ + R: GhostviewReopen() \n\ S: GhostviewSave() \n\ ShiftP: GhostviewPrintWhole() \n\ P: GhostviewPrintMarked() \n\ @@ -192,7 +194,6 @@ F: GhostviewNext() \n\ Next: GhostviewNext() \n\ period: GhostviewShow() \n\ - R: GhostviewShow() \n\ CtrlL: GhostviewShow() \n\ M: GhostviewMark() \n\ N: GhostviewUnmark() \n\ diff -N -u ghostview-1.3/Ghostview.c ghostview-1.4/Ghostview.c --- ghostview-1.3/Ghostview.c Tue May 12 20:20:42 1992 +++ ghostview-1.4/Ghostview.c Sun Oct 11 15:36:11 1992 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "GhostviewP.h" #include @@ -61,12 +62,17 @@ #define EAGAIN EWOULDBLOCK #endif -/* GV_BUFSIZ is set to the minimum POSIX PIPE_MAX to ensure that +#ifndef VMS +/* GV_BUFSIZ is set to the minimum POSIX PIPE_BUF to ensure that * nonblocking writes to ghostscript will work properly. - * GV_BUFSIZ must be 257 or greater to be able to read the largest - * PostScript input line allowed. (257 <= GV_BUFSIZ <= 512) */ #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 */ /* length calculates string length at compile time */ /* can only be used with character constants */ @@ -127,7 +133,6 @@ static void Message(); static void Notify(); static void Input(); -static void WriteBytes(); static void Output(); static void ClassInitialize(); @@ -351,7 +356,27 @@ #define SEEK_SET 0 #endif -/* Input - Feed data to ghostscript's stdin. */ +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) @@ -361,175 +386,83 @@ { Widget w = (Widget) client_data; GhostviewWidget gvw = (GhostviewWidget) w; - char *ret; - Boolean binary; + int bytes_written; + SIGVAL (*oldsig)(); - /* Have to seek at the beginning of each section */ + oldsig = signal(SIGPIPE, CatchPipe); - if (gvw->ghostview.ps_input->seek_needed) { - fseek(gvw->ghostview.ps_input->fp, gvw->ghostview.ps_input->begin, - SEEK_SET); - gvw->ghostview.ps_input->seek_needed = False; - gvw->ghostview.check_line = False; - } +#ifdef NON_BLOCKING_IO + do { +#endif - /* Complete any partially written records */ + if (gvw->ghostview.buffer_bytes_left == 0) { - if (gvw->ghostview.bytes_left > 0) { - WriteBytes(w); - } else { - - /* if no partially written records, get binary mode data if available - * and write that */ - if (gvw->ghostview.binary_bytes_left > 0) { - if (gvw->ghostview.binary_bytes_left > GV_BUFSIZ) { - gvw->ghostview.bytes_left = + /* 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 { - gvw->ghostview.bytes_left = + } else if (gvw->ghostview.bytes_left > 0) { + gvw->ghostview.buffer_bytes_left = fread(gvw->ghostview.input_buffer, - sizeof (char), gvw->ghostview.binary_bytes_left, + sizeof (char), gvw->ghostview.bytes_left, gvw->ghostview.ps_input->fp); - } - if (gvw->ghostview.bytes_left == 0) { /* Error occurred */ - InterpreterFailed(w); - return; + } else { + gvw->ghostview.buffer_bytes_left = 0; } - gvw->ghostview.input_buffer_ptr = gvw->ghostview.input_buffer; - WriteBytes(w); - } else if (gvw->ghostview.binary_lines_left > 0) { - ret = fgets(gvw->ghostview.input_buffer, GV_BUFSIZ, - gvw->ghostview.ps_input->fp); - if (ret == NULL) { /* Error occurred */ - InterpreterFailed(w); - return; + if (gvw->ghostview.bytes_left > 0 && + gvw->ghostview.buffer_bytes_left == 0) { + InterpreterFailed(w); /* Error occurred */ } - gvw->ghostview.bytes_left = strlen(gvw->ghostview.input_buffer); gvw->ghostview.input_buffer_ptr = gvw->ghostview.input_buffer; - WriteBytes(w); - } - } - - /* Check to see if we are still doing a binary mode copy */ - - binary = gvw->ghostview.binary_bytes_left > 0 || - gvw->ghostview.binary_lines_left > 0; - - /* The following is done in text mode copy after a full line has - * been written */ - if (!binary && (gvw->ghostview.bytes_left == 0)) { - - /* Check for end of section. If so, pop the section record - * off the ps_input list. If no input left, remove the input - * event from the application */ - if (ftell(gvw->ghostview.ps_input->fp) == - gvw->ghostview.ps_input->end) { - 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 == NULL) { - XtRemoveInput(gvw->ghostview.interpreter_input_id); - gvw->ghostview.interpreter_input_id = None; - } - return; + gvw->ghostview.bytes_left -= gvw->ghostview.buffer_bytes_left; } - /* If at least one line was written from the current section, - * check to see if it is the beginning of a binary section. - * If so, set the binary_{bytes|lines}_left and return. Binary - * output commences on next call to this routine. - */ - if (gvw->ghostview.check_line) { - gvw->ghostview.check_line = False; - if (!iscomment(gvw->ghostview.input_buffer, "%%")) { - /* Do nothing */ - } else if (iscomment(gvw->ghostview.input_buffer+2, "BeginData:")) { - char text[GV_BUFSIZ]; - sscanf(gvw->ghostview.input_buffer+length("%%BeginData:"), - "%d %*s %s", &(gvw->ghostview.binary_bytes_left), text); - if (strcmp(text, "Lines") == 0) { - gvw->ghostview.binary_lines_left = - gvw->ghostview.binary_bytes_left; - gvw->ghostview.binary_bytes_left = 0; + 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 */ } - return; - } else if (iscomment(gvw->ghostview.input_buffer+2, - "BeginBinary:")) { - sscanf(gvw->ghostview.input_buffer+length("%%BeginBinary:"), - "%d", &(gvw->ghostview.binary_bytes_left)); - return; + } else { + gvw->ghostview.buffer_bytes_left -= bytes_written; + gvw->ghostview.input_buffer_ptr += bytes_written; } } - - /* If not at the end of section, or in a binary section, read a - * line and the write it. Set check_line flag to check for - * %%BeginBinary/%%BeginData next time */ - ret = fgets(gvw->ghostview.input_buffer, GV_BUFSIZ, - gvw->ghostview.ps_input->fp); - if (ret == NULL) { /* Error occurred */ - InterpreterFailed(w); - return; - } - gvw->ghostview.check_line = True; - gvw->ghostview.bytes_left = strlen(gvw->ghostview.input_buffer); - gvw->ghostview.input_buffer_ptr = gvw->ghostview.input_buffer; - WriteBytes(w); - } -} - -static Boolean broken_pipe = False; - -static SIGVAL -CatchPipe(i) - int i; -{ - broken_pipe = True; -#ifdef SIGNALRETURNSINT - return 0; +#ifdef NON_BLOCKING_IO + } while(gvw->ghostview.ps_input && + gvw->ghostview.buffer_bytes_left == 0); #endif -} - -/* WriteBytes - 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 -WriteBytes(w) - Widget w; -{ - GhostviewWidget gvw = (GhostviewWidget) w; - int bytes; - SIGVAL (*oldsig)(); - - oldsig = signal(SIGPIPE, CatchPipe); - bytes = write(gvw->ghostview.interpreter_input, - gvw->ghostview.input_buffer_ptr, - gvw->ghostview.bytes_left); signal(SIGPIPE, oldsig); - - if (broken_pipe) { - broken_pipe = False; - InterpreterFailed(w); /* Something bad happened */ - return; - } else if (bytes == -1) { - if ((errno != EWOULDBLOCK) && (errno != EAGAIN)) { - InterpreterFailed(w); /* Something bad happened */ - return; - } - } else { - gvw->ghostview.bytes_left -= bytes; - gvw->ghostview.input_buffer_ptr += bytes; - if (gvw->ghostview.binary_bytes_left > 0) { - gvw->ghostview.binary_bytes_left -= bytes; - } - if ((gvw->ghostview.binary_lines_left > 0) && - (gvw->ghostview.bytes_left == 0)) { - gvw->ghostview.binary_lines_left -= 1; + 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; } } } @@ -576,6 +509,8 @@ } } +#endif /* VMS */ + /* Register the type converter required for the PageOrientation. */ /* This routine is called exactly once. */ static void @@ -619,18 +554,24 @@ ngvw->ghostview.disable_start = False; ngvw->ghostview.interpreter_pid = -1; ngvw->ghostview.input_buffer = NULL; - ngvw->ghostview.input_buffer_ptr = NULL; ngvw->ghostview.bytes_left = 0; - ngvw->ghostview.binary_bytes_left = 0; - ngvw->ghostview.binary_lines_left = 0; +#ifndef VMS + ngvw->ghostview.input_buffer_ptr = NULL; + ngvw->ghostview.buffer_bytes_left = 0; +#endif ngvw->ghostview.ps_input = NULL; - ngvw->ghostview.check_line = False; ngvw->ghostview.interpreter_input = -1; - ngvw->ghostview.interpreter_input_id = None; ngvw->ghostview.interpreter_output = -1; - ngvw->ghostview.interpreter_output_id = None; +#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; @@ -670,6 +611,9 @@ 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); } @@ -978,6 +922,25 @@ 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; + 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(). @@ -1006,22 +969,37 @@ 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) { - gvw->core.background_pixmap = XCreatePixmap(XtDisplay(w), - XtWindow(w), - gvw->core.width, - gvw->core.height, - gvw->core.depth); - XSetWindowBackgroundPixmap(XtDisplay(w), XtWindow(w), - gvw->core.background_pixmap); + /* Get a Backing Pixmap, but be ready for the BadAlloc. */ + 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; } - bpixmap = gvw->core.background_pixmap; - xswa.backing_store = NotUseful; - XChangeWindowAttributes(XtDisplay(w), XtWindow(w), - CWBackingStore, &xswa); } else { if (gvw->core.background_pixmap != XtUnspecifiedPixmap) { XFreePixmap(XtDisplay(w), gvw->core.background_pixmap); @@ -1029,6 +1007,13 @@ 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); @@ -1053,6 +1038,8 @@ 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. @@ -1082,7 +1069,7 @@ StopInterpreter(w); /* Clear the window before starting a new interpreter. */ - if (gvw->ghostview.use_bpixmap) { + if (gvw->core.background_pixmap != XtUnspecifiedPixmap) { XFillRectangle(XtDisplay(w), gvw->core.background_pixmap, gvw->ghostview.gc, 0, 0, gvw->core.width, gvw->core.height); @@ -1233,6 +1220,8 @@ XDefineCursor(XtDisplay(gvw), XtWindow(gvw), gvw->ghostview.cursor); } +#endif /* VMS */ + /* The interpeter failed, Stop what's left and notify application */ static void InterpreterFailed(w) @@ -1296,17 +1285,6 @@ return gvw->ghostview.interpreter_pid != -1; } -/* GhostviewGetInputFileDescriptor: - * Returns the file descriptor used to send input to ghostscript. - */ -int -GhostviewGetInputFileDescriptor(w) - Widget w; -{ - GhostviewWidget gvw = (GhostviewWidget) w; - return(gvw->ghostview.interpreter_input); -} - /* GhostviewGetBackingPixmap: * Returns the current backing pixmap. */ @@ -1321,6 +1299,8 @@ 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 @@ -1329,16 +1309,17 @@ * SendPS does not actually send the PostScript, it merely queues it * for output. * begin: position in file (returned from ftell()) to start. - * end: position in file (returned from ftell()) to stop. + * len: number of bytes to write. * * If an interpreter is not running, nothing is queued and * False is returned. */ Boolean -GhostviewSendPS(w, fp, begin, end, close) +GhostviewSendPS(w, fp, begin, len, close) Widget w; FILE *fp; - long begin, end; + long begin; + unsigned int len; Bool close; { GhostviewWidget gvw = (GhostviewWidget) w; @@ -1348,7 +1329,7 @@ ps_new = (struct record_list *) XtMalloc(sizeof (struct record_list)); ps_new->fp = fp; ps_new->begin = begin; - ps_new->end = end; + ps_new->len = len; ps_new->seek_needed = True; ps_new->close = close; ps_new->next = NULL; @@ -1359,9 +1340,8 @@ if (gvw->ghostview.ps_input == NULL) { gvw->ghostview.input_buffer_ptr = gvw->ghostview.input_buffer; - gvw->ghostview.bytes_left = 0; - gvw->ghostview.binary_bytes_left = 0; - gvw->ghostview.binary_lines_left = 0; + 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), @@ -1377,6 +1357,8 @@ return True; } +#endif /* VMS */ + /* GhostviewNextPage: * Tell ghostscript to start the next page. * Returns False if ghostscript is not running, or not ready to start @@ -1477,3 +1459,478 @@ XtDisplayStringConversionWarning(dpy, str, XtRPageOrientation); return False; } + +#ifdef VMS + +/* +** VMS specific include files +*/ +#include +#include +#include +#include +#include +#include +#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, " "); + if (gvw->ghostview.quiet) strcat(cmd, "\"-dQUIET\" "); + strcat(cmd, "\"-dNOPAUSE\" "); + if (gvw->ghostview.preload) { + strcat(cmd, gvw->ghostview.preload); + 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 */ diff -N -u ghostview-1.3/Ghostview.h ghostview-1.4/Ghostview.h --- ghostview-1.3/Ghostview.h Fri May 8 10:01:36 1992 +++ ghostview-1.4/Ghostview.h Mon Sep 21 19:34:46 1992 @@ -158,12 +158,6 @@ #endif ); -extern int GhostviewGetInputFileDescriptor( -#if NeedFunctionPrototypes - Widget /* w */ -#endif -); - extern Pixmap GhostviewGetBackingPixmap( #if NeedFunctionPrototypes Widget /* w */ @@ -175,7 +169,7 @@ Widget /* widget */, FILE* /* fp */, long /* begin */, - long /* end */, + unsigned int /* len */, Bool /* close */ #endif ); diff -N -u ghostview-1.3/GhostviewP.h ghostview-1.4/GhostviewP.h --- ghostview-1.3/GhostviewP.h Wed Apr 15 09:15:45 1992 +++ ghostview-1.4/GhostviewP.h Mon Sep 21 19:45:06 1992 @@ -48,7 +48,8 @@ /* structure to describe section of file to send to ghostscript */ struct record_list { FILE *fp; - long begin, end; + long begin; + unsigned int len; Boolean seek_needed; Boolean close; struct record_list *next; @@ -82,19 +83,25 @@ Window mwin; /* destination of ghostsript messages */ Boolean disable_start; /* whether to fork ghostscript */ int interpreter_pid;/* pid of ghostscript, -1 if none */ + struct record_list *ps_input; /* pointer it gs input queue */ char *input_buffer; /* pointer to input buffer */ + unsigned int bytes_left; /* bytes left in section */ +#ifndef VMS char *input_buffer_ptr; /* pointer into input buffer */ - int bytes_left; /* bytes left in buffer */ - unsigned int binary_bytes_left; /* bytes left in binary section */ - unsigned int binary_lines_left; /* lines left in binary section */ - struct record_list *ps_input; /* pointer it gs input queue */ - Boolean check_line; /* check buffer for %%BeginBinary:? */ + unsigned int buffer_bytes_left; /* bytes left in buffer */ +#endif int interpreter_input; /* fd gs stdin, -1 if None */ - XtInputId interpreter_input_id; /* XtInputId for above */ int interpreter_output; /* fd gs stdout, -1 if None */ - XtInputId interpreter_output_id; /* XtInputId for above */ +#ifndef VMS int interpreter_error; /* fd gs stderr, -1 if None */ + XtInputId interpreter_input_id; /* XtInputId for above */ + XtInputId interpreter_output_id; /* XtInputId for above */ XtInputId interpreter_error_id; /* XtInputId for above */ +#else /* VMS */ + short interpreter_input_iosb[4]; /* I/O Status Blocks */ + short interpreter_output_iosb[4]; /* for each mailbox */ + char *output_buffer; /* pointer to output buffer */ +#endif /* VMS */ Dimension gs_width; /* Width of window at last Setup() */ Dimension gs_height; /* Height of window at last Setup() */ Boolean busy; /* Is gs busy drawing? */ diff -N -u ghostview-1.3/HISTORY ghostview-1.4/HISTORY --- ghostview-1.3/HISTORY Tue May 12 21:58:34 1992 +++ ghostview-1.4/HISTORY Sun Oct 11 15:27:32 1992 @@ -1,3 +1,69 @@ +==================== ghostview 1.4 (11 Oct 92) ===================== + + 1. Merge in VMS support from Terry Poot . + + 2. Force the Alloc error to occur immediately after trying to allocate + the backing pixmap. Deal with it as best as we can. + + 3. Withdraw unused function GhostviewGetInputFileDescriptor(). + + 4. Use XCOMM trick from X11R5 to make Imakefile more portable. + + 5. Renamed ghostview.h to gv.h and Ghostview.ad.h to app-defaults.h to + avoid limitations in VMS file names. + + 6. Correct problem where ghostscript interpreter was not being killed + when the popup zoom window was dismissed. + + 7. Propagate error messages about alloc failures and interpreter failures + in both main and zoom windows back to the information window. + + 8. Catch X errors and gracefully die if one occurs. + + 9. Relayout ghostview whenever the document requests a new orientation or + page media. + +10. Allow for multipage encapsulated PostScript figures. + +11. More upgrades to PostScript scanner. + - Comment section now terminated by %X where X is unprintable. + - Length of section is now properly computed when there is an + included document. + - Cleaned up misuse of global variables. + - Ignore comments within %%Begin(End)Feature, %%Begin(End)File, + %%Begin(End)Font, %%Begin(End)ProcSet, %%Begin(End)Resource. + - Change enum {LLX, LLY, URX, URY} to #defines to avoid confusing some + compilers. + +12. Pay attention to ordinal number on %%Page comment to detect included + figures without %%Begin(End)Document guards. + +13. Added reopen button. + +14. Small POSIX change in Dir.c + +15. Make installStdCmap false by default. + +16. Fix error where wrong pages were being saved or printed when descending + page order is used. + +17. Be sure to discard old backing pixmap if new alloc fails. + +==================== ghostview 1.3-terry (30 May 92) ===================== + + 1. Rework the DSC comment scanner to return the length of the section as + well as the start and end position. + + 2. Rework sending PostScript input down the pipe to eliminate a gross + efficiency problem. I/O is done in 512 byte buffers rather than + line by line. As many buffers as possible are sent before returning + from routine. + + 3. Change Path.c to include to get and define + getuid in terms of uid_t. + + 4. Added #defines for memset() and memcpy() for use when BSD4_2 is defined. + ==================== ghostview 1.3 (12 May 92) ===================== 1. Fix bug where EPSF figures with a %%Page comment would cause ghostview diff -N -u ghostview-1.3/Imakefile ghostview-1.4/Imakefile --- ghostview-1.3/Imakefile Wed Apr 15 09:15:45 1992 +++ ghostview-1.4/Imakefile Mon Sep 21 19:31:41 1992 @@ -1,25 +1,29 @@ -# Imakefile -- Imakefile for ghostview. -# 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 +#ifndef XCOMM +#define XCOMM # +#endif + +XCOMM Imakefile -- Imakefile for ghostview. +XCOMM Copyright (C) 1992 Timothy O. Theisen +XCOMM +XCOMM This program is free software; you can redistribute it and/or modify +XCOMM it under the terms of the GNU General Public License as published by +XCOMM the Free Software Foundation; either version 2 of the License, or +XCOMM (at your option) any later version. +XCOMM +XCOMM This program is distributed in the hope that it will be useful, +XCOMM but WITHOUT ANY WARRANTY; without even the implied warranty of +XCOMM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +XCOMM GNU General Public License for more details. +XCOMM +XCOMM You should have received a copy of the GNU General Public License +XCOMM along with this program; if not, write to the Free Software +XCOMM Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +XCOMM +XCOMM Author: Tim Theisen Systems Programmer +XCOMM Internet: tim@cs.wisc.edu Department of Computer Sciences +XCOMM UUCP: uwvax!tim University of Wisconsin-Madison +XCOMM Phone: (608)262-0438 1210 West Dayton Street +XCOMM FAX: (608)262-9777 Madison, WI 53706 #define Use_SelFile @@ -43,6 +47,8 @@ LOCAL_LIBRARIES = XawClientLibs SYS_LIBRARIES = -lm +XCOMM Add -DBSD4_2 to DEFINES if you system does not have memset() and memcpy() + DEFINES = -DNON_BLOCKING_IO $(SIGNAL_DEFINES) $(SELFILE_DEFINE) .NOEXPORT: @@ -49,15 +55,15 @@ AllTarget(ghostview) -depend:: Ghostview.ad.h +depend:: app-defaults.h ComplexProgramTarget(ghostview) InstallAppDefaults(Ghostview) -main.o: Ghostview.ad.h +main.o: app-defaults.h -Ghostview.ad.h: Ghostview.ad - ./ad2c Ghostview.ad > Ghostview.ad.h +app-defaults.h: Ghostview.ad + ./ad2c Ghostview.ad > app-defaults.h clean:: - $(RM) Ghostview.ad.h + $(RM) app-defaults.h diff -N -u ghostview-1.3/Makefile ghostview-1.4/Makefile --- ghostview-1.3/Makefile Fri May 8 10:01:36 1992 +++ ghostview-1.4/Makefile Mon Sep 21 19:32:27 1992 @@ -289,7 +289,7 @@ all:: ghostview -depend:: Ghostview.ad.h +depend:: app-defaults.h PROGRAM = ghostview @@ -325,13 +325,13 @@ else (set -x; $(MKDIRHIER) $(DESTDIR)$(XAPPLOADDIR)); fi $(INSTALL) -c $(INSTAPPFLAGS) Ghostview.ad $(DESTDIR)$(XAPPLOADDIR)/Ghostview -main.o: Ghostview.ad.h +main.o: app-defaults.h -Ghostview.ad.h: Ghostview.ad - ./ad2c Ghostview.ad > Ghostview.ad.h +app-defaults.h: Ghostview.ad + ./ad2c Ghostview.ad > app-defaults.h clean:: - $(RM) Ghostview.ad.h + $(RM) app-defaults.h # ------------------------------------------------------------------------- # common rules for all Makefiles - do not edit @@ -370,15 +370,15 @@ # DO NOT DELETE main.o: Ghostview.h -main.o: ghostview.h -main.o: ps.h Ghostview.ad.h -misc.o: Ghostview.h ghostview.h +main.o: gv.h +main.o: ps.h app-defaults.h +misc.o: Ghostview.h gv.h misc.o: ps.h -callbacks.o: Ghostview.h ghostview.h +callbacks.o: Ghostview.h gv.h callbacks.o: ps.h -actions.o: ghostview.h +actions.o: gv.h actions.o: Ghostview.h ps.h -dialogs.o: ghostview.h +dialogs.o: gv.h dialogs.o: Ghostview.h Ghostview.o: GhostviewP.h Ghostview.h ps.o: ps.h diff -N -u ghostview-1.3/Path.c ghostview-1.4/Path.c --- ghostview-1.3/Path.c Fri May 8 10:01:36 1992 +++ ghostview-1.4/Path.c Tue May 19 17:30:53 1992 @@ -30,6 +30,7 @@ #include #endif /* def SEL_FILE_IGNORE_CASE */ +#include #include #include "SFinternal.h" #include "xstat.h" @@ -36,9 +37,7 @@ #include #if defined(SVR4) || defined(SYSV) || defined(USG) -#if !defined(SVR4) && !defined(_AIX) && !defined(hpux) && !defined(OCS88) -extern unsigned short getuid(); -#endif /* !defined(SVR4) && !defined(_AIX) && !defined(hpux) && !defined(OCS88) */ +extern uid_t getuid(); extern void qsort(); #endif /* defined(SVR4) || defined(SYSV) || defined(USG) */ diff -N -u ghostview-1.3/README ghostview-1.4/README --- ghostview-1.3/README Fri May 8 10:01:36 1992 +++ ghostview-1.4/README Thu Oct 1 16:33:10 1992 @@ -27,9 +27,9 @@ The Ghostview distribution includes a Ghostview Widget that people are encouraged to use in other programs. - Ghostview-1.3 is available via anonymous ftp from: - prep.ai.mit.edu:/pub/gnu/ghostview-1.3.tar.Z - appenzell.cs.wisc.edu:/pub/ghostview-1.3.tar.Z + Ghostview-1.4 is available via anonymous ftp from: + prep.ai.mit.edu:/pub/gnu/ghostview-1.4.tar.Z + ftp.cs.wisc.edu:/pub/X/ghostview-1.4.tar.Z 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 @@ -75,16 +75,15 @@ properly. You can pick up the current copy of ghostscript from the same place you got ghostview. - 3. When I start ghostview, I get an "X Error: BadAlloc". What went - wrong? + 3. When I start ghostview, the information window pops up with: + "Warning: Could not allocate backing pixmap in main window." + What does this mean? Ghostscript draws into a backing pixmap and copies from the pixmap to the window. Some X servers have limited resources for - pixmaps. You can turn off the backing pixmap by putting - "*Ghostview.useBackingPixmap: False" into the app-defaults or - your .Xdefaults. Ghostview will then request backing store on - the window. If the backing store request is not honored, obscured - portions of the window will be lost. + pixmaps. Creating the backing pixmap failed. Ghostview will then + request backing store on the window. If the backing store request + is not honored, obscured portions of the window will be lost. You might also request a smaller window by setting a smaller magstep or setting a smaller resolution. @@ -110,7 +109,7 @@ This also occurs on some SPARCS running SunOS. This does not happen for me and must be due to some differences in libraries or environment. I have placed a SPARC executable (compiled on SunOS 4.1 with X11R5pl10 - libraries statically linked in) on appenzell.cs.wisc.edu for people + libraries statically linked in) on ftp.cs.wisc.edu for people in this situation. 6. When using ncdwm, sometimes the window shrinks to an extremely @@ -142,6 +141,7 @@ ghostview. - Erik M. van der Poel, for writing a good publicly available file selection widget that I was able incorporate into ghostview. + - Terry Poot, for porting ghostview to VMS. NOTE: PLEASE send all ghostview related mail to ghostview@cs.wisc.edu. diff -N -u ghostview-1.3/README.VMS ghostview-1.4/README.VMS --- ghostview-1.3/README.VMS +++ ghostview-1.4/README.VMS Tue Sep 22 11:19:39 1992 @@ -0,0 +1,215 @@ +Release notes for VMS changes to Ghostview +8/18/92, Terry Poot + +Introduction +------------ + +I've gotten Ghostview version 1.4 working on VMS 5.5, compiled with VAX C +v3.2, and using Ghostscript 2.4.1 and George Carrette's + port of the R5 Athena widgets. + +Ghostscript availablility is, I believe, mentioned in the Ghostview readme +files. + +George's kit for building the Athena widgets is available from +vmsnet.sources archive sites, including FTP from white.cerritos.edu +[130.150.200.22] and acfcluster.nyu.edu , and mailserver access from +MAILSERV@Cerritos.edu. (Send a message with 'help' in the body for +instructions.) You will also need the directories mit/lib/Xmu and +mit/lib/Xaw from the MIT X11r5 source kit. I think you can get them from +export.ai.mit.edu. I don't know of any non-FTP way other than finding a +friend who can send them to you (that's what I did). + +There's nothing I can think of in the changes to require any of these +specific versions. I suspect it will work on VMS 5.0 or later, possibly +even 4.7. I don't have any of these systems to test on, however. Also, any +Ghostscript supported by Ghostview should work, as NO changes were made to +Ghostscript to support Ghostview on VMS. + +I did this port specifically because I required a Postscript previewer for +my current project, to preview files created by my applications. It is +likely that anything I don't use hasn't been tested much, if at all. +However, the relatively small number of changes is encouraging, and the +changes themselves have all been tested. + +The 2 large areas of changes are processing of print requests, and the +communications between Ghostview and Ghostscript. The changes to the print +code are in the routine print_file in misc.c, and changes to the resources +used by that code are in main.c. Changes to the communications code are all +in the ghostview widget, which is in ghostview.c, with changes to the +widget structure in ghostviewp.h. Most other changes were simple things +like dealing with different include files to get the program to compile. + +Building +-------- + +There are 2 build procedures provided. If you have MMS, you can use the +DESCRIP.MMS description file. If not, there is a DCL procedure name +VMS_BUILD.COM. The command procedure builds everything, whereas MMS will +only build the things that have changed. + +VMS POSIX is used to convert the application defaults file to a C include +file for use as fallback resources. The include file is provided for the +shipped version of the application defaults file, but if you don't have +POSIX installed, you won't be able to automatically update the include file +to match changes you make to the application defaults file. Note that the +data in the include file is used only if you do NOT install the application +defaults file on your system (see the Installation section below). + +(If you have a unix system available, you can move files back and forth +manually and run ad2c on that machine to create an updated app-defaults.h.) + +If you have MMS: + +First, edit DESCRIP.MMS. Change the second line to show the proper location +on your system for the command procedure that defines the Athena logical +names (this is the LOGICALS.COM procedure that came with George Carrette's +Athena widget kit). Also, if you don't have VMS POSIX 1.0 installed on your +system, delete the line that starts: + +source:app-defaults.h : source:Ghostview.ad + +and the following action lines, or just add a "!" before the POSIX/RUN +command. + +Once you've made these changes, just type "MMS" and it should build. + +If you don't have MMS: + +First, edit VMS_BUILD.COM. Change the first line to show the proper +location on your system for the command procedure that defines the Athena +logical names (this is the LOGICALS.COM procedure that came with George +Carrette's Athena widget kit). Also, if you don't have VMS POSIX 1.0 +installed on your system, delete or comment out the line that contains the +command POSIX/RUN. Then simply type in "@VMS_BUILD". + +You might notice that we don't use all the source files. The ones not part +of the VMS build procedure aren't needed for VMS. This includes setenv.c, +getenv.c, and all source files for the select file widget. The file +vms_types.h is new, and is used to define VMS data structures in +ghostview.c. This file was written by Jym Dyer in 1989, so I don't know if +the email address in the file is still good. I added a definition to it +(IOSB_GET_T). It was already Copyright'ed under the GPL, so there's no +conflict including it here. + +Installation +------------ + +To run Ghostview, you must define a foreign command for it. This can be +done in a user's login.com, or in the system wide sylogin.com for +convenience. The command to do this is: + +$ gv :==$dev:[dir]gv.exe + +Fill in the device and directory for your site. Note the "$" after the +":==". It's important that it be there. + +You can call this something other than gv, but DON'T call it ghostview!!! +Repeat: DON'T CALL IT GHOSTVIEW!!! If you do, Ghostscript will no longer +work on your system, except (maybe) when called by Ghostview. The reason, +for the curious, is that Ghostscript expects the environment variable +GHOSTVIEW, if it exists, to be the window id of the window it should draw +on. That's how Ghostview gets Ghostscript to use a Ghostview window for +output. Symbols, including foreign command symbols, will be seen as +environment variables, so Ghostscript will try to use your command +definition as a window id, and choke and die. + +Speaking of Ghostscript, the default resource setup expects it to be +defined as a foreign command named gs. If you choose to call the +Ghostscript command something else, you'll need to change the interpreter +resource of Ghostview to the command needed to run Ghostscript (or supply +the -interpreter command line option). It MUST be defined as a foreign +command so that Ghostview can set some command line options. + +The application defaults file can be installed system-wide by copying it to +DECW$SYSTEM_DEFAULTS:GHOSTVIEW.DAT (you have to have privileges to do +that). Alternately, each Ghostview user can copy it to +DECW$USER_DEFAULTS:GHOSTVIEW.DAT. (DECW$USER_DEFAULTS usually points to the +user's login directory.) If that file is not found, the compiled in values +will be used. Therefore, if you install the application defaults file, you +don't really have to worry about keeping app-defaults.h up to date, as it +is only used if the app defaults file isn't found. You will especially want +to install the file if you don't have VMS POSIX available to maintain the +include file that is derived from it. + +Notes for application users +--------------------------- + +There aren't too many differences to worry about. + +No attempt has been made to port the select file widget. Any prompt for a +file name will simply pop up a dialog box into which you type the file +name. I'd have tried to integrate the DECwindows file selection widget, but +this is an Athena program, and I figured the hassle to get it all to work +together wouldn't be worth the trouble. Besides, in my application, I +didn't need it. :-) + +Also the print related resources have been changed a bit. + +The printCommand resource must be a command that takes a filename argument. +The default for printCommand is "Print_dcl/Delete". The "_dcl" suffix is to +avoid any symbol redefinitions of the print command. + +The printerVariable resource is the name of a logical name that may contain +qualifiers to the print command. The logical name has been changed from +PRINTER to GV_PRINT_QUAL to make it a little bit safer to set system wide, +for instance with a /QUEUE=xxx qualifier to point to the queue serving your +postscript printer. The printPrompt resource has been changed to "Print +Qualifiers: " to reflect this usage. + +defaultPrinter defaults to NULL, but it will be set the the equivalence +string for GV_PRINT_QUAL at application startup if that logical is set (or +whatever logical might be named in printerVariable if you change it). Thus +you can default the print queue either with a logical name or by putting it +in Ghostview's application defaults file. + +Any print command can be used, but bear in mind that it must take one +argument, which is a temporary file name. The print command must delete +this file or it will be left lying around. printerVariable may be used to +pass any qualifiers to the command. It can be used to select a print queue, +form, etc. This is the item that is prompted for when you tell it to print. +(printPrompt has been changed from "Printer Name:" to "Print Qualifiers:"). +If you define a logical name or symbol named GV_PRINT_QUAL (or some other +name if you change printerVariable) it will be used as the +default response for this prompt. + +The command executed in any print request is the value of printComand, +followed by a space and then by the print qualifiers specified by the user +(which default to defaultPrinter, see above) followed by another space and +then the temp file name. You can fill in these 2 resources to suit +your needs. Just remember the user can over-ride the second one at run +time. (That's why the /DELETE is part of the print command as distributed, +rather than included as a default in defaultPrinter.) + +This would make a bit more sense if I'd renamed the resources, but that +would have created a lot of VMS specific code for little actual gain. If it +helps you keep track of them, here's a brief summary table: + +resource VMS Value What it is +-------- --------- ---------- +printCommand PRINT_DCL/DELETE The print command +printerVariable GV_PRINT_QUAL logical name to hold default qualifiers +defaultPrinter Default qualifiers, over-ridden by + GV_PRINT_QUAL if set +printPrompt "Print Qualifiers:" Just a prompt string + +Notes for widget users +---------------------- + +See the notes for application users for differences in resources. + +The widget uses VMS Event Flag number 23. You can change the event flag +number by changing the define for XtEFN in ghostview.c. Ghostview can +tolerate other modules in the program setting the flag, as it always checks +for actual I/O completion using IOSB's. However, if you clear the flag, Xt +may miss an I/O completion and your program could hang. Best to simply +avoid it. + +I've made changes to the definitions of the widget data in ghostviewp.h. +I've ifdef'ed out data items not used in the VMS version and added a few +that I needed under VMS. I might have missed a few of the former kind, but +if so, they should just sit around unused and not bother anyone. +-- +Terry Poot The McCall Pattern Company +(uucp: ...!rutgers!depot!mccall!tp) 615 McCall Road +(800)255-2762, in KS (913)776-4041 Manhattan, KS 66502, USA diff -N -u ghostview-1.3/actions.c ghostview-1.4/actions.c --- ghostview-1.3/actions.c Fri May 8 10:01:36 1992 +++ ghostview-1.4/actions.c Thu Oct 1 14:20:28 1992 @@ -27,7 +27,7 @@ #include #include #include -#include "ghostview.h" +#include "gv.h" #include "ps.h" /* Popup the copyright window */ @@ -63,6 +63,18 @@ popup_dialog(w, (XtPointer)OPEN, NULL); } +/* Popup the open file dialog box. */ +void +gv_reopen(w, event, params, num_params) + Widget w; + XEvent *event; + String *params; + Cardinal *num_params; +{ + if (!XtIsSensitive(reopenbutton)) return; + reopen_file(w, NULL, NULL); +} + /* Popup the save file dialog box. */ void gv_save(w, event, params, num_params) @@ -472,7 +484,6 @@ if (psfile) { if (!stat(filename, &sbuf) && mtime != sbuf.st_mtime) { - fprintf(stderr, "rescan\n"); show_page(current_page); } } diff -N -u ghostview-1.3/callbacks.c ghostview-1.4/callbacks.c --- ghostview-1.3/callbacks.c Tue May 12 17:49:51 1992 +++ ghostview-1.4/callbacks.c Thu Oct 1 15:37:32 1992 @@ -28,6 +28,10 @@ #define BUFSIZ 1024 #endif +#ifdef VMS +#define getenv _getenv +#endif + extern char *getenv(); #include @@ -40,7 +44,7 @@ #include #include "Ghostview.h" -#include "ghostview.h" +#include "gv.h" #include "ps.h" /* Start application folding up by Destroying the top level widget. */ @@ -145,6 +149,24 @@ } } +/* Explicitly reopen the file. */ +void +reopen_file(w, client_data, call_data) + Widget w; + XtPointer client_data, call_data; +{ + struct stat sbuf; + int number = current_page; + + fclose(psfile); + psfile = fopen(filename, "r"); + mtime = sbuf.st_mtime; + if (oldfilename) XtFree(oldfilename); + oldfilename = XtNewString(filename); + new_file(number); + show_page(number); +} + /* Get the selection, if no selection, get the insertion point. */ /* If the new_page is different from the current page show it. */ /* If not at the first page, show the previous page. */ @@ -488,7 +510,8 @@ zoompage = XtCreateManagedWidget("page", ghostviewWidgetClass, zoomform, args, num_args); num_ghosts++; - XtAddCallback(zoompage, XtNcallback, track_and_zoom, (XtPointer)zoom); + XtAddCallback(zoompage, XtNcallback, track_and_zoom, (XtPointer)0); + XtAddCallback(zoompage, XtNmessageCallback, message, (XtPointer)zoompage); XtAddCallback(zoompage, XtNdestroyCallback, destroy_ghost, (XtPointer)zoompage); @@ -504,7 +527,7 @@ XtSetArg(args[num_args], XtNright, XtChainRight); num_args++; zoomdismiss = XtCreateManagedWidget("dismiss", commandWidgetClass, zoomform, args, num_args); - XtAddCallback(zoomdismiss, XtNcallback, dismiss, (XtPointer)zoom); + XtAddCallback(zoomdismiss, XtNcallback, destroy, (XtPointer)zoom); XtSetArg(args[0], XtNwidth, &width); XtGetValues(zoompage, args, ONE); @@ -532,15 +555,15 @@ zoomfile = fopen(filename, "r"); if (zoomfile == NULL) return; GhostviewSendPS(zoompage, zoomfile, doc->beginprolog, - doc->endprolog, False); + doc->lenprolog, False); GhostviewSendPS(zoompage, zoomfile, doc->beginsetup, - doc->endsetup, False); + doc->lensetup, False); if (doc->pageorder == DESCEND) i = (doc->numpages - 1) - current_page; else i = current_page; GhostviewSendPS(zoompage, zoomfile, doc->pages[i].begin, - doc->pages[i].end, True); + doc->pages[i].len, True); } } @@ -552,21 +575,36 @@ XtPointer client_data, call_data; { int i; + char *error; if (!strcmp((char *) call_data, "Failed")) { - output(page, NULL, "Error: PostScript interpreter failed.\n\n"); + if ((Widget)client_data == page) { + error = "Error: PostScript interpreter failed in main window.\n\n"; + } else { + error = "Error: PostScript interpreter failed in zoom window.\n\n"; + } + output(w, NULL, error); + } else if (!strcmp((char *) call_data, "BadAlloc")) { + if ((Widget)client_data == page) { + error = + "Warning: Could not allocate backing pixmap in main window.\n\n"; + } else { + error = + "Warning: Could not allocate backing pixmap in zoom window.\n\n"; + } + output(w, NULL, error); } else if (!strcmp((char *) call_data, "Refresh")) { if (toc_text) { - GhostviewSendPS(page, psfile, doc->beginprolog, - doc->endprolog, False); - GhostviewSendPS(page, psfile, doc->beginsetup, - doc->endsetup, False); + GhostviewSendPS(w, psfile, doc->beginprolog, + doc->lenprolog, False); + GhostviewSendPS(w, psfile, doc->beginsetup, + doc->lensetup, False); if (doc->pageorder == DESCEND) i = (doc->numpages - 1) - current_page; else i = current_page; - GhostviewSendPS(page, psfile, doc->pages[i].begin, - doc->pages[i].end, False); + GhostviewSendPS(w, psfile, doc->pages[i].begin, + doc->pages[i].len, False); } } } @@ -663,6 +701,15 @@ if ((Widget)client_data == infopopup) info_up = False; } +/* Destroy popup window */ +void +destroy(w, client_data, call_data) + Widget w; + XtPointer client_data, call_data; +{ + XtDestroyWidget((Widget)client_data); +} + /* destroy callback for Ghostview widgets. */ /* The disable interpreter call ensures that ghostscript is killed. */ /* One the count goes to 0, we are sure that all forked processes have */ @@ -675,6 +722,7 @@ GhostviewDisableInterpreter((Widget) client_data); num_ghosts--; if (num_ghosts) return; + if (dying) old_Xerror(XtDisplay(w), &bomb); XtDestroyApplicationContext(app_con); exit(0); } diff -N -u ghostview-1.3/descrip.mms ghostview-1.4/descrip.mms --- ghostview-1.3/descrip.mms +++ ghostview-1.4/descrip.mms Mon Sep 21 19:32:51 1992 @@ -0,0 +1,65 @@ +.first + @lsrc:[x11]logicals.com !<<< change for your system! + copy/log x11_xmu:xmushr.psects,x11_xaw:xawshr.psects,x11_xaw:user.opt - + gv.opt +GV.EXE : GV.OLB XMUSHR XAWSHR + $(link) $(linkflags) /exe=gv.exe gv.olb/include=main/library,gv.opt/opt +GV.OLB : GV.OLB(MAIN=MAIN.OBJ) GV.OLB(MISC=MISC.OBJ) GV.OLB(CALLBACKS=CALLBACKS.OBJ) - + GV.OLB(ACTIONS=ACTIONS.OBJ) GV.OLB(DIALOGS=DIALOGS.OBJ) GV.OLB(GHOSTVIEW=GHOSTVIEW.OBJ) - + GV.OLB(PS=PS.OBJ) GV.OLB(STRCASECMP=STRCASECMP.OBJ) + @ continue +GV.OLB(MAIN=MAIN.OBJ) : MAIN.OBJ + If "''F$Search("$@")'" .EQS. "" Then $(LIBR)/Create $@ + $(LIBR)$(LIBRFLAGS) $@ MAIN.OBJ +MAIN.OBJ : MAIN.C GHOSTVIEW.H GV.H - + PS.H APP-DEFAULTS.H + $(CC) $(CFLAGS) MAIN.C +APP-DEFAULTS.H : GHOSTVIEW.AD + get_run = 0 + get_ad2c = 0 + if f$search("run-ad2c.").eqs."" then get_run = 1 + if f$search("ad2c.").eqs."" then get_ad2c = 1 + - if get_run then cms fetch run-ad2c. + - if get_ad2c then cms fetch ad2c. + - posix/run posix$bin:sh. run-ad2c + if get_run then delete run-ad2c.;* + if get_ad2c then delete ad2c.;* +GV.OLB(MISC=MISC.OBJ) : MISC.OBJ + If "''F$Search("$@")'" .EQS. "" Then $(LIBR)/Create $@ + $(LIBR)$(LIBRFLAGS) $@ MISC.OBJ +MISC.OBJ : MISC.C GHOSTVIEW.H GV.H - + PS.H + $(CC) $(CFLAGS) MISC.C +GV.OLB(CALLBACKS=CALLBACKS.OBJ) : CALLBACKS.OBJ + If "''F$Search("$@")'" .EQS. "" Then $(LIBR)/Create $@ + $(LIBR)$(LIBRFLAGS) $@ CALLBACKS.OBJ +CALLBACKS.OBJ : CALLBACKS.C GHOSTVIEW.H GV.H - + PS.H + $(CC) $(CFLAGS) CALLBACKS.C +GV.OLB(ACTIONS=ACTIONS.OBJ) : ACTIONS.OBJ + If "''F$Search("$@")'" .EQS. "" Then $(LIBR)/Create $@ + $(LIBR)$(LIBRFLAGS) $@ ACTIONS.OBJ +ACTIONS.OBJ : ACTIONS.C GV.H GHOSTVIEW.H - + PS.H + $(CC) $(CFLAGS) ACTIONS.C +GV.OLB(DIALOGS=DIALOGS.OBJ) : DIALOGS.OBJ + If "''F$Search("$@")'" .EQS. "" Then $(LIBR)/Create $@ + $(LIBR)$(LIBRFLAGS) $@ DIALOGS.OBJ +DIALOGS.OBJ : DIALOGS.C GV.H GHOSTVIEW.H + $(CC) $(CFLAGS) DIALOGS.C +GV.OLB(GHOSTVIEW=GHOSTVIEW.OBJ) : GHOSTVIEW.OBJ + If "''F$Search("$@")'" .EQS. "" Then $(LIBR)/Create $@ + $(LIBR)$(LIBRFLAGS) $@ GHOSTVIEW.OBJ +GHOSTVIEW.OBJ : GHOSTVIEW.C GHOSTVIEWP.H GHOSTVIEW.H - + VMS_TYPES.H + $(CC) $(CFLAGS) GHOSTVIEW.C +GV.OLB(PS=PS.OBJ) : PS.OBJ + If "''F$Search("$@")'" .EQS. "" Then $(LIBR)/Create $@ + $(LIBR)$(LIBRFLAGS) $@ PS.OBJ +PS.OBJ : PS.C PS.H + $(CC) $(CFLAGS) PS.C +GV.OLB(STRCASECMP=STRCASECMP.OBJ) : STRCASECMP.OBJ + If "''F$Search("$@")'" .EQS. "" Then $(LIBR)/Create $@ + $(LIBR)$(LIBRFLAGS) $@ STRCASECMP.OBJ +STRCASECMP.OBJ : STRCASECMP.C STDC.H + $(CC) $(CFLAGS) STRCASECMP.C diff -N -u ghostview-1.3/dialogs.c ghostview-1.4/dialogs.c --- ghostview-1.3/dialogs.c Thu Mar 19 19:48:25 1992 +++ ghostview-1.4/dialogs.c Fri Jun 19 15:21:41 1992 @@ -31,7 +31,7 @@ #include #include #include -#include "ghostview.h" +#include "gv.h" static String okay_accelerators = "#override\n\ diff -N -u ghostview-1.3/ghostview.h ghostview-1.4/ghostview.h --- ghostview-1.3/ghostview.h Fri May 8 10:01:36 1992 +++ ghostview-1.4/ghostview.h @@ -1,247 +0,0 @@ -/* - * ghostview.h -- Main include file for ghostview. - * 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 -#include -#include -#include -#define XtSetFloatArg(arg, n, d) \ - if (sizeof(float) > sizeof(XtArgVal)) { \ - XtSetArg(arg, n, &(d)); \ - } else { \ - XtArgVal *ld = (XtArgVal *)&(d); \ - XtSetArg(arg, n, *ld); \ - } -#include "Ghostview.h" - -/* Application resources */ -typedef struct _AppResources { - Boolean show_title; /* whether to show title */ - Boolean show_date; /* whether to show date */ - Boolean show_locator; /* whether to show locator */ - Boolean install_std_cmap; /* whether to install standard colormap */ - Boolean retain_std_cmap; /* whether to retain standard colormap */ - Boolean private_cmap; /* whether to use private colormap */ - Boolean auto_center; /* whether to automatically center the page */ - int wm_horiz_margin; /* Space taken by window manager */ - int wm_vert_margin; /* Space taken by window manager */ - int minimum_magstep; /* smallest magstep allowed */ - int maximum_magstep; /* largest magstep allowed */ - int magstep; /* default magstep */ - XtPageOrientation orientation; /* default orientation */ - String page; /* first page to show */ - String pagemedia; /* default page media */ - Boolean force_orientation; /* use default to override document comments */ - Boolean force_pagemedia; /* use default to override document comments */ - Boolean swap_landscape; /* Landscape comment maps to Seascape */ - String print_command; /* command used to print doc, usually "lpr" */ - String printer_variable; /* env varaible to use, usually "PRINTER" */ - String default_printer; /* printer to use if no PRINTER is not set*/ - String print_prompt; /* string to prompt user for printer name */ - String print_fail; /* string to inform user that print failed */ - String open_prompt; /* string to prompt for file name to open */ - String open_fail; /* string to inform user that open failed */ - String save_prompt; /* string to prompt for file name to save */ - String save_fail; /* string to inform user that save failed */ - /* Work arounds for others' bugs */ - Boolean openwindows; /* whether to work around openwindow bug */ - Boolean ncdwm; /* whether to work around ncdwm bug */ -} AppResources; - -extern float default_xdpi; -extern float default_ydpi; - -extern int num_ghosts; -extern FILE *psfile; -extern String filename; -extern String oldfilename; -extern int current_page; -extern int current_magstep; -extern XtPageOrientation current_orientation; -extern int default_pagemedia; -extern int current_pagemedia; -extern Boolean force_document_media; -extern int document_media; -extern int current_llx; -extern int current_lly; -extern int current_urx; -extern int current_ury; -extern int base_papersize; -extern Boolean info_up; -extern int force_setting; -extern Pixmap dot_bitmap; -extern Pixmap menu16_bitmap; -extern Pixmap tie_fighter_bitmap; -extern String toc_text; -extern int toc_length; -extern int toc_entry_length; -extern int info_length; -extern time_t mtime; -extern struct document *doc; -extern struct document *olddoc; -extern Colormap cmap; -extern Boolean special_cmap; -extern Pixel white; -extern Pixel black; -extern Atom wm_delete_window; - -enum {OPEN, PRINT_WHOLE, PRINT_MARKED, SAVE}; -extern int mode; - -extern XtAppContext app_con; -extern AppResources app_res; - -/* Widgets */ -extern Widget toplevel; -extern Widget form; -extern Widget titlebutton; -extern Widget titlemenu; -extern Widget datebutton; -extern Widget datemenu; -extern Widget locator; -extern Widget box; -extern Widget filebutton; -extern Widget filemenu; -extern Widget openbutton; -extern Widget printwholebutton; -extern Widget printmarkedbutton; -extern Widget savebutton; -extern Widget copyrightbutton; -extern Widget quitbutton; -extern Widget pagebutton; -extern Widget pagemenu; -extern Widget nextbutton; -extern Widget showbutton; -extern Widget prevbutton; -extern Widget centerbutton; -extern Widget markbutton; -extern Widget unmarkbutton; -extern Widget magstepbutton; -extern Widget magstepmenu; -extern Widget *magstepentry; -extern Widget orientationbutton; -extern Widget orientationmenu; -extern Widget portraitbutton; -extern Widget landscapebutton; -extern Widget upsidedownbutton; -extern Widget seascapebutton; -extern Widget swapbutton; -extern Widget pagemediabutton; -extern Widget pagemediamenu; -extern Widget *pagemediaentry; -extern Widget toc; -extern Widget pageview; -extern Widget page; - -/* Popup widgets */ -extern Widget infopopup; -extern Widget infoform; -extern Widget infotext; -extern Widget infobutton; -extern Widget copyrightpopup; -extern Widget copyrightform; -extern Widget copyrighttext; -extern Widget copyrightbutton; -extern Widget dialogpopup; -extern Widget dialog; - -/* Dialogs */ -extern Widget CreateDialog(); -extern String GetDialogPrompt(); -extern void SetDialogPrompt(); -extern String GetDialogResponse(); -extern void SetDialogResponse(); -extern void ClearDialogResponse(); - -/* Callbacks */ -extern void quit_ghostview(); -extern void popup(); -extern void popup_dialog(); -extern void print_popup(); -extern void prev_page(); -extern void this_page(); -extern void next_page(); -extern void center_page(); -extern void mark_page(); -extern void unmark_page(); -extern void set_magstep(); -extern void set_orientation(); -extern void swap_landscape(); -extern void set_pagemedia(); -extern void track_and_zoom(); -extern void message(); -extern void output(); -extern void okay(); -extern void dismiss(); -extern void destroy_ghost(); - -/* Actions */ -extern void gv_copyright(); -extern void gv_quit(); -extern void gv_open(); -extern void gv_save(); -extern void gv_print_whole(); -extern void gv_print_marked(); -extern void gv_prev(); -extern void gv_show(); -extern void gv_next(); -extern void gv_center(); -extern void gv_mark(); -extern void gv_unmark(); -extern void gv_set_magstep(); -extern void gv_increase_magstep(); -extern void gv_decrease_magstep(); -extern void gv_set_orientation(); -extern void gv_swap_landscape(); -extern void gv_set_pagemedia(); -extern void gv_default(); -extern void gv_force(); -extern void gv_delete_window(); -extern void gv_delete_zoom(); -extern void gv_dismiss(); -extern void gv_scroll_up(); -extern void gv_scroll_down(); -extern void gv_scroll_left(); -extern void gv_scroll_right(); -extern void gv_erase_locator(); -extern void gv_check_file(); - -/* Misc */ -extern void show_page(); -extern Boolean setup_ghostview(); -extern void layout_ghostview(); -extern void SetStandardColormap(); -extern void magnify(); -extern String open_file(); -extern String save_file(); -extern String print_file(); -extern void pscopydoc(); -extern void positionpopup(); -extern Boolean set_new_magstep(); -extern Boolean set_new_orientation(); -extern Boolean set_new_pagemedia(); -extern void build_pagemedia_menu(); -extern Widget build_label_menu(); -extern void new_file(); diff -N -u ghostview-1.3/ghostview.man ghostview-1.4/ghostview.man --- ghostview-1.3/ghostview.man Fri May 8 10:01:36 1992 +++ ghostview-1.4/ghostview.man Tue Oct 6 21:03:43 1992 @@ -166,6 +166,8 @@ Pops up the Select File window in preparation to open a file. The Select File widget is in total control until it pops down. Opens the file for viewing. +.IP "\fBReopen\fP" 1i +Reopens the current file. .IP "\fBPrint...\fP" 1i Pops up a dialog widget to ask for the printer name. Sends the whole document to the printer. @@ -291,6 +293,9 @@ .IP \fBO\fP 1i Bound to \fBGhostviewOpen()\fP which is equivalent to pushing the \fBOpen...\fP menu button on the \fBFile\fP menu. +.IP \fBR\fP 1i +Bound to \fBGhostviewReopen()\fP which is +equivalent to pushing the \fBReopen\fP menu button on the \fBFile\fP menu. .IP \fBS\fP 1i Bound to \fBGhostviewSave()\fP which is equivalent to pushing the \fBSave marked pages...\fP menu button on the \fBFile\fP menu. @@ -306,7 +311,7 @@ .IP "\fBspace\fP, \fBReturn\fP, \fBNext\fP, \fBF\fP" 1i Bound to \fBGhostviewNext()\fP which is equivalent to pushing the \fBNext\fP menu button on the \fBPage\fP menu. -.IP "\fBperiod\fP, \fBR\fP, \fBCtrl\-L\fP" 1i +.IP "\fBperiod\fP, \fBCtrl\-L\fP" 1i Bound to \fBGhostviewShow()\fP which is equivalent to pushing the \fBRedisplay\fP menu button on the \fBPage\fP menu. .IP \fBM\fP 1i @@ -391,6 +396,8 @@ Equivalent to pushing the \fBQuit\fP menu button on the \fBGhostview\fP menu. .IP \fBGhostviewOpen()\fP 1i Equivalent to pushing the \fBOpen...\fP menu button on the \fBFile\fP menu. +.IP \fBGhostviewReopen()\fP 1i +Equivalent to pushing the \fBReopen\fP menu button on the \fBFile\fP menu. .IP \fBGhostviewSave()\fP 1i Equivalent to pushing the \fBSave marked pages...\fP menu button on the \fBFile\fP menu. .IP \fBGhostviewPrintWhole()\fP 1i @@ -463,7 +470,7 @@ The default is ``true''. .IP "\fBinstallStdCmap (\fPclass\fB InstallStdCmap)\fP" 1i Tells whether to attempt to install a standard colormap. -The default is ``true''. +The default is ``false''. .IP "\fBprivateCmap (\fPclass\fB PrivateCmap)\fP" 1i Tells whether to use a standard colormap that is not the default colormap. The default is ``false''. @@ -734,6 +741,7 @@ MenuButton fileButton SimpleMenu menu SmeBSB open + SmeBSB reopen SmeBSB printwhole SmeBSB printmarked SmeBSB save diff -N -u ghostview-1.3/gv.h ghostview-1.4/gv.h --- ghostview-1.3/gv.h +++ ghostview-1.4/gv.h Thu Oct 1 14:14:26 1992 @@ -0,0 +1,254 @@ +/* + * gv.h -- Main include file for ghostview. + * 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 +#include +#include +#include +#define XtSetFloatArg(arg, n, d) \ + if (sizeof(float) > sizeof(XtArgVal)) { \ + XtSetArg(arg, n, &(d)); \ + } else { \ + XtArgVal *ld = (XtArgVal *)&(d); \ + XtSetArg(arg, n, *ld); \ + } +#include "Ghostview.h" + +/* Application resources */ +typedef struct _AppResources { + Boolean show_title; /* whether to show title */ + Boolean show_date; /* whether to show date */ + Boolean show_locator; /* whether to show locator */ + Boolean install_std_cmap; /* whether to install standard colormap */ + Boolean retain_std_cmap; /* whether to retain standard colormap */ + Boolean private_cmap; /* whether to use private colormap */ + Boolean auto_center; /* whether to automatically center the page */ + int wm_horiz_margin; /* Space taken by window manager */ + int wm_vert_margin; /* Space taken by window manager */ + int minimum_magstep; /* smallest magstep allowed */ + int maximum_magstep; /* largest magstep allowed */ + int magstep; /* default magstep */ + XtPageOrientation orientation; /* default orientation */ + String page; /* first page to show */ + String pagemedia; /* default page media */ + Boolean force_orientation; /* use default to override document comments */ + Boolean force_pagemedia; /* use default to override document comments */ + Boolean swap_landscape; /* Landscape comment maps to Seascape */ + String print_command; /* command used to print doc, usually "lpr" */ + String printer_variable; /* env varaible to use, usually "PRINTER" */ + String default_printer; /* printer to use if no PRINTER is not set*/ + String print_prompt; /* string to prompt user for printer name */ + String print_fail; /* string to inform user that print failed */ + String open_prompt; /* string to prompt for file name to open */ + String open_fail; /* string to inform user that open failed */ + String save_prompt; /* string to prompt for file name to save */ + String save_fail; /* string to inform user that save failed */ + /* Work arounds for others' bugs */ + Boolean openwindows; /* whether to work around openwindow bug */ + Boolean ncdwm; /* whether to work around ncdwm bug */ +} AppResources; + +extern float default_xdpi; +extern float default_ydpi; + +extern int num_ghosts; +extern FILE *psfile; +extern String filename; +extern String oldfilename; +extern int current_page; +extern int current_magstep; +extern XtPageOrientation current_orientation; +extern int default_pagemedia; +extern int current_pagemedia; +extern Boolean force_document_media; +extern int document_media; +extern int current_llx; +extern int current_lly; +extern int current_urx; +extern int current_ury; +extern int base_papersize; +extern Boolean info_up; +extern int force_setting; +extern Pixmap dot_bitmap; +extern Pixmap menu16_bitmap; +extern Pixmap tie_fighter_bitmap; +extern String toc_text; +extern int toc_length; +extern int toc_entry_length; +extern int info_length; +extern time_t mtime; +extern struct document *doc; +extern struct document *olddoc; +extern Colormap cmap; +extern Boolean special_cmap; +extern Pixel white; +extern Pixel black; +extern Atom wm_delete_window; +extern int catch_Xerror(); +extern XErrorHandler old_Xerror; +extern Boolean dying; +extern XErrorEvent bomb; + +enum {OPEN, PRINT_WHOLE, PRINT_MARKED, SAVE}; +extern int mode; + +extern XtAppContext app_con; +extern AppResources app_res; + +/* Widgets */ +extern Widget toplevel; +extern Widget form; +extern Widget titlebutton; +extern Widget titlemenu; +extern Widget datebutton; +extern Widget datemenu; +extern Widget locator; +extern Widget box; +extern Widget filebutton; +extern Widget filemenu; +extern Widget openbutton; +extern Widget reopenbutton; +extern Widget printwholebutton; +extern Widget printmarkedbutton; +extern Widget savebutton; +extern Widget copyrightbutton; +extern Widget quitbutton; +extern Widget pagebutton; +extern Widget pagemenu; +extern Widget nextbutton; +extern Widget showbutton; +extern Widget prevbutton; +extern Widget centerbutton; +extern Widget markbutton; +extern Widget unmarkbutton; +extern Widget magstepbutton; +extern Widget magstepmenu; +extern Widget *magstepentry; +extern Widget orientationbutton; +extern Widget orientationmenu; +extern Widget portraitbutton; +extern Widget landscapebutton; +extern Widget upsidedownbutton; +extern Widget seascapebutton; +extern Widget swapbutton; +extern Widget pagemediabutton; +extern Widget pagemediamenu; +extern Widget *pagemediaentry; +extern Widget toc; +extern Widget pageview; +extern Widget page; + +/* Popup widgets */ +extern Widget infopopup; +extern Widget infoform; +extern Widget infotext; +extern Widget infobutton; +extern Widget copyrightpopup; +extern Widget copyrightform; +extern Widget copyrighttext; +extern Widget copyrightbutton; +extern Widget dialogpopup; +extern Widget dialog; + +/* Dialogs */ +extern Widget CreateDialog(); +extern String GetDialogPrompt(); +extern void SetDialogPrompt(); +extern String GetDialogResponse(); +extern void SetDialogResponse(); +extern void ClearDialogResponse(); + +/* Callbacks */ +extern void quit_ghostview(); +extern void popup(); +extern void popup_dialog(); +extern void reopen_file(); +extern void prev_page(); +extern void this_page(); +extern void next_page(); +extern void center_page(); +extern void mark_page(); +extern void unmark_page(); +extern void set_magstep(); +extern void set_orientation(); +extern void swap_landscape(); +extern void set_pagemedia(); +extern void track_and_zoom(); +extern void message(); +extern void output(); +extern void okay(); +extern void dismiss(); +extern void destroy(); +extern void destroy_ghost(); + +/* Actions */ +extern void gv_copyright(); +extern void gv_quit(); +extern void gv_open(); +extern void gv_reopen(); +extern void gv_save(); +extern void gv_print_whole(); +extern void gv_print_marked(); +extern void gv_prev(); +extern void gv_show(); +extern void gv_next(); +extern void gv_center(); +extern void gv_mark(); +extern void gv_unmark(); +extern void gv_set_magstep(); +extern void gv_increase_magstep(); +extern void gv_decrease_magstep(); +extern void gv_set_orientation(); +extern void gv_swap_landscape(); +extern void gv_set_pagemedia(); +extern void gv_default(); +extern void gv_force(); +extern void gv_delete_window(); +extern void gv_delete_zoom(); +extern void gv_dismiss(); +extern void gv_scroll_up(); +extern void gv_scroll_down(); +extern void gv_scroll_left(); +extern void gv_scroll_right(); +extern void gv_erase_locator(); +extern void gv_check_file(); + +/* Misc */ +extern void show_page(); +extern Boolean setup_ghostview(); +extern void layout_ghostview(); +extern void SetStandardColormap(); +extern void magnify(); +extern String open_file(); +extern String save_file(); +extern String print_file(); +extern void pscopydoc(); +extern void positionpopup(); +extern Boolean set_new_magstep(); +extern Boolean set_new_orientation(); +extern Boolean set_new_pagemedia(); +extern void build_pagemedia_menu(); +extern Widget build_label_menu(); +extern void new_file(); diff -N -u ghostview-1.3/main.c ghostview-1.4/main.c --- ghostview-1.3/main.c Fri May 8 10:01:36 1992 +++ ghostview-1.4/main.c Tue Oct 6 21:01:56 1992 @@ -27,9 +27,15 @@ #include #include #include +#ifdef VMS +#include +#include +#include +#else #include #include #include +#endif #include #include @@ -44,12 +50,12 @@ #include #include "Ghostview.h" -#include "ghostview.h" +#include "gv.h" #include "ps.h" extern char *getenv(); -static String version = "Ghostview, version 1.3"; +static String version = "Ghostview, version 1.4"; static XtResource resources[] = { {"showTitle", "Labels", XtRBoolean, sizeof(Boolean), @@ -59,7 +65,8 @@ {"showLocator", "Labels", XtRBoolean, sizeof(Boolean), XtOffsetOf(AppResources, show_locator), XtRImmediate, (XtPointer)True}, {"installStdCmap", "InstallStdCmap", XtRBoolean, sizeof(Boolean), - XtOffsetOf(AppResources, install_std_cmap), XtRImmediate, (XtPointer)True}, + XtOffsetOf(AppResources, install_std_cmap), XtRImmediate, + (XtPointer)False}, {"retainStdCmap", "RetainStdCmap", XtRBoolean, sizeof(Boolean), XtOffsetOf(AppResources, retain_std_cmap), XtRImmediate, (XtPointer)True}, {"privateCmap", "PrivateCmap", XtRBoolean, sizeof(Boolean), @@ -66,7 +73,7 @@ XtOffsetOf(AppResources, private_cmap), XtRImmediate, (XtPointer)False}, {"autoCenter", "AutoCenter", XtRBoolean, sizeof(Boolean), XtOffsetOf(AppResources, auto_center), XtRImmediate, (XtPointer)True}, - {"horizonalMargin", "Margin", XtRInt, sizeof(int), + {"horizontalMargin", "Margin", XtRInt, sizeof(int), XtOffsetOf(AppResources, wm_horiz_margin), XtRImmediate, (XtPointer)20}, {"verticalMargin", "Margin", XtRInt, sizeof(int), XtOffsetOf(AppResources, wm_vert_margin), XtRImmediate, (XtPointer)44}, @@ -90,6 +97,7 @@ XtOffsetOf(AppResources, force_pagemedia), XtRImmediate, (XtPointer)False}, {"swapLandscape", "SwapLandscape", XtRBoolean, sizeof(Boolean), XtOffsetOf(AppResources, swap_landscape), XtRImmediate, (XtPointer)False}, +#ifndef VMS #if defined(SVR4) || defined(SYSV) || defined(USG) {"printCommand", "PrintCommand", XtRString, sizeof(String), XtOffsetOf(AppResources, print_command), XtRImmediate, "lp"}, @@ -101,10 +109,18 @@ {"printerVariable", "PrinterVariable", XtRString, sizeof(String), XtOffsetOf(AppResources, printer_variable), XtRImmediate, "PRINTER"}, #endif - {"defaultPrinter", "DefaultPrinter", XtRString, sizeof(String), - XtOffsetOf(AppResources, default_printer), XtRImmediate, NULL}, {"printPrompt", "PrintPrompt", XtRString, sizeof(String), XtOffsetOf(AppResources, print_prompt), XtRImmediate, "Printer Name:"}, +#else /* VMS */ + {"printCommand", "PrintCommand", XtRString, sizeof(String), + XtOffsetOf(AppResources, print_command), XtRImmediate, "Print_dcl/Delete"}, + {"printerVariable", "PrinterVariable", XtRString, sizeof(String), + XtOffsetOf(AppResources, printer_variable), XtRImmediate, "GV_PRINT_QUAL"}, + {"printPrompt", "PrintPrompt", XtRString, sizeof(String), + XtOffsetOf(AppResources, print_prompt), XtRImmediate, "Print Qualifiers:"}, +#endif /* VMS */ + {"defaultPrinter", "DefaultPrinter", XtRString, sizeof(String), + XtOffsetOf(AppResources, default_printer), XtRImmediate, NULL}, {"printFail", "printFail", XtRString, sizeof(String), XtOffsetOf(AppResources, print_fail), XtRImmediate, "\"%s\" command failed."}, @@ -187,6 +203,7 @@ {"GhostviewCopyright", gv_copyright}, {"GhostviewQuit", gv_quit}, {"GhostviewOpen", gv_open}, + {"GhostviewReopen", gv_reopen}, {"GhostviewSave", gv_save}, {"GhostviewPrintWhole", gv_print_whole}, {"GhostviewPrintMarked", gv_print_marked}, @@ -216,7 +233,7 @@ }; String fallback_resources[] = { -# include "Ghostview.ad.h" +# include "app-defaults.h" NULL }; @@ -285,6 +302,9 @@ Pixel white; /* white pixel in above colormap */ Pixel black; /* black pixel in above colormap */ Atom wm_delete_window; /* Atom sent to destroy a window */ +XErrorHandler old_Xerror; /* standard error handler */ +Boolean dying; /* whether an X error caused our exit */ +XErrorEvent bomb; /* what the error was */ XtAppContext app_con; AppResources app_res; @@ -301,6 +321,7 @@ Widget filebutton; Widget filemenu; Widget openbutton; + Widget reopenbutton; Widget printwholebutton; Widget printmarkedbutton; Widget savebutton; @@ -385,8 +406,13 @@ if (argc == 2) { filename = XtNewString(argv[1]); if (strcmp(filename, "-")) { +#ifdef VMS + if ((psfile = fopen(argv[1], "r", "mbc=100")) == NULL) { +#else if ((psfile = fopen(argv[1], "r")) == NULL) { - perror("Cannot open file"); +#endif + fprintf(stderr, "Cannot open "); + perror(argv[1]); exit(1); } stat(filename, &sbuf); @@ -394,6 +420,7 @@ } } + old_Xerror = XSetErrorHandler(catch_Xerror); scr = DefaultScreenOfDisplay(dpy); wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); @@ -695,6 +722,15 @@ XtSetArg(args[num_args], XtNforeground, black); num_args++; XtSetArg(args[num_args], XtNbackground, white); num_args++; } + reopenbutton = XtCreateManagedWidget("reopen", smeBSBObjectClass, + filemenu, args, num_args); + XtAddCallback(reopenbutton, XtNcallback, reopen_file, (XtPointer)NULL); + + num_args = 0; + if (special_cmap) { + XtSetArg(args[num_args], XtNforeground, black); num_args++; + XtSetArg(args[num_args], XtNbackground, white); num_args++; + } printwholebutton = XtCreateManagedWidget("printwhole", smeBSBObjectClass, filemenu, args, num_args); XtAddCallback(printwholebutton, XtNcallback, popup_dialog, @@ -1051,7 +1087,7 @@ num_ghosts++; XtAddCallback(page, XtNcallback, track_and_zoom, (XtPointer)0); XtAddCallback(page, XtNdestroyCallback, destroy_ghost, (XtPointer)page); - XtAddCallback(page, XtNmessageCallback, message, (XtPointer)0); + XtAddCallback(page, XtNmessageCallback, message, (XtPointer)page); XtAddCallback(page, XtNoutputCallback, output, (XtPointer)0); num_args = 0; XtSetArg(args[num_args], XtNxdpi, &default_xdpi); num_args++; diff -N -u ghostview-1.3/misc.c ghostview-1.4/misc.c --- ghostview-1.3/misc.c Fri May 8 10:01:36 1992 +++ ghostview-1.4/misc.c Sat Oct 10 15:08:38 1992 @@ -28,7 +28,7 @@ #define SEEK_SET 0 #endif -#include +#include #include #ifdef SIGNALRETURNSINT #define SIGVAL int @@ -57,11 +57,15 @@ #include /* BSD 4.3 errno.h does not declare errno */ extern int errno; +#ifdef VMS +#include +#else extern int sys_nerr; extern char *sys_errlist[]; +#endif #include "Ghostview.h" -#include "ghostview.h" +#include "gv.h" #include "ps.h" #ifndef max @@ -230,6 +234,9 @@ if (number < 0) number = 0; } + if (set_new_orientation(number) || set_new_pagemedia(number)) + layout_ghostview(); + if (toc_text) { int marker; current_page = number; @@ -243,9 +250,9 @@ } else { GhostviewEnableInterpreter(page); GhostviewSendPS(page, psfile, doc->beginprolog, - doc->endprolog, False); + doc->lenprolog, False); GhostviewSendPS(page, psfile, doc->beginsetup, - doc->endsetup, False); + doc->lensetup, False); } if (doc->pageorder == DESCEND) i = (doc->numpages - 1) - current_page; @@ -252,7 +259,7 @@ else i = current_page; GhostviewSendPS(page, psfile, doc->pages[i].begin, - doc->pages[i].end, False); + doc->pages[i].len, False); } else { if (!GhostviewIsInterpreterRunning(page)) GhostviewEnableInterpreter(page); @@ -363,7 +370,8 @@ } /* Build table of contents */ - if (doc && !doc->epsf && doc->numpages) { + if (doc && (!doc->epsf && doc->numpages > 0 || + doc->epsf && doc->numpages > 1)) { int maxlen = 0; int i, j; useful_page_labels = False; @@ -418,6 +426,7 @@ } XtSetValues(toc, args, num_args); + XtSetSensitive(reopenbutton, (psfile != NULL)); XtSetSensitive(printwholebutton, (psfile != NULL)); XtSetSensitive(printmarkedbutton, (psfile != NULL)); XtSetSensitive(savebutton, (toc_text != NULL)); @@ -913,13 +922,22 @@ SIGVAL (*oldsig)(); int bytes; char buf[BUFSIZ]; +#ifdef VMS + char fnam[64], *p; +#endif + Boolean failed; String ret_val; +#ifdef VMS + sprintf(fnam, "sys$scratch:%s.tmp", tmpnam(NULL)); + printer = fopen(fnam, "w"); +#else /* VMS */ if (*name != '\0') { setenv(app_res.printer_variable, name, True); } oldsig = signal(SIGPIPE, SIG_IGN); printer = popen(app_res.print_command, "w"); +#endif /* VMS */ if (toc_text && !whole_mode) { pscopydoc(printer); } else { @@ -928,13 +946,21 @@ bytes = write(fileno(printer), buf, bytes); fclose(psfile); } - if (pclose(printer)) { +#ifdef VMS + sprintf(buf, "%s %s %s", app_res.print_command, name, fnam); + failed = fclose(printer) != 0 || system(buf) != 1; +#else /* VMS */ + failed = pclose(printer) != 0; +#endif /* VMS */ + if (failed) { sprintf(buf, app_res.print_fail, app_res.print_command); ret_val = XtNewString(buf); } else { ret_val = NULL; } +#ifndef VMS signal(SIGPIPE, oldsig); +#endif /* VMS */ return(ret_val); } @@ -1008,12 +1034,12 @@ else j = i; if (toc_text[toc_entry_length * j] == '*') { - comment = pscopyuntil(psfile, fp, doc->pages[j].begin, - doc->pages[j].end, "%%Page:"); + comment = pscopyuntil(psfile, fp, doc->pages[i].begin, + doc->pages[i].end, "%%Page:"); fprintf(fp, "%%%%Page: %s %d\n", - doc->pages[j].label, page++); + doc->pages[i].label, page++); free(comment); - pscopy(psfile, fp, -1, doc->pages[j].end); + pscopy(psfile, fp, -1, doc->pages[i].end); } } @@ -1437,4 +1463,21 @@ if (set_new_orientation(number)) layout_changed = True; if (set_new_pagemedia(number)) layout_changed = True; if (layout_changed) layout_ghostview(); +} + +/* Catch X errors die gracefully if one occurs */ +int +catch_Xerror(dpy, err) + Display *dpy; + XErrorEvent *err; +{ + if (err->error_code == BadImplementation) { + old_Xerror(dpy, err); + return 0; + } + if (dying) return 0; + dying = True; + bomb = *err; + XtDestroyWidget(toplevel); + return 0; } diff -N -u ghostview-1.3/ps.c ghostview-1.4/ps.c --- ghostview-1.3/ps.c Thu Mar 19 19:48:25 1992 +++ ghostview-1.4/ps.c Wed Sep 30 17:01:34 1992 @@ -30,9 +30,14 @@ #ifndef BUFSIZ #define BUFSIZ 1024 #endif +#include #include /* #includes the appropriate */ #include "ps.h" +#ifdef BSD4_2 +#define memset(a,b,c) bzero(a,c) +#endif + /* length calculates string length at compile time */ /* can only be used with character constants */ #define length(a) (sizeof(a)-1) @@ -62,14 +67,8 @@ static char *readline(); - /* Position of file just before the current line was read */ -static long file_position; - static char *gettextline(); static char *gettext(); - /* Pointer to first character after text returned by gettext */ -static char *next_char; - static int isblank(); /* @@ -160,7 +159,7 @@ * Next each page starts explicitly with %%Page and ends implicitly with * %%Page or %%Trailer or %%EOF. The following comments are recognized: * - * %%Page: + * %%Page: * %%PageBoundingBox: |(atend) * %%PageOrientation: Portrait|Landscape * %%PageMedia: @@ -180,7 +179,7 @@ * * + A DC-3 received severe damage to one of its wings. The wing was a total * loss. There was no replacement readily available, so the mechanic - * install a wing from a DC-2. + * installed a wing from a DC-2. */ struct document * @@ -197,13 +196,21 @@ int preread; /* flag which tells the readline isn't needed */ int i; unsigned int maxpages = 0; + unsigned int nextpage = 1; /* Next expected page */ + unsigned int thispage; + int ignore = 0; /* whether to ignore page ordinals */ + char *label; char line[PSLINELENGTH]; /* 255 characters + 1 newline + 1 NULL */ char text[PSLINELENGTH]; /* Temporary storage for text */ + long position; /* Position of the current line */ + unsigned int line_len; /* Length of the current line */ + unsigned int section_len; /* Place to accumulate the section length */ + char *next_char; /* 1st char after text returned by gettext() */ char *cp; struct documentmedia *dmp; rewind(file); - if (readline(line, sizeof line, file) == NULL) { + if (readline(line, sizeof line, file, &position, &line_len) == NULL) { fprintf(stderr, "Warning: empty file.\n"); return(NULL); } @@ -219,17 +226,20 @@ memset(doc, 0, sizeof(struct document)); sscanf(line, "%*s %s", text); doc->epsf = iscomment(text, "EPSF-"); - doc->beginheader = file_position; + doc->beginheader = position; + section_len = line_len; } else { return(NULL); } preread = 0; - while (preread || readline(line, sizeof line, file)) { + while (preread || readline(line, sizeof line, file, &position, &line_len)) { + if (!preread) section_len += line_len; preread = 0; if (iscomment(line, "%%EndComments") || line[0] != '%' || - (line[1] == ' ' || line[1] == '\t' || line[1] == '\n')) { + (!isprint(line[1]) || line[1] == ' ' || + line[1] == '\t' || line[1] == '\n')) { break; } else if (!iscomment(line, "%%")) { /* Do nothing */ @@ -333,7 +343,8 @@ fprintf(stderr, "Fatal Error: Dynamic memory exhausted.\n"); exit(-1); } - doc->media[0].name = gettext(line+length("%%DocumentMedia:")); + doc->media[0].name = gettext(line+length("%%DocumentMedia:"), + &next_char); if (doc->media[0].name != NULL) { if (sscanf(next_char, "%f %f", &w, &h) == 2) { doc->media[0].width = w + 0.5; @@ -345,8 +356,9 @@ free(doc->media[0].name); } preread=1; - while (readline(line, sizeof line, file) && + while (readline(line, sizeof line, file, &position, &line_len) && iscomment(line, "%%+")) { + section_len += line_len; doc->media = (struct documentmedia *) realloc(doc->media, (doc->nummedia+1)* @@ -355,7 +367,8 @@ fprintf(stderr, "Fatal Error: Dynamic memory exhausted.\n"); exit(-1); } - doc->media[doc->nummedia].name = gettext(line+length("%%+")); + doc->media[doc->nummedia].name = gettext(line+length("%%+"), + &next_char); if (doc->media[doc->nummedia].name != NULL) { if (sscanf(next_char, "%f %f", &w, &h) == 2) { doc->media[doc->nummedia].width = w + 0.5; @@ -367,6 +380,7 @@ free(doc->media[doc->nummedia].name); } } + section_len += line_len; if (doc->nummedia != 0) doc->default_page_media = doc->media; } else if (doc->nummedia == NONE && iscomment(line+2, "DocumentPaperSizes:")) { @@ -377,7 +391,8 @@ fprintf(stderr, "Fatal Error: Dynamic memory exhausted.\n"); exit(-1); } - doc->media[0].name = gettext(line+length("%%DocumentPaperSizes:")); + doc->media[0].name = gettext(line+length("%%DocumentPaperSizes:"), + &next_char); if (doc->media[0].name != NULL) { doc->media[0].width = 0; doc->media[0].height = 0; @@ -406,7 +421,7 @@ else free(doc->media[0].name); } - while (cp = gettext(next_char)) { + while (cp = gettext(next_char, &next_char)) { doc->media = (struct documentmedia *) realloc(doc->media, (doc->nummedia+1)* @@ -446,10 +461,11 @@ free(doc->media[doc->nummedia].name); } preread=1; - while (readline(line, sizeof line, file) && + while (readline(line, sizeof line, file, &position, &line_len) && iscomment(line, "%%+")) { + section_len += line_len; next_char = line + length("%%+"); - while (cp = gettext(next_char)) { + while (cp = gettext(next_char, &next_char)) { doc->media = (struct documentmedia *) realloc(doc->media, (doc->nummedia+1)* @@ -480,33 +496,50 @@ free(doc->media[doc->nummedia].name); } } + section_len += line_len; if (doc->nummedia != 0) doc->default_page_media = doc->media; } } - if (iscomment(line, "%%EndComments")) readline(line, sizeof line, file); - doc->endheader = file_position; + if (iscomment(line, "%%EndComments")) { + readline(line, sizeof line, file, &position, &line_len); + section_len += line_len; + } + doc->endheader = position; + doc->lenheader = section_len - line_len; /* Optional Preview comments for encapsulated PostScript files */ - while (isblank(line) && readline(line, sizeof line, file)) {} + while (isblank(line) && + readline(line, sizeof line, file, &position, &line_len)) { + } if (doc->epsf && iscomment(line, "%%BeginPreview")) { - doc->beginpreview = file_position; - while (readline(line, sizeof line, file) && - !iscomment(line, "%%EndPreview")) {} - readline(line, sizeof line, file); - doc->endpreview = file_position; + doc->beginpreview = position; + section_len = line_len; + while (readline(line, sizeof line, file, &position, &line_len) && + !iscomment(line, "%%EndPreview")) { + section_len += line_len; + } + section_len += line_len; + readline(line, sizeof line, file, &position, &line_len); + section_len += line_len; + doc->endpreview = position; + doc->lenpreview = section_len - line_len; } /* Page Defaults for Version 3.0 files */ - while (isblank(line) && readline(line, sizeof line, file)) {} + while (isblank(line) && + readline(line, sizeof line, file, &position, &line_len)) { + } if (iscomment(line, "%%BeginDefaults")) { - doc->begindefaults = file_position; - while (readline(line, sizeof line, file) && + doc->begindefaults = position; + section_len = line_len; + while (readline(line, sizeof line, file, &position, &line_len) && !iscomment(line, "%%EndDefaults")) { + section_len += line_len; if (!iscomment(line, "%%")) { /* Do nothing */ } else if (doc->default_page_orientation == NONE && @@ -519,7 +552,7 @@ } } else if (page_media_set == NONE && iscomment(line+2, "PageMedia:")) { - cp = gettext(line+length("%%PageMedia:")); + cp = gettext(line+length("%%PageMedia:"), NULL); for (dmp = doc->media, i=0; inummedia; i++, dmp++) { if (strcmp(cp, dmp->name) == 0) { doc->default_page_media = dmp; @@ -557,44 +590,59 @@ } } } - readline(line, sizeof line, file); - doc->enddefaults = file_position; + section_len += line_len; + readline(line, sizeof line, file, &position, &line_len); + section_len += line_len; + doc->enddefaults = position; + doc->lendefaults = section_len - line_len; } /* Document Prolog */ - while (isblank(line) && readline(line, sizeof line, file)) {} + while (isblank(line) && + readline(line, sizeof line, file, &position, &line_len)) { + } if (!iscomment(line, "%%BeginSetup") && !iscomment(line, "%%Page:") && !iscomment(line, "%%Trailer") && !iscomment(line, "%%EOF")) { - doc->beginprolog = file_position; + doc->beginprolog = position; + section_len = line_len; preread = 1; - while ((preread || readline(line, sizeof line, file)) && + while ((preread || + readline(line, sizeof line, file, &position, &line_len)) && !iscomment(line, "%%EndProlog") && !iscomment(line, "%%BeginSetup") && !iscomment(line, "%%Page:") && !iscomment(line, "%%Trailer") && !iscomment(line, "%%EOF")) { + if (!preread) section_len += line_len; preread = 0; - } + section_len += line_len; if (iscomment(line, "%%EndProlog")) { - readline(line, sizeof line, file); + readline(line, sizeof line, file, &position, &line_len); + section_len += line_len; } - doc->endprolog = file_position; + doc->endprolog = position; + doc->lenprolog = section_len - line_len; } /* Document Setup, Page Defaults found here for Version 2 files */ - while (isblank(line) && readline(line, sizeof line, file)) {} + while (isblank(line) && + readline(line, sizeof line, file, &position, &line_len)) { + } if (!iscomment(line, "%%Page:") && !iscomment(line, "%%Trailer") && !iscomment(line, "%%EOF")) { - doc->beginsetup = file_position; + doc->beginsetup = position; + section_len = line_len; preread = 1; - while ((preread || readline(line, sizeof line, file)) && + while ((preread || + readline(line, sizeof line, file, &position, &line_len)) && !iscomment(line, "%%EndSetup") && !iscomment(line, "%%Page:") && !iscomment(line, "%%Trailer") && !iscomment(line, "%%EOF")) { + if (!preread) section_len += line_len; preread = 0; if (!iscomment(line, "%%")) { /* Do nothing */ @@ -608,7 +656,7 @@ } } else if (page_media_set == NONE && iscomment(line+2, "PaperSize:")) { - cp = gettext(line+length("%%PaperSize:")); + cp = gettext(line+length("%%PaperSize:"), NULL); for (dmp = doc->media, i=0; inummedia; i++, dmp++) { /* Note: Paper size comment uses down cased paper size * name. Case insensitive compares are only used for @@ -650,16 +698,22 @@ } } } + section_len += line_len; if (iscomment(line, "%%EndSetup")) { - readline(line, sizeof line, file); + readline(line, sizeof line, file, &position, &line_len); + section_len += line_len; } - doc->endsetup = file_position; + doc->endsetup = position; + doc->lensetup = section_len - line_len; } /* Individual Pages */ - while (isblank(line) && readline(line, sizeof line, file)) {} + while (isblank(line) && + readline(line, sizeof line, file, &position, &line_len)) { + } +newpage: while (iscomment(line, "%%Page:")) { if (maxpages == 0) { maxpages = 1; @@ -670,6 +724,17 @@ exit(-1); } } + label = gettext(line+length("%%Page:"), &next_char); + if (sscanf(next_char, "%d", &thispage) != 1) thispage = 0; + if (nextpage == 1) { + ignore = thispage != 1; + } + if (!ignore && thispage != nextpage) { + free(label); + doc->numpages--; + goto continuepage; + } + nextpage++; if (doc->numpages == maxpages) { maxpages++; doc->pages = (struct page *) @@ -681,11 +746,14 @@ } memset(&(doc->pages[doc->numpages]), 0, sizeof(struct page)); page_bb_set = NONE; - doc->pages[doc->numpages].label = gettext(line+length("%%Page:")); - doc->pages[doc->numpages].begin = file_position; - while (readline(line, sizeof line, file) && + doc->pages[doc->numpages].label = label; + doc->pages[doc->numpages].begin = position; + section_len = line_len; +continuepage: + while (readline(line, sizeof line, file, &position, &line_len) && !iscomment(line, "%%Page:") && !iscomment(line, "%%Trailer") && !iscomment(line, "%%EOF")) { + section_len += line_len; if (!iscomment(line, "%%")) { /* Do nothing */ } else if (doc->pages[doc->numpages].orientation == NONE && @@ -698,7 +766,7 @@ } } else if (doc->pages[doc->numpages].media == NULL && iscomment(line+2, "PageMedia:")) { - cp = gettext(line+length("%%PageMedia:")); + cp = gettext(line+length("%%PageMedia:"), NULL); for (dmp = doc->media, i=0; inummedia; i++, dmp++) { if (strcmp(cp, dmp->name) == 0) { doc->pages[doc->numpages].media = dmp; @@ -708,7 +776,7 @@ free(cp); } else if (doc->pages[doc->numpages].media == NULL && iscomment(line+2, "PaperSize:")) { - cp = gettext(line+length("%%PaperSize:")); + cp = gettext(line+length("%%PaperSize:"), NULL); for (dmp = doc->media, i=0; inummedia; i++, dmp++) { /* Note: Paper size comment uses down cased paper size * name. Case insensitive compares are only used for @@ -759,20 +827,33 @@ } } } - doc->pages[doc->numpages].end = file_position; + section_len += line_len; + doc->pages[doc->numpages].end = position; + doc->pages[doc->numpages].len = section_len - line_len; doc->numpages++; } /* Document Trailer */ - doc->begintrailer = file_position; + doc->begintrailer = position; + section_len = line_len; preread = 1; - while ((preread || readline(line, sizeof line, file)) && + while ((preread || + readline(line, sizeof line, file, &position, &line_len)) && !iscomment(line, "%%EOF")) { + if (!preread) section_len += line_len; preread = 0; if (!iscomment(line, "%%")) { /* Do nothing */ + } else if (iscomment(line+2, "Page:")) { + free(gettext(line+length("%%Page:"), &next_char)); + if (sscanf(next_char, "%d", &thispage) != 1) thispage = 0; + if (!ignore && thispage == nextpage) { + doc->pages[doc->numpages-1].end = position; + doc->pages[doc->numpages-1].len += section_len - line_len; + goto newpage; + } } else if (bb_set == ATEND && iscomment(line+2, "BoundingBox:")) { if (sscanf(line+length("%%BoundingBox:"), "%d %d %d %d", &(doc->boundingbox[LLX]), @@ -823,10 +904,31 @@ } } } + section_len += line_len; if (iscomment(line, "%%EOF")) { - readline(line, sizeof line, file); + readline(line, sizeof line, file, &position, &line_len); + section_len += line_len; } - doc->endtrailer = file_position; + doc->endtrailer = position; + doc->lentrailer = section_len - line_len; + + section_len = line_len; + preread = 1; + while (preread || + readline(line, sizeof line, file, &position, &line_len)) { + if (!preread) section_len += line_len; + preread = 0; + if (iscomment(line, "%%Page:")) { + free(gettext(line+length("%%Page:"), &next_char)); + if (sscanf(next_char, "%d", &thispage) != 1) thispage = 0; + if (!ignore && thispage == nextpage) { + doc->pages[doc->numpages-1].end = position; + doc->pages[doc->numpages-1].len += doc->lentrailer + + section_len - line_len; + goto newpage; + } + } + } return doc; } @@ -869,7 +971,7 @@ while (*line && (*line == ' ' || *line == '\t')) line++; if (*line == '(') { - return gettext(line); + return gettext(line, NULL); } else { if (strlen(line) == 0) return NULL; cp = (char *) malloc(strlen(line)); @@ -886,12 +988,12 @@ /* * gettext -- return the next text string on the line. * return NULL if nothing is present. - * NOTE: next_char is modified by this routine. */ static char * -gettext(line) +gettext(line, next_char) char *line; + char **next_char; { char text[PSLINELENGTH]; /* Temporary storage for text */ char *cp; @@ -962,7 +1064,7 @@ *cp++ = *line++; } *cp = '\0'; - next_char = line; + if (next_char) *next_char = line; if (!quoted && strlen(text) == 0) return NULL; cp = (char *) malloc(strlen(text)+1); if (cp == NULL) { @@ -980,56 +1082,118 @@ * comments.) * Also, skip over included documents (as indicated by * %%BeginDocument/%%EndDocument comments.) - * Note: file_position is modified by this routine. */ static char * -readline(line, size, fp) +readline(line, size, fp, position, line_len) char *line; int size; FILE *fp; + long *position; + unsigned int *line_len; { char text[PSLINELENGTH]; /* Temporary storage for text */ + char save[PSLINELENGTH]; /* Temporary storage for text */ char *cp; unsigned int num; + unsigned int nbytes; int i; char buf[BUFSIZ]; - long position; - position = ftell(fp); + if (position) *position = ftell(fp); cp = fgets(line, size, fp); + *line_len = cp ? strlen(line) : 0; if (iscomment(line, "%%BeginDocument:")) { - while (readline(line, size, fp) && !iscomment(line, "%%EndDocument")) {} - cp = readline(line, size, fp); + strcpy(save, line+7); + while (readline(line, size, fp, NULL, &nbytes) && + !iscomment(line, "%%EndDocument")) { + *line_len += nbytes; + } + *line_len += nbytes; + strcpy(line+2, save); + } else if (iscomment(line, "%%BeginFeature:")) { + strcpy(save, line+7); + while (readline(line, size, fp, NULL, &nbytes) && + !iscomment(line, "%%EndFeature")) { + *line_len += nbytes; + } + *line_len += nbytes; + strcpy(line+2, save); + } else if (iscomment(line, "%%BeginFile:")) { + strcpy(save, line+7); + while (readline(line, size, fp, NULL, &nbytes) && + !iscomment(line, "%%EndFile")) { + *line_len += nbytes; + } + *line_len += nbytes; + strcpy(line+2, save); + } else if (iscomment(line, "%%BeginFont:")) { + strcpy(save, line+7); + while (readline(line, size, fp, NULL, &nbytes) && + !iscomment(line, "%%EndFont")) { + *line_len += nbytes; + } + *line_len += nbytes; + strcpy(line+2, save); + } else if (iscomment(line, "%%BeginProcSet:")) { + strcpy(save, line+7); + while (readline(line, size, fp, NULL, &nbytes) && + !iscomment(line, "%%EndProcSet")) { + *line_len += nbytes; + } + *line_len += nbytes; + strcpy(line+2, save); + } else if (iscomment(line, "%%BeginResource:")) { + strcpy(save, line+7); + while (readline(line, size, fp, NULL, &nbytes) && + !iscomment(line, "%%EndResource")) { + *line_len += nbytes; + } + *line_len += nbytes; + strcpy(line+2, save); } else if (iscomment(line, "%%BeginData:")) { text[0] = '\0'; + strcpy(save, line+7); if (sscanf(line+length("%%BeginData:"), "%d %*s %s", &num, text) >= 1) { if (strcmp(text, "Lines") == 0) { for (i=0; i < num; i++) { cp = fgets(line, size, fp); + *line_len += cp ? strlen(line) : 0; } } else { while (num > BUFSIZ) { fread(buf, sizeof (char), BUFSIZ, fp); + *line_len += BUFSIZ; num -= BUFSIZ; } fread(buf, sizeof (char), num, fp); + *line_len += num; } } - while (readline(line, size, fp) && !iscomment(line, "%%EndData")) {} - cp = readline(line, size, fp); + while (readline(line, size, fp, NULL, &nbytes) && + !iscomment(line, "%%EndData")) { + *line_len += nbytes; + } + *line_len += nbytes; + strcpy(line+2, save); } else if (iscomment(line, "%%BeginBinary:")) { + strcpy(save, line+7); if(sscanf(line+length("%%BeginBinary:"), "%d", &num) == 1) { while (num > BUFSIZ) { fread(buf, sizeof (char), BUFSIZ, fp); + *line_len += BUFSIZ; num -= BUFSIZ; } fread(buf, sizeof (char), num, fp); + *line_len += num; + } + while (readline(line, size, fp, NULL, &nbytes) && + !iscomment(line, "%%EndBinary")) { + *line_len += nbytes; } - while (readline(line, size, fp) && !iscomment(line, "%%EndBinary")) {} - cp = readline(line, size, fp); + *line_len += nbytes; + strcpy(line+2, save); } - file_position = position; return cp; } diff -N -u ghostview-1.3/ps.h ghostview-1.4/ps.h --- ghostview-1.3/ps.h Thu Mar 19 19:48:25 1992 +++ ghostview-1.4/ps.h Fri Sep 25 14:59:12 1992 @@ -33,7 +33,10 @@ /* Constants used to index into the bounding box array. */ -enum {LLX, LLY, URX, URY}; +#define LLX 0 +#define LLY 1 +#define URX 2 +#define URY 3 /* Constants used to store keywords that are scanned. */ /* NONE is not a keyword, it tells when a field was not set */ @@ -48,11 +51,17 @@ char *date; /* Creation date. */ int pageorder; /* ASCEND, DESCEND, SPECIAL */ long beginheader, endheader; /* offsets into file */ + unsigned int lenheader; long beginpreview, endpreview; + unsigned int lenpreview; long begindefaults, enddefaults; + unsigned int lendefaults; long beginprolog, endprolog; + unsigned int lenprolog; long beginsetup, endsetup; + unsigned int lensetup; long begintrailer, endtrailer; + unsigned int lentrailer; int boundingbox[4]; int default_page_boundingbox[4]; int orientation; /* PORTRAIT, LANDSCAPE */ @@ -70,6 +79,7 @@ struct documentmedia *media; int orientation; /* PORTRAIT, LANDSCAPE */ long begin, end; /* offsets into file */ + unsigned int len; }; struct documentmedia { diff -N -u ghostview-1.3/run-ad2c ghostview-1.4/run-ad2c --- ghostview-1.3/run-ad2c +++ ghostview-1.4/run-ad2c Mon Sep 21 19:33:13 1992 @@ -0,0 +1 @@ +ad2c ghostview.ad >app-defaults.h diff -N -u ghostview-1.3/setenv.c ghostview-1.4/setenv.c --- ghostview-1.3/setenv.c Wed Apr 15 09:15:45 1992 +++ ghostview-1.4/setenv.c Thu Jun 25 15:39:26 1992 @@ -25,6 +25,10 @@ #include extern char *malloc(); +#ifdef BSD4_2 +#define memcpy(a,b,c) bcopy(b,a,c) +#endif + /* * setenv -- * Set the value of the environmental variable "name" to be @@ -94,6 +98,7 @@ extern char **environ; register char **P; int offset; + char *_findenv(); while (_findenv(name, &offset)) /* if set multiple times */ for (P = &environ[offset];; ++P) diff -N -u ghostview-1.3/strcasecmp.c ghostview-1.4/strcasecmp.c --- ghostview-1.3/strcasecmp.c Tue Jul 23 17:26:25 1991 +++ ghostview-1.4/strcasecmp.c Mon Sep 21 19:13:17 1992 @@ -20,6 +20,10 @@ #include "stdc.h" #include +#ifdef VMS +#include +#endif + #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)strcasecmp.c 5.9 (Berkeley) 6/1/90"; #endif /* LIBC_SCCS and not lint */ diff -N -u ghostview-1.3/vms_build.com ghostview-1.4/vms_build.com --- ghostview-1.3/vms_build.com +++ ghostview-1.4/vms_build.com Tue Aug 18 13:14:31 1992 @@ -0,0 +1,37 @@ +$ @lsrc:[x11]logicals.com !<<< change for your system! +$ copy/log x11_xmu:xmushr.psects,x11_xaw:xawshr.psects,x11_xaw:user.opt gv.opt +$ get_run = 0 +$ get_ad2c = 0 +$ if f$search("run-ad2c.").eqs."" then get_run = 1 +$ if f$search("ad2c.").eqs."" then get_ad2c = 1 +$ if get_run then cms fetch run-ad2c. +$ if get_ad2c then cms fetch ad2c. +$ posix/run posix$bin:sh. run-ad2c +$ if get_run then delete run-ad2c.;* +$ if get_ad2c then delete ad2c.;* +$ CC /NOLIST/OBJECT=MAIN.OBJ MAIN.C +$ If "''F$Search("GV.OLB")'" .EQS. "" Then LIBRARY/Create GV.OLB +$ LIBRARY/REPLACE GV.OLB MAIN.OBJ +$ CC /NOLIST/OBJECT=MISC.OBJ MISC.C +$ If "''F$Search("GV.OLB")'" .EQS. "" Then LIBRARY/Create GV.OLB +$ LIBRARY/REPLACE GV.OLB MISC.OBJ +$ CC /NOLIST/OBJECT=CALLBACKS.OBJ CALLBACKS.C +$ If "''F$Search("GV.OLB")'" .EQS. "" Then LIBRARY/Create GV.OLB +$ LIBRARY/REPLACE GV.OLB CALLBACKS.OBJ +$ CC /NOLIST/OBJECT=ACTIONS.OBJ ACTIONS.C +$ If "''F$Search("GV.OLB")'" .EQS. "" Then LIBRARY/Create GV.OLB +$ LIBRARY/REPLACE GV.OLB ACTIONS.OBJ +$ CC /NOLIST/OBJECT=DIALOGS.OBJ DIALOGS.C +$ If "''F$Search("GV.OLB")'" .EQS. "" Then LIBRARY/Create GV.OLB +$ LIBRARY/REPLACE GV.OLB DIALOGS.OBJ +$ CC /NOLIST/OBJECT=GHOSTVIEW.OBJ GHOSTVIEW.C +$ If "''F$Search("GV.OLB")'" .EQS. "" Then LIBRARY/Create GV.OLB +$ LIBRARY/REPLACE GV.OLB GHOSTVIEW.OBJ +$ CC /NOLIST/OBJECT=PS.OBJ PS.C +$ If "''F$Search("GV.OLB")'" .EQS. "" Then LIBRARY/Create GV.OLB +$ LIBRARY/REPLACE GV.OLB PS.OBJ +$ CC /NOLIST/OBJECT=STRCASECMP.OBJ STRCASECMP.C +$ If "''F$Search("GV.OLB")'" .EQS. "" Then LIBRARY/Create GV.OLB +$ LIBRARY/REPLACE GV.OLB STRCASECMP.OBJ +$ continue +$ LINK /TRACE/NOMAP/EXEC=GV.EXE /exe=gv.exe gv.olb/include=main/library,gv.opt/opt diff -N -u ghostview-1.3/vms_types.h ghostview-1.4/vms_types.h --- ghostview-1.3/vms_types.h +++ ghostview-1.4/vms_types.h Tue Aug 18 13:14:32 1992 @@ -0,0 +1,351 @@ +/* DEC/CMS REPLACEMENT HISTORY, Element VMS_TYPES.H */ +/* *4 13-AUG-1992 12:49:50 TP "Added IOSB_GET_T" */ +/* *3 10-AUG-1992 14:20:29 TP "MOVE" */ +/* *2 10-AUG-1992 14:19:45 TP "MOVE" */ +/* *1 10-AUG-1992 14:19:31 TP "VMS data type definitions and macros" */ +/* DEC/CMS REPLACEMENT HISTORY, Element VMS_TYPES.H */ +/* VMS_TYPES.H +**============================================================================= +** Copyright (C) 1989 Jym Dyer (jym@wheaties.ai.mit.edu) +** +** 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 1, 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. +**----------------------------------------------------------------------------- +** Version: V1.0-001 +**----------------------------------------------------------------------------- +** Facility: None +**----------------------------------------------------------------------------- +** Prefix: None +**----------------------------------------------------------------------------- +** Abstract +** ~~~~~~~~ +** These are typedefs and macro functions for various VMS data types. +**----------------------------------------------------------------------------- +** Contents +** ~~~~~~~~ +** EXIT_BLOCK_T +** IOSB_T +** IOSB_ACP_T +** IOSB_CR_T +** IOSB_DISK_T +** IOSB_DISK_SENSEMODE_T +** IOSB_LPA_T +** IOSB_LP_WRITE_T +** IOSB_LP_SETMODE_T +** IOSB_MBX_READ_T +** IOSB_MBX_WRITE_T +** IOSB_MBX_SETPROTECTION_T +** IOSB_MT_T +** IOSB_TTY_ITEMLIST_READ_T +** IOSB_TTY_READ_T +** IOSB_TTY_SETSENSE_T +** IOSB_TTY_WRITE_T +** ITEM_2_T +** ITEM_3_T +** ITEM_LIST_2_T() +** ITEM_LIST_3_T() +**----------------------------------------------------------------------------- +** Environment +** ~~~~~~~~~~~ +** Should be portable to any compiler running on VMS. +**----------------------------------------------------------------------------- +** Author: Jym Dyer - 15-May-1989 +**----------------------------------------------------------------------------- +** Modifications +** ~~~~~~~~~~~~~ +** 1.0-001 - Original version. {Jym 15-May-1989} +** 1.0-002 - Added IOSB_GET_T {Terry Poot 8/10/1992} +**============================================================================= +*/ + +#ifndef __VMS_TYPES_H__ +#define __VMS_TYPES_H__ + +/* -=- MACRO FUNCTIONS AND TYPEDEFS -=- */ + +/* --- Exit Handler Block --- */ + +/* The exit handler block is a variable-length structure. What we provide +** here is a header for that structure. For the simplest uses (exit +** handlers that don't take arguments) the typedef alone will suffice: +** +** extern void exit_function(unsigned int * status_p); +** unsigned int exh_status; +** . . . +** EXIT_BLOCK_T exit_block = +** {NULL,exit_function,0,{0,0,0},&exh_status}; +** . . . +** void +** exit_function(status_p) +** unsigned int * status_p; +** { +** . . . +** +** For more complicated uses (when you want to pass several arguments to +** the exit handler) the typedef can be used as a header in a structure: +** +** extern void exit_function( +** unsigned int * status_p,int * yin_p,int * yang_p +** ); +** unsigned int exh_status; +** int that; +** int this; +** . . . +** struct +** { +** EXIT_BLOCK_T header; +** int * this_p; +** int * that_p; +** } = {{NULL,exit_function,0,{0,0,0},&exh_status},&this,&that}; +** . . . +** void +** exit_function(status_p,yin_p,yang_p) +** unsigned int * status_p; +** int * yin_p; +** int * yang_p; +** { +** . . . +*/ + +typedef struct +{ + void * flink_p; + void (*exit_handler_p)(); + unsigned char arg_count; + unsigned char must_be_zero[3]; + unsigned int * status_p; +} EXIT_BLOCK_T; + +/* --- All-Purpose IOSB --- */ + +/* This all-purpose IOSB can be used for any IO function (though it could +** be a bit of a hassle with terminal set and sense functions). Just be +** careful with the device dependent data, remembering to use casts where +** appropriate. Use of the other IOSB typedefs is recommended over use of +** this one, as their fields have more relevant names. +*/ + +typedef struct +{ + unsigned short int status; + unsigned short int count; + unsigned char device_dependent_data[4]; +} IOSB_T; + +/* --- Ancillary Control Process (ACP) IOSB --- */ + +typedef struct +{ + unsigned short int status; + unsigned short int not_used_0; + unsigned long int not_used_1; +} IOSB_ACP_T; + +/* --- CR11 Card Reader IOSB --- */ + +/* Identical to the all-purpose IOSB. +*/ + +#define IOSB_CR_T IOSB_T + +/* --- Disk Device IOSBs --- */ + +/* IOSB_DISK_T is for all disk device functions except for sense mode; +** IOSB_DISK_SENSEMODE_T is for sense mode. +*/ + +typedef struct +{ + unsigned short int status; + unsigned short int byte_count_low_order; + unsigned short int byte_count_high_order; + unsigned short int zero; +} IOSB_DISK_T; + +typedef struct +{ + unsigned short int status; + unsigned short int zero; + unsigned char sectors; + unsigned char tracks; + unsigned short int cylinders; +} IOSB_DISK_SENSEMODE_T; + +/* --- Laboratory Peripheral Accelarator (LPA) IOSB --- */ + +typedef struct +{ + unsigned short int status; + unsigned short int byte_count; + unsigned short int ready_out; + unsigned short int maintenance_status; +} IOSB_LPA_T; + +/* --- Line Printer IOSBs --- */ + +/* IOSB_LP_WRITE_T is for write functions; IOSB_LP_SETMODE_T is for +** set mode functions. IOSB_LP_SETMODE_T is identical to IOSB_ACP_T. +*/ + +typedef struct +{ + unsigned short int status; + unsigned short int byte_count; + unsigned long int num_lines_paper_moved; +} IOSB_LP_WRITE_T; + +#define IOSB_LP_SETMODE_T IOSB_ACP_T + +/* --- Magnetic Tape IOSB --- */ + +/* Identical to the all-purpose IOSB. +*/ + +#define IOSB_MT_T IOSB_T + +/* --- Mailbox (MBX) IOSBs --- */ + +/* IOSB_MBX_READ_T is for the read function; IOSB_MBX_WRITE_T +** is for the write function; IOSB_MBX_SETPROTECTION_T is for +** the set protection function. +*/ + +typedef struct +{ + unsigned short int status; + unsigned short int byte_count; + unsigned long int sender_pid; +} IOSB_MBX_READ_T; + +typedef struct +{ + unsigned short int status; + unsigned short int byte_count; + unsigned long int receiver_pid; +} IOSB_MBX_WRITE_T; + +typedef struct +{ + unsigned short int status; + unsigned short int zero; + unsigned long int protection_mask_value; +} IOSB_MBX_SETPROTECTION_T; + +/* --- Terminal (TTY) IOSBs --- */ + +/* IOSB_TTY_READ_T is for the read function; IOSB_TTY_ITEMLIST_READ_T +** is for the itemlist read function; IOSB_TTY_WRITE_T is for the +** write function; IOSB_TTY_SETSENSE_T is for the set mode, set +** characteristscs, sense mode, and sense characteristics functions. +*/ + +typedef struct +{ + unsigned short int status; + unsigned short int offset_to_terminator; + unsigned short int terminator; + unsigned short int terminator_size; +} IOSB_TTY_READ_T; + +typedef struct +{ + unsigned short int status; + unsigned short int offset_to_terminator; + unsigned char terminator_character; + unsigned char reserved; + unsigned char terminator_length; + unsigned char cursor_position_from_eol; +} IOSB_TTY_ITEMLIST_READ_T; + +typedef struct +{ + unsigned short int status; + unsigned short int byte_count; + unsigned short int zero_0; + unsigned short int zero_1; +} IOSB_TTY_WRITE_T; + +typedef struct +{ + unsigned short int status; + unsigned char transmit_speed; + unsigned char receive_speed; + unsigned char cr_fill_count; + unsigned char lf_fill_count; + unsigned char parity_flags; + unsigned char zero; +} IOSB_TTY_SETSENSE_T; + +/* Many of the VMS GETxxx system services also use IOSB's, but they are laid +** out differently. IOSB_GET_T is such a structure. The first longword (not +** word) is the status code, and the second word is reserved to DEC. +*/ + +typedef struct +{ + unsigned long int status; + unsigned long int reserved; +} IOSB_GET_T; + +/* --- Item Lists --- */ + +/* The item list structures change dynamically according to the number +** of items in them. For this reason, typedefs (ITEM_2_T and ITEM_3_T) +** are provided for the items, and macro functions (ITEM_LIST_2_T() and +** ITEM_LIST_3_T()) are provided for the item lists. Here is an example +** showing the usage of an item list macro function: +** +** static const ITEM_LIST_3_T(item_list,2) = +** { +** { +** {sizeof pid,JPI$_PID,&pid,NULL}, +** {sizeof username,JPI$_USERNAME,&username,&username_length} +** }, +** 0 +** }; +** +** The number 2 means, of course, that there are two items in the +** itemlist (i.e., the PID and the username). +*/ + +typedef struct +{ + unsigned short int component_size; + unsigned short int item_code; + void * component_p; +} ITEM_2_T; + +typedef struct +{ + unsigned short int buffer_size; + unsigned short int item_code; + void * buffer_p; + unsigned short int * buffer_length_p; +} ITEM_3_T; + +#define ITEM_LIST_2_T(variable_name,num_items) \ + struct \ + { \ + ITEM_2_T item[num_items]; \ + int terminating_zero; \ + } variable_name + +#define ITEM_LIST_3_T(variable_name,num_items) \ + struct \ + { \ + ITEM_3_T item[num_items]; \ + int terminating_zero; \ + } variable_name + +#endif /* !__VMS_TYPES_H__ */