e16/src/cmclass.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