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