http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[xscreensaver] / hacks / shadebobs.c
index d0942bcf4395b1b0e845cbc621a8d664197a6b32..72d5aa04f76bb186a04490b89aff8601a6c88cbe 100644 (file)
  *                Base color can be any color now.
  */
 
+
 #include <math.h>
 #include "screenhack.h"
-#include <X11/Xutil.h>
 
 /* #define VERBOSE */
 
-char *progclass = "ShadeBobs";
-
-char *defaults [] = {
+static const char *shadebobs_defaults [] = {
   ".background: black",
   ".foreground: white",
   "*degrees:  0",      /* default: Automatic degree calculation */
@@ -56,7 +54,7 @@ char *defaults [] = {
   0
 };
 
-XrmOptionDescRec options [] = {
+static XrmOptionDescRec shadebobs_options [] = {
   { "-degrees", ".degrees", XrmoptionSepArg, 0 },
   { "-color",   ".color",   XrmoptionSepArg, 0 },
   { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
@@ -66,17 +64,6 @@ XrmOptionDescRec options [] = {
   { 0, 0, 0, 0 }
 };
 
-static unsigned short iDegreeCount;
-static double *anSinTable, *anCosTable;
-static unsigned short iWinWidth, iWinHeight;
-static unsigned short iWinCenterX, iWinCenterY;
-static char *sColor;
-static unsigned char iBobRadius, iBobDiameter; 
-static unsigned char iVelocity;
-
-#define RANDOM() ((int) (random() & 0X7FFFFFFFL))
-
-
 /* Ahem. Chocolate is a flavor; not a food. Thank you */
 
 
@@ -87,167 +74,187 @@ typedef struct
        double nPosX, nPosY;
 } SShadeBob;
 
+struct state {
+  Display *dpy;
+  Window window;
+  unsigned short iDegreeCount;
+  double *anSinTable, *anCosTable;
+  unsigned short iWinWidth, iWinHeight;
+  unsigned short iWinCenterX, iWinCenterY;
+  char *sColor;
+  unsigned char iBobRadius, iBobDiameter; 
+  unsigned char iVelocity;
+
+  unsigned long *aiColorVals;
+  signed short iColorCount;
+  int cycles;
+  XImage *pImage;
+  unsigned char nShadeBobCount, iShadeBob;
+  SShadeBob *aShadeBobs;
+  GC gc;
+  int delay;
+  int draw_i;
+};
+
+#define RANDOM() ((int) (random() & 0X7FFFFFFFL))
 
-static void ResetShadeBob( SShadeBob *pShadeBob )
+
+
+static void ResetShadeBob( struct state *st, SShadeBob *pShadeBob )
 {
-       pShadeBob->nPosX = RANDOM() % iWinWidth;
-       pShadeBob->nPosY = RANDOM() % iWinHeight;
-       pShadeBob->nAngle = RANDOM() % iDegreeCount;
-       pShadeBob->nAngleDelta = ( RANDOM() % iDegreeCount ) - ( iDegreeCount / 2.0F );
+       pShadeBob->nPosX = RANDOM() % st->iWinWidth;
+       pShadeBob->nPosY = RANDOM() % st->iWinHeight;
+       pShadeBob->nAngle = RANDOM() % st->iDegreeCount;
+       pShadeBob->nAngleDelta = ( RANDOM() % st->iDegreeCount ) - ( st->iDegreeCount / 2.0F );
        pShadeBob->nAngleInc = pShadeBob->nAngleDelta / 50.0F; 
        if( pShadeBob->nAngleInc == 0.0F )      
                pShadeBob->nAngleInc = ( pShadeBob->nAngleDelta > 0.0F ) ? 0.0001F : -0.0001F;
 }
 
 
-static void InitShadeBob( SShadeBob *pShadeBob, Bool bDark )
+static void InitShadeBob( struct state *st, SShadeBob *pShadeBob, Bool bDark )
 {
        double nDelta;
        int iWidth, iHeight;
 
-       if( ( pShadeBob->anDeltaMap = calloc( iBobDiameter * iBobDiameter, sizeof(char) ) ) == NULL )
+       if( ( pShadeBob->anDeltaMap = calloc( st->iBobDiameter * st->iBobDiameter, sizeof(char) ) ) == NULL )
        {
-               fprintf( stderr, "%s: Could not allocate Delta Map!\n", progclass );
+               fprintf( stderr, "%s: Could not allocate Delta Map!\n", progname );
                return;
        }
 
-       for( iHeight=-iBobRadius; iHeight<iBobRadius; iHeight++ )
-               for( iWidth=-iBobRadius; iWidth<iBobRadius; iWidth++ )
+       for( iHeight=-st->iBobRadius; iHeight<st->iBobRadius; iHeight++ )
+               for( iWidth=-st->iBobRadius; iWidth<st->iBobRadius; iWidth++ )
                {
-                       nDelta = 9 - ( ( sqrt( pow( iWidth+0.5, 2 ) + pow( iHeight+0.5, 2 ) ) / iBobRadius ) * 8 );
+                       nDelta = 9 - ( ( sqrt( pow( iWidth+0.5, 2 ) + pow( iHeight+0.5, 2 ) ) / st->iBobRadius ) * 8 );
                        if( nDelta < 0 )  nDelta = 0;
                        if( bDark ) nDelta = -nDelta;
-                       pShadeBob->anDeltaMap[ ( iWidth + iBobRadius ) * iBobDiameter + iHeight + iBobRadius ] = (char)nDelta;
+                       pShadeBob->anDeltaMap[ ( iWidth + st->iBobRadius ) * st->iBobDiameter + iHeight + st->iBobRadius ] = (char)nDelta;
                }
   
-       ResetShadeBob( pShadeBob );
+       ResetShadeBob( st, pShadeBob );
 }
 
 
 /* A delta is calculated, and the shadebob turns at an increment.  When the delta
  * falls to 0, a new delta and increment are calculated. */
-static void MoveShadeBob( SShadeBob *pShadeBob )
+static void MoveShadeBob( struct state *st, SShadeBob *pShadeBob )
 {
        pShadeBob->nAngle          += pShadeBob->nAngleInc;
        pShadeBob->nAngleDelta -= pShadeBob->nAngleInc;
 
-       if( pShadeBob->nAngle >= iDegreeCount ) pShadeBob->nAngle -= iDegreeCount;
-       else if( pShadeBob->nAngle < 0 )                pShadeBob->nAngle += iDegreeCount;
+       if( pShadeBob->nAngle >= st->iDegreeCount )     pShadeBob->nAngle -= st->iDegreeCount;
+       else if( pShadeBob->nAngle < 0 )                pShadeBob->nAngle += st->iDegreeCount;
        
        if( ( pShadeBob->nAngleInc>0.0F  && pShadeBob->nAngleDelta<pShadeBob->nAngleInc ) ||
            ( pShadeBob->nAngleInc<=0.0F && pShadeBob->nAngleDelta>pShadeBob->nAngleInc ) )
        {
-               pShadeBob->nAngleDelta = ( RANDOM() % iDegreeCount ) - ( iDegreeCount / 2.0F );
+               pShadeBob->nAngleDelta = ( RANDOM() % st->iDegreeCount ) - ( st->iDegreeCount / 2.0F );
                pShadeBob->nAngleInc = pShadeBob->nAngleDelta / 50.0F;
                if( pShadeBob->nAngleInc == 0.0F )
                        pShadeBob->nAngleInc = ( pShadeBob->nAngleDelta > 0.0F ) ? 0.0001F : -0.0001F;
        }
        
-       pShadeBob->nPosX = ( anSinTable[ (int)pShadeBob->nAngle ] * iVelocity ) + pShadeBob->nPosX;
-       pShadeBob->nPosY = ( anCosTable[ (int)pShadeBob->nAngle ] * iVelocity ) + pShadeBob->nPosY;
+       pShadeBob->nPosX = ( st->anSinTable[ (int)pShadeBob->nAngle ] * st->iVelocity ) + pShadeBob->nPosX;
+       pShadeBob->nPosY = ( st->anCosTable[ (int)pShadeBob->nAngle ] * st->iVelocity ) + pShadeBob->nPosY;
 
        /* This wraps it around the screen. */
-       if( pShadeBob->nPosX >= iWinWidth )     pShadeBob->nPosX -= iWinWidth;
-       else if( pShadeBob->nPosX < 0 )         pShadeBob->nPosX += iWinWidth;
+       if( pShadeBob->nPosX >= st->iWinWidth ) pShadeBob->nPosX -= st->iWinWidth;
+       else if( pShadeBob->nPosX < 0 )         pShadeBob->nPosX += st->iWinWidth;
        
-       if( pShadeBob->nPosY >= iWinHeight )    pShadeBob->nPosY -= iWinHeight;
-       else if( pShadeBob->nPosY < 0 )                 pShadeBob->nPosY += iWinHeight;
+       if( pShadeBob->nPosY >= st->iWinHeight )        pShadeBob->nPosY -= st->iWinHeight;
+       else if( pShadeBob->nPosY < 0 )                 pShadeBob->nPosY += st->iWinHeight;
 }
 
 
-static void Execute( SShadeBob *pShadeBob, Display *pDisplay,
-                     Window MainWindow,
-                     GC *pGC, XImage *pImage,
-                     signed short iColorCount, unsigned long *aiColorVals )
+static void Execute( struct state *st, SShadeBob *pShadeBob )
 {
        unsigned long iColor;
        short iColorVal;
        int iPixelX, iPixelY;
        unsigned int iWidth, iHeight;
 
-       MoveShadeBob( pShadeBob );
+       MoveShadeBob( st, pShadeBob );
        
-       for( iHeight=0; iHeight<iBobDiameter; iHeight++ )
+       for( iHeight=0; iHeight<st->iBobDiameter; iHeight++ )
        {
                iPixelY = pShadeBob->nPosY + iHeight;
-               if( iPixelY >= iWinHeight )     iPixelY -= iWinHeight;
+               if( iPixelY >= st->iWinHeight ) iPixelY -= st->iWinHeight;
 
-               for( iWidth=0; iWidth<iBobDiameter; iWidth++ )
+               for( iWidth=0; iWidth<st->iBobDiameter; iWidth++ )
                {
                        iPixelX = pShadeBob->nPosX + iWidth;
-                       if( iPixelX >= iWinWidth )      iPixelX -= iWinWidth;
+                       if( iPixelX >= st->iWinWidth )  iPixelX -= st->iWinWidth;
 
-                       iColor = XGetPixel( pImage, iPixelX, iPixelY );
+                       iColor = XGetPixel( st->pImage, iPixelX, iPixelY );
 
                        /*  FIXME: Here is a loop I'd love to take out. */
-                       for( iColorVal=0; iColorVal<iColorCount; iColorVal++ )
-                               if( aiColorVals[ iColorVal ] == iColor )
+                       for( iColorVal=0; iColorVal<st->iColorCount; iColorVal++ )
+                               if( st->aiColorVals[ iColorVal ] == iColor )
                                        break;
 
-                       iColorVal += pShadeBob->anDeltaMap[ iWidth * iBobDiameter + iHeight ];
-                       if( iColorVal >= iColorCount ) iColorVal = iColorCount - 1;
+                       iColorVal += pShadeBob->anDeltaMap[ iWidth * st->iBobDiameter + iHeight ];
+                       if( iColorVal >= st->iColorCount ) iColorVal = st->iColorCount - 1;
                        if( iColorVal < 0 )                        iColorVal = 0;
 
-                       XPutPixel( pImage, iPixelX, iPixelY, aiColorVals[ iColorVal ] );
+                       XPutPixel( st->pImage, iPixelX, iPixelY, st->aiColorVals[ iColorVal ] );
                }
        }
 
        /* FIXME: if it's next to the top or left sides of screen this will break. However, it's not noticable. */
-       XPutImage( pDisplay, MainWindow, *pGC, pImage,
-             pShadeBob->nPosX, pShadeBob->nPosY, pShadeBob->nPosX, pShadeBob->nPosY, iBobDiameter, iBobDiameter );
-       XSync( pDisplay, False );
+       XPutImage( st->dpy, st->window, st->gc, st->pImage,
+             pShadeBob->nPosX, pShadeBob->nPosY, pShadeBob->nPosX, pShadeBob->nPosY, st->iBobDiameter, st->iBobDiameter );
 }
 
 
-static void CreateTables( unsigned int nDegrees )
+static void CreateTables( struct state *st, unsigned int nDegrees )
 {
        double nRadian;
        unsigned int iDegree;
-       anSinTable = calloc( nDegrees, sizeof(double) );
-       anCosTable = calloc( nDegrees, sizeof(double) );
+       st->anSinTable = calloc( nDegrees, sizeof(double) );
+       st->anCosTable = calloc( nDegrees, sizeof(double) );
 
        for( iDegree=0; iDegree<nDegrees; iDegree++ )
        {
                nRadian = ( (double)(2*iDegree) / (double)nDegrees ) * M_PI;
-               anSinTable[ iDegree ] = sin( nRadian );
-               anCosTable[ iDegree ] = cos( nRadian );
+               st->anSinTable[ iDegree ] = sin( nRadian );
+               st->anCosTable[ iDegree ] = cos( nRadian );
        }
 }
 
 
-static unsigned long * SetPalette(Display *pDisplay, Window Win, char *sColor, signed short *piColorCount )
+static unsigned long * SetPalette(struct state *st )
 {
        XWindowAttributes XWinAttribs;
        XColor Color, *aColors;
-       unsigned long *aiColorVals;
        signed short iColor;
        float nHalfColors;
        
-       XGetWindowAttributes( pDisplay, Win, &XWinAttribs );
+       XGetWindowAttributes( st->dpy, st->window, &XWinAttribs );
        
        Color.red =   RANDOM() % 0xFFFF;
        Color.green = RANDOM() % 0xFFFF;
        Color.blue =  RANDOM() % 0xFFFF;
 
-       if( strcasecmp( sColor, "random" ) && !XParseColor( pDisplay, XWinAttribs.colormap, sColor, &Color ) )
-               fprintf( stderr, "%s: color %s not found in database. Choosing to random...\n", progname, sColor );
+       if( strcasecmp( st->sColor, "random" ) && !XParseColor( st->dpy, XWinAttribs.colormap, st->sColor, &Color ) )
+               fprintf( stderr, "%s: color %s not found in database. Choosing to random...\n", progname, st->sColor );
 
 #ifdef VERBOSE
-       printf( "%s: Base color (RGB): <%d, %d, %d>\n", progclass, Color.red, Color.green, Color.blue );
+       printf( "%s: Base color (RGB): <%d, %d, %d>\n", progname, Color.red, Color.green, Color.blue );
 #endif  /*  VERBOSE */
 
-       *piColorCount = get_integer_resource( "ncolors", "Integer" );
-       if( *piColorCount <   2 )       *piColorCount = 2;
-       if( *piColorCount > 255 )       *piColorCount = 255;
+       st->iColorCount = get_integer_resource(st->dpy,  "ncolors", "Integer" );
+       if( st->iColorCount <   2 )     st->iColorCount = 2;
+       if( st->iColorCount > 255 )     st->iColorCount = 255;
 
-       aColors    = calloc( *piColorCount, sizeof(XColor) );
-       aiColorVals = calloc( *piColorCount, sizeof(unsigned long) );
+       aColors    = calloc( st->iColorCount, sizeof(XColor) );
+       st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) );
        
-       for( iColor=0; iColor<*piColorCount; iColor++ )
+       for( iColor=0; iColor<st->iColorCount; iColor++ )
        {
-               nHalfColors = *piColorCount / 2.0F;
+               nHalfColors = st->iColorCount / 2.0F;
                /* Black -> Base Color */
-               if( iColor < (*piColorCount/2) )
+               if( iColor < (st->iColorCount/2) )
                {
                        aColors[ iColor ].red   = ( Color.red   / nHalfColors ) * iColor;
                        aColors[ iColor ].green = ( Color.green / nHalfColors ) * iColor;
@@ -261,42 +268,42 @@ static unsigned long * SetPalette(Display *pDisplay, Window Win, char *sColor, s
                        aColors[ iColor ].blue  = ( ( ( 0xFFFF - Color.blue )  / nHalfColors ) * ( iColor - nHalfColors ) ) + Color.blue;
                }
 
-               if( !XAllocColor( pDisplay, XWinAttribs.colormap, &aColors[ iColor ] ) )
+               if( !XAllocColor( st->dpy, XWinAttribs.colormap, &aColors[ iColor ] ) )
                {
                        /* start all over with less colors */   
-                       XFreeColors( pDisplay, XWinAttribs.colormap, aiColorVals, iColor, 0 );
+                       XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, iColor, 0 );
                        free( aColors );
-                       free( aiColorVals );
-                       piColorCount--;
-                       aColors     = calloc( *piColorCount, sizeof(XColor) );
-                       aiColorVals = calloc( *piColorCount, sizeof(unsigned long) );
+                       free( st->aiColorVals );
+                       st->iColorCount--;
+                       aColors     = calloc( st->iColorCount, sizeof(XColor) );
+                       st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) );
                        iColor = -1;
                }
                else
-                       aiColorVals[ iColor ] = aColors[ iColor ].pixel;
+                       st->aiColorVals[ iColor ] = aColors[ iColor ].pixel;
        }
 
        free( aColors );
 
-       XSetWindowBackground( pDisplay, Win, aiColorVals[ 0 ] );
+       XSetWindowBackground( st->dpy, st->window, st->aiColorVals[ 0 ] );
 
-       return aiColorVals;
+       return st->aiColorVals;
 }
 
 
