Greets all, what I've got is a much simplified snippet of a real program that has to update the label strings in 45 million Motif label widgets. Simplified version: I create two label widgets and set their label strings to "text." I place the two widgets into a standard C array and pass it as client_data to a callback function using XtAddCallback. The callback is invoked by a pushbutton and it's supposed to change the label strings from "text" to "different text," but it only changes the string in the first label widget. I'm assuming that for whatever reason the client_data (an XtPointer) that's supposed to have the two widget array actually only has the first widget. I realize full well that I could access the label widgets from the parent widget that's passed in as the first parameter in XtAddCallback, then use XtNameToWidget to get the labels, but that would entail 45 million calls to XtNameToWidget, which I'd rather avoid. I also realize I could put the all the label widgets into a global array, and then index over the array to change the label strings, but globals are also something I'd rather avoid. Another thing that's weird, if there is no second widget I would have thought that calling XtSetValues on it would crash the program, but it doesn't. So, if anyone's interested in taking a look at this (doubtful), here's the simplified snippet, if you name it arrays.c, it compiles (at least on Linux) with gcc -lXm -lXt -lX11 -o arrays arrays.c - Oh and for reasons that defy logical explanation, I'm being forced to use Motif-2.1.32
/* Impossible to pass a widget array using XtAddCallback? */
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <stdio.h>
#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
void pass_array_cb(Widget, XtPointer, XtPointer);
int main(int argc, char * argv[])
{
XtAppContext app_context;
XmString text;
Widget toplevel;
Widget form, button, label_01, label_02;
Arg av[10];
int ac = 0;
toplevel = XtOpenApplication(
&app_context,
"arrays",
NULL,
0,
&argc,
argv,
NULL,
applicationShellWidgetClass,
av,
ac);
form = XtVaCreateManagedWidget("form",
xmFormWidgetClass, toplevel,
XmNheight, 100,
XmNwidth, 200,
NULL);
text = XmStringCreateLocalized((char *) "text");
label_01 = XtVaCreateManagedWidget("label_01",
xmLabelWidgetClass, form,
XmNwidth, 60,
XmNheight, 20,
XmNlabelString, text,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, toplevel,
NULL);
label_02 = XtVaCreateManagedWidget("label_02",
xmLabelWidgetClass, form,
XmNwidth, 60,
XmNheight, 20,
XmNlabelString, text,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, label_01,
NULL);
XmStringFree(text);
Widget label_widgets[2] = { label_01, label_02 };
button = XtVaCreateManagedWidget("button",
xmPushButtonWidgetClass, form,
XmNwidth, 60,
XmNheight, 20,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, label_02,
NULL);
XtAddCallback(button, XmNactivateCallback, pass_array_cb, *label_widgets);
XtRealizeWidget (toplevel);
XtAppMainLoop (app_context);
return 0;
}
void pass_array_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
Widget (*label_widgets)[2] = (Widget (*)[2])client_data;
XmString text = XmStringCreateLocalized((char *)"different text");
int i;
for(i = 0; i < 2; i++)
{
printf("in the callback, widget index is %d\n", i);
XtVaSetValues(*label_widgets[i], XmNlabelString, text, NULL);
}
XmStringFree(text);
}
*label_widgetsis exactly the same aslabel_widgets[0]which in your case is exactly the same aslabel_01. You are passinglabel_01as your callback argument. It has typeWidget.label_widgetsis now a pointer to a 2-element array ofWidget, which is very different fromWidgetyou have passed as the argument.*label_widgets[i]is the same aslabel_widgets[i][0]. Sincelabel_widgetsis a pointer (see above), it is taken as a pointer to the first element of an array. An array of what? Of two-element arrays orWidget. So it takes theith element of that array, which happens to be a 2-element array ofWidget, and takes the0ths widget of that. Needles to say, there is no array of arrays ofWidgetanywhere, so this code just wanders off to the La-La Land.You want this:
Pass a pointer to the first element of
label_widgets. Look up array-to-pointer decay for more info.Receive a pointer to the first element of an array of
Widget.Index into the aforementioned array using a pointer to its first element (all array indexing works this way).