/* Copyright 1987, Massachusetts Institute of Technology */

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include "patchlevel.h"

/*
 * xfuncursor  
 * 
 * Author: Thierry Leconte, 1990.
 * 
 * Permission to use, copy, modify and distribute without charge this software,
 * documentation, images, etc. is granted, provided that this comment and the
 * author's name is retained.  The author assumes no responsibility for lost
 * sleep as a consequence of use of this software.
 * 
 * Send any comments, bug reports, etc. to: leconte@irisa.fr
 * 
 */


char           *program_name;
Display        *dpy;
int             screen;
Window          root;
char           *fore_color = NULL;
char           *back_color = NULL;
Pixmap          save_pixmap = (Pixmap) None;

usage()
{
	fprintf(stderr, "usage: %s [options]\n", program_name);
	fprintf(stderr, "  where options are:\n");
	fprintf(stderr, "  -display <display>   or   -d <display>\n");
	fprintf(stderr, "  -fg <color>   or   -foreground <color>\n");
	fprintf(stderr, "  -bg <color>   or   -background <color>\n");
	fprintf(stderr, "  -cycle <int>\n");
	fprintf(stderr, "  -delta <int>\n");
	fprintf(stderr, "  -cursor <bitmap name prefix>\n");
	fprintf(stderr, "  -help\n");
	exit(1);
	/* NOTREACHED */
}

Pixmap          MakeModulaBitmap(), ReadBitmapFile();
XColor          NameToXColor();
unsigned long   NameToPixel();
Cursor          CreateCursorFromName();

#define VERT 1
#define HORI -1
#define POS 1
#define NEG -1

main(argc, argv)
	int             argc;
	char          **argv;
{

	char           *display_name = NULL;
	char           *name = NULL;
	char           *cursor_name = BITMAP ;
	Cursor          cursor[40];
	int             i;
	XEvent          ev;
	int             x, y, last_x, last_y, dx, dy;
	int             dl, n;
	int             delta = 13;
	int             cycle = 2;
	int             sens, orientation, last_sens, last_orientation, anim = 0;
	char            tmpname[1300],tmpmask[1300];

	program_name = argv[0];

	for (i = 1; i < argc; i++) {
		if (!strcmp("-display", argv[i]) || !strcmp("-d", argv[i])) {
			if (++i >= argc)
				usage();
			display_name = argv[i];
			continue;
		}
		if (!strcmp("-help", argv[i])) {
			usage();
		}
		if (!strcmp("-cursor", argv[i])) {
			if (++i >= argc)
				usage();
			strcpy(cursor_name,argv[i]);
			continue;
		}
		if (!strcmp("-delta", argv[i])) {
			if (++i >= argc)
				usage();
			delta = atoi(argv[i]);
			continue;
		}
		if (!strcmp("-cycle", argv[i])) {
			if (++i >= argc)
				usage();
			cycle = atoi(argv[i]);
			continue;
		}
		if (!strcmp("-fg", argv[i]) || !strcmp("-foreground", argv[i])) {
			if (++i >= argc)
				usage();
			fore_color = argv[i];
			continue;
		}
		if (!strcmp("-bg", argv[i]) || !strcmp("-background", argv[i])) {
			if (++i >= argc)
				usage();
			back_color = argv[i];
			continue;
		}
		usage();
	}


	dpy = XOpenDisplay(display_name);
	if (!dpy) {
		fprintf(stderr, "%s:  unable to open display '%s'\n",
			program_name, XDisplayName(display_name));
		usage();
	}
	screen = DefaultScreen(dpy);
	root = RootWindow(dpy, screen);

	printf("Reading files...");

	for (i = 0; i <= 4*cycle; i++) {
		sprintf(tmpname, "%s.%d", cursor_name, i);
		sprintf(tmpmask, "%s.%d.mask", cursor_name, i);
		cursor[i] = CreateCursorFromFiles(tmpname,tmpmask);
	}

	printf("Done.\n");

	XSelectInput(dpy, DefaultRootWindow(dpy), PointerMotionMask);

	while (1) {
		XNextEvent(dpy, &ev);
		if (ev.type != MotionNotify)
			continue;

		if (ev.xmotion.subwindow != None)
			continue;

		x = ev.xmotion.x;
		y = ev.xmotion.y;

		dx = x - last_x;
		dy = y - last_y;



		if (dx * dx >= dy * dy) {
			orientation = HORI;
			dl = dx;
			n = 1;
		} else {
			orientation = VERT;
			dl = dy;
			n = 2;
		}
		if (dl * dl < delta)
			continue;

		if (dl > 0) {
			sens = POS;
		} else {
			sens = NEG;
			n = n + 2;
		}
		n = n + 4*anim;

		if ((orientation != last_orientation) || (sens != last_sens))
			n = 0;

		XDefineCursor(dpy, root, cursor[n]);

		last_x = x;
		last_y = y;
		last_orientation = orientation;
		last_sens = sens;
		anim = (anim + 1) % cycle;

	}
}


