xsetroot.c revision 0f595aed
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    unsigned int ww, hh;
121c95b42baSmrg    Pixmap bitmap;
122c95b42baSmrg
123c95b42baSmrg    program_name=argv[0];
124c95b42baSmrg
1250f595aedSmrg    for (int i = 1; i < argc; i++) {
126c95b42baSmrg	if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
127b8f63ae3Smrg	    if (++i>=argc) usage ("-display requires an argument");
128c95b42baSmrg	    display_name = argv[i];
129c95b42baSmrg	    continue;
130c95b42baSmrg	}
131c95b42baSmrg	if (!strcmp("-help", argv[i])) {
132b8f63ae3Smrg	    usage(NULL);
133c95b42baSmrg	}
13462aeb71dSmrg	if (!strcmp("-version", argv[i])) {
13562aeb71dSmrg            printf("%s\n", PACKAGE_STRING);
13662aeb71dSmrg            exit(0);
13762aeb71dSmrg	}
138c95b42baSmrg	if (!strcmp("-def", argv[i]) || !strcmp("-default", argv[i])) {
139c95b42baSmrg	    restore_defaults = 1;
140c95b42baSmrg	    continue;
141c95b42baSmrg	}
142c95b42baSmrg	if (!strcmp("-name", argv[i])) {
143b8f63ae3Smrg	    if (++i>=argc) usage("-name requires an argument");
144c95b42baSmrg	    name = argv[i];
145c95b42baSmrg	    nonexcl++;
146c95b42baSmrg	    continue;
147c95b42baSmrg	}
148c95b42baSmrg	if (!strcmp("-cursor", argv[i])) {
149b8f63ae3Smrg	    if (++i>=argc)
150b8f63ae3Smrg		usage("missing cursorfile & maskfile arguments for -cursor");
151c95b42baSmrg	    cursor_file = argv[i];
152b8f63ae3Smrg	    if (++i>=argc)
153b8f63ae3Smrg		usage("missing maskfile argument for -cursor");
154c95b42baSmrg	    cursor_mask = argv[i];
155c95b42baSmrg	    nonexcl++;
156c95b42baSmrg	    continue;
157c95b42baSmrg	}
158c95b42baSmrg	if (!strcmp("-cursor_name", argv[i])) {
159b8f63ae3Smrg	    if (++i>=argc) usage("-cursor_name requires an argument");
160c95b42baSmrg	    cursor_name = argv[i];
161c95b42baSmrg	    nonexcl++;
162c95b42baSmrg	    continue;
163c95b42baSmrg	}
164d80571a9Smrg	if (!strcmp("-xcf", argv[i])) {
165b8f63ae3Smrg	    if (++i>=argc)
166b8f63ae3Smrg		usage("missing cursorfile & cursorsize arguments for -xcf");
167d80571a9Smrg	    xcf = argv[i];
168b8f63ae3Smrg	    if (++i>=argc)
169b8f63ae3Smrg		usage("missing cursorsize argument for -xcf");
170d80571a9Smrg	    xcf_size = atoi(argv[i]);
171d80571a9Smrg	    if (xcf_size <= 0)
172d80571a9Smrg		xcf_size = 32;
173d80571a9Smrg	    nonexcl++;
174d80571a9Smrg	    continue;
175d80571a9Smrg	}
176c95b42baSmrg	if (!strcmp("-fg",argv[i]) || !strcmp("-foreground",argv[i])) {
177b8f63ae3Smrg	    if (++i>=argc) usage("-foreground requires an argument");
178c95b42baSmrg	    fore_color = argv[i];
179c95b42baSmrg	    continue;
180c95b42baSmrg	}
181c95b42baSmrg	if (!strcmp("-bg",argv[i]) || !strcmp("-background",argv[i])) {
182b8f63ae3Smrg	    if (++i>=argc) usage("-background requires an argument");
183c95b42baSmrg	    back_color = argv[i];
184c95b42baSmrg	    continue;
185c95b42baSmrg	}
186c95b42baSmrg	if (!strcmp("-solid", argv[i])) {
187b8f63ae3Smrg	    if (++i>=argc) usage("-solid requires an argument");
188c95b42baSmrg	    solid_color = argv[i];
189c95b42baSmrg	    excl++;
190c95b42baSmrg	    continue;
191c95b42baSmrg	}
192c95b42baSmrg	if (!strcmp("-gray", argv[i]) || !strcmp("-grey", argv[i])) {
193c95b42baSmrg	    gray = 1;
194c95b42baSmrg	    excl++;
195c95b42baSmrg	    continue;
196c95b42baSmrg	}
197c95b42baSmrg	if (!strcmp("-bitmap", argv[i])) {
198b8f63ae3Smrg	    if (++i>=argc) usage("-bitmap requires an argument");
199c95b42baSmrg	    bitmap_file = argv[i];
200c95b42baSmrg	    excl++;
201c95b42baSmrg	    continue;
202c95b42baSmrg	}
203c95b42baSmrg	if (!strcmp("-mod", argv[i])) {
204b8f63ae3Smrg	    if (++i>=argc) usage("missing x & y arguments for -mod");
205c95b42baSmrg	    mod_x = atoi(argv[i]);
206c95b42baSmrg	    if (mod_x <= 0) mod_x = 1;
207b8f63ae3Smrg	    if (++i>=argc) usage("missing y argument for -mod");
208c95b42baSmrg	    mod_y = atoi(argv[i]);
209c95b42baSmrg	    if (mod_y <= 0) mod_y = 1;
210c95b42baSmrg	    excl++;
211c95b42baSmrg	    continue;
212c95b42baSmrg	}
213c95b42baSmrg	if (!strcmp("-rv",argv[i]) || !strcmp("-reverse",argv[i])) {
214c95b42baSmrg	    reverse = 1;
215c95b42baSmrg	    continue;
216c95b42baSmrg	}
217b8f63ae3Smrg	fprintf(stderr, "%s: unrecognized argument '%s'\n",
218b8f63ae3Smrg		program_name, argv[i]);
219b8f63ae3Smrg	usage(NULL);
220c95b42baSmrg    }
221c95b42baSmrg
222c95b42baSmrg    /* Check for multiple use of exclusive options */
223c95b42baSmrg    if (excl > 1) {
224c95b42baSmrg	fprintf(stderr, "%s: choose only one of {solid, gray, bitmap, mod}\n",
225c95b42baSmrg		program_name);
226b8f63ae3Smrg	usage(NULL);
227c95b42baSmrg    }
228c95b42baSmrg
229c95b42baSmrg    dpy = XOpenDisplay(display_name);
230c95b42baSmrg    if (!dpy) {
231c95b42baSmrg	fprintf(stderr, "%s:  unable to open display '%s'\n",
232c95b42baSmrg		program_name, XDisplayName (display_name));
233c95b42baSmrg	exit (2);
234c95b42baSmrg    }
235c95b42baSmrg    screen = DefaultScreen(dpy);
236c95b42baSmrg    root = RootWindow(dpy, screen);
237c95b42baSmrg
238c95b42baSmrg    /* If there are no arguments then restore defaults. */
239c95b42baSmrg    if (!excl && !nonexcl)
240c95b42baSmrg	restore_defaults = 1;
241c95b42baSmrg
242c95b42baSmrg    /* Handle a cursor file */
243c95b42baSmrg    if (cursor_file) {
244c95b42baSmrg	cursor = CreateCursorFromFiles(cursor_file, cursor_mask);
245c95b42baSmrg	XDefineCursor(dpy, root, cursor);
246c95b42baSmrg	XFreeCursor(dpy, cursor);
247c95b42baSmrg    }
248c95b42baSmrg
249c95b42baSmrg    if (cursor_name) {
250c95b42baSmrg	cursor = CreateCursorFromName (cursor_name);
251c95b42baSmrg	if (cursor)
252c95b42baSmrg	{
253c95b42baSmrg	    XDefineCursor (dpy, root, cursor);
254c95b42baSmrg	    XFreeCursor (dpy, cursor);
255c95b42baSmrg	}
256c95b42baSmrg    }
257d80571a9Smrg    if (xcf) {
258d80571a9Smrg	XcursorImages *images = XcursorFilenameLoadImages(xcf, xcf_size);
259d80571a9Smrg	if (!images) {
260d80571a9Smrg	    fprintf(stderr, "Invalid cursor file \"%s\"\n", xcf);
261d80571a9Smrg	} else {
262d80571a9Smrg	    cursor = XcursorImagesLoadCursor(dpy, images);
263d80571a9Smrg	    if (cursor)
264d80571a9Smrg	    {
265d80571a9Smrg		XDefineCursor (dpy, root, cursor);
266d80571a9Smrg		XFreeCursor (dpy, cursor);
267d80571a9Smrg	    }
268d80571a9Smrg	}
269d80571a9Smrg    }
270c95b42baSmrg    /* Handle -gray and -grey options */
271c95b42baSmrg    if (gray) {
272c95b42baSmrg	bitmap = XCreateBitmapFromData(dpy, root, gray_bits,
273c95b42baSmrg				       gray_width, gray_height);
274c95b42baSmrg	SetBackgroundToBitmap(bitmap, gray_width, gray_height);
275c95b42baSmrg    }
276c95b42baSmrg
277c95b42baSmrg    /* Handle -solid option */
278c95b42baSmrg    if (solid_color) {
279c95b42baSmrg	XSetWindowBackground(dpy, root, NameToPixel(solid_color,
280c95b42baSmrg						    BlackPixel(dpy, screen)));
281c95b42baSmrg	XClearWindow(dpy, root);
282c95b42baSmrg	unsave_past = 1;
283c95b42baSmrg    }
284c95b42baSmrg
285c95b42baSmrg    /* Handle -bitmap option */
286c95b42baSmrg    if (bitmap_file) {
287c95b42baSmrg	bitmap = ReadBitmapFile(bitmap_file, &ww, &hh, (int *)NULL, (int *)NULL);
288c95b42baSmrg	SetBackgroundToBitmap(bitmap, ww, hh);
289c95b42baSmrg    }
290c95b42baSmrg
291c95b42baSmrg    /* Handle set background to a modula pattern */
292c95b42baSmrg    if (mod_x) {
293c95b42baSmrg	bitmap = MakeModulaBitmap(mod_x, mod_y);
294c95b42baSmrg	SetBackgroundToBitmap(bitmap, 16, 16);
295c95b42baSmrg    }
296c95b42baSmrg
297c95b42baSmrg    /* Handle set name */
298c95b42baSmrg    if (name)
299c95b42baSmrg	XStoreName(dpy, root, name);
300c95b42baSmrg
301c95b42baSmrg    /* Handle restore defaults */
302c95b42baSmrg    if (restore_defaults) {
303c95b42baSmrg	if (!cursor_file)
304c95b42baSmrg	    XUndefineCursor(dpy, root);
305c95b42baSmrg	if (!excl) {
306c95b42baSmrg	    XSetWindowBackgroundPixmap(dpy, root, (Pixmap) None);
307c95b42baSmrg	    XClearWindow(dpy, root);
308c95b42baSmrg	    unsave_past = 1;
309c95b42baSmrg	}
310c95b42baSmrg    }
311c95b42baSmrg
312c95b42baSmrg    FixupState();
313c95b42baSmrg    XCloseDisplay(dpy);
314c95b42baSmrg    exit (0);
315c95b42baSmrg}
316c95b42baSmrg
317c95b42baSmrg
318c95b42baSmrg/* Free past incarnation if needed, and retain state if needed. */
319c95b42baSmrgstatic void
320c95b42baSmrgFixupState(void)
321c95b42baSmrg{
322c95b42baSmrg    Atom prop, type;
323c95b42baSmrg    int format;
324c95b42baSmrg    unsigned long length, after;
325c95b42baSmrg    unsigned char *data;
326c95b42baSmrg
327c95b42baSmrg    if (!(DefaultVisual(dpy, screen)->class & Dynamic))
328c95b42baSmrg	unsave_past = 0;
329c95b42baSmrg    if (!unsave_past && !save_colors)
330c95b42baSmrg	return;
331c95b42baSmrg    prop = XInternAtom(dpy, "_XSETROOT_ID", False);
332c95b42baSmrg    if (unsave_past) {
333b8f63ae3Smrg	if (XGetWindowProperty(dpy, root, prop, 0L, 1L, True, AnyPropertyType,
334b8f63ae3Smrg		       &type, &format, &length, &after, &data) != Success)
335b8f63ae3Smrg	    fprintf(stderr,
336b8f63ae3Smrg		    "%s: warning: cannot get _XSETROOT_ID property from root window\n",
337b8f63ae3Smrg		    program_name);
338b8f63ae3Smrg	else if ((type == XA_PIXMAP) && (format == 32) &&
339b8f63ae3Smrg		 (length == 1) && (after == 0))
340c95b42baSmrg	    XKillClient(dpy, *((Pixmap *)data));
341c95b42baSmrg	else if (type != None)
342c95b42baSmrg	    fprintf(stderr, "%s: warning: _XSETROOT_ID property is garbage\n",
343c95b42baSmrg		    program_name);
344c95b42baSmrg    }
345c95b42baSmrg    if (save_colors) {
346c95b42baSmrg	if (!save_pixmap)
347c95b42baSmrg	    save_pixmap = XCreatePixmap(dpy, root, 1, 1, 1);
348c95b42baSmrg	XChangeProperty(dpy, root, prop, XA_PIXMAP, 32, PropModeReplace,
349c95b42baSmrg			(unsigned char *) &save_pixmap, 1);
350c95b42baSmrg	XSetCloseDownMode(dpy, RetainPermanent);
351c95b42baSmrg    }
352c95b42baSmrg}
353c95b42baSmrg
354c95b42baSmrg/*
355c95b42baSmrg * SetBackgroundToBitmap: Set the root window background to a caller supplied
356c95b42baSmrg *                        bitmap.
357c95b42baSmrg */
358c95b42baSmrgstatic void
359c95b42baSmrgSetBackgroundToBitmap(Pixmap bitmap, unsigned int width, unsigned int height)
360c95b42baSmrg{
361c95b42baSmrg    Pixmap pix;
362c95b42baSmrg    GC gc;
363c95b42baSmrg    XGCValues gc_init;
364c95b42baSmrg
365c95b42baSmrg    gc_init.foreground = NameToPixel(fore_color, BlackPixel(dpy, screen));
366c95b42baSmrg    gc_init.background = NameToPixel(back_color, WhitePixel(dpy, screen));
367c95b42baSmrg    if (reverse) {
368c95b42baSmrg	unsigned long temp=gc_init.foreground;
369c95b42baSmrg	gc_init.foreground=gc_init.background;
370c95b42baSmrg	gc_init.background=temp;
371c95b42baSmrg    }
372c95b42baSmrg    gc = XCreateGC(dpy, root, GCForeground|GCBackground, &gc_init);
373c95b42baSmrg    pix = XCreatePixmap(dpy, root, width, height,
374c95b42baSmrg			(unsigned int)DefaultDepth(dpy, screen));
375c95b42baSmrg    XCopyPlane(dpy, bitmap, pix, gc, 0, 0, width, height, 0, 0, (unsigned long)1);
376c95b42baSmrg    XSetWindowBackgroundPixmap(dpy, root, pix);
377c95b42baSmrg    XFreeGC(dpy, gc);
378c95b42baSmrg    XFreePixmap(dpy, bitmap);
379c95b42baSmrg    if (save_colors)
380c95b42baSmrg	save_pixmap = pix;
381c95b42baSmrg    else
382c95b42baSmrg	XFreePixmap(dpy, pix);
383c95b42baSmrg    XClearWindow(dpy, root);
384c95b42baSmrg    unsave_past = 1;
385c95b42baSmrg}
386c95b42baSmrg
387c95b42baSmrg
388c95b42baSmrg/*
389c95b42baSmrg * CreateCursorFromFiles: make a cursor of the right colors from two bitmap
390c95b42baSmrg *                        files.
391c95b42baSmrg */
392c95b42baSmrg#define BITMAP_HOT_DEFAULT 8
393c95b42baSmrg
394c95b42baSmrgstatic Cursor
395c95b42baSmrgCreateCursorFromFiles(char *cursor_file, char *mask_file)
396c95b42baSmrg{
397c95b42baSmrg    Pixmap cursor_bitmap, mask_bitmap;
398c95b42baSmrg    unsigned int width, height, ww, hh;
399c95b42baSmrg    int x_hot, y_hot;
400c95b42baSmrg    Cursor cursor;
4010f595aedSmrg    XColor fg, bg;
402c95b42baSmrg
403c95b42baSmrg    fg = NameToXColor(fore_color, BlackPixel(dpy, screen));
404c95b42baSmrg    bg = NameToXColor(back_color, WhitePixel(dpy, screen));
405c95b42baSmrg    if (reverse) {
4060f595aedSmrg	XColor temp = fg;
4070f595aedSmrg	fg = bg;
4080f595aedSmrg	bg = temp;
409c95b42baSmrg    }
410c95b42baSmrg
411c95b42baSmrg    cursor_bitmap = ReadBitmapFile(cursor_file, &width, &height, &x_hot, &y_hot);
412c95b42baSmrg    mask_bitmap = ReadBitmapFile(mask_file, &ww, &hh, (int *)NULL, (int *)NULL);
413c95b42baSmrg
414c95b42baSmrg    if (width != ww || height != hh) {
415c95b42baSmrg	fprintf(stderr,
416c95b42baSmrg"%s: dimensions of cursor bitmap and cursor mask bitmap are different\n",
417c95b42baSmrg		program_name);
418c95b42baSmrg	exit(1);
419c95b42baSmrg	/*NOTREACHED*/
420c95b42baSmrg    }
421c95b42baSmrg
422c95b42baSmrg    if ((x_hot == -1) && (y_hot == -1)) {
423c95b42baSmrg	x_hot = BITMAP_HOT_DEFAULT;
424c95b42baSmrg	y_hot = BITMAP_HOT_DEFAULT;
425c95b42baSmrg    }
4260f595aedSmrg    if ((x_hot < 0) || ((unsigned int)x_hot >= width) ||
4270f595aedSmrg	(y_hot < 0) || ((unsigned int)y_hot >= height)) {
428c95b42baSmrg	fprintf(stderr, "%s: hotspot is outside cursor bounds\n", program_name);
429c95b42baSmrg	exit(1);
430c95b42baSmrg	/*NOTREACHED*/
431c95b42baSmrg    }
432c95b42baSmrg
433c95b42baSmrg    cursor = XCreatePixmapCursor(dpy, cursor_bitmap, mask_bitmap, &fg, &bg,
434c95b42baSmrg				 (unsigned int)x_hot, (unsigned int)y_hot);
435c95b42baSmrg    XFreePixmap(dpy, cursor_bitmap);
436c95b42baSmrg    XFreePixmap(dpy, mask_bitmap);
437c95b42baSmrg
438c95b42baSmrg    return(cursor);
439c95b42baSmrg}
440c95b42baSmrg
441c95b42baSmrgstatic Cursor
442c95b42baSmrgCreateCursorFromName(char *name)
443c95b42baSmrg{
4440f595aedSmrg    XColor fg, bg;
445c95b42baSmrg    int	    i;
446c95b42baSmrg    Font    fid;
447c95b42baSmrg
448c95b42baSmrg    fg = NameToXColor(fore_color, BlackPixel(dpy, screen));
449c95b42baSmrg    bg = NameToXColor(back_color, WhitePixel(dpy, screen));
450c95b42baSmrg    if (reverse) {
4510f595aedSmrg	XColor temp = fg;
4520f595aedSmrg	fg = bg;
4530f595aedSmrg	bg = temp;
454c95b42baSmrg    }
455c95b42baSmrg    i = XmuCursorNameToIndex (name);
456c95b42baSmrg    if (i == -1)
457c95b42baSmrg	return (Cursor) 0;
458c95b42baSmrg    fid = XLoadFont (dpy, "cursor");
459c95b42baSmrg    if (!fid)
460c95b42baSmrg	return (Cursor) 0;
461c95b42baSmrg    return XCreateGlyphCursor (dpy, fid, fid,
462c95b42baSmrg			       i, i+1, &fg, &bg);
463c95b42baSmrg}
464c95b42baSmrg
465c95b42baSmrg/*
466c95b42baSmrg * MakeModulaBitmap: Returns a modula bitmap based on an x & y mod.
467c95b42baSmrg */
468c95b42baSmrgstatic Pixmap
469c95b42baSmrgMakeModulaBitmap(int mod_x, int mod_y)
470c95b42baSmrg{
471c95b42baSmrg    long pattern_line = 0;
472c95b42baSmrg    char modula_data[16*16/8];
473c95b42baSmrg
4740f595aedSmrg    for (int i = 16; i--; ) {
475c95b42baSmrg	pattern_line <<=1;
476c95b42baSmrg	if ((i % mod_x) == 0) pattern_line |= 0x0001;
477c95b42baSmrg    }
4780f595aedSmrg    for (int i = 0; i < 16; i++) {
479c95b42baSmrg	if ((i % mod_y) == 0) {
480c95b42baSmrg	    modula_data[i*2] = (char)0xff;
481c95b42baSmrg	    modula_data[i*2+1] = (char)0xff;
482c95b42baSmrg	} else {
483c95b42baSmrg	    modula_data[i*2] = pattern_line & 0xff;
484c95b42baSmrg	    modula_data[i*2+1] = (pattern_line>>8) & 0xff;
485c95b42baSmrg	}
486c95b42baSmrg    }
487c95b42baSmrg
488c95b42baSmrg    return(XCreateBitmapFromData(dpy, root, modula_data, 16, 16));
489c95b42baSmrg}
490c95b42baSmrg
491c95b42baSmrg
492c95b42baSmrg/*
493c95b42baSmrg * NameToXColor: Convert the name of a color to its Xcolor value.
494c95b42baSmrg */
495c95b42baSmrgstatic XColor
496c95b42baSmrgNameToXColor(char *name, unsigned long pixel)
497c95b42baSmrg{
498c95b42baSmrg    XColor c;
499c95b42baSmrg
500c95b42baSmrg    if (!name || !*name) {
501c95b42baSmrg	c.pixel = pixel;
502c95b42baSmrg	XQueryColor(dpy, DefaultColormap(dpy, screen), &c);
503c95b42baSmrg    } else if (!XParseColor(dpy, DefaultColormap(dpy, screen), name, &c)) {
504c95b42baSmrg	fprintf(stderr, "%s: unknown color or bad color format: %s\n",
505c95b42baSmrg			program_name, name);
506c95b42baSmrg	exit(1);
507c95b42baSmrg	/*NOTREACHED*/
508c95b42baSmrg    }
509c95b42baSmrg    return(c);
510c95b42baSmrg}
511c95b42baSmrg
512c95b42baSmrgstatic unsigned long
513c95b42baSmrgNameToPixel(char *name, unsigned long pixel)
514c95b42baSmrg{
515c95b42baSmrg    XColor ecolor;
516c95b42baSmrg
517c95b42baSmrg    if (!name || !*name)
518c95b42baSmrg	return pixel;
519c95b42baSmrg    if (!XParseColor(dpy,DefaultColormap(dpy,screen),name,&ecolor)) {
520c95b42baSmrg	fprintf(stderr,"%s:  unknown color \"%s\"\n",program_name,name);
521c95b42baSmrg	exit(1);
522c95b42baSmrg	/*NOTREACHED*/
523c95b42baSmrg    }
524c95b42baSmrg    if (!XAllocColor(dpy, DefaultColormap(dpy, screen),&ecolor)) {
525c95b42baSmrg	fprintf(stderr, "%s:  unable to allocate color for \"%s\"\n",
526c95b42baSmrg		program_name, name);
527c95b42baSmrg	exit(1);
528c95b42baSmrg	/*NOTREACHED*/
529c95b42baSmrg    }
530c95b42baSmrg    if ((ecolor.pixel != BlackPixel(dpy, screen)) &&
531c95b42baSmrg	(ecolor.pixel != WhitePixel(dpy, screen)) &&
532c95b42baSmrg	(DefaultVisual(dpy, screen)->class & Dynamic))
533c95b42baSmrg	save_colors = 1;
534c95b42baSmrg    return(ecolor.pixel);
535c95b42baSmrg}
536c95b42baSmrg
537c95b42baSmrgstatic Pixmap
538c95b42baSmrgReadBitmapFile(char *filename, unsigned int *width, unsigned int *height,
539c95b42baSmrg	       int *x_hot, int *y_hot)
540c95b42baSmrg{
541c95b42baSmrg    Pixmap bitmap;
542c95b42baSmrg    int status;
543c95b42baSmrg
544c95b42baSmrg    status = XReadBitmapFile(dpy, root, filename, width,
545c95b42baSmrg			     height, &bitmap, x_hot, y_hot);
546c95b42baSmrg    if (status == BitmapSuccess)
547c95b42baSmrg      return(bitmap);
548c95b42baSmrg    else if (status == BitmapOpenFailed)
549c95b42baSmrg	fprintf(stderr, "%s: can't open file: %s\n", program_name, filename);
550c95b42baSmrg    else if (status == BitmapFileInvalid)
551c95b42baSmrg	fprintf(stderr, "%s: bad bitmap format file: %s\n",
552c95b42baSmrg			program_name, filename);
553c95b42baSmrg    else
554c95b42baSmrg	fprintf(stderr, "%s: insufficient memory for bitmap: %s",
555c95b42baSmrg			program_name, filename);
556c95b42baSmrg    exit(1);
557c95b42baSmrg    /*NOTREACHED*/
558c95b42baSmrg}
559