diff -ur xlockmore-4.05-redhat/xalock/modes.h xlockmore-4.05-hacked/xalock/modes.h --- xlockmore-4.05-redhat/xalock/modes.h Tue Aug 26 09:52:47 1997 +++ xlockmore-4.05-hacked/xalock/modes.h Wed Apr 22 20:40:30 1998 @@ -34,6 +34,9 @@ "helix", "hop", "hyper", +#if 1 /* johnh */ + "hyperer", +#endif /* 1 */ "ico", "ifs", "image", diff -ur xlockmore-4.05-redhat/xlock/mode.c xlockmore-4.05-hacked/xlock/mode.c --- xlockmore-4.05-redhat/xlock/mode.c Sat Oct 4 21:07:03 1997 +++ xlockmore-4.05-hacked/xlock/mode.c Wed Apr 22 20:49:32 1998 @@ -146,6 +146,12 @@ refresh_hyper, init_hyper, NULL, &hyper_opts, 10000, 1, 300, 1, 1.0, "Shows a spinning tesseract in 4D space", 0, NULL}, +#if 1 /* johnh */ + {"hyperer", init_hyperer, draw_hyperer, release_hyperer, + refresh_hyperer, init_hyperer, NULL, &hyperer_opts, + 10000, 1, 300, 1, 1.0, + "Shows n-dimensional spinning hypercubes", 0, NULL}, +#endif /* 1 */ {"ico", init_ico, draw_ico, release_ico, refresh_ico, change_ico, NULL, &ico_opts, 100000, 0, 400, 0, 1.0, diff -ur xlockmore-4.05-redhat/xlock/mode.h xlockmore-4.05-hacked/xlock/mode.h --- xlockmore-4.05-redhat/xlock/mode.h Thu Sep 18 19:45:10 1997 +++ xlockmore-4.05-hacked/xlock/mode.h Wed Apr 22 20:41:49 1998 @@ -374,6 +374,14 @@ extern ModeHook refresh_hyper; extern ModeSpecOpt hyper_opts; +#if 1 /* johnh */ +extern ModeHook init_hyperer; +extern ModeHook draw_hyperer; +extern ModeHook release_hyperer; +extern ModeHook refresh_hyperer; +extern ModeSpecOpt hyperer_opts; +#endif /* 1 */ + extern ModeHook init_ico; extern ModeHook draw_ico; extern ModeHook release_ico; diff -ur xlockmore-4.05-redhat/xlock/xlock.man xlockmore-4.05-hacked/xlock/xlock.man --- xlockmore-4.05-redhat/xlock/xlock.man Tue Sep 30 21:04:16 1997 +++ xlockmore-4.05-hacked/xlock/xlock.man Wed Apr 22 22:35:53 1998 @@ -384,6 +384,9 @@ .B hyper Shows a spinning tesseract in 4D space. .TP 8 +.B hyper +Shows spinning N-dimensional hypercubes. +.TP 8 .B ico Shows a bouncing polyhedra. .TP 8 diff -urN xlockmore-4.05-redhat/modes/hyperer.c xlockmore-4.05-hacked/modes/hyperer.c --- xlockmore-4.05-redhat/modes/hyperer.c Wed Dec 31 16:00:00 1969 +++ xlockmore-4.05-hacked/modes/hyperer.c Sat May 2 15:09:09 1998 @@ -0,0 +1,819 @@ + +/* + * hyperer.c (nee multidico) + * Copyright (C) 1992,1998 John Heidemann + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + *** + * + * hyperer (then called multidico) was originally written for + * xscreensaver in 1992. Unfortunately it didn't make it into that + * code because Jamie Zawinski was implementing his own tesseract and + * preferred his version (optimized for speed) to my version + * (with support for more than 4 dimesnions). + * + * In 1998 I finally got around to porting it to xlockmore and sending + * it off. + * + * (The implementation is independent of jwz's---I started with ico.) + */ + + +#include +#include +#include +#include +#include + + +#ifdef STANDALONE +#define PROGCLASS "Hyperer" +#define HACK_INIT init_hyperer +#define HACK_DRAW draw_hyperer +#define HACK_CHANGE change_hyperer +#define hyperer_opts xlockmore_opts +#define DEFAULTS "*delay: 10000 \n" \ + "*cycles: 300 \n" \ + "*ncolors: 200 \n" \ + "*background: black \n" \ + "*foreground: white \n" \ + "*dimension: 0 \n" \ + "*spinDelay: 2 \n" \ + "*colorDimension: 3 \n" \ + "*showAxes: false \n" \ + "*randomStart: false \n" \ + "*debug: false \n" +#include "xlockmore.h" /* in xscreensaver distribution */ +#else /* STANDALONE */ +#include "xlock.h" /* in xlockmore distribution */ +#endif /* STANDALONE */ + + + +struct dpoint { double x, y; }; + +#define max_d 9 +#define max_mat (max_d+1) +struct vector { double x[max_mat]; }; +struct matrix { double x[max_mat][max_mat]; }; +struct line_segment { int from, to; long color; }; + +static Bool random_start; +static Bool show_axes; +static int dimension; +static int spin_delay; +static int debug; +static int color_dimension; +static int group_dimension; +static int color_groups; + +extern XFontStruct *getFont(); + +static XrmOptionDescRec opts[] = { + { "-dimension", ".hyperer.dimension", XrmoptionSepArg, 0 }, + { "-color-dimension", ".hyperer.colorDimension", XrmoptionSepArg, 0 }, + { "-group-dimension", ".hyperer.groupDimension", XrmoptionSepArg, 0 }, + { "-spin-delay", ".hyperer.spinDelay", XrmoptionSepArg, 0 }, + { "-show-axes", ".hyperer.showAxes", XrmoptionNoArg, "false" }, + { "+show-axes", ".hyperer.showAxes", XrmoptionNoArg, "true" }, + { "+random-start", ".hyperer.randomStart", XrmoptionNoArg, "true" }, + { "-random-start", ".hyperer.randomStart", XrmoptionNoArg, "false" }, + { "+color-groups", ".hyperer.colorGroups", XrmoptionNoArg, "true" }, + { "-color-groups", ".hyperer.colorGroups", XrmoptionNoArg, "false" }, +}; +static argtype vars[] = { + {(caddr_t *) &random_start, "randomStart", "RandomStart", "True", t_Bool}, + {(caddr_t *) &show_axes, "showAxes", "ShowAxes", "True", t_Bool}, + {(caddr_t *) &dimension, "dimension", "Dimension", "0", t_Int}, + {(caddr_t *) &color_dimension, "colorDimension", "ColorDimension", "3", t_Int}, + {(caddr_t *) &group_dimension, "groupDimension", "GroupDimension", "0", t_Int}, + {(caddr_t *) &spin_delay, "spinDelay", "SpinDelay", "2", t_Int}, + {(caddr_t *) &color_groups, "colorGroups", "ColorGroups", "false", t_Bool}, +}; +static OptionStruct desc[] = { + { "-dimension num", "how many dimensions to the hypercube (0=random)" }, + { "-color-dimension num", "color sub-cubes of this many dimensions the same" }, + { "-group-dimension num", "aggregate this many dimensions as a single color (use +color-groups as a simpler interface)" }, + { "-/+color-groups", "turn off/on coloring sub-groups of the hypercube" }, + { "-spin-delay num", "delay in seconds before chaning spin speed" }, + { "-/+show-axes", "turn off/on showing the axes" }, + { "-/+random-start", "turn off/on begining with random rotations" }, +}; + +ModeSpecOpt hyperer_opts = { 10, opts, 7, vars, desc }; + + + +struct hyperer { + Display *dpy; + Window window; + XFontStruct *font; + + int show_axes_p; + + GC gc; + int maxx, maxy; + int delay; + int spinDelay; + Colormap cmap; + + /* + * Data storage. + */ + int num_d; /* number of dimensions */ + int num_mat; + + /* there are C(num_d,2) planes */ +#define max_planes 40 + int num_planes; + XPoint *rotation_planes; + double rotations[max_planes]; /* where we are in each dimension */ + double d_rotations[max_planes]; /* change in rotation */ + double dd_rotations[max_planes]; /* change in change in rotation */ + int cdd_rotations[max_planes]; /* how many turns to apply dd_rotations */ + struct matrix Trotations[max_planes]; + + struct matrix Tall; + + int num_points; + struct vector *points; + int num_lines; + struct line_segment *lines; + + int point_set; /* which bank of points are we using */ + XPoint *xpoints[2]; + + int num_axis_points; + int axis_points[max_mat]; + + /* + * Inter-step state: + */ + int translated; + int this_set; + + time_t spin_timer, debug_timer; +}; + + +static struct hyperer *hyperers = NULL; + + +/* + * Matrix handling & 3d transformation routines + */ + +static void +MatMult (struct matrix *a, struct matrix *b, struct matrix *c, int n) + /* c = a * b for n x n matricies */ +{ + register int i, j, k; + double temp; + + /* Strassen' method... what's that? */ + for (i=0; ix[i][k] * b->x [k][j]; + c->x[i][j] = temp; + }; +} + +static void +MatVecMult (struct matrix *a, struct vector *b, struct vector *c, int n) + /* c = a * b for a n x n, b&c 1 x n */ +{ + register int i, k; + double temp; + + for (i=0; ix[i][k] * b->x[k]; + c->x[i] = temp; + }; +} + +static void +MatCopy (struct matrix *a, struct matrix *b, int n) + /* b <- a */ +{ + register int i, j; + for (i=0; ix[i][j] = a->x[i][j]; +} + +static void +MatZero (struct matrix *a, int n) + /* a = 0 */ +{ + register int i, j; + for (i=0; ix[i][j] = 0.0; +} + +static void +MatIdent (struct matrix *a, int n) + /* a = I */ +{ + register int i; + MatZero (a, n); + for (i=0; ix[i][i] = 1.0; +} + + + + +/* + * X stuff + */ + +static void +get_geom (ModeInfo *mi, struct hyperer *hp) +{ + XWindowAttributes xgwa; + XGetWindowAttributes(hp->dpy, hp->window, &xgwa); + hp->cmap = xgwa.colormap; + hp->maxx = xgwa.width; + hp->maxy = xgwa.height; +} + + +static void +ZeroMultiCounter(int *c, int n) +{ + int i; + for (i=0; i= n) + return 0; + else if (++c[place] >= BASE) { + c[place] = 0; + return RealIncMultiCounter(c, n, place+1); + } else return 1; +} + + +static int +IncMultiCounter(int *c, int n) +{ + return RealIncMultiCounter(c, n, 0); +} + + +static int +figure_num_points(int d) +{ +/* return (int)pow(2.0, (double)d); */ + return 1 << d; +} + +static int +figure_num_lines(int d) +{ + return d * figure_num_points(d-1); +} + +static int +figure_num_planes(int d) +{ + return ((d-1) * d) / 2; +} + +static long +color_from_point(ModeInfo *mi, struct hyperer *hp, struct vector *from, struct vector *to) +{ + int n = 0, i, same_in_low_bits = 1; + long color; + + for (i = 0; i < hp->num_d; i++) { + n = (n << 1) + (to->x[i] ? 1 : 0); + if (i < group_dimension && from->x[i] != to->x[i]) + same_in_low_bits = 0; + }; + if (same_in_low_bits) { + /* toss some number of dimensions */ + n &= ~((1 << color_dimension) - 1); + /* scale it across the points */ + color = MI_PIXEL(mi, (int) ((n * MI_NPIXELS(mi)) / hp->num_points)); + /* printf ("color %d (%x)\n", n, color); */ + } else { + color = MI_WIN_WHITE_PIXEL(mi); + /* printf ("color white\n"); */ + }; + return color; +} + +static void +figure_points(ModeInfo *mi, struct hyperer *hp) +{ + int i, j, k, n, d; + int *c; + +#define allocarray(ELTYPE,N) ((ELTYPE*)malloc((N)*sizeof(ELTYPE))) + /* + * First, figure out the points. + */ + hp->num_points = figure_num_points(hp->num_d); + /* assert(num_points <= max_points); */ + hp->points = allocarray(struct vector, hp->num_points); + hp->xpoints[0] = allocarray(XPoint, hp->num_points); + hp->xpoints[1] = allocarray(XPoint, hp->num_points); + c = allocarray(int, hp->num_points); /* will be lost, sigh */ + ZeroMultiCounter(c, hp->num_d); + n = 0; + do { + for (i=0; inum_d; i++) + hp->points[n].x[i] = c[i]; + n++; + } while (IncMultiCounter(c, hp->num_d)); + XFree(c); + assert(hp->num_points == n); + + /* + * Next connect them. + * We could do this more intelligently, but why bother? + * + * Connect points that differ by only one coordinate. + */ + hp->num_lines = figure_num_lines(hp->num_d); + /* assert(hp->num_lines <= hp->max_lines); */ + hp->lines = (struct line_segment*)malloc(hp->num_lines * sizeof(struct line_segment)); + for (n=i=0; inum_points; i++) + for (j=i+1; jnum_points; j++) { + for (d=k=0; knum_d; k++) + if (hp->points[i].x[k] != hp->points[j].x[k]) + d++; + if (d==1) { + hp->lines[n].from = i; + hp->lines[n].to = j; + /* printf ("from %x to %x ", i, j); */ + hp->lines[n].color = color_from_point(mi, hp, &hp->points[i], &hp->points[j]); + n++; + }; + }; + assert(hp->num_lines == n); + + /* + * Now determine the planes of rotation. + */ + hp->num_planes = figure_num_planes(hp->num_d); + assert(hp->num_planes <= max_planes); + hp->rotation_planes = allocarray(XPoint, hp->num_planes); + for (n=i=0; inum_d; i++) + for (j=i+1; jnum_d; j++) { + hp->rotation_planes[n].x = i; + hp->rotation_planes[n].y = j; + n++; + }; + assert(hp->num_planes == n); + + /* + * Potential random initial rotations. + */ +#define FRAC (1024*16) + if (random_start) { + for (i=0; inum_planes; i++) + hp->rotations[i] = 2.0 * NRAND(FRAC) * M_PI / FRAC; + }; +} + + +void +figure_axis_points(struct hyperer *hp) +{ + int i, j, num_set; + + hp->show_axes_p = show_axes; + for (hp->num_axis_points=i=0; inum_points; i++) { + for (num_set=j=0; jnum_d; j++) + if (hp->points[i].x[j] != 0.0) + num_set++; + if (num_set <= 1) + hp->axis_points[hp->num_axis_points++] = i; + }; +} + + +void +init_font_stuff(ModeInfo *mi, struct hyperer *hp) +{ + if (hp->font == None) + hp->font = getFont(hp->dpy); +} + + +void +init_x_stuff(ModeInfo *mi, struct hyperer *hp) +{ + XGCValues gcv; + XWindowAttributes xgwa; + int options = 0; + + hp->dpy = MI_DISPLAY(mi); + hp->window = MI_WINDOW(mi); + + XGetWindowAttributes(hp->dpy, hp->window, &xgwa); + get_geom(mi, hp); + +#if 0 + hp->delay = get_integer_resource ("delay", "Integer"); + if (hp->delay < 0) hp->delay = 0; +#endif /* 0 */ + + hp->spinDelay = spin_delay; + if (hp->spinDelay < 0) hp->spinDelay = 0; + + hp->num_d = dimension; + if (hp->num_d == 0) { + hp->num_d = NRAND(max_d - 3) + 3; + }; + if (hp->num_d < 2) hp->num_d = 2; + if (hp->num_d >= max_d) { + fprintf (stderr, "Dimensionality too high. Reset to maximum of %d.\n", max_d-1); + hp->num_d = max_d-1; + }; + hp->num_mat = hp->num_d+1; + + init_font_stuff(mi, hp); + + options |= GCForeground|GCFont; + gcv.foreground = MI_WIN_WHITE_PIXEL(mi); + gcv.font = hp->font->fid; + hp->gc = XCreateGC (hp->dpy, hp->window, GCForeground, &gcv); +} + + +void +init_hyperer(ModeInfo *mi) +{ + struct hyperer *hp; + int i; + + if (hyperers == NULL) { + if ((hyperers = (struct hyperer *) calloc(MI_NUM_SCREENS(mi), + sizeof (struct hyperer))) == NULL) + return; + } + hp = &hyperers[MI_SCREEN(mi)]; + + /* options hacking + * color groups superceeds the more complex color-same-dimensions + */ + if (color_groups) + group_dimension = dimension - color_dimension; + + init_x_stuff(mi, hp); + + figure_points(mi, hp); + + /* + * Fix the d+1 coord of all points. + */ + for (i=0; inum_points; i++) + hp->points[i].x[hp->num_d] = 1; + + figure_axis_points(hp); + + hp->this_set = hp->translated = 0; +} + + +/* + * Flickering is a problem here since we erase the whole + * thing and draw the whole thning. + * #define'ing XOR_HACK draws the lines with xor which helps a lot + * (it's what hyper, the 4-d hypercube does), but it doesn't work + * for us because frequently when we have no rotation in one + * (of our *many*) axes then we end up XOR'ing twice => nothing. + * + */ +static void +draw_hyperer_step(ModeInfo *mi, struct hyperer *hp, int draw_p, int set) +{ + int i; + int from, to; + char tmps[80]; + unsigned long color; +#ifdef XOR_HACK + int other_set = !set; +#endif /* XOR_HACK */ + + if (draw_p) { + color = MI_WIN_WHITE_PIXEL(mi); + } else { + color = MI_WIN_BLACK_PIXEL(mi); + }; + XSetForeground(hp->dpy, hp->gc, color); + +#ifdef XOR_HACK + XSetFunction(hp->dpy, hp->gc, (draw_p == 2 ? GXxor : GXcopy)); +#endif /* XOR_HACK */ + + for (i=0; inum_lines; i++) { + from = hp->lines[i].from; + to = hp->lines[i].to; + if (draw_p && MI_NPIXELS(mi) > 2) + XSetForeground(hp->dpy, hp->gc, hp->lines[i].color); + XDrawLine(hp->dpy, hp->window, hp->gc, + hp->xpoints[set][from].x, hp->xpoints[set][from].y, + hp->xpoints[set][to].x, hp->xpoints[set][to].y); +#ifdef XOR_HACK + if (draw_p == 2) + XDrawLine(hp->dpy, hp->window, hp->gc, + hp->xpoints[other_set][from].x, hp->xpoints[other_set][from].y, + hp->xpoints[other_set][to].x, hp->xpoints[other_set][to].y); +#endif /* XOR_HACK */ + }; + + if (hp->show_axes_p) { + XSetForeground(hp->dpy, hp->gc, color); + for (i=0; inum_axis_points; i++) { + sprintf (tmps, "%d", i); + to = hp->axis_points[i]; + XDrawString(hp->dpy, hp->window, hp->gc, + hp->xpoints[set][to].x, hp->xpoints[set][to].y, + tmps, strlen(tmps)); + }; + }; +} + +static time_t +timer_time(time_t *start_time) +{ + time_t current_time; + + if (*start_time == 0) + time(start_time); + time(¤t_time); + return current_time - *start_time; +} + +static void +move_hyperer(struct hyperer *hp) +{ + int i; + int stationary = 0; +/* NEEDSWORK: These should be resources */ +#define default_cdd_rotation 10 +#define default_dd_rotation (M_PI/1024.0) + int axis, max_axis; + int faster; + + if (timer_time(&hp->spin_timer) > spin_delay) { + hp->spin_timer = (time_t)0; + /* + * Change rotation? + * + * 66% chance if stationary, 33% if not. + */ + stationary = 1; + for (i=0; inum_planes; i++) + if (hp->d_rotations[i] != 0.0 || hp->cdd_rotations[i]) { + stationary = 0; + break; + }; + if (NRAND(3) < 1+stationary) { + /* Change! But what? */ + max_axis = hp->num_planes; + + if (max_axis > hp->num_planes || max_axis < 0) + max_axis = hp->num_planes; + axis = NRAND(max_axis); + + /* + * And how much? 33% chance faster, 66% slower. + * If stopped, slower doesn't start it moving + * unless we're stationary. + */ + hp->cdd_rotations[axis] = default_cdd_rotation + + NRAND(7) - 3; + faster = (NRAND(3) < 1); + if (faster || hp->dd_rotations[axis] != 0.0 || stationary) + hp->dd_rotations[axis] = default_dd_rotation * + (hp->dd_rotations[axis] >= 0.0 ? 1 : -1) * + (faster ? 1 : -1); + if (debug) + fprintf(stderr,"axis %d made %s at %d\n", + axis, faster ? "faster" : "slower", + (int) timer_time(&hp->debug_timer)); + }; + }; + + /* + * Rotate. + */ + for (i=0; inum_planes; i++) { + if (hp->cdd_rotations[i]) { + hp->cdd_rotations[i]--; + hp->d_rotations[i] += hp->dd_rotations[i]; + }; + hp->rotations[i] += hp->d_rotations[i]; + }; +} + +#define NEED_SINCOS +#ifdef NEED_SINCOS +static void +sincos(double a, double *s, double *c) +{ + *s = sin(a); + *c = cos(a); +} +#endif /* NEED_SINCOS */ + +static void +calc_transformation(struct hyperer *hp) +{ + double cosa, sina; + int p1, p2; + struct matrix Ttmp; + struct matrix Tpre, Tuser, Tpretranspose, Tscale, Tposttranspose; + int i; + struct dpoint scale, range, offset; + double scale_used; + + /* + * Adjust the data. + * Since the data goes from 0->1 on each axis, + * we shift it by -0.5 here to center the figure. + */ + MatIdent(&Tpre, hp->num_mat); + for (i=0; inum_d; i++) { + Tpre.x[i][hp->num_d] = -0.5; + }; + + + /* + * Figure the rotation. + */ + MatIdent(&Tuser, hp->num_mat); + for (i=0; i< hp->num_planes; i++) { + p1 = hp->rotation_planes[i].x; + p2 = hp->rotation_planes[i].y; + sincos(hp->rotations[i], &sina, &cosa); + MatIdent(&hp->Trotations[i], hp->num_mat); + hp->Trotations[i].x[p1][p1] = hp->Trotations[i].x[p2][p2] = cosa; + hp->Trotations[i].x[p1][p2] = sina; + hp->Trotations[i].x[p2][p1] = -sina; + MatMult(&hp->Trotations[i], &Tuser, &Ttmp, hp->num_mat); + MatCopy(&Ttmp, &Tuser, hp->num_mat); + }; + +/* Now calculate the scaling matrix */ + if (1) { + /* + * Calculate the best scale of the two axes. + * Multiply by 0.9 to use 90% of the display. + * Divide by the sqrt(2.0) because it's bigest when + * rotated by 45 degrees. + * + * This principle generalizes to sqrt(hp->num_d). + */ +#define border_width (0.05) + range.x = range.y = sqrt((double) hp->num_d); + scale.x = (1.0-2*border_width) * hp->maxx / range.x; + scale.y = (1.0-2*border_width) * hp->maxy / range.y; + scale_used = ((scale.x < scale.y) ? scale.x : scale.y); + offset.x = hp->maxx / 2.0; + offset.y = hp->maxy / 2.0; + + /* + * Setup & compute the matricies + */ + MatIdent (&Tpretranspose, hp->num_mat); + Tpretranspose.x[0][hp->num_d] = 0; + Tpretranspose.x[1][hp->num_d] = 0; + + MatIdent (&Tscale, hp->num_mat); + Tscale.x[0][0] = scale_used; + Tscale.x[1][1] = -scale_used; + + MatIdent (&Tposttranspose, hp->num_mat); + Tposttranspose.x[0][hp->num_d] = offset.x; + Tposttranspose.x[1][hp->num_d] = offset.y; + + MatMult (&Tscale, &Tpretranspose, &Ttmp, hp->num_mat); + MatMult (&Tposttranspose, &Ttmp, &Tscale, hp->num_mat); + } else MatIdent (&Tscale, hp->num_mat); + + /* + * Put it all together. + */ + MatMult(&Tuser, &Tpre, &Ttmp, hp->num_mat); + MatMult(&Tscale, &Ttmp, &hp->Tall, hp->num_mat); +} + + +static void +translate_point(struct hyperer *hp, struct vector *real, XPoint *screen_image) +{ + struct vector image; + MatVecMult (&hp->Tall, real, &image, hp->num_mat); + screen_image->x = (short)image.x[0]; + screen_image->y = (short)image.x[1]; +} + +static void +translate_points(struct hyperer *hp, int set) +{ + int i; + calc_transformation(hp); + for (i=0; inum_points; i++) { + translate_point(hp, &hp->points[i], &hp->xpoints[set][i]); + }; +} + + + +void +draw_hyperer(ModeInfo *mi) +{ + struct hyperer *hp = &hyperers[MI_SCREEN(mi)]; + int next_set = !hp->this_set; + + if (!hp->translated) { + /* First time through */ + translate_points(hp, next_set); + translate_points(hp, hp->this_set); + hp->translated = 1; + }; + +#ifdef XOR_HACK + draw_hyperer_step(mi, hp, 2, next_set); +#else /* ! XOR_HACK */ + draw_hyperer_step(mi, hp, 0, hp->this_set); + draw_hyperer_step(mi, hp, 1, next_set); +#endif /* XOR_HACK */ + XSync (hp->dpy, True); + + /* Set up next place */ + move_hyperer(hp); + translate_points(hp, hp->this_set); + hp->this_set = next_set; +} + +void +refresh_hyperer(ModeInfo *mi) +{ + struct hyperer *hp = &hyperers[MI_SCREEN(mi)]; + + XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); + if (hp->translated) + draw_hyperer_step(mi, hp, 1, hp->this_set); +} + +void +change_hyperer(ModeInfo *mi) +{ + struct hyperer *hp = &hyperers[MI_SCREEN(mi)]; + + /* make it change */ + hp->spin_timer = 1; +} + +void +release_hyperer(ModeInfo *mi) +{ + if (hyperers != NULL) { + int screen; + + for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { + struct hyperer *hp = &hyperers[screen]; + + if (hp->gc != NULL) + XFreeGC(hp->dpy, hp->gc); + if (hp->points) + XFree(hp->points); + if (hp->lines) + XFree(hp->lines); + if (hp->rotation_planes) + XFree(hp->rotation_planes); + if (hp->font) + XFreeFont(hp->dpy, hp->font); + + } + (void) free((void *) hyperers); + hyperers = NULL; + } +} + +