v08i004: Ball 2.0, Part01/01

Dave Nedde daven at maxine.wpi.edu
Wed Jun 27 16:39:31 AEST 1990


Submitted-by: daven at maxine.wpi.edu (Dave Nedde)
Posting-number: Volume 8, Issue 4
Archive-name: ball2/part01

This is xball V2.0.  Improvements include:
  - Athena widget interface (For either X11 R3 or X11 R4)
  - Dynamic gravity and elasticity adjustment via scrollbars
  - Colored balls work correctly now
  - Additional ball creation algorithms via buttons 2 & 3

As a bonus, A DrawingArea widget for use with Athena widgets
is included, with documentation.  This widget is modeled after
Motif's DrawingArea widget, defining callbacks for input, resizing,
pointer movement, and exposure.  See DrawingA.doc for documentation.

Please send me any comments, suggestions, ideas, and fixes.

  -Dave Nedde

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	xball
# This archive created: Thu Jun 21 09:55:32 1990
export PATH; PATH=/bin:$PATH
if test ! -d 'xball'
then
	echo shar: creating directory "'xball'"
	mkdir 'xball'
fi
echo shar: entering directory "'xball'"
cd 'xball'
echo shar: extracting "'Makefile'" '(294 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X
X#R3 = -DX11_R3  # Use this if you have X11 R3 installed
XCFLAGS = -O -DDELAY=1000 $(R3)
X
X
Xxball:	xball.c DrawingA.h DrawingA.o
X	$(CC) $(CFLAGS) -o xball xball.c DrawingA.o -lXaw -lXmu -lXt -lX11
X
XDrawingA.o: DrawingA.c DrawingA.h DrawingAP.h
X
Xclean:
X	rm -f core xball xball.o DrawingA.o *~ #*
X	
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'README'" '(1206 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
XXBall V2.0 - By David Nedde  6/15/90
X
XInfo:
X  This X11 program allows you to throw balls around in the window.
X  Hold down mouse button 1 to create a ball, then throw the ball
X  by moving the pointer and letting go of the button.  The ball
X  will be going the speed of the pointer at release time.
X  Hold down button 2 and move the mouse to create random velocity balls.
X  Hold down button 3 and move the mouse to create zero velocity balls. 
X  On color displays the balls are different, random colors.
X
XCompiling:
X  Uncomment the R3 variable in the Makefile if you are compiling on an 
X  X11 R3 machine.  Decrease the DELAY define in the Makefile if XBall
X  runs too slow on your machine.
X
XOptions:
X  Standard X11 options
X
XCopying:
X  Copyright 1990, David Nedde
X 
X  XBall is released into the public domain.
X  Permission to use, copy, modify, and distribute this
X  software and its documentation for any purpose and without
X  fee provided that the above copyright notice appears in all copies.
X  It is provided "as is" without express or implied warranty.
X
XHappy bouncing!
X
X--
XDavid Nedde, Computer Science Dept.	daven at maxine.wpi.edu
XWorcester Polytecnic Institute		(508) 831-5117/5668
XWorcester, MA 01609
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'xball.c'" '(35731 characters)'
if test -f 'xball.c'
then
	echo shar: will not over-write existing file "'xball.c'"
