http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[xscreensaver] / hacks / eruption.c
index 26ed801c823b269b2de27eebf2d224a44d4c7db5..2084cbf27bc77cfd150c57f5d44f2c806e4cbab1 100644 (file)
 
 #include <math.h>
 #include "screenhack.h"
-#include <X11/Xutil.h>
 
 /*#define VERBOSE*/ 
 
-char *progclass = "Eruption";
-
-char *defaults [] = {
-  ".background: black",
-  ".foreground: white",
-  "*cycles:   80",
-  "*ncolors:  256",
-  "*delay:    5000",
-  "*particles: 300",
-  "*cooloff: 2",
-  "*gravity: 1",
-  "*heat: 256",
-  0
-};
-
-XrmOptionDescRec options [] = {
-  { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
-  { "-delay",   ".delay",   XrmoptionSepArg, 0 },
-  { "-cycles",  ".cycles",  XrmoptionSepArg, 0 },
-  { "-particles",  ".particles",  XrmoptionSepArg, 0 },
-  { "-cooloff",  ".cooloff",  XrmoptionSepArg, 0 },
-  { "-gravity",  ".gravity",  XrmoptionSepArg, 0 },
-  { "-heat",  ".heat",  XrmoptionSepArg, 0 },
-  { 0, 0, 0, 0 }
-};
-
 /* Slightly whacked, for better explosions
  */
 #define PI_2000 6284
 #define SPREAD 15
 
-static int sin_cache[PI_2000];
-static int cos_cache[PI_2000];
-
 /*particle structure*/
 typedef struct 
 {
@@ -63,16 +33,32 @@ typedef struct
   unsigned char dead;
 } PARTICLE;
 
-static PARTICLE *particles;
-static unsigned short iWinWidth, iWinHeight;
-static unsigned char **fire;
-static unsigned short nParticleCount;
-static unsigned char xdelta, ydelta, decay;
-static signed char gravity;
-static signed short heat;
+struct state {
+  Display *dpy;
+  Window window;
+
+ int sin_cache[PI_2000];
+ int cos_cache[PI_2000];
+
+  PARTICLE *particles;
+  unsigned short iWinWidth, iWinHeight;
+  unsigned char **fire;
+  unsigned short nParticleCount;
+  unsigned char xdelta, ydelta, decay;
+  signed char gravity;
+  signed short heat;
+
+  int cycles, delay;
+  GC gc;
+  signed short iColorCount;
+  unsigned long *aiColorVals;
+  XImage *pImage;
+
+  int draw_i;
+};
 
 static void
-cache(void) /* jwz */
+cache(struct state *st) /* jwz */
 {               /*needs to be run once. Could easily be */
   int i;        /*reimplemented to run and cache at compile-time,*/
   double dA;    
@@ -83,196 +69,191 @@ cache(void) /* jwz */
       dA+=asin(frand(1.0))/M_PI_2*0.1;
       /*Approximating the integration of the binominal, for
         well-distributed randomness*/
-      cos_cache[i]=-abs((int) (cos(((double)i)/1000.0)*dA*ydelta));
-      sin_cache[i]=(int) (sin(((double)i)/1000.0)*dA*xdelta);
+      st->cos_cache[i]=-abs((int) (cos(((double)i)/1000.0)*dA*st->ydelta));
+      st->sin_cache[i]=(int) (sin(((double)i)/1000.0)*dA*st->xdelta);
     }
 }
 
-void init_particle(PARTICLE* particle, signed short iColorCount, unsigned short xcenter, unsigned short ycenter)
+static void init_particle(struct state *st, PARTICLE* particle, unsigned short xcenter, unsigned short ycenter)
 {
   int v = random() % PI_2000;
   particle->xpos = xcenter - SPREAD + (random() % (SPREAD * 2));
   particle->ypos = ycenter - SPREAD + (random() % (SPREAD * 2));;
-  particle->xdir = sin_cache[v];
-  particle->ydir = cos_cache[v];
-  particle->colorindex = iColorCount;
+  particle->xdir = st->sin_cache[v];
+  particle->ydir = st->cos_cache[v];
+  particle->colorindex = st->iColorCount-1;
   particle->dead = 0;
 }
 
