"Fossies" - the Fresh Open Source Software Archive

Member "ghostview-1.4.1/callbacks.c" (1 Oct 1992, 20521 Bytes) of package /linux/misc/old/ghost/gnu/ghostview/ghostview-1.4.1.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  * callbacks.c -- X11 callbacks for ghostview.
    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 BUFSIZ
   28 #define BUFSIZ 1024
   29 #endif
   30 
   31 #ifdef VMS
   32 #define getenv _getenv
   33 #endif
   34 
   35 extern char *getenv();
   36 
   37 #include <X11/Intrinsic.h>
   38 #include <X11/StringDefs.h>
   39 #include <X11/Shell.h>
   40 #include <X11/Xaw/Cardinals.h>
   41 #include <X11/Xaw/AsciiText.h>
   42 #include <X11/Xaw/Scrollbar.h>
   43 #include <X11/Xaw/Form.h>
   44 #include <X11/Xaw/Command.h>
   45 
   46 #include "Ghostview.h"
   47 #include "gv.h"
   48 #include "ps.h"
   49 
   50 /* Start application folding up by Destroying the top level widget. */
   51 /* The application exits when the last interpreter is killed during */
   52 /* a destroy callback from ghostview widgets. */
   53 void
   54 quit_ghostview(w, client_data, call_data)
   55     Widget w;
   56     XtPointer client_data, call_data;
   57 {
   58     XtDestroyWidget(toplevel);
   59 }
   60 
   61 /* Popup a window. */
   62 void
   63 popup(w, client_data, call_data)
   64     Widget w;
   65     XtPointer client_data, call_data;
   66 {
   67     positionpopup((Widget)client_data);
   68     XtPopup((Widget)client_data, XtGrabNone);
   69     XRaiseWindow(XtDisplay((Widget)client_data), XtWindow((Widget)client_data));
   70 }
   71 
   72 /* Popup a dialog box. */
   73 void
   74 popup_dialog(w, client_data, call_data)
   75     Widget w;
   76     XtPointer client_data, call_data;
   77 {
   78 #ifdef SELFILE
   79     Widget button;
   80     String okay, cancel;
   81     String name, init_path;
   82     Arg args[1];
   83     FILE* fp;
   84     struct stat sbuf;
   85     extern FILE *XsraSelFile();
   86 
   87     button = XtNameToWidget(dialog, "cancel");
   88     if (button) {
   89     XtSetArg(args[0], XtNlabel, &cancel);
   90     XtGetValues(button, args, ONE);
   91     }
   92     button = XtNameToWidget(dialog, "okay");
   93     if (button) {
   94     XtSetArg(args[0], XtNlabel, &okay);
   95     XtGetValues(button, args, ONE);
   96     }
   97 #endif
   98 
   99     mode = (int) client_data;
  100     switch (mode) {
  101     case PRINT_WHOLE:
  102     case PRINT_MARKED:
  103     SetDialogPrompt(dialog, app_res.print_prompt);
  104     if (app_res.default_printer)
  105         SetDialogResponse(dialog, app_res.default_printer);
  106     else
  107         ClearDialogResponse(dialog);
  108     popup(w, (XtPointer)dialogpopup, call_data);
  109     break;
  110     case OPEN:
  111 #ifdef SELFILE
  112     if (filename && strcmp(filename, "-")) init_path = filename;
  113     else init_path = NULL;
  114     fp = XsraSelFile(toplevel, app_res.open_prompt, okay, cancel,
  115              app_res.open_fail, init_path, "r", NULL, &name);
  116     if (fp == NULL) break;
  117     if (oldfilename) XtFree(oldfilename);
  118     oldfilename = filename;
  119     filename = name;
  120     if (psfile) fclose(psfile);
  121     psfile = fp;
  122     stat(filename, &sbuf);
  123     mtime = sbuf.st_mtime;
  124     new_file(0);
  125     show_page(0);
  126 #else
  127     SetDialogPrompt(dialog, app_res.open_prompt);
  128     if (filename && strcmp(filename, "-"))
  129         SetDialogResponse(dialog, filename);
  130     else
  131         ClearDialogResponse(dialog);
  132     popup(w, dialogpopup, call_data);
  133 #endif
  134     break;
  135     case SAVE:
  136 #ifdef SELFILE
  137     fp = XsraSelFile(toplevel, app_res.save_prompt, okay, cancel,
  138              app_res.save_fail, "", "w", NULL, &name);
  139     if (fp == NULL) break;
  140     pscopydoc(fp);
  141     fclose(fp);
  142     XtFree(name);
  143 #else
  144     SetDialogPrompt(dialog, app_res.save_prompt);
  145     ClearDialogResponse(dialog);
  146     popup(w, dialogpopup, call_data);
  147 #endif
  148     break;
  149     }
  150 }
  151 
  152 /* Explicitly reopen the file. */
  153 void
  154 reopen_file(w, client_data, call_data)
  155     Widget w;
  156     XtPointer client_data, call_data;
  157 {
  158     struct stat sbuf;
  159     int number = current_page;
  160 
  161     fclose(psfile);
  162     psfile = fopen(filename, "r");
  163     mtime = sbuf.st_mtime;
  164     if (oldfilename) XtFree(oldfilename);
  165     oldfilename = XtNewString(filename);
  166     new_file(number);
  167     show_page(number);
  168 }
  169 
  170 /* Get the selection, if no selection, get the insertion point. */
  171 /* If the new_page is different from the current page show it.  */
  172 /* If not at the first page, show the previous page. */
  173 void
  174 prev_page(w, client_data, call_data)
  175     Widget w;
  176     XtPointer client_data, call_data;
  177 {
  178     XawTextPosition pos, end;
  179     int new_page;
  180 
  181     XawTextGetSelectionPos(toc, &pos, &end);
  182     if (pos == end) {       /* Nothing selected */
  183     pos = XawTextGetInsertionPoint(toc);
  184     }
  185     if ((new_page = pos/toc_entry_length) == current_page) {
  186     new_page = current_page - 1;
  187     }
  188     if (new_page < 0) return;
  189     show_page(new_page);
  190 }
  191 
  192 /* Get the selection, if no selection, get the insertion point. */
  193 /* Show this page.  */
  194 void
  195 this_page(w, client_data, call_data)
  196     Widget w;
  197     XtPointer client_data, call_data;
  198 {
  199     if (toc_text) {
  200     XawTextPosition pos, end;
  201     int new_page;
  202 
  203     XawTextGetSelectionPos(toc, &pos, &end);
  204     if (pos == end) {       /* Nothing selected */
  205         pos = XawTextGetInsertionPoint(toc);
  206     }
  207     new_page = pos/toc_entry_length;
  208     show_page(new_page);
  209     } else {
  210     GhostviewDisableInterpreter(page);
  211     show_page(0);
  212     }
  213 }
  214 
  215 /* Get the selection, if no selection, get the insertion point. */
  216 /* If the new_page is different from the current page show it.  */
  217 /* If not at the last page, show the next page. */
  218 void
  219 next_page(w, client_data, call_data)
  220     Widget w;
  221     XtPointer client_data, call_data;
  222 {
  223     XawTextPosition pos, end;
  224     int new_page = 0;
  225 
  226     if (toc_text) {
  227     XawTextGetSelectionPos(toc, &pos, &end);
  228     if (pos == end) {       /* Nothing selected */
  229         pos = XawTextGetInsertionPoint(toc);
  230     }
  231     if ((new_page = pos/toc_entry_length) == current_page) {
  232         new_page = current_page + 1;
  233     }
  234     if (new_page >= doc->numpages) return;
  235     }
  236     show_page(new_page);
  237 }
  238 
  239 /* Center the viewport over the page */
  240 void
  241 center_page(w, client_data, call_data)
  242     Widget w;
  243     XtPointer client_data, call_data;
  244 {
  245     Arg args[2];
  246     Widget scroll;
  247     float top, shown;
  248 
  249     scroll = XtNameToWidget(pageview, "vertical");
  250     if (scroll) {
  251     XtSetArg(args[0], XtNshown, &shown);
  252     XtSetArg(args[1], XtNtopOfThumb, &top);
  253     XtGetValues(scroll, args, TWO);
  254 
  255     top = (1.0 - shown) / 2.0;
  256     XtCallCallbacks(scroll, XtNjumpProc, &top);
  257     }
  258 
  259     scroll = XtNameToWidget(pageview, "horizontal");
  260     if (scroll) {
  261     XtSetArg(args[0], XtNshown, &shown);
  262     XtSetArg(args[1], XtNtopOfThumb, &top);
  263     XtGetValues(scroll, args, TWO);
  264 
  265     top = (1.0 - shown) / 2.0;
  266     XtCallCallbacks(scroll, XtNjumpProc, &top);
  267     }
  268 }
  269 
  270 /* Get the selection, if no selection, get the insertion point. */
  271 /* Mark all pages in range, and cause toc to update. */
  272 void
  273 mark_page(w, client_data, call_data)
  274     Widget w;
  275     XtPointer client_data, call_data;
  276 {
  277     XawTextPosition begin, end;
  278     int i;
  279 
  280     XawTextGetSelectionPos(toc, &begin, &end);
  281     if (begin == end) {     /* Nothing selected */
  282     begin = end = XawTextGetInsertionPoint(toc);
  283     } else {
  284     end--;          /* Sometimes end spills onto next line */
  285     }
  286     for (i = begin/toc_entry_length; i <= end/toc_entry_length; i++) {
  287     toc_text[i*toc_entry_length] = '*';
  288     XawTextInvalidate(toc, i*toc_entry_length, i*toc_entry_length+1);
  289     }
  290 }
  291 
  292 /* Get the selection, if no selection, get the insertion point. */
  293 /* Unmark all pages in range, and cause toc to update. */
  294 void
  295 unmark_page(w, client_data, call_data)
  296     Widget w;
  297     XtPointer client_data, call_data;
  298 {
  299     XawTextPosition begin, end;
  300     int i;
  301 
  302     XawTextGetSelectionPos(toc, &begin, &end);
  303     if (begin == end) {     /* Nothing selected */
  304     begin = end = XawTextGetInsertionPoint(toc);
  305     } else {
  306     end--;          /* Sometimes end spills onto next line */
  307     }
  308     for (i = begin/toc_entry_length; i <= end/toc_entry_length; i++) {
  309     toc_text[i*toc_entry_length] = ' ';
  310     XawTextInvalidate(toc, i*toc_entry_length, i*toc_entry_length+1);
  311     }
  312 }
  313 
  314 /* Set new magstep.  Reshow the current page if magstep changed. */
  315 void
  316 set_magstep(w, client_data, call_data)
  317     Widget w;
  318     XtPointer client_data, call_data;
  319 {
  320     app_res.magstep = (int)client_data;
  321     if (set_new_magstep()) {
  322     layout_ghostview();
  323     show_page(current_page);
  324     }
  325 }
  326 
  327 /* Set new orientation.  Reshow the current page if orientation changed. */
  328 void
  329 set_orientation(w, client_data, call_data)
  330     Widget w;
  331     XtPointer client_data, call_data;
  332 {
  333     app_res.force_orientation = force_setting;
  334     app_res.orientation = (XtPageOrientation) client_data;
  335     if (set_new_orientation(current_page)) {
  336     layout_ghostview();
  337     show_page(current_page);
  338     }
  339 }
  340 
  341 /* Swap the landscape labels and change the flag. */
  342 void
  343 swap_landscape(w, client_data, call_data)
  344     Widget w;
  345     XtPointer client_data, call_data;
  346 {
  347     Arg args[1];
  348     String s1, s2;
  349 
  350     app_res.swap_landscape = !app_res.swap_landscape;
  351 
  352     XtSetArg(args[0], XtNlabel, &s1);
  353     XtGetValues(landscapebutton, args, ONE);
  354     s1 = XtNewString(s1);
  355     XtSetArg(args[0], XtNlabel, &s2);
  356     XtGetValues(seascapebutton, args, ONE);
  357     s2 = XtNewString(s2);
  358     XtSetArg(args[0], XtNlabel, s2);
  359     XtSetValues(landscapebutton, args, ONE);
  360     XtSetArg(args[0], XtNlabel, s1);
  361     XtSetValues(seascapebutton, args, ONE);
  362     XtFree(s1);
  363     XtFree(s2);
  364 
  365     if (set_new_orientation(current_page)) {
  366     layout_ghostview();
  367     show_page(current_page);
  368     }
  369 }
  370 
  371 /* Set new page media.  If new page media is different, update app_resources */
  372 /* and redisplay page. */
  373 void
  374 set_pagemedia(w, client_data, call_data)
  375     Widget w;
  376     XtPointer client_data, call_data;
  377 {
  378     int new_pagemedia = (int) client_data;
  379     if (new_pagemedia >= base_papersize) {
  380     default_pagemedia = new_pagemedia;
  381     app_res.force_pagemedia = force_setting;
  382     } else {
  383     document_media = new_pagemedia;
  384     force_document_media = force_setting;
  385     }
  386     if (set_new_pagemedia(current_page)) {
  387     layout_ghostview();
  388     show_page(current_page);
  389     }
  390 }
  391 
  392 /* track mouse pointer and popup zoom window */
  393 void
  394 track_and_zoom(w, client_data, call_data)
  395     Widget w;
  396     XtPointer client_data, call_data;
  397 {
  398     Arg args[20];
  399     Cardinal num_args;
  400     Dimension width, height;
  401     Widget zoom;
  402     Widget zoomform;
  403     Widget zoompage;
  404     Widget zoomdismiss;
  405     FILE *zoomfile;
  406     struct stat sbuf;
  407     GhostviewReturnStruct *p = (GhostviewReturnStruct *)call_data;
  408     int llx;
  409     int lly;
  410     int urx;
  411     int ury;
  412     int bottom_margin;
  413     int left_margin;
  414     int right_margin;
  415     int top_margin;
  416     int i;
  417 
  418     /* locator events have zero width and height */
  419     if ((p->width == 0) || (p->height == 0)) {
  420     char buf[32];
  421     if (!app_res.show_locator) return;
  422     sprintf(buf, "(%d, %d)", p->psx, p->psy);
  423     XtSetArg(args[0], XtNlabel, buf);
  424     XtSetValues(locator, args, ONE);
  425     return;
  426     }
  427 
  428     /* If no file, nothing to zoom. */
  429     if (!psfile) return;
  430 
  431     /* If the file changed, cannot zoom */
  432     stat(filename, &sbuf);
  433     if (mtime != sbuf.st_mtime) return;
  434                             num_args = 0;
  435     XtSetArg(args[num_args], XtNcolormap, cmap);    num_args++;
  436     if (special_cmap) {
  437     XtSetArg(args[num_args], XtNbackground, white); num_args++;
  438     }
  439     zoom = XtCreatePopupShell("zoom", topLevelShellWidgetClass,
  440                   toplevel, args, num_args);
  441 
  442                             num_args = 0;
  443     if (special_cmap) {
  444     XtSetArg(args[num_args], XtNbackground, white); num_args++;
  445     }
  446     zoomform = XtCreateManagedWidget("form", formWidgetClass,
  447                      zoom, args, num_args);
  448 
  449     llx = p->psx - p->width/2;
  450     lly = p->psy - p->height/2;
  451     urx = p->psx + p->width/2;
  452     ury = p->psy + p->height/2;
  453 
  454     /* Make sure zoom window doesn't go off the edge of the page */
  455     if (llx < current_llx) {
  456     llx = current_llx;
  457     urx = llx + p->width;
  458     }
  459     if (lly < current_lly) {
  460     lly = current_lly;
  461     ury = lly + p->height;
  462     }
  463     if (urx > current_urx) {
  464     urx = current_urx;
  465     llx = urx - p->width;
  466     }
  467     if (ury > current_ury) {
  468     ury = current_ury;
  469     lly = ury - p->height;
  470     }
  471     if (llx < current_llx) {
  472     llx = current_llx;
  473     }
  474     if (lly < current_lly) {
  475     lly = current_lly;
  476     }
  477     bottom_margin = lly - current_lly;
  478     left_margin = llx - current_llx;
  479     right_margin = current_urx - urx;
  480     top_margin = current_ury - ury;
  481 
  482                             num_args = 0;
  483     if (special_cmap) {
  484     XtSetArg(args[num_args], XtNbackground, white); num_args++;
  485     }
  486     XtSetArg(args[num_args], XtNtop, XtChainTop);   num_args++;
  487     XtSetArg(args[num_args], XtNbottom, XtChainBottom); num_args++;
  488     XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
  489     XtSetArg(args[num_args], XtNright, XtChainRight);   num_args++;
  490     XtSetArg(args[num_args], XtNorientation, current_orientation);
  491                             num_args++;
  492     XtSetArg(args[num_args], XtNllx, llx);          num_args++;
  493     XtSetArg(args[num_args], XtNlly, lly);          num_args++;
  494     XtSetArg(args[num_args], XtNurx, urx);          num_args++;
  495     XtSetArg(args[num_args], XtNury, ury);          num_args++;
  496     XtSetArg(args[num_args], XtNbottomMargin, bottom_margin);
  497                             num_args++;
  498     XtSetArg(args[num_args], XtNleftMargin, left_margin);
  499                             num_args++;
  500     XtSetArg(args[num_args], XtNrightMargin, right_margin);
  501                             num_args++;
  502     XtSetArg(args[num_args], XtNtopMargin, top_margin); num_args++;
  503     XtSetArg(args[num_args], XtNbottomMargin, bottom_margin);
  504                             num_args++;
  505     XtSetFloatArg(args[num_args], XtNxdpi, p->xdpi);    num_args++;
  506     XtSetFloatArg(args[num_args], XtNydpi, p->ydpi);    num_args++;
  507     if (!toc_text) {
  508         XtSetArg(args[num_args], XtNfilename, filename);    num_args++;
  509     }
  510     zoompage = XtCreateManagedWidget("page", ghostviewWidgetClass,
  511                      zoomform, args, num_args);
  512     num_ghosts++;
  513     XtAddCallback(zoompage, XtNcallback, track_and_zoom, (XtPointer)0);
  514     XtAddCallback(zoompage, XtNmessageCallback, message, (XtPointer)zoompage);
  515     XtAddCallback(zoompage, XtNdestroyCallback, destroy_ghost,
  516           (XtPointer)zoompage);
  517 
  518                             num_args = 0;
  519     if (special_cmap) {
  520     XtSetArg(args[num_args], XtNforeground, black); num_args++;
  521     XtSetArg(args[num_args], XtNbackground, white); num_args++;
  522     }
  523     XtSetArg(args[num_args], XtNfromVert, zoompage);    num_args++;
  524     XtSetArg(args[num_args], XtNtop, XtChainBottom);    num_args++;
  525     XtSetArg(args[num_args], XtNbottom, XtChainBottom); num_args++;
  526     XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
  527     XtSetArg(args[num_args], XtNright, XtChainRight);   num_args++;
  528     zoomdismiss = XtCreateManagedWidget("dismiss", commandWidgetClass,
  529                        zoomform, args, num_args);
  530     XtAddCallback(zoomdismiss, XtNcallback, destroy, (XtPointer)zoom);
  531 
  532     XtSetArg(args[0], XtNwidth, &width);
  533     XtGetValues(zoompage, args, ONE);
  534     XtSetArg(args[0], XtNwidth, width);
  535     XtSetValues(zoomdismiss, args, ONE);
  536 
  537     XtRealizeWidget(zoom);
  538     positionpopup(zoom);
  539 
  540                             num_args = 0;
  541     XtSetArg(args[num_args], XtNwidth, &width);     num_args++;
  542     XtSetArg(args[num_args], XtNheight, &height);   num_args++;
  543     XtGetValues(zoom, args, num_args);
  544 
  545                                     num_args = 0;
  546     XtSetArg(args[num_args], XtNminWidth, width);       num_args++;
  547     XtSetArg(args[num_args], XtNminHeight, height);     num_args++;
  548     XtSetArg(args[num_args], XtNmaxWidth, width);       num_args++;
  549     XtSetArg(args[num_args], XtNmaxHeight, height);     num_args++;
  550     XtSetValues(zoom, args, num_args);
  551     XSetWMProtocols(XtDisplay(zoom), XtWindow(zoom), &wm_delete_window, 1);
  552     XtPopup(zoom, XtGrabNone);
  553 
  554     if (toc_text) {
  555     zoomfile = fopen(filename, "r");
  556     if (zoomfile == NULL) return;
  557     GhostviewSendPS(zoompage, zoomfile, doc->beginprolog,
  558             doc->lenprolog, False);
  559     GhostviewSendPS(zoompage, zoomfile, doc->beginsetup,
  560             doc->lensetup, False);
  561     if (doc->pageorder == DESCEND)
  562         i = (doc->numpages - 1) - current_page;
  563     else
  564         i = current_page;
  565     GhostviewSendPS(zoompage, zoomfile, doc->pages[i].begin,
  566             doc->pages[i].len, True);
  567     }
  568 }
  569 
  570 /* Process messages from ghostscript */
  571 /* Refresh occurs when window was resized unexpectedly */
  572 void
  573 message(w, client_data, call_data)
  574     Widget w;
  575     XtPointer client_data, call_data;
  576 {
  577     int i;
  578     char *error;
  579 
  580     if (!strcmp((char *) call_data, "Failed")) {
  581     if ((Widget)client_data == page) {
  582         error = "Error: PostScript interpreter failed in main window.\n\n";
  583     } else {
  584         error = "Error: PostScript interpreter failed in zoom window.\n\n";
  585     }
  586     output(w, NULL, error);
  587     } else if (!strcmp((char *) call_data, "BadAlloc")) {
  588     if ((Widget)client_data == page) {
  589         error = 
  590            "Warning: Could not allocate backing pixmap in main window.\n\n";
  591     } else {
  592         error = 
  593            "Warning: Could not allocate backing pixmap in zoom window.\n\n";
  594     }
  595     output(w, NULL, error);
  596     } else if (!strcmp((char *) call_data, "Refresh")) {
  597     if (toc_text) {
  598         GhostviewSendPS(w, psfile, doc->beginprolog,
  599                 doc->lenprolog, False);
  600         GhostviewSendPS(w, psfile, doc->beginsetup,
  601                 doc->lensetup, False);
  602         if (doc->pageorder == DESCEND)
  603         i = (doc->numpages - 1) - current_page;
  604         else
  605         i = current_page;
  606         GhostviewSendPS(w, psfile, doc->pages[i].begin,
  607                 doc->pages[i].len, False);
  608     }
  609     }
  610 }
  611 
  612 /* Take output from ghostscript and display it in the infotext popup window */
  613 void
  614 output(w, client_data, call_data)
  615     Widget w;
  616     XtPointer client_data, call_data;
  617 {
  618     Arg args[2];
  619     XawTextBlock message_block;
  620 
  621     message_block.firstPos = 0;
  622     message_block.length = strlen(call_data);
  623     message_block.ptr = call_data;
  624     message_block.format = FMT8BIT;
  625 
  626     XawTextDisableRedisplay(infotext);
  627 
  628     XtSetArg(args[0], XtNeditType, XawtextAppend);
  629     XtSetValues(infotext, args, ONE);
  630     XawTextReplace(infotext, info_length, info_length, &message_block);
  631     info_length = info_length + message_block.length;
  632 
  633     XtSetArg(args[0], XtNeditType, XawtextRead);
  634     XtSetArg(args[1], XtNinsertPosition, info_length);
  635     XtSetValues(infotext, args, TWO);
  636     XawTextEnableRedisplay(infotext);
  637     if (!info_up) XtPopup(infopopup, XtGrabNone);
  638     info_up = True;
  639 }
  640 
  641 /* Dismiss popup dialog */
  642 void
  643 okay(w, client_data, call_data)
  644     Widget w;
  645     XtPointer client_data, call_data;
  646 {
  647     String name, error;
  648     Widget dialog;
  649 
  650     dialog = (Widget)client_data;
  651     name = GetDialogResponse(dialog);
  652     switch (mode) {
  653     case PRINT_WHOLE:
  654     case PRINT_MARKED:
  655     if (error = print_file(name, (mode == PRINT_WHOLE))) {
  656         char *buf = XtMalloc(strlen(error) +
  657                  strlen(app_res.print_prompt) + 2);
  658         sprintf(buf, "%s\n%s", error, app_res.print_prompt);
  659         SetDialogPrompt(dialog, buf);
  660         XtFree(error);
  661         XtFree(buf);
  662     } else {
  663         XtPopdown(XtParent(dialog));
  664     }
  665     break;
  666     case OPEN:
  667     if (error = open_file(name)) {
  668         char *buf = XtMalloc(strlen(error) +
  669                  strlen(app_res.open_prompt) + 2);
  670         sprintf(buf, "%s\n%s", error, app_res.open_prompt);
  671         SetDialogPrompt(dialog, buf);
  672         XtFree(error);
  673         XtFree(buf);
  674     } else {
  675         XtPopdown(XtParent(dialog));
  676     }
  677     break;
  678     case SAVE:
  679     if (error = save_file(name)) {
  680         char *buf = XtMalloc(strlen(error) +
  681                  strlen(app_res.save_prompt) + 2);
  682         sprintf(buf, "%s\n%s", error, app_res.save_prompt);
  683         SetDialogPrompt(dialog, buf);
  684         XtFree(error);
  685         XtFree(buf);
  686     } else {
  687         XtPopdown(XtParent(dialog));
  688     }
  689     break;
  690     }
  691     XtFree(name);
  692 }
  693 
  694 /* Dismiss popup window */
  695 void
  696 dismiss(w, client_data, call_data)
  697     Widget w;
  698     XtPointer client_data, call_data;
  699 {
  700     XtPopdown((Widget)client_data);
  701     if ((Widget)client_data == infopopup) info_up = False;
  702 }
  703 
  704 /* Destroy popup window */
  705 void
  706 destroy(w, client_data, call_data)
  707     Widget w;
  708     XtPointer client_data, call_data;
  709 {
  710     XtDestroyWidget((Widget)client_data);
  711 }
  712 
  713 /* destroy callback for Ghostview widgets. */
  714 /* The disable interpreter call ensures that ghostscript is killed. */
  715 /* One the count goes to 0, we are sure that all forked processes have */
  716 /* been killed and that we can safely exit. */
  717 void
  718 destroy_ghost(w, client_data, call_data)
  719     Widget w;
  720     XtPointer client_data, call_data;
  721 {
  722     GhostviewDisableInterpreter((Widget) client_data);
  723     num_ghosts--;
  724     if (num_ghosts) return;
  725     if (dying) old_Xerror(XtDisplay(w), &bomb);
  726     XtDestroyApplicationContext(app_con);
  727     exit(0);
  728 }