Add reminder to investigate recursive commands for 2.6
[fvwm.git] / libs / XResource.c
blob7621e2c26288e2d3193afe892d14d09f52a23e8a
1 /* -*-c-*- */
2 /* Copyright (C) 1999 Dominik Vogt */
3 /* This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ** XResource.c:
20 ** These routines provide modules with an interface to parse all kinds of
21 ** configuration options (X resources, command line options and configuration
22 ** file lines) in the same way (Xrm database).
25 #include "config.h"
27 #include <X11/Xlib.h>
28 #include <X11/Xresource.h>
30 #include "fvwmlib.h"
31 #include "XResource.h"
36 * If you have a module MyModule and want to parse X resources as well as
37 * command line options and a config file:
39 *** EXAMPLE */
40 #if 0
41 #include <fvwmlib.h>
43 void main(int argc, char **argv)
45 const char *MyName = "MyModule";
46 XrmDatabase db = NULL;
47 XrmValue *rm_value;
48 char *line;
50 /* our private options */
51 const XrmOptionDescRec my_opts[] = {
52 { "-iconic", ".Iconic", XrmoptionNoArg, "any_string" },
53 { "-foo", "*bar", XrmoptionSepArg, NULL }
55 int opt_argc = argc - 6; /* options start at 6th argument for modules */
56 char **opt_argv = argv + 6;
58 /* ... (open config file, etc.) */
60 /* Get global X resources */
61 MergeXResources(NULL, &db, False);
63 /* config file descriptor in fd; config file takes precedence over X
64 * resources (this may not be what you want). */
65 for (GetConfigLine(fd, &line); line != NULL; GetConfigLine(fd, &line))
67 if (!MergeConfigLineResource(&db, line, MyName, '*'))
69 /* Parse other lines here (e.g. "ImagePath") */
71 else
73 /* You may still have to parse the line here yourself (e.g.
74 * FvwmButtons may have multiple lines for the same resource). */
78 /* command line takes precedence over all */
79 MergeCmdLineResources(&db, (XrmOptionDescList)my_opts, 2, MyName,
80 &opt_argc, opt_argv, True /*no default options*/);
82 /* Now parse the database values: */
83 if (GetResourceString(db, "iconic", MyName, &rm_value))
85 /* Just see if there is *any* string and don't mind it's value. */
86 /* flags |= ICONIC */
88 if (GetResourceString(db, "bar", MyName, &rm_value))
90 /* ... */
93 /* ... */
94 XrmDestroyDatabase(db);
96 #endif
98 /*** END OF EXAMPLE ***/
103 /* Default option table */
104 static XrmOptionDescRec default_opts[] =
106 { "-fg", "*Foreground", XrmoptionSepArg, NULL },
107 { "-bg", "*Background", XrmoptionSepArg, NULL },
108 { "-fn", "*Font", XrmoptionSepArg, NULL },
109 { "-geometry", "*Geometry", XrmoptionSepArg, NULL },
110 { "-title", "*Title", XrmoptionSepArg, NULL }
111 /* Remember to update NUM_DEFAULT_OPTIONS if you change this list! */
113 #define NUM_DEFAULT_OPTS 5
117 /* internal function */
118 static void DoMergeString(char *resource, XrmDatabase *ptarget, Bool override)
120 XrmDatabase db;
122 if (!resource)
123 return;
124 db = XrmGetStringDatabase(resource);
125 XrmCombineDatabase(db, ptarget, override);
130 * Merges all X resources for the display/screen into a Xrm database.
131 * If the database does not exist (*pdb == NULL), a new database is created.
132 * If override is True, existing entries of the same name are overwritten.
134 * Please remember to destroy the database with XrmDestroyDatabase(*pdb)
135 * if you do not need it amymore.
138 void MergeXResources(Display *dpy, XrmDatabase *pdb, Bool override)
140 if (!*pdb)
141 /* create new database */
142 XrmPutStringResource(pdb, "", "");
143 DoMergeString(XResourceManagerString(dpy), pdb, override);
144 DoMergeString(XScreenResourceString(DefaultScreenOfDisplay(dpy)), pdb,
145 override);
150 * Parses the command line given through pargc/argv and puts recognized
151 * entries into the Xrm database *pdb (if *pdb is NULL a new database is
152 * created). The caller may provide an option list in XrmOptionDescList
153 * format (see XrmParseCommand manpage) and/or parse only standard options
154 * (fg, bg, geometry, fn, title). User given options have precedence over
155 * standard options which are disabled if fNoDefaults is True. Existing
156 * values are overwritten.
158 * All recognised options are removed from the command line (*pargc and
159 * argv are updated accordingly).
161 * Please remember to destroy the database with XrmDestroyDatabase(*pdb)
162 * if you do not need it amymore.
165 void MergeCmdLineResources(XrmDatabase *pdb, XrmOptionDescList opts,
166 int num_opts, char *name, int *pargc, char **argv,
167 Bool fNoDefaults)
169 if (!name)
170 return;
171 if (opts && num_opts > 0)
172 XrmParseCommand(pdb, opts, num_opts, name, pargc, argv);
173 if (!fNoDefaults)
174 XrmParseCommand(pdb, default_opts, NUM_DEFAULT_OPTS,
175 name, pargc, argv);
180 * Takes a line from a config file and puts a corresponding value into the
181 * Xrm database *pdb (will be created if *pdb is NULL). 'prefix' is the
182 * name of the module. A specific type of binding in the database must be
183 * provided in bindstr (either "*" or "."). Leading unquoted whitespace are
184 * stripped from value. Existing values in the database are overwritten.
185 * True is returned if the line was indeed merged into the database (i.e. it
186 * had the correct format) or False if not.
188 * Example: If prefix = "MyModule" and bindstr = "*", the line
190 * *MyModuleGeometry 80x25+0+0
192 * will be put into the database as if you had this line in your .Xdefaults:
194 * MyModule*Geometry: 80x25+0+0
196 * Please remember to destroy the database with XrmDestroyDatabase(*pdb)
197 * if you do not need it amymore.
200 Bool MergeConfigLineResource(XrmDatabase *pdb, char *line, char *prefix,
201 char *bindstr)
203 int len;
204 char *end;
205 char *value;
206 char *myvalue;
207 char *resource;
209 /* translate "*(prefix)(suffix)" to "(prefix)(binding)(suffix)",
210 * e.g. "*FvwmPagerGeometry" to "FvwmPager.Geometry" */
211 if (!line || *line != '*')
212 return False;
214 line++;
215 len = (prefix) ? strlen(prefix) : 0;
216 if (!prefix || strncasecmp(line, prefix, len))
217 return False;
219 line += len;
220 end = line;
221 while (*end && !isspace((unsigned char)*end))
222 end++;
223 if (line == end)
224 return False;
225 value = end;
226 while (*value && isspace((unsigned char)*value))
227 value++;
229 /* prefix*suffix: value */
230 resource = (char *)safemalloc(len + (end - line) + 2);
231 strcpy(resource, prefix);
232 strcat(resource, bindstr);
233 strncat(resource, line, end - line);
235 len = strlen(value);
236 myvalue = (char *)safemalloc(len + 1);
237 strcpy(myvalue, value);
238 for (len--; len >= 0 && isspace((unsigned char)myvalue[len]); len--)
239 myvalue[len] = 0;
241 /* merge string into database */
242 XrmPutStringResource(pdb, resource, myvalue);
244 free(resource);
245 free(myvalue);
246 return True;
251 * Reads the string-value for the pair prefix/resource from the Xrm database
252 * db and returns a pointer to it. The string may only be read and must not
253 * be freed by the caller. 'prefix' is the class name (usually the name of
254 * the module). If no value is found in the database, *val will be NULL.
255 * True is returned if a value was found, False if not. If you are only
256 * interested if there is a string, but not it's value, you can set val to
257 * NULL.
259 * Example:
261 * GetResourceString(db, "Geometry", "MyModule", &r)
263 * returns the resource value of the "Geometry" resource for MyModule in r.
266 Bool GetResourceString(
267 XrmDatabase db, const char *resource, const char *prefix, XrmValue *xval)
269 char *str_type;
270 char *name;
271 char *Name;
272 int i;
274 name = (char *)safemalloc(strlen(resource) + strlen(prefix) + 2);
275 Name = (char *)safemalloc(strlen(resource) + strlen(prefix) + 2);
276 strcpy(name, prefix);
277 strcat(name, ".");
278 strcat(name, resource);
279 strcpy(Name, name);
280 if (isupper(name[0]))
281 name[0] = tolower(name[0]);
282 if (islower(Name[0]))
283 Name[0] = toupper(Name[0]);
284 i = strlen(prefix) + 1;
285 if (isupper(name[i]))
286 name[i] = tolower(name[i]);
287 if (islower(Name[i]))
288 Name[i] = toupper(Name[i]);
289 if (!XrmGetResource(db, name, Name, &str_type, xval) ||
290 xval->addr == NULL || xval->size == 0)
292 free(name);
293 free(Name);
294 xval->size = 0;
295 xval->addr = NULL;
297 return False;
299 free(name);
300 free(Name);
302 return True;