xsetroot.c revision b8f63ae3
1c95b42baSmrg/*
2c95b42baSmrg *
3c95b42baSmrgCopyright 1987, 1998  The Open Group
4c95b42baSmrg
5c95b42baSmrgPermission to use, copy, modify, distribute, and sell this software and its
6c95b42baSmrgdocumentation for any purpose is hereby granted without fee, provided that
7c95b42baSmrgthe above copyright notice appear in all copies and that both that
8c95b42baSmrgcopyright notice and this permission notice appear in supporting
9c95b42baSmrgdocumentation.
10c95b42baSmrg
11c95b42baSmrgThe above copyright notice and this permission notice shall be included in
12c95b42baSmrgall copies or substantial portions of the Software.
13c95b42baSmrg
14c95b42baSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15c95b42baSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16c95b42baSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17c95b42baSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18c95b42baSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19c95b42baSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20c95b42baSmrg
21c95b42baSmrgExcept as contained in this notice, the name of The Open Group shall not be
22c95b42baSmrgused in advertising or otherwise to promote the sale, use or other dealings
23c95b42baSmrgin this Software without prior written authorization from The Open Group.
24c95b42baSmrg */
25c95b42baSmrg
26c95b42baSmrg/*
27c95b42baSmrg * xsetroot.c 	MIT Project Athena, X Window System root window
28c95b42baSmrg *		parameter setting utility.  This program will set
29c95b42baSmrg *		various parameters of the X root window.
30c95b42baSmrg *
31c95b42baSmrg *  Author:	Mark Lillibridge, MIT Project Athena
32c95b42baSmrg *		11-Jun-87
33c95b42baSmrg */
34c95b42baSmrg
3562aeb71dSmrg#ifdef HAVE_CONFIG_H
3662aeb71dSmrg# include "config.h"
3762aeb71dSmrg#endif
3862aeb71dSmrg
39c95b42baSmrg#include <X11/Xlib.h>
40c95b42baSmrg#include <X11/Xutil.h>
41c95b42baSmrg#include <X11/Xatom.h>
42c95b42baSmrg#include <X11/Xmu/CurUtil.h>
43d80571a9Smrg#include <X11/Xcursor/Xcursor.h>
44c95b42baSmrg#include <stdio.h>
45c95b42baSmrg#include <stdlib.h>
46c95b42baSmrg#include <string.h>
47c95b42baSmrg#include "X11/bitmaps/gray"
48c95b42baSmrg
49c95b42baSmrg#define Dynamic 1
50c95b42baSmrg
51f40e0d56Smrgstatic char *program_name;
52f40e0d56Smrgstatic Display *dpy;
53f40e0d56Smrgstatic int screen;
54f40e0d56Smrgstatic Window root;
55f40e0d56Smrgstatic char *fore_color = NULL;
56f40e0d56Smrgstatic char *back_color = NULL;
57f40e0d56Smrgstatic int reverse = 0;
58f40e0d56Smrgstatic int save_colors = 0;
59f40e0d56Smrgstatic int unsave_past = 0;
60f40e0d56Smrgstatic Pixmap save_pixmap = (Pixmap)None;
61c95b42baSmrg
62c95b42baSmrgstatic void FixupState(void);
63c95b42baSmrgstatic void SetBackgroundToBitmap(Pixmap bitmap,
64c95b42baSmrg				  unsigned int width, unsigned int height);
65c95b42baSmrgstatic Cursor CreateCursorFromFiles(char *cursor_file, char *mask_file);
66c95b42baSmrgstatic Cursor CreateCursorFromName(char *name);
67c95b42baSmrgstatic Pixmap MakeModulaBitmap(int mod_x, int mod_y);
68c95b42baSmrgstatic XColor NameToXColor(char *name, unsigned long pixel);
69c95b42baSmrgstatic unsigned long NameToPixel(char *name, unsigned long pixel);
70c95b42baSmrgstatic Pixmap ReadBitmapFile(char *filename, unsigned int *width, unsigned int *height, int *x_hot, int *y_hot);
71c95b42baSmrg
72b8f63ae3Smrgstatic void _X_NORETURN _X_COLD
73b8f63ae3Smrgusage(const char *errmsg)
74c95b42baSmrg{
75b8f63ae3Smrg    if (errmsg != NULL)
76b8f63ae3Smrg	fprintf (stderr, "%s: %s\n\n", program_name, errmsg);
77b8f63ae3Smrg
78b8f63ae3Smrg    fprintf(stderr, "Usage: %s [options]\n%s\n", program_name,
7962aeb71dSmrg            "  where options are:\n"
80b8f63ae3Smrg            "  -help                           Print this help\n"
81b8f63ae3Smrg            "  -version                        Print a version message\n"
82b8f63ae3Smrg            "  -def, -default                  Reset unspecified attributes\n"
83b8f63ae3Smrg            "  -cursor <cursorfile> <maskfile> Pointer cursor used when outside of any windows\n"
84b8f63ae3Smrg            "  -cursor_name <cursorfontname>   Use a pointer cursor from the cursor font\n"
85b8f63ae3Smrg            "  -xcf <cursorfile> <cursorsize>  Load a pointer cursor from an Xcursor file\n"
86b8f63ae3Smrg            "  -bitmap <filename>              Use the bitmap specified in the file\n"
87b8f63ae3Smrg            "  -mod <x> <y>                    Use a plaid-like grid pattern on screen\n"
88b8f63ae3Smrg            "  -gray, -grey                    Make the entire background grey\n"
89b8f63ae3Smrg            "  -bg,  -background <color>       Set background color\n"
90b8f63ae3Smrg            "  -fg,  -foreground <color>       Set foreground color\n"
91b8f63ae3Smrg            "  -rv,  -reverse                  Swap foreground and background colors\n"
92b8f63ae3Smrg            "  -solid <color>                  Set the background of the root window\n"
93b8f63ae3Smrg            "  -name <string>                  Set the name of the root window\n"
94b8f63ae3Smrg            "  -d,   -display <display>        Specifies the server to connect to\n"
9562aeb71dSmrg            );
96c95b42baSmrg    exit(1);
97c95b42baSmrg    /*NOTREACHED*/
98c95b42baSmrg}
99c95b42baSmrg
100c95b42baSmrg
101c95b42baSmrgint
102c95b42baSmrgmain(int argc, char *argv[])
103c95b42baSmrg{
104c95b42baSmrg    int excl = 0;
105c95b42baSmrg    int nonexcl = 0;
106c95b42baSmrg    int restore_defaults = 0;
107c95b42baSmrg    char *display_name = NULL;
108c95b42baSmrg    char *name = NULL;
109c95b42baSmrg    char *cursor_file = NULL;
110c95b42baSmrg    char *cursor_mask = NULL;
111c95b42baSmrg    char *cursor_name = NULL;
112c95b42baSmrg    char *solid_color = NULL;
113d80571a9Smrg    char *xcf = NULL;
114d80571a9Smrg    int xcf_size = 32;
115c95b42baSmrg    Cursor cursor;
116c95b42baSmrg    int gray = 0;
117c95b42baSmrg    char *bitmap_file = NULL;
118c95b42baSmrg    int mod_x = 0;
119c95b42baSmrg    int mod_y = 0;
120c95b42baSmrg    register int i;
121c95b42baSmrg    unsigned int ww, hh;
122c95b42baSmrg    Pixmap bitmap;
123c95b42baSmrg
124c95b42baSmrg    program_name=argv[0];
125c95b42baSmrg
126c95b42baSmrg    for (i = 1; i < argc; i++) {
127c95b42baSmrg	if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
128b8f63ae3Smrg	    if (++i>=argc) usage ("-display requires an argument");
129c95b42baSmrg	    display_name = argv[i];
130c95b42baSmrg	    continue;
131c95b42baSmrg	}
132c95b42baSmrg	if (!strcmp("-help", argv[i])) {
133b8f63ae3Smrg	    usage(NULL);
134c95b42baSmrg	}
13562aeb71dSmrg	if (!strcmp("-version", argv[i])) {
13662aeb71dSmrg            printf("%s\n", PACKAGE_STRING);
13762aeb71dSmrg            exit(0);
13862aeb71dSmrg	}
139c95b42baSmrg	if (!strcmp("-def", argv[i]) || !strcmp("-default", argv[i])) {
140c95b42baSmrg	    restore_defaults = 1;
141c95b42baSmrg	    continue;
142c95b42baSmrg	}
143c95b42baSmrg	if (!strcmp("-name", argv[i])) {
144b8f63ae3Smrg	    if (++i>=argc) usage("-name requires an argument");
145c95b42baSmrg	    name = argv[i];
146c95b42baSmrg	    nonexcl++;
147c95b42baSmrg	    continue;
148c95b42baSmrg	}
149c95b42baSmrg	if (!strcmp("-cursor", argv[i])) {
150b8f63ae3Smrg	    if (++i>=argc)
151b8f63ae3Smrg		usage("missing cursorfile & maskfile arguments for -cursor");
152c95b42baSmrg	    cursor_file = argv[i];
153b8f63ae3Smrg	    if (++i>=argc)
154b8f63ae3Smrg		usage("missing maskfile argument for -cursor");
155c95b42baSmrg	    cursor_mask = argv[i];
156c95b42baSmrg	    nonexcl++;
157c95b42baSmrg	    continue;
158c95b42baSmrg	}
159c95b42baSmrg	if (!strcmp("-cursor_name", argv[i])) {
160b8f63ae3Smrg	    if (++i>=argc) usage("-cursor_name requires an argument");
161c95b42baSmrg	    cursor_name = argv[i];
162c95b42baSmrg	    nonexcl++;
163c95b42baSmrg	    continue;
164c95b42baSmrg	}
165d80571a9Smrg	if (!strcmp("-xcf", argv[i])) {
166b8f63ae3Smrg	    if (++i>=argc)
167b8f63ae3Smrg		usage("missing cursorfile & cursorsize arguments for -xcf");
168d80571a9Smrg	    xcf = argv[i];
169b8f63ae3Smrg	    if (++i>=argc)
170b8f63ae3Smrg		usage("missing cursorsize argument for -xcf");
171d80571a9Smrg	    xcf_size = atoi(argv[i]);
172d80571a9Smrg	    if (xcf_size <= 0)
173d80571a9Smrg		xcf_size = 32;
174d80571a9Smrg	    nonexcl++;
175d80571a9Smrg	    continue;
176d80571a9Smrg	}
177c95b42baSmrg	if (!strcmp("-fg",argv[i]) || !strcmp("-foreground",argv[i])) {
178b8f63ae3Smrg	    if (++i>=argc) usage("-foreground requires an argument");
179c95b42baSmrg	    fore_color = argv[i];
180c95b42baSmrg	    continue;
181c95b42baSmrg	}
182c95b42baSmrg	if (!strcmp("-bg",argv[i]) || !strcmp("-background",argv[i])) {
183b8f63ae3Smrg	    if (++i>=argc) usage("-background requires an argument");
184c95b42baSmrg	    back_color = argv[i];
185c95b42baSmrg	    continue;
186c95b42baSmrg	}
187c95b42baSmrg	if (!strcmp("-solid", argv[i])) {
188b8f63ae3Smrg	    if (++i>=argc) usage("-solid requires an argument");
189c95b42baSmrg	    solid_color = argv[i];
190c95b42baSmrg	    excl++;
191c95b42baSmrg	    continue;
192c95b42baSmrg	}
193c95b42baSmrg	if (!strcmp("-gray", argv[i]) || !strcmp("-grey", argv[i])) {
194c95b42baSmrg	    gray = 1;
195c95b42baSmrg	    excl++;
196c95b42baSmrg	    continue;
197c95b42baSmrg	}
198c95b42baSmrg	if (!strcmp("-bitmap", argv[i])) {
199b8f63ae3Smrg	    if (++i>=argc) usage("-bitmap requires an argument");
200c95b42baSmrg	    bitmap_file = argv[i];
201c95b42baSmrg	    excl++;
202c95b42baSmrg	    continue;
203c95b42baSmrg	}
204c95b42baSmrg	if (!strcmp("-mod", argv[i])) {
205b8f63ae3Smrg	    if (++i>=argc) usage("missing x & y arguments for -mod");
206c95b42baSmrg	    mod_x = atoi(argv[i]);
207c95b42baSmrg	    if (mod_x <= 0) mod_x = 1;
208b8f63ae3Smrg	    if (++i>=argc) usage("missing y argument for -mod");
209c95b42baSmrg	    mod_y = atoi(argv[i]);
210c95b42baSmrg	    if (mod_y <= 0) mod_y = 1;
211c95b42baSmrg	    excl++;
212c95b42baSmrg	    continue;
213c95b42baSmrg	}
214c95b42baSmrg	if (!strcmp("-rv",argv[i]) || !strcmp("-reverse",argv[i])) {
215c95b42baSmrg	    reverse = 1;
216c95b42baSmrg	    continue;
217c95b42baSmrg	}
218b8f63ae3Smrg	fprintf(stderr, "%s: unrecognized argument '%s'\n",
219b8f63ae3Smrg		program_name, argv[i]);
220b8f63ae3Smrg	usage(NULL);
221c95b42baSmrg    }
222c95b42baSmrg
223c95b42baSmrg    /* Check for multiple use of exclusive options */
224c95b42baSmrg    if (excl > 1) {
225c95b42baSmrg	fprintf(stderr, "%s: choose only one of {solid, gray, bitmap, mod}\n",
226c95b42baSmrg		program_name);
227b8f63ae3Smrg	usage(NULL);
228c95b42baSmrg    }
229c95b42baSmrg
230c95b42baSmrg    dpy = XOpenDisplay(display_name);
231c95b42baSmrg    if (!dpy) {
232c95b42baSmrg	fprintf(stderr, "%s:  unable to open display '%s'\n",
233c95b42baSmrg		program_name, XDisplayName (display_name));
234c95b42baSmrg	exit (2);
235c95b42baSmrg    }
236c95b42baSmrg    screen = DefaultScreen(dpy);
237c95b42baSmrg    root = RootWindow(dpy, screen);
238c95b42baSmrg
239c95b42baSmrg    /* If there are no arguments then restore defaults. */
240c95b42baSmrg    if (!excl && !nonexcl)
241c95b42baSmrg	restore_defaults = 1;
242c95b42baSmrg
243c95b42baSmrg    /* Handle a cursor file */
244c95b42baSmrg    if (cursor_file) {
245c95b42baSmrg	cursor = CreateCursorFromFiles(cursor_file, cursor_mask);
246c95b42baSmrg	XDefineCursor(dpy, root, cursor);
247c95b42baSmrg	XFreeCursor(dpy, cursor);
248c95b42baSmrg    }
249c95b42baSmrg
250c95b42baSmrg    if (cursor_name) {
251c95b42baSmrg	cursor = CreateCursorFromName (cursor_name);
252c95b42baSmrg	if (cursor)
253c95b42baSmrg	{
254c95b42baSmrg	    XDefineCursor (dpy, root, cursor);
255c95b42baSmrg	    XFreeCursor (dpy, cursor);
256c95b42baSmrg	}
257c95b42baSmrg    }
258d80571a9Smrg    if (xcf) {
259d80571a9Smrg	XcursorImages *images = XcursorFilenameLoadImages(xcf, xcf_size);
260d80571a9Smrg	if (!images) {
261d80571a9Smrg	    fprintf(stderr, "Invalid cursor file \"%s\"\n", xcf);
262d80571a9Smrg	} else {
263d80571a9Smrg	    cursor = XcursorImagesLoadCursor(dpy, images);
264d80571a9Smrg	    if (cursor)
265d80571a9Smrg	    {
266d80571a9Smrg		XDefineCursor (dpy, root, cursor);
267d80571a9Smrg		XFreeCursor (dpy, cursor);
268d80571a9Smrg	    }
269d80571a9Smrg	}
270d80571a9Smrg    }
271c95b42baSmrg    /* Handle -gray and -grey options */
272c95b42baSmrg    if (gray) {
273c95b42baSmrg	bitmap = XCreateBitmapFromData(dpy, root, gray_bits,
274c95b42baSmrg				       gray_width, gray_height);
275c95b42baSmrg	SetBackgroundToBitmap(bitmap, gray_width, gray_height);
276c95b42baSmrg    }
277c95b42baSmrg
278c95b42baSmrg    /* Handle -solid option */
279c95b42baSmrg    if (solid_color) {
280c95b42baSmrg	XSetWindowBackground(dpy, root, NameToPixel(solid_color,
281c95b42baSmrg						    BlackPixel(dpy, screen)));
282c95b42baSmrg	XClearWindow(dpy, root);
283c95b42baSmrg	unsave_past = 1;
284c95b42baSmrg    }
285c95b42baSmrg
286c95b42baSmrg    /* Handle -bitmap option */
287c95b42baSmrg    if (bitmap_file) {
288c95b42baSmrg	bitmap = ReadBitmapFile(bitmap_file, &ww, &hh, (int *)NULL, (int *)NULL);
289c95b42baSmrg	SetBackgroundToBitmap(bitmap, ww, hh);
290c95b42baSmrg    }
291c95b42baSmrg
292c95b42baSmrg    /* Handle set background to a modula pattern */
293c95b42baSmrg    if (mod_x) {
294c95b42baSmrg	bitmap = MakeModulaBitmap(mod_x, mod_y);
295c95b42baSmrg	SetBackgroundToBitmap(bitmap, 16, 16);
296c95b42baSmrg    }
297c95b42baSmrg
298c95b42baSmrg    /* Handle set name */
299c95b42baSmrg    if (name)
300c95b42baSmrg	XStoreName(dpy, root, name);
301c95b42baSmrg
302c95b42baSmrg    /* Handle restore defaults */
303c95b42baSmrg    if (restore_defaults) {
304c95b42baSmrg	if (!cursor_file)
305c95b42baSmrg	    XUndefineCursor(dpy, root);
306c95b42baSmrg	if (!excl) {
307c95b42baSmrg	    XSetWindowBackgroundPixmap(dpy, root, (Pixmap) None);
308c95b42baSmrg	    XClearWindow(dpy, root);
309c95b42baSmrg	    unsave_past = 1;
310c95b42baSmrg	}
311c95b42baSmrg    }
312c95b42baSmrg
313c95b42baSmrg    FixupState();
314c95b42baSmrg    XCloseDisplay(dpy);
315c95b42baSmrg    exit (0);
316c95b42baSmrg}
317c95b42baSmrg
318c95b42baSmrg
319c95b42baSmrg/* Free past incarnation if needed, and retain state if needed. */
320c95b42baSmrgstatic void
321c95b42baSmrgFixupState(void)
322c95b42baSmrg{
323c95b42baSmrg    Atom prop, type;
324c95b42baSmrg    int format;
325c95b42baSmrg    unsigned long length, after;
326c95b42baSmrg    unsigned char *data;
327c95b42baSmrg
328c95b42baSmrg    if (!(DefaultVisual(dpy, screen)->class & Dynamic))
329c95b42baSmrg	unsave_past = 0;
330c95b42baSmrg    if (!unsave_past && !save_colors)
331c95b42baSmrg	return;
332c95b42baSmrg    prop = XInternAtom(dpy, "_XSETROOT_ID", False);
333c95b42baSmrg    if (unsave_past) {
334b8f63ae3Smrg	if (XGetWindowProperty(dpy, root, prop, 0L, 1L, True, AnyPropertyType,
335b8f63ae3Smrg		       &type, &format, &length, &after, &data) != Success)
336b8f63ae3Smrg	    fprintf(stderr,
337b8f63ae3Smrg		    "%s: warning: cannot get _XSETROOT_ID property from root window\n",
338b8f63ae3Smrg		    program_name);
339b8f63ae3Smrg	else if ((type == XA_PIXMAP) && (format == 32) &&
340b8f63ae3Smrg		 (length == 1) && (after == 0))
341c95b42baSmrg	    XKillClient(dpy, *((Pixmap *)data));
342c95b42baSmrg	else if (type != None)
343c95b42baSmrg	    fprintf(stderr, "%s: warning: _XSETROOT_ID property is garbage\n",
344c95b42baSmrg		    program_name);
345c95b42baSmrg    }
346c95b42baSmrg    if (save_colors) {
347c95b42baSmrg	if (!save_pixmap)
348c95b42baSmrg	    save_pixmap = XCreatePixmap(dpy, root, 1, 1, 1);
349c95b42baSmrg	XChangeProperty(dpy, root, prop, XA_PIXMAP, 32, PropModeReplace,
350c95b42baSmrg			(unsigned char *) &save_pixmap, 1);
351c95b42baSmrg	XSetCloseDownMode(dpy, RetainPermanent);
352c95b42baSmrg    }
353c95b42baSmrg}
354c95b42baSmrg
355c95b42baSmrg/*
356c95b42baSmrg * SetBackgroundToBitmap: Set the root window background to a caller supplied
357c95b42baSmrg *                        bitmap.
358c95b42baSmrg */
359c95b42baSmrgstatic void
360c95b42baSmrgSetBackgroundToBitmap(Pixmap bitmap, unsigned int width, unsigned int height)
361c95b42baSmrg{
362c95b42baSmrg    Pixmap pix;
363c95b42baSmrg    GC gc;
364c95b42baSmrg    XGCValues gc_init;
365c95b42baSmrg
366c95b42baSmrg    gc_init.foreground = NameToPixel(fore_color, BlackPixel(dpy, screen));
367c95b42baSmrg    gc_init.background = NameToPixel(back_color, WhitePixel(dpy, screen));
368c95b42baSmrg    if (reverse) {
369c95b42baSmrg	unsigned long temp=gc_init.foreground;
370c95b42baSmrg	gc_init.foreground=gc_init.background;
371c95b42baSmrg	gc_init.background=temp;
372c95b42baSmrg    }
373c95b42baSmrg    gc = XCreateGC(dpy, root, GCForeground|GCBackground, &gc_init);
374c95b42baSmrg    pix = XCreatePixmap(dpy, root, width, height,
375c95b42baSmrg			(unsigned int)DefaultDepth(dpy, screen));
376c95b42baSmrg    XCopyPlane(dpy, bitmap, pix, gc, 0, 0, width, height, 0, 0, (unsigned long)1);
377c95b42baSmrg    XSetWindowBackgroundPixmap(dpy, root, pix);
378c95b42baSmrg    XFreeGC(dpy, gc);
379c95b42baSmrg    XFreePixmap(dpy, bitmap);
380c95b42baSmrg    if (save_colors)
381c95b42baSmrg	save_pixmap = pix;
382c95b42baSmrg    else
383c95b42baSmrg	XFreePixmap(dpy, pix);
384c95b42baSmrg    XClearWindow(dpy, root);
385c95b42baSmrg    unsave_past = 1;
386c95b42baSmrg}
387c95b42baSmrg
388c95b42baSmrg
389c95b42baSmrg/*
390c95b42baSmrg * CreateCursorFromFiles: make a cursor of the right colors from two bitmap
391c95b42baSmrg *                        files.
392c95b42baSmrg */
393c95b42baSmrg#define BITMAP_HOT_DEFAULT 8
394c95b42baSmrg
395c95b42baSmrgstatic Cursor
396c95b42baSmrgCreateCursorFromFiles(char *cursor_file, char *mask_file)
397c95b42baSmrg{
398c95b42baSmrg    Pixmap cursor_bitmap, mask_bitmap;
399c95b42baSmrg    unsigned int width, height, ww, hh;
400c95b42baSmrg    int x_hot, y_hot;
401c95b42baSmrg    Cursor cursor;
402c95b42baSmrg    XColor fg, bg, temp;
403c95b42baSmrg
404c95b42baSmrg    fg = NameToXColor(fore_color, BlackPixel(dpy, screen));
405c95b42baSmrg    bg = NameToXColor(back_color, WhitePixel(dpy, screen));
406c95b42baSmrg    if (reverse) {
407c95b42baSmrg	temp = fg; fg = bg; bg = temp;
408c95b42baSmrg    }
409c95b42baSmrg
410c95b42baSmrg    cursor_bitmap = ReadBitmapFile(cursor_file, &width, &height, &x_hot, &y_hot);
411c95b42baSmrg    mask_bitmap = ReadBitmapFile(mask_file, &ww, &hh, (int *)NULL, (int *)NULL);
412c95b42baSmrg
413c95b42baSmrg    if (width != ww || height != hh) {
414c95b42baSmrg	fprintf(stderr,
415c95b42baSmrg"%s: dimensions of cursor bitmap and cursor mask bitmap are different\n",
416c95b42baSmrg		program_name);
417c95b42baSmrg	exit(1);
418c95b42baSmrg	/*NOTREACHED*/
419c95b42baSmrg    }
420c95b42baSmrg
421c95b42baSmrg    if ((x_hot == -1) && (y_hot == -1)) {
422c95b42baSmrg	x_hot = BITMAP_HOT_DEFAULT;
423c95b42baSmrg	y_hot = BITMAP_HOT_DEFAULT;
424c95b42baSmrg    }
425c95b42baSmrg    if ((x_hot < 0) || (x_hot >= width) ||
426c95b42baSmrg	(y_hot < 0) || (y_hot >= height)) {
427c95b42baSmrg	fprintf(stderr, "%s: hotspot is outside cursor bounds\n", program_name);
428c95b42baSmrg	exit(1);
429c95b42baSmrg	/*NOTREACHED*/
430c95b42baSmrg    }
431c95b42baSmrg
432c95b42baSmrg    cursor = XCreatePixmapCursor(dpy, cursor_bitmap, mask_bitmap, &fg, &bg,
433c95b42baSmrg				 (unsigned int)x_hot, (unsigned int)y_hot);
434c95b42baSmrg    XFreePixmap(dpy, cursor_bitmap);
435c95b42baSmrg    XFreePixmap(dpy, mask_bitmap);
436c95b42baSmrg
437c95b42baSmrg    return(cursor);
438c95b42baSmrg}
439c95b42baSmrg
440c95b42baSmrgstatic Cursor
441c95b42baSmrgCreateCursorFromName(char *name)
442c95b42baSmrg{
443c95b42baSmrg    XColor fg, bg, temp;
444c95b42baSmrg    int	    i;
445c95b42baSmrg    Font    fid;
446c95b42baSmrg
447c95b42baSmrg    fg = NameToXColor(fore_color, BlackPixel(dpy, screen));
448c95b42baSmrg    bg = NameToXColor(back_color, WhitePixel(dpy, screen));
449c95b42baSmrg    if (reverse) {
450c95b42baSmrg	temp = fg; fg = bg; bg = temp;
451c95b42baSmrg    }
452c95b42baSmrg    i = XmuCursorNameToIndex (name);
453c95b42baSmrg    if (i == -1)
454c95b42baSmrg	return (Cursor) 0;
455c95b42baSmrg    fid = XLoadFont (dpy, "cursor");
456c95b42baSmrg    if (!fid)
457c95b42baSmrg	return (Cursor) 0;
458c95b42baSmrg    return XCreateGlyphCursor (dpy, fid, fid,
459c95b42baSmrg			       i, i+1, &fg, &bg);
460c95b42baSmrg}
461c95b42baSmrg
462c95b42baSmrg/*
463c95b42baSmrg * MakeModulaBitmap: Returns a modula bitmap based on an x & y mod.
464c95b42baSmrg */
465c95b42baSmrgstatic Pixmap
466c95b42baSmrgMakeModulaBitmap(int mod_x, int mod_y)
467c95b42baSmrg{
468c95b42baSmrg    int i;
469c95b42baSmrg    long pattern_line = 0;
470c95b42baSmrg    char modula_data[16*16/8];
471c95b42baSmrg
472c95b42baSmrg    for (i=16; i--; ) {
473c95b42baSmrg	pattern_line <<=1;
474c95b42baSmrg	if ((i % mod_x) == 0) pattern_line |= 0x0001;
475c95b42baSmrg    }
476c95b42baSmrg    for (i=0; i<16; i++) {
477c95b42baSmrg	if ((i % mod_y) == 0) {
478c95b42baSmrg	    modula_data[i*2] = (char)0xff;
479c95b42baSmrg	    modula_data[i*2+1] = (char)0xff;
480c95b42baSmrg	} else {
481c95b42baSmrg	    modula_data[i*2] = pattern_line & 0xff;
482c95b42baSmrg	    modula_data[i*2+1] = (pattern_line>>8) & 0xff;
483c95b42baSmrg	}
484c95b42baSmrg    }
485c95b42baSmrg
486c95b42baSmrg    return(XCreateBitmapFromData(dpy, root, modula_data, 16, 16));
487c95b42baSmrg}
488c95b42baSmrg
489c95b42baSmrg
490c95b42baSmrg/*
491c95b42baSmrg * NameToXColor: Convert the name of a color to its Xcolor value.
492c95b42baSmrg */
493c95b42baSmrgstatic XColor
494c95b42baSmrgNameToXColor(char *name, unsigned long pixel)
495c95b42baSmrg{
496c95b42baSmrg    XColor c;
497c95b42baSmrg
498c95b42baSmrg    if (!name || !*name) {
499c95b42baSmrg	c.pixel = pixel;
500c95b42baSmrg	XQueryColor(dpy, DefaultColormap(dpy, screen), &c);
501c95b42baSmrg    } else if (!XParseColor(dpy, DefaultColormap(dpy, screen), name, &c)) {
502c95b42baSmrg	fprintf(stderr, "%s: unknown color or bad color format: %s\n",
503c95b42baSmrg			program_name, name);
504c95b42baSmrg	exit(1);
505c95b42baSmrg	/*NOTREACHED*/
506c95b42baSmrg    }
507c95b42baSmrg    return(c);
508c95b42baSmrg}
509c95b42baSmrg
510c95b42baSmrgstatic unsigned long
511c95b42baSmrgNameToPixel(char *name, unsigned long pixel)
512c95b42baSmrg{
513c95b42baSmrg    XColor ecolor;
514c95b42baSmrg
515c95b42baSmrg    if (!name || !*name)
516c95b42baSmrg	return pixel;
517c95b42baSmrg    if (!XParseColor(dpy,DefaultColormap(dpy,screen),name,&ecolor)) {
518c95b42baSmrg	fprintf(stderr,"%s:  unknown color \"%s\"\n",program_name,name);
519c95b42baSmrg	exit(1);
520c95b42baSmrg	/*NOTREACHED*/
521c95b42baSmrg    }
522c95b42baSmrg    if (!XAllocColor(dpy, DefaultColormap(dpy, screen),&ecolor)) {
523c95b42baSmrg	fprintf(stderr, "%s:  unable to allocate color for \"%s\"\n",
524c95b42baSmrg		program_name, name);
525c95b42baSmrg	exit(1);
526c95b42baSmrg	/*NOTREACHED*/
527c95b42baSmrg    }
528c95b42baSmrg    if ((ecolor.pixel != BlackPixel(dpy, screen)) &&
529c95b42baSmrg	(ecolor.pixel != WhitePixel(dpy, screen)) &&
530c95b42baSmrg	(DefaultVisual(dpy, screen)->class & Dynamic))
531c95b42baSmrg	save_colors = 1;
532c95b42baSmrg    return(ecolor.pixel);
533c95b42baSmrg}
534c95b42baSmrg
535c95b42baSmrgstatic Pixmap
536c95b42baSmrgReadBitmapFile(char *filename, unsigned int *width, unsigned int *height,
537c95b42baSmrg	       int *x_hot, int *y_hot)
538c95b42baSmrg{
539c95b42baSmrg    Pixmap bitmap;
540c95b42baSmrg    int status;
541c95b42baSmrg
542c95b42baSmrg    status = XReadBitmapFile(dpy, root, filename, width,
543c95b42baSmrg			     height, &bitmap, x_hot, y_hot);
544c95b42baSmrg    if (status == BitmapSuccess)
545c95b42baSmrg      return(bitmap);
546c95b42baSmrg    else if (status == BitmapOpenFailed)
547c95b42baSmrg	fprintf(stderr, "%s: can't open file: %s\n", program_name, filename);
548c95b42baSmrg    else if (status == BitmapFileInvalid)
549c95b42baSmrg	fprintf(stderr, "%s: bad bitmap format file: %s\n",
550c95b42baSmrg			program_name, filename);
551c95b42baSmrg    else
552c95b42baSmrg	fprintf(stderr, "%s: insufficient memory for bitmap: %s",
553c95b42baSmrg			program_name, filename);
554c95b42baSmrg    exit(1);
555c95b42baSmrg    /*NOTREACHED*/
556c95b42baSmrg}
557