diff options
Diffstat (limited to 'support/hypertex/tanmoy/ghostview-1.5-hacked/misc.c')
-rw-r--r-- | support/hypertex/tanmoy/ghostview-1.5-hacked/misc.c | 1314 |
1 files changed, 1314 insertions, 0 deletions
diff --git a/support/hypertex/tanmoy/ghostview-1.5-hacked/misc.c b/support/hypertex/tanmoy/ghostview-1.5-hacked/misc.c new file mode 100644 index 0000000000..6c2d9bccd8 --- /dev/null +++ b/support/hypertex/tanmoy/ghostview-1.5-hacked/misc.c @@ -0,0 +1,1314 @@ +/* + * misc.c -- Everything that isn't a callback or action. + * 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 + */ +/* This file is part of the hacked version of the ghostview package */ +/* which is distributed under the terms of the gnu license. The */ +/* modification referred to above is by Tanmoy Bhattacharya, */ +/* <tanmoy@qcd.lanl.gov> on Nov 17, 1994. Neither the modification, */ +/* nor the original program provides any warranty. */ + +#include <stdio.h> +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#include <X11/Xos.h> +#include <signal.h> +#ifdef SIGNALRETURNSINT +#define SIGVAL int +#else +#define SIGVAL void +#endif + +#include <math.h> + +#include <X11/Xatom.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Shell.h> +#include <X11/Xaw/Cardinals.h> +#include <X11/Xaw/Form.h> +#include <X11/Xaw/SimpleMenu.h> +#include <X11/Xaw/SmeBSB.h> +#include <X11/Xaw/SmeLine.h> +#include <X11/Xaw/Scrollbar.h> +#include <X11/Xaw/AsciiText.h> +/* Yuck, cannot get vScrollbar via the usual methods */ +#include <X11/IntrinsicP.h> +#include <X11/Xaw/TextP.h> +#include <X11/Xmu/StdCmap.h> + +#include <errno.h> +/* BSD 4.3 errno.h does not declare errno */ +extern int errno; +#ifdef VMS +#include <perror.h> +#else +extern int sys_nerr; +extern char *sys_errlist[]; +#endif + +#include "Ghostview.h" +#include "gv.h" +#include "ps.h" +#include "pdf.h" + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +/* Translate orientations defined by the enum in "ps.h" to + * XtPageOrientations defined in "Ghostview.h". + */ +static XtPageOrientation +xorient(psorient) + int psorient; +{ + switch (psorient) { + case PORTRAIT: return XtPageOrientationPortrait; + case LANDSCAPE: + if (app_res.swap_landscape) { + return XtPageOrientationSeascape; + } else { + return XtPageOrientationLandscape; + } + } +} + +static void +break_chains() +{ + Arg args[2]; + XtSetArg(args[0], XtNbottom, XtChainTop); + XtSetArg(args[1], XtNright, XtChainLeft); + XtSetValues(toc, args, ONE); + XtSetValues(pageview, args, TWO); +} + +static void +set_chains() +{ + Arg args[2]; + + XtSetArg(args[0], XtNbottom, XtChainBottom); + XtSetArg(args[1], XtNright, XtChainRight); + XtSetValues(toc, args, ONE); + XtSetValues(pageview, args, TWO); +} + +static void +reset_size_hints() +{ + Arg args[4]; + if (app_res.ncdwm) return; + XtSetArg(args[0], XtNmaxWidth, XtUnspecifiedShellInt); + XtSetArg(args[1], XtNmaxHeight, XtUnspecifiedShellInt); + XtSetArg(args[2], XtNminWidth, XtUnspecifiedShellInt); + XtSetArg(args[3], XtNminHeight, XtUnspecifiedShellInt); + XtSetValues(toplevel, args, FOUR); +} + +static void +set_size_hints(minw, minh, maxw, maxh) + Dimension minw, minh, maxw, maxh; +{ + Arg args[4]; + + XtSetArg(args[0], XtNminWidth, minw); + XtSetArg(args[1], XtNminHeight, minh); + XtSetArg(args[2], XtNmaxWidth, maxw); + XtSetArg(args[3], XtNmaxHeight, maxh); + XtSetValues(toplevel, args, FOUR); +} + +static Boolean horiz_scroll_saved = False; +static Boolean vert_scroll_saved = False; +static float horiz_top; +static float vert_top; + +static void +reset_scroll_bars() +{ + Arg args[1]; + Widget scroll; + float zero = 0.0; + + if (horiz_scroll_saved || vert_scroll_saved) return; + + scroll = XtNameToWidget(pageview, "horizontal"); + if (scroll) { + XtSetArg(args[0], XtNtopOfThumb, &horiz_top); + XtGetValues(scroll, args, ONE); + XtCallCallbacks(scroll, XtNjumpProc, &zero); + horiz_scroll_saved = True; + } + + scroll = XtNameToWidget(pageview, "vertical"); + if (scroll) { + XtSetArg(args[0], XtNtopOfThumb, &vert_top); + XtGetValues(scroll, args, ONE); + XtCallCallbacks(scroll, XtNjumpProc, &zero); + vert_scroll_saved = True; + } +} + +static void +set_scroll_bars() +{ + Arg args[1]; + Widget scroll; + float shown; + + if (horiz_scroll_saved) { + scroll = XtNameToWidget(pageview, "horizontal"); + if (scroll) { + XtSetArg(args[0], XtNshown, &shown); + XtGetValues(scroll, args, ONE); + if (horiz_top > (1.0 - shown)) horiz_top = (1.0 - shown); + XtCallCallbacks(scroll, XtNjumpProc, &horiz_top); + } + } + + if (vert_scroll_saved) { + scroll = XtNameToWidget(pageview, "vertical"); + if (scroll) { + XtSetArg(args[0], XtNshown, &shown); + XtGetValues(scroll, args, ONE); + if (vert_top > (1.0 - shown)) vert_top = (1.0 - shown); + XtCallCallbacks(scroll, XtNjumpProc, &vert_top); + } + } + + horiz_scroll_saved = vert_scroll_saved = False; +} + +/* Start rendering a new page */ +void +show_page(number) + int number; +{ + 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; + } + pdf_clear(); + + 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 { + if (!GhostviewIsInterpreterRunning(page)) + GhostviewEnableInterpreter(page); + else if (GhostviewIsInterpreterReady(page)) + GhostviewNextPage(page); + else + XBell(XtDisplay(page), 0); + } + + if (toc_text) { + XtSetSensitive(prevbutton, current_page != 0); + XtSetSensitive(nextbutton, current_page != doc->numpages-1); + XtSetSensitive(showbutton, True); + } +} + +/* setup ghostview. This includes: + * scanning the PostScript file, + * setting the title and date labels, + * building the pagemedia menu, + * building the toc (table of contents) + * sensitizing the appropriate menu buttons, + * popping down and erasing the infotext popup. + */ + +static Boolean useful_page_labels; +Boolean +setup_ghostview() +{ + Arg args[20]; + Cardinal num_args; + int oldtoc_entry_length; + char *tocp; + XawTextBlock message_block; + static String nothing = ""; + String label; + Pixmap bitmap; + + /* Reset to a known state. */ + psfree(olddoc); + olddoc = doc; + doc = NULL; + current_page = -1; + if (toc_text) XtFree(toc_text); + oldtoc_entry_length = toc_entry_length; + toc_text = NULL; + + /* Scan document and start setting things up */ + if (psfile) doc = psscan(psfile); + + if (app_res.show_title) { + if (doc && doc->title) { + label = doc->title; + bitmap = menu16_bitmap; + } else { + if (filename) { + label = filename; + } else { + label = ""; + } + bitmap = None; + } + XtSetArg(args[0], XtNlabel, label); + XtSetValues(titlebutton, args, ONE); + if (titlemenu) XtDestroyWidget(titlemenu); + titlemenu = build_label_menu(titlebutton, "title", label, bitmap); + } + + if (app_res.show_date) { + if (doc && doc->date) { + label = doc->date; + bitmap = menu16_bitmap; + } else { + if (psfile) { + label = ctime(&mtime); + } else { + label = ""; + } + bitmap = None; + } + XtSetArg(args[0], XtNlabel, label); + XtSetValues(datebutton, args, ONE); + if (datemenu) XtDestroyWidget(datemenu); + datemenu = build_label_menu(datebutton, "date", label, bitmap); + } + + build_pagemedia_menu(); + + /* Reset ghostscript and output messages popup */ + if (!doc || !olddoc || + strcmp(oldfilename, filename) || + olddoc->beginprolog != doc->beginprolog || + olddoc->endprolog != doc->endprolog || + olddoc->beginsetup != doc->beginsetup || + olddoc->endsetup != doc->endsetup) { + + GhostviewDisableInterpreter(page); + XtPopdown(infopopup); + info_up = False; + XtSetArg(args[0], XtNeditType, XawtextEdit); + XtSetArg(args[1], XtNinsertPosition, 0); + XtSetValues(infotext, args, TWO); + message_block.length = 0; + XawTextReplace(infotext, 0, info_length, &message_block); + info_length = 0; + XtSetArg(args[0], XtNeditType, XawtextRead); + XtSetValues(infotext, args, ONE); + } + + /* Build table of contents */ + if (doc && (!doc->epsf && doc->numpages > 0 || + doc->epsf && doc->numpages > 1)) { + int maxlen = 0; + int i, j; + useful_page_labels = False; + + if (doc->numpages == 1) useful_page_labels = True; + for (i = 1; i < doc->numpages; i++) + if (useful_page_labels = (useful_page_labels || + strcmp(doc->pages[i-1].label, doc->pages[i].label))) break; + if (useful_page_labels) { + for (i = 0; i < doc->numpages; i++) + maxlen = max(maxlen, strlen(doc->pages[i].label)); + } else { + double x; + x = doc->numpages; + maxlen = log10(x) + 1; + } + toc_entry_length = maxlen + 3; + toc_length = doc->numpages * toc_entry_length - 1; + toc_text = XtMalloc(toc_length + 2); /* include final NULL */ + + for (i = 0, tocp = toc_text; i < doc->numpages; + i++, tocp += toc_entry_length) { + if (useful_page_labels) { + if (doc->pageorder == DESCEND) { + j = (doc->numpages - 1) - i; + } else { + j = i; + } + sprintf(tocp, " %*s \n", maxlen, doc->pages[j].label); + } else { + sprintf(tocp, " %*d \n", maxlen, i+1); + } + } + toc_text[toc_length] = '\0'; + num_args = 0; + XtSetArg(args[num_args], XtNfilename, NULL); num_args++; + XtSetValues(page, args, num_args); + } else { + toc_length = 0; + toc_entry_length = 3; + num_args = 0; + XtSetArg(args[num_args], XtNfilename, filename); num_args++; + XtSetValues(page, args, num_args); + } + num_args = 0; + XtSetArg(args[num_args], XtNlength, toc_length); num_args++; + if (toc_text) { + XtSetArg(args[num_args], XtNstring, toc_text); num_args++; + } else { + /* Text widget sometime blows up when given a NULL pointer */ + XtSetArg(args[num_args], XtNstring, nothing); num_args++; + } + XtSetValues(toc, args, num_args); + + XtSetSensitive(reopenbutton, (psfile != NULL)); + XtSetSensitive(printwholebutton, (psfile != NULL)); + XtSetSensitive(printmarkedbutton, (psfile != NULL)); + XtSetSensitive(savebutton, (toc_text != NULL)); + XtSetSensitive(nextbutton, (filename != NULL)); + XtSetSensitive(showbutton, (filename != NULL)); + XtSetSensitive(prevbutton, (toc_text != NULL)); + XtSetSensitive(centerbutton, (filename != NULL)); + XtSetSensitive(markbutton, (toc_text != NULL)); + XtSetSensitive(unmarkbutton, (toc_text != NULL)); + + return oldtoc_entry_length != toc_entry_length; +} + +int +find_page(label) + String label; +{ + int i, j; + + if (label == NULL || doc == NULL) return 0; + + if (useful_page_labels) { + for (i = 0; i < doc->numpages; i++) { + if (doc->pageorder == DESCEND) { + j = (doc->numpages - 1) - i; + } else { + j = i; + } + if (!strcmp(label, doc->pages[j].label)) return i; + } + return 0; + } else { + return atoi(label) - 1; + } +} + +/* try_try_again sets the geometry of the form when the form failed + * to do it earlier. It uses activity check with exponential backoff + * to make sure that the dust has settled before trying again. + */ +static unsigned int delay = 125; /* Start with 1/8 second delay */ + +static void +try_try_again(client_data, timer) + XtPointer client_data; + XtIntervalId *timer; +{ + XSync(XtDisplay(toplevel), False); /* Push everything out */ + if (XtAppPending(app_con)) { + XtAppAddTimeOut(app_con, delay, try_try_again, NULL); + /* fprintf(stderr, "Delaying(%d)...\n",delay); */ + delay *= 2; + } else { + /* fprintf(stderr, "Trying again...\n"); */ + layout_ghostview(); + } +} + +/* set the dimensions for items in the main form widget. */ +/* set foreground and background color in scrollbars. */ +/* (The scroll bars come and go as size changes.) */ +/* Set window manager hints to keep window manager from causing main */ +/* viewport from growing too large */ +void +layout_ghostview() +{ + Arg args[20]; + Dimension min_width, min_height; + Dimension max_width, max_height; + Dimension form_width, form_height; + Dimension title_height, title_border; + Dimension date_height, date_border; + Dimension locator_height, locator_border; + Dimension box_width, box_height, box_border; + Dimension label_width; + Dimension toc_width, toc_height, toc_border; + Dimension view_width, view_height, view_border; + Dimension page_width, page_height; + Dimension leftMargin, rightMargin; + Dimension width, height; + Boolean correct = True; + int distance; + int a_label; + XFontStruct *font; + + XawFormDoLayout(form, False); + reset_size_hints(); + reset_scroll_bars(); + break_chains(); + + XtSetArg(args[0], XtNdefaultDistance, &distance); + XtGetValues(form, args, ONE); + + a_label = 0; + if (app_res.show_title) { + XtSetArg(args[0], XtNheight, &title_height); + XtSetArg(args[1], XtNborderWidth, &title_border); + XtGetValues(titlebutton, args, TWO); + a_label = 1; + } else { + title_height = title_border = 0; + } + + if (app_res.show_date) { + XtSetArg(args[0], XtNheight, &date_height); + XtSetArg(args[1], XtNborderWidth, &date_border); + XtGetValues(datebutton, args, TWO); + a_label = 1; + } else { + date_height = date_border = 0; + } + + if (app_res.show_locator) { + XtSetArg(args[0], XtNheight, &locator_height); + XtSetArg(args[1], XtNborderWidth, &locator_border); + XtGetValues(locator, args, TWO); + a_label = 1; + } else { + locator_height = locator_border = 0; + } + + XtSetArg(args[0], XtNwidth, &box_width); + XtSetArg(args[1], XtNheight, &box_height); + XtSetArg(args[2], XtNborderWidth, &box_border); + XtGetValues(box, args, THREE); + + XtSetArg(args[0], XtNfont, &font); + XtSetArg(args[1], XtNleftMargin, &leftMargin); + XtSetArg(args[2], XtNrightMargin, &rightMargin); + XtSetArg(args[3], XtNborderWidth, &toc_border); + XtGetValues(toc, args, FOUR); + toc_width = font->max_bounds.width * (toc_entry_length - 1) + + leftMargin + rightMargin; + + XtSetArg(args[0], XtNwidth, &page_width); + XtSetArg(args[1], XtNheight, &page_height); + XtGetValues(page, args, TWO); + + XtSetArg(args[0], XtNborderWidth, &view_border); + XtGetValues(pageview, args, ONE); + view_width = page_width; + view_height = page_height; + + min_width = box_width + 2*box_border + toc_width + 2*toc_border + + 2*view_border + 4*distance; + min_height = title_height + 2*title_border + date_height + 2*date_border + + locator_height + 2*locator_border + box_height + 2*box_border + + (2+a_label)*distance; + + max_width = WidthOfScreen(XtScreen(toplevel)) - app_res.wm_horiz_margin; + max_height = HeightOfScreen(XtScreen(toplevel)) - app_res.wm_vert_margin; + + if (min_width + view_width > max_width) + view_width = max_width - min_width; + if (2*(view_border + distance) + view_height > max_height) + view_height = max_height - 2*(view_border + distance); + form_width = view_width + min_width; + form_height = max(view_height + 2*(view_border + distance), min_height); + toc_height = view_height - (title_height + 2*title_border + + date_height + 2*date_border + + locator_height + 2*locator_border + + a_label*distance); + + label_width = box_width + 2*box_border + distance + + toc_width + 2*toc_border; + + XtSetArg(args[0], XtNwidth, form_width); + XtSetArg(args[1], XtNheight, form_height); + XtSetValues(form, args, TWO); + + XtSetArg(args[0], XtNwidth, label_width); + if (app_res.show_title) XtSetValues(titlebutton, args, ONE); + if (app_res.show_date) XtSetValues(datebutton, args, ONE); + if (app_res.show_locator) XtSetValues(locator, args, ONE); + + XtSetArg(args[0], XtNwidth, toc_width); + XtSetArg(args[1], XtNheight, toc_height); + XtSetValues(toc, args, TWO); + + XtSetArg(args[0], XtNwidth, view_width); + XtSetArg(args[1], XtNheight, view_height); + XtSetValues(pageview, args, TWO); + + XawFormDoLayout(form, True); + + /* Check to make sure everything was done as planned. */ + XtSetArg(args[0], XtNwidth, &width); + XtSetArg(args[1], XtNheight, &height); + + XtGetValues(form, args, TWO); + if (width != form_width || height != form_height) { + correct = False; + /* fprintf(stderr, "Oops, %dx%d form was supposed to be %dx%d.\n", + width, height, form_width, form_height); */ + } + if (app_res.show_title) { + XtGetValues(titlebutton, args, ONE); + if (width != label_width) { + correct = False; + /* fprintf(stderr, + "Oops, %d wide title was supposed to be %d wide.\n", + width, label_width); */ + } + } + if (app_res.show_date) { + XtGetValues(datebutton, args, ONE); + if (width != label_width) { + correct = False; + /* fprintf(stderr, + "Oops, %d wide date was supposed to be %d wide.\n", + width, label_width); */ + } + } + if (app_res.show_locator) { + XtGetValues(locator, args, ONE); + if (width != label_width) { + correct = False; + /* fprintf(stderr, + "Oops, %d wide locator was supposed to be %d wide.\n", + width, label_width); */ + } + } + XtGetValues(toc, args, TWO); + if (width != toc_width || height != toc_height) { + correct = False; + /* fprintf(stderr, "Oops, %dx%d toc was supposed to be %dx%d.\n", + width, height, toc_width, toc_height); */ + } + XtGetValues(pageview, args, TWO); + if (width != view_width || height != view_height) { + correct = False; + /* fprintf(stderr, "Oops, %dx%d pageview was supposed to be %dx%d.\n", + width, height, view_width, view_height); */ + } + + if (correct) { + set_size_hints(min_width, min_height, min_width+page_width, + max(form_height, + page_height + 2*(view_border + distance))); + if (app_res.auto_center) { + horiz_scroll_saved = vert_scroll_saved = False; + center_page(form, NULL, NULL); + } else { + set_scroll_bars(); + } + set_chains(); + delay = 125; /* Reset to 1/8 second delay */ + /* fprintf(stderr, "Layout correct.\n"); */ + } else { + XSync(XtDisplay(toplevel), False); + XtAppAddTimeOut(app_con, delay, try_try_again, NULL); + /* fprintf(stderr, "Didn't work, scheduling(%d)...\n",delay); */ + } + +} + +/* Compute new dpi from magstep */ +void +magnify(dpi, magstep) + float *dpi; + int magstep; +{ + if (magstep < 0) { + while (magstep++) *dpi /= 1.2; + } else { + while (magstep--) *dpi *= 1.2; + } +} + +/* Attempt to open file, return error message string on failure */ +String +open_file(name) + String name; +{ + FILE *fp; + struct stat sbuf; + + if (*name == '\0') { /* Null filename */ + return(NULL); + } + if (strcmp(name, "-")) { + if ((fp = fopen(name, "r")) == NULL) { + String buf = XtMalloc(strlen(app_res.open_fail) + + strlen(sys_errlist[errno]) + 1); + strcpy(buf, app_res.open_fail); + if (errno <= sys_nerr) strcat(buf, sys_errlist[errno]); + return buf; + } else { + if (oldfilename) XtFree(oldfilename); + oldfilename = filename; + filename = XtNewString(name); + if (psfile) fclose(psfile); + psfile = fp; + stat(filename, &sbuf); + mtime = sbuf.st_mtime; + new_file(0); + show_page(0); + return(NULL); + } + } else { + if (oldfilename) XtFree(oldfilename); + oldfilename = filename; + filename = XtNewString(name); + if (psfile) fclose(psfile); + psfile = NULL; + new_file(0); + show_page(0); + return(NULL); + } +} + +/* Attempt to save file, return error message string on failure */ +String +save_file(name) + String name; +{ + FILE *pswrite; + + if (*name == '\0') { /* Null filename */ + return(NULL); + } + if ((pswrite = fopen(name, "w")) == NULL) { + String buf = XtMalloc(strlen(app_res.save_fail) + + strlen(sys_errlist[errno]) + 1); + strcpy(buf, app_res.save_fail); + if (errno <= sys_nerr) strcat(buf, sys_errlist[errno]); + return buf; + } else { + pscopydoc(pswrite); + fclose(pswrite); + return(NULL); + } +} + +/* Attempt to print file. Return error string on failure */ +String +print_file(name, whole_mode) + String name; + Boolean whole_mode; +{ + FILE *printer; + 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 { + FILE *psfile = fopen(filename, "r"); + while (bytes = read(fileno(psfile), buf, BUFSIZ)) + bytes = write(fileno(printer), buf, bytes); + fclose(psfile); + } +#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); +} + +/* length calculates string length at compile time */ +/* can only be used with character constants */ +#define length(a) (sizeof(a)-1) + +/* Copy the headers, marked pages, and trailer to fp */ +void +pscopydoc(fp) + FILE *fp; +{ + FILE *psfile; + char text[PSLINELENGTH]; + char *comment; + Boolean pages_written = False; + Boolean pages_atend = False; + Boolean marked_pages = False; + int pages = 0; + int page = 1; + int i, j; + long here; + + psfile = fopen(filename, "r"); + + for (i = 0; i < doc->numpages; i++) { + if (toc_text[toc_entry_length * i] == '*') pages++; + } + + if (pages == 0) { /* User forgot to mark the pages */ + mark_page(form, NULL, NULL); + marked_pages = True; + for (i = 0; i < doc->numpages; i++) { + if (toc_text[toc_entry_length * i] == '*') pages++; + } + } + + here = doc->beginheader; + while (comment = pscopyuntil(psfile, fp, here, + doc->endheader, "%%Pages:")) { + here = ftell(psfile); + if (pages_written || pages_atend) { + free(comment); + continue; + } + sscanf(comment+length("%%Pages:"), "%s", text); + if (strcmp(text, "(atend)") == 0) { + fputs(comment, fp); + pages_atend = True; + } else { + switch (sscanf(comment+length("%%Pages:"), "%*d %d", &i)) { + case 1: + fprintf(fp, "%%%%Pages: %d %d\n", pages, i); + break; + default: + fprintf(fp, "%%%%Pages: %d\n", pages); + break; + } + pages_written = True; + } + free(comment); + } + pscopy(psfile, fp, doc->beginpreview, doc->endpreview); + pscopy(psfile, fp, doc->begindefaults, doc->enddefaults); + pscopy(psfile, fp, doc->beginprolog, doc->endprolog); + pscopy(psfile, fp, doc->beginsetup, doc->endsetup); + + for (i = 0; i < doc->numpages; i++) { + if (doc->pageorder == DESCEND) + j = (doc->numpages - 1) - i; + else + j = i; + if (toc_text[toc_entry_length * j] == '*') { + comment = pscopyuntil(psfile, fp, doc->pages[i].begin, + doc->pages[i].end, "%%Page:"); + fprintf(fp, "%%%%Page: %s %d\n", + doc->pages[i].label, page++); + free(comment); + pscopy(psfile, fp, -1, doc->pages[i].end); + } + } + + here = doc->begintrailer; + while (comment = pscopyuntil(psfile, fp, here, + doc->endtrailer, "%%Pages:")) { + here = ftell(psfile); + if (pages_written) { + free(comment); + continue; + } + switch (sscanf(comment+length("%%Pages:"), "%*d %d", &i)) { + case 1: + fprintf(fp, "%%%%Pages: %d %d\n", pages, i); + break; + default: + fprintf(fp, "%%%%Pages: %d\n", pages); + break; + } + pages_written = True; + free(comment); + } + fclose(psfile); + + if (marked_pages) unmark_page(form, NULL, NULL); +} +#undef length + +/* position popup window under the cursor */ +void +positionpopup(w) + Widget w; +{ + Arg args[3]; + Cardinal num_args; + Dimension width, height, b_width; + int x, y, max_x, max_y; + Window root, child; + int dummyx, dummyy; + unsigned int dummymask; + + XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y, + &dummyx, &dummyy, &dummymask); + num_args = 0; + XtSetArg(args[num_args], XtNwidth, &width); num_args++; + XtSetArg(args[num_args], XtNheight, &height); num_args++; + XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++; + XtGetValues(w, args, num_args); + + width += 2 * b_width; + height += 2 * b_width; + + x -= ( (Position) width/2 ); + if (x < 0) x = 0; + if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x; + + y -= ( (Position) height/2 ); + if (y < 0) y = 0; + if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y; + + num_args = 0; + XtSetArg(args[num_args], XtNx, x); num_args++; + XtSetArg(args[num_args], XtNy, y); num_args++; + XtSetValues(w, args, num_args); +} + +/* Set new magstep */ +Boolean +set_new_magstep() +{ + int new_magstep; + Boolean changed = False; + Arg args[20]; + Cardinal num_args; + float xdpi, ydpi; + + new_magstep = app_res.magstep; + /* If magstep changed, stop interpreter and setup for new dpi. */ + if (new_magstep != current_magstep) { + GhostviewDisableInterpreter(page); + XawFormDoLayout(form, False); + reset_size_hints(); + reset_scroll_bars(); + break_chains(); + changed = True; + xdpi = default_xdpi; + ydpi = default_ydpi; + magnify(&xdpi, new_magstep); + magnify(&ydpi, new_magstep); + num_args = 0; + XtSetFloatArg(args[num_args], XtNxdpi, xdpi); num_args++; + XtSetFloatArg(args[num_args], XtNydpi, ydpi); num_args++; + XtSetValues(page, args, num_args); + + XtSetArg(args[0], XtNleftBitmap, None); + XtSetValues(magstepentry[current_magstep - app_res.minimum_magstep], + args, ONE); + current_magstep = new_magstep; + } + XtSetArg(args[0], XtNleftBitmap, dot_bitmap); + XtSetValues(magstepentry[current_magstep - app_res.minimum_magstep], + args, ONE); + + return changed; +} + +/* Set new orientation */ +Boolean +set_new_orientation(number) + int number; +{ + Boolean changed = False; + Boolean from_doc = False; + Arg args[1]; + XtPageOrientation new_orientation; + + if (app_res.force_orientation) { + new_orientation = app_res.orientation; + } else { + if (doc) { + if (toc_text && doc->pages[number].orientation != NONE) { + new_orientation = xorient(doc->pages[number].orientation); + from_doc = True; + } else if (doc->default_page_orientation != NONE) { + new_orientation = xorient(doc->default_page_orientation); + from_doc = True; + } else if (doc->orientation != NONE) { + new_orientation = xorient(doc->orientation); + from_doc = True; + } else { + new_orientation = app_res.orientation; + } + } else { + new_orientation = app_res.orientation; + } + } + + /* If orientation changed, + * stop interpreter and setup for new orientation. */ + if (new_orientation != current_orientation) { + GhostviewDisableInterpreter(page); + XawFormDoLayout(form, False); + reset_size_hints(); + reset_scroll_bars(); + break_chains(); + changed = True; + XtSetArg(args[0], XtNorientation, new_orientation); + XtSetValues(page, args, ONE); + XtSetArg(args[0], XtNleftBitmap, None); + if (current_orientation == XtPageOrientationPortrait) + XtSetValues(portraitbutton, args, ONE); + else if (current_orientation == XtPageOrientationLandscape) + XtSetValues(landscapebutton, args, ONE); + else if (current_orientation == XtPageOrientationUpsideDown) + XtSetValues(upsidedownbutton, args, ONE); + else if (current_orientation == XtPageOrientationSeascape) + XtSetValues(seascapebutton, args, ONE); + current_orientation = new_orientation; + } + + /* mark forced orientation with tie fighter. ("Use the force, Luke") */ + if (app_res.force_orientation) { + XtSetArg(args[0], XtNleftBitmap, tie_fighter_bitmap); + } else if (from_doc) { + XtSetArg(args[0], XtNleftBitmap, menu16_bitmap); + } else { + XtSetArg(args[0], XtNleftBitmap, dot_bitmap); + } + if (current_orientation == XtPageOrientationPortrait) + XtSetValues(portraitbutton, args, ONE); + else if (current_orientation == XtPageOrientationLandscape) + XtSetValues(landscapebutton, args, ONE); + else if (current_orientation == XtPageOrientationUpsideDown) + XtSetValues(upsidedownbutton, args, ONE); + else if (current_orientation == XtPageOrientationSeascape) + XtSetValues(seascapebutton, args, ONE); + + return changed; +} + +/* Set new pagemedia */ +Boolean +set_new_pagemedia(number) + int number; +{ + int new_pagemedia; + int new_llx; + int new_lly; + int new_urx; + int new_ury; + Boolean changed = False; + Boolean from_doc = False; + Arg args[4]; + + if (force_document_media) { + new_pagemedia = document_media; + } else if (app_res.force_pagemedia) { + new_pagemedia = default_pagemedia; + } else { + if (doc) { + if (toc_text && doc->pages[number].media != NULL) { + new_pagemedia = doc->pages[number].media - doc->media; + from_doc = True; + } else if (doc->default_page_media != NULL) { + new_pagemedia = doc->default_page_media - doc->media; + from_doc = True; + } else { + new_pagemedia = default_pagemedia; + } + } else { + new_pagemedia = default_pagemedia; + } + } + + /* If pagemedia changed, remove the old marker. */ + if (new_pagemedia != current_pagemedia) { + XtSetArg(args[0], XtNleftBitmap, None); + if (pagemediaentry[current_pagemedia]) + XtSetValues(pagemediaentry[current_pagemedia], args, ONE); + else + XtSetValues(pagemediaentry[current_pagemedia-1], args, ONE); + + current_pagemedia = new_pagemedia; + } + + /* mark forced page media with tie fighter. ("Use the force, Luke") */ + if (force_document_media || app_res.force_pagemedia) { + XtSetArg(args[0], XtNleftBitmap, tie_fighter_bitmap); + } else if (from_doc) { + XtSetArg(args[0], XtNleftBitmap, menu16_bitmap); + } else { + XtSetArg(args[0], XtNleftBitmap, dot_bitmap); + } + if (pagemediaentry[current_pagemedia]) + XtSetValues(pagemediaentry[current_pagemedia], args, ONE); + else + XtSetValues(pagemediaentry[current_pagemedia-1], args, ONE); + + /* Compute bounding box */ + if (!force_document_media && !app_res.force_pagemedia && + doc && doc->epsf && + /* Ignore malformed bounding boxes */ + (doc->boundingbox[URX] > doc->boundingbox[LLX]) && + (doc->boundingbox[URY] > doc->boundingbox[LLY])) { + new_llx = doc->boundingbox[LLX]; + new_lly = doc->boundingbox[LLY]; + new_urx = doc->boundingbox[URX]; + new_ury = doc->boundingbox[URY]; + } else { + new_llx = new_lly = 0; + if (new_pagemedia < base_papersize) { + new_urx = doc->media[new_pagemedia].width; + new_ury = doc->media[new_pagemedia].height; + } else { + new_urx = papersizes[new_pagemedia-base_papersize].width; + new_ury = papersizes[new_pagemedia-base_papersize].height; + } + } + + /* If bounding box changed, setup for new size. */ + if ((new_llx != current_llx) || (new_lly != current_lly) || + (new_urx != current_urx) || (new_ury != current_ury)) { + GhostviewDisableInterpreter(page); + XawFormDoLayout(form, False); + reset_size_hints(); + reset_scroll_bars(); + break_chains(); + changed = True; + current_llx = new_llx; + current_lly = new_lly; + current_urx = new_urx; + current_ury = new_ury; + XtSetArg(args[0], XtNllx, current_llx); + XtSetArg(args[1], XtNlly, current_lly); + XtSetArg(args[2], XtNurx, current_urx); + XtSetArg(args[3], XtNury, current_ury); + XtSetValues(page, args, FOUR); + } + + return changed; +} + +static Boolean +same_document_media() +{ + int i; + + if (olddoc == NULL && doc == NULL) return True; + if (olddoc == NULL || doc == NULL) return False; + if (olddoc->nummedia != doc->nummedia) return False; + for (i = 0; i < doc->nummedia; i++) + if (strcmp(olddoc->media[i].name, doc->media[i].name)) return False; + return True; +} + +void +build_pagemedia_menu() +{ + Arg args[20]; + Cardinal num_args; + Widget w; + int i; + + if (pagemediamenu && same_document_media()) return; + if (pagemediamenu) XtDestroyWidget(pagemediamenu); + force_document_media = False; + + pagemediamenu = XtCreatePopupShell("menu", simpleMenuWidgetClass, + pagemediabutton, NULL, ZERO); + + /* Build the Page Media menu */ + /* the Page media menu has two parts. + * - the document defined page medias + * - the standard page media defined from Adobe's PPD + */ + base_papersize = 0; + if (doc) base_papersize = doc->nummedia; + for (i = 0; papersizes[i].name; i++) {} /* Count the standard entries */ + i += base_papersize; + pagemediaentry = (Widget *) XtMalloc(i * sizeof(Widget)); + + if (doc && doc->nummedia) { + for (i = 0; i < doc->nummedia; i++) { + num_args = 0; + XtSetArg(args[num_args], XtNleftMargin, 20); num_args++; + pagemediaentry[i] = XtCreateManagedWidget(doc->media[i].name, + smeBSBObjectClass, pagemediamenu, + args, num_args); + XtAddCallback(pagemediaentry[i], XtNcallback, + set_pagemedia, (XtPointer)i); + } + + num_args = 0; + w = XtCreateManagedWidget("line", smeLineObjectClass, pagemediamenu, + args, num_args); + } + + for (i = 0; papersizes[i].name; i++) { + pagemediaentry[i+base_papersize] = NULL; + if (i > 0) { + /* Skip over same paper size with small imageable area */ + if ((papersizes[i].width == papersizes[i-1].width) && + (papersizes[i].height == papersizes[i-1].height)) { + continue; + } + } + num_args = 0; + XtSetArg(args[num_args], XtNleftMargin, 20); num_args++; + pagemediaentry[i+base_papersize] = XtCreateManagedWidget( + papersizes[i].name, + smeBSBObjectClass, pagemediamenu, + args, num_args); + XtAddCallback(pagemediaentry[i+base_papersize], XtNcallback, + set_pagemedia, (XtPointer)(i+base_papersize)); + } +} + +Widget +build_label_menu(parent, name, label, bitmap) + Widget parent; + String name, label; + Pixmap bitmap; +{ + Arg args[20]; + Cardinal num_args; + Widget menu, entry; + num_args = 0; + menu = XtCreatePopupShell("menu", simpleMenuWidgetClass, + parent, args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, label); num_args++; + if (bitmap) { + XtSetArg(args[num_args], XtNleftMargin, 20); num_args++; + XtSetArg(args[num_args], XtNleftBitmap, bitmap); num_args++; + } + entry = XtCreateManagedWidget(name, smeBSBObjectClass, + menu, args, num_args); + return menu; +} + +void +new_file(number) + int number; +{ + Boolean layout_changed = False; + + if (setup_ghostview()) layout_changed = True; + + /* 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)) 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; +} |