749N/A/* $XConsortium: Toggle.c,v 1.28 94/04/17 20:13:17 kaleb Exp $ */
749N/A
749N/A/*
749N/A
749N/ACopyright (c) 1989, 1994 X Consortium
749N/A
749N/APermission is hereby granted, free of charge, to any person obtaining a copy
749N/Aof this software and associated documentation files (the "Software"), to deal
749N/Ain the Software without restriction, including without limitation the rights
749N/Ato use, copy, modify, merge, publish, distribute, sublicense, and/or sell
749N/Acopies of the Software, and to permit persons to whom the Software is
749N/Afurnished to do so, subject to the following conditions:
749N/A
749N/AThe above copyright notice and this permission notice shall be included in
749N/Aall copies or substantial portions of the Software.
749N/A
749N/ATHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
749N/AIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
749N/AFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
749N/AX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
749N/AAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
749N/ACONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
749N/A
749N/AExcept as contained in this notice, the name of the X Consortium shall not be
749N/Aused in advertising or otherwise to promote the sale, use or other dealings
749N/Ain this Software without prior written authorization from the X Consortium.
749N/A
749N/A*/
749N/A
749N/A/*
749N/A * Toggle.c - Toggle button widget
749N/A *
749N/A * Author: Chris D. Peterson
749N/A * MIT X Consortium
749N/A * kit@expo.lcs.mit.edu
749N/A *
749N/A * Date: January 12, 1989
749N/A *
749N/A */
749N/A
749N/A#include <stdio.h>
749N/A
749N/A#include <X11/IntrinsicP.h>
749N/A#include <X11/StringDefs.h>
749N/A#include <X11/Xaw/XawInit.h>
749N/A#include <X11/Xmu/Converters.h>
749N/A#include <X11/Xmu/Misc.h>
749N/A#include <X11/Xaw/ToggleP.h>
749N/A
749N/A/****************************************************************
749N/A *
749N/A * Full class record constant
749N/A *
749N/A ****************************************************************/
749N/A
749N/A/* Private Data */
749N/A
749N/A/*
749N/A * The order of toggle and notify are important, as the state has
749N/A * to be set when we call the notify proc.
749N/A */
749N/A
749N/Astatic char defaultTranslations[] =
749N/A "<EnterWindow>: highlight(Always) \n\
749N/A <LeaveWindow>: unhighlight() \n\
749N/A <Btn1Down>,<Btn1Up>: toggle() notify()";
749N/A
749N/A#define offset(field) XtOffsetOf(ToggleRec, field)
749N/A
749N/Astatic XtResource resources[] = {
749N/A {XtNstate, XtCState, XtRBoolean, sizeof(Boolean),
749N/A offset(command.set), XtRString, "off"},
749N/A {XtNradioGroup, XtCWidget, XtRWidget, sizeof(Widget),
749N/A offset(toggle.widget), XtRWidget, (XtPointer) NULL },
749N/A {XtNradioData, XtCRadioData, XtRPointer, sizeof(XtPointer),
749N/A offset(toggle.radio_data), XtRPointer, (XtPointer) NULL },
749N/A};
749N/A
749N/A#undef offset
749N/A
749N/A
749N/Astatic void Toggle(), Initialize(), Notify(), ToggleSet();
749N/Astatic void ToggleDestroy(), ClassInit();
749N/Astatic Boolean SetValues();
749N/A
749N/A/* Functions for handling the Radio Group. */
749N/A
749N/Astatic RadioGroup * GetRadioGroup();
749N/Astatic void CreateRadioGroup(), AddToRadioGroup(), TurnOffRadioSiblings();
749N/Astatic void RemoveFromRadioGroup();
749N/A
749N/Astatic XtActionsRec actionsList[] =
749N/A{
749N/A {"toggle", Toggle},
749N/A {"notify", Notify},
749N/A {"set", ToggleSet},
749N/A};
749N/A
749N/A#define SuperClass ((CommandWidgetClass)&commandClassRec)
749N/A
749N/AToggleClassRec toggleClassRec = {
749N/A {
749N/A (WidgetClass) SuperClass, /* superclass */
749N/A "Toggle", /* class_name */
749N/A sizeof(ToggleRec), /* size */
749N/A ClassInit, /* class_initialize */
749N/A NULL, /* class_part_initialize */
749N/A FALSE, /* class_inited */
749N/A Initialize, /* initialize */
749N/A NULL, /* initialize_hook */
749N/A XtInheritRealize, /* realize */
749N/A actionsList, /* actions */
749N/A XtNumber(actionsList), /* num_actions */
749N/A resources, /* resources */
749N/A XtNumber(resources), /* resource_count */
749N/A NULLQUARK, /* xrm_class */
749N/A FALSE, /* compress_motion */
749N/A TRUE, /* compress_exposure */
749N/A TRUE, /* compress_enterleave */
749N/A FALSE, /* visible_interest */
749N/A NULL, /* destroy */
749N/A XtInheritResize, /* resize */
749N/A XtInheritExpose, /* expose */
749N/A SetValues, /* set_values */
749N/A NULL, /* set_values_hook */
749N/A XtInheritSetValuesAlmost, /* set_values_almost */
749N/A NULL, /* get_values_hook */
749N/A NULL, /* accept_focus */
749N/A XtVersion, /* version */
749N/A NULL, /* callback_private */
749N/A defaultTranslations, /* tm_table */
749N/A XtInheritQueryGeometry, /* query_geometry */
749N/A XtInheritDisplayAccelerator, /* display_accelerator */
749N/A NULL /* extension */
749N/A }, /* CoreClass fields initialization */
749N/A {
749N/A XtInheritChangeSensitive /* change_sensitive */
749N/A }, /* SimpleClass fields initialization */
749N/A {
749N/A 0 /* field not used */
749N/A }, /* LabelClass fields initialization */
749N/A {
749N/A 0 /* field not used */
749N/A }, /* CommandClass fields initialization */
749N/A {
749N/A NULL, /* Set Procedure. */
749N/A NULL, /* Unset Procedure. */
749N/A NULL /* extension. */
749N/A } /* ToggleClass fields initialization */
749N/A};
749N/A
749N/A /* for public consumption */
749N/AWidgetClass toggleWidgetClass = (WidgetClass) &toggleClassRec;
749N/A
749N/A/****************************************************************
749N/A *
749N/A * Private Procedures
749N/A *
749N/A ****************************************************************/
749N/A
749N/Astatic void
749N/AClassInit()
749N/A{
749N/A XtActionList actions;
749N/A Cardinal num_actions;
749N/A Cardinal i;
749N/A ToggleWidgetClass class = (ToggleWidgetClass) toggleWidgetClass;
749N/A static XtConvertArgRec parentCvtArgs[] = {
749N/A {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent),
749N/A sizeof(Widget)}
749N/A };
749N/A
749N/A XawInitializeWidgetSet();
749N/A XtSetTypeConverter(XtRString, XtRWidget, XmuNewCvtStringToWidget,
749N/A parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone,
749N/A (XtDestructor)NULL);
749N/A/*
749N/A * Find the set and unset actions in the command widget's action table.
749N/A */
749N/A
749N/A XtGetActionList(commandWidgetClass, &actions, &num_actions);
749N/A
749N/A for (i = 0 ; i < num_actions ; i++) {
749N/A if (streq(actions[i].string, "set"))
749N/A class->toggle_class.Set = actions[i].proc;
749N/A if (streq(actions[i].string, "unset"))
749N/A class->toggle_class.Unset = actions[i].proc;
749N/A
749N/A if ( (class->toggle_class.Set != NULL) &&
749N/A (class->toggle_class.Unset != NULL) ) {
749N/A XtFree((char *) actions);
749N/A return;
749N/A }
749N/A }
749N/A
749N/A/* We should never get here. */
749N/A XtError("Aborting, due to errors resolving bindings in the Toggle widget.");
749N/A}
749N/A
749N/A/*ARGSUSED*/
749N/Astatic void Initialize(request, new, args, num_args)
749N/A Widget request, new;
749N/A ArgList args;
749N/A Cardinal *num_args;
749N/A{
749N/A ToggleWidget tw = (ToggleWidget) new;
749N/A ToggleWidget tw_req = (ToggleWidget) request;
749N/A
749N/A tw->toggle.radio_group = NULL;
749N/A
749N/A if (tw->toggle.radio_data == NULL)
749N/A tw->toggle.radio_data = (XtPointer) new->core.name;
749N/A
749N/A if (tw->toggle.widget != NULL) {
749N/A if ( GetRadioGroup(tw->toggle.widget) == NULL)
749N/A CreateRadioGroup(new, tw->toggle.widget);
749N/A else
749N/A AddToRadioGroup( GetRadioGroup(tw->toggle.widget), new);
749N/A }
749N/A XtAddCallback(new, XtNdestroyCallback, ToggleDestroy, (XtPointer)NULL);
749N/A
749N/A/*
749N/A * Command widget assumes that the widget is unset, so we only
749N/A * have to handle the case where it needs to be set.
749N/A *
749N/A * If this widget is in a radio group then it may cause another
749N/A * widget to be unset, thus calling the notify proceedure.
749N/A *
749N/A * I want to set the toggle if the user set the state to "On" in
749N/A * the resource group, reguardless of what my ancestors did.
749N/A */
749N/A
749N/A if (tw_req->command.set)
749N/A ToggleSet(new, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
749N/A}
749N/A
749N/A/************************************************************
749N/A *
749N/A * Action Procedures
749N/A *
749N/A ************************************************************/
749N/A
749N/A/* ARGSUSED */
749N/Astatic void
749N/AToggleSet(w,event,params,num_params)
749N/AWidget w;
749N/AXEvent *event;
749N/AString *params; /* unused */
749N/ACardinal *num_params; /* unused */
749N/A{
749N/A ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class;
749N/A
749N/A TurnOffRadioSiblings(w);
749N/A class->toggle_class.Set(w, event, NULL, 0);
749N/A}
749N/A
749N/A/* ARGSUSED */
749N/Astatic void
749N/AToggle(w,event,params,num_params)
749N/AWidget w;
749N/AXEvent *event;
749N/AString *params; /* unused */
749N/ACardinal *num_params; /* unused */
749N/A{
749N/A ToggleWidget tw = (ToggleWidget)w;
749N/A ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class;
749N/A
749N/A if (tw->command.set)
749N/A class->toggle_class.Unset(w, event, NULL, 0);
749N/A else
749N/A ToggleSet(w, event, params, num_params);
749N/A}
749N/A
749N/A/* ARGSUSED */
749N/Astatic void Notify(w,event,params,num_params)
749N/AWidget w;
749N/AXEvent *event;
749N/AString *params; /* unused */
749N/ACardinal *num_params; /* unused */
749N/A{
749N/A ToggleWidget tw = (ToggleWidget) w;
749N/A long antilint = tw->command.set;
749N/A
749N/A XtCallCallbacks( w, XtNcallback, (XtPointer) antilint );
749N/A}
749N/A
749N/A/************************************************************
749N/A *
749N/A * Set specified arguments into widget
749N/A *
749N/A ***********************************************************/
749N/A
749N/A/* ARGSUSED */
749N/Astatic Boolean
749N/ASetValues (current, request, new, args, num_args)
749N/AWidget current, request, new;
749N/AArgList args;
749N/ACardinal *num_args;
749N/A{
749N/A ToggleWidget oldtw = (ToggleWidget) current;
749N/A ToggleWidget tw = (ToggleWidget) new;
749N/A ToggleWidget rtw = (ToggleWidget) request;
749N/A
749N/A if (oldtw->toggle.widget != tw->toggle.widget)
749N/A XawToggleChangeRadioGroup(new, tw->toggle.widget);
749N/A
749N/A if (!tw->core.sensitive && oldtw->core.sensitive && rtw->command.set)
749N/A tw->command.set = True;
749N/A
749N/A if (oldtw->command.set != tw->command.set) {
749N/A tw->command.set = oldtw->command.set;
749N/A Toggle(new, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
749N/A }
749N/A return(FALSE);
749N/A}
749N/A
749N/A/* Function Name: ToggleDestroy
749N/A * Description: Destroy Callback for toggle widget.
749N/A * Arguments: w - the toggle widget that is being destroyed.
749N/A * junk, grabage - not used.
749N/A * Returns: none.
749N/A */
749N/A
749N/A/* ARGSUSED */
749N/Astatic void
749N/AToggleDestroy(w, junk, garbage)
749N/AWidget w;
749N/AXtPointer junk, garbage;
749N/A{
749N/A RemoveFromRadioGroup(w);
749N/A}
749N/A
749N/A/************************************************************
749N/A *
749N/A * Below are all the private procedures that handle
749N/A * radio toggle buttons.
749N/A *
749N/A ************************************************************/
749N/A
749N/A/* Function Name: GetRadioGroup
749N/A * Description: Gets the radio group associated with a give toggle
749N/A * widget.
749N/A * Arguments: w - the toggle widget who's radio group we are getting.
749N/A * Returns: the radio group associated with this toggle group.
749N/A */
749N/A
749N/Astatic RadioGroup *
749N/AGetRadioGroup(w)
749N/AWidget w;
749N/A{
749N/A ToggleWidget tw = (ToggleWidget) w;
749N/A
749N/A if (tw == NULL) return(NULL);
749N/A return( tw->toggle.radio_group );
749N/A}
749N/A
749N/A/* Function Name: CreateRadioGroup
749N/A * Description: Creates a radio group. give two widgets.
749N/A * Arguments: w1, w2 - the toggle widgets to add to the radio group.
749N/A * Returns: none.
749N/A *
749N/A * NOTE: A pointer to the group is added to each widget's radio_group
749N/A * field.
749N/A */
749N/A
749N/Astatic void
749N/ACreateRadioGroup(w1, w2)
749N/AWidget w1, w2;
749N/A{
749N/A char error_buf[BUFSIZ];
749N/A ToggleWidget tw1 = (ToggleWidget) w1;
749N/A ToggleWidget tw2 = (ToggleWidget) w2;
749N/A
749N/A if ( (tw1->toggle.radio_group != NULL) || (tw2->toggle.radio_group != NULL) ) {
749N/A (void) sprintf(error_buf, "%s %s", "Toggle Widget Error - Attempting",
749N/A "to create a new toggle group, when one already exists.");
749N/A XtWarning(error_buf);
749N/A }
749N/A
749N/A AddToRadioGroup( (RadioGroup *)NULL, w1 );
749N/A AddToRadioGroup( GetRadioGroup(w1), w2 );
749N/A}
749N/A
749N/A/* Function Name: AddToRadioGroup
749N/A * Description: Adds a toggle to the radio group.
749N/A * Arguments: group - any element of the radio group the we are adding to.
749N/A * w - the new toggle widget to add to the group.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/AAddToRadioGroup(group, w)
749N/ARadioGroup * group;
749N/AWidget w;
749N/A{
749N/A ToggleWidget tw = (ToggleWidget) w;
749N/A RadioGroup * local;
749N/A
749N/A local = (RadioGroup *) XtMalloc( sizeof(RadioGroup) );
749N/A local->widget = w;
749N/A tw->toggle.radio_group = local;
749N/A
749N/A if (group == NULL) { /* Creating new group. */
749N/A group = local;
749N/A group->next = NULL;
749N/A group->prev = NULL;
749N/A return;
749N/A }
749N/A local->prev = group; /* Adding to previous group. */
749N/A if ((local->next = group->next) != NULL)
749N/A local->next->prev = local;
749N/A group->next = local;
749N/A}
749N/A
749N/A/* Function Name: TurnOffRadioSiblings
749N/A * Description: Deactivates all radio siblings.
749N/A * Arguments: widget - a toggle widget.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/ATurnOffRadioSiblings(w)
749N/AWidget w;
749N/A{
749N/A RadioGroup * group;
749N/A ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class;
749N/A
749N/A if ( (group = GetRadioGroup(w)) == NULL) /* Punt if there is no group */
749N/A return;
749N/A
749N/A /* Go to the top of the group. */
749N/A
749N/A for ( ; group->prev != NULL ; group = group->prev );
749N/A
749N/A while ( group != NULL ) {
749N/A ToggleWidget local_tog = (ToggleWidget) group->widget;
749N/A if ( local_tog->command.set ) {
749N/A class->toggle_class.Unset(group->widget, NULL, NULL, 0);
749N/A Notify( group->widget, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
749N/A }
749N/A group = group->next;
749N/A }
749N/A}
749N/A
749N/A/* Function Name: RemoveFromRadioGroup
749N/A * Description: Removes a toggle from a RadioGroup.
749N/A * Arguments: w - the toggle widget to remove.
749N/A * Returns: none.
749N/A */
749N/A
749N/Astatic void
749N/ARemoveFromRadioGroup(w)
749N/AWidget w;
749N/A{
749N/A RadioGroup * group = GetRadioGroup(w);
749N/A if (group != NULL) {
749N/A if (group->prev != NULL)
749N/A (group->prev)->next = group->next;
749N/A if (group->next != NULL)
749N/A (group->next)->prev = group->prev;
749N/A XtFree((char *) group);
749N/A }
749N/A}
749N/A
749N/A/************************************************************
749N/A *
749N/A * Public Routines
749N/A *
749N/A ************************************************************/
749N/A
749N/A/* Function Name: XawToggleChangeRadioGroup
749N/A * Description: Allows a toggle widget to change radio groups.
749N/A * Arguments: w - The toggle widget to change groups.
749N/A * radio_group - any widget in the new group.
749N/A * Returns: none.
749N/A */
749N/A
749N/Avoid
749N/A#if NeedFunctionPrototypes
749N/AXawToggleChangeRadioGroup(Widget w, Widget radio_group)
749N/A#else
749N/AXawToggleChangeRadioGroup(w, radio_group)
749N/AWidget w, radio_group;
749N/A#endif
749N/A{
749N/A ToggleWidget tw = (ToggleWidget) w;
749N/A RadioGroup * group;
749N/A
749N/A RemoveFromRadioGroup(w);
749N/A
749N/A/*
749N/A * If the toggle that we are about to add is set then we will
749N/A * unset all toggles in the new radio group.
749N/A */
749N/A
749N/A if ( tw->command.set && radio_group != NULL )
749N/A XawToggleUnsetCurrent(radio_group);
749N/A
749N/A if (radio_group != NULL)
749N/A if ((group = GetRadioGroup(radio_group)) == NULL)
749N/A CreateRadioGroup(w, radio_group);
749N/A else AddToRadioGroup(group, w);
749N/A}
749N/A
749N/A/* Function Name: XawToggleGetCurrent
749N/A * Description: Returns the RadioData associated with the toggle
749N/A * widget that is currently active in a toggle group.
749N/A * Arguments: w - any toggle widget in the toggle group.
749N/A * Returns: The XtNradioData associated with the toggle widget.
749N/A */
749N/A
749N/AXtPointer
749N/A#if NeedFunctionPrototypes
749N/AXawToggleGetCurrent(Widget w)
749N/A#else
749N/AXawToggleGetCurrent(w)
749N/AWidget w;
749N/A#endif
749N/A{
749N/A RadioGroup * group;
749N/A
749N/A if ( (group = GetRadioGroup(w)) == NULL) return(NULL);
749N/A for ( ; group->prev != NULL ; group = group->prev);
749N/A
749N/A while ( group != NULL ) {
749N/A ToggleWidget local_tog = (ToggleWidget) group->widget;
749N/A if ( local_tog->command.set )
749N/A return( local_tog->toggle.radio_data );
749N/A group = group->next;
749N/A }
749N/A return(NULL);
749N/A}
749N/A
749N/A/* Function Name: XawToggleSetCurrent
749N/A * Description: Sets the Toggle widget associated with the
749N/A * radio_data specified.
749N/A * Arguments: radio_group - any toggle widget in the toggle group.
749N/A * radio_data - radio data of the toggle widget to set.
749N/A * Returns: none.
749N/A */
749N/A
749N/Avoid
749N/A#if NeedFunctionPrototypes
749N/AXawToggleSetCurrent(Widget radio_group, XtPointer radio_data)
749N/A#else
749N/AXawToggleSetCurrent(radio_group, radio_data)
749N/AWidget radio_group;
749N/AXtPointer radio_data;
749N/A#endif
749N/A{
749N/A RadioGroup * group;
749N/A ToggleWidget local_tog;
749N/A
749N/A/* Special case of no radio group. */
749N/A
749N/A if ( (group = GetRadioGroup(radio_group)) == NULL) {
749N/A local_tog = (ToggleWidget) radio_group;
749N/A if ( (local_tog->toggle.radio_data == radio_data) )
749N/A if (!local_tog->command.set) {
749N/A ToggleSet((Widget) local_tog, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
749N/A Notify((Widget) local_tog, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
749N/A }
749N/A return;
749N/A }
749N/A
749N/A/*
749N/A * find top of radio_roup
749N/A */
749N/A
749N/A for ( ; group->prev != NULL ; group = group->prev);
749N/A
749N/A/*
749N/A * search for matching radio data.
749N/A */
749N/A
749N/A while ( group != NULL ) {
749N/A local_tog = (ToggleWidget) group->widget;
749N/A if ( (local_tog->toggle.radio_data == radio_data) ) {
749N/A if (!local_tog->command.set) { /* if not already set. */
749N/A ToggleSet((Widget) local_tog, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
749N/A Notify((Widget) local_tog, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
749N/A }
749N/A return; /* found it, done */
749N/A }
749N/A group = group->next;
749N/A }
749N/A}
749N/A
749N/A/* Function Name: XawToggleUnsetCurrent
749N/A * Description: Unsets all Toggles in the radio_group specified.
749N/A * Arguments: radio_group - any toggle widget in the toggle group.
749N/A * Returns: none.
749N/A */
749N/A
749N/Avoid
749N/A#if NeedFunctionPrototypes
749N/AXawToggleUnsetCurrent(Widget radio_group)
749N/A#else
749N/AXawToggleUnsetCurrent(radio_group)
749N/AWidget radio_group;
749N/A#endif
749N/A{
749N/A ToggleWidgetClass class;
749N/A ToggleWidget local_tog = (ToggleWidget) radio_group;
749N/A
749N/A /* Special Case no radio group. */
749N/A
749N/A if (local_tog->command.set) {
749N/A class = (ToggleWidgetClass) local_tog->core.widget_class;
749N/A class->toggle_class.Unset(radio_group, NULL, NULL, 0);
749N/A Notify(radio_group, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
749N/A }
749N/A if ( GetRadioGroup(radio_group) == NULL) return;
749N/A TurnOffRadioSiblings(radio_group);
749N/A}
749N/A