v12i077: xancur - root cursor animation program, Part04/04

Christopher North-Keys erlkonig at gnu.ai.mit.edu
Fri May 3 16:44:15 AEST 1991


Submitted-by: erlkonig at gnu.ai.mit.edu (Christopher North-Keys)
Posting-number: Volume 12, Issue 77
Archive-name: xancur/part04

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 4)."
# Contents:  ./xancur/xancur.c
# Wrapped by chudnall at pooh.cc.utexas.edu on Thu May  2 00:31:51 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f './xancur/xancur.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./xancur/xancur.c'\"
else
echo shar: Extracting \"'./xancur/xancur.c'\" \(16343 characters\)
sed "s/^X//" >'./xancur/xancur.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1990 Microelectronics and Computer Technology Corp. (M.C.C.)
X *
X * Permission to use, copy, modify, distribute, and sell this software and its
X * documentation for any purpose is hereby granted without fee, provided that
X * the above copyright notice appear in all copies and that both that
X * copyright notice and this permission notice appear in supporting
X * documentation, and that the name of M.C.C. not be used in advertising or
X * publicity pertaining to distribution of the software without specific,
X * written prior permission.  M.C.C. makes no representations about the
X * suitability of this software for any purpose.  It is provided "as is"
X * without express or implied warranty.
X *
X * M.C.C. disclaims all warranties with regard to this software, including
X * all implied warranties of merchantability and fitness, in no event shall
X * M.C.C. be liable for any special, indirect or consequential damages or
X * any damages whatsoever resulting from loss of use, data or profits, whether
X * in an action of contract, negligence or other tortious action, arising out
X * of or in connection with the use or performance of this software.
X */
X
X/* Written by Christopher Alexander North-Keys @M.C.C.
X * Thanks to Mark Lillibridge of MIT Project Athena for having written xsetroot
X *
X * xancur.c -- X11R4 animatation of the cursor in the root window.
X *
X * summary: cycle through a list of (cursor, mask) pairs.
X */
X
X#ifndef lint
Xstatic char Version[]="@(#)xancur.c v1.2, Christopher North-Keys, 25.Mar.1991";
X#endif
X
X#include <stdio.h>
X#include <ctype.h>
X#include <strings.h>
X#include <pwd.h>
X#include <signal.h>
X#include <sys/file.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/param.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xatom.h>
X;
X
X#ifndef XANCUR_SCRIPT
X#define XANCUR_SCRIPT "."
X#endif
X
X#ifndef FAIL
X#define FAIL (-1)
X#endif
X
Xtypedef struct _CursorList
X{
X    char *scriptdir;
X	char *image;
X	char *mask;
X	char *fg;
X	char *bg;
X	Cursor cursor;
X	struct _CursorList *next;
X} CursorList;
X
Xextern char *strpbrk();
Xextern char *strtok();
Xextern char *strchr();
Xextern char *strrchr();
Xextern char *getenv();
Xextern char *getwd();
Xextern struct passwd *getpwnam();
X
Xchar		*Home = NULL;
Xchar		*ProgramName = NULL;
XDisplay		*Dpy;
Xint			 Scr;
XWindow		 Root;
Xchar		*Foreground = NULL;
Xchar		*Background = NULL;
Xint			 Reverse = 0;
Xunsigned	 Microsecs = 200000;
Xint			 Iterations = -1;
Xint          Debug = 0;
XCursorList	*Cursors = NULL;
X
Xvoid	 SetCursorFiles();
Xvoid     OpenScript(/* char *name */);
Xvoid     ExecuteData();
Xchar	*FileNameExpand(/* char *name */);
Xchar    *EnrootPathName(/* char *dir, char *name */);
Xlong	 SwallowFile(/*char **addr_buffer, char *path */);
XPixmap	 ReadBitmapFile();
XXColor	 NameToXColor();
XCursor 	 CreateCursorFromFiles();
X
Xvoid
XFatal(location, call, addition)
Xchar *location, *call, *addition;
X{
X    (void)fprintf(stderr, "%s: (%s)", ProgramName, location);
X    if(addition) (void)fprintf(stderr, " %s\n", addition);
X    if(call)
X    {
X        (void)fprintf(stderr, "\t");
X        perror(call);
X    }
X    exit(FAIL);
X}
X
Xvoid Usage()
X{
X	(void)fprintf(stderr, "%s: usage error.\n", ProgramName);
X	(void)fprintf(stderr, "[cursor_defs]  :cursorfile/maskfile pairs -- bitmap filenames\n");
X	(void)fprintf(stderr, "-script <name> :read cursor_definitions from script <name>\n");
X	(void)fprintf(stderr, "-fg <color>    :set foreground\n");
X	(void)fprintf(stderr, "-bg <color>    :set background\n");
X	(void)fprintf(stderr, "-rv            :reverse fg and bg\n");
X	(void)fprintf(stderr, "-usleep <int>  :set frame delay in microseconds, default %d\n", Microsecs);
X	(void)fprintf(stderr, "-iter <int>    :set number of iterations, default infinite\n");
X	(void)fprintf(stderr, "-display <dpy> :connect to X server [dpy] (also -d [dpy])\n");
X	exit (1);
X	return;
X}
X
Xvoid
XAbortClean()
X{
X	XUndefineCursor(Dpy, Root);
X	XCloseDisplay(Dpy);
X	exit(0);
X}
X
Xint
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	char *display_name = NULL;
X	int i;
X	
X	ProgramName = argv[0];
X	Home = getenv("HOME");
X	
X	for (i = 1; i < argc; i++)
X	{
X		if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
X			if (++i>=argc) Usage();
X			display_name = argv[i];
X			continue;
X		}
X		if (!strcmp("-fg", argv[i]))
X		{
X			if (++i>=argc) Usage();
X			Foreground = argv[i];
X			continue;
X		}
X		if (!strcmp("-bg", argv[i]))
X		{
X			if (++i>=argc) Usage();
X			Background = argv[i];
X			continue;
X		}
X		if (!strcmp("-rv", argv[i]))
X		{
X			Reverse = 1;
X			continue;
X		}
X		if (!strcmp("-usleep", argv[i]))
X		{
X			if (++i>=argc) Usage();
X			Microsecs = (unsigned)atoi(argv[i]);
X			continue;
X		}
X		if (!strcmp("-iter", argv[i]))
X		{
X			if (++i>=argc) Usage();
X			Iterations = atoi(argv[i]);
X			continue;
X		}
X		if (!strcmp("-debug", argv[i]))
X		{
X			Debug = 1;
X			continue;
X		}
X		if (!strcmp("-script", argv[i]))
X		{
X			char *pathname[MAXPATHLEN];
X			if (++i>=argc) Usage();
X			/* Time to fetch a file */
X			OpenScript(EnrootPathName(getwd(pathname), argv[i]));
X			continue;
X		}
X		if (argv[i][0] != '-') 
X		{	
X			
X			if (i+1>=argc) Usage();
X			SetCursorFiles(NULL, argv[i], argv[i+1]);
X			i++;
X			continue;
X		}
X		Usage();
X	}
X	
X	if (!Cursors)
X	{
X		char *name;
X		if(NULL == (name = (char *)malloc(strlen(ProgramName)+1)))
X            Fatal("main", "malloc", NULL);
X		(void)strcat(name, ".");
X		(void)strcat(name, ProgramName);
X		OpenScript(EnrootPathName("~", name));
X	}
X	
X	if (!Cursors) OpenScript(XANCUR_SCRIPT);
X	
X	if (!(Dpy = XOpenDisplay(display_name)))
X	{
X		(void)fprintf(stderr, "%s:  unable to open display '%s'\n",
X					  ProgramName, XDisplayName (display_name));
X		exit (-1);
X	}
X	Root = RootWindow(Dpy, Scr = DefaultScreen(Dpy));
X	
X	signal(SIGTERM, AbortClean);
X	signal(SIGHUP,  AbortClean);
X	signal(SIGINT,  AbortClean);
X		   	
X	/* handle minor cursor insanity, an endless loop */
X	if (Cursors)
X	{
X		CursorList *cur;
X		
X		for(cur = Cursors ; cur ; cur = cur->next)
X            cur->cursor = CreateCursorFromFiles(cur->image, cur->mask,
X                                                cur->fg, cur->bg);
X		
X		while(Iterations < 0 ? 1 : Iterations--)
X		{
X			for(cur = Cursors ;
X				cur ;
X				cur = cur->next)
X			{
X				XDefineCursor(Dpy, Root, cur->cursor);
X				XFlush(Dpy);
X				usleep(Microsecs);
X			}
X		}
X		
X		for(cur = Cursors ; cur ; cur = cur->next)
X			XFreeCursor(Dpy, cur->cursor);
X	}
X
X	AbortClean();
X	return (0);
X}
X
X/* Open script file.  Should be given a full pathname. */
Xvoid
XOpenScript(script)	/* RECURSIVE */
Xchar *script;
X{	
X	char *data;		        /* the actual data */
X
X    if(Debug)(void)fprintf(stderr,
X                           "%s: OpenScript %s\n", ProgramName, script);
X    
X    if((long)0 < SwallowFile(&data, script))	/*Dense, do not free*/
X        ExecuteData(data, script);
X    
X    return;
X}
X
X
X/* execute instructions contained in data just read in */
Xvoid
XExecuteData(data, script)
Xchar *data;
Xchar *script;    /* name of script from which data was taken. */
X{
X    char *p;							/* pointer into data */
X    
X    for(p = data ; p && *p ; /*internal*/ )	/* parse the file */
X    {	/* resolve to a line */
X        char *b;						/* beginning of a line */
X        
X        p = &p[strspn(p, " \t\n")];		/* skip white space */
X        b = p;							/* found beginning */
X        
X        p = strpbrk(p, "\n");			/* seek to newline */
X        if (p)
X        {
X            *p = '\0';		  		 	/* zero newline */
X            if(p) p++;					/* now at beginning of new line */
X        }
X        
X        /* analyze line ----------------------------------------*/
X        /* an attempt was made to use strtok, which was munged. */
X
X        if(*b == '#')       /* a comment */
X            continue;
X        
X        if(*b == '-')		/* a switch */
X        {
X            char *s;	/* switch */
X            char *a;	/* argument to switch */
X            
X            if(NULL == (s = strpbrk(b, " \t")))
X            {
X                if(!strcmp(b, "-rv"))
X                {
X                    char *tmp_color;
X                    tmp_color = Foreground;
X                    Foreground = Background;
X                    Background = tmp_color;
X                }
X            } else {
X                *s++ = '\0';                /* make first field a string */
X                a = &s[strspn(s, " \t")];             /* skip whitespace */
X                if(s = strpbrk(a, " \t")) *s = '\0';    /* eol already 0 */
X                if(!strcmp(b, "-script"))
X                {
X                    char *newscr = NULL;
X                    char *nsp;              /* newscript pointer */
X                    if(NULL == (newscr = (char *)malloc(MAXPATHLEN)))
X                        Fatal("ExecuteData", "malloc", "new script");
X                    
X                    (void)strcpy(newscr, script);
X                    nsp = rindex(newscr, '/');
X                    (void)strcpy(++nsp, a);
X
X                    OpenScript(newscr);
X                }
X                if(!strcmp(b, "-fg")) Foreground = a;
X                if(!strcmp(b, "-bg")) Background = a;
X            }
X        } else {
X            char *s;			/* ptr (eventually) to mask_file */
X            
X            /* look for cursor filenames */
X            if(NULL == (s = strpbrk(b, " \t")))
X            {
X                SetCursorFiles(script, b, (char *)NULL);
X            } else {
X                char *m;
X                *s++ = '\0';
X                m = &s[strspn(s, " \t")];
X                if(s = strpbrk(m, " \t")) *s = '\0';
X                
X                SetCursorFiles(script, b, m);
X            }
X        } /*else*/
X    } /*for*/
X    return;
X}
X
Xchar *
XFileNameExpand(orig)
Xchar *orig;
X{
X	char *hi;
X	
X	if(!orig) return orig;
X	if(*orig == '/') return orig;
X    if(*orig != '~') return orig;
X
X	/* at this point we know that a username expansion is required */
X
X    if(orig[1] == '\0') return Home;
X
X	if(NULL == (hi = (char *)malloc(MAXPATHLEN)))
X        Fatal("FileNameExpand", "malloc", "expansion buffer");
X	
X	if(orig[1] == '/')
X	{
X		(void)strcpy(hi, Home);
X		(void)strcpy(hi, &orig[1]);
X	} else {
X		char *user, *end;
X		struct passwd *tmp;
X		
X		if((NULL == (user = (char *)malloc(MAXPATHLEN))))
X            Fatal("FileNameExpand", "malloc", "user buffer");
X
X		(void)strcpy(user, &orig[1]);
X		end = strchr(user, '/');
X		*end = '\0';
X		end++;
X		
X		if(NULL == (tmp = getpwnam(user)))
X            Fatal("FileNameExpand", "getpwname", "user appears bogus");
X
X		(void)strcpy(hi, (tmp->pw_dir));
X		(void)strcat(hi, "/");
X		(void)strcat(hi, end);
X	}
X	return hi;
X}
X
Xchar *
XEnrootPathName(curdir, orig)
Xchar *curdir, *orig;
X{
X    char *hi;
X    
X    curdir = FileNameExpand(curdir);
X    orig = FileNameExpand(orig);
X    
X    if(*orig == '/') return orig;
X
X	if(NULL == (hi = (char *)malloc(strlen(curdir)+strlen(orig)+1)))
X	{
X        Fatal("EnrootPathName", "malloc", Home);
X	}
X    (void)strcpy(hi, curdir);
X    (void)strcat(hi, "/");
X    (void)strcat(hi, orig);
X
X    if(*hi != '/')
X        Fatal("EnrootPathName", NULL, "enrooting failed");
X    else
X        return hi;
X}
X
X/* Create a new cursor, link it in, and set filenames and colors. */
Xvoid
XSetCursorFiles(script, cursor_file, mask_file)
Xchar *script;
Xchar *cursor_file;
Xchar *mask_file;
X{
X    char *dir = NULL;
X	static CursorList *Tail;
X	CursorList *hi;  /* say "hi" to the new boy... */
X	
X	if(NULL == (hi = (CursorList *)malloc(sizeof(CursorList))))
X	{
X		(void)fprintf(stderr, "%s:  malloc failed\n", ProgramName);
X		exit(-1);
X	}
X
X    if(script)
X    {
X        if(NULL == (dir = (char*)malloc(MAXPATHLEN)))
X            Fatal("SetCursorFiles", "malloc", "script directory");
X        else
X        {
X            char *end;
X            (void)strcpy(dir, script);
X            end = rindex(dir, '/');
X            *end = '\0';
X        }            
X    } else {
X		char *pathname[MAXPATHLEN];
X        dir = getwd(pathname);
X    }
X    
X	if(!mask_file)
X	{
X		if(NULL == (mask_file = (char *)malloc(strlen(cursor_file)+6)))
X		{
X			perror("malloc");
X			exit(1);
X		}
X		(void)strcpy(mask_file, cursor_file);
X		(void)strcat(mask_file, ".mask");
X	}
X
X	cursor_file = EnrootPathName(dir, cursor_file);
X	mask_file = EnrootPathName(dir, mask_file);
X	
X	if(!Cursors) Cursors = hi;
X	if(Tail) Tail->next = hi;
X	Tail = hi;
X	hi->next = NULL;
X    hi->scriptdir = dir;
X	hi->image = cursor_file;
X	hi->mask = mask_file;
X	hi->fg = Foreground;
X	hi->bg = Background;
X	
X	return;
X}
X
X/* make a cursor of the right colors from two bitmap files. */
XCursor
XCreateCursorFromFiles(cursor_file, mask_file, foreground, background)
Xchar *cursor_file, *mask_file, *foreground, *background;
X{
X	Pixmap cursor_bitmap, mask_bitmap;
X	unsigned int c_width, c_height, m_width, m_height;
X	int x_hot, y_hot;
X	Cursor cursor;
X	XColor fg, bg;
X	
X	fg = NameToXColor(foreground, BlackPixel(Dpy, Scr));
X	bg = NameToXColor(background, WhitePixel(Dpy, Scr));
X	
X	cursor_bitmap = ReadBitmapFile(cursor_file, &c_width, &c_height,
X								   &x_hot, &y_hot);
X	
X    mask_bitmap = ReadBitmapFile(mask_file, &m_width, &m_height,
X								 (int *)NULL, (int *)NULL);
X	
X	if (!cursor_bitmap || !mask_bitmap)
X	{
X		(void)fprintf(stderr, "%s: read failure on cursor %s, aborting\n",
X					  ProgramName, cursor_file);
X		exit (1);
X	}
X	
X    if (c_width != m_width || c_height != m_height)
X	{
X		(void)fprintf(stderr, "%s: dimensions of bitmap and mask differ\n",
X					  ProgramName);
X		exit(1);
X    }
X	
X    if ((x_hot == -1) && (y_hot == -1))
X	{
X		x_hot = (int)(c_width / 2);
X		y_hot = (int)(c_height / 2);
X		(void)fprintf(stderr, "%s: hotspot defaulting to (%d,%d) in %s\n",
X					  ProgramName, x_hot, y_hot, cursor_file);
X    }
X    if ((x_hot < 0) || (x_hot >= c_width) ||
X		(y_hot < 0) || (y_hot >= c_height))
X	{
X		(void)fprintf(stderr,
X					  "%s: hotspot at (%d,%d) outside cursor bounds [0,%d],[0,%d]\n",
X					  ProgramName, x_hot, y_hot, c_width, c_height);
X		(void)fprintf(stderr, "in cursor bitmap %s\n", cursor_file);
X		exit(1);
X    }
X	
X    cursor = XCreatePixmapCursor(Dpy, cursor_bitmap, mask_bitmap, &fg, &bg,
X								 (unsigned int)x_hot, (unsigned int)y_hot);
X    XFreePixmap(Dpy, cursor_bitmap);
X    XFreePixmap(Dpy, mask_bitmap);
X	
X    return(cursor);
X}
X
X/* Resolve name to actual X color. */
XXColor
XNameToXColor(name, pixel)
Xchar *name;
Xunsigned long pixel;
X{
X    XColor color;
X	
X    if (name && *name)
X	{
X		if (!XParseColor(Dpy, DefaultColormap(Dpy, Scr), name, &color))
X		{
X			(void)fprintf(stderr, "%s: unknown color or bad color format: %s\n",
X						  ProgramName, name);
X			Usage();
X		}
X    } else {
X		color.pixel = pixel;
X		XQueryColor(Dpy, DefaultColormap(Dpy, Scr), &color);
X	}
X	
X    return(color);
X}
X
XPixmap
XReadBitmapFile(filename, width, height, x_hot, y_hot)
Xchar *filename;
Xunsigned int *width, *height;
Xint *x_hot, *y_hot;
X{
X    Pixmap bitmap;
X    int status;
X	
X    status = XReadBitmapFile(Dpy, Root, filename, width, height,
X							 &bitmap, x_hot, y_hot);
X	switch(status)
X	{
X	  case BitmapSuccess:
X		return(bitmap);
X		break;
X	  case BitmapOpenFailed:
X		(void)fprintf(stderr, "%s: can't open file: %s\n",
X					  ProgramName, filename);
X		break;
X	  case BitmapFileInvalid:
X		(void)fprintf(stderr, "%s: bad bitmap format file: %s\n",
X					  ProgramName, filename);
X		break;
X	  default:
X		(void)fprintf(stderr, "%s: insufficient memory for bitmap: %s",
X					  ProgramName, filename);
X		exit(-1);
X	}
X	return((Pixmap)0);
X}
X
Xlong
XSwallowFile(addr_buffer, path)
Xchar **addr_buffer, *path;
X{
X    struct stat statbuf;
X    int         in_count;
X    int         fd = -1;
X	
X    /* Attempt to open desired file */
X    if(((fd)=open(path, O_RDONLY))==-1)
X    {
X        /* (void)fprintf(stderr, "SwallowFile: %s not opened\n", path);
X		 */
X        return (FAIL);
X    }
X	
X    if(fstat(fd, &statbuf)==-1)
X    {
X        (void)fprintf(stderr, "SwallowFile: error on fstat file %s\n", path);
X        return (FAIL);
X    }
X	
X    /* Get a buffer to fit */
X    if((*addr_buffer=(char *)calloc(1, statbuf.st_size+1))==NULL)
X    {
X        (void)fprintf(stderr, "SwallowFile: no space for calloc\n");
X        return (FAIL);
X    }
X	
X    /* Read in the file */
X	/* Warning:  this will probably break on files over 64K in length */
X    if((in_count = read(fd, *addr_buffer, statbuf.st_size)) != statbuf.st_size)
X    {
X        (void)fprintf(stdout,
X                      "SwallowFile: error(?) %d/%d bytes read from %s\n",
X                      in_count, statbuf.st_size, path);
X        (void)free(*addr_buffer);
X        return (FAIL);
X    }
X    return (in_count);
X}
END_OF_FILE
if test 16343 -ne `wc -c <'./xancur/xancur.c'`; then
    echo shar: \"'./xancur/xancur.c'\" unpacked with wrong size!
fi
# end of './xancur/xancur.c'
fi
echo shar: End of archive 4 \(of 4\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

--
Dan Heller
O'Reilly && Associates       Z-Code Software    Comp-sources-x:
Senior Writer                President          comp-sources.x at uunet.uu.net
argv at ora.com                 argv at zipcode.com



More information about the Comp.sources.x mailing list