[comp.windows.x] xlock enhancements

vesper@3d.dec.com.UUCP (07/01/88)

---cut here---
/*
 *                             XLOCK V1.2
 *
 *                      A Terminal Locker for X11
 *
 *              Copyright (c) 1988 by Patrick J. Naughton
 *
 *                         All Rights Reserved
 *
 * 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.
 *
 * Original version posted to comp.windows.x by:
 * Walter Milliken
 * (milliken@heron.bbn.com)
 * BBN Advanced Computers, Inc., Cambridge, MA
 *
 * Comments and additions may be sent the author at:
 *
 * naughton@sun.soe.clarkson.edu
 *
 * or by Snail Mail:
 * Patrick J. Naughton
 * 23 Pleasant Street, #3
 * Potsdam, NY  13676
 *         or
 * (315) 265-2853 (voice)
 *
 *
 * Revision History:
 *  1-Jul-88: AFV (vesper@3d.dec.com)
 *		Fixed color support (allocates every free color map entry
 *		    with a random color)
 *		Made sure the GrabKeyboard works else beep and die
 *		Rudimentary support for VMS (password `Secret')
 *		Added message area
 *		Added -fg, -bg and -font switches
 *		Beep on bad password
 * 30-Mar-88: Removed startup password requirement (why did I add that?)
 *            Removed cursor to avoid phosphor burn.
 * 27-Mar-88: Rotate fractal by 45 degrees clockwise. (aesthetics)
 * 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.
 *
 */
 
#include <stdio.h>
#ifndef VMS
#include <pwd.h>
#endif
#include <math.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
 
#ifndef VMS
char *crypt();
#endif

#ifdef VMS
#define random rand
#define srandom srand
#endif
 
static char no_bits[] = {0};
 
Display *dsp = NULL;		/* current display (must be inited) */
Window w;			/* window used to cover screen */
GContext gc;
 
int width;			/* width of screen */
int height;			/* height of screen */
 
Window rootw;			/* root window */
int screen;			/* current screen */
Colormap cmap;			/* colormap of current screen */
Cursor mycursor;                /* blank cursor */
 
unsigned long bg_pixel;		/* pixel value for black */
unsigned long fg_pixel;		/* pixel value for white */
XColor bg_color;		/* color value for black */
XColor fg_color;		/* color value for white */

XColor random_color;		/* generate random colors if -c is specified */

XComposeStatus compose;
 
int centerx, centery, iter, maxiter, range, color;
double a, b, c, i, j;
 

ReadXString(s, slen)
char *s;
int slen;
{
    int bp;
    char c;
    XEvent evt;
    char keystr[20];
    int len;
    int i;
 
    bp = 0;
    while (1) {
	if (XPending(dsp)) {
	    XNextEvent(dsp, &evt);
	    if (evt.type == KeyPress) {
		len = XLookupString(&evt.xkey, keystr, 20, NULL, &compose);
		for (i = 0; i < len; i++) {
		    c = keystr[i];
		    switch (c) {
			case 8:			/* ^H */
			    if (bp > 0) bp--;
			    break;
			case 13:		/* ^M */
			    s[bp] = '\0';
			    return;
			case 21:		/* ^U */
			    bp = 0;
			    break;
			default:
			    s[bp] = c;
			    if (bp < slen-1) bp++;
		    }
		}
	    }
	}
	else iterate();
    }
}

