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