"Fossies" - the Fresh Open Source Software Archive 
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 }