http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.01.tar.gz
[xscreensaver] / hacks / demon.c
index db0255aefbbee22bdaf4dcaf5d7caf568b9a3cdc..df7ea3e8a501ad1a487a9c09e350c2f86f53b0d8 100644 (file)
@@ -2,7 +2,7 @@
 /* demon --- David Griffeath's cellular automata */
 
 #if !defined( lint ) && !defined( SABER )
-static const char sccsid[] = "@(#)demon.c      4.07 97/11/24 xlockmore";
+static const char sccsid[] = "@(#)demon.c      5.00 2000/11/01 xlockmore";
 
 #endif
 
@@ -22,16 +22,17 @@ static const char sccsid[] = "@(#)demon.c   4.07 97/11/24 xlockmore";
  * other special, indirect and consequential damages.
  *
  * Revision History:
- * 10-May-97: Compatible with xscreensaver
- * 16-Apr-97: -neighbors 3, 9 (not sound mathematically), 12, and 8 added
- * 30-May-96: Ron Hitchens <ron@idiom.com>
+ * 01-Nov-2000: Allocation checks
+ * 10-May-1997: Compatible with xscreensaver
+ * 16-Apr-1997: -neighbors 3, 9 (not sound mathematically), 12, and 8 added
+ * 30-May-1996: Ron Hitchens <ron@idiom.com>
  *            Fixed memory management that caused leaks
- * 14-Apr-96: -neighbors 6 runtime-time option added
- * 21-Aug-95: Coded from A.K. Dewdney's "Computer Recreations", Scientific
- *            American Magazine" Aug 1989 pp 102-105.  Also very similar to
- *            hodgepodge machine described in A.K. Dewdney's "Computer
- *            Recreations", Scientific American Magazine" Aug 1988 pp 104-107.
- *            also used life.c as a guide.
+ * 14-Apr-1996: -neighbors 6 runtime-time option added
+ * 21-Aug-1995: Coded from A.K. Dewdney's "Computer Recreations", Scientific
+ *              American Magazine" Aug 1989 pp 102-105.  Also very similar
+ *              to hodgepodge machine described in A.K. Dewdney's "Computer
+ *              Recreations", Scientific American Magazine" Aug 1988
+ *              pp 104-107.  Also used life.c as a guide.
  */
 
 /*-
@@ -39,7 +40,7 @@ static const char sccsid[] = "@(#)demon.c     4.07 97/11/24 xlockmore";
  */
 
 /*-
-  Grid     Number of Neigbors
+  Grid     Number of Neighbors
   ----     ------------------
   Square   4 or 8
   Hexagon  6
@@ -47,47 +48,64 @@ static const char sccsid[] = "@(#)demon.c   4.07 97/11/24 xlockmore";
 */
 
 #ifdef STANDALONE
+#define MODE_demon
 #define PROGCLASS "Demon"
 #define HACK_INIT init_demon
 #define HACK_DRAW draw_demon
 #define demon_opts xlockmore_opts
-#define DEFAULTS       "*delay:        50000 \n"       \
                                      "*count:            0 \n"       \
                                      "*cycles:        1000 \n"       \
                                      "*size:            -7 \n"       \
                                      "*ncolors:         64 \n"       \
                                      "*neighbors:    0 \n"
-# define SMOOTH_COLORS
-# include "xlockmore.h"                /* in xscreensaver distribution */
+#define DEFAULTS "*delay: 50000 \n" \
"*count: 0 \n" \
"*cycles: 1000 \n" \
"*size: -7 \n" \
"*ncolors: 64 \n" \
"*neighbors: 0 \n"
+#define UNIFORM_COLORS
+#include "xlockmore.h"         /* in xscreensaver distribution */
 #else /* STANDALONE */
-# include "xlock.h"                    /* in xlockmore distribution */
+#include "xlock.h"             /* in xlockmore distribution */
+
 #endif /* STANDALONE */
 #include "automata.h"
 
+#ifdef MODE_demon
+
 /*-
  * neighbors of 0 randomizes it between 3, 4, 6, 8, 9, and 12.
  */
