xditview.c revision f80a6dcd
1/* $XConsortium: xditview.c,v 1.32 94/04/17 20:43:36 eswu Exp $ */
2/*
3
4Copyright (c) 1991  X Consortium
5
6Permission is hereby granted, free of charge, to any person obtaining
7a copy of this software and associated documentation files (the
8"Software"), to deal in the Software without restriction, including
9without limitation the rights to use, copy, modify, merge, publish,
10distribute, sublicense, and/or sell copies of the Software, and to
11permit persons to whom the Software is furnished to do so, subject to
12the following conditions:
13
14The above copyright notice and this permission notice shall be included
15in all copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
21OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of the X Consortium shall
26not be used in advertising or otherwise to promote the sale, use or
27other dealings in this Software without prior written authorization
28from the X Consortium.
29
30*/
31/* $XFree86: xc/programs/xditview/xditview.c,v 1.4tsi Exp $ */
32/*
33 * xditview --
34 *
35 *   Display ditroff output in an X window
36 */
37
38#include <X11/Intrinsic.h>
39#include <X11/StringDefs.h>
40#include <X11/Xatom.h>
41#include <X11/Shell.h>
42#include <X11/Xos.h>		/* rindex declaration */
43#include <X11/Xaw/Paned.h>
44#include <X11/Xaw/Panner.h>
45#include <X11/Xaw/Porthole.h>
46#include <X11/Xaw/Viewport.h>
47#include <X11/Xaw/Box.h>
48#include <X11/Xaw/Command.h>
49#include <X11/Xaw/Dialog.h>
50#include <X11/Xaw/Label.h>
51#include <X11/Xaw/MenuButton.h>
52#include <X11/Xaw/SimpleMenu.h>
53#include <X11/Xaw/SmeBSB.h>
54#include <X11/Xaw/AsciiText.h>
55
56#include "Dvi.h"
57
58#include "xdit.bm"
59#include "xdit_mask.bm"
60#include <stdio.h>
61#include <stdlib.h>
62
63/* Command line options table.  Only resources are entered here...there is a
64   pass over the remaining options after XtParseCommand is let loose. */
65
66static XrmOptionDescRec options[] = {
67{"-page",	    "*dvi.pageNumber",	    XrmoptionSepArg,	NULL},
68{"-backingStore",   "*dvi.backingStore",    XrmoptionSepArg,	NULL},
69{"-noPolyText",	    "*dvi.noPolyText",	    XrmoptionNoArg,	"TRUE"},
70{"-resolution",	    "*dvi.screenResolution",XrmoptionSepArg,    NULL},
71};
72
73static char	current_file_name[1024];
74static FILE	*current_file;
75
76static void MakePrompt(Widget, char *, void (*)(char *), char *);
77
78/*
79 * Report the syntax for calling xditview.
80 */
81
82static void
83Syntax(char *call)
84{
85	(void) printf ("Usage: %s [-fg <color>] [-bg <color>]\n", call);
86	(void) printf ("       [-bd <color>] [-bw <pixels>] [-help]\n");
87	(void) printf ("       [-display displayname] [-geometry geom]\n");
88	(void) printf ("       [-page <page-number>] [-backing <backing-store>]\n");
89	(void) printf ("       [-resolution <screen-resolution>]\n\n");
90	exit(1);
91}
92
93static void	NewResolution (char *resString);
94static void	NewFile (char *name);
95static void	DisplayPageNumber (void);
96static void	VisitFile (char *name, Boolean resetPage);
97static Widget	toplevel, paned, porthole, dvi;
98#ifdef NOTDEF
99static Widget	form, panner;
100#endif
101static Widget	popupMenu;
102static Widget	menuBar;
103static Widget	fileMenuButton, fileMenu;
104static Widget	pageNumber;
105
106static void	NextPage(Widget entry, XtPointer name, XtPointer data);
107static void	PreviousPage(Widget entry, XtPointer name, XtPointer data);
108static void	SetResolution(Widget entry, XtPointer name, XtPointer data);
109static void	OpenFile(Widget entry, XtPointer name, XtPointer data);
110static void	RevisitFile(Widget entry, XtPointer name, XtPointer data);
111static void	Quit(Widget entry, XtPointer closure, XtPointer data);
112
113struct menuEntry {
114    char    *name;
115    void    (*function)(Widget entry, XtPointer name, XtPointer data);
116};
117
118static struct menuEntry popupMenuEntries[] = {
119    { "nextPage",	    NextPage },
120    { "previousPage",	    PreviousPage },
121    { "setResolution",	    SetResolution },
122    { "openFile",	    OpenFile },
123    { "revisitFile",	    RevisitFile },
124    { "quit",		    Quit }
125};
126
127static struct menuEntry fileMenuEntries[] = {
128    { "openFile",	    OpenFile },
129    { "revisitFile",	    RevisitFile },
130    { "setResolution",	    SetResolution },
131    { "quit",		    Quit }
132};
133
134static void	NextPageAction(Widget, XEvent *, String *, Cardinal *);
135static void	PreviousPageAction(Widget, XEvent *, String *, Cardinal *);
136static void	SetResolutionAction(Widget, XEvent *, String *, Cardinal *);
137static void	OpenFileAction(Widget, XEvent *, String *, Cardinal *);
138static void	RevisitFileAction(Widget, XEvent *, String *, Cardinal *);
139static void	QuitAction(Widget, XEvent *, String *, Cardinal *);
140static void	AcceptAction(Widget, XEvent *, String *, Cardinal *);
141static void	CancelAction(Widget, XEvent *, String *, Cardinal *);
142static void	UpdatePageNumber(Widget, XEvent *, String *, Cardinal *);
143static void	Noop(Widget, XEvent *, String *, Cardinal *);
144
145XtActionsRec xditview_actions[] = {
146    { "NextPage",	    NextPageAction },
147    { "PreviousPage",	    PreviousPageAction },
148    { "SetResolution",	    SetResolutionAction },
149    { "OpenFile",	    OpenFileAction },
150    { "Quit",		    QuitAction },
151    { "Accept",		    AcceptAction },
152    { "Cancel",		    CancelAction },
153    { "SetPageNumber",	    UpdatePageNumber },
154    { "Noop",		    Noop }
155};
156
157static Atom wm_delete_window;
158
159#ifdef NOTDEF
160/*	Function Name: PannerCallback
161 *	Description: called when the panner has moved.
162 *	Arguments: panner - the panner widget.
163 *                 closure - *** NOT USED ***.
164 *                 report_ptr - the panner record.
165 *	Returns: none.
166 */
167
168/* ARGSUSED */
169static void
170PannerCallback(Widget w, XtPointer closure, XtPointer report_ptr)
171{
172    Arg args[2];
173    XawPannerReport *report = (XawPannerReport *) report_ptr;
174
175    if (!dvi)
176	return;
177    XtSetArg (args[0], XtNx, -report->slider_x);
178    XtSetArg (args[1], XtNy, -report->slider_y);
179
180    XtSetValues(dvi, args, 2);
181}
182
183/*	Function Name: PortholeCallback
184 *	Description: called when the porthole or its child has
185 *                   changed
186 *	Arguments: porthole - the porthole widget.
187 *                 panner_ptr - the panner widget.
188 *                 report_ptr - the porthole record.
189 *	Returns: none.
190 */
191
192/* ARGSUSED */
193static void
194PortholeCallback(Widget w, XtPointer panner_ptr, XtPointer report_ptr)
195{
196    Arg args[10];
197    Cardinal n = 0;
198    XawPannerReport *report = (XawPannerReport *) report_ptr;
199    Widget panner = (Widget) panner_ptr;
200
201    XtSetArg (args[n], XtNsliderX, report->slider_x); n++;
202    XtSetArg (args[n], XtNsliderY, report->slider_y); n++;
203    if (report->changed != (XawPRSliderX | XawPRSliderY)) {
204	XtSetArg (args[n], XtNsliderWidth, report->slider_width); n++;
205	XtSetArg (args[n], XtNsliderHeight, report->slider_height); n++;
206	XtSetArg (args[n], XtNcanvasWidth, report->canvas_width); n++;
207	XtSetArg (args[n], XtNcanvasHeight, report->canvas_height); n++;
208    }
209    XtSetValues (panner, args, n);
210}
211#endif
212
213int
214main(int argc, char **argv)
215{
216    char	    *file_name = 0;
217    int		    i;
218    XtAppContext    xtcontext;
219    Arg		    topLevelArgs[2];
220    Widget          entry;
221
222    XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL);
223
224    toplevel = XtAppInitialize(&xtcontext, "Xditview",
225			       options, XtNumber (options),
226			       &argc, argv, NULL, NULL, 0);
227    if (argc > 2)
228	Syntax(argv[0]);
229
230    XtAppAddActions(xtcontext, xditview_actions, XtNumber (xditview_actions));
231    XtOverrideTranslations
232	(toplevel, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()"));
233
234    XtSetArg (topLevelArgs[0], XtNiconPixmap,
235	      XCreateBitmapFromData (XtDisplay (toplevel),
236				     XtScreen(toplevel)->root,
237				     (char *) xdit_bits,
238				     xdit_width, xdit_height));
239
240    XtSetArg (topLevelArgs[1], XtNiconMask,
241	      XCreateBitmapFromData (XtDisplay (toplevel),
242				     XtScreen(toplevel)->root,
243				     (char *) xdit_mask_bits,
244				     xdit_mask_width, xdit_mask_height));
245    XtSetValues (toplevel, topLevelArgs, 2);
246    if (argc > 1)
247	file_name = argv[1];
248
249    /*
250     * create the popup menu and insert the entries
251     */
252    popupMenu = XtCreatePopupShell ("popupMenu", simpleMenuWidgetClass, toplevel,
253				    NULL, 0);
254    for (i = 0; i < XtNumber (popupMenuEntries); i++) {
255	entry = XtCreateManagedWidget(popupMenuEntries[i].name,
256				      smeBSBObjectClass, popupMenu,
257				      NULL, (Cardinal) 0);
258	XtAddCallback(entry, XtNcallback, popupMenuEntries[i].function, NULL);
259    }
260
261    paned = XtCreateManagedWidget("paned", panedWidgetClass, toplevel,
262				    NULL, (Cardinal) 0);
263    menuBar = XtCreateManagedWidget ("menuBar", boxWidgetClass, paned, 0, 0);
264
265    fileMenuButton = XtCreateManagedWidget ("fileMenuButton", menuButtonWidgetClass,
266				    menuBar, NULL, (Cardinal) 0);
267    fileMenu = XtCreatePopupShell ("fileMenu", simpleMenuWidgetClass,
268				    fileMenuButton, NULL, (Cardinal) 0);
269    for (i = 0; i < XtNumber (fileMenuEntries); i++) {
270	entry = XtCreateManagedWidget(fileMenuEntries[i].name,
271				      smeBSBObjectClass, fileMenu,
272				      NULL, (Cardinal) 0);
273	XtAddCallback (entry, XtNcallback, fileMenuEntries[i].function, NULL);
274    }
275
276    (void) XtCreateManagedWidget ("prevButton", commandWidgetClass,
277				  menuBar, NULL, (Cardinal) 0);
278
279    pageNumber = XtCreateManagedWidget("pageNumber", asciiTextWidgetClass,
280					menuBar, NULL, (Cardinal) 0);
281
282    (void) XtCreateManagedWidget ("nextButton", commandWidgetClass,
283				  menuBar, NULL, (Cardinal) 0);
284
285#ifdef NOTDEF
286    form = XtCreateManagedWidget ("form", formWidgetClass, paned,
287				    NULL, (Cardinal) 0);
288    panner = XtCreateManagedWidget ("panner", pannerWidgetClass,
289				    form, NULL, 0);
290    porthole = XtCreateManagedWidget ("porthole", portholeWidgetClass,
291				      form, NULL, 0);
292    XtAddCallback(porthole,
293		  XtNreportCallback, PortholeCallback, (XtPointer) panner);
294    XtAddCallback(panner,
295		  XtNreportCallback, PannerCallback, (XtPointer) porthole);
296#else
297    porthole = XtCreateManagedWidget ("viewport", viewportWidgetClass,
298				      paned, NULL, 0);
299#endif
300    dvi = XtCreateManagedWidget ("dvi", dviWidgetClass, porthole, NULL, 0);
301    if (file_name)
302	VisitFile (file_name, FALSE);
303    XtRealizeWidget (toplevel);
304    wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW",
305				   False);
306    (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel),
307                            &wm_delete_window, 1);
308    XtAppMainLoop(xtcontext);
309
310    return 0;
311}
312
313static void
314DisplayPageNumber ()
315{
316    Arg	arg[2];
317    int	actual_number, last_page;
318    XawTextBlock    text;
319    int		    length;
320    char	    value[128];
321    char	    *cur;
322
323    XtSetArg (arg[0], XtNpageNumber, &actual_number);
324    XtSetArg (arg[1], XtNlastPageNumber, &last_page);
325    XtGetValues (dvi, arg, 2);
326    if (actual_number == 0)
327	sprintf (value, "<none>");
328    else if (last_page > 0)
329	sprintf (value, "%d of %d", actual_number, last_page);
330    else
331	sprintf (value, "%d", actual_number);
332    text.firstPos = 0;
333    text.length = strlen (value);
334    text.ptr = value;
335    text.format = FMT8BIT;
336    XtSetArg (arg[0], XtNstring, &cur);
337    XtGetValues (XawTextGetSource (pageNumber), arg, 1);
338    length = strlen (cur);
339    XawTextReplace (pageNumber, 0, length, &text);
340}
341
342static void
343SetPageNumber (int number)
344{
345    Arg	arg[1];
346
347    XtSetArg (arg[0], XtNpageNumber, number);
348    XtSetValues (dvi, arg, 1);
349    DisplayPageNumber ();
350}
351
352static void
353UpdatePageNumber (Widget w, XEvent *xev, String *s, Cardinal *c)
354{
355    char    *string;
356    Arg	    arg[1];
357
358    XtSetArg (arg[0], XtNstring, &string);
359    XtGetValues (XawTextGetSource(pageNumber), arg, 1);
360    SetPageNumber (atoi(string));
361}
362
363static void
364NewResolution(resString)
365char	*resString;
366{
367    int	res;
368    Arg	arg[1];
369
370    res = atoi (resString);
371    if (res <= 0)
372	return;
373    XtSetArg (arg[0], XtNscreenResolution, res);
374    XtSetValues (dvi, arg, 1);
375}
376
377static void
378VisitFile (char *name, Boolean resetPage)
379{
380    Arg	    arg[3];
381    char    *n;
382    FILE    *new_file;
383    Boolean seek = 0;
384    int	    i;
385
386    if (current_file) {
387	if (!strcmp (current_file_name, "-"))
388	    ;
389	else if (current_file_name[0] == '|')
390	    pclose (current_file);
391	else
392	    fclose (current_file);
393    }
394    if (!strcmp (name, "-"))
395	new_file = stdin;
396    else if (name[0] == '|')
397	new_file = popen (name+1, "r");
398    else {
399	new_file = fopen (name, "r");
400	seek = 1;
401    }
402    if (!new_file) {
403	/* XXX display error message */
404	return;
405    }
406    i = 0;
407    XtSetArg (arg[i], XtNfile, new_file); i++;
408    XtSetArg (arg[i], XtNseek, seek); i++;
409    if (resetPage) {
410	XtSetArg (arg[i], XtNpageNumber, 1); i++;
411    }
412    XtSetValues (dvi, arg, i);
413    XtSetArg (arg[0], XtNtitle, name);
414    if (name[0] != '/' && (n = rindex (name, '/')))
415	n = n + 1;
416    else
417	n = name;
418    XtSetArg (arg[1], XtNiconName, n);
419    XtSetValues (toplevel, arg, 2);
420    strcpy (current_file_name, name);
421    current_file = new_file;
422    DisplayPageNumber ();
423}
424
425static void
426NewFile (name)
427char	*name;
428{
429    VisitFile (name, TRUE);
430}
431
432static char fileBuf[1024];
433static char resolutionBuf[1024];
434
435static void
436ResetMenuEntry (Widget entry)
437{
438    Arg	arg[1];
439
440    XtSetArg (arg[0], XtNpopupOnEntry, entry);
441    XtSetValues (XtParent(entry) , arg, (Cardinal) 1);
442}
443
444/*ARGSUSED*/
445static void
446NextPage (entry, name, data)
447    Widget  entry;
448    XtPointer name, data;
449{
450    NextPageAction(entry, NULL, NULL, NULL);
451    ResetMenuEntry (entry);
452}
453
454static void
455NextPageAction (Widget w, XEvent *xev, String *s, Cardinal *c)
456{
457    Arg	args[1];
458    int	number;
459
460    XtSetArg (args[0], XtNpageNumber, &number);
461    XtGetValues (dvi, args, 1);
462    SetPageNumber (number+1);
463}
464
465/*ARGSUSED*/
466static void
467PreviousPage (entry, name, data)
468    Widget  entry;
469    XtPointer name, data;
470{
471    PreviousPageAction (entry, NULL, NULL, NULL);
472    ResetMenuEntry (entry);
473}
474
475static void
476PreviousPageAction (Widget w, XEvent *xev, String *s, Cardinal *c)
477{
478    Arg	args[1];
479    int	number;
480
481    XtSetArg (args[0], XtNpageNumber, &number);
482    XtGetValues (dvi, args, 1);
483    SetPageNumber (number-1);
484}
485
486/*ARGSUSED*/
487static void
488SetResolution (entry, name, data)
489    Widget  entry;
490    XtPointer name, data;
491{
492    SetResolutionAction (entry, NULL, NULL, NULL);
493    ResetMenuEntry (entry);
494}
495
496static void
497SetResolutionAction (Widget w, XEvent *xev, String *s, Cardinal *c)
498{
499    Arg	    args[1];
500    int	    cur;
501
502    XtSetArg (args[0], XtNscreenResolution, &cur);
503    XtGetValues (dvi, args, 1);
504    sprintf (resolutionBuf, "%d", cur);
505    MakePrompt (toplevel, "Screen resolution:", NewResolution, resolutionBuf);
506}
507
508/*ARGSUSED*/
509static void
510OpenFile (entry, name, data)
511    Widget  entry;
512    XtPointer name, data;
513{
514    OpenFileAction (entry, NULL, NULL, NULL);
515    ResetMenuEntry (entry);
516}
517
518static void
519OpenFileAction (Widget w, XEvent *xev, String *s, Cardinal *c)
520{
521    if (current_file_name[0])
522	strcpy (fileBuf, current_file_name);
523    else
524	fileBuf[0] = '\0';
525    MakePrompt (toplevel, "File to open:", NewFile, fileBuf);
526}
527
528/*ARGSUSED*/
529static void
530RevisitFile (entry, name, data)
531    Widget  entry;
532    XtPointer name, data;
533{
534    RevisitFileAction (entry, NULL, NULL, NULL);
535    ResetMenuEntry (entry);
536}
537
538static void
539RevisitFileAction (Widget w, XEvent *xev, String *s, Cardinal *c)
540{
541    if (current_file_name[0])
542	VisitFile (current_file_name, FALSE);
543}
544
545/*ARGSUSED*/
546static void
547Quit (entry, closure, data)
548    Widget  entry;
549    XtPointer closure, data;
550{
551    QuitAction (entry, NULL, NULL, NULL);
552}
553
554static void
555QuitAction (Widget w, XEvent *xev, String *s, Cardinal *c)
556{
557    exit (0);
558}
559
560Widget	promptShell, promptDialog;
561void	(*promptfunction)(char *);
562
563/* ARGSUSED */
564static
565void CancelAction (widget, event, params, num_params)
566    Widget	widget;
567    XEvent	*event;
568    String	*params;
569    Cardinal	*num_params;
570{
571    if (promptShell) {
572	XtSetKeyboardFocus(toplevel, (Widget) None);
573	XtDestroyWidget(promptShell);
574	promptShell = (Widget) 0;
575    }
576}
577
578
579/* ARGSUSED */
580static
581void AcceptAction (widget, event, params, num_params)
582    Widget	widget;
583    XEvent	*event;
584    String	*params;
585    Cardinal	*num_params;
586{
587    (*promptfunction)(XawDialogGetValueString(promptDialog));
588    CancelAction (widget, event, params, num_params);
589}
590
591static
592void Noop (Widget w, XEvent *xev, String *s, Cardinal *c)
593{
594}
595
596static void
597MakePrompt(centerw, prompt, func, def)
598Widget	centerw;
599char *prompt;
600void (*func)(char *);
601char	*def;
602{
603    static Arg dialogArgs[] = {
604	{XtNlabel, (XtArgVal) 0},
605	{XtNvalue, (XtArgVal) 0},
606    };
607    Arg valueArgs[1];
608    Arg centerArgs[2];
609    Position	source_x, source_y;
610    Position	dest_x, dest_y;
611    Dimension center_width, center_height;
612    Dimension prompt_width, prompt_height;
613    Widget  valueWidget;
614
615    CancelAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
616    promptShell = XtCreatePopupShell ("promptShell", transientShellWidgetClass,
617				      toplevel, NULL, (Cardinal) 0);
618    dialogArgs[0].value = (XtArgVal)prompt;
619    dialogArgs[1].value = (XtArgVal)def;
620    promptDialog = XtCreateManagedWidget( "promptDialog", dialogWidgetClass,
621		    promptShell, dialogArgs, XtNumber (dialogArgs));
622    XawDialogAddButton(promptDialog, "accept", NULL, NULL);
623    XawDialogAddButton(promptDialog, "cancel", NULL, NULL);
624    valueWidget = XtNameToWidget (promptDialog, "value");
625    if (valueWidget) {
626    	XtSetArg (valueArgs[0], XtNresizable, TRUE);
627    	XtSetValues (valueWidget, valueArgs, 1);
628	/*
629	 * as resizable isn't set until just above, the
630	 * default value will be displayed incorrectly.
631	 * rectify the situation by resetting the values
632	 */
633        XtSetValues (promptDialog, dialogArgs, XtNumber (dialogArgs));
634    }
635    XtSetKeyboardFocus (promptDialog, valueWidget);
636    XtSetKeyboardFocus (toplevel, valueWidget);
637    XtRealizeWidget (promptShell);
638    /*
639     * place the widget in the center of the "parent"
640     */
641    XtSetArg (centerArgs[0], XtNwidth, &center_width);
642    XtSetArg (centerArgs[1], XtNheight, &center_height);
643    XtGetValues (centerw, centerArgs, 2);
644    XtSetArg (centerArgs[0], XtNwidth, &prompt_width);
645    XtSetArg (centerArgs[1], XtNheight, &prompt_height);
646    XtGetValues (promptShell, centerArgs, 2);
647    source_x = (int)(center_width - prompt_width) / 2;
648    source_y = (int)(center_height - prompt_height) / 3;
649    XtTranslateCoords (centerw, source_x, source_y, &dest_x, &dest_y);
650    XtSetArg (centerArgs[0], XtNx, dest_x);
651    XtSetArg (centerArgs[1], XtNy, dest_y);
652    XtSetValues (promptShell, centerArgs, 2);
653    XtMapWidget(promptShell);
654    promptfunction = func;
655}
656