Logo Search packages:      
Sourcecode: beryl-core version File versions

option.c

/*
 * Copyright © 2005 Novell, Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Author: David Reveman <davidr@novell.com>
 */

#define _GNU_SOURCE

#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <math.h>

#include <beryl.h>
#include <beryl-private.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))

static char *edgeName[] = {
      N_("Left"),
      N_("Right"),
      N_("Top"),
      N_("Bottom"),
      N_("TopLeft"),
      N_("TopRight"),
      N_("BottomLeft"),
      N_("BottomRight")
};

CompOption *compFindOption(CompOption * option, int nOption, 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;
      float equalRange;

      p = 1.0f / option->rest.f.precision;
      v = ((int)(value->f * p + 0.5f)) / p;

      // Workaround for float error problems
      equalRange = 1e-5;

      if (v - option->rest.f.min < -equalRange ||
            v - option->rest.f.max > equalRange || v == option->value.f)
            return FALSE;

      option->value.f = v;

      return TRUE;
}

Bool compSetStringOption(CompOption * option, CompOptionValue * value)
{
      char *s;

      s = value->s;
      if (!s)
            s = "";

      if (option->rest.s.nString)
      {
            int i;

            for (i = 0; i < option->rest.s.nString; i++)
            {
                  if (strcmp(option->rest.s.string[i], s) == 0)
                        break;
            }

            if (i == option->rest.s.nString)
                  s = option->rest.s.string[0];
      }

      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 = NULL;
      }
      //s can be NULL at this point
      option->value.s = s ? strdup(s) : strdup("");

      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;

      if (value->action.type == action->type &&
            value->action.bell == action->bell &&
            value->action.edgeMask == action->edgeMask)
      {
            Bool equal = TRUE;

            if (value->action.type & CompBindingTypeButton)
            {
                  if (action->button.button !=
                        value->action.button.button
                        || action->button.modifiers != value->action.button.modifiers)
                        equal = FALSE;
            }

            if (value->action.type & CompBindingTypeKey)
            {
                  if (action->key.keysym != value->action.key.keysym
                        || action->key.modifiers != value->action.key.modifiers)
                        equal = FALSE;
            }

            if (value->action.type & CompBindingTypeEdgeButton)
            {
                  if (action->edgeButton != value->action.edgeButton)
                        equal = FALSE;
            }

            if (equal)
                  return FALSE;
      }

      *action = value->action;

      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 = malloc(sizeof(CompOptionValue) * value->list.nValue);
            if (!v)
                  return FALSE;

            min = MIN(value->list.nValue, option->value.list.nValue);

            if (min < option->value.list.nValue)
            {
                  switch (option->value.list.type)
                  {
                  case CompOptionTypeString:
                        for (i = min; i < option->value.list.nValue; i++)
                        {
                              if (option->value.list.value[i].s)
                              {
                                    free(option->value.list.value[i].s);
                                    option->value.list.value[i].s = NULL;
                              }
                        }
                  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 = NULL;
            }

            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]);
            default:
                  break;
            }

            option->value.list.value[i] = o.value;
      }

      return status;
}

Bool
getBoolOptionNamed(CompOption * option,
                           int nOption, 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, 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, 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, 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,
                                                      char *name, unsigned short *defaultValue)
{
      while (nOption--)
      {
            if (option->type == CompOptionTypeColor)
                  if (strcmp(option->name, name) == 0)
                        return option->value.c;

            option++;
      }

      return defaultValue;
}

static char *stringAppend(char *s, char *a)
{
      char *r;
      int len;

      len = strlen(a);

      if (s)
            len += strlen(s);

      r = 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;
}

char *keyBindingToString(CompDisplay * d, CompKeyBinding * key)
{
      char *binding;

      binding = modifiersToString(d, key->modifiers);

      if (key->keysym != 0)
      {
            char *keyname;

            keyname = XKeysymToString(key->keysym);

            if (keyname)
            {
                  binding = stringAppend(binding, keyname);
            }

            return binding;
      }
      return "Disabled";
}

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;
}

static unsigned int stringToModifiers(CompDisplay * d, const char *binding)
{
      unsigned int mods = 0;
      int i;

      for (i = 0; i < N_MODIFIERS; i++)
      {
            if (strcasestr(binding, modifiers[i].name))
                  mods |= modifiers[i].modifier;
      }

      return mods;
}

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++;

      keysym = XStringToKeysym(binding);
      if (keysym != NoSymbol)
      {
            key->keysym = keysym;
            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;
}

char *edgeToString(unsigned int edge)
{
      return edgeName[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);
}

char *optionTypeToString(CompOptionType type)
{
      switch (type)
      {
      case CompOptionTypeAction:
            return "action";
      case CompOptionTypeBool:
            return "bool";
      case CompOptionTypeInt:
            return "int";
      case CompOptionTypeFloat:
            return "float";
      case CompOptionTypeString:
            return "string";
      case CompOptionTypeColor:
            return "color";
      case CompOptionTypeList:
            return "list";
      }

      return "unknown";
}

Bool compSetOption(CompDisplay *display, CompOption *option, CompOptionValue *value)
{
      switch (option->type) {
      case CompOptionTypeAction:
            return setDisplayAction(display, option, value);
      case CompOptionTypeBool:
            return compSetBoolOption(option, value);
      case CompOptionTypeFloat:
            return compSetFloatOption(option, value);
      case CompOptionTypeInt:
            return compSetIntOption(option, value);
      case CompOptionTypeList:
            return compSetOptionList(option, value);
      case CompOptionTypeString:
            return compSetStringOption(option, value);
      default:
            return FALSE;
      }
}

Generated by  Doxygen 1.6.0   Back to index