rendered paste bodydiff --git a/plugins/ini.c b/plugins/ini.c
index a8696dc..2441e99 100644
--- a/plugins/ini.c
+++ b/plugins/ini.c
@@ -52,6 +52,9 @@
static int displayPrivateIndex;
+/*
+ * IniFileData
+ */
typedef struct _IniFileData IniFileData;
struct _IniFileData {
char *filename;
@@ -65,20 +68,9 @@ struct _IniFileData {
IniFileData *prev;
};
-#define N_ACTION_PARTS 5
-typedef struct _IniActionProxy {
- int nSet;
-
- CompBindingType type;
- CompKeyBinding key;
- CompButtonBinding button;
-
- Bool bell;
-
- unsigned int edgeMask;
- int edgeButton;
-} IniActionProxy;
-
+/*
+ * IniDisplay
+ */
typedef struct _IniDisplay {
int screenPrivateIndex;
@@ -91,30 +83,60 @@ typedef struct _IniDisplay {
IniFileData *fileData;
} IniDisplay;
+/*
+ * IniScreeen
+ */
typedef struct _IniScreen {
InitPluginForScreenProc initPluginForScreen;
SetScreenOptionProc setScreenOption;
SetScreenOptionForPluginProc setScreenOptionForPlugin;
} IniScreen;
-static void
-initActionProxy (IniActionProxy *a)
-{
- a->type = 0;
-
- a->nSet = 0;
-
- a->key.keycode = 0;
- a->key.modifiers = 0;
+/*
+ * IniAction
+ */
+static char * validActionTypes[] = {
+ "key",
+ "button",
+ "bell",
+ "edge",
+ "edgebutton"};
+
+#define ACTION_VALUE_KEY (1 << 0)
+#define ACTION_VALUE_BUTTON (1 << 1)
+#define ACTION_VALUE_BELL (1 << 2)
+#define ACTION_VALUE_EDGE (1 << 3)
+#define ACTION_VALUE_EDGEBUTTON (1 << 4)
+#define ACTION_VALUES_ALL \
+ ( ACTION_VALUE_KEY \
+ | ACTION_VALUE_BUTTON \
+ | ACTION_VALUE_BELL \
+ | ACTION_VALUE_EDGE \
+ | ACTION_VALUE_EDGEBUTTON )
+
+static int actionValueMasks[] = {
+ ACTION_VALUE_KEY,
+ ACTION_VALUE_BUTTON,
+ ACTION_VALUE_BELL,
+ ACTION_VALUE_EDGE,
+ ACTION_VALUE_EDGEBUTTON
+};
- a->button.button = 0;
- a->button.modifiers = 0;
+enum {
+ ACTION_TYPE_KEY = 0,
+ ACTION_TYPE_BUTTON,
+ ACTION_TYPE_BELL,
+ ACTION_TYPE_EDGE,
+ ACTION_TYPE_EDGEBUTTON,
+ ACTION_TYPES_NUM
+};
- a->bell = FALSE;
+typedef struct _IniAction {
+ char *realOptionName;
+ unsigned int valueMasks;
+ CompAction a;
+} IniAction;
- a->edgeMask = 0;
- a->edgeButton = 0;
-}
static IniFileData *
iniGetFileDataFromFilename (CompDisplay *d,
@@ -471,6 +493,135 @@ iniMakeDirectories (void)
}
static Bool
+findActionType(char *optionName, int *type)
+{
+ char * optionType = strrchr(optionName, '_');
+ if (!optionType)
+ return FALSE;
+
+ optionType++; // skip the '_'
+
+ int i;
+ for (i = 0; i < ACTION_TYPES_NUM; i++)
+ {
+ if (strcmp(optionType, validActionTypes[i]) == 0)
+ {
+ if (type)
+ *type = i;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static Bool
+parseAction(CompDisplay *d, char *optionName, char *optionValue, IniAction *action)
+{
+ int type;
+ if (!findActionType(optionName, &type))
+ return FALSE; // no action, exit the loop
+
+ // we have a new action
+ if (!action->realOptionName)
+ {
+ char *optionType = strrchr(optionName, '_');
+ // chars until the last "_"
+ int len = strlen(optionName) - strlen(optionType);
+
+ action->realOptionName = malloc(sizeof(char)*(len+1));
+ strncpy(action->realOptionName, optionName, len);
+ action->realOptionName[len] = '\0';
+
+ // make sure all defaults are set
+ action->a.type = 0;
+ action->a.key.keycode = 0;
+ action->a.key.modifiers = 0;
+ action->a.button.button = 0;
+ action->a.button.modifiers = 0;
+ action->a.bell = FALSE;
+ action->a.edgeMask = 0;
+ action->a.edgeButton = 0;
+ }
+ // detect a new option (might happen when the options are incomplete)
+ else if (action->valueMasks != ACTION_VALUES_ALL)
+ {
+ char *optionType = strrchr(optionName, '_');
+ // chars until the last "_"
+ int len = strlen(optionName) - strlen(optionType);
+
+ char *realOptionName = malloc(sizeof(char)*(len+1));
+ strncpy(realOptionName, optionName, len);
+ realOptionName[len] = '\0';
+
+ if (strcmp(action->realOptionName, realOptionName) != 0) {
+ free(realOptionName);
+ return FALSE;
+ }
+
+ free(realOptionName);
+ }
+
+ int i, j;
+ CompListValue edges;
+ switch (type)
+ {
+ case ACTION_TYPE_KEY:
+ if (optionValue[0] != '\0' &&
+ strcasecmp(optionValue, "disabled") != 0 &&
+ stringToKeyBinding (d, optionValue, &action->a.key))
+ action->a.type |= CompBindingTypeKey;
+ break;
+
+ case ACTION_TYPE_BUTTON:
+ if (optionValue[0] != '\0' &&
+ strcasecmp(optionValue, "disabled") != 0 &&
+ stringToButtonBinding (d, optionValue, &action->a.button))
+ action->a.type |= CompBindingTypeButton;
+ break;
+
+ case ACTION_TYPE_BELL:
+ action->a.bell = (Bool) atoi(optionValue);
+ break;
+
+ case ACTION_TYPE_EDGE:
+ if (optionValue[0] != '\0' &&
+ csvToList (optionValue, &edges, CompOptionTypeString))
+ {
+ for (i = 0; i < edges.nValue; i++) {
+ for (j = 0; j < SCREEN_EDGE_NUM; j++) {
+ if (strcasecmp (edges.value[i].s, edgeToString(j)) == 0)
+ {
+ action->a.edgeMask |= (1 << j);
+
+ // found corresponding mask, next value
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case ACTION_TYPE_EDGEBUTTON:
+ action->a.edgeButton = atoi(optionValue);
+ if (action->a.edgeButton != 0)
+ action->a.type |= CompBindingTypeEdgeButton;
+ break;
+
+ default:
+ break;
+ }
+
+ action->valueMasks |= actionValueMasks[type];
+
+ // no need to read any further since all value are set
+ if (action->valueMasks == ACTION_VALUES_ALL)
+ return FALSE;
+
+ return TRUE; // continue loop, not finished parsing yet
+}
+
+static Bool
iniLoadOptionsFromFile (CompDisplay *d,
FILE *optionFile,
char *plugin,
@@ -478,9 +629,6 @@ iniLoadOptionsFromFile (CompDisplay *d,
{
char *optionName = NULL;
char *optionValue = NULL;
- char *actionTest = NULL;
- char *actionTmp = NULL;
- char *realOption = NULL;
char tmp[MAX_OPTION_LENGTH];
CompOption *option = NULL, *o;
int nOption;
@@ -534,10 +682,9 @@ iniLoadOptionsFromFile (CompDisplay *d,
option = compGetDisplayOptions (d, &nOption);
}
- IniActionProxy actionProxy;
-
- initActionProxy (&actionProxy);
-
+ IniAction action;
+ action.realOptionName = NULL;
+ Bool continueReading = FALSE;
while (fgets (&tmp[0], MAX_OPTION_LENGTH, optionFile) != NULL)
{
status = FALSE;
@@ -554,42 +701,6 @@ iniLoadOptionsFromFile (CompDisplay *d,
o = compFindOption (option, nOption, optionName, 0);
if (o)
{
- if (actionProxy.nSet != 0)
- {
- /* there is an action where a line is
- missing / out of order. realOption
- should still be set from the last loop */
-
- value.action.type = actionProxy.type;
- value.action.key = actionProxy.key;
- value.action.button = actionProxy.button;
- value.action.bell = actionProxy.bell;
- value.action.edgeMask = actionProxy.edgeMask;
- value.action.edgeButton = actionProxy.edgeButton;
-
- if (plugin && p)
- {
- if (s)
- status = (*s->setScreenOptionForPlugin) (s,
- plugin,
- realOption,
- &value);
- else
- status = (*d->setDisplayOptionForPlugin) (d, plugin,
- realOption,
- &value);
- }
- else
- {
- if (s)
- status = (*s->setScreenOption) (s, realOption, &value);
- else
- status = (*d->setDisplayOption) (d, realOption, &value);
- }
-
- initActionProxy (&actionProxy);
- }
-
value = o->value;
switch (o->type)
@@ -656,147 +767,61 @@ iniLoadOptionsFromFile (CompDisplay *d,
}
else
{
- /* option not found, it might be an action option */
- actionTmp = strchr (optionName, '_');
- if (actionTmp)
+ // an action has several values, so we need
+ // to read more then one line into our buffer
+ continueReading = parseAction(d, optionName, optionValue, &action);
+ }
+
+ // parsing action finished, write it
+ if (action.realOptionName &&
+ !continueReading)
+ {
+ o = compFindOption (option, nOption, action.realOptionName, 0);
+ value = o->value;
+
+ value.action.type = action.a.type;
+ value.action.key = action.a.key;
+ value.action.button = action.a.button;
+ value.action.bell = action.a.bell;
+ value.action.edgeMask = action.a.edgeMask;
+ value.action.edgeButton = action.a.edgeButton;
+
+ if (plugin)
{
- actionTmp++; /* skip the _ */
- actionTest = strchr (actionTmp, '_');
- while (actionTest)
- {
- actionTmp++;
- actionTest = strchr (actionTmp, '_');
- if (actionTest)
- actionTmp = strchr (actionTmp, '_');
- }
+ if (s)
+ status = (*s->setScreenOptionForPlugin) (s, plugin, action.realOptionName, &value);
+ else
+ status = (*d->setDisplayOptionForPlugin) (d, plugin, action.realOptionName, &value);
+ }
+ else
+ {
+ if (s)
+ status = (*s->setScreenOption) (s, action.realOptionName, &value);
+ else
+ status = (*d->setDisplayOption) (d, action.realOptionName, &value);
+ }
- if (actionTmp)
- {
- /* find the real option */
- int len = strlen (optionName) - strlen (actionTmp) - 1;
- realOption = realloc (realOption, sizeof (char) * len);
- strncpy (realOption, optionName, len);
- realOption[len] = '\0';
- o = compFindOption (option, nOption, realOption, 0);
-
- if (o)
- {
- value = o->value;
-
- if (strcmp (actionTmp, "key") == 0)
- {
- if (!*optionValue ||
- strcasecmp (optionValue, "disabled") == 0)
- {
- actionProxy.type &= ~CompBindingTypeKey;
- }
- else
- {
- if (stringToKeyBinding (d,
- optionValue,
- &actionProxy.key))
- actionProxy.type |= CompBindingTypeKey;
- }
- actionProxy.nSet++;
- }
- else if (strcmp (actionTmp, "button") == 0)
- {
- if (!*optionValue ||
- strcasecmp (optionValue, "disabled") == 0)
- {
- actionProxy.type &= ~CompBindingTypeButton;
- }
- else
- {
- if (stringToButtonBinding (d, optionValue,
- &actionProxy.button))
- actionProxy.type |= CompBindingTypeButton;
- }
- actionProxy.nSet++;
- }
- else if (strcmp (actionTmp, "edge") == 0)
- {
- actionProxy.edgeMask = 0;
- if (optionValue[0] != '\0')
- {
- int i, e;
- CompListValue edges;
-
- if (csvToList (optionValue, &edges, CompOptionTypeString))
- {
- for (i = 0; i < SCREEN_EDGE_NUM; i++)
- {
- for (e=0; e<edges.nValue; e++)
- {
- if (strcasecmp (edges.value[e].s, edgeToString (i)) == 0)
- actionProxy.edgeMask |= 1 << i;
- }
- }
- }
- }
- actionProxy.nSet++;
- }
- else if (strcmp (actionTmp, "edgebutton") == 0)
- {
- actionProxy.edgeButton = atoi (optionValue);
-
- if (actionProxy.edgeButton)
- actionProxy.type |= CompBindingTypeEdgeButton;
- else
- actionProxy.type &= ~CompBindingTypeEdgeButton;
-
- actionProxy.nSet++;
- }
- else if (strcmp (actionTmp, "bell") == 0)
- {
- actionProxy.bell = (Bool) atoi (optionValue);
- actionProxy.nSet++;
- }
-
- if (actionProxy.nSet >= N_ACTION_PARTS)
- {
- value.action.type = actionProxy.type;
- value.action.key = actionProxy.key;
- value.action.button = actionProxy.button;
- value.action.bell = actionProxy.bell;
- value.action.edgeMask = actionProxy.edgeMask;
- value.action.edgeButton = actionProxy.edgeButton;
-
- if (plugin)
- {
- if (s)
- status = (*s->setScreenOptionForPlugin) (s,
- plugin,
- realOption,
- &value);
- else
- status = (*d->setDisplayOptionForPlugin) (d, plugin,
- realOption,
- &value);
- }
- else
- {
- if (s)
- status = (*s->setScreenOption) (s, realOption, &value);
- else
- status = (*d->setDisplayOption) (d, realOption, &value);
- }
-
- initActionProxy (&actionProxy);
- }
- }
- }
+ // clear the buffer
+ free(action.realOptionName);
+ action.realOptionName = NULL;
+
+ // we missed the current line because we exited it in the first call
+ if (!o && action.valueMasks == ACTION_VALUES_ALL) {
+ action.valueMasks = 0;
+ parseAction(d, optionName, optionValue, &action);
+ } else {
+ action.valueMasks = 0;
}
}
}
- }
- if (optionName)
- free (optionName);
- if (optionValue)
- free (optionValue);
- if (realOption)
- free (realOption);
+ // clear up
+ if (optionName)
+ free (optionName);
+ if (optionValue)
+ free (optionValue);
+ continueReading = FALSE;
+ }
return TRUE;
}