[comp.windows.x] Question on Callbacks

dan@salt.uucp (Dan Williams) (03/10/89)

	I am working in X11r3 on a sun and I am building a widget subclass
of an athena box widget.  I added a callback list for button press events
and that worked so well that I wanted to add another call back that would
do the client procedures for redrawing my graphics and be initiated from
the expose procedure in the widget.  I copied what I did for the button
press callback list and attempted to add the second callback.  The widget
subclass gave me no errors but when I attempt to do an XtPopup of  my root
I get the infamous "Segmentation fault" error and everything bombs out.
	What am I doing wrong ? 
	The following is a shar file containing a tstmain.c and 3 diff
files that give the difference of my widget BaarsBox from the Template
widget code under X11/lib/Xaw/ Template.c Template.h and TemplateP.h
and a Makefile for the set.  Run patch and compile the set to see it "run"
then produce educated analysis on where I fouled up.

_______________________________________________________________

#The following is a shar file delete all above this line before running
#through sh
echo x - tstmain.c
sed 's/^X//' >tstmain.c <<'*-*-END-of-tstmain.c-*-*'
X/* SCCS ID %W%    %G% */
X#include <stdio.h>
X#include <X11/Cardinals.h>
X#include <X11/Xlib.h>
X#include <X11/Intrinsic.h>
X#include <X11/Shell.h>
X#include <X11/StringDefs.h>
X#include "BaarsBox.h"
X#include <X11/Shell.h>
X
XWidget root_widget;            /* global toplevel shell. */
Xstatic int next_window_num = 1; /* private variable to set the window num */
X
Xvoid my_button3_hit (w,widget_winid,eventptr)
X     Widget  w;
X     caddr_t widget_winid;	/* passes parent of window */
X     caddr_t eventptr;		/* unused */
X{
X     fprintf (stderr,"got a button 3 hit\n");      
X     return;
X}
X
Xvoid expose_graphics (w,windata,call_data)
X     Widget  w;
X     caddr_t windata;	        /* passes data with window */
X     caddr_t call_data;		/* unused */
X{    
X     printf ("doing expose_graphics routine\n");
X     return;  
X}
X
Xint  make_window (toplevel,xloc,yloc,xsiz,ysiz)
X     Widget   toplevel;
X     long xloc,yloc,xsiz,ysiz;     
X{
X     Dimension          win_height,win_width;
X     int                i;
X     Widget             pop_shell,viewpane;
X     XtCallbackRec      callbacks [2];
X     XtCallbackRec      morecallbacks [2];
X     Arg                carg[10];
X     char               widget_name[20];
X     XtCallbackStatus   stat;
X     int                win_data;
X    
X     win_data = next_window_num++; /* setup window data */
X     i = 0;
X     XtSetArg( carg[i], XtNx,(Position)xloc ) ; i++;
X     XtSetArg( carg[i], XtNy,(Position)yloc ) ; i++;
X     sprintf(widget_name,"popshell%d\0",win_data);
X     pop_shell = XtCreatePopupShell(widget_name,applicationShellWidgetClass,
X                              toplevel, carg, i);
X     i = 0;
X     win_height = (Dimension) (ysiz);
X     win_width = (Dimension) (xsiz);
X     XtSetArg(carg[i],XtNheight, win_height ); i++;
X     XtSetArg(carg[i],XtNwidth, win_width ); i++;
X     viewpane =
X	  XtCreateWidget("VIEWPANE",baarsBoxWidgetClass,pop_shell,carg,i);
X     XtManageChild(viewpane);
X     /* add a call back for button 3 hits */
X     XtAddCallback(viewpane,XtNbaarsBoxCallback,(XtCallbackProc)my_button3_hit,
X		   (caddr_t)win_data);
X
X/* if this next call is commented out then this program runs */
X
X     XtAddCallback(viewpane,XtNboxExposeCallback,
X		   (XtCallbackProc)expose_graphics,(caddr_t)win_data); /*  */
X
X     stat = XtHasCallbacks(viewpane,XtNboxExposeCallback);
X     switch (stat) {
X	  case XtCallbackNoList :
X	       fprintf (stderr,"Nolist"); 
X	       break;
X	  case XtCallbackHasSome :
X	       fprintf (stderr,"HasSome\n"); 
X	       break;
X	  case XtCallbackHasNone :
X	       fprintf (stderr,"HasNone\n"); 
X	       break;
X     }
X        /* Now pop up the widget */
X
X/* here is where the error manifests itself */
X
X     XtPopup(pop_shell,XtGrabNone);
X     return(win_data);
X}
X
X  XrmOptionDescRec options[] = {
X     {"-label","*button.label",XrmoptionSepArg,NULL}
X  };
X
Xmain (argc, argv)
X     int argc;
X     char *argv [];
X{
X     
X  root_widget = XtInitialize("main","DEMO",options,XtNumber(options),
X			     &argc,argv);
X
X  make_window(root_widget, (long)300, (long)300,
X	       (long)500, (long)500);
X
X  XtMainLoop();
X}
*-*-END-of-tstmain.c-*-*
echo x - diff.c2
sed 's/^X//' >diff.c2 <<'*-*-END-of-diff.c2-*-*'
X2c2,3
X< /* $XConsortium: BaarsBox.c,v 1.2 88/10/25 17:40:25 swick Exp $ */
X---
X> 
X> /* $XConsortium: Template.c,v 1.2 88/10/25 17:40:25 swick Exp $ */
X5,6d5
X< 
X< #include <stdio.h>
X9,10c8
X< #include <X11/XawMisc.h>
X< #include "BaarsBoxP.h"
X---
X> #include "TemplateP.h"
X12,21d9
X< /* #DEFINES */
X< #define offset(field) XtOffset(BaarsBoxWidget, BaarsBox.field)
X< 
X< /* TYPEDEFS */
X< 
X< struct EventData {
X< 	XEvent *oldEvent;
X< 	int count;
X< };
X< 
X22a11
X> #define offset(field) XtOffset(TemplateWidget, template.field)
X24,28c13,14
X<     { XtNbaarsBoxCallback, XtCCallback, XtRCallback, sizeof(caddr_t),
X< 	  offset(baarsbox_callback), XtRCallback, NULL },
X<     { XtNboxExposeCallback, XtCCallback, XtRCallback, sizeof(caddr_t),
X< 	  offset(boxexpose_callback), XtRCallback, NULL },
X< };
X---
X>     { XtNtemplateResource, XtCTemplateResource, XtRTemplateResource, sizeof(char*),
X> 	  offset(resource), XtRString, "default" },
X29a16
X> };
X31,32c18
X<  /* superclass definition */
X< #define superclass   (&boxClassRec)
X---
X> static void TemplateAction(/* Widget, XEvent*, String*, Cardinal* */);
X34,44d19
X< 
X< /* GLOBALS */
X< 
X< 
X< /* EXTERNS */
X< extern void GotButton3Hit(/* Widget, XEvent*, String*, Cardinal* */);
X< 
X< static void Initialize();
X< static void Realize();
X< static void Expose_proc();
X< static void ExtractPosition();
X47,48c22,23
X<   /* {name,              procedure}, */
X<   {"GotButton3Hit",	GotButton3Hit},
X---
X>   /* {name, procedure}, */
X>     {"template",	TemplateAction},
X50,52d24
X< static char defaultTranslations[] =
X<    /*   event,       procedure   */
X<    "<Btn3Down>:   GotButton3Hit()";
X53a26,28
X> static char translations[] =
X> "<Key>:		template()	\n\
X> ";
X55,60c30,34
X< BaarsBoxClassRec baarsBoxClassRec = {
X<       /* core fields */
X<   {
X<     /* superclass		*/	(WidgetClass) &boxClassRec,
X<     /* class_name		*/	"BaarsBox",
X<     /* widget_size		*/	sizeof(BaarsBoxRec),
X---
X> TemplateClassRec templateClassRec = {
X>   { /* core fields */
X>     /* superclass		*/	(WidgetClass) &widgetClassRec,
X>     /* class_name		*/	"Template",
X>     /* widget_size		*/	sizeof(TemplateRec),
X64c38
X<     /* initialize		*/	Initialize,
X---
X>     /* initialize		*/	NULL,
X66c40
X<     /* realize function		*/	Realize,
X---
X>     /* realize			*/	XtInheritRealize,
X78c52
X<     /* expose			*/	Expose_proc,
X---
X>     /* expose			*/	NULL,
X86c60
X<     /* tm_table			*/	defaultTranslations,
X---
X>     /* tm_table			*/	translations,
X90,99d63
X<   },{
X< /* composite_class fields */
X<     /* geometry_manager   */    XtInheritGeometryManager,
X<     /* change_managed     */    XtInheritChangeManaged,
X<     /* insert_child       */    XtInheritInsertChild,
X<     /* delete_child       */    XtInheritDeleteChild,
X<     /* extension          */    NULL
X<   },{
X< /* Box class fields */
X<     /* empty              */    0,
X101,104c65,66
X< 
X< 	  /* BaarsBox fields */
X<   {
X<     /* empty		*/	0,
X---
X>   { /* template fields */
X>     /* empty			*/	0
X108,224c70
X< WidgetClass baarsBoxWidgetClass = (WidgetClass)&baarsBoxClassRec;
X< 
X< /* FUNCTIONS */
X< 
X< 
X< static void Initialize(request,new)
X<      Widget request, new;
X< {
X<      BaarsBoxWidget newbbw = (BaarsBoxWidget)new;
X<      BaarsBoxWidget rw = (BaarsBoxWidget)request;
X<      XtCallbackStatus stat;
X<      
X<      fprintf (stderr,"In the Initialize\n"); 
X< 
X< 
X< }
X< 
X< static void Realize(widget, value_mask, attributes)
X<     Widget widget;/* ARGSUSED */
X<     XtValueMask *value_mask;
X<     XSetWindowAttributes *attributes;
X< {
X<     *value_mask |= CWBitGravity;
X<     attributes->bit_gravity = NorthWestGravity;
X<     XtCreateWindow(widget, (unsigned int)CopyFromParent, 
X< 		   (Visual *)CopyFromParent, *value_mask, attributes);
X<         XSelectInput(XtDisplay(widget),XtWindow(widget), ButtonPressMask |
X< 		  ButtonReleaseMask | ButtonMotionMask |
X< 		  PointerMotionHintMask | ExposureMask);
X< } 
X< 
X< static void Expose_proc(widget,event,region)
X<      Widget widget;
X<      XEvent event;
X<      Region region;
X< {
X<      fprintf (stderr,"Got an Expose call\n"); 
X<      
X<      XtCallCallbacks(widget,XtNboxExposeCallback,(caddr_t)0);
X< 				/*  */
X< }
X< 
X< static Boolean CompareEvents( oldEvent, newEvent )
X<     XEvent *oldEvent, *newEvent;
X< {
X< #define Check(field) if (newEvent->field != oldEvent->field) return False;
X< 
X<     Check(xany.display);
X<     Check(xany.type);
X<     Check(xany.window);
X< 
X<     switch( newEvent->type ) {
X<       case MotionNotify:
X< 		Check(xmotion.state); break;
X<       case ButtonPress:
X<       case ButtonRelease:
X< 		Check(xbutton.state);
X< 		Check(xbutton.button); break;
X<       case KeyPress:
X<       case KeyRelease:
X< 		Check(xkey.state);
X< 		Check(xkey.keycode); break;
X<       case EnterNotify:
X<       case LeaveNotify:
X< 		Check(xcrossing.mode);
X< 		Check(xcrossing.detail);
X< 		Check(xcrossing.state); break;
X<     }
X< #undef Check
X< 
X<     return True;
X< }
X< 
X< static Boolean PeekNotifyEvent( dpy, event, args )
X<     Display *dpy;
X<     XEvent *event;
X<     char *args;
X< {
X<     struct EventData *eventData = (struct EventData*)args;
X< 
X<     return ((++eventData->count == QLength(dpy)) /* since PeekIf blocks */
X< 	    || CompareEvents(event, eventData->oldEvent));
X< }
X< 
X< static Boolean LookAhead( w, event )
X<     Widget w;
X<     XEvent *event;
X< {
X<     XEvent newEvent;
X<     struct EventData eventData;
X< 
X<     if (QLength(XtDisplay(w)) == 0) return False;
X< 
X<     eventData.count = 0;
X<     eventData.oldEvent = event;
X< 
X<     XPeekIfEvent(XtDisplay(w), &newEvent, PeekNotifyEvent, (char*)&eventData);
X< 
X<     if (CompareEvents(event, &newEvent))
X< 	return True;
X<     else
X< 	return False;
X< }
X< 
X< void GotButton3Hit (gw, event, params, num_params )
X<    Widget gw;
X<    XEvent *event;
X<    String *params;		/* unused */
X<    Cardinal *num_params;	/* unused */
X< {
X<     BaarsBoxWidget w = (BaarsBoxWidget) gw;
X<     Position x, y;
X< 
X<     if (LookAhead(gw, event)) return;
X<     XtCallCallbacks(w, XtNbaarsBoxCallback, (caddr_t)event);
X< 
X< }
X---
X> WidgetClass templateWidgetClass = (WidgetClass)&templateClassRec;
*-*-END-of-diff.c2-*-*
echo x - diff.h2
sed 's/^X//' >diff.h2 <<'*-*-END-of-diff.h2-*-*'
X1,2d0
X< /* SCCS ID "@(#)BaarsBox.h     1.1        11/17/88" */
X< 
X5c3
X< /* $XConsortium: BaarsBox.h,v 1.2 88/10/25 17:22:09 swick Exp $ */
X---
X> /* $XConsortium: Template.h,v 1.2 88/10/25 17:22:09 swick Exp $ */
X8,9c6,7
X< #ifndef BaarsBox_h
X< #define BaarsBox_h
X---
X> #ifndef _Template_h
X> #define _Template_h
X11,12d8
X< #include <X11/Box.h>
X< 
X15c11
X<  * BaarsBox widget
X---
X>  * Template widget
X26,27d21
X<  baarsBoxCallback    Callback		Pointer		NULL
X<  boxExposeCallback   Callback		Pointer		NULL
X40,41c34
X< #define XtNbaarsBoxCallback		"baarsBoxCallback"
X< #define XtCBaarsBoxCallback		"BaarsBoxCallback"
X---
X> #define XtNtemplateResource		"templateResource"
X43,44c36
X< #define XtNboxExposeCallback		"boxExoseCallback"
X< #define XtCBoxExposeCallback		"BoxExposeCallback"
X---
X> #define XtCTemplateResource		"TemplateResource"
X46c38
X< /* declare specific BaarsBoxWidget class and instance datatypes */
X---
X> /* declare specific TemplateWidget class and instance datatypes */
X48,49c40,41
X< typedef struct _BaarsBoxClassRec*	BaarsBoxWidgetClass;
X< typedef struct _BaarsBoxRec*		BaarsBoxWidget;
X---
X> typedef struct _TemplateClassRec*	TemplateWidgetClass;
X> typedef struct _TemplateRec*		TemplateWidget;
X53c45
X< extern WidgetClass baarsBoxWidgetClass;
X---
X> extern WidgetClass templateWidgetClass;
X55c47
X< #endif  BaarsBox_h
X---
X> #endif  _Template_h
*-*-END-of-diff.h2-*-*
echo x - diffP.h2
sed 's/^X//' >diffP.h2 <<'*-*-END-of-diffP.h2-*-*'
X1,2d0
X< /* SCCS ID "@(#)BaarsBoxP.h     1.1        11/17/88" */
X< 
X5c3
X< /* $XConsortium: BaarsBoxP.h,v 1.2 88/10/25 17:37:59 swick Exp $ */
X---
X> /* $XConsortium: TemplateP.h,v 1.2 88/10/25 17:37:59 swick Exp $ */
X8,9c6,7
X< #ifndef BaarsBoxP_h
X< #define BaarsBoxP_h
X---
X> #ifndef _TemplateP_h
X> #define _TemplateP_h
X11,12c9
X< #include "BaarsBox.h"
X< 
X---
X> #include "Template.h"
X14c11
X< #include <X11/BoxP.h>	
X---
X> #include <X11/CoreP.h>
X17d13
X< 				/* no unique types */
X19,22c15
X< typedef struct
X< {
X<   int make_compiler_happy;
X< } BaarsBoxClassPart;
X---
X> #define XtRTemplateResource		"TemplateResource"
X24,30c17,19
X< typedef struct _BaarsBoxClassRec
X< {
X<   CoreClassPart	      core_class;
X<   CompositeClassPart  composite_class;
X<   BoxClassPart        box_class;
X<   BaarsBoxClassPart   baarsbox_class;
X< } BaarsBoxClassRec;
X---
X> typedef struct {
X>     int empty;
X> } TemplateClassPart;
X32c21,24
X< extern BaarsBoxClassRec baarsBoxClassRec;
X---
X> typedef struct _TemplateClassRec {
X>     CoreClassPart	core_class;
X>     TemplateClassPart	template_class;
X> } TemplateClassRec;
X34,40c26
X< typedef struct
X< {
X<   /* resources */
X<   XtCallbackList baarsbox_callback;
X<   XtCallbackList boxexpose_callback;
X<   /* private state */
X< } BaarsBoxPart;
X---
X> extern TemplateClassRec templateClassRec;
X42,46c28,32
X< typedef struct _BaarsBoxRec
X< {
X<   CorePart	core;
X<   BaarsBoxPart	BaarsBox;
X< } BaarsBoxRec;
X---
X> typedef struct {
X>     /* resources */
X>     char* resource;
X>     /* private state */
X> } TemplatePart;
X48c34,39
X< #endif  BaarsBoxP_h
X---
X> typedef struct _TemplateRec {
X>     CorePart		core;
X>     TemplatePart	template;
X> } TemplateRec;
X> 
X> #endif  _TemplateP_h
*-*-END-of-diffP.h2-*-*
echo x - Makefile
sed 's/^X//' >Makefile <<'*-*-END-of-Makefile-*-*'
X# Dan's personal makefile for his test and development area 
X#
XCC = /bin/cc
XINC_DIR = /usr/xbaars/include
XTEST_INC_DIR = /u1/dan/X/VIEW
XLIBS = -lXaw -lXmu -lXt -lX11 -lm
XEWO_DIR = /usr/xbaars/src/ewo/
XMENU_DIR = /usr/xbaars/src/xmenu/
XCFLAGS = -g
XCC = cc
XLIBS = -lXaw -lXmu -lXt -lX11 -lm
X
X
X#############################################################################
Xall	:	tst
X
Xtst	:  tstmain.o BaarsBox.o 
X	$(CC) tstmain.o BaarsBox.o -o tst $(CFLAGS) $(LIBS)
X
Xclean	:
X	rm -f *.o core tst 
X
Xtstmain.o : tstmain.c
X	$(CC) -c $(CFLAGS) $*.c 
X
XBaarsBox.o : BaarsBox.c BaarsBox.h BaarsBoxP.h
X	$(CC) -c $(CFLAGS) $*.c 
X
*-*-END-of-Makefile-*-*
exit

kit@ATHENA.MIT.EDU (Chris D. Peterson) (03/11/89)

> I get the infamous "Segmentation fault" error and everything bombs out.
> 	What am I doing wrong ? 

Saber C to the rescue...

In your Private header file the definition for the instance record for
you widget is:

typedef struct _BaarsBoxRec
{
  CorePart	  core;
  BaarsBoxPart	  BaarsBox;
} BaarsBoxRec;

It should be:

typedef struct _BaarsBoxRec
{
  CorePart	  core;
  CompositePart   composite;
  BoxPart 	  box;
  BaarsBoxPart	  BaarsBox;
} BaarsBoxRec;

Since you are leaving out some of the fields the XtOffset() macro gets
confused and when you specify a resource (In this case a callback list with
XtAddCallback) it scribbles all over your instance record.  In your case it
was setting the number of children to some garbage value, and thus running off
the end of an array, causing a seg. fault.

						Chris D. Peterson     
						MIT X Consortium /
						Project Athena 

Net:	kit@athena.mit.edu		
Phone: (617) 253 - 1326			
USMail: MIT - Room E40-321
	77 Massachusetts Ave.		
	Cambridge, MA 02139