|  |     Very interesting.  This could well be the problem.  I haven't looked
    into this before.  I do read events frequently and I seem to get alot
    of events that don't fit any of the catagories that I'm looking for,
    but I haven't gone so far as to see what they are.  Anyway, I'm posting
    some code for kicks.  I have since sidestepped the problem by no
    calling XCopyArea until the my last level of recursion.  Thus I only
    get around 50 calls per run versus 1000's before.  I will have to see
    about this expose business though.  
    
    Thanks alot.
    
    	John
    
    P.S. Please excuse code sloppiness - still in testing phase.
    
/* This is an attempt to speed up the Mandelbrot drawing by recursively	      */
/* deviding the spaces into areas of all the same color to minimize the	      */
/* number of pixels to calculate.					      */
#include <stdio.h>
#include <math.h>
#include <time.h>
#ifdef VMS
#  include <decw$include:Xlib.h>
#  include <decw$include:Xutil.h>
#else
#  include <X11/Xlib.h>
#  include <X11/Xutil.h>
#endif
#include "mandel.h"
#define SCREEN_SIZE 730
#define REC_LIMIT 1
double xcorner = -2.0, ycorner = 2.0;
double gap = 4.0 / SCREEN_SIZE;
unsigned short current_side;
static XImage *mimage;
static int one_third,	   /* 1/3 the distance of the current block size */
	   two_thirds;	   /* 2 * one_third */
char iter_level = 0, color_changed[6][9][4];
/******************************************************************************/
int get_count( x, y )
/******************************************************************************/
/* calculate and return the count value for complex number at window	      */
/* coordinate (x, y)							      */
double x, y;   /* window coordinate of pixel to calculate		      */
{
register count;
static double z_imag, z_real, z_imag2, z_real2;
   z_imag2 = z_real2 = z_imag = z_real = 0;
   for( count = 0; count < LIMIT; count++ )
   {
      if ( z_real2 + z_imag2 > 4.0 ) return count;
	 z_imag = 2 * z_real * z_imag + y;
	 z_real = z_real2 - z_imag2 + x;
	 z_real2 = z_real * z_real;
	 z_imag2 = z_imag * z_imag;
   }
   return count;
}
/******************************************************************************/
void calc_hline( xwin, ywin, npixels )
/******************************************************************************/
/* calculate and draw a horizontal line starting at window coord (xwin, ywin) */
/* and going for 'npixels'						      */
short xwin, ywin, /* upper-left hand window coord of current block	      */
      npixels;	  /* number of pixels to calculate and draw		      */
{
register n, count;
double c_imag, c_real, z_imag, z_real, z_imag2, z_real2;
   c_imag = ycorner - ywin*gap;
   for ( n = 0; n < npixels; n++ )
   {
      c_real = xcorner + (xwin+n)*gap;
      z_imag2 = z_real2 = z_imag = z_real = 0;
      for( count = 0; count < LIMIT; count++ )
      {
	 if ( z_real2 + z_imag2 > 4.0 ) break;
	 z_imag = 2 * z_real * z_imag + c_imag;
	 z_real = z_real2 - z_imag2 + c_real;
	 z_real2 = z_real * z_real;
	 z_imag2 = z_imag * z_imag;
      }
      XPutPixel( mimage, xwin+n, ywin, color_indices[count-1] );
   }
}
/******************************************************************************/
void calc_vline( xwin, ywin, npixels )
/******************************************************************************/
/* calculate and draw a vertical line starting at window coord (xwin, ywin)   */
/* and going for 'npixels'						      */
short xwin, ywin, /* upper-left hand window coord of current block	      */
      npixels;	  /* number of pixels to calculate and draw		      */
{
register n, count;
double c_imag, c_real, z_imag, z_real, z_imag2, z_real2;
   c_real = xcorner + xwin*gap;
   for ( n = 0; n < npixels; n++ )
   {
      c_imag = ycorner - (ywin+n)*gap;
      z_imag2 = z_real2 = z_imag = z_real = 0;
      for( count = 0; count < LIMIT; count++ )
      {
	 if ( z_real2 + z_imag2 > 4.0 ) break;
	 z_imag = 2 * z_real * z_imag + c_imag;
	 z_real = z_real2 - z_imag2 + c_real;
	 z_real2 = z_real * z_real;
	 z_imag2 = z_imag * z_imag;
      }
      XPutPixel( mimage, xwin, ywin+n, color_indices[count-1] );
   }
}
/******************************************************************************/
void cut_it_up( x, y, side )
/******************************************************************************/
/* divide the block whose upper-left window coord. is (x, y), into a 3 x 3    */
/* matrix of smaller blocks each of side length 'side / 3'		      */
 
