[comp.sources.x] v05i008: xfade -- demonstrate dubble buffering and font stuff, Part01/01

argv@island.uu.net (Dan Heller) (10/04/89)

Submitted-by: Dave Lemke <sun!lemke>
Posting-number: Volume 5, Issue 8
Archive-name: xfade/part01

here's an intersting little demo that might be of use to people wanting
to do colormap double buffering or playing with fonts.


Dave Lemke				ARPA: lemke@sun.com
Window Systems Group			UUCP: ucbvax!sun!lemke
Sun Microsystems, Inc.


#! /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:
#	README
#	Imakefile
#	xfade.c
#	xfade.man
#	fader
# This archive created: Tue Oct  3 15:34:56 1989
# By:	Dave Lemke (Sun Microsystems)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'README'" '(243 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^	X//' << \SHAR_EOF > 'README'
	Xxfade is based on fader, a NeWS demo written using tNt and requiring
	XX11/NeWS.
	X
	Xxfade works best with scalable fonts, but should work on any X11.
	Xit prefers to use X Logical Font Description style names (as in R3)
	Xbut will work without them.
	X
SHAR_EOF
if test 243 -ne "`wc -c < 'README'`"
then
	echo shar: "error transmitting 'README'" '(should have been 243 characters)'
fi
fi
echo shar: "extracting 'Imakefile'" '(55 characters)'
if test -f 'Imakefile'
then
	echo shar: "will not over-write existing file 'Imakefile'"
else
sed 's/^	X//' << \SHAR_EOF > 'Imakefile'
	XLOCAL_LIBRARIES = $(XLIB)
	X
	XSimpleProgramTarget(xfade)
	X
SHAR_EOF
if test 55 -ne "`wc -c < 'Imakefile'`"
then
	echo shar: "error transmitting 'Imakefile'" '(should have been 55 characters)'
