summaryrefslogtreecommitdiff
path: root/support/hypertex/tanmoy/ghostview-1.5-hacked/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'support/hypertex/tanmoy/ghostview-1.5-hacked/misc.c')
-rw-r--r--support/hypertex/tanmoy/ghostview-1.5-hacked/misc.c1314
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;
+}