else
sed 's/^X//' << \SHAR_EOF > 'xball.c'
X/* XBall.c - Written by David Nedde (daven at maxine.wpi.edu) 6/15/90
X/* Features: Athena widget interface
X/*	     Item collision detection
X/*           Window resize -> boundry change
X/*	     Randomly colored balls
X/*	     Different ball creation algorithms
X/*
X/* Copyright 1990, David Nedde
X/*
X/* XBall is released into the public domain.
X/* Permission to use, copy, modify, and distribute this
X/* software and its documentation for any purpose and without fee
X/* is granted provided that the above copyright notice appears in all copies.
X/* It is provided "as is" without express or implied warranty.
X*/
X
X#include <string.h>
X#include <X11/Intrinsic.h>
X#include <X11/StringDefs.h>
X#include <X11/Xutil.h>
X#include <X11/Shell.h>
X#include "DrawingA.h"
X#ifdef X11_R3
X#include <X11/Form.h>
X#include <X11/Command.h>
X#include <X11/Scroll.h>
X#include <X11/AsciiText.h>
X#else
X#include <X11/Xaw/Form.h>
X#include <X11/Xaw/Command.h>
X#include <X11/Xaw/Scrollbar.h>
X#include <X11/Xaw/AsciiText.h>
X#endif
X
Xvoid  quit();			/* Quit button callback */
Xvoid  clear();			/* Clear button callback */
Xvoid  about();			/* About button callback */
Xvoid  author();			/* Author button callback */
Xvoid  change_gravity();		/* Gravity scrollbar JumpProc callback */
Xvoid  scroll_gravity();		/* Gravity scrollbar ScrollProc callback */
Xvoid  change_elasticity();	/* Elasticity scrollbar JumpProc callback */
Xvoid  scroll_elasticity();	/* Elasticity scrollbar ScrollProc callback */
Xint   background_processing();	/* Background processing callback */
Xvoid  redisplay();		/* DrawingArea canvas redisplay callback */
Xvoid  resize();			/* DrawingArea canvas resize callback */
Xvoid  process_input();		/* DrawingArea canvas input callback */
Xvoid  process_motion();		/* DrawingArea canvas motion callback */
X
X#define ABS(x) ((x) < 0 ? -(x) : (x))
X#define MIN(x,y) ((x) > (y) ? (y) : (x))
X#define SWAP(x,y,type) { type t; t = (x); (x) = (y); (y) = t; }
X#define INTFAC	16	/* Multiplied to everything but velocities */
X#define	MULI(x)	((x)*INTFAC)
X#define	DIVI(x)	((x)/INTFAC)
X
X#define MOTION_MODE 1	/* Ball creation modes for get_velocity() */
X#define RANDOM_MODE 2
X#define STILL_MODE  3
X
X#define MAX_ITEM	500		/* Max items on the screen */
X#define MAX_COLORS	200		/* Max colors allocated */
X#define GRAVITY		MULI(3)		/* Default gravity */
X#define MAX_GRAVITY	(5*GRAVITY)	/* Max gravity allowable */
X#define ELASTICITY	10		/* Default elasticity */
X#define MAX_ELASTICITY  (10*ELASTICITY)	/* Max elasticity */
X
X#define ITEM_WIDTH  10		/* The item's size */
X#define ITEM_HEIGHT 10
X#define WIN_HEIGHT 400		/* Default window's size */
X#define WIN_WIDTH  500
X
X#ifdef X11_R3
Xtypedef char *XtPointer;
X#define XawScrollbarSetThumb XtScrollBarSetThumb
X#endif
X
X
X/* Holds window information */
Xtypedef struct {
X  Widget   w;
X  Colormap colormap;
X  GC       set_gc;		/* Draw item */
X  GC       unset_gc;		/* Erase item */
X  GC       clear_gc;		/* Draw in background color */
X  GC	   color_gc;
X  int	   monochrome;		/* True if screen is monochrome */
X} win_info_type;
X
X/* Holds one item's position and velocity */
Xstruct item_struct { 
X  int	x,y;		/* Location of item */
X  int	y_velocity;	/* vel < 0 means dropping, > 0 means climbing */
X  int	x_velocity;	/* vel < 0 means to left, > 0 means to right */
X  char	valid;		/* TRUE if item is valid */
X  int	rebounded;	/* Used to determine if item collision */
X                        /* had already been calculated for this item */
X  int	p_index;	/* Index of pixel map to use for drawing item */
X};
X
Xtypedef struct data_package_struct {
X  win_info_type     *winfo_ptr;			/* Holds window info */
X  struct item_struct item_list[MAX_ITEM];	/* Holds all items */
X  Pixmap   pixmaps[ MAX_COLORS];		/* Holds all ball drawings */
X  int      item_index;       /* Points to next unused item in item_list */
X  int      max_color; 	     /* Holds number of colors/pixmaps used */
X  int      curr_pixmap;      /* Holds pixmap index to use for next ball */
X  /**********************************************************************
X   * Used to calculate velocity when a item is let go.
X   * save_newx,save_newy is the most recent motion position
X   * from the pointer.  save_oldx,save_oldy is the next oldest
X   ***********************************************************************/
X  int	   save_oldx, save_oldy, save_newx, save_newy;
X  int	   button1_pressed,button2_pressed,button3_pressed;
X  int      right_wall; /* Locations of room structures */
X  int      left_wall;
X  int      ceiling;
X  int      floor;
X  int	   gravity;	/* Current gravity */
X  int	   elasticity;	/* current elasticity */
X} datap_type;
X
X
X/*** Start of main program ***/
Xmain(argc,argv)
Xint    argc;
Xchar **argv;
X{
X  datap_type	 datap;
X  win_info_type  win_info;
X  Widget   toplevel;		/* The core widget */
X  Widget   form_widget;		/* Holds stuff together */
X  Widget   title;		/* Title widget */
X  Widget   title1;		/* Second title widget */
X  Widget   quit_button;		/* Quit button */
X  Widget   clear_button;	/* Clear button */
X  Widget   grav_label;		/* Gravity scroll bar label */
X  Widget   gravity_bar;		/* Gravity scroll bar */
X  Widget   elas_label;		/* Elasticity scroll bar label */
X  Widget   elasticity_bar;	/* Elasticity scroll bar */
X  Widget   canvas_widget;	/* Where balls are drawn */
X  Arg      wargs[10];		/* Used to set widget resources */
X  int      n;
X
X
X  datap.item_index = 0;			/* No items yet */
X  datap.winfo_ptr  = &win_info;
X  datap.right_wall = MULI(WIN_WIDTH);	/* Locations of room structures */
X  datap.left_wall  = 0;
X  datap.ceiling    = 0;
X  datap.floor      = MULI(WIN_HEIGHT);
X  datap.gravity	   = GRAVITY;
X  datap.elasticity = ELASTICITY;
X  datap.button1_pressed = FALSE;
X  datap.button2_pressed = FALSE;
X  datap.button3_pressed = FALSE;
X
X  toplevel = XtInitialize(argv[0],"XBall", NULL, 0, &argc, argv);
X
X  win_info.w = toplevel;
X  setup_win_info( toplevel, &win_info);
X
X
X  /* Setup a different colored item for each available color */
X  if (win_info.monochrome)
X  {
X    datap.max_color = 0;
X
X    /* Create pixmap for item */
X    datap.pixmaps[datap.max_color] = XCreatePixmap( XtDisplay(toplevel), 
X				       DefaultRootWindow(XtDisplay(toplevel)),
X				       ITEM_WIDTH, ITEM_HEIGHT,
X				       DefaultDepth( XtDisplay(toplevel), 
X						     XtWindow(toplevel)));
X    /* Clear pixmap */
X    XFillRectangle(XtDisplay(toplevel), datap.pixmaps[datap.max_color], 
X		   win_info.clear_gc, 0, 0, ITEM_WIDTH, ITEM_HEIGHT);
X    /* Draw item */
X    XDrawArc(XtDisplay(toplevel), datap.pixmaps[datap.max_color],
X	     win_info.set_gc,0,0, ITEM_WIDTH-1,ITEM_HEIGHT-1,0,360*64);
X    XFillArc(XtDisplay(toplevel), datap.pixmaps[datap.max_color],
X	     win_info.set_gc,0,0, ITEM_WIDTH-1,ITEM_HEIGHT-1,0,360*64);
X    datap.max_color++;
X  }
X  else
X  {
X    XColor   color;
X    int      cells[10];
X    int	     back_g;
X    int      max_colors;
X
X
X    max_colors = MIN(DisplayCells(XtDisplay(toplevel), 
X				  DefaultScreen(XtDisplay(toplevel))), 
X		     MAX_COLORS);
X    back_g = WhitePixel(XtDisplay(toplevel),
X			DefaultScreen(XtDisplay(toplevel)));
X
X    color.flags = DoRed | DoGreen | DoBlue;
X    datap.curr_pixmap = 0;
X    for (datap.max_color = 0; datap.max_color < max_colors; datap.max_color++)
X    {
X      if (!XAllocColorCells( XtDisplay(toplevel),win_info.colormap, TRUE, NULL,
X			    0, cells,1))
X	break; /* Can't allocate any more colors */
X
X      color.red   = random()%65535;
X      color.green = random()%65535;
X      color.blue  = random()%65535;
X      color.pixel = cells[0];
X      XStoreColor( XtDisplay(toplevel), win_info.colormap, &color);
X
X      /* Create pixmap for item */
X      datap.pixmaps[datap.max_color] = 
X	XCreatePixmap(XtDisplay(toplevel), 
X		      DefaultRootWindow(XtDisplay(toplevel)), 
X		      ITEM_WIDTH, ITEM_HEIGHT,
X		      DefaultDepth(XtDisplay(toplevel), XtWindow(toplevel)));
X      /* Clear pixmap */
X      XFillRectangle(XtDisplay(toplevel),datap.pixmaps[datap.max_color], 
X		     win_info.clear_gc, 0, 0, ITEM_WIDTH, ITEM_HEIGHT);
X      /* Draw item */
X      XSetForeground(XtDisplay(toplevel), win_info.color_gc, 
X		     color.pixel ^ back_g);
X      XDrawArc(XtDisplay(toplevel), datap.pixmaps[datap.max_color],
X	       win_info.color_gc, 0, 0, ITEM_WIDTH-1,ITEM_HEIGHT-1,0,360*64);
X      XFillArc(XtDisplay(toplevel), datap.pixmaps[datap.max_color],
X	       win_info.color_gc, 0, 0, ITEM_WIDTH-1,ITEM_HEIGHT-1,0,360*64);
X    }
X  }
X
X  XSetFunction( XtDisplay(toplevel), win_info.set_gc, GXxor);
X  XCopyGC(XtDisplay(toplevel),win_info.set_gc,0x3fffffL,win_info.unset_gc);
X
X
X  n = 0;
X  form_widget = XtCreateManagedWidget("form", formWidgetClass, toplevel,
X				      wargs,n);
X  
X  n = 0;
X  XtSetArg(wargs[n],XtNlabel,"XBall V2.0    ");		n++;
X  title = XtCreateManagedWidget("Title", commandWidgetClass, form_widget,
X				wargs,n);
X  XtAddCallback(title,XtNcallback,about,NULL);
X
X  n = 0;
X  XtSetArg(wargs[n],XtNlabel,"by David Nedde");		n++;
X  XtSetArg(wargs[n],XtNfromVert,title);			n++;
X  title1 = XtCreateManagedWidget("Title1", commandWidgetClass,
X				 form_widget,wargs,n);
X  XtAddCallback(title1,XtNcallback,author,NULL);
X
X  n = 0;
X  XtSetArg(wargs[n],XtNlabel,"Quit ");			n++;
X  XtSetArg(wargs[n],XtNfromHoriz,title);		n++;
X  quit_button = XtCreateManagedWidget("Quit", commandWidgetClass,
X				      form_widget,wargs,n);
X  XtAddCallback(quit_button,XtNcallback,quit,NULL);
X
X  n = 0;
X  XtSetArg(wargs[n],XtNfromHoriz,title1);		n++;
X  XtSetArg(wargs[n],XtNfromVert,quit_button);		n++;
X  clear_button = XtCreateManagedWidget("Clear", commandWidgetClass,
X				       form_widget,wargs,n);
X  XtAddCallback(clear_button,XtNcallback,clear,&datap);
X
X  n = 0;
X  XtSetArg(wargs[n],XtNlabel,"Gravity   ");		n++;
X  XtSetArg(wargs[n],XtNborderWidth,0);			n++;
X  XtSetArg(wargs[n],XtNfromHoriz,quit_button);		n++;
X  XtSetArg(wargs[n],XtNhorizDistance,30);		n++;
X  grav_label = XtCreateManagedWidget("GravLabel", labelWidgetClass,
X				     form_widget,wargs,n);
X
X  n = 0;
X  XtSetArg(wargs[n],XtNlength,100);			n++;
X  XtSetArg(wargs[n],XtNorientation,XtorientHorizontal);	n++;
X  XtSetArg(wargs[n],XtNfromHoriz,grav_label);		n++;
X  gravity_bar = XtCreateManagedWidget("GravityBar", scrollbarWidgetClass,
X				      form_widget,wargs,n);
X  XtAddCallback(gravity_bar,XtNjumpProc,change_gravity,&datap);
X  XtAddCallback(gravity_bar,XtNscrollProc,scroll_gravity,&datap);
X  XawScrollbarSetThumb(gravity_bar,(float)GRAVITY/MAX_GRAVITY, 0.1);
X
X  n = 0;
X  XtSetArg(wargs[n],XtNlabel,"Elasticity");		n++;
X  XtSetArg(wargs[n],XtNborderWidth,0);			n++;
X  XtSetArg(wargs[n],XtNfromHoriz,clear_button);		n++;
X  XtSetArg(wargs[n],XtNfromVert,grav_label);		n++;
X  XtSetArg(wargs[n],XtNhorizDistance,30);		n++;
X  elas_label = XtCreateManagedWidget("ElasLabel", labelWidgetClass,
X				     form_widget,wargs,n);
X
X  n = 0;
X  XtSetArg(wargs[n],XtNfromVert,gravity_bar);		n++;
X  XtSetArg(wargs[n],XtNfromHoriz,elas_label);		n++;
X  XtSetArg(wargs[n],XtNorientation,XtorientHorizontal);	n++;
X  XtSetArg(wargs[n],XtNlength,100);			n++;
X  elasticity_bar = XtCreateManagedWidget("ElasticityBar", scrollbarWidgetClass,
X					 form_widget,wargs,n);
X  XtAddCallback(elasticity_bar,XtNjumpProc,change_elasticity,&datap);
X  XtAddCallback(elasticity_bar,XtNscrollProc,scroll_elasticity,&datap);
X  XawScrollbarSetThumb(elasticity_bar,(1.0 - (float)ELASTICITY/MAX_ELASTICITY),
X		       0.1);
X
X  n = 0;
X  XtSetArg(wargs[n],XtNwidth, WIN_WIDTH);		n++;
X  XtSetArg(wargs[n],XtNheight,WIN_HEIGHT);		n++;
X  XtSetArg(wargs[n],XtNfromVert,clear_button);		n++;
X  canvas_widget = XtCreateManagedWidget("canvas", drawingAreaWidgetClass,
X					form_widget,wargs,n);
X  XtAddCallback(canvas_widget,XtNexposeCallback,redisplay,&datap);
X  XtAddCallback(canvas_widget,XtNinputCallback, process_input,&datap);
X  XtAddCallback(canvas_widget,XtNmotionCallback,process_motion,&datap);
X  XtAddCallback(canvas_widget,XtNresizeCallback,resize,&datap);
X  win_info.w = canvas_widget;
X
X  XtAddWorkProc(background_processing, &datap);
X
X  XtRealizeWidget(toplevel);
X
X  XtMainLoop();
X}
X
X
X/**********************************************************************
X * Setup_win_info - Setup the window info
X **********************************************************************/
Xsetup_win_info(w, winfo_ptr)
XWidget         w;
Xwin_info_type *winfo_ptr;
X{
X  int  		fore_g,back_g; 	/* Fore and back ground pixels */
X
X
X  /*** Start of code ***/
X  back_g = WhitePixel(XtDisplay(w),DefaultScreen(XtDisplay(w)));
X  fore_g = BlackPixel(XtDisplay(w),DefaultScreen(XtDisplay(w)));
X
X  /* Create drawing and erasing GC */
X				       
X
X  winfo_ptr->set_gc = XCreateGC(XtDisplay(w), DefaultRootWindow(XtDisplay(w)),
X				0, 0);
X  XSetBackground(XtDisplay(w), winfo_ptr->set_gc, 0);
X  XSetForeground(XtDisplay(w), winfo_ptr->set_gc, fore_g ^ back_g);
X  XSetGraphicsExposures(XtDisplay(w),winfo_ptr->set_gc,False);
X  winfo_ptr->unset_gc = XCreateGC(XtDisplay(w),DefaultRootWindow(XtDisplay(w))
X				  , 0, 0);
X  XSetBackground(XtDisplay(w), winfo_ptr->unset_gc, 0);
X  XSetForeground(XtDisplay(w), winfo_ptr->unset_gc, fore_g ^ back_g);
X  XSetGraphicsExposures(XtDisplay(w),winfo_ptr->unset_gc,False);
X  winfo_ptr->clear_gc = XCreateGC(XtDisplay(w),DefaultRootWindow(XtDisplay(w))
X				  , 0, 0);
X  XSetBackground(XtDisplay(w), winfo_ptr->clear_gc, fore_g ^ back_g);
X  XSetForeground(XtDisplay(w), winfo_ptr->clear_gc, 0);
X  XSetGraphicsExposures(XtDisplay(w),winfo_ptr->clear_gc,False);
X  /* Setup the color GC */
X  winfo_ptr->color_gc = XCreateGC(XtDisplay(w),DefaultRootWindow(XtDisplay(w))
X				  , 0, 0);
X  XSetBackground(XtDisplay(w), winfo_ptr->color_gc, 0);
X  XSetForeground(XtDisplay(w), winfo_ptr->color_gc, fore_g ^ back_g);
X  XSetGraphicsExposures(XtDisplay(w),winfo_ptr->color_gc,False);
X
X  winfo_ptr->colormap = DefaultColormap(XtDisplay(w), 
X                                        DefaultScreen(XtDisplay(w)));
X  XSetWindowColormap( XtDisplay(w), DefaultRootWindow(XtDisplay(w)),
X                      winfo_ptr->colormap);
X  winfo_ptr->monochrome = DisplayCells( XtDisplay(w), 
X                                        DefaultScreen(XtDisplay(w))) == 2;
X}
X
X
X/* Called when DrawingArea canvas is redisplayed */
Xvoid redisplay(w, datap_ptr, call_data)
XWidget			      w;
Xdatap_type		     *datap_ptr;
XXawDrawingAreaCallbackStruct *call_data;
X{
X  int x;
X
X
X  if (call_data->event->xexpose.count == 0) /* Wait until last expose event */
X  {
X    XClearWindow( XtDisplay(w), XtWindow(w));
X    for (x = 0; x < datap_ptr->item_index; x++) /* Redraw all items */
X      XCopyArea( call_data->event->xexpose.display,
X		 datap_ptr->pixmaps[datap_ptr->item_list[x].p_index],
X		 call_data->event->xexpose.window,
X		 datap_ptr->winfo_ptr->set_gc, 0, 0, ITEM_WIDTH, ITEM_HEIGHT,
X		 DIVI(datap_ptr->item_list[x].x) - ITEM_WIDTH/2, 
X		 DIVI(datap_ptr->item_list[x].y) - ITEM_HEIGHT/2);
X  }
X}
X
X
X/* Called when DrawingArea canvas is resized */
Xvoid resize (w, datap_ptr, call_data)
XWidget			      w;
Xdatap_type		     *datap_ptr;
XXawDrawingAreaCallbackStruct *call_data;
X{
X  Arg wargs[2];
X  int n;
X  Dimension width,height;
X
X  n = 0;
X  XtSetArg(wargs[n], XtNwidth,  &width);  n++;
X  XtSetArg(wargs[n], XtNheight, &height); n++;
X  XtGetValues(w, wargs, n);
X
X  datap_ptr->right_wall = MULI(width);
X  datap_ptr->floor      = MULI(height);
X}
X
X
X/* Called when no events are in the queue */
Xint background_processing(datap_ptr)
Xdatap_type *datap_ptr;
X{
X  int x,y; 		/* Index variables */
X  int oldx,oldy;	/* Save old item position while caclculating new pos */
X
X  
X  XFlush(XtDisplay(datap_ptr->winfo_ptr->w));
X  delay(20 - datap_ptr->item_index); /* Slow down the first 20 balls */
X
X  /* Move each item on the screen */
X  for (x = 0; x < datap_ptr->item_index; x++)
X  {
X    /* See if item is valid */
X    if (!datap_ptr->item_list[x].valid)
X    {
X      /* Copy last item in list to here */
X      datap_ptr->item_index--;
X      if (x != datap_ptr->item_index)
X	datap_ptr->item_list[x] = datap_ptr->item_list[datap_ptr->item_index];
X      else
X	continue; /* Killed last item */
X    }
X
X    /* Calculate new position of item */
X    /* Save old position so we can erase it */
X    oldy = DIVI(datap_ptr->item_list[x].y);
X    oldx = DIVI(datap_ptr->item_list[x].x);
X
X    /* Calculate new y position */
X    /* Gravity adds to velocity */
X    if ((datap_ptr->item_list[x].y < datap_ptr->floor) ||
X	(datap_ptr->item_list[x].y_velocity != 0))
X      datap_ptr->item_list[x].y_velocity += DIVI(datap_ptr->gravity);
X
X    /* Move vertically based on velocity */
X    datap_ptr->item_list[x].y += datap_ptr->item_list[x].y_velocity;
X
X    if (datap_ptr->item_list[x].y >= datap_ptr->floor)
X    {
X      /* item hit floor -- bounce off floor */
X      datap_ptr->item_list[x].y = 2*datap_ptr->floor - 
X	datap_ptr->item_list[x].y; /* Bounce back */
X
X      datap_ptr->item_list[x].y_velocity = 
X	(-datap_ptr->item_list[x].y_velocity) + /* Rev vel */
X	  DIVI(datap_ptr->gravity);
X
X      if (ABS(datap_ptr->item_list[x].y_velocity) < datap_ptr->elasticity)
X	datap_ptr->item_list[x].y_velocity = 0;
X      else
X	/* Remove some inertia */
X	datap_ptr->item_list[x].y_velocity += datap_ptr->elasticity;
X    }
X    else
X    if (datap_ptr->item_list[x].y < datap_ptr->ceiling)
X    {
X      /* item hit ceiling */
X      datap_ptr->item_list[x].y = 2*datap_ptr->ceiling - 
X	datap_ptr->item_list[x].y; /* Bounce off */
X      datap_ptr->item_list[x].y_velocity = 
X	-datap_ptr->item_list[x].y_velocity; /* Rev dir */
X    }
X
X    /* Calculate new x position */
X    datap_ptr->item_list[x].x += 
X      datap_ptr->item_list[x].x_velocity; /* Move horiz base on vel */
X    if (datap_ptr->item_list[x].x > datap_ptr->right_wall)
X    {
X      /* Hit right wall */
X
X      datap_ptr->item_list[x].x = 2*datap_ptr->right_wall -
X	datap_ptr->item_list[x].x; /* Bounce off */
X      datap_ptr->item_list[x].x_velocity = 
X	-datap_ptr->item_list[x].x_velocity; /* Rev dir */
X    }
X    else
X    if (datap_ptr->item_list[x].x < datap_ptr->left_wall)
X    {
X      /* Hit left wall */
X      datap_ptr->item_list[x].x = 2 * datap_ptr->left_wall - 
X	datap_ptr->item_list[x].x; /* Bounce off */
X      datap_ptr->item_list[x].x_velocity = 
X	-datap_ptr->item_list[x].x_velocity; /* Rev dir */
X    }
X
X    /* See if collided with another item */
X    for (y = 0; y < datap_ptr->item_index &&
X	        datap_ptr->item_list[x].rebounded == FALSE; y++)
X      if (x != y)
X	rebound_item( &datap_ptr->item_list[x], &datap_ptr->item_list[y]);
X    datap_ptr->item_list[x].rebounded = FALSE;
X
X    /* Don't redraw if item hasn't moved */
X    if (oldx == DIVI(datap_ptr->item_list[x].x) &&
X	oldy == DIVI(datap_ptr->item_list[x].y))
X      continue; /* Item hasn't moved */
X
X    /* Erase old object */
X    XCopyArea( XtDisplay(datap_ptr->winfo_ptr->w),
X	       datap_ptr->pixmaps[datap_ptr->item_list[x].p_index],
X	       XtWindow(datap_ptr->winfo_ptr->w),
X	       datap_ptr->winfo_ptr->unset_gc, 0, 0, ITEM_WIDTH, ITEM_HEIGHT,
X	       oldx - ITEM_WIDTH/2, 
X	       oldy - ITEM_HEIGHT/2);
X
X    /* See if item has come to a peaceful rest */
X    if (ABS(datap_ptr->item_list[x].y - datap_ptr->floor) <
X	  datap_ptr->gravity/4 &&  /* on floor */
X	ABS(datap_ptr->item_list[x].y_velocity) <= 
X	  datap_ptr->elasticity*2) /* Not bouncing */
X    {
X       if (ABS(datap_ptr->item_list[x].x_velocity) < 
X	   datap_ptr->gravity/10) /* No roll */
X       {
X	 datap_ptr->item_list[x].valid = FALSE;
X	 continue; /* Don't draw item */
X       }
X
X       /* Slow down velocity once rolling */
X       if (datap_ptr->item_list[x].x_velocity > 0)
X	 datap_ptr->item_list[x].x_velocity -= DIVI(datap_ptr->gravity);
X       else
X	 datap_ptr->item_list[x].x_velocity += DIVI(datap_ptr->gravity);
X    }
X
X    /* Draw new item */
X    XCopyArea( XtDisplay(datap_ptr->winfo_ptr->w),
X	       datap_ptr->pixmaps[datap_ptr->item_list[x].p_index],
X	       XtWindow(datap_ptr->winfo_ptr->w),
X	       datap_ptr->winfo_ptr->set_gc, 0, 0, ITEM_WIDTH, ITEM_HEIGHT,
X	       DIVI(datap_ptr->item_list[x].x) - ITEM_WIDTH/2, 
X	       DIVI(datap_ptr->item_list[x].y) - ITEM_HEIGHT/2);
X  }
X  return(FALSE); /* Don't remove work procedure */
X}
X
X
X/* Called when DrawingArea canvas has input */
Xvoid process_input(w, datap_ptr, call_data)
XWidget			      w;
Xdatap_type		     *datap_ptr;
XXawDrawingAreaCallbackStruct *call_data;
X{
X  switch (call_data->event->type)
X  {
X    /* Process mouse button events */
X    case ButtonPress:
X	switch (call_data->event->xbutton.button) 
X	{
X	  case 1:  
X	    if (datap_ptr->item_index == MAX_ITEM - 1)
X	      break; /* Too many items already */
X	    datap_ptr->button1_pressed = TRUE;
X	    datap_ptr->save_oldx = datap_ptr->save_newx = 
X	      call_data->event->xbutton.x;
X	    datap_ptr->save_oldy = datap_ptr->save_newy =
X	      call_data->event->xbutton.y;
X	    /* Draw an item under the pointer */
X	    XCopyArea(call_data->event->xbutton.display,
X		      datap_ptr->pixmaps[datap_ptr->curr_pixmap],
X		       call_data->event->xbutton.window,
X		       datap_ptr->winfo_ptr->set_gc, 0, 0, 
X		       ITEM_WIDTH, ITEM_HEIGHT,
X		       call_data->event->xbutton.x - ITEM_WIDTH/2, 
X		       call_data->event->xbutton.y - ITEM_HEIGHT/2);
X	    break;
X
X	  /* Not used */
X	  case 2:  datap_ptr->button2_pressed = TRUE; break;
X	  case 3:  datap_ptr->button3_pressed = TRUE; break;
X	}
X	break;
X
X    case ButtonRelease:
X	switch (call_data->event->xbutton.button) 
X	{
X	  case 1:  
X	  {
X	    int x_vel,y_vel;
X
X	    if (datap_ptr->button1_pressed == FALSE)
X	      break; /* Item was never created */
X
X	    datap_ptr->button1_pressed = FALSE;
X
X	    /* Erase button ball */
X	    XCopyArea(call_data->event->xbutton.display,
X		      datap_ptr->pixmaps[datap_ptr->curr_pixmap],
X		       call_data->event->xbutton.window,
X		       datap_ptr->winfo_ptr->unset_gc, 0, 0, 
X		       ITEM_WIDTH, ITEM_HEIGHT,
X		       call_data->event->xbutton.x - ITEM_WIDTH/2, 
X		       call_data->event->xbutton.y - ITEM_HEIGHT/2);
X
X	    /* Create new item when button let go */
X	    get_velocity( &x_vel,&y_vel, MOTION_MODE, datap_ptr);
X	    create_item( datap_ptr->save_newx, datap_ptr->save_newy, 
X			 x_vel, y_vel, datap_ptr);
X	    XCopyArea( call_data->event->xbutton.display, 
X	        datap_ptr->
X		pixmaps[datap_ptr->item_list[datap_ptr->item_index-1].p_index],
X		   call_data->event->xbutton.window,
X		   datap_ptr->winfo_ptr->set_gc, 0, 0, ITEM_WIDTH, ITEM_HEIGHT,
X		   call_data->event->xbutton.x - ITEM_WIDTH/2, 
X		   call_data->event->xbutton.y - ITEM_HEIGHT/2);
X	    break;
X	  }
X
X	  /* Not used */
X	  case 2:  datap_ptr->button2_pressed = FALSE; break;
X	  case 3:  datap_ptr->button3_pressed = FALSE; break;
X	}
X	break;
X  }
X}
X
X
X
X/* Velocity is based on how fast the pointer is moving which is based */
X/* on the last two motion events received's delta-x and delta-y       */
Xget_velocity( x_vel_ptr, y_vel_ptr, mode, datap_ptr)
Xint        *x_vel_ptr;
Xint        *y_vel_ptr;
Xint	    mode;
Xdatap_type *datap_ptr;
X{
X  switch (mode)
X  {
X    case MOTION_MODE:
X      *x_vel_ptr = (datap_ptr->save_newx - datap_ptr->save_oldx) * 10;
X      *y_vel_ptr = (datap_ptr->save_newy - datap_ptr->save_oldy) * 10;
X      break;
X
X    case RANDOM_MODE:
X      *x_vel_ptr = (random() & 0xff) - 128;  /* Random x velocity */
X      *y_vel_ptr = (random() & 0x3f) - 128;  /* Random, but up, y vel */
X      break;
X
X    case STILL_MODE:
X      *x_vel_ptr = 0; /* No x velocity */
X      *y_vel_ptr = 0; /* No y velocity */
X      break;
X  }
X}
X
X
X/* See if items have hit and rebound them if they have */
X/* Itema is assumed to have just been moved */
Xrebound_item( itema_ptr, itemb_ptr)
Xstruct item_struct *itema_ptr, *itemb_ptr;
X{
X  int xdiff,ydiff;
X
X  xdiff = DIVI(itema_ptr->x - itemb_ptr->x);
X  ydiff = DIVI(itema_ptr->y - itemb_ptr->y);
X  if (ABS(xdiff) < ITEM_WIDTH && ABS(ydiff) < ITEM_HEIGHT)
X  {
X    itema_ptr->rebounded = TRUE; /* Mark as rebound */
X    itemb_ptr->rebounded = TRUE; /* Mark as rebound */
X
X    SWAP( itema_ptr->x_velocity, itemb_ptr->x_velocity, int);
X    SWAP( itema_ptr->y_velocity, itemb_ptr->y_velocity, int);
X
X    if (itema_ptr->y_velocity <= ITEM_WIDTH &&
X	itemb_ptr->y_velocity <= ITEM_WIDTH)
X    {
X      itema_ptr->y_velocity += ydiff;
X      itemb_ptr->y_velocity -= ydiff;
X    }
X    if (itema_ptr->x_velocity <= ITEM_WIDTH &&
X	itemb_ptr->x_velocity <= ITEM_WIDTH)
X    {
X      itema_ptr->x_velocity += xdiff;
X      itemb_ptr->x_velocity -= xdiff;
X    }
X  }
X}
X
X
X/* Initialize an item in the main data structure */
Xcreate_item(x,y, x_vel, y_vel, datap_ptr)
Xint x,y;
Xint x_vel, y_vel;
Xdatap_type *datap_ptr;
X{
X  datap_ptr->item_list[datap_ptr->item_index].x = MULI(x);
X  datap_ptr->item_list[datap_ptr->item_index].y = MULI(y);
X  datap_ptr->item_list[datap_ptr->item_index].x_velocity = x_vel;
X  datap_ptr->item_list[datap_ptr->item_index].y_velocity = y_vel;
X  datap_ptr->item_list[datap_ptr->item_index].valid = TRUE;
X  datap_ptr->item_list[datap_ptr->item_index].p_index = datap_ptr->curr_pixmap;
X  datap_ptr->curr_pixmap = (datap_ptr->curr_pixmap + 1) % datap_ptr->max_color;
X  datap_ptr->item_list[datap_ptr->item_index].rebounded = FALSE;
X
X  datap_ptr->item_index++;
X}        
X
X
X#ifndef DELAY
X#define DELAY 100
X#endif
X
Xdelay(length)
Xint length;
X{
X  int x,y,sum;
X
X
X  /* Yes, a delay loop to slow small amounts of items */
X  for (x = 0; x < length; x++)
X    for (y = 0; y < DELAY; y++)
X      sum = sum + y * x;
X
X  return(sum); /* Try to keep it from getting optimized out */
X}
X
X
X/* Called when DrawingArea canvas have pointer motion events */
Xvoid process_motion(w, datap_ptr, call_data)
XWidget			      w;
Xdatap_type		     *datap_ptr;
XXawDrawingAreaCallbackStruct *call_data;
X{
X  int x_vel,y_vel;
X
X
X  if (datap_ptr->button1_pressed)
X  {
X    /* When button 1 pressed during movement */
X    datap_ptr->save_oldx = datap_ptr->save_newx;  /* Save 'speed' */
X    datap_ptr->save_oldy = datap_ptr->save_newy;
X    datap_ptr->save_newx = call_data->event->xmotion.x;
X    datap_ptr->save_newy = call_data->event->xmotion.y;
X
X    /* Erase old object */
X    XCopyArea( call_data->event->xmotion.display,
X	      datap_ptr->pixmaps[datap_ptr->curr_pixmap],
X	       call_data->event->xmotion.window,
X	       datap_ptr->winfo_ptr->unset_gc, 0, 0, 
X	       ITEM_WIDTH, ITEM_HEIGHT,
X	       datap_ptr->save_oldx - ITEM_WIDTH/2, 
X	       datap_ptr->save_oldy - ITEM_HEIGHT/2);
X
X    /* Draw new one */
X    XCopyArea( call_data->event->xmotion.display,
X	      datap_ptr->pixmaps[datap_ptr->curr_pixmap],
X	       call_data->event->xmotion.window,
X	       datap_ptr->winfo_ptr->set_gc, 0, 0, ITEM_WIDTH, ITEM_HEIGHT,
X	       datap_ptr->save_newx - ITEM_WIDTH/2, 
X	       datap_ptr->save_newy - ITEM_HEIGHT/2);
X  }
X  else
X  if (datap_ptr->button2_pressed && datap_ptr->item_index < MAX_ITEM-1)
X  {
X    get_velocity( &x_vel,&y_vel, RANDOM_MODE, datap_ptr);
X    create_item( call_data->event->xmotion.x, call_data->event->xmotion.y,
X		 x_vel, y_vel, datap_ptr);
X    XCopyArea( call_data->event->xmotion.display, 
X	datap_ptr->
X	pixmaps[datap_ptr->item_list[datap_ptr->item_index-1].p_index],
X	   call_data->event->xmotion.window,
X	   datap_ptr->winfo_ptr->set_gc, 0, 0, ITEM_WIDTH, ITEM_HEIGHT,
X	   call_data->event->xmotion.x - ITEM_WIDTH/2, 
X	   call_data->event->xmotion.y - ITEM_HEIGHT/2);
X  }
X  else
X  if (datap_ptr->button3_pressed && datap_ptr->item_index < MAX_ITEM-1)
X  {
X    get_velocity( &x_vel,&y_vel, STILL_MODE, datap_ptr);
X    create_item( call_data->event->xmotion.x,call_data->event->xmotion.y,
X		 x_vel, y_vel, datap_ptr);
X    XCopyArea( call_data->event->xmotion.display, 
X	datap_ptr->
X	pixmaps[datap_ptr->item_list[datap_ptr->item_index-1].p_index],
X	   call_data->event->xmotion.window,
X	   datap_ptr->winfo_ptr->set_gc, 0, 0, ITEM_WIDTH, ITEM_HEIGHT,
X	   call_data->event->xmotion.x - ITEM_WIDTH/2, 
X	   call_data->event->xmotion.y - ITEM_HEIGHT/2);
X  }
X}
X
X
X/* Called when quit button pressed */
Xvoid quit(w, closure, call_data)
XWidget  w;
Xcaddr_t closure;
Xcaddr_t call_data;
X{
X  XtCloseDisplay(XtDisplay(w));
X  exit(0);
X}
X
X
X/* Called when clear button pressed */
Xvoid clear(w, datap_ptr, call_data)
XWidget      w;
Xdatap_type *datap_ptr;
Xcaddr_t     call_data;
X{
X  XClearWindow( XtDisplay(datap_ptr->winfo_ptr->w), 
X		XtWindow(datap_ptr->winfo_ptr->w));
X  datap_ptr->item_index = 0;
X}
X
X
X/* Called when gravity bar's JumpProc callback is called */
Xvoid change_gravity(w, datap_ptr, percent_ptr)
XWidget      w;
Xdatap_type *datap_ptr;
XXtPointer   percent_ptr;
X{
X  float percent = *(float *)percent_ptr;
X
X  datap_ptr->gravity = MAX_GRAVITY * percent;
X}
X
X
X/* Called when gravity bar's ScrollProc callback is called */
Xvoid scroll_gravity(w,datap_ptr,position_ptr)
XWidget	    w;
Xdatap_type *datap_ptr;
XXtPointer   position_ptr;
X{
X  Arg args[10];
X  Dimension length;
X  int n;
X  int position = (int)position_ptr;
X  float percent_change;
X
X
X  n = 0;
X  XtSetArg(args[n], XtNlength, &length); n++;
X  XtGetValues(w, args, n);
X
X  percent_change = (float)position / (length*3);
X
X  datap_ptr->gravity = datap_ptr->gravity + MAX_GRAVITY * percent_change;
X  if (datap_ptr->gravity >= MAX_GRAVITY)
X    datap_ptr->gravity = MAX_GRAVITY;
X  else
X  if (datap_ptr->gravity <= 0)
X    datap_ptr->gravity = 0;
X
X  XawScrollbarSetThumb(w,(float)datap_ptr->gravity/MAX_GRAVITY, 0.1);
X}
X
X
X/* Called when elasticity bar's ScrollProc callback is called */
Xvoid scroll_elasticity(w,datap_ptr,position_ptr)
XWidget	    w;
Xdatap_type *datap_ptr;
XXtPointer   position_ptr;
X{
X  Arg args[10];
X  Dimension length;
X  int n;
X  int position = (int)position_ptr;
X  float percent_change;
X
X
X  n = 0;
X  XtSetArg(args[n], XtNlength, &length); n++;
X  XtGetValues(w, args, n);
X
X  percent_change = (float)position / (length*3);
X
X  datap_ptr->elasticity = datap_ptr->elasticity -MAX_ELASTICITY*percent_change;
X  if (datap_ptr->elasticity > MAX_ELASTICITY)
X    datap_ptr->elasticity = MAX_ELASTICITY;
X  else
X  if (datap_ptr->elasticity < 1)
X    datap_ptr->elasticity = 1;
X
X  XawScrollbarSetThumb(w,1.0 -(float)datap_ptr->elasticity/MAX_ELASTICITY,0.1);
X}
X
X
X/* Called when elasticity bar's JumpProc callback is called */
Xvoid change_elasticity(w, datap_ptr, percent_ptr)
XWidget      w;
Xdatap_type *datap_ptr;
XXtPointer   percent_ptr;
X{
X  float percent = *(float *)percent_ptr;
X
X  /* ... + 1 is because 0 elasticity reveales algotithm deficiencies */
X  datap_ptr->elasticity = MAX_ELASTICITY * (1.0 - percent) + 1;
X}
X
Xchar *malloc();
Xchar *concat_words(n, words)
Xint   n;
Xchar *words[];
X{
X  char *str;
X  int   i, len = 0;
X
X
X  if (n <= 0)
X    return(NULL);
X
X  str = NULL;
X
X  for (i = 0; i < n; i++)
X    len += strlen(words[i]) + 1;
X
X  str = malloc(len);
X  str[0] = '\0';
X
X  for (i = 0; i < n; i++)
X    strcat(str,words[i]);
X
X  return(str);
X}
X
X
X/* Called when OK button pressed */
Xvoid finish_ok(w, popup_parent, call_data)
XWidget      w;
XWidget	    popup_parent;
Xcaddr_t     call_data;
X{
X  XtPopdown(popup_parent);
X}
X
Xvoid free_string(w, temp_str, call_data)
XWidget      w;
XWidget	   *temp_str;
Xcaddr_t     call_data;
X{
X  free(temp_str);
X}
X
X
X/* Author message */
Xstatic char *author_string[] = {
X  "XBall V2.0\n",
X  "David Nedde, Computer Science Dept.  daven at maxine.wpi.edu\n",
X  "Worcester Polytechnic Institute      (508) 831-5117/5668\n",
X  "Worcester, MA 01609\n"
X};
X
X
X/* Called when author button pressed */
Xvoid author(w, closure, call_data)
XWidget      w;
Xcaddr_t     closure;
Xcaddr_t     call_data;
X{
X  Widget popup_parent;
X  Widget form_widget;
X  Widget text_widget;
X  Widget ok_btn;
X  Widget title;
X  char  *temp_str;
X  int    n;
X  Arg	 wargs[10];
X
X  popup_parent = XtCreatePopupShell("AuthorParent",overrideShellWidgetClass,
X				    w,NULL,0);
X  n = 0;
X  form_widget = XtCreateManagedWidget("PopupForm", formWidgetClass,
X				      popup_parent,wargs,n);
X
X  n = 0;
X  XtSetArg(wargs[n],XtNlabel,"OK");				n++;
X  ok_btn = XtCreateManagedWidget("OkBtn", commandWidgetClass,
X				 form_widget,wargs,n);
X  XtAddCallback(ok_btn,XtNcallback,finish_ok,popup_parent);
X
X  n = 0;
X  XtSetArg(wargs[n],XtNborderWidth,0);				n++;
X  XtSetArg(wargs[n],XtNfromHoriz,ok_btn);			n++;
X  XtSetArg(wargs[n],XtNlabel,"XBall's Author");			n++;
X  title = XtCreateManagedWidget("Title2", labelWidgetClass,
X				form_widget,wargs,n);
X  XtAddCallback(ok_btn,XtNcallback,finish_ok,popup_parent);
X
X  temp_str = concat_words(sizeof(author_string)/sizeof(char *),author_string);
X  n = 0;
X#ifdef X11_R3
X  XtSetArg(wargs[n],XtNfromVert,ok_btn);			n++;
X  XtSetArg(wargs[n],XtNheight,100);				n++;
X  XtSetArg(wargs[n],XtNwidth,450);				n++;
X  XtSetArg(wargs[n],XtNstring,temp_str);			n++;
X  text_widget = XtCreateManagedWidget("TextWidget", asciiStringWidgetClass,
X				      form_widget,wargs,n);
X#else
X  XtSetArg(wargs[n],XtNscrollVertical,XawtextScrollWhenNeeded);	n++;
X  XtSetArg(wargs[n],XtNwrap,XawtextWrapWord);			n++;
X  XtSetArg(wargs[n],XtNfromVert,ok_btn);			n++;
X  XtSetArg(wargs[n],XtNheight,70);				n++;
X  XtSetArg(wargs[n],XtNwidth,450);				n++;
X  XtSetArg(wargs[n],XtNstring,temp_str);			n++;
X  text_widget = XtCreateManagedWidget("TextWidget", asciiTextWidgetClass,
X				      form_widget,wargs,n);
X#endif
X  XtAddCallback(text_widget,XtNdestroyCallback,free_string,temp_str);
X  
X  XtPopup(popup_parent,XtGrabNone);
X}
X
X/* About message */
Xstatic char *about_string[] = {
X  "XBall V2.0\n",
X  "Written by David Nedde 6/15/90\n\n",
X  "This program allows you to throw balls around in the window.\n",
X  "Hold down button 1 to create a ball, then throw the ball by\n",
X  "moving the pointer and letting go of the button.\n",
X  "The ball will be going the speed of the pointer at release time.\n",
X  "Hold down button 2 and move the mouse to create random velocity balls.\n",
X  "Hold down button 3 and move the mouse to create zero velocity balls.\n",
X  "On color displays the balls are different, random colors.\n\n\n",
X  "Copyright 1990, David Nedde\n\n",
X  "XBall is released into the public domain.\n",
X  "Permission to use, copy, modify, and distribute this software\n",
X  "and its documentation for any purpose and without fee is granted\n",
X  "provided that the above copyright notice appears in all copies.\n",
X  "It is provided \"as is\" without express or implied warranty.\n"
X  };
X
X/* Called when about button pressed */
Xvoid about(w, closure, call_data)
XWidget      w;
Xcaddr_t     closure;
Xcaddr_t     call_data;
X{
X  Widget popup_parent;
X  Widget form_widget;
X  Widget text_widget;
X  Widget ok_btn;
X  Widget title;
X  char  *temp_str;
X  int    n;
X  Arg	 wargs[10];
X
X  popup_parent = XtCreatePopupShell("AuthorParent",overrideShellWidgetClass,
X				    w,NULL,0);
X  n = 0;
X  form_widget = XtCreateManagedWidget("PopupForm", formWidgetClass,
X				      popup_parent,wargs,n);
X
X  n = 0;
X  XtSetArg(wargs[n],XtNlabel,"OK");				n++;
X  ok_btn = XtCreateManagedWidget("OkBtn", commandWidgetClass,
X				 form_widget,wargs,n);
X  XtAddCallback(ok_btn,XtNcallback,finish_ok,popup_parent);
X
X  n = 0;
X  XtSetArg(wargs[n],XtNborderWidth,0);				n++;
X  XtSetArg(wargs[n],XtNfromHoriz,ok_btn);			n++;
X  XtSetArg(wargs[n],XtNlabel,"About XBall");			n++;
X  title = XtCreateManagedWidget("Title2", labelWidgetClass,
X				form_widget,wargs,n);
X  XtAddCallback(ok_btn,XtNcallback,finish_ok,popup_parent);
X
X  temp_str = concat_words(sizeof(about_string)/sizeof(char *),about_string);
X  n = 0;
X#ifdef X11_R3
X  XtSetArg(wargs[n],XtNfromVert,ok_btn);			n++;
X  XtSetArg(wargs[n],XtNheight,350);				n++;
X  XtSetArg(wargs[n],XtNwidth,450);				n++;
X  XtSetArg(wargs[n],XtNstring,temp_str);			n++;
X  text_widget = XtCreateManagedWidget("TextWidget", asciiStringWidgetClass,
X				      form_widget,wargs,n);
X#else
X  XtSetArg(wargs[n],XtNfromVert,ok_btn);			n++;
X  XtSetArg(wargs[n],XtNscrollVertical,XawtextScrollWhenNeeded);	n++;
X  XtSetArg(wargs[n],XtNheight,150);				n++;
X  XtSetArg(wargs[n],XtNwidth,450);				n++;
X  XtSetArg(wargs[n],XtNwrap,XawtextWrapWord);			n++;
X  XtSetArg(wargs[n],XtNstring,temp_str);			n++;
X  text_widget = XtCreateManagedWidget("TextWidget", asciiTextWidgetClass,
X				      form_widget,wargs,n);
X#endif
X  XtAddCallback(text_widget,XtNdestroyCallback,free_string,temp_str);
X  
X  XtPopup(popup_parent,XtGrabNone);
X}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'DrawingA.c'" '(4789 characters)'
if test -f 'DrawingA.c'
then
	echo shar: will not over-write existing file "'DrawingA.c'"
