v05i004: xlock -- lockscreen for X displays, Part01/01

Dan Heller argv at island.uu.net
Mon Sep 25 03:49:29 AEST 1989


Submitted-by: Patrick Naughton <naughton at sun.com>
Posting-number: Volume 5, Issue 4
Archive-name: xlock/part01

[ This was posted once before, but this is a repost due to the large number
  of changes.  Note the version number and patchlevel.h.  Systems without
  usleep(2) may consider writing a one or two liner using select() and
  polling for N microseconds (see README).  --argv ]

#! /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
#	Makefile
#	patchlevel.h
#	xlock.1
#	xlock.c
#	hopalong.c
#	qix.c
#	life.c
#	lifeicon.bit
#	XCrDynCmap.c
#	XCrHsbCmap.c
#	HSBmap.c
# This archive created: Sat Sep 23 09:39:30 1989
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
cat << \SHAR_EOF > 'README'

This is the latest version of xlock (sccs version 22.4)

This will start with patchlevel = 1.1

There were serveral minor bugfixes made after I put this on expo, but before
it was posted to comp.sources.x

   o -display hostname:0 did not work even when hostname was the localhost.
   o -mode qix failed with a count < 4.
   o qix was using rand() shifted right some amount to get some randomness.
     I switched to random() and srandom() and the performance is still too
     fast to worry about measuring... (at least on OpenWindows on a 4/60)
   o I was coughing on EnterNotify and LeaveNotify, now I ignore them.
   o The window manager was sometimes installing the default colormap when
     the mouse crossed a window boundry *after* I had installed my colormap,
     but *before* I had my window up to block crossing events.  I moved the
     colormap installation down to the very last moment.
   o a couple of gratuitous non-portable functions were used.
	- strtok() replaced with simple strchr() and a null store.
	- srand48() replaced with srandom();
	- usleep() this is still used in life.c, but people can just rip it
	out if they don't have it, or stick in a loop polling timeofday, or
	use VTALRM, but usleep works nice and cleanly under SunOS, so I'm
	not really motivated to change it.

----------------------------------------------------------------------

    There is a minimal Makefile which you may need to massage in order
    to get it to generate the right thing from the Imakefile.  Neither
    of these has been tested since we don't use Imake.

Changes since last version (1.8):

    Ability to set the nice level of the xlock process, to keep it from
    hogging all of the cpu.

    -display is parsed to be able to lock unix:1, etc...

    new modal interface to different lockscreen screensavers.

    three sample modes.
	-mode qix is the old spinning lines demo...
	-mode life is a new implementation of Conway's Life simulation.
	-mode hop is the "hopalong fractals" from last version.

    lots of bug fixes and code cleanup.

    ______________________________________________________________________
    Patrick J. Naughton				    ARPA: naughton at sun.com
    Window Systems Group			    UUCP: ...!sun!naughton
    Sun Microsystems, Inc.			    AT&T: (415) 336 - 1080
SHAR_EOF
fi
if test -f 'Imakefile'
then
	echo shar: "will not over-write existing file 'Imakefile'"
else
cat << \SHAR_EOF > 'Imakefile'
# @(#)Imakefile 22.2 89/09/20
# Imakefile - xlock
#
# Copyright (c) 1989 by Sun Microsystems, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation.
#
# This file is provided AS IS with no warranties of any kind.  The author
# shall have no liability with respect to the infringement of copyrights,
# trade secrets or any patents by this file or any part thereof.  In no
# event will the author be liable for any lost revenue or profits or
# other special, indirect and consequential damages.
#
#
       INCLUDES = -I$(TOP) -I$(TOP)/X11
LOCAL_LIBRARIES = $(XLIB)
  SYS_LIBRARIES = -lm
           SRCS = xlock.c hopalong.c life.c qix.c \
		XCrHsbCmap.c HSBmap.c XCrDynCmap.c
           OBJS = xlock.o hopalong.o life.o qix.o \
		XCrHsbCmap.o HSBmap.o XCrDynCmap.o

ComplexProgramTarget(xlock)
SHAR_EOF
fi
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
            TOP = ./../..
             MV = mv
             RM = rm -f
        UTILSRC = $(TOP)/util
       IMAKESRC = $(UTILSRC)/imake
       IRULESRC = $(UTILSRC)/imake.includes
          IMAKE = $(IMAKESRC)/imake
      IMAKE_CMD = $(NEWTOP)$(IMAKE) -TImake.tmpl \
                        -I$(NEWTOP)$(IRULESRC) \
                        -s Makefile

Makefile:: Imakefile
        -$(RM) Makefile.bak; $(MV) Makefile Makefile.bak
        $(IMAKE_CMD) -DTOPDIR=$(TOP)
SHAR_EOF
fi
if test -f 'patchlevel.h'
then
	echo shar: "will not over-write existing file 'patchlevel.h'"
else
cat << \SHAR_EOF > 'patchlevel.h'
1.1
SHAR_EOF
fi
if test -f 'xlock.1'
then
	echo shar: "will not over-write existing file 'xlock.1'"
else
cat << \SHAR_EOF > 'xlock.1'
.\" @(#)xlock.n 22.2 89/09/20; Copyright (c) 1989 - Sun Microsystems, Inc.
.TH XLOCK 1 "20 Sep 1989" "X11R4"
.SH NAME
xlock \- Locks the local X display till a password is entered.

.SH SYNOPSIS
.B xlock
[
.BI \-display " dsp"
]
[
.BI \-mode " mode"
]
[
.BI \-time " timeout"
]
[
.BI \-count " n"
]
[
.BI \-font " fontname"
]
[
.BI \-nice " nicelevel"
]
[
.B \-mono
]
[
.B \-saver
]
[
.B \-root
]
[
.B \-v
]

.SH DESCRIPTION
.B xlock
locks the X server till the user enters their password at the keyboard.
While
.B xlock
is running,
all new server connections are refused.
The screen saver is disabled.
The mouse cursor is turned off.
The screen is blanked and a changing pattern is put on the screen.
The pattern changes after
.I timeout
seconds. 
If a key or a mouse button is pressed then the user is prompted for the
password of the user who started
.B xlock.

If the correct password is typed, then the screen is unlocked and the X
server is restored.  When typing the password, characters are echoed
to the screen as question marks (?), and Control-U and Control-H are
active as kill and erase respectively.  To return to the locked screen,
click in the small icon version of the changing pattern.

.SH OPTIONS
.TP 5
.B \-display " dsp"
The
.I display
option sets the X11 display to lock.
.B xlock
will not allow one to lock another server's displays thus only
.BI unix:server.screen,
.BI localhost:server.screen,
and
.BI :server.screen
are allowed for
.I dsp.
Where
.I server
is which X11 server socket to connect to and
.I screen
is which head to display the pattern on.
.TP 5
.B \-mode " modename"
As of this writing there are three display modes supported.
.TP 8
.B hop
Hop mode shows the "real plane fractals" from the September 1986 issue of
Scientific American.
.TP 8
.B life
Life mode shows Conway's game of life.
.TP 8
.B qix
Qix mode shows the spinning lines similar to the old video game
by the same name.
.TP 5
.B \-time " timeout"
The
.I time
option sets the number of seconds that each unique fractal will remain on
the screen before being replaced by the next one to
.I timeout.
.TP 5
.B \-count " n"
The
.I count
option sets the speed at which a mode will operate.  The different modes
interpret this value differently.  For 'hop' and 'qix' this sets the
number of pixels and lines respectively to draw in each color.
These patterns are calculated in batches of
.I n
objects, then sent to the server in a single color.  Faster machines,
expecially machines with floating point hardware can set this to a
higher number and still have fast changing patterns.
The 'life' mode, in contrast interprets this number as the number of
milliseconds to delay after each generation of the "critters".  A low
number here makes the pattern change rapidly, where 1000 means wait a
second between generations.
.TP 5
.B \-font " fontname"
The
.I font
option sets the font to be used on the prompt screen.
.TP 5
.B \-nice " nicelevel"
The
.I nice
option sets system nicelevel of the xlock process to
.I nicelevel .
.TP 5
.B \-mono
The
.I mono
option causes xlock to display monochrome, (black and white) pixels rather
than the default colored ones on color displays.
.TP 5
.B \-saver
The
.I saver
option causes xlock to only draw the patterns and not lock the display.
A keypress or a mouse click will terminate the screen saver.
.TP 5
.B \-root
The
.I root
option allows the root password to unlock the server as well as the user
who started xlock.
.TP 5
.B \-v
Verbose mode, tells what options it is going to use.

