672 lines
15 KiB
C
672 lines
15 KiB
C
/*
|
|
* Copyright (C) 2000-2005 Carsten Haitzler, Geoff Harrison and various contributors
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to
|
|
* deal in the Software without restriction, including without limitation the
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies of the Software, its documentation and marketing & publicity
|
|
* materials, and acknowledgment shall be given in the documentation, materials
|
|
* and software packages that this Software was used.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
#include "E.h"
|
|
#include "conf.h"
|
|
|
|
void
|
|
CreateCurve(ModCurve * c)
|
|
{
|
|
int i, j, cx, v1, v2, val, dist;
|
|
|
|
if (!c)
|
|
return;
|
|
|
|
if (c->num == 0)
|
|
{
|
|
for (i = 0; i < 256; i++)
|
|
c->map[i] = i;
|
|
return;
|
|
}
|
|
|
|
cx = 0;
|
|
c->map[cx++] = c->py[0];
|
|
|
|
for (i = 1; i < c->num; i++)
|
|
{
|
|
v1 = c->py[i - 1];
|
|
v2 = c->py[i];
|
|
dist = c->px[i] - c->px[i - 1];
|
|
if (dist < 2)
|
|
{
|
|
c->map[cx++] = v2;
|
|
}
|
|
else
|
|
{
|
|
for (j = 0; j < dist; j++)
|
|
{
|
|
val = ((v2 * j) + (v1 * (dist - j - 1))) / (dist - 1);
|
|
c->map[cx++] = (unsigned char)val;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
FreeModCurve(ModCurve * c)
|
|
{
|
|
if (!c)
|
|
return;
|
|
|
|
Efree(c->px);
|
|
Efree(c->py);
|
|
}
|
|
|
|
void
|
|
FreeCMClass(ColorModifierClass * cm)
|
|
{
|
|
if (!cm)
|
|
return;
|
|
|
|
if (cm->ref_count > 0)
|
|
{
|
|
DialogOK(_("ColorModClass Error!"), _("%u references remain\n"),
|
|
cm->ref_count);
|
|
return;
|
|
}
|
|
|
|
while (RemoveItemByPtr(cm, LIST_TYPE_COLORMODIFIER));
|
|
|
|
Efree(cm->name);
|
|
FreeModCurve(&(cm->red));
|
|
FreeModCurve(&(cm->green));
|
|
FreeModCurve(&(cm->blue));
|
|
}
|
|
|
|
ColorModifierClass *
|
|
CreateCMClass(char *name, int rnum, unsigned char *rpx,
|
|
unsigned char *rpy, int gnum,
|
|
unsigned char *gpx, unsigned char *gpy,
|
|
int bnum, unsigned char *bpx, unsigned char *bpy)
|
|
{
|
|
ColorModifierClass *cm;
|
|
|
|
cm = Emalloc(sizeof(ColorModifierClass));
|
|
if (!cm)
|
|
return NULL;
|
|
|
|
cm->name = Estrdup(name);
|
|
cm->red.px = NULL;
|
|
cm->red.py = NULL;
|
|
cm->green.px = NULL;
|
|
cm->green.py = NULL;
|
|
cm->blue.px = NULL;
|
|
cm->blue.py = NULL;
|
|
cm->ref_count = 0;
|
|
|
|
if (rnum < 2)
|
|
{
|
|
cm->red.num = 0;
|
|
}
|
|
else
|
|
{
|
|
cm->red.num = rnum;
|
|
cm->red.px = Emalloc(rnum);
|
|
memcpy(cm->red.px, rpx, rnum);
|
|
cm->red.py = Emalloc(rnum);
|
|
memcpy(cm->red.py, rpy, rnum);
|
|
}
|
|
|
|
if (gnum < 2)
|
|
{
|
|
cm->green.num = 0;
|
|
}
|
|
else
|
|
{
|
|
cm->green.num = gnum;
|
|
cm->green.px = Emalloc(gnum);
|
|
memcpy(cm->green.px, gpx, gnum);
|
|
cm->green.py = Emalloc(gnum);
|
|
memcpy(cm->green.py, gpy, gnum);
|
|
}
|
|
|
|
if (bnum < 2)
|
|
{
|
|
cm->blue.num = 0;
|
|
}
|
|
else
|
|
{
|
|
cm->blue.num = bnum;
|
|
cm->blue.px = Emalloc(bnum);
|
|
memcpy(cm->blue.px, bpx, bnum);
|
|
cm->blue.py = Emalloc(bnum);
|
|
memcpy(cm->blue.py, bpy, bnum);
|
|
}
|
|
|
|
CreateCurve(&(cm->red));
|
|
CreateCurve(&(cm->green));
|
|
CreateCurve(&(cm->blue));
|
|
|
|
return cm;
|
|
}
|
|
|
|
int
|
|
ColorModifierConfigLoad(FILE * fs)
|
|
{
|
|
int err = 0;
|
|
char s[FILEPATH_LEN_MAX];
|
|
char s2[FILEPATH_LEN_MAX];
|
|
int i1;
|
|
char *name = NULL;
|
|
const char *params = NULL;
|
|
const char *current_param = NULL;
|
|
unsigned char *rx = NULL;
|
|
unsigned char *ry = NULL;
|
|
unsigned char *gx = NULL;
|
|
unsigned char *gy = NULL;
|
|
unsigned char *bx = NULL;
|
|
unsigned char *by = NULL;
|
|
int i = 0, tx, ty;
|
|
int rnum = 0, gnum = 0, bnum = 0;
|
|
ColorModifierClass *cm;
|
|
int fields;
|
|
|
|
while (GetLine(s, sizeof(s), fs))
|
|
{
|
|
s2[0] = 0;
|
|
i = 0;
|
|
i1 = CONFIG_INVALID;
|
|
fields = sscanf(s, "%i %4000s", &i1, s2);
|
|
|
|
if (fields < 1)
|
|
{
|
|
i1 = CONFIG_INVALID;
|
|
}
|
|
else if (i1 == CONFIG_CLOSE)
|
|
{
|
|
if (fields != 1)
|
|
{
|
|
RecoverUserConfig();
|
|
Alert(_("CONFIG: ignoring extra data in \"%s\"\n"), s);
|
|
}
|
|
}
|
|
else if (i1 != CONFIG_INVALID)
|
|
{
|
|
if (fields != 2)
|
|
{
|
|
RecoverUserConfig();
|
|
Alert(_("CONFIG: missing required data in \"%s\"\n"), s);
|
|
}
|
|
}
|
|
switch (i1)
|
|
{
|
|
case CONFIG_CLOSE:
|
|
cm = (ColorModifierClass *) FindItem(name, 0, LIST_FINDBY_NAME,
|
|
LIST_TYPE_COLORMODIFIER);
|
|
if (cm)
|
|
{
|
|
ModifyCMClass(name, rnum, rx, ry, gnum, gx, gy, bnum, bx, by);
|
|
}
|
|
else
|
|
{
|
|
cm = CreateCMClass(name, rnum, rx, ry, gnum, gx, gy, bnum,
|
|
bx, by);
|
|
AddItem(cm, cm->name, 0, LIST_TYPE_COLORMODIFIER);
|
|
}
|
|
goto done;
|
|
case CONFIG_CLASSNAME:
|
|
if (ConfigSkipIfExists(fs, s2, LIST_TYPE_COLORMODIFIER))
|
|
goto done;
|
|
name = Estrdup(s2);
|
|
break;
|
|
case COLORMOD_RED:
|
|
params = atword(s, 2);
|
|
current_param = params;
|
|
if (!current_param)
|
|
goto done;
|
|
do
|
|
{
|
|
while (*current_param == ' ')
|
|
current_param++;
|
|
if (rx)
|
|
{
|
|
rx = Erealloc(rx, sizeof(unsigned char) * (i + 1));
|
|
ry = Erealloc(ry, sizeof(unsigned char) * (i + 1));
|
|
}
|
|
else
|
|
{
|
|
rx = Emalloc(sizeof(unsigned char));
|
|
ry = Emalloc(sizeof(unsigned char));
|
|
}
|
|
if (strstr(current_param, ","))
|
|
*(strstr(current_param, ",")) = ' ';
|
|
sscanf(current_param, "%i %i", &tx, &ty);
|
|
rx[i] = (unsigned char)tx;
|
|
ry[i++] = (unsigned char)ty;
|
|
current_param = strstr(current_param, " ") + 1;
|
|
current_param = strstr(current_param, " ");
|
|
}
|
|
while ((current_param)
|
|
&& (current_param = strstr(current_param, " "))
|
|
&& (current_param));
|
|
rnum = i;
|
|
break;
|
|
case COLORMOD_GREEN:
|
|
params = atword(s, 2);
|
|
current_param = params;
|
|
if (!current_param)
|
|
goto done;
|
|
do
|
|
{
|
|
while (*current_param == ' ')
|
|
current_param++;
|
|
if (gx)
|
|
{
|
|
gx = Erealloc(gx, sizeof(unsigned char) * (i + 1));
|
|
gy = Erealloc(gy, sizeof(unsigned char) * (i + 1));
|
|
}
|
|
else
|
|
{
|
|
gx = Emalloc(sizeof(unsigned char));
|
|
gy = Emalloc(sizeof(unsigned char));
|
|
}
|
|
if (strstr(current_param, ","))
|
|
*(strstr(current_param, ",")) = ' ';
|
|
sscanf(current_param, "%i %i", &tx, &ty);
|
|
gx[i] = (unsigned char)tx;
|
|
gy[i++] = (unsigned char)ty;
|
|
current_param = strstr(current_param, " ") + 1;
|
|
current_param = strstr(current_param, " ");
|
|
}
|
|
while ((current_param)
|
|
&& (current_param = strstr(current_param, " "))
|
|
&& (current_param));
|
|
gnum = i;
|
|
break;
|
|
case COLORMOD_BLUE:
|
|
params = atword(s, 2);
|
|
current_param = params;
|
|
if (!current_param)
|
|
goto done;
|
|
do
|
|
{
|
|
while (*current_param == ' ')
|
|
current_param++;
|
|
if (bx)
|
|
{
|
|
bx = Erealloc(bx, sizeof(unsigned char) * (i + 1));
|
|
by = Erealloc(by, sizeof(unsigned char) * (i + 1));
|
|
}
|
|
else
|
|
{
|
|
bx = Emalloc(sizeof(unsigned char));
|
|
by = Emalloc(sizeof(unsigned char));
|
|
}
|
|
if (strstr(current_param, ","))
|
|
*(strstr(current_param, ",")) = ' ';
|
|
sscanf(current_param, "%i %i", &tx, &ty);
|
|
bx[i] = (unsigned char)tx;
|
|
by[i++] = (unsigned char)ty;
|
|
current_param = strstr(current_param, " ") + 1;
|
|
current_param = strstr(current_param, " ");
|
|
}
|
|
while ((current_param)
|
|
&& (current_param = strstr(current_param, " "))
|
|
&& (current_param));
|
|
bnum = i;
|
|
break;
|
|
default:
|
|
RecoverUserConfig();
|
|
Alert(_("Warning: unable to determine what to do with\n"
|
|
"the following text in the middle of current "
|
|
" ColorModifier definition:\n"
|
|
"%s\nWill ignore and continue...\n"), s);
|
|
break;
|
|
}
|
|
}
|
|
err = -1;
|
|
|
|
done:
|
|
if (name)
|
|
Efree(name);
|
|
if (rx)
|
|
Efree(rx);
|
|
if (ry)
|
|
Efree(ry);
|
|
if (gx)
|
|
Efree(gx);
|
|
if (gy)
|
|
Efree(gy);
|
|
if (bx)
|
|
Efree(bx);
|
|
if (by)
|
|
Efree(by);
|
|
|
|
return err;
|
|
}
|
|
|
|
void
|
|
ModifyCMClass(char *name, int rnum, unsigned char *rpx, unsigned char *rpy,
|
|
int gnum, unsigned char *gpx, unsigned char *gpy, int bnum,
|
|
unsigned char *bpx, unsigned char *bpy)
|
|
{
|
|
ColorModifierClass *cm;
|
|
|
|
cm = (ColorModifierClass *) FindItem(name, 0, LIST_FINDBY_NAME,
|
|
LIST_TYPE_COLORMODIFIER);
|
|
if (!cm)
|
|
return;
|
|
|
|
if (cm->red.px)
|
|
Efree(cm->red.px);
|
|
if (cm->red.py)
|
|
Efree(cm->red.py);
|
|
if (cm->green.px)
|
|
Efree(cm->green.px);
|
|
if (cm->green.py)
|
|
Efree(cm->green.py);
|
|
if (cm->blue.px)
|
|
Efree(cm->blue.px);
|
|
if (cm->blue.py)
|
|
Efree(cm->blue.py);
|
|
|
|
cm->red.px = NULL;
|
|
cm->red.py = NULL;
|
|
cm->green.px = NULL;
|
|
cm->green.py = NULL;
|
|
cm->blue.px = NULL;
|
|
cm->blue.py = NULL;
|
|
|
|
if (rnum < 2)
|
|
{
|
|
cm->red.num = 0;
|
|
}
|
|
else
|
|
{
|
|
cm->red.num = rnum;
|
|
cm->red.px = Emalloc(rnum);
|
|
memcpy(cm->red.px, rpx, rnum);
|
|
cm->red.py = Emalloc(rnum);
|
|
memcpy(cm->red.py, rpy, rnum);
|
|
}
|
|
|
|
if (gnum < 2)
|
|
{
|
|
cm->green.num = 0;
|
|
}
|
|
else
|
|
{
|
|
cm->green.num = gnum;
|
|
cm->green.px = Emalloc(gnum);
|
|
memcpy(cm->green.px, gpx, gnum);
|
|
cm->green.py = Emalloc(gnum);
|
|
memcpy(cm->green.py, gpy, gnum);
|
|
}
|
|
|
|
if (bnum < 2)
|
|
{
|
|
cm->blue.num = 0;
|
|
}
|
|
else
|
|
{
|
|
cm->blue.num = bnum;
|
|
cm->blue.px = Emalloc(bnum);
|
|
memcpy(cm->blue.px, bpx, bnum);
|
|
cm->blue.py = Emalloc(bnum);
|
|
memcpy(cm->blue.py, bpy, bnum);
|
|
}
|
|
|
|
CreateCurve(&(cm->red));
|
|
CreateCurve(&(cm->green));
|
|
CreateCurve(&(cm->blue));
|
|
}
|
|
|
|
#if 0 /* Unused */
|
|
|
|
static void
|
|
IPC_ColorModifierClass(const char *params, Client * c)
|
|
{
|
|
char buf[FILEPATH_LEN_MAX];
|
|
|
|
buf[0] = 0;
|
|
|
|
if (params)
|
|
{
|
|
char param1[FILEPATH_LEN_MAX];
|
|
char param2[FILEPATH_LEN_MAX];
|
|
char param3[FILEPATH_LEN_MAX];
|
|
|
|
param1[0] = 0;
|
|
param2[0] = 0;
|
|
param3[0] = 0;
|
|
|
|
word(params, 1, param1);
|
|
word(params, 2, param2);
|
|
if (param2[0])
|
|
{
|
|
if (!strcmp(param1, "create"))
|
|
{
|
|
}
|
|
else if (!strcmp(param2, "delete"))
|
|
{
|
|
ColorModifierClass *cm;
|
|
|
|
cm = (ColorModifierClass *) FindItem(param1, 0,
|
|
LIST_FINDBY_NAME,
|
|
LIST_TYPE_COLORMODIFIER);
|
|
if (cm)
|
|
FreeCMClass(cm);
|
|
}
|
|
else if (!strcmp(param2, "modify"))
|
|
{
|
|
}
|
|
else if (!strcmp(param2, "ref_count"))
|
|
{
|
|
ColorModifierClass *cm;
|
|
|
|
cm = (ColorModifierClass *) FindItem(param1, 0,
|
|
LIST_FINDBY_NAME,
|
|
LIST_TYPE_COLORMODIFIER);
|
|
if (cm)
|
|
Esnprintf(buf, sizeof(buf), "%u references remain.",
|
|
cm->ref_count);
|
|
}
|
|
else
|
|
{
|
|
Esnprintf(buf, sizeof(buf),
|
|
"Error: unknown operation specified");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Esnprintf(buf, sizeof(buf), "Error: no class specified");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Esnprintf(buf, sizeof(buf), "Error: no operation specified");
|
|
}
|
|
|
|
if (buf[0])
|
|
CommsSend(c, buf);
|
|
}
|
|
|
|
static void
|
|
IPC_ColormodifierDelete(const char *params, Client * c __UNUSED__)
|
|
{
|
|
char param1[FILEPATH_LEN_MAX], buf[FILEPATH_LEN_MAX];
|
|
ColorModifierClass *cm;
|
|
|
|
if (params == NULL)
|
|
return;
|
|
|
|
sscanf(params, "%1000s", param1);
|
|
cm = (ColorModifierClass *) FindItem(param1, 0, LIST_FINDBY_NAME,
|
|
LIST_TYPE_COLORMODIFIER);
|
|
Esnprintf(buf, sizeof(buf), "(null)");
|
|
if (cm)
|
|
FreeCMClass(cm);
|
|
}
|
|
|
|
static void
|
|
IPC_ColormodifierGet(const char *params, Client * c)
|
|
{
|
|
char param1[FILEPATH_LEN_MAX];
|
|
char buf[FILEPATH_LEN_MAX], buf2[FILEPATH_LEN_MAX];
|
|
ColorModifierClass *cm;
|
|
int i;
|
|
|
|
if (params == NULL)
|
|
return;
|
|
|
|
sscanf(params, "%1000s", param1);
|
|
cm = (ColorModifierClass *) FindItem(param1, 0, LIST_FINDBY_NAME,
|
|
LIST_TYPE_COLORMODIFIER);
|
|
Esnprintf(buf, sizeof(buf), "(null)");
|
|
if (cm)
|
|
{
|
|
Esnprintf(buf, sizeof(buf), "%i", (int)(cm->red.num));
|
|
for (i = 0; i < cm->red.num; i++)
|
|
{
|
|
Esnprintf(buf2, sizeof(buf2), " %i", (int)(cm->red.px[i]));
|
|
strcat(buf, buf2);
|
|
Esnprintf(buf2, sizeof(buf2), " %i", (int)(cm->red.py[i]));
|
|
strcat(buf, buf2);
|
|
}
|
|
Esnprintf(buf2, sizeof(buf2), "\n%i", (int)(cm->green.num));
|
|
strcat(buf, buf2);
|
|
for (i = 0; i < cm->green.num; i++)
|
|
{
|
|
Esnprintf(buf2, sizeof(buf2), " %i", (int)(cm->green.px[i]));
|
|
strcat(buf, buf2);
|
|
Esnprintf(buf2, sizeof(buf2), " %i", (int)(cm->green.py[i]));
|
|
strcat(buf, buf2);
|
|
}
|
|
Esnprintf(buf2, sizeof(buf2), "\n%i", (int)(cm->red.num));
|
|
strcat(buf, buf2);
|
|
for (i = 0; i < cm->blue.num; i++)
|
|
{
|
|
Esnprintf(buf2, sizeof(buf2), " %i", (int)(cm->blue.px[i]));
|
|
strcat(buf, buf2);
|
|
Esnprintf(buf2, sizeof(buf2), " %i", (int)(cm->blue.py[i]));
|
|
strcat(buf, buf2);
|
|
}
|
|
}
|
|
CommsSend(c, buf);
|
|
}
|
|
|
|
static void
|
|
IPC_ColormodifierSet(const char *params, Client * c __UNUSED__)
|
|
{
|
|
char w[FILEPATH_LEN_MAX];
|
|
ColorModifierClass *cm;
|
|
int i, j, k;
|
|
char *name;
|
|
int rnum = 0, gnum = 0, bnum = 0;
|
|
unsigned char *rpx = NULL, *rpy = NULL;
|
|
unsigned char *gpx = NULL, *gpy = NULL;
|
|
unsigned char *bpx = NULL, *bpy = NULL;
|
|
|
|
if (params == NULL)
|
|
return;
|
|
|
|
sscanf(params, "%1000s", w);
|
|
cm = (ColorModifierClass *) FindItem(w, 0, LIST_FINDBY_NAME,
|
|
LIST_TYPE_COLORMODIFIER);
|
|
name = Estrdup(w);
|
|
i = 2;
|
|
word(params, i++, w);
|
|
rnum = atoi(w);
|
|
j = 0;
|
|
rpx = Emalloc(rnum);
|
|
rpy = Emalloc(rnum);
|
|
while (j < rnum)
|
|
{
|
|
word(params, i++, w);
|
|
k = atoi(w);
|
|
rpx[j] = k;
|
|
word(params, i++, w);
|
|
k = atoi(w);
|
|
rpy[j++] = k;
|
|
}
|
|
word(params, i++, w);
|
|
gnum = atoi(w);
|
|
j = 0;
|
|
gpx = Emalloc(gnum);
|
|
gpy = Emalloc(gnum);
|
|
while (j < gnum)
|
|
{
|
|
word(params, i++, w);
|
|
k = atoi(w);
|
|
gpx[j] = k;
|
|
word(params, i++, w);
|
|
k = atoi(w);
|
|
gpy[j++] = k;
|
|
}
|
|
word(params, i++, w);
|
|
bnum = atoi(w);
|
|
j = 0;
|
|
bpx = Emalloc(bnum);
|
|
bpy = Emalloc(bnum);
|
|
while (j < bnum)
|
|
{
|
|
word(params, i++, w);
|
|
k = atoi(w);
|
|
bpx[j] = k;
|
|
word(params, i++, w);
|
|
k = atoi(w);
|
|
bpy[j++] = k;
|
|
}
|
|
if (cm)
|
|
ModifyCMClass(name, rnum, rpx, rpy, gnum, gpx, gpy, bnum, bpx, bpy);
|
|
else
|
|
{
|
|
cm = CreateCMClass(name, rnum, rpx, rpy, gnum, gpx, gpy, bnum, bpx,
|
|
bpy);
|
|
AddItem(cm, cm->name, 0, LIST_TYPE_COLORMODIFIER);
|
|
}
|
|
Efree(name);
|
|
if (rpx)
|
|
Efree(rpx);
|
|
if (rpy)
|
|
Efree(rpy);
|
|
if (gpx)
|
|
Efree(gpx);
|
|
if (gpy)
|
|
Efree(gpy);
|
|
if (bpx)
|
|
Efree(bpx);
|
|
if (bpy)
|
|
Efree(bpy);
|
|
}
|
|
|
|
IpcItem CmClassIpcArray[] = {
|
|
{
|
|
IPC_ColorModifierClass,
|
|
"colormod", NULL,
|
|
"Create/Delete/Modify a ColorModifierClass",
|
|
"This doesn't do anything yet."}
|
|
,
|
|
{
|
|
IPC_ColormodifierDelete, "del_colmod", NULL, "TBD", NULL}
|
|
,
|
|
{
|
|
IPC_ColormodifierGet, "get_colmod", NULL, "TBD", NULL}
|
|
,
|
|
{
|
|
IPC_ColormodifierSet, "set_colmod", NULL, "TBD", NULL}
|
|
,
|
|
};
|
|
#define N_IPC_FUNCS (sizeof(CmClassIpcArray)/sizeof(IpcItem))
|
|
|
|
#endif
|