fi
fi
echo shar: "extracting 'xfade.c'" '(17083 characters)'
if test -f 'xfade.c'
then
	echo shar: "will not over-write existing file 'xfade.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'xfade.c'
	X/*
	X * xfade - fade two strings in & out
	X *
	X * Dave Lemke
	X * lemke@sun.com
	X *
	X * acknowledgements to Hesh for providing the usleep() replacement
	X * and inspiring creeping featurism. 
	X */
	X
	X/*
	X * define USLEEP if you don't have it in libc
	X * define R4 if you have the MIT R4 Xlib and want full ICCCM compliance
	X *
	X * cc -O -o xfade xfade.c -lX11
	X */
	X
	X/************************************************************
	XCopyright 1989 by Sun Microsystems, Inc. Mountain View, CA.
	X
	X		All Rights Reserved
	X
	XPermission to use, copy, modify, and distribute this software and its
	Xdocumentation for any purpose and without fee is hereby granted,
	Xprovided that the above copyright notice appear in all copies and that
	Xboth that copyright notice and this permission notice appear in
	Xsupporting documentation, and that the names of Sun or MIT not be
	Xused in advertising or publicity pertaining to distribution of the
	Xsoftware without specific prior written permission. Sun and M.I.T.
	Xmake no representations about the suitability of this software for
	Xany purpose. It is provided "as is" without any express or implied warranty.
	X
	XSUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
	XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE. IN NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT
	XOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
	XOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
	XOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
	XOR PERFORMANCE OF THIS SOFTWARE.
	X************************************************************/
	X
	X#include	<stdio.h>
	X#include	<sys/types.h>
	X#include	<string.h>
	X#include	<ctype.h>
	X#include	<X11/Xos.h>
	X#include	<X11/Xlib.h>
	X#include	<X11/Xutil.h>
	X
	X#define	MAX_VALUE	65535
	X
	X#define	max(a, b)	(((a) > (b)) ? (a) : (b))
	X#define	abs(a)		(((a) > 0) ? (a) : -(a))
	X
	X#define	FONT	"*-times-medium-r-*"
	Xchar       *pattern = FONT;
	Xchar      **font_list;
	Xint         num_fonts;
	Xchar       *scale_name;
	X
	XDisplay    *dpy;
	XWindow      fadewin;
	Xint         screen;
	XColormap    cmap;
	XVisual     *visual;
	Xint         depth;
	XGC          gc;
	Xint         num_steps = 32;
	X#ifdef R4
	XAtom        kill_atom,
	X            protocol_atom;
	X#endif
	X
	X/* relative size of strings */
	Xint         basewidth,
	X            baseheight;
	Xint         basexloc,
	X            baseyloc;
	Xint         basescale = 12;
	X
	Xint         full_scaling;
	X
	XFont        fid;
	X
	X/* these all get adjusted when the window gets resized */
	Xint         width = 300;
	Xint         height = 100;
	Xint         xloc = 30;
	Xint         yloc = 90;
	X
	Xunsigned    sleeptime = 100000;
	Xunsigned    pausetime = 400000;
	X
	Xlong        pixel;
	Xlong        masks[2];
	XXColor		fg1, fg2, bg;
	X
	Xchar       *string1 = "Tastes Great";
	Xchar       *string2 = "Less Filling";
	X
	Xchar       *scale_res();
	Xchar       *scaled_font();
	X
	Xextern char *getenv();
	X
	Xmain(argc, argv)
	X    int         argc;
	X    char      **argv;
	X{
	X    char       *display = NULL;
	X    register int i;
	X    char       *cmd;
	X    XSetWindowAttributes xswat;
	X    XSizeHints  xsh;
	X    int         vmask;
	X    char	*foreground1 = "black";
	X    char	*foreground2 = "black";
	X    char	*background = "white";
	X
	X    cmd = strrchr(argv[0], '/');
	X    if (cmd)
	X	cmd++;
	X    else
	X	cmd = argv[0];
	X    for (i = 1; i < argc; i++) {
	X	if (strncmp(argv[i], "-d", 2) == 0) {
	X	    if (argv[++i])
	X		display = argv[i];
	X	    else
	X		usage(cmd);
	X	} else if (strncmp(argv[i], "-st", 3) == 0) {
	X	    if (argv[i + 1] && argv[i + 2]) {
	X		string1 = argv[++i];
	X		string2 = argv[++i];
	X	    } else
	X		usage(cmd);
	X	} else if (strncmp(argv[i], "-sl", 3) == 0) {
	X	    if (argv[++i])
	X		sleeptime = atoi(argv[i]);
	X	    else
	X		usage(cmd);
	X	} else if (strncmp(argv[i], "-fg", 2) == 0) {
	X	    if (argv[i + 1] && argv[i + 2])	{
	X		foreground1 = argv[++i];
	X		foreground2 = argv[++i];
	X	    } else
	X		usage(cmd);
	X	} else if (strncmp(argv[i], "-bg", 2) == 0) {
	X	    if (argv[++i])
	X		background = argv[i];
	X	    else
	X		usage(cmd);
	X	} else if (strncmp(argv[i], "-pau", 4) == 0) {
	X	    if (argv[++i])
	X		pausetime = atoi(argv[i]);
	X	    else
	X		usage(cmd);
	X	} else if (strncmp(argv[i], "-pat", 4) == 0) {
	X	    if (argv[++i])
	X		pattern = argv[i];
	X	    else
	X		usage(cmd);
	X	} else
	X	    usage(cmd);
	X    }
	X
	X    /* sanity check time */
	X    /* if this is too small, it can take over the server */
	X    if (sleeptime < 100) {
	X	sleeptime = 100000;
	X    }
	X    if ((dpy = XOpenDisplay(display)) == NULL) {
	X	fprintf(stderr, "Can\'t open %s\n",
	X		(display ? display : getenv("DISPLAY")));
	X	exit(1);
	X    }
	X    screen = DefaultScreen(dpy);
	X
	X    /* set up the color map */
	X    if (DisplayCells(dpy, screen) > 2)	{
	X	/* find the proper colors */
	X	XParseColor(dpy, DefaultColormap(dpy, screen), foreground1, &fg1);
	X	XParseColor(dpy, DefaultColormap(dpy, screen), foreground2, &fg2);
	X	XParseColor(dpy, DefaultColormap(dpy, screen), background, &bg);
	X	cmap_init();
	X    } else {
	X	fprintf(stderr, "%s doesn't make sense on a monchrome\n", argv[0]);
	X	exit(1);
	X    }
	X
	X    gc = XCreateGC(dpy, RootWindow(dpy, screen), NULL, 0);
	X
	X    init_fonts();
	X
	X    vmask = CWColormap | CWEventMask | CWBackPixel;
	X    xswat.colormap = cmap;
	X    xswat.event_mask = ExposureMask | StructureNotifyMask;
	X    xswat.background_pixel = pixel;
	X
	X    fadewin = XCreateWindow(dpy, RootWindow(dpy, screen),
	X			    100, 100, width, height, 0, depth,
	X			    InputOutput, visual, vmask, &xswat);
	X
	X    xsh.flags = PPosition | PSize;
	X    xsh.x = 100;
	X    xsh.y = 100;
	X    xsh.width = width;
	X    xsh.height = height;
	X    XSetStandardProperties(dpy, fadewin, "Fader", "Fader", None,
	X			   argv, argc, &xsh);
	X
	X#ifdef R4
	X    protocol_atom = XInternAtom(dpy, "WM_PROTOCOLS", False);
	X    kill_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
	X    XSetWMProtocols(dpy, fadewin, &kill_atom, 1);
	X#endif
	X
	X    XMapWindow(dpy, fadewin);
	X    while (1) {
	X	XEvent      ev;
	X
	X	if (XPending(dpy)) {
	X	    XNextEvent(dpy, &ev);
	X
	X	    if (ev.type == Expose && ev.xexpose.count == 0) {
	X		/* get rid of any in the queue */
	X		while (XCheckTypedEvent(dpy, Expose, &ev))
	X		    ;
	X		redraw();
	X	    } else if (ev.type == ConfigureNotify) {
	X		rescale((XConfigureEvent *)&ev);
	X#ifdef R4
	X	    } else if (ev.type == ClientMessage) {
	X		XClientMessageEvent *cmev = (XClientMessageEvent *) & ev;
	X
	X		if (cmev->message_type == protocol_atom &&
	X			cmev->data.l[0] == kill_atom)
	X		    exit(0);
	X#endif
	X	    }
	X	}
	X	/* fade strings */
	X	fadeit();
	X    }
	X}
	X
	Xusage(cmd)
	X    char       *cmd;
	X{
	X    (void) fprintf(stderr,
	X		   "usage: %s [-display display] [-string string1 string2]\n\t[-sleep sleeptime in useconds] [-pause pausetime in useconds]\n\t[-fg foreground color] [-bg background color] [-pattern font_pattern]\n", cmd);
	X    exit(1);
	X}
	X
	X/*
	X * initializes colormap
	X *
	X * finds dynamic visual and creates a new colormap
	X */
	Xcmap_init()
	X{
	X    XVisualInfo vinfo;
	X    int         planes;
	X    XColor      colors[4];
	X
	X    planes = DisplayPlanes(dpy, screen);
	X    /* see what kind of visual we're dealing with */
	X    if (!(XMatchVisualInfo(dpy, screen, planes, PseudoColor, &vinfo)
	X	  || XMatchVisualInfo(dpy, screen, planes, GrayScale, &vinfo)
	X	  || XMatchVisualInfo(dpy, screen, planes, DirectColor, &vinfo))) {
	X	fprintf(stderr, "%s can't run on this display\n");
	X	exit(1);
	X    }
	X    visual = vinfo.visual;
	X    depth = vinfo.depth;
	X
	X    /* try to use default cmap to minimize flashing */
	X    if (visual == DefaultVisual(dpy, screen))	{
	X	cmap = DefaultColormap(dpy, screen);
	X	if (XAllocColorCells(dpy, cmap, True, masks, 2, &pixel, 1) == 0) {
	X	    cmap = XCreateColormap(dpy, RootWindow(dpy, screen), visual, 
	X		AllocNone);
	X	    if (XAllocColorCells(dpy, cmap, True, masks, 2, &pixel, 1) == 0) {
	X		fprintf(stderr, "Couldn't allocate all colors - exiting\n");
	X		exit(1);
	X	    }
	X	}
	X    } else	{
	X	cmap = XCreateColormap(dpy, RootWindow(dpy, screen), visual, AllocNone);
	X	if (XAllocColorCells(dpy, cmap, True, masks, 2, &pixel, 1) == 0) {
	X	    fprintf(stderr, "Couldn't allocate all colors - exiting\n");
	X	    exit(1);
	X	}
	X    }
	X
	X    /* background */
	X    colors[0].flags = DoRed | DoGreen | DoBlue;
	X    colors[0].pixel = pixel;
	X    colors[0].red = bg.red;
	X    colors[0].green = bg.green;
	X    colors[0].blue = bg.blue;
	X
	X    /* color 1 */
	X    colors[1].flags = DoRed | DoGreen | DoBlue;
	X    colors[1].pixel = pixel | masks[0];
	X    colors[1].red = fg1.red;
	X    colors[1].green = fg1.green;
	X    colors[1].blue = fg1.blue;
	X
	X    /* color 2 */
	X    colors[2].flags = DoRed | DoGreen | DoBlue;
	X    colors[2].pixel = pixel | masks[1];
	X    colors[2].red = fg2.red;
	X    colors[2].green = fg2.green;
	X    colors[2].blue = fg2.blue;
	X
	X    /* both */
	X    colors[3].flags = DoRed | DoGreen | DoBlue;
	X    colors[3].pixel = pixel | masks[0] | masks[1];
	X    colors[3].red = fg2.red;
	X    colors[3].green = fg2.green;
	X    colors[3].blue = fg2.blue;
	X
	X    XStoreColors(dpy, cmap, colors, 4);
	X}
	X
	X/*
	X * find all the fonts we have that match the pattern.
	X * flag things if we've got a scalable font
	X *
	X * calculate the base scales and locations
	X */
	Xinit_fonts()
	X{
	X    int         dir,
	X                ascent,
	X                descent;
	X    XCharStruct overall1,
	X                overall2;
	X    char       *fname;
	X    int         f;
	X    XFontStruct *pfont;
	X
	X    font_list = XListFonts(dpy, pattern, 50, &num_fonts);
	X    if (num_fonts == 0) {
	X	fprintf(stderr, "Sorry, can't find any fonts matching %s\n", pattern);
	X	exit(1);
	X    }
	X    if ((f = found_scalable()) != -1) {
	X	full_scaling = 1;
	X	scale_name = font_list[f];
	X	fname = scale_res(basescale, 75, 75);
	X	pfont = XLoadQueryFont(dpy, fname);
	X	if (pfont == (XFontStruct *) 0) {
	X	    fprintf(stderr, "can't get font\n");
	X	    exit(1);
	X	}
	X    } else {
	X	full_scaling = 0;
	X	fname = scaled_font(basescale);
	X	pfont = XLoadQueryFont(dpy, fname);
	X	if (pfont == (XFontStruct *) 0) {
	X	    fprintf(stderr, "can't get font\n");
	X	    exit(1);
	X	}
	X    }
	X
	X
	X    XTextExtents(pfont, string1, strlen(string1), &dir, &ascent,
	X		 &descent, &overall1);
	X
	X    XTextExtents(pfont, string2, strlen(string2), &dir, &ascent,
	X		 &descent, &overall2);
	X
	X    basexloc = XTextWidth(pfont, "A", 1);
	X    baseyloc = pfont->ascent + pfont->descent;
	X
	X    basewidth = max(overall1.width, overall2.width) +
	X	2 * basexloc;
	X    baseheight = max((overall1.ascent + overall1.descent),
	X		     (overall2.ascent + overall2.descent)) * 2;
	X
	X    width = basewidth;
	X    height = baseheight;
	X
	X    /* dump the extent info, and reload as an ID */
	X    XFreeFont(dpy, pfont);
	X    fid = XLoadFont(dpy, fname);
	X    free(fname);
	X
	X    XSetFont(dpy, gc, fid);
	X}
	X
	X/*
	X * returns the font (as an index into the list) if it finds a scalable
	X * version
	X */
	Xfound_scalable()
	X{
	X    int         i,
	X                j;
	X    char       *d;
	X    int         scale;
	X
	X    for (i = 0; i < num_fonts; i++) {
	X	d = font_list[i];
	X	for (j = 0; j < 7; j++) {
	X	    d = strchr(d, '-');
	X	    if (d == NULL)
	X		goto next;
	X	    d++;		/* skip over '-' */
	X	}
	X	scale = atoi(d);
	X	if (scale == 0)
	X	    return i;
	Xnext:
	X	;
	X    }
	X    return -1;
	X}
	X
	X/*
	X * returns the scale for the given font name
	X */
	Xreturn_scale(fname)
	X    char       *fname;
	X{
	X    int         i;
	X    char       *d;
	X
	X    d = fname;
	X    for (i = 0; i < 7; i++) {
	X	d = strchr(d, '-');
	X	if (d == NULL)
	X	    return -1;
	X	d++;		/* skip over '-' */
	X    }
	X    return atoi(d);
	X}
	X
	X/*
	X * builds a font name with the given scale and resolution out of scale_name
	X */
	Xchar       *
	Xscale_res(scale, xres, yres)
	X    int         scale,
	X                xres,
	X                yres;
	X{
	X    char       *newname;
	X    char        foo[10];
	X    int         dashes = 0;
	X    char       *c,
	X               *n,
	X               *f;
	X
	X    c = scale_name;
	X    n = newname = (char *) malloc(strlen(scale_name) * 2 + 1);
	X    while (*c != '\0') {
	X	*n = *c;
	X	if (*c == '-') {
	X	    n++;
	X	    c++;		/* skip dash */
	X	    dashes++;
	X	    if (dashes == 7) {
	X		sprintf(foo, "%1d", scale);
	X		f = foo;
	X		while (isdigit(*c))
	X		    c++;
	X		while (*f != '\0')
	X		    *n++ = *f++;
	X	    } else if (dashes == 9) {
	X		sprintf(foo, "%1d", xres);
	X		f = foo;
	X		while (isdigit(*c))
	X		    c++;
	X		while (*f != '\0')
	X		    *n++ = *f++;
	X	    } else if (dashes == 10) {
	X		sprintf(foo, "%1d", yres);
	X		f = foo;
	X		while (isdigit(*c))
	X		    c++;
	X		while (*f != '\0')
	X		    *n++ = *f++;
	X	    }
	X	} else {
	X	    n++;
	X	    c++;
	X	}
	X    }
	X    *n = '\0';
	X    return newname;
	X}
	X
	X/*
	X * returns the font name the server knows closest to the
	X * given scale
	X */
	Xchar       *
	Xscaled_font(scale)
	X    int         scale;
	X{
	X    int         i;
	X    int         cvalue = 10000;
	X    int         closest;
	X    int         newscale;
	X
	X    for (i = 0; i < num_fonts; i++) {
	X	newscale = return_scale(font_list[i]);
	X	if (abs(scale - newscale) < cvalue) {
	X	    closest = i;
	X	    cvalue = abs(scale - newscale);
	X	}
	X    }
	X    return strdup(font_list[closest]);
	X}
	X
	X/*
	X * handle a configure notify event.  rescale the font for the
	X * new window size, and adjust the text location
	X */
	Xrescale(ev)
	X    XConfigureEvent *ev;
	X{
	X    char       *fname;
	X    static	init = 0;
	X    int         scale,
	X                xres,
	X                yres;
	X
	X    if (init && ev->width == width && ev->height == height)
	X	return;
	X
	X    init = 1;
	X    width = ev->width;
	X    height = ev->height;
	X
	X    xres = (int) ((float) width / (float) basewidth *
	X		  (float) basescale * 75.0);
	X    yres = (int) ((float) height / (float) baseheight *
	X		  (float) basescale * 75.0);
	X    xloc = basexloc * xres / (75 * basescale);
	X    yloc = baseyloc * yres / (75 * basescale);
	X
	X    if (full_scaling) {
	X	scale = 1;
	X	/* normalize to avoid overflowing things */
	X	if (xres > 1000 && yres > 1000) {
	X	    xres /= 10;
	X	    yres /= 10;
	X	    scale = 10;
	X	}
	X	fname = scale_res(scale, xres, yres);
	X    } else {
	X	scale = (int) ((float) height / (float) baseheight *
	X		       (float) basescale);
	X	fname = scaled_font(scale);
	X    }
	X    XUnloadFont(dpy, fid);
	X    fid = XLoadFont(dpy, fname);
	X    free(fname);
	X    XSetFont(dpy, gc, fid);
	X
	X}
	X
	X/*
	X * deal with exposure.
	X */
	Xredraw()
	X{
	X    /* clear out window */
	X    XSetForeground(dpy, gc, pixel);
	X    XSetPlaneMask(dpy, gc, (long) ~0);
	X    XFillRectangle(dpy, fadewin, gc, 0, 0, width, height);
	X
	X    /* clear it out */
	X    XSetPlaneMask(dpy, gc, masks[0]);
	X    XSetForeground(dpy, gc, 0);
	X    XFillRectangle(dpy, fadewin, gc, 0, 0, width, height);
	X
	X    /* draw first string */
	X    XSetForeground(dpy, gc, pixel | masks[0]);
	X    XDrawString(dpy, fadewin, gc, xloc, yloc, string1, strlen(string1));
	X
	X    /* clear it out */
	X    XSetPlaneMask(dpy, gc, masks[1]);
	X    XSetForeground(dpy, gc, 0);
	X    XFillRectangle(dpy, fadewin, gc, 0, 0, width, height);
	X
	X    /* draw second string */
	X    XSetForeground(dpy, gc, pixel | masks[1]);
	X    XDrawString(dpy, fadewin, gc, xloc, yloc, string2, strlen(string2));
	X}
	X
	X#define	UP	1
	X#define	DOWN	0
	X
	X/*
	X * fade the two strings back and forth
	X *
	X * here's where we need the speed
	X */
	Xfadeit()
	X{
	X    static int  i;
	X    static      direction = UP;
	X    static      init = 0;
	X    static XColor colors[3];
	X    static	short d1red, d1green, d1blue;
	X    static	short d2red, d2green, d2blue;
	X    static	short ddred, ddgreen, ddblue;
	X
	X    if (!init) {
	X	init = 1;
	X	colors[0].flags = DoRed | DoGreen | DoBlue;
	X	colors[0].pixel = pixel | masks[0];
	X	colors[0].red = fg1.red;
	X	colors[0].green = fg1.green;
	X	colors[0].blue = fg1.blue;
	X
	X	colors[1].flags = DoRed | DoGreen | DoBlue;
	X	colors[1].pixel = pixel | masks[1];
	X	colors[1].red = bg.red;
	X	colors[1].green = bg.green;
	X	colors[1].blue = bg.blue;
	X
	X	colors[2].flags = DoRed | DoGreen | DoBlue;
	X	colors[2].pixel = pixel | masks[0] | masks[1];
	X	colors[2].red = fg1.red;
	X	colors[2].green = fg1.green;
	X	colors[2].blue = fg1.blue;
	X
	X	d1red = (bg.red - fg1.red)/num_steps;
	X	d1green = (bg.green - fg1.green)/num_steps;
	X	d1blue = (bg.blue - fg1.blue)/num_steps;
	X
	X	d2red = (bg.red - fg2.red)/num_steps;
	X	d2green = (bg.green - fg2.green)/num_steps;
	X	d2blue = (bg.blue - fg2.blue)/num_steps;
	X
	X	ddred = (fg1.red - fg2.red)/num_steps;
	X	ddgreen = (fg1.green - fg2.green)/num_steps;
	X	ddblue = (fg1.blue - fg2.blue)/num_steps;
	X
	X	i = 0;
	X    }
	X    if (direction == UP) {
	X	colors[0].red += d1red;
	X	colors[0].green += d1green;
	X	colors[0].blue += d1blue;
	X
	X	colors[1].red -= d2red; 
	X	colors[1].green -= d2green;
	X	colors[1].blue -= d2blue;
	X
	X	colors[2].red -= ddred; 
	X	colors[2].green -= ddgreen;
	X	colors[2].blue -= ddblue;
	X    } else {
	X	colors[0].red -= d1red;
	X	colors[0].green -= d1green;
	X	colors[0].blue -= d1blue;
	X
	X	colors[1].red += d2red; 
	X	colors[1].green += d2green;
	X	colors[1].blue += d2blue;
	X
	X	colors[2].red += ddred; 
	X	colors[2].green += ddgreen;
	X	colors[2].blue += ddblue;
	X    }
	X    XStoreColors(dpy, cmap, colors, 3);
	X    i++;
	X    if (i == num_steps) {
	X	direction = (direction == UP) ? DOWN : UP;
	X	i = 0;
	X	usleep(pausetime);	/* pause at the end of each cycle */
	X    }
	X    /* sleep a bit */
	X    usleep(sleeptime);
	X    XSync(dpy, 0);
	X}
	X
	X
	X#ifdef USLEEP
	X
	X#include <signal.h>
	X#include <time.h>
	X
	Xusleep(value)
	Xlong value;
	X{
	X	void stopme();
	X	struct itimerval ntval, otval;
	X
	X	ntval.it_interval.tv_sec = 0;
	X	ntval.it_interval.tv_usec = 0;
	X	ntval.it_value.tv_sec = 0;
	X	ntval.it_value.tv_usec = value;
	X	signal(SIGALRM, stopme);
	X	setitimer(ITIMER_REAL, &ntval, &otval);
	X	pause();
	X}
	X
	Xvoid
	Xstopme()
	X{
	X	signal(SIGALRM, SIG_DFL);
	X}
	X
	X#endif /* USLEEP */
	X
