csvsj@garnet.berkeley.edu (Steve Jacobson) (03/11/89)
We have just started trying to move our complex X application from R2 to R3. (We've waited till now because we used HP widgets). We use the closure member of the CallbackList structure to store client data associated with the widget instance. Our application originally was a SunView program, and SunView "objects" all have client data resources. For the X version, we used the CallbackList structure for this purpose. In many instances, we set a dummy destroy callback just so we could use the closure structure member. Question: Is there a more direct way to do this? Why isn't there a client data resource in the core widget structure? We were able to make this work in X11R2, though there were some things we did because they worked without understanding why. Here's an example: static void clear_values() { int i; Arg args[10]; XtCallbackRec *callback; XtSetArg(args[0], XtNstring, ""); XtSetArg(args[1], XtNinsertPosition, 0); XtSetArg(args[2], XtNvisibleInsert, TRUE); XtSetArg(args[3], XtNdestroyCallback, &callback); for (i = 0; i < text_count; i++) { XtSetValues(query_text_item[i], args, THREE); XtGetValues(query_text_item[i], &args[3], ONE); (callback+1)->closure = (caddr_t) 0; } } We didn't understand why we had to go to the 2nd callback list member when we had only set one destroycallback. However, it worked. Subsequently, we could use the same method to find out what the closure value was. It's clear from the R3 changes memo and by looking at the code, that this will no longer work. We haven't figured out how to make it work. Along the way, we found a bug in the Xt Callback.c file. The bug: In the _XtGetCallbackList routine, the automatic variable callback_count is not initialized to 0. In the code, it is incremented, then used in a XtMalloc call. When we ran our application on our DEC GPX, the automatic variable had a very large number in it, so the XtMalloc failed. Linting the file points the problem out. What we tried: First, it looked like we no longer needed to look at the 2nd callback list member if we had only set one. Second, it looked like we get a copy of the list, so changing a closure value wouldn't change it where it counted. I should state that these were guesses - in practice we have little idea just what is going on here. Here is our last attempt: static void clear_values() { int i; Arg args[10]; XtCallbackRec *callback; XtSetArg(args[0], XtNstring, ""); XtSetArg(args[1], XtNinsertPosition, 0); XtSetArg(args[2], XtNvisibleInsert, TRUE); XtSetArg(args[3], XtNdestroyCallback, &callback); for (i = 0; i < text_count; i++) { XtSetValues(query_text_item[i], args, THREE); XtGetValues(query_text_item[i], &args[3], ONE); callback->closure = (caddr_t) 0; XtSetValues(query_text_item[i], &args[3], ONE); } } This didn't work. First, it looked like this just added a destroy callback, rather than replacing the original list. Second, the closure value in both copies of the callback record were the same, and not the value we expected. (The fact that both list members looked the same makes me doubt the copy guess above.) Obviously, I've not presented enough code here to replicate the problem, but I hope I have made it clear what we are trying to do. We would appreciate responses that either suggest a more direct way of associating modifyable client data with widget instances or give us hints about what we're supposed to do to change the code the worked with R2 to code that works in R3. Thanks.