danny@humus.huji.ac.il (09/03/88)
Xsmoke is a program that generates a neet pattern, and together with xpalet makes weird things on a colour screen. It runs on a Sun-3/110C. and soon I will test it on an Apollo. I would be greatful to receive back comments/fixes, since this is a 'learning programme' for me, and though it works, there are many 'black magic' tricks that I'm not certain about. This program also causes the appearance of a bug that has been hunting me for some time. It concerns the sun running os-3.4, and anybody else! The tcp/ip gets stuck. When I run xsmoke on another cpu (ie Gould (4.3Bsd) or IBM-RT/PC(4.3)), it 'sometimes' hangs in 'XPutImage', and in most of the Yellow Pages updates too. (Sorry, but xpalet is still 'under developement', to be released soon, and xsmoke is unfinished) #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Makefile # xsmoke.1 # xsmoke.c # GetArgs.c # This archive created: Sat Sep 3 14:26:53 1988 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else cat << \SHAR_EOF > 'Makefile' LIB=GetArgs.o all: xsmoke xpalet xsmoke: xsmoke.o $(LIB) cc -o xsmoke xsmoke.o $(LIB) -lX xpalet: xpalet.o $(LIB) cc -o xpalet xpalet.o $(LIB) -lX clean: rm -f xsmoke xpalet *.o *~ core SHAR_EOF fi if test -f 'xsmoke.1' then echo shar: "will not over-write existing file 'xsmoke.1'" else cat << \SHAR_EOF > 'xsmoke.1' .TH XSMOKE 1 .SH NAME xsmoke - smoking clover program .SH SYNOPSIS .B xsmoke [x11 options] [-colors n] .SH DESCRIPTION This program runs the .B "smoking clover" algorithm which was deported from M.I.T by Phil Agre. It initializes a square window by drawing vectors from the center of the area to each point on the perimiter. The value of each pixel is set to the number of vectors crossing it mod the number of colors --the default is all the color available-- which can be set with .B "-colors n". This results in a rectangular moire pattern. .SH AUTHOR Revived by Daniel Braniss, moir pattern Algorithm supplied by Phil Agre. .SH "SEE ALSO" xpalet(1) .SH BUGS I see no connection between the program's name and output. SHAR_EOF fi if test -f 'xsmoke.c' then echo shar: "will not over-write existing file 'xsmoke.c'" else cat << \SHAR_EOF > 'xsmoke.c' #ifndef lint static char *rcsid = "$Header: xsmoke.c,v 1.1 88/09/02 21:07:43 danny Locked $"; #endif #include <stdio.h> #include <X11/Xlib.h> /* | Make SMOKE! */ #define USAGE "[X11 options] [-colors n]" int colors, size; char *pic; char *ST_display; char *ST_geometry; char *ST_fg; char *ST_bg; char *ST_fn; char *pname; int ST_reverse; Display *dpy; int screen; XImage IMAGE, *image; GC gc; int debug; Window SetupWindow(); int dontuse; main(cc, vv) char **vv; { Window wd; int ncolors = 0; cc = GetArgs(cc, vv); while(cc-- > 0) { char *p = *vv++; if(strcmp(p, "-colors") == 0) { if(cc > 0) { ncolors = atoi(*vv++); cc--; } } else if(strcmp(p, "-dontuse") == 0) { if(cc > 0) { dontuse = atoi(*vv++); cc--; } } else if(strcmp(p, "-d") == 0) debug++; else { fprintf(stderr, "Usage: %s %s\n", pname, USAGE); exit(-1); } } dpy = XOpenDisplay(ST_display); if(dpy == 0) exit(-1); screen = DefaultScreen(dpy); wd = SetupWindow(512, 512, &pic); size = image->height; colors -= dontuse; if((ncolors > 0) && ((ncolors) < colors)) colors = ncolors; if(debug) fprintf(stderr, "using %d colors\n", colors); MoirPattern(wd, image, colors); loop(wd); } /* | Init the Moir pattern */ MoirPattern(wd, image, colors) XImage *image; { char *pic; int size; int *rline; int x, y, alpha; int center; size = image->height; pic = image->data; rline = (int *) malloc(size * sizeof(int)); center= size/2; /* | 1/8 of the square; */ for(x = 0; x < center; x++) { /* | alpha is the length of a cross section of the triangle */ alpha = x + 1; bzero(rline, sizeof(int)*alpha); for(y = 0; y < center; y++) rline[(alpha * y) / center]++; /* | Now make 8 copies */ for(y = 0; y < alpha; y++) { int v = map_color(rline[y], colors); char *p; p = &pic[(center - y) * size]; p[x + center] = p[center - x] = v; p = &pic[(center - x) * size]; p[y + center] = p[center - y] = v; p = &pic[(center + y) * size]; p[x + center] = p[center - x] = v; p = &pic[(center + x) * size]; p[y + center] = p[center - y] = v; } } /* |now display it in 4 chunks */ XPutImage(dpy, wd, gc, image, center, 0, center, 0, center, center); XPutImage(dpy, wd, gc, image, 0, center, 0, center, center, center); XPutImage(dpy, wd, gc, image, center, center, center, center, center, center); XPutImage(dpy, wd, gc, image, 0, 0, 0, 0, center, center); } map_color(c, ncolors) { static int off = 0; if(off == 0) { int seed = time(0); srand(seed); off = rand(); } c += off; c %= (ncolors-dontuse); return c+dontuse; } /* | All that has to do with creating the image */ #include <X11/Xutil.h> #include <X11/cursorfont.h> Window SetupWindow(w, h, pic) char **pic; { XGCValues xGCv; XWindowAttributes ATR; XSetWindowAttributes attr; Window wd; Visual *visual; XVisualInfo vinfo, *vinfos; wd = XCreateSimpleWindow(dpy, RootWindow(dpy, screen), 0, 0, w, h, 0, BlackPixel(dpy, screen), WhitePixel(dpy, screen)); if(wd == 0) { fprintf(stderr, "cannot create window!\n"); return 0; } XStoreName(dpy, wd, pname); EXPose(dpy, wd); XGetWindowAttributes(dpy, wd, &ATR); if(ATR.height > ATR.width) h = w = ATR.width; else w = h = ATR.height; if(!*pic && (*pic = (char *)malloc((unsigned int)(h * w))) == 0) { fprintf(stderr, "Not enough memory for picture!\n"); exit(-1); } /* | find out if it's colour */ colors = ATR.visual->map_entries; if(colors <= 2) { fprintf(stderr, "Sorry, no colours\n"); exit(-1); } image = XCreateImage(dpy, DefaultVisual(dpy, screen), DisplayPlanes(dpy, screen), ZPixmap, 0, *pic, w, w, 8, 0); if(image == NULL) { perror("XCreateImage"); exit(-1); } XMoveResizeWindow(dpy, wd, ATR.x, ATR.y, w, w); attr.override_redirect = True; attr.colormap = DefaultColormap(dpy, screen); attr.cursor = XCreateFontCursor(dpy, XC_trek); attr.background_pixel = BlackPixel(dpy, screen); XChangeWindowAttributes(dpy, wd, CWOverrideRedirect | CWColormap | CWCursor | GCBackground, &attr); xGCv.function = GXcopy; xGCv.background = (unsigned long)WhitePixel(dpy, screen); xGCv.foreground = (unsigned long)BlackPixel(dpy, screen); #define GFMask GCFunction |GCForeground | GCBackground /**/ gc = XCreateGC(dpy, wd, GFMask, &xGCv); return wd; } EXPose(dpy, wd) Display *dpy; Window *wd; { XEvent event; XExposeEvent *expose = (XExposeEvent *)&event; XSelectInput(dpy, wd, ExposureMask); XMapWindow(dpy, wd); for(;;) { XNextEvent(dpy, &event); switch((int)event.type) { case Expose: return; } } } loop(wd) Window *wd; { XEvent event; XExposeEvent *expose = (XExposeEvent *)&event; XSelectInput(dpy, wd, ButtonPressMask | ExposureMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask); fprintf(stderr, "loop entered\n"); for(;;) { XNextEvent(dpy, &event); if(debug) fprintf(stderr, "type: %d\n", (int)event.type); switch((int)event.type) { case ButtonPress: { XButtonEvent *e = (XButtonEvent *) &event; switch(e->button) { case Button1: case Button3: case Button2: return 0; }} break; case Expose: if(debug) fprintf(stderr, "Exposing %d...\n", expose->count); XPutImage(dpy, wd, gc, image, expose->x, expose->y, expose->x, expose->y, expose->width, expose->height); break; } } } SHAR_EOF fi if test -f 'GetArgs.c' then echo shar: "will not over-write existing file 'GetArgs.c'" else cat << \SHAR_EOF > 'GetArgs.c' extern char *ST_display; extern char *ST_geometry; extern char *ST_fg; extern char *ST_bg; extern char *ST_fn; extern int ST_reverse; extern char *pname; char *index(), *rindex(); GetArgs(cc, vv) char **vv; { char **V, *p, **v0; V = v0 = vv; pname = *vv++; if(p = rindex(pname, '/')) pname = ++p; *V = *vv; while(cc-- > 1) { p = *vv++; switch(*p) { case '-': if(strcmp(p, "-display") == 0) ST_display = *vv++, cc--; else if(strcmp(p, "-geometry") == 0) ST_geometry = *vv++, cc--; else if(strcmp(p, "-fg") == 0) ST_fg = *vv++, cc--; else if(strcmp(p, "-bg") == 0) ST_bg = *vv++, cc--; else if(strcmp(p, "-fn") == 0) ST_fn = *vv++, cc--; else if(strcmp(p, "-rv") == 0) ST_reverse++; else goto copy; break; case '=': ST_geometry = ++p; break; default: if(index(p, ':')) ST_display = p; else { copy: if(V < vv) *V = p; V++; } } } return V - v0; } SHAR_EOF fi exit 0 # End of shell archive