"Fossies" - the Fresh Open Source Software Archive

Member "ghostview-1.5/callbacks.c" (24 Jul 1993, 19985 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  * 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     zoom = XtCreatePopupShell("zoom", topLevelShellWidgetClass,
  435                   toplevel, NULL, ZERO);
  436 
  437     zoomform = XtCreateManagedWidget("form", formWidgetClass,
  438                      zoom, NULL, ZERO);
  439 
  440     llx = p->psx - p->width/2;
  441     lly = p->psy - p->height/2;
  442     urx = p->psx + p->width/2;
  443     ury = p->psy + p->height/2;
  444 
  445     /* Make sure zoom window doesn't go off the edge of the page */
  446     if (llx < current_llx) {
  447     llx = current_llx;
  448     urx = llx + p->width;
  449     }
  450     if (lly < current_lly) {
  451     lly = current_lly;
  452     ury = lly + p->height;
  453     }
  454     if (urx > current_urx) {
  455     urx = current_urx;
  456     llx = urx - p->width;
  457     }
  458     if (ury > current_ury) {
  459     ury = current_ury;
  460     lly = ury - p->height;
  461     }
  462     if (llx < current_llx) {
  463     llx = current_llx;
  464     }
  465     if (lly < current_lly) {
  466     lly = current_lly;
  467     }
  468     bottom_margin = lly - current_lly;
  469     left_margin = llx - current_llx;
  470     right_margin = current_urx - urx;
  471     top_margin = current_ury - ury;
  472 
  473                             num_args = 0;
  474     XtSetArg(args[num_args], XtNtop, XtChainTop);   num_args++;
  475     XtSetArg(args[num_args], XtNbottom, XtChainBottom); num_args++;
  476     XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
  477     XtSetArg(args[num_args], XtNright, XtChainRight);   num_args++;
  478     XtSetArg(args[num_args], XtNorientation, current_orientation);
  479                             num_args++;
  480     XtSetArg(args[num_args], XtNllx, llx);          num_args++;
  481     XtSetArg(args[num_args], XtNlly, lly);          num_args++;
  482     XtSetArg(args[num_args], XtNurx, urx);          num_args++;
  483     XtSetArg(args[num_args], XtNury, ury);          num_args++;
  484     XtSetArg(args[num_args], XtNbottomMargin, bottom_margin);
  485                             num_args++;
  486     XtSetArg(args[num_args], XtNleftMargin, left_margin);
  487                             num_args++;
  488     XtSetArg(args[num_args], XtNrightMargin, right_margin);
  489                             num_args++;
  490     XtSetArg(args[num_args], XtNtopMargin, top_margin); num_args++;
  491     XtSetArg(args[num_args], XtNbottomMargin, bottom_margin);
  492                             num_args++;
  493     XtSetFloatArg(args[num_args], XtNxdpi, p->xdpi);    num_args++;
  494     XtSetFloatArg(args[num_args], XtNydpi, p->ydpi);    num_args++;
  495     if (!toc_text) {
  496         XtSetArg(args[num_args], XtNfilename, filename);    num_args++;
  497     }
  498     zoompage = XtCreateManagedWidget("page", ghostviewWidgetClass,
  499                      zoomform, args, num_args);
  500     num_ghosts++;
  501     XtAddCallback(zoompage, XtNcallback, track_and_zoom, (XtPointer)0);
  502     XtAddCallback(zoompage, XtNmessageCallback, message, (XtPointer)zoompage);
  503     XtAddCallback(zoompage, XtNdestroyCallback, destroy_ghost,
  504           (XtPointer)zoompage);
  505 
  506                             num_args = 0;
  507     XtSetArg(args[num_args], XtNfromVert, zoompage);    num_args++;
  508     XtSetArg(args[num_args], XtNtop, XtChainBottom);    num_args++;
  509     XtSetArg(args[num_args], XtNbottom, XtChainBottom); num_args++;
  510     XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
  511     XtSetArg(args[num_args], XtNright, XtChainRight);   num_args++;
  512     zoomdismiss = XtCreateManagedWidget("dismiss", commandWidgetClass,
  513                        zoomform, args, num_args);
  514     XtAddCallback(zoomdismiss, XtNcallback, destroy, (XtPointer)zoom);
  515 
  516     XtSetArg(args[0], XtNwidth, &width);
  517     XtGetValues(zoompage, args, ONE);
  518     XtSetArg(args[0], XtNwidth, width);
  519     XtSetValues(zoomdismiss, args, ONE);
  520 
  521     XtRealizeWidget(zoom);
  522     positionpopup(zoom);
  523 
  524                             num_args = 0;
  525     XtSetArg(args[num_args], XtNwidth, &width);     num_args++;
  526     XtSetArg(args[num_args], XtNheight, &height);   num_args++;
  527     XtGetValues(zoom, args, num_args);
  528 
  529                                     num_args = 0;
  530     XtSetArg(args[num_args], XtNminWidth, width);       num_args++;
  531     XtSetArg(args[num_args], XtNminHeight, height);     num_args++;
  532     XtSetArg(args[num_args], XtNmaxWidth, width);       num_args++;
  533     XtSetArg(args[num_args], XtNmaxHeight, height);     num_args++;
  534     XtSetValues(zoom, args, num_args);
  535     XSetWMProtocols(XtDisplay(zoom), XtWindow(zoom), &wm_delete_window, 1);
  536     XtPopup(zoom, XtGrabNone);
  537 
  538     if (toc_text) {
  539     zoomfile = fopen(filename, "r");
  540     if (zoomfile == NULL) return;
  541     GhostviewSendPS(zoompage, zoomfile, doc->beginprolog,
  542             doc->lenprolog, False);
  543     GhostviewSendPS(zoompage, zoomfile, doc->beginsetup,
  544             doc->lensetup, False);
  545     if (doc->pageorder == DESCEND)
  546         i = (doc->numpages - 1) - current_page;
  547     else
  548         i = current_page;
  549     GhostviewSendPS(zoompage, zoomfile, doc->pages[i].begin,
  550             doc->pages[i].len, True);
  551     }
  552 }
  553 
  554 /* Process messages from ghostscript */
  555 /* Refresh occurs when window was resized unexpectedly */
  556 void
  557 message(w, client_data, call_data)
  558     Widget w;
  559     XtPointer client_data, call_data;
  560 {
  561     int i;
  562     char *error;
  563 
  564     if (!strcmp((char *) call_data, "Failed")) {
  565     if ((Widget)client_data == page) {
  566         error = "Error: PostScript interpreter failed in main window.\n\n";
  567     } else {
  568         error = "Error: PostScript interpreter failed in zoom window.\n\n";
  569     }
  570     output(w, NULL, error);
  571     } else if (!strcmp((char *) call_data, "BadAlloc")) {
  572     if ((Widget)client_data == page) {
  573         error = 
  574            "Warning: Could not allocate backing pixmap in main window.\n\n";
  575     } else {
  576         error = 
  577            "Warning: Could not allocate backing pixmap in zoom window.\n\n";
  578     }
  579     output(w, NULL, error);
  580     } else if (!strcmp((char *) call_data, "Refresh")) {
  581     if (toc_text) {
  582         GhostviewSendPS(w, psfile, doc->beginprolog,
  583                 doc->lenprolog, False);
  584         GhostviewSendPS(w, psfile, doc->beginsetup,
  585                 doc->lensetup, False);
  586         if (doc->pageorder == DESCEND)
  587         i = (doc->numpages - 1) - current_page;
  588         else
  589         i = current_page;
  590         GhostviewSendPS(w, psfile, doc->pages[i].begin,
  591                 doc->pages[i].len, False);
  592     }
  593     }
  594 }
  595 
  596 /* Take output from ghostscript and display it in the infotext popup window */
  597 void
  598 output(w, client_data, call_data)
  599     Widget w;
  600     XtPointer client_data, call_data;
  601 {
  602     Arg args[2];
  603     XawTextBlock message_block;
  604 
  605     message_block.firstPos = 0;
  606     message_block.length = strlen(call_data);
  607     message_block.ptr = call_data;
  608     message_block.format = FMT8BIT;
  609 
  610     XawTextDisableRedisplay(infotext);
  611 
  612     XtSetArg(args[0], XtNeditType, XawtextAppend);
  613     XtSetValues(infotext, args, ONE);
  614     XawTextReplace(infotext, info_length, info_length, &message_block);
  615     info_length = info_length + message_block.length;
  616 
  617     XtSetArg(args[0], XtNeditType, XawtextRead);
  618     XtSetArg(args[1], XtNinsertPosition, info_length);
  619     XtSetValues(infotext, args, TWO);
  620     XawTextEnableRedisplay(infotext);
  621     if (!info_up) XtPopup(infopopup, XtGrabNone);
  622     info_up = True;
  623 }
  624 
  625 /* Dismiss popup dialog */
  626 void
  627 okay(w, client_data, call_data)
  628     Widget w;
  629     XtPointer client_data, call_data;
  630 {
  631     String name, error;
  632     Widget dialog;
  633 
  634     dialog = (Widget)client_data;
  635     name = GetDialogResponse(dialog);
  636     switch (mode) {
  637     case PRINT_WHOLE:
  638     case PRINT_MARKED:
  639     if (error = print_file(name, (mode == PRINT_WHOLE))) {
  640         char *buf = XtMalloc(strlen(error) +
  641                  strlen(app_res.print_prompt) + 2);
  642         sprintf(buf, "%s\n%s", error, app_res.print_prompt);
  643         SetDialogPrompt(dialog, buf);
  644         XtFree(error);
  645         XtFree(buf);
  646     } else {
  647         XtPopdown(XtParent(dialog));
  648     }
  649     break;
  650     case OPEN:
  651     if (error = open_file(name)) {
  652         char *buf = XtMalloc(strlen(error) +
  653                  strlen(app_res.open_prompt) + 2);
  654         sprintf(buf, "%s\n%s", error, app_res.open_prompt);
  655         SetDialogPrompt(dialog, buf);
  656         XtFree(error);
  657         XtFree(buf);
  658     } else {
  659         XtPopdown(XtParent(dialog));
  660     }
  661     break;
  662     case SAVE:
  663     if (error = save_file(name)) {
  664         char *buf = XtMalloc(strlen(error) +
  665                  strlen(app_res.save_prompt) + 2);
  666         sprintf(buf, "%s\n%s", error, app_res.save_prompt);
  667         SetDialogPrompt(dialog, buf);
  668         XtFree(error);
  669         XtFree(buf);
  670     } else {
  671         XtPopdown(XtParent(dialog));
  672     }
  673     break;
  674     }
  675     XtFree(name);
  676 }
  677 
  678 /* Dismiss popup window */
  679 void
  680 dismiss(w, client_data, call_data)
  681     Widget w;
  682     XtPointer client_data, call_data;
  683 {
  684     XtPopdown((Widget)client_data);
  685     if ((Widget)client_data == infopopup) info_up = False;
  686 }
  687 
  688 /* Destroy popup window */
  689 void
  690 destroy(w, client_data, call_data)
  691     Widget w;
  692     XtPointer client_data, call_data;
  693 {
  694     XtDestroyWidget((Widget)client_data);
  695 }
  696 
  697 /* destroy callback for Ghostview widgets. */
  698 /* The disable interpreter call ensures that ghostscript is killed. */
  699 /* One the count goes to 0, we are sure that all forked processes have */
  700 /* been killed and that we can safely exit. */
  701 void
  702 destroy_ghost(w, client_data, call_data)
  703     Widget w;
  704     XtPointer client_data, call_data;
  705 {
  706     GhostviewDisableInterpreter((Widget) client_data);
  707     num_ghosts--;
  708     if (num_ghosts) return;
  709     if (dying) old_Xerror(XtDisplay(w), &bomb);
  710     XtDestroyApplicationContext(app_con);
  711     exit(0);
  712 }