1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * PPD localization routines for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright 2007-2018 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright 1997-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker * information.
9*5e7646d2SAndroid Build Coastguard Worker *
10*5e7646d2SAndroid Build Coastguard Worker * PostScript is a trademark of Adobe Systems, Inc.
11*5e7646d2SAndroid Build Coastguard Worker */
12*5e7646d2SAndroid Build Coastguard Worker
13*5e7646d2SAndroid Build Coastguard Worker /*
14*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers.
15*5e7646d2SAndroid Build Coastguard Worker */
16*5e7646d2SAndroid Build Coastguard Worker
17*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
18*5e7646d2SAndroid Build Coastguard Worker #include "ppd-private.h"
19*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
20*5e7646d2SAndroid Build Coastguard Worker
21*5e7646d2SAndroid Build Coastguard Worker
22*5e7646d2SAndroid Build Coastguard Worker /*
23*5e7646d2SAndroid Build Coastguard Worker * Local functions...
24*5e7646d2SAndroid Build Coastguard Worker */
25*5e7646d2SAndroid Build Coastguard Worker
26*5e7646d2SAndroid Build Coastguard Worker static cups_lang_t *ppd_ll_CC(char *ll_CC, size_t ll_CC_size);
27*5e7646d2SAndroid Build Coastguard Worker
28*5e7646d2SAndroid Build Coastguard Worker
29*5e7646d2SAndroid Build Coastguard Worker /*
30*5e7646d2SAndroid Build Coastguard Worker * 'ppdLocalize()' - Localize the PPD file to the current locale.
31*5e7646d2SAndroid Build Coastguard Worker *
32*5e7646d2SAndroid Build Coastguard Worker * All groups, options, and choices are localized, as are ICC profile
33*5e7646d2SAndroid Build Coastguard Worker * descriptions, printer presets, and custom option parameters. Each
34*5e7646d2SAndroid Build Coastguard Worker * localized string uses the UTF-8 character encoding.
35*5e7646d2SAndroid Build Coastguard Worker *
36*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.2/macOS 10.5@
37*5e7646d2SAndroid Build Coastguard Worker */
38*5e7646d2SAndroid Build Coastguard Worker
39*5e7646d2SAndroid Build Coastguard Worker int /* O - 0 on success, -1 on error */
ppdLocalize(ppd_file_t * ppd)40*5e7646d2SAndroid Build Coastguard Worker ppdLocalize(ppd_file_t *ppd) /* I - PPD file */
41*5e7646d2SAndroid Build Coastguard Worker {
42*5e7646d2SAndroid Build Coastguard Worker int i, j, k; /* Looping vars */
43*5e7646d2SAndroid Build Coastguard Worker ppd_group_t *group; /* Current group */
44*5e7646d2SAndroid Build Coastguard Worker ppd_option_t *option; /* Current option */
45*5e7646d2SAndroid Build Coastguard Worker ppd_choice_t *choice; /* Current choice */
46*5e7646d2SAndroid Build Coastguard Worker ppd_coption_t *coption; /* Current custom option */
47*5e7646d2SAndroid Build Coastguard Worker ppd_cparam_t *cparam; /* Current custom parameter */
48*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t *attr, /* Current attribute */
49*5e7646d2SAndroid Build Coastguard Worker *locattr; /* Localized attribute */
50*5e7646d2SAndroid Build Coastguard Worker char ckeyword[PPD_MAX_NAME], /* Custom keyword */
51*5e7646d2SAndroid Build Coastguard Worker ll_CC[6]; /* Language + country locale */
52*5e7646d2SAndroid Build Coastguard Worker
53*5e7646d2SAndroid Build Coastguard Worker
54*5e7646d2SAndroid Build Coastguard Worker /*
55*5e7646d2SAndroid Build Coastguard Worker * Range check input...
56*5e7646d2SAndroid Build Coastguard Worker */
57*5e7646d2SAndroid Build Coastguard Worker
58*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("ppdLocalize(ppd=%p)", ppd));
59*5e7646d2SAndroid Build Coastguard Worker
60*5e7646d2SAndroid Build Coastguard Worker if (!ppd)
61*5e7646d2SAndroid Build Coastguard Worker return (-1);
62*5e7646d2SAndroid Build Coastguard Worker
63*5e7646d2SAndroid Build Coastguard Worker /*
64*5e7646d2SAndroid Build Coastguard Worker * Get the default language...
65*5e7646d2SAndroid Build Coastguard Worker */
66*5e7646d2SAndroid Build Coastguard Worker
67*5e7646d2SAndroid Build Coastguard Worker ppd_ll_CC(ll_CC, sizeof(ll_CC));
68*5e7646d2SAndroid Build Coastguard Worker
69*5e7646d2SAndroid Build Coastguard Worker /*
70*5e7646d2SAndroid Build Coastguard Worker * Now lookup all of the groups, options, choices, etc.
71*5e7646d2SAndroid Build Coastguard Worker */
72*5e7646d2SAndroid Build Coastguard Worker
73*5e7646d2SAndroid Build Coastguard Worker for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
74*5e7646d2SAndroid Build Coastguard Worker {
75*5e7646d2SAndroid Build Coastguard Worker if ((locattr = _ppdLocalizedAttr(ppd, "Translation", group->name,
76*5e7646d2SAndroid Build Coastguard Worker ll_CC)) != NULL)
77*5e7646d2SAndroid Build Coastguard Worker strlcpy(group->text, locattr->text, sizeof(group->text));
78*5e7646d2SAndroid Build Coastguard Worker
79*5e7646d2SAndroid Build Coastguard Worker for (j = group->num_options, option = group->options; j > 0; j --, option ++)
80*5e7646d2SAndroid Build Coastguard Worker {
81*5e7646d2SAndroid Build Coastguard Worker if ((locattr = _ppdLocalizedAttr(ppd, "Translation", option->keyword,
82*5e7646d2SAndroid Build Coastguard Worker ll_CC)) != NULL)
83*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, locattr->text, sizeof(option->text));
84*5e7646d2SAndroid Build Coastguard Worker
85*5e7646d2SAndroid Build Coastguard Worker for (k = option->num_choices, choice = option->choices;
86*5e7646d2SAndroid Build Coastguard Worker k > 0;
87*5e7646d2SAndroid Build Coastguard Worker k --, choice ++)
88*5e7646d2SAndroid Build Coastguard Worker {
89*5e7646d2SAndroid Build Coastguard Worker if (strcmp(choice->choice, "Custom") ||
90*5e7646d2SAndroid Build Coastguard Worker !ppdFindCustomOption(ppd, option->keyword))
91*5e7646d2SAndroid Build Coastguard Worker locattr = _ppdLocalizedAttr(ppd, option->keyword, choice->choice,
92*5e7646d2SAndroid Build Coastguard Worker ll_CC);
93*5e7646d2SAndroid Build Coastguard Worker else
94*5e7646d2SAndroid Build Coastguard Worker {
95*5e7646d2SAndroid Build Coastguard Worker snprintf(ckeyword, sizeof(ckeyword), "Custom%s", option->keyword);
96*5e7646d2SAndroid Build Coastguard Worker
97*5e7646d2SAndroid Build Coastguard Worker locattr = _ppdLocalizedAttr(ppd, ckeyword, "True", ll_CC);
98*5e7646d2SAndroid Build Coastguard Worker }
99*5e7646d2SAndroid Build Coastguard Worker
100*5e7646d2SAndroid Build Coastguard Worker if (locattr)
101*5e7646d2SAndroid Build Coastguard Worker strlcpy(choice->text, locattr->text, sizeof(choice->text));
102*5e7646d2SAndroid Build Coastguard Worker }
103*5e7646d2SAndroid Build Coastguard Worker }
104*5e7646d2SAndroid Build Coastguard Worker }
105*5e7646d2SAndroid Build Coastguard Worker
106*5e7646d2SAndroid Build Coastguard Worker /*
107*5e7646d2SAndroid Build Coastguard Worker * Translate any custom parameters...
108*5e7646d2SAndroid Build Coastguard Worker */
109*5e7646d2SAndroid Build Coastguard Worker
110*5e7646d2SAndroid Build Coastguard Worker for (coption = (ppd_coption_t *)cupsArrayFirst(ppd->coptions);
111*5e7646d2SAndroid Build Coastguard Worker coption;
112*5e7646d2SAndroid Build Coastguard Worker coption = (ppd_coption_t *)cupsArrayNext(ppd->coptions))
113*5e7646d2SAndroid Build Coastguard Worker {
114*5e7646d2SAndroid Build Coastguard Worker for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
115*5e7646d2SAndroid Build Coastguard Worker cparam;
116*5e7646d2SAndroid Build Coastguard Worker cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
117*5e7646d2SAndroid Build Coastguard Worker {
118*5e7646d2SAndroid Build Coastguard Worker snprintf(ckeyword, sizeof(ckeyword), "ParamCustom%s", coption->keyword);
119*5e7646d2SAndroid Build Coastguard Worker
120*5e7646d2SAndroid Build Coastguard Worker if ((locattr = _ppdLocalizedAttr(ppd, ckeyword, cparam->name,
121*5e7646d2SAndroid Build Coastguard Worker ll_CC)) != NULL)
122*5e7646d2SAndroid Build Coastguard Worker strlcpy(cparam->text, locattr->text, sizeof(cparam->text));
123*5e7646d2SAndroid Build Coastguard Worker }
124*5e7646d2SAndroid Build Coastguard Worker }
125*5e7646d2SAndroid Build Coastguard Worker
126*5e7646d2SAndroid Build Coastguard Worker /*
127*5e7646d2SAndroid Build Coastguard Worker * Translate ICC profile names...
128*5e7646d2SAndroid Build Coastguard Worker */
129*5e7646d2SAndroid Build Coastguard Worker
130*5e7646d2SAndroid Build Coastguard Worker if ((attr = ppdFindAttr(ppd, "APCustomColorMatchingName", NULL)) != NULL)
131*5e7646d2SAndroid Build Coastguard Worker {
132*5e7646d2SAndroid Build Coastguard Worker if ((locattr = _ppdLocalizedAttr(ppd, "APCustomColorMatchingName",
133*5e7646d2SAndroid Build Coastguard Worker attr->spec, ll_CC)) != NULL)
134*5e7646d2SAndroid Build Coastguard Worker strlcpy(attr->text, locattr->text, sizeof(attr->text));
135*5e7646d2SAndroid Build Coastguard Worker }
136*5e7646d2SAndroid Build Coastguard Worker
137*5e7646d2SAndroid Build Coastguard Worker for (attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
138*5e7646d2SAndroid Build Coastguard Worker attr;
139*5e7646d2SAndroid Build Coastguard Worker attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
140*5e7646d2SAndroid Build Coastguard Worker {
141*5e7646d2SAndroid Build Coastguard Worker cupsArraySave(ppd->sorted_attrs);
142*5e7646d2SAndroid Build Coastguard Worker
143*5e7646d2SAndroid Build Coastguard Worker if ((locattr = _ppdLocalizedAttr(ppd, "cupsICCProfile", attr->spec,
144*5e7646d2SAndroid Build Coastguard Worker ll_CC)) != NULL)
145*5e7646d2SAndroid Build Coastguard Worker strlcpy(attr->text, locattr->text, sizeof(attr->text));
146*5e7646d2SAndroid Build Coastguard Worker
147*5e7646d2SAndroid Build Coastguard Worker cupsArrayRestore(ppd->sorted_attrs);
148*5e7646d2SAndroid Build Coastguard Worker }
149*5e7646d2SAndroid Build Coastguard Worker
150*5e7646d2SAndroid Build Coastguard Worker /*
151*5e7646d2SAndroid Build Coastguard Worker * Translate printer presets...
152*5e7646d2SAndroid Build Coastguard Worker */
153*5e7646d2SAndroid Build Coastguard Worker
154*5e7646d2SAndroid Build Coastguard Worker for (attr = ppdFindAttr(ppd, "APPrinterPreset", NULL);
155*5e7646d2SAndroid Build Coastguard Worker attr;
156*5e7646d2SAndroid Build Coastguard Worker attr = ppdFindNextAttr(ppd, "APPrinterPreset", NULL))
157*5e7646d2SAndroid Build Coastguard Worker {
158*5e7646d2SAndroid Build Coastguard Worker cupsArraySave(ppd->sorted_attrs);
159*5e7646d2SAndroid Build Coastguard Worker
160*5e7646d2SAndroid Build Coastguard Worker if ((locattr = _ppdLocalizedAttr(ppd, "APPrinterPreset", attr->spec,
161*5e7646d2SAndroid Build Coastguard Worker ll_CC)) != NULL)
162*5e7646d2SAndroid Build Coastguard Worker strlcpy(attr->text, locattr->text, sizeof(attr->text));
163*5e7646d2SAndroid Build Coastguard Worker
164*5e7646d2SAndroid Build Coastguard Worker cupsArrayRestore(ppd->sorted_attrs);
165*5e7646d2SAndroid Build Coastguard Worker }
166*5e7646d2SAndroid Build Coastguard Worker
167*5e7646d2SAndroid Build Coastguard Worker return (0);
168*5e7646d2SAndroid Build Coastguard Worker }
169*5e7646d2SAndroid Build Coastguard Worker
170*5e7646d2SAndroid Build Coastguard Worker
171*5e7646d2SAndroid Build Coastguard Worker /*
172*5e7646d2SAndroid Build Coastguard Worker * 'ppdLocalizeAttr()' - Localize an attribute.
173*5e7646d2SAndroid Build Coastguard Worker *
174*5e7646d2SAndroid Build Coastguard Worker * This function uses the current locale to find the localized attribute for
175*5e7646d2SAndroid Build Coastguard Worker * the given main and option keywords. If no localized version of the
176*5e7646d2SAndroid Build Coastguard Worker * attribute exists for the current locale, the unlocalized version is returned.
177*5e7646d2SAndroid Build Coastguard Worker */
178*5e7646d2SAndroid Build Coastguard Worker
179*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t * /* O - Localized attribute or @code NULL@ if none exists */
ppdLocalizeAttr(ppd_file_t * ppd,const char * keyword,const char * spec)180*5e7646d2SAndroid Build Coastguard Worker ppdLocalizeAttr(ppd_file_t *ppd, /* I - PPD file */
181*5e7646d2SAndroid Build Coastguard Worker const char *keyword, /* I - Main keyword */
182*5e7646d2SAndroid Build Coastguard Worker const char *spec) /* I - Option keyword or @code NULL@ for none */
183*5e7646d2SAndroid Build Coastguard Worker {
184*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t *locattr; /* Localized attribute */
185*5e7646d2SAndroid Build Coastguard Worker char ll_CC[6]; /* Language + country locale */
186*5e7646d2SAndroid Build Coastguard Worker
187*5e7646d2SAndroid Build Coastguard Worker
188*5e7646d2SAndroid Build Coastguard Worker /*
189*5e7646d2SAndroid Build Coastguard Worker * Get the default language...
190*5e7646d2SAndroid Build Coastguard Worker */
191*5e7646d2SAndroid Build Coastguard Worker
192*5e7646d2SAndroid Build Coastguard Worker ppd_ll_CC(ll_CC, sizeof(ll_CC));
193*5e7646d2SAndroid Build Coastguard Worker
194*5e7646d2SAndroid Build Coastguard Worker /*
195*5e7646d2SAndroid Build Coastguard Worker * Find the localized attribute...
196*5e7646d2SAndroid Build Coastguard Worker */
197*5e7646d2SAndroid Build Coastguard Worker
198*5e7646d2SAndroid Build Coastguard Worker if (spec)
199*5e7646d2SAndroid Build Coastguard Worker locattr = _ppdLocalizedAttr(ppd, keyword, spec, ll_CC);
200*5e7646d2SAndroid Build Coastguard Worker else
201*5e7646d2SAndroid Build Coastguard Worker locattr = _ppdLocalizedAttr(ppd, "Translation", keyword, ll_CC);
202*5e7646d2SAndroid Build Coastguard Worker
203*5e7646d2SAndroid Build Coastguard Worker if (!locattr)
204*5e7646d2SAndroid Build Coastguard Worker locattr = ppdFindAttr(ppd, keyword, spec);
205*5e7646d2SAndroid Build Coastguard Worker
206*5e7646d2SAndroid Build Coastguard Worker return (locattr);
207*5e7646d2SAndroid Build Coastguard Worker }
208*5e7646d2SAndroid Build Coastguard Worker
209*5e7646d2SAndroid Build Coastguard Worker
210*5e7646d2SAndroid Build Coastguard Worker /*
211*5e7646d2SAndroid Build Coastguard Worker * 'ppdLocalizeIPPReason()' - Get the localized version of a cupsIPPReason
212*5e7646d2SAndroid Build Coastguard Worker * attribute.
213*5e7646d2SAndroid Build Coastguard Worker *
214*5e7646d2SAndroid Build Coastguard Worker * This function uses the current locale to find the corresponding reason
215*5e7646d2SAndroid Build Coastguard Worker * text or URI from the attribute value. If "scheme" is NULL or "text",
216*5e7646d2SAndroid Build Coastguard Worker * the returned value contains human-readable (UTF-8) text from the translation
217*5e7646d2SAndroid Build Coastguard Worker * string or attribute value. Otherwise the corresponding URI is returned.
218*5e7646d2SAndroid Build Coastguard Worker *
219*5e7646d2SAndroid Build Coastguard Worker * If no value of the requested scheme can be found, NULL is returned.
220*5e7646d2SAndroid Build Coastguard Worker *
221*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.3/macOS 10.5@
222*5e7646d2SAndroid Build Coastguard Worker */
223*5e7646d2SAndroid Build Coastguard Worker
224*5e7646d2SAndroid Build Coastguard Worker const char * /* O - Value or NULL if not found */
ppdLocalizeIPPReason(ppd_file_t * ppd,const char * reason,const char * scheme,char * buffer,size_t bufsize)225*5e7646d2SAndroid Build Coastguard Worker ppdLocalizeIPPReason(
226*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *ppd, /* I - PPD file */
227*5e7646d2SAndroid Build Coastguard Worker const char *reason, /* I - IPP reason keyword to look up */
228*5e7646d2SAndroid Build Coastguard Worker const char *scheme, /* I - URI scheme or NULL for text */
229*5e7646d2SAndroid Build Coastguard Worker char *buffer, /* I - Value buffer */
230*5e7646d2SAndroid Build Coastguard Worker size_t bufsize) /* I - Size of value buffer */
231*5e7646d2SAndroid Build Coastguard Worker {
232*5e7646d2SAndroid Build Coastguard Worker cups_lang_t *lang; /* Current language */
233*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t *locattr; /* Localized attribute */
234*5e7646d2SAndroid Build Coastguard Worker char ll_CC[6], /* Language + country locale */
235*5e7646d2SAndroid Build Coastguard Worker *bufptr, /* Pointer into buffer */
236*5e7646d2SAndroid Build Coastguard Worker *bufend, /* Pointer to end of buffer */
237*5e7646d2SAndroid Build Coastguard Worker *valptr; /* Pointer into value */
238*5e7646d2SAndroid Build Coastguard Worker int ch; /* Hex-encoded character */
239*5e7646d2SAndroid Build Coastguard Worker size_t schemelen; /* Length of scheme name */
240*5e7646d2SAndroid Build Coastguard Worker
241*5e7646d2SAndroid Build Coastguard Worker
242*5e7646d2SAndroid Build Coastguard Worker /*
243*5e7646d2SAndroid Build Coastguard Worker * Range check input...
244*5e7646d2SAndroid Build Coastguard Worker */
245*5e7646d2SAndroid Build Coastguard Worker
246*5e7646d2SAndroid Build Coastguard Worker if (buffer)
247*5e7646d2SAndroid Build Coastguard Worker *buffer = '\0';
248*5e7646d2SAndroid Build Coastguard Worker
249*5e7646d2SAndroid Build Coastguard Worker if (!ppd || !reason || (scheme && !*scheme) ||
250*5e7646d2SAndroid Build Coastguard Worker !buffer || bufsize < PPD_MAX_TEXT)
251*5e7646d2SAndroid Build Coastguard Worker return (NULL);
252*5e7646d2SAndroid Build Coastguard Worker
253*5e7646d2SAndroid Build Coastguard Worker /*
254*5e7646d2SAndroid Build Coastguard Worker * Get the default language...
255*5e7646d2SAndroid Build Coastguard Worker */
256*5e7646d2SAndroid Build Coastguard Worker
257*5e7646d2SAndroid Build Coastguard Worker lang = ppd_ll_CC(ll_CC, sizeof(ll_CC));
258*5e7646d2SAndroid Build Coastguard Worker
259*5e7646d2SAndroid Build Coastguard Worker /*
260*5e7646d2SAndroid Build Coastguard Worker * Find the localized attribute...
261*5e7646d2SAndroid Build Coastguard Worker */
262*5e7646d2SAndroid Build Coastguard Worker
263*5e7646d2SAndroid Build Coastguard Worker if ((locattr = _ppdLocalizedAttr(ppd, "cupsIPPReason", reason,
264*5e7646d2SAndroid Build Coastguard Worker ll_CC)) == NULL)
265*5e7646d2SAndroid Build Coastguard Worker locattr = ppdFindAttr(ppd, "cupsIPPReason", reason);
266*5e7646d2SAndroid Build Coastguard Worker
267*5e7646d2SAndroid Build Coastguard Worker if (!locattr)
268*5e7646d2SAndroid Build Coastguard Worker {
269*5e7646d2SAndroid Build Coastguard Worker if (lang && (!scheme || !strcmp(scheme, "text")) && strcmp(reason, "none"))
270*5e7646d2SAndroid Build Coastguard Worker {
271*5e7646d2SAndroid Build Coastguard Worker /*
272*5e7646d2SAndroid Build Coastguard Worker * Try to localize a standard printer-state-reason keyword...
273*5e7646d2SAndroid Build Coastguard Worker */
274*5e7646d2SAndroid Build Coastguard Worker
275*5e7646d2SAndroid Build Coastguard Worker char msgid[1024], /* State message identifier */
276*5e7646d2SAndroid Build Coastguard Worker *ptr; /* Pointer to state suffix */
277*5e7646d2SAndroid Build Coastguard Worker const char *message = NULL; /* Localized message */
278*5e7646d2SAndroid Build Coastguard Worker
279*5e7646d2SAndroid Build Coastguard Worker snprintf(msgid, sizeof(msgid), "printer-state-reasons.%s", reason);
280*5e7646d2SAndroid Build Coastguard Worker if ((ptr = strrchr(msgid, '-')) != NULL && (!strcmp(ptr, "-error") || !strcmp(ptr, "-report") || !strcmp(ptr, "-warning")))
281*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
282*5e7646d2SAndroid Build Coastguard Worker
283*5e7646d2SAndroid Build Coastguard Worker message = _cupsLangString(lang, msgid);
284*5e7646d2SAndroid Build Coastguard Worker
285*5e7646d2SAndroid Build Coastguard Worker if (message && strcmp(message, msgid))
286*5e7646d2SAndroid Build Coastguard Worker {
287*5e7646d2SAndroid Build Coastguard Worker strlcpy(buffer, _cupsLangString(lang, message), bufsize);
288*5e7646d2SAndroid Build Coastguard Worker return (buffer);
289*5e7646d2SAndroid Build Coastguard Worker }
290*5e7646d2SAndroid Build Coastguard Worker }
291*5e7646d2SAndroid Build Coastguard Worker
292*5e7646d2SAndroid Build Coastguard Worker return (NULL);
293*5e7646d2SAndroid Build Coastguard Worker }
294*5e7646d2SAndroid Build Coastguard Worker
295*5e7646d2SAndroid Build Coastguard Worker /*
296*5e7646d2SAndroid Build Coastguard Worker * Now find the value we need...
297*5e7646d2SAndroid Build Coastguard Worker */
298*5e7646d2SAndroid Build Coastguard Worker
299*5e7646d2SAndroid Build Coastguard Worker bufend = buffer + bufsize - 1;
300*5e7646d2SAndroid Build Coastguard Worker
301*5e7646d2SAndroid Build Coastguard Worker if (!scheme || !strcmp(scheme, "text"))
302*5e7646d2SAndroid Build Coastguard Worker {
303*5e7646d2SAndroid Build Coastguard Worker /*
304*5e7646d2SAndroid Build Coastguard Worker * Copy a text value (either the translation text or text:... URIs from
305*5e7646d2SAndroid Build Coastguard Worker * the value...
306*5e7646d2SAndroid Build Coastguard Worker */
307*5e7646d2SAndroid Build Coastguard Worker
308*5e7646d2SAndroid Build Coastguard Worker strlcpy(buffer, locattr->text, bufsize);
309*5e7646d2SAndroid Build Coastguard Worker
310*5e7646d2SAndroid Build Coastguard Worker for (valptr = locattr->value, bufptr = buffer; *valptr && bufptr < bufend;)
311*5e7646d2SAndroid Build Coastguard Worker {
312*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(valptr, "text:", 5))
313*5e7646d2SAndroid Build Coastguard Worker {
314*5e7646d2SAndroid Build Coastguard Worker /*
315*5e7646d2SAndroid Build Coastguard Worker * Decode text: URI and add to the buffer...
316*5e7646d2SAndroid Build Coastguard Worker */
317*5e7646d2SAndroid Build Coastguard Worker
318*5e7646d2SAndroid Build Coastguard Worker valptr += 5;
319*5e7646d2SAndroid Build Coastguard Worker
320*5e7646d2SAndroid Build Coastguard Worker while (*valptr && !_cups_isspace(*valptr) && bufptr < bufend)
321*5e7646d2SAndroid Build Coastguard Worker {
322*5e7646d2SAndroid Build Coastguard Worker if (*valptr == '%' && isxdigit(valptr[1] & 255) &&
323*5e7646d2SAndroid Build Coastguard Worker isxdigit(valptr[2] & 255))
324*5e7646d2SAndroid Build Coastguard Worker {
325*5e7646d2SAndroid Build Coastguard Worker /*
326*5e7646d2SAndroid Build Coastguard Worker * Pull a hex-encoded character from the URI...
327*5e7646d2SAndroid Build Coastguard Worker */
328*5e7646d2SAndroid Build Coastguard Worker
329*5e7646d2SAndroid Build Coastguard Worker valptr ++;
330*5e7646d2SAndroid Build Coastguard Worker
331*5e7646d2SAndroid Build Coastguard Worker if (isdigit(*valptr & 255))
332*5e7646d2SAndroid Build Coastguard Worker ch = (*valptr - '0') << 4;
333*5e7646d2SAndroid Build Coastguard Worker else
334*5e7646d2SAndroid Build Coastguard Worker ch = (tolower(*valptr) - 'a' + 10) << 4;
335*5e7646d2SAndroid Build Coastguard Worker valptr ++;
336*5e7646d2SAndroid Build Coastguard Worker
337*5e7646d2SAndroid Build Coastguard Worker if (isdigit(*valptr & 255))
338*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = (char)(ch | (*valptr - '0'));
339*5e7646d2SAndroid Build Coastguard Worker else
340*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = (char)(ch | (tolower(*valptr) - 'a' + 10));
341*5e7646d2SAndroid Build Coastguard Worker valptr ++;
342*5e7646d2SAndroid Build Coastguard Worker }
343*5e7646d2SAndroid Build Coastguard Worker else if (*valptr == '+')
344*5e7646d2SAndroid Build Coastguard Worker {
345*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = ' ';
346*5e7646d2SAndroid Build Coastguard Worker valptr ++;
347*5e7646d2SAndroid Build Coastguard Worker }
348*5e7646d2SAndroid Build Coastguard Worker else
349*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = *valptr++;
350*5e7646d2SAndroid Build Coastguard Worker }
351*5e7646d2SAndroid Build Coastguard Worker }
352*5e7646d2SAndroid Build Coastguard Worker else
353*5e7646d2SAndroid Build Coastguard Worker {
354*5e7646d2SAndroid Build Coastguard Worker /*
355*5e7646d2SAndroid Build Coastguard Worker * Skip this URI...
356*5e7646d2SAndroid Build Coastguard Worker */
357*5e7646d2SAndroid Build Coastguard Worker
358*5e7646d2SAndroid Build Coastguard Worker while (*valptr && !_cups_isspace(*valptr))
359*5e7646d2SAndroid Build Coastguard Worker valptr++;
360*5e7646d2SAndroid Build Coastguard Worker }
361*5e7646d2SAndroid Build Coastguard Worker
362*5e7646d2SAndroid Build Coastguard Worker /*
363*5e7646d2SAndroid Build Coastguard Worker * Skip whitespace...
364*5e7646d2SAndroid Build Coastguard Worker */
365*5e7646d2SAndroid Build Coastguard Worker
366*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*valptr))
367*5e7646d2SAndroid Build Coastguard Worker valptr ++;
368*5e7646d2SAndroid Build Coastguard Worker }
369*5e7646d2SAndroid Build Coastguard Worker
370*5e7646d2SAndroid Build Coastguard Worker if (bufptr > buffer)
371*5e7646d2SAndroid Build Coastguard Worker *bufptr = '\0';
372*5e7646d2SAndroid Build Coastguard Worker
373*5e7646d2SAndroid Build Coastguard Worker return (buffer);
374*5e7646d2SAndroid Build Coastguard Worker }
375*5e7646d2SAndroid Build Coastguard Worker else
376*5e7646d2SAndroid Build Coastguard Worker {
377*5e7646d2SAndroid Build Coastguard Worker /*
378*5e7646d2SAndroid Build Coastguard Worker * Copy a URI...
379*5e7646d2SAndroid Build Coastguard Worker */
380*5e7646d2SAndroid Build Coastguard Worker
381*5e7646d2SAndroid Build Coastguard Worker schemelen = strlen(scheme);
382*5e7646d2SAndroid Build Coastguard Worker if (scheme[schemelen - 1] == ':') /* Force scheme to be just the name */
383*5e7646d2SAndroid Build Coastguard Worker schemelen --;
384*5e7646d2SAndroid Build Coastguard Worker
385*5e7646d2SAndroid Build Coastguard Worker for (valptr = locattr->value, bufptr = buffer; *valptr && bufptr < bufend;)
386*5e7646d2SAndroid Build Coastguard Worker {
387*5e7646d2SAndroid Build Coastguard Worker if ((!strncmp(valptr, scheme, schemelen) && valptr[schemelen] == ':') ||
388*5e7646d2SAndroid Build Coastguard Worker (*valptr == '/' && !strcmp(scheme, "file")))
389*5e7646d2SAndroid Build Coastguard Worker {
390*5e7646d2SAndroid Build Coastguard Worker /*
391*5e7646d2SAndroid Build Coastguard Worker * Copy URI...
392*5e7646d2SAndroid Build Coastguard Worker */
393*5e7646d2SAndroid Build Coastguard Worker
394*5e7646d2SAndroid Build Coastguard Worker while (*valptr && !_cups_isspace(*valptr) && bufptr < bufend)
395*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = *valptr++;
396*5e7646d2SAndroid Build Coastguard Worker
397*5e7646d2SAndroid Build Coastguard Worker *bufptr = '\0';
398*5e7646d2SAndroid Build Coastguard Worker
399*5e7646d2SAndroid Build Coastguard Worker return (buffer);
400*5e7646d2SAndroid Build Coastguard Worker }
401*5e7646d2SAndroid Build Coastguard Worker else
402*5e7646d2SAndroid Build Coastguard Worker {
403*5e7646d2SAndroid Build Coastguard Worker /*
404*5e7646d2SAndroid Build Coastguard Worker * Skip this URI...
405*5e7646d2SAndroid Build Coastguard Worker */
406*5e7646d2SAndroid Build Coastguard Worker
407*5e7646d2SAndroid Build Coastguard Worker while (*valptr && !_cups_isspace(*valptr))
408*5e7646d2SAndroid Build Coastguard Worker valptr++;
409*5e7646d2SAndroid Build Coastguard Worker }
410*5e7646d2SAndroid Build Coastguard Worker
411*5e7646d2SAndroid Build Coastguard Worker /*
412*5e7646d2SAndroid Build Coastguard Worker * Skip whitespace...
413*5e7646d2SAndroid Build Coastguard Worker */
414*5e7646d2SAndroid Build Coastguard Worker
415*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*valptr))
416*5e7646d2SAndroid Build Coastguard Worker valptr ++;
417*5e7646d2SAndroid Build Coastguard Worker }
418*5e7646d2SAndroid Build Coastguard Worker
419*5e7646d2SAndroid Build Coastguard Worker return (NULL);
420*5e7646d2SAndroid Build Coastguard Worker }
421*5e7646d2SAndroid Build Coastguard Worker }
422*5e7646d2SAndroid Build Coastguard Worker
423*5e7646d2SAndroid Build Coastguard Worker
424*5e7646d2SAndroid Build Coastguard Worker /*
425*5e7646d2SAndroid Build Coastguard Worker * 'ppdLocalizeMarkerName()' - Get the localized version of a marker-names
426*5e7646d2SAndroid Build Coastguard Worker * attribute value.
427*5e7646d2SAndroid Build Coastguard Worker *
428*5e7646d2SAndroid Build Coastguard Worker * This function uses the current locale to find the corresponding name
429*5e7646d2SAndroid Build Coastguard Worker * text from the attribute value. If no localized text for the requested
430*5e7646d2SAndroid Build Coastguard Worker * name can be found, @code NULL@ is returned.
431*5e7646d2SAndroid Build Coastguard Worker *
432*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.4/macOS 10.6@
433*5e7646d2SAndroid Build Coastguard Worker */
434*5e7646d2SAndroid Build Coastguard Worker
435*5e7646d2SAndroid Build Coastguard Worker const char * /* O - Value or @code NULL@ if not found */
ppdLocalizeMarkerName(ppd_file_t * ppd,const char * name)436*5e7646d2SAndroid Build Coastguard Worker ppdLocalizeMarkerName(
437*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *ppd, /* I - PPD file */
438*5e7646d2SAndroid Build Coastguard Worker const char *name) /* I - Marker name to look up */
439*5e7646d2SAndroid Build Coastguard Worker {
440*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t *locattr; /* Localized attribute */
441*5e7646d2SAndroid Build Coastguard Worker char ll_CC[6]; /* Language + country locale */
442*5e7646d2SAndroid Build Coastguard Worker
443*5e7646d2SAndroid Build Coastguard Worker
444*5e7646d2SAndroid Build Coastguard Worker /*
445*5e7646d2SAndroid Build Coastguard Worker * Range check input...
446*5e7646d2SAndroid Build Coastguard Worker */
447*5e7646d2SAndroid Build Coastguard Worker
448*5e7646d2SAndroid Build Coastguard Worker if (!ppd || !name)
449*5e7646d2SAndroid Build Coastguard Worker return (NULL);
450*5e7646d2SAndroid Build Coastguard Worker
451*5e7646d2SAndroid Build Coastguard Worker /*
452*5e7646d2SAndroid Build Coastguard Worker * Get the default language...
453*5e7646d2SAndroid Build Coastguard Worker */
454*5e7646d2SAndroid Build Coastguard Worker
455*5e7646d2SAndroid Build Coastguard Worker ppd_ll_CC(ll_CC, sizeof(ll_CC));
456*5e7646d2SAndroid Build Coastguard Worker
457*5e7646d2SAndroid Build Coastguard Worker /*
458*5e7646d2SAndroid Build Coastguard Worker * Find the localized attribute...
459*5e7646d2SAndroid Build Coastguard Worker */
460*5e7646d2SAndroid Build Coastguard Worker
461*5e7646d2SAndroid Build Coastguard Worker if ((locattr = _ppdLocalizedAttr(ppd, "cupsMarkerName", name,
462*5e7646d2SAndroid Build Coastguard Worker ll_CC)) == NULL)
463*5e7646d2SAndroid Build Coastguard Worker locattr = ppdFindAttr(ppd, "cupsMarkerName", name);
464*5e7646d2SAndroid Build Coastguard Worker
465*5e7646d2SAndroid Build Coastguard Worker return (locattr ? locattr->text : NULL);
466*5e7646d2SAndroid Build Coastguard Worker }
467*5e7646d2SAndroid Build Coastguard Worker
468*5e7646d2SAndroid Build Coastguard Worker
469*5e7646d2SAndroid Build Coastguard Worker /*
470*5e7646d2SAndroid Build Coastguard Worker * '_ppdFreeLanguages()' - Free an array of languages from _ppdGetLanguages.
471*5e7646d2SAndroid Build Coastguard Worker */
472*5e7646d2SAndroid Build Coastguard Worker
473*5e7646d2SAndroid Build Coastguard Worker void
_ppdFreeLanguages(cups_array_t * languages)474*5e7646d2SAndroid Build Coastguard Worker _ppdFreeLanguages(
475*5e7646d2SAndroid Build Coastguard Worker cups_array_t *languages) /* I - Languages array */
476*5e7646d2SAndroid Build Coastguard Worker {
477*5e7646d2SAndroid Build Coastguard Worker char *language; /* Current language */
478*5e7646d2SAndroid Build Coastguard Worker
479*5e7646d2SAndroid Build Coastguard Worker
480*5e7646d2SAndroid Build Coastguard Worker for (language = (char *)cupsArrayFirst(languages);
481*5e7646d2SAndroid Build Coastguard Worker language;
482*5e7646d2SAndroid Build Coastguard Worker language = (char *)cupsArrayNext(languages))
483*5e7646d2SAndroid Build Coastguard Worker free(language);
484*5e7646d2SAndroid Build Coastguard Worker
485*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(languages);
486*5e7646d2SAndroid Build Coastguard Worker }
487*5e7646d2SAndroid Build Coastguard Worker
488*5e7646d2SAndroid Build Coastguard Worker
489*5e7646d2SAndroid Build Coastguard Worker /*
490*5e7646d2SAndroid Build Coastguard Worker * '_ppdGetLanguages()' - Get an array of languages from a PPD file.
491*5e7646d2SAndroid Build Coastguard Worker */
492*5e7646d2SAndroid Build Coastguard Worker
493*5e7646d2SAndroid Build Coastguard Worker cups_array_t * /* O - Languages array */
_ppdGetLanguages(ppd_file_t * ppd)494*5e7646d2SAndroid Build Coastguard Worker _ppdGetLanguages(ppd_file_t *ppd) /* I - PPD file */
495*5e7646d2SAndroid Build Coastguard Worker {
496*5e7646d2SAndroid Build Coastguard Worker cups_array_t *languages; /* Languages array */
497*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t *attr; /* cupsLanguages attribute */
498*5e7646d2SAndroid Build Coastguard Worker char *value, /* Copy of attribute value */
499*5e7646d2SAndroid Build Coastguard Worker *start, /* Start of current language */
500*5e7646d2SAndroid Build Coastguard Worker *ptr; /* Pointer into languages */
501*5e7646d2SAndroid Build Coastguard Worker
502*5e7646d2SAndroid Build Coastguard Worker
503*5e7646d2SAndroid Build Coastguard Worker /*
504*5e7646d2SAndroid Build Coastguard Worker * See if we have a cupsLanguages attribute...
505*5e7646d2SAndroid Build Coastguard Worker */
506*5e7646d2SAndroid Build Coastguard Worker
507*5e7646d2SAndroid Build Coastguard Worker if ((attr = ppdFindAttr(ppd, "cupsLanguages", NULL)) == NULL || !attr->value)
508*5e7646d2SAndroid Build Coastguard Worker return (NULL);
509*5e7646d2SAndroid Build Coastguard Worker
510*5e7646d2SAndroid Build Coastguard Worker /*
511*5e7646d2SAndroid Build Coastguard Worker * Yes, load the list...
512*5e7646d2SAndroid Build Coastguard Worker */
513*5e7646d2SAndroid Build Coastguard Worker
514*5e7646d2SAndroid Build Coastguard Worker if ((languages = cupsArrayNew((cups_array_func_t)strcmp, NULL)) == NULL)
515*5e7646d2SAndroid Build Coastguard Worker return (NULL);
516*5e7646d2SAndroid Build Coastguard Worker
517*5e7646d2SAndroid Build Coastguard Worker if ((value = strdup(attr->value)) == NULL)
518*5e7646d2SAndroid Build Coastguard Worker {
519*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(languages);
520*5e7646d2SAndroid Build Coastguard Worker return (NULL);
521*5e7646d2SAndroid Build Coastguard Worker }
522*5e7646d2SAndroid Build Coastguard Worker
523*5e7646d2SAndroid Build Coastguard Worker for (ptr = value; *ptr;)
524*5e7646d2SAndroid Build Coastguard Worker {
525*5e7646d2SAndroid Build Coastguard Worker /*
526*5e7646d2SAndroid Build Coastguard Worker * Skip leading whitespace...
527*5e7646d2SAndroid Build Coastguard Worker */
528*5e7646d2SAndroid Build Coastguard Worker
529*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*ptr))
530*5e7646d2SAndroid Build Coastguard Worker ptr ++;
531*5e7646d2SAndroid Build Coastguard Worker
532*5e7646d2SAndroid Build Coastguard Worker if (!*ptr)
533*5e7646d2SAndroid Build Coastguard Worker break;
534*5e7646d2SAndroid Build Coastguard Worker
535*5e7646d2SAndroid Build Coastguard Worker /*
536*5e7646d2SAndroid Build Coastguard Worker * Find the end of this language name...
537*5e7646d2SAndroid Build Coastguard Worker */
538*5e7646d2SAndroid Build Coastguard Worker
539*5e7646d2SAndroid Build Coastguard Worker for (start = ptr; *ptr && !_cups_isspace(*ptr); ptr ++);
540*5e7646d2SAndroid Build Coastguard Worker
541*5e7646d2SAndroid Build Coastguard Worker if (*ptr)
542*5e7646d2SAndroid Build Coastguard Worker *ptr++ = '\0';
543*5e7646d2SAndroid Build Coastguard Worker
544*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(start, "en"))
545*5e7646d2SAndroid Build Coastguard Worker continue;
546*5e7646d2SAndroid Build Coastguard Worker
547*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(languages, strdup(start));
548*5e7646d2SAndroid Build Coastguard Worker }
549*5e7646d2SAndroid Build Coastguard Worker
550*5e7646d2SAndroid Build Coastguard Worker /*
551*5e7646d2SAndroid Build Coastguard Worker * Free the temporary string and return either an array with one or more
552*5e7646d2SAndroid Build Coastguard Worker * values or a NULL pointer...
553*5e7646d2SAndroid Build Coastguard Worker */
554*5e7646d2SAndroid Build Coastguard Worker
555*5e7646d2SAndroid Build Coastguard Worker free(value);
556*5e7646d2SAndroid Build Coastguard Worker
557*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayCount(languages) == 0)
558*5e7646d2SAndroid Build Coastguard Worker {
559*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(languages);
560*5e7646d2SAndroid Build Coastguard Worker return (NULL);
561*5e7646d2SAndroid Build Coastguard Worker }
562*5e7646d2SAndroid Build Coastguard Worker else
563*5e7646d2SAndroid Build Coastguard Worker return (languages);
564*5e7646d2SAndroid Build Coastguard Worker }
565*5e7646d2SAndroid Build Coastguard Worker
566*5e7646d2SAndroid Build Coastguard Worker
567*5e7646d2SAndroid Build Coastguard Worker /*
568*5e7646d2SAndroid Build Coastguard Worker * '_ppdHashName()' - Generate a hash value for a device or profile name.
569*5e7646d2SAndroid Build Coastguard Worker *
570*5e7646d2SAndroid Build Coastguard Worker * This function is primarily used on macOS, but is generally accessible
571*5e7646d2SAndroid Build Coastguard Worker * since cupstestppd needs to check for profile name collisions in PPD files...
572*5e7646d2SAndroid Build Coastguard Worker */
573*5e7646d2SAndroid Build Coastguard Worker
574*5e7646d2SAndroid Build Coastguard Worker unsigned /* O - Hash value */
_ppdHashName(const char * name)575*5e7646d2SAndroid Build Coastguard Worker _ppdHashName(const char *name) /* I - Name to hash */
576*5e7646d2SAndroid Build Coastguard Worker {
577*5e7646d2SAndroid Build Coastguard Worker unsigned mult, /* Multiplier */
578*5e7646d2SAndroid Build Coastguard Worker hash = 0; /* Hash value */
579*5e7646d2SAndroid Build Coastguard Worker
580*5e7646d2SAndroid Build Coastguard Worker
581*5e7646d2SAndroid Build Coastguard Worker for (mult = 1; *name && mult <= 128; mult ++, name ++)
582*5e7646d2SAndroid Build Coastguard Worker hash += (*name & 255) * mult;
583*5e7646d2SAndroid Build Coastguard Worker
584*5e7646d2SAndroid Build Coastguard Worker return (hash);
585*5e7646d2SAndroid Build Coastguard Worker }
586*5e7646d2SAndroid Build Coastguard Worker
587*5e7646d2SAndroid Build Coastguard Worker
588*5e7646d2SAndroid Build Coastguard Worker /*
589*5e7646d2SAndroid Build Coastguard Worker * '_ppdLocalizedAttr()' - Find a localized attribute.
590*5e7646d2SAndroid Build Coastguard Worker */
591*5e7646d2SAndroid Build Coastguard Worker
592*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t * /* O - Localized attribute or NULL */
_ppdLocalizedAttr(ppd_file_t * ppd,const char * keyword,const char * spec,const char * ll_CC)593*5e7646d2SAndroid Build Coastguard Worker _ppdLocalizedAttr(ppd_file_t *ppd, /* I - PPD file */
594*5e7646d2SAndroid Build Coastguard Worker const char *keyword, /* I - Main keyword */
595*5e7646d2SAndroid Build Coastguard Worker const char *spec, /* I - Option keyword */
596*5e7646d2SAndroid Build Coastguard Worker const char *ll_CC) /* I - Language + country locale */
597*5e7646d2SAndroid Build Coastguard Worker {
598*5e7646d2SAndroid Build Coastguard Worker char lkeyword[PPD_MAX_NAME]; /* Localization keyword */
599*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t *attr; /* Current attribute */
600*5e7646d2SAndroid Build Coastguard Worker
601*5e7646d2SAndroid Build Coastguard Worker
602*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_ppdLocalizedAttr(ppd=%p, keyword=\"%s\", spec=\"%s\", "
603*5e7646d2SAndroid Build Coastguard Worker "ll_CC=\"%s\")", ppd, keyword, spec, ll_CC));
604*5e7646d2SAndroid Build Coastguard Worker
605*5e7646d2SAndroid Build Coastguard Worker /*
606*5e7646d2SAndroid Build Coastguard Worker * Look for Keyword.ll_CC, then Keyword.ll...
607*5e7646d2SAndroid Build Coastguard Worker */
608*5e7646d2SAndroid Build Coastguard Worker
609*5e7646d2SAndroid Build Coastguard Worker snprintf(lkeyword, sizeof(lkeyword), "%s.%s", ll_CC, keyword);
610*5e7646d2SAndroid Build Coastguard Worker if ((attr = ppdFindAttr(ppd, lkeyword, spec)) == NULL)
611*5e7646d2SAndroid Build Coastguard Worker {
612*5e7646d2SAndroid Build Coastguard Worker /*
613*5e7646d2SAndroid Build Coastguard Worker * <rdar://problem/22130168>
614*5e7646d2SAndroid Build Coastguard Worker *
615*5e7646d2SAndroid Build Coastguard Worker * Multiple locales need special handling... Sigh...
616*5e7646d2SAndroid Build Coastguard Worker */
617*5e7646d2SAndroid Build Coastguard Worker
618*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(ll_CC, "zh_HK"))
619*5e7646d2SAndroid Build Coastguard Worker {
620*5e7646d2SAndroid Build Coastguard Worker snprintf(lkeyword, sizeof(lkeyword), "zh_TW.%s", keyword);
621*5e7646d2SAndroid Build Coastguard Worker attr = ppdFindAttr(ppd, lkeyword, spec);
622*5e7646d2SAndroid Build Coastguard Worker }
623*5e7646d2SAndroid Build Coastguard Worker
624*5e7646d2SAndroid Build Coastguard Worker if (!attr)
625*5e7646d2SAndroid Build Coastguard Worker {
626*5e7646d2SAndroid Build Coastguard Worker snprintf(lkeyword, sizeof(lkeyword), "%2.2s.%s", ll_CC, keyword);
627*5e7646d2SAndroid Build Coastguard Worker attr = ppdFindAttr(ppd, lkeyword, spec);
628*5e7646d2SAndroid Build Coastguard Worker }
629*5e7646d2SAndroid Build Coastguard Worker
630*5e7646d2SAndroid Build Coastguard Worker if (!attr)
631*5e7646d2SAndroid Build Coastguard Worker {
632*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(ll_CC, "ja", 2))
633*5e7646d2SAndroid Build Coastguard Worker {
634*5e7646d2SAndroid Build Coastguard Worker /*
635*5e7646d2SAndroid Build Coastguard Worker * Due to a bug in the CUPS DDK 1.1.0 ppdmerge program, Japanese
636*5e7646d2SAndroid Build Coastguard Worker * PPD files were incorrectly assigned "jp" as the locale name
637*5e7646d2SAndroid Build Coastguard Worker * instead of "ja". Support both the old (incorrect) and new
638*5e7646d2SAndroid Build Coastguard Worker * locale names for Japanese...
639*5e7646d2SAndroid Build Coastguard Worker */
640*5e7646d2SAndroid Build Coastguard Worker
641*5e7646d2SAndroid Build Coastguard Worker snprintf(lkeyword, sizeof(lkeyword), "jp.%s", keyword);
642*5e7646d2SAndroid Build Coastguard Worker attr = ppdFindAttr(ppd, lkeyword, spec);
643*5e7646d2SAndroid Build Coastguard Worker }
644*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(ll_CC, "nb", 2))
645*5e7646d2SAndroid Build Coastguard Worker {
646*5e7646d2SAndroid Build Coastguard Worker /*
647*5e7646d2SAndroid Build Coastguard Worker * Norway has two languages, "Bokmal" (the primary one)
648*5e7646d2SAndroid Build Coastguard Worker * and "Nynorsk" (new Norwegian); this code maps from the (currently)
649*5e7646d2SAndroid Build Coastguard Worker * recommended "nb" to the previously recommended "no"...
650*5e7646d2SAndroid Build Coastguard Worker */
651*5e7646d2SAndroid Build Coastguard Worker
652*5e7646d2SAndroid Build Coastguard Worker snprintf(lkeyword, sizeof(lkeyword), "no.%s", keyword);
653*5e7646d2SAndroid Build Coastguard Worker attr = ppdFindAttr(ppd, lkeyword, spec);
654*5e7646d2SAndroid Build Coastguard Worker }
655*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(ll_CC, "no", 2))
656*5e7646d2SAndroid Build Coastguard Worker {
657*5e7646d2SAndroid Build Coastguard Worker /*
658*5e7646d2SAndroid Build Coastguard Worker * Norway has two languages, "Bokmal" (the primary one)
659*5e7646d2SAndroid Build Coastguard Worker * and "Nynorsk" (new Norwegian); we map "no" to "nb" here as
660*5e7646d2SAndroid Build Coastguard Worker * recommended by the locale folks...
661*5e7646d2SAndroid Build Coastguard Worker */
662*5e7646d2SAndroid Build Coastguard Worker
663*5e7646d2SAndroid Build Coastguard Worker snprintf(lkeyword, sizeof(lkeyword), "nb.%s", keyword);
664*5e7646d2SAndroid Build Coastguard Worker attr = ppdFindAttr(ppd, lkeyword, spec);
665*5e7646d2SAndroid Build Coastguard Worker }
666*5e7646d2SAndroid Build Coastguard Worker }
667*5e7646d2SAndroid Build Coastguard Worker }
668*5e7646d2SAndroid Build Coastguard Worker
669*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
670*5e7646d2SAndroid Build Coastguard Worker if (attr)
671*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_ppdLocalizedAttr: *%s %s/%s: \"%s\"\n", attr->name,
672*5e7646d2SAndroid Build Coastguard Worker attr->spec, attr->text, attr->value ? attr->value : ""));
673*5e7646d2SAndroid Build Coastguard Worker else
674*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_ppdLocalizedAttr: NOT FOUND");
675*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
676*5e7646d2SAndroid Build Coastguard Worker
677*5e7646d2SAndroid Build Coastguard Worker return (attr);
678*5e7646d2SAndroid Build Coastguard Worker }
679*5e7646d2SAndroid Build Coastguard Worker
680*5e7646d2SAndroid Build Coastguard Worker
681*5e7646d2SAndroid Build Coastguard Worker /*
682*5e7646d2SAndroid Build Coastguard Worker * 'ppd_ll_CC()' - Get the current locale names.
683*5e7646d2SAndroid Build Coastguard Worker */
684*5e7646d2SAndroid Build Coastguard Worker
685*5e7646d2SAndroid Build Coastguard Worker static cups_lang_t * /* O - Current language */
ppd_ll_CC(char * ll_CC,size_t ll_CC_size)686*5e7646d2SAndroid Build Coastguard Worker ppd_ll_CC(char *ll_CC, /* O - Country-specific locale name */
687*5e7646d2SAndroid Build Coastguard Worker size_t ll_CC_size) /* I - Size of country-specific name */
688*5e7646d2SAndroid Build Coastguard Worker {
689*5e7646d2SAndroid Build Coastguard Worker cups_lang_t *lang; /* Current language */
690*5e7646d2SAndroid Build Coastguard Worker
691*5e7646d2SAndroid Build Coastguard Worker
692*5e7646d2SAndroid Build Coastguard Worker /*
693*5e7646d2SAndroid Build Coastguard Worker * Get the current locale...
694*5e7646d2SAndroid Build Coastguard Worker */
695*5e7646d2SAndroid Build Coastguard Worker
696*5e7646d2SAndroid Build Coastguard Worker if ((lang = cupsLangDefault()) == NULL)
697*5e7646d2SAndroid Build Coastguard Worker {
698*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll_CC, "en_US", ll_CC_size);
699*5e7646d2SAndroid Build Coastguard Worker return (NULL);
700*5e7646d2SAndroid Build Coastguard Worker }
701*5e7646d2SAndroid Build Coastguard Worker
702*5e7646d2SAndroid Build Coastguard Worker /*
703*5e7646d2SAndroid Build Coastguard Worker * Copy the locale name...
704*5e7646d2SAndroid Build Coastguard Worker */
705*5e7646d2SAndroid Build Coastguard Worker
706*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll_CC, lang->language, ll_CC_size);
707*5e7646d2SAndroid Build Coastguard Worker
708*5e7646d2SAndroid Build Coastguard Worker if (strlen(ll_CC) == 2)
709*5e7646d2SAndroid Build Coastguard Worker {
710*5e7646d2SAndroid Build Coastguard Worker /*
711*5e7646d2SAndroid Build Coastguard Worker * Map "ll" to primary/origin country locales to have the best
712*5e7646d2SAndroid Build Coastguard Worker * chance of finding a match...
713*5e7646d2SAndroid Build Coastguard Worker */
714*5e7646d2SAndroid Build Coastguard Worker
715*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(ll_CC, "cs"))
716*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll_CC, "cs_CZ", ll_CC_size);
717*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ll_CC, "en"))
718*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll_CC, "en_US", ll_CC_size);
719*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ll_CC, "ja"))
720*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll_CC, "ja_JP", ll_CC_size);
721*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ll_CC, "sv"))
722*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll_CC, "sv_SE", ll_CC_size);
723*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ll_CC, "zh")) /* Simplified Chinese */
724*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll_CC, "zh_CN", ll_CC_size);
725*5e7646d2SAndroid Build Coastguard Worker }
726*5e7646d2SAndroid Build Coastguard Worker
727*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("8ppd_ll_CC: lang->language=\"%s\", ll_CC=\"%s\"...",
728*5e7646d2SAndroid Build Coastguard Worker lang->language, ll_CC));
729*5e7646d2SAndroid Build Coastguard Worker return (lang);
730*5e7646d2SAndroid Build Coastguard Worker }
731