/*
* Animation plugin for compiz/beryl
*
* animation.c
*
* Copyright : (C) 2006 Erkin Bahceci
* E-mail : erkinbah@gmail.com
*
* Based on Wobbly and Minimize plugins by
* : David Reveman
* E-mail : davidr@novell.com>
*
* 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.
*/
#include "animation-internal.h"
// ================= Option Related Functions =================
CompOptionValue *
animGetOptVal(AnimScreen *as,
AnimWindow *aw,
int optionId)
{
OptionSet *os =
&as->eventOptionSets[aw->curWindowEvent]->sets[aw->curAnimSelectionRow];
IdValuePair *pair = os->pairs;
int i;
for (i = 0; i < os->nPairs; i++, pair++)
if (pair->id == optionId)
return &pair->value;
return &as->opt[optionId].value;
}
inline Bool
animGetB(AnimScreen *as,
AnimWindow *aw,
int optionId)
{
return animGetOptVal(as, aw, optionId)->b;
}
inline int
animGetI(AnimScreen *as,
AnimWindow *aw,
int optionId)
{
return animGetOptVal(as, aw, optionId)->i;
}
inline float
animGetF(AnimScreen *as,
AnimWindow *aw,
int optionId)
{
return animGetOptVal(as, aw, optionId)->f;
}
inline char *
animGetS(AnimScreen *as,
AnimWindow *aw,
int optionId)
{
return animGetOptVal(as, aw, optionId)->s;
}
inline unsigned short *
animGetC(AnimScreen *as,
AnimWindow *aw,
int optionId)
{
return animGetOptVal(as, aw, optionId)->c;
}
static
void freeSingleEventOptionSets(OptionSets *oss)
{
int j;
for (j = 0; j < oss->nSets; j++)
if (oss->sets[j].pairs)
free(oss->sets[j].pairs);
free (oss->sets);
oss->sets = NULL;
}
void
freeAllOptionSets(OptionSets **eventsOss)
{
int i;
for (i = 0; i < NUM_EVENTS; i++)
{
OptionSets *oss = eventsOss[i];
if (!oss->sets)
continue;
freeSingleEventOptionSets(oss);
}
free (eventsOss[WindowEventOpen]);
free (eventsOss[WindowEventClose]);
free (eventsOss[WindowEventMinimize]);
free (eventsOss[WindowEventFocus]);
free (eventsOss[WindowEventShade]);
for (i = 0; i < NUM_EVENTS; i++)
eventsOss[i] = NULL;
}
static void
updateOptionSet(CompScreen *s, OptionSet *os, char *optNamesValuesOrig)
{
ANIM_SCREEN(s);
int len = strlen(optNamesValuesOrig);
char *optNamesValues = calloc(len + 1, 1);
// Find the first substring with no spaces in it
sscanf(optNamesValuesOrig, " %s ", optNamesValues);
if (strlen(optNamesValues) == 0)
{
free(optNamesValues);
return;
}
// Backup original, since strtok is destructive
strcpy(optNamesValues, optNamesValuesOrig);
char *name;
char *nameTrimmed = calloc(len + 1, 1);
char *valueStr = NULL;
char *betweenPairs = ",";
char *betweenOptVal = "=";
// Count number of pairs
char *pairToken = optNamesValuesOrig;
int nPairs = 1;
while ((pairToken = strchr(pairToken, betweenPairs[0])))
{
pairToken++; // skip delimiter
nPairs++;
}
if (os->pairs)
free(os->pairs);
os->pairs = calloc(nPairs, sizeof(IdValuePair));
if (!os->pairs)
{
os->nPairs = 0;
free(optNamesValues);
free(nameTrimmed);
compLogMessage (s->display, "animation", CompLogLevelError,
"Not enough memory");
return;
}
os->nPairs = nPairs;
// Tokenize pairs
name = strtok(optNamesValues, betweenOptVal);
int errorNo = -1;
int i;
for (i = 0; name && i < nPairs; i++)
{
errorNo = 0;
if (strchr(name, betweenPairs[0])) // handle "a, b=4" case
{
errorNo = 1;
break;
}
sscanf(name, " %s ", nameTrimmed);
if (strlen(nameTrimmed) == 0)
{
errorNo = 2;
break;
}
valueStr = strtok(NULL, betweenPairs);
if (!valueStr)
{
errorNo = 3;
break;
}
CompOption *o;
int j;
// Skip non-effect options
for (j = 0; j < ANIM_SCREEN_OPTION_NUM; j++)
{
o = &as->opt[j];
if (strcasecmp(nameTrimmed, o->name) == 0)
break;
}
if (j == ANIM_SCREEN_OPTION_NUM) // no match
{
errorNo = 4;
break;
}
else if (j < NUM_NONEFFECT_OPTIONS)
{
errorNo = 5;
break;
}
CompOptionValue v;
os->pairs[i].id = j;
int valueRead = -1;
switch (o->type)
{
case CompOptionTypeBool:
valueRead = sscanf(valueStr, " %d ", &os->pairs[i].value.b);
break;
case CompOptionTypeInt:
valueRead = sscanf(valueStr, " %d ", &v.i);
if (valueRead > 0)
{
// Store option's original value
int backup = o->value.i;
if (compSetIntOption (o, &v))
os->pairs[i].value = v;
else
errorNo = 7;
// Restore value
o->value.i = backup;
}
break;
case CompOptionTypeFloat:
valueRead = sscanf(valueStr, " %f ", &v.f);
if (valueRead > 0)
{
// Store option's original value
float backup = o->value.f;
if (compSetFloatOption (o, &v))
os->pairs[i].value = v;
else
errorNo = 7;
// Restore value
o->value.f = backup;
}
break;
case CompOptionTypeString:
v.s = calloc (strlen(valueStr) + 1, 1); // TODO: not freed
if (!v.s)
{
compLogMessage (s->display, "animation", CompLogLevelError,
"Not enough memory");
return;
}
strcpy(v.s, valueStr);
valueRead = 1;
break;
case CompOptionTypeColor:
{
unsigned int c[4];
valueRead = sscanf (valueStr, " #%2x%2x%2x%2x ",
&c[0], &c[1], &c[2], &c[3]);
if (valueRead == 4)
{
CompOptionValue * pv = &os->pairs[i].value;
int j;
for (j = 0; j < 4; j++)
pv->c[j] = c[j] << 8 | c[j];
}
else
errorNo = 6;
break;
}
default:
break;
}
if (valueRead == 0)
errorNo = 6;
if (errorNo > 0)
break;
// If valueRead is -1 here, then it must be a
// non-(int/float/string) option, which is not supported yet.
// Such an option doesn't currently exist anyway.
errorNo = -1;
name = strtok(NULL, betweenOptVal);
}
if (i < nPairs)
{
switch (errorNo)
{
case -1:
case 2:
compLogMessage (s->display, "animation", CompLogLevelError,
"Option name missing in \"%s\"",
optNamesValuesOrig);
break;
case 1:
case 3:
compLogMessage (s->display, "animation", CompLogLevelError,
"Option value missing in \"%s\"",
optNamesValuesOrig);
break;
case 4:
compLogMessage (s->display, "animation", CompLogLevelError,
"Unknown option \"%s\" in \"%s\"",
nameTrimmed, optNamesValuesOrig);
break;
case 5:
compLogMessage (s->display, "animation", CompLogLevelError,
"Option \"%s\" cannot be changed in option strings.",
nameTrimmed);
break;
case 6:
compLogMessage (s->display, "animation", CompLogLevelError,
"Invalid value \"%s\" in \"%s\"",
valueStr, optNamesValuesOrig);
break;
case 7:
compLogMessage (s->display, "animation", CompLogLevelError,
"Value \"%s\" out of range in \"%s\"",
valueStr, optNamesValuesOrig);
break;
default:
break;
}
free(os->pairs);
os->pairs = 0;
os->nPairs = 0;
}
free(optNamesValues);
free(nameTrimmed);
}
void
updateOptionSets(CompScreen *s,
OptionSets *oss,
CompListValue *listVal)
{
int n = listVal->nValue;
if (oss->sets)
freeSingleEventOptionSets(oss);
oss->sets = calloc(n, sizeof(OptionSet));
if (!oss->sets)
{
compLogMessage (s->display, "animation", CompLogLevelError,
"Not enough memory");
return;
}
oss->nSets = n;
int i;
for (i = 0; i < n; i++)
updateOptionSet(s, &oss->sets[i], listVal->value[i].s);
}
syntax highlighted by Code2HTML, v. 0.9.1