You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1468 lines
31 KiB
1468 lines
31 KiB
4 years ago
|
/*
|
||
|
* Copyright © 2007 Dennis Kasprzyk
|
||
|
* Copyright © 2007 Novell, Inc.
|
||
|
*
|
||
|
* Permission to use, copy, modify, distribute, and sell this software
|
||
|
* and its documentation for any purpose is hereby granted without
|
||
|
* fee, provided that the above copyright notice appear in all copies
|
||
|
* and that both that copyright notice and this permission notice
|
||
|
* appear in supporting documentation, and that the name of
|
||
|
* Dennis Kasprzyk not be used in advertising or publicity pertaining to
|
||
|
* distribution of the software without specific, written prior permission.
|
||
|
* Dennis Kasprzyk makes no representations about the suitability of this
|
||
|
* software for any purpose. It is provided "as is" without express or
|
||
|
* implied warranty.
|
||
|
*
|
||
|
* DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
||
|
* NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||
|
*
|
||
|
* Authors: Dennis Kasprzyk <onestone@deltatauchi.de>
|
||
|
* David Reveman <davidr@novell.com>
|
||
|
*/
|
||
|
|
||
|
#include <string.h>
|
||
|
#include <libxml/tree.h>
|
||
|
#include <libxml/xpath.h>
|
||
|
#include <libxml/xpathInternals.h>
|
||
|
#include <locale.h>
|
||
|
|
||
|
#include <compiz-core.h>
|
||
|
|
||
|
#define HOME_METADATADIR ".compiz/metadata"
|
||
|
#define EXTENSION ".xml"
|
||
|
|
||
|
Bool
|
||
|
compInitMetadata (CompMetadata *metadata)
|
||
|
{
|
||
|
metadata->path = strdup ("core");
|
||
|
if (!metadata->path)
|
||
|
return FALSE;
|
||
|
|
||
|
metadata->doc = NULL;
|
||
|
metadata->nDoc = 0;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
compInitPluginMetadata (CompMetadata *metadata,
|
||
|
const char *plugin)
|
||
|
{
|
||
|
char str[1024];
|
||
|
|
||
|
snprintf (str, 1024, "plugin[@name=\"%s\"]", plugin);
|
||
|
|
||
|
metadata->path = strdup (str);
|
||
|
if (!metadata->path)
|
||
|
return FALSE;
|
||
|
|
||
|
metadata->doc = NULL;
|
||
|
metadata->nDoc = 0;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
compFiniMetadata (CompMetadata *metadata)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < metadata->nDoc; i++)
|
||
|
xmlFreeDoc (metadata->doc[i]);
|
||
|
|
||
|
if (metadata->doc)
|
||
|
free (metadata->doc);
|
||
|
|
||
|
free (metadata->path);
|
||
|
}
|
||
|
|
||
|
static xmlDoc *
|
||
|
readXmlFile (const char *path,
|
||
|
const char *name)
|
||
|
{
|
||
|
char *file;
|
||
|
int length = strlen (name) + strlen (EXTENSION) + 1;
|
||
|
xmlDoc *doc = NULL;
|
||
|
FILE *fp;
|
||
|
|
||
|
if (path)
|
||
|
length += strlen (path) + 1;
|
||
|
|
||
|
file = malloc (length);
|
||
|
if (!file)
|
||
|
return NULL;
|
||
|
|
||
|
if (path)
|
||
|
sprintf (file, "%s/%s%s", path, name, EXTENSION);
|
||
|
else
|
||
|
sprintf (file, "%s%s", name, EXTENSION);
|
||
|
|
||
|
fp = fopen (file, "r");
|
||
|
if (!fp)
|
||
|
{
|
||
|
free (file);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
fclose (fp);
|
||
|
|
||
|
doc = xmlReadFile (file, NULL, 0);
|
||
|
|
||
|
free (file);
|
||
|
|
||
|
return doc;
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
addMetadataFromFilename (CompMetadata *metadata,
|
||
|
const char *path,
|
||
|
const char *file)
|
||
|
{
|
||
|
xmlDoc **d, *doc;
|
||
|
|
||
|
doc = readXmlFile (path, file);
|
||
|
if (!doc)
|
||
|
return FALSE;
|
||
|
|
||
|
d = realloc (metadata->doc, (metadata->nDoc + 1) * sizeof (xmlDoc *));
|
||
|
if (!d)
|
||
|
{
|
||
|
xmlFreeDoc (doc);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
d[metadata->nDoc++] = doc;
|
||
|
metadata->doc = d;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
compAddMetadataFromFile (CompMetadata *metadata,
|
||
|
const char *file)
|
||
|
{
|
||
|
char *home;
|
||
|
Bool status = FALSE;
|
||
|
|
||
|
home = getenv ("HOME");
|
||
|
if (home)
|
||
|
{
|
||
|
char *path;
|
||
|
|
||
|
path = malloc (strlen (home) + strlen (HOME_METADATADIR) + 2);
|
||
|
if (path)
|
||
|
{
|
||
|
sprintf (path, "%s/%s", home, HOME_METADATADIR);
|
||
|
status |= addMetadataFromFilename (metadata, path, file);
|
||
|
free (path);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
status |= addMetadataFromFilename (metadata, METADATADIR, file);
|
||
|
if (!status)
|
||
|
{
|
||
|
compLogMessage ("core", CompLogLevelWarn,
|
||
|
"Unable to parse XML metadata from file \"%s%s\"",
|
||
|
file, EXTENSION);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
compAddMetadataFromString (CompMetadata *metadata,
|
||
|
const char *string)
|
||
|
{
|
||
|
xmlDoc **d, *doc;
|
||
|
|
||
|
doc = xmlReadMemory (string, strlen (string), NULL, NULL, 0);
|
||
|
if (!doc)
|
||
|
{
|
||
|
compLogMessage ("core", CompLogLevelWarn,
|
||
|
"Unable to parse XML metadata");
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
d = realloc (metadata->doc, (metadata->nDoc + 1) * sizeof (xmlDoc *));
|
||
|
if (!d)
|
||
|
{
|
||
|
xmlFreeDoc (doc);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
d[metadata->nDoc++] = doc;
|
||
|
metadata->doc = d;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
compAddMetadataFromIO (CompMetadata *metadata,
|
||
|
xmlInputReadCallback ioread,
|
||
|
xmlInputCloseCallback ioclose,
|
||
|
void *ioctx)
|
||
|
{
|
||
|
xmlDoc **d, *doc;
|
||
|
|
||
|
doc = xmlReadIO (ioread, ioclose, ioctx, NULL, NULL, 0);
|
||
|
if (!doc)
|
||
|
{
|
||
|
compLogMessage ("core", CompLogLevelWarn,
|
||
|
"Unable to parse XML metadata");
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
d = realloc (metadata->doc, (metadata->nDoc + 1) * sizeof (xmlDoc *));
|
||
|
if (!d)
|
||
|
{
|
||
|
xmlFreeDoc (doc);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
d[metadata->nDoc++] = doc;
|
||
|
metadata->doc = d;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
typedef struct _CompIOCtx {
|
||
|
int offset;
|
||
|
const char *name;
|
||
|
const CompMetadataOptionInfo *displayOInfo;
|
||
|
int nDisplayOInfo;
|
||
|
const CompMetadataOptionInfo *screenOInfo;
|
||
|
int nScreenOInfo;
|
||
|
} CompIOCtx;
|
||
|
|
||
|
static int
|
||
|
readPluginXmlCallback (void *context,
|
||
|
char *buffer,
|
||
|
int length)
|
||
|
{
|
||
|
CompIOCtx *ctx = (CompIOCtx *) context;
|
||
|
int offset = ctx->offset;
|
||
|
int i, j;
|
||
|
|
||
|
i = compReadXmlChunk ("<compiz><plugin name=\"", &offset, buffer, length);
|
||
|
i += compReadXmlChunk (ctx->name, &offset, buffer + i, length - i);
|
||
|
i += compReadXmlChunk ("\">", &offset, buffer + i, length - i);
|
||
|
|
||
|
if (ctx->nDisplayOInfo)
|
||
|
{
|
||
|
i += compReadXmlChunk ("<display>", &offset, buffer + i, length - i);
|
||
|
|
||
|
for (j = 0; j < ctx->nDisplayOInfo; j++)
|
||
|
i += compReadXmlChunkFromMetadataOptionInfo (&ctx->displayOInfo[j],
|
||
|
&offset,
|
||
|
buffer + i,
|
||
|
length - i);
|
||
|
|
||
|
i += compReadXmlChunk ("</display>", &offset, buffer + i, length - i);
|
||
|
}
|
||
|
|
||
|
if (ctx->nScreenOInfo)
|
||
|
{
|
||
|
i += compReadXmlChunk ("<screen>", &offset, buffer + i, length - i);
|
||
|
|
||
|
for (j = 0; j < ctx->nScreenOInfo; j++)
|
||
|
i += compReadXmlChunkFromMetadataOptionInfo (&ctx->screenOInfo[j],
|
||
|
&offset,
|
||
|
buffer + i,
|
||
|
length - i);
|
||
|
|
||
|
i += compReadXmlChunk ("</screen>", &offset, buffer + i, length - i);
|
||
|
}
|
||
|
|
||
|
i += compReadXmlChunk ("</plugin></compiz>", &offset, buffer + i,
|
||
|
length - i);
|
||
|
|
||
|
if (!offset && length > i)
|
||
|
buffer[i++] = '\0';
|
||
|
|
||
|
ctx->offset += i;
|
||
|
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
compInitPluginMetadataFromInfo (CompMetadata *metadata,
|
||
|
const char *plugin,
|
||
|
const CompMetadataOptionInfo *displayOptionInfo,
|
||
|
int nDisplayOptionInfo,
|
||
|
const CompMetadataOptionInfo *screenOptionInfo,
|
||
|
int nScreenOptionInfo)
|
||
|
{
|
||
|
if (!compInitPluginMetadata (metadata, plugin))
|
||
|
return FALSE;
|
||
|
|
||
|
if (nDisplayOptionInfo || nScreenOptionInfo)
|
||
|
{
|
||
|
CompIOCtx ctx;
|
||
|
|
||
|
ctx.offset = 0;
|
||
|
ctx.name = plugin;
|
||
|
ctx.displayOInfo = displayOptionInfo;
|
||
|
ctx.nDisplayOInfo = nDisplayOptionInfo;
|
||
|
ctx.screenOInfo = screenOptionInfo;
|
||
|
ctx.nScreenOInfo = nScreenOptionInfo;
|
||
|
|
||
|
if (!compAddMetadataFromIO (metadata,
|
||
|
readPluginXmlCallback, NULL,
|
||
|
(void *) &ctx))
|
||
|
{
|
||
|
compFiniMetadata (metadata);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
typedef struct _CompXPath {
|
||
|
xmlXPathObjectPtr obj;
|
||
|
xmlXPathContextPtr ctx;
|
||
|
xmlDocPtr doc;
|
||
|
} CompXPath;
|
||
|
|
||
|
static Bool
|
||
|
initXPathFromMetadataPath (CompXPath *xPath,
|
||
|
CompMetadata *metadata,
|
||
|
const xmlChar *path)
|
||
|
{
|
||
|
xmlXPathObjectPtr obj;
|
||
|
xmlXPathContextPtr ctx;
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < metadata->nDoc; i++)
|
||
|
{
|
||
|
ctx = xmlXPathNewContext (metadata->doc[i]);
|
||
|
if (ctx)
|
||
|
{
|
||
|
obj = xmlXPathEvalExpression (path, ctx);
|
||
|
if (obj)
|
||
|
{
|
||
|
if (obj->nodesetval && obj->nodesetval->nodeNr)
|
||
|
{
|
||
|
xPath->ctx = ctx;
|
||
|
xPath->obj = obj;
|
||
|
xPath->doc = metadata->doc[i];
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
xmlXPathFreeObject (obj);
|
||
|
}
|
||
|
|
||
|
xmlXPathFreeContext (ctx);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
initXPathFromMetadataPathElement (CompXPath *xPath,
|
||
|
CompMetadata *metadata,
|
||
|
const xmlChar *path,
|
||
|
const xmlChar *element)
|
||
|
{
|
||
|
char str[1024];
|
||
|
|
||
|
snprintf (str, 1024, "%s/%s", path, element);
|
||
|
|
||
|
return initXPathFromMetadataPath (xPath, metadata, BAD_CAST str);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
finiXPath (CompXPath *xPath)
|
||
|
{
|
||
|
xmlXPathFreeObject (xPath->obj);
|
||
|
xmlXPathFreeContext (xPath->ctx);
|
||
|
}
|
||
|
|
||
|
static CompOptionType
|
||
|
getOptionType (char *name)
|
||
|
{
|
||
|
static struct _TypeMap {
|
||
|
char *name;
|
||
|
CompOptionType type;
|
||
|
} map[] = {
|
||
|
{ "int", CompOptionTypeInt },
|
||
|
{ "float", CompOptionTypeFloat },
|
||
|
{ "string", CompOptionTypeString },
|
||
|
{ "color", CompOptionTypeColor },
|
||
|
{ "action", CompOptionTypeAction },
|
||
|
{ "key", CompOptionTypeKey },
|
||
|
{ "button", CompOptionTypeButton },
|
||
|
{ "edge", CompOptionTypeEdge },
|
||
|
{ "bell", CompOptionTypeBell },
|
||
|
{ "match", CompOptionTypeMatch },
|
||
|
{ "list", CompOptionTypeList }
|
||
|
};
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
|
||
|
if (strcasecmp (name, map[i].name) == 0)
|
||
|
return map[i].type;
|
||
|
|
||
|
return CompOptionTypeBool;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initBoolValue (CompOptionValue *v,
|
||
|
xmlDocPtr doc,
|
||
|
xmlNodePtr node)
|
||
|
{
|
||
|
xmlChar *value;
|
||
|
|
||
|
v->b = FALSE;
|
||
|
|
||
|
if (!doc)
|
||
|
return;
|
||
|
|
||
|
value = xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
|
||
|
if (value)
|
||
|
{
|
||
|
if (strcasecmp ((char *) value, "true") == 0)
|
||
|
v->b = TRUE;
|
||
|
|
||
|
xmlFree (value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initIntValue (CompOptionValue *v,
|
||
|
CompOptionRestriction *r,
|
||
|
xmlDocPtr doc,
|
||
|
xmlNodePtr node)
|
||
|
{
|
||
|
xmlChar *value;
|
||
|
|
||
|
v->i = (r->i.min + r->i.max) / 2;
|
||
|
|
||
|
if (!doc)
|
||
|
return;
|
||
|
|
||
|
value = xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
|
||
|
if (value)
|
||
|
{
|
||
|
int i = strtol ((char *) value, NULL, 0);
|
||
|
|
||
|
if (i >= r->i.min && i <= r->i.max)
|
||
|
v->i = i;
|
||
|
|
||
|
xmlFree (value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initFloatValue (CompOptionValue *v,
|
||
|
CompOptionRestriction *r,
|
||
|
xmlDocPtr doc,
|
||
|
xmlNodePtr node)
|
||
|
{
|
||
|
xmlChar *value;
|
||
|
char *loc;
|
||
|
|
||
|
v->f = (r->f.min + r->f.max) / 2;
|
||
|
|
||
|
if (!doc)
|
||
|
return;
|
||
|
|
||
|
loc = setlocale (LC_NUMERIC, NULL);
|
||
|
setlocale (LC_NUMERIC, "C");
|
||
|
value = xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
|
||
|
if (value)
|
||
|
{
|
||
|
float f = strtod ((char *) value, NULL);
|
||
|
|
||
|
if (f >= r->f.min && f <= r->f.max)
|
||
|
v->f = f;
|
||
|
|
||
|
xmlFree (value);
|
||
|
}
|
||
|
setlocale (LC_NUMERIC, loc);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initStringValue (CompOptionValue *v,
|
||
|
CompOptionRestriction *r,
|
||
|
xmlDocPtr doc,
|
||
|
xmlNodePtr node)
|
||
|
{
|
||
|
xmlChar *value;
|
||
|
|
||
|
v->s = strdup ("");
|
||
|
|
||
|
if (!doc)
|
||
|
return;
|
||
|
|
||
|
value = xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
|
||
|
if (value)
|
||
|
{
|
||
|
free (v->s);
|
||
|
v->s = strdup ((char *) value);
|
||
|
|
||
|
xmlFree (value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initColorValue (CompOptionValue *v,
|
||
|
xmlDocPtr doc,
|
||
|
xmlNodePtr node)
|
||
|
{
|
||
|
xmlNodePtr child;
|
||
|
|
||
|
v->c[0] = 0x0000;
|
||
|
v->c[1] = 0x0000;
|
||
|
v->c[2] = 0x0000;
|
||
|
v->c[3] = 0xffff;
|
||
|
|
||
|
if (!doc)
|
||
|
return;
|
||
|
|
||
|
for (child = node->xmlChildrenNode; child; child = child->next)
|
||
|
{
|
||
|
xmlChar *value;
|
||
|
int index;
|
||
|
|
||
|
if (!xmlStrcmp (child->name, BAD_CAST "red"))
|
||
|
index = 0;
|
||
|
else if (!xmlStrcmp (child->name, BAD_CAST "green"))
|
||
|
index = 1;
|
||
|
else if (!xmlStrcmp (child->name, BAD_CAST "blue"))
|
||
|
index = 2;
|
||
|
else if (!xmlStrcmp (child->name, BAD_CAST "alpha"))
|
||
|
index = 3;
|
||
|
else
|
||
|
continue;
|
||
|
|
||
|
value = xmlNodeListGetString (child->doc, child->xmlChildrenNode, 1);
|
||
|
if (value)
|
||
|
{
|
||
|
int color = strtol ((char *) value, NULL , 0);
|
||
|
|
||
|
v->c[index] = MAX (0, MIN (0xffff, color));
|
||
|
|
||
|
xmlFree (value);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initActionValue (CompDisplay *d,
|
||
|
CompOptionValue *v,
|
||
|
CompActionState state,
|
||
|
xmlDocPtr doc,
|
||
|
xmlNodePtr node)
|
||
|
{
|
||
|
memset (&v->action, 0, sizeof (v->action));
|
||
|
|
||
|
v->action.state = state;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initKeyValue (CompDisplay *d,
|
||
|
CompOptionValue *v,
|
||
|
CompActionState state,
|
||
|
xmlDocPtr doc,
|
||
|
xmlNodePtr node)
|
||
|
{
|
||
|
xmlChar *value;
|
||
|
|
||
|
memset (&v->action, 0, sizeof (v->action));
|
||
|
|
||
|
v->action.state = state | CompActionStateInitKey;
|
||
|
|
||
|
if (!doc)
|
||
|
return;
|
||
|
|
||
|
value = xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
|
||
|
if (value)
|
||
|
{
|
||
|
char *binding = (char *) value;
|
||
|
|
||
|
if (strcasecmp (binding, "disabled") && *binding)
|
||
|
stringToKeyAction (d, binding, &v->action);
|
||
|
|
||
|
xmlFree (value);
|
||
|
}
|
||
|
|
||
|
if (state & CompActionStateAutoGrab)
|
||
|
{
|
||
|
CompScreen *s;
|
||
|
|
||
|
for (s = d->screens; s; s = s->next)
|
||
|
addScreenAction (s, &v->action);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initButtonValue (CompDisplay *d,
|
||
|
CompOptionValue *v,
|
||
|
CompActionState state,
|
||
|
xmlDocPtr doc,
|
||
|
xmlNodePtr node)
|
||
|
{
|
||
|
xmlChar *value;
|
||
|
|
||
|
memset (&v->action, 0, sizeof (v->action));
|
||
|
|
||
|
v->action.state = state | CompActionStateInitButton |
|
||
|
CompActionStateInitEdge;
|
||
|
|
||
|
if (!doc)
|
||
|
return;
|
||
|
|
||
|
value = xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
|
||
|
if (value)
|
||
|
{
|
||
|
char *binding = (char *) value;
|
||
|
|
||
|
if (strcasecmp (binding, "disabled") && *binding)
|
||
|
stringToButtonAction (d, binding, &v->action);
|
||
|
|
||
|
xmlFree (value);
|
||
|
}
|
||
|
|
||
|
if (state & CompActionStateAutoGrab)
|
||
|
{
|
||
|
CompScreen *s;
|
||
|
|
||
|
for (s = d->screens; s; s = s->next)
|
||
|
addScreenAction (s, &v->action);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initEdgeValue (CompDisplay *d,
|
||
|
CompOptionValue *v,
|
||
|
CompActionState state,
|
||
|
xmlDocPtr doc,
|
||
|
xmlNodePtr node)
|
||
|
{
|
||
|
xmlNodePtr child;
|
||
|
xmlChar *value;
|
||
|
|
||
|
memset (&v->action, 0, sizeof (v->action));
|
||
|
|
||
|
v->action.state = state | CompActionStateInitEdge;
|
||
|
|
||
|
if (!doc)
|
||
|
return;
|
||
|
|
||
|
for (child = node->xmlChildrenNode; child; child = child->next)
|
||
|
{
|
||
|
value = xmlGetProp (child, BAD_CAST "name");
|
||
|
if (value)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < SCREEN_EDGE_NUM; i++)
|
||
|
if (strcasecmp ((char *) value, edgeToString (i)) == 0)
|
||
|
v->action.edgeMask |= (1 << i);
|
||
|
|
||
|
xmlFree (value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (state & CompActionStateAutoGrab)
|
||
|
{
|
||
|
CompScreen *s;
|
||
|
|
||
|
for (s = d->screens; s; s = s->next)
|
||
|
addScreenAction (s, &v->action);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initBellValue (CompDisplay *d,
|
||
|
CompOptionValue *v,
|
||
|
CompActionState state,
|
||
|
xmlDocPtr doc,
|
||
|
xmlNodePtr node)
|
||
|
{
|
||
|
xmlChar *value;
|
||
|
|
||
|
memset (&v->action, 0, sizeof (v->action));
|
||
|
|
||
|
v->action.state = state | CompActionStateInitBell;
|
||
|
|
||
|
if (!doc)
|
||
|
return;
|
||
|
|
||
|
value = xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
|
||
|
if (value)
|
||
|
{
|
||
|
if (strcasecmp ((char *) value, "true") == 0)
|
||
|
v->action.bell = TRUE;
|
||
|
|
||
|
xmlFree (value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initMatchValue (CompDisplay *d,
|
||
|
CompOptionValue *v,
|
||
|
Bool helper,
|
||
|
xmlDocPtr doc,
|
||
|
xmlNodePtr node)
|
||
|
{
|
||
|
xmlChar *value;
|
||
|
|
||
|
matchInit (&v->match);
|
||
|
|
||
|
if (!doc)
|
||
|
return;
|
||
|
|
||
|
value = xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
|
||
|
if (value)
|
||
|
{
|
||
|
matchAddFromString (&v->match, (char *) value);
|
||
|
xmlFree (value);
|
||
|
}
|
||
|
|
||
|
if (!helper)
|
||
|
matchUpdate (d, &v->match);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initListValue (CompDisplay *d,
|
||
|
CompOptionValue *v,
|
||
|
CompOptionRestriction *r,
|
||
|
CompActionState state,
|
||
|
Bool helper,
|
||
|
xmlDocPtr doc,
|
||
|
xmlNodePtr node)
|
||
|
{
|
||
|
xmlNodePtr child;
|
||
|
|
||
|
v->list.value = NULL;
|
||
|
v->list.nValue = 0;
|
||
|
|
||
|
if (!doc)
|
||
|
return;
|
||
|
|
||
|
for (child = node->xmlChildrenNode; child; child = child->next)
|
||
|
{
|
||
|
CompOptionValue *value;
|
||
|
|
||
|
if (xmlStrcmp (child->name, BAD_CAST "value"))
|
||
|
continue;
|
||
|
|
||
|
value = realloc (v->list.value,
|
||
|
sizeof (CompOptionValue) * (v->list.nValue + 1));
|
||
|
if (value)
|
||
|
{
|
||
|
switch (v->list.type) {
|
||
|
case CompOptionTypeBool:
|
||
|
initBoolValue (&value[v->list.nValue], doc, child);
|
||
|
break;
|
||
|
case CompOptionTypeInt:
|
||
|
initIntValue (&value[v->list.nValue], r, doc, child);
|
||
|
break;
|
||
|
case CompOptionTypeFloat:
|
||
|
initFloatValue (&value[v->list.nValue], r, doc, child);
|
||
|
break;
|
||
|
case CompOptionTypeString:
|
||
|
initStringValue (&value[v->list.nValue], r, doc, child);
|
||
|
break;
|
||
|
case CompOptionTypeColor:
|
||
|
initColorValue (&value[v->list.nValue], doc, child);
|
||
|
break;
|
||
|
case CompOptionTypeAction:
|
||
|
initActionValue (d, &value[v->list.nValue], state, doc, child);
|
||
|
break;
|
||
|
case CompOptionTypeKey:
|
||
|
initKeyValue (d, &value[v->list.nValue], state, doc, child);
|
||
|
break;
|
||
|
case CompOptionTypeButton:
|
||
|
initButtonValue (d, &value[v->list.nValue], state, doc, child);
|
||
|
break;
|
||
|
case CompOptionTypeEdge:
|
||
|
initEdgeValue (d, &value[v->list.nValue], state, doc, child);
|
||
|
break;
|
||
|
case CompOptionTypeBell:
|
||
|
initBellValue (d, &value[v->list.nValue], state, doc, child);
|
||
|
break;
|
||
|
case CompOptionTypeMatch:
|
||
|
initMatchValue (d, &value[v->list.nValue], helper, doc, child);
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
v->list.value = value;
|
||
|
v->list.nValue++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static char *
|
||
|
stringFromMetadataPathElement (CompMetadata *metadata,
|
||
|
const char *path,
|
||
|
const char *element)
|
||
|
{
|
||
|
char str[1024];
|
||
|
|
||
|
snprintf (str, 1024, "%s/%s", path, element);
|
||
|
|
||
|
return compGetStringFromMetadataPath (metadata, str);
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
boolFromMetadataPathElement (CompMetadata *metadata,
|
||
|
const char *path,
|
||
|
const char *element,
|
||
|
Bool defaultValue)
|
||
|
{
|
||
|
Bool value = FALSE;
|
||
|
char *str;
|
||
|
|
||
|
str = stringFromMetadataPathElement (metadata, path, element);
|
||
|
if (!str)
|
||
|
return defaultValue;
|
||
|
|
||
|
if (strcasecmp (str, "true") == 0)
|
||
|
value = TRUE;
|
||
|
|
||
|
free (str);
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initIntRestriction (CompMetadata *metadata,
|
||
|
CompOptionRestriction *r,
|
||
|
const char *path)
|
||
|
{
|
||
|
char *value;
|
||
|
|
||
|
r->i.min = MINSHORT;
|
||
|
r->i.max = MAXSHORT;
|
||
|
|
||
|
value = stringFromMetadataPathElement (metadata, path, "min");
|
||
|
if (value)
|
||
|
{
|
||
|
r->i.min = strtol ((char *) value, NULL, 0);
|
||
|
free (value);
|
||
|
}
|
||
|
|
||
|
value = stringFromMetadataPathElement (metadata, path, "max");
|
||
|
if (value)
|
||
|
{
|
||
|
r->i.max = strtol ((char *) value, NULL, 0);
|
||
|
free (value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initFloatRestriction (CompMetadata *metadata,
|
||
|
CompOptionRestriction *r,
|
||
|
const char *path)
|
||
|
{
|
||
|
char *value;
|
||
|
char *loc;
|
||
|
|
||
|
r->f.min = MINSHORT;
|
||
|
r->f.max = MAXSHORT;
|
||
|
r->f.precision = 0.1f;
|
||
|
|
||
|
loc = setlocale (LC_NUMERIC, NULL);
|
||
|
setlocale (LC_NUMERIC, "C");
|
||
|
value = stringFromMetadataPathElement (metadata, path, "min");
|
||
|
if (value)
|
||
|
{
|
||
|
r->f.min = strtod ((char *) value, NULL);
|
||
|
free (value);
|
||
|
}
|
||
|
|
||
|
value = stringFromMetadataPathElement (metadata, path, "max");
|
||
|
if (value)
|
||
|
{
|
||
|
r->f.max = strtod ((char *) value, NULL);
|
||
|
free (value);
|
||
|
}
|
||
|
|
||
|
value = stringFromMetadataPathElement (metadata, path, "precision");
|
||
|
if (value)
|
||
|
{
|
||
|
r->f.precision = strtod ((char *) value, NULL);
|
||
|
free (value);
|
||
|
}
|
||
|
|
||
|
setlocale (LC_NUMERIC, loc);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
initActionState (CompMetadata *metadata,
|
||
|
CompOptionType type,
|
||
|
CompActionState *state,
|
||
|
const char *path)
|
||
|
{
|
||
|
static struct _StateMap {
|
||
|
char *name;
|
||
|
CompActionState state;
|
||
|
} map[] = {
|
||
|
{ "key", CompActionStateInitKey },
|
||
|
{ "button", CompActionStateInitButton },
|
||
|
{ "bell", CompActionStateInitBell },
|
||
|
{ "edge", CompActionStateInitEdge },
|
||
|
{ "edgednd", CompActionStateInitEdgeDnd }
|
||
|
};
|
||
|
int i;
|
||
|
CompXPath xPath;
|
||
|
char *grab;
|
||
|
|
||
|
*state = CompActionStateAutoGrab;
|
||
|
|
||
|
grab = stringFromMetadataPathElement (metadata, path, "passive_grab");
|
||
|
if (grab)
|
||
|
{
|
||
|
if (strcmp (grab, "false") == 0)
|
||
|
*state = 0;
|
||
|
|
||
|
free (grab);
|
||
|
}
|
||
|
|
||
|
if (type == CompOptionTypeEdge)
|
||
|
{
|
||
|
char *noEdgeDelay;
|
||
|
|
||
|
noEdgeDelay = stringFromMetadataPathElement (metadata, path, "nodelay");
|
||
|
if (noEdgeDelay)
|
||
|
{
|
||
|
if (strcmp (noEdgeDelay, "true") == 0)
|
||
|
*state |= CompActionStateNoEdgeDelay;
|
||
|
|
||
|
free (noEdgeDelay);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!initXPathFromMetadataPathElement (&xPath, metadata, BAD_CAST path,
|
||
|
BAD_CAST "allowed"))
|
||
|
return;
|
||
|
|
||
|
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
|
||
|
{
|
||
|
xmlChar *value;
|
||
|
|
||
|
value = xmlGetProp (*xPath.obj->nodesetval->nodeTab,
|
||
|
BAD_CAST map[i].name);
|
||
|
if (value)
|
||
|
{
|
||
|
if (xmlStrcmp (value, BAD_CAST "true") == 0)
|
||
|
*state |= map[i].state;
|
||
|
xmlFree (value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
finiXPath (&xPath);
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
initOptionFromMetadataPath (CompDisplay *d,
|
||
|
CompMetadata *metadata,
|
||
|
CompOption *option,
|
||
|
const xmlChar *path)
|
||
|
{
|
||
|
CompXPath xPath, xDefaultPath;
|
||
|
xmlNodePtr node, defaultNode;
|
||
|
xmlDocPtr defaultDoc;
|
||
|
xmlChar *name, *type;
|
||
|
char *value;
|
||
|
CompActionState state = 0;
|
||
|
Bool helper = FALSE;
|
||
|
|
||
|
if (!initXPathFromMetadataPath (&xPath, metadata, path))
|
||
|
return FALSE;
|
||
|
|
||
|
node = *xPath.obj->nodesetval->nodeTab;
|
||
|
|
||
|
type = xmlGetProp (node, BAD_CAST "type");
|
||
|
if (type)
|
||
|
{
|
||
|
option->type = getOptionType ((char *) type);
|
||
|
xmlFree (type);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
option->type = CompOptionTypeBool;
|
||
|
}
|
||
|
|
||
|
name = xmlGetProp (node, BAD_CAST "name");
|
||
|
option->name = strdup ((char *) name);
|
||
|
xmlFree (name);
|
||
|
|
||
|
if (initXPathFromMetadataPathElement (&xDefaultPath, metadata, path,
|
||
|
BAD_CAST "default"))
|
||
|
{
|
||
|
defaultDoc = xDefaultPath.doc;
|
||
|
defaultNode = *xDefaultPath.obj->nodesetval->nodeTab;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
defaultDoc = NULL;
|
||
|
defaultNode = NULL;
|
||
|
}
|
||
|
|
||
|
switch (option->type) {
|
||
|
case CompOptionTypeBool:
|
||
|
initBoolValue (&option->value, defaultDoc, defaultNode);
|
||
|
break;
|
||
|
case CompOptionTypeInt:
|
||
|
initIntRestriction (metadata, &option->rest, (char *) path);
|
||
|
initIntValue (&option->value, &option->rest, defaultDoc, defaultNode);
|
||
|
break;
|
||
|
case CompOptionTypeFloat:
|
||
|
initFloatRestriction (metadata, &option->rest, (char *) path);
|
||
|
initFloatValue (&option->value, &option->rest, defaultDoc, defaultNode);
|
||
|
break;
|
||
|
case CompOptionTypeString:
|
||
|
initStringValue (&option->value, &option->rest,
|
||
|
defaultDoc, defaultNode);
|
||
|
break;
|
||
|
case CompOptionTypeColor:
|
||
|
initColorValue (&option->value, defaultDoc, defaultNode);
|
||
|
break;
|
||
|
case CompOptionTypeAction:
|
||
|
initActionState (metadata, option->type, &state, (char *) path);
|
||
|
initActionValue (d, &option->value, state, defaultDoc, defaultNode);
|
||
|
break;
|
||
|
case CompOptionTypeKey:
|
||
|
initActionState (metadata, option->type, &state, (char *) path);
|
||
|
initKeyValue (d, &option->value, state, defaultDoc, defaultNode);
|
||
|
break;
|
||
|
case CompOptionTypeButton:
|
||
|
initActionState (metadata, option->type, &state, (char *) path);
|
||
|
initButtonValue (d, &option->value, state, defaultDoc, defaultNode);
|
||
|
break;
|
||
|
case CompOptionTypeEdge:
|
||
|
initActionState (metadata, option->type, &state, (char *) path);
|
||
|
initEdgeValue (d, &option->value, state, defaultDoc, defaultNode);
|
||
|
break;
|
||
|
case CompOptionTypeBell:
|
||
|
initActionState (metadata, option->type, &state, (char *) path);
|
||
|
initBellValue (d, &option->value, state, defaultDoc, defaultNode);
|
||
|
break;
|
||
|
case CompOptionTypeMatch:
|
||
|
helper = boolFromMetadataPathElement (metadata, (char *) path, "helper",
|
||
|
FALSE);
|
||
|
initMatchValue (d, &option->value, helper, defaultDoc, defaultNode);
|
||
|
break;
|
||
|
case CompOptionTypeList:
|
||
|
value = stringFromMetadataPathElement (metadata, (char *) path, "type");
|
||
|
if (value)
|
||
|
{
|
||
|
option->value.list.type = getOptionType ((char *) value);
|
||
|
free (value);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
option->value.list.type = CompOptionTypeBool;
|
||
|
}
|
||
|
|
||
|
switch (option->value.list.type) {
|
||
|
case CompOptionTypeInt:
|
||
|
initIntRestriction (metadata, &option->rest, (char *) path);
|
||
|
break;
|
||
|
case CompOptionTypeFloat:
|
||
|
initFloatRestriction (metadata, &option->rest, (char *) path);
|
||
|
break;
|
||
|
case CompOptionTypeAction:
|
||
|
case CompOptionTypeKey:
|
||
|
case CompOptionTypeButton:
|
||
|
case CompOptionTypeEdge:
|
||
|
case CompOptionTypeBell:
|
||
|
initActionState (metadata, option->value.list.type,
|
||
|
&state, (char *) path);
|
||
|
break;
|
||
|
case CompOptionTypeMatch:
|
||
|
helper = boolFromMetadataPathElement (metadata, (char *) path,
|
||
|
"helper", FALSE);
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
initListValue (d, &option->value, &option->rest, state, helper,
|
||
|
defaultDoc, defaultNode);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (defaultDoc)
|
||
|
finiXPath (&xDefaultPath);
|
||
|
|
||
|
finiXPath (&xPath);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
compInitScreenOptionFromMetadata (CompScreen *s,
|
||
|
CompMetadata *m,
|
||
|
CompOption *o,
|
||
|
const char *name)
|
||
|
{
|
||
|
char str[1024];
|
||
|
|
||
|
sprintf (str, "/compiz/%s/screen//option[@name=\"%s\"]", m->path, name);
|
||
|
|
||
|
return initOptionFromMetadataPath (s->display, m, o, BAD_CAST str);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
finiScreenOptionValue (CompScreen *s,
|
||
|
CompOptionValue *v,
|
||
|
CompOptionType type)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
switch (type) {
|
||
|
case CompOptionTypeAction:
|
||
|
case CompOptionTypeKey:
|
||
|
case CompOptionTypeButton:
|
||
|
case CompOptionTypeEdge:
|
||
|
case CompOptionTypeBell:
|
||
|
if (v->action.state & CompActionStateAutoGrab)
|
||
|
removeScreenAction (s, &v->action);
|
||
|
break;
|
||
|
case CompOptionTypeList:
|
||
|
for (i = 0; i < v->list.nValue; i++)
|
||
|
finiScreenOptionValue (s, &v->list.value[i], v->list.type);
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
compFiniScreenOption (CompScreen *s,
|
||
|
CompOption *o)
|
||
|
{
|
||
|
finiScreenOptionValue (s, &o->value, o->type);
|
||
|
compFiniOption (o);
|
||
|
free (o->name);
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
compInitScreenOptionsFromMetadata (CompScreen *s,
|
||
|
CompMetadata *m,
|
||
|
const CompMetadataOptionInfo *info,
|
||
|
CompOption *opt,
|
||
|
int n)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < n; i++)
|
||
|
{
|
||
|
if (!compInitScreenOptionFromMetadata (s, m, &opt[i], info[i].name))
|
||
|
{
|
||
|
compFiniScreenOptions (s, opt, i);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (info[i].initiate)
|
||
|
opt[i].value.action.initiate = info[i].initiate;
|
||
|
|
||
|
if (info[i].terminate)
|
||
|
opt[i].value.action.terminate = info[i].terminate;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
compFiniScreenOptions (CompScreen *s,
|
||
|
CompOption *opt,
|
||
|
int n)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < n; i++)
|
||
|
compFiniScreenOption (s, &opt[i]);
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
compSetScreenOption (CompScreen *s,
|
||
|
CompOption *o,
|
||
|
CompOptionValue *value)
|
||
|
{
|
||
|
if (compSetOption (o, value))
|
||
|
return TRUE;
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
compInitDisplayOptionFromMetadata (CompDisplay *d,
|
||
|
CompMetadata *m,
|
||
|
CompOption *o,
|
||
|
const char *name)
|
||
|
{
|
||
|
char str[1024];
|
||
|
|
||
|
sprintf (str, "/compiz/%s/display//option[@name=\"%s\"]", m->path, name);
|
||
|
|
||
|
return initOptionFromMetadataPath (d, m, o, BAD_CAST str);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
finiDisplayOptionValue (CompDisplay *d,
|
||
|
CompOptionValue *v,
|
||
|
CompOptionType type)
|
||
|
{
|
||
|
CompScreen *s;
|
||
|
int i;
|
||
|
|
||
|
switch (type) {
|
||
|
case CompOptionTypeAction:
|
||
|
case CompOptionTypeKey:
|
||
|
case CompOptionTypeButton:
|
||
|
case CompOptionTypeEdge:
|
||
|
case CompOptionTypeBell:
|
||
|
if (v->action.state & CompActionStateAutoGrab)
|
||
|
for (s = d->screens; s; s = s->next)
|
||
|
removeScreenAction (s, &v->action);
|
||
|
break;
|
||
|
case CompOptionTypeList:
|
||
|
for (i = 0; i < v->list.nValue; i++)
|
||
|
finiDisplayOptionValue (d, &v->list.value[i], v->list.type);
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
compFiniDisplayOption (CompDisplay *d,
|
||
|
CompOption *o)
|
||
|
{
|
||
|
finiDisplayOptionValue (d, &o->value, o->type);
|
||
|
compFiniOption (o);
|
||
|
free (o->name);
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
compInitDisplayOptionsFromMetadata (CompDisplay *d,
|
||
|
CompMetadata *m,
|
||
|
const CompMetadataOptionInfo *info,
|
||
|
CompOption *opt,
|
||
|
int n)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < n; i++)
|
||
|
{
|
||
|
if (!compInitDisplayOptionFromMetadata (d, m, &opt[i], info[i].name))
|
||
|
{
|
||
|
compFiniDisplayOptions (d, opt, i);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (info[i].initiate)
|
||
|
opt[i].value.action.initiate = info[i].initiate;
|
||
|
|
||
|
if (info[i].terminate)
|
||
|
opt[i].value.action.terminate = info[i].terminate;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
compFiniDisplayOptions (CompDisplay *d,
|
||
|
CompOption *opt,
|
||
|
int n)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < n; i++)
|
||
|
compFiniDisplayOption (d, &opt[i]);
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
compSetDisplayOption (CompDisplay *d,
|
||
|
CompOption *o,
|
||
|
CompOptionValue *value)
|
||
|
{
|
||
|
if (isActionOption (o))
|
||
|
{
|
||
|
if (o->value.action.state & CompActionStateAutoGrab)
|
||
|
{
|
||
|
if (setDisplayAction (d, o, value))
|
||
|
return TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (compSetActionOption (o, value))
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (compSetOption (o, value))
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
compGetStringFromMetadataPath (CompMetadata *metadata,
|
||
|
const char *path)
|
||
|
{
|
||
|
CompXPath xPath;
|
||
|
char *v = NULL;
|
||
|
|
||
|
if (!initXPathFromMetadataPath (&xPath, metadata, BAD_CAST path))
|
||
|
return NULL;
|
||
|
|
||
|
xPath.obj = xmlXPathConvertString (xPath.obj);
|
||
|
|
||
|
if (xPath.obj->type == XPATH_STRING && xPath.obj->stringval)
|
||
|
v = strdup ((char *) xPath.obj->stringval);
|
||
|
|
||
|
finiXPath (&xPath);
|
||
|
|
||
|
return v;
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
compGetShortPluginDescription (CompMetadata *m)
|
||
|
{
|
||
|
char str[1024];
|
||
|
|
||
|
sprintf (str, "/compiz/%s/short/child::text()", m->path);
|
||
|
|
||
|
return compGetStringFromMetadataPath (m, str);
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
compGetLongPluginDescription (CompMetadata *m)
|
||
|
{
|
||
|
char str[1024];
|
||
|
|
||
|
sprintf (str, "/compiz/%s/long/child::text()", m->path);
|
||
|
|
||
|
return compGetStringFromMetadataPath (m, str);
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
compGetShortScreenOptionDescription (CompMetadata *m,
|
||
|
CompOption *o)
|
||
|
{
|
||
|
char str[1024];
|
||
|
|
||
|
sprintf (str, "/compiz/%s/screen//option[@name=\"%s\"]/short/child::text()",
|
||
|
m->path, o->name);
|
||
|
|
||
|
return compGetStringFromMetadataPath (m, str);
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
compGetLongScreenOptionDescription (CompMetadata *m,
|
||
|
CompOption *o)
|
||
|
{
|
||
|
char str[1024];
|
||
|
|
||
|
sprintf (str, "/compiz/%s/screen//option[@name=\"%s\"]/long/child::text()",
|
||
|
m->path, o->name);
|
||
|
|
||
|
return compGetStringFromMetadataPath (m, str);
|
||
|
}
|
||
|
|
||
|
|
||
|
char *
|
||
|
compGetShortDisplayOptionDescription (CompMetadata *m,
|
||
|
CompOption *o)
|
||
|
{
|
||
|
char str[1024];
|
||
|
|
||
|
sprintf (str,
|
||
|
"/compiz/%s/display//option[@name=\"%s\"]/short/child::text()",
|
||
|
m->path, o->name);
|
||
|
|
||
|
return compGetStringFromMetadataPath (m, str);
|
||
|
}
|
||
|
|
||
|
|
||
|
char *
|
||
|
compGetLongDisplayOptionDescription (CompMetadata *m,
|
||
|
CompOption *o)
|
||
|
{
|
||
|
char str[1024];
|
||
|
|
||
|
sprintf (str, "/compiz/%s/display//option[@name=\"%s\"]/long/child::text()",
|
||
|
m->path, o->name);
|
||
|
|
||
|
return compGetStringFromMetadataPath (m, str);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
compReadXmlChunk (const char *src,
|
||
|
int *offset,
|
||
|
char *buffer,
|
||
|
int length)
|
||
|
{
|
||
|
int srcLength = strlen (src);
|
||
|
int srcOffset = *offset;
|
||
|
|
||
|
if (srcOffset > srcLength)
|
||
|
srcOffset = srcLength;
|
||
|
|
||
|
*offset -= srcOffset;
|
||
|
|
||
|
src += srcOffset;
|
||
|
srcLength -= srcOffset;
|
||
|
|
||
|
if (srcLength > 0 && length > 0)
|
||
|
{
|
||
|
if (srcLength < length)
|
||
|
length = srcLength;
|
||
|
|
||
|
memcpy (buffer, src, length);
|
||
|
|
||
|
return length;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
compReadXmlChunkFromMetadataOptionInfo (const CompMetadataOptionInfo *info,
|
||
|
int *offset,
|
||
|
char *buffer,
|
||
|
int length)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
i = compReadXmlChunk ("<option name=\"", offset, buffer, length);
|
||
|
i += compReadXmlChunk (info->name, offset, buffer + i, length - i);
|
||
|
|
||
|
if (info->type)
|
||
|
{
|
||
|
i += compReadXmlChunk ("\" type=\"", offset, buffer + i, length - i);
|
||
|
i += compReadXmlChunk (info->type, offset, buffer + i, length - i);
|
||
|
}
|
||
|
|
||
|
if (info->data)
|
||
|
{
|
||
|
i += compReadXmlChunk ("\">", offset, buffer + i, length - i);
|
||
|
i += compReadXmlChunk (info->data, offset, buffer + i, length - i);
|
||
|
i += compReadXmlChunk ("</option>", offset, buffer + i, length - i);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
i += compReadXmlChunk ("\"/>", offset, buffer + i, length - i);
|
||
|
}
|
||
|
|
||
|
return i;
|
||
|
}
|