-#ifdef STANDALONE
-static int neighbors;
-#else
-extern int  neighbors;
-#endif /* !STANDALONE */
+#define DEF_NEIGHBORS  "0"      /* choose random value */
+
+static int  neighbors;
+
+static XrmOptionDescRec opts[] =
+{
+       {(char *) "-neighbors", (char *) ".demon.neighbors", XrmoptionSepArg, (caddr_t) NULL}
+};
+
+static argtype vars[] =
+{
+       {(caddr_t *) & neighbors, (char *) "neighbors", (char *) "Neighbors", (char *) DEF_NEIGHBORS, t_Int}
+};
+static OptionStruct desc[] =
+{
+       {(char *) "-neighbors num", (char *) "squares 4 or 8, hexagons 6, triangles 3, 9 or 12"}
+};
 
 ModeSpecOpt demon_opts =
-{0, NULL, 0, NULL, NULL};
+{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
 
 #ifdef USE_MODULES
 ModStruct   demon_description =
 {"demon", "init_demon", "draw_demon", "release_demon",
- "refresh_demon", "init_demon", NULL, &demon_opts,
+ "refresh_demon", "init_demon", (char *) NULL, &demon_opts,
  50000, 0, 1000, -7, 64, 1.0, "",
  "Shows Griffeath's cellular automata", 0, NULL};
 
 #endif
 
 #define DEMONBITS(n,w,h)\
-  dp->pixmaps[dp->init_bits++]=\
-  XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1)
+  if ((dp->pixmaps[dp->init_bits]=\
+  XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\
+  free_demon(display,dp); return;} else {dp->init_bits++;}
 
 #define REDRAWSTEP 2000                /* How many cells to draw per cycle */
 #define MINSTATES 2
@@ -129,7 +147,7 @@ static char plots[2][NEIGHBORKINDS] =
        {12, 16, 18, 20, 22, 24}        /* Number of states */
 };
 
-static demonstruct *demons = NULL;
+static demonstruct *demons = (demonstruct *) NULL;
 
 static void
 drawcell(ModeInfo * mi, int col, int row, unsigned char state)
@@ -161,8 +179,8 @@ drawcell(ModeInfo * mi, int col, int row, unsigned char state)
                dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
                dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
                if (dp->xs == 1 && dp->ys == 1)
-                       XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi),
-                                      gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y, 1, 1);
+                       XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
+                                      gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
                else
                        XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
                            dp->shape.hexagon, 6, Convex, CoordModePrevious);
@@ -176,9 +194,9 @@ drawcell(ModeInfo * mi, int col, int row, unsigned char state)
                dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
                dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
                if (dp->xs <= 3 || dp->ys <= 3)
-                       XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
+                       XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
                        ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
-                                      dp->shape.triangle[orient][0].y, 1, 1);
+                                      dp->shape.triangle[orient][0].y);
                else {
                        if (orient)
                                dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
@@ -191,18 +209,22 @@ drawcell(ModeInfo * mi, int col, int row, unsigned char state)
        }
 }
 
-static void
+static Bool
 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
 {
        demonstruct *dp = &demons[MI_SCREEN(mi)];
        CellList   *current;
 
        current = dp->cellList[state];
-       dp->cellList[state] = (CellList *) malloc(sizeof (CellList));
+       if ((dp->cellList[state] = (CellList *)
+               malloc(sizeof (CellList))) == NULL) {
+               return False;
+       }
        dp->cellList[state]->pt.x = col;
        dp->cellList[state]->pt.y = row;
        dp->cellList[state]->next = current;
        dp->ncells[state]++;
+       return True;
 }
 
 #ifdef DEBUG
@@ -235,8 +257,8 @@ free_state(demonstruct * dp, int state)
                dp->cellList[state] = dp->cellList[state]->next;
                (void) free((void *) current);
        }
-       dp->cellList[state] = NULL;
-       if (dp->ncells)
+       dp->cellList[state] = (CellList *) NULL;
+       if (dp->ncells != NULL)
                dp->ncells[state] = 0;
 }
 