short x, y, side;
{
/* calculate and draw horizontal line 1/3 the way down y */
   calc_hline( x+1, y+one_third, side-1 );
/* calculate and draw horizontal line 2/3 the way down y */
   calc_hline( x+1, y+two_thirds, side-1 );
/* calculate and draw vertical line 1/3 the way along x */
   calc_vline( x+one_third, y+1, one_third-1 );
   calc_vline( x+one_third, y+one_third+1, one_third-1 );
   calc_vline( x+one_third, y+two_thirds+1, one_third-1 );
/* calculate and draw vertical line 2/3 the way along x */
   calc_vline( x+two_thirds, y+1, one_third-1 );
   calc_vline( x+two_thirds, y+one_third+1, one_third-1 );
   calc_vline( x+two_thirds, y+two_thirds+1, one_third-1 );
/* last thing has been put in the image so update the pixmap		      */
   XPutImage( main_display, main_pixmap, main_gc, mimage,
	      x, y, x, y, side, side);
/*
   XCopyArea( main_display, main_pixmap, main_window, main_gc,
	      x, y, side, side, x, y );
*/
}  
/******************************************************************************/
void check_hline( x, y, npixels, flags )
/******************************************************************************/
/* check a horizontal line of pixels and return flags indication if the	      */
/* color changed in any of its three thirds				      */
short x, y,    /* starting coordinates					      */
      npixels; /* number of pixels to check;				      */
char *flags;   /* pointer to a set of flags indicating color change */
{
char color_changed;
unsigned long color, last_color;
register i;
   color_changed = FALSE;
   last_color = XGetPixel( mimage, x, y );
   for( i = 1; i < npixels; i++ )
   {
      if( (color = XGetPixel( mimage, x+i, y)) != last_color )
	 color_changed = TRUE;
      if( i == one_third )
      {
	 flags[0] = color_changed;
	 color_changed = FALSE;
      }
      if( i == two_thirds )
      {
	 flags[1] = color_changed;
	 color_changed = FALSE;
      }
      last_color = color;
   }
   flags[2] = color_changed;
}
/******************************************************************************/
void check_vline( x, y, npixels, flags )
/******************************************************************************/
/* check a vertical line of pixels and return flags indication if the	      */
/* color changed in any of its three thirds				      */
short x, y,    /* starting coordinates					      */
      npixels; /* number of pixels to check;				      */