else
sed 's/^X//' << \SHAR_EOF > 'DrawingA.c'
X/* DrawingA.c: The DrawingArea Widget Methods */
X
X/* Copyright 1990, David Nedde
X/*
X/* This software is released into the public domain.
X/* Permission to use, copy, modify, and distribute this
X/* software and its documentation for any purpose and without fee
X/* is granted provided that the above copyright notice appears in all copies.
X/* It is provided "as is" without express or implied warranty.
X*/
X
X#include <X11/IntrinsicP.h>
X#include <X11/StringDefs.h>
X#include "DrawingAP.h"
X
Xstatic void	Initialize();
Xstatic void	Redisplay();
Xstatic void	input_draw();
Xstatic void	motion_draw();
Xstatic void	resize_draw();
X
Xstatic char defaultTranslations[] = "<BtnDown>: input() \n <BtnUp>: input() \n <KeyDown>: input() \n <KeyUp>: input() \n <Motion>: motion() \n <Configure>: resize()";
Xstatic XtActionsRec actionsList[] = {
X  { "input",  (XtActionProc)input_draw },
X  { "motion", (XtActionProc)motion_draw },
X  { "resize", (XtActionProc)resize_draw },
X};
X
X/* Default instance record values */
Xstatic XtResource resources[] = {
X  {XtNexposeCallback, XtCCallback, XtRCallback, sizeof(caddr_t),
X     XtOffset(DrawingAreaWidget, drawing_area.expose_callbacks), 
X     XtRCallback, NULL },
X  {XtNinputCallback, XtCCallback, XtRCallback, sizeof(caddr_t),
X     XtOffset(DrawingAreaWidget, drawing_area.input_callbacks), 
X     XtRCallback, NULL },
X  {XtNmotionCallback, XtCCallback, XtRCallback, sizeof(caddr_t),
X     XtOffset(DrawingAreaWidget, drawing_area.motion_callbacks), 
X     XtRCallback, NULL },
X  {XtNresizeCallback, XtCCallback, XtRCallback, sizeof(caddr_t),
X     XtOffset(DrawingAreaWidget, drawing_area.resize_callbacks), 
X     XtRCallback, NULL },
X};
X
X
XDrawingAreaClassRec drawingAreaClassRec = {
X  /* CoreClassPart */
X{
X  (WidgetClass) &widgetClassRec,	/* superclass		  */	
X    "DrawingArea",			/* class_name		  */
X    sizeof(DrawingAreaRec),		/* size			  */
X    NULL,				/* class_initialize	  */
X    NULL,				/* class_part_initialize  */
X    FALSE,				/* class_inited		  */
X    Initialize,				/* initialize		  */
X    NULL,				/* initialize_hook	  */
X    XtInheritRealize,			/* realize		  */
X    actionsList,			/* actions		  */
X    XtNumber(actionsList),		/* num_actions		  */
X    resources,				/* resources		  */
X    XtNumber(resources),		/* resource_count	  */
X    NULLQUARK,				/* xrm_class		  */
X    FALSE,				/* compress_motion	  */
X    FALSE,				/* compress_exposure	  */
X    TRUE,				/* compress_enterleave    */
X    FALSE,				/* visible_interest	  */
X    NULL,				/* destroy		  */
X    NULL,				/* resize		  */
X    Redisplay,				/* expose		  */
X    NULL,				/* set_values		  */
X    NULL,				/* set_values_hook	  */
X    XtInheritSetValuesAlmost,		/* set_values_almost	  */
X    NULL,				/* get_values_hook	  */
X    NULL,				/* accept_focus		  */
X    XtVersion,				/* version		  */
X    NULL,				/* callback_private	  */
X    defaultTranslations,		/* tm_table		  */
X    XtInheritQueryGeometry,		/* query_geometry	  */
X    XtInheritDisplayAccelerator,	/* display_accelerator	  */
X    NULL				/* extension		  */
X  },  /* CoreClass fields initialization */
X  {
X    0,                                     /* field not used    */
X  },  /* LabelClass fields initialization */
X  {
X    0,                                     /* field not used    */
X  },  /* DrawingAreaClass fields initialization */
X};
X
X  
XWidgetClass drawingAreaWidgetClass = (WidgetClass)&drawingAreaClassRec;
X
X
Xstatic void Initialize( request, new)
XDrawingAreaWidget request, new;
X{
X  if (request->core.width == 0)
X    new->core.width = 100;
X  if (request->core.height == 0)
X    new->core.height = 100;
X}
X
X
X/* Invoke expose callbacks */
Xstatic void Redisplay(w, event, region)
XDrawingAreaWidget w;
XXEvent		 *event;
XRegion		  region;
X{
X  XawDrawingAreaCallbackStruct cb;
X
X  cb.reason = XawCR_EXPOSE;
X  cb.event  = event;
X  cb.window = XtWindow(w);
X  XtCallCallbacks(w, XtNexposeCallback, &cb);
X}
X
X/* Invoke resize callbacks */
Xstatic void resize_draw(w, event, args, n_args)
XDrawingAreaWidget w;
XXEvent		 *event;
Xchar		 *args[];
Xint		  n_args;
X{
X  XawDrawingAreaCallbackStruct cb;
X
X  cb.reason = XawCR_RESIZE;
X  cb.event  = event;
X  cb.window = XtWindow(w);
X  XtCallCallbacks(w, XtNresizeCallback, &cb);
X}
X
X/* Invoke input callbacks */
Xstatic void input_draw(w, event, args, n_args)
XDrawingAreaWidget w;
XXEvent		 *event;
Xchar		 *args[];
Xint		  n_args;
X{
X  XawDrawingAreaCallbackStruct cb;
X
X  cb.reason = XawCR_INPUT;
X  cb.event  = event;
X  cb.window = XtWindow(w);
X  XtCallCallbacks(w, XtNinputCallback, &cb);
X}
X
X/* Invoke motion callbacks */
Xstatic void motion_draw(w, event, args, n_args)
XDrawingAreaWidget w;
XXEvent		 *event;
Xchar		 *args[];
Xint		  n_args;
X{
X  XawDrawingAreaCallbackStruct cb;
X
X  cb.reason = XawCR_MOTION;
X  cb.event  = event;
X  cb.window = XtWindow(w);
X  XtCallCallbacks(w, XtNmotionCallback, &cb);
X}
X
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'DrawingA.doc'" '(4316 characters)'
if test -f 'DrawingA.doc'
then
	echo shar: will not over-write existing file "'DrawingA.doc'"