-static void Execute( Display *pDisplay,
-                     Window MainWindow,
-                     GC *pGC, XImage *pImage,
-                     signed short iColorCount, unsigned long *aiColorVals )
+static void Execute( struct state *st )
 {
   int i, j;
   unsigned int temp;
 
-  /* move and draw particles into fire array */
+  /* move and draw particles into st->fire array */
   
-  for (i = 0; i < nParticleCount; i++)
+  for (i = 0; i < st->nParticleCount; i++)
     {
-      if (!particles[i].dead)
+      if (!st->particles[i].dead)
        {
-         particles[i].xpos += particles[i].xdir;
-         particles[i].ypos += particles[i].ydir;
+         st->particles[i].xpos += st->particles[i].xdir;
+         st->particles[i].ypos += st->particles[i].ydir;
          
          /* is particle dead? */
          
-         if (particles[i].colorindex == 0)
+         if (st->particles[i].colorindex == 0)
            {
-             particles[i].dead = 1;
+             st->particles[i].dead = 1;
              continue;
            }
          
-         if (particles[i].xpos < 1)
+         if (st->particles[i].xpos < 1)
            {
-             particles[i].xpos = 1;
-             particles[i].xdir = -particles[i].xdir - 4;
-             particles[i].colorindex = iColorCount;
+             st->particles[i].xpos = 1;
+             st->particles[i].xdir = -st->particles[i].xdir - 4;
+             st->particles[i].colorindex = st->iColorCount;
            }
-         else if (particles[i].xpos >= iWinWidth - 2)
+         else if (st->particles[i].xpos >= st->iWinWidth - 2)
            {
-             particles[i].xpos = iWinWidth - 2;
-             particles[i].xdir = -particles[i].xdir + 4;
-             particles[i].colorindex = iColorCount;
+             st->particles[i].xpos = st->iWinWidth - 2;
+             st->particles[i].xdir = -st->particles[i].xdir + 4;
+             st->particles[i].colorindex = st->iColorCount;
            }
          
-         if (particles[i].ypos < 1)
+         if (st->particles[i].ypos < 1)
            {
-             particles[i].ypos = 1;
-             particles[i].ydir = -particles[i].ydir;
-             particles[i].colorindex = iColorCount;
+             st->particles[i].ypos = 1;
+             st->particles[i].ydir = -st->particles[i].ydir;
+             st->particles[i].colorindex = st->iColorCount;
            }
-         else if (particles[i].ypos >= iWinHeight - 3)
+         else if (st->particles[i].ypos >= st->iWinHeight - 3)
            {
-             particles[i].ypos = iWinHeight- 3;
-             particles[i].ydir = (-particles[i].ydir >> 2) - (random() % 2);
-             particles[i].colorindex = iColorCount;
+             st->particles[i].ypos = st->iWinHeight- 3;
+             st->particles[i].ydir = (-st->particles[i].ydir >> 2) - (random() % 2);
+             st->particles[i].colorindex = st->iColorCount;
            }
          
-         /* gravity kicks in */
-         particles[i].ydir += gravity;
+         /* st->gravity kicks in */
+         st->particles[i].ydir += st->gravity;
          
          /* particle cools off */
-         particles[i].colorindex--;
+         st->particles[i].colorindex--;
          
          /* draw particle */
-         fire[particles[i].ypos][particles[i].xpos] = particles[i].colorindex;
-         fire[particles[i].ypos][particles[i].xpos - 1] = particles[i].colorindex;
-         fire[particles[i].ypos + 1][particles[i].xpos] = particles[i].colorindex;
-         fire[particles[i].ypos - 1][particles[i].xpos] = particles[i].colorindex;
-         fire[particles[i].ypos][particles[i].xpos + 1] = particles[i].colorindex;
+         st->fire[st->particles[i].ypos][st->particles[i].xpos] = st->particles[i].colorindex;
+         st->fire[st->particles[i].ypos][st->particles[i].xpos - 1] = st->particles[i].colorindex;
+         st->fire[st->particles[i].ypos + 1][st->particles[i].xpos] = st->particles[i].colorindex;
+         st->fire[st->particles[i].ypos - 1][st->particles[i].xpos] = st->particles[i].colorindex;
+         st->fire[st->particles[i].ypos][st->particles[i].xpos + 1] = st->particles[i].colorindex;
        }
     }
   
-  /* create fire effect */ 
-  for (i = 0; i < iWinHeight; i++)
+  /* create st->fire effect */ 
+  for (i = 0; i < st->iWinHeight; i++)
     {
-      for (j = 0; j < iWinWidth; j++)
+      for (j = 0; j < st->iWinWidth; j++)
        {
-         if (j + 1 >= iWinWidth)
+         if (j + 1 >= st->iWinWidth)
            temp = 0;
          else
-           temp = fire[i][j + 1];
+           temp = st->fire[i][j + 1];
 
          if (j - 1 >= 0)  
-           temp += fire[i][j - 1];
+           temp += st->fire[i][j - 1];
 
          if (i - 1 >= 0)
            {
-             temp += fire[i - 1][j];
+             temp += st->fire[i - 1][j];
              if (j - 1 >= 0)
-               temp += fire[i - 1][j - 1];
-             if (j + 1 < iWinWidth)
-               temp += fire[i - 1][j + 1];
+               temp += st->fire[i - 1][j - 1];
+             if (j + 1 < st->iWinWidth)
+               temp += st->fire[i - 1][j + 1];
            }
          
-         if (i + 1 < iWinHeight)
+         if (i + 1 < st->iWinHeight)
            {
-             temp += fire[i + 1][j];
-             if (j + 1 < iWinWidth)
-               temp += fire[i + 1][j + 1];
+             temp += st->fire[i + 1][j];
+             if (j + 1 < st->iWinWidth)
+               temp += st->fire[i + 1][j + 1];
              if (j - 1 >= 0)
-               temp += fire[i + 1][j - 1];
+               temp += st->fire[i + 1][j - 1];
            }
          
          temp >>= 3;
          
-         if (temp > decay)
+         if (temp > st->decay)
            {
-             temp -= decay;
+             temp -= st->decay;
            }
          else
            temp = 0;
          
-         fire[i][j] = temp;
+         st->fire[i][j] = temp;
        }
     }
   
-  memset( pImage->data, 0, pImage->bytes_per_line * pImage->height );
+  memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height );
   
