From: inb@creare.creare.com (Ian Brown)
Newsgroups: comp.windows.x,comp.windows.x.motif
Subject: Too many push buttons?
Date: 14 Sep 92 19:08:45 GMT
Reply-To: inb@creare.UUCP (Ian Brown)
Organization: Creare Inc., Hanover, NH


The program included at the end of this file crashes with core dumps on two
machines (an HP running HPUX 8.0 and a Masscomp, both running Motif 1.1, and
X11R4.)  It appears that trying to create more than about 256 (258 seems to be
the trigger point) children of a row column causes problems in the pulldown
widget code.  Does anyone have any ideas (like, is this an X bug or what)?

Compile and link with Motif and X.  To run, type '<program> 774'.  This should
attempt to create 258 push buttons per row column and, for my machines at
least, crashes when I hit the pulldownButton.

------------------------------ cut here ------------------------------
# include	<stdio.h>
# include	<unistd.h>
# include	<math.h>
# include	<X11/Intrinsic.h>
# include	<X11/Shell.h>
# include	<Xm/Xm.h>
# include	<Xm/MainW.h>
# include	<Xm/RowColumn.h>
# include	<Xm/PushB.h>
# include	<Xm/CascadeB.h>
/*
  *****************************************************************
  ***								***
  ***	Name :	Xuseful.h	(Useful definitions)		***
  ***	By   :	Ian Brown	(Creare Inc., Hanover, NH)	***
  ***	For  :	Games						***
  ***	Date :	May, 1992					***
  ***								***
  ***	Description :						***
  ***	   Useful X related definitions.			***
  ***								***
  *****************************************************************
*/

# ifndef Xuseful_defined
#  define Xuseful_defined

/*
   Widget Resource Argument macros:
 
   By including this file at the beginning of each module in which argument
   setting is to be done, one can use a global store of arguments, with a
   global argument counter.  Note that since these are global, only one set of
   arguments can be prepared at one time (careful not to nest argument
   setting unless you mean to).  Each time you need to set arguments, call
   INIT_ARGS, followed by SET_ARG calls.  When using a widget creation routine
   or a set or get values routine, use ARGS in place of the argument list and 
   argument counter.
 
   If you are reusing argument lists (perhaps modifying a few resources only
   each time), it may be wiser to create your own.

   If not setting any args for a particular call, just call INIT_ARGS and pass
   in ARGS. (Don't forget to call INIT_ARGS).

   Make sure not to exceed the ___MAX_ARGS value that you set!
*/

#  define ___MAX_ARGS		50
#  define INIT_ARGS		(___num_args = 0)
#  define SET_ARG(a,b) \
	 { \
	    XtSetArg(___args[___num_args], (a), (XtArgVal)(b)); \
	    ___num_args++; \
	 }
#  define ARGS			___args, ___num_args

   static Arg			___args[___MAX_ARGS];
   static Cardinal		___num_args;

#  define HandlePendingEvents() \
	 { \
	    XEvent	event; \
	    while (XtPending()) { \
	       XtNextEvent(&event); \
	       XtDispatchEvent(&event); \
	    } \
	 }

#  define Sensitize(button,state) \
	 { \
	    ___num_args = 0; \
	    XtSetArg(___args[___num_args],XmNsensitive,state); \
	    ___num_args++; \
	    XtSetValues(button,ARGS); \
	 }
# endif




static void exitCallback(widget,data1,data2)

   Widget	widget;
   caddr_t	data1,
		data2;

{
   exit(0);
}

main(argc,argv)

   int		argc;
   String	argv[];

{
   XmString	label;
   char		string[256];
   Widget	shell,
		mainW,
		menuBar,
		workArea,
		workSubAreas[3],
		pulldown,
		button;
   XtAppContext	appcontext;
   Display	*display;
   int		idx,idx1,
		columns;


   INIT_ARGS;
   shell = XtAppInitialize(&appcontext,"Test",NULL,0,&argc,argv,NULL,ARGS);
   display = XtDisplay(shell);

   INIT_ARGS;
   mainW = XmCreateMainWindow(shell,"mainW",ARGS);

   INIT_ARGS;
   menuBar = XmCreateMenuBar(mainW,"menuBar",ARGS);
   XtManageChild(menuBar);

   INIT_ARGS;
   button = XmCreateCascadeButton(menuBar,"exitButton",ARGS);
   XtManageChild(button);
   XtAddCallback(button,XmNactivateCallback,exitCallback,NULL);

   INIT_ARGS;
   pulldown = XmCreatePulldownMenu(menuBar,"pulldownMenu",ARGS);
   for (idx = 0; idx < 4; ++idx) {
      sprintf(string,"pulldownButton%d",idx);
      INIT_ARGS;
      button = XmCreateCascadeButton(pulldown,string,ARGS);
      XtManageChild(button);
   }
   INIT_ARGS;
   SET_ARG(XmNsubMenuId,pulldown);
   button = XmCreateCascadeButton(menuBar,"pulldownButton",ARGS);
   XtManageChild(button);

   XtManageChild(menuBar);

   INIT_ARGS;
   SET_ARG(XmNpacking,XmPACK_COLUMN);
   workArea = XmCreateRowColumn(mainW,"workArea",ARGS);
   columns = (int) sqrt(atof(argv[1])/3.);
   if (columns > 10)
      columns = 10;
   for (idx1 = 0; idx1 < 3; ++idx1) {
      sprintf(string,"workSubArea%d",idx1);
      INIT_ARGS;
      SET_ARG(XmNpacking,XmPACK_COLUMN);
      SET_ARG(XmNnumColumns,columns);
      SET_ARG(XmNorientation,XmHORIZONTAL);
      workSubAreas[idx1] = XmCreateRowColumn(workArea,string,ARGS);
      for (idx = 0; idx < (atoi(argv[1]) + idx1)/3; ++idx) {
	 sprintf(string,"%d%%d",idx1,idx);
	 INIT_ARGS;
	 button = XmCreatePushButton(workSubAreas[idx1],string,ARGS);
	 XtManageChild(button);
      }
   }
   XtManageChildren(workSubAreas,3);
   XtManageChild(workArea);

   XmMainWindowSetAreas(mainW,menuBar,NULL,NULL,NULL,workArea);
   XtManageChild(mainW);
   XtRealizeWidget(shell);

   XtAppMainLoop(appcontext);
}
-- 
Ian Brown
inb@creare.com
Newsgroups: comp.windows.x