1 /*
2  * XDU - X Window System Interface.
3  *
4  * We hide all of the X hieroglyphics inside of this module.
5  *
6  * Phillip C. Dykstra
7  * <phil@arl.mil>
8  * 4 Sep 1991.
9  *
10  * Copyright (c)	Phillip C. Dykstra	1991, 1993, 1994
11  * The X Consortium, and any party obtaining a copy of these files from
12  * the X Consortium, directly or indirectly, is granted, free of charge, a
13  * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
14  * nonexclusive right and license to deal in this software and
15  * documentation files (the "Software"), including without limitation the
16  * rights to use, copy, modify, merge, publish, distribute, sublicense,
17  * and/or sell copies of the Software, and to permit persons who receive
18  * copies from any such party to do so.  This license includes without
19  * limitation a license to do the foregoing actions under any patents of
20  * the party supplying this software to the X Consortium.
21  */
22 #include <X11/Intrinsic.h>
23 #include <X11/StringDefs.h>
24 #include <X11/Shell.h>
25 
26 #include <X11/Xaw/AsciiText.h>
27 #include <X11/Xaw/AsciiSrc.h>
28 #include <X11/Xaw/Form.h>
29 #include <X11/Xaw/Label.h>
30 
31 #include <stdio.h>
32 
33 #ifndef X_NOT_STDC_ENV
34 #include <stdlib.h>	/* for exit() */
35 #endif
36 
37 /* IMPORTS: routines that this module vectors out to */
38 extern int press();
39 extern int reset();
40 extern int repaint();
41 extern int reorder();
42 extern int setorder();
43 extern int nodeinfo();
44 extern int helpinfo();
45 extern int ncols;
46 
47 /* EXPORTS: routines that this module exports outside */
48 extern int xsetup();
49 extern int xmainloop();
50 extern int xclear();
51 extern int xrepaint();
52 extern int xrepaint_noclear();
53 extern int xdrawrect();
54 
55 /* internal routines */
56 static void help_popup();
57 static void help_popdown();
58 
59 static String fallback_resources[] = {
60 "*window.width:		600",
61 "*window.height:	480",
62 "*help.width:		500",
63 "*help.height:		330",
64 "*order:		first",
65 NULL
66 };
67 
68 /* Application Resources */
69 typedef struct {
70 	Pixel	foreground;
71 	Pixel	background;
72 	XFontStruct *font;
73 	int	ncol;
74 	Boolean	showsize;
75 	char	*order;
76 } res_data, *res_data_ptr;
77 static res_data res;
78 
79 static XtResource application_resources[] = {
80 	{ XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
81 		XtOffset(res_data_ptr,foreground), XtRString, XtDefaultForeground},
82 	{ XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
83 		XtOffset(res_data_ptr,background), XtRString, XtDefaultBackground},
84 	{ XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
85 		XtOffset(res_data_ptr,font), XtRString, XtDefaultFont },
86 	{ "ncol", "Ncol", XtRInt, sizeof(int),
87 		XtOffset(res_data_ptr,ncol), XtRString, "5"},
88 	{ "showsize", "ShowSize", XtRBoolean, sizeof(Boolean),
89 		XtOffset(res_data_ptr,showsize), XtRString, "True"},
90 	{ "order", "Order", XtRString, sizeof(String),
91 		XtOffset(res_data_ptr,order), XtRString, "first"}
92 };
93 
94 /* Command Line Options */
95 static XrmOptionDescRec options[] = {
96 	{"-c",		"*ncol",	XrmoptionSepArg,	NULL},
97 	{"+s",		"*showsize",	XrmoptionNoArg,		"True"},
98 	{"-s",		"*showsize",	XrmoptionNoArg,		"False"},
99 	{"-n",		"*order",	XrmoptionNoArg,		"size"},
100 	{"-rn",		"*order",	XrmoptionNoArg,		"rsize"},
101 	{"-a",		"*order",	XrmoptionNoArg,		"alpha"},
102 	{"-ra",		"*order",	XrmoptionNoArg,		"ralpha"}
103 };
104 
105 /* action routines */
106 static void a_goto();
107 static void a_reset();
108 static void a_quit();
109 static void a_reorder();
110 static void a_size();
111 static void a_ncol();
112 static void a_info();
113 static void a_help();
114 static void a_removehelp();
115 
116 static XtActionsRec actionsTable[] = {
117 	{ "reset",	a_reset },
118 	{ "goto",	a_goto },
119 	{ "quit",	a_quit },
120 	{ "reorder",	a_reorder },
121 	{ "size",	a_size },
122 	{ "ncol",	a_ncol },
123 	{ "info",	a_info },
124 	{ "help",	a_help },
125 	{ "RemoveHelp",	a_removehelp }
126 };
127 
128 static char defaultTranslations[] = "\
129 <Key>Q:	quit()\n\
130 <Key>Escape: quit()\n\
131 :<Key>/: reset()\n\
132 <Key>S:	size()\n\
133 <Key>I:	info()\n\
134 <Key>H: help()\n\
135 <Key>Help: help()\n\
136 :<Key>?: help()\n\
137 <Key>A:	reorder(alpha)\n\
138 <Key>N:	reorder(size)\n\
139 <Key>F:	reorder(first)\n\
140 <Key>L:	reorder(last)\n\
141 <Key>R:	reorder(reverse)\n\
142 <Key>1:	ncol(1)\n\
143 <Key>2:	ncol(2)\n\
144 <Key>3:	ncol(3)\n\
145 <Key>4:	ncol(4)\n\
146 <Key>5:	ncol(5)\n\
147 <Key>6:	ncol(6)\n\
148 <Key>7:	ncol(7)\n\
149 <Key>8:	ncol(8)\n\
150 <Key>9:	ncol(9)\n\
151 <Key>0:	ncol(10)\n\
152 <Btn1Down>: goto()\n\
153 <Btn2Down>: reset()\n\
154 <Btn3Down>: quit()\n\
155 ";
156 
157 /*  action routines  */
158 
a_quit(w,event,params,num_params)159 static void a_quit(w, event, params, num_params)
160 Widget w;
161 XEvent *event;
162 String *params;
163 Cardinal *num_params;
164 {
165 	XtDestroyApplicationContext(XtWidgetToApplicationContext(w));
166 	exit(0);
167 }
168 
a_goto(w,event,params,num_params)169 static void a_goto(w, event, params, num_params)
170 Widget w;
171 XEvent *event;
172 String *params;
173 Cardinal *num_params;
174 {
175 	press(event->xbutton.x, event->xbutton.y);
176 }
177 
a_reset(w,event,params,num_params)178 static void a_reset(w, event, params, num_params)
179 Widget w;
180 XEvent *event;
181 String *params;
182 Cardinal *num_params;
183 {
184 	reset();
185 }
186 
a_reorder(w,event,params,num_params)187 static void a_reorder(w, event, params, num_params)
188 Widget w;
189 XEvent *event;
190 String *params;
191 Cardinal *num_params;
192 {
193 	if (*num_params != 1) {
194 		fprintf(stderr, "xdu: bad number of params to reorder action\n");
195 	} else {
196 		reorder(*params);
197 	}
198 }
199 
a_size(w,event,params,num_params)200 static void a_size(w, event, params, num_params)
201 Widget w;
202 XEvent *event;
203 String *params;
204 Cardinal *num_params;
205 {
206 	if (res.showsize)
207 		res.showsize = 0;
208 	else
209 		res.showsize = 1;
210 	xrepaint();
211 }
212 
a_ncol(w,event,params,num_params)213 static void a_ncol(w, event, params, num_params)
214 Widget w;
215 XEvent *event;
216 String *params;
217 Cardinal *num_params;
218 {
219 	int	n;
220 
221 	if (*num_params != 1) {
222 		fprintf(stderr, "xdu: bad number of params to ncol action\n");
223 		return;
224 	}
225 	n = atoi(*params);
226 	if (n < 1 || n > 1000) {
227 		fprintf(stderr, "xdu: bad value to ncol action\n");
228 		return;
229 	}
230 	ncols = res.ncol = n;
231 	xrepaint();
232 }
233 
a_info(w,event,params,num_params)234 static void a_info(w, event, params, num_params)
235 Widget w;
236 XEvent *event;
237 String *params;
238 Cardinal *num_params;
239 {
240 	nodeinfo();
241 }
242 
a_help(w,event,params,num_params)243 static void a_help(w, event, params, num_params)
244 Widget w;
245 XEvent *event;
246 String *params;
247 Cardinal *num_params;
248 {
249 	/*helpinfo();*/
250 	help_popup();
251 }
252 
a_removehelp(w,event,params,num_params)253 static void a_removehelp(w, event, params, num_params)
254 Widget w;
255 XEvent *event;
256 String *params;
257 Cardinal *num_params;
258 {
259 	help_popdown();
260 }
261 
262 /* callback routines */
263 
c_resize(w,data,event,continue_to_dispatch)264 static void c_resize(w, data, event, continue_to_dispatch)
265 Widget w;
266 XtPointer data;
267 XEvent *event;
268 Boolean *continue_to_dispatch;
269 {
270 	/*printf("Resize\n");*/
271 	xrepaint();
272 }
273 
c_repaint(w,data,event,continue_to_dispatch)274 static void c_repaint(w, data, event, continue_to_dispatch)
275 Widget w;
276 XtPointer data;
277 XEvent *event;
278 Boolean *continue_to_dispatch;
279 {
280 	/*printf("Expose\n");*/
281 	xrepaint_noclear();
282 }
283 
284 /* X Window related variables */
285 static Cursor WorkingCursor;
286 static Display *dpy;
287 static int screen;
288 static Visual *vis;
289 static Window win;
290 static GC gc;
291 static GC cleargc;
292 static XtAppContext app_con;
293 
294 Widget toplevel;
295 
296 /*  External Functions  */
297 
298 int
xsetup(argcp,argv)299 xsetup(argcp, argv)
300 int *argcp;
301 char **argv;
302 {
303 	XtTranslations trans_table;
304 	Widget w;
305 	XGCValues gcv;
306 	int n;
307 	Arg args[5];
308 
309 	/* Create the top level Widget */
310 	n = 0;
311 	XtSetArg(args[n], XtNtitle, "XDU Disk Usage Display ('h' for help)\n"); n++;
312 	toplevel = XtAppInitialize(&app_con, "XDu",
313 			options, XtNumber(options),
314 			argcp, argv,
315 			fallback_resources, args, n);
316 
317 	XtGetApplicationResources(toplevel, (XtPointer)&res,
318 		application_resources, XtNumber(application_resources),
319 		NULL, 0 );
320 
321 	XtAppAddActions(app_con, actionsTable, XtNumber(actionsTable));
322 	trans_table = XtParseTranslationTable(defaultTranslations);
323 
324 	/* Create a simple Label class widget to draw in */
325 	n = 0;
326 	XtSetArg(args[n], XtNlabel, ""); n++;
327 	w = XtCreateManagedWidget("window", labelWidgetClass, toplevel,
328 		args, n);
329 
330 	/* events */
331 	XtAddEventHandler(w, ExposureMask, False, c_repaint, NULL);
332 	XtAddEventHandler(w, StructureNotifyMask, False, c_resize, NULL);
333 	XtAugmentTranslations(w, trans_table);
334 
335 	XtRealizeWidget(toplevel);
336 
337 	/* We need these for the raw Xlib calls */
338 	win = XtWindow(w);
339 	dpy = XtDisplay(w);
340 	screen = DefaultScreen(dpy);
341 	vis = DefaultVisual(dpy,screen);
342 
343 	gcv.foreground = res.foreground;
344 	gcv.background = res.background;
345 	gcv.font = res.font->fid;
346 	gc = XCreateGC(dpy, win, (GCFont|GCForeground|GCBackground), &gcv);
347 
348 	setorder(res.order);
349 	ncols = res.ncol;
350 }
351 
xmainloop()352 xmainloop()
353 {
354 	XtAppMainLoop(app_con);
355 	return(0);
356 }
357 
xclear()358 xclear()
359 {
360 	XClearWindow(dpy, win);
361 }
362 
xrepaint()363 xrepaint()
364 {
365 	XWindowAttributes xwa;
366 
367 	XClearWindow(dpy, win);
368 	XGetWindowAttributes(dpy, win, &xwa);
369 	repaint(xwa.width, xwa.height);
370 }
371 
xrepaint_noclear()372 xrepaint_noclear()
373 {
374 	XWindowAttributes xwa;
375 
376 	XGetWindowAttributes(dpy, win, &xwa);
377 	repaint(xwa.width, xwa.height);
378 }
379 
xdrawrect(name,size,x,y,width,height)380 xdrawrect(name, size, x, y, width, height)
381 char *name;
382 int size;
383 int x, y, width, height;
384 {
385 	int	textx, texty;
386 	char	label[1024];
387 	XCharStruct overall;
388 	int	ascent, descent, direction;
389 	int	cheight;
390 
391 	/*printf("draw(%d,%d,%d,%d)\n", x, y, width, height );*/
392 	XDrawRectangle(dpy, win, gc, x, y, width, height);
393 
394 	if (res.showsize) {
395 		sprintf(label,"%s (%d)", name, size);
396 		name = label;
397 	}
398 
399 	XTextExtents(res.font, name, strlen(name), &direction,
400 		&ascent, &descent, &overall);
401 	cheight = overall.ascent + overall.descent;
402 	if (height < (cheight + 2))
403 		return 0;
404 
405 	/* print label */
406 	textx = x + 4;
407 	texty = y + height/2.0 + (overall.ascent - overall.descent)/2.0 + 1.5;
408 	XDrawString(dpy, win, gc, textx, texty, name, strlen(name));
409 
410 	return 0;
411 }
412 
413 static Widget popup;
414 
415 static void
help_popup()416 help_popup()
417 {
418 	Widget form, text, src;
419 	Arg args[15];
420 	int n;
421 	Atom wm_delete_window;
422 	XtTranslations trans_table;
423 
424 	if (popup != NULL) {
425 		XtPopup(popup, XtGrabNone);
426 		return;
427 	}
428 
429 	/* popup shell */
430 	n = 0;
431 	XtSetArg(args[n], XtNtitle, "XDU Help"); n++;
432 	popup = XtCreatePopupShell("helpPopup", transientShellWidgetClass,
433 		toplevel, args, n);
434 
435 	/* form container */
436 	n = 0;
437 	XtSetArg(args[n], XtNborderWidth, 0); n++;
438 	XtSetArg(args[n], XtNdefaultDistance, 0); n++;
439 	form = XtCreateManagedWidget("form", formWidgetClass,
440 		popup, args, n);
441 
442 	/* text widget in form */
443 	n = 0;
444 	XtSetArg(args[n], XtNborderWidth, 0); n++;
445 	XtSetArg(args[n], XtNresize, XawtextResizeBoth); n++;
446 	/* fallback resources weren't working here on the Sun */
447 	XtSetArg(args[n], XtNwidth, 500); n++;
448 	XtSetArg(args[n], XtNheight, 330); n++;
449 	text = XtCreateManagedWidget("help", asciiTextWidgetClass,
450 		form, args, n);
451 
452 	/* create text source */
453 	n = 0;
454 	XtSetArg(args[n], XtNtype, XawAsciiString); n++;
455 	XtSetArg(args[n], XtNeditType, XawtextRead); n++;
456 	XtSetArg(args[n], XtNstring, "\
457 XDU Version 3.0 - Phil Dykstra <phil@arl.mil>\n\
458 \n\
459 Keyboard Commands\n\
460   a  sort alphabetically\n\
461   n  sort numerically (largest first)\n\
462   f  sort first-in-first-out\n\
463   l  sort last-in-first-out\n\
464   r  reverse sort\n\
465   s  toggle size display\n\
466   /  goto the root\n\
467   i  node info to standard out\n\
468   h  this help message\n\
469   q  quit (also Escape)\n\
470 0-9  set number of columns (0=10)\n\
471 \n\
472 Mouse Commands\n\
473   Left   Goto node (goto parent if leftmost box)\n\
474   Middle Back to root\n\
475   Right  Quit\n\
476 "); n++;
477 	src = XtCreateWidget("textSource", asciiSrcObjectClass,
478 		text, args, n);
479 	/* set text source */
480 	XawTextSetSource(text, src, 0);
481 
482 	XtRealizeWidget(popup);
483 	XtPopup(popup, XtGrabNone);
484 
485 	trans_table = XtParseTranslationTable("<Key>Q: RemoveHelp()");
486 	XtAugmentTranslations(form, trans_table);
487 
488 	/* Set up ICCCM delete window */
489 	wm_delete_window = XInternAtom(XtDisplay(popup), "WM_DELETE_WINDOW", False);
490 	XtOverrideTranslations(popup, XtParseTranslationTable("<Message>WM_PROTOCOLS: RemoveHelp()"));
491 	XSetWMProtocols(XtDisplay(popup), XtWindow(popup), &wm_delete_window, 1);
492 }
493 
494 static void
help_popdown()495 help_popdown()
496 {
497 	XtPopdown(popup);
498 }
499