From http://www.jwz.org/xscreensaver/xscreensaver-5.27.tar.gz
[xscreensaver] / utils / resources.c
1 /* xscreensaver, Copyright (c) 1992, 1997, 1998, 2001, 2003, 2006
2  *  Jamie Zawinski <jwz@jwz.org>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  */
12
13 #include "utils.h"
14 #include "resources.h"
15
16 extern char *progname;
17
18
19 #ifndef HAVE_COCOA
20
21 #include <X11/Xresource.h>
22
23 /* These are the Xlib/Xrm versions of these functions.
24    The Cocoa versions are on OSX/XScreenSaverView.m.
25  */
26
27 extern char *progclass;
28 extern XrmDatabase XtDatabase (Display *);
29
30 static unsigned int get_time_resource (Display *dpy, 
31                                        char *res_name, char *res_class,
32                                        Bool sec_p);
33
34 #ifndef isupper
35 # define isupper(c)  ((c) >= 'A' && (c) <= 'Z')
36 #endif
37 #ifndef _tolower
38 # define _tolower(c)  ((c) - 'A' + 'a')
39 #endif
40
41 char *
42 get_string_resource (Display *dpy, char *res_name, char *res_class)
43 {
44   XrmValue value;
45   char  *type;
46   char full_name [1024], full_class [1024];
47   strcpy (full_name, progname);
48   strcat (full_name, ".");
49   strcat (full_name, res_name);
50   strcpy (full_class, progclass);
51   strcat (full_class, ".");
52   strcat (full_class, res_class);
53   if (XrmGetResource (XtDatabase (dpy), full_name, full_class, &type, &value))
54     {
55       char *str = (char *) malloc (value.size + 1);
56       strncpy (str, (char *) value.addr, value.size);
57       str [value.size] = 0;
58       return str;
59     }
60   return 0;
61 }
62
63 Bool 
64 get_boolean_resource (Display *dpy, char *res_name, char *res_class)
65 {
66   char *tmp, buf [100];
67   char *s = get_string_resource (dpy, res_name, res_class);
68   char *os = s;
69   if (! s) return 0;
70   for (tmp = buf; *s; s++)
71     *tmp++ = isupper (*s) ? _tolower (*s) : *s;
72   *tmp = 0;
73   free (os);
74
75   while (*buf &&
76          (buf[strlen(buf)-1] == ' ' ||
77           buf[strlen(buf)-1] == '\t'))
78     buf[strlen(buf)-1] = 0;
79
80   if (!strcmp (buf, "on") || !strcmp (buf, "true") || !strcmp (buf, "yes"))
81     return 1;
82   if (!strcmp (buf,"off") || !strcmp (buf, "false") || !strcmp (buf,"no"))
83     return 0;
84   fprintf (stderr, "%s: %s must be boolean, not %s.\n",
85            progname, res_name, buf);
86   return 0;
87 }
88
89 int 
90 get_integer_resource (Display *dpy, char *res_name, char *res_class)
91 {
92   int val;
93   char c, *s = get_string_resource (dpy, res_name, res_class);
94   char *ss = s;
95   if (!s) return 0;
96
97   while (*ss && *ss <= ' ') ss++;                       /* skip whitespace */
98
99   if (ss[0] == '0' && (ss[1] == 'x' || ss[1] == 'X'))   /* 0x: parse as hex */
100     {
101       if (1 == sscanf (ss+2, "%x %c", (unsigned int *) &val, &c))
102         {
103           free (s);
104           return val;
105         }
106     }
107   else                                                  /* else parse as dec */
108     {
109       if (1 == sscanf (ss, "%d %c", &val, &c))
110         {
111           free (s);
112           return val;
113         }
114     }
115
116   fprintf (stderr, "%s: %s must be an integer, not %s.\n",
117            progname, res_name, s);
118   free (s);
119   return 0;
120 }
121
122 double
123 get_float_resource (Display *dpy, char *res_name, char *res_class)
124 {
125   double val;
126   char c, *s = get_string_resource (dpy, res_name, res_class);
127   if (! s) return 0.0;
128   if (1 == sscanf (s, " %lf %c", &val, &c))
129     {
130       free (s);
131       return val;
132     }
133   fprintf (stderr, "%s: %s must be a float, not %s.\n",
134            progname, res_name, s);
135   free (s);
136   return 0.0;
137 }
138
139 #endif /* !HAVE_COCOA */
140
141
142 /* These functions are the same with Xlib and Cocoa:
143  */
144
145
146 unsigned int
147 get_pixel_resource (Display *dpy, Colormap cmap,
148                     char *res_name, char *res_class)
149 {
150   XColor color;
151   char *s = get_string_resource (dpy, res_name, res_class);
152   char *s2;
153   Bool ok = True;
154   if (!s) goto DEFAULT;
155
156   for (s2 = s + strlen(s) - 1; s2 > s; s2--)
157     if (*s2 == ' ' || *s2 == '\t')
158       *s2 = 0;
159     else
160       break;
161
162   if (! XParseColor (dpy, cmap, s, &color))
163     {
164       fprintf (stderr, "%s: can't parse color %s", progname, s);
165       ok = False;
166       goto DEFAULT;
167     }
168   if (! XAllocColor (dpy, cmap, &color))
169     {
170       fprintf (stderr, "%s: couldn't allocate color %s", progname, s);
171       ok = False;
172       goto DEFAULT;
173     }
174   free (s);
175   return (unsigned int) color.pixel;
176  DEFAULT:
177   if (s) free (s);
178
179   {
180     Bool black_p = (strlen(res_class) >= 10 &&
181                     !strcasecmp ("Background",
182                                  res_class + strlen(res_class) - 10));
183     if (!ok)
184       fprintf (stderr, ": using %s.\n", (black_p ? "black" : "white"));
185     color.flags = DoRed|DoGreen|DoBlue;
186     color.red = color.green = color.blue = (black_p ? 0 : 0xFFFF);
187     if (XAllocColor (dpy, cmap, &color))
188       return (unsigned int) color.pixel;
189     else
190       {
191         fprintf (stderr, "%s: couldn't allocate %s either!\n", progname,
192                  (black_p ? "black" : "white"));
193         /* We can't use BlackPixel/WhitePixel here, because we don't know
194            what screen we're allocating on (only an issue when running inside
195            the xscreensaver daemon: for hacks, DefaultScreen is fine.)
196          */
197         return 0;
198       }
199   }
200 }
201
202
203 int
204 parse_time (const char *string, Bool seconds_default_p, Bool silent_p)
205 {
206   unsigned int h, m, s;
207   char c;
208   if (3 == sscanf (string,   " %u : %2u : %2u %c", &h, &m, &s, &c))
209     ;
210   else if (2 == sscanf (string, " : %2u : %2u %c", &m, &s, &c) ||
211            2 == sscanf (string,    " %u : %2u %c", &m, &s, &c))
212     h = 0;
213   else if (1 == sscanf (string,       " : %2u %c", &s, &c))
214     h = m = 0;
215   else if (1 == sscanf (string,          " %u %c",
216                         (seconds_default_p ? &s : &m), &c))
217     {
218       h = 0;
219       if (seconds_default_p) m = 0;
220       else s = 0;
221     }
222   else
223     {
224       if (! silent_p)
225         fprintf (stderr, "%s: invalid time interval specification \"%s\".\n",
226                  progname, string);
227       return -1;
228     }
229   if (s >= 60 && (h != 0 || m != 0))
230     {
231       if (! silent_p)
232         fprintf (stderr, "%s: seconds > 59 in \"%s\".\n", progname, string);
233       return -1;
234     }
235   if (m >= 60 && h > 0)
236     {
237       if (! silent_p)
238         fprintf (stderr, "%s: minutes > 59 in \"%s\".\n", progname, string);
239       return -1;
240     }
241   return ((h * 60 * 60) + (m * 60) + s);
242 }
243
244 static unsigned int 
245 get_time_resource (Display *dpy, char *res_name, char *res_class, Bool sec_p)
246 {
247   int val;
248   char *s = get_string_resource (dpy, res_name, res_class);
249   if (!s) return 0;
250   val = parse_time (s, sec_p, False);
251   free (s);
252   return (val < 0 ? 0 : val);
253 }
254
255 unsigned int 
256 get_seconds_resource (Display *dpy, char *res_name, char *res_class)
257 {
258   return get_time_resource (dpy, res_name, res_class, True);
259 }
260
261 unsigned int 
262 get_minutes_resource (Display *dpy, char *res_name, char *res_class)
263 {
264   return get_time_resource (dpy, res_name, res_class, False);
265 }