.SH BUGS
"kill -KILL
.B xlock
" causes server to be unusable, since
.B xlock
has removed all hosts (including localhost) from the access control list
to lock out all new X clients, and SIGKILL cannot be caught by any program,
.B xlock
will terminate before restoring the access control list.  This will
leave the X server in a state where
\fI "you can no longer connect to that server, and this operation cannot be
reversed short of resetting the server."\fP
		-From the X11R2 Xlib Documentation page 140. 
.SH SEE ALSO
X(1), Xlib Documentation.

.SH AUTHOR
 Patrick J. Naughton	 (naughton at sun.com)
 Window Systems Group
 Sun Microsystems, Inc.
 Mountain View, CA  94043
 415/336-1080

.SH COPYRIGHT
Copyright (c) 1988-89 by Patrick J. Naughton and Sun Microsystems, Inc.

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation. 

.SH CONTRIBUTORS
  milliken at heron.bbn.com	karlton at wsl.dec.com
  dana at thumper.bellcore.com	vesper at 3d.dec.com	flar at sun.com
SHAR_EOF
fi
if test -f 'xlock.c'
then
	echo shar: "will not over-write existing file 'xlock.c'"
else
cat << \SHAR_EOF > 'xlock.c'
#ifndef lint
static char sccsid[] = "@(#)xlock.c 22.4 89/09/23";
#endif
/*-
 * xlock.c - X11 client to lock a display and show a screen saver.
 *
 * Copyright (c) 1988-89 by Patrick Naughton and Sun Microsystems, Inc.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * This file is provided AS IS with no warranties of any kind.  The author
 * shall have no liability with respect to the infringement of copyrights,
 * trade secrets or any patents by this file or any part thereof.  In no
 * event will the author be liable for any lost revenue or profits or
 * other special, indirect and consequential damages.
 *
 * Comments and additions should be sent to the author:
 *
 *		       naughton at sun.com
 *
 *		       Patrick J. Naughton
 *		       Window Systems Group, MS 14-40
 *		       Sun Microsystems, Inc.
 *		       2550 Garcia Ave
 *		       Mountain View, CA  94043
 *
 * Revision History:
 * 23-Sep-89: Added fix to allow local hostname:0 as a display.
 *	      Put empty case for Enter/Leave events.
 *	      Moved colormap installation later in startup.
 * 20-Sep-89: Linted and made -saver mode grab the keyboard and mouse.
 *	      Replaced SunView code for life mode with Jim Graham's version,
 *		so I could contrib it without legal problems.
 *	      Sent to expo for X11R4 contrib.
 * 19-Sep-89: Added '?'s on input.
 * 27-Mar-89: Added -qix mode.
 *	      Fixed GContext->GC.
 * 20-Mar-89: Added backup font (fixed) if XQueryLoadFont() fails.
 *	      Changed default font to lucida-sans-24.
 * 08-Mar-89: Added -nice, -mode and -display, built vector for life and hop.
 * 24-Feb-89: Replaced hopalong display with life display from SunView1.
 * 22-Feb-89: Added fix for color servers with n < 8 planes.
 * 16-Feb-89: Updated calling conventions for XCreateHsbColormap();
 *	      Added -count for number of iterations per color.
 *	      Fixed defaulting mechanism.
 *	      Ripped out VMS hacks.
 *	      Sent to expo for X11R3 contrib.
 * 15-Feb-89: Changed default font to pellucida-sans-18.
 * 20-Jan-89: Added -verbose and fixed usage message.
 * 19-Jan-89: Fixed monochrome gc bug.
 * 16-Dec-88: Added SunView style password prompting.
 * 19-Sep-88: Changed -color to -mono. (default is color on color displays).
 *	      Added -saver option. (just do display... don't lock.)
 * 31-Aug-88: Added -time option.
 *	      Removed code for fractals to separate file for modularity.
 *	      Added signal handler to restore host access.
 *	      Installs dynamic colormap with a Hue Ramp.
 *	      If grabs fail then exit.
 *	      Added VMS Hacks. (password 'iwiwuu').
 *	      Sent to expo for X11R2 contrib.
 * 08-Jun-88: Fixed root password pointer problem and changed PASSLENGTH to 20.
 * 20-May-88: Added -root to allow root to unlock.
 * 12-Apr-88: Added root password override.
 *	      Added screen saver override.
 *	      Removed XGrabServer/XUngrabServer.
 *	      Added access control handling instead.
 * 01-Apr-88: Added XGrabServer/XUngrabServer for more security.
 * 30-Mar-88: Removed startup password requirement.
 *	      Removed cursor to avoid phosphor burn.
 * 27-Mar-88: Rotate fractal by 45 degrees clockwise.
 * 24-Mar-88: Added color support. [-color]
 *	      wrote the man page.
 * 23-Mar-88: Added HOPALONG routines from Scientific American Sept. 86 p. 14.
 *	      added password requirement for invokation
 *	      removed option for command line password
 *	      added requirement for display to be "unix:0".
 * 22-Mar-88: Recieved Walter Milliken's comp.windows.x posting.
 *
 * Contributors:
 *  milliken at heron.bbn.com
 *  karlton at wsl.dec.com
 *  dana at thumper.bellcore.com
 *  vesper at 3d.dec.com
 */

#include <stdio.h>
#include <signal.h>
#include <sys/param.h>
#include <string.h>
#include <pwd.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>

extern char *crypt();
extern char *getenv();

typedef struct {
    char       *cmdline_arg;
    int		(*lp_reinit) ();
    void	(*lp_callback) ();
    void	(*lp_init) ();
}	    lockProc;

/*
 * Declare external interface routines for supported screen savers.
 */

extern void randomInithop();
extern int  hopdone();
extern void hop();

extern void initlife();
extern int  lifedone();
extern void drawlife();

extern void initqix();
extern int  qixdone();
extern void drawqix();

lockProc    LockProcs[] = {
    {"hop", hopdone, hop, randomInithop},
    {"life", lifedone, drawlife, initlife},
    {"qix", qixdone, drawqix, initqix}
/*
 * New screen savers may be added here.
 * Refer to qix.c for simple sample screen saver.
 */

};
#define NUMPROCS (sizeof(LockProcs) / sizeof(lockProc))

int	    (*reinit) () = NULL;
void	    (*callback) () = NULL;
void	    (*init) () = NULL;

char	   *pname;		/* argv[0] */
Display	   *dsp = NULL;		/* server display connection */
int	    screen;		/* current screen */
Window	    w,			/* window used to cover screen */
	    icon,		/* window used during password typein */
	    root;		/* convenience pointer to the root window */
GC	    gc,			/* main graphics drawing graphics context */
	    textgc;		/* graphics context used for text rendering */
XColor	    black,		/* used for text rendering */
	    white;		/* background of text screen */
Colormap    cmap;		/* colormap */
Cursor	    mycursor;		/* blank cursor */
Pixmap	    lockc,
	    lockm;		/* pixmaps for cursor and mask */
char	    no_bits[] = {0};	/* dummy array for the blank cursor */
int	    passx,		/* position of the ?'s */
	    passy;
XFontStruct *font;
char	   *fontname = NULL;	/* the font used in the password screen */
int	    inittime = -1;	/* time to iterate before calling init */
int	    skipRoot;		/* skip root password check */
int	    color;		/* color or mono */
int	    count = -1;		/* number of pixels to draw in each color */
int	    nicelevel = -1;	/* system priority at which to run process */
int	    lock;		/* locked or just screensaver mode */
int	    verbose = False;	/* print configuration info to stderr? */
char	   *display = NULL;	/* X display variable */
int	    timeout,
	    interval,
	    blanking,
	    exposures;		/* screen saver parameters */

#define ICONX			300
#define ICONY			150
#define ICONW			64
#define ICONH			64
#define ICONLOOPS		600
#define DEFAULT_FONTNAME	"LucidaSans-24"
#define BACKUP_FONTNAME		"fixed"
#define DEFAULT_INITTIME	60
#define DEFAULT_SKIPROOT	True
#define DEFAULT_COUNT		100
#define DEFAULT_NICE		10
#define DEFAULT_DISPLAY		":0"

/* VARARGS1 */
void
error(s1, s2)
    char       *s1,
	       *s2;
{
    fprintf(stderr, s1, pname, s2);
    exit(1);
}


int	    oldsigmask;

void
block()
{
    oldsigmask = sigblock(sigmask(SIGINT)
			  | sigmask(SIGQUIT)
			  | sigmask(SIGFPE)
			  | sigmask(SIGSEGV));
}

void
unblock()
{
    sigsetmask(oldsigmask);
}

void
allowsig()
{
    unblock();
    block();
}


XHostAddress *XHosts;
int	    HostAccessCount;
Bool	    HostAccessState;

void
XGrabHosts(dsp)
    Display    *dsp;
{
    XHosts = XListHosts(dsp, &HostAccessCount, &HostAccessState);
    XRemoveHosts(dsp, XHosts, HostAccessCount);
    XEnableAccessControl(dsp);
}

