/* * Motif Tools Library, Version 3.1 * $Id: Chooser.c,v 1.1.1.1 2001/07/18 11:06:02 root Exp $ * * Written by David Flanagan. * Copyright (c) 1992-2001 by David Flanagan. * All Rights Reserved. See the file COPYRIGHT for details. * This is open source software. See the file LICENSE for details. * There is no warranty for this software. See NO_WARRANTY for details. * * $Log: Chooser.c,v $ * Revision 1.1.1.1 2001/07/18 11:06:02 root * Initial checkin. * * Revision 1.2 2001/06/12 16:25:28 andre * *** empty log message *** * * */ #include #include #include #include #include #include #include #include /* for XmtNlayoutSensitive resource */ #include #include #include #include #include #if XmVersion >= 2000 #include #endif static XtResource resources[] = { {XmtNchooserType, XmtCChooserType, XmtRXmtChooserType, sizeof(XmtChooserType), XtOffsetOf(XmtChooserRec, chooser.type), XtRImmediate, (XtPointer)XmtChooserRadioBox}, {XmtNnumItems, XmtCNumItems, XtRInt, sizeof(int), XtOffsetOf(XmtChooserRec, chooser.num_items), XtRImmediate, (XtPointer) -1}, {XmtNstrings, XmtCStrings, XmtRStringList, sizeof(String *), XtOffsetOf(XmtChooserRec, chooser.strings), XmtRStringList, NULL}, {XmtNpixmaps, XmtCPixmaps, XmtRPixmapList, sizeof(Pixmap *), XtOffsetOf(XmtChooserRec, chooser.pixmaps), XmtRPixmapList, NULL}, {XmtNselectPixmaps, XmtCSelectPixmaps, XmtRPixmapList, sizeof(Pixmap *), XtOffsetOf(XmtChooserRec, chooser.select_pixmaps), XmtRPixmapList, NULL}, {XmtNinsensitivePixmaps, XmtCInsensitivePixmaps, XmtRPixmapList, sizeof(Pixmap *), XtOffsetOf(XmtChooserRec, chooser.insensitive_pixmaps), XmtRPixmapList, NULL}, {XmtNvalues, XmtCValues, XtRPointer, sizeof(XtPointer), XtOffsetOf(XmtChooserRec, chooser.values), XtRImmediate, NULL}, {XmtNvalueStrings, XmtCValueStrings, XmtRStringList, sizeof(String *), XtOffsetOf(XmtChooserRec, chooser.value_strings), XmtRStringList, NULL}, {XmtNvalueType, XmtCValueType, XtRString, sizeof(String), XtOffsetOf(XmtChooserRec, chooser.value_type), XtRString, NULL}, {XmtNvalueSize, XmtCValueSize, XtRInt, sizeof(int), XtOffsetOf(XmtChooserRec, chooser.value_size), XtRImmediate, (XtPointer) 0}, {XmtNfontList, XmCFontList, XmRFontList, sizeof(XmFontList), XtOffsetOf(XmtChooserRec, chooser.font_list), XtRImmediate, NULL}, #if XmVersion >= 2000 {XmtNrenderTable, XmCRenderTable, XmRRenderTable, sizeof(XmRenderTable), XtOffsetOf(XmtChooserRec, chooser.render_table), XtRImmediate, (XtPointer) NULL}, #endif {XmtNvisibleItems, XmtCVisibleItems, XtRInt, sizeof(int), XtOffsetOf(XmtChooserRec, chooser.visible_items), XtRImmediate, (XtPointer) 8}, {XmtNstate, XmtCState, XtRInt, sizeof(int), XtOffsetOf(XmtChooserRec, chooser.state), XtRImmediate, (XtPointer) 0}, {XmtNsymbolName, XmtCSymbolName, XtRString, sizeof(String), XtOffsetOf(XmtChooserRec, chooser.symbol_name), XtRImmediate, NULL}, {XmtNlabelType, XmtCLabelType, XmRLabelType, sizeof(unsigned char), XtOffsetOf(XmtChooserRec, chooser.label_type), XtRImmediate, (XtPointer)XmSTRING}, {XmtNvalueChangedCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), XtOffsetOf(XmtChooserRec, chooser.callback), XtRCallback, NULL}, {XmtNitemWidgets, XtCReadOnly, XtRWidgetList, sizeof(WidgetList), XtOffsetOf(XmtChooserRec, chooser.item_widgets), XtRImmediate, NULL}, /* * override defaults for some RowColumn resources */ {XmNadjustLast, XmCAdjustLast, XtRBoolean, sizeof(Boolean), XtOffsetOf(XmtChooserRec, row_column.adjust_last), XtRImmediate, (XtPointer) False}, {XmNpacking, XmCPacking, XmRPacking, sizeof(unsigned char), XtOffsetOf(XmtChooserRec, row_column.packing), XtRImmediate, (XtPointer) XmPACK_COLUMN}, }; #if NeedFunctionPrototypes static void ClassInitialize(void); static void ClassPartInitialize(WidgetClass); static void Initialize(Widget, Widget, ArgList, Cardinal *); static void Destroy(Widget); static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *); #else static void ClassInitialize(); static void ClassPartInitialize(); static void Initialize(); static void Destroy(); static Boolean SetValues(); #endif #define Superclass (&xmRowColumnClassRec) externaldef(xmtchooserclassrec) XmtChooserClassRec xmtChooserClassRec = { { /* core_class fields */ /* superclass */ (WidgetClass) Superclass, /* class_name */ "XmtChooser", /* widget_size */ sizeof(XmtChooserRec), /* class_initialize */ ClassInitialize, /* class_part_init */ ClassPartInitialize, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ XtExposeCompressMaximal, /* compress_enterleave*/ FALSE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ XtInheritAcceptFocus, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator*/ XtInheritDisplayAccelerator, /* extension */ NULL }, { /* composite_class fields */ /* geometry_manager */ XtInheritGeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL }, { /* constraint_class fields */ /* resource list */ NULL, /* num resources */ 0, /* constraint size */ sizeof(XmRowColumnConstraintRec), /* init proc */ NULL, /* destroy proc */ NULL, /* set values proc */ NULL, /* extension */ NULL }, { /* manager_class */ /* translations */ XtInheritTranslations, /* syn_resources */ NULL, /* num_syn_resources */ 0, /* syn_cont_resources */ NULL, /* num_syn_cont_resources */0, /* parent_process */ XmInheritParentProcess, /* extension */ NULL }, { /* row column class record */ /* proc to interface with widgets */ XmInheritMenuProc, /* proc to arm&activate menu */ XmInheritArmAndActivate, /* traversal handler */ XmInheritMenuTraversalProc, /* extension */ NULL, }, { /* XmtChooser */ /* extension */ NULL } }; externaldef(xmtchooserwidgetclass) WidgetClass xmtChooserWidgetClass = (WidgetClass)&xmtChooserClassRec; #if NeedFunctionPrototypes static void SetStateOnWidgets(XmtChooserWidget cw) #else static void SetStateOnWidgets(cw) XmtChooserWidget cw; #endif { int i, bit; /* * update the subwidgets to reflect the current state. Don't touch * the symbol value or call callbacks. */ if (cw->chooser.num_items == 0) return; if (cw->chooser.type == XmtChooserRadioList) { XmListDeselectAllItems(cw->chooser.list); XmListSelectPos(cw->chooser.list, cw->chooser.state+1, False); } #if XmVersion >= 2000 else if (cw->chooser.type == XmtChooserComboBox) { XtVaSetValues(cw->chooser.combo_box, XmNselectedPosition, cw->chooser.state+1, NULL); } #endif else if (cw->chooser.type == XmtChooserCheckList) { XmListDeselectAllItems(cw->chooser.list); for(i=0, bit = 1; i < cw->chooser.num_items; i++, bit = bit << 1) if (cw->chooser.state & bit) XmListSelectPos(cw->chooser.list, i+1, False); } else if (cw->chooser.type == XmtChooserOption) { /* XXX this may not work before Motif 1.1.4 */ XtVaSetValues(cw->chooser.option, XmNmenuHistory, cw->chooser.item_widgets[cw->chooser.state], NULL); } else if ((cw->chooser.type == XmtChooserCheckBox) || (cw->chooser.type == XmtChooserCheckPalette)) { for(i=0, bit = 1; i < cw->chooser.num_items; i++, bit = bit << 1) if (cw->chooser.state & bit) XmToggleButtonSetState(cw->chooser.item_widgets[i], True, False); else XmToggleButtonSetState(cw->chooser.item_widgets[i], False, False); } else if ((cw->chooser.type == XmtChooserRadioBox) || (cw->chooser.type == XmtChooserRadioPalette)) { for(i=0; i < cw->chooser.num_items; i++) XmToggleButtonSetState(cw->chooser.item_widgets[i], False, False); XmToggleButtonSetState(cw->chooser.item_widgets[cw->chooser.state], True, False); } else { /* a button box; it doesn't have state */ ; } } /* ARGSUSED */ #if NeedFunctionPrototypes static void ChooserCallback(Widget w, XtPointer tag, XtPointer data) #else static void ChooserCallback(w, tag, data) Widget w; XtPointer tag; XtPointer data; #endif { XmtChooserWidget cw = (XmtChooserWidget) tag; XmListCallbackStruct *listdata = (XmListCallbackStruct *) data; #if XmVersion >= 2000 XmComboBoxCallbackStruct *combodata = (XmComboBoxCallbackStruct *) data; #endif XmtChooserCallbackStruct call_data; int i; /* * Figure out and record the new state of the Chooser. * Enforce RadioBox behavior where required. * Enforce sensitivity where required (in list widgets). * Update the symbol value, if a symbol was specified. * Invoke the callback that was registered with this Chooser, if it exists. */ /* * if a list, check sensitivity. If the item that was * clicked on is insensitive, restore the old state and return */ if ((cw->chooser.type == XmtChooserRadioList) || (cw->chooser.type == XmtChooserCheckList)) { if (cw->chooser.insensitive & (1 << (listdata->item_position-1))) { SetStateOnWidgets(cw); return; } } #if XmVersion >= 2000 else if (cw->chooser.type == XmtChooserComboBox) { if (cw->chooser.insensitive & (1 << (combodata->item_position-1))) { SetStateOnWidgets(cw); return; } } #endif if (cw->chooser.type == XmtChooserRadioList) { /* list positions start numbering from 1 */ call_data.item = call_data.state = cw->chooser.state = listdata->item_position - 1; } #if XmVersion >= 2000 else if (cw->chooser.type == XmtChooserComboBox) { /* list positions start numbering from 1 */ call_data.item = call_data.state = cw->chooser.state = combodata->item_position - 1; } #endif else if (cw->chooser.type == XmtChooserCheckList) { cw->chooser.state = 0; for(i=0; i < listdata->selected_item_count; i++) cw->chooser.state |= (1<<(listdata->selected_item_positions[i]-1)); call_data.state = cw->chooser.state; call_data.item = listdata->item_position; } else { /* figure out which button was pressed */ for(i = 0; i < cw->chooser.num_items; i++) if (cw->chooser.item_widgets[i] == w) break; if (i == cw->chooser.num_items) return; /* just in case */ call_data.item = i; if ((cw->chooser.type == XmtChooserCheckBox) || (cw->chooser.type == XmtChooserCheckPalette)) { cw->chooser.state ^= (1 << i); call_data.state = cw->chooser.state; } else if ((cw->chooser.type == XmtChooserRadioBox) || (cw->chooser.type == XmtChooserRadioPalette)) { /* * if user clicked on an already selected item, reselect it * otherwise unselect the old selected item. */ if (cw->chooser.state == i) XmToggleButtonSetState(w, True, False); else XmToggleButtonSetState(cw->chooser.item_widgets [cw->chooser.state], False,False); cw->chooser.state = call_data.state = i; } else if (cw->chooser.type == XmtChooserOption) cw->chooser.state = call_data.state = i; else /* button box */ call_data.state = -1; } /* * update the symbol value, if we have one. * set a flag that tells our own symbol notify callback that the * widgets are already in the correct state and it need not do * anything. */ if (cw->chooser.symbol) { cw->chooser.ignore_symbol_notify = True; XmtSymbolSetValue(cw->chooser.symbol, (XtArgVal)cw->chooser.state); cw->chooser.ignore_symbol_notify = False; } /* * figure out the call_data.valuep, if we have values set. */ if (cw->chooser.values) call_data.valuep = (XtPointer) &((char *)cw->chooser.values) [call_data.item * cw->chooser.value_size]; else call_data.valuep = NULL; /* invoke the callbacks registered for this Chooser */ XtCallCallbackList((Widget)cw, cw->chooser.callback,(XtPointer)&call_data); } #if NeedFunctionPrototypes static void SetStateOnSymbol(XmtChooserWidget cw) #else static void SetStateOnSymbol(cw) XmtChooserWidget cw; #endif { /* * set the symbol state. This will cause the notify callbacks to * be invoked, which in our case will call SetStateOnWidgets. * So if you call this function, don't call SetStateOnWidgets. */ if (cw->chooser.symbol) XmtSymbolSetValue(cw->chooser.symbol, (XtArgVal)cw->chooser.state); } /* ARGSUSED */ #if NeedFunctionPrototypes static void ValueChanged(XmtSymbol s, XtPointer tag, XtArgVal value) #else static void ValueChanged(s, tag, value) XmtSymbol s; XtPointer tag; XtArgVal value; #endif { XmtChooserWidget cw = (XmtChooserWidget)tag; /* * update the widget's internal and displayed state when the symbol value * changes from underneath us. Note that we do not call the * valueChangedCallback; this is only called when the user changes the * state by interacting with the widget. Also, it prevents us from * getting into a loop. * * We don't do anything if the ignore flag is set. This is the case * when the user interacts with the widget to change the state--the widget * state and the subwidgets are already correct, the symbol is updated * and the notify callbacks are called to notify anyone else who cares * about the symbol. */ if (cw->chooser.ignore_symbol_notify) return; cw->chooser.state = (int) value; SetStateOnWidgets(cw); } #if NeedFunctionPrototypes static void BindSymbol(XmtChooserWidget cw) #else static void BindSymbol(cw) XmtChooserWidget cw; #endif { if (cw->chooser.symbol_name) { cw->chooser.symbol = XmtLookupSymbol(cw->chooser.symbol_name); if (cw->chooser.symbol) { if (XmtSymbolSize(cw->chooser.symbol)!=sizeof(cw->chooser.state)) { XmtWarningMsg("XmtChooser", "symbolSize", "%s: symbol '%s' has wrong size;\n\tshould be int.", XtName((Widget)cw), cw->chooser.symbol_name); cw->chooser.symbol = NULL; } else { XmtSymbolAddCallback(cw->chooser.symbol, ValueChanged, (XtPointer)cw); XmtSymbolGetValue(cw->chooser.symbol, (XtArgVal*) &cw->chooser.state); } } else { XmtWarningMsg("XmtChooser", "badSymbol", "%s: symbol '%s' is undefined.", XtName((Widget)cw), cw->chooser.symbol_name); } } else cw->chooser.symbol = NULL; } #if NeedFunctionPrototypes static void ReleaseSymbol(XmtChooserWidget cw) #else static void ReleaseSymbol(cw) XmtChooserWidget cw; #endif { if (cw->chooser.symbol) { XmtSymbolRemoveCallback(cw->chooser.symbol, ValueChanged, (XtPointer)cw); cw->chooser.symbol = NULL; } } #if NeedFunctionPrototypes static void CheckType(XmtChooserWidget cw) #else static void CheckType(cw) XmtChooserWidget cw; #endif { /* if this is a check box, then we can't have values */ if ((cw->chooser.type == XmtChooserCheckBox) || (cw->chooser.type == XmtChooserCheckPalette) || (cw->chooser.type == XmtChooserCheckList)) { XmtWarningMsg("XmtChooser", "badType", "%s: XmtNvalues and XmtNvalueStrings resources ignored\n\twhen XmtNchooserType is CheckBox, CheckPalette or CheckList", XtName((Widget)cw)); cw->chooser.values = NULL; cw->chooser.value_strings = NULL; return; } /* also check that value type and size are set */ if (!cw->chooser.value_type || !cw->chooser.value_size) { XmtWarningMsg("XmtChooser", "badValues", "%s: can't set XmtNvalues or XmtNvalueStrings without\n\talso setting XmtNvalueType and XmtNvalueSize resources", XtName((Widget)cw)); cw->chooser.values = NULL; cw->chooser.value_strings = NULL; } } #if NeedFunctionPrototypes static void CopyValues(XmtChooserWidget cw) #else static void CopyValues(cw) XmtChooserWidget cw; #endif { char *values; size_t size = cw->chooser.num_items * cw->chooser.value_size; /* if XmtNvalues is set, be sure to ignore XmtNvalueStrings */ cw->chooser.value_strings = NULL; values = XtMalloc(size); memcpy(values, (char *)cw->chooser.values, size); cw->chooser.values = (XtPointer) values; } #if NeedFunctionPrototypes static void ConvertValueStrings(XmtChooserWidget cw) #else static void ConvertValueStrings(cw) XmtChooserWidget cw; #endif { char *values; XrmValue from, to; Boolean status; int i; values = XtCalloc(cw->chooser.num_items, cw->chooser.value_size); /* String values are a special case; no conversion required */ if (strcmp(cw->chooser.value_type, XtRString) == 0) { for(i=0; i < cw->chooser.num_items; i++) ((String *)values)[i] = cw->chooser.value_strings[i]; } else{ for(i=0; i < cw->chooser.num_items; i++) { from.addr = cw->chooser.value_strings[i]; from.size = strlen(cw->chooser.value_strings[i]) + 1; to.addr = &values[i * cw->chooser.value_size]; to.size = cw->chooser.value_size; status = XtConvertAndStore((Widget)cw, XtRString, &from, cw->chooser.value_type, &to); if (!status) { XmtWarningMsg("XmtChooser", "convert", "%s: conversion failed for item %d of XmtNvalueStrings", XtName((Widget)cw), i); } else if (to.size != cw->chooser.value_size) { XmtWarningMsg("XmtChooser", "badSize", "%s: size of converted values not equal to XmtNvalueSize", XtName((Widget)cw)); XtFree(values); values = NULL; break; } } } cw->chooser.values = values; /* * we set value_strings to NULL, because we're not making a copy of them, * and so we'll notice a change if the programmer specifies the same * array with different values in it. This means that querying this * resource doesn't make sense. */ cw->chooser.value_strings = NULL; } #if NeedFunctionPrototypes static void ClassInitialize(void) #else static void ClassInitialize() #endif { static String names[] = { "ButtonBox", "CheckBox", "CheckList", "CheckPalette", #if XmVersion >= 2000 "ComboBox", #endif "Option", "RadioBox", "RadioList", "RadioPalette" }; static Cardinal values[] = { XmtChooserButtonBox, XmtChooserCheckBox, XmtChooserCheckList, XmtChooserCheckPalette, #if XmVersion >= 2000 XmtChooserComboBox, #endif XmtChooserOption, XmtChooserRadioBox, XmtChooserRadioList, XmtChooserRadioPalette }; static String prefixes[] = {"Xmt", "Chooser", NULL}; XmtRegisterStringListConverter(); XmtRegisterEnumConverter(XmtRXmtChooserType, names, values, XtNumber(names), prefixes); } #if NeedFunctionPrototypes static void ClassPartInitialize(WidgetClass subclass) #else static void ClassPartInitialize(subclass) WidgetClass subclass; #endif { XmtChooserWidgetClass sub = (XmtChooserWidgetClass)subclass; XmtChooserWidgetClass sup = (XmtChooserWidgetClass)sub->core_class.superclass; /* * the XmtChooser widget doesn't have any class fields that need * inheritance, but the XmRowColumn does, and that widget does not * handle the inheritance itself. So we do it here. */ #define inherit(field) \ if ((XtProc)sub->field == _XtInherit) sub->field = sup->field inherit(row_column_class.menuProcedures); inherit(row_column_class.armAndActivate); inherit(row_column_class.traversalHandler); #undef inherit } /* ARGSUSED */ #if NeedFunctionPrototypes static void Initialize(Widget request, Widget init, ArgList arglist, Cardinal *num_args) #else static void Initialize(request, init, arglist, num_args) Widget request; Widget init; ArgList arglist; Cardinal *num_args; #endif { XmtChooserWidget nw = (XmtChooserWidget) init; String *array; Pixmap *p; XmString *item_labels = NULL; char namebuf[200]; Arg args[10]; int i,j; #if XmVersion >= 2000 int len; short num_columns; #endif /* lists can't have pixmaps */ #if XmVersion < 2000 if ((nw->chooser.label_type == XmPIXMAP) && ((nw->chooser.type == XmtChooserRadioList) || (nw->chooser.type == XmtChooserCheckList))) { #else /* Motif 2.0 or later */ if ((nw->chooser.label_type == XmPIXMAP) && ((nw->chooser.type == XmtChooserRadioList) || (nw->chooser.type == XmtChooserCheckList) || (nw->chooser.type == XmtChooserComboBox))) { #endif nw->chooser.label_type = XmSTRING; XmtWarningMsg("XmtChooser", "pixmapType", "%s: XmtNlabelType must be XmSTRING for XmList types.", XtName((Widget)nw)); } /* * Palettes have zero spacing. This is a dynamic default resource, * so we can't just override it. RowCol may do some special processing * on it, so we don't just set it directly. */ if ((nw->chooser.type == XmtChooserRadioPalette) || (nw->chooser.type == XmtChooserCheckPalette)) XtVaSetValues(init, XmNspacing, 0, NULL); #if XmVersion < 2000 /* get the default font from an ancestor font list if none set. */ if (nw->chooser.font_list == NULL) nw->chooser.font_list = _XmGetDefaultFontList(init, XmBUTTON_FONTLIST); /* make a private copy of the font list */ nw->chooser.font_list = XmFontListCopy(nw->chooser.font_list); #else /* Motif 2.0 or later */ if (!nw->chooser.render_table) { if (nw->chooser.font_list) { /* * There is a fontList, so copy it to the renderTable. * NOTE: This code relies on the fact that there is no * disitinction between a fontList and a renderTable * in Motif 2.0. */ nw->chooser.render_table = XmFontListCopy(nw->chooser.font_list); } else { /* * Nothing was specified, so look up the default * renderTable. */ nw->chooser.render_table = XmeGetDefaultRenderTable(init, XmBUTTON_FONTLIST); /* Make a copy of the renderTable. */ nw->chooser.render_table = XmRenderTableCopy(nw->chooser.render_table, NULL, 0); } } else { /* Make a copy of the renderTable. */ nw->chooser.render_table = XmRenderTableCopy(nw->chooser.render_table, NULL, 0); } #endif /* * if we're insensitve, set layoutSensitive, in case we're a child * of a layout and have a caption */ if (!nw->core.sensitive || !nw->core.ancestor_sensitive) XtVaSetValues(init, XmtNlayoutSensitive, False, NULL); /* * Count the strings or pixmaps. * The strings resource may be NULL terminated at this point, or it may * not be. If num_items is -1 (ie. unspecified) then it had better be * NULL-terminated. The resource converter delivers a NULL-terminated * array, but most programmers will probably use counted arrays. It is * also possible that strings is NULL-terminated at less than num_items. * So figure out num_items. */ if (nw->chooser.label_type == XmSTRING) array = nw->chooser.strings; else array = (String *)nw->chooser.pixmaps; if (array != NULL) { if (nw->chooser.num_items == -1) /* if unspecified look for a NULL */ for(i=0; array[i]; i++); else /* if specified, look for a NULL anyway */ for(i=0; i < nw->chooser.num_items && array[i]; i++); nw->chooser.num_items = i; } else /* if no strings are specified */ nw->chooser.num_items = 0; /* * Now copy the array of strings and the arrays of pixmaps. * We copy all arrays, regardless of mode. * We copy the array, but not the strings in it. * While copying the selected and insensitive pixmaps we count them, too. */ if (nw->chooser.strings != NULL) { array = (String *)XtMalloc(nw->chooser.num_items*sizeof(String)); for(i=0; i < nw->chooser.num_items; i++) { if (nw->chooser.strings[i] == NULL) break; array[i] = nw->chooser.strings[i]; } for(; i < nw->chooser.num_items; i++) array[i] = NULL; nw->chooser.strings = array; } if (nw->chooser.pixmaps != NULL) { p = (Pixmap *)XtMalloc(nw->chooser.num_items*sizeof(Pixmap)); for(i=0; i < nw->chooser.num_items; i++) { if (nw->chooser.pixmaps[i] == None) break; p[i] = nw->chooser.pixmaps[i]; } for(; i < nw->chooser.num_items; i++) p[i] = XmUNSPECIFIED_PIXMAP; nw->chooser.pixmaps = p; } if (nw->chooser.select_pixmaps != NULL) { p = (Pixmap *)XtMalloc(nw->chooser.num_items*sizeof(Pixmap)); for(i=0; i < nw->chooser.num_items; i++) { if (nw->chooser.select_pixmaps[i] == None) break; p[i] = nw->chooser.select_pixmaps[i]; } for(; i < nw->chooser.num_items; i++) p[i] = XmUNSPECIFIED_PIXMAP; nw->chooser.select_pixmaps = p; } if (nw->chooser.insensitive_pixmaps != NULL) { p = (Pixmap *)XtMalloc(nw->chooser.num_items*sizeof(Pixmap)); for(i=0; i < nw->chooser.num_items; i++) { if (nw->chooser.insensitive_pixmaps[i] == None) break; p[i] = nw->chooser.insensitive_pixmaps[i]; } for(; i < nw->chooser.num_items; i++) p[i] = XmUNSPECIFIED_PIXMAP; nw->chooser.insensitive_pixmaps = p; } /* * if values or valueStrings is set, make sure that the type is okay, * and make sure we have a size and type */ if (nw->chooser.values || nw->chooser.value_strings) CheckType(nw); /* * if values is set, copy the array. * otherwise, if values is not set, but valueStrings is, * convert the strings, and store in values. We don't copy * valueStrings, because we'll never need to referece it again, * but we set it to NULL, so we can detect when it changes. */ if (nw->chooser.values) CopyValues(nw); else if (nw->chooser.value_strings) ConvertValueStrings(nw); /* create the label XmStrings in string mode */ if (nw->chooser.label_type == XmSTRING) { item_labels = (XmString *) XtMalloc(nw->chooser.num_items*sizeof(XmString)); for(i = 0; i < nw->chooser.num_items; i++) item_labels[i] = XmtCreateLocalizedXmString((Widget) nw, nw->chooser.strings[i]); } /* * Create the widgets. Option menus are handled separately. */ if (nw->chooser.type == XmtChooserOption) { /* * In order to create an Option menu, we have to create the * menu pane first before the cascade button and label. * The menu shell is automatically created, and * its name is not publicly documented. */ i = 0; nw->chooser.pane = XmCreatePulldownMenu(init, "pane", NULL, 0); XtSetArg(args[i], XmNsubMenuId, nw->chooser.pane); i++; nw->chooser.option = XmCreateOptionMenu(init, "option", args, i); #if XmVersion >= 1002 /* * In Motif 1.2.0, a NULL option label string gives an option menu * with some bogus widget name as the label, so we just unmanage * the label altogether. We don't do this in 1.1.4, because * with ICS 1.1.4, at least, the option menu doesn't shrink; it * continues to allocate space for the label gadget. */ XtUnmanageChild(XmOptionLabelGadget(nw->chooser.option)); #endif XtManageChild(nw->chooser.option); #if XmVersion < 2000 XtVaSetValues(XmOptionButtonGadget(nw->chooser.option), XmNfontList, nw->chooser.font_list, NULL); #else /* Motif 2.0 or later */ XtVaSetValues(XmOptionButtonGadget(nw->chooser.option), XmNrenderTable, nw->chooser.render_table, NULL); #endif } else if ((nw->chooser.type == XmtChooserRadioList) || (nw->chooser.type == XmtChooserCheckList)) { i = 0; XtSetArg(args[i], XmNitems, item_labels); i++; #if XmVersion < 2000 XtSetArg(args[i], XmNfontList, nw->chooser.font_list); i++; #else /* Motif 2.0 or later */ XtSetArg(args[i], XmNrenderTable, nw->chooser.render_table); i++; #endif XtSetArg(args[i], XmNitemCount, nw->chooser.num_items); i++; XtSetArg(args[i], XmNvisibleItemCount, nw->chooser.visible_items); i++; XtSetArg(args[i], XmNselectionPolicy, ((nw->chooser.type==XmtChooserRadioList) ? XmBROWSE_SELECT : XmMULTIPLE_SELECT)); i++; nw->chooser.list = XmCreateScrolledList(init, "list", args, i); if (nw->chooser.type == XmtChooserRadioList) XtAddCallback(nw->chooser.list, XmNbrowseSelectionCallback, ChooserCallback, (XtPointer) nw); else XtAddCallback(nw->chooser.list, XmNmultipleSelectionCallback, ChooserCallback, (XtPointer) nw); XtManageChild(nw->chooser.list); } #if XmVersion >= 2000 else if (nw->chooser.type == XmtChooserComboBox) { i = 0; XtSetArg(args[i], XmNitems, item_labels); i++; XtSetArg(args[i], XmNrenderTable, nw->chooser.render_table); i++; XtSetArg(args[i], XmNitemCount, nw->chooser.num_items); i++; /* * ComboBoxes look funny with blank space at the bottom, so * if the actual number of items is smaller than the visible * items resource, we override the visible item count. */ if (nw->chooser.visible_items > nw->chooser.num_items) nw->chooser.visible_items = nw->chooser.num_items; XtSetArg(args[i], XmNvisibleItemCount, nw->chooser.visible_items); i++; XtSetArg(args[i], XmNcomboBoxType, XmDROP_DOWN_LIST); i++; XtSetArg(args[i], XmNmatchBehavior, XmQUICK_NAVIGATE); i++; /* * ComboBoxes do not automatically size themselves based on * their contents. We therefore change the width manually to * match the widest item. */ num_columns = 0; for(j=0; j < nw->chooser.num_items; j++) { len = strlen(nw->chooser.strings[j]); if (len > num_columns) num_columns = len; } XtSetArg(args[i], XmNcolumns, num_columns); i++; nw->chooser.combo_box = XmCreateComboBox(init, "combobox", args, i); XtAddCallback(nw->chooser.combo_box, XmNselectionCallback, ChooserCallback, (XtPointer) nw); /* * Get the list widget that was created as part of the ComboBox * so we can manipulate it directly. */ nw->chooser.list = XmtNameToWidget(nw->chooser.combo_box, "*List"); XtManageChild(nw->chooser.combo_box); } #endif /* If it is not a List widget, go create the internal buttons */ #if XmVersion < 2000 if ((nw->chooser.type != XmtChooserRadioList) && (nw->chooser.type != XmtChooserCheckList)) { #else /* Motif 2.0 or later */ if ((nw->chooser.type != XmtChooserRadioList) && (nw->chooser.type != XmtChooserCheckList) && (nw->chooser.type != XmtChooserComboBox)) { #endif int ac; Widget parent; /* For a menu, parent is pane; otherwise self */ if (nw->chooser.type == XmtChooserOption) parent = nw->chooser.pane; else parent = (Widget) nw; /* set up the fixed arguments */ i = 0; XtSetArg(args[i], XmNlabelType, nw->chooser.label_type); i++; #if XmVersion < 2000 XtSetArg(args[i], XmNfontList, nw->chooser.font_list); i++; #else /* Motif 2.0 or later */ XtSetArg(args[i], XmNrenderTable, nw->chooser.render_table); i++; #endif if ((nw->chooser.type != XmtChooserButtonBox) && (nw->chooser.type != XmtChooserOption)) { XtSetArg(args[i], XmNset, False); i++; if (nw->chooser.type == XmtChooserCheckBox) { XtSetArg(args[i], XmNindicatorType, XmN_OF_MANY); i++; } else if (nw->chooser.type == XmtChooserRadioBox) { #if XmVersion < 2000 XtSetArg(args[i], XmNindicatorType, XmONE_OF_MANY); i++; #else /* Motif 2.0 or later */ Boolean enable_toggle_visual; XtVaGetValues(XmGetXmDisplay(XtDisplay((Widget) nw)), XmNenableToggleVisual, &enable_toggle_visual, NULL); if (!enable_toggle_visual) { XtSetArg(args[i], XmNindicatorType, XmONE_OF_MANY); i++; } else { XtSetArg(args[i], XmNindicatorType, XmONE_OF_MANY_ROUND); i++; } #endif } else if ((nw->chooser.type == XmtChooserRadioPalette) || (nw->chooser.type == XmtChooserCheckPalette)) { XtSetArg(args[i], XmNindicatorOn, False); i++; XtSetArg(args[i], XmNshadowThickness, 2); i++; /* XXX shadow thickness should not be hardcoded. */ } } /* remember the number of fixed arguments */ ac = i; /* create an array to hold the widgets we create */ nw->chooser.item_widgets = (Widget *) XtMalloc(nw->chooser.num_items * sizeof(Widget)); /* set up the label arg(s) and create the widgets */ for(j = 0; j < nw->chooser.num_items; j++) { i = ac; sprintf(namebuf, "item%d", j); if (nw->chooser.label_type == XmSTRING) { XtSetArg(args[i], XmNlabelString, item_labels[j]); i++; } else { XtSetArg(args[i], XmNlabelPixmap, nw->chooser.pixmaps[j]); i++; if (nw->chooser.select_pixmaps) { XtSetArg(args[i], XmNselectPixmap, nw->chooser.select_pixmaps[j]); i++; } if (nw->chooser.insensitive_pixmaps) { XtSetArg(args[i], XmNlabelInsensitivePixmap, nw->chooser.insensitive_pixmaps[j]); i++; } } if ((nw->chooser.type == XmtChooserOption) || (nw->chooser.type == XmtChooserButtonBox)) { nw->chooser.item_widgets[j] = XmCreatePushButton(parent, namebuf, args,i); XtAddCallback(nw->chooser.item_widgets[j], XmNactivateCallback, ChooserCallback, (XtPointer)nw); } else { nw->chooser.item_widgets[j] = XmCreateToggleButton(parent, namebuf, args,i); XtAddCallback(nw->chooser.item_widgets[j], XmNvalueChangedCallback, ChooserCallback, (XtPointer)nw); } } XtManageChildren(nw->chooser.item_widgets, nw->chooser.num_items); } else { /* if it is a list */ nw->chooser.item_widgets = NULL; } /* free all the item XmStrings */ if (nw->chooser.label_type == XmSTRING) { for(i = 0; i < nw->chooser.num_items; i++) XmStringFree(item_labels[i]); XtFree((char *)item_labels); } /* * if there is a symbol, bind the symbol, * set up notification, read the initial state, * and copy the symbol_name. */ if (nw->chooser.symbol_name) { nw->chooser.symbol_name = XtNewString(nw->chooser.symbol_name); BindSymbol(nw); } else nw->chooser.symbol = NULL; /* make the widgets correspond to the initial state */ SetStateOnWidgets(nw); /* set initial sensitivity */ nw->chooser.insensitive = 0; /* and do other initialization */ nw->chooser.ignore_symbol_notify = False; } #if NeedFunctionPrototypes static void Destroy(Widget w) #else static void Destroy(w) Widget w; #endif { XmtChooserWidget cw = (XmtChooserWidget)w; #if XmVersion < 2000 /* free the font list */ XmFontListFree(cw->chooser.font_list); #else /* Motif 2.0 or later */ /* free the renderTable */ XmRenderTableFree(cw->chooser.render_table); #endif /* free the widget array */ XtFree((char *)cw->chooser.item_widgets); /* free the arrays, but not the strings themselves */ XtFree((char *)cw->chooser.strings); XtFree((char *)cw->chooser.pixmaps); XtFree((char *)cw->chooser.select_pixmaps); XtFree((char *)cw->chooser.insensitive_pixmaps); XtFree((char *)cw->chooser.values); /* free the symbol name */ XtFree(cw->chooser.symbol_name); /* remove symbol callback and free the symbol, if we have one */ ReleaseSymbol(cw); } /* ARGSUSED */ #if NeedFunctionPrototypes static Boolean SetValues(Widget current, Widget request, Widget set, ArgList arglist, Cardinal *num_args) #else static Boolean SetValues(current, request, set, arglist, num_args) Widget current; Widget request; Widget set; ArgList arglist; Cardinal *num_args; #endif { XmtChooserWidget cw = (XmtChooserWidget) current; XmtChooserWidget nw = (XmtChooserWidget) set; Arg args[5]; if (nw->chooser.type != cw->chooser.type) { nw->chooser.type = cw->chooser.type; XmtWarningMsg("XmtChooser","cantChangeType", "%s: can't change XmtNchooserType resource.", XtName(set)); } if ((nw->chooser.strings != cw->chooser.strings) || (nw->chooser.pixmaps != cw->chooser.pixmaps) || (nw->chooser.select_pixmaps != cw->chooser.select_pixmaps) || (nw->chooser.insensitive_pixmaps != cw->chooser.insensitive_pixmaps)) XmtWarningMsg("XmtChooser", "cantChange", "%s: can't change labels or pixmaps.", XtName((Widget) nw)); if (nw->chooser.values != cw->chooser.values) { XtFree((char *)cw->chooser.values); CheckType(nw); if (nw->chooser.values) CopyValues(nw); } else if (nw->chooser.value_strings != cw->chooser.value_strings) { XtFree((char*) cw->chooser.values); CheckType(nw); if (nw->chooser.value_strings) ConvertValueStrings(nw); } if (nw->chooser.visible_items != cw->chooser.visible_items) { #if XmVersion < 2000 if ((nw->chooser.type==XmtChooserRadioList) || (nw->chooser.type==XmtChooserCheckList)) { #else /* Motif 2.0 or later */ if ((nw->chooser.type==XmtChooserRadioList) || (nw->chooser.type==XmtChooserCheckList) || (nw->chooser.type==XmtChooserComboBox)) { #endif XtSetArg(args[0], XmNvisibleItemCount, nw->chooser.visible_items); XtSetValues(nw->chooser.list, args, (Cardinal) 1); } } if (nw->chooser.symbol_name != cw->chooser.symbol_name) { /* * forget the old symbol, if there is one. * bind the new, if not NULL, register callbacks, set new state. * If there is a new state, update the widgets. */ XtFree(cw->chooser.symbol_name); nw->chooser.symbol_name = XtNewString(nw->chooser.symbol_name); ReleaseSymbol(cw); BindSymbol(nw); if (nw->chooser.state != cw->chooser.state) SetStateOnWidgets(nw); } else if (nw->chooser.state != cw->chooser.state) { /* if state changed, but symbol name didn't */ if (nw->chooser.symbol) SetStateOnSymbol(nw); /* sets widgets too */ else SetStateOnWidgets(nw); } /* * if sensitivity changes, set the layoutSensitive resource, in case * we're a child of XmtLayout, and have a caption. */ if ((nw->core.sensitive != cw->core.sensitive) || (nw->core.ancestor_sensitive != cw->core.ancestor_sensitive)) { XtVaSetValues(set, XmtNlayoutSensitive, nw->core.sensitive && nw->core.ancestor_sensitive, NULL); } return False; } #if NeedFunctionPrototypes static void BoundsWarning(XmtChooserWidget cw, int n) #else static void BoundsWarning(cw, n) XmtChooserWidget cw; int n; #endif { XmtWarningMsg("XmtChooser", "bounds", "Widget '%s' has %d items. Item %d requested.", XtName((Widget) cw), cw->chooser.num_items, n); } #if NeedFunctionPrototypes Widget XmtCreateChooser(Widget parent, StringConst name, ArgList args, Cardinal n) #else Widget XmtCreateChooser(parent, name, args, n) Widget parent; StringConst name; ArgList args; Cardinal n; #endif { return XtCreateWidget((String)name,xmtChooserWidgetClass, parent, args, n); } #if NeedFunctionPrototypes int XmtChooserGetState(Widget w) #else int XmtChooserGetState(w) Widget w; #endif { XmtAssertWidgetClass(w, xmtChooserWidgetClass, "XmtChooserGetState"); return ((XmtChooserWidget)w)->chooser.state; } #if NeedFunctionPrototypes XtPointer XmtChooserGetValue(Widget w) #else XtPointer XmtChooserGetValue(w) Widget w; #endif { XmtChooserWidget cw = (XmtChooserWidget) w; XmtAssertWidgetClass(w, xmtChooserWidgetClass, "XmtChooserGetValue"); if (cw->chooser.values) return (XtPointer) &((char *)cw->chooser.values) [cw->chooser.state * cw->chooser.value_size]; else return NULL; } #if NeedFunctionPrototypes XtPointer XmtChooserLookupItemValue(Widget w, int item) #else XtPointer XmtChooserLookupItemValue(w, item) Widget w; int item; #endif { XmtChooserWidget cw = (XmtChooserWidget) w; XmtAssertWidgetClass(w, xmtChooserWidgetClass,"XmtChooserLookupItemValue"); if ((item < 0) || (item > cw->chooser.num_items)) { BoundsWarning(cw, item); return NULL; } if (cw->chooser.values) return (XtPointer)&((char *)cw->chooser.values) [item * cw->chooser.value_size]; else return NULL; } #if NeedFunctionPrototypes void XmtChooserSetItemValue(Widget w, int item, XtPointer valuep) #else void XmtChooserSetItemValue(w, item, valuep) Widget w; int item; XtPointer valuep; #endif { XmtChooserWidget cw = (XmtChooserWidget) w; XmtAssertWidgetClass(w, xmtChooserWidgetClass,"XmtChooserLookupItemValue"); if ((item < 0) || (item > cw->chooser.num_items)) { BoundsWarning(cw, item); return; } if (!cw->chooser.values) cw->chooser.values = (XtPointer) XtCalloc(cw->chooser.num_items, cw->chooser.value_size); memmove(&((char *)cw->chooser.values)[item * cw->chooser.value_size], valuep, cw->chooser.value_size); } #if NeedFunctionPrototypes void XmtChooserSetState(Widget w, int state, XmtWideBoolean notify) #else void XmtChooserSetState(w, state, notify) Widget w; int state; int notify; #endif { XmtChooserWidget cw = (XmtChooserWidget)w; XmtChooserCallbackStruct call_data; XmtAssertWidgetClass(w, xmtChooserWidgetClass, "XmtChooserSetState"); /* the XmtChooserButtonBox doesn't have a state to set */ if (cw->chooser.type == XmtChooserButtonBox) return; /* if this chooser has radio behavior, check bounds on state */ if ((cw->chooser.type != XmtChooserCheckBox) && (cw->chooser.type != XmtChooserCheckPalette) && (cw->chooser.type != XmtChooserCheckList) && ((state < 0) || (state > cw->chooser.num_items))) { BoundsWarning(cw, state); return; } cw->chooser.state = state; if (cw->chooser.symbol) SetStateOnSymbol(cw); /* indirectly sets widgets */ else SetStateOnWidgets(cw); if (notify) { call_data.state = state; call_data.item = -1; /* -1 flags synthetic state changes */ if (cw->chooser.values && #if XmVersion < 2000 ((cw->chooser.type == XmtChooserRadioBox) || (cw->chooser.type == XmtChooserRadioPalette) || (cw->chooser.type == XmtChooserRadioList) || (cw->chooser.type == XmtChooserOption))) #else /* Motif 2.0 or later */ ((cw->chooser.type == XmtChooserRadioBox) || (cw->chooser.type == XmtChooserRadioPalette) || (cw->chooser.type == XmtChooserRadioList) || (cw->chooser.type == XmtChooserOption) || (cw->chooser.type == XmtChooserComboBox))) #endif call_data.valuep = (XtPointer) &((char *)cw->chooser.values) [state * cw->chooser.value_size]; else call_data.valuep = NULL; XtCallCallbackList(w, cw->chooser.callback, (XtPointer)&call_data); } } #if NeedFunctionPrototypes int XmtChooserLookupItemByName(Widget w, StringConst name) #else int XmtChooserLookupItemByName(w, name) Widget w; StringConst name; #endif { XmtChooserWidget cw = (XmtChooserWidget)w; int i; XmtAssertWidgetClass(w, xmtChooserWidgetClass,"XmtChooserLookupItemByName"); if (!name || !cw->chooser.strings) return -1; for(i = cw->chooser.num_items-1; i >= 0; i--) if (cw->chooser.strings[i] && (strcmp(name, cw->chooser.strings[i])==0)) break; return i; } #if NeedFunctionPrototypes int XmtChooserLookupItemByValue(Widget w, XtPointer valuep) #else int XmtChooserLookupItemByValue(w, valuep) Widget w; XtPointer valuep; #endif { XmtChooserWidget cw = (XmtChooserWidget)w; int i; XmtAssertWidgetClass(w, xmtChooserWidgetClass, "XmtChooserLookupItemByValue"); if (!cw->chooser.values) return -1; if (strcmp(cw->chooser.value_type, XtRString) == 0) { for(i = cw->chooser.num_items-1; i >= 0; i--) if (strcmp(*(String *)valuep, *(String*)&((char *)cw->chooser.values)[i*cw->chooser.value_size]) == 0) break; } else { for(i = cw->chooser.num_items-1; i >= 0; i--) if (memcmp(valuep, &((char*)cw->chooser.values)[i*cw->chooser.value_size], cw->chooser.value_size) == 0) break; } return i; } #if NeedFunctionPrototypes String XmtChooserLookupItemName(Widget w, int n) #else String XmtChooserLookupItemName(w, n) Widget w; int n; #endif { XmtChooserWidget cw = (XmtChooserWidget)w; XmtAssertWidgetClass(w, xmtChooserWidgetClass,"XmtChooserLookupItemName"); if ((n < 0) || (n > cw->chooser.num_items)) { BoundsWarning(cw, n); return NULL; } if (cw->chooser.strings) return cw->chooser.strings[n]; else return NULL; } #if NeedFunctionPrototypes void XmtChooserSetSensitive(Widget w, int n, XmtWideBoolean sensitive) #else void XmtChooserSetSensitive(w, n, sensitive) Widget w; int n; int sensitive; #endif { XmtChooserWidget cw = (XmtChooserWidget)w; XmtAssertWidgetClass(w, xmtChooserWidgetClass,"XmtChooserSetSensitive"); if ((n < 0) || (n > cw->chooser.num_items)) { BoundsWarning(cw, n); return; } if (n > 31) { XmtWarningMsg("XmtChooserSetSensitive", "size", "can only set sensitivity on first 32 items."); return; } /* * if this is not a list chooser, set the button's sensitivity. */ if (cw->chooser.item_widgets) XtSetSensitive(cw->chooser.item_widgets[n], sensitive); /* * set our internal state */ if (sensitive) cw->chooser.insensitive &= ~(1 << n); else cw->chooser.insensitive |= 1 << n; } #if NeedFunctionPrototypes Boolean XmtChooserGetSensitivity(Widget w, int n) #else Boolean XmtChooserGetSensitivity(w, n) Widget w; int n; #endif { XmtChooserWidget cw = (XmtChooserWidget)w; XmtAssertWidgetClass(w, xmtChooserWidgetClass,"XmtChooserGetSensitivity"); if ((n < 0) || (n > cw->chooser.num_items)) { BoundsWarning(cw, n); return False; } if (n > 31) { XmtWarningMsg("XmtChooserGetSensitivity", "size", "can only get sensitivity on first 32 items."); return False; } if (cw->chooser.insensitive & (1 << n)) return False; else return True; } #if NeedFunctionPrototypes static void setvalue(Widget w, XtPointer address, XrmQuark type, Cardinal size) #else static void setvalue(w, address, type, size) Widget w; XtPointer address; XrmQuark type; Cardinal size; #endif { XmtChooserWidget cw = (XmtChooserWidget) w; if (cw->chooser.values) { if (XrmStringToQuark(cw->chooser.value_type) == type) { int i = XmtChooserLookupItemByValue(w, address); if (i != -1) XmtChooserSetState(w, i, False); else XmtWarningMsg("XmtChooser", "setvalue0", "Widget '%s':\n\tCan't set value from resource.\n\tSpecified value is not one of the legal values.", XtName(w)); } else XmtWarningMsg("XmtChooser", "setvalue1", "Type mismatch:\n\tcan't set value from a resource of type '%s';\n\tWidget '%s' expects a value of type '%s'", XrmQuarkToString(type), XtName(w), cw->chooser.value_type); } else { int value; if (size == sizeof(int)) value = *(int *)address; else if (size == sizeof(short)) value = (int) *(short *)address; else if (size == sizeof(char)) value = (int) *(char *)address; else { XmtWarningMsg("XmtChooser", "setvalue2", "Type mismatch: \n\tCan't set value from a resource of non-scalar type '%s'.", XrmQuarkToString(type)); return; } XmtChooserSetState(w, value, False); } } #if NeedFunctionPrototypes static void getvalue(Widget w, XtPointer address, XrmQuark type, Cardinal size) #else static void getvalue(w, address, type, size) Widget w; XtPointer address; XrmQuark type; Cardinal size; #endif { XmtChooserWidget cw = (XmtChooserWidget) w; if (cw->chooser.values) { if (XrmStringToQuark(cw->chooser.value_type) == type) memmove(address, XmtChooserGetValue(w), cw->chooser.value_size); else XmtWarningMsg("XmtChooser", "getvalue0", "Type mismatch:\n\tcan't set value on a resource of type '%s';\n\tWidget '%s' has values of type '%s'", XrmQuarkToString(type), XtName(w), cw->chooser.value_type); } else { int state = XmtChooserGetState(w); if (size == sizeof(int)) *(int *)address = state; else if (size == sizeof(short)) /* note we don't warn on overflow */ *(short *)address = state; else if (size == sizeof(char)) *(char *)address = state; else { XmtWarningMsg("XmtChooser", "setvalue2", "Type mismatch: \n\tCan't set value from a resource of non-scalar type '%s'.", XrmQuarkToString(type)); return; } } } static XmtWidgetType chooser_widget = { "XmtChooser", (WidgetClass)&xmtChooserClassRec, NULL, setvalue, getvalue, }; #if NeedFunctionPrototypes void XmtRegisterChooser(void) #else void XmtRegisterChooser() #endif { XmtRegisterWidgetTypes(&chooser_widget, 1); }