1/*
2 * $XConsortium: bbox.c,v 2.35 91/07/10 19:34:59 converse Exp $
3 *
4 *
5 *			COPYRIGHT 1987, 1989
6 *		   DIGITAL EQUIPMENT CORPORATION
7 *		       MAYNARD, MASSACHUSETTS
8 *			ALL RIGHTS RESERVED.
9 *
10 * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
11 * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
12 * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
13 * ANY PURPOSE.  IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
14 *
15 * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT
16 * RIGHTS, APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN
17 * ADDITION TO THAT SET FORTH ABOVE.
18 *
19 * Permission to use, copy, modify, and distribute this software and its
20 * documentation for any purpose and without fee is hereby granted, provided
21 * that the above copyright notice appear in all copies and that both that
22 * copyright notice and this permission notice appear in supporting
23 * documentation, and that the name of Digital Equipment Corporation not be
24 * used in advertising or publicity pertaining to distribution of the software
25 * without specific, written prior permission.
26 */
27/* $XFree86: xc/programs/xmh/bbox.c,v 1.2 2001/10/28 03:34:38 tsi Exp $ */
28
29/* bbox.c -- management of buttons and buttonboxes.
30 *
31 * This module implements a simple interface to buttonboxes, allowing a client
32 * to create new buttonboxes and manage their contents.
33 */
34
35#include "xmh.h"
36#include "bboxint.h"
37
38static XtTranslations	RadioButtonTranslations = NULL;
39
40
41void BBoxInit(void)
42{
43    RadioButtonTranslations =
44	XtParseTranslationTable("<Btn1Down>,<Btn1Up>:set()\n");
45}
46
47
48/*
49 * Create a new button box.  The widget for it will be a child of the given
50 * scrn's widget, and it will be added to the scrn's pane.
51 */
52
53ButtonBox BBoxCreate(
54    Scrn	scrn,
55    const char	*name)	/* name of the buttonbox widgets */
56{
57    Cardinal	n;
58    ButtonBox	buttonbox = XtNew(ButtonBoxRec);
59    Arg		args[5];
60
61    n = 0;
62    XtSetArg(args[n], XtNallowVert, True);	n++;
63    XtSetArg(args[n], XtNskipAdjust, True);	n++;
64
65    buttonbox->outer =
66	XtCreateManagedWidget(name, viewportWidgetClass, scrn->widget,
67			      args, n);
68    buttonbox->inner =
69	XtCreateManagedWidget(name, boxWidgetClass, buttonbox->outer,
70			      args, (Cardinal) 0);
71    buttonbox->numbuttons = 0;
72    buttonbox->button = (Button *) NULL;
73    buttonbox->scrn = scrn;
74    return buttonbox;
75}
76
77
78ButtonBox RadioBBoxCreate(
79    Scrn	scrn,
80    const char	*name)	/* name of the buttonbox widgets */
81{
82    return BBoxCreate(scrn, name);
83}
84
85
86/* Create a new button, and add it to a buttonbox. */
87
88static void bboxAddButton(
89    ButtonBox	buttonbox,
90    const char	*name,
91    WidgetClass	kind,
92    Boolean	enabled,
93    Boolean	radio)
94{
95    Button	button;
96    Cardinal	i;
97    Widget	radio_group;
98    Arg		args[5];
99
100    buttonbox->numbuttons++;
101    buttonbox->button = XtReallocArray(buttonbox->button,
102                                       buttonbox->numbuttons, sizeof(Button));
103    button = buttonbox->button[buttonbox->numbuttons - 1] = XtNew(ButtonRec);
104    button->buttonbox = buttonbox;
105    button->name = XtNewString(name);
106    button->menu = (Widget) NULL;
107
108    i = 0;
109    if (!enabled) {
110	XtSetArg(args[i], XtNsensitive, False);		i++;
111    }
112
113    if (radio && kind == toggleWidgetClass) {
114	if (buttonbox->numbuttons > 1)
115	    radio_group = (button == buttonbox->button[0])
116		? (buttonbox->button[1]->widget)
117		: (buttonbox->button[0]->widget);
118	else radio_group = NULL;
119	XtSetArg(args[i], XtNradioGroup, radio_group);		i++;
120	XtSetArg(args[i], XtNradioData, button->name);		i++;
121    }
122
123    /* Prevent the folder buttons from picking up labels from resources */
124
125    if (buttonbox == buttonbox->scrn->folderbuttons) {
126	XtSetArg(args[i], XtNlabel, button->name);	i++;
127    }
128
129    button->widget =
130	XtCreateManagedWidget(name, kind, buttonbox->inner, args, i);
131
132    if (radio)
133	XtOverrideTranslations(button->widget, RadioButtonTranslations);
134}
135
136
137void BBoxAddButton(
138    ButtonBox	buttonbox,
139    const char	*name,
140    WidgetClass	kind,
141    Boolean	enabled)
142{
143    bboxAddButton(buttonbox, name, kind, enabled, False);
144}
145
146
147void RadioBBoxAddButton(
148    ButtonBox	buttonbox,
149    const char	*name,
150    Boolean	enabled)
151{
152    bboxAddButton(buttonbox, name, toggleWidgetClass, enabled, True);
153}
154
155
156/* Set the current button in a radio buttonbox. */
157
158void RadioBBoxSet(
159    Button button)
160{
161    XawToggleSetCurrent(button->widget, button->name);
162}
163
164
165/* Get the name of the current button in a radio buttonbox. */
166
167char *RadioBBoxGetCurrent(
168    ButtonBox buttonbox)
169{
170    return ((char *) XawToggleGetCurrent(buttonbox->button[0]->widget));
171}
172
173
174/* Remove the given button from its buttonbox, and free all resources
175 * used in association with the button.  If the button was the current
176 * button in a radio buttonbox, the current button becomes the first
177 * button in the box.
178 */
179
180void BBoxDeleteButton(
181    Button	button)
182{
183    ButtonBox	buttonbox;
184    int		i, found;
185
186    if (button == NULL) return;
187    buttonbox = button->buttonbox;
188    found = False;
189
190    for (i=0 ; i<buttonbox->numbuttons; i++) {
191	if (found)
192	    buttonbox->button[i-1] = buttonbox->button[i];
193	else if (buttonbox->button[i] == button) {
194	    found = True;
195
196	    /* Free the resources used by the given button. */
197
198	    if (button->menu != NULL && button->menu != NoMenuForButton)
199		XtDestroyWidget(button->menu);
200	    XtDestroyWidget(button->widget);
201	    XtFree(button->name);
202	    XtFree((char *) button);
203	}
204    }
205    if (found)
206	buttonbox->numbuttons--;
207}
208
209
210void RadioBBoxDeleteButton(
211    Button	button)
212{
213    ButtonBox	buttonbox;
214    Boolean	reradio = False;
215    char *	current;
216
217    if (button == NULL) return;
218    buttonbox = button->buttonbox;
219    current = RadioBBoxGetCurrent(buttonbox);
220    if (current) reradio = ! strcmp(current, button->name);
221    BBoxDeleteButton(button);
222
223    if (reradio && BBoxNumButtons(buttonbox))
224	RadioBBoxSet(buttonbox->button[0]);
225}
226
227
228/* Enable or disable the given button widget. */
229
230static void SendEnableMsg(
231    Widget	widget,
232    int		value)	/* TRUE for enable, FALSE for disable. */
233{
234    static Arg arglist[] = {{XtNsensitive, (XtArgVal)False}};
235    arglist[0].value = (XtArgVal) value;
236    XtSetValues(widget, arglist, XtNumber(arglist));
237}
238
239
240/* Enable the given button (if it's not already). */
241
242void BBoxEnable(
243    Button button)
244{
245    SendEnableMsg(button->widget, True);
246}
247
248
249/* Disable the given button (if it's not already). */
250
251void BBoxDisable(
252    Button button)
253{
254    SendEnableMsg(button->widget, False);
255}
256
257
258/* Given a buttonbox and a button name, find the button in the box with that
259   name. */
260
261Button BBoxFindButtonNamed(
262    ButtonBox buttonbox,
263    const char *name)
264{
265    register int i;
266    for (i=0 ; i<buttonbox->numbuttons; i++)
267	if (strcmp(name, buttonbox->button[i]->name) == 0)
268	    return buttonbox->button[i];
269    return (Button) NULL;
270}
271
272
273/* Given a buttonbox and a widget, find the button which is that widget. */
274
275Button BBoxFindButton(
276    ButtonBox	buttonbox,
277    Widget	w)
278{
279    register int i;
280    for (i=0; i < buttonbox->numbuttons; i++)
281	if (buttonbox->button[i]->widget == w)
282	    return buttonbox->button[i];
283    return (Button) NULL;
284}
285
286
287/* Return the nth button in the given buttonbox. */
288
289Button BBoxButtonNumber(
290    ButtonBox buttonbox,
291    int n)
292{
293    return buttonbox->button[n];
294}
295
296
297/* Return how many buttons are in a buttonbox. */
298
299int BBoxNumButtons(
300    ButtonBox buttonbox)
301{
302    return buttonbox->numbuttons;
303}
304
305
306/* Given a button, return its name. */
307
308char *BBoxNameOfButton(
309    Button button)
310{
311    return button->name;
312}
313
314
315/* Given a button, return its menu. */
316
317Widget	BBoxMenuOfButton(
318    Button button)
319{
320    return button->menu;
321}
322
323
324/* Set maximum size for a bbox so that it cannot be resized any taller
325 * than the space needed to stack all the buttons on top of each other.
326 * Allow the user to set the minimum size.
327 */
328
329void BBoxLockSize(
330    ButtonBox buttonbox)
331{
332    Dimension	maxheight;
333    Arg		args[1];
334
335    if (buttonbox == NULL) return;
336    maxheight = (Dimension) GetHeight(buttonbox->inner);
337    XtSetArg(args[0], XtNmax, maxheight);	/* for Paned widget */
338    XtSetValues(buttonbox->outer, args, (Cardinal) 1);
339}
340
341
342Boolean BBoxIsGrandparent(
343    ButtonBox	buttonbox,
344    Widget	widget)
345{
346    return (XtParent(XtParent(widget)) == buttonbox->inner);
347}
348
349
350void BBoxMailFlag(
351    ButtonBox	buttonbox,
352    const char*	name,
353    int		up)
354{
355    Arg		args[1];
356    Pixel	flag;
357    Button	button = BBoxFindButtonNamed(buttonbox, name);
358
359    if (button) {
360	/* avoid unnecessary exposures */
361	XtSetArg(args[0], XtNleftBitmap, &flag);
362	XtGetValues(button->widget, args, (Cardinal)1);
363	if (up && flag != app_resources.flag_up) {
364	    XtSetArg(args[0], XtNleftBitmap, app_resources.flag_up);
365	    XtSetValues(button->widget, args, (Cardinal)1);
366	}
367	else if (!up && flag != app_resources.flag_down) {
368	    XtSetArg(args[0], XtNleftBitmap, app_resources.flag_down);
369	    XtSetValues(button->widget, args, (Cardinal)1);
370	}
371    }
372}
373