else
sed 's/^X//' << \SHAR_EOF > 'DrawingA.doc'
XDrawingArea Widget
X
X
XSYNOPSIS
X  Application header file	"DrawingA.h"
X  Class header file		"DrawingAP.h"
X  Class				drawingAreaWidgetClass
X  Class Name			DrawingArea
X  Superclass			Label
X
X
XOVERVIEW
X  This widget was needed to allow a drawing area in the Athena widget
X  set that doesn't require hacking up the Label widget by adding
X  complicated actions.  This widget follows Motif's DrawingArea widget
X  closely, except that it follows Athena's naming conventions and there
X  is no resize policy.  Also, Motif's Drawing area is a composite widget,
X  while this one is a simple widget.  This widget is NOT officially
X  part of the Athena widget set.
X
X
XDESCRIPTION
X  The DrawingArea widget is modeled after Motif's DrawingArea widget.
X  The DrawingArea widget is an empty widget that is easily adaptable to
X  a variety of purposes.  It does no drawing and defines no behavior
X  except for invoking callbacks.  Callbacks notify the application when
X  graphics need to be drawn (exposure events or widget resize) and when
X  the widget receives input from the keyboard or mouse.  Applications
X  are responsible for defining appearence and behavior as needed in
X  response to DrawingArea callbacks.
X
X
XClasses
X  DrawingArea inherits behavior and resources from the Core, Simple, and Label
X  classes.
X  The class pointer if DrawingAreaWidgetClass.  The class name if DrawingArea.
X
X
XNew Resources
X   Name		     	Class		RepType		Default Value
X   ----		     	-----		-------		-------------
X   exposeCallback	Callback	Pointer		NULL
X   inputCallback	Callback	Pointer		NULL
X   motionCallback	Callback	Pointer		NULL
X   resizeCallback	Callback	Pointer		NULL
X
X   XtNexposeCallback
X     Specifies list of callbacks that is called when DrawingArea recieves
X     an exposure event.  The callback reason is XawCR_EXPOSE.
X   XtNinputCallback
X     Specifies list of callbacks that is called when DrawingArea recieves
X     an keyboard or mouse event (key or button, up or down).  The callback 
X     reason is XawCR_INPUT.
X   XtNmotionCallback   
X     Specifies list of callbacks that is called when DrawingArea recieves
X     a mouse motion event.  The callback reason is XawCR_MOTION.
X   XtNresizeCallback
X     Specifies list of callbacks that is called when the DrawingArea is
X     resized.  The callback reason is XawCR_RESIZE.
X
X
XInherited Resources, Changed defaults
X   Name		     	Class		RepType		Default Value
X   ----		     	-----		-------		-------------
X   height		Height		Dimension	100
X   width		Width		Dimension	100
X
X
XCallback Information
X  The following structure is returned with each callback.
X
X  typedef struct {
X    int	    reason;
X    XEvent *event;
X    Window  window;
X  } XawDrawingAreaCallbackStruct;
X
X  reason: Indicates why the callback was invoked
X  event:  Points to the XEvent that triggered the callback
X  window: Is set to the widget window
X
X
XBehavior
X <KeyDown>,<KeyUp>,<BtnDown>,<BtnUp>:
X   The callbacks for XtNinputCallback are called when a key or button is 
X   pressed or released.
X <Expose>:
X   The callbacks for XtNexposeCallbacks are called when the widget recieves
X   an exposure event.
X <Configure>:
X   The callbacks for XtNresizeCallbacks are called when the widget is resized.
X <Motion>:
X   The callbacks for XtNresizeCallbacks are called when the widget recieves a 
X   pointer motion event.
X
X
XDefault Translations
X  <BtnDown>:	input()
X  <BtnUp>:	input()
X  <KeyDown>:	input()
X  <KeyUp>:	input()
X  <Motion>:	motion()
X  <ResReq>:	resize()
X
X
XSEE ALSO
X  OSF/Motif Programmer's reference: XmDrawingArea
X    Open Software Foundation
X  Athena Widget Set - C Language Interface Rel 4: 3.3 Label Widget
X    Chris D. Peterson
X  X Toolkit Intrinsics - C Language Interface
X    Joel McCormack, Paul Asenta, Ralph R. Swick
X  The X Window System, programming and Applications with Xt, OSF/Motif Edition
X    Douglas A. Young
X
X
XCOPYRIGHT
X  Copyright 1990, David Nedde
X 
X  This software is released into the public domain.
X  Permission to use, copy, modify, and distribute this
X  software and its documentation for any purpose and without
X  fee is provided that the above copyright notice appears in all copies.
X  It is provided "as is" without express or implied warranty.
X
X
XAUTHOR
X  David Nedde, Computer Science Dept.		daven at maxine.wpi.edu
X  Worcester Polytechnic Institute		(508) 831-5117/5668
X  Worcester, MA 01609
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'DrawingA.h'" '(1452 characters)'
if test -f 'DrawingA.h'
then
	echo shar: will not over-write existing file "'DrawingA.h'"
