276 lines
8.4 KiB
C
276 lines
8.4 KiB
C
/*
|
|
** XResource.c:
|
|
** These routines provide modules with an interface to parse all kinds of
|
|
** configuration options (X resources, command line options and configuration
|
|
** file lines) in the same way (Xrm database).
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xresource.h>
|
|
#include <string.h>
|
|
|
|
#include "fvwmlib.h"
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
* If you have a module MyModule and want to parse X resources as well as
|
|
* command line options and a config file:
|
|
*
|
|
*** EXAMPLE ***************************************************************/
|
|
#if 0
|
|
#include <fvwmlib.h>
|
|
|
|
void main(int argc, char **argv)
|
|
{
|
|
const char *MyName = "MyModule";
|
|
XrmDatabase db = NULL;
|
|
char *value;
|
|
char *line;
|
|
|
|
/* our private options */
|
|
const XrmOptionDescRec my_opts[] = {
|
|
{ "-iconic", ".Iconic", XrmoptionNoArg, "any_string" },
|
|
{ "-foo", "*bar", XrmoptionSepArg, NULL }
|
|
};
|
|
int opt_argc = argc - 6; /* options start at 6th argument for modules */
|
|
char **opt_argv = argv + 6;
|
|
|
|
/* ... (open config file, etc.) */
|
|
|
|
/* Get global X resources */
|
|
MergeXResources(NULL, &db, False);
|
|
|
|
/* config file descriptor in fd; config file takes precedence over X
|
|
* resources (this may not be what you want). */
|
|
for (GetConfigLine(fd, &line); line != NULL; GetConfigLine(fd, &line))
|
|
{
|
|
if (!MergeConfigLineResource(&db, line, MyName, '*'))
|
|
{
|
|
/* Parse other lines here (e.g. "IconPath") */
|
|
}
|
|
else
|
|
{
|
|
/* You may still have to parse the line here yourself (e.g.
|
|
* FvwmButtons may have multiple lines for the same resource). */
|
|
}
|
|
}
|
|
|
|
/* command line takes precedence over all */
|
|
MergeCmdLineResources(&db, (XrmOptionDescList)my_opts, 2, MyName,
|
|
&opt_argc, opt_argv, True /*no default options*/);
|
|
|
|
/* Now parse the database values: */
|
|
if (GetResourceString(db, "iconic", MyName, &value))
|
|
{
|
|
/* Just see if there is *any* string and don't mind it's value. */
|
|
/* flags |= ICONIC */
|
|
}
|
|
if (GetResourceString(db, "bar", MyName, &value))
|
|
{
|
|
/* ... */
|
|
}
|
|
|
|
/* ... */
|
|
XrmDestroyDatabase(db);
|
|
}
|
|
#endif
|
|
|
|
/*** END OF EXAMPLE ********************************************************/
|
|
|
|
|
|
|
|
|
|
/* Default option table */
|
|
static XrmOptionDescRec default_opts[] =
|
|
{
|
|
{ "-fg", "*Foreground", XrmoptionSepArg, NULL },
|
|
{ "-bg", "*Background", XrmoptionSepArg, NULL },
|
|
{ "-fn", "*Font", XrmoptionSepArg, NULL },
|
|
{ "-geometry", "*Geometry", XrmoptionSepArg, NULL },
|
|
{ "-title", "*Title", XrmoptionSepArg, NULL }
|
|
/* Remember to update NUM_DEFAULT_OPTIONS if you change this list! */
|
|
};
|
|
#define NUM_DEFAULT_OPTS 5
|
|
|
|
|
|
|
|
/* internal function */
|
|
static void DoMergeString(char *resource, XrmDatabase *ptarget, Bool override)
|
|
{
|
|
XrmDatabase db;
|
|
|
|
if (!resource)
|
|
return;
|
|
db = XrmGetStringDatabase(resource);
|
|
XrmCombineDatabase(db, ptarget, override);
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Merges all X resources for the display/screen into a Xrm database.
|
|
* If the database does not exist (*pdb == NULL), a new database is created.
|
|
* If override is True, existing entries of the same name are overwritten.
|
|
*
|
|
* Please remember to destroy the database with XrmDestroyDatabase(*pdb)
|
|
* if you do not need it amymore.
|
|
*
|
|
***************************************************************************/
|
|
void MergeXResources(Display *dpy, XrmDatabase *pdb, Bool override)
|
|
{
|
|
if (!*pdb)
|
|
/* create new database */
|
|
XrmPutStringResource(pdb, "", "");
|
|
DoMergeString(XResourceManagerString(dpy), pdb, override);
|
|
DoMergeString(XScreenResourceString(DefaultScreenOfDisplay(dpy)), pdb,
|
|
override);
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Parses the command line given through pargc/argv and puts recognized
|
|
* entries into the Xrm database *pdb (if *pdb is NULL a new database is
|
|
* created). The caller may provide an option list in XrmOptionDescList
|
|
* format (see XrmParseCommand manpage) and/or parse only standard options
|
|
* (fg, bg, geometry, fn, title). User given options have precedence over
|
|
* standard options which are disabled if fNoDefaults is True. Existing
|
|
* values are overwritten.
|
|
*
|
|
* All recognised options are removed from the command line (*pargc and
|
|
* argv are updated accordingly).
|
|
*
|
|
* Please remember to destroy the database with XrmDestroyDatabase(*pdb)
|
|
* if you do not need it amymore.
|
|
*
|
|
***************************************************************************/
|
|
void MergeCmdLineResources(XrmDatabase *pdb, XrmOptionDescList opts,
|
|
int num_opts, char *name, int *pargc, char **argv,
|
|
Bool fNoDefaults)
|
|
{
|
|
if (opts && num_opts > 0)
|
|
XrmParseCommand(pdb, opts, num_opts, name, pargc, argv);
|
|
if (!fNoDefaults)
|
|
XrmParseCommand(pdb, default_opts, NUM_DEFAULT_OPTS,
|
|
name, pargc, argv);
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Takes a line from a config file and puts a corresponding value into the
|
|
* Xrm database *pdb (will be created if *pdb is NULL). 'prefix' is the
|
|
* name of the module. A specific type of binding in the database must be
|
|
* provided in bindstr (either "*" or "."). Leading unquoted whitespace are
|
|
* stripped from value. Existing values in the database are overwritten.
|
|
* True is returned if the line was indeed merged into the database (i.e. it
|
|
* had the correct format) or False if not.
|
|
*
|
|
* Example: If prefix = "MyModule" and bindstr = "*", the line
|
|
*
|
|
* *MyModuleGeometry 80x25+0+0
|
|
*
|
|
* will be put into the database as if you had this line in your .Xdefaults:
|
|
*
|
|
* MyModule*Geometry: 80x25+0+0
|
|
*
|
|
* Please remember to destroy the database with XrmDestroyDatabase(*pdb)
|
|
* if you do not need it amymore.
|
|
*
|
|
***************************************************************************/
|
|
Bool MergeConfigLineResource(XrmDatabase *pdb, char *line, char *prefix,
|
|
char *bindstr)
|
|
{
|
|
int len;
|
|
char *end;
|
|
char *value;
|
|
char *myvalue;
|
|
char *resource;
|
|
size_t reslen;
|
|
|
|
/* translate "*(prefix)(suffix)" to "(prefix)(binding)(suffix)",
|
|
* e.g. "*FvwmPagerGeometry" to "FvwmPager.Geometry" */
|
|
if (!line || *line != '*')
|
|
return False;
|
|
|
|
line++;
|
|
len = (prefix) ? strlen(prefix) : 0;
|
|
if (!prefix || strncasecmp(line, prefix, len))
|
|
return False;
|
|
|
|
line += len;
|
|
end = line;
|
|
while (*end && !isspace(*end))
|
|
end++;
|
|
if (line == end)
|
|
return False;
|
|
value = end;
|
|
while (*value && isspace(*value))
|
|
value++;
|
|
|
|
/* prefix*suffix: value */
|
|
reslen = len + (end - line) + 2;
|
|
resource = (char *)safemalloc(reslen);
|
|
strlcpy(resource, prefix,reslen);
|
|
strlcat(resource, bindstr,reslen);
|
|
strncat(resource, line, end - line);
|
|
|
|
len = strlen(value);
|
|
myvalue = (char *)safemalloc(len + 1);
|
|
strlcpy(myvalue, value,len+1);
|
|
for (len--; len >= 0 && isspace(myvalue[len]); len--)
|
|
myvalue[len] = 0;
|
|
|
|
/* merge string into database */
|
|
XrmPutStringResource(pdb, resource, myvalue);
|
|
|
|
free(resource);
|
|
free(myvalue);
|
|
return True;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Reads the string-value for the pair prefix/resource from the Xrm database
|
|
* db and returns a pointer to it. The string may only be read and must not
|
|
* be freed by the caller. 'prefix' is the class name (usually the name of
|
|
* the module). If no value is found in the database, *val will be NULL.
|
|
* True is returned if a value was found, False if not. If you are only
|
|
* interested if there is a string, but not it's value, you can set val to
|
|
* NULL.
|
|
*
|
|
* Example:
|
|
*
|
|
* GetResourceString(db, "Geometry", "MyModule", &s)
|
|
*
|
|
* returns the string value of the "Geometry" resource for MyModule in s.
|
|
*
|
|
***************************************************************************/
|
|
Bool GetResourceString(XrmDatabase db, const char *resource,
|
|
const char *prefix, char **val)
|
|
{
|
|
XrmValue xval = { 0, NULL };
|
|
char *str_type;
|
|
char *name;
|
|
size_t len;
|
|
|
|
len = strlen(resource) + strlen(prefix) + 2;
|
|
name = (char *)safemalloc(len);
|
|
strlcpy(name, prefix,len);
|
|
strlcat(name, ".",len);
|
|
strlcat(name, resource,len);
|
|
|
|
if (!XrmGetResource(db, name, name, &str_type, &xval) || xval.addr == NULL)
|
|
{
|
|
free(name);
|
|
if (val)
|
|
*val = NULL;
|
|
return False;
|
|
}
|
|
free(name);
|
|
if (val)
|
|
*val = xval.addr;
|
|
|
|
return True;
|
|
}
|