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