1 /*
2  *   xmmix - Motif(tm) Audio Mixer
3  *
4  *   Copyright (C) 1994-1996  Ti Kan
5  *   E-mail: ti@amb.org
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 2 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22 #ifndef LINT
23 static char *_widget_c_ident_ = "@(#)widget.c	3.3 96/07/14";
24 #endif
25 
26 #include "appenv.h"
27 #include "widget.h"
28 #include "mixer.h"
29 #include "xmmix.xbm"
30 
31 
32 extern appdata_t	app_data;
33 extern widgets_t	widgets;
34 extern int		maxdevs;
35 
36 #define CTL_DISTANCE	48
37 
38 
39 #define PD_FILE_LOAD	0
40 #define PD_FILE_SAVE	1
41 #define PD_FILE_SEP	2
42 #define PD_FILE_EXIT	3
43 
44 STATIC btinfo_t		file_btinfo[] = {
45     { NULL, "Load...", "loadButton",    "l",  "L"  },
46     { NULL, "Save...", "saveButton",    "s",  "S"  },
47     { NULL, NULL,      "fileSeparator", NULL, NULL },
48     { NULL, "Exit",    "exitButton",    "x",  "x"  },
49     { NULL, NULL,      NULL,            NULL, NULL },
50 };
51 
52 #define PD_OPTS_RESET	0
53 
54 STATIC btinfo_t		options_btinfo[] = {
55     { NULL, "Reset", "resetButton", "r",  "R" },
56     { NULL, NULL,    NULL,          NULL, NULL },
57 };
58 
59 #define PD_HELP_MANPG	0
60 #define PD_HELP_ABOUT	1
61 
62 STATIC btinfo_t		help_btinfo[] = {
63     { NULL, "Man page...", "manPageButton", "m",  "M" },
64     { NULL, "About...",    "aboutButton",   "a",  "A" },
65     { NULL, NULL,          NULL,            NULL, NULL },
66 };
67 
68 STATIC pdinfo_t		file_pd = {
69     NULL, "File",    "file",    "f", "F", file_btinfo
70 };
71 
72 STATIC pdinfo_t		opts_pd = {
73     NULL, "Options", "options", "o", "O", options_btinfo
74 };
75 
76 STATIC pdinfo_t		help_pd = {
77     NULL, "Help",    "help",    "h", "H", help_btinfo
78 };
79 
80 STATIC slinfo_t		slinfo[] = {
81     {	/* 0 */
82 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
83 	"Master", "master", CTL_OUTPUT, 17, TRUE, FALSE
84     },
85     {	/* 1 */
86 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
87 	"Bass", "bass", CTL_MISC, 10, TRUE, FALSE
88     },
89     {	/* 2 */
90 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
91 	"Treble", "treble", CTL_MISC, 11, TRUE, FALSE
92     },
93     {	/* 3 */
94 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
95 	"Synth", "synth", CTL_INPUT, 1, TRUE, TRUE
96     },
97     {	/* 4 */
98 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
99 	"PCM", "pcm", CTL_INPUT, 2, TRUE, TRUE
100     },
101     {	/* 5 */
102 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
103 	"Speaker", "speaker", CTL_OUTPUT, 16, TRUE, FALSE
104     },
105     {	/* 6 */
106 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
107 	"Line", "line", CTL_INPUT, 4, TRUE, TRUE
108     },
109     {	/* 7 */
110 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
111 	"Mic", "mic", CTL_INPUT, 8, TRUE, TRUE
112     },
113     {	/* 8 */
114 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
115 	"CD", "cd", CTL_INPUT, 9, TRUE, TRUE
116     },
117     {	/* 9 */
118 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
119 	"Rec Mon", "recmon", CTL_OUTPUT, 12, TRUE, FALSE
120     },
121     {	/* 10 */
122 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
123 	"Alt PCM", "altpcm", CTL_INPUT, 3, TRUE, TRUE
124     },
125     {	/* 11 */
126 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
127 	"Rec Out", "recout", CTL_OUTPUT, 13, TRUE, FALSE
128     },
129     {	/* 12 */
130 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
131 	"In Gain", "igain", CTL_MISC, 14, TRUE, FALSE
132     },
133     {	/* 13 */
134 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
135 	"Out Gain", "ogain", CTL_MISC, 15, TRUE, FALSE
136     },
137     {	/* 14 */
138 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
139 	"Line-1", "line1", CTL_INPUT, 5, TRUE, TRUE
140     },
141     {	/* 15 */
142 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
143 	"Line-2", "line2", CTL_INPUT, 6, TRUE, TRUE
144     },
145     {	/* 16 */
146 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
147 	"Line-3", "line3", CTL_INPUT, 7, TRUE, TRUE
148     },
149     {	/* 17 */
150 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
151 	NULL, NULL, 0, 0, FALSE, FALSE
152     },
153     {	/* 18 */
154 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
155 	NULL, NULL, 0, 0, FALSE, FALSE
156     },
157     {	/* 19 */
158 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
159 	NULL, NULL, 0, 0, FALSE, FALSE
160     },
161     {	/* 20 */
162 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
163 	NULL, NULL, 0, 0, FALSE, FALSE
164     },
165     {	/* 21 */
166 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
167 	NULL, NULL, 0, 0, FALSE, FALSE
168     },
169     {	/* 22 */
170 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
171 	NULL, NULL, 0, 0, FALSE, FALSE
172     },
173     {	/* 23 */
174 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
175 	NULL, NULL, 0, 0, FALSE, FALSE
176     },
177     {	/* 24 */
178 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
179 	NULL, NULL, 0, 0, FALSE, FALSE
180     },
181     {	/* 25 */
182 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
183 	NULL, NULL, 0, 0, FALSE, FALSE
184     },
185     {	/* 26 */
186 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
187 	NULL, NULL, 0, 0, FALSE, FALSE
188     },
189     {	/* 27 */
190 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
191 	NULL, NULL, 0, 0, FALSE, FALSE
192     },
193     {	/* 28 */
194 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
195 	NULL, NULL, 0, 0, FALSE, FALSE
196     },
197     {	/* 29 */
198 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
199 	NULL, NULL, 0, 0, FALSE, FALSE
200     },
201     {	/* 30 */
202 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
203 	NULL, NULL, 0, 0, FALSE, FALSE
204     },
205     {	/* 31 */
206 	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
207 	NULL, NULL, 0, 0, FALSE, FALSE
208     }
209 };
210 
211 STATIC XmString		xs_lock,
212 			xs_rec,
213 			xs_left,
214 			xs_right;
215 
216 STATIC Atom		delw;
217 
218 
219 /***********************
220  *  internal routines  *
221  ***********************/
222 
223 /*
224  * Widget-related functions
225  */
226 
227 /*
228  * create_pdmnu
229  *	Create a pulldown menu
230  *
231  * Args:
232  *	parent - The parent widget
233  *	pd - The pulldown menu info structure
234  *
235  * Return:
236  *	The menu widget
237  */
238 STATIC Widget
create_pdmnu(Widget parent,pdinfo_t * pd)239 create_pdmnu(Widget parent, pdinfo_t *pd)
240 {
241 	int		i,
242 			n;
243 	Arg		arg[10];
244 	XmString	xs;
245 	XmString	xs_acc;
246 	char		wname[STR_BUF_SZ];
247 	Widget		ret_widget;
248 
249 	/* Create File pulldown menu */
250 	sprintf(wname, "%sMenu", pd->name);
251 	ret_widget = XmCreatePulldownMenu(parent, wname, NULL, 0);
252 
253 	for (i = 0; pd->btip[i].name != NULL; i++) {
254 		n = 0;
255 		if (pd->btip[i].label == NULL) {
256 			/* Separator */
257 			pd->btip[i].widget = XmCreateSeparator(
258 				ret_widget, pd->btip[i].name, NULL, 0
259 			);
260 			XtManageChild(pd->btip[i].widget);
261 		}
262 		else {
263 			/* Button */
264 			if (pd->btip[i].label != NULL) {
265 				xs = XmStringCreateSimple(pd->btip[i].label);
266 				XtSetArg(arg[n], XmNlabelString, xs); n++;
267 			}
268 
269 			if (pd->btip[i].acc != NULL) {
270 				xs_acc = XmStringCreateSimple(pd->btip[i].acc);
271 				XtSetArg(arg[n], XmNaccelerator, xs_acc); n++;
272 			}
273 
274 			if (pd->btip[i].mne != NULL) {
275 				XtSetArg(arg[n], XmNmnemonic,
276 					 XStringToKeysym(pd->btip[i].mne)); n++;
277 			}
278 
279 			pd->btip[i].widget = XmCreatePushButton(
280 				ret_widget, pd->btip[i].name, arg, n
281 			);
282 			XtManageChild(pd->btip[i].widget);
283 
284 			if (pd->btip[i].label != NULL)
285 				XmStringFree(xs);
286 			if (pd->btip[i].acc != NULL)
287 				XmStringFree(xs_acc);
288 		}
289 	}
290 
291 	/* Create cascade button as menu activator */
292 	sprintf(wname, "%sButton", pd->name);
293 
294 	n = 0;
295 	if (pd->label != NULL) {
296 		xs = XmStringCreateSimple(pd->label);
297 		XtSetArg(arg[n], XmNlabelString, xs); n++;
298 	}
299 	if (pd->acc != NULL) {
300 		xs_acc = XmStringCreateSimple(pd->acc);
301 		XtSetArg(arg[n], XmNaccelerator, xs_acc); n++;
302 	}
303 	if (pd->mne != NULL) {
304 		XtSetArg(arg[n], XmNmnemonic, XStringToKeysym(pd->mne)); n++;
305 	}
306 
307 	XtSetArg(arg[n], XmNsubMenuId, ret_widget); n++;
308 	pd->widget = XmCreateCascadeButton(parent, wname, arg, n);
309 	XtManageChild(pd->widget);
310 
311 	if (pd->label != NULL)
312 		XmStringFree(xs);
313 	if (pd->acc != NULL)
314 		XmStringFree(xs_acc);
315 
316 	return (ret_widget);
317 }
318 
319 
320 /*
321  * create_vert_controls
322  *	Create a group of mixer controls including the vertical slider
323  *	and associated toggle buttons and labels.
324  *
325  * Args:
326  *	m - Pointer to the main widgets structure
327  *	dev - The mixer control device index
328  *	y1 - The top reference position (percent)
329  *	y2 - The bottom reference position (percent)
330  *	pos - The display position number
331  *	tot - Total number of controls to be displayed
332  *
333  * Return:
334  *	Nothing
335  */
336 STATIC void
create_vert_controls(widgets_t * m,int dev,int y1,int y2,int pos,int tot)337 create_vert_controls(widgets_t *m, int dev, int y1, int y2, int pos, int tot)
338 {
339 	int		x,
340 			n;
341 	Arg		arg[20];
342 	char		wname[STR_BUF_SZ];
343 	XmString	xs;
344 
345 	x = CTL_DISTANCE * pos;
346 
347 	/* Right slider */
348 	sprintf(wname, "%sRightScale", slinfo[dev].name);
349 	n = 0;
350 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
351 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_NONE); n++;
352 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
353 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
354 	XtSetArg(arg[n], XmNleftOffset, x); n++;
355 	XtSetArg(arg[n], XmNtopPosition, y1); n++;
356 	XtSetArg(arg[n], XmNbottomPosition, y2); n++;
357 	XtSetArg(arg[n], XmNshowValue, False); n++;
358 	XtSetArg(arg[n], XmNorientation, XmVERTICAL); n++;
359 	XtSetArg(arg[n], XmNprocessingDirection, XmMAX_ON_TOP); n++;
360 	XtSetArg(arg[n], XmNminimum, 0); n++;
361 	XtSetArg(arg[n], XmNmaximum, 100); n++;
362 	XtSetArg(arg[n], XmNhighlightOnEnter, True); n++;
363 	slinfo[dev].widget_r = XmCreateScale(m->form, wname, arg, n);
364 	XtManageChild(slinfo[dev].widget_r);
365 
366 	/* Left slider */
367 	sprintf(wname, "%sLeftScale", slinfo[dev].name);
368 	n = 0;
369 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_NONE); n++;
370 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
371 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
372 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
373 	XtSetArg(arg[n], XmNrightWidget, slinfo[dev].widget_r); n++;
374 	XtSetArg(arg[n], XmNtopPosition, y1); n++;
375 	XtSetArg(arg[n], XmNbottomPosition, y2); n++;
376 	XtSetArg(arg[n], XmNshowValue, False); n++;
377 	XtSetArg(arg[n], XmNorientation, XmVERTICAL); n++;
378 	XtSetArg(arg[n], XmNprocessingDirection, XmMAX_ON_TOP); n++;
379 	XtSetArg(arg[n], XmNminimum, 0); n++;
380 	XtSetArg(arg[n], XmNmaximum, 100); n++;
381 	XtSetArg(arg[n], XmNhighlightOnEnter, True); n++;
382 	slinfo[dev].widget_l = XmCreateScale(m->form, wname, arg, n);
383 	XtManageChild(slinfo[dev].widget_l);
384 
385 	/* Left label */
386 	sprintf(wname, "%sLeftLabel", slinfo[dev].name);
387 	n = 0;
388 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
389 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_NONE); n++;
390 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
391 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
392 	XtSetArg(arg[n], XmNleftWidget, slinfo[dev].widget_l); n++;
393 	XtSetArg(arg[n], XmNtopPosition, y1 - 4); n++;
394 	XtSetArg(arg[n], XmNbottomWidget, slinfo[dev].widget_l); n++;
395 	XtSetArg(arg[n], XmNlabelString, xs_left); n++;
396 	slinfo[dev].widget_lbl_l = XmCreateLabel(
397 		m->form, wname, arg, n
398 	);
399 	XtManageChild(slinfo[dev].widget_lbl_l);
400 
401 	/* Right label */
402 	sprintf(wname, "%sRightLabel", slinfo[dev].name);
403 	n = 0;
404 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_NONE); n++;
405 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
406 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
407 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
408 	XtSetArg(arg[n], XmNrightWidget, slinfo[dev].widget_r); n++;
409 	XtSetArg(arg[n], XmNtopPosition, y1 - 4); n++;
410 	XtSetArg(arg[n], XmNbottomWidget, slinfo[dev].widget_r); n++;
411 	XtSetArg(arg[n], XmNlabelString, xs_right); n++;
412 	slinfo[dev].widget_lbl_r = XmCreateLabel(
413 		m->form, wname, arg, n
414 	);
415 	XtManageChild(slinfo[dev].widget_lbl_r);
416 
417 	/* Slider label */
418 	sprintf(wname, "%sLabel", slinfo[dev].name);
419 	xs = XmStringCreateSimple(slinfo[dev].label);
420 	n = 0;
421 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
422 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
423 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
424 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
425 	XtSetArg(arg[n], XmNleftWidget, slinfo[dev].widget_lbl_l); n++;
426 	XtSetArg(arg[n], XmNrightWidget, slinfo[dev].widget_lbl_r); n++;
427 	XtSetArg(arg[n], XmNleftOffset, -4); n++;
428 	XtSetArg(arg[n], XmNrightOffset, -4); n++;
429 	XtSetArg(arg[n], XmNtopWidget, m->menu_bar); n++;
430 	XtSetArg(arg[n], XmNtopOffset, 3); n++;
431 	XtSetArg(arg[n], XmNbottomWidget, slinfo[dev].widget_lbl_l); n++;
432 	XtSetArg(arg[n], XmNlabelString, xs); n++;
433 	slinfo[dev].widget_lbl = XmCreateLabel(
434 		m->form, slinfo[dev].name, arg, n
435 	);
436 	XtManageChild(slinfo[dev].widget_lbl);
437 	XmStringFree(xs);
438 
439 	/* Lock button */
440 	sprintf(wname, "%sLockButton", slinfo[dev].name);
441 	n = 0;
442 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
443 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
444 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
445 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
446 	XtSetArg(arg[n], XmNleftWidget, slinfo[dev].widget_l); n++;
447 	XtSetArg(arg[n], XmNrightWidget, slinfo[dev].widget_r); n++;
448 	XtSetArg(arg[n], XmNtopWidget, slinfo[dev].widget_l); n++;
449 	XtSetArg(arg[n], XmNlabelString, xs_lock); n++;
450 	slinfo[dev].widget_lock_btn = XmCreateToggleButton(
451 		m->form, wname, arg, n
452 	);
453 	XtManageChild(slinfo[dev].widget_lock_btn);
454 
455 	/* Record selector buttons */
456 	if (slinfo[dev].recsupp) {
457 		sprintf(wname, "%sRecButton", slinfo[dev].name);
458 		n = 0;
459 		XtSetArg(arg[n], XmNleftAttachment,
460 			 XmATTACH_OPPOSITE_WIDGET); n++;
461 		XtSetArg(arg[n], XmNrightAttachment,
462 			 XmATTACH_OPPOSITE_WIDGET); n++;
463 		XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
464 		XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
465 		XtSetArg(arg[n], XmNleftWidget, slinfo[dev].widget_l); n++;
466 		XtSetArg(arg[n], XmNrightWidget, slinfo[dev].widget_r); n++;
467 		XtSetArg(arg[n], XmNtopWidget,
468 			 slinfo[dev].widget_lock_btn); n++;
469 		XtSetArg(arg[n], XmNlabelString, xs_rec); n++;
470 		slinfo[dev].widget_rec_btn = XmCreateToggleButton(
471 			m->form, wname, arg, n
472 		);
473 		XtManageChild(slinfo[dev].widget_rec_btn);
474 	}
475 }
476 
477 
478 /*
479  * bm_to_px
480  *	Convert a bitmap into a pixmap.
481  *
482  * Args:
483  *	w - A widget the pixmap should be associated with
484  *	bits - Pointer to the raw bitmap data
485  *	width, height - The resultant pixmap dimensions
486  *
487  * Return:
488  *	The pixmap ID, or NULL if failure.
489  */
490 Pixmap
bm_to_px(Widget w,void * bits,int width,int height,int depth)491 bm_to_px(Widget w, void *bits, int width, int height, int depth)
492 {
493 	Display		*display = XtDisplay(w);
494 	Window		window	 = XtWindow(w);
495 	int		screen	 = DefaultScreen(display);
496 	Pixmap		ret_pixmap;
497 	Pixel		fg,
498 			bg;
499 
500 	/* Allocate colors for pixmap if on color screen */
501 	if (DisplayCells(display, screen) > 2 && depth > 1) {
502 		XtVaGetValues(w,
503 			XmNforeground, &fg,
504 			XmNbackground, &bg,
505 			NULL
506 		);
507 	}
508 	else {
509 		fg = BlackPixel(display, screen);
510 		bg = WhitePixel(display, screen);
511 	}
512 
513 	ret_pixmap = XCreatePixmapFromBitmapData(
514 		display, window, (char *) bits, width, height, fg, bg, depth
515 	);
516 
517 	if (ret_pixmap == (Pixmap) NULL)
518 		return ((Pixmap) NULL);
519 
520 	return (ret_pixmap);
521 }
522 
523 
524 /***********************
525  *   public routines   *
526  ***********************/
527 
528 
529 /*
530  * widget_init
531  *	Initialize widget-related structures.
532  *
533  * Args:
534  *	m - Pointer to the main widgets structure
535  *
536  * Return:
537  *	Nothing
538  */
539 void
widget_init(widgets_t * m)540 widget_init(widgets_t *m)
541 {
542 	/* Initialize structures */
543 	m->sl = slinfo;
544 	m->file_pd = &file_pd;
545 	m->opts_pd = &opts_pd;
546 	m->help_pd = &help_pd;
547 }
548 
549 
550 /*
551  * create_widgets
552  *	Top-level function to create all widgets.
553  *
554  * Args:
555  *	m - Pointer to the main widgets structure
556  *
557  * Return:
558  *	Nothing
559  */
560 void
create_widgets(widgets_t * m)561 create_widgets(widgets_t *m)
562 {
563 	int		i, j, k, n,
564 			ctls,
565 			form_width;
566 	Arg		arg[20];
567 	char		wname[STR_BUF_SZ],
568 			str[STR_BUF_SZ];
569 	XmString	xs;
570 
571 	/* Count the number of slider controls we will display */
572 	for (i = 0, ctls = 0; i < maxdevs; i++) {
573 		if (slinfo[i].supp)
574 			ctls++;
575 	}
576 
577 	/* Create compound strings that will be used repetitively */
578 	xs_left = XmStringCreateSimple("L");
579 	xs_right = XmStringCreateSimple("R");
580 	xs_lock = XmStringCreateSimple("lock");
581 	xs_rec = XmStringCreateSimple("rec");
582 
583 	/* Create form widget as container */
584 	if ((form_width = (ctls + 1) * CTL_DISTANCE) < 300)
585 		form_width = 300;
586 	n = 0;
587 	XtSetArg(arg[n], XmNwidth, form_width); n++;
588 	XtSetArg(arg[n], XmNheight, 320); n++;
589 	XtSetArg(arg[n], XmNresizePolicy, XmRESIZE_NONE); n++;
590 	m->form = XmCreateForm(m->toplevel, "mainForm", arg, n);
591 	XtManageChild(m->form);
592 
593 	/* Create logo label */
594 	n = 0;
595 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
596 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_NONE); n++;
597 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
598 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
599 	XtSetArg(arg[n], XmNleftOffset, (form_width/2) - (xmmix_width/2)); n++;
600 	XtSetArg(arg[n], XmNtopPosition, 88); n++;
601 	XtSetArg(arg[n], XmNlabelType, XmPIXMAP); n++;
602 	XtSetArg(arg[n], XmNmarginHeight, 0); n++;
603 	XtSetArg(arg[n], XmNmarginWidth, 0); n++;
604 	XtSetArg(arg[n], XmNhighlightThickness, 0); n++;
605 	XtSetArg(arg[n], XmNwidth, xmmix_width); n++;
606 	XtSetArg(arg[n], XmNheight, xmmix_height); n++;
607 	m->logolbl = XmCreateLabel(m->form, "logoLabel", arg, n);
608 	XtManageChild(m->logolbl);
609 
610 	/* Create menu bar */
611 	n = 0;
612 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
613 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
614 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_FORM); n++;
615 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
616 	m->menu_bar = XmCreateMenuBar(m->form, "menuBar", arg, n);
617 	XtManageChild(m->menu_bar);
618 
619 	/* Create File pulldown menu */
620 	m->file_mnu = create_pdmnu(m->menu_bar, &file_pd);
621 
622 	/* Create Options pulldown menu */
623 	m->options_mnu = create_pdmnu(m->menu_bar, &opts_pd);
624 
625 	/* Create Help pulldown menu */
626 	m->help_mnu = create_pdmnu(m->menu_bar, &help_pd);
627 	XtVaSetValues(m->menu_bar,
628 		XmNmenuHelpWidget, help_pd.widget,
629 		NULL
630 	);
631 
632 	/* Create all sliders and associated labels and buttons */
633 	for (j = 1, k = 0; j <= MAXDEVS; j++) {
634 		for (i = 0; i < maxdevs; i++) {
635 			if (j == slinfo[i].order && slinfo[i].supp) {
636 				create_vert_controls(m, i, 22, 70, ++k, ctls);
637 			}
638 		}
639 	}
640 
641 	/* Horizontal separator */
642 	n = 0;
643 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
644 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
645 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
646 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
647 	XtSetArg(arg[n], XmNtopPosition, 84); n++;
648 	XtSetArg(arg[n], XmNleftOffset, 1); n++;
649 	XtSetArg(arg[n], XmNrightOffset, 1); n++;
650 	XtSetArg(arg[n], XmNorientation, XmHORIZONTAL); n++;
651 	m->hsep = XmCreateSeparator(m->form, "horizontalSeparator", arg, n);
652 	XtManageChild(m->hsep);
653 
654 	/*
655 	 * Flat button
656 	 */
657 	if (slinfo[SOUND_MIXER_BASS].supp || slinfo[SOUND_MIXER_TREBLE].supp) {
658 		xs = XmStringCreateSimple("Flat");
659 		n = 0;
660 		XtSetArg(arg[n], XmNleftAttachment,
661 			 XmATTACH_OPPOSITE_WIDGET); n++;
662 		XtSetArg(arg[n], XmNrightAttachment,
663 			 XmATTACH_OPPOSITE_WIDGET); n++;
664 		XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
665 		XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
666 		if (slinfo[SOUND_MIXER_BASS].supp) {
667 			XtSetArg(arg[n], XmNleftWidget,
668 			     m->sl[SOUND_MIXER_BASS].widget_l); n++;
669 			XtSetArg(arg[n], XmNtopWidget,
670 			     m->sl[SOUND_MIXER_BASS].widget_lock_btn); n++;
671 		}
672 		else {
673 			XtSetArg(arg[n], XmNleftWidget,
674 			     m->sl[SOUND_MIXER_TREBLE].widget_l); n++;
675 			XtSetArg(arg[n], XmNtopWidget,
676 			     m->sl[SOUND_MIXER_TREBLE].widget_lock_btn); n++;
677 		}
678 		if (slinfo[SOUND_MIXER_TREBLE].supp) {
679 			XtSetArg(arg[n], XmNrightWidget,
680 			     m->sl[SOUND_MIXER_TREBLE].widget_r); n++;
681 			XtSetArg(arg[n], XmNtopWidget,
682 			     m->sl[SOUND_MIXER_TREBLE].widget_lock_btn); n++;
683 		}
684 		else {
685 			XtSetArg(arg[n], XmNrightWidget,
686 			     m->sl[SOUND_MIXER_BASS].widget_r); n++;
687 			XtSetArg(arg[n], XmNtopWidget,
688 			     m->sl[SOUND_MIXER_BASS].widget_lock_btn); n++;
689 		}
690 		XtSetArg(arg[n], XmNlabelString, xs); n++;
691 		m->flat_btn = XmCreatePushButton(m->form, "flatButton", arg, n);
692 		XtManageChild(m->flat_btn);
693 		XmStringFree(xs);
694 	}
695 
696 	/*
697 	 * Mute button
698 	 */
699 	if (m->mute_supp) {
700 		xs = XmStringCreateSimple("Mute");
701 		n = 0;
702 		XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
703 		XtSetArg(arg[n], XmNrightAttachment, XmATTACH_NONE); n++;
704 		XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
705 		XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
706 		XtSetArg(arg[n], XmNleftOffset, form_width - 100); n++;
707 		XtSetArg(arg[n], XmNtopPosition, 87); n++;
708 		XtSetArg(arg[n], XmNbottomPosition, 92); n++;
709 		XtSetArg(arg[n], XmNwidth, 66); n++;
710 		XtSetArg(arg[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
711 		XtSetArg(arg[n], XmNlabelString, xs); n++;
712 		m->mute_btn = XmCreateToggleButton(
713 			m->form, "muteButton", arg, n
714 		);
715 		XtManageChild(m->mute_btn);
716 		XmStringFree(xs);
717 	}
718 
719 	/*
720 	 * Loudness button
721 	 */
722 	if (m->loud_supp) {
723 		xs = XmStringCreateSimple("Loudness");
724 		n = 0;
725 		XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
726 		XtSetArg(arg[n], XmNrightAttachment, XmATTACH_NONE); n++;
727 		XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
728 		XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
729 		XtSetArg(arg[n], XmNleftOffset, form_width - 100); n++;
730 		XtSetArg(arg[n], XmNtopPosition, 92); n++;
731 		XtSetArg(arg[n], XmNbottomPosition, 97); n++;
732 		XtSetArg(arg[n], XmNwidth, 66); n++;
733 		XtSetArg(arg[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
734 		XtSetArg(arg[n], XmNlabelString, xs); n++;
735 		m->loud_btn = XmCreateToggleButton(
736 			m->form, "loudnessButton", arg, n
737 		);
738 		XtManageChild(m->loud_btn);
739 		XmStringFree(xs);
740 	}
741 
742 	/*
743 	 * Enhance option menu
744 	 */
745 	if (m->enh_supp) {
746 		m->enh_mnu = XmCreatePulldownMenu(
747 			m->form, "enhancePulldownMenu", NULL, 0
748 		);
749 
750 		for (i = 0; i < NENHANCE; i++) {
751 			sprintf(wname, "enhanceButton%d", i);
752 			sprintf(str, "%d", i);
753 			xs = XmStringCreateSimple(str);
754 			n = 0;
755 			XtSetArg(arg[n], XmNlabelString, xs); n++;
756 			m->enh_btn[i] = XmCreatePushButton(
757 				m->enh_mnu, wname, arg, n
758 			);
759 			XtManageChild(m->enh_btn[i]);
760 			XmStringFree(xs);
761 		}
762 
763 		xs = XmStringCreateSimple("Enhance");
764 		n = 0;
765 		XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
766 		XtSetArg(arg[n], XmNrightAttachment, XmATTACH_NONE); n++;
767 		XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
768 		XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
769 		XtSetArg(arg[n], XmNleftOffset, 28); n++;
770 		XtSetArg(arg[n], XmNtopPosition, 88); n++;
771 		XtSetArg(arg[n], XmNsubMenuId, m->enh_mnu); n++;
772 		m->enh_opt = XmCreateOptionMenu(
773 			m->form, "enhanceOptionMenu", arg, n
774 		);
775 		XtVaSetValues(
776 			XmOptionLabelGadget(m->enh_opt),
777 			XmNlabelString, xs,
778 			NULL
779 		);
780 		XtManageChild(m->enh_opt);
781 		XmStringFree(xs);
782 	}
783 
784 	/*
785 	 * File selection box form
786 	 */
787 	n = 0;
788 	XtSetArg(arg[n], XmNresizePolicy, XmRESIZE_NONE); n++;
789 	XtSetArg(arg[n], XmNautoUnmanage, False); n++;
790 	XtSetArg(arg[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
791 	XtSetArg(arg[n], XmNwidth, 330); n++;
792 	XtSetArg(arg[n], XmNheight, 370); n++;
793 	m->fsform = XmCreateFormDialog(
794 		m->toplevel, "fileSelectionForm", arg, n
795 	);
796 
797 	/*
798 	 * File selection box
799 	 */
800 	xs = XmStringCreateSimple("*.mxr");
801 	n = 0;
802 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
803 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
804 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_FORM); n++;
805 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_FORM); n++;
806 	XtSetArg(arg[n], XmNmustMatch, False); n++;
807 	XtSetArg(arg[n], XmNpattern, xs); n++;
808 	m->fsbox = XmCreateFileSelectionBox(
809 		m->fsform, "fileSelectionBox", arg, n
810 	);
811 	XtUnmanageChild(
812 		XmFileSelectionBoxGetChild(m->fsbox, XmDIALOG_HELP_BUTTON)
813 	);
814 	XtManageChild(m->fsbox);
815 	XmStringFree(xs);
816 
817 	XmStringFree(xs_left);
818 	XmStringFree(xs_right);
819 	XmStringFree(xs_lock);
820 	XmStringFree(xs_rec);
821 
822 	/*
823 	 * Man page window widgets
824 	 */
825 
826 	/* Create form widget as container */
827 	xs = XmStringCreateSimple("Xmmix Help");
828 	n = 0;
829 	XtSetArg(arg[n], XmNdialogTitle, xs); n++;
830 	XtSetArg(arg[n], XmNautoUnmanage, True); n++;
831 	XtSetArg(arg[n], XmNresizePolicy, XmRESIZE_NONE); n++;
832 	XtSetArg(arg[n], XmNwidth, 460); n++;
833 	XtSetArg(arg[n], XmNheight, 340); n++;
834 	m->helpform = XmCreateFormDialog(m->form, "helpForm", arg, n);
835 	XmStringFree(xs);
836 
837 	/* Create text widget as help text viewer */
838 	n = 0;
839 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_POSITION); n++;
840 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_POSITION); n++;
841 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
842 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
843 	XtSetArg(arg[n], XmNleftPosition, 2); n++;
844 	XtSetArg(arg[n], XmNrightPosition, 98); n++;
845 	XtSetArg(arg[n], XmNtopPosition, 4); n++;
846 	XtSetArg(arg[n], XmNbottomPosition, 81); n++;
847 	XtSetArg(arg[n], XmNeditable, False); n++;
848 	XtSetArg(arg[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
849 	XtSetArg(arg[n], XmNcursorPositionVisible, False); n++;
850 	XtSetArg(arg[n], XmNcursorPosition, 0); n++;
851 	m->helptxt = XmCreateScrolledText(m->helpform, "helpText", arg, n);
852 	XtManageChild(m->helptxt);
853 
854 	/* Create separator bar widget */
855 	n = 0;
856 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
857 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
858 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
859 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
860 	XtSetArg(arg[n], XmNleftOffset, 2); n++;
861 	XtSetArg(arg[n], XmNrightOffset, 2); n++;
862 	XtSetArg(arg[n], XmNtopPosition, 84); n++;
863 	m->helpsep = XmCreateSeparator(m->helpform, "helpSeparator", arg, n);
864 	XtManageChild(m->helpsep);
865 
866 	/* Create pushbutton widget as OK button */
867 	xs = XmStringCreateSimple("OK");
868 	n = 0;
869 	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_POSITION); n++;
870 	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_POSITION); n++;
871 	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
872 	XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
873 	XtSetArg(arg[n], XmNleftPosition, 44); n++;
874 	XtSetArg(arg[n], XmNrightPosition, 56); n++;
875 	XtSetArg(arg[n], XmNtopPosition, 89); n++;
876 	XtSetArg(arg[n], XmNlabelString, xs); n++;
877 	m->helpok_btn = XmCreatePushButton(
878 		m->helpform, "helpOkButton", arg, n
879 	);
880 	XtManageChild(m->helpok_btn);
881 	XmStringFree(xs);
882 
883 	/*
884 	 * Info dialog widget for the About popup
885 	 */
886 	xs = XmStringCreateSimple("About");
887 	n = 0;
888 	XtSetArg(arg[n], XmNdialogTitle, xs); n++;
889 	XtSetArg(arg[n], XmNdialogStyle, XmDIALOG_MODELESS); n++;
890 	m->about = XmCreateInformationDialog(
891 		m->toplevel, "aboutDialog", arg, n
892 	);
893 	XtUnmanageChild(
894 		XmMessageBoxGetChild(m->about, XmDIALOG_HELP_BUTTON)
895 	);
896 	XtUnmanageChild(
897 		XmMessageBoxGetChild(m->about, XmDIALOG_CANCEL_BUTTON)
898 	);
899 	XmStringFree(xs);
900 
901 	/*
902 	 * Info dialog widget for warning popups
903 	 */
904 	xs = XmStringCreateSimple("Warning");
905 	n = 0;
906 	XtSetArg(arg[n], XmNdialogTitle, xs); n++;
907 	XtSetArg(arg[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
908 	m->warning = XmCreateWarningDialog(
909 		m->toplevel, "warningDialog", arg, n
910 	);
911 	XtUnmanageChild(
912 		XmMessageBoxGetChild(m->warning, XmDIALOG_HELP_BUTTON)
913 	);
914 	XtUnmanageChild(
915 		XmMessageBoxGetChild(m->warning, XmDIALOG_CANCEL_BUTTON)
916 	);
917 	XmStringFree(xs);
918 }
919 
920 
921 /*
922  * post_realize_config
923  *	Top-level function to perform set-up and initialization tasks
924  *	after realizing all widgets.
925  *
926  * Args:
927  *	m - Pointer to the main widgets structure
928  *
929  * Return:
930  *	Nothing
931  */
932 void
post_realize_config(widgets_t * m)933 post_realize_config(widgets_t *m)
934 {
935 	int	i, n;
936 	Display	*display = XtDisplay(m->toplevel);
937 	Pixmap	px;
938 	char	title[STR_BUF_SZ],
939 		*p;
940 
941 	/* Set main window title bar string */
942 	if (app_data.demo)
943 		strcpy(title, "Motif Audio Mixer (Demo)");
944 	else {
945 		n = 0;
946 		if ((i = strlen(app_data.device)) > 0) {
947 			/* Find mixer device number */
948 			p = app_data.device + i;
949 			while (p > app_data.device) {
950 				if (!isdigit(*(p - 1)))
951 					break;
952 				p--;
953 			}
954 			if (isdigit(*p))
955 				n = atoi(p);
956 		}
957 		sprintf(title, "Motif Audio Mixer %d", n);
958 	}
959 	XStoreName(display, XtWindow(m->toplevel), title);
960 
961 	/*
962 	 * Create logo pixmap
963 	 */
964 	px = bm_to_px(m->logolbl, xmmix_bits, xmmix_width, xmmix_height, 1);
965 	XtVaSetValues(m->toplevel, XmNiconPixmap, px, NULL);
966 
967 	px = bm_to_px(m->logolbl, xmmix_bits, xmmix_width, xmmix_height,
968 		      DefaultDepth(display, DefaultScreen(display)));
969 	XtVaSetValues(m->logolbl, XmNlabelPixmap, px, NULL);
970 	XtVaSetValues(m->about, XmNsymbolPixmap, px, NULL);
971 
972 	/* Get WM_DELETE_WINDOW atom */
973 	delw = XmInternAtom(display, "WM_DELETE_WINDOW", False);
974 }
975 
976 
977 /*
978  * register_callbacks
979  *	Top-level function to register all callback routines.
980  *
981  * Args:
982  *	m - Pointer to the main widgets structure
983  *
984  * Return:
985  *	Nothing
986  */
987 void
register_callbacks(widgets_t * m)988 register_callbacks(widgets_t *m)
989 {
990 	int	i;
991 
992 	/*
993 	 * Main window callbacks
994 	 */
995 
996 	/* Callbacks for each control group */
997 	for (i = 0; i < maxdevs; i++) {
998 		if (!slinfo[i].supp)
999 			continue;
1000 
1001 		/* Left Slider callbacks */
1002 		XtAddCallback(slinfo[i].widget_l,
1003 			XmNvalueChangedCallback,
1004 			(XtCallbackProc) mx_slider_l, (XtPointer) i
1005 		);
1006 		XtAddCallback(slinfo[i].widget_l,
1007 			XmNdragCallback,
1008 			(XtCallbackProc) mx_slider_l, (XtPointer) i
1009 		);
1010 
1011 		/* Right Slider callbacks */
1012 		XtAddCallback(slinfo[i].widget_r,
1013 			XmNvalueChangedCallback,
1014 			(XtCallbackProc) mx_slider_r, (XtPointer) i
1015 		);
1016 		XtAddCallback(slinfo[i].widget_r,
1017 			XmNdragCallback,
1018 			(XtCallbackProc) mx_slider_r, (XtPointer) i
1019 		);
1020 
1021 		/* Lock button callback */
1022 		XtAddCallback(slinfo[i].widget_lock_btn,
1023 			XmNvalueChangedCallback,
1024 			(XtCallbackProc) mx_lock_btn, (XtPointer) i
1025 		);
1026 
1027 		/* Rec button callback */
1028 		if (slinfo[i].recsupp) {
1029 			XtAddCallback(slinfo[i].widget_rec_btn,
1030 				XmNvalueChangedCallback,
1031 				(XtCallbackProc) mx_rec_btn, (XtPointer) i
1032 			);
1033 		}
1034 	}
1035 
1036 	/* Flat button callback */
1037 	if (slinfo[SOUND_MIXER_BASS].supp || slinfo[SOUND_MIXER_TREBLE].supp) {
1038 		XtAddCallback(m->flat_btn,
1039 			XmNactivateCallback,
1040 			(XtCallbackProc) mx_flat_btn, NULL
1041 		);
1042 	}
1043 
1044 	/* Mute button callback */
1045 	if (m->mute_supp) {
1046 		XtAddCallback(m->mute_btn,
1047 			XmNvalueChangedCallback,
1048 			(XtCallbackProc) mx_mute_btn, NULL
1049 		);
1050 	}
1051 
1052 	/* Loudness button callback */
1053 	if (m->loud_supp) {
1054 		XtAddCallback(m->loud_btn,
1055 			XmNvalueChangedCallback,
1056 			(XtCallbackProc) mx_loud_btn, NULL
1057 		);
1058 	}
1059 
1060 	/* Stereo enhance button callbacks */
1061 	if (m->enh_supp) {
1062 		for (i = 0; i < NENHANCE; i++) {
1063 			XtAddCallback(m->enh_btn[i],
1064 				XmNactivateCallback,
1065 				(XtCallbackProc) mx_enhance_btn, (XtPointer) i
1066 			);
1067 		}
1068 	}
1069 
1070 	/* Load button callback */
1071 	XtAddCallback(file_pd.btip[PD_FILE_LOAD].widget,
1072 		XmNactivateCallback,
1073 		(XtCallbackProc) mx_load, NULL
1074 	);
1075 
1076 	/* Save button callback */
1077 	XtAddCallback(file_pd.btip[PD_FILE_SAVE].widget,
1078 		XmNactivateCallback,
1079 		(XtCallbackProc) mx_save, NULL
1080 	);
1081 
1082 	/* Exit button callback */
1083 	XtAddCallback(file_pd.btip[PD_FILE_EXIT].widget,
1084 		XmNactivateCallback,
1085 		(XtCallbackProc) mx_exit, NULL
1086 	);
1087 
1088 	/* Reset button callback */
1089 	XtAddCallback(opts_pd.btip[PD_OPTS_RESET].widget,
1090 		XmNactivateCallback,
1091 		(XtCallbackProc) mx_reset, NULL
1092 	);
1093 
1094 	/* Man Page button callback */
1095 	XtAddCallback(help_pd.btip[PD_HELP_MANPG].widget,
1096 		XmNactivateCallback,
1097 		(XtCallbackProc) mx_manpg, NULL
1098 	);
1099 
1100 	/* About button callback */
1101 	XtAddCallback(help_pd.btip[PD_HELP_ABOUT].widget,
1102 		XmNactivateCallback,
1103 		(XtCallbackProc) mx_about, NULL
1104 	);
1105 
1106 	/*
1107 	 * File Selection Box callbacks
1108 	 */
1109 
1110 	/* OK button callback */
1111 	XtAddCallback(m->fsbox,
1112 		XmNokCallback,
1113 		(XtCallbackProc) mx_fsok_btn, NULL
1114 	);
1115 
1116 	/* Cancel button callback */
1117 	XtAddCallback(m->fsbox,
1118 		XmNcancelCallback,
1119 		(XtCallbackProc) mx_fscancel_btn, NULL
1120 	);
1121 
1122 	/*
1123 	 * Focus change callback
1124 	 */
1125 	XtAddCallback(m->form,
1126 		XmNfocusCallback,
1127 		(XtCallbackProc) mx_focuschg, (XtPointer) m->form
1128 	);
1129 
1130 	/*
1131 	 * Install WM_DELETE_WINDOW handler
1132 	 */
1133 	XmAddWMProtocolCallback(
1134 		m->toplevel,
1135 		delw,
1136 		(XtCallbackProc) mx_exit, (XtPointer) NULL
1137 	);
1138 }
1139 
1140 
1141