else
sed 's/^X//' << \SHAR_EOF > 'DrawingA.h'
X/* DrawingA.h - Public Header file */
X
X/* Copyright 1990, David Nedde
X/*
X/* This software is released into the public domain.
X/* Permission to use, copy, modify, and distribute this
X/* software and its documentation for any purpose and without fee
X/* is granted provided that the above copyright notice appears in all copies.
X/* It is provided "as is" without express or implied warranty.
X*/
X
X/* Define widget's class pointer and strings used to specify resources */
X
X#ifndef _XawDrawingArea_h
X#define _XawDrawingArea_h
X
X/* Resources ADDED to label widget:
X
X Name		     Class		RepType		Default Value
X ----		     -----		-------		-------------
X exposeCallback	     Callback		Pointer		NULL
X inputCallback	     Callback		Pointer		NULL
X motionCallback	     Callback		Pointer		NULL
X resizeCallback	     Callback		Pointer		NULL
X*/
X
X
Xextern WidgetClass drawingAreaWidgetClass;
X
Xtypedef struct _DrawingAreaClassRec *DrawingAreaWidgetClass;
Xtypedef struct _DrawingAreaRec	    *DrawingAreaWidget;
X
X
X/* Resource strings */
X#define XtNexposeCallback	"exposeCallback"
X#define XtNinputCallback	"inputCallback"
X#define XtNmotionCallback	"motionCallback"
X#define XtNresizeCallback	"resizeCallback"
X
X
Xtypedef struct _XawDrawingAreaCallbackStruct {
X  int	  reason;
X  XEvent *event;
X  Window  window;
X} XawDrawingAreaCallbackStruct;
X
X/* Reasons */
X#define XawCR_EXPOSE 1
X#define XawCR_INPUT  2
X#define XawCR_MOTION 3
X#define XawCR_RESIZE 4
X
X#endif /* _XawDrawingArea_h */
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'DrawingAP.h'" '(1476 characters)'
if test -f 'DrawingAP.h'
then
	echo shar: will not over-write existing file "'DrawingAP.h'"