void
XUngrabHosts(dsp)
    Display    *dsp;
{
    XAddHosts(dsp, XHosts, HostAccessCount);
    XFree(XHosts);
    if (HostAccessState == False)
	XDisableAccessControl(dsp);
}


void
GrabKeyboardAndMouse()
{
    Status	status;

    status = XGrabKeyboard(dsp, w, True,
			   GrabModeAsync, GrabModeAsync, CurrentTime);
    if (status != GrabSuccess)
	error("%s: couldn't grab keyboard! (%d)\n", status);
    status = XGrabPointer(dsp, w, True, -1,
			  GrabModeAsync, GrabModeAsync, None, mycursor,
			  CurrentTime);
    if (status != GrabSuccess)
	error("%s: couldn't grab pointer! (%d)\n", status);
}


void
XChangeGrabbedCursor(cursor)
    Cursor	cursor;
{
    XGrabPointer(dsp, w, True, -1,
		 GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime);
}

void
finish()
{
    XSync(dsp, 0);
    XUngrabHosts(dsp);
    XUngrabPointer(dsp, CurrentTime);
    XUngrabKeyboard(dsp, CurrentTime);
    XSetScreenSaver(dsp, timeout, interval, blanking, exposures);
    XDestroyWindow(dsp, w);
    if (color)
	XUninstallColormap(dsp, cmap);
    XFlush(dsp);
    XCloseDisplay(dsp);
}

void
sigcatch()
{
    finish();
    error("%s: caught terminate signal.\nAccess control list restored.\n");
}

int
ReadXString(s, slen)
    char       *s;
    int		slen;
{
    XEvent	event;
    char	keystr[20];
    char	c;
    int		i,
		bp,
		len,
		loops;
    char       *pwbuf = (char *) malloc(slen);

    XSetForeground(dsp, gc, BlackPixel(dsp, screen));
    init(dsp, icon, gc, color, inittime, count);
    bp = 0;
    nice(-nicelevel);		/* make sure we can read the keystrokes... */
    while (True) {
	loops = 0;
	while (!XPending(dsp)) {
	    allowsig();
	    callback();
	    if (reinit())
		init(dsp, icon, gc, color, inittime, count);
	    if (++loops >= ICONLOOPS) {
		nice(nicelevel);
		free(pwbuf);
		return 1;
	    }
	}
	XNextEvent(dsp, &event);
	switch (event.type) {
	case KeyPress:
	    len = XLookupString((XKeyEvent *) & event, keystr, 20, NULL, NULL);
	    for (i = 0; i < len; i++) {
		c = keystr[i];
		switch (c) {
		case 8:	/* ^H */
		case 127:	/* DEL */
		    if (bp > 0)
			bp--;
		    break;
		case 10:	/* ^J */
		case 13:	/* ^M */
		    s[bp] = '\0';
		    nice(nicelevel);
		    free(pwbuf);
		    return 0;
		case 21:	/* ^U */
		    bp = 0;
		    break;
		default:
		    s[bp] = c;
		    if (bp < slen - 1)
			bp++;
		}
	    }
	    memset(pwbuf, '?', slen);
	    XSetForeground(dsp, gc, white.pixel);
	    XFillRectangle(dsp, w, gc, passx, passy - font->ascent,
			   XTextWidth(font, pwbuf, slen),
			   font->ascent + font->descent);
	    XDrawString(dsp, w, textgc, passx, passy, pwbuf, bp);
	    break;

	case ButtonPress:
	    if (((XButtonEvent *) & event)->window == icon) {
		nice(nicelevel);
		free(pwbuf);
		return 1;
	    }
	    break;

	case KeyRelease:
	case ButtonRelease:
	case MotionNotify:
	case LeaveNotify:
	case EnterNotify:
	    break;

	default:
	    fprintf(stderr, "%s: unexpected event: %d\n", pname, event.type);
	    break;
	}
    }
}

int
getPassword()
{
#define PASSLENGTH 20
    char	buffer[PASSLENGTH];
    char	userpass[PASSLENGTH];
    char	rootpass[PASSLENGTH];
    struct passwd *pw;
    XWindowAttributes xgwa;
    char       *user = getenv("USER");
    char       *name = "Name: ";
    char       *pass = "Password: ";
    char       *info = "Enter password to unlock; select icon to lock.";
    char       *validate = "Validating login...";
    char       *invalid = "Invalid login.";
    int		y,
		left,
		done;

    XGetWindowAttributes(dsp, w, &xgwa);

    XChangeGrabbedCursor(XCreateFontCursor(dsp, XC_left_ptr));

    XSetForeground(dsp, gc, WhitePixel(dsp, screen));
    XFillRectangle(dsp, w, gc, 0, 0, xgwa.width, xgwa.height);

    XMapWindow(dsp, icon);
    XRaiseWindow(dsp, icon);

    left = ICONX + ICONW + font->max_bounds.width;
    y = ICONY + font->ascent;

    XDrawString(dsp, w, textgc, left, y, name, strlen(name));
    XDrawString(dsp, w, textgc, left + 1, y, name, strlen(name));
    XDrawString(dsp, w, textgc,
		left + XTextWidth(font, name, strlen(name)), y,
		user, strlen(user));

    y += font->ascent + font->descent + 2;
    XDrawString(dsp, w, textgc, left, y, pass, strlen(pass));
    XDrawString(dsp, w, textgc, left + 1, y, pass, strlen(pass));

    passx = left + 1 + XTextWidth(font, pass, strlen(pass))
	+ XTextWidth(font, " ", 1);
    passy = y;

    y = ICONY + ICONH + font->ascent + 2;
    XDrawString(dsp, w, textgc, ICONX, y, info, strlen(info));

    XFlush(dsp);

    y += font->ascent + font->descent + 2;

    pw = getpwuid(0);
    strcpy(rootpass, pw->pw_passwd);

    pw = getpwuid(getuid());
    strcpy(userpass, pw->pw_passwd);

    done = False;
    while (!done) {

	if (ReadXString(buffer, PASSLENGTH)) {
	    XChangeGrabbedCursor(mycursor);
	    XUnmapWindow(dsp, icon);
	    XSetForeground(dsp, gc, WhitePixel(dsp, screen));
	    return 1;
	}
	XSetForeground(dsp, gc, WhitePixel(dsp, screen));
	XFillRectangle(dsp, w, gc, ICONX, y - font->ascent,
		       XTextWidth(font, validate, strlen(validate)),
		       font->ascent + font->descent + 2);

	XDrawString(dsp, w, textgc, ICONX, y, validate, strlen(validate));

	done = !((strcmp(crypt(buffer, userpass), userpass))
		 && (skipRoot || strcmp(crypt(buffer, rootpass), rootpass)));

	if (!done) {
	    XFlush(dsp);
	    sleep(1);
	    XFillRectangle(dsp, w, gc, ICONX, y - font->ascent,
			   XTextWidth(font, validate, strlen(validate)),
			   font->ascent + font->descent + 2);

	    XDrawString(dsp, w, textgc, ICONX, y, invalid, strlen(invalid));
	}
    }
    return 0;
}

void
justDisplay()
{
    XEvent	event;

    init(dsp, w, gc, color, inittime, count);
    do {
	while (!XPending(dsp)) {
	    callback();
	    if (reinit())
		init(dsp, w, gc, color, inittime, count);
	}
	XNextEvent(dsp, &event);
    } while (event.type != ButtonPress && event.type != KeyPress);
}

void
lockDisplay()
{
    do {
	justDisplay();
    } while (getPassword());
}

void
usage(s)
    char       *s;
{
    int		i;

    fprintf(stderr, "%s\nusage: %s [-display dsp] [-mode %s",
	    s, pname, LockProcs[0].cmdline_arg);
    for (i = 1; i < NUMPROCS; i++)
	fprintf(stderr, " | %s", LockProcs[i].cmdline_arg);
    fprintf(stderr, "]\n");
    fprintf(stderr, "\t%s %s\n",
	    "[-time n] [-count n] [-nice n]",
	    "[-font f] [-mono] [-saver] [-root] [-v]");
    exit(1);
}

void
BuildPointersFromString(s)
    char       *s;
{
    int		i;

    for (i = 0; i < NUMPROCS; i++) {
	if (!strncmp(LockProcs[i].cmdline_arg, s, strlen(s))) {
	    reinit = LockProcs[i].lp_reinit;
	    callback = LockProcs[i].lp_callback;
	    init = LockProcs[i].lp_init;
	    if (verbose)
		fprintf(stderr, "Mode: %s\n", s);
	    return;
	}
    }
    usage("Unknown Mode.");
}