char *flags;   /* pointer to a set of flags indicating color change */
{
char color_changed;
unsigned long color, last_color;
register i;
   color_changed = FALSE;
   last_color = XGetPixel( mimage, x, y );
   for( i = 1; i < npixels; i++ )
   {
      if( (color = XGetPixel( mimage, x, y+i)) != last_color )
	 color_changed = TRUE;
      if( i == one_third )
      {
	 flags[0] = color_changed;
	 color_changed = FALSE;
      }
      if( i == two_thirds )
      {
	 flags[1] = color_changed;
	 color_changed = FALSE;
      }
      last_color = color;
   }
   flags[2] = color_changed;
}
/******************************************************************************/
void update_flags( x, y, side )
/******************************************************************************/
/* this routine check the lines that make the exterior of the current block   */
/* who's upper right hand window coordinate is (x,y);  for each line it	      */
/* returns flags indicating if and where it changed color		      */
short x, y,    /* current position in the window */
      side;    /* number of pixels on a side of the current block */
{
char flags[3];
/* check the horizontal lines						      */
   check_hline( x, y, side, flags );		/* top side */
   color_changed[iter_level][0][0] = flags[0];
   color_changed[iter_level][3][0] = flags[1];
   color_changed[iter_level][6][0] = flags[2];
   check_hline( x, y+one_third, side, flags );	/* first third */
   color_changed[iter_level][0][2] = color_changed[iter_level][1][0] = flags[0];
   color_changed[iter_level][3][2] = color_changed[iter_level][4][0] = flags[1];
   color_changed[iter_level][6][2] = color_changed[iter_level][7][0] = flags[2];
   check_hline( x, y+two_thirds, side, flags );	/* second third */
   color_changed[iter_level][1][2] = color_changed[iter_level][2][0] = flags[0];
   color_changed[iter_level][4][2] = color_changed[iter_level][5][0] = flags[1];
   color_changed[iter_level][7][2] = color_changed[iter_level][8][0] = flags[2];
   check_hline( x, y+side, side, flags );	/* bottom side */
   color_changed[iter_level][2][2] = flags[0];
   color_changed[iter_level][5][2] = flags[1];
   color_changed[iter_level][8][2] = flags[2];
/* check the virtical lines						      */
   check_vline( x, y, side, flags );		/* left side */
   color_changed[iter_level][0][3] = flags[0];
   color_changed[iter_level][1][3] = flags[1];
   color_changed[iter_level][2][3] = flags[2];
   check_vline( x+one_third, y, side, flags );	/* first third */
   color_changed[iter_level][0][1] = color_changed[iter_level][3][3] = flags[0];
   color_changed[iter_level][1][1] = color_changed[iter_level][4][3] = flags[1];
   color_changed[iter_level][2][1] = color_changed[iter_level][5][3] = flags[2];
   check_vline( x+two_thirds, y, side, flags );	/* second third */
   color_changed[iter_level][3][1] = color_changed[iter_level][6][3] = flags[0];
   color_changed[iter_level][4][1] = color_changed[iter_level][7][3] = flags[1];
   color_changed[iter_level][5][1] = color_changed[iter_level][8][3] = flags[2];
   check_vline( x+side, y, side, flags );	/* right side */
   color_changed[iter_level][6][1] = flags[0];
   color_changed[iter_level][7][1] = flags[1];
   color_changed[iter_level][8][1] = flags[2];
}
/******************************************************************************/
void fill_by_ones( x, y )
/******************************************************************************/
/* This routine is called when the side of the current block that is being    */
/* calculated is 3, thus making it necessary to fill it in pixel by pixel     */
short x, y;
{
register i, j;
int count;
/* since the outside is already done we only have to fill in the middle four  */
/* pixels								      */
   if( (count = get_count( xcorner+(x+1)*gap, ycorner-(y+1)*gap )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, x+1, y+1 );
   }
   if( (count = get_count( xcorner+(x+2)*gap, ycorner-(y+1)*gap )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, x+2, y+1 );
   }
   if( (count = get_count( xcorner+(x+1)*gap, ycorner-(y+2)*gap )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, x+1, y+2 );
   }
   if( (count = get_count( xcorner+(x+2)*gap, ycorner-(y+2)*gap )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, x+2, y+2 );
   }
}
/******************************************************************************/
void check_blocks( x, y, side )
/******************************************************************************/
/* this is the main engine; for the current block whose upper-left hand	      */
/* window coordinte is (x, y) and length of side is 'side', check to see if   */
/* all the walls of all 9 interior smaller blocks are of the same color	      */
/* if they are then fill in the particular block with that color and move on  */
/* to the next; else cut that block up and start again			      */
short x, y, side;
{
register i, j, block_number;
short newside, newy;
unsigned long color;
   newside = side / 3;
   
   if ( newside > 1 )
   {
      block_number = 0;
      for ( i = 0; i < 3; i++ )
      {
    	 newy = y;
	 for ( j = 0; j < 3; j++, block_number++ )
	 {
	    if( !color_changed[iter_level][block_number][0] &&
		!color_changed[iter_level][block_number][1] &&
	        !color_changed[iter_level][block_number][2] &&
		!color_changed[iter_level][block_number][3] )
	    {
	       if( (color = XGetPixel( mimage, x, newy )) != 0 )
	       {
		  XSetForeground( main_display, main_gc, color );
		  XFillRectangle( main_display, main_pixmap, main_gc,
				  x+1, newy+1, newside-1, newside-1 );
	       }
	       if( iter_level <= 1 )
		  XCopyArea( main_display, main_pixmap, main_window, main_gc,
			     x, newy, newside, newside, x, newy );
	    }
	    else if( newside != 3 )
	    {
	       iter_level++;
	       one_third = newside / 3;
	       two_thirds = 2 * one_third;
	       cut_it_up( x, newy, newside );
	       update_flags( x, newy, newside );
	       check_blocks( x, newy, newside );
	       if( iter_level == 1 )
		  XCopyArea( main_display, main_pixmap, main_window, main_gc,
			     x, newy, newside, newside, x, newy );
	    }
	    else
	       fill_by_ones( x, newy );
	    newy += newside;
	 }
	 x += newside;
      }
   }
   iter_level--;
}
/******************************************************************************/
void createWindow( )
/******************************************************************************/
{
/* Open the display */
   if ( !(main_display = XOpenDisplay( 0 )) ){
      printf( "Can't open display\n" );
      exit( 1 );
   }
/* Create the mask that tells what events to look for in the window */
   main_xswa.save_under = TRUE;
/* set the background and color */
   main_xswa.background_pixel = BlackPixel( main_display,
					    DefaultScreen( main_display ) );
/* create the screen */
   main_screen = XDefaultScreenOfDisplay( main_display );
/* create the window and give it a name */
   main_window =
      XCreateWindow( main_display,     /* display id */
		     XRootWindowOfScreen( main_screen ),  /* window id*/
		     50, 0,	       /* position of upper left hand corner */
		     SCREEN_SIZE, SCREEN_SIZE, /* width and height in pixels */
		     0,		       /* width of border in pixels */
		     XDefaultDepthOfScreen( main_screen ), /* bits per pixel  */
		     InputOutput,      /* type if interaction */
		     XDefaultVisualOfScreen( main_screen ), /* visual struct  */
		     CWBackPixel | CWSaveUnder,  /* attb mask  */
		     &main_xswa);      /* attributes */
   XStoreName( main_display, main_window, "Recursive Mandel " );
   main_gc = XCreateGC( main_display, main_window, 0, 0 );
   XMapWindow( main_display, main_window );
}
/******************************************************************************/
/******************************************************************************/
main(argc, argv)
int argc;
char *argv[];
/******************************************************************************/
/******************************************************************************/
{
int count;
time_t time1, time2, tp;
   createWindow( );
   if ( argc == 1 )
      XSynchronize( main_display, 1 );
   initColors( );
   main_pixmap = XCreatePixmap( main_display, main_window,
				SCREEN_SIZE, SCREEN_SIZE,
				XDefaultDepthOfScreen( main_screen ) );
   XSetForeground( main_display, main_gc, BlackPixelOfScreen( main_screen ) );
   XFillRectangle( main_display, main_pixmap, main_gc,
		   0, 0, SCREEN_SIZE, SCREEN_SIZE );
   mimage = XGetImage( main_display, main_pixmap,
		       0, 0, SCREEN_SIZE, SCREEN_SIZE, AllPlanes, ZPixmap );
/* take a time stamp */
   time1 = time( &tp );
   printf( "%s", ctime( &tp ) );
/* prime the pump by calculating the for corner points */
   if( (count = get_count( -2.0, 2.0 )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, 0, 0 );
      XPutPixel( mimage, 0, 0, color_indices[count-1] );
   }
   if( (count = get_count( 2.0, 2.0 )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, SCREEN_SIZE-1, 0 );
      XPutPixel( mimage, SCREEN_SIZE-1, 0, color_indices[count-1] );
   }
   
   if( (count = get_count( -2.0, -2.0 )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, 0, SCREEN_SIZE-1 );
      XPutPixel( mimage, 0, SCREEN_SIZE-1, color_indices[count-1] );
   }
   if( (count = get_count( 2.0, -2.0 )) != LIMIT )
   {
      XSetForeground( main_display, main_gc, color_indices[count-1] );
      XDrawPoint( main_display, main_pixmap, main_gc, SCREEN_SIZE-1, SCREEN_SIZE-1 );
      XPutPixel( mimage, SCREEN_SIZE-1, SCREEN_SIZE-1, color_indices[count-1] );
   }
   one_third = (SCREEN_SIZE-1) / 3;
   two_thirds = 2 * one_third;
/* upper left to upper right */
   calc_hline( 1, 0, SCREEN_SIZE-2 );
/* upper left to lower left */
   calc_vline( 0, 1, SCREEN_SIZE-2 );
/* upper right to lower right */
   calc_vline( SCREEN_SIZE-1, 1, SCREEN_SIZE-2 );
/* lower left to lower right */
   calc_hline( 1, SCREEN_SIZE-1, SCREEN_SIZE-2 );
   cut_it_up( 0, 0, SCREEN_SIZE );
   update_flags( 0, 0, SCREEN_SIZE );
   check_blocks( 0, 0, SCREEN_SIZE-1 );
   XCopyArea( main_display, main_pixmap, main_window, main_gc,
	      SCREEN_SIZE-1, 0, 1, SCREEN_SIZE, SCREEN_SIZE-1, 0 );
   XCopyArea( main_display, main_pixmap, main_window, main_gc,
	      0, SCREEN_SIZE-1, SCREEN_SIZE, 1, 0, SCREEN_SIZE-1);
   time2 = time( &tp );
   printf( "%s", ctime( &tp ) );
   printf( "#Mins: %f\n", difftime( time2, time1 ) / 60.0 );
   XFlush( main_display );
   printf( "Hit return to end:\007\n" );
   getchar( );
   XFree( mimage );
   WritePixmapFile( main_display, "wholeset.bit", main_pixmap, 0, 0 );
}
    
 |