#include "cups-private.h"
#include "ppd-private.h"
static cups_lang_t *ppd_ll_CC(char *ll_CC, int ll_CC_size);
int
ppdLocalize(ppd_file_t *ppd)
{
int i, j, k;
ppd_group_t *group;
ppd_option_t *option;
ppd_choice_t *choice;
ppd_coption_t *coption;
ppd_cparam_t *cparam;
ppd_attr_t *attr,
*locattr;
char ckeyword[PPD_MAX_NAME],
ll_CC[6];
DEBUG_printf(("ppdLocalize(ppd=%p)", ppd));
if (!ppd)
return (-1);
ppd_ll_CC(ll_CC, sizeof(ll_CC));
for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
{
if ((locattr = _ppdLocalizedAttr(ppd, "Translation", group->name,
ll_CC)) != NULL)
strlcpy(group->text, locattr->text, sizeof(group->text));
for (j = group->num_options, option = group->options; j > 0; j --, option ++)
{
if ((locattr = _ppdLocalizedAttr(ppd, "Translation", option->keyword,
ll_CC)) != NULL)
strlcpy(option->text, locattr->text, sizeof(option->text));
for (k = option->num_choices, choice = option->choices;
k > 0;
k --, choice ++)
{
if (strcmp(choice->choice, "Custom") ||
!ppdFindCustomOption(ppd, option->keyword))
locattr = _ppdLocalizedAttr(ppd, option->keyword, choice->choice,
ll_CC);
else
{
snprintf(ckeyword, sizeof(ckeyword), "Custom%s", option->keyword);
locattr = _ppdLocalizedAttr(ppd, ckeyword, "True", ll_CC);
}
if (locattr)
strlcpy(choice->text, locattr->text, sizeof(choice->text));
}
}
}
for (coption = (ppd_coption_t *)cupsArrayFirst(ppd->coptions);
coption;
coption = (ppd_coption_t *)cupsArrayNext(ppd->coptions))
{
for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
cparam;
cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
{
snprintf(ckeyword, sizeof(ckeyword), "ParamCustom%s", coption->keyword);
if ((locattr = _ppdLocalizedAttr(ppd, ckeyword, cparam->name,
ll_CC)) != NULL)
strlcpy(cparam->text, locattr->text, sizeof(cparam->text));
}
}
if ((attr = ppdFindAttr(ppd, "APCustomColorMatchingName", NULL)) != NULL)
{
if ((locattr = _ppdLocalizedAttr(ppd, "APCustomColorMatchingName",
attr->spec, ll_CC)) != NULL)
strlcpy(attr->text, locattr->text, sizeof(attr->text));
}
for (attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
attr;
attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
{
cupsArraySave(ppd->sorted_attrs);
if ((locattr = _ppdLocalizedAttr(ppd, "cupsICCProfile", attr->spec,
ll_CC)) != NULL)
strlcpy(attr->text, locattr->text, sizeof(attr->text));
cupsArrayRestore(ppd->sorted_attrs);
}
for (attr = ppdFindAttr(ppd, "APPrinterPreset", NULL);
attr;
attr = ppdFindNextAttr(ppd, "APPrinterPreset", NULL))
{
cupsArraySave(ppd->sorted_attrs);
if ((locattr = _ppdLocalizedAttr(ppd, "APPrinterPreset", attr->spec,
ll_CC)) != NULL)
strlcpy(attr->text, locattr->text, sizeof(attr->text));
cupsArrayRestore(ppd->sorted_attrs);
}
return (0);
}
ppd_attr_t *
ppdLocalizeAttr(ppd_file_t *ppd,
const char *keyword,
const char *spec)
{
ppd_attr_t *locattr;
char ll_CC[6];
ppd_ll_CC(ll_CC, sizeof(ll_CC));
if (spec)
locattr = _ppdLocalizedAttr(ppd, keyword, spec, ll_CC);
else
locattr = _ppdLocalizedAttr(ppd, "Translation", keyword, ll_CC);
if (!locattr)
locattr = ppdFindAttr(ppd, keyword, spec);
return (locattr);
}
const char *
ppdLocalizeIPPReason(
ppd_file_t *ppd,
const char *reason,
const char *scheme,
char *buffer,
size_t bufsize)
{
cups_lang_t *lang;
ppd_attr_t *locattr;
char ll_CC[6],
*bufptr,
*bufend,
*valptr;
int ch,
schemelen;
if (buffer)
*buffer = '\0';
if (!ppd || !reason || (scheme && !*scheme) ||
!buffer || bufsize < PPD_MAX_TEXT)
return (NULL);
lang = ppd_ll_CC(ll_CC, sizeof(ll_CC));
if ((locattr = _ppdLocalizedAttr(ppd, "cupsIPPReason", reason,
ll_CC)) == NULL)
locattr = ppdFindAttr(ppd, "cupsIPPReason", reason);
if (!locattr)
{
if (lang && (!scheme || !strcmp(scheme, "text")))
{
const char *message = NULL;
if (!strncmp(reason, "media-needed", 12))
message = _("The paper tray needs to be filled.");
else if (!strncmp(reason, "media-jam", 9))
message = _("There is a paper jam.");
else if (!strncmp(reason, "offline", 7) ||
!strncmp(reason, "shutdown", 8))
message = _("The printer is not connected.");
else if (!strncmp(reason, "toner-low", 9))
message = _("The printer is running low on toner.");
else if (!strncmp(reason, "toner-empty", 11))
message = _("The printer may be out of toner.");
else if (!strncmp(reason, "cover-open", 10))
message = _("The printer's cover is open.");
else if (!strncmp(reason, "interlock-open", 14))
message = _("The printer's interlock is open.");
else if (!strncmp(reason, "door-open", 9))
message = _("The printer's door is open.");
else if (!strncmp(reason, "input-tray-missing", 18))
message = _("The paper tray is missing.");
else if (!strncmp(reason, "media-low", 9))
message = _("The paper tray is almost empty.");
else if (!strncmp(reason, "media-empty", 11))
message = _("The paper tray is empty.");
else if (!strncmp(reason, "output-tray-missing", 19))
message = _("The output bin is missing.");
else if (!strncmp(reason, "output-area-almost-full", 23))
message = _("The output bin is almost full.");
else if (!strncmp(reason, "output-area-full", 16))
message = _("The output bin is full.");
else if (!strncmp(reason, "marker-supply-low", 17))
message = _("The printer is running low on ink.");
else if (!strncmp(reason, "marker-supply-empty", 19))
message = _("The printer may be out of ink.");
else if (!strncmp(reason, "marker-waste-almost-full", 24))
message = _("The printer's waste bin is almost full.");
else if (!strncmp(reason, "marker-waste-full", 17))
message = _("The printer's waste bin is full.");
else if (!strncmp(reason, "fuser-over-temp", 15))
message = _("The fuser's temperature is high.");
else if (!strncmp(reason, "fuser-under-temp", 16))
message = _("The fuser's temperature is low.");
else if (!strncmp(reason, "opc-near-eol", 12))
message = _("The optical photoconductor will need to be replaced soon.");
else if (!strncmp(reason, "opc-life-over", 13))
message = _("The optical photoconductor needs to be replaced.");
else if (!strncmp(reason, "developer-low", 13))
message = _("The developer unit will need to be replaced soon.");
else if (!strncmp(reason, "developer-empty", 15))
message = _("The developer unit needs to be replaced.");
if (message)
{
strlcpy(buffer, _cupsLangString(lang, message), bufsize);
return (buffer);
}
}
return (NULL);
}
bufend = buffer + bufsize - 1;
if (!scheme || !strcmp(scheme, "text"))
{
strlcpy(buffer, locattr->text, bufsize);
for (valptr = locattr->value, bufptr = buffer; *valptr && bufptr < bufend;)
{
if (!strncmp(valptr, "text:", 5))
{
valptr += 5;
while (*valptr && !_cups_isspace(*valptr) && bufptr < bufend)
{
if (*valptr == '%' && isxdigit(valptr[1] & 255) &&
isxdigit(valptr[2] & 255))
{
valptr ++;
if (isdigit(*valptr & 255))
ch = (*valptr - '0') << 4;
else
ch = (tolower(*valptr) - 'a' + 10) << 4;
valptr ++;
if (isdigit(*valptr & 255))
*bufptr++ = ch | (*valptr - '0');
else
*bufptr++ = ch | (tolower(*valptr) - 'a' + 10);
valptr ++;
}
else if (*valptr == '+')
{
*bufptr++ = ' ';
valptr ++;
}
else
*bufptr++ = *valptr++;
}
}
else
{
while (*valptr && !_cups_isspace(*valptr))
valptr++;
}
while (_cups_isspace(*valptr))
valptr ++;
}
if (bufptr > buffer)
*bufptr = '\0';
return (buffer);
}
else
{
schemelen = strlen(scheme);
if (scheme[schemelen - 1] == ':')
schemelen --;
for (valptr = locattr->value, bufptr = buffer; *valptr && bufptr < bufend;)
{
if ((!strncmp(valptr, scheme, schemelen) && valptr[schemelen] == ':') ||
(*valptr == '/' && !strcmp(scheme, "file")))
{
while (*valptr && !_cups_isspace(*valptr) && bufptr < bufend)
*bufptr++ = *valptr++;
*bufptr = '\0';
return (buffer);
}
else
{
while (*valptr && !_cups_isspace(*valptr))
valptr++;
}
while (_cups_isspace(*valptr))
valptr ++;
}
return (NULL);
}
}
const char *
ppdLocalizeMarkerName(
ppd_file_t *ppd,
const char *name)
{
ppd_attr_t *locattr;
char ll_CC[6];
if (!ppd || !name)
return (NULL);
ppd_ll_CC(ll_CC, sizeof(ll_CC));
if ((locattr = _ppdLocalizedAttr(ppd, "cupsMarkerName", name,
ll_CC)) == NULL)
locattr = ppdFindAttr(ppd, "cupsMarkerName", name);
return (locattr ? locattr->text : NULL);
}
void
_ppdFreeLanguages(
cups_array_t *languages)
{
char *language;
for (language = (char *)cupsArrayFirst(languages);
language;
language = (char *)cupsArrayNext(languages))
free(language);
cupsArrayDelete(languages);
}
cups_array_t *
_ppdGetLanguages(ppd_file_t *ppd)
{
cups_array_t *languages;
ppd_attr_t *attr;
char *value,
*start,
*ptr;
if ((attr = ppdFindAttr(ppd, "cupsLanguages", NULL)) == NULL || !attr->value)
return (NULL);
if ((languages = cupsArrayNew((cups_array_func_t)strcmp, NULL)) == NULL)
return (NULL);
if ((value = strdup(attr->value)) == NULL)
{
cupsArrayDelete(languages);
return (NULL);
}
for (ptr = value; *ptr;)
{
while (_cups_isspace(*ptr))
ptr ++;
if (!*ptr)
break;
for (start = ptr; *ptr && !_cups_isspace(*ptr); ptr ++);
if (*ptr)
*ptr++ = '\0';
if (!strcmp(start, "en"))
continue;
cupsArrayAdd(languages, strdup(start));
}
free(value);
if (cupsArrayCount(languages) == 0)
{
cupsArrayDelete(languages);
return (NULL);
}
else
return (languages);
}
unsigned
_ppdHashName(const char *name)
{
int mult;
unsigned hash = 0;
for (mult = 1; *name && mult <= 128; mult ++, name ++)
hash += (*name & 255) * mult;
return (hash);
}
ppd_attr_t *
_ppdLocalizedAttr(ppd_file_t *ppd,
const char *keyword,
const char *spec,
const char *ll_CC)
{
char lkeyword[PPD_MAX_NAME];
ppd_attr_t *attr;
DEBUG_printf(("4_ppdLocalizedAttr(ppd=%p, keyword=\"%s\", spec=\"%s\", "
"ll_CC=\"%s\")", ppd, keyword, spec, ll_CC));
snprintf(lkeyword, sizeof(lkeyword), "%s.%s", ll_CC, keyword);
if ((attr = ppdFindAttr(ppd, lkeyword, spec)) == NULL)
{
snprintf(lkeyword, sizeof(lkeyword), "%2.2s.%s", ll_CC, keyword);
attr = ppdFindAttr(ppd, lkeyword, spec);
if (!attr)
{
if (!strncmp(ll_CC, "ja", 2))
{
snprintf(lkeyword, sizeof(lkeyword), "jp.%s", keyword);
attr = ppdFindAttr(ppd, lkeyword, spec);
}
else if (!strncmp(ll_CC, "no", 2))
{
snprintf(lkeyword, sizeof(lkeyword), "nb.%s", keyword);
attr = ppdFindAttr(ppd, lkeyword, spec);
}
}
}
#ifdef DEBUG
if (attr)
DEBUG_printf(("5_ppdLocalizedAttr: *%s %s/%s: \"%s\"\n", attr->name,
attr->spec, attr->text, attr->value ? attr->value : ""));
else
DEBUG_puts("5_ppdLocalizedAttr: NOT FOUND");
#endif
return (attr);
}
static cups_lang_t *
ppd_ll_CC(char *ll_CC,
int ll_CC_size)
{
cups_lang_t *lang;
if ((lang = cupsLangDefault()) == NULL)
{
strlcpy(ll_CC, "en_US", ll_CC_size);
return (NULL);
}
strlcpy(ll_CC, lang->language, ll_CC_size);
if (strlen(ll_CC) == 2)
{
if (!strcmp(ll_CC, "cs"))
strlcpy(ll_CC, "cs_CZ", ll_CC_size);
else if (!strcmp(ll_CC, "en"))
strlcpy(ll_CC, "en_US", ll_CC_size);
else if (!strcmp(ll_CC, "ja"))
strlcpy(ll_CC, "ja_JP", ll_CC_size);
else if (!strcmp(ll_CC, "sv"))
strlcpy(ll_CC, "sv_SE", ll_CC_size);
else if (!strcmp(ll_CC, "zh"))
strlcpy(ll_CC, "zh_CN", ll_CC_size);
}
DEBUG_printf(("8ppd_ll_CC: lang->language=\"%s\", ll_CC=\"%s\"...",
lang->language, ll_CC));
return (lang);
}