"Fossies" - the Fresh Open Source Software Archive

Member "ghostview-1.5/misc.c" (24 Jul 1993, 36416 Bytes) of package /linux/misc/old/ghost/gnu/ghostview/ghostview-1.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * misc.c -- Everything that isn't a callback or action.
    3  * Copyright (C) 1992  Timothy O. Theisen
    4  *
    5  * This program is free software; you can redistribute it and/or modify
    6  * it under the terms of the GNU General Public License as published by
    7  * the Free Software Foundation; either version 2 of the License, or
    8  * (at your option) any later version.
    9  *
   10  * This program is distributed in the hope that it will be useful,
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  * GNU General Public License for more details.
   14  *
   15  * You should have received a copy of the GNU General Public License
   16  * along with this program; if not, write to the Free Software
   17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   18  *
   19  *   Author: Tim Theisen           Systems Programmer
   20  * Internet: tim@cs.wisc.edu       Department of Computer Sciences
   21  *     UUCP: uwvax!tim             University of Wisconsin-Madison
   22  *    Phone: (608)262-0438         1210 West Dayton Street
   23  *      FAX: (608)262-9777         Madison, WI   53706
   24  */
   25 
   26 #include <stdio.h>
   27 #ifndef SEEK_SET
   28 #define SEEK_SET 0
   29 #endif
   30 
   31 #include <X11/Xos.h>
   32 #include <signal.h>
   33 #ifdef SIGNALRETURNSINT
   34 #define SIGVAL int
   35 #else
   36 #define SIGVAL void
   37 #endif
   38 
   39 #include <math.h>
   40 
   41 #include <X11/Xatom.h>
   42 #include <X11/Intrinsic.h>
   43 #include <X11/StringDefs.h>
   44 #include <X11/Shell.h>
   45 #include <X11/Xaw/Cardinals.h>
   46 #include <X11/Xaw/Form.h>
   47 #include <X11/Xaw/SimpleMenu.h>
   48 #include <X11/Xaw/SmeBSB.h>
   49 #include <X11/Xaw/SmeLine.h>
   50 #include <X11/Xaw/Scrollbar.h>
   51 #include <X11/Xaw/AsciiText.h>
   52 /* Yuck, cannot get vScrollbar via the usual methods */
   53 #include <X11/IntrinsicP.h>
   54 #include <X11/Xaw/TextP.h>
   55 #include <X11/Xmu/StdCmap.h>
   56 
   57 #include <errno.h>
   58 /* BSD 4.3 errno.h does not declare errno */
   59 extern int errno;
   60 #ifdef VMS
   61 #include <perror.h>
   62 #else
   63 extern int sys_nerr;
   64 extern char *sys_errlist[];
   65 #endif
   66 
   67 #include "Ghostview.h"
   68 #include "gv.h"
   69 #include "ps.h"
   70 
   71 #ifndef max
   72 #define max(a, b)   ((a) > (b) ? (a) : (b))
   73 #endif
   74 
   75 /* Translate orientations defined by the enum in "ps.h" to
   76  * XtPageOrientations defined in "Ghostview.h".
   77  */
   78 static XtPageOrientation
   79 xorient(psorient)
   80     int psorient;
   81 {
   82     switch (psorient) {
   83     case PORTRAIT: return XtPageOrientationPortrait;
   84     case LANDSCAPE:
   85     if (app_res.swap_landscape) {
   86         return XtPageOrientationSeascape;
   87     } else {
   88         return XtPageOrientationLandscape;
   89     }
   90     }
   91 }
   92 
   93 static void
   94 break_chains()
   95 {
   96     Arg args[2];
   97     XtSetArg(args[0], XtNbottom, XtChainTop);
   98     XtSetArg(args[1], XtNright, XtChainLeft);
   99     XtSetValues(toc, args, ONE);
  100     XtSetValues(pageview, args, TWO);
  101 }
  102 
  103 static void
  104 set_chains()
  105 {
  106     Arg args[2];
  107 
  108     XtSetArg(args[0], XtNbottom, XtChainBottom);
  109     XtSetArg(args[1], XtNright, XtChainRight);
  110     XtSetValues(toc, args, ONE);
  111     XtSetValues(pageview, args, TWO);
  112 }
  113 
  114 static void
  115 reset_size_hints()
  116 {
  117     Arg args[4];
  118     if (app_res.ncdwm) return;
  119     XtSetArg(args[0], XtNmaxWidth, XtUnspecifiedShellInt);
  120     XtSetArg(args[1], XtNmaxHeight, XtUnspecifiedShellInt);
  121     XtSetArg(args[2], XtNminWidth, XtUnspecifiedShellInt);
  122     XtSetArg(args[3], XtNminHeight, XtUnspecifiedShellInt);
  123     XtSetValues(toplevel, args, FOUR);
  124 }
  125 
  126 static void
  127 set_size_hints(minw, minh, maxw, maxh)
  128     Dimension minw, minh, maxw, maxh;
  129 {
  130     Arg args[4];
  131 
  132     XtSetArg(args[0], XtNminWidth, minw);
  133     XtSetArg(args[1], XtNminHeight, minh);
  134     XtSetArg(args[2], XtNmaxWidth, maxw);
  135     XtSetArg(args[3], XtNmaxHeight, maxh);
  136     XtSetValues(toplevel, args, FOUR);
  137 }
  138 
  139 static Boolean horiz_scroll_saved = False;
  140 static Boolean vert_scroll_saved = False;
  141 static float horiz_top;
  142 static float vert_top;
  143 
  144 static void
  145 reset_scroll_bars()
  146 {
  147     Arg args[1];
  148     Widget scroll;
  149     float zero = 0.0;
  150     
  151     if (horiz_scroll_saved || vert_scroll_saved) return;
  152 
  153     scroll = XtNameToWidget(pageview, "horizontal");
  154     if (scroll) {
  155     XtSetArg(args[0], XtNtopOfThumb, &horiz_top);
  156     XtGetValues(scroll, args, ONE);
  157     XtCallCallbacks(scroll, XtNjumpProc, &zero);
  158     horiz_scroll_saved = True;
  159     }
  160 
  161     scroll = XtNameToWidget(pageview, "vertical");
  162     if (scroll) {
  163     XtSetArg(args[0], XtNtopOfThumb, &vert_top);
  164     XtGetValues(scroll, args, ONE);
  165     XtCallCallbacks(scroll, XtNjumpProc, &zero);
  166     vert_scroll_saved = True;
  167     }
  168 }
  169 
  170 static void
  171 set_scroll_bars()
  172 {
  173     Arg args[1];
  174     Widget scroll;
  175     float shown;
  176 
  177     if (horiz_scroll_saved) {
  178     scroll = XtNameToWidget(pageview, "horizontal");
  179     if (scroll) {
  180         XtSetArg(args[0], XtNshown, &shown);
  181         XtGetValues(scroll, args, ONE);
  182         if (horiz_top > (1.0 - shown)) horiz_top = (1.0 - shown);
  183         XtCallCallbacks(scroll, XtNjumpProc, &horiz_top);
  184     }
  185     }
  186 
  187     if (vert_scroll_saved) {
  188     scroll = XtNameToWidget(pageview, "vertical");
  189     if (scroll) {
  190         XtSetArg(args[0], XtNshown, &shown);
  191         XtGetValues(scroll, args, ONE);
  192         if (vert_top > (1.0 - shown)) vert_top = (1.0 - shown);
  193         XtCallCallbacks(scroll, XtNjumpProc, &vert_top);
  194     }
  195     }
  196 
  197     horiz_scroll_saved = vert_scroll_saved = False;
  198 }
  199 
  200 /* Start rendering a new page */
  201 void
  202 show_page(number)
  203     int number;
  204 {
  205     struct stat sbuf;
  206     int i;
  207 
  208     if (!filename) return;
  209 
  210     /* Unmark current_page as current */
  211     if (toc_text && (current_page >= 0)) {
  212     int marker = current_page*toc_entry_length + toc_entry_length-2;
  213     toc_text[marker] = ' ';
  214     XawTextInvalidate(toc, marker, marker+1);
  215     }
  216 
  217     /* If the file has changed, rescan it so that offsets into the file
  218      * are still correct.  If the file is rescanned, we must setup ghostview
  219      * again.  Also, force a new copy of ghostscript to start. */
  220     if (psfile) {
  221     if (!stat(filename, &sbuf) && mtime != sbuf.st_mtime) {
  222         fclose(psfile);
  223         psfile = fopen(filename, "r");
  224         mtime = sbuf.st_mtime;
  225         if (oldfilename) XtFree(oldfilename);
  226         oldfilename = XtNewString(filename);
  227         new_file(number);
  228     }
  229     }
  230 
  231     /* Coerce page number to fall in range */
  232     if (toc_text) {
  233     if (number >= doc->numpages) number = doc->numpages - 1;
  234     if (number < 0) number = 0;
  235     }
  236 
  237     if (set_new_orientation(number) || set_new_pagemedia(number))
  238     layout_ghostview();
  239 
  240     if (toc_text) {
  241     int marker;
  242     current_page = number;
  243     XawTextUnsetSelection(toc);
  244     XawTextSetInsertionPoint(toc, current_page * toc_entry_length);
  245     marker = current_page*toc_entry_length + toc_entry_length-2;
  246     toc_text[marker] = '<';
  247     XawTextInvalidate(toc, marker, marker+1);
  248     if (GhostviewIsInterpreterReady(page)) {
  249         GhostviewNextPage(page);
  250     } else {
  251         GhostviewEnableInterpreter(page);
  252         GhostviewSendPS(page, psfile, doc->beginprolog,
  253                 doc->lenprolog, False);
  254         GhostviewSendPS(page, psfile, doc->beginsetup,
  255                 doc->lensetup, False);
  256     }
  257     if (doc->pageorder == DESCEND)
  258         i = (doc->numpages - 1) - current_page;
  259     else
  260         i = current_page;
  261     GhostviewSendPS(page, psfile, doc->pages[i].begin,
  262             doc->pages[i].len, False);
  263     } else {
  264     if (!GhostviewIsInterpreterRunning(page))
  265         GhostviewEnableInterpreter(page);
  266     else if (GhostviewIsInterpreterReady(page))
  267         GhostviewNextPage(page);
  268     else
  269         XBell(XtDisplay(page), 0);
  270     }
  271 
  272     if (toc_text) {
  273     XtSetSensitive(prevbutton, current_page != 0);
  274     XtSetSensitive(nextbutton, current_page != doc->numpages-1);
  275     XtSetSensitive(showbutton, True);
  276     }
  277 }
  278 
  279 /* setup ghostview.  This includes:
  280  *  scanning the PostScript file,
  281  *  setting the title and date labels,
  282  *  building the pagemedia menu,
  283  *  building the toc (table of contents)
  284  *  sensitizing the appropriate menu buttons,
  285  *  popping down and erasing the infotext popup.
  286  */
  287 
  288 static Boolean useful_page_labels;
  289 Boolean
  290 setup_ghostview()
  291 {
  292     Arg args[20];
  293     Cardinal num_args;
  294     int oldtoc_entry_length;
  295     char *tocp;
  296     XawTextBlock message_block;
  297     static String nothing = "";
  298     String label;
  299     Pixmap bitmap;
  300 
  301     /* Reset to a known state. */
  302     psfree(olddoc);
  303     olddoc = doc;
  304     doc = NULL;
  305     current_page = -1;
  306     if (toc_text) XtFree(toc_text);
  307     oldtoc_entry_length = toc_entry_length;
  308     toc_text = NULL;
  309 
  310     /* Scan document and start setting things up */
  311     if (psfile) doc = psscan(psfile);
  312 
  313     if (app_res.show_title) {
  314     if (doc && doc->title) {
  315         label = doc->title;
  316         bitmap = menu16_bitmap;
  317     } else {
  318         if (filename) {
  319         label = filename;
  320         } else {
  321         label = "";
  322         }
  323         bitmap = None;
  324     }
  325     XtSetArg(args[0], XtNlabel, label);
  326     XtSetValues(titlebutton, args, ONE);
  327     if (titlemenu) XtDestroyWidget(titlemenu);
  328     titlemenu = build_label_menu(titlebutton, "title", label, bitmap);
  329     }
  330 
  331     if (app_res.show_date) {
  332     if (doc && doc->date) {
  333         label = doc->date;
  334         bitmap = menu16_bitmap;
  335     } else {
  336         if (psfile) {
  337         label = ctime(&mtime);
  338         } else {
  339         label = "";
  340         }
  341         bitmap = None;
  342     }
  343     XtSetArg(args[0], XtNlabel, label);
  344     XtSetValues(datebutton, args, ONE);
  345     if (datemenu) XtDestroyWidget(datemenu);
  346     datemenu = build_label_menu(datebutton, "date", label, bitmap);
  347     }
  348 
  349     build_pagemedia_menu();
  350 
  351     /* Reset ghostscript and output messages popup */
  352     if (!doc || !olddoc ||
  353     strcmp(oldfilename, filename) ||
  354     olddoc->beginprolog != doc->beginprolog ||
  355     olddoc->endprolog != doc->endprolog ||
  356     olddoc->beginsetup != doc->beginsetup ||
  357     olddoc->endsetup != doc->endsetup) {
  358 
  359     GhostviewDisableInterpreter(page);
  360     XtPopdown(infopopup);
  361     info_up = False;
  362     XtSetArg(args[0], XtNeditType, XawtextEdit);
  363     XtSetArg(args[1], XtNinsertPosition, 0);
  364     XtSetValues(infotext, args, TWO);
  365     message_block.length = 0;
  366     XawTextReplace(infotext, 0, info_length, &message_block);
  367     info_length = 0;
  368     XtSetArg(args[0], XtNeditType, XawtextRead);
  369     XtSetValues(infotext, args, ONE);
  370     }
  371 
  372     /* Build table of contents */
  373     if (doc && (!doc->epsf && doc->numpages > 0 ||
  374          doc->epsf && doc->numpages > 1)) {
  375     int maxlen = 0;
  376     int i, j;
  377     useful_page_labels = False;
  378 
  379     if (doc->numpages == 1) useful_page_labels = True;
  380     for (i = 1; i < doc->numpages; i++)
  381         if (useful_page_labels = (useful_page_labels ||
  382             strcmp(doc->pages[i-1].label, doc->pages[i].label))) break;
  383     if (useful_page_labels) {
  384         for (i = 0; i < doc->numpages; i++) 
  385         maxlen = max(maxlen, strlen(doc->pages[i].label));
  386     } else {
  387         double x;
  388         x = doc->numpages;
  389         maxlen = log10(x) + 1;
  390     }
  391     toc_entry_length = maxlen + 3;
  392     toc_length = doc->numpages * toc_entry_length - 1;
  393     toc_text = XtMalloc(toc_length + 2); /* include final NULL */
  394 
  395     for (i = 0, tocp = toc_text; i < doc->numpages;
  396          i++, tocp += toc_entry_length) {
  397         if (useful_page_labels) {
  398         if (doc->pageorder == DESCEND) {
  399             j = (doc->numpages - 1) - i;
  400         } else {
  401             j = i;
  402         }
  403         sprintf(tocp, " %*s \n", maxlen, doc->pages[j].label);
  404         } else {
  405         sprintf(tocp, " %*d \n", maxlen, i+1);
  406         }
  407     }
  408     toc_text[toc_length] = '\0';
  409                                     num_args = 0;
  410     XtSetArg(args[num_args], XtNfilename, NULL);        num_args++;
  411     XtSetValues(page, args, num_args);
  412     } else {
  413     toc_length = 0;
  414     toc_entry_length = 3;
  415                                     num_args = 0;
  416     XtSetArg(args[num_args], XtNfilename, filename);        num_args++;
  417     XtSetValues(page, args, num_args);
  418     }
  419                                 num_args = 0;
  420     XtSetArg(args[num_args], XtNlength, toc_length);        num_args++;
  421     if (toc_text) {
  422     XtSetArg(args[num_args], XtNstring, toc_text);      num_args++;
  423     } else {
  424     /* Text widget sometime blows up when given a NULL pointer */
  425     XtSetArg(args[num_args], XtNstring, nothing);       num_args++;
  426     }
  427     XtSetValues(toc, args, num_args);
  428 
  429     XtSetSensitive(reopenbutton, (psfile != NULL));
  430     XtSetSensitive(printwholebutton, (psfile != NULL));
  431     XtSetSensitive(printmarkedbutton, (psfile != NULL));
  432     XtSetSensitive(savebutton, (toc_text != NULL));
  433     XtSetSensitive(nextbutton, (filename != NULL));
  434     XtSetSensitive(showbutton, (filename != NULL));
  435     XtSetSensitive(prevbutton, (toc_text != NULL));
  436     XtSetSensitive(centerbutton, (filename != NULL));
  437     XtSetSensitive(markbutton, (toc_text != NULL));
  438     XtSetSensitive(unmarkbutton, (toc_text != NULL));
  439 
  440     return oldtoc_entry_length != toc_entry_length;
  441 }
  442 
  443 int
  444 find_page(label)
  445     String label;
  446 {
  447     int i, j;
  448 
  449     if (label == NULL || doc == NULL) return 0;
  450 
  451     if (useful_page_labels) {
  452     for (i = 0; i < doc->numpages; i++) {
  453         if (doc->pageorder == DESCEND) {
  454         j = (doc->numpages - 1) - i;
  455         } else {
  456         j = i;
  457         }
  458         if (!strcmp(label, doc->pages[j].label)) return i;
  459     }
  460     return 0;
  461     } else {
  462     return atoi(label) - 1;
  463     }
  464 }
  465 
  466 /* try_try_again sets the geometry of the form when the form failed
  467  * to do it earlier.  It uses activity check with exponential backoff
  468  * to make sure that the dust has settled before trying again.
  469  */
  470 static unsigned int delay = 125;    /* Start with 1/8 second delay */
  471 
  472 static void
  473 try_try_again(client_data, timer)
  474     XtPointer client_data;
  475     XtIntervalId *timer;
  476 {
  477     XSync(XtDisplay(toplevel), False);  /* Push everything out */
  478     if (XtAppPending(app_con)) {
  479     XtAppAddTimeOut(app_con, delay, try_try_again, NULL);
  480     /* fprintf(stderr, "Delaying(%d)...\n",delay); */
  481     delay *= 2;
  482     } else {
  483     /* fprintf(stderr, "Trying again...\n"); */
  484     layout_ghostview();
  485     }
  486 }
  487 
  488 /* set the dimensions for items in the main form widget. */
  489 /* set foreground and background color in scrollbars. */
  490 /* (The scroll bars come and go as size changes.) */
  491 /* Set window manager hints to keep window manager from causing main */
  492 /* viewport from growing too large */
  493 void
  494 layout_ghostview()
  495 {
  496     Arg args[20];
  497     Dimension min_width, min_height;
  498     Dimension max_width, max_height;
  499     Dimension form_width, form_height;
  500     Dimension title_height, title_border;
  501     Dimension date_height, date_border;
  502     Dimension locator_height, locator_border;
  503     Dimension box_width, box_height, box_border;
  504     Dimension label_width;
  505     Dimension toc_width, toc_height, toc_border;
  506     Dimension view_width, view_height, view_border;
  507     Dimension page_width, page_height;
  508     Dimension leftMargin, rightMargin;
  509     Dimension width, height;
  510     Boolean correct = True;
  511     int distance;
  512     int a_label;
  513     XFontStruct *font;
  514 
  515     XawFormDoLayout(form, False);
  516     reset_size_hints();
  517     reset_scroll_bars();
  518     break_chains();
  519 
  520     XtSetArg(args[0], XtNdefaultDistance, &distance);
  521     XtGetValues(form, args, ONE);
  522 
  523     a_label = 0;
  524     if (app_res.show_title) {
  525     XtSetArg(args[0], XtNheight, &title_height);
  526     XtSetArg(args[1], XtNborderWidth, &title_border);
  527     XtGetValues(titlebutton, args, TWO);
  528     a_label = 1;
  529     } else {
  530     title_height = title_border = 0;
  531     }
  532 
  533     if (app_res.show_date) {
  534     XtSetArg(args[0], XtNheight, &date_height);
  535     XtSetArg(args[1], XtNborderWidth, &date_border);
  536     XtGetValues(datebutton, args, TWO);
  537     a_label = 1;
  538     } else {
  539     date_height = date_border = 0;
  540     }
  541 
  542     if (app_res.show_locator) {
  543     XtSetArg(args[0], XtNheight, &locator_height);
  544     XtSetArg(args[1], XtNborderWidth, &locator_border);
  545     XtGetValues(locator, args, TWO);
  546     a_label = 1;
  547     } else {
  548     locator_height = locator_border = 0;
  549     }
  550 
  551     XtSetArg(args[0], XtNwidth, &box_width);
  552     XtSetArg(args[1], XtNheight, &box_height);
  553     XtSetArg(args[2], XtNborderWidth, &box_border);
  554     XtGetValues(box, args, THREE);
  555 
  556     XtSetArg(args[0], XtNfont, &font);
  557     XtSetArg(args[1], XtNleftMargin, &leftMargin);
  558     XtSetArg(args[2], XtNrightMargin, &rightMargin);
  559     XtSetArg(args[3], XtNborderWidth, &toc_border);
  560     XtGetValues(toc, args, FOUR);
  561     toc_width = font->max_bounds.width * (toc_entry_length - 1) +
  562         leftMargin + rightMargin;
  563 
  564     XtSetArg(args[0], XtNwidth, &page_width);
  565     XtSetArg(args[1], XtNheight, &page_height);
  566     XtGetValues(page, args, TWO);
  567 
  568     XtSetArg(args[0], XtNborderWidth, &view_border);
  569     XtGetValues(pageview, args, ONE);
  570     view_width = page_width;
  571     view_height = page_height;
  572 
  573     min_width = box_width + 2*box_border + toc_width + 2*toc_border +
  574         2*view_border + 4*distance;
  575     min_height = title_height + 2*title_border + date_height + 2*date_border +
  576          locator_height + 2*locator_border + box_height + 2*box_border +
  577          (2+a_label)*distance;
  578 
  579     max_width = WidthOfScreen(XtScreen(toplevel)) - app_res.wm_horiz_margin;
  580     max_height = HeightOfScreen(XtScreen(toplevel)) - app_res.wm_vert_margin;
  581 
  582     if (min_width + view_width > max_width)
  583     view_width = max_width - min_width;
  584     if (2*(view_border + distance) + view_height > max_height)
  585     view_height = max_height - 2*(view_border + distance);
  586     form_width = view_width + min_width;
  587     form_height = max(view_height + 2*(view_border + distance), min_height);
  588     toc_height = view_height - (title_height + 2*title_border +
  589                 date_height + 2*date_border +
  590                 locator_height + 2*locator_border +
  591                 a_label*distance);
  592 
  593     label_width = box_width + 2*box_border + distance +
  594           toc_width + 2*toc_border;
  595 
  596     XtSetArg(args[0], XtNwidth, form_width);
  597     XtSetArg(args[1], XtNheight, form_height);
  598     XtSetValues(form, args, TWO);
  599 
  600     XtSetArg(args[0], XtNwidth, label_width);
  601     if (app_res.show_title) XtSetValues(titlebutton, args, ONE);
  602     if (app_res.show_date) XtSetValues(datebutton, args, ONE);
  603     if (app_res.show_locator) XtSetValues(locator, args, ONE);
  604 
  605     XtSetArg(args[0], XtNwidth, toc_width);
  606     XtSetArg(args[1], XtNheight, toc_height);
  607     XtSetValues(toc, args, TWO);
  608 
  609     XtSetArg(args[0], XtNwidth, view_width);
  610     XtSetArg(args[1], XtNheight, view_height);
  611     XtSetValues(pageview, args, TWO);
  612 
  613     XawFormDoLayout(form, True);
  614 
  615     /* Check to make sure everything was done as planned. */
  616     XtSetArg(args[0], XtNwidth, &width);
  617     XtSetArg(args[1], XtNheight, &height);
  618 
  619     XtGetValues(form, args, TWO);
  620     if (width != form_width || height != form_height) {
  621     correct = False;
  622     /* fprintf(stderr, "Oops, %dx%d form was supposed to be %dx%d.\n",
  623         width, height, form_width, form_height); */
  624     }
  625     if (app_res.show_title) {
  626     XtGetValues(titlebutton, args, ONE);
  627     if (width != label_width) {
  628         correct = False;
  629         /* fprintf(stderr,
  630         "Oops, %d wide title was supposed to be %d wide.\n",
  631         width, label_width); */
  632     }
  633     }
  634     if (app_res.show_date) {
  635     XtGetValues(datebutton, args, ONE);
  636     if (width != label_width) {
  637         correct = False;
  638         /* fprintf(stderr,
  639         "Oops, %d wide date was supposed to be %d wide.\n",
  640         width, label_width); */
  641     }
  642     }
  643     if (app_res.show_locator) {
  644     XtGetValues(locator, args, ONE);
  645     if (width != label_width) {
  646         correct = False;
  647         /* fprintf(stderr,
  648         "Oops, %d wide locator was supposed to be %d wide.\n",
  649         width, label_width); */
  650     }
  651     }
  652     XtGetValues(toc, args, TWO);
  653     if (width != toc_width || height != toc_height) {
  654     correct = False;
  655     /* fprintf(stderr, "Oops, %dx%d toc was supposed to be %dx%d.\n",
  656         width, height, toc_width, toc_height); */
  657     }
  658     XtGetValues(pageview, args, TWO);
  659     if (width != view_width || height != view_height) {
  660     correct = False;
  661     /* fprintf(stderr, "Oops, %dx%d pageview was supposed to be %dx%d.\n",
  662         width, height, view_width, view_height); */
  663     }
  664 
  665     if (correct) {
  666     set_size_hints(min_width, min_height, min_width+page_width,
  667                max(form_height,
  668                page_height + 2*(view_border + distance)));
  669     if (app_res.auto_center) {
  670         horiz_scroll_saved = vert_scroll_saved = False;
  671         center_page(form, NULL, NULL);
  672     } else {
  673         set_scroll_bars();
  674     }
  675     set_chains();
  676     delay = 125;    /* Reset to 1/8 second delay */
  677     /* fprintf(stderr, "Layout correct.\n"); */
  678     } else {
  679     XSync(XtDisplay(toplevel), False);
  680     XtAppAddTimeOut(app_con, delay, try_try_again, NULL);
  681     /* fprintf(stderr, "Didn't work, scheduling(%d)...\n",delay); */
  682     }
  683 
  684 }
  685 
  686 /* Compute new dpi from magstep */
  687 void
  688 magnify(dpi, magstep)
  689     float *dpi;
  690     int    magstep;
  691 {
  692     if (magstep < 0) {
  693     while (magstep++) *dpi /= 1.2;
  694     } else {
  695     while (magstep--) *dpi *= 1.2;
  696     }
  697 }
  698 
  699 /* Attempt to open file, return error message string on failure */
  700 String
  701 open_file(name)
  702     String name;
  703 {
  704     FILE *fp;
  705     struct stat sbuf;
  706 
  707     if (*name == '\0') {    /* Null filename */
  708     return(NULL);
  709     }
  710     if (strcmp(name, "-")) {
  711     if ((fp = fopen(name, "r")) == NULL) {
  712         String buf = XtMalloc(strlen(app_res.open_fail) +
  713                   strlen(sys_errlist[errno]) + 1);
  714         strcpy(buf, app_res.open_fail);
  715         if (errno <= sys_nerr) strcat(buf, sys_errlist[errno]);
  716         return buf;
  717     } else {
  718         if (oldfilename) XtFree(oldfilename);
  719         oldfilename = filename;
  720         filename = XtNewString(name);
  721         if (psfile) fclose(psfile);
  722         psfile = fp;
  723         stat(filename, &sbuf);
  724         mtime = sbuf.st_mtime;
  725         new_file(0);
  726         show_page(0);
  727         return(NULL);
  728     }
  729     } else {
  730     if (oldfilename) XtFree(oldfilename);
  731     oldfilename = filename;
  732     filename = XtNewString(name);
  733     if (psfile) fclose(psfile);
  734     psfile = NULL;
  735     new_file(0);
  736     show_page(0);
  737     return(NULL);
  738     }
  739 }
  740 
  741 /* Attempt to save file, return error message string on failure */
  742 String
  743 save_file(name)
  744     String name;
  745 {
  746     FILE *pswrite;
  747 
  748     if (*name == '\0') {    /* Null filename */
  749     return(NULL);
  750     }
  751     if ((pswrite = fopen(name, "w")) == NULL) {
  752     String buf = XtMalloc(strlen(app_res.save_fail) +
  753                   strlen(sys_errlist[errno]) + 1);
  754     strcpy(buf, app_res.save_fail);
  755     if (errno <= sys_nerr) strcat(buf, sys_errlist[errno]);
  756     return buf;
  757     } else {
  758     pscopydoc(pswrite);
  759     fclose(pswrite);
  760     return(NULL);
  761     }
  762 }
  763 
  764 /* Attempt to print file.  Return error string on failure */ 
  765 String
  766 print_file(name, whole_mode)
  767     String name;
  768     Boolean whole_mode;
  769 {
  770     FILE *printer;
  771     SIGVAL (*oldsig)();
  772     int bytes;
  773     char buf[BUFSIZ];
  774 #ifdef VMS
  775     char fnam[64], *p;
  776 #endif
  777     Boolean failed;
  778     String ret_val;
  779 
  780 #ifdef VMS
  781     sprintf(fnam, "sys$scratch:%s.tmp", tmpnam(NULL));
  782     printer = fopen(fnam, "w");
  783 #else /* VMS */
  784     if (*name != '\0') {
  785     setenv(app_res.printer_variable, name, True);
  786     }
  787     oldsig = signal(SIGPIPE, SIG_IGN);
  788     printer = popen(app_res.print_command, "w");
  789 #endif /* VMS */
  790     if (toc_text && !whole_mode) {
  791     pscopydoc(printer);
  792     } else {
  793     FILE *psfile = fopen(filename, "r");
  794     while (bytes = read(fileno(psfile), buf, BUFSIZ))
  795         bytes = write(fileno(printer), buf, bytes);
  796     fclose(psfile);
  797     }
  798 #ifdef VMS
  799     sprintf(buf, "%s %s %s", app_res.print_command, name, fnam);
  800     failed = fclose(printer) != 0 || system(buf) != 1;
  801 #else /* VMS */
  802     failed = pclose(printer) != 0;
  803 #endif /* VMS */
  804     if (failed) {
  805     sprintf(buf, app_res.print_fail, app_res.print_command);
  806     ret_val = XtNewString(buf);
  807     } else {
  808     ret_val = NULL;
  809     }
  810 #ifndef VMS
  811     signal(SIGPIPE, oldsig);
  812 #endif /* VMS */
  813     return(ret_val);
  814 }
  815 
  816 /* length calculates string length at compile time */
  817 /* can only be used with character constants */
  818 #define length(a) (sizeof(a)-1)
  819 
  820 /* Copy the headers, marked pages, and trailer to fp */
  821 void
  822 pscopydoc(fp)
  823     FILE *fp;
  824 {
  825     FILE *psfile;
  826     char text[PSLINELENGTH];
  827     char *comment;
  828     Boolean pages_written = False;
  829     Boolean pages_atend = False;
  830     Boolean marked_pages = False;
  831     int pages = 0;
  832     int page = 1;
  833     int i, j;
  834     long here;
  835 
  836     psfile = fopen(filename, "r");
  837 
  838     for (i = 0; i < doc->numpages; i++) {
  839     if (toc_text[toc_entry_length * i] == '*') pages++;
  840     }
  841 
  842     if (pages == 0) {   /* User forgot to mark the pages */
  843     mark_page(form, NULL, NULL);
  844     marked_pages = True;
  845     for (i = 0; i < doc->numpages; i++) {
  846         if (toc_text[toc_entry_length * i] == '*') pages++;
  847     }
  848     }
  849 
  850     here = doc->beginheader;
  851     while (comment = pscopyuntil(psfile, fp, here,
  852                  doc->endheader, "%%Pages:")) {
  853     here = ftell(psfile);
  854     if (pages_written || pages_atend) {
  855         free(comment);
  856         continue;
  857     }
  858     sscanf(comment+length("%%Pages:"), "%s", text);
  859     if (strcmp(text, "(atend)") == 0) {
  860         fputs(comment, fp);
  861         pages_atend = True;
  862     } else {
  863         switch (sscanf(comment+length("%%Pages:"), "%*d %d", &i)) {
  864         case 1:
  865             fprintf(fp, "%%%%Pages: %d %d\n", pages, i);
  866             break;
  867         default:
  868             fprintf(fp, "%%%%Pages: %d\n", pages);
  869             break;
  870         }
  871         pages_written = True;
  872     }
  873     free(comment);
  874     }
  875     pscopy(psfile, fp, doc->beginpreview, doc->endpreview);
  876     pscopy(psfile, fp, doc->begindefaults, doc->enddefaults);
  877     pscopy(psfile, fp, doc->beginprolog, doc->endprolog);
  878     pscopy(psfile, fp, doc->beginsetup, doc->endsetup);
  879 
  880     for (i = 0; i < doc->numpages; i++) {
  881     if (doc->pageorder == DESCEND) 
  882         j = (doc->numpages - 1) - i;
  883     else
  884         j = i;
  885     if (toc_text[toc_entry_length * j] == '*') {
  886         comment = pscopyuntil(psfile, fp, doc->pages[i].begin,
  887                   doc->pages[i].end, "%%Page:");
  888         fprintf(fp, "%%%%Page: %s %d\n",
  889             doc->pages[i].label, page++);
  890         free(comment);
  891         pscopy(psfile, fp, -1, doc->pages[i].end);
  892     }
  893     }
  894 
  895     here = doc->begintrailer;
  896     while (comment = pscopyuntil(psfile, fp, here,
  897                  doc->endtrailer, "%%Pages:")) {
  898     here = ftell(psfile);
  899     if (pages_written) {
  900         free(comment);
  901         continue;
  902     }
  903     switch (sscanf(comment+length("%%Pages:"), "%*d %d", &i)) {
  904         case 1:
  905         fprintf(fp, "%%%%Pages: %d %d\n", pages, i);
  906         break;
  907         default:
  908         fprintf(fp, "%%%%Pages: %d\n", pages);
  909         break;
  910     }
  911     pages_written = True;
  912     free(comment);
  913     }
  914     fclose(psfile);
  915 
  916     if (marked_pages) unmark_page(form, NULL, NULL);
  917 }
  918 #undef length
  919 
  920 /* position popup window under the cursor */
  921 void
  922 positionpopup(w)
  923     Widget w;
  924 {
  925     Arg args[3];
  926     Cardinal num_args;
  927     Dimension width, height, b_width;
  928     int x, y, max_x, max_y;
  929     Window root, child;
  930     int dummyx, dummyy;
  931     unsigned int dummymask;
  932     
  933     XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
  934           &dummyx, &dummyy, &dummymask);
  935     num_args = 0;
  936     XtSetArg(args[num_args], XtNwidth, &width); num_args++;
  937     XtSetArg(args[num_args], XtNheight, &height); num_args++;
  938     XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
  939     XtGetValues(w, args, num_args);
  940 
  941     width += 2 * b_width;
  942     height += 2 * b_width;
  943 
  944     x -= ( (Position) width/2 );
  945     if (x < 0) x = 0;
  946     if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
  947 
  948     y -= ( (Position) height/2 );
  949     if (y < 0) y = 0;
  950     if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
  951     
  952     num_args = 0;
  953     XtSetArg(args[num_args], XtNx, x); num_args++;
  954     XtSetArg(args[num_args], XtNy, y); num_args++;
  955     XtSetValues(w, args, num_args);
  956 }
  957 
  958 /* Set new magstep */
  959 Boolean
  960 set_new_magstep()
  961 {
  962     int new_magstep;
  963     Boolean changed = False;
  964     Arg args[20];
  965     Cardinal num_args;
  966     float xdpi, ydpi;
  967 
  968     new_magstep = app_res.magstep;
  969     /* If magstep changed, stop interpreter and setup for new dpi. */
  970     if (new_magstep != current_magstep) {
  971     GhostviewDisableInterpreter(page);
  972     XawFormDoLayout(form, False);
  973     reset_size_hints();
  974     reset_scroll_bars();
  975     break_chains();
  976     changed = True;
  977     xdpi = default_xdpi;
  978     ydpi = default_ydpi;
  979     magnify(&xdpi, new_magstep);
  980     magnify(&ydpi, new_magstep);
  981                             num_args = 0;
  982     XtSetFloatArg(args[num_args], XtNxdpi, xdpi);   num_args++;
  983     XtSetFloatArg(args[num_args], XtNydpi, ydpi);   num_args++;
  984     XtSetValues(page, args, num_args);
  985 
  986     XtSetArg(args[0], XtNleftBitmap, None);
  987     XtSetValues(magstepentry[current_magstep - app_res.minimum_magstep],
  988             args, ONE);
  989     current_magstep = new_magstep;
  990     }
  991     XtSetArg(args[0], XtNleftBitmap, dot_bitmap);
  992     XtSetValues(magstepentry[current_magstep - app_res.minimum_magstep],
  993         args, ONE);
  994 
  995     return changed;
  996 }
  997 
  998 /* Set new orientation */
  999 Boolean
 1000 set_new_orientation(number)
 1001     int number;
 1002 {
 1003     Boolean changed = False;
 1004     Boolean from_doc = False;
 1005     Arg args[1];
 1006     XtPageOrientation new_orientation;
 1007 
 1008     if (app_res.force_orientation) {
 1009     new_orientation = app_res.orientation;
 1010     } else {
 1011     if (doc) {
 1012         if (toc_text && doc->pages[number].orientation != NONE) {
 1013         new_orientation = xorient(doc->pages[number].orientation);
 1014         from_doc = True;
 1015         } else if (doc->default_page_orientation != NONE) {
 1016         new_orientation = xorient(doc->default_page_orientation);
 1017         from_doc = True;
 1018         } else if (doc->orientation != NONE) {
 1019         new_orientation = xorient(doc->orientation);
 1020         from_doc = True;
 1021         } else {
 1022         new_orientation = app_res.orientation;
 1023         }
 1024     } else {
 1025         new_orientation = app_res.orientation;
 1026     }
 1027     }
 1028 
 1029     /* If orientation changed,
 1030      * stop interpreter and setup for new orientation. */
 1031     if (new_orientation != current_orientation) {
 1032     GhostviewDisableInterpreter(page);
 1033     XawFormDoLayout(form, False);
 1034     reset_size_hints();
 1035     reset_scroll_bars();
 1036     break_chains();
 1037     changed = True;
 1038     XtSetArg(args[0], XtNorientation, new_orientation);
 1039     XtSetValues(page, args, ONE);
 1040     XtSetArg(args[0], XtNleftBitmap, None);
 1041     if (current_orientation == XtPageOrientationPortrait) 
 1042         XtSetValues(portraitbutton, args, ONE);
 1043     else if (current_orientation == XtPageOrientationLandscape)
 1044             XtSetValues(landscapebutton, args, ONE);
 1045         else if (current_orientation == XtPageOrientationUpsideDown)
 1046             XtSetValues(upsidedownbutton, args, ONE);
 1047         else if (current_orientation == XtPageOrientationSeascape)
 1048             XtSetValues(seascapebutton, args, ONE);
 1049     current_orientation = new_orientation;
 1050     }
 1051 
 1052     /* mark forced orientation with tie fighter. ("Use the force, Luke") */
 1053     if (app_res.force_orientation) {
 1054     XtSetArg(args[0], XtNleftBitmap, tie_fighter_bitmap);
 1055     } else if (from_doc) {
 1056     XtSetArg(args[0], XtNleftBitmap, menu16_bitmap);
 1057     } else {
 1058     XtSetArg(args[0], XtNleftBitmap, dot_bitmap);
 1059     }
 1060     if (current_orientation == XtPageOrientationPortrait) 
 1061     XtSetValues(portraitbutton, args, ONE);
 1062     else if (current_orientation == XtPageOrientationLandscape)
 1063     XtSetValues(landscapebutton, args, ONE);
 1064     else if (current_orientation == XtPageOrientationUpsideDown)
 1065     XtSetValues(upsidedownbutton, args, ONE);
 1066     else if (current_orientation == XtPageOrientationSeascape)
 1067     XtSetValues(seascapebutton, args, ONE);
 1068     
 1069     return changed;
 1070 }
 1071 
 1072 /* Set new pagemedia */
 1073 Boolean
 1074 set_new_pagemedia(number)
 1075     int number;
 1076 {
 1077     int new_pagemedia;
 1078     int new_llx;
 1079     int new_lly;
 1080     int new_urx;
 1081     int new_ury;
 1082     Boolean changed = False;
 1083     Boolean from_doc = False;
 1084     Arg args[4];
 1085 
 1086     if (force_document_media) {
 1087     new_pagemedia = document_media;
 1088     } else if (app_res.force_pagemedia) {
 1089     new_pagemedia = default_pagemedia;
 1090     } else {
 1091     if (doc) {
 1092         if (toc_text && doc->pages[number].media != NULL) {
 1093         new_pagemedia = doc->pages[number].media - doc->media;
 1094         from_doc = True;
 1095         } else if (doc->default_page_media != NULL) {
 1096         new_pagemedia = doc->default_page_media - doc->media;
 1097         from_doc = True;
 1098         } else {
 1099         new_pagemedia = default_pagemedia;
 1100         }
 1101     } else {
 1102         new_pagemedia = default_pagemedia;
 1103     }
 1104     }
 1105 
 1106     /* If pagemedia changed, remove the old marker. */
 1107     if (new_pagemedia != current_pagemedia) {
 1108     XtSetArg(args[0], XtNleftBitmap, None);
 1109     if (pagemediaentry[current_pagemedia])
 1110         XtSetValues(pagemediaentry[current_pagemedia], args, ONE);
 1111     else
 1112         XtSetValues(pagemediaentry[current_pagemedia-1], args, ONE);
 1113 
 1114     current_pagemedia = new_pagemedia;
 1115     }
 1116 
 1117     /* mark forced page media with tie fighter. ("Use the force, Luke") */
 1118     if (force_document_media || app_res.force_pagemedia) {
 1119     XtSetArg(args[0], XtNleftBitmap, tie_fighter_bitmap);
 1120     } else if (from_doc) {
 1121     XtSetArg(args[0], XtNleftBitmap, menu16_bitmap);
 1122     } else {
 1123     XtSetArg(args[0], XtNleftBitmap, dot_bitmap);
 1124     }
 1125     if (pagemediaentry[current_pagemedia])
 1126     XtSetValues(pagemediaentry[current_pagemedia], args, ONE);
 1127     else
 1128     XtSetValues(pagemediaentry[current_pagemedia-1], args, ONE);
 1129 
 1130     /* Compute bounding box */
 1131     if (!force_document_media && !app_res.force_pagemedia &&
 1132     doc && doc->epsf &&
 1133     /* Ignore malformed bounding boxes */
 1134     (doc->boundingbox[URX] > doc->boundingbox[LLX]) &&
 1135     (doc->boundingbox[URY] > doc->boundingbox[LLY])) {
 1136     new_llx = doc->boundingbox[LLX];
 1137     new_lly = doc->boundingbox[LLY];
 1138     new_urx = doc->boundingbox[URX];
 1139     new_ury = doc->boundingbox[URY];
 1140     } else {
 1141     new_llx = new_lly = 0;
 1142     if (new_pagemedia < base_papersize) {
 1143         new_urx = doc->media[new_pagemedia].width;
 1144         new_ury = doc->media[new_pagemedia].height;
 1145     } else {
 1146         new_urx = papersizes[new_pagemedia-base_papersize].width;
 1147         new_ury = papersizes[new_pagemedia-base_papersize].height;
 1148     }
 1149     }
 1150 
 1151     /* If bounding box changed, setup for new size. */
 1152     if ((new_llx != current_llx) || (new_lly != current_lly) ||
 1153     (new_urx != current_urx) || (new_ury != current_ury)) {
 1154     GhostviewDisableInterpreter(page);
 1155     XawFormDoLayout(form, False);
 1156     reset_size_hints();
 1157     reset_scroll_bars();
 1158     break_chains();
 1159     changed = True;
 1160     current_llx = new_llx;
 1161     current_lly = new_lly;
 1162     current_urx = new_urx;
 1163     current_ury = new_ury;
 1164     XtSetArg(args[0], XtNllx, current_llx);
 1165     XtSetArg(args[1], XtNlly, current_lly);
 1166     XtSetArg(args[2], XtNurx, current_urx);
 1167     XtSetArg(args[3], XtNury, current_ury);
 1168     XtSetValues(page, args, FOUR);
 1169     }
 1170 
 1171     return changed;
 1172 }
 1173 
 1174 static Boolean
 1175 same_document_media()
 1176 {
 1177     int i;
 1178 
 1179     if (olddoc == NULL && doc == NULL) return True;
 1180     if (olddoc == NULL || doc == NULL) return False;
 1181     if (olddoc->nummedia != doc->nummedia) return False;
 1182     for (i = 0; i < doc->nummedia; i++)
 1183     if (strcmp(olddoc->media[i].name, doc->media[i].name)) return False;
 1184     return True;
 1185 }
 1186 
 1187 void
 1188 build_pagemedia_menu()
 1189 {
 1190     Arg args[20];
 1191     Cardinal num_args;
 1192     Widget w;
 1193     int i;
 1194 
 1195     if (pagemediamenu && same_document_media()) return;
 1196     if (pagemediamenu) XtDestroyWidget(pagemediamenu);
 1197     force_document_media = False;
 1198 
 1199     pagemediamenu = XtCreatePopupShell("menu", simpleMenuWidgetClass,
 1200                        pagemediabutton, NULL, ZERO);
 1201 
 1202     /* Build the Page Media menu */
 1203     /* the Page media menu has two parts.
 1204      *  - the document defined page medias
 1205      *  - the standard page media defined from Adobe's PPD
 1206      */
 1207     base_papersize = 0;
 1208     if (doc) base_papersize = doc->nummedia;
 1209     for (i = 0; papersizes[i].name; i++) {} /* Count the standard entries */
 1210     i += base_papersize;
 1211     pagemediaentry = (Widget *) XtMalloc(i * sizeof(Widget));
 1212 
 1213     if (doc && doc->nummedia) {
 1214     for (i = 0; i < doc->nummedia; i++) {
 1215                                 num_args = 0;
 1216         XtSetArg(args[num_args], XtNleftMargin, 20);    num_args++;
 1217         pagemediaentry[i] = XtCreateManagedWidget(doc->media[i].name,
 1218                 smeBSBObjectClass, pagemediamenu,
 1219                 args, num_args);
 1220         XtAddCallback(pagemediaentry[i], XtNcallback,
 1221               set_pagemedia, (XtPointer)i);
 1222     }
 1223 
 1224                             num_args = 0;
 1225     w = XtCreateManagedWidget("line", smeLineObjectClass, pagemediamenu,
 1226                   args, num_args);
 1227     }
 1228 
 1229     for (i = 0; papersizes[i].name; i++) {
 1230     pagemediaentry[i+base_papersize] = NULL;
 1231     if (i > 0) {
 1232         /* Skip over same paper size with small imageable area */
 1233         if ((papersizes[i].width == papersizes[i-1].width) &&
 1234         (papersizes[i].height == papersizes[i-1].height)) {
 1235         continue;
 1236         }
 1237     }
 1238                             num_args = 0;
 1239     XtSetArg(args[num_args], XtNleftMargin, 20);    num_args++;
 1240     pagemediaentry[i+base_papersize] = XtCreateManagedWidget(
 1241                         papersizes[i].name,
 1242                         smeBSBObjectClass, pagemediamenu,
 1243                         args, num_args);
 1244     XtAddCallback(pagemediaentry[i+base_papersize], XtNcallback,
 1245               set_pagemedia, (XtPointer)(i+base_papersize));
 1246     }
 1247 }
 1248 
 1249 Widget
 1250 build_label_menu(parent, name, label, bitmap)
 1251     Widget parent;
 1252     String name, label;
 1253     Pixmap bitmap;
 1254 {
 1255     Arg args[20];
 1256     Cardinal num_args;
 1257     Widget menu, entry;
 1258                                 num_args = 0;
 1259     menu = XtCreatePopupShell("menu", simpleMenuWidgetClass,
 1260                   parent, args, num_args);
 1261 
 1262                                 num_args = 0;
 1263     XtSetArg(args[num_args], XtNlabel, label);      num_args++;
 1264     if (bitmap) {
 1265         XtSetArg(args[num_args], XtNleftMargin, 20);    num_args++;
 1266         XtSetArg(args[num_args], XtNleftBitmap, bitmap);    num_args++;
 1267     }
 1268     entry = XtCreateManagedWidget(name, smeBSBObjectClass,
 1269                       menu, args, num_args);
 1270     return menu;
 1271 }
 1272 
 1273 void
 1274 new_file(number)
 1275     int number;
 1276 {
 1277     Boolean layout_changed = False;
 1278 
 1279     if (setup_ghostview()) layout_changed = True;
 1280 
 1281     /* Coerce page number to fall in range */
 1282     if (toc_text) {
 1283     if (number >= doc->numpages) number = doc->numpages - 1;
 1284     if (number < 0) number = 0;
 1285     }
 1286 
 1287     if (set_new_orientation(number)) layout_changed = True;
 1288     if (set_new_pagemedia(number)) layout_changed = True;
 1289     if (layout_changed) layout_ghostview();
 1290 }
 1291 
 1292 /* Catch X errors die gracefully if one occurs */
 1293 int
 1294 catch_Xerror(dpy, err)
 1295     Display *dpy;
 1296     XErrorEvent *err;
 1297 {
 1298     if (err->error_code == BadImplementation) {
 1299     old_Xerror(dpy, err);
 1300     return 0;
 1301     }
 1302     if (dying) return 0;
 1303     dying = True;
 1304     bomb = *err;
 1305     XtDestroyWidget(toplevel);
 1306     return 0;
 1307 }