main(argc, argv)
    int		argc;
    char       *argv[];
{
    XSetWindowAttributes xswa;
    XGCValues	xgcv;
    int		i;
    char       *s;
    int		n;

    pname = argv[0];
    color = True;
    lock = True;
    skipRoot = -1;

    for (i = 1; i < argc; i++) {
	s = argv[i];
	n = strlen(s);
	if (!strncmp("-display", s, n)) {
	    if (++i >= argc)
		usage(s);
	    display = argv[i];
	} else if (!strncmp("-mono", s, n)) {
	    color = False;
	} else if (!strncmp("-saver", s, n)) {
	    lock = False;
	} else if (!strncmp("-root", s, n)) {
	    skipRoot = False;
	} else if (!strncmp("-verbose", s, n)) {
	    verbose = True;
	} else if (!strncmp("-time", s, n)) {
	    if (++i >= argc)
		usage(s);
	    inittime = atoi(argv[i]);
	    if (inittime < 1)
		usage("-time argument must be positive.");
	} else if (!strncmp("-count", s, n)) {
	    if (++i >= argc)
		usage(s);
	    count = atoi(argv[i]);
	    if (count < 1)
		usage("-count argument must be positive.\n");
	} else if (!strncmp("-nice", s, n)) {
	    if (++i >= argc)
		usage(s);
	    nicelevel = atoi(argv[i]);
	} else if (!strncmp("-font", s, n)) {
	    if (++i >= argc)
		usage(s);
	    fontname = argv[i];
	} else if (!strncmp("-mode", s, n)) {
	    if (++i >= argc)
		usage(s);
	    BuildPointersFromString(argv[i]);
	} else {
	    fprintf(stderr, "Bad switch: ");
	    usage(s);
	}
    }

    if (display == NULL)
	display = getenv("DISPLAY");

    if (display != NULL) {
	char	   *colon = strchr(display, ':');
	int	    n = colon - display;
	char	    hostname[MAXHOSTNAMELEN];

	if (gethostname(hostname, MAXHOSTNAMELEN))
	    error("%s: Can't get local hostname.\n");

	if (colon == NULL)
	    error("%s: Malformed -display argument, \"%s\"\n", display);

	if (n) {
	    if (strncmp(display, "unix", n)
	     && strncmp(display, "localhost", n)
	     && strncmp(display, hostname, n)) {
		*colon = (char) 0;
		error("%s: can't lock %s's display\n", display);
	     }
	}
    } else
	display = DEFAULT_DISPLAY;

    if (lock) {
	block();
	signal(SIGINT, sigcatch);
	signal(SIGQUIT, sigcatch);
	signal(SIGSEGV, sigcatch);
    }
    if (!(dsp = XOpenDisplay(display)))
	error("%s: unable to open display %s.\n", display);

    if (fontname == NULL)
	fontname = XGetDefault(dsp, pname, "font");
    if (fontname == NULL)
	fontname = DEFAULT_FONTNAME;

    if (count == -1) {
	s = XGetDefault(dsp, pname, "count");
	if (s != NULL)
	    count = atoi(s);
	else
	    count = DEFAULT_COUNT;
    }
    if (nicelevel == -1) {
	s = XGetDefault(dsp, pname, "nice");
	if (s != NULL)
	    nicelevel = atoi(s);
	else
	    nicelevel = DEFAULT_NICE;
    }
    if (inittime == -1) {
	s = XGetDefault(dsp, pname, "time");
	if (s != NULL)
	    inittime = atoi(s);
	else
	    inittime = DEFAULT_INITTIME;
    }
    if (init == NULL) {
	s = XGetDefault(dsp, pname, "mode");
	if (s != NULL) {
	    BuildPointersFromString(s);
	} else {
	    reinit = LockProcs[0].lp_reinit;
	    callback = LockProcs[0].lp_callback;
	    init = LockProcs[0].lp_init;
	    if (verbose)
		fprintf(stderr, "Mode: %s\n", LockProcs[0].cmdline_arg);
	}
    }
    if (skipRoot == -1) {
	s = XGetDefault(dsp, pname, "root");
	if (s != NULL)
	    skipRoot = !(strncmp("on", s, strlen(s)) == 0);
	else
	    skipRoot = DEFAULT_SKIPROOT;
    }
    if (verbose) {
	fprintf(stderr,
		"%s: Font: %s, Time: %d, Root: %s, Nice: %d\n", pname,
		fontname, inittime, skipRoot ? "False" : "True", nicelevel);
    }
    font = XLoadQueryFont(dsp, fontname);
    if (font == NULL) {
	fprintf(stderr, "%s: can't find font: %s, using %s...\n",
		pname, fontname, BACKUP_FONTNAME);
	font = XLoadQueryFont(dsp, BACKUP_FONTNAME);
	if (font == NULL)
	    error("%s: can't even find %s!!!\n", BACKUP_FONTNAME);
    }
    screen = DefaultScreen(dsp);
    if (color)
	color = (DisplayCells(dsp, screen) > 2);
    root = RootWindow(dsp, screen);

    if (color) {
	if (XCreateHSBColormap(dsp, screen, &cmap, DisplayCells(dsp, screen),
			       0.0, 1.0, 1.0, 1.0, 1.0, 1.0, True) != Success)
	    error("%s: couldn't create colormap.");
    } else
	cmap = DefaultColormap(dsp, screen);

    black.pixel = BlackPixel(dsp, screen);
    XQueryColor(dsp, cmap, &black);

    white.pixel = WhitePixel(dsp, screen);
    XQueryColor(dsp, cmap, &white);

    lockc = XCreateBitmapFromData(dsp, root, no_bits, 1, 1);
    lockm = XCreateBitmapFromData(dsp, root, no_bits, 1, 1);
    mycursor = XCreatePixmapCursor(dsp, lockc, lockm, &black, &black, 0, 0);
    XFreePixmap(dsp, lockc);
    XFreePixmap(dsp, lockm);

    xswa.cursor = mycursor;
    xswa.override_redirect = True;
    xswa.background_pixel = black.pixel;
    xswa.event_mask = KeyPressMask | ButtonPressMask;

    w = XCreateWindow(dsp, root,
		      0, 0,
		      DisplayWidth(dsp, screen),
		      DisplayHeight(dsp, screen),
		      0, CopyFromParent, InputOutput, CopyFromParent,
		      CWCursor | CWOverrideRedirect |
		      CWBackPixel | CWEventMask, &xswa);

    xswa.cursor = XCreateFontCursor(dsp, XC_target);
    xswa.background_pixel = white.pixel;
    xswa.event_mask = ButtonPressMask;

    icon = XCreateWindow(dsp, w,
			 ICONX, ICONY,
			 ICONW, ICONH,
			 1, CopyFromParent, InputOutput, CopyFromParent,
			 CWCursor | CWBackPixel | CWEventMask, &xswa);

    XMapWindow(dsp, w);
    XRaiseWindow(dsp, w);

    xgcv.foreground = white.pixel;
    xgcv.background = black.pixel;
    gc = XCreateGC(dsp, w, GCForeground | GCBackground, &xgcv);

    xgcv.foreground = black.pixel;
    xgcv.background = white.pixel;
    xgcv.font = font->fid;
    textgc = XCreateGC(dsp, w, GCFont | GCForeground | GCBackground, &xgcv);

    XGetScreenSaver(dsp, &timeout, &interval, &blanking, &exposures);
    XSetScreenSaver(dsp, 0, 0, 0, 0);	/* disable screen saver */
    GrabKeyboardAndMouse();

    if (lock) {
	XGrabHosts(dsp);
	allowsig();
    }
    nice(nicelevel);
    srandom(getpid());

    if (color)
	XInstallColormap(dsp, cmap);

    if (lock)
	lockDisplay();
    else
	justDisplay();

    finish();

    if (lock)
	unblock();

    exit(0);
}
SHAR_EOF
fi
if test -f 'hopalong.c'
then
	echo shar: "will not over-write existing file 'hopalong.c'"
else
cat << \SHAR_EOF > 'hopalong.c'
#ifndef lint
static char sccsid[] = "@(#)hopalong.c 22.2 89/09/20";
#endif
/*-
 * hopalong.c - Real Plane Fractals for the xlock X11 terminal locker.
 *
 * Copyright (c) 1988-89 by Patrick Naughton and Sun Microsystems, Inc.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * This file is provided AS IS with no warranties of any kind.  The author
 * shall have no liability with respect to the infringement of copyrights,
 * trade secrets or any patents by this file or any part thereof.  In no
 * event will the author be liable for any lost revenue or profits or
 * other special, indirect and consequential damages.
 *
 * Comments and additions should be sent to the author:
 *
 *		       naughton at sun.com
 *
 *		       Patrick J. Naughton
 *		       Window Systems Group, MS 14-40
 *		       Sun Microsystems, Inc.
 *		       2550 Garcia Ave
 *		       Mountain View, CA  94043
 *
 * Revision History:
 * 20-Sep-89: Lint.
 * 31-Aug-88: Forked from xlock.c for modularity.
 * 23-Mar-88: Coded HOPALONG routines from Scientific American Sept. 86 p. 14.
 */