-  /* draw fire array to screen */
-  for (i = 0; i < iWinHeight; ++i)
+  /* draw st->fire array to screen */
+  for (i = 0; i < st->iWinHeight; ++i)
     {
-      for (j = 0; j < iWinWidth; ++j)
+      for (j = 0; j < st->iWinWidth; ++j)
        {
-         if (fire[i][j] > 0)
-           XPutPixel( pImage, j, i, aiColorVals[ fire[i][j] ] );
+         if (st->fire[i][j] > 0)
+           XPutPixel( st->pImage, j, i, st->aiColorVals[ st->fire[i][j] ] );
        }
     }
-  XPutImage( pDisplay, MainWindow, *pGC, pImage,
-            0,0,0,0, iWinWidth, iWinHeight );
-  XSync( pDisplay, False );
+  XPutImage( st->dpy, st->window, st->gc, st->pImage,
+            0,0,0,0, st->iWinWidth, st->iWinHeight );
 }
 
-static unsigned long * SetPalette(Display *pDisplay, Window Win, signed short *piColorCount )
+static unsigned long * SetPalette(struct state *st)
 {
        XWindowAttributes XWinAttribs;
        XColor Color, *aColors;
-       unsigned long *aiColorVals;
        signed short iColor;
 
-       XGetWindowAttributes( pDisplay, Win, &XWinAttribs );
+       XGetWindowAttributes( st->dpy, st->window, &XWinAttribs );
        
-       *piColorCount = get_integer_resource( "ncolors", "Integer" );
-       if( *piColorCount < 16 )        *piColorCount = 16;
-       if( *piColorCount > 255 )       *piColorCount = 256;
+       st->iColorCount = get_integer_resource(st->dpy,  "ncolors", "Integer" );
+       if( st->iColorCount < 16 )      st->iColorCount = 16;
+       if( st->iColorCount > 255 )     st->iColorCount = 256;
 
-       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) );
        