main(argc, argv)
int argc;
char *argv[];
{
    char	    buf [20];
    XSetWindowAttributes attrs;
    XGCValues	    xgcv;
    struct passwd   * pw;
    Pixmap	    lockc, lockm;   
    char	    text [200];
    register char   * cp;
    int		    text_length;
    Window	    window_text;
    int		    ascent;
    int		    descent;
    int		    direction;
    XCharStruct	    overall;
    int		    width_text;
    int		    height_text;
    register int    i;
    int		    x;
    int		    y;
    char	    * fg_color_name;
    char	    * bg_color_name;
    char	    * font_name;
    int		    stat;
    XFontStruct	    * font;
    int		    delay;

    color = 0;
    fg_color_name = NULL;
    bg_color_name = NULL;
    font_name = NULL;
    cp = text;
    *cp++ = ' ';

    for (i = 1; i < argc; i++) {

        if (strcmp("-color", argv[i]) == 0) color = 1;
	else if (strcmp ("-fg", argv[i]) == 0) {
	    if (++i >= argc) break;
	    fg_color_name = argv[i];
	}
	else if (strcmp ("-bg", argv[i]) == 0) {
	    if (++i >= argc) break;
	    bg_color_name = argv[i];
	}
	else if (strcmp ("-font", argv[i]) == 0) {
	    if (++i >= argc) break;
	    font_name = argv[i];
	}
	else {
	    strcpy (cp, argv[i]);
	    cp += strlen (cp);
	    *cp++ = ' ';
	}

    }

    text_length = cp - text;
    if (text_length == 1) text_length = 0;

#ifdef VMS
    dsp = XOpenDisplay (NULL);
#else
    dsp = XOpenDisplay("unix:0");
#endif
    if (dsp == NULL) exit(1);

    rootw = DefaultRootWindow(dsp);
    screen = DefaultScreen(dsp);
    width = DisplayWidth(dsp, screen);
    height = DisplayHeight(dsp, screen);
    centerx = width / 2;
    centery = height / 2;
    range = (int) sqrt((double)centerx*centerx+(double)centery*centery);
    cmap = DefaultColormap(dsp, screen);

    bg_pixel = -1;

    if (bg_color_name != NULL) {
	stat = XParseColor (dsp, cmap, bg_color_name, &bg_color);
	if (stat != 0) {
	    stat = XAllocColor (dsp, cmap, &bg_color);
	}
	if (stat != 0) bg_pixel = bg_color.pixel;
	    
    }

    if (bg_pixel == -1) {
	bg_pixel = BlackPixel(dsp, screen);
	bg_color.pixel = bg_pixel;
	XQueryColor(dsp, cmap, &bg_color);
    }

    fg_pixel = -1;

    if (fg_color_name != NULL) {
	stat = XParseColor (dsp, cmap, fg_color_name, &fg_color);
	if (stat != 0) {
	    stat = XAllocColor (dsp, cmap, &fg_color);
	}
	if (stat != 0) fg_pixel = fg_color.pixel;
	    
    }

    if (fg_pixel == -1) {
	fg_pixel = WhitePixel(dsp, screen);
	fg_color.pixel = fg_pixel;
	XQueryColor(dsp, cmap, &fg_color);
    }
 
    attrs.background_pixel = bg_pixel;
    attrs.override_redirect = True;
    attrs.event_mask = KeyPressMask;

    w = XCreateWindow(dsp, rootw, 0, 0, width, height, 0,
		CopyFromParent, InputOutput, CopyFromParent,
		CWOverrideRedirect | CWBackPixel | CWEventMask, &attrs);
 
    lockc = XCreateBitmapFromData(dsp, w, no_bits, 8, 1);
    lockm = XCreateBitmapFromData(dsp, w, no_bits, 8, 1);
    mycursor = XCreatePixmapCursor(dsp, lockc, lockm,
				   &bg_color, &bg_color,
				   0, 0);
    XFreePixmap(dsp, lockc);
    XFreePixmap(dsp, lockm);
 
    xgcv.foreground = fg_pixel;
    xgcv.background = bg_pixel;
    gc = (GContext) XCreateGC(dsp, w, GCForeground | GCBackground, &xgcv);

    if (font_name != NULL) {
	font = XLoadQueryFont (dsp, font_name);
	if (font != NULL) {
	    XSetFont (dsp, gc, font->fid);
	}
    }

    if (text_length > 0) {
	XQueryTextExtents (dsp, XGContextFromGC (gc), text, text_length,
		&direction, &ascent, &descent, &overall);
	width_text = overall.rbearing - overall.lbearing;
	height_text = ascent + descent;
	x = ( DisplayWidth (dsp, screen) - width_text ) / 2;
	y = 2 * height_text;
	window_text = XCreateSimpleWindow (dsp, w, x, y, 
		width_text, height_text, 2, fg_pixel, bg_pixel);
    }

    XMapWindow(dsp, w);

    stat = XGrabKeyboard(dsp, w, True, GrabModeAsync, GrabModeAsync, 
	    CurrentTime);

    if (stat == AlreadyGrabbed) {
	sleep (2);
	stat = XGrabKeyboard(dsp, w, True, GrabModeAsync, GrabModeAsync, 
		CurrentTime);
	if (stat == AlreadyGrabbed) {
	    fprintf (stderr, "Keyboard already grabbed!!!\n");
	    XBell (dsp, 100);	
	    XFlush (dsp, True);
	    exit (1);
	}
    }

    if (stat != GrabSuccess) {
	fprintf (stderr, "XGrabKeyboard failed, code = %d\n", stat);
	exit (1);
    }

    stat = XGrabPointer(dsp, w, False, 0, GrabModeAsync, GrabModeAsync, None,
		 mycursor, CurrentTime);
    if (stat != GrabSuccess) {
	fprintf (stderr, "XGrabPointer failed, code = %d\n", stat);
	}

    XGrabServer (dsp);
    XRaiseWindow (dsp, w);

    if (text_length > 0) {
	XMapWindow (dsp, window_text);
	XDrawString (dsp, window_text, gc, 0, ascent, text, text_length);
    }

#ifndef VMS
    pw = getpwuid(getuid());
#endif

    srandom(time(NULL));
    do {
	inithop();
	ReadXString(buf, 20);
#ifdef VMS
	stat = strcmp (buf, "Secret");
#else
	stat = strcmp(crypt(buf, pw->pw_passwd), pw->pw_passwd);
#endif
	if (stat != 0) XBell (dsp, 20);
    } while (stat != 0);
 
    XUngrabServer (dsp);
    XUngrabPointer(dsp, CurrentTime);
    XUngrabKeyboard(dsp, CurrentTime);
    XDestroyWindow(dsp, w);

}