#include <math.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

static int  centerx,
	    centery;		/* center of the screen */
static double a,
	    b,
	    c,
	    i,
	    j;			/* hopalong parameters */
static int  color;
static unsigned long pix = 0;
static Display *Dsp;
static Window Win;
static GC   Gc;
static XPoint *pointBuffer = 0;	/* pointer for XDrawPoints */
static int  Npoints = 0;
static long startTime;
static int  timeout;

static long
seconds()
{
    struct timeval foo;

    gettimeofday(&foo, (struct timezone *) 0);
    return (foo.tv_sec);
}

void
inithop(d, w, g, c, t, n, p, x, y, A, B, C)
    Display    *d;
    Window	w;
    GC		g;
    int		c,
		t,
		n,
		p,
		x,
		y;
    double	A,
		B,
		C;
{
    i = j = 0.0;
    startTime = seconds();

    if ((pointBuffer) || (n != Npoints)) {
	if (pointBuffer)
	    free((char *) pointBuffer);
	pointBuffer = (XPoint *) malloc(n * sizeof(XPoint));
	Npoints = n;
    }
    Dsp = d;
    Win = w;
    Gc = g;
    color = c;
    timeout = t;
    if (p >= 0)
	pix = (unsigned long) p;
    centerx = x;
    centery = y;
    a = A;
    b = B;
    c = C;
    XClearWindow(Dsp, Win);
}


void
randomInithop(d, w, g, c, t, n)
    Display    *d;
    Window	w;
    GC		g;
    int		c,
		t,
		n;
{
    int		range;
    XWindowAttributes xgwa;
    double	A,
		B,
		C;
    int		x,
		y;

    XGetWindowAttributes(d, w, &xgwa);
    x = xgwa.width / 2;
    y = xgwa.height / 2;
    range = (int) sqrt((double) x * x + (double) y * y);
    A = random() % (range * 100) * (random() % 2 ? -1.0 : 1.0) / 100.0;
    B = random() % (range * 100) * (random() % 2 ? -1.0 : 1.0) / 100.0;
    C = random() % (range * 100) * (random() % 2 ? -1.0 : 1.0) / 100.0;

    if (!(random() % 3))
	a /= 10.0;
    if (!(random() % 2))
	b /= 100.0;

    inithop(d, w, g, c, t, n, -1, x, y, A, B, C);
}

int
hopdone()
{
    return (seconds() - startTime > timeout);
}


void
hop()
{
    register double oldj;
    register int k = Npoints;
    register XPoint *xp = pointBuffer;

    if (color) {
	XSetForeground(Dsp, Gc, pix++);
	pix %= 254;
    }
    while (k--) {
	oldj = j;
	j = a - i;
	i = oldj + (i < 0 ? sqrt(fabs(b * i - c)) : -sqrt(fabs(b * i - c)));
	xp->x = centerx + (int) (i + j);
	xp->y = centery - (int) (i - j);
	xp++;
    }
    XDrawPoints(Dsp, Win, Gc, pointBuffer, Npoints, CoordModeOrigin);
}
SHAR_EOF
fi
if test -f 'qix.c'
then
	echo shar: "will not over-write existing file 'qix.c'"
else
cat << \SHAR_EOF > 'qix.c'
#ifndef lint
static char sccsid[] = "@(#)qix.c 22.4 89/09/23";
#endif
/*-
 * qix.c - The old standby vector swirl for the xlock X11 terminal locker.
 *
 * Copyright (c) 1989 by Sun Microsystems Inc.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * This file is provided AS IS with no warranties of any kind.  The author
 * shall have no liability with respect to the infringement of copyrights,
 * trade secrets or any patents by this file or any part thereof.  In no
 * event will the author be liable for any lost revenue or profits or
 * other special, indirect and consequential damages.
 *
 * Comments and additions should be sent to the author:
 *
 *		       naughton at sun.com
 *
 *		       Patrick J. Naughton
 *		       Window Systems Group, MS 14-40
 *		       Sun Microsystems, Inc.
 *		       2550 Garcia Ave
 *		       Mountain View, CA  94043
 *
 * Revision History:
 * 23-Sep-89: Switch to random() and fixed bug w/ less than 4 lines.
 * 20-Sep-89: Lint.
 * 24-Mar-89: Written.
 */

#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

static Display *Dsp;
static Window Win;
static GC   Gc,
	    eraseGC = (GC) 0;
static int  timeout;
static int  color;
static unsigned long pix = 0;
static long startTime;
static int  first,
	    last,
	    dx1,
	    dy1,
	    dx2,
	    dy2,
	    x1,
	    y1,
	    x2,
	    y2,
	    offset,
	    delta,
	    width,
	    height;

typedef struct {
    int		x,
		y;
}	    point;

static int  Nlines = 0;
static point *lineq = (point *) 0;

static long
seconds()
{
    struct timeval foo;

    gettimeofday(&foo, (struct timezone *) 0);
    return (foo.tv_sec);
}

void
initqix(d, w, g, c, t, n)
    Display    *d;
    Window	w;
    GC		g;
    int		c,
		t,
		n;
{
    XWindowAttributes xgwa;
    XGCValues	xgcv;

    startTime = seconds();
    if (n < 4)
	n = 4;

    if (n != Nlines) {
	if (lineq)
	    free((char *) lineq);
	lineq = (point *) malloc(n * sizeof(point));
	Nlines = n;
    }
    Dsp = d;
    Win = w;
    Gc = g;
    color = c;
    timeout = t;

    if (eraseGC == (GC) 0) {
	xgcv.foreground = BlackPixel(Dsp, 0);
	eraseGC = XCreateGC(Dsp, Win, GCForeground, &xgcv);
    }
    if (!color)
	XSetForeground(Dsp, Gc, WhitePixel(Dsp, 0));

    XGetWindowAttributes(Dsp, Win, &xgwa);
    width = xgwa.width;
    height = xgwa.height;

    if (width < 100)		/* icon window */
	delta = 2;
    else
	delta = 15;
    offset = delta / 3;
    last = 0;

    srandom(time((long *) 0));
    dx1 = random() & (width - 1) + 50;
    dy1 = random() & (height - 1) + 50;
    dx2 = random() & (width - 1) + 50;
    dy2 = random() & (height - 1) + 50;
    x1 = random() & width;
    y1 = random() & height;
    x2 = random() & width;
    y2 = random() & height;
    XFillRectangle(Dsp, Win, eraseGC, 0, 0, width, height);
}

int
qixdone()
{
    return (seconds() - startTime > timeout);
}

void
drawqix()
{
    register int n = Nlines;

    while (n--) {
	first = (last + 2) % Nlines;

	x1 += dx1;
	y1 += dy1;
	x2 += dx2;
	y2 += dy2;
	check_bounds_x(x1, &dx1);
	check_bounds_y(y1, &dy1);
	check_bounds_x(x2, &dx2);
	check_bounds_y(y2, &dy2);
	if (color) {
	    XSetForeground(Dsp, Gc, pix++);
	    if (pix > 253)
		pix = 0;
	}
	XDrawLine(Dsp, Win, eraseGC,
		  lineq[first].x, lineq[first].y,
		  lineq[first + 1].x, lineq[first + 1].y);
	XDrawLine(Dsp, Win, Gc, x1, y1, x2, y2);

	lineq[last].x = x1;
	lineq[last].y = y1;
	last += 1;
	if (last >= Nlines)
	    last = 0;

	lineq[last].x = x2;
	lineq[last].y = y2;
	last += 1;
	if (last >= Nlines)
	    last = 0;
    }
}

static
check_bounds_y(y, dy)
    int		y,
	       *dy;
{
    if (y < 0) {
	*dy = (random() & delta) + offset;
    } else if (y > height) {
	*dy = -(random() & delta) - offset;
    }
}

static
check_bounds_x(x, dx)
    int		x,
	       *dx;
{
    if (x < 0) {
	*dx = (random() & delta) + offset;
    } else if (x > width) {
	*dx = -(random() & delta) - offset;
    }
}
SHAR_EOF
fi
if test -f 'life.c'
then
	echo shar: "will not over-write existing file 'life.c'"
