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
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).
28 #include <X11/Xresource.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:
43 void main(int argc
, char **argv
)
45 const char *MyName
= "MyModule";
46 XrmDatabase db
= NULL
;
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") */
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. */
88 if (GetResourceString(db
, "bar", MyName
, &rm_value
))
94 XrmDestroyDatabase(db
);
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
)
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
)
141 /* create new database */
142 XrmPutStringResource(pdb
, "", "");
143 DoMergeString(XResourceManagerString(dpy
), pdb
, override
);
144 DoMergeString(XScreenResourceString(DefaultScreenOfDisplay(dpy
)), pdb
,
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
,
171 if (opts
&& num_opts
> 0)
172 XrmParseCommand(pdb
, opts
, num_opts
, name
, pargc
, argv
);
174 XrmParseCommand(pdb
, default_opts
, NUM_DEFAULT_OPTS
,
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
,
209 /* translate "*(prefix)(suffix)" to "(prefix)(binding)(suffix)",
210 * e.g. "*FvwmPagerGeometry" to "FvwmPager.Geometry" */
211 if (!line
|| *line
!= '*')
215 len
= (prefix
) ? strlen(prefix
) : 0;
216 if (!prefix
|| strncasecmp(line
, prefix
, len
))
221 while (*end
&& !isspace((unsigned char)*end
))
226 while (*value
&& isspace((unsigned char)*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
);
236 myvalue
= (char *)safemalloc(len
+ 1);
237 strcpy(myvalue
, value
);
238 for (len
--; len
>= 0 && isspace((unsigned char)myvalue
[len
]); len
--)
241 /* merge string into database */
242 XrmPutStringResource(pdb
, resource
, myvalue
);
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
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
)
274 name
= (char *)safemalloc(strlen(resource
) + strlen(prefix
) + 2);
275 Name
= (char *)safemalloc(strlen(resource
) + strlen(prefix
) + 2);
276 strcpy(name
, prefix
);
278 strcat(name
, resource
);
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)