X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fmunch.c;h=226edc210dd211768627c833dd1ea84b5cd196f7;hp=b3cd73517d2c477dc638eb727a72a7bdd1586476;hb=49f5b54f312fe4ac2e9bc47581a72451bd0e8439;hpb=ccb7f4903325f92555a9722bba74b58346654ba0 diff --git a/hacks/munch.c b/hacks/munch.c index b3cd7351..226edc21 100644 --- a/hacks/munch.c +++ b/hacks/munch.c @@ -41,108 +41,89 @@ #define SHIFT_KY (0x04) #define GRAV (0x08) -char *progclass = "Munch"; -char *defaults [] = { - ".background: black", - ".foreground: white", - "*delay: 5000", - "*hold: 100000", - "*clear: 50", - "*logminwidth: 7", - "*shift: True", - "*xor: True", - 0 -}; +struct state { + Display *dpy; + Window window; -XrmOptionDescRec options [] = { - { "-delay", ".delay", XrmoptionSepArg, 0 }, - { "-hold", ".hold", XrmoptionSepArg, 0 }, - { "-clear", ".clear", XrmoptionSepArg, "true" }, - { "-shift", ".shift", XrmoptionNoArg, "true" }, - { "-no-shift", ".shift", XrmoptionNoArg, "false" }, - { "-logminwidth", ".logminwidth", XrmoptionSepArg, 0 }, - { "-xor", ".xor", XrmoptionNoArg, "true" }, - { "-no-xor", ".xor", XrmoptionNoArg, "false" }, - { 0, 0, 0, 0 } -}; + GC gc; + int delay, hold, clear, logminwidth, shiftk, xor; + int logmaxwidth; + int maxwidth; + int randflags; + int thiswidth; + XWindowAttributes xgwa; -static GC gc; -/* only configurable things right now */ -static int delay, hold, clear, logminwidth, shiftk, xor; + int munch_t; -static void munchOnce (Display* dpy, Window w, - int width, /* pixels */ - int atX, int atY, /* pixels */ - int kX, int kT, int kY, /* pixels */ - int grav /* 0 or not */) { + int reset; + int atX, atY, kX, kT, kY, grav; + int square_count; +}; - int x, y, t; - static Colormap cmap; - XWindowAttributes xgwa; - XColor fgc; - int drawX, drawY; - /* - fprintf(stderr,"Doing width %d at %d %d shift %d %d %d grav %d\n", - width, atX, atY, kX, kT, kY, grav); - */ - - XGetWindowAttributes (dpy, w, &xgwa); +static int munchOnce (struct state *st, int width) +{ - if (!mono_p) { - /* XXX there are probably bugs with this. */ - cmap = xgwa.colormap; - + if (st->munch_t == 0) { + /* + fprintf(stderr,"Doing width %d at %d %d shift %d %d %d grav %d\n", + width, atX, atY, kX, kT, kY, grav); + */ + + if (!mono_p) { + XColor fgc; fgc.red = random() % 65535; fgc.green = random() % 65535; fgc.blue = random() % 65535; - if (XAllocColor(dpy, cmap, &fgc)) { - XSetForeground(dpy, gc, fgc.pixel); + if (XAllocColor(st->dpy, st->xgwa.colormap, &fgc)) { + XSetForeground(st->dpy, st->gc, fgc.pixel); } + } } /* Finally draw this munching square. */ - for(t = 0; t < width; t++) { - for(x = 0; x < width; x++) { - /* figure out the next point */ - y = ((x ^ ((t + kT) % width)) + kY) % width; - - drawX = ((x + kX) % width) + atX; - drawY = (grav ? y + atY : atY + width - 1 - y); - - /* used to be bugs where it would draw partially offscreen. - while that might be a pretty feature, I didn't want it to do - that yet. if these trigger, please let me know. - */ -/* assert(drawX >= 0 && drawX < xgwa.width); - assert(drawY >= 0 && drawY < xgwa.height); -*/ - - XDrawPoint(dpy, w, gc, drawX, drawY); - /* XXX may want to change this to XDrawPoints, - but it's fast enough without it for the moment. */ + /* for(munch_t = 0; munch_t < width; munch_t++) */ + { + int x; + for(x = 0; x < width; x++) { + /* figure out the next point */ + int y = ((x ^ ((st->munch_t + st->kT) % width)) + st->kY) % width; + int drawX = ((x + st->kX) % width) + st->atX; + int drawY = (st->grav ? y + st->atY : st->atY + width - 1 - y); + + /* used to be bugs where it would draw partially offscreen. + while that might be a pretty feature, I didn'munch_t want it to do + that yet. if these trigger, please let me know. + */ + /* assert(drawX >= 0 && drawX < xgwa.width); + assert(drawY >= 0 && drawY < xgwa.height); + */ + + XDrawPoint(st->dpy, st->window, st->gc, drawX, drawY); + /* XXX may want to change this to XDrawPoints, + but it's fast enough without it for the moment. */ - } - - /* we've drawn one pass' worth of points. let the server catch up - or this won't be interesting to watch at all. we call this here - in the hopes of having one whole sequence of dots appear at the - same time (one for each value of x, surprisingly enough) - */ - XSync(dpy, False); - screenhack_handle_events (dpy); - if (delay) usleep(delay); + } + } + + st->munch_t++; + if (st->munch_t >= width) { + st->munch_t = 0; + return 1; } + + return 0; } /* * dumb way to get # of digits in number. Probably faster than actually * doing a log and a division, maybe. */ -static int dumb_log_2(int k) { +static int dumb_log_2(int k) +{ int r = -1; while (k > 0) { k >>= 1; r++; @@ -150,109 +131,168 @@ static int dumb_log_2(int k) { return r; } -/* This parses arguments, initializes the window, etc., and finally starts - * calling munchOnce ad infinitum. - */ -void -screenhack (dpy, w) Display *dpy; Window w; +static void * +munch_init (Display *dpy, Window w) { - int logmaxwidth; - int maxwidth; - XWindowAttributes xgwa; - Colormap cmap; + struct state *st = (struct state *) calloc (1, sizeof(*st)); XGCValues gcv; - int n = 0; /* number of squares before we have to clear */ - int randflags; - int thiswidth; + st->dpy = dpy; + st->window = w; + /* get the dimensions of the window */ - XGetWindowAttributes (dpy, w, &xgwa); + XGetWindowAttributes (st->dpy, w, &st->xgwa); /* We need a square; limit on screen size? */ /* we want a power of 2 for the width or the munch doesn't fill up. */ - logmaxwidth = (int) - dumb_log_2(xgwa.height < xgwa.width ? xgwa.height : xgwa.width); + st->logmaxwidth = (int) + dumb_log_2(st->xgwa.height < st->xgwa.width ? st->xgwa.height : st->xgwa.width); - maxwidth = 1 << logmaxwidth; + st->maxwidth = 1 << st->logmaxwidth; - if (logmaxwidth < logminwidth) { + if (st->logmaxwidth < st->logminwidth) { /* off-by-one error here? Anyone running on < 640x480? */ fprintf(stderr, "munch: screen too small; use -logminwidth\n"); fprintf(stderr, "\t(width is %d; log is %d; log must be at least " "%d)\n", - (xgwa.height < xgwa.width ? xgwa.height : xgwa.width), - logmaxwidth, logminwidth); + (st->xgwa.height < st->xgwa.width ? st->xgwa.height : st->xgwa.width), + st->logmaxwidth, st->logminwidth); exit(0); } /* create the gc */ - cmap = xgwa.colormap; - gcv.foreground= get_pixel_resource("foreground","Foreground", - dpy, cmap); - gcv.background= get_pixel_resource("background","Background", - dpy, cmap); + gcv.foreground= get_pixel_resource(st->dpy, st->xgwa.colormap, + "foreground","Foreground"); + gcv.background= get_pixel_resource(st->dpy, st->xgwa.colormap, + "background","Background"); - gc = XCreateGC(dpy, w, GCForeground|GCBackground, &gcv); + st->gc = XCreateGC(st->dpy, w, GCForeground|GCBackground, &gcv); - delay = get_integer_resource ("delay", "Integer"); - if (delay < 0) delay = 0; + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + if (st->delay < 0) st->delay = 0; - hold = get_integer_resource ("hold", "Integer"); - if (hold < 0) hold = 0; + st->hold = get_integer_resource (st->dpy, "hold", "Integer"); + if (st->hold < 0) st->hold = 0; - clear = get_integer_resource ("clear", "Integer"); - if (clear < 0) clear = 0; + st->clear = get_integer_resource (st->dpy, "clear", "Integer"); + if (st->clear < 0) st->clear = 0; - logminwidth = get_integer_resource ("logminwidth", "Integer"); - if (logminwidth < 2) logminwidth = 2; + st->logminwidth = get_integer_resource (st->dpy, "logminwidth", "Integer"); + if (st->logminwidth < 2) st->logminwidth = 2; - shiftk = get_boolean_resource("shift", "Boolean"); + st->shiftk = get_boolean_resource(st->dpy, "shift", "Boolean"); - xor = get_boolean_resource("xor", "Boolean"); + st->xor = get_boolean_resource(st->dpy, "xor", "Boolean"); /* always draw xor on mono. */ - if (mono_p || xor) { - XSetFunction(dpy, gc, GXxor); + if (mono_p || st->xor) { + XSetFunction(st->dpy, st->gc, GXxor); } - for(;;) { - /* saves some calls to random. big deal */ - randflags = random(); + st->reset = 1; - /* choose size -- power of two */ - thiswidth = 1 << (logminwidth + - (random() % (1 + logmaxwidth - logminwidth))); + return st; +} - munchOnce(dpy, w, - thiswidth, /* Width, in pixels */ - - /* draw at this location */ - (random() % (xgwa.width <= thiswidth ? 1 - : xgwa.width - thiswidth)), - (random() % (xgwa.height <= thiswidth ? 1 - : xgwa.width - thiswidth)), +static unsigned long +munch_draw (Display *dpy, Window w, void *closure) +{ + struct state *st = (struct state *) closure; + int this_delay = st->delay; + + if (st->reset) + { + st->reset = 0; + + this_delay = st->hold; + /* saves some calls to random. big deal */ + st->randflags = random(); + + /* choose size -- power of two */ + st->thiswidth = 1 << (st->logminwidth + + (random() % (1 + st->logmaxwidth - st->logminwidth))); + + if (st->clear && ++st->square_count >= st->clear) { + XClearWindow(st->dpy, w); + st->square_count = 0; + } + + /* draw at this location */ + st->atX = (random() % (st->xgwa.width <= st->thiswidth ? 1 + : st->xgwa.width - st->thiswidth)); + st->atY = (random() % (st->xgwa.height <= st->thiswidth ? 1 + : st->xgwa.width - st->thiswidth)); - /* wrap-around by these values; no need to % - as we end up doing that later anyway*/ - ((shiftk && (randflags & SHIFT_KX)) - ? (random() % thiswidth) : 0), - ((shiftk && (randflags & SHIFT_KT)) - ? (random() % thiswidth) : 0), - ((shiftk && (randflags & SHIFT_KY)) - ? (random() % thiswidth) : 0), + /* wrap-around by these values; no need to % + as we end up doing that later anyway*/ + st->kX = ((st->shiftk && (st->randflags & SHIFT_KX)) + ? (random() % st->thiswidth) : 0); + st->kT = ((st->shiftk && (st->randflags & SHIFT_KT)) + ? (random() % st->thiswidth) : 0); + st->kY = ((st->shiftk && (st->randflags & SHIFT_KY)) + ? (random() % st->thiswidth) : 0); - /* set the gravity of the munch, or rather, - which direction we draw stuff in. */ - (randflags & GRAV) - ); - - screenhack_handle_events (dpy); - if (hold) usleep(hold); - - if (clear && ++n >= clear) { - XClearWindow(dpy, w); - n = 0; - } + /* set the gravity of the munch, or rather, + which direction we draw stuff in. */ + st->grav = (st->randflags & GRAV); } + + if (munchOnce (st, st->thiswidth)) + st->reset = 1; + +/* printf("%d\n",this_delay);*/ + return this_delay; } + +static void +munch_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->xgwa.width = w; + st->xgwa.height = h; + st->logmaxwidth = (int) + dumb_log_2(st->xgwa.height < st->xgwa.width ? st->xgwa.height : st->xgwa.width); + st->maxwidth = 1 << st->logmaxwidth; +} + +static Bool +munch_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +munch_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *munch_defaults [] = { + ".background: black", + ".foreground: white", + "*delay: 5000", + "*hold: 100000", + "*clear: 50", + "*logminwidth: 7", + "*shift: True", + "*xor: True", + 0 +}; + +static XrmOptionDescRec munch_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-hold", ".hold", XrmoptionSepArg, 0 }, + { "-clear", ".clear", XrmoptionSepArg, "true" }, + { "-shift", ".shift", XrmoptionNoArg, "true" }, + { "-no-shift", ".shift", XrmoptionNoArg, "false" }, + { "-logminwidth", ".logminwidth", XrmoptionSepArg, 0 }, + { "-xor", ".xor", XrmoptionNoArg, "true" }, + { "-no-xor", ".xor", XrmoptionNoArg, "false" }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Munch", munch)