else
cat << \SHAR_EOF > 'life.c'
#ifndef lint
static char sccsid[] = "@(#)life.c 22.1 89/09/20";
#endif
/*-
 * life.c - Conway's game of Life for the xlock X11 terminal locker.
 *
 * Copyright (c) 1989 by Sun Microsystems, Inc.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * This file is provided AS IS with no warranties of any kind.	The author
 * shall have no liability with respect to the infringement of copyrights,
 * trade secrets or any patents by this file or any part thereof.  In no
 * event will the author be liable for any lost revenue or profits or
 * other special, indirect and consequential damages.
 *
 * Comments and additions should be sent to the authors:
 *
 *		       flar at sun.com or naughton at sun.com
 *
 *		       James A. Graham
 *		       Patrick J. Naughton
 *		       Window Systems Group, MS 14-40
 *		       Sun Microsystems, Inc.
 *		       2550 Garcia Ave
 *		       Mountain View, CA  94043
 *
 * Revision History:
 * 20-Sep-89: Written.
 */

#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "lifeicon.bit";

static XImage logo = {
    0, 0,			/* width, height */
    0, XYBitmap, 0,		/* xoffset, format, data */
    LSBFirst, 8,		/* byte-order, bitmap-unit */
    LSBFirst, 8, 1		/* bitmap-bit-order, bitmap-pad, depth */
};

static Display *Dsp;
static Window Win;
static GC   Gc;
static GC   eraseGC = (GC) 0;
static int  timeout;
static int  shooter;
static int  delay;
static int  color;
static int  pixels;
static int  width,
            height;
static int  xs,
            ys,
            xb,
            yb;
static long startTime;

#define	NROWS	30
#define NCOLS	38

/* Buffer stores the data for each cell.  Each cell is stored as
 * 8 bits representing the presence of a critter in each of it's
 * surrounding 8 cells.	 There is an empty row and column around
 * the whole array to allow stores without bounds checking as well
 * as an extra row at the end for the fetches into tempbuf.
 */
#define	UPLT	0x01
#define UP	0x02
#define UPRT	0x04
#define LT	0x08
#define RT	0x10
#define DNLT	0x20
#define DN	0x40
#define DNRT	0x80
static unsigned char buffer[(NROWS + 2) * (NCOLS + 2) + 2];
static unsigned char agebuf[(NROWS + 2) * (NCOLS + 2)];

/* Tempbuf stores the data for the next two rows so that we know
 * the state of those critter before he was modified by the fate
 * of the critters that have already been processed.
 */
static unsigned char tempbuf[NCOLS * 2];

/* Fates is a lookup table for the fate of a critter.  The 256
 * entries represent the 256 possible combinations of the 8
 * neighbor cells.  Each entry is one of BIRTH (create a cell
 * or leave one alive), SAME (leave the cell alive or dead),
 * or DEATH (kill anything in the cell).
 */
#define BIRTH	0
#define SAME	1
#define DEATH	2
static unsigned char fates[256];


static int  patterns[][200] = {
    {				/* EIGHT */
	-3, -3, -2, -3, -1, -3,
	-3, -2, -2, -2, -1, -2,
	-3, -1, -2, -1, -1, -1,
	0, 0, 1, 0, 2, 0,
	0, 1, 1, 1, 2, 1,
	0, 2, 1, 2, 2, 2,
	99
    },
    {				/* PULSAR */
	1, 1, 2, 1, 3, 1, 4, 1, 5, 1,
	1, 2, 5, 2,
	99
    },
    {				/* BARBER */
	-7, -7, -6, -7,
	-7, -6, -5, -6,
	-5, -4, -3, -4,
	-3, -2, -1, -2,
	-1, 0, 1, 0,
	1, 2, 3, 2,
	3, 4, 5, 4,
	4, 5, 5, 5,
	99
    },
    {				/* HERTZ */
	-2, -6, -1, -6,
	-2, -5, -1, -5,
	-7, -3, -6, -3, -2, -3, -1, -3, 0, -3, 1, -3, 5, -3, 6, -3,
	-7, -2, -5, -2, -3, -2, 2, -2, 4, -2, 6, -2,
	-5, -1, -3, -1, -2, -1, 2, -1, 4, -1,
	-7, 0, -5, 0, -3, 0, 2, 0, 4, 0, 6, 0,
	-7, 1, -6, 1, -2, 1, -1, 1, 0, 1, 1, 1, 5, 1, 6, 1,
	-2, 3, -1, 3,
	-2, 4, -1, 4,
	99
    },
    {				/* TUMBLER */
	-6, -6, -5, -6, 6, -6, 7, -6,
	-6, -5, -5, -5, 6, -5, 7, -5,
	-5, 5, 6, 5,
	-7, 6, -5, 6, 6, 6, 8, 6,
	-7, 7, -5, 7, 6, 7, 8, 7,
	-7, 8, -6, 8, 7, 8, 8, 8,
	99
    },
    {				/* PERIOD4 */
	-5, -8, -4, -8,
	-7, -7, -5, -7,
	-8, -6, -2, -6,
	-7, -5, -3, -5, -2, -5,
	-5, -3, -3, -3,
	-4, -2,
	99
    },
    {				/* PERIOD5 */
	-5, -8, -4, -8,
	-6, -7, -3, -7,
	-7, -6, -2, -6,
	-8, -5, -1, -5,
	-8, -4, -1, -4,
	-7, -3, -2, -3,
	-6, -2, -3, -2,
	-5, -1, -4, -1,
	99
    },
    {				/* PERIOD6 */
	-4, -8, -3, -8,
	-8, -7, -7, -7, -5, -7,
	-8, -6, -7, -6, -4, -6, -1, -6,
	-3, -5, -1, -5,
	-2, -4,
	-3, -2, -2, -2,
	-3, -1, -2, -1,
	99
    },
    {				/* PINWHEEL */
	-4, -8, -3, -8,
	-4, -7, -3, -7,
	-4, -5, -3, -5, -2, -5, -1, -5,
	-5, -4, -3, -4, 0, -4, 2, -4, 3, -4,
	-5, -3, -1, -3, 0, -3, 2, -3, 3, -3,
	-8, -2, -7, -2, -5, -2, -2, -2, 0, -2,
	-8, -1, -7, -1, -5, -1, 0, -1,
	-4, 0, -3, 0, -2, 0, -1, 0,
	-2, 2, -1, 2,
	-2, 3, -1, 3,
	99
    },
    {				/* ] */
	-1, -1, 0, -1, 1, -1,
	0, 0, 1, 0,
	-1, 1, 0, 1, 1, 1,
	99
    },
    {				/* cc: */
	-3, -1, -2, -1, -1, -1, 1, -1, 2, -1, 3, -1,
	-3, 0, -2, 0, 1, 0, 2, 0,
	-3, 1, -2, 1, -1, 1, 1, 1, 2, 1, 3, 1,
	99
    },
    {				/* DOLBY */
	-3, -1, -2, -1, -1, -1, 1, -1, 2, -1, 3, -1,
	-3, 0, -2, 0, 2, 0, 3, 0,
	-3, 1, -2, 1, -1, 1, 1, 1, 2, 1, 3, 1,
	99
    },
    {				/* HORIZON */
	-15, 0, -14, 0, -13, 0, -12, 0, -11, 0,
	-10, 0, -9, 0, -8, 0, -7, 0, -6, 0,
	-5, 0, -4, 0, -3, 0, -2, 0, -1, 0,
	4, 0, 3, 0, 2, 0, 1, 0, 0, 0,
	9, 0, 8, 0, 7, 0, 6, 0, 5, 0,
	14, 0, 13, 0, 12, 0, 11, 0, 10, 0,
	99
    },
    {				/* SHEAR */
	-7, -2, -6, -2, -5, -2, -4, -2, -3, -2,
	-2, -2, -1, -2, 0, -2, 1, -2, 2, -2,
	-5, -1, -4, -1, -3, -1, -2, -1, -1, -1,
	0, -1, 1, -1, 2, -1, 3, -1, 4, -1,
	-3, 0, -2, 0, -1, 0, 0, 0, 1, 0,
	2, 0, 3, 0, 4, 0, 5, 0, 6, 0,
	-10, 1, -9, 1, -8, 1, -7, 1, -6, 1,
	-5, 1, -4, 1, -3, 1, -2, 1, -1, 1,
	-10, 2, -9, 2, -8, 2, -7, 2, -6, 2,
	-5, 2, -4, 2, -3, 2, -2, 2, -1, 2,
	99
    },
    {				/* VERTIGO */
	0, -7,
	0, -6,
	0, -5,
	0, -4,
	0, -3,
	0, -2,
	0, -1,
	0, 0,
	0, 7,
	0, 6,
	0, 5,
	0, 4,
	0, 3,
	0, 2,
	0, 1,
	99
    },
    {				/* CROSSBAR */
	-5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 4, 0, 3, 0, 2, 0, 1, 0, 0, 0,
	99
    },
    {				/* GOALPOSTS */
	-8, -7, 8, -7,
	-8, -6, 8, -6,
	-8, -5, 8, -5,
	-8, -4, 8, -4,
	-8, -3, 8, -3,
	-8, -2, 8, -2,
	-8, -1, 8, -1,
	-8, 0, 8, 0,
	-8, 1, 8, 1,
	-8, 2, 8, 2,
	-8, 3, 8, 3,
	-8, 4, 8, 4,
	-8, 5, 8, 5,
	-8, 6, 8, 6,
	-8, 7, 8, 7,
	99
    },
    {				/* \ */
	-8, -8, -7, -8,
	-7, -7, -6, -7,
	-6, -6, -5, -6,
	-5, -5, -4, -5,
	-4, -4, -3, -4,
	-3, -3, -2, -3,
	-2, -2, -1, -2,
	-1, -1, 0, -1,
	0, 0, 1, 0,
	1, 1, 2, 1,
	2, 2, 3, 2,
	3, 3, 4, 3,
	4, 4, 5, 4,
	5, 5, 6, 5,
	6, 6, 7, 6,
	7, 7, 8, 7,
	99
    },
    {				/* LABYRINTH */
	-4, -4, -3, -4, -2, -4, -1, -4, 0, -4, 1, -4, 2, -4, 3, -4, 4, -4,
	-4, -3, 0, -3, 4, -3,
	-4, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, 4, -2,
	-4, -1, -2, -1, 2, -1, 4, -1,
	-4, 0, -2, 0, -1, 0, 0, 0, 1, 0, 2, 0, 4, 0,
	-4, 1, -2, 1, 2, 1, 4, 1,
	-4, 2, -2, 2, -1, 2, 0, 2, 1, 2, 2, 2, 4, 2,
	-4, 3, 0, 3, 4, 3,
	-4, 4, -3, 4, -2, 4, -1, 4, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4,
	99
    }
};

