*/
static int cups_connect(http_t **http, const char *url, char *resource, size_t ressize);
-static int cups_get_url(http_t **http, const char *url, char *name, size_t namesize);
+static cups_array_t *cups_get_languages(void);
+static cups_lang_t *cups_get_strings(http_t **http, const char *printer_uri, const char *language);
+static int cups_get_url(http_t **http, const char *url, const char *suffix, char *name, size_t namesize);
static const char *ppd_inputslot_for_keyword(_ppd_cache_t *pc, const char *keyword);
+static void ppd_put_strings(cups_file_t *fp, cups_lang_t *langs, const char *ppd_option, const char *ppd_choice, const char *pwg_msgid);
static void pwg_add_finishing(cups_array_t *finishings, ipp_finishings_t template, const char *name, const char *value);
static void pwg_add_message(cups_array_t *a, const char *msg, const char *str);
static int pwg_compare_finishings(_pwg_finishings_t *a, _pwg_finishings_t *b, void *data);
* of an IPP printer.
*/
-char * /* O - PPD filename or @code NULL@ on error */
+char * /* O - PPD filename or `NULL` on error */
_ppdCreateFromIPP(char *buffer, /* I - Filename buffer */
size_t bufsize, /* I - Size of filename buffer */
ipp_t *supported) /* I - Get-Printer-Attributes response */
{
- return (_ppdCreateFromIPP2(buffer, bufsize, supported, cupsLangDefault()));
-}
-
-
-/*
- * '_ppdCreateFromIPP2()' - Create a PPD file describing the capabilities
- * of an IPP printer.
- */
-
-
-char *
-_ppdCreateFromIPP2(
- char *buffer, /* I - Filename buffer */
- size_t bufsize, /* I - Size of filename buffer */
- ipp_t *supported, /* I - Get-Printer-Attributes response */
- cups_lang_t *lang) /* I - Language */
-{
+ const char *printer_uri; /* Printer URI */
+ http_t *http = NULL; /* HTTP connection */
+ cups_array_t *languages; /* List of languages */
+ cups_lang_t *lang, /* Current language information */
+ *langs = NULL; /* Language (strings) files */
+ const char *prefix; /* Prefix string */
cups_file_t *fp; /* PPD file */
cups_array_t *sizes; /* Media sizes supported by printer */
cups_size_t *size; /* Current media size */
/* Array of resolution indices */
int have_qdraft = 0,/* Have draft quality? */
have_qhigh = 0; /* Have high quality? */
- char msgid[256]; /* Message identifier (attr.value) */
- const char *keyword, /* Keyword value */
- *msgstr; /* Localized string */
- cups_array_t *strings = NULL;/* Printer strings file */
+ char msgid[256]; /* PWG message identifier (attr.value) */
+ const char *keyword; /* Keyword value */
struct lconv *loc = localeconv();
/* Locale data */
cups_array_t *fin_options = NULL;
return (NULL);
}
+ if ((printer_uri = ippGetString(ippFindAttribute(supported, "printer-uri-supported", IPP_TAG_URI), 0, NULL)) == NULL)
+ {
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No printer-uri-supported attribute."), 1);
+ return (NULL);
+ }
+
/*
* Open a temporary file for the PPD...
*/
- if ((fp = cupsTempFile2(buffer, (int)bufsize)) == NULL)
+ if ((fp = cupsCreateTempFile("ippeve", ".ppd", buffer, bufsize)) == NULL)
{
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
return (NULL);
}
+ /*
+ * Figure out the languages to load/generate...
+ */
+
+ languages = cups_get_languages();
+
/*
* Standard stuff for PPD file...
*/
cupsFilePrintf(fp, "*NickName: \"%s - IPP Everywhere\"\n", model);
cupsFilePrintf(fp, "*ShortNickName: \"%s - IPP Everywhere\"\n", model);
- if ((attr = ippFindAttribute(supported, "color-supported", IPP_TAG_BOOLEAN)) != NULL && ippGetBoolean(attr, 0))
+ if (ippGetBoolean(ippFindAttribute(supported, "color-supported", IPP_TAG_BOOLEAN), 0))
cupsFilePuts(fp, "*ColorDevice: True\n");
else
cupsFilePuts(fp, "*ColorDevice: False\n");
cupsFilePrintf(fp, "*APAirPrint: True\n");
#endif // __APPLE__
cupsFilePuts(fp, "*cupsSNMPSupplies: False\n");
- cupsFilePrintf(fp, "*cupsLanguages: \"%s", lang->language);
- if ((lang_supp = ippFindAttribute(supported, "printer-strings-languages-supported", IPP_TAG_LANGUAGE)) != NULL)
- {
- for (i = 0, count = ippGetCount(lang_supp); i < count; i ++)
- {
- keyword = ippGetString(lang_supp, i, NULL);
- if (strcmp(keyword, lang->language))
- cupsFilePrintf(fp, " %s", keyword);
- }
- }
- cupsFilePuts(fp, "\"\n");
-
- if ((attr = ippFindAttribute(supported, "printer-more-info", IPP_TAG_URI)) != NULL)
- cupsFilePrintf(fp, "*APSupplies: \"%s\"\n", ippGetString(attr, 0, NULL));
-
- if ((attr = ippFindAttribute(supported, "printer-charge-info-uri", IPP_TAG_URI)) != NULL)
- cupsFilePrintf(fp, "*cupsChargeInfoURI: \"%s\"\n", ippGetString(attr, 0, NULL));
-
- if ((attr = ippFindAttribute(supported, "printer-strings-uri", IPP_TAG_URI)) != NULL)
+ if ((lang_supp = ippFindAttribute(supported, "printer-strings-languages-supported", IPP_TAG_LANGUAGE)) != NULL)
{
- http_t *http = NULL; /* Connection to printer */
- char stringsfile[1024]; /* Temporary strings file */
+ /*
+ * List supported languages...
+ */
- if (cups_get_url(&http, ippGetString(attr, 0, NULL), stringsfile, sizeof(stringsfile)))
+ for (i = 0, count = ippGetCount(lang_supp), prefix = "*cupsLanguages: \""; i < count; i ++)
{
- const char *printer_uri = ippGetString(ippFindAttribute(supported, "printer-uri-supported", IPP_TAG_URI), 0, NULL);
- // Printer URI
- char resource[256]; // Resource path
- ipp_t *request, // Get-Printer-Attributes request
- *response; // Response to request
-
- /*
- * Load strings and save the URL for clients using the destination API
- * instead of this PPD file...
- */
-
- cupsFilePrintf(fp, "*cupsStringsURI: \"%s\"\n", ippGetString(attr, 0, NULL));
-
- strings = _cupsMessageLoad(stringsfile, _CUPS_MESSAGE_STRINGS | _CUPS_MESSAGE_UNQUOTE);
-
- unlink(stringsfile);
+ keyword = ippGetString(lang_supp, i, NULL);
- if (lang_supp && printer_uri && cups_connect(&http, printer_uri, resource, sizeof(resource)))
+ if (cupsArrayFind(languages, (void *)keyword) && (lang = cups_get_strings(&http, printer_uri, keyword)) != NULL)
{
/*
- * Loop through all of the languages and save their URIs...
- */
+ * Add language...
+ */
- for (i = 0, count = ippGetCount(lang_supp); i < count; i ++)
- {
- keyword = ippGetString(lang_supp, i, NULL);
+ lang->next = langs;
+ langs = lang;
- request = ippNew();
- ippSetOperation(request, IPP_OP_GET_PRINTER_ATTRIBUTES);
- ippSetRequestId(request, i + 1);
- ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_CHARSET), "attributes-charset", NULL, "utf-8");
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, keyword);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri);
- ippAddString(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_KEYWORD), "requested-attributes", NULL, "printer-strings-uri");
-
- response = cupsDoRequest(http, request, resource);
-
- if ((attr = ippFindAttribute(response, "printer-strings-uri", IPP_TAG_URI)) != NULL)
- cupsFilePrintf(fp, "*cupsStringsURI %s: \"%s\"\n", keyword, ippGetString(attr, 0, NULL));
-
- ippDelete(response);
- }
+ cupsFilePrintf(fp, "%s%s", prefix, keyword);
+ prefix = ",";
}
}
- if (http)
- httpClose(http);
+ if (!strcmp(prefix, ","))
+ cupsFilePuts(fp, "\"\n");
+ }
+
+ if (http)
+ {
+ httpClose(http);
+ http = NULL;
}
+ if ((attr = ippFindAttribute(supported, "printer-more-info", IPP_TAG_URI)) != NULL)
+ cupsFilePrintf(fp, "*APSupplies: \"%s\"\n", ippGetString(attr, 0, NULL));
+
+ if ((attr = ippFindAttribute(supported, "printer-charge-info-uri", IPP_TAG_URI)) != NULL)
+ cupsFilePrintf(fp, "*cupsChargeInfoURI: \"%s\"\n", ippGetString(attr, 0, NULL));
+
/*
* Accounting...
*/
if ((attr = ippFindAttribute(supported, "printer-mandatory-job-attributes", IPP_TAG_KEYWORD)) != NULL)
{
- char prefix = '\"'; // Prefix for string
-
- cupsFilePuts(fp, "*cupsMandatory: \"");
- for (i = 0, count = ippGetCount(attr); i < count; i ++)
+ for (i = 0, count = ippGetCount(attr), prefix = "*cupsMandatory: \""; i < count; i ++)
{
keyword = ippGetString(attr, i, NULL);
if (strcmp(keyword, "attributes-charset") && strcmp(keyword, "attributes-natural-language") && strcmp(keyword, "printer-uri"))
{
- cupsFilePrintf(fp, "%c%s", prefix, keyword);
- prefix = ',';
+ cupsFilePrintf(fp, "%s%s", prefix, keyword);
+ prefix = ",";
}
}
- cupsFilePuts(fp, "\"\n");
+
+ if (!strcmp(prefix, ","))
+ cupsFilePuts(fp, "\"\n");
}
if ((attr = ippFindAttribute(supported, "printer-requested-job-attributes", IPP_TAG_KEYWORD)) != NULL)
{
- char prefix = '\"'; // Prefix for string
-
- cupsFilePuts(fp, "*cupsRequested: \"");
- for (i = 0, count = ippGetCount(attr); i < count; i ++)
+ for (i = 0, count = ippGetCount(attr), prefix = "*cupsRequested: \""; i < count; i ++)
{
keyword = ippGetString(attr, i, NULL);
if (strcmp(keyword, "attributes-charset") && strcmp(keyword, "attributes-natural-language") && strcmp(keyword, "printer-uri"))
{
- cupsFilePrintf(fp, "%c%s", prefix, keyword);
- prefix = ',';
+ cupsFilePrintf(fp, "%s%s", prefix, keyword);
+ prefix = ",";
}
}
- cupsFilePuts(fp, "\"\n");
+
+ if (!strcmp(prefix, ","))
+ cupsFilePuts(fp, "\"\n");
}
/*
cupsFilePrintf(fp, "*DefaultInputSlot: %s\n", ppdname);
for (j = 0; j < (int)(sizeof(sources) / sizeof(sources[0])); j ++)
+ {
if (!strcmp(sources[j], keyword))
{
snprintf(msgid, sizeof(msgid), "media-source.%s", keyword);
- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
- msgstr = keyword;
-
cupsFilePrintf(fp, "*InputSlot %s: \"<</MediaPosition %d>>setpagedevice\"\n", ppdname, j);
- cupsFilePrintf(fp, "*%s.InputSlot %s/%s: \"\"\n", lang->language, ppdname, msgstr);
+ ppd_put_strings(fp, langs, "InputSlot", ppdname, msgid);
break;
}
+ }
}
cupsFilePuts(fp, "*CloseUI: *InputSlot\n");
}
pwg_ppdize_name(keyword, ppdname, sizeof(ppdname));
snprintf(msgid, sizeof(msgid), "media-type.%s", keyword);
- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
- msgstr = keyword;
- cupsFilePrintf(fp, "*MediaType %s: \"<</MediaType(%s)>>setpagedevice\"\n", ppdname, ppdname);
- cupsFilePrintf(fp, "*%s.MediaType %s/%s: \"\"\n", lang->language, ppdname, msgstr);
+ cupsFilePrintf(fp, "*MediaType %s: \"<</MediaType(%s)>>setpagedevice\"\n", ppdname, keyword);
+ ppd_put_strings(fp, langs, "MediaType", ppdname, msgid);
}
cupsFilePuts(fp, "*CloseUI: *MediaType\n");
}
cupsFilePrintf(fp, "*DefaultResolution: %ddpi\n", lowdpi);
- cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality: PickOne\n"
- "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
- "*%s.Translation cupsPrintQuality/%s: \"\"\n"
- "*DefaultcupsPrintQuality: Normal\n", lang->language, _cupsLangString(lang, _("Print Quality")));
+ cupsFilePuts(fp, "*OpenUI *cupsPrintQuality: PickOne\n"
+ "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
+ "*DefaultcupsPrintQuality: Normal\n");
if ((lowdpi & 1) == 0)
{
- cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Draft/%s: \"\"\n", lowdpi, lowdpi / 2, lang->language, _cupsLangString(lang, _("Draft")));
+ cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n", lowdpi, lowdpi / 2);
have_qdraft = 1;
}
else if (ippContainsInteger(quality, IPP_QUALITY_DRAFT))
{
- cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Draft/%s: \"\"\n", lowdpi, lowdpi, lang->language, _cupsLangString(lang, _("Draft")));
+ cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*", lowdpi, lowdpi);
have_qdraft = 1;
}
- cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Normal/%s: \"\"\n", lowdpi, lowdpi, lang->language, _cupsLangString(lang, _("Normal")));
+ cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n", lowdpi, lowdpi);
if (hidpi > lowdpi || ippContainsInteger(quality, IPP_QUALITY_HIGH))
{
- cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality High/%s: \"\"\n", hidpi, hidpi, lang->language, _cupsLangString(lang, _("High")));
+ cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n", hidpi, hidpi);
have_qhigh = 1;
}
pwg_ppdize_resolution(attr, resolutions[count / 2], &xres, &yres, ppdname, sizeof(ppdname));
cupsFilePrintf(fp, "*DefaultResolution: %s\n", ppdname);
- cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality: PickOne\n"
- "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
- "*%s.Translation cupsPrintQuality/%s: \"\"\n"
- "*DefaultcupsPrintQuality: Normal\n", lang->language, _cupsLangString(lang, _("Print Quality")));
+ cupsFilePuts(fp, "*OpenUI *cupsPrintQuality: PickOne\n"
+ "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
+ "*DefaultcupsPrintQuality: Normal\n");
if (count > 2 || ippContainsInteger(quality, IPP_QUALITY_DRAFT))
{
pwg_ppdize_resolution(attr, resolutions[0], &xres, &yres, NULL, 0);
cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres);
- cupsFilePrintf(fp, "*%s.cupsPrintQuality Draft/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Draft")));
have_qdraft = 1;
}
pwg_ppdize_resolution(attr, resolutions[count / 2], &xres, &yres, NULL, 0);
cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres);
- cupsFilePrintf(fp, "*%s.cupsPrintQuality Normal/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Normal")));
if (count > 1 || ippContainsInteger(quality, IPP_QUALITY_HIGH))
{
pwg_ppdize_resolution(attr, resolutions[count - 1], &xres, &yres, NULL, 0);
cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres);
- cupsFilePrintf(fp, "*%s.cupsPrintQuality High/%s: \"\"\n", lang->language, _cupsLangString(lang, _("High")));
have_qhigh = 1;
}
cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n");
}
else if (is_apple || is_pwg)
+ {
goto bad_ppd;
+ }
else
{
if ((attr = ippFindAttribute(supported, "printer-resolution-default", IPP_TAG_RESOLUTION)) != NULL)
cupsFilePrintf(fp, "*DefaultResolution: %s\n", ppdname);
- cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality: PickOne\n"
- "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
- "*%s.Translation cupsPrintQuality/%s: \"\"\n"
- "*DefaultcupsPrintQuality: Normal\n", lang->language, _cupsLangString(lang, _("Print Quality")));
+ cupsFilePuts(fp, "*OpenUI *cupsPrintQuality: PickOne\n"
+ "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
+ "*DefaultcupsPrintQuality: Normal\n");
if (ippContainsInteger(quality, IPP_QUALITY_DRAFT))
{
- cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Draft/%s: \"\"\n", xres, yres, lang->language, _cupsLangString(lang, _("Draft")));
+ cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*", xres, yres);
have_qdraft = 1;
}
- cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Normal/%s: \"\"\n", xres, yres, lang->language, _cupsLangString(lang, _("Normal")));
+ cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres);
if (ippContainsInteger(quality, IPP_QUALITY_HIGH))
{
- cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality High/%s: \"\"\n", xres, yres, lang->language, _cupsLangString(lang, _("High")));
+ cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres);
have_qhigh = 1;
}
cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n");
{
keyword = ippGetString(attr, i, NULL);
-#define PRINTF_COLORMODEL if (!wrote_color) { cupsFilePrintf(fp, "*OpenUI *ColorModel: PickOne\n*OrderDependency: 10 AnySetup *ColorModel\n*%s.Translation ColorModel/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Color Mode"))); wrote_color = 1; }
-#define PRINTF_COLOROPTION(name,text,cspace,bpp) { cupsFilePrintf(fp, "*ColorModel %s: \"<</cupsColorSpace %d/cupsBitsPerColor %d/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n", name, cspace, bpp); cupsFilePrintf(fp, "*%s.ColorModel %s/%s: \"\"\n", lang->language, name, _cupsLangString(lang, text)); }
+#define PRINTF_COLORMODEL if (!wrote_color) { cupsFilePuts(fp, "*OpenUI *ColorModel: PickOne\n*OrderDependency: 10 AnySetup *ColorModel\n"); wrote_color = 1; }
+#define PRINTF_COLOROPTION(name,text,cspace,bpp) cupsFilePrintf(fp, "*ColorModel %s/%s: \"<</cupsColorSpace %d/cupsBitsPerColor %d/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n", name, text, cspace, bpp);
if (!strcasecmp(keyword, "black_1") || !strcmp(keyword, "bi-level") || !strcmp(keyword, "process-bi-level"))
{
if ((attr = ippFindAttribute(supported, "sides-supported", IPP_TAG_KEYWORD)) != NULL && ippContainsString(attr, "two-sided-long-edge"))
{
- cupsFilePrintf(fp, "*OpenUI *Duplex: PickOne\n"
- "*OrderDependency: 10 AnySetup *Duplex\n"
- "*%s.Translation Duplex/%s: \"\"\n"
- "*DefaultDuplex: None\n"
- "*Duplex None: \"<</Duplex false>>setpagedevice\"\n"
- "*%s.Duplex None/%s: \"\"\n"
- "*Duplex DuplexNoTumble: \"<</Duplex true/Tumble false>>setpagedevice\"\n"
- "*%s.Duplex DuplexNoTumble/%s: \"\"\n"
- "*Duplex DuplexTumble: \"<</Duplex true/Tumble true>>setpagedevice\"\n"
- "*%s.Duplex DuplexTumble/%s: \"\"\n"
- "*CloseUI: *Duplex\n", lang->language, _cupsLangString(lang, _("2-Sided Printing")), lang->language, _cupsLangString(lang, _("Off (1-Sided)")), lang->language, _cupsLangString(lang, _("Long-Edge (Portrait)")), lang->language, _cupsLangString(lang, _("Short-Edge (Landscape)")));
+ cupsFilePuts(fp, "*OpenUI *Duplex: PickOne\n"
+ "*OrderDependency: 10 AnySetup *Duplex\n"
+ "*DefaultDuplex: None\n"
+ "*Duplex None: \"<</Duplex false>>setpagedevice\"\n"
+ "*Duplex DuplexNoTumble: \"<</Duplex true/Tumble false>>setpagedevice\"\n"
+ "*Duplex DuplexTumble: \"<</Duplex true/Tumble true>>setpagedevice\"\n"
+ "*CloseUI: *Duplex\n");
if ((attr = ippFindAttribute(supported, "urf-supported", IPP_TAG_KEYWORD)) != NULL)
{
pwg_ppdize_name(keyword, ppdname, sizeof(ppdname));
snprintf(msgid, sizeof(msgid), "output-bin.%s", keyword);
- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
- msgstr = keyword;
cupsFilePrintf(fp, "*OutputBin %s: \"\"\n", ppdname);
- cupsFilePrintf(fp, "*%s.OutputBin %s/%s: \"\"\n", lang->language, ppdname, msgstr);
+ ppd_put_strings(fp, langs, "OutputBin", ppdname, msgid);
if ((tray_ptr = ippGetOctetString(trays, i, &tray_len)) != NULL)
{
cupsFilePuts(fp, "*OpenUI *StapleLocation: PickOne\n");
cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *StapleLocation\n");
- cupsFilePrintf(fp, "*%s.Translation StapleLocation/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Staple")));
+ ppd_put_strings(fp, langs, "Translation", "StapleLocation", "finishings.4");
cupsFilePuts(fp, "*DefaultStapleLocation: None\n");
cupsFilePuts(fp, "*StapleLocation None: \"\"\n");
- cupsFilePrintf(fp, "*%s.StapleLocation None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
+ ppd_put_strings(fp, langs, "StapleLocation", "None", "finishings.3");
for (; i < count; i ++)
{
cupsArrayAdd(names, (char *)keyword);
snprintf(msgid, sizeof(msgid), "finishings.%d", value);
- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
- msgstr = keyword;
if (value >= IPP_FINISHINGS_NONE && value <= IPP_FINISHINGS_LAMINATE)
ppd_keyword = base_keywords[value - IPP_FINISHINGS_NONE];
continue;
cupsFilePrintf(fp, "*StapleLocation %s: \"\"\n", ppd_keyword);
- cupsFilePrintf(fp, "*%s.StapleLocation %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr);
+ ppd_put_strings(fp, langs, "StapleLocation", ppd_keyword, msgid);
cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*StapleLocation %s\"\n", value, keyword, ppd_keyword);
}
cupsFilePuts(fp, "*OpenUI *FoldType: PickOne\n");
cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *FoldType\n");
- cupsFilePrintf(fp, "*%s.Translation FoldType/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Fold")));
+ ppd_put_strings(fp, langs, "Translation", "FoldType", "finishings.10");
cupsFilePuts(fp, "*DefaultFoldType: None\n");
cupsFilePuts(fp, "*FoldType None: \"\"\n");
- cupsFilePrintf(fp, "*%s.FoldType None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
+ ppd_put_strings(fp, langs, "FoldType", "None", "finishings.3");
for (; i < count; i ++)
{
cupsArrayAdd(names, (char *)keyword);
snprintf(msgid, sizeof(msgid), "finishings.%d", value);
- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
- msgstr = keyword;
if (value >= IPP_FINISHINGS_NONE && value <= IPP_FINISHINGS_LAMINATE)
ppd_keyword = base_keywords[value - IPP_FINISHINGS_NONE];
continue;
cupsFilePrintf(fp, "*FoldType %s: \"\"\n", ppd_keyword);
- cupsFilePrintf(fp, "*%s.FoldType %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr);
+ ppd_put_strings(fp, langs, "FoldType", ppd_keyword, msgid);
cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*FoldType %s\"\n", value, keyword, ppd_keyword);
}
cupsFilePuts(fp, "*OpenUI *PunchMedia: PickOne\n");
cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *PunchMedia\n");
- cupsFilePrintf(fp, "*%s.Translation PunchMedia/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Punch")));
+ ppd_put_strings(fp, langs, "Translation", "PunchMedia", "finishings.5");
cupsFilePuts(fp, "*DefaultPunchMedia: None\n");
cupsFilePuts(fp, "*PunchMedia None: \"\"\n");
- cupsFilePrintf(fp, "*%s.PunchMedia None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
+ ppd_put_strings(fp, langs, "PunchMedia", "None", "finishings.3");
for (i = 0; i < count; i ++)
{
cupsArrayAdd(names, (char *)keyword);
snprintf(msgid, sizeof(msgid), "finishings.%d", value);
- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
- msgstr = keyword;
if (value >= IPP_FINISHINGS_NONE && value <= IPP_FINISHINGS_LAMINATE)
ppd_keyword = base_keywords[value - IPP_FINISHINGS_NONE];
continue;
cupsFilePrintf(fp, "*PunchMedia %s: \"\"\n", ppd_keyword);
- cupsFilePrintf(fp, "*%s.PunchMedia %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr);
+ ppd_put_strings(fp, langs, "PunchMedia", ppd_keyword, msgid);
cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*PunchMedia %s\"\n", value, keyword, ppd_keyword);
}
cupsFilePuts(fp, "*OpenUI *Booklet: Boolean\n");
cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *Booklet\n");
- cupsFilePrintf(fp, "*%s.Translation Booklet/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Booklet")));
+ ppd_put_strings(fp, langs, "Translation", "StapleLocation", "finishings.13");
cupsFilePuts(fp, "*DefaultBooklet: False\n");
cupsFilePuts(fp, "*Booklet False: \"\"\n");
cupsFilePuts(fp, "*Booklet True: \"\"\n");
cupsFilePuts(fp, "*OpenUI *CutMedia: PickOne\n");
cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *CutMedia\n");
- cupsFilePrintf(fp, "*%s.Translation CutMedia/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Cut")));
+ ppd_put_strings(fp, langs, "Translation", "CutMedia", "finishings.11");
cupsFilePuts(fp, "*DefaultCutMedia: None\n");
cupsFilePuts(fp, "*CutMedia None: \"\"\n");
- cupsFilePrintf(fp, "*%s.CutMedia None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
+ ppd_put_strings(fp, langs, "CutMedia", "None", "finishings.3");
for (i = 0; i < count; i ++)
{
cupsArrayAdd(names, (char *)keyword);
snprintf(msgid, sizeof(msgid), "finishings.%d", value);
- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
- msgstr = keyword;
if (value == IPP_FINISHINGS_TRIM)
ppd_keyword = "Auto";
ppd_keyword = trim_keywords[value - IPP_FINISHINGS_TRIM_AFTER_PAGES];
cupsFilePrintf(fp, "*CutMedia %s: \"\"\n", ppd_keyword);
- cupsFilePrintf(fp, "*%s.CutMedia %s/%s: \"\"\n", lang->language, ppd_keyword, msgstr);
+ ppd_put_strings(fp, langs, "CutMedia", ppd_keyword, msgid);
cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*CutMedia %s\"\n", value, keyword, ppd_keyword);
}
cupsFilePuts(fp, "*OpenUI *cupsFinishingTemplate: PickOne\n");
cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *cupsFinishingTemplate\n");
- cupsFilePrintf(fp, "*%s.Translation cupsFinishingTemplate/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Finishing Preset")));
+ ppd_put_strings(fp, langs, "Translation", "cupsFinishingTemplate", "finishing-template");
cupsFilePuts(fp, "*DefaultcupsFinishingTemplate: none\n");
cupsFilePuts(fp, "*cupsFinishingTemplate none: \"\"\n");
- cupsFilePrintf(fp, "*%s.cupsFinishingTemplate none/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None")));
+ ppd_put_strings(fp, langs, "cupsFinishingTemplate", "none", "finishings.3");
templates = cupsArrayNew((cups_array_func_t)_cupsArrayStrcmp, NULL);
count = ippGetCount(attr);
cupsArrayAdd(templates, (void *)keyword);
snprintf(msgid, sizeof(msgid), "finishing-template.%s", keyword);
- if ((msgstr = _cupsLangString(lang, msgid)) == msgid || !strcmp(msgid, msgstr))
- if ((msgstr = _cupsMessageLookup(strings, msgid)) == msgid)
- msgstr = keyword;
cupsFilePrintf(fp, "*cupsFinishingTemplate %s: \"\n", keyword);
for (finishing_attr = ippFirstAttribute(finishing_col); finishing_attr; finishing_attr = ippNextAttribute(finishing_col))
}
}
cupsFilePuts(fp, "\"\n");
- cupsFilePrintf(fp, "*%s.cupsFinishingTemplate %s/%s: \"\"\n", lang->language, keyword, msgstr);
+ ppd_put_strings(fp, langs, "cupsFinishingTemplate", keyword, msgid);
cupsFilePuts(fp, "*End\n");
}
cupsFilePrintf(fp, " %s", fin_option);
cupsFilePuts(fp, "\"\n");
- cupsFilePuts(fp, "*cupsUIResolver finishing-template: \"*cupsFinishingTemplate None");
+ cupsFilePuts(fp, "*cupsUIResolver finishing-template: \"*cupsFinishingTemplate none");
for (fin_option = (const char *)cupsArrayFirst(fin_options); fin_option; fin_option = (const char *)cupsArrayNext(fin_options))
cupsFilePrintf(fp, " %s None", fin_option);
cupsFilePuts(fp, "\"\n");
{
ipp_t *preset = ippGetCollection(attr, i);
/* Preset collection */
- const char *preset_name = ippGetString(ippFindAttribute(preset, "preset-name", IPP_TAG_ZERO), 0, NULL),
+ const char *preset_name = ippGetString(ippFindAttribute(preset, "preset-name", IPP_TAG_ZERO), 0, NULL);
/* Preset name */
- *localized_name; /* Localized preset name */
ipp_attribute_t *member; /* Member attribute in preset */
const char *member_name; /* Member attribute name */
char member_value[256]; /* Member attribute value */
cupsFilePuts(fp, "\"\n*End\n");
- if ((localized_name = _cupsMessageLookup(strings, preset_name)) != preset_name)
- cupsFilePrintf(fp, "*%s.APPrinterPreset %s/%s: \"\"\n", lang->language, preset_name, localized_name);
+// if ((localized_name = _cupsMessageLookup(strings, preset_name)) != preset_name)
+// cupsFilePrintf(fp, "*%s.APPrinterPreset %s/%s: \"\"\n", lang->language, preset_name, localized_name);
}
}
cupsFileClose(fp);
- _cupsMessageFree(strings);
+ for (lang = langs; lang;)
+ {
+ cups_lang_t *next = lang->next;
+
+ cupsArrayDelete(lang->strings);
+ free(lang);
+
+ lang = next;
+ }
return (buffer);
bad_ppd:
cupsFileClose(fp);
+
+ for (lang = langs; lang;)
+ {
+ cups_lang_t *next = lang->next;
+
+ cupsArrayDelete(lang->strings);
+ free(lang);
+
+ lang = next;
+ }
+
unlink(buffer);
*buffer = '\0';
- _cupsMessageFree(strings);
-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Printer does not support required IPP attributes or document formats."), 1);
return (NULL);
}
+/*
+ * 'cups_get_languages()' - Get the languages to load for PPDs.
+ */
+
+static cups_array_t * /* O - Array of languages */
+cups_get_languages(void)
+{
+ cups_array_t *languages = NULL; /* Array of languages */
+ cups_file_t *fp; /* CUPS_SERVERROOT/cups-files.conf file */
+ char filename[1024]; /* Filename */
+ _cups_globals_t *cg = _cupsGlobals(); /* Global data */
+
+
+ snprintf(filename, sizeof(filename), "%s/cups-files.conf", cg->cups_serverroot);
+
+ if ((fp = cupsFileOpen(filename, "r")) != NULL)
+ {
+ /*
+ * Read the cups-files.conf file, looking for a Languages directive...
+ */
+
+ char line[1024], /* Line from file */
+ *value; /* Value from line */
+ int linenum = 0; /* Current line number */
+
+ while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
+ {
+ if (!_cups_strcasecmp(line, "Languages") && value)
+ {
+ languages = cupsArrayNewStrings(value, ' ');
+ break;
+ }
+ }
+
+ cupsFileClose(fp);
+ }
+
+ if (!languages)
+ {
+ /*
+ * No Languages directive in CUPS_SERVERROOT/cups-files.conf, so use the
+ * current locale...
+ */
+
+ cups_lang_t *deflang; /* Default language */
+
+ languages = cupsArrayNewStrings(NULL, ' ');
+ deflang = cupsLangDefault();
+
+ cupsArrayAdd(languages, deflang->language);
+ }
+
+ return (languages);
+}
+
+
+/*
+ * 'cups_get_strings()' - Get the strings for the specified language.
+ */
+
+static cups_lang_t * /* O - Language data */
+cups_get_strings(
+ http_t **http, /* IO - Current HTTP connection */
+ const char *printer_uri, /* I - Printer URI */
+ const char *language) /* I - Language name */
+{
+ cups_lang_t *lang = NULL; /* Language data */
+ char resource[256]; /* Resource path for printer */
+ ipp_t *request, /* IPP request */
+ *response = NULL; /* IPP response */
+ const char *strings_uri; /* "printer-strings-uri" value */
+ char strings_file[1024] = "";/* Strings filename */
+
+
+ /*
+ * Connect to the printer...
+ */
+
+ if (!cups_connect(http, printer_uri, resource, sizeof(resource)))
+ goto done;
+
+ /*
+ * Get the URL for the corresponding language strings...
+ */
+
+ request = ippNew();
+ ippSetOperation(request, IPP_OP_GET_PRINTER_ATTRIBUTES);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", /*language*/NULL, "utf-8");
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", /*language*/NULL, language);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", /*language*/NULL, printer_uri);
+
+ response = cupsDoRequest(*http, request, resource);
+
+ if ((strings_uri = ippGetString(ippFindAttribute(response, "printer-strings-uri", IPP_TAG_URI), 0, NULL)) != NULL)
+ {
+ /*
+ * Download the strings file...
+ */
+
+ if (!cups_get_url(http, strings_uri, ".strings", strings_file, sizeof(strings_file)))
+ goto done;
+
+ /*
+ * Allocate memory...
+ */
+
+ if ((lang = (cups_lang_t *)calloc(1, sizeof(cups_lang_t))) == NULL)
+ goto done;
+
+ /*
+ * Load the strings...
+ */
+
+ cupsCopyString(lang->language, language, sizeof(lang->language));
+ lang->strings = _cupsMessageLoad(strings_file, _CUPS_MESSAGE_STRINGS);
+ }
+
+ done:
+
+ ippDelete(response);
+
+ if (strings_file[0])
+ unlink(strings_file);
+
+ return (lang);
+}
+
+
/*
* 'cups_get_url()' - Get a copy of the file at the given URL.
*/
static int /* O - 1 on success, 0 on failure */
cups_get_url(http_t **http, /* IO - Current HTTP connection */
const char *url, /* I - URL to get */
+ const char *suffix, /* I - Filename suffix */
char *name, /* I - Temporary filename */
size_t namesize) /* I - Size of temporary filename buffer */
{
if (!cups_connect(http, url, resource, sizeof(resource)))
return (0);
- if ((fd = cupsTempFd(name, (int)namesize)) < 0)
+ if ((fd = cupsCreateTempFd("ippeve", suffix, name, namesize)) < 0)
return (0);
status = cupsGetFd(*http, resource, fd);
}
+/*
+ * 'ppd_put_strings()' - Write localization attributes to a PPD file.
+ */
+
+static void
+ppd_put_strings(cups_file_t *fp, /* I - PPD file */
+ cups_lang_t *langs, /* I - Languages */
+ const char *ppd_option,/* I - PPD option */
+ const char *ppd_choice,/* I - PPD choice */
+ const char *pwg_msgid) /* I - PWG message ID */
+{
+ cups_lang_t *lang; /* Current language */
+ const char *text; /* Localized text */
+
+
+ for (lang = langs; lang; lang = lang->next)
+ {
+ if ((text = _cupsLangString(lang, pwg_msgid)) != pwg_msgid)
+ cupsFilePrintf(fp, "*%s.%s %s/%s: \"\"\n", lang->language, ppd_option, ppd_choice, text);
+ }
+}
+
+
/*
* 'pwg_add_finishing()' - Add a finishings value.
*/