summaryrefslogtreecommitdiff
path: root/src/option.cpp
diff options
context:
space:
mode:
authorDennis Kasprzyk <onestone@opencompositing.org>2008-07-25 23:54:30 +0200
committerDennis kasprzyk <onestone@opencompositing.org>2008-07-25 23:54:30 +0200
commit0e942665257980878d6271cbcad4647d04204093 (patch)
tree83ca2da9686e90a5f257a360e5a15e4158165907 /src/option.cpp
parent83e50fca60fb85aff79e4b6118ad57361caa6a8a (diff)
downloadunity-window-decorator-0e942665257980878d6271cbcad4647d04204093.tar.gz
unity-window-decorator-0e942665257980878d6271cbcad4647d04204093.tar.bz2
Switch to c++ and compile with a basic set of plugins.
Diffstat (limited to 'src/option.cpp')
-rw-r--r--src/option.cpp964
1 files changed, 964 insertions, 0 deletions
diff --git a/src/option.cpp b/src/option.cpp
new file mode 100644
index 0000000..1c704fc
--- /dev/null
+++ b/src/option.cpp
@@ -0,0 +1,964 @@
+/*
+ * Copyright © 2005 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
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <math.h>
+
+#include <compiz-core.h>
+
+struct _Modifier {
+ char *name;
+ int modifier;
+} modifiers[] = {
+ { "<Shift>", ShiftMask },
+ { "<Control>", ControlMask },
+ { "<Mod1>", Mod1Mask },
+ { "<Mod2>", Mod2Mask },
+ { "<Mod3>", Mod3Mask },
+ { "<Mod4>", Mod4Mask },
+ { "<Mod5>", Mod5Mask },
+ { "<Alt>", CompAltMask },
+ { "<Meta>", CompMetaMask },
+ { "<Super>", CompSuperMask },
+ { "<Hyper>", CompHyperMask },
+ { "<ModeSwitch>", CompModeSwitchMask }
+};
+
+#define N_MODIFIERS (sizeof (modifiers) / sizeof (struct _Modifier))
+
+struct _Edge {
+ char *name;
+ char *modifierName;
+} edges[] = {
+ { "Left", "<LeftEdge>" },
+ { "Right", "<RightEdge>" },
+ { "Top", "<TopEdge>" },
+ { "Bottom", "<BottomEdge>" },
+ { "TopLeft", "<TopLeftEdge>" },
+ { "TopRight", "<TopRightEdge>" },
+ { "BottomLeft", "<BottomLeftEdge>" },
+ { "BottomRight", "<BottomRightEdge>" }
+};
+
+void
+compInitOptionValue (CompOptionValue *v)
+{
+ memset (v, 0, sizeof (CompOptionValue));
+}
+
+void
+compFiniOptionValue (CompOptionValue *v,
+ CompOptionType type)
+{
+ int i;
+
+ switch (type) {
+ case CompOptionTypeString:
+ if (v->s)
+ free (v->s);
+ break;
+ case CompOptionTypeMatch:
+ matchFini (&v->match);
+ break;
+ case CompOptionTypeList:
+ for (i = 0; i < v->list.nValue; i++)
+ compFiniOptionValue (&v->list.value[i], v->list.type);
+
+ if (v->list.value)
+ free (v->list.value);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+compInitOption (CompOption *o)
+{
+ memset (o, 0, sizeof (CompOption));
+}
+
+void
+compFiniOption (CompOption *o)
+{
+ compFiniOptionValue (&o->value, o->type);
+}
+
+CompOption *
+compFindOption (CompOption *option,
+ int nOption,
+ const char *name,
+ int *index)
+{
+ int i;
+
+ for (i = 0; i < nOption; i++)
+ {
+ if (strcmp (option[i].name, name) == 0)
+ {
+ if (index)
+ *index = i;
+
+ return &option[i];
+ }
+ }
+
+ return 0;
+}
+
+Bool
+compSetBoolOption (CompOption *option,
+ CompOptionValue *value)
+{
+ int b;
+
+ b = (value->b) ? TRUE : FALSE;
+
+ if (option->value.b == b)
+ return FALSE;
+
+ option->value.b = b;
+
+ return TRUE;
+}
+
+Bool
+compSetIntOption (CompOption *option,
+ CompOptionValue *value)
+{
+ if (value->i < option->rest.i.min ||
+ value->i > option->rest.i.max ||
+ value->i == option->value.i)
+ return FALSE;
+
+ option->value.i = value->i;
+
+ return TRUE;
+}
+
+Bool
+compSetFloatOption (CompOption *option,
+ CompOptionValue *value)
+{
+ float v, p;
+
+ /* Workaround for float rounding errors */
+ static float equalRange = 1e-5;
+
+ int sign = (value->f < 0 ? -1 : 1);
+
+ p = 1.0f / option->rest.f.precision;
+ v = ((int) (value->f * p + sign * 0.5f)) / p;
+
+ if (v < (option->rest.f.min - equalRange) ||
+ v > (option->rest.f.max + equalRange))
+ return FALSE;
+
+ if (v > (option->value.f - equalRange) &&
+ v < (option->value.f + equalRange))
+ return FALSE;
+
+ option->value.f = v;
+
+ return TRUE;
+}
+
+Bool
+compSetStringOption (CompOption *option,
+ CompOptionValue *value)
+{
+ char *s;
+
+ s = value->s;
+ if (!s)
+ s = "";
+
+ if (option->value.s == s)
+ return FALSE;
+
+ if (option->value.s && s)
+ {
+ if (strcmp (option->value.s, s) == 0)
+ return FALSE;
+ }
+
+ if (option->value.s)
+ free (option->value.s);
+
+ option->value.s = strdup (s);
+
+ return TRUE;
+}
+
+Bool
+compSetColorOption (CompOption *option,
+ CompOptionValue *value)
+{
+ if (memcmp (value->c, option->value.c, sizeof (value->c)) == 0)
+ return FALSE;
+
+ memcpy (option->value.c, value->c, sizeof (value->c));
+
+ return TRUE;
+}
+
+Bool
+compSetActionOption (CompOption *option,
+ CompOptionValue *value)
+{
+ CompAction *action = &option->value.action;
+ CompOptionValue v = *value;
+
+ /* initiate, terminate and state should never be changed */
+ v.action.initiate = action->initiate;
+ v.action.terminate = action->terminate;
+ v.action.state = action->state;
+
+ if (action->type == v.action.type)
+ {
+ switch (option->type) {
+ case CompOptionTypeKey:
+ if (!(action->type & CompBindingTypeKey))
+ return FALSE;
+
+ if (action->key.keycode == v.action.key.keycode &&
+ action->key.modifiers == v.action.key.modifiers)
+ return FALSE;
+ break;
+ case CompOptionTypeButton:
+ if (!(action->type & (CompBindingTypeButton |
+ CompBindingTypeEdgeButton)))
+ return FALSE;
+
+ if (action->type & CompBindingTypeEdgeButton)
+ {
+ if (action->button.button == v.action.button.button &&
+ action->button.modifiers == v.action.button.modifiers &&
+ action->edgeMask == v.action.edgeMask)
+ return FALSE;
+ }
+ else if (action->type & CompBindingTypeButton)
+ {
+ if (action->button.button == v.action.button.button &&
+ action->button.modifiers == v.action.button.modifiers)
+ return FALSE;
+ }
+ break;
+ case CompOptionTypeEdge:
+ if (v.action.edgeMask == action->edgeMask)
+ return FALSE;
+ break;
+ case CompOptionTypeBell:
+ if (v.action.bell == action->bell)
+ return FALSE;
+ break;
+ default:
+ return FALSE;
+ }
+ }
+
+ *action = v.action;
+
+ return TRUE;
+}
+
+Bool
+compSetMatchOption (CompOption *option,
+ CompOptionValue *value)
+{
+ CompDisplay *display = option->value.match.display;
+ CompMatch match;
+
+ if (matchEqual (&option->value.match, &value->match))
+ return FALSE;
+
+ if (!matchCopy (&match, &value->match))
+ return FALSE;
+
+ matchFini (&option->value.match);
+
+ option->value.match.op = match.op;
+ option->value.match.nOp = match.nOp;
+
+ if (display)
+ matchUpdate (display, &option->value.match);
+
+ return TRUE;
+}
+
+Bool
+compSetOptionList (CompOption *option,
+ CompOptionValue *value)
+{
+ CompOption o;
+ Bool status = FALSE;
+ int i, min;
+
+ if (value->list.nValue != option->value.list.nValue)
+ {
+ CompOptionValue *v;
+
+ v = (CompOptionValue *) malloc (sizeof (CompOptionValue) * value->list.nValue);
+ if (!v)
+ return FALSE;
+
+ min = MIN (value->list.nValue, option->value.list.nValue);
+
+ for (i = min; i < option->value.list.nValue; i++)
+ {
+ switch (option->value.list.type) {
+ case CompOptionTypeString:
+ if (option->value.list.value[i].s)
+ free (option->value.list.value[i].s);
+ break;
+ case CompOptionTypeMatch:
+ matchFini (&option->value.list.value[i].match);
+ default:
+ break;
+ }
+ }
+
+ memset (v, 0, sizeof (CompOptionValue) * value->list.nValue);
+
+ if (min)
+ memcpy (v, option->value.list.value,
+ sizeof (CompOptionValue) * min);
+
+ if (option->value.list.value)
+ free (option->value.list.value);
+
+ option->value.list.value = v;
+ option->value.list.nValue = value->list.nValue;
+
+ status = TRUE;
+ }
+
+ o = *option;
+ o.type = option->value.list.type;
+
+ for (i = 0; i < value->list.nValue; i++)
+ {
+ o.value = option->value.list.value[i];
+
+ switch (o.type) {
+ case CompOptionTypeBool:
+ status |= compSetBoolOption (&o, &value->list.value[i]);
+ break;
+ case CompOptionTypeInt:
+ status |= compSetIntOption (&o, &value->list.value[i]);
+ break;
+ case CompOptionTypeFloat:
+ status |= compSetFloatOption (&o, &value->list.value[i]);
+ break;
+ case CompOptionTypeString:
+ status |= compSetStringOption (&o, &value->list.value[i]);
+ break;
+ case CompOptionTypeColor:
+ status |= compSetColorOption (&o, &value->list.value[i]);
+ break;
+ case CompOptionTypeMatch:
+ status |= compSetMatchOption (&o, &value->list.value[i]);
+ default:
+ break;
+ }
+
+ option->value.list.value[i] = o.value;
+ }
+
+ return status;
+}
+
+Bool
+compSetOption (CompOption *option,
+ CompOptionValue *value)
+{
+ switch (option->type) {
+ case CompOptionTypeBool:
+ return compSetBoolOption (option, value);
+ case CompOptionTypeInt:
+ return compSetIntOption (option, value);
+ case CompOptionTypeFloat:
+ return compSetFloatOption (option, value);
+ case CompOptionTypeString:
+ return compSetStringOption (option, value);
+ case CompOptionTypeColor:
+ return compSetColorOption (option, value);
+ case CompOptionTypeMatch:
+ return compSetMatchOption (option, value);
+ case CompOptionTypeAction:
+ case CompOptionTypeKey:
+ case CompOptionTypeButton:
+ case CompOptionTypeEdge:
+ case CompOptionTypeBell:
+ return compSetActionOption (option, value);
+ case CompOptionTypeList:
+ return compSetOptionList (option, value);
+ }
+
+ return FALSE;
+}
+
+Bool
+getBoolOptionNamed (CompOption *option,
+ int nOption,
+ const char *name,
+ Bool defaultValue)
+{
+ while (nOption--)
+ {
+ if (option->type == CompOptionTypeBool)
+ if (strcmp (option->name, name) == 0)
+ return option->value.b;
+
+ option++;
+ }
+
+ return defaultValue;
+}
+
+int
+getIntOptionNamed (CompOption *option,
+ int nOption,
+ const char *name,
+ int defaultValue)
+{
+ while (nOption--)
+ {
+ if (option->type == CompOptionTypeInt)
+ if (strcmp (option->name, name) == 0)
+ return option->value.i;
+
+ option++;
+ }
+
+ return defaultValue;
+}
+
+float
+getFloatOptionNamed (CompOption *option,
+ int nOption,
+ const char *name,
+ float defaultValue)
+{
+ while (nOption--)
+ {
+ if (option->type == CompOptionTypeFloat)
+ if (strcmp (option->name, name) == 0)
+ return option->value.f;
+
+ option++;
+ }
+
+ return defaultValue;
+}
+
+char *
+getStringOptionNamed (CompOption *option,
+ int nOption,
+ const char *name,
+ char *defaultValue)
+{
+ while (nOption--)
+ {
+ if (option->type == CompOptionTypeString)
+ if (strcmp (option->name, name) == 0)
+ return option->value.s;
+
+ option++;
+ }
+
+ return defaultValue;
+}
+
+unsigned short *
+getColorOptionNamed (CompOption *option,
+ int nOption,
+ const char *name,
+ unsigned short *defaultValue)
+{
+ while (nOption--)
+ {
+ if (option->type == CompOptionTypeColor)
+ if (strcmp (option->name, name) == 0)
+ return option->value.c;
+
+ option++;
+ }
+
+ return defaultValue;
+}
+
+CompMatch *
+getMatchOptionNamed (CompOption *option,
+ int nOption,
+ const char *name,
+ CompMatch *defaultValue)
+{
+ while (nOption--)
+ {
+ if (option->type == CompOptionTypeMatch)
+ if (strcmp (option->name, name) == 0)
+ return &option->value.match;
+
+ option++;
+ }
+
+ return defaultValue;
+}
+
+static char *
+stringAppend (char *s,
+ const char *a)
+{
+ char *r;
+ int len;
+
+ len = strlen (a);
+
+ if (s)
+ len += strlen (s);
+
+ r = (char *) malloc (len + 1);
+ if (r)
+ {
+ if (s)
+ {
+ sprintf (r, "%s%s", s, a);
+ free (s);
+ }
+ else
+ {
+ sprintf (r, "%s", a);
+ }
+
+ s = r;
+ }
+
+ return s;
+}
+
+static char *
+modifiersToString (CompDisplay *d,
+ unsigned int modMask)
+{
+ char *binding = NULL;
+ int i;
+
+ for (i = 0; i < N_MODIFIERS; i++)
+ {
+ if (modMask & modifiers[i].modifier)
+ binding = stringAppend (binding, modifiers[i].name);
+ }
+
+ return binding;
+}
+
+static char *
+edgeMaskToBindingString (CompDisplay *d,
+ unsigned int edgeMask)
+{
+ char *binding = NULL;
+ int i;
+
+ for (i = 0; i < SCREEN_EDGE_NUM; i++)
+ if (edgeMask & (1 << i))
+ binding = stringAppend (binding, edges[i].modifierName);
+
+ return binding;
+}
+
+char *
+keyBindingToString (CompDisplay *d,
+ CompKeyBinding *key)
+{
+ char *binding;
+
+ binding = modifiersToString (d, key->modifiers);
+
+ if (key->keycode != 0)
+ {
+ KeySym keysym;
+ char *keyname;
+
+ keysym = XKeycodeToKeysym (d->display, key->keycode, 0);
+ keyname = XKeysymToString (keysym);
+
+ if (keyname)
+ {
+ binding = stringAppend (binding, keyname);
+ }
+ else
+ {
+ char keyCodeStr[256];
+
+ snprintf (keyCodeStr, 256, "0x%x", key->keycode);
+ binding = stringAppend (binding, keyCodeStr);
+ }
+ }
+
+ return binding;
+}
+
+char *
+buttonBindingToString (CompDisplay *d,
+ CompButtonBinding *button)
+{
+ char *binding;
+ char buttonStr[256];
+
+ binding = modifiersToString (d, button->modifiers);
+
+ snprintf (buttonStr, 256, "Button%d", button->button);
+ binding = stringAppend (binding, buttonStr);
+
+ return binding;
+}
+
+char *
+keyActionToString (CompDisplay *d,
+ CompAction *action)
+{
+ char *binding;
+
+ binding = keyBindingToString (d, &action->key);
+ if (!binding)
+ return strdup ("Disabled");
+
+ return binding;
+}
+
+char *
+buttonActionToString (CompDisplay *d,
+ CompAction *action)
+{
+ char *binding, *edge;
+ char buttonStr[256];
+
+ binding = modifiersToString (d, action->button.modifiers);
+ edge = edgeMaskToBindingString (d, action->edgeMask);
+
+ if (edge)
+ {
+ binding = stringAppend (binding, edge);
+ free (edge);
+ }
+
+ snprintf (buttonStr, 256, "Button%d", action->button.button);
+ binding = stringAppend (binding, buttonStr);
+
+ if (!binding)
+ return strdup ("Disabled");
+
+ return binding;
+}
+
+static unsigned int
+stringToModifiers (CompDisplay *d,
+ const char *binding)
+{
+ unsigned int mods = 0;
+ int i;
+
+ for (i = 0; i < N_MODIFIERS; i++)
+ {
+ if (strstr (binding, modifiers[i].name))
+ mods |= modifiers[i].modifier;
+ }
+
+ return mods;
+}
+
+static unsigned int
+bindingStringToEdgeMask (CompDisplay *d,
+ const char *binding)
+{
+ unsigned int edgeMask = 0;
+ int i;
+
+ for (i = 0; i < SCREEN_EDGE_NUM; i++)
+ if (strstr (binding, edges[i].modifierName))
+ edgeMask |= 1 << i;
+
+ return edgeMask;
+}
+
+Bool
+stringToKeyBinding (CompDisplay *d,
+ const char *binding,
+ CompKeyBinding *key)
+{
+ char *ptr;
+ unsigned int mods;
+ KeySym keysym;
+
+ mods = stringToModifiers (d, binding);
+
+ ptr = strrchr (binding, '>');
+ if (ptr)
+ binding = ptr + 1;
+
+ while (*binding && !isalnum (*binding))
+ binding++;
+
+ if (!*binding)
+ {
+ if (mods)
+ {
+ key->keycode = 0;
+ key->modifiers = mods;
+
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ keysym = XStringToKeysym (binding);
+ if (keysym != NoSymbol)
+ {
+ KeyCode keycode;
+
+ keycode = XKeysymToKeycode (d->display, keysym);
+ if (keycode)
+ {
+ key->keycode = keycode;
+ key->modifiers = mods;
+
+ return TRUE;
+ }
+ }
+
+ if (strncmp (binding, "0x", 2) == 0)
+ {
+ key->keycode = strtol (binding, NULL, 0);
+ key->modifiers = mods;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+Bool
+stringToButtonBinding (CompDisplay *d,
+ const char *binding,
+ CompButtonBinding *button)
+{
+ char *ptr;
+ unsigned int mods;
+
+ mods = stringToModifiers (d, binding);
+
+ ptr = strrchr (binding, '>');
+ if (ptr)
+ binding = ptr + 1;
+
+ while (*binding && !isalnum (*binding))
+ binding++;
+
+ if (strncmp (binding, "Button", strlen ("Button")) == 0)
+ {
+ int buttonNum;
+
+ if (sscanf (binding + strlen ("Button"), "%d", &buttonNum) == 1)
+ {
+ button->button = buttonNum;
+ button->modifiers = mods;
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void
+stringToKeyAction (CompDisplay *d,
+ const char *binding,
+ CompAction *action)
+{
+ if (stringToKeyBinding (d, binding, &action->key))
+ action->type = CompBindingTypeKey;
+ else
+ action->type = CompBindingTypeNone;
+}
+
+void
+stringToButtonAction (CompDisplay *d,
+ const char *binding,
+ CompAction *action)
+{
+ if (stringToButtonBinding (d, binding, &action->button))
+ {
+ action->edgeMask = bindingStringToEdgeMask (d, binding);
+ if (action->edgeMask)
+ action->type = CompBindingTypeEdgeButton;
+ else
+ action->type = CompBindingTypeButton;
+ }
+ else
+ {
+ action->type = CompBindingTypeNone;
+ }
+}
+
+const char *
+edgeToString (unsigned int edge)
+{
+ return edges[edge].name;
+}
+
+unsigned int
+stringToEdgeMask (const char *edge)
+{
+ unsigned int edgeMask = 0;
+ char *needle;
+ int i;
+
+ for (i = 0; i < SCREEN_EDGE_NUM; i++)
+ {
+ needle = strstr (edge, edgeToString (i));
+ if (needle)
+ {
+ if (needle != edge && isalnum (*(needle - 1)))
+ continue;
+
+ needle += strlen (edgeToString (i));
+
+ if (*needle && isalnum (*needle))
+ continue;
+
+ edgeMask |= 1 << i;
+ }
+ }
+
+ return edgeMask;
+}
+
+char *
+edgeMaskToString (unsigned int edgeMask)
+{
+ char *edge = NULL;
+ int i;
+
+ for (i = 0; i < SCREEN_EDGE_NUM; i++)
+ {
+ if (edgeMask & (1 << i))
+ {
+ if (edge)
+ edge = stringAppend (edge, " | ");
+
+ edge = stringAppend (edge, edgeToString (i));
+ }
+ }
+
+ if (!edge)
+ return strdup ("");
+
+ return edge;
+}
+
+Bool
+stringToColor (const char *color,
+ unsigned short *rgba)
+{
+ int c[4];
+
+ if (sscanf (color, "#%2x%2x%2x%2x", &c[0], &c[1], &c[2], &c[3]) == 4)
+ {
+ rgba[0] = c[0] << 8 | c[0];
+ rgba[1] = c[1] << 8 | c[1];
+ rgba[2] = c[2] << 8 | c[2];
+ rgba[3] = c[3] << 8 | c[3];
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+char *
+colorToString (unsigned short *rgba)
+{
+ char tmp[256];
+
+ snprintf (tmp, 256, "#%.2x%.2x%.2x%.2x",
+ rgba[0] / 256, rgba[1] / 256, rgba[2] / 256, rgba[3] / 256);
+
+ return strdup (tmp);
+}
+
+const char *
+optionTypeToString (CompOptionType type)
+{
+ switch (type) {
+ case CompOptionTypeBool:
+ return "bool";
+ case CompOptionTypeInt:
+ return "int";
+ case CompOptionTypeFloat:
+ return "float";
+ case CompOptionTypeString:
+ return "string";
+ case CompOptionTypeColor:
+ return "color";
+ case CompOptionTypeAction:
+ return "action";
+ case CompOptionTypeKey:
+ return "key";
+ case CompOptionTypeButton:
+ return "button";
+ case CompOptionTypeEdge:
+ return "edge";
+ case CompOptionTypeBell:
+ return "bell";
+ case CompOptionTypeMatch:
+ return "match";
+ case CompOptionTypeList:
+ return "list";
+ }
+
+ return "unknown";
+}
+
+Bool
+isActionOption (CompOption *option)
+{
+ switch (option->type) {
+ case CompOptionTypeAction:
+ case CompOptionTypeKey:
+ case CompOptionTypeButton:
+ case CompOptionTypeEdge:
+ case CompOptionTypeBell:
+ return TRUE;
+ default:
+ break;
+ }
+
+ return FALSE;
+}