iterate()
{
double oldj;
register int k;
static int stat = 1;
 
    for (k=0;k<500;k++) {
	oldj = j;
	j = a - i;
	i = oldj + (i<0?sqrt(fabs(b*i - c)):-sqrt(fabs(b*i - c))); 
	if (color) {
	    if (stat == 0) {
		XSetForeground(dsp, gc, iter);
	    }
	    else {
		random_color.red = random ();
		random_color.green = random ();
		random_color.blue = random ();
		stat = XAllocColor (dsp, cmap, &random_color);
		XSetForeground (dsp, gc, random_color.pixel);
	    }
	}
	XDrawPoint(dsp, w, gc,
		centerx + (int)(i+j), /* sneaky way to rotate +45 deg. */
		centery - (int)(i-j));
	iter++;
    }
    if (iter > maxiter) inithop();
}

inithop()
{
	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;
 
	maxiter = (color?10000+random()%20000:20000+random()%50000);
	iter = 0;
	i = j = 0.0;
	XClearWindow(dsp, w);
}
---cut here---

naughton%wind@Sun.COM (Patrick Naughton) (07/07/88)

The message Referenced above appeared on comp.windows.x on July 1st
without my prior knowledge.  This "vesper@3d.dec.com" person took it
upon him/herself to take a four month (two revision) old version of
xlock, make some changes to it and post it to the net. 

The source very clearly documented that I was maintaining this code and
that additions should be sent to me for integration, "Comments and
additions may be sent the author at:"...  The three other contributors
to xlock never had problems interpreting that simple statement over five
revisions. 

Ever since the poorly modified version of xlock appeared on the net, I
have been swamped with requests/complaints about "Which version is the
latest?"

The answer is this:
  Throw away the hacked V1.2 and wait a couple of days till I get a
chance to test V1.6 with vesper's changes integrated.  I'll post the
full file then, (the diffs would be as big as the file...  I never
released 1.5... too busy driving from NY to CA...). 

-Patrick
    ______________________________________________________________________
    Patrick J. Naughton				    ARPA: naughton@Sun.COM
    Window Systems Group			    UUCP: ...!sun!naughton
    Sun Microsystems, Inc.			    AT&T: (415) 336 - 1080