-       Color.red = Color.green = Color.blue = 65535 / *piColorCount;
+       Color.red = Color.green = Color.blue = 65535 / st->iColorCount;
 
-       /* create fire palette */
-       for( iColor=0; iColor < *piColorCount; iColor++ )
+       /* create st->fire palette */
+       for( iColor=0; iColor < st->iColorCount; iColor++ )
        {
-         if (iColor < *piColorCount >> 3)
+         if (iColor < st->iColorCount >> 3)
            {
              /* black to blue */
              aColors[iColor].red = 0;
              aColors[iColor].green = 0;
              aColors[iColor].blue = Color.blue * (iColor << 1);
            }
-         else if (iColor < *piColorCount >> 2)
+         else if (iColor < st->iColorCount >> 2)
            {
              /* blue to red */
-             signed short temp = (iColor - (*piColorCount >> 3));
+             signed short temp = (iColor - (st->iColorCount >> 3));
              aColors[iColor].red = Color.red * (temp << 3);
              aColors[iColor].green = 0;
              aColors[iColor].blue = 16383 - Color.blue * (temp << 1);
            }
-         else if (iColor < (*piColorCount >> 2) + (*piColorCount >> 3))
+         else if (iColor < (st->iColorCount >> 2) + (st->iColorCount >> 3))
            {
              /* red to yellow */
-             signed short temp = (iColor - (*piColorCount >> 2)) << 3;
+             signed short temp = (iColor - (st->iColorCount >> 2)) << 3;
              aColors[iColor].red = 65535;
              aColors[iColor].green = Color.green * temp;
              aColors[iColor].blue = 0;
            }
-         else if (iColor < *piColorCount >> 1)
+         else if (iColor < st->iColorCount >> 1)
            {
              /* yellow to white */
-             signed int temp = (iColor - ((*piColorCount >> 2) + (*piColorCount >> 3))) << 3;
+             signed int temp = (iColor - ((st->iColorCount >> 2) + (st->iColorCount >> 3))) << 3;
              aColors[iColor].red = 65535;
              aColors[iColor].green = 65535;
              aColors[iColor].blue = Color.blue * temp;
@@ -283,45 +264,45 @@ static unsigned long * SetPalette(Display *pDisplay, Window Win, signed short *p
              aColors[iColor].red = aColors[iColor].green = aColors[iColor].blue = 65535;
            }
 
-         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;
        }
 
-       if (heat < *piColorCount)
-         *piColorCount = heat;
+       if (st->heat < st->iColorCount)
+         st->iColorCount = st->heat;
        
        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, i;
 
        /* Create the Image for drawing */
-       XGetWindowAttributes( pDisplay, Win, &XWinAttribs );
+       XGetWindowAttributes( st->dpy, st->window, &XWinAttribs );
 
        /* Find the preferred bits-per-pixel. (jwz) */
        {
                int 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 )
                        {
@@ -333,135 +314,189 @@ 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, 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;
 
-       /* create fire array */
-       fire = calloc( iWinHeight, sizeof(unsigned char*));
-       for (i = 0; i < iWinHeight; ++i)
-         fire[i] = calloc( iWinWidth, sizeof(unsigned char));
+       /* create st->fire array */
+       st->fire = calloc( st->iWinHeight, sizeof(unsigned char*));
+       for (i = 0; i < st->iWinHeight; ++i)
+         st->fire[i] = calloc( st->iWinWidth, sizeof(unsigned char));
 
-       /*create particles */
-       particles = malloc (nParticleCount * sizeof(PARTICLE));
+       /*create st->particles */
+       st->particles = malloc (st->nParticleCount * sizeof(PARTICLE));
 }
 
-void screenhack(Display *pDisplay, Window Win )
+static void *
+eruption_init (Display *dpy, Window window)
 {
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
        XWindowAttributes XWinAttribs;
-       GC gc;
-       signed short iColorCount = 0;
-       unsigned long *aiColorVals = NULL;
        unsigned short sum = 0;
-       XImage *pImage = NULL;
 #ifdef VERBOSE
        time_t nTime = time( NULL );
        unsigned short iFrame = 0;
 #endif  /*  VERBOSE */
-       int delay, cycles, i;
-
-       nParticleCount = get_integer_resource( "particles", "Integer" );
-       if (nParticleCount < 100)
-         nParticleCount = 100;
-       if (nParticleCount > 2000)
-         nParticleCount = 2000;
-
-       decay = get_integer_resource( "cooloff", "Integer" );
-       if (decay <= 0)
-         decay = 0;
-       if (decay > 10)
-         decay = 10;
-
-       gravity = get_integer_resource( "gravity", "Integer" );
-       if (gravity < -5)
-         gravity = -5;
-       if (gravity > 5)
-         gravity = 5;
-
-       heat = get_integer_resource( "heat", "Integer" );
-       if (heat < 64)
-         heat = 64;
-       if (heat > 256)
-         heat = 256;
+        int i;
+
+  st->dpy = dpy;
+  st->window = window;
+
+       st->nParticleCount = get_integer_resource(st->dpy,  "particles", "Integer" );
+       if (st->nParticleCount < 100)
+         st->nParticleCount = 100;
+       if (st->nParticleCount > 2000)
+         st->nParticleCount = 2000;
+
+       st->decay = get_integer_resource(st->dpy,  "cooloff", "Integer" );
+       if (st->decay <= 0)
+         st->decay = 0;
+       if (st->decay > 10)
+         st->decay = 10;
+
+       st->gravity = get_integer_resource(st->dpy,  "gravity", "Integer" );
+       if (st->gravity < -5)
+         st->gravity = -5;
+       if (st->gravity > 5)
+         st->gravity = 5;
+
+       st->heat = get_integer_resource(st->dpy,  "heat", "Integer" );
+       if (st->heat < 64)
+         st->heat = 64;
+       if (st->heat > 256)
+         st->heat = 256;
 
 #ifdef VERBOSE 
-       printf( "%s: Allocated %d particles\n", progclass, nParticleCount );
+       printf( "%s: Allocated %d st->particles\n", progclass, st->nParticleCount );
 #endif  /*  VERBOSE */
 
-       Initialize( pDisplay, Win, &gc, &pImage );
+       Initialize( st );
 
-       ydelta = 0;
-       while (sum < (iWinHeight >> 1) - SPREAD)
+       st->ydelta = 0;
+       while (sum < (st->iWinHeight >> 1) - SPREAD)
          {
-           ydelta++;
-           sum += ydelta;
+           st->ydelta++;
+           sum += st->ydelta;
          }
 
        sum = 0;
-       while (sum < (iWinWidth >> 3))
+       while (sum < (st->iWinWidth >> 3))
          {
-           xdelta++;
-           sum += xdelta;
+           st->xdelta++;
+           sum += st->xdelta;
          }
 
-       delay = get_integer_resource( "delay", "Integer" );
-       cycles = get_integer_resource( "cycles", "Integer" );
-       i = cycles;
+       st->delay = get_integer_resource(st->dpy,  "delay", "Integer" );
+       st->cycles = get_integer_resource(st->dpy,  "cycles", "Integer" );
+       i = st->cycles;
 
-       cache();
+       cache(st);
        
-       XGetWindowAttributes( pDisplay, Win, &XWinAttribs );
-       XFreeColors( pDisplay, XWinAttribs.colormap, aiColorVals, iColorCount, 0 );
-       free( aiColorVals );
-       aiColorVals = SetPalette( pDisplay, Win, &iColorCount );
-       XClearWindow( pDisplay, Win );
-       memset( pImage->data, 0, pImage->bytes_per_line * pImage->height );
-
-       while( 1 )
-         {
-           screenhack_handle_events( pDisplay );
+       XGetWindowAttributes( st->dpy, st->window, &XWinAttribs );
+       XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, st->iColorCount, 0 );
+       free( st->aiColorVals );
+       st->aiColorVals = SetPalette( st );
+       XClearWindow( st->dpy, st->window );
+       memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height );
+
+        st->draw_i = -1;
+
+        return st;
+}
+
+
+static unsigned long
+eruption_draw (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
            
-           if( i++ >= cycles )
-             {
-               /* compute random center */
-               unsigned short xcenter, ycenter;
-               xcenter = random() % iWinWidth;
-               ycenter = random() % iWinHeight;
+  if( st->draw_i < 0 || st->draw_i++ >= st->cycles )
+    {
+      /* compute random center */
+      unsigned short xcenter, ycenter;
+      xcenter = random() % st->iWinWidth;
+      ycenter = random() % st->iWinHeight;
                
-               for (i = 0; i < nParticleCount; i++)
-                 init_particle(particles + i, iColorCount - 1, xcenter, ycenter);
-               i = 0;
-             }
-           
-           Execute( pDisplay, Win, &gc, pImage, iColorCount - 1, aiColorVals );
+      for (st->draw_i = 0; st->draw_i < st->nParticleCount; st->draw_i++)
+        init_particle(st, st->particles + st->draw_i, xcenter, ycenter);
+      st->draw_i = 0;
+    }
            
-           if( delay && !(i % 4) )
-             usleep(delay);
+  Execute( st );
            
 #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", progclass, iFrame );
+      nTime = time( NULL );
+      iFrame = 0;
+    }
 #endif  /*  VERBOSE */
