1 /* nerverot, nervous rotation of random thingies, v1.2
2 * by Dan Bornstein, danfuzz@milk.com
3 * Copyright (c) 2000 Dan Bornstein.
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation. No representations are made about the suitability of this
10 * software for any purpose. It is provided "as is" without express or
13 * The goal of this screensaver is to be interesting and compelling to
14 * watch, yet induce a state of nervous edginess in the viewer.
16 * See the included man page for more details.
20 #include "screenhack.h"
24 /* random float in the range (-1..1) */
25 #define RAND_FLOAT_PM1 \
26 (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000) * 2 - 1)
28 /* random float in the range (0..1) */
29 #define RAND_FLOAT_01 \
30 (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000))
34 /* parameters that are user configurable */
37 static int requestedBlotCount;
39 /* delay (usec) between iterations */
42 /* variability of xoff/yoff per iteration (0..1) */
43 static FLOAT nervousness;
45 /* max nervousness radius (0..1) */
46 static FLOAT maxNerveRadius;
48 /* chance per iteration that an event will happen */
49 static FLOAT eventChance;
51 /* fraction (0..1) towards rotation target or scale target to move each
55 /* min and max scale for drawing, as fraction of baseScale */
56 static FLOAT minScale;
57 static FLOAT maxScale;
59 /* min and max radius of blot drawing */
63 /* the number of colors to use */
64 static int colorCount;
69 /* whether or not to do double-buffering */
70 static Bool doubleBuffer;
74 /* non-user-modifiable immutable definitions */
76 /* base scale factor for drawing, calculated as
77 * max(screenWidth,screenHeight) */
80 /* width and height of the window */
81 static int windowWidth;
82 static int windowHeight;
84 /* center position of the window */
88 static Display *display; /* the display to draw on */
89 static Window window; /* the window to draw on */
90 static Drawable drawable; /* the thing to directly draw on */
91 static GC *gcs; /* array of gcs, one per color used */
95 /* structure of the model */
97 /* each point-like thingy to draw is represented as a blot */
100 FLOAT x; /* 3d x position (-1..1) */
101 FLOAT y; /* 3d y position (-1..1) */
102 FLOAT z; /* 3d z position (-1..1) */
103 FLOAT xoff[3][3]; /* display x offset per drawn point (-1..1) */
104 FLOAT yoff[3][3]; /* display x offset per drawn point (-1..1) */
107 /* each drawn line is represented as a LineSegment */
108 typedef struct linesegment_s
117 /* array of the blots in the model */
118 static Blot *blots = NULL;
119 static int blotCount;
121 /* each blot draws as a simple 2d shape with each coordinate as an int
122 * in the range (-1..1); this is the base shape */
123 static XPoint blotShape[] = { { 0, 0}, { 1, 0}, { 1, 1},
124 { 0, 1}, {-1, 1}, {-1, 0},
125 {-1,-1}, { 0,-1}, { 1,-1} };
126 static int blotShapeCount = sizeof (blotShape) / sizeof (XPoint);
128 /* two arrays of line segments; one for the ones to erase, and one for the
131 static LineSegment *segsToDraw = NULL;
132 static LineSegment *segsToErase = NULL;
134 /* current rotation values per axis, scale factor, and light position */
138 static FLOAT curScale;
143 /* target rotation values per axis, scale factor, and light position */
144 static FLOAT xRotTarget;
145 static FLOAT yRotTarget;
146 static FLOAT zRotTarget;
147 static FLOAT scaleTarget;
148 static FLOAT lightXTarget;
149 static FLOAT lightYTarget;
150 static FLOAT lightZTarget;
152 /* current absolute offsets from the center */
153 static int centerXOff = 0;
154 static int centerYOff = 0;
156 /* iterations until the model changes */
157 static int itersTillNext;
165 /* initialize a blot with the given coordinates and random display offsets */
166 static void initBlot (Blot *b, FLOAT x, FLOAT y, FLOAT z)
174 for (i = 0; i < 3; i++)
176 for (j = 0; j < 3; j++)
178 b->xoff[i][j] = RAND_FLOAT_PM1;
179 b->yoff[i][j] = RAND_FLOAT_PM1;
184 /* scale the blots to have a max distance of 1 from the center */
185 static void scaleBlotsToRadius1 (void)
190 for (n = 0; n < blotCount; n++)
193 blots[n].x * blots[n].x +
194 blots[n].y * blots[n].y +
195 blots[n].z * blots[n].z;
196 if (distSquare > max)
209 for (n = 0; n < blotCount; n++)
217 /* randomly reorder the blots */
218 static void randomlyReorderBlots (void)
222 for (n = 0; n < blotCount; n++)
224 int m = RAND_FLOAT_01 * (blotCount - n) + n;
225 Blot tmpBlot = blots[n];
231 /* set up the initial array of blots to be a at the edge of a sphere */
232 static void setupBlotsSphere (void)
236 blotCount = requestedBlotCount;
237 blots = calloc (sizeof (Blot), blotCount);
239 for (n = 0; n < blotCount; n++)
241 /* pick a spot, but reject if its radius is < 0.2 or > 1 to
242 * avoid scaling problems */
243 FLOAT x, y, z, radius;
251 radius = sqrt (x * x + y * y + z * z);
252 if ((radius >= 0.2) && (radius <= 1.0))
262 initBlot (&blots[n], x, y, z);
268 /* set up the initial array of blots to be a simple cube */
269 static void setupBlotsCube (void)
273 /* derive blotsPerEdge from blotCount, but then do the reverse
274 * since roundoff may have changed blotCount */
275 int blotsPerEdge = ((requestedBlotCount - 8) / 12) + 2;
278 if (blotsPerEdge < 2)
283 distBetween = 2.0 / (blotsPerEdge - 1.0);
285 blotCount = 8 + (blotsPerEdge - 2) * 12;
286 blots = calloc (sizeof (Blot), blotCount);
289 /* define the corners */
290 for (i = -1; i < 2; i += 2)
292 for (j = -1; j < 2; j += 2)
294 for (k = -1; k < 2; k += 2)
296 initBlot (&blots[n], i, j, k);
302 /* define the edges */
303 for (i = 1; i < (blotsPerEdge - 1); i++)
305 FLOAT varEdge = distBetween * i - 1;
306 initBlot (&blots[n++], varEdge, -1, -1);
307 initBlot (&blots[n++], varEdge, 1, -1);
308 initBlot (&blots[n++], varEdge, -1, 1);
309 initBlot (&blots[n++], varEdge, 1, 1);
310 initBlot (&blots[n++], -1, varEdge, -1);
311 initBlot (&blots[n++], 1, varEdge, -1);
312 initBlot (&blots[n++], -1, varEdge, 1);
313 initBlot (&blots[n++], 1, varEdge, 1);
314 initBlot (&blots[n++], -1, -1, varEdge);
315 initBlot (&blots[n++], 1, -1, varEdge);
316 initBlot (&blots[n++], -1, 1, varEdge);
317 initBlot (&blots[n++], 1, 1, varEdge);
320 scaleBlotsToRadius1 ();
321 randomlyReorderBlots ();
326 /* set up the initial array of blots to be a cylinder */
327 static void setupBlotsCylinder (void)
331 /* derive blotsPerEdge from blotCount, but then do the reverse
332 * since roundoff may have changed blotCount */
333 int blotsPerEdge = requestedBlotCount / 32;
336 if (blotsPerEdge < 2)
341 distBetween = 2.0 / (blotsPerEdge - 1);
343 blotCount = blotsPerEdge * 32;
344 blots = calloc (sizeof (Blot), blotCount);
347 /* define the edges */
348 for (i = 0; i < 32; i++)
350 FLOAT x = sin (2 * M_PI / 32 * i);
351 FLOAT y = cos (2 * M_PI / 32 * i);
352 for (j = 0; j < blotsPerEdge; j++)
354 initBlot (&blots[n], x, y, j * distBetween - 1);
359 scaleBlotsToRadius1 ();
360 randomlyReorderBlots ();
365 /* set up the initial array of blots to be a squiggle */
366 static void setupBlotsSquiggle (void)
368 FLOAT x, y, z, xv, yv, zv, len;
371 blotCount = requestedBlotCount;
372 blots = calloc (sizeof (Blot), blotCount);
381 len = sqrt (xv * xv + yv * yv + zv * zv);
386 for (n = 0; n < blotCount; n++)
388 FLOAT newx, newy, newz;
389 initBlot (&blots[n], x, y, z);
393 xv += RAND_FLOAT_PM1 * 0.1;
394 yv += RAND_FLOAT_PM1 * 0.1;
395 zv += RAND_FLOAT_PM1 * 0.1;
396 len = sqrt (xv * xv + yv * yv + zv * zv);
405 if ( (newx >= -1) && (newx <= 1)
406 && (newy >= -1) && (newy <= 1)
407 && (newz >= -1) && (newz <= 1))
418 scaleBlotsToRadius1 ();
419 randomlyReorderBlots ();
424 /* set up the initial array of blots to be near the corners of a
425 * cube, distributed slightly */
426 static void setupBlotsCubeCorners (void)
430 blotCount = requestedBlotCount;
431 blots = calloc (sizeof (Blot), blotCount);
433 for (n = 0; n < blotCount; n++)
435 FLOAT x = rint (RAND_FLOAT_01) * 2 - 1;
436 FLOAT y = rint (RAND_FLOAT_01) * 2 - 1;
437 FLOAT z = rint (RAND_FLOAT_01) * 2 - 1;
439 x += RAND_FLOAT_PM1 * 0.3;
440 y += RAND_FLOAT_PM1 * 0.3;
441 z += RAND_FLOAT_PM1 * 0.3;
443 initBlot (&blots[n], x, y, z);
446 scaleBlotsToRadius1 ();
451 /* forward declaration for recursive use immediately below */
452 static void setupBlots (void);
454 /* set up the blots to be two of the other choices, placed next to
456 static void setupBlotsDuo (void)
458 int origRequest = requestedBlotCount;
459 FLOAT tx, ty, tz, radius;
460 Blot *blots1, *blots2;
464 if (requestedBlotCount < 15)
466 /* special case bottom-out */
474 radius = sqrt (tx * tx + ty * ty + tz * tz);
479 /* recursive call to setup set 1 */
480 requestedBlotCount = origRequest / 2;
483 if (blotCount >= origRequest)
485 /* return immediately if this satisfies the original count request */
486 requestedBlotCount = origRequest;
495 /* translate to new position */
496 for (n = 0; n < count1; n++)
503 /* recursive call to setup set 2 */
504 requestedBlotCount = origRequest - count1;
509 /* translate to new position */
510 for (n = 0; n < count2; n++)
517 /* combine the two arrays */
518 blotCount = count1 + count2;
519 blots = calloc (sizeof (Blot), blotCount);
520 memcpy (&blots[0], blots1, sizeof (Blot) * count1);
521 memcpy (&blots[count1], blots2, sizeof (Blot) * count2);
525 scaleBlotsToRadius1 ();
526 randomlyReorderBlots ();
528 /* restore the original requested count, for future iterations */
529 requestedBlotCount = origRequest;
534 /* free the blots, in preparation for a new shape */
535 static void freeBlots (void)
543 if (segsToErase != NULL)
549 if (segsToDraw != NULL)
558 /* set up the initial arrays of blots */
559 static void setupBlots (void)
561 int which = RAND_FLOAT_01 * 7;
574 setupBlotsCylinder ();
577 setupBlotsSquiggle ();
580 setupBlotsCubeCorners ();
591 /* set up the segments arrays */
592 static void setupSegs (void)
594 /* there are blotShapeCount - 1 line segments per blot */
595 segCount = blotCount * (blotShapeCount - 1);
596 segsToErase = calloc (sizeof (LineSegment), segCount);
597 segsToDraw = calloc (sizeof (LineSegment), segCount);
599 /* erase the world */
600 XFillRectangle (display, drawable, gcs[0], 0, 0,
601 windowWidth, windowHeight);
610 /* set up the colormap */
611 static void setupColormap (XWindowAttributes *xgwa)
615 XColor *colors = (XColor *) calloc (sizeof (XColor), colorCount + 1);
617 unsigned short r, g, b;
619 double s1, s2, v1, v2;
621 r = RAND_FLOAT_01 * 0x10000;
622 g = RAND_FLOAT_01 * 0x10000;
623 b = RAND_FLOAT_01 * 0x10000;
624 rgb_to_hsv (r, g, b, &h1, &s1, &v1);
628 r = RAND_FLOAT_01 * 0x10000;
629 g = RAND_FLOAT_01 * 0x10000;
630 b = RAND_FLOAT_01 * 0x10000;
631 rgb_to_hsv (r, g, b, &h2, &s2, &v2);
635 colors[0].pixel = get_pixel_resource ("background", "Background",
636 display, xgwa->colormap);
638 make_color_ramp (display, xgwa->colormap, h1, s1, v1, h2, s2, v2,
639 colors + 1, &colorCount, False, True, False);
643 fprintf (stderr, "%s: couldn't allocate any colors\n", progname);
647 gcs = (GC *) calloc (sizeof (GC), colorCount + 1);
649 for (n = 0; n <= colorCount; n++)
651 gcv.foreground = colors[n].pixel;
652 gcv.line_width = lineWidth;
653 gcs[n] = XCreateGC (display, window, GCForeground | GCLineWidth, &gcv);
662 * overall setup stuff
665 /* set up the system */
666 static void setup (void)
668 XWindowAttributes xgwa;
670 XGetWindowAttributes (display, window, &xgwa);
672 windowWidth = xgwa.width;
673 windowHeight = xgwa.height;
674 centerX = windowWidth / 2;
675 centerY = windowHeight / 2;
676 baseScale = (xgwa.height < xgwa.width) ? xgwa.height : xgwa.width;
680 drawable = XCreatePixmap (display, window, xgwa.width, xgwa.height,
688 setupColormap (&xgwa);
692 /* set up the initial rotation, scale, and light values as random, but
693 * with the targets equal to where it is */
694 xRot = xRotTarget = RAND_FLOAT_01 * M_PI;
695 yRot = yRotTarget = RAND_FLOAT_01 * M_PI;
696 zRot = zRotTarget = RAND_FLOAT_01 * M_PI;
697 curScale = scaleTarget = RAND_FLOAT_01 * (maxScale - minScale) + minScale;
698 lightX = lightXTarget = RAND_FLOAT_PM1;
699 lightY = lightYTarget = RAND_FLOAT_PM1;
700 lightZ = lightZTarget = RAND_FLOAT_PM1;
702 itersTillNext = RAND_FLOAT_01 * 1234;
711 /* "render" the blots into segsToDraw, with the current rotation factors */
712 static void renderSegs (void)
717 /* rotation factors */
718 FLOAT sinX = sin (xRot);
719 FLOAT cosX = cos (xRot);
720 FLOAT sinY = sin (yRot);
721 FLOAT cosY = cos (yRot);
722 FLOAT sinZ = sin (zRot);
723 FLOAT cosZ = cos (zRot);
725 for (n = 0; n < blotCount; n++)
735 FLOAT x1 = blots[n].x;
736 FLOAT y1 = blots[n].y;
737 FLOAT z1 = blots[n].z;
740 /* rotate on z axis */
741 x2 = x1 * cosZ - y1 * sinZ;
742 y2 = x1 * sinZ + y1 * cosZ;
745 /* rotate on x axis */
746 y1 = y2 * cosX - z2 * sinX;
747 z1 = y2 * sinX + z2 * cosX;
750 /* rotate on y axis */
751 z2 = z1 * cosY - x1 * sinY;
752 x2 = z1 * sinY + x1 * cosY;
755 /* the color to draw is based on the distance from the light of
756 * the post-rotation blot */
760 color = 1 + (x1 * x1 + y1 * y1 + z1 * z1) / 4 * colorCount;
761 if (color > colorCount)
766 /* set up the base screen coordinates for drawing */
767 baseX = x2 / 2 * baseScale * curScale + centerX + centerXOff;
768 baseY = y2 / 2 * baseScale * curScale + centerY + centerYOff;
770 radius = (z2 + 1) / 2 * (maxRadius - minRadius) + minRadius;
772 for (i = 0; i < 3; i++)
774 for (j = 0; j < 3; j++)
777 ((i - 1) + (b->xoff[i][j] * maxNerveRadius)) * radius;
779 ((j - 1) + (b->yoff[i][j] * maxNerveRadius)) * radius;
783 for (i = 1; i < blotShapeCount; i++)
785 segsToDraw[m].gc = gcs[color];
786 segsToDraw[m].x1 = x[blotShape[i-1].x + 1][blotShape[i-1].y + 1];
787 segsToDraw[m].y1 = y[blotShape[i-1].x + 1][blotShape[i-1].y + 1];
788 segsToDraw[m].x2 = x[blotShape[i].x + 1][blotShape[i].y + 1];
789 segsToDraw[m].y2 = y[blotShape[i].x + 1][blotShape[i].y + 1];
795 /* update blots, adjusting the offsets and rotation factors. */
796 static void updateWithFeeling (void)
800 /* pick a new model if the time is right */
802 if (itersTillNext < 0)
804 itersTillNext = RAND_FLOAT_01 * 1234;
810 /* update the rotation factors by moving them a bit toward the targets */
811 xRot = xRot + (xRotTarget - xRot) * iterAmt;
812 yRot = yRot + (yRotTarget - yRot) * iterAmt;
813 zRot = zRot + (zRotTarget - zRot) * iterAmt;
815 /* similarly the scale factor */
816 curScale = curScale + (scaleTarget - curScale) * iterAmt;
818 /* and similarly the light position */
819 lightX = lightX + (lightXTarget - lightX) * iterAmt;
820 lightY = lightY + (lightYTarget - lightY) * iterAmt;
821 lightZ = lightZ + (lightZTarget - lightZ) * iterAmt;
823 /* for each blot... */
824 for (n = 0; n < blotCount; n++)
826 /* add a bit of random jitter to xoff/yoff */
827 for (i = 0; i < 3; i++)
829 for (j = 0; j < 3; j++)
833 newOff = blots[n].xoff[i][j] + RAND_FLOAT_PM1 * nervousness;
834 if (newOff < -1) newOff = -(newOff + 1) - 1;
835 else if (newOff > 1) newOff = -(newOff - 1) + 1;
836 blots[n].xoff[i][j] = newOff;
838 newOff = blots[n].yoff[i][j] + RAND_FLOAT_PM1 * nervousness;
839 if (newOff < -1) newOff = -(newOff + 1) - 1;
840 else if (newOff > 1) newOff = -(newOff - 1) + 1;
841 blots[n].yoff[i][j] = newOff;
846 /* depending on random chance, update one or more factors */
847 if (RAND_FLOAT_01 <= eventChance)
849 int which = RAND_FLOAT_01 * 14;
854 xRotTarget = RAND_FLOAT_PM1 * M_PI * 2;
859 yRotTarget = RAND_FLOAT_PM1 * M_PI * 2;
864 zRotTarget = RAND_FLOAT_PM1 * M_PI * 2;
869 xRotTarget = RAND_FLOAT_PM1 * M_PI * 2;
870 yRotTarget = RAND_FLOAT_PM1 * M_PI * 2;
875 xRotTarget = RAND_FLOAT_PM1 * M_PI * 2;
876 zRotTarget = RAND_FLOAT_PM1 * M_PI * 2;
881 yRotTarget = RAND_FLOAT_PM1 * M_PI * 2;
882 zRotTarget = RAND_FLOAT_PM1 * M_PI * 2;
887 xRotTarget = RAND_FLOAT_PM1 * M_PI * 2;
888 yRotTarget = RAND_FLOAT_PM1 * M_PI * 2;
889 zRotTarget = RAND_FLOAT_PM1 * M_PI * 2;
894 centerXOff = RAND_FLOAT_PM1 * maxRadius;
899 centerYOff = RAND_FLOAT_PM1 * maxRadius;
904 centerXOff = RAND_FLOAT_PM1 * maxRadius;
905 centerYOff = RAND_FLOAT_PM1 * maxRadius;
911 RAND_FLOAT_01 * (maxScale - minScale) + minScale;
917 RAND_FLOAT_01 * (maxScale - minScale) + minScale;
922 lightX = RAND_FLOAT_PM1;
923 lightY = RAND_FLOAT_PM1;
924 lightZ = RAND_FLOAT_PM1;
929 lightXTarget = RAND_FLOAT_PM1;
930 lightYTarget = RAND_FLOAT_PM1;
931 lightZTarget = RAND_FLOAT_PM1;
938 /* erase segsToErase and draw segsToDraw */
939 static void eraseAndDraw (void)
943 for (n = 0; n < segCount; n++)
945 LineSegment *seg = &segsToErase[n];
946 XDrawLine (display, drawable, gcs[0],
947 seg->x1, seg->y1, seg->x2, seg->y2);
948 seg = &segsToDraw[n];
949 XDrawLine (display, drawable, seg->gc,
950 seg->x1, seg->y1, seg->x2, seg->y2);
955 XCopyArea (display, drawable, window, gcs[0], 0, 0,
956 windowWidth, windowHeight, 0, 0);
960 /* do one iteration */
961 static void oneIteration (void)
963 /* switch segsToErase and segsToDraw */
964 LineSegment *temp = segsToDraw;
965 segsToDraw = segsToErase;
968 /* update the model */
969 updateWithFeeling ();
971 /* render new segments */
974 /* erase old segments and draw new ones */
978 char *progclass = "NerveRot";
980 char *defaults [] = {
981 ".background: black",
982 ".foreground: white",
986 "*doubleBuffer: false",
994 "*maxNerveRadius: 0.7",
999 XrmOptionDescRec options [] = {
1000 { "-count", ".count", XrmoptionSepArg, 0 },
1001 { "-colors", ".colors", XrmoptionSepArg, 0 },
1002 { "-delay", ".delay", XrmoptionSepArg, 0 },
1003 { "-db", ".doubleBuffer", XrmoptionNoArg, "true" },
1004 { "-no-db", ".doubleBuffer", XrmoptionNoArg, "false" },
1005 { "-event-chance", ".eventChance", XrmoptionSepArg, 0 },
1006 { "-iter-amt", ".iterAmt", XrmoptionSepArg, 0 },
1007 { "-line-width", ".lineWidth", XrmoptionSepArg, 0 },
1008 { "-min-scale", ".minScale", XrmoptionSepArg, 0 },
1009 { "-max-scale", ".maxScale", XrmoptionSepArg, 0 },
1010 { "-min-radius", ".minRadius", XrmoptionSepArg, 0 },
1011 { "-max-radius", ".maxRadius", XrmoptionSepArg, 0 },
1012 { "-max-nerve-radius", ".maxNerveRadius", XrmoptionSepArg, 0 },
1013 { "-nervousness", ".nervousness", XrmoptionSepArg, 0 },
1017 /* initialize the user-specifiable params */
1018 static void initParams (void)
1022 delay = get_integer_resource ("delay", "Delay");
1025 fprintf (stderr, "error: delay must be at least 0\n");
1029 doubleBuffer = get_boolean_resource ("doubleBuffer", "Boolean");
1031 requestedBlotCount = get_integer_resource ("count", "Count");
1032 if (requestedBlotCount <= 0)
1034 fprintf (stderr, "error: count must be at least 0\n");
1038 colorCount = get_integer_resource ("colors", "Colors");
1039 if (colorCount <= 0)
1041 fprintf (stderr, "error: colors must be at least 1\n");
1045 lineWidth = get_integer_resource ("lineWidth", "LineWidth");
1048 fprintf (stderr, "error: line width must be at least 0\n");
1052 nervousness = get_float_resource ("nervousness", "Float");
1053 if ((nervousness < 0) || (nervousness > 1))
1055 fprintf (stderr, "error: nervousness must be in the range 0..1\n");
1059 maxNerveRadius = get_float_resource ("maxNerveRadius", "Float");
1060 if ((maxNerveRadius < 0) || (maxNerveRadius > 1))
1062 fprintf (stderr, "error: maxNerveRadius must be in the range 0..1\n");
1066 eventChance = get_float_resource ("eventChance", "Float");
1067 if ((eventChance < 0) || (eventChance > 1))
1069 fprintf (stderr, "error: eventChance must be in the range 0..1\n");
1073 iterAmt = get_float_resource ("iterAmt", "Float");
1074 if ((iterAmt < 0) || (iterAmt > 1))
1076 fprintf (stderr, "error: iterAmt must be in the range 0..1\n");
1080 minScale = get_float_resource ("minScale", "Float");
1081 if ((minScale < 0) || (minScale > 10))
1083 fprintf (stderr, "error: minScale must be in the range 0..10\n");
1087 maxScale = get_float_resource ("maxScale", "Float");
1088 if ((maxScale < 0) || (maxScale > 10))
1090 fprintf (stderr, "error: maxScale must be in the range 0..10\n");
1094 if (maxScale < minScale)
1096 fprintf (stderr, "error: maxScale must be >= minScale\n");
1100 minRadius = get_integer_resource ("minRadius", "Integer");
1101 if ((minRadius < 1) || (minRadius > 100))
1103 fprintf (stderr, "error: minRadius must be in the range 1..100\n");
1107 maxRadius = get_integer_resource ("maxRadius", "Integer");
1108 if ((maxRadius < 1) || (maxRadius > 100))
1110 fprintf (stderr, "error: maxRadius must be in the range 1..100\n");
1114 if (maxRadius < minRadius)
1116 fprintf (stderr, "error: maxRadius must be >= minRadius\n");
1127 void screenhack (Display *dpy, Window win)
1135 /* make a valid set to erase at first */
1142 screenhack_handle_events (dpy);