else
sed 's/^X//' << \SHAR_EOF > 'DrawingAP.h'
X/* DrawingArea Private header file */
X
X/* Copyright 1990, David Nedde
X/*
X/* This software is released into the public domain.
X/* Permission to use, copy, modify, and distribute this
X/* software and its documentation for any purpose and without fee
X/* is granted provided that the above copyright notice appears in all copies.
X/* It is provided "as is" without express or implied warranty.
X*/
X
X#ifndef _XtDrawingAreaP_h
X#define _XtDrawingAreaP_h
X
X#include "DrawingA.h"
X#ifdef X11_R3
X#include <X11/LabelP.h>
X#else
X#include <X11/Xaw/LabelP.h>
X#endif
X
X/* The drawing area's contribution to the class record */
Xtypedef struct _DrawingAreaClassPart {
X  int ignore;
X} DrawingAreaClassPart;
X
X/* Drawing area's full class record */
Xtypedef struct _DrawingAreaClassRec {
X    CoreClassPart	core_class;
X    SimpleClassPart	simple_class;
X    LabelClassPart	label_class;
X    DrawingAreaClassPart drawing_area;
X} DrawingAreaClassRec;
X
Xextern DrawingAreaClassRec drawingAreaClassRec;
X
X/* Resources added and status of drawing area widget */
Xtypedef struct _XsDrawingAreaPart {
X  /* Resources */
X  XtCallbackList	expose_callbacks;
X  XtCallbackList	input_callbacks;
X  XtCallbackList	motion_callbacks;
X  XtCallbackList	resize_callbacks;
X} DrawingAreaPart;
X
X
X/* Drawing area's instance record */
Xtypedef struct _DrawingAreaRec {
X    CorePart         core;
X    SimplePart	     simple;
X    LabelPart	     label;
X    DrawingAreaPart  drawing_area;
X} DrawingAreaRec;
X
X#endif /* _XawDrawingAreaP_h */
SHAR_EOF
fi # end of overwriting check
echo shar: done with directory "'xball'"
cd ..
#	End of shell archive
exit 0

dan
----------------------------------------------------
O'Reilly && Associates   argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.



More information about the Comp.sources.x mailing list