-static void Initialize( Display *pDisplay, Window Win, GC *pGC, XImage **ppImage )
+static void Initialize( struct state *st )
 {
        XGCValues gcValues;
        XWindowAttributes XWinAttribs;
        int iBitsPerPixel;
 
        /* Create the Image for drawing */
-       XGetWindowAttributes( pDisplay, Win, &XWinAttribs );
+       XGetWindowAttributes( st->dpy, st->window, &XWinAttribs );
 
        /* Find the preferred bits-per-pixel. (jwz) */
        {
                int i, pfvc = 0;
-               XPixmapFormatValues *pfv = XListPixmapFormats( pDisplay, &pfvc );
+               XPixmapFormatValues *pfv = XListPixmapFormats( st->dpy, &pfvc );
                for( i=0; i<pfvc; i++ )
                        if( pfv[ i ].depth == XWinAttribs.depth )
                        {
@@ -308,124 +315,156 @@ static void Initialize( Display *pDisplay, Window Win, GC *pGC, XImage **ppImage
        }
 
        /*  Create the GC. */
-       *pGC = XCreateGC( pDisplay, Win, 0, &gcValues );
+       st->gc = XCreateGC( st->dpy, st->window, 0, &gcValues );
 
-       *ppImage = XCreateImage( pDisplay, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL,
-                                                         XWinAttribs.width, XWinAttribs.height, BitmapPad( pDisplay ), 0 );
-       (*ppImage)->data = calloc((*ppImage)->bytes_per_line, (*ppImage)->height);
+       st->pImage = XCreateImage( st->dpy, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL,
+                                                         XWinAttribs.width, XWinAttribs.height, 8 /*BitmapPad( st->dpy )*/, 0 );
+       st->pImage->data = calloc((st->pImage)->bytes_per_line, (st->pImage)->height);
 
-       iWinWidth = XWinAttribs.width;
-       iWinHeight = XWinAttribs.height;
+       st->iWinWidth = XWinAttribs.width;
+       st->iWinHeight = XWinAttribs.height;
 
        /*  These are precalculations used in Execute(). */
-       iBobDiameter = ( ( iWinWidth < iWinHeight ) ? iWinWidth : iWinHeight ) / 25;
-       iBobRadius = iBobDiameter / 2;
+       st->iBobDiameter = ( ( st->iWinWidth < st->iWinHeight ) ? st->iWinWidth : st->iWinHeight ) / 25;
+       st->iBobRadius = st->iBobDiameter / 2;
 #ifdef VERBOSE
-       printf( "%s: Bob Diameter = %d\n", progclass, iBobDiameter );
+       printf( "%s: Bob Diameter = %d\n", progname, st->iBobDiameter );
 #endif
 
-       iWinCenterX = ( XWinAttribs.width / 2 ) - iBobRadius;
-       iWinCenterY = ( XWinAttribs.height / 2 ) - iBobRadius;
+       st->iWinCenterX = ( XWinAttribs.width / 2 ) - st->iBobRadius;
+       st->iWinCenterY = ( XWinAttribs.height / 2 ) - st->iBobRadius;
 
-       iVelocity = ( ( iWinWidth < iWinHeight ) ? iWinWidth : iWinHeight ) / 150;
+       st->iVelocity = ( ( st->iWinWidth < st->iWinHeight ) ? st->iWinWidth : st->iWinHeight ) / 150;
        
        /*  Create the Sin and Cosine lookup tables. */
-       iDegreeCount = get_integer_resource( "degrees", "Integer" );
-       if(      iDegreeCount == 0   ) iDegreeCount = ( XWinAttribs.width / 6 ) + 400;
-       else if( iDegreeCount < 90   ) iDegreeCount = 90;
-       else if( iDegreeCount > 5400 ) iDegreeCount = 5400;
-       CreateTables( iDegreeCount );
+       st->iDegreeCount = get_integer_resource(st->dpy,  "degrees", "Integer" );
+       if(      st->iDegreeCount == 0   ) st->iDegreeCount = ( XWinAttribs.width / 6 ) + 400;
+       else if( st->iDegreeCount < 90   ) st->iDegreeCount = 90;
+       else if( st->iDegreeCount > 5400 ) st->iDegreeCount = 5400;
+       CreateTables( st, st->iDegreeCount );
 #ifdef VERBOSE
-       printf( "%s: Using a %d degree circle.\n", progclass );
+       printf( "%s: Using a %d degree circle.\n", progname );
 #endif /* VERBOSE */
   
        /*  Get the base color. */
-       sColor = get_string_resource( "color", "Color" );
+       st->sColor = get_string_resource(st->dpy,  "color", "Color" );
 }
 
 
-void screenhack(Display *pDisplay, Window Win )
+static void *
+shadebobs_init (Display *dpy, Window window)
 {
-       GC gc;
-       signed short iColorCount = 0;
-       unsigned long *aiColorVals = NULL;
-       XImage *pImage = NULL;
-       unsigned char nShadeBobCount, iShadeBob;
-       SShadeBob *aShadeBobs;
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
+
 #ifdef VERBOSE
        time_t nTime = time( NULL );
        unsigned short iFrame = 0;
 #endif  /*  VERBOSE */
-       int delay, cycles, i;
 
-       nShadeBobCount = get_integer_resource( "count", "Integer" );
-       if( nShadeBobCount > 64 ) nShadeBobCount = 64;
-       if( nShadeBobCount <  1 ) nShadeBobCount = 1;
+  st->dpy = dpy;
+  st->window = window;
+
+       st->nShadeBobCount = get_integer_resource(st->dpy,  "count", "Integer" );
+       if( st->nShadeBobCount > 64 ) st->nShadeBobCount = 64;
+       if( st->nShadeBobCount <  1 ) st->nShadeBobCount = 1;
 
-       if( ( aShadeBobs = calloc( nShadeBobCount, sizeof(SShadeBob) ) ) == NULL )
+       if( ( st->aShadeBobs = calloc( st->nShadeBobCount, sizeof(SShadeBob) ) ) == NULL )
        {
-               fprintf( stderr, "%s: Could not allocate %d ShadeBobs\n", progclass, nShadeBobCount );
-               return;
+               fprintf( stderr, "%s: Could not allocate %d ShadeBobs\n", progname, st->nShadeBobCount );
+                abort();
        }
 #ifdef VERBOSE 
-       printf( "%s: Allocated %d ShadeBobs\n", progclass, nShadeBobCount );
+       printf( "%s: Allocated %d ShadeBobs\n", progname, st->nShadeBobCount );
 #endif  /*  VERBOSE */
 
-       Initialize( pDisplay, Win, &gc, &pImage );
+       Initialize( st );
 
-       for( iShadeBob=0; iShadeBob<nShadeBobCount; iShadeBob++ )
-               InitShadeBob( &aShadeBobs[ iShadeBob ], iShadeBob % 2 );
+       for( st->iShadeBob=0; st->iShadeBob<st->nShadeBobCount; st->iShadeBob++ )
+               InitShadeBob( st, &st->aShadeBobs[ st->iShadeBob ], st->iShadeBob % 2 );
 
-       delay = get_integer_resource( "delay", "Integer" );
-       cycles = get_integer_resource( "cycles", "Integer" ) * iDegreeCount;
-       i = cycles;
+       st->delay = get_integer_resource(st->dpy,  "delay", "Integer" );
+       st->cycles = get_integer_resource(st->dpy,  "cycles", "Integer" ) * st->iDegreeCount;
 
-       while( 1 )
-       {
-               screenhack_handle_events( pDisplay );
+        st->draw_i = 99999999;
+        return st;
+}
 
-               if( i++ >= cycles )
-               {
-                        XWindowAttributes XWinAttribs;
-                        XGetWindowAttributes( pDisplay, Win, &XWinAttribs );
-
-                       i = 0;
-                       memset( pImage->data, 0, pImage->bytes_per_line * pImage->height );
-                       for( iShadeBob=0; iShadeBob<nShadeBobCount; iShadeBob++ )
-                               ResetShadeBob( &aShadeBobs[ iShadeBob ] );
-                        XFreeColors( pDisplay, XWinAttribs.colormap, aiColorVals, iColorCount, 0 );
-                       free( aiColorVals );
-                       aiColorVals = SetPalette( pDisplay, Win, sColor, &iColorCount );
-                        XClearWindow( pDisplay, Win );
-               }
+static unsigned long
+shadebobs_draw (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+
+  if( st->draw_i++ >= st->cycles )
+    {
+      XWindowAttributes XWinAttribs;
+      XGetWindowAttributes( st->dpy, st->window, &XWinAttribs );
+
+      st->draw_i = 0;
+#if 0
+      memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height );
+#else
+      {
+        /* fill the image with the actual value of the black pixel, not 0. */
+        unsigned long black = BlackPixelOfScreen (XWinAttribs.screen);
+        int x, y;
+        for (y = 0; y < XWinAttribs.height; y++)
+          for (x = 0; x < XWinAttribs.width; x++)
+            XPutPixel (st->pImage, x, y, black);
+      }
+#endif
 
-               for( iShadeBob=0; iShadeBob<nShadeBobCount; iShadeBob++ )
-                       Execute( &aShadeBobs[ iShadeBob ], pDisplay, Win, &gc, pImage, iColorCount, aiColorVals );
+      for( st->iShadeBob=0; st->iShadeBob<st->nShadeBobCount; st->iShadeBob++ )
+        ResetShadeBob( st, &st->aShadeBobs[ st->iShadeBob ] );
+      XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, st->iColorCount, 0 );
+      free( st->aiColorVals );
+      st->aiColorVals = SetPalette( st );
+      XClearWindow( st->dpy, st->window );
+    }
 
-               if( delay && !(i % 4) )
-                       usleep(delay);
+  for( st->iShadeBob=0; st->iShadeBob<st->nShadeBobCount; st->iShadeBob++ )
+    Execute( st, &st->aShadeBobs[ st->iShadeBob ] );
 
 #ifdef VERBOSE
-               iFrame++;
-               if( nTime - time( NULL ) )
-               {
-                       printf( "%s: %d FPS\n", progclass, iFrame );
-                       nTime = time( NULL );
-                       iFrame = 0;
-               }
+  iFrame++;
+  if( nTime - time( NULL ) )
+    {
+      printf( "%s: %d FPS\n", progname, iFrame );
+      nTime = time( NULL );
+      iFrame = 0;
+    }
 #endif  /*  VERBOSE */
-       }
 
-       free( anSinTable );
-       free( anCosTable );
-       free( pImage->data );
-       XDestroyImage( pImage );
-       for( iShadeBob=0; iShadeBob<nShadeBobCount; iShadeBob++ )
-               free( aShadeBobs[ iShadeBob ].anDeltaMap );
-       free( aShadeBobs );
-       free( aiColorVals );
+  return st->delay;
+}
+
+static void
+shadebobs_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
+}
+
+static Bool
+shadebobs_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  return False;
 }
 
+static void
+shadebobs_free (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+       free( st->anSinTable );
+       free( st->anCosTable );
+       /* free( st->pImage->data ); */
+       XDestroyImage( st->pImage );
+       for( st->iShadeBob=0; st->iShadeBob<st->nShadeBobCount; st->iShadeBob++ )
+               free( st->aShadeBobs[ st->iShadeBob ].anDeltaMap );
+       free( st->aShadeBobs );
+       free( st->aiColorVals );
+}
+
+
+XSCREENSAVER_MODULE ("ShadeBobs", shadebobs)
 
 /* End of Module - "shadebobs.c" */