#include "cups.h"
#include "string.h"
#include "debug.h"
static void ppd_defaults(ppd_file_t *ppd, ppd_group_t *g);
int
ppdConflicts(ppd_file_t *ppd)
{
int i,
conflicts;
ppd_const_t *c;
ppd_option_t *o1, *o2;
ppd_choice_t *c1, *c2;
ppd_choice_t key;
if (!ppd)
return (0);
conflicts = 0;
for (o1 = ppdFirstOption(ppd); o1; o1 = ppdNextOption(ppd))
o1->conflicted = 0;
cupsArraySave(ppd->marked);
for (i = ppd->num_consts, c = ppd->consts, o1 = o2 = NULL, c1 = c2 = NULL;
i > 0;
i --, c ++)
{
if (!o1 || strcmp(c->option1, o1->keyword))
{
o1 = ppdFindOption(ppd, c->option1);
c1 = NULL;
}
if (!o1)
continue;
else if (c->choice1[0] && (!c1 || strcmp(c->choice1, c1->choice)))
{
key.option = o1;
if ((c1 = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL &&
(!c1->marked || strcmp(c->choice1, c1->choice)))
c1 = NULL;
}
else if (!c1)
{
key.option = o1;
if ((c1 = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL &&
(!strcasecmp(c1->choice, "None") || !strcasecmp(c1->choice, "Off") ||
!strcasecmp(c1->choice, "False")))
c1 = NULL;
}
if (!o2 || strcmp(c->option2, o2->keyword))
{
o2 = ppdFindOption(ppd, c->option2);
c2 = NULL;
}
if (!o2)
continue;
else if (c->choice2[0] && (!c2 || strcmp(c->choice2, c2->choice)))
{
key.option = o2;
if ((c2 = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL &&
(!c2->marked || strcmp(c->choice2, c2->choice)))
c2 = NULL;
}
else if (!c2)
{
key.option = o2;
if ((c2 = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL &&
(!strcasecmp(c2->choice, "None") || !strcasecmp(c2->choice, "Off") ||
!strcasecmp(c2->choice, "False")))
c2 = NULL;
}
if (c1 && c1->marked && c2 && c2->marked)
{
DEBUG_printf(("%s->%s conflicts with %s->%s (%s %s %s %s)\n",
o1->keyword, c1->choice, o2->keyword, c2->choice,
c->option1, c->choice1, c->option2, c->choice2));
conflicts ++;
o1->conflicted = 1;
o2->conflicted = 1;
}
}
cupsArrayRestore(ppd->marked);
return (conflicts);
}
ppd_choice_t *
ppdFindChoice(ppd_option_t *o,
const char *choice)
{
int i;
ppd_choice_t *c;
if (!o || !choice)
return (NULL);
if (choice[0] == '{' || !strncasecmp(choice, "Custom.", 7))
choice = "Custom";
for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
if (!strcasecmp(c->choice, choice))
return (c);
return (NULL);
}
ppd_choice_t *
ppdFindMarkedChoice(ppd_file_t *ppd,
const char *option)
{
ppd_choice_t key;
if ((key.option = ppdFindOption(ppd, option)) == NULL)
return (NULL);
return ((ppd_choice_t *)cupsArrayFind(ppd->marked, &key));
}
ppd_option_t *
ppdFindOption(ppd_file_t *ppd,
const char *option)
{
if (!ppd || !option)
return (NULL);
if (ppd->options)
{
ppd_option_t key;
strlcpy(key.keyword, option, sizeof(key.keyword));
return ((ppd_option_t *)cupsArrayFind(ppd->options, &key));
}
else
{
int i, j;
ppd_group_t *group;
ppd_option_t *optptr;
for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
for (j = group->num_options, optptr = group->options;
j > 0;
j --, optptr ++)
if (!strcasecmp(optptr->keyword, option))
return (optptr);
return (NULL);
}
}
int
ppdIsMarked(ppd_file_t *ppd,
const char *option,
const char *choice)
{
ppd_choice_t key,
*c;
if (!ppd)
return (0);
if ((key.option = ppdFindOption(ppd, option)) == NULL)
return (0);
if ((c = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) == NULL)
return (0);
return (!strcmp(c->choice, choice));
}
void
ppdMarkDefaults(ppd_file_t *ppd)
{
int i;
ppd_group_t *g;
ppd_choice_t *c;
if (!ppd)
return;
for (c = (ppd_choice_t *)cupsArrayFirst(ppd->marked);
c;
c = (ppd_choice_t *)cupsArrayNext(ppd->marked))
cupsArrayRemove(ppd->marked, c);
for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
ppd_defaults(ppd, g);
}
int
ppdMarkOption(ppd_file_t *ppd,
const char *option,
const char *choice)
{
int i, j;
ppd_option_t *o;
ppd_choice_t *c,
*oldc,
key;
struct lconv *loc;
DEBUG_printf(("ppdMarkOption(ppd=%p, option=\"%s\", choice=\"%s\")\n",
ppd, option, choice));
if (!ppd || !option || !choice)
return (0);
if (!strcasecmp(option, "AP_D_InputSlot"))
{
if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
{
key.option = o;
if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
{
oldc->marked = 0;
cupsArrayRemove(ppd->marked, oldc);
}
}
}
if ((o = ppdFindOption(ppd, option)) == NULL)
return (0);
loc = localeconv();
if (!strncasecmp(choice, "Custom.", 7))
{
if ((c = ppdFindChoice(o, "Custom")) == NULL)
return (0);
if (!strcasecmp(option, "PageSize"))
{
ppdPageSize(ppd, choice);
}
else
{
ppd_coption_t *coption;
ppd_cparam_t *cparam;
char *units;
if ((coption = ppdFindCustomOption(ppd, option)) != NULL)
{
if ((cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params)) == NULL)
return (0);
switch (cparam->type)
{
case PPD_CUSTOM_CURVE :
case PPD_CUSTOM_INVCURVE :
case PPD_CUSTOM_REAL :
cparam->current.custom_real = (float)_cupsStrScand(choice + 7,
NULL, loc);
break;
case PPD_CUSTOM_POINTS :
cparam->current.custom_points = (float)_cupsStrScand(choice + 7,
&units,
loc);
if (units)
{
if (!strcasecmp(units, "cm"))
cparam->current.custom_points *= 72.0f / 2.54f;
else if (!strcasecmp(units, "mm"))
cparam->current.custom_points *= 72.0f / 25.4f;
else if (!strcasecmp(units, "m"))
cparam->current.custom_points *= 72.0f / 0.0254f;
else if (!strcasecmp(units, "in"))
cparam->current.custom_points *= 72.0f;
else if (!strcasecmp(units, "ft"))
cparam->current.custom_points *= 12.0f * 72.0f;
}
break;
case PPD_CUSTOM_INT :
cparam->current.custom_int = atoi(choice + 7);
break;
case PPD_CUSTOM_PASSCODE :
case PPD_CUSTOM_PASSWORD :
case PPD_CUSTOM_STRING :
if (cparam->current.custom_string)
free(cparam->current.custom_string);
cparam->current.custom_string = strdup(choice + 7);
break;
}
}
}
choice = "Custom";
}
else if (choice[0] == '{')
{
ppd_coption_t *coption;
ppd_cparam_t *cparam;
char *units;
int num_vals;
cups_option_t *vals,
*val;
if ((c = ppdFindChoice(o, "Custom")) == NULL)
return (0);
if ((coption = ppdFindCustomOption(ppd, option)) != NULL)
{
num_vals = cupsParseOptions(choice + 1, 0, &vals);
for (i = 0, val = vals; i < num_vals; i ++, val ++)
{
if ((cparam = ppdFindCustomParam(coption, val->name)) == NULL)
continue;
switch (cparam->type)
{
case PPD_CUSTOM_CURVE :
case PPD_CUSTOM_INVCURVE :
case PPD_CUSTOM_REAL :
cparam->current.custom_real = (float)_cupsStrScand(val->value,
NULL, loc);
break;
case PPD_CUSTOM_POINTS :
cparam->current.custom_points = (float)_cupsStrScand(val->value,
&units,
loc);
if (units)
{
if (!strcasecmp(units, "cm"))
cparam->current.custom_points *= 72.0f / 2.54f;
else if (!strcasecmp(units, "mm"))
cparam->current.custom_points *= 72.0f / 25.4f;
else if (!strcasecmp(units, "m"))
cparam->current.custom_points *= 72.0f / 0.0254f;
else if (!strcasecmp(units, "in"))
cparam->current.custom_points *= 72.0f;
else if (!strcasecmp(units, "ft"))
cparam->current.custom_points *= 12.0f * 72.0f;
}
break;
case PPD_CUSTOM_INT :
cparam->current.custom_int = atoi(val->value);
break;
case PPD_CUSTOM_PASSCODE :
case PPD_CUSTOM_PASSWORD :
case PPD_CUSTOM_STRING :
if (cparam->current.custom_string)
free(cparam->current.custom_string);
cparam->current.custom_string = strdup(val->value);
break;
}
}
cupsFreeOptions(num_vals, vals);
}
}
else
{
for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
if (!strcasecmp(c->choice, choice))
break;
if (!i)
return (0);
}
if (o->ui != PPD_UI_PICKMANY)
{
if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, c)) != NULL)
{
oldc->marked = 0;
cupsArrayRemove(ppd->marked, oldc);
}
if (!strcasecmp(option, "PageSize") || !strcasecmp(option, "PageRegion"))
{
for (j = 0; j < ppd->num_sizes; j ++)
ppd->sizes[j].marked = !strcasecmp(ppd->sizes[j].name,
choice);
if (!strcasecmp(option, "PageSize"))
{
if ((o = ppdFindOption(ppd, "PageRegion")) != NULL)
{
key.option = o;
if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
{
oldc->marked = 0;
cupsArrayRemove(ppd->marked, oldc);
}
}
}
else
{
if ((o = ppdFindOption(ppd, "PageSize")) != NULL)
{
key.option = o;
if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
{
oldc->marked = 0;
cupsArrayRemove(ppd->marked, oldc);
}
}
}
}
else if (!strcasecmp(option, "InputSlot"))
{
if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL)
{
key.option = o;
if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
{
oldc->marked = 0;
cupsArrayRemove(ppd->marked, oldc);
}
}
}
else if (!strcasecmp(option, "ManualFeed") &&
!strcasecmp(choice, "True"))
{
if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
{
key.option = o;
if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
{
oldc->marked = 0;
cupsArrayRemove(ppd->marked, oldc);
}
}
}
}
c->marked = 1;
cupsArrayAdd(ppd->marked, c);
return (ppdConflicts(ppd));
}
ppd_option_t *
ppdFirstOption(ppd_file_t *ppd)
{
if (!ppd)
return (NULL);
else
return ((ppd_option_t *)cupsArrayFirst(ppd->options));
}
ppd_option_t *
ppdNextOption(ppd_file_t *ppd)
{
if (!ppd)
return (NULL);
else
return ((ppd_option_t *)cupsArrayNext(ppd->options));
}
static void
ppd_defaults(ppd_file_t *ppd,
ppd_group_t *g)
{
int i;
ppd_option_t *o;
ppd_group_t *sg;
for (i = g->num_options, o = g->options; i > 0; i --, o ++)
if (strcasecmp(o->keyword, "PageRegion") != 0)
ppdMarkOption(ppd, o->keyword, o->defchoice);
for (i = g->num_subgroups, sg = g->subgroups; i > 0; i --, sg ++)
ppd_defaults(ppd, sg);
}