diff options
Diffstat (limited to 'nx-X11/lib/Xaw/Toggle.c')
-rw-r--r-- | nx-X11/lib/Xaw/Toggle.c | 632 |
1 files changed, 632 insertions, 0 deletions
diff --git a/nx-X11/lib/Xaw/Toggle.c b/nx-X11/lib/Xaw/Toggle.c new file mode 100644 index 000000000..dfbcf7677 --- /dev/null +++ b/nx-X11/lib/Xaw/Toggle.c @@ -0,0 +1,632 @@ +/* $Xorg: Toggle.c,v 1.4 2001/02/09 02:03:47 xorgcvs Exp $ */ + +/* + +Copyright 1989, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* $XFree86: xc/lib/Xaw/Toggle.c,v 1.8 2001/08/23 00:03:20 dawes Exp $ */ + +/* + * Author: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + * + * Date: January 12, 1989 + * + */ + +#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> + +/* + * Class Methods + */ +static void XawToggleClassInitialize(void); +static void XawToggleInitialize(Widget, Widget, ArgList, Cardinal*); +static Boolean XawToggleSetValues(Widget, Widget, Widget, ArgList, Cardinal*); + +/* + * Prototypes + */ +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); + +/* + * Actions + */ +static void Notify(Widget, XEvent*, String*, Cardinal*); +static void Toggle(Widget, XEvent*, String*, Cardinal*); +static void ToggleSet(Widget, XEvent*, String*, Cardinal*); + +/* + * Initialization + */ +/* + * The order of toggle and notify are important, as the state has + * to be set when we call the notify proc + */ +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 = { + /* core */ + { + (WidgetClass)Superclass, /* superclass */ + "Toggle", /* class_name */ + sizeof(ToggleRec), /* size */ + XawToggleClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawToggleInitialize, /* 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 */ + XawToggleSetValues, /* 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 */ + }, + /* simple */ + { + XtInheritChangeSensitive, /* change_sensitive */ + }, + /* label */ + { + NULL, /* extension */ + }, + /* command */ + { + NULL, /* extension */ + }, + /* toggle */ + { + NULL, /* Set */ + NULL, /* Unset */ + NULL, /* extension */ + } +}; + +WidgetClass toggleWidgetClass = (WidgetClass)&toggleClassRec; + +/* + * Impelementation + */ +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); + + /* + * Find the set and unset actions in the command widget's action table + */ + 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; + } + } + + /* We should never get here */ + XtError("Aborting, due to errors resolving bindings in the Toggle widget."); +} + +/*ARGSUSED*/ +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); + + /* + * 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(cnew, NULL, NULL, NULL); +} + +/*ARGSUSED*/ +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); +} + +/*ARGSUSED*/ +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); +} + +/*ARGSUSED*/ +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); +} + +/* + * Function: + * XawToggleDestroy + * + * Parameters: + * w - toggle widget that is being destroyed + * temp1 - not used + * temp2 - "" + * + * Description: + * Destroy Callback for toggle widget. + */ +/*ARGSUSED*/ +static void +XawToggleDestroy(Widget w, XtPointer temp1, XtPointer temp2) +{ + RemoveFromRadioGroup(w); +} + +/* + * Function: + * GetRadioGroup + * + * Parameters: + * w - toggle widget who's radio group we are getting + * + * Description: + * Gets the radio group associated with a give toggle widget. + * + * Returns: + * The radio group associated with this toggle group + */ +static RadioGroup * +GetRadioGroup(Widget w) +{ + ToggleWidget tw = (ToggleWidget)w; + + if (tw == NULL) + return (NULL); + + return (tw->toggle.radio_group); +} + +/* + * Function: + * CreateRadioGroup + * + * Parameters: + * w1 - toggle widgets to add to the radio group + * w2 - "" + * + * Description: + * Creates a radio group. give two widgets. + * + * Note: + * A pointer to the group is added to each widget's radio_group field. + */ +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); +} + +/* + * Function: + * AddToRadioGroup + * + * Parameters: + * group - element of the radio group the we are adding to + * w - new toggle widget to add to the group + * + * Description: + * Adds a toggle to the radio group. + */ +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) { /* 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: + * TurnOffRadioSiblings + * + * Parameters: + * widget - toggle widget + * + * Description: + * Deactivates all radio siblings. + */ +static void +TurnOffRadioSiblings(Widget w) +{ + RadioGroup *group; + ToggleWidgetClass cclass = (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) { + cclass->toggle_class.Unset(group->widget, NULL, NULL, NULL); + Notify(group->widget, NULL, NULL, NULL); + } + group = group->next; + } +} + +/* + * Function: + * RemoveFromRadioGroup + * + * Parameters: + * w - toggle widget to remove + * + * Description: + * Removes a toggle from a RadioGroup. + */ +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); + } +} + +/* + * Function: + * XawToggleChangeRadioGroup + * + * Parameters: + * w - toggle widget to change groups + * radio_group - any widget in the new group + * + * Description: + * Allows a toggle widget to change radio groups. + */ +void +XawToggleChangeRadioGroup(Widget w, Widget radio_group) +{ + ToggleWidget tw = (ToggleWidget)w; + RadioGroup *group; + + 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); + + if (radio_group != NULL) { + if ((group = GetRadioGroup(radio_group)) == NULL) + CreateRadioGroup(w, radio_group); + else + AddToRadioGroup(group, w); + } +} + +/* + * Function: + * XawToggleGetCurrent + * + * Parameters: + * w - any toggle widget in the toggle group + * + * Description: + * Returns the RadioData associated with the toggle + * widget that is currently active in a toggle group. + * + * Returns: + * The XtNradioData associated with the toggle widget + */ +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); +} + +/* + * Function: + * XawToggleSetCurrent + * + * Parameters: + * radio_group - any toggle widget in the toggle group + * radio_data - radio data of the toggle widget to set + * + * Description: + * Sets the Toggle widget associated with the radio_data specified. + */ +void +XawToggleSetCurrent(Widget radio_group, XtPointer radio_data) +{ + RadioGroup *group; + ToggleWidget local_tog; + + /* Special case of no radio group */ + + 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; + } + + /* + * 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(group->widget, NULL, NULL, NULL); + Notify(group->widget, NULL, NULL, NULL); + } + return; /* found it, done */ + } + group = group->next; + } +} + +/* + * Function: + * XawToggleUnsetCurrent + * + * Parameters: + * radio_group - any toggle widget in the toggle group + * + * Description: + * Unsets all Toggles in the radio_group specified. + */ +void +XawToggleUnsetCurrent(Widget radio_group) +{ + ToggleWidgetClass cclass; + ToggleWidget local_tog = (ToggleWidget)radio_group; + + /* Special Case no 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); +} |