#define NPATS	(sizeof(patterns)/sizeof(patterns[0]))

static void
drawcell(row, col, age)
    unsigned char age;
{
    if (color)
	XSetForeground(Dsp, Gc, (unsigned long) age);
    if (pixels)
	XFillRectangle(Dsp, Win, Gc,
		       xb + xs * col, yb + ys * row, xs, ys);
    else
	XPutImage(Dsp, Win, Gc, &logo,
		  0, 0, xb + xs * col, yb + ys * row,
		  lifeicon_width, lifeicon_height);
}

static void
erasecell(row, col)
{
    XFillRectangle(Dsp, Win, eraseGC,
		   xb + xs * col, yb + ys * row, xs, ys);
}

static void
spawn(loc)
    unsigned char *loc;
{
    *(loc - NCOLS - 2 - 1) |= UPLT;
    *(loc - NCOLS - 2) |= UP;
    *(loc - NCOLS - 2 + 1) |= UPRT;
    *(loc - 1) |= LT;
    *(loc + 1) |= RT;
    *(loc + NCOLS + 2 - 1) |= DNLT;
    *(loc + NCOLS + 2) |= DN;
    *(loc + NCOLS + 2 + 1) |= DNRT;
    *(agebuf + (loc - buffer)) = 0;
}

static void
kill(loc)
    unsigned char *loc;
{
    *(loc - NCOLS - 2 - 1) &= ~UPLT;
    *(loc - NCOLS - 2) &= ~UP;
    *(loc - NCOLS - 2 + 1) &= ~UPRT;
    *(loc - 1) &= ~LT;
    *(loc + 1) &= ~RT;
    *(loc + NCOLS + 2 - 1) &= ~DNLT;
    *(loc + NCOLS + 2) &= ~DN;
    *(loc + NCOLS + 2 + 1) &= ~DNRT;
}

static void
setcell(row, col)
{
    register unsigned char *loc;

    loc = buffer + ((row + 1) * (NCOLS + 2)) + col + 1;
    spawn(loc);
    drawcell(row, col, 0);
}

static long
seconds()
{
    struct timeval foo;

    gettimeofday(&foo, (struct timezone *) 0);
    return foo.tv_sec;
}

void
drawlife()
{
    unsigned char *loc,
               *temploc;
    int         row,
                col,
                cells = 0;
    unsigned char fate;


    loc = buffer + NCOLS + 2 + 1;
    temploc = tempbuf;
    /* copy the first 2 rows to the tempbuf */
    bcopy(loc, temploc, NCOLS);
    bcopy(loc + NCOLS + 2, temploc + NCOLS, NCOLS);
    for (row = 0; row < NROWS; ++row) {
	for (col = 0; col < NCOLS; ++col) {
	    fate = fates[*temploc];
	    *temploc = *(loc + (NCOLS + 2) * 2);
	    switch (fate) {
	    case BIRTH:
		if (!(*(loc + 1) & RT)) {
		    spawn(loc);
		}
		/* NO BREAK */
	    case SAME:
		if (*(loc + 1) & RT) {
		    register unsigned char *ageptr;
		    register unsigned char age;

		    ++cells;
		    ageptr = agebuf + (loc - buffer);
		    age = *ageptr;
		    if (++age > 253)
			age = 0;
		    *ageptr = age;
		    drawcell(row, col, age);
		}
		break;
	    case DEATH:
		if (*(loc + 1) & RT) {
		    kill(loc);
		    erasecell(row, col);
		}
		break;
	    }
	    loc++;
	    temploc++;
	}
	loc += 2;
	if (temploc >= tempbuf + NCOLS * 2)
	    temploc = tempbuf;
    }
    XFlush(Dsp);
    usleep(delay * 1000);
    if (!cells)
	startTime = 0;
}

static void
init_fates()
{
    int         i,
                bits,
                neighbors;

    for (i = 0; i < 256; i++) {
	neighbors = 0;
	for (bits = i; bits; bits &= (bits - 1))
	    neighbors++;
	if (neighbors == 3)
	    fates[i] = BIRTH;
	else if (neighbors == 2)
	    fates[i] = SAME;
	else
	    fates[i] = DEATH;
    }
}

void
initlife(d, w, g, c, t, n)
    Display    *d;
    Window      w;
    GC          g;
    int         c,
                t,
                n;
{
    int         row,
                col;
    int        *patptr;
    XWindowAttributes xgwa;

    startTime = seconds();
    shooter = 0;
    Dsp = d;
    Win = w;
    Gc = g;
    color = c;
    timeout = t;
    delay = n;

    if (eraseGC == (GC) 0) {
	XGCValues   xgcv;

	xgcv.foreground = BlackPixel(Dsp, 0);
	eraseGC = XCreateGC(Dsp, Win, GCForeground, &xgcv);

	srandom(time((long *) 0));
	init_fates();
	logo.data = lifeicon_bits;
	logo.width = lifeicon_width;
	logo.height = lifeicon_height;
	logo.bytes_per_line = 4;
    }
    if (!color)
	XSetForeground(Dsp, Gc, WhitePixel(Dsp, 0));

    XGetWindowAttributes(Dsp, Win, &xgwa);
    width = xgwa.width;
    height = xgwa.height;
    xs = width / NCOLS;
    ys = height / NROWS;
    xb = (width - xs * NCOLS) / 2;
    yb = (height - ys * NROWS) / 2;
    pixels = (xs < lifeicon_width || ys < lifeicon_height);

    XFillRectangle(Dsp, Win, eraseGC, 0, 0, width, height);

    bzero(buffer, sizeof(buffer));
    patptr = &patterns[(random() >> 3) % NPATS][0];
    while ((col = *patptr++) != 99) {
	row = *patptr++;
	col += NCOLS / 2;
	row += NROWS / 2;
	setcell(row, col);
    }
    XFlush(Dsp);
    sleep(1);
}

int
lifedone()
{
    int         elapsedTime = seconds() - startTime;

    if (elapsedTime > timeout)
	return 1;
    if (!shooter && elapsedTime > timeout / 2) {
	setcell(0, 2);
	setcell(1, 2);
	setcell(2, 2);
	setcell(2, 1);
	setcell(1, 0);
	shooter = 1;
    }
    return 0;
}
SHAR_EOF
fi
if test -f 'lifeicon.bit'
then
	echo shar: "will not over-write existing file 'lifeicon.bit'"
