erlkonig@gnu.ai.mit.edu (Christopher North-Keys) (05/03/91)
Submitted-by: erlkonig@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@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@uunet.uu.net argv@ora.com argv@zipcode.com