X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fdemon.c;h=df7ea3e8a501ad1a487a9c09e350c2f86f53b0d8;hp=db0255aefbbee22bdaf4dcaf5d7caf568b9a3cdc;hb=a94197e76a5dea5cb60542840809d6c20d0abbf3;hpb=8eb2873d7054e705c4e83f22d18c40946a9e2529 diff --git a/hacks/demon.c b/hacks/demon.c index db0255ae..df7ea3e8 100644 --- a/hacks/demon.c +++ b/hacks/demon.c @@ -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 + * 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 * 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 */