hoenig@tsetse.informatik.uni-kl.de (Helmut Hoenig) (10/22/90)
X11R4 - Is there a bug in the Athena Dialog Widget ? The following program queries some strings by using the dialog-widget. On my Sun, it crashes exactly when querying the 4th string, during the dispatch of the first KeyPress-Event for the popup-widget. As the program didn't crash so exactly all the time I wrote a small recorder, which stores the events for the first popup-widgets and lets them be dispatched again for the following popups. (It can be enabled by setting the RECORDER-macro.) Even if the program doesn't crash one can see, that the memory-size of the program slowly rises without any reason. Has somebody already had that Problem ? How can I solve it ? Or is it just a foolish mistake of mine in the use the dialog-widget in the do_string_query()-function ? I just tried to use it similary to the popup-example of the Athena Widget Set. I hope somebody could help me as I don't want to miss the popup-up widgets in my programs and I could not find a bug in my source. Helmut Hoenig hoenig@informatik.uni-kl.de (just to be compiled and linked with -lXaw -lXmu -lXt -lXext -lX11) ---------------------------------- CUT HERE ------------------------------------ #define _RECORDER /* no events will be recorded when the RECORDER-macro is not set */ #include <stdio.h> #include <strings.h> #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/Shell.h> #include <X11/Xaw/Cardinals.h> #include <X11/Xaw/Command.h> #include <X11/Xaw/Dialog.h> static XtAppContext app_con; Widget toplevel; static int return_button = 0; static void return_key(); static String fallback_resources[] = { "*string*Dialog*translations: #override\\n \ <Key>Return: ReturnKey()", NULL }; static XtActionsRec actionTable[] = { { "ReturnKey", return_key }, }; /****************************************************************************** * event-recorder: To record the events independend to their * window-ids, the window-entries are converted through a * window-table, which is set after realizing the widget. * All arriving events are stored, when the popup-widget is used * for the first time. The next time, the stored events are * dispatched with exchanged window-ids. */ #define MAX_EVENTS 200 #define MAX_WINDOWS 10 static XEvent event_list[MAX_EVENTS]; static int write_index = 0; static int read_index; static Window window_table[MAX_WINDOWS]; /* stores the windows of a window-tree */ static int len; /* number of ids in the table */ /*----------------------------------------------------------------------------*/ static Window wid_to_window( wid ) int wid; { return( window_table[wid] ); } static int window_to_wid( window ) Window window; { int wid; for (wid=0;wid<len;wid++) { if (window==window_table[wid]) break; } if (wid==len) { fprintf( stderr, "window not in window-tree\n" ); return(-1); } else return( wid ); } /*--------------------*/ static void store_tree( display, window ) Display *display; Window window; { Window root, parent; Window *children; unsigned nchildren; int i; if (len==MAX_WINDOWS) { fprintf( stderr, "*** too many windows.\n" ); exit(-1); } window_table[len++] = window; XQueryTree( display, window, &root, &parent, &children, &nchildren ); for (i=0;i<nchildren;i++) { store_tree( display, children[i] ); } XFree( (char*)children ); } /*--------------------*/ void init_window_table( display, root ) Display *display; Window root; /* * constructs a table containing the window and all its subwindows * to convert the subwindows to a unique id, depending on the tree-structure. */ { len = 0; store_tree( display, root ); } /*----------------------------------------------------------------------------*/ int store_event( event ) XEvent *event; { if (write_index==MAX_EVENTS) { fprintf( stderr, "*** too many events.\n" ); exit (-1); } memcpy( &event_list[write_index], event, sizeof(XEvent) ); event_list[write_index].xany.window = window_to_wid( event->xany.window ); write_index++; return(0); } int read_event( event ) XEvent *event; { if (read_index<write_index) { memcpy( event, event_list+read_index, sizeof(XEvent) ); event->xany.window = wid_to_window( event->xany.window ); read_index++; return(0); } else return(1); } int rewind() { if (write_index) { read_index = 0; return(0); } else return(-1); } void init_event_list() { write_index = 0; read_index = 0; } /****************************************************************************** * callbacks for the buttons and for pressing the return-key */ static void button_selected( widget, client_data, call_data ) Widget widget; XtPointer client_data, call_data; { return_button = (int)client_data; } /*--------------------*/ static void return_key( widget, event, params, num_params ) Widget widget; XEvent *event; String *params; Cardinal num_params; { return_button = 0; } /****************************************************************************** * function to create a dialog-widget, execute events * and destroying the widget again. */ void do_string_query( label, default_string ) char *label; char *default_string; { Arg args[5]; Widget popup, dialog; Cardinal n; XEvent event; int root_x, root_y; /* * create the widgets and realize it */ n = 0; XtSetArg(args[n], XtNallowShellResize, True ); n++; popup = XtCreatePopupShell( "string", transientShellWidgetClass, toplevel, args, n); n = 0; XtSetArg(args[n], XtNlabel, label ); n++; XtSetArg(args[n], XtNvalue, default_string ); n++; dialog = XtCreateManagedWidget( "dialog", dialogWidgetClass, popup, args, n); XawDialogAddButton(dialog, "ok", button_selected, 0 ); XawDialogAddButton(dialog, "cancel", button_selected, 1 ); XtRealizeWidget( popup ); /* * map it. */ XtPopup(popup,XtGrabNone); return_button = -1; #ifndef RECORDER while(return_button<0) { XNextEvent( XtDisplay(popup), &event ); XtDispatchEvent( &event ); } #else { int store_mode; init_window_table( XtDisplay(popup), XtWindow(popup) ); if (rewind()) { init_event_list(); store_mode = 1; } else store_mode = 0; while(return_button<0) { if (store_mode) { XNextEvent( XtDisplay(popup), &event ); store_event( &event ); } else { if (read_event(&event)) { fprintf( stderr, "*** out of events.\n" ); exit(0); } } XtDispatchEvent( &event ); XSync( XtDisplay(popup), 0 ); } } #endif /* * ignore rest of the events to be sure that no events have to be * queued, when the recorder is working. */ XSync( XtDisplay(popup), 1 ); XtDestroyWidget( popup ); } /*----------------------------------------------------------------------------*/ main( argc, argv ) int argc; char **argv; { char *ret; int count = 0; char label[BUFSIZ]; /* * initialize the toolkit */ toplevel = XtAppInitialize(&app_con, "Test", NULL, ZERO, &argc, argv, fallback_resources, NULL, ZERO); if (!toplevel) exit(-1); XtAppAddActions(app_con, actionTable, XtNumber(actionTable)); /* * endless loop to query strings */ while(1) { sprintf( label, "Enter String %d:", ++count ); do_string_query( label, "" ); } }