#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xmu/Converters.h>
#include <X11/Xmu/Misc.h>
#include <X11/Xmu/SysUtil.h>
#include <X11/Xaw/ToggleP.h>
#include <X11/Xaw/XawInit.h>
static void XawToggleClassInitialize(void);
static void XawToggleInitialize(Widget, Widget, ArgList, Cardinal*);
static Boolean XawToggleSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
static void AddToRadioGroup(RadioGroup*, Widget);
static void CreateRadioGroup(Widget, Widget);
static RadioGroup *GetRadioGroup(Widget);
static void RemoveFromRadioGroup(Widget);
static void TurnOffRadioSiblings(Widget);
static void XawToggleDestroy(Widget, XtPointer, XtPointer);
static void Notify(Widget, XEvent*, String*, Cardinal*);
static void Toggle(Widget, XEvent*, String*, Cardinal*);
static void ToggleSet(Widget, XEvent*, String*, Cardinal*);
static char defaultTranslations[] =
"<Enter>:" "highlight(Always)\n"
"<Leave>:" "unhighlight()\n"
"<Btn1Down>,<Btn1Up>:" "toggle() notify()\n"
;
#define offset(field) XtOffsetOf(ToggleRec, field)
static XtResource resources[] = {
{
XtNstate,
XtCState,
XtRBoolean,
sizeof(Boolean),
offset(command.set),
XtRString,
"off"
},
{
XtNradioGroup,
XtCWidget,
XtRWidget,
sizeof(Widget),
offset(toggle.widget),
XtRWidget,
NULL
},
{
XtNradioData,
XtCRadioData,
XtRPointer,
sizeof(XtPointer),
offset(toggle.radio_data),
XtRPointer,
NULL
},
};
#undef offset
static XtActionsRec actionsList[] = {
{"toggle", Toggle},
{"notify", Notify},
{"set", ToggleSet},
};
#define Superclass ((CommandWidgetClass)&commandClassRec)
ToggleClassRec toggleClassRec = {
{
(WidgetClass)Superclass,
"Toggle",
sizeof(ToggleRec),
XawToggleClassInitialize,
NULL,
False,
XawToggleInitialize,
NULL,
XtInheritRealize,
actionsList,
XtNumber(actionsList),
resources,
XtNumber(resources),
NULLQUARK,
False,
True,
True,
False,
NULL,
XtInheritResize,
XtInheritExpose,
XawToggleSetValues,
NULL,
XtInheritSetValuesAlmost,
NULL,
NULL,
XtVersion,
NULL,
defaultTranslations,
XtInheritQueryGeometry,
XtInheritDisplayAccelerator,
NULL,
},
{
XtInheritChangeSensitive,
},
{
NULL,
},
{
NULL,
},
{
NULL,
NULL,
NULL,
}
};
WidgetClass toggleWidgetClass = (WidgetClass)&toggleClassRec;
static void
XawToggleClassInitialize(void)
{
XtActionList actions;
Cardinal num_actions;
Cardinal i;
ToggleWidgetClass cclass = (ToggleWidgetClass)toggleWidgetClass;
static XtConvertArgRec parentCvtArgs[] = {
{XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent),
sizeof(Widget)}
};
XawInitializeWidgetSet();
XtSetTypeConverter(XtRString, XtRWidget, XmuNewCvtStringToWidget,
parentCvtArgs, XtNumber(parentCvtArgs),
XtCacheNone, NULL);
XtSetTypeConverter(XtRWidget, XtRString, XmuCvtWidgetToString,
NULL, 0, XtCacheNone, NULL);
XtGetActionList(commandWidgetClass, &actions, &num_actions);
for (i = 0 ; i < num_actions ; i++) {
if (streq(actions[i].string, "set"))
cclass->toggle_class.Set = actions[i].proc;
if (streq(actions[i].string, "unset"))
cclass->toggle_class.Unset = actions[i].proc;
if (cclass->toggle_class.Set != NULL &&
cclass->toggle_class.Unset != NULL) {
XtFree((char *)actions);
return;
}
}
XtError("Aborting, due to errors resolving bindings in the Toggle widget.");
}
static void
XawToggleInitialize(Widget request, Widget cnew,
ArgList args, Cardinal *num_args)
{
ToggleWidget tw = (ToggleWidget)cnew;
ToggleWidget tw_req = (ToggleWidget)request;
tw->toggle.radio_group = NULL;
if (tw->toggle.radio_data == NULL)
tw->toggle.radio_data = (XtPointer)cnew->core.name;
if (tw->toggle.widget != NULL) {
if (GetRadioGroup(tw->toggle.widget) == NULL)
CreateRadioGroup(cnew, tw->toggle.widget);
else
AddToRadioGroup(GetRadioGroup(tw->toggle.widget), cnew);
}
XtAddCallback(cnew, XtNdestroyCallback, XawToggleDestroy, NULL);
if (tw_req->command.set)
ToggleSet(cnew, NULL, NULL, NULL);
}
static void
ToggleSet(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
ToggleWidgetClass cclass = (ToggleWidgetClass)w->core.widget_class;
TurnOffRadioSiblings(w);
cclass->toggle_class.Set(w, event, NULL, NULL);
}
static void
Toggle(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
ToggleWidget tw = (ToggleWidget)w;
ToggleWidgetClass cclass = (ToggleWidgetClass)w->core.widget_class;
if (tw->command.set)
cclass->toggle_class.Unset(w, event, NULL, NULL);
else
ToggleSet(w, event, params, num_params);
}
static void
Notify(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
ToggleWidget tw = (ToggleWidget)w;
long antilint = tw->command.set;
XtCallCallbacks(w, XtNcallback, (XtPointer)antilint);
}
static Boolean
XawToggleSetValues(Widget current, Widget request, Widget cnew,
ArgList args, Cardinal *num_args)
{
ToggleWidget oldtw = (ToggleWidget)current;
ToggleWidget tw = (ToggleWidget)cnew;
ToggleWidget rtw = (ToggleWidget)request;
if (oldtw->toggle.widget != tw->toggle.widget)
XawToggleChangeRadioGroup(cnew, tw->toggle.widget);
if (!tw->core.sensitive && oldtw->core.sensitive && rtw->command.set)
tw->command.set = True;
if (oldtw->command.set != tw->command.set) {
tw->command.set = oldtw->command.set;
Toggle(cnew, NULL, NULL, NULL);
}
return (False);
}
static void
XawToggleDestroy(Widget w, XtPointer temp1, XtPointer temp2)
{
RemoveFromRadioGroup(w);
}
static RadioGroup *
GetRadioGroup(Widget w)
{
ToggleWidget tw = (ToggleWidget)w;
if (tw == NULL)
return (NULL);
return (tw->toggle.radio_group);
}
static void
CreateRadioGroup(Widget w1, Widget w2)
{
ToggleWidget tw1 = (ToggleWidget)w1;
ToggleWidget tw2 = (ToggleWidget) w2;
if (tw1->toggle.radio_group != NULL || tw2->toggle.radio_group != NULL)
XtAppWarning(XtWidgetToApplicationContext(w1),
"Toggle Widget Error - Attempting to create a "
"new toggle group, when one already exists.");
AddToRadioGroup(NULL, w1);
AddToRadioGroup(GetRadioGroup(w1), w2);
}
static void
AddToRadioGroup(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) {
group = local;
group->next = NULL;
group->prev = NULL;
return;
}
local->prev = group;
if ((local->next = group->next) != NULL)
local->next->prev = local;
group->next = local;
}
static void
TurnOffRadioSiblings(Widget w)
{
RadioGroup *group;
ToggleWidgetClass cclass = (ToggleWidgetClass)w->core.widget_class;
if ((group = GetRadioGroup(w)) == NULL)
return;
for (; group->prev != NULL ; group = group->prev)
;
while (group != NULL) {
ToggleWidget local_tog = (ToggleWidget)group->widget;
if (local_tog->command.set) {
cclass->toggle_class.Unset(group->widget, NULL, NULL, NULL);
Notify(group->widget, NULL, NULL, NULL);
}
group = group->next;
}
}
static void
RemoveFromRadioGroup(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((char *)group);
}
}
void
XawToggleChangeRadioGroup(Widget w, Widget radio_group)
{
ToggleWidget tw = (ToggleWidget)w;
RadioGroup *group;
RemoveFromRadioGroup(w);
if (tw->command.set && radio_group != NULL)
XawToggleUnsetCurrent(radio_group);
if (radio_group != NULL) {
if ((group = GetRadioGroup(radio_group)) == NULL)
CreateRadioGroup(w, radio_group);
else
AddToRadioGroup(group, w);
}
}
XtPointer
XawToggleGetCurrent(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);
}
void
XawToggleSetCurrent(Widget radio_group, XtPointer radio_data)
{
RadioGroup *group;
ToggleWidget local_tog;
if ((group = GetRadioGroup(radio_group)) == NULL) {
local_tog = (ToggleWidget)radio_group;
if (local_tog->toggle.radio_data == radio_data &&
!local_tog->command.set) {
ToggleSet(radio_group, NULL, NULL, NULL);
Notify(radio_group, NULL, NULL, NULL);
}
return;
}
for (; group->prev != NULL ; group = group->prev)
;
while (group != NULL) {
local_tog = (ToggleWidget)group->widget;
if (local_tog->toggle.radio_data == radio_data) {
if (!local_tog->command.set) {
ToggleSet(group->widget, NULL, NULL, NULL);
Notify(group->widget, NULL, NULL, NULL);
}
return;
}
group = group->next;
}
}
void
XawToggleUnsetCurrent(Widget radio_group)
{
ToggleWidgetClass cclass;
ToggleWidget local_tog = (ToggleWidget)radio_group;
if (local_tog->command.set) {
cclass = (ToggleWidgetClass)local_tog->core.widget_class;
cclass->toggle_class.Unset(radio_group, NULL, NULL, NULL);
Notify(radio_group, NULL, NULL, NULL);
}
if (GetRadioGroup(radio_group) == NULL)
return;
TurnOffRadioSiblings(radio_group);
}