xref: /netbsd-src/external/gpl2/groff/dist/src/devices/xditview/xditview.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
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
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 
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
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
293 SelectPageNumber (const char *number_string)
294 {
295 	SetPageNumber (atoi(number_string));
296 }
297 
298 static int hadFile = 0;
299 
300 static void
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, &center_width);
635     XtSetArg (centerArgs[1], XtNheight, &center_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