|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T k
Length: 32418 (0x7ea2)
Types: TextFile
Names: »kaleid.c.orig«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/X/Kaleid/kaleid.c.orig«
#include <stdio.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include "kalicon.h"
#include <signal.h>
/*
KALEIDOSCOPE (X11 Version)
By Nathan Meyers, nathanm@hp-pcd.hp.com.
Based on a kaleidoscope algorithm from a PC-based program by:
Judson D. McClendon (Compuserve: [74415,1003])
*/
char *progname;
char *strchr();
char *calloc();
/* Approximation of CGA/EGA/VGA colors -- (out of standard order) */
unsigned long colors[][3] = { { 0x0000, 0x0000, 0x0000 }, /* black */
{ 0xffff, 0xffff, 0xffff }, /* bright white */
{ 0xaaaa, 0x0000, 0x0000 }, /* red */
{ 0x0000, 0xaaaa, 0x0000 }, /* green */
{ 0x0000, 0x0000, 0xaaaa }, /* blue */
{ 0x0000, 0xaaaa, 0xaaaa }, /* cyan */
{ 0xaaaa, 0x0000, 0xaaaa }, /* magenta */
{ 0xffff, 0xffff, 0x5555 }, /* yellow */
{ 0xaaaa, 0x5555, 0x0000 }, /* brown */
{ 0xaaaa, 0xaaaa, 0xaaaa }, /* white */
{ 0x5555, 0x5555, 0x5555 }, /* dark grey */
{ 0x5555, 0x5555, 0xffff }, /* light blue */
{ 0x5555, 0xffff, 0x5555 }, /* light green */
{ 0x5555, 0xffff, 0xffff }, /* light cyan */
{ 0xffff, 0x5555, 0x5555 }, /* light red */
{ 0xffff, 0x5555, 0xffff } }; /* light magenta */
#define NCOLORS 16
static char *what = "@(#)kaleid.c $Revision: 1.98 $";
Display *display;
int screen;
Window *window;
int nwindows=1, nvisible=0;
unsigned long palette[NCOLORS];
GC *window_gcs;
int nclips = 0;
XRectangle *cliplist;
struct fclip {
double x, y, width, height;
} *clips;
int *visible;
int *CX, *CY, *M;
int *OX, *OY;
int *X1, *Y1, *X2, *Y2, *XV1, *YV1, *XV2, *YV2;
int *XA, *YA, *XB, *YB, *XC, *YC, *XD, *YD;
int qix = 0;
int D[] = { 2, 4, 4, 4, 4, 2, -2, -4, -4, -4, -4, -2, 2, 4, 4, 4, 4, 2 };
struct timeval *schedule;
long *intervals;
int *refreshcount, *itercount;
unsigned short (*randomseed)[3], (*randombase)[3];
int numcolors=NCOLORS;
int dynamic_colors=0;
long refresh=0L;
long rndm();
int rootx=1, rooty=1;
int ww, wh;
int doroot = 0;
int killed = 0;
char *ucolors = NULL;
void sighandler()
{
killed=1;
return;
}
void refreshrootquit()
{
XClearWindow(display,RootWindow(display,screen));
XSync(display,0);
exit(0);
}
main(argc,argv)
int argc;
char *argv[];
{
unsigned long bgcolor, bdcolor;
int bwidth = 2;
XSizeHints size_hints;
XIconSize icon_size_hints, *icon_size_list;
int numsizes, currsize;
XWMHints wm_hints;
char *displayname = NULL, *background = NULL, *border = NULL;
char *geomstring = NULL;
XColor screen_in_out, visual_def_return, exact_def_return;
XEvent event;
int iconic=0, bstore=0;
long delayvalue = -1L, icondelay=100L;
char *clipcoords = NULL;
int monochrome=0;
int o_argc = argc;
char **o_argv = argv;
int i,j;
long time();
char *basename;
long atol();
progname = argv[0];
if ((basename=strrchr(progname,'/'))!=NULL) basename++;
else basename=progname;
while (--argc>0) {
char *option = (*++argv);
if (!strcmp(option,"-delay")) {
if (--argc==0) usage();
delayvalue = atol(*++argv);
if (delayvalue<0L) delayvalue = 0L;
}
else if (!strcmp(option,"-qix")) {
qix=1;
}
else if (!strcmp(option,"-mono")) {
monochrome=1;
}
else if (!strcmp(option,"-randomcolor")) {
dynamic_colors = 1;
}
else if (!strcmp(option,"-display")) {
if (--argc==0) usage();
displayname = (*++argv);
}
else if (strchr(option,':')) {
displayname = option;
}
else if (!strcmp(option,"-bg")) {
if (--argc==0) usage();
background = (*++argv);
}
else if (!strcmp(option,"-bd")) {
if (--argc==0) usage();
border = (*++argv);
}
else if (!strcmp(option,"-bstore")) {
bstore = 1;
}
else if (!strcmp(option,"-bw")) {
if (--argc==0) usage();
bwidth = atoi(*++argv);
if (bwidth<0) bwidth = 0;
}
else if (!strcmp(option,"-colors")) {
if (--argc==0) usage();
ucolors = (*++argv);
}
else if (!strcmp(option,"-clip")) {
if (--argc==0) usage();
clipcoords = (*++argv);
}
else if (!strcmp(option,"-icondelay")) {
if (--argc==0) usage();
icondelay = atol(*++argv);
if (icondelay<0L) icondelay = 0L;
}
else if (!strcmp(option,"-iconic")) {
iconic = 1;
}
else if (!strcmp(option,"-geometry")) {
if (--argc==0) usage();
geomstring = (*++argv);
}
else if (*option=='=') {
geomstring = option;
}
else if (!strcmp(option,"-mult")) {
if (--argc==0) usage();
nwindows = atoi(*++argv);
if (nwindows<1) nwindows = 1;
}
else if (!strcmp(option,"-r")) {
doroot = 1;
}
else if (!strcmp(option,"-refresh")) {
refresh = ExposureMask;
}
else if (!strcmp(option,"-root")) {
doroot = 1;
}
else usage();
}
if (monochrome) dynamic_colors = 0;
if (delayvalue == -1L) delayvalue = doroot ? 100L : 10L;
display = XOpenDisplay(displayname);
if (display==NULL) {
(void)fprintf(stderr,
(displayname==NULL) ?
"%s: Failed to open display.\n" :
"%s: Failed to open display %s.\n",
progname,displayname);
exit(1);
}
screen = DefaultScreen(display);
srand48(time((long *)NULL));
if (background == NULL ||
XAllocNamedColor(display,
DefaultColormap(display,screen),
background,
&visual_def_return,
&exact_def_return)==False)
bgcolor = BlackPixel(display,screen);
else bgcolor = exact_def_return.pixel;
if (border==NULL ||
XAllocNamedColor(display,
DefaultColormap(display,screen),
border,
&visual_def_return,
&exact_def_return)==False)
bdcolor = WhitePixel(display,screen);
else bdcolor = exact_def_return.pixel;
if (clipcoords != NULL) {
char *temp = clipcoords;
char *calloc();
double strtod();
int commacount = 0;
int len;
while (*temp != '\0') commacount += (*(temp++) == ',') ? 1 : 0;
if ((commacount & 0x3) != 3) usage();
nclips = (commacount >> 2) + 1;
clips = (struct fclip *)calloc(nclips, sizeof(struct fclip));
cliplist = (XRectangle *)calloc(nclips, sizeof(XRectangle));
if (clips == NULL || cliplist == NULL) {
fprintf(stderr,"%s: calloc() failed\n",progname);
exit(1);
}
for (i=0; i<nclips; i++) {
clips[i].x = strtod(clipcoords, &temp);
if (temp == clipcoords) usage();
clipcoords = strchr(temp, ',') + 1;
clips[i].y = strtod(clipcoords, &temp);
if (temp == clipcoords) usage();
clipcoords = strchr(temp, ',') + 1;
clips[i].width = strtod(clipcoords, &temp);
if (temp == clipcoords) usage();
clipcoords = strchr(temp, ',') + 1;
clips[i].height = strtod(clipcoords, &temp);
if (temp == clipcoords) usage();
clipcoords = strchr(temp, ',') + 1;
}
}
if (!monochrome && DisplayCells(display,screen) > 2) {
if (dynamic_colors) {
for (numcolors=NCOLORS; numcolors>=2; numcolors--) {
if (XAllocColorCells(display,DefaultColormap(display,screen),
0, (unsigned long *)NULL, 0,
palette, (unsigned int)numcolors) == True) {
randomize_colors();
break;
}
}
if (numcolors < 2) fatalerror("Cannot allocate R/W color cells",NULL);
}
else if (ucolors != NULL) {
int thiscolor;
numcolors = 0;
for (thiscolor=0; thiscolor<NCOLORS; thiscolor++) {
char *comma=strchr(ucolors,',');
if (comma != NULL) *comma='\0';
if (XAllocNamedColor(display,
DefaultColormap(display,screen),
ucolors,
&visual_def_return,
&exact_def_return) == True)
palette[numcolors++] = exact_def_return.pixel;
if (comma == NULL) break;
ucolors = comma + 1;
}
if (numcolors < 1) fatalerror("Cannot allocate colors",NULL);
}
else {
int thiscolor;
numcolors = 0;
for (thiscolor=0; thiscolor<NCOLORS; thiscolor++) {
screen_in_out.flags = DoRed | DoGreen | DoBlue;
screen_in_out.red = colors[thiscolor][0];
screen_in_out.green = colors[thiscolor][1];
screen_in_out.blue = colors[thiscolor][2];
if (XAllocColor(display, DefaultColormap(display,screen),
&screen_in_out)==True)
palette[numcolors++] = screen_in_out.pixel;
}
if (numcolors < 2) fatalerror("Cannot allocate colors",NULL);
}
}
else {
numcolors=2;
palette[0] = WhitePixel(display,screen);
palette[1] = BlackPixel(display,screen);
}
size_hints.x = 0;
size_hints.y = 0;
size_hints.width = 300;
size_hints.height = 300;
size_hints.flags = PPosition | PSize;
if (geomstring!=NULL) {
int result;
result = XParseGeometry(geomstring,&size_hints.x,&size_hints.y,
&size_hints.width,&size_hints.height);
if (result & XNegative)
size_hints.x += DisplayWidth(display,screen)
- size_hints.width
- bwidth*2;
if (result & YNegative)
size_hints.y += DisplayHeight(display,screen)
- size_hints.height
- bwidth*2;
if (result & XValue || result & YValue) {
size_hints.flags |= USPosition;
size_hints.flags &= ~PPosition;
}
if (result & WidthValue || result & HeightValue) {
size_hints.flags |= USSize;
size_hints.flags &= ~PSize;
}
if (result & WidthValue && !(rootx = size_hints.width)) rootx = 1;
if (result & HeightValue && !(rooty = size_hints.height)) rooty = 1;
}
if (doroot) {
nwindows=rootx*rooty;
if (!allocate_arrays(nwindows)) {
(void)fprintf(stderr,"%s: malloc() failure\n",progname);
exit(1);
}
for (i=0; i<nwindows; i++) {
intervals[i] = delayvalue;
window[i] = RootWindow(display,screen);
visible[i]=1;
}
nvisible=nwindows;
XSelectInput(display,window[0],refresh);
}
else {
Pixmap bitmapicon;
if (!allocate_arrays((unsigned)(2*nwindows))) {
(void)fprintf(stderr,"%s: malloc() failure\n",progname);
exit(1);
}
for (i=0; i<nwindows; i++)
window[i] = XCreateSimpleWindow(display,RootWindow(display,screen),
size_hints.x,size_hints.y,
size_hints.width,size_hints.height,
bwidth,bdcolor,bgcolor);
icon_size_hints.max_width=64;
icon_size_hints.max_height=64;
currsize=0;
if (XGetIconSizes(display,RootWindow(display,screen),
&icon_size_list,&numsizes)) {
for (i=1; i<numsizes; i++) { /* Look for largest icon size */
if (icon_size_list[i].max_width >= icon_size_list[currsize].max_width &&
icon_size_list[i].max_height >= icon_size_list[currsize].max_height)
currsize=i;
}
if (icon_size_list[currsize].max_width <= 0 ||
icon_size_list[currsize].max_height <= 0 ) {
XFree(icon_size_list);
icon_size_list = &icon_size_hints;
}
}
else
icon_size_list = &icon_size_hints;
for (i=0; i<nwindows; i++) {
window[i+nwindows] = XCreateSimpleWindow(display,
RootWindow(display,screen), 0,0,
icon_size_list[currsize].max_width,
icon_size_list[currsize].max_height,
2,BlackPixel(display,screen),
WhitePixel(display,screen));
if (qix) {
CX[i+nwindows] = icon_size_list[currsize].max_width;
CY[i+nwindows] = icon_size_list[currsize].max_height;
}
else {
CX[i+nwindows] = icon_size_list[currsize].max_width >> 1;
CY[i+nwindows] = icon_size_list[currsize].max_height >> 1;
M[i+nwindows] = (CX[i+nwindows]>CY[i+nwindows]) ?
CX[i+nwindows] :
CY[i+nwindows];
M[i+nwindows] = M[i+nwindows] ? M[i+nwindows] : 1;
}
}
if (bstore) {
XSetWindowAttributes attributes;
attributes.backing_store = WhenMapped;
for (i=0; i<2*nwindows; i++) {
XChangeWindowAttributes(display,window[i],CWBackingStore,&attributes);
}
}
for (i=0; i<nwindows; i++)
XSetStandardProperties(display,window[i],"Kaleidoscope",basename,
None,o_argv,o_argc,&size_hints);
/* Create bitmap icon for wm's that don't support window icons */
bitmapicon=XCreateBitmapFromData(display,RootWindow(display,screen),
icon_bits, icon_width, icon_height);
/* Use window icon for window managers that support one */
wm_hints.icon_pixmap = bitmapicon;
wm_hints.flags = IconPixmapHint | IconWindowHint;
if (iconic) {
wm_hints.initial_state = IconicState;
wm_hints.flags |= StateHint;
}
for (i=0; i<nwindows; i++) {
wm_hints.icon_window = window[i+nwindows];
XSetWMHints(display,window[i],&wm_hints);
XSelectInput(display,window[i],
StructureNotifyMask|VisibilityChangeMask|refresh);
XSelectInput(display,window[i+nwindows],
StructureNotifyMask|VisibilityChangeMask|refresh);
XMapWindow(display,window[i]);
intervals[i] = delayvalue;
intervals[i+nwindows] = icondelay;
if (qix) {
CX[i] = size_hints.width;
CY[i] = size_hints.height;
}
else {
CX[i] = size_hints.width/2;
CY[i] = size_hints.height/2;
M[i] = (CX[i]>CY[i]) ? CX[i] : CY[i];
M[i] = M[i] ? M[i] : 1;
}
}
}
for (i = 0; i<(doroot ? nwindows : nwindows << 1 ); i++)
window_gcs[i] = XCreateGC(display,window[i],0,(XGCValues *)NULL);
if (doroot) {
int dontcare, winno;
Window wdontcare;
struct sigvec vec;
XGetGeometry(display,RootWindow(display,screen),&wdontcare,&dontcare,
&dontcare, &ww, &wh, &dontcare, &dontcare);
for (winno=0; winno<nwindows; winno++) {
i = winno % rootx;
j = winno / rootx;
CX[winno] = ww/rootx;
CY[winno] = wh/rooty;
OX[winno] = i * CX[winno];
OY[winno] = j * CY[winno];
if (!qix) {
CX[winno] >>= 1;
CY[winno] >>= 1;
M[winno] = (CX[winno]>CY[winno]) ? CX[winno] : CY[winno];
M[winno] = M[winno] ? M[winno] : 1;
}
if (nclips) {
int k;
double frootx = (double)rootx, frooty = (double)rooty;
double fww = (double)ww, fwh = (double)wh;
for (k=0; k<nclips; k++) {
cliplist[k].x = (int)(fww * clips[k].x / frootx + .5);
cliplist[k].y = (int)(fwh * clips[k].y / frooty + .5);
cliplist[k].width = (int)(fww * clips[k].width / frootx + .5);
cliplist[k].height = (int)(fwh * clips[k].height / frooty + .5);
}
XSetClipRectangles(display, window_gcs[winno], OX[winno], OY[winno],
cliplist, nclips, Unsorted);
}
}
for (i=0; i<nwindows; i++) {
refreshcount[i]=0;
itercount[i]=0;
randombase[i][0]=randomseed[i][0];
randombase[i][1]=randomseed[i][1];
randombase[i][2]=randomseed[i][2];
randomize_state_vars(i);
}
vec.sv_handler = sighandler;
vec.sv_mask = 0x0;
vec.sv_flags = 0;
(void)sigvec(SIGINT, &vec, (struct sigvec *)NULL);
(void)sigvec(SIGQUIT, &vec, (struct sigvec *)NULL);
(void)sigvec(SIGTERM, &vec, (struct sigvec *)NULL);
}
else {
for (i=0; i<nclips; i++) {
cliplist[i].x = (int)((double)size_hints.width * clips[i].x + .5);
cliplist[i].y = (int)((double)size_hints.height * clips[i].y + .5);
cliplist[i].width = (int)((double)size_hints.width * clips[i].width + .5);
cliplist[i].height = (int)((double)size_hints.height * clips[i].height +
.5);
}
if (nclips) for (i=0; i<nwindows; i++)
XSetClipRectangles(display, window_gcs[i], 0, 0,
cliplist, nclips, Unsorted);
for (i=0; i<nclips; i++) {
cliplist[i].x = (int)((double)icon_size_list[currsize].max_width *
clips[i].x + .5);
cliplist[i].y = (int)((double)icon_size_list[currsize].max_height *
clips[i].y + .5);
cliplist[i].width = (int)((double)icon_size_list[currsize].max_width *
clips[i].width + .5);
cliplist[i].height = (int)((double)icon_size_list[currsize].max_height *
clips[i].height + .5);
}
if (nclips) for (i=0; i<nwindows; i++)
XSetClipRectangles(display, window_gcs[i+nwindows], 0, 0,
cliplist, nclips, Unsorted);
nwindows <<= 1;
if (icon_size_list != &icon_size_hints) XFree(icon_size_list);
}
for (;;) {
int winno;
for (winno=0; winno<nwindows; winno++) if (visible[winno]) break;
while (nvisible) {
if (qix) {
XDrawLine(display,window[winno], window_gcs[winno],
X1[winno]+OX[winno], Y1[winno]+OY[winno],
X2[winno]+OX[winno], Y2[winno]+OY[winno]);
if (!rndm(25L,winno)) {
XGCValues values;
values.foreground = palette[rndm((long)numcolors,winno)];
XChangeGC(display, window_gcs[winno], GCForeground, &values);
}
if (X1[winno] < 3) XV1[winno] = rndm(6L,winno);
if (Y1[winno] > CY[winno]-4) XV1[winno] = rndm(6L,winno)+3;
if (X1[winno] > CX[winno]-4) XV1[winno] = rndm(6L,winno)+6;
if (Y1[winno] < 3) XV1[winno] = rndm(6L,winno)+9;
if (X2[winno] < 3) XV2[winno] = rndm(6L,winno);
if (Y2[winno] > CY[winno]-4) XV2[winno] = rndm(6L,winno)+3;
if (X2[winno] > CX[winno]-4) XV2[winno] = rndm(6L,winno)+6;
if (Y2[winno] < 3) XV2[winno] = rndm(6L,winno)+9;
X1[winno] += D[XV1[winno]];
Y1[winno] += D[XV1[winno]+3];
X2[winno] += D[XV2[winno]];
Y2[winno] += D[XV2[winno]+3];
}
else {
XSegment segs[8];
if (!rndm(50L,winno)) {
X1[winno] = rndm((long)M[winno],winno) + 1;
X2[winno] = rndm((long)M[winno],winno) + 1;
Y1[winno] = rndm((long)X1[winno],winno);
Y2[winno] = rndm((long)X2[winno],winno);
}
if (!rndm(10L,winno)) {
XGCValues values;
XV1[winno] = rndm(7L,winno)-3;
XV2[winno] = rndm(7L,winno)-3;
YV1[winno] = rndm(7L,winno)-3;
YV2[winno] = rndm(7L,winno)-3;
values.foreground = palette[rndm((long)numcolors,winno)];
XChangeGC(display, window_gcs[winno], GCForeground, &values);
}
if (CX[winno]<CY[winno]) {
XA[winno] = (long)X1[winno]*(long)CX[winno]/(long)CY[winno];
YA[winno] = (long)Y1[winno]*(long)CX[winno]/(long)CY[winno];
XB[winno] = X1[winno];
YB[winno] = Y1[winno];
XC[winno] = (long)X2[winno]*(long)CX[winno]/(long)CY[winno];
YC[winno] = (long)Y2[winno]*(long)CX[winno]/(long)CY[winno];
XD[winno] = X2[winno];
YD[winno] = Y2[winno];
}
else {
XA[winno] = X1[winno];
YA[winno] = Y1[winno];
XB[winno] = (long)X1[winno]*(long)CY[winno]/(long)CX[winno];
YB[winno] = (long)Y1[winno]*(long)CY[winno]/(long)CX[winno];
XC[winno] = X2[winno];
YC[winno] = Y2[winno];
XD[winno] = (long)X2[winno]*(long)CY[winno]/(long)CX[winno];
YD[winno] = (long)Y2[winno]*(long)CY[winno]/(long)CX[winno];
}
segs[0].x1 = CX[winno]+XA[winno]+OX[winno];
segs[0].y1 = CY[winno]-YB[winno]+OY[winno];
segs[0].x2 = CX[winno]+XC[winno]+OX[winno];
segs[0].y2 = CY[winno]-YD[winno]+OY[winno];
segs[1].x1 = CX[winno]-YA[winno]+OX[winno];
segs[1].y1 = CY[winno]+XB[winno]+OY[winno];
segs[1].x2 = CX[winno]-YC[winno]+OX[winno];
segs[1].y2 = CY[winno]+XD[winno]+OY[winno];
segs[2].x1 = CX[winno]-XA[winno]+OX[winno];
segs[2].y1 = CY[winno]-YB[winno]+OY[winno];
segs[2].x2 = CX[winno]-XC[winno]+OX[winno];
segs[2].y2 = CY[winno]-YD[winno]+OY[winno];
segs[3].x1 = CX[winno]-YA[winno]+OX[winno];
segs[3].y1 = CY[winno]-XB[winno]+OY[winno];
segs[3].x2 = CX[winno]-YC[winno]+OX[winno];
segs[3].y2 = CY[winno]-XD[winno]+OY[winno];
segs[4].x1 = CX[winno]-XA[winno]+OX[winno];
segs[4].y1 = CY[winno]+YB[winno]+OY[winno];
segs[4].x2 = CX[winno]-XC[winno]+OX[winno];
segs[4].y2 = CY[winno]+YD[winno]+OY[winno];
segs[5].x1 = CX[winno]+YA[winno]+OX[winno];
segs[5].y1 = CY[winno]-XB[winno]+OY[winno];
segs[5].x2 = CX[winno]+YC[winno]+OX[winno];
segs[5].y2 = CY[winno]-XD[winno]+OY[winno];
segs[6].x1 = CX[winno]+XA[winno]+OX[winno];
segs[6].y1 = CY[winno]+YB[winno]+OY[winno];
segs[6].x2 = CX[winno]+XC[winno]+OX[winno];
segs[6].y2 = CY[winno]+YD[winno]+OY[winno];
segs[7].x1 = CX[winno]+YA[winno]+OX[winno];
segs[7].y1 = CY[winno]+XB[winno]+OY[winno];
segs[7].x2 = CX[winno]+YC[winno]+OX[winno];
segs[7].y2 = CY[winno]+XD[winno]+OY[winno];
XDrawSegments(display,window[winno],window_gcs[winno],
segs, 8);
X1[winno]= (X1[winno] + XV1[winno]) % M[winno];
Y1[winno]= (Y1[winno] + YV1[winno]) % M[winno];
X2[winno]= (X2[winno] + XV2[winno]) % M[winno];
Y2[winno]= (Y2[winno] + YV2[winno]) % M[winno];
}
if (!refreshcount[winno] && intervals[winno])
XFlush(display);
itercount[winno]++;
if (!rndm(500L,winno)) {
if (doroot) {
int x,y,w,h;
i = winno % rootx;
j = winno / rootx;
w = ww / rootx;
h = wh / rooty;
x = i * w;
y = j * h;
if (i == rootx-1) w=0;
if (j == rooty-1) h=0;
XClearArea(display,window[winno],x,y,w,h,False);
}
else XClearWindow(display,window[winno]);
refreshcount[winno]=0;
itercount[winno]=0;
randombase[winno][0]=randomseed[winno][0];
randombase[winno][1]=randomseed[winno][1];
randombase[winno][2]=randomseed[winno][2];
randomize_state_vars(winno);
}
winno=scheduler();
if (!refreshcount[winno] && dynamic_colors &&
!rndm((long)(800/numcolors),-1)) randomize_color();
if (XCheckMaskEvent(display,~0L,&event)==True) handle_event(&event);
}
XNextEvent(display,&event);
handle_event(&event);
}
}
randomize_color()
{
XColor color;
color.pixel = palette[rndm((long)numcolors,-1)];
color.red = rndm(65535L,-1);
color.green = rndm(65535L,-1);
color.blue = rndm(65535L,-1);
color.flags = DoRed|DoGreen|DoBlue;
XStoreColor(display, DefaultColormap(display,screen), &color);
}
randomize_colors()
{
int i;
XColor color[NCOLORS];
for (i=0; i<numcolors; i++) {
color[i].pixel = palette[i];
color[i].red = rndm(65535L,-1);
color[i].green = rndm(65535L,-1);
color[i].blue = rndm(65535L,-1);
color[i].flags = DoRed|DoGreen|DoBlue;
}
XStoreColors(display, DefaultColormap(display,screen), color, numcolors);
}
handle_event(event)
XEvent *event;
{
int i;
if (event->type==ConfigureNotify) {
for (i=0; i<nwindows; i++) {
if (event->xconfigure.window==window[i]) {
int dorandom=0;
if (qix) {
if (CX[i] != event->xconfigure.width ||
CY[i] != event->xconfigure.height) {
XClearWindow(display,event->xconfigure.window);
refreshcount[i]=0;
itercount[i]=0;
randombase[i][0]=randomseed[i][0];
randombase[i][1]=randomseed[i][1];
randombase[i][2]=randomseed[i][2];
dorandom=1;
}
CX[i] = event->xconfigure.width;
CY[i] = event->xconfigure.height;
}
else {
int dorandom=0;
if (CX[i] != event->xconfigure.width/2 ||
CY[i] != event->xconfigure.height/2) {
XClearWindow(display,event->xconfigure.window);
refreshcount[i]=0;
itercount[i]=0;
randombase[i][0]=randomseed[i][0];
randombase[i][1]=randomseed[i][1];
randombase[i][2]=randomseed[i][2];
dorandom=1;
}
CX[i] = event->xconfigure.width/2;
CY[i] = event->xconfigure.height/2;
M[i] = (CX[i]>CY[i]) ? CX[i] : CY[i];
M[i] = M[i] ? M[i] : 1;
}
if (dorandom) randomize_state_vars(i);
if (nclips) {
int j;
for (j=0; j<nclips; j++) {
cliplist[j].x = (int)((double)event->xconfigure.width *
clips[j].x + .5);
cliplist[j].y = (int)((double)event->xconfigure.height *
clips[j].y + .5);
cliplist[j].width = (int)((double)event->xconfigure.width *
clips[j].width + .5);
cliplist[j].height = (int)((double)event->xconfigure.height *
clips[j].height + .5);
}
XSetClipRectangles(display, window_gcs[i], 0, 0,
cliplist, nclips, Unsorted);
}
break;
}
}
}
else if (event->type==MapNotify) {
for (i=0; i<nwindows; i++) {
if (event->xmap.window==window[i]) {
refreshcount[i]=0;
itercount[i]=0;
randombase[i][0]=randomseed[i][0];
randombase[i][1]=randomseed[i][1];
randombase[i][2]=randomseed[i][2];
randomize_state_vars(i);
break;
}
}
}
else if (event->type==Expose) {
for (i=0; i<nwindows; i++) {
if (doroot) {
int x,y,w,h,ix,iy;
ix = i % rootx;
iy = i / rootx;
w = ww / rootx;
h = wh / rooty;
x = ix * w;
y = iy * h;
if (ix != rootx-1 && event->xexpose.x >= x+w ||
event->xexpose.x + event->xexpose.width < x ||
iy != rooty-1 && event->xexpose.y >= y+h ||
event->xexpose.y + event->xexpose.height < y)
continue;
}
if (event->xexpose.window==window[i]) {
refreshcount[i] += itercount[i];
itercount[i] = 0;
randomseed[i][0] = randombase[i][0];
randomseed[i][1] = randombase[i][1];
randomseed[i][2] = randombase[i][2];
randomize_state_vars(i);
if (!doroot) break;
}
}
}
else if (event->type==VisibilityNotify) {
for (i=0; i<nwindows; i++) {
if (event->xvisibility.window==window[i]) {
if (visible[i] &&
event->xvisibility.state == VisibilityFullyObscured) {
visible[i]=0;
nvisible--;
}
else if (!visible[i] &&
event->xvisibility.state != VisibilityFullyObscured) {
visible[i]=1;
nvisible++;
}
break;
}
}
}
}
randomize_state_vars(i)
int i;
{
XGCValues values;
if (qix) {
X1[i] = (CX[i]>10) ? rndm((long)(CX[i]-10),i)+5 : 5;
X2[i] = (CX[i]>10) ? rndm((long)(CX[i]-10),i)+5 : 5;
Y1[i] = (CY[i]>10) ? rndm((long)(CY[i]-10),i)+5 : 5;
Y2[i] = (CY[i]>10) ? rndm((long)(CY[i]-10),i)+5 : 5;
XV1[i] = rndm(12L,i)+1;
XV2[i] = rndm(12L,i)+1;
values.foreground = palette[rndm((long)numcolors,i)];
XChangeGC(display, window_gcs[i], GCForeground, &values);
}
else {
X1[i] = rndm((long)M[i],i) + 1;
X2[i] = rndm((long)M[i],i) + 1;
Y1[i] = rndm((long)X1[i],i);
Y2[i] = rndm((long)X2[i],i);
XV1[i] = rndm(7L,i)-3;
XV2[i] = rndm(7L,i)-3;
YV1[i] = rndm(7L,i)-3;
YV2[i] = rndm(7L,i)-3;
values.foreground = palette[rndm((long)numcolors,i)];
XChangeGC(display, window_gcs[i], GCForeground, &values);
}
}
usage()
{
int i,j,spaces,xloc;
static char *options[] = {
"[-bd <border>]",
"[-bg <background>]",
"[-bstore]",
"[-bw <borderwidth>]",
"[-clip x,y,w,h[,x,y,w,h[,x,y,w,h]]]",
"[-colors <color1>[,<color2>[,...]]]",
"[-delay <msec>]",
"[-display <displayname>]",
"[-geometry <geometry>]",
"[-icondelay <msec>]",
"[-iconic]",
"[-mono]",
"[-mult <number>]",
"[-qix]",
"[-r]",
"[-randomcolor]",
"[-refresh]"
};
(void)fprintf(stderr,"Usage: %s", progname);
spaces=strlen(progname)+7;
xloc=spaces;
for (j=0; j<(sizeof(options)/sizeof(char *)); j++) {
if (xloc+strlen(options[j]) > 78) {
putc('\n',stderr);
for (i = 0; i<spaces; i++) (void)putc(' ',stderr);
xloc=spaces;
}
xloc += strlen(options[j])+1;
fprintf(stderr," %s",options[j]);
}
putc('\n',stderr);
exit(1);
}
fatalerror(s1,s2)
char *s1,*s2;
{
(void)fprintf(stderr,"%s: ",progname);
(void)fprintf(stderr,s1,s2);
(void)putc('\n',stderr);
exit(1);
}
long rndm(maxval,element)
long maxval;
int element;
{
long lrand48();
int sr1=15, sr2=16;
long mv=maxval;
while (mv > 0x8000L) {
sr1++;
sr2--;
mv >>= 1;
}
if (element == -1) return ((lrand48() >> sr1) * maxval) >> sr2;
return ((nrand48(randomseed[element]) >> sr1) * maxval) >> sr2;
}
allocate_arrays(nwin)
unsigned nwin;
{
int i;
if ((window=(Window *)calloc(nwin,sizeof(Window))) == NULL) return 0;
if ((window_gcs=(GC *)calloc(nwin,sizeof(GC))) == NULL) return 0;
if ((CX=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((CY=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((OX=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((OY=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((visible=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((X1=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((Y1=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((X2=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((Y2=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((XV1=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((XV2=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((schedule=(struct timeval *)calloc(nwin,sizeof(struct timeval))) == NULL)
return 0;
if ((intervals=(long *)calloc(nwin,sizeof(long))) == NULL) return 0;
if ((randomseed=(unsigned short **)calloc(nwin,3*sizeof(short))) == NULL)
return 0;
if ((randombase=(unsigned short **)calloc(nwin,3*sizeof(short))) == NULL)
return 0;
for (i=0; i<nwin; i++) {
randombase[i][0] = randomseed[i][0] = (unsigned short)rndm(0xffffL,-1);
randombase[i][1] = randomseed[i][1] = (unsigned short)rndm(0xffffL,-1);
randombase[i][2] = randomseed[i][2] = (unsigned short)rndm(0xffffL,-1);
}
if ((refreshcount=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((itercount=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if (qix) return 1;
if ((M=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((YV1=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((YV2=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((XA=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((YA=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((XB=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((YB=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((XC=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((YC=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((XD=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
if ((YD=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
return 1;
}
int scheduler()
{
struct timeval currtime, *nextalarm, *alarmindex;
struct timezone tzp;
long interval;
int i;
/* Has root-mode operation gotten a die signal? */
if (killed) refreshrootquit();
/* Look for any windows performing refresh... immediate return if found */
for (i=0; i<nwindows; i++) if (refreshcount[i] && visible[i]) {
refreshcount[i]--;
return i;
}
/* Get current time */
(void)gettimeofday(&currtime, &tzp);
/* Find earliest alarm due */
alarmindex = nextalarm = schedule;
for (i=1; i<nwindows; i++) {
if (visible[++alarmindex - schedule] &&
( alarmindex->tv_sec < nextalarm->tv_sec ||
alarmindex->tv_sec == nextalarm->tv_sec &&
alarmindex->tv_usec < nextalarm->tv_usec ))
nextalarm = alarmindex;
}
/* If the next alarm is not past due, sleep until it comes due */
if (currtime.tv_sec < nextalarm->tv_sec ||
currtime.tv_sec == nextalarm->tv_sec &&
currtime.tv_usec < nextalarm->tv_usec) {
struct timeval timeout;
int fd=ConnectionNumber(display), readfds;
timeout.tv_sec = nextalarm->tv_sec - currtime.tv_sec;
timeout.tv_usec = nextalarm->tv_usec - currtime.tv_usec;
if (timeout.tv_usec < 0) {
timeout.tv_sec -= 1L;
timeout.tv_usec += 1000000L;
}
readfds = 1<<fd;
if (killed) refreshrootquit();
(void)select(fd+1, &readfds, NULL, NULL, &timeout);
/* Recompute current time */
(void)gettimeofday(&currtime, &tzp);
}
/* Set next alarm to current time + interval. If more than one window
is visible, introduce a random variance so update is staggered. */
interval = intervals[nextalarm-schedule];
if (nvisible > 1) interval += rndm(interval/5L,-1) - interval/10L;
nextalarm->tv_sec = currtime.tv_sec + interval/1000;
nextalarm->tv_usec = currtime.tv_usec + (interval%1000)*1000;
if (nextalarm->tv_usec >= 1000000) {
nextalarm->tv_sec += 1;
nextalarm->tv_usec -= 1000000;
}
/* Return index of next alarm */
return nextalarm-schedule;
}