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