@@ -249,7 +271,7 @@ free_list(demonstruct * dp)
        for (state = 0; state < dp->states; state++)
                free_state(dp, state);
        (void) free((void *) dp->cellList);
-       dp->cellList = NULL;
+       dp->cellList = (CellList **) NULL;
 }
 
 static void
@@ -260,19 +282,35 @@ free_struct(demonstruct * dp)
        }
        if (dp->ncells != NULL) {
                (void) free((void *) dp->ncells);
-               dp->ncells = NULL;
+               dp->ncells = (int *) NULL;
        }
        if (dp->oldcell != NULL) {
                (void) free((void *) dp->oldcell);
-               dp->oldcell = NULL;
+               dp->oldcell = (unsigned char *) NULL;
        }
        if (dp->newcell != NULL) {
                (void) free((void *) dp->newcell);
-               dp->newcell = NULL;
+               dp->newcell = (unsigned char *) NULL;
        }
 }
 
 static void
+free_demon(Display *display, demonstruct *dp)
+{
+       int         shade;
+
+       if (dp->stippledGC != None) {
+               XFreeGC(display, dp->stippledGC);
+               dp->stippledGC = None;
+       }
+       for (shade = 0; shade < dp->init_bits; shade++) {
+               XFreePixmap(display, dp->pixmaps[shade]);
+       }
+       dp->init_bits = 0;
+       free_struct(dp);
+}
+
+static Bool
 draw_state(ModeInfo * mi, int state)
 {
        demonstruct *dp = &demons[MI_SCREEN(mi)];
@@ -309,8 +347,8 @@ draw_state(ModeInfo * mi, int state)
                        dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
                        dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
                        if (dp->xs == 1 && dp->ys == 1)
-                               XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi),
-                                              gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y, 1, 1);
+                               XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
+                                              gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
                        else
                                XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
                                             dp->shape.hexagon, 6, Convex, CoordModePrevious);
@@ -321,7 +359,10 @@ draw_state(ModeInfo * mi, int state)
                int         ncells = 0;
 
                /* Create Rectangle list from part of the cellList */
-               rects = (XRectangle *) malloc(dp->ncells[state] * sizeof (XRectangle));
+               if ((rects = (XRectangle *) malloc(dp->ncells[state] *
+                        sizeof (XRectangle))) == NULL) {
+                       return False;
+               }
                current = dp->cellList[state];
                while (current) {
                        rects[ncells].x = dp->xb + current->pt.x * dp->xs;
@@ -346,9 +387,9 @@ draw_state(ModeInfo * mi, int state)
                        dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
                        dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
                        if (dp->xs <= 3 || dp->ys <= 3)
-                               XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
+                               XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
                                               ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
-                                     dp->shape.triangle[orient][0].y, 1, 1);
+                                     dp->shape.triangle[orient][0].y);
                        else {
                                if (orient)
                                        dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
@@ -362,6 +403,7 @@ draw_state(ModeInfo * mi, int state)
        }
        free_state(dp, state);
        XFlush(MI_DISPLAY(mi));
+       return True;
 }
 
 static void
@@ -374,7 +416,8 @@ RandomSoup(ModeInfo * mi)
                for (col = 0; col < dp->ncols; ++col) {
                        dp->oldcell[col + mrow] =
                                (unsigned char) LRAND() % ((unsigned char) dp->states);
-                       addtolist(mi, col, row, dp->oldcell[col + mrow]);
+                       if (!addtolist(mi, col, row, dp->oldcell[col + mrow]))
+                               return; /* sparse soup */
                }
                mrow += dp->ncols;
        }
@@ -394,6 +437,7 @@ init_demon(ModeInfo * mi)
                        return;
        }
        dp = &demons[MI_SCREEN(mi)];
