1 /* xscreensaver, Copyright (c) 1992-2014 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
13 #include "resources.h"
15 extern char *progname;
18 #if !defined(HAVE_COCOA) && !defined(HAVE_ANDROID)
20 #include <X11/Xresource.h>
22 /* These are the Xlib/Xrm versions of these functions.
23 The Cocoa versions are on OSX/XScreenSaverView.m.
26 extern char *progclass;
27 extern XrmDatabase XtDatabase (Display *);
29 static unsigned int get_time_resource (Display *dpy,
30 char *res_name, char *res_class,
34 # define isupper(c) ((c) >= 'A' && (c) <= 'Z')
37 # define _tolower(c) ((c) - 'A' + 'a')
41 get_string_resource (Display *dpy, char *res_name, char *res_class)
45 char full_name [1024], full_class [1024];
46 strcpy (full_name, progname);
47 strcat (full_name, ".");
48 strcat (full_name, res_name);
49 strcpy (full_class, progclass);
50 strcat (full_class, ".");
51 strcat (full_class, res_class);
52 if (XrmGetResource (XtDatabase (dpy), full_name, full_class, &type, &value))
54 char *str = (char *) malloc (value.size + 1);
55 strncpy (str, (char *) value.addr, value.size);
63 get_boolean_resource (Display *dpy, char *res_name, char *res_class)
66 char *s = get_string_resource (dpy, res_name, res_class);
69 for (tmp = buf; *s; s++)
70 *tmp++ = isupper (*s) ? _tolower (*s) : *s;
75 (buf[strlen(buf)-1] == ' ' ||
76 buf[strlen(buf)-1] == '\t'))
77 buf[strlen(buf)-1] = 0;
79 if (!strcmp (buf, "on") || !strcmp (buf, "true") || !strcmp (buf, "yes"))
81 if (!strcmp (buf,"off") || !strcmp (buf, "false") || !strcmp (buf,"no"))
83 fprintf (stderr, "%s: %s must be boolean, not %s.\n",
84 progname, res_name, buf);
89 get_integer_resource (Display *dpy, char *res_name, char *res_class)
92 char c, *s = get_string_resource (dpy, res_name, res_class);
96 while (*ss && *ss <= ' ') ss++; /* skip whitespace */
98 if (ss[0] == '0' && (ss[1] == 'x' || ss[1] == 'X')) /* 0x: parse as hex */
100 if (1 == sscanf (ss+2, "%x %c", (unsigned int *) &val, &c))
106 else /* else parse as dec */
108 if (1 == sscanf (ss, "%d %c", &val, &c))
115 fprintf (stderr, "%s: %s must be an integer, not %s.\n",
116 progname, res_name, s);
122 get_float_resource (Display *dpy, char *res_name, char *res_class)
125 char c, *s = get_string_resource (dpy, res_name, res_class);
127 if (1 == sscanf (s, " %lf %c", &val, &c))
132 fprintf (stderr, "%s: %s must be a float, not %s.\n",
133 progname, res_name, s);
138 #endif /* !HAVE_COCOA && !HAVE_ANDROID */
141 /* These functions are the same with Xlib, Cocoa and Android:
146 get_pixel_resource (Display *dpy, Colormap cmap,
147 char *res_name, char *res_class)
150 char *s = get_string_resource (dpy, res_name, res_class);
153 if (!s) goto DEFAULT;
155 for (s2 = s + strlen(s) - 1; s2 > s; s2--)
156 if (*s2 == ' ' || *s2 == '\t')
161 if (! XParseColor (dpy, cmap, s, &color))
163 fprintf (stderr, "%s: can't parse color %s", progname, s);
167 if (! XAllocColor (dpy, cmap, &color))
169 fprintf (stderr, "%s: couldn't allocate color %s", progname, s);
174 return (unsigned int) color.pixel;
179 Bool black_p = (strlen(res_class) >= 10 &&
180 !strcasecmp ("Background",
181 res_class + strlen(res_class) - 10));
183 fprintf (stderr, ": using %s.\n", (black_p ? "black" : "white"));
184 color.flags = DoRed|DoGreen|DoBlue;
185 color.red = color.green = color.blue = (black_p ? 0 : 0xFFFF);
186 if (XAllocColor (dpy, cmap, &color))
187 return (unsigned int) color.pixel;
190 fprintf (stderr, "%s: couldn't allocate %s either!\n", progname,
191 (black_p ? "black" : "white"));
192 /* We can't use BlackPixel/WhitePixel here, because we don't know
193 what screen we're allocating on (only an issue when running inside
194 the xscreensaver daemon: for hacks, DefaultScreen is fine.)
203 parse_time (const char *string, Bool seconds_default_p, Bool silent_p)
205 unsigned int h, m, s;
207 if (3 == sscanf (string, " %u : %2u : %2u %c", &h, &m, &s, &c))
209 else if (2 == sscanf (string, " : %2u : %2u %c", &m, &s, &c) ||
210 2 == sscanf (string, " %u : %2u %c", &m, &s, &c))
212 else if (1 == sscanf (string, " : %2u %c", &s, &c))
214 else if (1 == sscanf (string, " %u %c",
215 (seconds_default_p ? &s : &m), &c))
218 if (seconds_default_p) m = 0;
224 fprintf (stderr, "%s: invalid time interval specification \"%s\".\n",
228 if (s >= 60 && (h != 0 || m != 0))
231 fprintf (stderr, "%s: seconds > 59 in \"%s\".\n", progname, string);
234 if (m >= 60 && h > 0)
237 fprintf (stderr, "%s: minutes > 59 in \"%s\".\n", progname, string);
240 return ((h * 60 * 60) + (m * 60) + s);
244 get_time_resource (Display *dpy, char *res_name, char *res_class, Bool sec_p)
247 char *s = get_string_resource (dpy, res_name, res_class);
249 val = parse_time (s, sec_p, False);
251 return (val < 0 ? 0 : val);
255 get_seconds_resource (Display *dpy, char *res_name, char *res_class)
257 return get_time_resource (dpy, res_name, res_class, True);
261 get_minutes_resource (Display *dpy, char *res_name, char *res_class)
263 return get_time_resource (dpy, res_name, res_class, False);
267 /* A utility function for event-handler functions:
268 Returns True if the event is a simple click, Space, Tab, etc.
269 Returns False otherwise.
270 The idea here is that most hacks interpret to clicks or basic
271 keypresses as "change it up".
273 This isn't really the right file for this, but whatever.
276 screenhack_event_helper (Display *dpy, Window window, XEvent *event)
278 if (event->xany.type == KeyPress)
282 XLookupString (&event->xkey, &c, 1, &keysym, 0);
283 if (c == ' ' || c == '\t' || c == '\r' || c == '\n' ||
284 keysym == XK_Left || keysym == XK_Right ||
285 keysym == XK_Up || keysym == XK_Down ||
286 keysym == XK_Prior || keysym == XK_Next)
289 else if (event->xany.type == ButtonPress)
291 if (event->xbutton.button == 1)