|
|
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 x
Length: 19200 (0x4b00)
Types: TextFile
Names: »xmoire.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/X/Xmoire/xmoire.c«
/*
* xmoire.c
* Copyright 1988 The Student Information Processing Board (SIPB)
* Written by Mark W. Eichin, begun April 13, 1988.
*
* All distribution rights hereby granted, as long as
* 1) you do not charge for this code or derivatives of it
* without my consent;
* 2) you leave this header comment in place unchanged;
* 3) you attempt to inform myself <eichin@athena.mit.edu> or the
* Board <sipb@athena.mit.edu> of any changes or improvements.
*
* The idea for this program comes from a public domain `screensaver'
* for the Mac labeled:
* * * "Moire V1.1 by John Lim"
* * * "Algorithm by Anonymous"
* * * "Portions (c) John Lim and THINK Tech."
* After watching it for a short time, it was obvious how to implement
* a similar (if not identical) program; however, all the code here is
* my original work, its purpose only being to provide the same look
* and feel under X11. Due to the eminent simplicity of the concept, I
* feel I am not stepping on any toes by creating this. In any case,
* it is a different window system, and the user interface differs in
* certain ways (unlabeled keys do NOT produce rectangles; space bar
* does NOT produce an instructional message (yet); curly braces are
* used to control operation speed, not 0-9) and that this alone may
* be sufficient to call the look and feel different. The people here
* who have found it most similar included at least one person who
* despised the original, and wanted me to port Pyro instead...
*/
/*
* Mutable comments follow:
* $Header: xmoire.c,v 1.1 88/04/15 12:51:10 eichin Exp $
* $Log: xmoire.c,v $
* Revision 1.1 88/04/15 12:51:10 eichin
* Initial revision
*
*/
/*
* Things to add (may be superseded by the above logs):
* geometry spec for the mousetrap window
* password locking (or integration with xscreensaver)
* Things *not* to add (don't waste time on:)
* number keys to control speed
*/
#include <X11/Xlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <strings.h>
Display *dpy;
#define SIZ 51
/* SIZ is for alloc'ing */
#define MAXSIZ SIZ-1
/* valid indices are <= MAXSIZ, so if (x>MAXSIZ) x=0; */
#define INITSIZ 5
#define MINSIZ 2
#define MAXTIM 1000000
#define MINTIM 1000
#define SLEEPTIME 50000
#define XR 5
#define XRM 1
#define YR 5
#define YRM 1
#define CHCHANCE (25 - 1)
void init_random()
{
/*
* We really don't need a VERY random seed, since we are only
* adjusting the vectors, and that only needs about 4 bits/sample of
* magnitude change. Low part of time would be ok, I suppose. So
* what?
*/
srandom(getpid());
}
/*
* These are global, so they don't have to be passed between main and
* the draw/undraw procs. They should at least be made local to a
* smaller file/set of procs... for now, they just sit here.
*
* The routine simply bounces a bounding box around the screen, and
* then draws the correct image within it; these are the origin and
* sides of the bounding box.
*/
int xx[SIZ], yy[SIZ], xs[SIZ], ys[SIZ];
void draw(), undraw();
/*
* pic is all the possible returns from a keyboard entry; it is also
* all of the possible shapes (a subset.)
*/
typedef enum _pic {
RECT, CIRC, PENT, DIAM, LEFT, RIGHT, HGLS, PLUS, CROSS, VEE, TRI,
PUNT, LONG, SHORT, FAST, SLOW,
} pic;
/* HGLS == HourGlass, also H key... */
/*
* opts are the keys pressed, and popts are the values returned from
* char2pic for those keys.
*/
char opts[] = "ropd/\\h+xvtQ][}{";
pic popts[] = {
RECT, CIRC, PENT, DIAM, LEFT, RIGHT, HGLS, PLUS, CROSS, VEE, TRI,
PUNT, LONG, SHORT, FAST, SLOW,
};
pic char2pic(in,old)
char in;
pic old;
{
char *where;
where = index(opts, in);
return(where?popts[where-opts]:old);
}
/*
* again, it is easier to make these global than to pass them to the
* draw/undraw routines all the time.
*/
GC gc, ungc;
Window win;
/*
* This could stand to be broken down a bit more. But then, none of
* the important bottlenecks are here... far too much time was spent
* writing it in the first place to justify rewriting it. Unless of
* course we can merge it into the other xscreensaver...
*/
main (argc, argv)
int argc;
char **argv;
{
Window rtwin, scanwin; /* root and mouse entry windows */
int scrn;
XGCValues gc_val;
pic pictype = RECT; /* current displayed picture */
int siz = INITSIZ;
int start, end, ostart;
int swid, shi;
int xxoff, yyoff, xsoff, ysoff;
unsigned long vmask;
XSetWindowAttributes wvals;
int timeout, interval, blanking, exposures; /* screen saver parameters */
unsigned micr = SLEEPTIME; /* microseconds between motion */
init_random(); /* start random number generator */
dpy = XOpenDisplay("");
scrn = DefaultScreen(dpy);
rtwin = RootWindow(dpy, scrn);
swid = DisplayWidth(dpy, scrn);
shi = DisplayHeight(dpy, scrn);
wvals.override_redirect = True;
wvals.background_pixel = BlackPixel(dpy, scrn);
vmask = CWOverrideRedirect | CWBackPixel;
/*
* Creating the drawing window to fill the whole screen and get mapped
* later on.
*/
win = XCreateWindow(dpy, rtwin, /* excitement window */
0, 0, /* origin */
swid, shi, /* size */
0, /* border width */
0, /* depth from parent */
InputOutput, /* class */
CopyFromParent, /* visual */
vmask, &wvals);
#define BOXSIZ 50
vmask = CWOverrideRedirect;
/*
* Creating the window to catch the mouse motion, into and out of the
* ``corner''; this perhaps ought to be smaller, and should parse the
* geometry specification from somwhere as well.
*/
scanwin = XCreateWindow(dpy, rtwin, /* toggle window */
swid-BOXSIZ, 0, /* origin */
BOXSIZ, BOXSIZ, /* size */
0, /* border width */
0, /* depth from parent */
InputOnly, /* class */
CopyFromParent, /* visual */
vmask, &wvals);
/*
* The GC's for draw and undraw. The method used is to draw the first
* shapes, then erase the last one and repeat.
*/
gc_val.foreground = (unsigned long) WhitePixel (dpy, scrn);
gc_val.background = (unsigned long) BlackPixel (dpy, scrn);
gc = XCreateGC (dpy, win, GCForeground|GCBackground, &gc_val);
gc_val.foreground = (unsigned long) BlackPixel (dpy, scrn);
gc_val.background = (unsigned long) WhitePixel (dpy, scrn);
ungc = XCreateGC (dpy, win, GCForeground|GCBackground, &gc_val);
start = 0; /* duplicated later... */
xx[start] = 0; /* initial vals, should read them? */
yy[start] = 0;
xs[start] = 100;
ys[start] = 100;
xxoff = 3;
yyoff = 3;
xsoff = 0;
ysoff = 0;
for (;;)
{
int sizoff;
/*
* First we deal with the selector window, then we fall into the
* drawing window, and then back to the selector window.
*/
XSelectInput(dpy, scanwin, EnterWindowMask);
XMapWindow(dpy, scanwin);
for (;;)
{
XEvent event;
XNextEvent(dpy, &event);
if(event.type == EnterNotify)
{
break; /*
* they came in to the corner zone...
* interesting frob here might be to
* check the position on an angle.
*/
}
}
/*
* Nuke the screensaver, for now WE are the screensaver. There
* really should be a ``screensaver activated'' event of some
* sort, so we could trigger on this too...
*/
XGetScreenSaver(dpy, &timeout, &interval, &blanking, &exposures);
XSetScreenSaver(dpy, /* all these are zero, but lets do it right */
DisableScreenSaver,
DisableScreenInterval,
DontPreferBlanking,
DontAllowExposures); /* disable screen saver */
/*
* Now wait for the full-screen drawing window to show up
*/
XSelectInput(dpy, win, ExposureMask);
XMapRaised(dpy, win); /* put it on top */
/*
* Turn off entry, just notice when the mouse exits. To make it
* appear on top again, and to allow other events to leak
* through, reparent the mousetrap window into the drawing
* window.
*/
XSelectInput(dpy, scanwin, LeaveWindowMask);
XReparentWindow(dpy, scanwin, win, swid-BOXSIZ, 0);
/*
* always start with one, but make end negative so that we don't
* start erasing things until we have enough of them there.
*/
start = 0;
end = start - siz;
for (;;)
{
XEvent event;
XNextEvent(dpy, &event);
if(event.type == Expose)
{
break; /*
* same type of loop as above, but
* this time it is waiting for the
* mapping to finish. This could be
* made MUCH prettier. */
}
}
/*
* Now start looking for key presses to change the display. Note
* that we could just look at scanwin (we know we are in it,
* right?) but this way is more fun...
*/
XSelectInput(dpy, win, KeyPressMask);
for (;;)
{
usleep(micr); /* bored with the X server, sleeping... */
if(XPending(dpy)) /* Got one! */
{
XEvent event;
XNextEvent(dpy, &event);
if(event.type == KeyPress) /* Could listen to both windows... */
{
char input;
pic tmppic;
/* just get the first char of the keypress */
(void)XLookupString(&event.xkey, &input, 1, NULL, NULL);
/* convert it to a picture index */
tmppic = char2pic(input, pictype);
if (tmppic == pictype)
continue; /* punt if already running that one */
if (tmppic == PUNT) /* get out, should check passwd? */
{
break; /*
* actually a relic from before
* mousing stuff worked.
*/
}
if (tmppic == LONG) /* make the pattern longer */
{
sizoff = 1;
continue;
}
if (tmppic == SHORT) /* make it shorter */
{
sizoff = -1;
continue;
}
if (tmppic == FAST) /* update faster */
{
micr <<= (micr>=MAXTIM)?0:1;
continue;
}
if (tmppic == SLOW) /* update slower */
{
micr >>= (micr<=MINTIM)?0:1;
continue;
}
while(start != end) /* ok, it IS a new pattern, wipe old */
{
undraw(pictype, end);
end++;
if(end > MAXSIZ) end = 0;
}
/* set up as a fresh start for the new one */
xx[0] = xx[start]; xs[0] = xs[start];
yy[0] = yy[start]; ys[0] = ys[start];
start = 0;
end = start - siz;
pictype = tmppic;
}
else if (event.type == LeaveNotify)
{
/* this is the REAL escape method... */
break; /* getting out... Password? */
}
continue;
}
if(sizoff == -1)
{
if(siz > MINSIZ)
{
siz--;
undraw(pictype, end);
end++;
if(end > MAXSIZ) end = 0;
}
sizoff = 0;
}
/* else */
{
if (sizoff == 0 || siz >= MAXSIZ)
{
undraw(pictype, end);
end++;
if(end > MAXSIZ) end = 0;
}
if(sizoff == 1 && siz <= MAXSIZ)
{
siz++;
}
sizoff = 0;
}
draw(pictype, start); /* actually draw a stage */
/*
* Now for the common box incrementing code...
*/
ostart = start++;
if(start >= SIZ) start = 0;
/* jump the bounding box a step... */
xx[start] = xx[ostart] + xxoff;
xs[start] = xs[ostart] + xsoff;
yy[start] = yy[ostart] + yyoff;
ys[start] = ys[ostart] + ysoff;
if(xx[start]+xs[start] + xxoff + xsoff > swid) /* past right edge */
{
if(xxoff>0) xxoff = -xxoff;
if(xsoff>0) xsoff = -xsoff;
}
if(xx[start]+xxoff < 0) /* past left edge */
{
xxoff = -xxoff;
}
if(yy[start]+ys[start] + yyoff + ysoff > shi) /* below bottom */
{
if(yyoff>0) yyoff = -yyoff;
if(ysoff>0) ysoff = -ysoff;
}
if(yy[start]+yyoff < 0) /* above top */
{
yyoff = -yyoff;
}
if(xs[start]+xsoff < 0) /* too narrow */
{
xsoff = - xsoff;
}
if(ys[start]+ysoff < 0) /* too short */
{
ysoff = - ysoff;
}
if(!small_random(0,CHCHANCE)) /* 1:20 chance of actual change */
{
if(small_random(0,1)) /* 1:2 choice... */
{
xxoff =
small_random((xxoff>0?XRM:-XR),
(xxoff>0?XR:-XRM));
}
else
{
yyoff =
small_random((yyoff>0?YRM:-YR),
(yyoff>0?YR:-YRM));
}
}
if(!small_random(0,CHCHANCE))
{
if(small_random(0,1)) /* 1:2 choice... */
{
xsoff =
2*small_random((xsoff>0?XRM:-XR),
(xsoff>0?XR:-XRM));
}
else
{
ysoff =
2*small_random((ysoff>0?YRM:-YR),
(ysoff>0?YR:-YRM));
}
}
}
/* put the special box back in the root window */
XReparentWindow(dpy, scanwin, rtwin, swid-BOXSIZ, 0);
/* turn the drawing window off */
XUnmapWindow(dpy, win); /*
* hide the graphics, and fall up to
* the top.
*/
/* restore the screensaver to the old defaults */
XSetScreenSaver(dpy, timeout, interval, blanking, exposures);
}
}
void undraw(ptype, ind)
pic ptype;
int ind;
{
switch(ptype)
{
case RECT:
if (ind>=0)
{
XDrawRectangle(dpy, win, ungc,
xx[ind], yy[ind],
xs[ind], ys[ind]);
}
break;
case CIRC:
if(ind>=0) XDrawArc(dpy, win, ungc,
xx[ind], yy[ind],
xs[ind], ys[ind],
0, 360*64);
break;
case PENT:
if(ind>=0)
{
XPoint xps[6];
xps[5].x = xps[0].x = xx[ind]+xs[ind]/2;
xps[5].y = xps[0].y = yy[ind];
xps[2].x = xx[ind];
xps[2].y = yy[ind]+ys[ind]/2;
xps[3].x = xx[ind]+xs[ind];
xps[3].y = yy[ind]+ys[ind]/2;
xps[4].x = xx[ind]+xs[ind]/3;
xps[4].y = yy[ind]+ys[ind];
xps[1].x = xx[ind]+2*xs[ind]/3;
xps[1].y = yy[ind]+ys[ind];
XDrawLines(dpy, win, ungc, xps, 6, CoordModeOrigin);
}
break;
case DIAM:
if(ind>=0)
{
XPoint xps[5];
xps[4].x = xps[0].x = xx[ind]+xs[ind]/2;
xps[4].y = xps[0].y = yy[ind];
xps[1].x = xx[ind]+xs[ind];
xps[1].y = yy[ind]+ys[ind]/2;
xps[2].x = xx[ind]+xs[ind]/2;
xps[2].y = yy[ind]+ys[ind];
xps[3].x = xx[ind];
xps[3].y = yy[ind]+ys[ind]/2;
XDrawLines(dpy, win, ungc, xps, 5, CoordModeOrigin);
}
break;
case LEFT: /* / */
if(ind>=0) XDrawLine(dpy, win, ungc,
xx[ind], yy[ind]+ys[ind],
xx[ind]+xs[ind], yy[ind]);
break;
case RIGHT: /* \ */
if(ind>=0) XDrawLine(dpy, win, ungc,
xx[ind], yy[ind],
xx[ind]+xs[ind], yy[ind]+ys[ind]);
break;
case HGLS:
if(ind>=0)
{
XPoint xps[5];
xps[4].x = xps[0].x = xx[ind];
xps[4].y = xps[0].y = yy[ind];
xps[1].x = xx[ind]+xs[ind];
xps[1].y = yy[ind];
xps[2].x = xx[ind];
xps[2].y = yy[ind]+ys[ind];
xps[3].x = xx[ind]+xs[ind];
xps[3].y = yy[ind]+ys[ind];
XDrawLines(dpy, win, ungc, xps, 5, CoordModeOrigin);
}
break;
case PLUS:
if(ind>=0)
{
XDrawLine(dpy, win, ungc, /* - */
xx[ind], yy[ind]+ys[ind]/2,
xx[ind]+xs[ind], yy[ind]+ys[ind]/2);
XDrawLine(dpy, win, ungc, /* | */
xx[ind]+xs[ind]/2, yy[ind],
xx[ind]+xs[ind]/2, yy[ind]+ys[ind]);
}
break;
case CROSS:
if(ind>=0)
{
XDrawLine(dpy, win, ungc, /* / */
xx[ind], yy[ind]+ys[ind],
xx[ind]+xs[ind], yy[ind]);
XDrawLine(dpy, win, ungc, /* \ */
xx[ind], yy[ind],
xx[ind]+xs[ind], yy[ind]+ys[ind]);
}
break;
case VEE:
if(ind>=0)
{
XDrawLine(dpy, win, ungc, /* \ */
xx[ind], yy[ind],
xx[ind]+xs[ind]/2, yy[ind]+ys[ind]);
XDrawLine(dpy, win, ungc, /* / */
xx[ind]+xs[ind], yy[ind],
xx[ind]+xs[ind]/2, yy[ind]+ys[ind]);
}
break;
case TRI:
if(ind>=0)
{
XPoint xps[4];
xps[3].x = xps[0].x = xx[ind]+xs[ind]/2;
xps[3].y = xps[0].y = yy[ind];
xps[1].x = xx[ind]+xs[ind];
xps[1].y = yy[ind]+ys[ind];
xps[2].x = xx[ind];
xps[2].y = yy[ind]+ys[ind];
XDrawLines(dpy, win, ungc, xps, 4, CoordModeOrigin);
}
break;
/* , TRI, */
default:
break;
}
}
void draw(ptype, ind)
pic ptype;
int ind;
{
switch(ptype)
{
case RECT:
XDrawRectangle(dpy, win, gc,
xx[ind], yy[ind],
xs[ind], ys[ind]);
break;
case CIRC:
XDrawArc(dpy, win, gc,
xx[ind], yy[ind],
xs[ind], ys[ind],
0, 360*64);
break;
case PENT:
/*
* Pentagon: five points.
* Top center,
* upper left/right (same y, diff. x)
* lower left/right (same y, diff. x)
* This should fit in a rectangle...
* tc = (xx+xs/2, yy)
* ul = (xx, yy+ys/2) ur = (xx+xs, yy+ys/2)
* ll = (xx+xs/3, yy+ys) lr = (xx+2xs/3, yy+ys)
* draw tc->lr->ul->ur->ll->tc.
*/
{
XPoint xps[6];
xps[5].x = xps[0].x = xx[ind]+xs[ind]/2;
xps[5].y = xps[0].y = yy[ind];
xps[2].x = xx[ind];
xps[2].y = yy[ind]+ys[ind]/2;
xps[3].x = xx[ind]+xs[ind];
xps[3].y = yy[ind]+ys[ind]/2;
xps[4].x = xx[ind]+xs[ind]/3;
xps[4].y = yy[ind]+ys[ind];
xps[1].x = xx[ind]+2*xs[ind]/3;
xps[1].y = yy[ind]+ys[ind];
XDrawLines(dpy, win, gc, xps, 6, CoordModeOrigin);
}
break;
case DIAM:
{
XPoint xps[5];
xps[4].x = xps[0].x = xx[ind]+xs[ind]/2;
xps[4].y = xps[0].y = yy[ind];
xps[1].x = xx[ind]+xs[ind];
xps[1].y = yy[ind]+ys[ind]/2;
xps[2].x = xx[ind]+xs[ind]/2;
xps[2].y = yy[ind]+ys[ind];
xps[3].x = xx[ind];
xps[3].y = yy[ind]+ys[ind]/2;
XDrawLines(dpy, win, gc, xps, 5, CoordModeOrigin);
}
break;
case LEFT: /* / */
XDrawLine(dpy, win, gc,
xx[ind], yy[ind]+ys[ind],
xx[ind]+xs[ind], yy[ind]);
break;
case RIGHT: /* \ */
XDrawLine(dpy, win, gc,
xx[ind], yy[ind],
xx[ind]+xs[ind], yy[ind]+ys[ind]);
break;
case HGLS:
{
XPoint xps[5];
xps[4].x = xps[0].x = xx[ind];
xps[4].y = xps[0].y = yy[ind];
xps[1].x = xx[ind]+xs[ind];
xps[1].y = yy[ind];
xps[2].x = xx[ind];
xps[2].y = yy[ind]+ys[ind];
xps[3].x = xx[ind]+xs[ind];
xps[3].y = yy[ind]+ys[ind];
XDrawLines(dpy, win, gc, xps, 5, CoordModeOrigin);
}
break;
case PLUS:
XDrawLine(dpy, win, gc, /* - */
xx[ind], yy[ind]+ys[ind]/2,
xx[ind]+xs[ind], yy[ind]+ys[ind]/2);
XDrawLine(dpy, win, gc, /* | */
xx[ind]+xs[ind]/2, yy[ind],
xx[ind]+xs[ind]/2, yy[ind]+ys[ind]);
break;
case CROSS:
XDrawLine(dpy, win, gc, /* / */
xx[ind], yy[ind]+ys[ind],
xx[ind]+xs[ind], yy[ind]);
XDrawLine(dpy, win, gc, /* \ */
xx[ind], yy[ind],
xx[ind]+xs[ind], yy[ind]+ys[ind]);
break;
case VEE:
XDrawLine(dpy, win, gc, /* \ */
xx[ind], yy[ind],
xx[ind]+xs[ind]/2, yy[ind]+ys[ind]);
XDrawLine(dpy, win, gc, /* / */
xx[ind]+xs[ind], yy[ind],
xx[ind]+xs[ind]/2, yy[ind]+ys[ind]);
break;
case TRI:
{
XPoint xps[4];
xps[3].x = xps[0].x = xx[ind]+xs[ind]/2;
xps[3].y = xps[0].y = yy[ind];
xps[1].x = xx[ind]+xs[ind];
xps[1].y = yy[ind]+ys[ind];
xps[2].x = xx[ind];
xps[2].y = yy[ind]+ys[ind];
XDrawLines(dpy, win, gc, xps, 4, CoordModeOrigin);
}
break;
default:
break;
}
}
int small_random(low, high) /* low <= s_r <= high */
int low, high;
{
long r;
r = random();
return((r % (high-low+1))+low);
}