+
        dp->generation = 0;
        dp->redrawing = 0;
        if (MI_NPIXELS(mi) < NUMSTIPPLES) {
@@ -401,13 +445,18 @@ init_demon(ModeInfo * mi)
                        XGCValues   gcv;
 
                        gcv.fill_style = FillOpaqueStippled;
-                       dp->stippledGC = XCreateGC(display, window, GCFillStyle, &gcv);
+                       if ((dp->stippledGC = XCreateGC(display, window,
+                                GCFillStyle, &gcv)) == None) {
+                               free_demon(display, dp);
+                               return;
+                       }
                }
                if (dp->init_bits == 0) {
                        int         i;
 
-                       for (i = 1; i < NUMSTIPPLES; i++)
+                       for (i = 1; i < NUMSTIPPLES; i++) {
                                DEMONBITS(stipples[i], STIPPLESIZE, STIPPLESIZE);
+                       }
                }
        }
        free_struct(dp);
@@ -429,8 +478,15 @@ init_demon(ModeInfo * mi)
                dp->states = NRAND(-dp->states - MINSTATES + 1) + MINSTATES;
        else if (dp->states < MINSTATES)
                dp->states = plots[1][nk];
-       dp->cellList = (CellList **) calloc(dp->states, sizeof (CellList *));
-       dp->ncells = (int *) calloc(dp->states, sizeof (int));
+       if ((dp->cellList = (CellList **) calloc(dp->states,
+               sizeof (CellList *))) == NULL) {
+               free_demon(display, dp);
+               return;
+       }
+       if ((dp->ncells = (int *) calloc(dp->states, sizeof (int))) == NULL) {
+               free_demon(display, dp);
+               return;
+       }
 
        dp->state = 0;
 
@@ -440,10 +496,10 @@ init_demon(ModeInfo * mi)
        if (dp->neighbors == 6) {
                int         nccols, ncrows, i;
 
-               if (dp->width < 2)
-                       dp->width = 2;
-               if (dp->height < 4)
-                       dp->height = 4;
+               if (dp->width < 8)
+                       dp->width = 8;
+               if (dp->height < 8)
+                       dp->height = 8;
                if (size < -MINSIZE)
                        dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
                                      MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
@@ -457,11 +513,11 @@ init_demon(ModeInfo * mi)
                                               MINGRIDSIZE));
                dp->xs = dp->ys;
                nccols = MAX(dp->width / dp->xs - 2, 2);
-               ncrows = MAX(dp->height / dp->ys - 1, 2);
+               ncrows = MAX(dp->height / dp->ys - 1, 4);
                dp->ncols = nccols / 2;
                dp->nrows = 2 * (ncrows / 4);
                dp->xb = (dp->width - dp->xs * nccols) / 2 + dp->xs / 2;