-         }
+
+  return st->delay;
+}
        
-       free( pImage->data );
-       XDestroyImage( pImage );
-       free( aiColorVals );
-       for (i = 0; i < iWinHeight; ++i)
-         free( fire[i] );
-       free( fire );
-       free( particles );
+
+static void
+eruption_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
+}
+
+static Bool
+eruption_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  return False;
 }
 
+static void
+eruption_free (Display *dpy, Window window, void *closure)
+{
+#if 0
+  struct state *st = (struct state *) closure;
+       free( st->pImage->data );
+       XDestroyImage( st->pImage );
+       free( st->aiColorVals );
+       for (i = 0; i < st->iWinHeight; ++i)
+         free( st->fire[i] );
+       free( st->fire );
+       free( st->particles );
+#endif
+}
+
+
+static const char *eruption_defaults [] = {
+  ".background: black",
+  ".foreground: white",
+  "*cycles:   80",
+  "*ncolors:  256",
+  "*delay:    10000",
+  "*particles: 300",
+  "*cooloff: 2",
+  "*gravity: 1",
+  "*heat: 256",
+  0
+};
+
+static XrmOptionDescRec eruption_options [] = {
+  { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
+  { "-delay",   ".delay",   XrmoptionSepArg, 0 },
+  { "-cycles",  ".cycles",  XrmoptionSepArg, 0 },
+  { "-particles",  ".particles",  XrmoptionSepArg, 0 },
+  { "-cooloff",  ".cooloff",  XrmoptionSepArg, 0 },
+  { "-gravity",  ".gravity",  XrmoptionSepArg, 0 },
+  { "-heat",  ".heat",  XrmoptionSepArg, 0 },
+  { 0, 0, 0, 0 }
+};
+
+
+XSCREENSAVER_MODULE ("Eruption", eruption)
+
 /* End of Module - "eruption.c" */