diff options
Diffstat (limited to 'src/option.cpp')
-rw-r--r-- | src/option.cpp | 964 |
1 files changed, 964 insertions, 0 deletions
diff --git a/src/option.cpp b/src/option.cpp new file mode 100644 index 0000000..1fb69f0 --- /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 <boost/foreach.hpp> +#define foreach BOOST_FOREACH + +#include <core/core.h> +#include <core/option.h> +#include "privateoption.h" + +CompOption::Vector noOptions (0); + +CompOption::Value::Value () : + priv (new PrivateValue ()) +{ +} + +CompOption::Value::Value (const Value &v) : + priv (new PrivateValue (*v.priv)) +{ +} + +CompOption::Value::~Value () +{ + delete priv; +} + +CompOption::Value::Value (const bool b) : + priv (new PrivateValue ()) +{ + set (b); +} + +CompOption::Value::Value (const int i) : + priv (new PrivateValue ()) +{ + set (i); +} + +CompOption::Value::Value (const float f) : + priv (new PrivateValue ()) +{ + set (f); +} + +CompOption::Value::Value (const unsigned short *color) : + priv (new PrivateValue ()) +{ + set (color); +} + +CompOption::Value::Value (const CompString& s) : + priv (new PrivateValue ()) +{ + set (s); +} + +CompOption::Value::Value (const char *s) : + priv (new PrivateValue ()) +{ + set (s); +} + + +CompOption::Value::Value (const CompMatch& m) : + priv (new PrivateValue ()) +{ + set (m); +} + +CompOption::Value::Value (const CompAction& a) : + priv (new PrivateValue ()) +{ + set (a); +} + +CompOption::Value::Value (CompOption::Type type, const Vector& l) : + priv (new PrivateValue ()) +{ + set (type, l); +} + +CompOption::Type +CompOption::Value::type () const +{ + return priv->type; +} + +void +CompOption::Value::set (const bool b) +{ + priv->reset (); + priv->type = CompOption::TypeBool; + priv->value.b = b; +} + +void +CompOption::Value::set (const int i) +{ + priv->reset (); + priv->type = CompOption::TypeInt; + priv->value.i = i; +} + +void +CompOption::Value::set (const float f) +{ + priv->reset (); + priv->type = CompOption::TypeFloat; + priv->value.f = f; +} + +void +CompOption::Value::set (const unsigned short *color) +{ + priv->reset (); + priv->type = CompOption::TypeColor; + priv->value.c[0] = color[0]; + priv->value.c[1] = color[1]; + priv->value.c[2] = color[2]; + priv->value.c[3] = color[3]; +} + +void +CompOption::Value::set (const CompString& s) +{ + priv->reset (); + priv->type = CompOption::TypeString; + priv->string = s; +} + +void +CompOption::Value::set (const char *s) +{ + priv->reset (); + priv->type = CompOption::TypeString; + priv->string = CompString (s); +} + +void +CompOption::Value::set (const CompMatch& m) +{ + priv->reset (); + priv->type = CompOption::TypeMatch; + priv->match = m; +} + +void +CompOption::Value::set (const CompAction& a) +{ + priv->reset (); + priv->type = CompOption::TypeAction; + priv->action = a; +} + +void +CompOption::Value::set (CompOption::Type type, const Vector& l) +{ + priv->reset (); + priv->type = CompOption::TypeList; + priv->list = l; + priv->listType = type; +} + +static bool +checkIsAction (CompOption::Type type) +{ + switch (type) { + case CompOption::TypeAction: + case CompOption::TypeKey: + case CompOption::TypeButton: + case CompOption::TypeEdge: + case CompOption::TypeBell: + return true; + default: + break; + } + + return false; +} + +bool +CompOption::Value::b () +{ + if (!priv->checkType (CompOption::TypeBool)) + return false; + + return priv->value.b; +} + +int +CompOption::Value::i () +{ + if (!priv->checkType (CompOption::TypeInt)) + return 0; + + return priv->value.i; +} + +float +CompOption::Value::f () +{ + if (!priv->checkType (CompOption::TypeFloat)) + return 0.0; + + return priv->value.f; +} + +static unsigned short defaultColor[4] = { 0x0, 0x0, 0x0, 0xffff}; + +unsigned short * +CompOption::Value::c () +{ + if (!priv->checkType (CompOption::TypeColor)) + return reinterpret_cast<unsigned short *> (defaultColor); + + return priv->value.c; +} + +CompString +CompOption::Value::s () +{ + if (!priv->checkType (CompOption::TypeString)) + return ""; + + return priv->string; +} + +CompMatch & +CompOption::Value::match () +{ + priv->checkType (CompOption::TypeMatch); + + return priv->match; +} + +CompAction & +CompOption::Value::action () +{ + priv->checkType (priv->type); + + if (!checkIsAction (priv->type)) + compLogMessage ("core", CompLogLevelWarn, + "CompOption::Value not an action"); + + return priv->action; +} + +CompOption::Type +CompOption::Value::listType () +{ + priv->checkType (CompOption::TypeList); + + return priv->listType; +} + +CompOption::Value::Vector & +CompOption::Value::list () +{ + priv->checkType (CompOption::TypeList); + + return priv->list; +} + +CompOption::Value::operator bool () +{ + return b (); +} + +CompOption::Value::operator int () +{ + return i (); +} + +CompOption::Value::operator float () +{ + return f (); +} + +CompOption::Value::operator unsigned short * () +{ + return c (); +} + +CompOption::Value::operator CompString () +{ + return s (); +} + +CompOption::Value::operator CompMatch & () +{ + return match (); +} + +CompOption::Value::operator CompAction & () +{ + return action (); +} + +CompOption::Value::operator CompAction * () +{ + return &action (); +} + +CompOption::Value::operator Type () +{ + return listType (); +} + +CompOption::Value::operator Vector & () +{ + return list (); +} + +bool +CompOption::Value::operator== (const CompOption::Value &val) +{ + if (priv->type != val.priv->type) + return false; + + switch (priv->type) + { + case CompOption::TypeBool: + return priv->value.b == val.priv->value.b; + break; + + case CompOption::TypeInt: + return priv->value.i == val.priv->value.i; + break; + + case CompOption::TypeFloat: + return priv->value.f == val.priv->value.f; + break; + + case CompOption::TypeColor: + return (priv->value.c[0] == val.priv->value.c[0]) && + (priv->value.c[1] == val.priv->value.c[1]) && + (priv->value.c[2] == val.priv->value.c[2]) && + (priv->value.c[3] == val.priv->value.c[3]); + break; + + case CompOption::TypeString: + return priv->string.compare (val.priv->string) == 0; + break; + + case CompOption::TypeMatch: + return priv->match == val.priv->match; + break; + + case CompOption::TypeAction: + return priv->action == val.priv->action; + break; + + case CompOption::TypeList: + if (priv->listType != val.priv->listType) + return false; + + if (priv->list.size () != val.priv->list.size ()) + return false; + + for (unsigned int i = 0; i < priv->list.size (); i++) + if (priv->list[i] != val.priv->list[i]) + return false; + + return true; + break; + + default: + break; + } + + return true; +} + +bool +CompOption::Value::operator!= (const CompOption::Value &val) +{ + return !(*this == val); +} + +CompOption::Value & +CompOption::Value::operator= (const CompOption::Value &val) +{ + delete priv; + priv = new PrivateValue (*val.priv); + + return *this; +} + +PrivateValue::PrivateValue () : + type (CompOption::TypeUnset), + string (""), + action (), + match (), + listType (CompOption::TypeUnset), + list () +{ + memset (&value, 0, sizeof (ValueUnion)); +} + +PrivateValue::PrivateValue (const PrivateValue& p) : + type (p.type), + string (p.string), + action (p.action), + match (p.match), + listType (p.listType), + list (p.list) +{ + memcpy (&value, &p.value, sizeof (ValueUnion)); +} + +bool +PrivateValue::checkType (CompOption::Type refType) +{ + if (type == CompOption::TypeUnset) + { + compLogMessage ("core", CompLogLevelWarn, + "Value type is not yet set"); + return false; + } + + if (type != refType) + { + compLogMessage ("core", CompLogLevelWarn, + "Value type does not match (is %d, expected %d)", + type, refType); + return false; + } + + return true; +} + +void +PrivateValue::reset () +{ + switch (type) { + case CompOption::TypeString: + string = ""; + break; + case CompOption::TypeMatch: + match = CompMatch (); + break; + case CompOption::TypeAction: + action = CompAction (); + break; + case CompOption::TypeList: + list.clear (); + listType = CompOption::TypeBool; + break; + default: + break; + } + type = CompOption::TypeBool; +} + +CompOption::Restriction::Restriction () : + priv (new PrivateRestriction ()) +{ +} + +CompOption::Restriction::Restriction (const CompOption::Restriction &r) : + priv (new PrivateRestriction (*r.priv)) +{ +} + +CompOption::Restriction::~Restriction () +{ + delete priv; +} + +int +CompOption::Restriction::iMin () +{ + if (priv->type == CompOption::TypeInt) + return priv->rest.i.min; + return MINSHORT; +} + +int +CompOption::Restriction::iMax () +{ + if (priv->type == CompOption::TypeInt) + return priv->rest.i.max; + return MAXSHORT; +} + +float +CompOption::Restriction::fMin () +{ + if (priv->type == CompOption::TypeFloat) + return priv->rest.f.min; + return MINSHORT; +} + +float +CompOption::Restriction::fMax () +{ + if (priv->type == CompOption::TypeFloat) + return priv->rest.f.min; + return MINSHORT; +} + +float +CompOption::Restriction::fPrecision () +{ + if (priv->type == CompOption::TypeFloat) + return priv->rest.f.precision; + return 0.1f; +} + + +void +CompOption::Restriction::set (int min, int max) +{ + priv->type = CompOption::TypeInt; + priv->rest.i.min = min; + priv->rest.i.max = max; +} + +void +CompOption::Restriction::set (float min, float max, float precision) +{ + priv->type = CompOption::TypeFloat; + priv->rest.f.min = min; + priv->rest.f.max = max; + priv->rest.f.precision = precision; +} + +bool +CompOption::Restriction::inRange (int i) +{ + if (priv->type != CompOption::TypeInt) + return true; + if (i < priv->rest.i.min) + return false; + if (i > priv->rest.i.max) + return false; + return true; +} + +bool +CompOption::Restriction::inRange (float f) +{ + if (priv->type != CompOption::TypeFloat) + return true; + if (f < priv->rest.f.min) + return false; + if (f > priv->rest.f.max) + return false; + return true; +} + +CompOption::Restriction & +CompOption::Restriction::operator= (const CompOption::Restriction &rest) +{ + delete priv; + priv = new PrivateRestriction (*rest.priv); + return *this; +} + +CompOption * +CompOption::Class::getOption (const CompString &name) +{ + CompOption *o = CompOption::findOption (getOptions (), name); + return o; +} + +CompOption * +CompOption::findOption (CompOption::Vector &options, + CompString name, + unsigned int *index) +{ + unsigned int i; + + for (i = 0; i < options.size (); i++) + { + if (options[i].priv->name == name) + { + if (index) + *index = i; + + return &options[i]; + } + } + + return NULL; +} + +CompOption::CompOption () : + priv (new PrivateOption ()) +{ +} + +CompOption::CompOption (const CompOption &o) : + priv (new PrivateOption (*o.priv)) +{ +} + +CompOption::CompOption (CompString name, CompOption::Type type) : + priv (new PrivateOption ()) +{ + setName (name, type); +} + +static void +finiScreenOptionValue (CompScreen *s, + CompOption::Value &v, + CompOption::Type type) +{ + switch (type) { + case CompOption::TypeAction: + case CompOption::TypeKey: + case CompOption::TypeButton: + case CompOption::TypeEdge: + case CompOption::TypeBell: + if (v.action ().state () & CompAction::StateAutoGrab) + s->removeAction (&v.action ()); + break; + + case CompOption::TypeList: + foreach (CompOption::Value &val, v.list ()) + finiScreenOptionValue (s, val, v.listType ()); + break; + + default: + break; + } +} + +static void +finiOptionValue (CompOption::Value &v, + CompOption::Type type) +{ + switch (type) { + case CompOption::TypeAction: + case CompOption::TypeKey: + case CompOption::TypeButton: + case CompOption::TypeEdge: + case CompOption::TypeBell: + if (v.action ().state () & CompAction::StateAutoGrab && screen) + screen->removeAction (&v.action ()); + break; + + case CompOption::TypeList: + foreach (CompOption::Value &val, v.list ()) + finiOptionValue (val, v.listType ()); + break; + + default: + break; + } +} + +CompOption::~CompOption () +{ + finiOptionValue (priv->value, priv->type); + delete priv; +} + +void +CompOption::setName (CompString name, CompOption::Type type) +{ + priv->name = name; + priv->type = type; +} + +CompString +CompOption::name () +{ + return priv->name; +} + +CompOption::Type +CompOption::type () +{ + return priv->type; +} + +CompOption::Value & +CompOption::value () +{ + return priv->value; +} + +CompOption::Restriction & +CompOption::rest () +{ + return priv->rest; +} + +bool +CompOption::set (CompOption::Value &val) +{ + if (isAction () && priv->type != CompOption::TypeAction) + val.action ().copyState (priv->value.action ()); + + if (priv->type != val.type () && + (!isAction () || !checkIsAction (val.type ()))) + { + compLogMessage ("core", CompLogLevelWarn, + "Can't set Value with type %d to " + "option \"%s\" with type %d", + val.type (), priv->name.c_str (), priv->type); + return false; + } + + if (priv->value == val) + return false; + + if (isAction () && + priv->value.action ().state () & CompAction::StateAutoGrab && screen) + { + if (!screen->addAction (&val.action ())) + return false; + else + screen->removeAction (&priv->value.action ()); + } + + switch (priv->type) + { + case CompOption::TypeInt: + if (!priv->rest.inRange (val.i ())) + return false; + break; + + case CompOption::TypeFloat: + { + float v, p; + int sign = (val.f () < 0 ? -1 : 1); + + if (!priv->rest.inRange (val.f ())) + return false; + + p = 1.0f / priv->rest.fPrecision (); + v = ((int) (val.f () * p + sign * 0.5f)) / p; + + priv->value.set (v); + return true; + } + + case CompOption::TypeAction: + return false; + + case CompOption::TypeKey: + if (val.action ().type () == value().action ().type () && + !(val.action ().type () & CompAction::BindingTypeKey)) + return false; + break; + + case CompOption::TypeButton: + if (val.action ().type () == value().action ().type () && + !(val.action ().type () & (CompAction::BindingTypeButton | + CompAction::BindingTypeEdgeButton))) + return false; + break; + + default: + break; + } + + priv->value = val; + + return true; +} + +bool +CompOption::isAction () +{ + return checkIsAction (priv->type); +} + +CompOption & +CompOption::operator= (const CompOption &option) +{ + delete priv; + priv = new PrivateOption (*option.priv); + return *this; +} + +bool +CompOption::getBoolOptionNamed (const Vector& options, + const CompString& name, + bool defaultValue) +{ + foreach (const CompOption &o, options) + if (o.priv->type == CompOption::TypeBool && o.priv->name == name) + return o.priv->value.b (); + + return defaultValue; +} + +int +CompOption::getIntOptionNamed (const Vector& options, + const CompString& name, + int defaultValue) +{ + foreach (const CompOption &o, options) + if (o.priv->type == CompOption::TypeInt && o.priv->name == name) + return o.priv->value.i (); + + return defaultValue; +} + +float +CompOption::getFloatOptionNamed (const Vector& options, + const CompString& name, + const float& defaultValue) +{ + foreach (const CompOption &o, options) + if (o.priv->type == CompOption::TypeFloat && o.priv->name == name) + return o.priv->value.f (); + + return defaultValue; +} + +CompString +CompOption::getStringOptionNamed (const Vector& options, + const CompString& name, + const CompString& defaultValue) +{ + foreach (const CompOption &o, options) + if (o.priv->type == CompOption::TypeString && o.priv->name == name) + return o.priv->value.s (); + + return defaultValue; +} + +unsigned short * +CompOption::getColorOptionNamed (const Vector& options, + const CompString& name, + unsigned short *defaultValue) +{ + foreach (const CompOption &o, options) + if (o.priv->type == CompOption::TypeColor && o.priv->name == name) + return o.priv->value.c (); + + return defaultValue; +} + +CompMatch +CompOption::getMatchOptionNamed (const Vector& options, + const CompString& name, + const CompMatch& defaultValue) +{ + foreach (const CompOption &o, options) + if (o.priv->type == CompOption::TypeMatch && o.priv->name == name) + return o.priv->value.match (); + + return defaultValue; +} + +bool +CompOption::stringToColor (CompString color, + unsigned short *rgba) +{ + int c[4]; + + if (sscanf (color.c_str (), "#%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; +} + +CompString +CompOption::colorToString (unsigned short *rgba) +{ + return compPrintf ("#%.2x%.2x%.2x%.2x", rgba[0] / 256, rgba[1] / 256, + rgba[2] / 256, rgba[3] / 256); +} + +CompString +CompOption::typeToString (CompOption::Type type) +{ + switch (type) { + case CompOption::TypeBool: + return "bool"; + case CompOption::TypeInt: + return "int"; + case CompOption::TypeFloat: + return "float"; + case CompOption::TypeString: + return "string"; + case CompOption::TypeColor: + return "color"; + case CompOption::TypeAction: + return "action"; + case CompOption::TypeKey: + return "key"; + case CompOption::TypeButton: + return "button"; + case CompOption::TypeEdge: + return "edge"; + case CompOption::TypeBell: + return "bell"; + case CompOption::TypeMatch: + return "match"; + case CompOption::TypeList: + return "list"; + default: + break; + } + + return "unknown"; +} + +bool +CompOption::setOption (CompOption &o, + CompOption::Value &value) +{ + return o.set (value); +} + +PrivateOption::PrivateOption () : + name (""), + type (CompOption::TypeUnset), + value (), + rest () +{ +} + +PrivateOption::PrivateOption (const PrivateOption &p) : + name (p.name), + type (p.type), + value (p.value), + rest (p.rest) +{ +} + |