SHAR_EOF
if test 17083 -ne "`wc -c < 'xfade.c'`"
then
	echo shar: "error transmitting 'xfade.c'" '(should have been 17083 characters)'
fi
fi
echo shar: "extracting 'xfade.man'" '(1732 characters)'
if test -f 'xfade.man'
then
	echo shar: "will not over-write existing file 'xfade.man'"
else
sed 's/^	X//' << \SHAR_EOF > 'xfade.man'
	X.\" @(#)xfade.man 1.3 89/08/02; Copyright (c) 1989 - Sun Microsystems
	X.TH xfade 1 "25 July 1989"
	X.SH NAME
	Xxfade \- xfade fade between two strings
	X
	X.SH SYNOPSIS
	X.B xfade
	X[
	X.BI \-display " connection"
	X]
	X[
	X.BI \-string " string1 string2"
	X]
	X[
	X.BI \-sleep " sleeptime"
	X]
	X[
	X.BI \-pause " pausetime"
	X]
	X[
	X.BI \-fg " foreground1 foreground2"
	X]
	X[
	X.BI \-bg " background"
	X]
	X[
	X.BI \-p " font_pattern"
	X]
	X.SH DESCRIPTION
	X.I xfade
	Xuses colormap double buffering to fade between two strings.  It requires
	Xa dynamic visual to run.  As the window is resized, its does its best
	Xto find a font in \fIfont_pattern\fR to best fit the window.
	X.SH OPTIONS
	X.TP 5
	X.BI \-display " connection"
	XConnect to X server display,
	X.IR connection.
	X.TP 5
	X.BI \-string " string1 string2"
	XUse
	X.IR string1
	Xand
	X.IR string2
	Xas the strings to fade between.
	X.TP 5
	X.BI \-sleep " sleeptime"
	XMicroseconds to sleep between changes in the colormap.  The default
	Xis 100000.  Two small a sleeptime can overwhelm the server.
	X.TP 5
	X.BI \-pause " pasuetime"
	XMicroseconds to pause at the end of a cycle.  The default
	Xis 400000.
	X.TP 5
	X.BI \-fg " foreground1 foreground2"
	XThe colors of the two strings.
	X.TP 5
	X.BI \-bg " background"
	XThe color of the window.
	X.TP 5
	X.BI \-pattern " font_pattern"
	XUse
	X.IR font_pattern
	Xas the font family.  The default is
	X.IR *times-medium-r*.
	X.SH SEE ALSO
	X    X(1)
	X.SH COPYRIGHT
	X Copyright (c) 1988 by Sun Microsystems, Inc.
	X David Lemke (lemke@wirehead.sun.com)
	X
	X Permission to use, copy, modify, and distribute this software and its
	Xdocumentation for any purpose and without fee is hereby granted,
	Xprovided that the above copyright notice appear in all copies and that
	Xboth that copyright notice and this permission notice appear in
	Xsupporting documentation. 
