561N/A#ifndef lint
561N/Astatic char Xrcsid[] = "$XConsortium: Toggle.c,v 1.15 89/12/11 15:22:59 kit Exp $";
911N/A#endif /* lint */
837N/A
561N/A/*
561N/A * Copyright 1989 Massachusetts Institute of Technology
919N/A *
919N/A * Permission to use, copy, modify, distribute, and sell this software and its
919N/A * documentation for any purpose is hereby granted without fee, provided that
919N/A * the above copyright notice appear in all copies and that both that
919N/A * copyright notice and this permission notice appear in supporting
919N/A * documentation, and that the name of M.I.T. not be used in advertising or
919N/A * publicity pertaining to distribution of the software without specific,
919N/A * written prior permission. M.I.T. makes no representations about the
919N/A * suitability of this software for any purpose. It is provided "as is"
919N/A * without express or implied warranty.
919N/A *
919N/A * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
919N/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
919N/A * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
919N/A * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
919N/A * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
919N/A * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
561N/A *
561N/A */
561N/A
561N/A/*
561N/A * Toggle.c - Toggle button widget
561N/A *
561N/A * Author: Chris D. Peterson
837N/A * MIT X Consortium
561N/A * kit@expo.lcs.mit.edu
911N/A *
911N/A * Date: January 12, 1989
911N/A *
911N/A */
561N/A
561N/A#include <stdio.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <./Xaw3_1XawInit.h>
#include <X11/Xmu/Misc.h>
#include <./Xaw3_1ToggleP.h>
/****************************************************************
*
* Full class record constant
*
****************************************************************/
/* Private Data */
/* This is a hack, see the comments in ClassInit(). */
extern XtActionList xaw_command_actions_list;
/*
* The order of toggle and notify are important, as the state has
* to be set when we call the notify proc.
*/
static char defaultTranslations[] =
"<EnterWindow>: highlight(Always) \n\
<LeaveWindow>: unhighlight() \n\
<Btn1Down>,<Btn1Up>: toggle() notify()";
#define offset(field) XtOffset(ToggleWidget, field)
static XtResource resources[] = {
{XtNstate, XtCState, XtRBoolean, sizeof(Boolean),
offset(command.set), XtRString, "off"},
{XtNradioGroup, XtCWidget, XtRWidget, sizeof(Widget),
offset(toggle.widget), XtRWidget, (caddr_t) NULL },
{XtNradioData, XtCRadioData, XtRPointer, sizeof(caddr_t),
offset(toggle.radio_data), XtRPointer, (caddr_t) NULL },
};
#undef offset
/* Action proceedures retrieved from the command widget */
static void Toggle(), Initialize(), Notify(), ToggleSet();
static void ToggleDestroy(), ClassInit();
static Boolean SetValues();
/* Functions for handling the Radio Group. */
static RadioGroup * GetRadioGroup();
static void CreateRadioGroup(), AddToRadioGroup(), TurnOffRadioSiblings();
static void RemoveFromRadioGroup();
static XtActionsRec actionsList[] =
{
{"toggle", Toggle},
{"notify", Notify},
{"set", ToggleSet},
};
#define SuperClass ((CommandWidgetClass)&commandClassRec)
ToggleClassRec toggleClassRec = {
{
(WidgetClass) SuperClass, /* superclass */
"Toggle", /* class_name */
sizeof(ToggleRec), /* size */
ClassInit, /* class_initialize */
NULL, /* class_part_initialize */
FALSE, /* class_inited */
Initialize, /* initialize */
NULL, /* initialize_hook */
XtInheritRealize, /* realize */
actionsList, /* actions */
XtNumber(actionsList), /* num_actions */
resources, /* resources */
XtNumber(resources), /* resource_count */
NULLQUARK, /* xrm_class */
FALSE, /* compress_motion */
TRUE, /* compress_exposure */
TRUE, /* compress_enterleave */
FALSE, /* visible_interest */
NULL, /* destroy */
XtInheritResize, /* resize */
XtInheritExpose, /* expose */
SetValues, /* set_values */
NULL, /* set_values_hook */
XtInheritSetValuesAlmost, /* set_values_almost */
NULL, /* get_values_hook */
NULL, /* accept_focus */
XtVersion, /* version */
NULL, /* callback_private */
defaultTranslations, /* tm_table */
XtInheritQueryGeometry, /* query_geometry */
XtInheritDisplayAccelerator, /* display_accelerator */
NULL /* extension */
}, /* CoreClass fields initialization */
{
XtInheritChangeSensitive /* change_sensitive */
}, /* SimpleClass fields initialization */
{
0 /* field not used */
}, /* LabelClass fields initialization */
{
0 /* field not used */
}, /* CommmandClass fields initialization */
{
NULL, /* Set Proceedure. */
NULL, /* Unset Proceedure. */
NULL /* extension. */
} /* ToggleClass fields initialization */
};
/* for public consumption */
WidgetClass toggleWidgetClass = (WidgetClass) &toggleClassRec;
/****************************************************************
*
* Private Procedures
*
****************************************************************/
static void
ClassInit()
{
XtActionList actions;
Cardinal i;
ToggleWidgetClass class = (ToggleWidgetClass) toggleWidgetClass;
XawInitializeWidgetSet();
/* actions = SuperClass->core_class.actions; */
/* The actions table should really be retrieved from the toggle widget's
* Superclass, but this information is munged by the R3 intrinsics so the
* I have hacked the Athena command widget to export its action table
* as a global variable.
*
* Chris D. Peterson 12/28/88.
*/
actions = xaw_command_actions_list;
/*
* Find the set and unset actions in the command widget's action table.
*/
for (i = 0 ; i < SuperClass->core_class.num_actions ; i++) {
if (streq(actions[i].string, "set"))
class->toggle_class.Set = actions[i].proc;
if (streq(actions[i].string, "unset"))
class->toggle_class.Unset = actions[i].proc;
if ( (class->toggle_class.Set != NULL) &&
(class->toggle_class.Unset != NULL) ) return;
}
/* We should never get here. */
if (class->toggle_class.Set == NULL)
XtWarning(
"Toggle could not find action Proceedure Set() in the Command Widget.");
if (class->toggle_class.Unset == NULL)
XtWarning(
"Toggle could not find action Proceedure Unset() in the Command Widget.");
XtError("Aborting, due to errors in Toggle widget.");
}
static void Initialize(request, new)
Widget request, new;
{
ToggleWidget tw = (ToggleWidget) new;
ToggleWidget tw_req = (ToggleWidget) request;
tw->toggle.radio_group = NULL;
if (tw->toggle.radio_data == NULL)
tw->toggle.radio_data = (caddr_t) new->core.name;
if (tw->toggle.widget != NULL) {
if ( GetRadioGroup(tw->toggle.widget) == NULL)
CreateRadioGroup(new, tw->toggle.widget);
else
AddToRadioGroup( GetRadioGroup(tw->toggle.widget), new);
}
XtAddCallback(new, XtNdestroyCallback, ToggleDestroy, NULL);
/*
* Command widget assumes that the widget is unset, so we only
* have to handle the case where it needs to be set.
*
* If this widget is in a radio group then it may cause another
* widget to be unset, thus calling the notify proceedure.
*
* I want to set the toggle if the user set the state to "On" in
* the resource group, reguardless of what my ancestors did.
*/
if (tw_req->command.set)
ToggleSet(new, NULL, NULL, 0);
}
/************************************************************
*
* Action Procedures
*
************************************************************/
/* ARGSUSED */
static void
ToggleSet(w,event,params,num_params)
Widget w;
XEvent *event;
String *params; /* unused */
Cardinal *num_params; /* unused */
{
ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class;
TurnOffRadioSiblings(w);
class->toggle_class.Set(w, event, NULL, 0);
}
/* ARGSUSED */
static void
Toggle(w,event,params,num_params)
Widget w;
XEvent *event;
String *params; /* unused */
Cardinal *num_params; /* unused */
{
ToggleWidget tw = (ToggleWidget)w;
ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class;
if (tw->command.set)
class->toggle_class.Unset(w, event, NULL, 0);
else
ToggleSet(w, event, params, num_params);
}
/* ARGSUSED */
static void Notify(w,event,params,num_params)
Widget w;
XEvent *event;
String *params; /* unused */
Cardinal *num_params; /* unused */
{
ToggleWidget tw = (ToggleWidget) w;
XtCallCallbacks(w, XtNcallback, tw->command.set);
}
/************************************************************
*
* Set specified arguments into widget
*
***********************************************************/
/* ARGSUSED */
static Boolean
SetValues (current, request, new)
Widget current, request, new;
{
ToggleWidget oldtw = (ToggleWidget) current;
ToggleWidget tw = (ToggleWidget) new;
if (oldtw->toggle.widget != tw->toggle.widget)
XawToggleChangeRadioGroup(new, tw->toggle.widget);
if (oldtw->command.set != tw->command.set) {
tw->command.set = oldtw->command.set;
Toggle(new, NULL, NULL, 0); /* Does a redisplay. */
}
return(FALSE);
}
/* Function Name: ToggleDestroy
* Description: Destroy Callback for toggle widget.
* Arguments: w - the toggle widget that is being destroyed.
* junk, grabage - not used.
* Returns: none.
*/
/* ARGSUSED */
static void
ToggleDestroy(w, junk, garbage)
Widget w;
caddr_t junk, garbage;
{
RemoveFromRadioGroup(w);
}
/************************************************************
*
* Below are all the private proceedures that handle
* radio toggle buttons.
*
************************************************************/
/* Function Name: GetRadioGroup
* Description: Gets the radio group associated with a give toggle
* widget.
* Arguments: w - the toggle widget who's radio group we are getting.
* Returns: the radio group associated with this toggle group.
*/
static RadioGroup *
GetRadioGroup(w)
Widget w;
{
ToggleWidget tw = (ToggleWidget) w;
if (tw == NULL) return(NULL);
return( tw->toggle.radio_group );
}
/* Function Name: CreateRadioGroup
* Description: Creates a radio group. give two widgets.
* Arguments: w1, w2 - the toggle widgets to add to the radio group.
* Returns: none.
*
* NOTE: A pointer to the group is added to each widget's radio_group
* field.
*/
static void
CreateRadioGroup(w1, w2)
Widget w1, w2;
{
char error_buf[BUFSIZ];
ToggleWidget tw1 = (ToggleWidget) w1;
ToggleWidget tw2 = (ToggleWidget) w2;
if ( (tw1->toggle.radio_group != NULL) || (tw2->toggle.radio_group != NULL) ) {
sprintf(error_buf, "%s %s", "Toggle Widget Error - Attempting",
"to create a new toggle group, when one already exists.");
XtWarning(error_buf);
}
AddToRadioGroup( NULL, w1 );
AddToRadioGroup( GetRadioGroup(w1), w2 );
}
/* Function Name: AddToRadioGroup
* Description: Adds a toggle to the radio group.
* Arguments: group - any element of the radio group the we are adding to.
* w - the new toggle widget to add to the group.
* Returns: none.
*/
static void
AddToRadioGroup(group, w)
RadioGroup * group;
Widget w;
{
ToggleWidget tw = (ToggleWidget) w;
RadioGroup * local;
local = (RadioGroup *) XtMalloc( sizeof(RadioGroup) );
local->widget = w;
tw->toggle.radio_group = local;
if (group == NULL) { /* Creating new group. */
group = local;
group->next = NULL;
group->prev = NULL;
return;
}
local->prev = group; /* Adding to previous group. */
if ((local->next = group->next) != NULL)
local->next->prev = local;
group->next = local;
}
/* Function Name: TurnOffRadioSiblings
* Description: Deactivates all radio siblings.
* Arguments: widget - a toggle widget.
* Returns: none.
*/
static void
TurnOffRadioSiblings(w)
Widget w;
{
RadioGroup * group;
ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class;
if ( (group = GetRadioGroup(w)) == NULL) /* Punt if there is no group */
return;
/* Go to the top of the group. */
for ( ; group->prev != NULL ; group = group->prev );
while ( group != NULL ) {
ToggleWidget local_tog = (ToggleWidget) group->widget;
if ( local_tog->command.set ) {
class->toggle_class.Unset(group->widget, NULL, NULL, 0);
Notify( group->widget, NULL, NULL, 0);
}
group = group->next;
}
}
/* Function Name: RemoveFromRadioGroup
* Description: Removes a toggle from a RadioGroup.
* Arguments: w - the toggle widget to remove.
* Returns: none.
*/
static void
RemoveFromRadioGroup(w)
Widget w;
{
RadioGroup * group = GetRadioGroup(w);
if (group != NULL) {
if (group->prev != NULL)
(group->prev)->next = group->next;
if (group->next != NULL)
(group->next)->prev = group->prev;
XtFree(group);
}
}
/************************************************************
*
* Public Routines
*
************************************************************/
/* Function Name: XawToggleChangeRadioGroup
* Description: Allows a toggle widget to change radio groups.
* Arguments: w - The toggle widget to change groups.
* radio_group - any widget in the new group.
* Returns: none.
*/
void
XawToggleChangeRadioGroup(w, radio_group)
Widget w, radio_group;
{
ToggleWidget tw = (ToggleWidget) w;
RemoveFromRadioGroup(w);
/*
* If the toggle that we are about to add is set then we will
* unset all toggles in the new radio group.
*/
if ( tw->command.set && radio_group != NULL )
XawToggleUnsetCurrent(radio_group);
AddToRadioGroup( GetRadioGroup(radio_group), w );
}
/* Function Name: XawToggleGetCurrent
* Description: Returns the RadioData associated with the toggle
* widget that is currently active in a toggle group.
* Arguments: w - any toggle widget in the toggle group.
* Returns: The XtNradioData associated with the toggle widget.
*/
caddr_t
XawToggleGetCurrent(w)
Widget w;
{
RadioGroup * group;
if ( (group = GetRadioGroup(w)) == NULL) return(NULL);
for ( ; group->prev != NULL ; group = group->prev);
while ( group != NULL ) {
ToggleWidget local_tog = (ToggleWidget) group->widget;
if ( local_tog->command.set )
return( local_tog->toggle.radio_data );
group = group->next;
}
return(NULL);
}
/* Function Name: XawToggleSetCurrent
* Description: Sets the Toggle widget associated with the
* radio_data specified.
* Arguments: radio_group - any toggle widget in the toggle group.
* radio_data - radio data of the toggle widget to set.
* Returns: none.
*/
void
XawToggleSetCurrent(radio_group, radio_data)
Widget radio_group;
caddr_t radio_data;
{
RadioGroup * group;
ToggleWidget local_tog;
/* Special case case of no radio group. */
if ( (group = GetRadioGroup(radio_group)) == NULL) {
local_tog = (ToggleWidget) radio_group;
if ( (local_tog->toggle.radio_data == radio_data) )
if (!local_tog->command.set) {
ToggleSet((Widget) local_tog, NULL, NULL, 0);
Notify((Widget) local_tog, NULL, NULL, 0);
}
return;
}
/*
* find top of radio_roup
*/
for ( ; group->prev != NULL ; group = group->prev);
/*
* search for matching radio data.
*/
while ( group != NULL ) {
local_tog = (ToggleWidget) group->widget;
if ( (local_tog->toggle.radio_data == radio_data) ) {
if (!local_tog->command.set) { /* if not already set. */
ToggleSet((Widget) local_tog, NULL, NULL, 0);
Notify((Widget) local_tog, NULL, NULL, 0);
}
return; /* found it, done */
}
group = group->next;
}
}
/* Function Name: XawToggleUnsetCurrent
* Description: Unsets all Toggles in the radio_group specified.
* Arguments: radio_group - any toggle widget in the toggle group.
* Returns: none.
*/
void
XawToggleUnsetCurrent(radio_group)
Widget radio_group;
{
ToggleWidgetClass class;
ToggleWidget local_tog = (ToggleWidget) radio_group;
/* Special Case no radio group. */
if (local_tog->command.set) {
class = (ToggleWidgetClass) local_tog->core.widget_class;
class->toggle_class.Unset(radio_group, NULL, NULL, 0);
Notify(radio_group, NULL, NULL, 0);
}
if ( GetRadioGroup(radio_group) == NULL) return;
TurnOffRadioSiblings(radio_group);
}