-               dp->yb = (dp->height - dp->ys * (ncrows / 2) * 2) / 2 + dp->ys;
+               dp->yb = (dp->height - dp->ys * (ncrows / 2) * 2) / 2 + dp->ys - 2;
                for (i = 0; i < 6; i++) {
                        dp->shape.hexagon[i].x = (dp->xs - 1) * hexagonUnit[i].x;
                        dp->shape.hexagon[i].y = ((dp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
@@ -518,11 +574,17 @@ init_demon(ModeInfo * mi)
 
        MI_CLEARWINDOW(mi);
 
-       dp->oldcell = (unsigned char *)
-               malloc(dp->ncols * dp->nrows * sizeof (unsigned char));
+       if ((dp->oldcell = (unsigned char *)
+               malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
+               free_demon(display, dp);
+               return;
+       }
 
-       dp->newcell = (unsigned char *)
-               malloc(dp->ncols * dp->nrows * sizeof (unsigned char));
+       if ((dp->newcell = (unsigned char *)
+               malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
+               free_demon(display, dp);
+               return;
+       }
 
        RandomSoup(mi);
 }
@@ -530,11 +592,16 @@ init_demon(ModeInfo * mi)
 void
 draw_demon(ModeInfo * mi)
 {
-       demonstruct *dp = &demons[MI_SCREEN(mi)];
        int         i, j, k, l, mj = 0, ml;
+       demonstruct *dp;
 
-       MI_IS_DRAWN(mi) = True;
+       if (demons == NULL)
+               return;
+       dp = &demons[MI_SCREEN(mi)];
+       if (dp->cellList == NULL)
+               return;
 
+       MI_IS_DRAWN(mi) = True;
        if (dp->state >= dp->states) {
                (void) memcpy((char *) dp->newcell, (char *) dp->oldcell,
                              dp->ncols * dp->nrows * sizeof (unsigned char));
@@ -554,7 +621,6 @@ draw_demon(ModeInfo * mi)
                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
                                        /* E */
                                        k = (i + 1 == dp->ncols) ? 0 : i + 1;
-                                       l = j;
                                        ml = mj;
                                        if (dp->oldcell[k + ml] ==
                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
@@ -581,7 +647,6 @@ draw_demon(ModeInfo * mi)
                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
                                        /* W */
                                        k = (!i) ? dp->ncols - 1 : i - 1;
-                                       l = j;
                                        ml = mj;
                                        if (dp->oldcell[k + ml] ==
                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
@@ -611,7 +676,6 @@ draw_demon(ModeInfo * mi)
                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
                                        /* E */
                                        k = (i + 1 == dp->ncols) ? 0 : i + 1;
-                                       l = j;
                                        ml = mj;
                                        if (dp->oldcell[k + ml] ==
                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
@@ -676,7 +740,6 @@ draw_demon(ModeInfo * mi)
                                        if ((i + j) % 2) {      /* right */
                                                /* W */
                                                k = (!i) ? dp->ncols - 1 : i - 1;
-                                               l = j;
                                                ml = mj;
                                                if (dp->oldcell[k + ml] ==
                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
@@ -684,7 +747,6 @@ draw_demon(ModeInfo * mi)
                                        } else {        /* left */
                                                /* E */
                                                k = (i + 1 == dp->ncols) ? 0 : i + 1;
-                                               l = j;
                                                ml = mj;
                                                if (dp->oldcell[k + ml] ==
                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
@@ -846,7 +908,10 @@ draw_demon(ModeInfo * mi)
                        for (i = 0; i < dp->ncols; i++)
                                if (dp->oldcell[i + mj] != dp->newcell[i + mj]) {
                                        dp->oldcell[i + mj] = dp->newcell[i + mj];
-                                       addtolist(mi, i, j, dp->oldcell[i + mj]);
+                                       if (!addtolist(mi, i, j, dp->oldcell[i + mj])) {
+                                               free_demon(MI_DISPLAY(mi), dp);
+                                               return;
+                                       }
                                }
                        mj += dp->ncols;
                }
@@ -855,7 +920,10 @@ draw_demon(ModeInfo * mi)
                dp->state = 0;
        } else {
                if (dp->ncells[dp->state])
-                       draw_state(mi, dp->state);
+                       if (!draw_state(mi, dp->state)) {
+                               free_demon(MI_DISPLAY(mi), dp);
+                               return;
+                       }
                dp->state++;
        }
        if (dp->redrawing) {
@@ -877,26 +945,24 @@ release_demon(ModeInfo * mi)
        if (demons != NULL) {
                int         screen;
 
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
-                       demonstruct *dp = &demons[screen];
-                       int         shade;
-
-                       if (dp->stippledGC != None) {
-                               XFreeGC(MI_DISPLAY(mi), dp->stippledGC);
-                       }
-                       for (shade = 0; shade < dp->init_bits; shade++)
-                               XFreePixmap(MI_DISPLAY(mi), dp->pixmaps[shade]);
-                       free_struct(dp);
-               }
+               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
+                       free_demon(MI_DISPLAY(mi), &demons[screen]);
                (void) free((void *) demons);
-               demons = NULL;
+               demons = (demonstruct *) NULL;
        }
-} void
+}
 
+void
 refresh_demon(ModeInfo * mi)
 {
-       demonstruct *dp = &demons[MI_SCREEN(mi)];
+       demonstruct *dp;
+
+       if (demons == NULL)
+               return;
+       dp = &demons[MI_SCREEN(mi)];
 
        dp->redrawing = 1;
        dp->redrawpos = 0;
 }
+
+#endif /* MODE_demon */