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