SHAR_EOF
if test 1732 -ne "`wc -c < 'xfade.man'`"
then
	echo shar: "error transmitting 'xfade.man'" '(should have been 1732 characters)'
fi
fi
echo shar: "extracting 'fader'" '(11990 characters)'
if test -f 'fader'
then
	echo shar: "will not over-write existing file 'fader'"
else
sed 's/^	X//' << \SHAR_EOF > 'fader'
	X%
	X% This file is a product of Sun Microsystems, Inc. and is provided for
	X% unrestricted use provided that this legend is included on all tape
	X% media and as a part of the software program in whole or part.  Users
	X% may copy or modify this file without charge, but are not authorized to
	X% license or distribute it to anyone else except as part of a product
	X% or program developed by the user.
	X%
	X% THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
	X% WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
	X% PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
	X%
	X% This file is provided with no support and without any obligation on the
	X% part of Sun Microsystems, Inc. to assist in its use, correction,
	X% modification or enhancement.
	X%
	X% SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
	X% INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
	X% OR ANY PART THEREOF.
	X%
	X% In no event will Sun Microsystems, Inc. be liable for any lost revenue
	X% or profits or other special, indirect and consequential damages, even
	X% if Sun has been advised of the possibility of such damages.
	X%
	X% Sun Microsystems, Inc.
	X% 2550 Garcia Avenue
	X% Mountain View, California  94043
	X%
	X%	fader 22.2 89/08/29
	X%
	X%  Fader:
	X%  Fade 2 strings in and out
	X%
	X% Fader uses colormap double buffering to get its results.  4 pixels
	X% are allocated by asking for 1 cell and 2 planes.  combining this one 
	X% cell with the 4 possible plane mask combinations gives the 4 pixels
	X% used.  the base cell with no planes ORd in is used as the background
	X% for the window.  the cell with either plane turned on gives the two
	X% foreground colors.  the cell with both planes turned on is the
	X% pixel value of the combined foregrounds.
	X%
	X% usually, what happens is that the cell is at 0, and the two planes
	X% are 1 and 2.
	X%
	X% so:
	X% background 0	(cell)
	X% foreground1 1 (cell or plane1)
	X% foreground2 2 (cell or plane2)
	X% sum	      3 (cell or plane1 or plane2)
	X%
	X% the sum pixel is painted wherever the two strings intersect.
	X%
	X% the background cell is set to white.  the sum is set to black.
	X% the two foregrounds are changed over time to be fading between
	X% black and white.  since the sum is always black, the intersected
	X% areas are as well.
	X%
	X
	X% make a subclass of BaseFrame that catches iconification
	X%
	X/FadeBaseFrame /defaultclass ClassBaseFrame send []
	Xclassbegin
	X    /open {
	X	dup
	X	/open super send
	X	/open /client self send send
	X    } def
	Xclassend def
	X
	X/FadeWindow ClassCanvas dictbegin
	X    /vis null def			% the visual
	X    /cmap null def			% the colormap
	X    /segs null def			% the segments
	X
	X    /pix1 0 def				% the foreground pixels
	X    /pix2 0 def
	X    /mask1 0 def			% the planemasks
	X    /mask2 0 def
	X
	X    /color1 0 0 0 rgbcolor def		% the foreground colors
	X    /color2 1 1 1 rgbcolor def
	X    /bg 1 1 1 rgbcolor def		% the background
	X    /fg 0.1 0 0 rgbcolor def		% the sum color
	X
	X    /stepsize 32 def			% number of steps between White & Black
	X    /stepsleep .005 def			% sleep time between steps
	X    /up? true def			% fade direction
	X
	X    /string1 (Tastes Great) def		% the strings
	X    /string2 (Less Filling) def
	X
	X    /x .5 def				% string positioning information
	X    /y .5 def
	X    /basewidth 0 def			% window sizing info
	X    /baseheight 0 def
	X
	X    /fadeproc null def			% the process handling the animation
	X    /sleepsecs 1 60 div def		% how long to sleep between steps
	X    /wasfading? false def		% bool for handling iconification
	X
	X    /minfadescale 20 def		% initial text size
	X    /fadefontname /Times-Roman def	% the font we use
	X
	X    /StepMenu null def			% some menus
	X    /SloganMenu null def
	X
	Xdictend classbegin
	X
	X    /PseudoColor 3 def			% visual types are returned as numbers
	X					% so make a constant
	X    /GrayScale 1 def
	X
	X    /useenter? true def			% type of colormap installation routine 
	X					% to use
	X
	X    %
	X    % creates the client canvas
	X    %
	X    % finds the proper visual if it can and builds the colormap,
	X    % then passes both (eventually, via newinit) to newcanvas so that it is
	X    % built with the proper visual & colormap
	X    %
	X    /newobject {	% canvas => cv
	X	getvisual {
	X	    dup createcolormap
	X	    2 copy 5 2 roll		% vis cmap cv vis cmap
	X	    /newobject super send	% vis instance
	X	} {
	X	    pop				% toss parent
	X	    (Sorry, Fader can't run on this display\n) printf
	X	    quit
	X	} ifelse
	X    } def
	X
	X    %
	X    % gets the new canvas (with the proper visual and colormap),
	X    % the visual and the colormap.  stashes the last two, and
	X    % initilaizes the colormap, the text and the menus
	X    %
	X    /newinit {	% cv vis cmap => cv
	X	/cmap exch def
	X	/vis exch def
	X	/newinit super send
	X	/makecmap self send
	X	text_size
	X	/CreateMenu self send
	X    } def
	X
	X    % 
	X    % calculate proper text scale factors for strings
	X    %
	X    /text_size	{
	X	gsave
	X	    fadefontname findfont minfadescale scalefont setfont
	X	    string1 stringbbox 4 -2 roll pop pop	% w1 h1
	X	    string2 stringbbox 4 -2 roll pop pop	% w1 h1 w2 h2
	X	    3 -1 roll					% h1 h2 w1 w2
	X	    max 3 1 roll max				% [h1 | h2 ] [w1 | w2 ]
	X	    /baseheight exch 20 div x 2 mul add def
	X	    /basewidth exch 20 div y 1.5 mul add def
	X	grestore
	X    } def
	X
	X    %
	X    % does the installation of the colormap so that the proper colors 
	X    % are displayed
	X    %
	X    /installcmap { % bool => -
	X	cmap /Installed 3 -1 roll put
	X    } def
	X
	X    %
	X    % express interest in Enter & Exit events so that the colormap
	X    % can be (un)installed as required
	X    %
	X    /MakeInterests	{
	X	/MakeInterests super send
	X
	X	useenter? {
	X	    Canvas soften null
	X	    2 dict dup begin
	X		/EnterEvent	/ClientEnter self soften buildsend def
	X		/ExitEvent	/ClientExit self soften buildsend def
	X	    end /new ClassInterest send
	X	} if
	X
	X    } def
	X
	X    % REMIND -- may want to add turning fadeproc on & off on
	X    % Enter/Exit
	X    %
	X    % handle the events
	X    %
	X    useenter? {
	X	/ClientEnter	{
	X	    pop true /installcmap self send
	X	} def
	X	/ClientExit {
	X	    pop false /installcmap self send
	X	} def
	X    } if
	X
	X    %
	X    % tries to find a dynamic visual and return it and a boolean
	X    %
	X    /getvisual {	% - => vis true | false
	X	false
	X	framebuffer /VisualList get {
	X	    dup /Class get		% false vis class
	X	    dup
	X	    PseudoColor eq exch GrayScale eq or {
	X		exch pop		% wipe the false
	X		true exit		% vis true
	X	    } {
	X		pop
	X	    } ifelse
	X	} forall
	X    } def
	X
	X    % build the colormap and get the proper pixels & masks
	X    /makecmap {
	X	/segs cmap 1 2 createcolorsegment 0 get def
	X
	X	% calculate masks
	X	/mask1 segs /Mask get dup neg and def
	X	/mask2 segs /Mask get mask1 xor def
	X
	X	% save the pixels
	X	/pix1 segs /Slot get mask1 or def
	X	/pix2 segs /Slot get mask2 or def
	X
	X	% store the fg & bg into the proper places
	X	segs segs /Slot get bg putcolor
	X	segs segs /Slot get segs /Mask get or fg putcolor
	X
	X	% init the colors
	X	segs pix1 color1 putcolor
	X	segs pix2 color2 putcolor
	X    } def
	X
	X    % display the strings
	X    /showtext {
	X	fadefontname findfont 1 scalefont setfont
	X	% show the first set
	X	mask1 setplanemask  	    	% affect only plane1
	X	0 setpixel clippath fill	% clear out extraneous bits
	X	pix1 setpixel			% use pixel1
	X	x y moveto string1 show
	X
	X	mask2 setplanemask
	X	0 setpixel clippath fill
	X	pix2 setpixel
	X	x y moveto string2 show
	X    } def
	X
	X    % adjust the colors up or down, sleeping between changes to keep
	X    % things smooth
	X    %
	X    % the colors are N and abs(1 - N)
	X    /fadetext {
	X	up? {
	X	    0 1 stepsize {
	X		dup
	X		/color1 exch stepsize div dup dup rgbcolor def
	X		/color2 exch stepsize sub abs stepsize div dup dup rgbcolor def
	X		segs pix1 color1 putcolor
	X		segs pix2 color2 putcolor
	X		stepsleep sleep
	X	    } for
	X	    /up? false def
	X	    sleepsecs sleep
	X	} {
	X	    0 1 stepsize {
	X		dup
	X		/color2 exch stepsize div dup dup rgbcolor def
	X		/color1 exch stepsize sub abs stepsize div dup dup rgbcolor def
	X		segs pix1 color1 putcolor
	X		segs pix2 color2 putcolor
	X		stepsleep sleep
	X	    } for
	X	    /up? true def
	X	    sleepsecs sleep
	X	} ifelse
	X    } def
	X
	X    % adjust font size to fit in given window
	X    /scaletext {
	X	clippath pathbbox		% x y w h
	X	basewidth div			% x y w h'
	X	exch baseheight div exch	% x y w' h'
	X	scale
	X	pop pop
	X    } def
	X
	X    /PaintCanvas {
	X	/scaletext self send
	X	% clean the slate so we have no garbage interfering
	X	segs /Slot get setpixel
	X	0 not setplanemask  	% paint all planes
	X	clippath fill
	X	showtext		% display the text
	X    } def
	X
	X    % turn the fader off when we go iconic, and restore when we
	X    % come back
	X    /open {	% bool => -
	X	{
	X	    wasfading? {
	X		/fadeproc { { fadetext } loop } fork def
	X	    } if
	X	} {
	X	    wasfading? {
	X		fadeproc killprocess
	X		/fadeproc null def
	X	    } if
	X	} ifelse
	X    } def
	X
	X    /destroy {
	X	% make sure we return the cmap to normal
	X	cmap /Installed false put
	X
	X        StepMenu null ne {
	X	    /destroy StepMenu send
	X	    /StepMenu null def
	X        } if
	X
	X        SloganMenu null ne {
	X	    /destroy SloganMenu send
	X            /SloganMenu  null def
	X        } if
	X
	X	fadeproc null ne {
	X	    fadeproc killprocess
	X	    /fadeproc null def
	X	} if
	X
	X	/destroy super send
	X    } def
	X
	X    % set up the minimum size
	X    /minsize {	% => width height
	X	/minsize super send			% mw mh
	X	baseheight minfadescale mul max
	X	exch basewidth minfadescale mul max
	X    } def
	X
	X    /preferredsize {	% => width height
	X	/minsize self send			% mw mh
	X    } def
	X
	X    % turn the fader proc on & off
	X    /fadetoggle {
	X	fadeproc null ne {
	X	    fadeproc killprocess
	X	    /fadeproc null def
	X	    /wasfading? false def
	X	} {
	X	    /fadeproc { { fadetext } loop } fork def
	X	    /wasfading? true def
	X	} ifelse
	X    } def
	X
	X    % convert the menu entry into a numeric sleep time
	X    /setstepfrommenu {
	X	dup
	X	/value exch send
	X	[ .01 .005 .001 .0005 .00001 .00005 0 ] exch get
	X	/stepsleep exch def
	X	null /valuething 3 -1 roll send /setfooter /Parent self send send
	X    } def
	X
	X    /showstep	{	% - => stepsleep
	X	stepsleep
	X    } def
	X
	X    % change the strings and adjust the scale
	X    /changestring	{	% str1 str2
	X	/string2 exch store
	X	/string1 exch store
	X	text_size
	X	/paint self send
	X    } def
	X
	X    /CreateMenu	{
	X    % menu choice for how long to sleep between color changes
	X        /StepMenu
	X	    [ (slowest) (slower) (slow) (normal) (fast) (faster) (fastest) ]
	X	    null /setstepfrommenu self soften buildsend
	X	    framebuffer /newdefault ClassMenu send def
	X	    3 /setdefault StepMenu send
	X
	X	/SloganMenu
	X	    [
	X		(Beer) null { pop (Tastes Great) (Less Filling) /changestring }
	X			self soften buildsend
	X		(Focus) null { pop (Follow Mouse) (Click To Type) /changestring }
	X			self soften buildsend
	X		(Editors) null { pop (    Vi) (Emacs) /changestring }
	X			self soften buildsend
	X		(Politics) null { pop (Republican) (Democrat) /changestring }
	X			self soften buildsend
	X		% space NeWS out so they combine to X11NeWS...
	X		(Window Systems) null { pop (       NeWS) (X11) /changestring }
	X			self soften buildsend
	X		(Operating Systems) null { pop (UNIX) (VMS) /changestring }
	X			self soften buildsend
	X	    ]
	X	    framebuffer /newdefault ClassMenu send def
	X
	X        /CanvasMenu
	X	    [
	X		(Toggle Fade)	null { pop /fadetoggle } self soften buildsend
	X		(Slogans) SloganMenu null
	X		(Fade Time) StepMenu null
	X	    ]
	X	    framebuffer /newdefault ClassMenu send
	X	    (Fader) /setlabel 2 index send
	X	    (Fader) /setowner 2 index send
	X        def
	X
	X    } def
	X
	Xclassend def
	X
	X[FadeWindow] [] framebuffer /new FadeBaseFrame send
	X/win exch def
	X(Fader) /setlabel win send
	X(Fade Time) (normal)
	X    /setfooter win send
	X
	X% icon painter
	X{
	X    gsave
	X	1 fillcanvas
	X	clippath pathbbox scale pop pop		% got 0-1, 0-1 coords
	X	/Helvetica-Bold findfont .30 scalefont setfont
	X
	X	% top row
	X	.8 setgray
	X	.1 .7 moveto
	X	(F) show
	X	.6 setgray
	X	(a) show
	X	.4 setgray
	X	(d) show
	X	.2 setgray
	X	(e) show
	X	0 setgray
	X	(r) show
	X
	X	% middle row
	X	0 setgray
	X	.1 .4 moveto
	X	(Fader) show
	X
	X	% bottom row
	X	0 setgray
	X	.1 .1 moveto
	X	(F) show
	X	.2 setgray
	X	(a) show
	X	.4 setgray
	X	(d) show
	X	.6 setgray
	X	(e) show
	X	.8 setgray
	X	(r) show
	X    grestore
	X} /seticon win send
	X
	Xnull /seticonlabel win send
	X
	X/place win send
	X/activate win send
	X/map win send
	X
	Xnewprocessgroup
	Xcurrentfile closefile
SHAR_EOF
if test 11990 -ne "`wc -c < 'fader'`"
then
	echo shar: "error transmitting 'fader'" '(should have been 11990 characters)'
fi
fi
exit 0
#	End of shell archive