"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 * 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 Cardinal num_args;
498 Widget w;
499 /* Yuck, cannot get vScrollbar via the usual methods */
500 TextWidget tw;
501 Dimension min_width, min_height;
502 Dimension max_width, max_height;
503 Dimension form_width, form_height;
504 Dimension title_height, title_border;
505 Dimension date_height, date_border;
506 Dimension locator_height, locator_border;
507 Dimension box_width, box_height, box_border;
508 Dimension label_width;
509 Dimension toc_width, toc_height, toc_border;
510 Dimension view_width, view_height, view_border;
511 Dimension page_width, page_height;
512 Dimension leftMargin, rightMargin;
513 Dimension width, height;
514 Boolean correct = True;
515 int distance;
516 int a_label;
517 XFontStruct *font;
518
519 XawFormDoLayout(form, False);
520 reset_size_hints();
521 reset_scroll_bars();
522 break_chains();
523
524 XtSetArg(args[0], XtNdefaultDistance, &distance);
525 XtGetValues(form, args, ONE);
526
527 a_label = 0;
528 if (app_res.show_title) {
529 XtSetArg(args[0], XtNheight, &title_height);
530 XtSetArg(args[1], XtNborderWidth, &title_border);
531 XtGetValues(titlebutton, args, TWO);
532 a_label = 1;
533 } else {
534 title_height = title_border = 0;
535 }
536
537 if (app_res.show_date) {
538 XtSetArg(args[0], XtNheight, &date_height);
539 XtSetArg(args[1], XtNborderWidth, &date_border);
540 XtGetValues(datebutton, args, TWO);
541 a_label = 1;
542 } else {
543 date_height = date_border = 0;
544 }
545
546 if (app_res.show_locator) {
547 XtSetArg(args[0], XtNheight, &locator_height);
548 XtSetArg(args[1], XtNborderWidth, &locator_border);
549 XtGetValues(locator, args, TWO);
550 a_label = 1;
551 } else {
552 locator_height = locator_border = 0;
553 }
554
555 XtSetArg(args[0], XtNwidth, &box_width);
556 XtSetArg(args[1], XtNheight, &box_height);
557 XtSetArg(args[2], XtNborderWidth, &box_border);
558 XtGetValues(box, args, THREE);
559
560 XtSetArg(args[0], XtNfont, &font);
561 XtSetArg(args[1], XtNleftMargin, &leftMargin);
562 XtSetArg(args[2], XtNrightMargin, &rightMargin);
563 XtSetArg(args[3], XtNborderWidth, &toc_border);
564 XtGetValues(toc, args, FOUR);
565 toc_width = font->max_bounds.width * (toc_entry_length - 1) +
566 leftMargin + rightMargin;
567
568 XtSetArg(args[0], XtNwidth, &page_width);
569 XtSetArg(args[1], XtNheight, &page_height);
570 XtGetValues(page, args, TWO);
571
572 XtSetArg(args[0], XtNborderWidth, &view_border);
573 XtGetValues(pageview, args, ONE);
574 view_width = page_width;
575 view_height = page_height;
576
577 min_width = box_width + 2*box_border + toc_width + 2*toc_border +
578 2*view_border + 4*distance;
579 min_height = title_height + 2*title_border + date_height + 2*date_border +
580 locator_height + 2*locator_border + box_height + 2*box_border +
581 (2+a_label)*distance;
582
583 max_width = WidthOfScreen(XtScreen(toplevel)) - app_res.wm_horiz_margin;
584 max_height = HeightOfScreen(XtScreen(toplevel)) - app_res.wm_vert_margin;
585
586 if (min_width + view_width > max_width)
587 view_width = max_width - min_width;
588 if (2*(view_border + distance) + view_height > max_height)
589 view_height = max_height - 2*(view_border + distance);
590 form_width = view_width + min_width;
591 form_height = max(view_height + 2*(view_border + distance), min_height);
592 toc_height = view_height - (title_height + 2*title_border +
593 date_height + 2*date_border +
594 locator_height + 2*locator_border +
595 a_label*distance);
596
597 label_width = box_width + 2*box_border + distance +
598 toc_width + 2*toc_border;
599
600 XtSetArg(args[0], XtNwidth, form_width);
601 XtSetArg(args[1], XtNheight, form_height);
602 XtSetValues(form, args, TWO);
603
604 XtSetArg(args[0], XtNwidth, label_width);
605 if (app_res.show_title) XtSetValues(titlebutton, args, ONE);
606 if (app_res.show_date) XtSetValues(datebutton, args, ONE);
607 if (app_res.show_locator) XtSetValues(locator, args, ONE);
608
609 XtSetArg(args[0], XtNwidth, toc_width);
610 XtSetArg(args[1], XtNheight, toc_height);
611 XtSetValues(toc, args, TWO);
612
613 XtSetArg(args[0], XtNwidth, view_width);
614 XtSetArg(args[1], XtNheight, view_height);
615 XtSetValues(pageview, args, TWO);
616
617 XawFormDoLayout(form, True);
618
619 /* Check to make sure everything was done as planned. */
620 XtSetArg(args[0], XtNwidth, &width);
621 XtSetArg(args[1], XtNheight, &height);
622
623 XtGetValues(form, args, TWO);
624 if (width != form_width || height != form_height) {
625 correct = False;
626 /* fprintf(stderr, "Oops, %dx%d form was supposed to be %dx%d.\n",
627 width, height, form_width, form_height); */
628 }
629 if (app_res.show_title) {
630 XtGetValues(titlebutton, args, ONE);
631 if (width != label_width) {
632 correct = False;
633 /* fprintf(stderr,
634 "Oops, %d wide title was supposed to be %d wide.\n",
635 width, label_width); */
636 }
637 }
638 if (app_res.show_date) {
639 XtGetValues(datebutton, args, ONE);
640 if (width != label_width) {
641 correct = False;
642 /* fprintf(stderr,
643 "Oops, %d wide date was supposed to be %d wide.\n",
644 width, label_width); */
645 }
646 }
647 if (app_res.show_locator) {
648 XtGetValues(locator, args, ONE);
649 if (width != label_width) {
650 correct = False;
651 /* fprintf(stderr,
652 "Oops, %d wide locator was supposed to be %d wide.\n",
653 width, label_width); */
654 }
655 }
656 XtGetValues(toc, args, TWO);
657 if (width != toc_width || height != toc_height) {
658 correct = False;
659 /* fprintf(stderr, "Oops, %dx%d toc was supposed to be %dx%d.\n",
660 width, height, toc_width, toc_height); */
661 }
662 XtGetValues(pageview, args, TWO);
663 if (width != view_width || height != view_height) {
664 correct = False;
665 /* fprintf(stderr, "Oops, %dx%d pageview was supposed to be %dx%d.\n",
666 width, height, view_width, view_height); */
667 }
668
669 if (correct) {
670 if (special_cmap) {
671 /* Yuck, cannot get vScrollbar via the usual methods */
672 /* w = XtNameToWidget(toc, "*vScrollbar"); */
673 tw = (TextWidget) toc;
674 w = tw->text.vbar;
675 if (w) {
676 /* Double Yuck, have to set them twice to make them */
677 /* get the right colors */
678 num_args = 0;
679 XtSetArg(args[num_args], XtNforeground, white); num_args++;
680 XtSetArg(args[num_args], XtNbackground, black); num_args++;
681 XtSetValues(w, args, num_args);
682 num_args = 0;
683 XtSetArg(args[num_args], XtNforeground, black); num_args++;
684 XtSetArg(args[num_args], XtNbackground, white); num_args++;
685 XtSetValues(w, args, num_args);
686 }
687
688 w = XtNameToWidget(pageview, "horizontal");
689 if (w) {
690 num_args = 0;
691 XtSetArg(args[num_args], XtNforeground, black); num_args++;
692 XtSetArg(args[num_args], XtNbackground, white); num_args++;
693 XtSetValues(w, args, num_args);
694 }
695
696 w = XtNameToWidget(pageview, "vertical");
697 if (w) {
698 num_args = 0;
699 XtSetArg(args[num_args], XtNforeground, black); num_args++;
700 XtSetArg(args[num_args], XtNbackground, white); num_args++;
701 XtSetValues(w, args, num_args);
702 }
703 }
704
705 set_size_hints(min_width, min_height, min_width+page_width,
706 max(form_height,
707 page_height + 2*(view_border + distance)));
708 if (app_res.auto_center) {
709 horiz_scroll_saved = vert_scroll_saved = False;
710 center_page(form, NULL, NULL);
711 } else {
712 set_scroll_bars();
713 }
714 set_chains();
715 delay = 125; /* Reset to 1/8 second delay */
716 /* fprintf(stderr, "Layout correct.\n"); */
717 } else {
718 XSync(XtDisplay(toplevel), False);
719 XtAppAddTimeOut(app_con, delay, try_try_again, NULL);
720 /* fprintf(stderr, "Didn't work, scheduling(%d)...\n",delay); */
721 }
722
723 }
724
725 /* Create a Standard colormap for ghostscript to use. */
726 void
727 SetStandardColormap(w)
728 Widget w;
729 {
730 XVisualInfo xvinfo;
731 XVisualInfo *xvinfop;
732 Atom prop;
733 XStandardColormap *std_cmap = NULL;
734 XStandardColormap *scmap, *sp;
735 Screen *scr = DefaultScreenOfDisplay(XtDisplay(w));
736 int nitems, i;
737 Boolean has_color;
738 Arg args[20];
739 Cardinal num_args;
740
741 XtSetArg(args[0], XtNvisual, &(xvinfo.visual));
742 XtGetValues(w, args, ONE);
743 if (xvinfo.visual == CopyFromParent)
744 xvinfo.visual = DefaultVisualOfScreen(scr);
745 xvinfo.visualid = XVisualIDFromVisual(xvinfo.visual);
746 xvinfop = XGetVisualInfo(XtDisplay(w), VisualIDMask, &xvinfo, &nitems);
747 if (xvinfop == NULL) {
748 fprintf(stderr, "Bad visual class.\n");
749 exit(1);
750 }
751 xvinfo = *xvinfop;
752 XtFree((char *)xvinfop);
753
754 has_color = (xvinfo.class != StaticGray) && (xvinfo.class != GrayScale);
755
756 if (has_color) {
757 if (xvinfo.visual == DefaultVisualOfScreen(scr)) {
758 prop = XA_RGB_DEFAULT_MAP;
759 } else {
760 prop = XA_RGB_BEST_MAP;
761 }
762 } else {
763 prop = XA_RGB_GRAY_MAP;
764 }
765
766 if (XGetRGBColormaps(XtDisplay(w), RootWindowOfScreen(scr),
767 &scmap, &nitems, prop)) {
768 for (i = 0, sp = scmap; i < nitems; i++, sp++) {
769 if (xvinfo.visualid == sp->visualid) {
770 std_cmap = sp;
771 break;
772 }
773 }
774 }
775
776 if (!std_cmap && app_res.install_std_cmap) {
777 if (XmuLookupStandardColormap(XtDisplay(w),
778 DefaultScreen(XtDisplay(w)),
779 xvinfo.visualid, xvinfo.depth,
780 prop, False, app_res.retain_std_cmap)) {
781 if (XGetRGBColormaps(XtDisplay(w), RootWindowOfScreen(scr),
782 &scmap, &nitems, prop)) {
783 for (i = 0, sp = scmap; i < nitems; i++, sp++) {
784 if (xvinfo.visualid == sp->visualid) {
785 std_cmap = sp;
786 }
787 }
788 }
789 }
790 }
791
792 if (std_cmap && xvinfo.visual == DefaultVisualOfScreen(scr) &&
793 std_cmap->colormap != DefaultColormapOfScreen(scr) &&
794 !app_res.private_cmap) {
795 std_cmap = NULL;
796 }
797 if (std_cmap) {
798 cmap = std_cmap->colormap;
799 if (std_cmap->colormap != DefaultColormapOfScreen(scr)) {
800 black = std_cmap->base_pixel;
801 white = std_cmap->red_max * std_cmap->red_mult +
802 std_cmap->green_max * std_cmap->green_mult +
803 std_cmap->blue_max * std_cmap->blue_mult +
804 std_cmap->base_pixel;
805 } else {
806 white = WhitePixelOfScreen(scr);
807 black = BlackPixelOfScreen(scr);
808 }
809 } else {
810 if (xvinfo.visual == DefaultVisualOfScreen(scr)) {
811 cmap = DefaultColormapOfScreen(scr);
812 white = WhitePixelOfScreen(scr);
813 black = BlackPixelOfScreen(scr);
814 } else {
815 XColor c;
816 cmap = XCreateColormap(XtDisplay(w), RootWindowOfScreen(scr),
817 xvinfo.visual, AllocNone);
818 c.red = c.green = c.blue = ~(unsigned short)0;
819 XAllocColor(XtDisplay(w), cmap, &c);
820 white = c.pixel;
821 c.red = c.green = c.blue = 0;
822 XAllocColor(XtDisplay(w), cmap, &c);
823 black = c.pixel;
824 }
825 }
826 special_cmap = cmap != DefaultColormapOfScreen(scr);
827
828 num_args = 0;
829 XtSetArg(args[num_args], XtNcolormap, cmap); num_args++;
830 if (special_cmap) {
831 XtSetArg(args[num_args], XtNforeground, black); num_args++;
832 XtSetArg(args[num_args], XtNbackground, white); num_args++;
833 }
834 XtSetValues(w, args, num_args);
835 }
836
837 /* Compute new dpi from magstep */
838 void
839 magnify(dpi, magstep)
840 float *dpi;
841 int magstep;
842 {
843 if (magstep < 0) {
844 while (magstep++) *dpi /= 1.2;
845 } else {
846 while (magstep--) *dpi *= 1.2;
847 }
848 }
849
850 /* Attempt to open file, return error message string on failure */
851 String
852 open_file(name)
853 String name;
854 {
855 FILE *fp;
856 struct stat sbuf;
857
858 if (*name == '\0') { /* Null filename */
859 return(NULL);
860 }
861 if (strcmp(name, "-")) {
862 if ((fp = fopen(name, "r")) == NULL) {
863 String buf = XtMalloc(strlen(app_res.open_fail) +
864 strlen(sys_errlist[errno]) + 1);
865 strcpy(buf, app_res.open_fail);
866 if (errno <= sys_nerr) strcat(buf, sys_errlist[errno]);
867 return buf;
868 } else {
869 if (oldfilename) XtFree(oldfilename);
870 oldfilename = filename;
871 filename = XtNewString(name);
872 if (psfile) fclose(psfile);
873 psfile = fp;
874 stat(filename, &sbuf);
875 mtime = sbuf.st_mtime;
876 new_file(0);
877 show_page(0);
878 return(NULL);
879 }
880 } else {
881 if (oldfilename) XtFree(oldfilename);
882 oldfilename = filename;
883 filename = XtNewString(name);
884 if (psfile) fclose(psfile);
885 psfile = NULL;
886 new_file(0);
887 show_page(0);
888 return(NULL);
889 }
890 }
891
892 /* Attempt to save file, return error message string on failure */
893 String
894 save_file(name)
895 String name;
896 {
897 FILE *pswrite;
898
899 if (*name == '\0') { /* Null filename */
900 return(NULL);
901 }
902 if ((pswrite = fopen(name, "w")) == NULL) {
903 String buf = XtMalloc(strlen(app_res.save_fail) +
904 strlen(sys_errlist[errno]) + 1);
905 strcpy(buf, app_res.save_fail);
906 if (errno <= sys_nerr) strcat(buf, sys_errlist[errno]);
907 return buf;
908 } else {
909 pscopydoc(pswrite);
910 fclose(pswrite);
911 return(NULL);
912 }
913 }
914
915 /* Attempt to print file. Return error string on failure */
916 String
917 print_file(name, whole_mode)
918 String name;
919 Boolean whole_mode;
920 {
921 FILE *printer;
922 SIGVAL (*oldsig)();
923 int bytes;
924 char buf[BUFSIZ];
925 #ifdef VMS
926 char fnam[64], *p;
927 #endif
928 Boolean failed;
929 String ret_val;
930
931 #ifdef VMS
932 sprintf(fnam, "sys$scratch:%s.tmp", tmpnam(NULL));
933 printer = fopen(fnam, "w");
934 #else /* VMS */
935 if (*name != '\0') {
936 setenv(app_res.printer_variable, name, True);
937 }
938 oldsig = signal(SIGPIPE, SIG_IGN);
939 printer = popen(app_res.print_command, "w");
940 #endif /* VMS */
941 if (toc_text && !whole_mode) {
942 pscopydoc(printer);
943 } else {
944 FILE *psfile = fopen(filename, "r");
945 while (bytes = read(fileno(psfile), buf, BUFSIZ))
946 bytes = write(fileno(printer), buf, bytes);
947 fclose(psfile);
948 }
949 #ifdef VMS
950 sprintf(buf, "%s %s %s", app_res.print_command, name, fnam);
951 failed = fclose(printer) != 0 || system(buf) != 1;
952 #else /* VMS */
953 failed = pclose(printer) != 0;
954 #endif /* VMS */
955 if (failed) {
956 sprintf(buf, app_res.print_fail, app_res.print_command);
957 ret_val = XtNewString(buf);
958 } else {
959 ret_val = NULL;
960 }
961 #ifndef VMS
962 signal(SIGPIPE, oldsig);
963 #endif /* VMS */
964 return(ret_val);
965 }
966
967 /* length calculates string length at compile time */
968 /* can only be used with character constants */
969 #define length(a) (sizeof(a)-1)
970
971 /* Copy the headers, marked pages, and trailer to fp */
972 void
973 pscopydoc(fp)
974 FILE *fp;
975 {
976 FILE *psfile;
977 char text[PSLINELENGTH];
978 char *comment;
979 Boolean pages_written = False;
980 Boolean pages_atend = False;
981 Boolean marked_pages = False;
982 int pages = 0;
983 int page = 1;
984 int i, j;
985 long here;
986
987 psfile = fopen(filename, "r");
988
989 for (i = 0; i < doc->numpages; i++) {
990 if (toc_text[toc_entry_length * i] == '*') pages++;
991 }
992
993 if (pages == 0) { /* User forgot to mark the pages */
994 mark_page(form, NULL, NULL);
995 marked_pages = True;
996 for (i = 0; i < doc->numpages; i++) {
997 if (toc_text[toc_entry_length * i] == '*') pages++;
998 }
999 }
1000
1001 here = doc->beginheader;
1002 while (comment = pscopyuntil(psfile, fp, here,
1003 doc->endheader, "%%Pages:")) {
1004 here = ftell(psfile);
1005 if (pages_written || pages_atend) {
1006 free(comment);
1007 continue;
1008 }
1009 sscanf(comment+length("%%Pages:"), "%s", text);
1010 if (strcmp(text, "(atend)") == 0) {
1011 fputs(comment, fp);
1012 pages_atend = True;
1013 } else {
1014 switch (sscanf(comment+length("%%Pages:"), "%*d %d", &i)) {
1015 case 1:
1016 fprintf(fp, "%%%%Pages: %d %d\n", pages, i);
1017 break;
1018 default:
1019 fprintf(fp, "%%%%Pages: %d\n", pages);
1020 break;
1021 }
1022 pages_written = True;
1023 }
1024 free(comment);
1025 }
1026 pscopy(psfile, fp, doc->beginpreview, doc->endpreview);
1027 pscopy(psfile, fp, doc->begindefaults, doc->enddefaults);
1028 pscopy(psfile, fp, doc->beginprolog, doc->endprolog);
1029 pscopy(psfile, fp, doc->beginsetup, doc->endsetup);
1030
1031 for (i = 0; i < doc->numpages; i++) {
1032 if (doc->pageorder == DESCEND)
1033 j = (doc->numpages - 1) - i;
1034 else
1035 j = i;
1036 if (toc_text[toc_entry_length * j] == '*') {
1037 comment = pscopyuntil(psfile, fp, doc->pages[i].begin,
1038 doc->pages[i].end, "%%Page:");
1039 fprintf(fp, "%%%%Page: %s %d\n",
1040 doc->pages[i].label, page++);
1041 free(comment);
1042 pscopy(psfile, fp, -1, doc->pages[i].end);
1043 }
1044 }
1045
1046 here = doc->begintrailer;
1047 while (comment = pscopyuntil(psfile, fp, here,
1048 doc->endtrailer, "%%Pages:")) {
1049 here = ftell(psfile);
1050 if (pages_written) {
1051 free(comment);
1052 continue;
1053 }
1054 switch (sscanf(comment+length("%%Pages:"), "%*d %d", &i)) {
1055 case 1:
1056 fprintf(fp, "%%%%Pages: %d %d\n", pages, i);
1057 break;
1058 default:
1059 fprintf(fp, "%%%%Pages: %d\n", pages);
1060 break;
1061 }
1062 pages_written = True;
1063 free(comment);
1064 }
1065 fclose(psfile);
1066
1067 if (marked_pages) unmark_page(form, NULL, NULL);
1068 }
1069 #undef length
1070
1071 /* position popup window under the cursor */
1072 void
1073 positionpopup(w)
1074 Widget w;
1075 {
1076 Arg args[3];
1077 Cardinal num_args;
1078 Dimension width, height, b_width;
1079 int x, y, max_x, max_y;
1080 Window root, child;
1081 int dummyx, dummyy;
1082 unsigned int dummymask;
1083
1084 XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
1085 &dummyx, &dummyy, &dummymask);
1086 num_args = 0;
1087 XtSetArg(args[num_args], XtNwidth, &width); num_args++;
1088 XtSetArg(args[num_args], XtNheight, &height); num_args++;
1089 XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
1090 XtGetValues(w, args, num_args);
1091
1092 width += 2 * b_width;
1093 height += 2 * b_width;
1094
1095 x -= ( (Position) width/2 );
1096 if (x < 0) x = 0;
1097 if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
1098
1099 y -= ( (Position) height/2 );
1100 if (y < 0) y = 0;
1101 if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
1102
1103 num_args = 0;
1104 XtSetArg(args[num_args], XtNx, x); num_args++;
1105 XtSetArg(args[num_args], XtNy, y); num_args++;
1106 XtSetValues(w, args, num_args);
1107 }
1108
1109 /* Set new magstep */
1110 Boolean
1111 set_new_magstep()
1112 {
1113 int new_magstep;
1114 Boolean changed = False;
1115 Arg args[20];
1116 Cardinal num_args;
1117 float xdpi, ydpi;
1118
1119 new_magstep = app_res.magstep;
1120 /* If magstep changed, stop interpreter and setup for new dpi. */
1121 if (new_magstep != current_magstep) {
1122 GhostviewDisableInterpreter(page);
1123 XawFormDoLayout(form, False);
1124 reset_size_hints();
1125 reset_scroll_bars();
1126 break_chains();
1127 changed = True;
1128 xdpi = default_xdpi;
1129 ydpi = default_ydpi;
1130 magnify(&xdpi, new_magstep);
1131 magnify(&ydpi, new_magstep);
1132 num_args = 0;
1133 XtSetFloatArg(args[num_args], XtNxdpi, xdpi); num_args++;
1134 XtSetFloatArg(args[num_args], XtNydpi, ydpi); num_args++;
1135 XtSetValues(page, args, num_args);
1136
1137 XtSetArg(args[0], XtNleftBitmap, None);
1138 XtSetValues(magstepentry[current_magstep - app_res.minimum_magstep],
1139 args, ONE);
1140 current_magstep = new_magstep;
1141 }
1142 XtSetArg(args[0], XtNleftBitmap, dot_bitmap);
1143 XtSetValues(magstepentry[current_magstep - app_res.minimum_magstep],
1144 args, ONE);
1145
1146 return changed;
1147 }
1148
1149 /* Set new orientation */
1150 Boolean
1151 set_new_orientation(number)
1152 int number;
1153 {
1154 Boolean changed = False;
1155 Boolean from_doc = False;
1156 Arg args[1];
1157 XtPageOrientation new_orientation;
1158
1159 if (app_res.force_orientation) {
1160 new_orientation = app_res.orientation;
1161 } else {
1162 if (doc) {
1163 if (toc_text && doc->pages[number].orientation != NONE) {
1164 new_orientation = xorient(doc->pages[number].orientation);
1165 from_doc = True;
1166 } else if (doc->default_page_orientation != NONE) {
1167 new_orientation = xorient(doc->default_page_orientation);
1168 from_doc = True;
1169 } else if (doc->orientation != NONE) {
1170 new_orientation = xorient(doc->orientation);
1171 from_doc = True;
1172 } else {
1173 new_orientation = app_res.orientation;
1174 }
1175 } else {
1176 new_orientation = app_res.orientation;
1177 }
1178 }
1179
1180 /* If orientation changed,
1181 * stop interpreter and setup for new orientation. */
1182 if (new_orientation != current_orientation) {
1183 GhostviewDisableInterpreter(page);
1184 XawFormDoLayout(form, False);
1185 reset_size_hints();
1186 reset_scroll_bars();
1187 break_chains();
1188 changed = True;
1189 XtSetArg(args[0], XtNorientation, new_orientation);
1190 XtSetValues(page, args, ONE);
1191 XtSetArg(args[0], XtNleftBitmap, None);
1192 if (current_orientation == XtPageOrientationPortrait)
1193 XtSetValues(portraitbutton, args, ONE);
1194 else if (current_orientation == XtPageOrientationLandscape)
1195 XtSetValues(landscapebutton, args, ONE);
1196 else if (current_orientation == XtPageOrientationUpsideDown)
1197 XtSetValues(upsidedownbutton, args, ONE);
1198 else if (current_orientation == XtPageOrientationSeascape)
1199 XtSetValues(seascapebutton, args, ONE);
1200 current_orientation = new_orientation;
1201 }
1202
1203 /* mark forced orientation with tie fighter. ("Use the force, Luke") */
1204 if (app_res.force_orientation) {
1205 XtSetArg(args[0], XtNleftBitmap, tie_fighter_bitmap);
1206 } else if (from_doc) {
1207 XtSetArg(args[0], XtNleftBitmap, menu16_bitmap);
1208 } else {
1209 XtSetArg(args[0], XtNleftBitmap, dot_bitmap);
1210 }
1211 if (current_orientation == XtPageOrientationPortrait)
1212 XtSetValues(portraitbutton, args, ONE);
1213 else if (current_orientation == XtPageOrientationLandscape)
1214 XtSetValues(landscapebutton, args, ONE);
1215 else if (current_orientation == XtPageOrientationUpsideDown)
1216 XtSetValues(upsidedownbutton, args, ONE);
1217 else if (current_orientation == XtPageOrientationSeascape)
1218 XtSetValues(seascapebutton, args, ONE);
1219
1220 return changed;
1221 }
1222
1223 /* Set new pagemedia */
1224 Boolean
1225 set_new_pagemedia(number)
1226 int number;
1227 {
1228 int new_pagemedia;
1229 int new_llx;
1230 int new_lly;
1231 int new_urx;
1232 int new_ury;
1233 Boolean changed = False;
1234 Boolean from_doc = False;
1235 Arg args[4];
1236
1237 if (force_document_media) {
1238 new_pagemedia = document_media;
1239 } else if (app_res.force_pagemedia) {
1240 new_pagemedia = default_pagemedia;
1241 } else {
1242 if (doc) {
1243 if (toc_text && doc->pages[number].media != NULL) {
1244 new_pagemedia = doc->pages[number].media - doc->media;
1245 from_doc = True;
1246 } else if (doc->default_page_media != NULL) {
1247 new_pagemedia = doc->default_page_media - doc->media;
1248 from_doc = True;
1249 } else {
1250 new_pagemedia = default_pagemedia;
1251 }
1252 } else {
1253 new_pagemedia = default_pagemedia;
1254 }
1255 }
1256
1257 /* If pagemedia changed, remove the old marker. */
1258 if (new_pagemedia != current_pagemedia) {
1259 XtSetArg(args[0], XtNleftBitmap, None);
1260 if (pagemediaentry[current_pagemedia])
1261 XtSetValues(pagemediaentry[current_pagemedia], args, ONE);
1262 else
1263 XtSetValues(pagemediaentry[current_pagemedia-1], args, ONE);
1264
1265 current_pagemedia = new_pagemedia;
1266 }
1267
1268 /* mark forced page media with tie fighter. ("Use the force, Luke") */
1269 if (force_document_media || app_res.force_pagemedia) {
1270 XtSetArg(args[0], XtNleftBitmap, tie_fighter_bitmap);
1271 } else if (from_doc) {
1272 XtSetArg(args[0], XtNleftBitmap, menu16_bitmap);
1273 } else {
1274 XtSetArg(args[0], XtNleftBitmap, dot_bitmap);
1275 }
1276 if (pagemediaentry[current_pagemedia])
1277 XtSetValues(pagemediaentry[current_pagemedia], args, ONE);
1278 else
1279 XtSetValues(pagemediaentry[current_pagemedia-1], args, ONE);
1280
1281 /* Compute bounding box */
1282 if (!force_document_media && !app_res.force_pagemedia &&
1283 doc && doc->epsf &&
1284 /* Ignore malformed bounding boxes */
1285 (doc->boundingbox[URX] > doc->boundingbox[LLX]) &&
1286 (doc->boundingbox[URY] > doc->boundingbox[LLY])) {
1287 new_llx = doc->boundingbox[LLX];
1288 new_lly = doc->boundingbox[LLY];
1289 new_urx = doc->boundingbox[URX];
1290 new_ury = doc->boundingbox[URY];
1291 } else {
1292 new_llx = new_lly = 0;
1293 if (new_pagemedia < base_papersize) {
1294 new_urx = doc->media[new_pagemedia].width;
1295 new_ury = doc->media[new_pagemedia].height;
1296 } else {
1297 new_urx = papersizes[new_pagemedia-base_papersize].width;
1298 new_ury = papersizes[new_pagemedia-base_papersize].height;
1299 }
1300 }
1301
1302 /* If bounding box changed, setup for new size. */
1303 if ((new_llx != current_llx) || (new_lly != current_lly) ||
1304 (new_urx != current_urx) || (new_ury != current_ury)) {
1305 GhostviewDisableInterpreter(page);
1306 XawFormDoLayout(form, False);
1307 reset_size_hints();
1308 reset_scroll_bars();
1309 break_chains();
1310 changed = True;
1311 current_llx = new_llx;
1312 current_lly = new_lly;
1313 current_urx = new_urx;
1314 current_ury = new_ury;
1315 XtSetArg(args[0], XtNllx, current_llx);
1316 XtSetArg(args[1], XtNlly, current_lly);
1317 XtSetArg(args[2], XtNurx, current_urx);
1318 XtSetArg(args[3], XtNury, current_ury);
1319 XtSetValues(page, args, FOUR);
1320 }
1321
1322 return changed;
1323 }
1324
1325 static Boolean
1326 same_document_media()
1327 {
1328 int i;
1329
1330 if (olddoc == NULL && doc == NULL) return True;
1331 if (olddoc == NULL || doc == NULL) return False;
1332 if (olddoc->nummedia != doc->nummedia) return False;
1333 for (i = 0; i < doc->nummedia; i++)
1334 if (strcmp(olddoc->media[i].name, doc->media[i].name)) return False;
1335 return True;
1336 }
1337
1338 void
1339 build_pagemedia_menu()
1340 {
1341 Arg args[20];
1342 Cardinal num_args;
1343 Widget w;
1344 int i;
1345
1346 if (pagemediamenu && same_document_media()) return;
1347 if (pagemediamenu) XtDestroyWidget(pagemediamenu);
1348 force_document_media = False;
1349
1350 num_args = 0;
1351 XtSetArg(args[num_args], XtNcolormap, cmap); num_args++;
1352 if (special_cmap) {
1353 XtSetArg(args[num_args], XtNbackground, white); num_args++;
1354 }
1355 pagemediamenu = XtCreatePopupShell("menu", simpleMenuWidgetClass,
1356 pagemediabutton, args, num_args);
1357
1358 /* Build the Page Media menu */
1359 /* the Page media menu has two parts.
1360 * - the document defined page medias
1361 * - the standard page media defined from Adobe's PPD
1362 */
1363 base_papersize = 0;
1364 if (doc) base_papersize = doc->nummedia;
1365 for (i = 0; papersizes[i].name; i++) {} /* Count the standard entries */
1366 i += base_papersize;
1367 pagemediaentry = (Widget *) XtMalloc(i * sizeof(Widget));
1368
1369 if (doc && doc->nummedia) {
1370 for (i = 0; i < doc->nummedia; i++) {
1371 num_args = 0;
1372 if (special_cmap) {
1373 XtSetArg(args[num_args], XtNforeground, black); num_args++;
1374 XtSetArg(args[num_args], XtNbackground, white); num_args++;
1375 }
1376 XtSetArg(args[num_args], XtNleftMargin, 20); num_args++;
1377 pagemediaentry[i] = XtCreateManagedWidget(doc->media[i].name,
1378 smeBSBObjectClass, pagemediamenu,
1379 args, num_args);
1380 XtAddCallback(pagemediaentry[i], XtNcallback,
1381 set_pagemedia, (XtPointer)i);
1382 }
1383
1384 num_args = 0;
1385 if (special_cmap) {
1386 XtSetArg(args[num_args], XtNforeground, black); num_args++;
1387 XtSetArg(args[num_args], XtNbackground, white); num_args++;
1388 }
1389 w = XtCreateManagedWidget("line", smeLineObjectClass, pagemediamenu,
1390 args, num_args);
1391 }
1392
1393 for (i = 0; papersizes[i].name; i++) {
1394 pagemediaentry[i+base_papersize] = NULL;
1395 if (i > 0) {
1396 /* Skip over same paper size with small imageable area */
1397 if ((papersizes[i].width == papersizes[i-1].width) &&
1398 (papersizes[i].height == papersizes[i-1].height)) {
1399 continue;
1400 }
1401 }
1402 num_args = 0;
1403 if (special_cmap) {
1404 XtSetArg(args[num_args], XtNforeground, black); num_args++;
1405 XtSetArg(args[num_args], XtNbackground, white); num_args++;
1406 }
1407 XtSetArg(args[num_args], XtNleftMargin, 20); num_args++;
1408 pagemediaentry[i+base_papersize] = XtCreateManagedWidget(
1409 papersizes[i].name,
1410 smeBSBObjectClass, pagemediamenu,
1411 args, num_args);
1412 XtAddCallback(pagemediaentry[i+base_papersize], XtNcallback,
1413 set_pagemedia, (XtPointer)(i+base_papersize));
1414 }
1415 }
1416
1417 Widget
1418 build_label_menu(parent, name, label, bitmap)
1419 Widget parent;
1420 String name, label;
1421 Pixmap bitmap;
1422 {
1423 Arg args[20];
1424 Cardinal num_args;
1425 Widget menu, entry;
1426 num_args = 0;
1427 XtSetArg(args[num_args], XtNcolormap, cmap); num_args++;
1428 if (special_cmap) {
1429 XtSetArg(args[num_args], XtNbackground, white); num_args++;
1430 }
1431 menu = XtCreatePopupShell("menu", simpleMenuWidgetClass,
1432 parent, args, num_args);
1433
1434 num_args = 0;
1435 if (special_cmap) {
1436 XtSetArg(args[num_args], XtNforeground, black); num_args++;
1437 XtSetArg(args[num_args], XtNbackground, white); num_args++;
1438 }
1439 XtSetArg(args[num_args], XtNlabel, label); num_args++;
1440 if (bitmap) {
1441 XtSetArg(args[num_args], XtNleftMargin, 20); num_args++;
1442 XtSetArg(args[num_args], XtNleftBitmap, bitmap); num_args++;
1443 }
1444 entry = XtCreateManagedWidget(name, smeBSBObjectClass,
1445 menu, args, num_args);
1446 return menu;
1447 }
1448
1449 void
1450 new_file(number)
1451 int number;
1452 {
1453 Boolean layout_changed = False;
1454
1455 if (setup_ghostview()) layout_changed = True;
1456
1457 /* Coerce page number to fall in range */
1458 if (toc_text) {
1459 if (number >= doc->numpages) number = doc->numpages - 1;
1460 if (number < 0) number = 0;
1461 }
1462
1463 if (set_new_orientation(number)) layout_changed = True;
1464 if (set_new_pagemedia(number)) layout_changed = True;
1465 if (layout_changed) layout_ghostview();
1466 }
1467
1468 /* Catch X errors die gracefully if one occurs */
1469 int
1470 catch_Xerror(dpy, err)
1471 Display *dpy;
1472 XErrorEvent *err;
1473 {
1474 if (err->error_code == BadImplementation) {
1475 old_Xerror(dpy, err);
1476 return 0;
1477 }
1478 if (dying) return 0;
1479 dying = True;
1480 bomb = *err;
1481 XtDestroyWidget(toplevel);
1482 return 0;
1483 }