xenocara/app/xlockmore/xlock/erase.c
2006-11-26 11:07:42 +00:00

1161 lines
28 KiB
C
Raw Blame History

#if !defined( lint ) && !defined( SABER )
static const char sccsid[] = "@(#)erase.c 5.03 2001/10/18 xlockmore";
#endif
/*-
* erase.c: Erase the screen in various more or less interesting ways.
*
* (c) 1997 by Johannes Keukelaar <johannes@nada.kth.se>
*
* Revision History:
* 23-Oct-2001: slide_lines added features by Jouk Jansen:
* horizontal & vertical slicing
* random slection of slice thickness
* 18-Oct-2001: slide_lines & losira added
* 01-Nov-2000: Allocation checks
* 17-May-1999: changed timing by Jouk Jansen
* 13-Aug-1998: changed to be used with xlockmore by Jouk Jansen
* <joukj@hrem.stm.tudelft.nl>
* 1997: original version by Johannes Keukelaar <johannes@nada.kth.se>
*
* Permission to use in any way granted. Provided "as is" without expressed
* or implied warranty. NO WARRANTY, NO EXPRESSION OF SUITABILITY FOR ANY
* PURPOSE. (I.e.: Use in any way, but at your own risk!)
*/
#include "xlock.h"
#undef countof
#define countof(x) (sizeof(x)/sizeof(*(x)))
extern int erasedelay, erasetime;
extern void erasemodefromname(char *name, Bool verbose);
static int advanceErase();
typedef void (*Eraser) (Display * dpy, Window window, GC gc,
int width, int height, int delay, int granularity);
static void
no_fade(Display * dpy, Window window, GC gc,
int width, int height, int delay, int granularity)
{
}
static void
random_lines(Display * dpy, Window window, GC gc,
int width, int height, int delay, int granularity)
{
#define ERASEMODE "random_lines"
Bool horiz_p = (Bool) (LRAND() & 1);
int max = (horiz_p ? height : width);
int *lines;
int i;
int actual_delay = delay / max;
#include "erase_init.h"
if ((lines = (int *) calloc(max, sizeof (int))) == NULL) {
XDrawRectangle(dpy, window, gc, 0, 0, width, height);
return;
}
for (i = 0; i < max; i++)
lines[i] = i;
for (i = 0; i < max; i++) {
int t, r;
t = lines[i];
r = NRAND(max);
lines[i] = lines[r];
lines[r] = t;
}
for (i = 0; i < max; i++) {
if (horiz_p)
XDrawLine(dpy, window, gc, 0, lines[i], width,
lines[i]);
else
XDrawLine(dpy, window, gc, lines[i], 0, lines[i],
height);
XSync(dpy, False);
#define LOOPVAR i
#include "erase.h"
#undef LOOPVAR
}
free(lines);
#include "erase_debug.h"
}
#undef ERASEMODE
static void
random_squares(Display * dpy, Window window, GC gc,
int width, int height, int delay, int granularity)
{
#define ERASEMODE "random_squares"
int randsize = MAX(1, MIN(width, height) / (16 + NRAND(32)));
int max = (height / randsize + 1) * (width / randsize + 1);
int *squares;
int i;
int columns = width / randsize + 1; /* Add an extra for roundoff */
int actual_delay = delay / max;
#include "erase_init.h"
if ((squares = (int *) calloc(max, sizeof (int))) == NULL) {
XDrawRectangle(dpy, window, gc, 0, 0, width, height);
return;
}
for (i = 0; i < max; i++)
squares[i] = i;
for (i = 0; i < max; i++) {
int t, r;
t = squares[i];
r = NRAND(max);
squares[i] = squares[r];
squares[r] = t;
}
for (i = 0; i < max; i++) {
XFillRectangle(dpy, window, gc,
(squares[i] % columns) * randsize,
(squares[i] / columns) *
randsize, randsize, randsize);
XSync(dpy, False);
#define LOOPVAR i
#include "erase.h"
#undef LOOPVAR
}
free(squares);
#include "erase_debug.h"
}
#undef ERASEMODE
static void
venetian(Display * dpy, Window window, GC gc,
int width, int height, int delay, int granularity)
{
#define ERASEMODE "venetian"
Bool horiz_p = (Bool) (LRAND() & 1);
Bool flip_p = (Bool) (LRAND() & 1);
int max = (horiz_p ? height : width);
int *lines;
int i, j;
int actual_delay = delay / max;
#include "erase_init.h"
/* granularity /= 6;*/
if ((lines = (int *) calloc(max, sizeof (int))) == NULL) {
XDrawRectangle(dpy, window, gc, 0, 0, width, height);
return;
}
j = 0;
for (i = 0; i < max * 2; i++) {
int line = ((i / 16) * 16) - ((i % 16) * 15);
if (line >= 0 && line < max)
lines[j++] = (flip_p ? max - line : line);
}
for (i = 0; i < max; i++) {
if (horiz_p)
XDrawLine(dpy, window, gc, 0, lines[i], width,
lines[i]);
else
XDrawLine(dpy, window, gc, lines[i], 0, lines[i],
height);
XSync(dpy, False);
#define LOOPVAR i
#include "erase.h"
#undef LOOPVAR
}
free(lines);
#include "erase_debug.h"
}
#undef ERASEMODE
static void
triple_wipe(Display * dpy, Window window, GC gc,
int width, int height, int delay, int granularity)
{
#define ERASEMODE "triple_wipe"
Bool flip_x = (Bool) (LRAND() & 1);
Bool flip_y = (Bool) (LRAND() & 1);
int max = width + (height / 2);
int *lines;
int i;
int actual_delay = delay / max;
#include "erase_init.h"
if ((lines = (int *) calloc(max, sizeof (int))) == NULL) {
XDrawRectangle(dpy, window, gc, 0, 0, width, height);
return;
}
for (i = 0; i < width / 2; i++)
lines[i] = i * 2 + height;
for (i = 0; i < height / 2; i++)
lines[i + width / 2] = i * 2;
for (i = 0; i < width / 2; i++)
lines[i + width / 2 + height / 2] = width - i * 2 - (width % 2 ?
0 : 1) + height;
/* granularity /= 6;*/
for (i = 0; i < max; i++) {
int x, y, x2, y2;
if (lines[i] < height)
x = 0, y = lines[i], x2 = width, y2 = y;
else
x = lines[i] - height, y = 0, x2 = x, y2 = height;
if (flip_x)
x = width - x - 1, x2 = width - x2 - 1;
if (flip_y)
y = height - y - 1, y2 = height - y2 - 1;
XDrawLine(dpy, window, gc, x, y, x2, y2);
XSync(dpy, False);
#define LOOPVAR i
#include "erase.h"
#undef LOOPVAR
}
free(lines);
#include "erase_debug.h"
}
#undef ERASEMODE
static void
quad_wipe(Display * dpy, Window window, GC gc,
int width, int height, int delay, int granularity)
{
#define ERASEMODE "quad_wipe"
Bool flip_x = (Bool) (LRAND() & 1);
Bool flip_y = (Bool) (LRAND() & 1);
int max = width + height;
int *lines;
int i;
int actual_delay = delay / max;
#include "erase_init.h"
if ((lines = (int *) calloc(max, sizeof (int))) == NULL) {
XDrawRectangle(dpy, window, gc, 0, 0, width, height);
return;
}
/* granularity /= 3;*/
for (i = 0; i < max / 4; i++) {
lines[i * 4] = i * 2;
lines[i * 4 + 1] = height - i * 2 - (height % 2 ? 0 : 1);
lines[i * 4 + 2] = height + i * 2;
lines[i * 4 + 3] = height + width - i * 2 - (width % 2 ? 0 : 1);
}
for (i = 0; i < max; i++) {
int x, y, x2, y2;
if (lines[i] < height)
x = 0, y = lines[i], x2 = width, y2 = y;
else
x = lines[i] - height, y = 0, x2 = x, y2 = height;
if (flip_x)
x = width - x, x2 = width - x2;
if (flip_y)
y = height - y, y2 = height - y2;
XDrawLine(dpy, window, gc, x, y, x2, y2);
XSync(dpy, False);
#define LOOPVAR i
#include "erase.h"
#undef LOOPVAR
}
free(lines);
#include "erase_debug.h"
}
#undef ERASEMODE
static void
circle_wipe(Display * dpy, Window window, GC gc,
int width, int height, int delay, int granularity)
{
#define ERASEMODE "circle_wipe"
int full = 360 * 64;
int inc = 360;
int start = NRAND(full);
int rad = (width > height ? width : height);
int i;
int actual_delay = delay * inc / full;
#include "erase_init.h"
if (LRAND() & 1)
inc = -inc;
for (i = (inc > 0 ? 0 : full);
(inc > 0 ? i < full : i > 0);
i += inc) {
XFillArc(dpy, window, gc,
(width / 2) - rad, (height / 2) - rad, rad * 2, rad * 2,
(i + start) % full, inc);
XFlush(dpy);
#define LOOPVAR i
#include "erase.h"
#undef LOOPVAR
}
#include "erase_debug.h"
}
#undef ERASEMODE
static void
three_circle_wipe(Display * dpy, Window window, GC gc,
int width, int height, int delay, int granularity)
{
#define ERASEMODE "three_circle_wipe"
int i;
int full = 360 * 64;
int q = full / 6;
int q2 = q * 2;
int inc = full / 240;
int start = NRAND(q);
int rad = (width > height ? width : height);
int actual_delay = delay * inc / q;
#include "erase_init.h"
for (i = 0; i < q; i += inc) {
XFillArc(dpy, window, gc, (width / 2) - rad, (height / 2) - rad,
rad * 2, rad * 2,
(start + i) % full, inc);
XFillArc(dpy, window, gc, (width / 2) - rad, (height / 2) - rad,
rad * 2, rad * 2,
(start - i) % full, -inc);
XFillArc(dpy, window, gc, (width / 2) - rad, (height / 2) - rad,
rad * 2, rad * 2,
(start + q2 + i) % full, inc);
XFillArc(dpy, window, gc, (width / 2) - rad, (height / 2) - rad,
rad * 2, rad * 2,
(start + q2 - i) % full, -inc);
XFillArc(dpy, window, gc, (width / 2) - rad, (height / 2) - rad,
rad * 2, rad * 2,
(start + q2 + q2 + i) % full, inc);
XFillArc(dpy, window, gc, (width / 2) - rad, (height / 2) - rad,
rad * 2, rad * 2,
(start + q2 + q2 - i) % full, -inc);
XSync(dpy, False);
#define LOOPVAR i
#include "erase.h"
#undef LOOPVAR
}
#include "erase_debug.h"
}
#undef ERASEMODE
static void
squaretate(Display * dpy, Window window, GC gc,
int width, int height, int delay, int granularity)
{
#define ERASEMODE "squaretate"
#ifdef FAST_CPU
int steps = (((width > height ? width : height) * 2) /
granularity + 1);
#else
int steps = (((width > height ? width : height)) / (8 *
granularity) + 1);
#endif
int i;
Bool flip = (Bool) (LRAND() & 1);
int actual_delay = delay / steps;
#include "erase_init.h"
#define DRAW() \
if (flip) { \
points[0].x = width-points[0].x; \
points[1].x = width-points[1].x; \
points[2].x = width-points[2].x; } \
XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin)
for (i = 0; i < steps; i++) {
XPoint points[3];
points[0].x = 0;
points[0].y = 0;
points[1].x = width;
points[1].y = 0;
points[2].x = 0;
points[2].y = points[0].y + ((i * height) / steps);
DRAW();
points[0].x = 0;
points[0].y = 0;
points[1].x = 0;
points[1].y = height;
points[2].x = ((i * width) / steps);
points[2].y = height;
DRAW();
points[0].x = width;
points[0].y = height;
points[1].x = 0;
points[1].y = height;
points[2].x = width;
points[2].y = height - ((i * height) / steps);
DRAW();
points[0].x = width;
points[0].y = height;
points[1].x = width;
points[1].y = 0;
points[2].x = width - ((i * width) / steps);
points[2].y = 0;
DRAW();
XSync(dpy, True);
#define LOOPVAR i
#include "erase.h"
#undef LOOPVAR
}
#undef DRAW
#include "erase_debug.h"
}
#undef ERASEMODE
static void
fizzle (Display *dpy, Window window, GC gc,
int width, int height, int delay, int granularity)
{
#define ERASEMODE "fizzle"
/* These dimensions must be prime numbers. They should be roughly the
square root of the width and height. */
# define BX 31
# define BY 31
# define SIZE (BX*BY)
int array[SIZE];
int i, j;
XPoint *skews;
int nx, ny;
int actual_delay = delay / SIZE;
#include "erase_init.h"
/* Distribute the numbers [0,SIZE) randomly in the array */
{
int indices[SIZE];
for (i = 0; i < SIZE; i++) {
array[i] = -1;
indices[i] = i;
}
for (i = 0; i < SIZE; i++) {
j = (int) (LRAND() % (SIZE - i));
array[indices[j]] = i;
indices[j] = indices[SIZE - i - 1];
}
}
/* nx, ny are the number of cells across and down, rounded up */
nx = width / BX + (0 == (width % BX) ? 0 : 1);
ny = height / BY + (0 == (height % BY) ? 0 : 1);
if ((skews = (XPoint *) malloc(nx * ny * sizeof (XPoint))) == NULL) {
XDrawRectangle(dpy, window, gc, 0, 0, width, height);
return;
}
for (i = 0; i < nx; i++) {
for (j = 0; j < ny; j++) {
skews[j * nx + i].x = (short) (LRAND() % BX);
skews[j * nx + i].y = (short) (LRAND() % BY);
}
}
# define SKEWX(cx, cy) (skews[cy*nx + cx].x)
# define SKEWY(cx, cy) (skews[cy*nx + cx].y)
for (i = 0; i < SIZE; i++) {
int x = array[i] % BX;
int y = array[i] / BX;
int iy, cy;
for (iy = 0, cy = 0; iy < height; iy += BY, cy++) {
int ix, cx;
for (ix = 0, cx = 0; ix < width; ix += BX, cx++) {
int xx = ix + (SKEWX(cx, cy) + x*((cx%(BX-1))+1))%BX;
int yy = iy + (SKEWY(cx, cy) + y*((cy%(BY-1))+1))%BY;
XDrawPoint(dpy, window, gc, xx, yy);
}
}
if ((BX-1) == (i%BX)) {
XSync (dpy, False);
}
#define LOOPVAR i
# include "erase.h"
#undef LOOPVAR
}
# undef SKEWX
# undef SKEWY
free(skews);
# undef BX
# undef BY
# undef SIZE
#include "erase_debug.h"
}
/* from Rick Campbell <rick@campbellcentral.org> */
#undef ERASEMODE
static void
spiral (Display *display, Window window, GC context,
int width, int height, int delay, int granularity)
{
#define ERASEMODE "spiral"
# define SPIRAL_ERASE_PI_2 (M_PI + M_PI)
# define SPIRAL_ERASE_LOOP_COUNT (100)
# define SPIRAL_ERASE_ARC_COUNT (360.0)
# define SPIRAL_ERASE_ANGLE_INCREMENT (SPIRAL_ERASE_PI_2 / \
SPIRAL_ERASE_ARC_COUNT)
# define SPIRAL_ERASE_DELAY (0)
double angle;
int arc_limit;
int arc_max_limit;
int length_step;
XPoint points [3];
int actual_delay;
#include "erase_init.h"
angle = 0.0;
arc_max_limit = (int) (ceil (sqrt((double) (width * width) + (height * height)))
/ 2.0);
length_step = ((arc_max_limit + SPIRAL_ERASE_LOOP_COUNT - 1) /
SPIRAL_ERASE_LOOP_COUNT);
arc_max_limit += length_step;
points [0].x = width / 2;
points [0].y = height / 2;
points [1].x = points [0].x + length_step;
points [1].y = points [0].y;
points [2].x = points [1].x;
points [2].y = points [1].y;
actual_delay = delay * length_step / arc_max_limit;
for (arc_limit = length_step;
arc_limit < arc_max_limit;
arc_limit += length_step)
{
int arc_length = length_step;
int length_base = arc_limit;
for (angle = 0.0; angle < SPIRAL_ERASE_PI_2;
angle += SPIRAL_ERASE_ANGLE_INCREMENT)
{
arc_length = length_base + (int) ((length_step * angle) /
SPIRAL_ERASE_PI_2);
points [1].x = points [2].x;
points [1].y = points [2].y;
points [2].x = points [0].x + (int)(cos (angle) * arc_length);
points [2].y = points [0].y + (int)(sin (angle) * arc_length);
XFillPolygon (display, window, context, points, 3, Convex,
CoordModeOrigin);
}
#define LOOPVAR arc_limit
#include "erase.h"
#undef LOOPVAR
#if (SPIRAL_ERASE_DELAY != 0)
(void) usleep (SPIRAL_ERASE_DELAY);
# endif /* (SPIRAL_ERASE_DELAY != 0) */
}
# undef SPIRAL_ERASE_DELAY
# undef SPIRAL_ERASE_ANGLE_INCREMENT
# undef SPIRAL_ERASE_ARC_COUNT
# undef SPIRAL_ERASE_LOOP_COUNT
# undef SPIRAL_ERASE_PI_2
#include "erase_debug.h"
}
/* I first saw something like this, albeit in reverse, in an early Tetris
implementation for the Mac.
-- Torbj<62>rn Andersson <torbjorn@dev.eurotime.se>
*/
#undef ERASEMODE
static void
slide_lines (Display *display, Window window, GC context,
int width, int height, int delay, int granularity)
{
#define ERASEMODE "slide_lines"
Bool horiz_p = (Bool) (LRAND() & 1);
int max = width;
int dy;
int i;
int actual_delay = delay / max;
int tick_init = NRAND( 2 );
int int1,int2;
#include "erase_init.h"
if ( horiz_p )
{
max = width;
}
else
{
max = height;
height = width;
width = max;
}
int1 = height - 10;
int2 = NRAND( int1 );
dy = 10 + ( int2 * int2 ) / int1;
XSetGraphicsExposures(display , context , False );
for ( i = 0; i < max; i++ )
{
int tick = tick_init;
int y;
int from1 = i - 1;
int to1 = i;
int w = width - to1;
int from2 = width - i + 1 - w;
int to2 = width - i - w;
for (y = 0; y < height; y += dy)
{
if ( ++tick & 1)
{
if ( horiz_p )
{
XCopyArea (display, window, window, context, from1, y,
w, dy, to1, y);
XFillRectangle (display, window, context, from1, y,
to1-from1, dy);
}
else
{
XCopyArea (display, window, window, context, y , from1,
dy, w, y, to1);
XFillRectangle (display, window, context, y, from1,
dy, to1-from1);
}
}
else
{
if ( horiz_p )
{
XCopyArea (display, window, window, context, from2, y,
w, dy, to2, y);
XFillRectangle (display, window, context, from2+w, y,
to2-from2, dy);
}
else
{
XCopyArea (display, window, window, context, y, from2,
dy, w, y, to2);
XFillRectangle (display, window, context, y, from2+w,
dy, to2-from2);
}
}
}
XSync( display , False );
#define LOOPVAR i
#include "erase.h"
#undef LOOPVAR
}
#include "erase_debug.h"
}
/* from Frederick Roeber <roeber@xigo.com> */
#undef ERASEMODE
static void
losira (Display *dpy, Window window, GC gc, int width, int height, int delay,
int granularity)
{
#define ERASEMODE "losira"
XGCValues gcv;
XWindowAttributes wa;
GC white_gc;
XArc arc[2][8];
double xx[8], yy[8], dx[8], dy[8];
int i;
int max = width/2;
int max_off = MAX(1, max / 12);
int actual_delay = (int) (0.55 * delay / max);
#include "erase_init.h"
(void) XGetWindowAttributes(dpy, window, &wa);
gcv.foreground = XWhitePixelOfScreen(wa.screen);
white_gc = XCreateGC(dpy, window, GCForeground, &gcv);
XSetGraphicsExposures(dpy , gc , False );
XSetGraphicsExposures(dpy , white_gc , False );
/* Squeeze in from the sides */
for ( i=0; i<max; i++ )
{
int off = ( i * max_off ) / max;
int from1 = i - 1;
int to1 = i;
int w = max - to1 - off/2 + 1;
int from2 = max+(to1-from1)+off/2;
int to2 = max+off/2;
if (w < 0)
break;
XCopyArea (dpy, window, window, gc, from1, 0, w, height, to1, 0);
XCopyArea (dpy, window, window, gc, from2, 0, w, height, to2, 0);
XFillRectangle (dpy, window, gc, from1, 0, (to1-from1), height);
XFillRectangle (dpy, window, gc, to2+w, 0, from2+w, height);
XFillRectangle (dpy, window, white_gc, max-off/2, 0, off, height);
XSync(dpy, False);
#define LOOPVAR i
#include "erase.h"
#undef LOOPVAR
}
XFillRectangle(dpy, window, white_gc, max-max_off/2, 0, max_off, height);
/* Cap the top and bottom of the line */
XFillRectangle(dpy, window, gc, max-max_off/2, 0, max_off, max_off/2);
XFillRectangle(dpy, window, gc, max-max_off/2, height-max_off/2,
max_off, max_off/2);
XFillArc(dpy, window, white_gc, max-max_off/2-1, 0,
max_off-1, max_off-1, 0, 180*64);
XFillArc(dpy, window, white_gc, max-max_off/2-1, height-max_off,
max_off-1, max_off-1,
180*64, 360*64);
XFillRectangle(dpy, window, gc, 0, 0, max-max_off/2, height);
XFillRectangle(dpy, window, gc, max+max_off/2-1, 0, max-max_off/2, height);
XSync(dpy, False);
/* Collapse vertically */
max = height/2;
actual_delay = (int) (0.30 * delay / max);
for ( i=0; i<max; i++ )
{
int x = (width-max_off)/2;
int w = max_off;
int off = ( i * max_off ) / max;
int from1 = i - 1;
int to1 = i;
int h = max - to1 - off/2;
int from2 = max+(to1-from1)+off/2;
int to2 = max+off/2;
if (h < max_off/2)
break;
XCopyArea (dpy, window, window, gc, x, from1, w, h, x, to1);
XCopyArea (dpy, window, window, gc, x, from2, w, h, x, to2);
XFillRectangle(dpy, window, gc, x, from1, w, (to1 - from1));
XFillRectangle(dpy, window, gc, x, to2+h, w, (to2 - from2));
XSync(dpy, False);
#define LOOPVAR i
#include "erase.h"
#undef LOOPVAR
}
/* "This is Sci-Fi" */
for( i = 0; i < 8; i++ ) {
arc[0][i].width = arc[0][i].height = max_off;
arc[1][i].width = arc[1][i].height = max_off;
arc[0][i].x = arc[1][i].x = width/2;
arc[0][i].y = arc[1][i].y = height/2;
xx[i] = (double)(width/2) - max_off/2;
yy[i] = (double)(height/2) - max_off/2;
}
arc[0][0].angle1 = arc[1][0].angle1 = 0*64; arc[0][0].angle2 = arc[1][0].angle2 = 45*64;
arc[0][1].angle1 = arc[1][1].angle1 = 45*64; arc[0][1].angle2 = arc[1][1].angle2 = 45*64;
arc[0][2].angle1 = arc[1][2].angle1 = 90*64; arc[0][2].angle2 = arc[1][2].angle2 = 45*64;
arc[0][3].angle1 = arc[1][3].angle1 = 135*64; arc[0][3].angle2 = arc[1][3].angle2 = 45*64;
arc[0][4].angle1 = arc[1][4].angle1 = 180*64; arc[0][4].angle2 = arc[1][4].angle2 = 45*64;
arc[0][5].angle1 = arc[1][5].angle1 = 225*64; arc[0][5].angle2 = arc[1][5].angle2 = 45*64;
arc[0][6].angle1 = arc[1][6].angle1 = 270*64; arc[0][6].angle2 = arc[1][6].angle2 = 45*64;
arc[0][7].angle1 = arc[1][7].angle1 = 315*64; arc[0][7].angle2 = arc[1][7].angle2 = 45*64;
for( i = 0; i < 8; i++ ) {
dx[i] = cos((i*45 + 22.5)/360 * 2*M_PI);
dy[i] = -sin((i*45 + 22.5)/360 * 2*M_PI);
}
gcv.line_width = 3;
XChangeGC(dpy, gc, GCLineWidth, &gcv);
XClearWindow (dpy, window);
XFillArc(dpy, window, white_gc,
width/2-max_off/2-1, height/2-max_off/2-1,
max_off-1, max_off-1,
0, 360*64);
XDrawLine(dpy, window, gc, 0, height/2-1, width, height/2-1);
XDrawLine(dpy, window, gc, width/2-1, 0, width/2-1, height);
XDrawLine(dpy, window, gc, width/2-1-max_off, height/2-1-max_off,
width/2+max_off, height/2+max_off);
XDrawLine(dpy, window, gc, width/2+max_off, height/2-1-max_off,
width/2-1-max_off, height/2+max_off);
XSync(dpy, False);
/* Fan out */
actual_delay = (int) (0.15 * delay / max_off);
for ( i=0; i<max_off; i++ )
{
int j;
for (j = 0; j < 8; j++)
{
xx[j] += 2*dx[j];
yy[j] += 2*dy[j];
arc[(i+1)%2][j].x = (short) xx[j];
arc[(i+1)%2][j].y = (short) yy[j];
}
XFillRectangle (dpy, window, gc,
(width-max_off*5)/2, (height-max_off*5)/2,
max_off*5, max_off*5);
XFillArcs(dpy, window, white_gc, arc[(i+1)%2], 8);
XSync(dpy, False);
#define LOOPVAR i
#include "erase.h"
#undef LOOPVAR
}
XFreeGC(dpy, white_gc);
gcv.line_width = 1;
XChangeGC(dpy, gc, GCLineWidth, &gcv);
}
#undef ERASEMODE
static struct eraser_names {
Eraser mode;
char *name;
} erasers[] = {
{
random_lines, (char *) "random_lines"
},
{
random_squares, (char *) "random_squares"
},
{
venetian, (char *) "venetian"
},
{
triple_wipe, (char *) "triple_wipe"
},
{
quad_wipe, (char *) "quad_wipe"
},
{
circle_wipe, (char *) "circle_wipe"
},
{
three_circle_wipe, (char *) "three_circle_wipe"
},
{
squaretate, (char *) "squaretate"
},
{
fizzle, (char *) "fizzle"
},
{
spiral, (char *) "spiral"
},
{
slide_lines, (char *) "slide_lines"
},
{
losira, (char *) "losira"
},
{
no_fade, (char *) "no_fade"
}
};
static void
erase_window(ModeInfo * mi, GC erase_gc, unsigned long pixel, int delay)
{
int granularity = 1, mode;
XSetForeground(MI_DISPLAY(mi), erase_gc, pixel);
if (MI_IS_DRAWN(mi) && delay > 0) {
#if 0
if (mode < 0 || mode >= (int) countof(erasers))
mode = NRAND(countof(erasers));
#else
mode = advanceErase();
if (MI_IS_VERBOSE(mi))
(void) fprintf(stdout, "erasemode %d: %s\n", mode,
erasers[mode].name);
#endif
(*(erasers[mode].mode)) (MI_DISPLAY(mi), MI_WINDOW(mi),
erase_gc, MI_WIDTH(mi), MI_HEIGHT(mi),
delay, granularity);
MI_IS_DRAWN(mi) = False;
}
XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), erase_gc, 0, 0,
(unsigned int) MI_WIDTH(mi), (unsigned int) MI_HEIGHT(mi));
}
void
erase_full_window(ModeInfo * mi, GC erase_gc, unsigned long pixel)
{
erase_window(mi, erase_gc, pixel, erasedelay);
}
#if 0
int
erasemodefromname(char *name, Bool verbose)
{
int a;
char *s1, *s2;
int eraseMode = -1;
for (a = 0; a < (int) countof(erasers); a++) {
for (s1 = erasers[a].name, s2 = name; *s1 && *s2; s1++, s2++)
if ((isupper((int) *s1) ? tolower((int) *s1) : *s1) !=
(isupper((int) *s2) ? tolower((int) *s2) : *s2))
break;
if ((*s1 == '\0') || (*s2 == '\0')) {
if (eraseMode != -1) {
(void) fprintf(stderr,
"%s does not uniquely describe an erase mode (set to random)\n"
,name);
return (-1);
}
eraseMode = a;
}
}
if (verbose)
(void) fprintf(stderr, "Using erase mode %s\n", name);
return (eraseMode);
}
#else
static int currentEraseMode = -1;
/* static int previousEraseMode = -1; */
static int *eraseModes;
static int nEraseModes;
#ifdef DEBUG
static Bool sequential = True;
#else
static Bool sequential = False;
#endif
static int
pickMode(void)
{
static int *eraseModeIndexes = (int *) NULL;
static int eraseModeCount = 0;
static int lastEraseMode = -1, lastIndex = -1;
int eraseMode, i;
if (eraseModeIndexes == NULL) {
if ((eraseModeIndexes = (int *) calloc(nEraseModes,
sizeof (int))) == NULL) {
if (sequential)
return eraseModes[0];
else
return eraseModes[NRAND(nEraseModes)];
}
}
if (eraseModeCount == 0) {
for (i = 0; i < nEraseModes; i++) {
eraseModeIndexes[i] = eraseModes[i];
}
eraseModeCount = nEraseModes;
}
if (eraseModeCount == 1) {
/* only one left, let's use that one */
lastIndex = -1;
return (lastEraseMode = eraseModeIndexes[--eraseModeCount]);
} else {
/* pick a random slot in the list, check for last */
if (sequential) {
lastIndex = i = (lastIndex + 1) % nEraseModes;
} else
while (eraseModeIndexes[i = NRAND(eraseModeCount)] == lastEraseMode);
}
eraseMode = eraseModeIndexes[i]; /* copy out chosen eraseMode */
/* move eraseMode at end of list to slot vacated by chosen eraseMode, dec count */
eraseModeIndexes[i] = eraseModeIndexes[--eraseModeCount];
return (lastEraseMode = eraseMode); /* remember last eraseMode picked */
}
static char *
strpmtok(int *sign, char *str)
{
static int nextsign = 0;
static char *loc;
char *p, *r;
if (str)
loc = str;
if (nextsign) {
*sign = nextsign;
nextsign = 0;
}
p = loc - 1;
for (;;) {
switch (*++p) {
case '+':
*sign = 1;
continue;
case '-':
*sign = -1;
continue;
case ' ':
case ',':
case '\t':
case '\n':
continue;
case 0:
loc = p;
return (char *) NULL;
}
break;
}
r = p;
for (;;) {
switch (*++p) {
case '+':
nextsign = 1;
break;
case '-':
nextsign = -1;
break;
case ' ':
case ',':
case '\t':
case '\n':
case 0:
break;
default:
continue;
}
break;
}
if (*p) {
*p = 0;
loc = p + 1;
} else
loc = p;
return r;
}
static Bool
parseEraseModeList(char * eraseModeList, Bool verbose)
{
int i, sign = 1;
char *p;
if ((eraseModes = (int *) calloc(countof(erasers), sizeof (int))) == NULL) {
return False;
}
p = strpmtok(&sign, (eraseModeList) ? eraseModeList : (char *) "");
while (p) {
if (!strcmp(p, "all")) {
for (i = 0; i < (int) countof(erasers); i++) {
eraseModes[i] = (sign > 0);
}
} else {
for (i = 0; i < (int) countof(erasers); i++)
if (!strcmp(p, erasers[i].name))
break;
if (i < (int) countof(erasers))
eraseModes[i] = (sign > 0);
else
(void) fprintf(stderr, "unrecognized eraseMode \"%s\"\n", p);
}
p = strpmtok(&sign, (char *) NULL);
}
nEraseModes = 0;
for (i = 0; i < (int) countof(erasers); i++)
if (eraseModes[i])
eraseModes[nEraseModes++] = i;
if (!nEraseModes) { /* empty list */
for (i = 0; i < (int) countof(erasers); i++) {
eraseModes[i] = i;
}
nEraseModes = (int) countof(erasers);
}
if (verbose) {
(void) fprintf(stderr, "%d eraseMode%s: ", nEraseModes, ((nEraseModes == 1) ? "" : "s"));
for (i = 0; i < nEraseModes; i++)
(void) fprintf(stderr, "%s ", erasers[eraseModes[i]].name);
(void) fprintf(stderr, "\n");
}
return True;
}
void
erasemodefromname(char *name, Bool verbose)
{
if (currentEraseMode < 0) {
if (!parseEraseModeList(name, verbose))
return;
currentEraseMode = pickMode();
}
}
static int
advanceErase()
{
if (currentEraseMode < 0)
return 0;
/* previousEraseMode = currentEraseMode; */
currentEraseMode = pickMode();
return currentEraseMode;
}
#endif