else
cat << \SHAR_EOF > 'lifeicon.bit'
#define lifeicon_width 29
#define lifeicon_height 29
static char lifeicon_bits[] = {
   0x00, 0xe0, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0xb8, 0x03, 0x00,
   0x00, 0x74, 0x07, 0x00, 0x00, 0xee, 0x0e, 0x00, 0x00, 0xdd, 0x1d, 0x00,
   0x80, 0xbb, 0x3b, 0x00, 0x40, 0x77, 0x57, 0x00, 0xe0, 0xee, 0xee, 0x00,
   0x70, 0xdd, 0x75, 0x01, 0xb8, 0xbb, 0xb9, 0x03, 0xdc, 0xf1, 0xdd, 0x01,
   0xee, 0xee, 0xee, 0x0e, 0x77, 0x1f, 0x77, 0x1f, 0xbb, 0x1b, 0xbb, 0x1b,
   0xdf, 0x1d, 0xdf, 0x1d, 0xee, 0xee, 0xee, 0x0e, 0x70, 0xf7, 0x71, 0x07,
   0xb8, 0xb3, 0xbb, 0x03, 0xd0, 0x75, 0xd7, 0x01, 0xe0, 0xee, 0xee, 0x00,
   0x40, 0xdd, 0x5d, 0x00, 0x80, 0xbb, 0x3b, 0x00, 0x00, 0x77, 0x17, 0x00,
   0x00, 0xee, 0x0e, 0x00, 0x00, 0xdc, 0x05, 0x00, 0x00, 0xb8, 0x01, 0x00,
   0x00, 0xf0, 0x01, 0x00, 0x00, 0xe0, 0x00, 0x00};
SHAR_EOF
fi
if test -f 'XCrDynCmap.c'
then
	echo shar: "will not over-write existing file 'XCrDynCmap.c'"
else
cat << \SHAR_EOF > 'XCrDynCmap.c'
#ifndef lint
static char sccsid[] = "@(#)XCrDynCmap.c 22.2 89/09/20";
#endif
/*-
 * XCrDynCmap.c - X11 library routine to create dynamic colormaps.
 *
 * Copyright (c) 1989 by Sun Microsystems, Inc.
 *
 * Author: Patrick J. Naughton
 * naughton at sun.com
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * This file is provided AS IS with no warranties of any kind.  The author
 * shall have no liability with respect to the infringement of copyrights,
 * trade secrets or any patents by this file or any part thereof.  In no
 * event will the author be liable for any lost revenue or profits or
 * other special, indirect and consequential damages.
 *
 */

#include <X11/X.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

Status
XCreateDynamicColormap(dsp, screen, cmap, visual, colors,
		       count, red, green, blue)
    Display    *dsp;
    int		screen;
    Colormap   *cmap;
    Visual    **visual;
    XColor     *colors;
    int		count;
    u_char     *red,
	       *green,
	       *blue;
{
    XVisualInfo vinfo;
    int		pixels[256];
    int		i,
		ncolors,
		planes;
    unsigned long pmasks;
    Status	allocReturn;

    planes = DisplayPlanes(dsp, screen);
    if (XMatchVisualInfo(dsp, screen, planes, PseudoColor, &vinfo)) {

	*visual = vinfo.visual;
	*cmap = XCreateColormap(dsp, RootWindow(dsp, screen),
				*visual, AllocNone);
	ncolors = vinfo.colormap_size;

	if (count > ncolors)
	    return BadValue;

	allocReturn = XAllocColorCells(dsp, *cmap,
				       False, &pmasks, 0,
				       pixels, count);

/*	This should return Success, but it doesn't... Xlib bug?
 *	(I'll ignore the return value for now...)
 */
#ifdef NOTDEF
	if (allocReturn != Success)
	    return allocReturn;
#endif				/* NOTDEF */

	for (i = 0; i < count; i++) {
	    colors[i].pixel = pixels[i];
	    colors[i].red = *red++ << 8;
	    colors[i].green = *green++ << 8;
	    colors[i].blue = *blue++ << 8;
	    colors[i].flags = DoRed | DoGreen | DoBlue;
	}
	XStoreColors(dsp, *cmap, colors, count);
	return Success;
    } else
	return BadMatch;
}
SHAR_EOF
fi
if test -f 'XCrHsbCmap.c'
then
	echo shar: "will not over-write existing file 'XCrHsbCmap.c'"
else
cat << \SHAR_EOF > 'XCrHsbCmap.c'
#ifndef lint
static char sccsid[] = "@(#)XCrHsbCmap.c 22.2 89/09/20";
#endif
/*-
 * XCrHsbCmap.c - X11 library routine to create an HSB ramp colormaps.
 *
 * Copyright (c) 1989 by Sun Microsystems, Inc.
 *
 * Author: Patrick J. Naughton
 * naughton at sun.com
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * This file is provided AS IS with no warranties of any kind.  The author
 * shall have no liability with respect to the infringement of copyrights,
 * trade secrets or any patents by this file or any part thereof.  In no
 * event will the author be liable for any lost revenue or profits or
 * other special, indirect and consequential damages.
 *
 */

#include <X11/X.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>

extern void HSBmap();

Status
XCreateHSBColormap(dsp, screen, cmap, count, h1, s1, b1, h2, s2, b2, bw)
    Display    *dsp;
    int         screen;
    Colormap   *cmap;		/* colormap return value */
    int         count;		/* number of entrys to use */
    double      h1,		/* starting hue */
                s1,		/* starting saturation */
                b1,		/* starting brightness */
                h2,		/* ending hue */
                s2,		/* ending saturation */
                b2;		/* ending brightness */
    int         bw;		/* Boolean: True = save black and white */
{
    u_char      red[256];
    u_char      green[256];
    u_char      blue[256];
    unsigned long pixel;
    Status      status;
    Visual     *visual;
    XColor      xcolors[256];

    if (count > 256)
	return BadValue;

    HSBramp(h1, s1, b1, h2, s2, b2, 0, count - 1, red, green, blue);

    if (bw) {
	pixel = WhitePixel(dsp, screen);
	red[pixel] = green[pixel] = blue[pixel] = 0xff;

	pixel = BlackPixel(dsp, screen);
	red[pixel] = green[pixel] = blue[pixel] = 0;
    }
    status = XCreateDynamicColormap(dsp, screen, cmap, &visual, xcolors,
				    count, red, green, blue);

    return status;
}
SHAR_EOF
fi
if test -f 'HSBmap.c'
then
	echo shar: "will not over-write existing file 'HSBmap.c'"
else
cat << \SHAR_EOF > 'HSBmap.c'
#ifndef lint
static char sccsid[] = "@(#)HSBmap.c 22.2 89/09/20";
#endif
/*-
 * HSBmap.c - Create an HSB ramp.
 *
 * Copyright (c) 1989 by Sun Microsystems, Inc.
 *
 * Author: Patrick J. Naughton
 * naughton at sun.com
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * This file is provided AS IS with no warranties of any kind.  The author
 * shall have no liability with respect to the infringement of copyrights,
 * trade secrets or any patents by this file or any part thereof.  In no
 * event will the author be liable for any lost revenue or profits or
 * other special, indirect and consequential damages.
 *
 */

#include <sys/types.h>
#include <math.h>

void
hsb2rgb(H, S, B, r, g, b)
    double      H,
                S,
                B;
    u_char     *r,
               *g,
               *b;
{
    register int i;
    register double f,
                bb;
    register u_char p,
                q,
                t;

    H -= floor(H);		/* remove anything over 1 */
    H *= 6.0;
    i = floor(H);		/* 0..5 */
    f = H - (float) i;		/* f = fractional part of H */
    bb = 255.0 * B;
    p = (u_char) (bb * (1.0 - S));
    q = (u_char) (bb * (1.0 - (S * f)));
    t = (u_char) (bb * (1.0 - (S * (1.0 - f))));
    switch (i) {
    case 0:
	*r = (u_char) bb;
	*g = t;
	*b = p;
	break;
    case 1:
	*r = q;
	*g = (u_char) bb;
	*b = p;
	break;
    case 2:
	*r = p;
	*g = (u_char) bb;
	*b = t;
	break;
    case 3:
	*r = p;
	*g = q;
	*b = (u_char) bb;
	break;
    case 4:
	*r = t;
	*g = p;
	*b = (u_char) bb;
	break;
    case 5:
	*r = (u_char) bb;
	*g = p;
	*b = q;
	break;
    }
}


void
HSBramp(h1, s1, b1, h2, s2, b2, start, end, red, green, blue)
    double      h1,
                s1,
                b1,
                h2,
                s2,
                b2;
    int         start,
                end;
    u_char     *red,
               *green,
               *blue;
{
    double      dh,
                ds,
                db;
    register u_char *r,
               *g,
               *b;
    register int i;

    r = red;
    g = green;
    b = blue;
    dh = (h2 - h1) / 255.0;
    ds = (s2 - s1) / 255.0;
    db = (b2 - b1) / 255.0;
    for (i = start; i <= end; i++) {
	hsb2rgb(h1, s1, b1, r++, g++, b++);
	h1 += dh;
	s1 += ds;
	b1 += db;
    }
}
SHAR_EOF
fi
exit 0
#	End of shell archive



More information about the Comp.sources.x mailing list