#line 15 "postscript.c-nw" static char copyright[] = "Copyright NBBI, Den Haag, 1995"; #include #include #include #include #include #include #include #include #include #include #include "Ghostview.h" #define XtSetFloatArg(arg, n, d) \ do { \ if (sizeof(float) > sizeof(XtArgVal)) { \ XtSetArg(arg, n, &(d)); \ } else { \ XtArgVal *ld = (XtArgVal *)&(d); \ XtSetArg(arg, n, *ld); \ } \ } while (0) typedef struct { Widget w; /* Ghostview widget */ char *filename; /* Temp file */ FILE *f; /* Temp file */ int page; /* Page number */ } *Info; typedef struct _Assoc { /* Keeps id/Info pairs */ long id; Info b; struct _Assoc *next; } *Assoc; static Assoc assoclist = NULL; /* store -- store an ID/Info combination */ static void store(Info b, long id) { Assoc h; new(h); h->id = id; h->b = b; h->next = assoclist; assoclist = h; } /* delete -- delete an ID/Info combination */ static void delete(long id) { Assoc g, h; assert(assoclist); if (assoclist->id == id) { h = assoclist; assoclist = assoclist->next; dispose(h); } else { assert(assoclist->next); for (h = assoclist; h->next->id != id; h = h->next) assert(h->next); g = h->next; h->next = g->next; dispose(g); } } /* find -- find the Info associated with an ID */ static Info find(long id) { Assoc h; assert(assoclist); for (h = assoclist; h->id != id; h = h->next) assert(h->next); return h->b; } /* destroy_ghost -- ensure that ghostscript is killed. */ static void destroy_ghost(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { GhostviewDisableInterpreter((Widget) client_data); } /* output -- display output from ghostscript */ static void output(Widget w, XtPointer client_data, XtPointer call_data) { XtAppWarning(XtWidgetToApplicationContext(w), (String) call_data); } /* show_page -- start rendering a new page */ static void show_page(Info info) { #if 0 struct stat sbuf; int i; if (!filename) return; /* Unmark current_page as current */ if (toc_text && (current_page >= 0)) { int marker = current_page*toc_entry_length + toc_entry_length-2; toc_text[marker] = ' '; XawTextInvalidate(toc, marker, marker+1); } /* If the file has changed, rescan it so that offsets into the file * are still correct. If the file is rescanned, we must setup ghostview * again. Also, force a new copy of ghostscript to start. */ if (psfile) { if (!stat(filename, &sbuf) && mtime != sbuf.st_mtime) { fclose(psfile); psfile = fopen(filename, "r"); mtime = sbuf.st_mtime; if (oldfilename) XtFree(oldfilename); oldfilename = XtNewString(filename); new_file(number); } } /* Coerce page number to fall in range */ if (toc_text) { if (number >= doc->numpages) number = doc->numpages - 1; if (number < 0) number = 0; } if (set_new_orientation(number) || set_new_pagemedia(number)) layout_ghostview(); if (toc_text) { int marker; current_page = number; XawTextUnsetSelection(toc); XawTextSetInsertionPoint(toc, current_page * toc_entry_length); marker = current_page*toc_entry_length + toc_entry_length-2; toc_text[marker] = '<'; XawTextInvalidate(toc, marker, marker+1); if (GhostviewIsInterpreterReady(page)) { GhostviewNextPage(page); } else { GhostviewEnableInterpreter(page); GhostviewSendPS(page, psfile, doc->beginprolog, doc->lenprolog, False); GhostviewSendPS(page, 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].len, False); } else { #endif if (!GhostviewIsInterpreterRunning(info->w)) GhostviewEnableInterpreter(info->w); else if (GhostviewIsInterpreterReady(info->w)) GhostviewNextPage(info->w); else XBell(XtDisplay(info->w), 0); #if 0 } if (toc_text) { XtSetSensitive(prevbutton, current_page != 0); XtSetSensitive(nextbutton, current_page != doc->numpages-1); XtSetSensitive(showbutton, True); } #endif } /* next_page -- callback for next page button */ static void next_page(Widget w, XtPointer client_data, XtPointer call_data) { Info info = (Info) client_data; info->page++; show_page(info); } /* to_start -- callback for to-start button */ static void to_start(Widget w, XtPointer client_data, XtPointer call_data) { Info info = (Info) client_data; GhostviewDisableInterpreter(info->w); info->page = 0; show_page(info); } /* zoom_in -- callback for zoom-in button */ static void zoom_in(Widget w, XtPointer client_data, XtPointer call_data) { Info info = (Info) client_data; float dpi; Arg args[20]; Cardinal num_args; XtVaGetValues(info->w, XtNxdpi, &dpi, NULL); dpi *= 1.2; num_args = 0; XtSetFloatArg(args[num_args], XtNxdpi, dpi); num_args++; XtSetFloatArg(args[num_args], XtNydpi, dpi); num_args++; XtSetValues(info->w, args, num_args); /* show_page(info); */ } /* zoom_out -- callback for zoom-out button */ static void zoom_out(Widget w, XtPointer client_data, XtPointer call_data) { Info info = (Info) client_data; float dpi; Arg args[20]; Cardinal num_args; XtVaGetValues(info->w, XtNxdpi, &dpi, NULL); dpi /= 1.2; num_args = 0; XtSetFloatArg(args[num_args], XtNxdpi, dpi); num_args++; XtSetFloatArg(args[num_args], XtNydpi, dpi); num_args++; XtSetValues(info->w, args, num_args); /* show_page(info); */ } static void nyi(Widget w, XtPointer client_data, XtPointer call_data) { XtAppWarning(XtWidgetToApplicationContext(w), "This function of the Postscript viewer\n\ is not yet implemented,\n\ sorry."); } /* initPostScript -- initialize class variables for the viewer */ EXPORT Bool initPostscript(char ***mime_types, int *nrtypes, float **qual) { static char *types[] = {"application/postscript"}; static float pref[] = {0.5}; *mime_types = types; *nrtypes = XtNumber(types); *qual = pref; return TRUE; /* Nothing to initialize */ } #line 265 "postscript.c-nw" /* openPostScript -- open a PostScript viewer */ EXPORT Bool openPostscript(const W3ADocumentInfo doc, W3AWindow area, long id) { Info info; Widget form, prev, next, scroll, zoomin, zoomout, tostart, toend; new(info); store(info, id); info->filename = newstring(tmpnam(NULL)); info->f = fopen(info->filename, "w"); info->page = 0; form = XtVaCreateManagedWidget ("postscript", xmFormWidgetClass, area, NULL); prev = XtVaCreateManagedWidget ("prev", xmPushButtonWidgetClass, form, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 50, XmNbottomAttachment, XmATTACH_FORM, NULL); next = XtVaCreateManagedWidget ("next", xmPushButtonWidgetClass, form, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, prev, XmNbottomAttachment, XmATTACH_FORM, NULL); zoomout = XtVaCreateManagedWidget ("zoom-out", xmPushButtonWidgetClass, form, XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL); zoomin = XtVaCreateManagedWidget ("zoom-in", xmPushButtonWidgetClass, form, XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget, zoomout, XmNbottomAttachment, XmATTACH_FORM, NULL); tostart = XtVaCreateManagedWidget ("to-start", xmPushButtonWidgetClass, form, XmNleftAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL); toend = XtVaCreateManagedWidget ("to-end", xmPushButtonWidgetClass, form, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, tostart, XmNbottomAttachment, XmATTACH_FORM, NULL); #if 0 (void) XtVaCreateManagedWidget ("separator", xmSeparatorGadgetClass, form, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, next, XmNrightAttachment, XmATTACH_WIDGET, XmNleftWidget, tostart, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, next, XmNbottomAttachment, XmATTACH_FORM, XmNorientation, XmVERTICAL, NULL); (void) XtVaCreateManagedWidget ("separator", xmSeparatorGadgetClass, form, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, toend, XmNrightAttachment, XmATTACH_WIDGET, XmNleftWidget, zoomin, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, next, XmNbottomAttachment, XmATTACH_FORM, XmNorientation, XmVERTICAL, NULL); #endif scroll = XtVaCreateManagedWidget ("scrollledwindow", xmScrolledWindowWidgetClass, form, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, next, XmNrightAttachment, XmATTACH_FORM, XmNscrollingPolicy, XmAUTOMATIC, NULL); info->w = XtVaCreateManagedWidget ("canvas", ghostviewWidgetClass, scroll, XtNfilename, info->filename, NULL); XtAddCallback(info->w, XtNdestroyCallback, destroy_ghost, info->w); XtAddCallback(info->w, XtNoutputCallback, output, NULL); XtAddCallback(next, XmNactivateCallback, next_page, info); XtAddCallback(prev, XmNactivateCallback, nyi, info); XtAddCallback(tostart, XmNactivateCallback, to_start, info); XtAddCallback(toend, XmNactivateCallback, nyi, info); XtAddCallback(zoomin, XmNactivateCallback, zoom_in, info); XtAddCallback(zoomout, XmNactivateCallback, zoom_out, info); return TRUE; } /* writeExtern -- copy data to external viewer */ EXPORT int writePostscript(long id, const char *buf, size_t nchars) { Info info = find(id); int n; if (nchars != 0) { while ((n = fwrite(buf, 1, nchars, info->f)) == -1 && errno == EINTR) ; return n; } else { /* End of input */ return fclose(info->f); } } /* closeExtern -- close external viewer */ EXPORT Bool closePostscript(long id) { Info info = find(id); (void) fclose(info->f); (void) unlink(info->filename); XtDestroyWidget(info->w); dispose(info); delete(id); return TRUE; } /* infoExtern -- change document info, if needed */ EXPORT Bool infoPostscript(long id, W3ADocumentInfo *info) { return TRUE; /* No changes */ } EXPORT void eventPostscript(long id, long sourceid, long eventtype, void *params) { /* Doesn't handle W3A events */ }