1 /* $NetBSD: xditview.c,v 1.1.1.1 2016/01/13 18:41:49 christos Exp $ */
2
3 /*
4 * Copyright 1991 Massachusetts Institute of Technology
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of M.I.T. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. M.I.T. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
15 *
16 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 */
24 /*
25 * xditview --
26 *
27 * Display ditroff output in an X window
28 */
29
30 #ifndef SABER
31 #ifndef lint
32 static char rcsid[] = "$XConsortium: xditview.c,v 1.17 89/12/10 17:05:08 rws Exp $";
33 #endif /* lint */
34 #endif /* SABER */
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <X11/Xatom.h>
41 #include <X11/Xlib.h>
42 #include <X11/Xos.h>
43 #include <X11/Intrinsic.h>
44 #include <X11/StringDefs.h>
45 #include <X11/Shell.h>
46 #include <X11/Xaw/Paned.h>
47 #include <X11/Xaw/Viewport.h>
48 #include <X11/Xaw/Box.h>
49 #include <X11/Xaw/Command.h>
50 #include <X11/Xaw/Dialog.h>
51 #include <X11/Xaw/Label.h>
52 #include <X11/Xaw/SimpleMenu.h>
53 #include <X11/Xaw/SmeBSB.h>
54
55 #include <stdlib.h>
56 #include <signal.h>
57 #include <stdio.h>
58
59 #include "Dvi.h"
60
61 #include "xdit.bm"
62 #include "xdit_mask.bm"
63
64 #ifdef NEED_DECLARATION_POPEN
65 FILE *popen(const char *, const char *);
66 #endif /* NEED_DECLARATION_POPEN */
67
68 #ifdef NEED_DECLARATION_PCLOSE
69 int pclose (FILE *);
70 #endif /* NEED_DECLARATION_PCLOSE */
71
72 typedef void (*MakePromptFunc)(const char *);
73
74 static String fallback_resources[] = {
75 #include "GXditview-ad.h"
76 NULL
77 };
78
79 static struct app_resources {
80 char *print_command;
81 char *filename;
82 } app_resources;
83
84 #define offset(field) XtOffset(struct app_resources *, field)
85
86 /* Application resources. */
87
88 static XtResource resources[] = {
89 {(String)"printCommand", (String)"PrintCommand", (String)XtRString,
90 sizeof(char*), offset(print_command), (String)XtRString, NULL},
91 {(String)"filename", (String)"Filename", (String)XtRString,
92 sizeof(char*), offset(filename), (String)XtRString, NULL},
93 };
94
95 #undef offset
96
97 /* Command line options table. Only resources are entered here...there is a
98 pass over the remaining options after XtParseCommand is let loose. */
99
100 static XrmOptionDescRec options[] = {
101 {(char *)"-page", (char *)"*dvi.pageNumber",
102 XrmoptionSepArg, NULL},
103 {(char *)"-backingStore", (char *)"*dvi.backingStore",
104 XrmoptionSepArg, NULL},
105 {(char *)"-resolution", (char *)"*dvi.resolution",
106 XrmoptionSepArg, NULL},
107 {(char *)"-printCommand", (char *)".printCommand",
108 XrmoptionSepArg, NULL},
109 {(char *)"-filename", (char *)".filename",
110 XrmoptionSepArg, NULL},
111 {(char *)"-noPolyText", (char *)"*dvi.noPolyText",
112 XrmoptionNoArg, (XPointer)"TRUE"},
113 };
114
115 static char current_print_command[1024];
116
117 static char current_file_name[1024];
118 static FILE *current_file;
119
120 /*
121 * Report the syntax for calling xditview.
122 */
123
124 static void
Syntax(const char * call)125 Syntax(const char *call)
126 {
127 (void) printf ("Usage: %s [-fg <color>] [-bg <color>]\n", call);
128 (void) printf (" [-bd <color>] [-bw <pixels>] [-help]\n");
129 (void) printf (" [-display displayname] [-geometry geom]\n");
130 (void) printf (" [-page <page-number>] [-backing <backing-store>]\n");
131 (void) printf (" [-resolution <res>] [-print <command>]\n");
132 (void) printf (" [-filename <file>] [filename]\n\n");
133 exit(1);
134 }
135
136 static void NewFile (const char *);
137 static void SetPageNumber (int);
138 static Widget toplevel, paned, viewport, dvi;
139 static Widget page;
140 static Widget simpleMenu;
141
142 static void NextPage(Widget, XtPointer, XtPointer);
143 static void PreviousPage(Widget, XtPointer, XtPointer);
144 static void SelectPage(Widget, XtPointer, XtPointer);
145 static void OpenFile(Widget, XtPointer, XtPointer);
146 static void Quit(Widget, XtPointer, XtPointer);
147 static void Print(Widget, XtPointer, XtPointer);
148
149 static struct menuEntry {
150 const char *name;
151 XtCallbackProc function;
152 } menuEntries[] = {
153 {"nextPage", NextPage},
154 {"previousPage", PreviousPage},
155 {"selectPage", SelectPage},
156 {"print", Print},
157 {"openFile", OpenFile},
158 {"quit", Quit},
159 };
160
161 static void NextPageAction(Widget, XEvent *, String *, Cardinal *);
162 static void PreviousPageAction(Widget, XEvent *, String *, Cardinal *);
163 static void SelectPageAction(Widget, XEvent *, String *, Cardinal *);
164 static void OpenFileAction(Widget, XEvent *, String *, Cardinal *);
165 static void QuitAction(Widget, XEvent *, String *, Cardinal *);
166 static void AcceptAction(Widget, XEvent *, String *, Cardinal *);
167 static void CancelAction(Widget, XEvent *, String *, Cardinal *);
168 static void PrintAction(Widget, XEvent *, String *, Cardinal *);
169 static void RerasterizeAction(Widget, XEvent *, String *, Cardinal *);
170
171 static void MakePrompt(Widget, const char *, MakePromptFunc, const char *);
172
173 XtActionsRec xditview_actions[] = {
174 {(String)"NextPage", NextPageAction},
175 {(String)"PreviousPage", PreviousPageAction},
176 {(String)"SelectPage", SelectPageAction},
177 {(String)"Print", PrintAction},
178 {(String)"OpenFile", OpenFileAction},
179 {(String)"Rerasterize", RerasterizeAction},
180 {(String)"Quit", QuitAction},
181 {(String)"Accept", AcceptAction},
182 {(String)"Cancel", CancelAction},
183 };
184
185 #define MenuNextPage 0
186 #define MenuPreviousPage 1
187 #define MenuSelectPage 2
188 #define MenuPrint 3
189 #define MenuOpenFile 4
190 #define MenuQuit 5
191
192 static char pageLabel[256] = "Page <none>";
193
main(int argc,char ** argv)194 int main(int argc, char **argv)
195 {
196 char *file_name = 0;
197 Cardinal i;
198 static Arg labelArgs[] = {
199 {XtNlabel, (XtArgVal) pageLabel},
200 };
201 XtAppContext xtcontext;
202 Arg topLevelArgs[2];
203 Widget entry;
204 Arg pageNumberArgs[1];
205 int page_number;
206
207 toplevel = XtAppInitialize(&xtcontext, "GXditview",
208 options, XtNumber (options),
209 &argc, argv, fallback_resources, NULL, 0);
210 if (argc > 2
211 || (argc == 2 && (!strcmp(argv[1], "-help")
212 || !strcmp(argv[1], "--help"))))
213 Syntax(argv[0]);
214
215 XtGetApplicationResources(toplevel, (XtPointer)&app_resources,
216 resources, XtNumber(resources),
217 NULL, (Cardinal) 0);
218 if (app_resources.print_command)
219 strcpy(current_print_command, app_resources.print_command);
220
221 XtAppAddActions(xtcontext, xditview_actions, XtNumber (xditview_actions));
222
223 XtSetArg (topLevelArgs[0], XtNiconPixmap,
224 XCreateBitmapFromData (XtDisplay (toplevel),
225 XtScreen(toplevel)->root,
226 (char *)xdit_bits,
227 xdit_width, xdit_height));
228
229 XtSetArg (topLevelArgs[1], XtNiconMask,
230 XCreateBitmapFromData (XtDisplay (toplevel),
231 XtScreen(toplevel)->root,
232 (char *)xdit_mask_bits,
233 xdit_mask_width, xdit_mask_height));
234 XtSetValues (toplevel, topLevelArgs, 2);
235 if (argc > 1)
236 file_name = argv[1];
237
238 /*
239 * create the menu and insert the entries
240 */
241 simpleMenu = XtCreatePopupShell ("menu", simpleMenuWidgetClass, toplevel,
242 NULL, 0);
243 for (i = 0; i < XtNumber (menuEntries); i++) {
244 entry = XtCreateManagedWidget(menuEntries[i].name,
245 smeBSBObjectClass, simpleMenu,
246 NULL, (Cardinal) 0);
247 XtAddCallback(entry, XtNcallback, menuEntries[i].function, NULL);
248 }
249
250 paned = XtCreateManagedWidget("paned", panedWidgetClass, toplevel,
251 NULL, (Cardinal) 0);
252 viewport = XtCreateManagedWidget("viewport", viewportWidgetClass, paned,
253 NULL, (Cardinal) 0);
254 dvi = XtCreateManagedWidget ("dvi", dviWidgetClass, viewport, NULL, 0);
255 page = XtCreateManagedWidget ("label", labelWidgetClass, paned,
256 labelArgs, XtNumber (labelArgs));
257 XtSetArg (pageNumberArgs[0], XtNpageNumber, &page_number);
258 XtGetValues (dvi, pageNumberArgs, 1);
259 if (file_name)
260 NewFile (file_name);
261 /* NewFile modifies current_file_name, so do this here. */
262 if (app_resources.filename)
263 strcpy(current_file_name, app_resources.filename);
264 XtRealizeWidget (toplevel);
265 if (file_name)
266 SetPageNumber (page_number);
267 XtAppMainLoop(xtcontext);
268 return 0;
269 }
270
271 static void
SetPageNumber(int number)272 SetPageNumber (int number)
273 {
274 Arg arg[2];
275 int actual_number, last_page;
276
277 XtSetArg (arg[0], XtNpageNumber, number);
278 XtSetValues (dvi, arg, 1);
279 XtSetArg (arg[0], XtNpageNumber, &actual_number);
280 XtSetArg (arg[1], XtNlastPageNumber, &last_page);
281 XtGetValues (dvi, arg, 2);
282 if (actual_number == 0)
283 sprintf (pageLabel, "Page <none>");
284 else if (last_page > 0)
285 sprintf (pageLabel, "Page %d of %d", actual_number, last_page);
286 else
287 sprintf (pageLabel, "Page %d", actual_number);
288 XtSetArg (arg[0], XtNlabel, pageLabel);
289 XtSetValues (page, arg, 1);
290 }
291
292 static void
SelectPageNumber(const char * number_string)293 SelectPageNumber (const char *number_string)
294 {
295 SetPageNumber (atoi(number_string));
296 }
297
298 static int hadFile = 0;
299
300 static void
NewFile(const char * name)301 NewFile (const char *name)
302 {
303 Arg arg[2];
304 char *n;
305 FILE *new_file;
306 Boolean seek = 0;
307
308 if (current_file) {
309 if (!strcmp (current_file_name, "-"))
310 ;
311 else if (current_file_name[0] == '|')
312 pclose (current_file);
313 else
314 fclose (current_file);
315 }
316 if (!strcmp (name, "-"))
317 new_file = stdin;
318 else if (name[0] == '|')
319 new_file = popen (name+1, "r");
320 else {
321 new_file = fopen (name, "r");
322 seek = 1;
323 }
324 if (!new_file) {
325 /* XXX display error message */
326 return;
327 }
328 XtSetArg (arg[0], XtNfile, new_file);
329 XtSetArg (arg[1], XtNseek, seek);
330 XtSetValues (dvi, arg, 2);
331 if (hadFile || name[0] != '-' || name[1] != '\0') {
332 XtSetArg (arg[0], XtNtitle, name);
333 if (name[0] != '/' && (n = strrchr (name, '/')))
334 n = n + 1;
335 else
336 n = (char *)name;
337 XtSetArg (arg[1], XtNiconName, n);
338 XtSetValues (toplevel, arg, 2);
339 }
340 hadFile = 1;
341 SelectPageNumber ("1");
342 strcpy (current_file_name, name);
343 current_file = new_file;
344 }
345
346 static char fileBuf[1024];
347
348 static void
ResetMenuEntry(Widget entry)349 ResetMenuEntry (Widget entry)
350 {
351 Arg arg[1];
352
353 XtSetArg (arg[0], (String)XtNpopupOnEntry, entry);
354 XtSetValues (XtParent(entry) , arg, (Cardinal) 1);
355 }
356
357 /*ARGSUSED*/
358
359 static void
NextPage(Widget entry,XtPointer name,XtPointer data)360 NextPage (Widget entry, XtPointer name, XtPointer data)
361 {
362 name = name; /* unused; suppress compiler warning */
363 data = data;
364
365 NextPageAction((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
366 ResetMenuEntry (entry);
367 }
368
369 static void
NextPageAction(Widget widget,XEvent * event,String * params,Cardinal * num_params)370 NextPageAction (Widget widget, XEvent *event,
371 String *params, Cardinal *num_params)
372 {
373 Arg args[1];
374 int number;
375
376 XtSetArg (args[0], XtNpageNumber, &number);
377 XtGetValues (dvi, args, 1);
378 SetPageNumber (number+1);
379
380 widget = widget; /* unused; suppress compiler warning */
381 event = event;
382 params = params;
383 num_params = num_params;
384 }
385
386 /*ARGSUSED*/
387
388 static void
PreviousPage(Widget entry,XtPointer name,XtPointer data)389 PreviousPage (Widget entry, XtPointer name, XtPointer data)
390 {
391 name = name; /* unused; suppress compiler warning */
392 data = data;
393
394 PreviousPageAction ((Widget)NULL, (XEvent *) 0, (String *) 0,
395 (Cardinal *) 0);
396 ResetMenuEntry (entry);
397 }
398
399 static void
PreviousPageAction(Widget widget,XEvent * event,String * params,Cardinal * num_params)400 PreviousPageAction (Widget widget, XEvent *event,
401 String *params, Cardinal *num_params)
402 {
403 Arg args[1];
404 int number;
405
406 XtSetArg (args[0], XtNpageNumber, &number);
407 XtGetValues (dvi, args, 1);
408 SetPageNumber (number-1);
409
410 widget = widget; /* unused; suppress compiler warning */
411 event = event;
412 params = params;
413 num_params = num_params;
414 }
415
416 /* ARGSUSED */
417
418 static void
SelectPage(Widget entry,XtPointer name,XtPointer data)419 SelectPage (Widget entry, XtPointer name, XtPointer data)
420 {
421 name = name; /* unused; suppress compiler warning */
422 data = data;
423
424 SelectPageAction ((Widget)NULL, (XEvent *) 0, (String *) 0,
425 (Cardinal *) 0);
426 ResetMenuEntry (entry);
427 }
428
429 static void
SelectPageAction(Widget widget,XEvent * event,String * params,Cardinal * num_params)430 SelectPageAction (Widget widget, XEvent *event,
431 String *params, Cardinal *num_params)
432 {
433 widget = widget; /* unused; suppress compiler warning */
434 event = event;
435 params = params;
436 num_params = num_params;
437
438 MakePrompt (toplevel, "Page number", SelectPageNumber, "");
439 }
440
441
442 static void
DoPrint(const char * name)443 DoPrint (const char *name)
444 {
445 FILE *print_file;
446 RETSIGTYPE (*handler)(int);
447
448 /* Avoid dieing because of an invalid command. */
449 handler = signal(SIGPIPE, SIG_IGN);
450
451 print_file = popen(name, "w");
452 if (!print_file)
453 /* XXX print error message */
454 return;
455 DviSaveToFile(dvi, print_file);
456 pclose(print_file);
457 signal(SIGPIPE, handler);
458 strcpy(current_print_command, name);
459 }
460
461 static void
RerasterizeAction(Widget widget,XEvent * event,String * params,Cardinal * num_params)462 RerasterizeAction (Widget widget, XEvent *event,
463 String *params, Cardinal *num_params)
464 {
465 Arg args[1];
466 int number;
467
468 if (current_file_name[0] == 0) {
469 /* XXX display an error message */
470 return;
471 }
472 XtSetArg (args[0], XtNpageNumber, &number);
473 XtGetValues (dvi, args, 1);
474 NewFile(current_file_name);
475 SetPageNumber (number);
476
477 widget = widget; /* unused; suppress compiler warning */
478 event = event;
479 params = params;
480 num_params = num_params;
481 }
482
483 /* ARGSUSED */
484
485 static void
Print(Widget entry,XtPointer name,XtPointer data)486 Print (Widget entry, XtPointer name, XtPointer data)
487 {
488 name = name; /* unused; suppress compiler warning */
489 data = data;
490
491 PrintAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
492 ResetMenuEntry (entry);
493 }
494
495 static void
PrintAction(Widget widget,XEvent * event,String * params,Cardinal * num_params)496 PrintAction (Widget widget, XEvent *event,
497 String *params, Cardinal *num_params)
498 {
499 widget = widget; /* unused; suppress compiler warning */
500 event = event;
501 params = params;
502 num_params = num_params;
503
504 if (current_print_command[0])
505 strcpy (fileBuf, current_print_command);
506 else
507 fileBuf[0] = '\0';
508 MakePrompt (toplevel, "Print command:", DoPrint, fileBuf);
509 }
510
511
512 /* ARGSUSED */
513
514 static void
OpenFile(Widget entry,XtPointer name,XtPointer data)515 OpenFile (Widget entry, XtPointer name, XtPointer data)
516 {
517 name = name; /* unused; suppress compiler warning */
518 data = data;
519
520 OpenFileAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
521 ResetMenuEntry (entry);
522 }
523
524 static void
OpenFileAction(Widget widget,XEvent * event,String * params,Cardinal * num_params)525 OpenFileAction (Widget widget, XEvent *event,
526 String *params, Cardinal *num_params)
527 {
528 widget = widget; /* unused; suppress compiler warning */
529 event = event;
530 params = params;
531 num_params = num_params;
532
533 if (current_file_name[0])
534 strcpy (fileBuf, current_file_name);
535 else
536 fileBuf[0] = '\0';
537 MakePrompt (toplevel, "File to open:", NewFile, fileBuf);
538 }
539
540 /* ARGSUSED */
541
542 static void
Quit(Widget entry,XtPointer closure,XtPointer data)543 Quit (Widget entry, XtPointer closure, XtPointer data)
544 {
545 entry = entry; /* unused; suppress compiler warning */
546 closure = closure;
547 data = data;
548
549 QuitAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
550 }
551
552 static void
QuitAction(Widget widget,XEvent * event,String * params,Cardinal * num_params)553 QuitAction (Widget widget, XEvent *event,
554 String *params, Cardinal *num_params)
555 {
556 widget = widget; /* unused; suppress compiler warning */
557 event = event;
558 params = params;
559 num_params = num_params;
560
561 exit (0);
562 }
563
564 Widget promptShell, promptDialog;
565 MakePromptFunc promptfunction;
566
567 /* ARGSUSED */
568 static
CancelAction(Widget widget,XEvent * event,String * params,Cardinal * num_params)569 void CancelAction (Widget widget, XEvent *event,
570 String *params, Cardinal *num_params)
571 {
572 widget = widget; /* unused; suppress compiler warning */
573 event = event;
574 params = params;
575 num_params = num_params;
576
577 if (promptShell) {
578 XtSetKeyboardFocus(toplevel, (Widget) None);
579 XtDestroyWidget(promptShell);
580 promptShell = (Widget) 0;
581 }
582 }
583
584 static
AcceptAction(Widget widget,XEvent * event,String * params,Cardinal * num_params)585 void AcceptAction (Widget widget, XEvent *event,
586 String *params, Cardinal *num_params)
587 {
588 (*promptfunction)(XawDialogGetValueString(promptDialog));
589 CancelAction (widget, event, params, num_params);
590 }
591
592 static void
MakePrompt(Widget centerw,const char * prompt,MakePromptFunc func,const char * def)593 MakePrompt(Widget centerw, const char *prompt,
594 MakePromptFunc func, const char *def)
595 {
596 static Arg dialogArgs[] = {
597 {XtNlabel, 0},
598 {XtNvalue, 0},
599 };
600 Arg valueArgs[1];
601 Arg centerArgs[2];
602 Position source_x, source_y;
603 Position dest_x, dest_y;
604 Dimension center_width, center_height;
605 Dimension prompt_width, prompt_height;
606 Widget valueWidget;
607
608 CancelAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
609 promptShell = XtCreatePopupShell ("promptShell", transientShellWidgetClass,
610 toplevel, NULL, (Cardinal) 0);
611 dialogArgs[0].value = (XtArgVal)prompt;
612 dialogArgs[1].value = (XtArgVal)def;
613 promptDialog = XtCreateManagedWidget( "promptDialog", dialogWidgetClass,
614 promptShell, dialogArgs, XtNumber (dialogArgs));
615 XawDialogAddButton(promptDialog, "accept", NULL, (XtPointer) 0);
616 XawDialogAddButton(promptDialog, "cancel", NULL, (XtPointer) 0);
617 valueWidget = XtNameToWidget (promptDialog, "value");
618 if (valueWidget) {
619 XtSetArg (valueArgs[0], (String)XtNresizable, TRUE);
620 XtSetValues (valueWidget, valueArgs, 1);
621 /*
622 * as resizable isn't set until just above, the
623 * default value will be displayed incorrectly.
624 * rectify the situation by resetting the values
625 */
626 XtSetValues (promptDialog, dialogArgs, XtNumber (dialogArgs));
627 }
628 XtSetKeyboardFocus (promptDialog, valueWidget);
629 XtSetKeyboardFocus (toplevel, valueWidget);
630 XtRealizeWidget (promptShell);
631 /*
632 * place the widget in the center of the "parent"
633 */
634 XtSetArg (centerArgs[0], XtNwidth, ¢er_width);
635 XtSetArg (centerArgs[1], XtNheight, ¢er_height);
636 XtGetValues (centerw, centerArgs, 2);
637 XtSetArg (centerArgs[0], XtNwidth, &prompt_width);
638 XtSetArg (centerArgs[1], XtNheight, &prompt_height);
639 XtGetValues (promptShell, centerArgs, 2);
640 source_x = (center_width - prompt_width) / 2;
641 source_y = (center_height - prompt_height) / 3;
642 XtTranslateCoords (centerw, source_x, source_y, &dest_x, &dest_y);
643 XtSetArg (centerArgs[0], XtNx, dest_x);
644 XtSetArg (centerArgs[1], XtNy, dest_y);
645 XtSetValues (promptShell, centerArgs, 2);
646 XtMapWidget(promptShell);
647 promptfunction = func;
648 }
649
650 /*
651 Local Variables:
652 c-indent-level: 4
653 c-continued-statement-offset: 4
654 c-brace-offset: -4
655 c-argdecl-indent: 4
656 c-label-offset: -4
657 c-tab-always-indent: nil
658 End:
659 */
660