/* xsetroot procedures
 * Author:	Mark Lillibridge, MIT Project Athena 11-Jun-87
 */



/*
 * CreateCursorFromFiles: make a cursor of the right colors from two bitmap
 * files.
 */
#define BITMAP_HOT_DEFAULT 8

CreateCursorFromFiles(cursor_file,cursor_mask)
	char           *cursor_file,*cursor_mask;
{
	Pixmap          cursor_bitmap, mask_bitmap;
	unsigned int    width, height, ww, hh;
	int             x_hot, y_hot;
	Cursor          cursor;
	XColor          fg, bg, temp;

	fg = NameToXColor(fore_color, BlackPixel(dpy, screen));
	bg = NameToXColor(back_color, WhitePixel(dpy, screen));

	cursor_bitmap = ReadBitmapFile(cursor_file, &width, &height, &x_hot, &y_hot);
	mask_bitmap = ReadBitmapFile(cursor_mask, &ww, &hh, (int *) NULL, (int *) NULL);


	if ((x_hot == -1) && (y_hot == -1)) {
		x_hot = BITMAP_HOT_DEFAULT;
		y_hot = BITMAP_HOT_DEFAULT;
	}
	if ((x_hot < 0) || (x_hot >= width) ||
	    (y_hot < 0) || (y_hot >= height)) {
		fprintf(stderr, "%s: hotspot is outside cursor bounds in file %s\n", program_name,cursor_file);
		exit(1);
	}
	if ((width != ww) || (height != hh)) {
		fprintf(stderr,"%s : cursor file %s and mask have not the same size\n",cursor_file);
		exit(1);
	}
 
	cursor = XCreatePixmapCursor(dpy, cursor_bitmap, mask_bitmap, &fg, &bg,
				(unsigned int) x_hot, (unsigned int) y_hot);
	XFreePixmap(dpy, cursor_bitmap);
	XFreePixmap(dpy, mask_bitmap);

	return (cursor);
}


/*
 * NameToXColor: Convert the name of a color to its Xcolor value.
 */
XColor 
NameToXColor(name, pixel)
	char           *name;
	unsigned long   pixel;
{
	XColor          c;

	if (!name || !*name) {
		c.pixel = pixel;
		XQueryColor(dpy, DefaultColormap(dpy, screen), &c);
	} else if (!XParseColor(dpy, DefaultColormap(dpy, screen), name, &c)) {
		fprintf(stderr, "%s: unknown color or bad color format: %s\n",
			program_name, name);
		exit(1);
		/* NOTREACHED */
	}
	return (c);
}


Pixmap 
ReadBitmapFile(filename, width, height, x_hot, y_hot)
	char           *filename;
	unsigned int   *width, *height;
	int            *x_hot, *y_hot;
{
	Pixmap          bitmap;
	int             status;

	status = XReadBitmapFile(dpy, root, filename, width,
				 height, &bitmap, x_hot, y_hot);
	if (status == BitmapSuccess)
		return (bitmap);
	else if (status == BitmapOpenFailed)
		fprintf(stderr, "%s: can't open file: %s\n", program_name, filename);
	else if (status == BitmapFileInvalid)
		fprintf(stderr, "%s: bad bitmap format file: %s\n",
			program_name, filename);
	else
		fprintf(stderr, "%s: insufficient memory for bitmap: %s",
			program_name, filename);
	exit(1);
	/* NOTREACHED */
}
