X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=cups%2Flanguage.c;h=5f20831086968b7a4b3632235f002b561da8fc76;hb=75bd9771f6e44fdd887ee90faac46f403aefc0fc;hp=435c84bc446a37526093cde32d009e9487ebf4b1;hpb=7a6a01ddca9307aa0f0abe27bb0f9074b86b1093;p=thirdparty%2Fcups.git diff --git a/cups/language.c b/cups/language.c index 435c84bc4..5f2083108 100644 --- a/cups/language.c +++ b/cups/language.c @@ -1,30 +1,23 @@ /* - * "$Id$" + * "$Id: language.c 7558 2008-05-12 23:46:44Z mike $" * * I18N/language support for the Common UNIX Printing System (CUPS). * - * Copyright 1997-2006 by Easy Software Products. + * Copyright 2007-2008 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the - * property of Easy Software Products and are protected by Federal - * copyright law. Distribution and use rights are outlined in the file - * "LICENSE.txt" which should have been included with this file. If this - * file is missing or damaged please contact Easy Software Products - * at: - * - * Attn: CUPS Licensing Information - * Easy Software Products - * 44141 Airport View Drive, Suite 204 - * Hollywood, Maryland 20636 USA - * - * Voice: (301) 373-9600 - * EMail: cups-info@cups.org - * WWW: http://www.cups.org + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". * * This file is subject to the Apple OS-Developed Software exception. * * Contents: * + * _cupsAppleLanguage() - Get the Apple language identifier associated + * with a locale ID. * _cupsEncodingName() - Return the character encoding name string * for the given encoding enumeration. * cupsLangDefault() - Return the default language. @@ -74,26 +67,6 @@ static pthread_mutex_t lang_mutex = PTHREAD_MUTEX_INITIALIZER; #endif /* HAVE_PTHREAD_H */ static cups_lang_t *lang_cache = NULL; /* Language string cache */ - - -/* - * Local functions... - */ - -#ifdef __APPLE__ -static const char *appleLangDefault(void); -#endif /* __APPLE__ */ -static cups_lang_t *cups_cache_lookup(const char *name, - cups_encoding_t encoding); -static int cups_message_compare(_cups_message_t *m1, - _cups_message_t *m2); -static void cups_unquote(char *d, const char *s); - - -/* - * Local globals... - */ - static const char * const lang_encodings[] = { /* Encoding strings */ "us-ascii", "iso-8859-1", @@ -164,6 +137,123 @@ static const char * const lang_encodings[] = "euc-kr", "euc-tw" }; +#ifdef __APPLE__ +typedef struct +{ + const char * const language; /* Language ID */ + const char * const locale; /* Locale ID */ +} _apple_language_locale_t; + +static const _apple_language_locale_t apple_language_locale[] = +{ /* Locale to language ID LUT */ + { "en" , "en_US" }, + { "nb" , "no" }, + { "zh-Hans" , "zh_CN" }, + { "zh-Hant" , "zh_TW" } +}; +#endif /* __APPLE__ */ + + +/* + * Local functions... + */ + +#ifdef __APPLE__ +static const char *appleLangDefault(void); +#endif /* __APPLE__ */ +static cups_lang_t *cups_cache_lookup(const char *name, + cups_encoding_t encoding); +static int cups_message_compare(_cups_message_t *m1, + _cups_message_t *m2); +static void cups_unquote(char *d, const char *s); + + +#ifdef __APPLE__ +/* + * _cupsAppleLanguage() - Get the Apple language identifier associated + * with a locale ID. + */ + +const char * /* O - Language ID */ +_cupsAppleLanguage(const char *locale, /* I - Locale ID */ + char *language,/* I - Language ID buffer */ + size_t langsize) /* I - Size of language ID buffer */ +{ + int i; /* Looping var */ + CFStringRef localeid, /* CF locale identifier */ + langid; /* CF language identifier */ + + + /* + * Copy the locale name and convert, as needed, to the Apple-specific + * locale identifier... + */ + + switch (strlen(locale)) + { + default : + /* + * Invalid locale... + */ + + strlcpy(language, "en", langsize); + break; + + case 2 : + strlcpy(language, locale, langsize); + break; + + case 5 : + strlcpy(language, locale, langsize); + + if (language[2] == '-') + { + /* + * Convert ll-cc to ll_CC... + */ + + language[2] = '_'; + language[3] = toupper(language[3] & 255); + language[4] = toupper(language[4] & 255); + } + break; + } + + for (i = 0; + i < (int)(sizeof(apple_language_locale) / + sizeof(apple_language_locale[0])); + i ++) + if (!strcmp(locale, apple_language_locale[i].locale)) + { + strlcpy(language, apple_language_locale[i].language, sizeof(language)); + break; + } + + /* + * Attempt to map the locale ID to a language ID... + */ + + if ((localeid = CFStringCreateWithCString(kCFAllocatorDefault, language, + kCFStringEncodingASCII)) != NULL) + { + if ((langid = CFLocaleCreateCanonicalLanguageIdentifierFromString( + kCFAllocatorDefault, localeid)) != NULL) + { + CFStringGetCString(langid, language, langsize, kCFStringEncodingASCII); + CFRelease(langid); + } + + CFRelease(localeid); + } + + /* + * Return what we got... + */ + + return (language); +} +#endif /* __APPLE__ */ + /* * '_cupsEncodingName()' - Return the character encoding name string @@ -254,7 +344,7 @@ cupsLangFlush(void) /* * 'cupsLangFree()' - Free language data. * - * This does not actually free anything; use cupsLangFlush() for that. + * This does not actually free anything; use @link cupsLangFlush@ for that. */ void @@ -352,7 +442,12 @@ cupsLangGet(const char *language) /* I - Language or locale */ */ if (!language) - language = appleLangDefault(); + { + if ((language = getenv("LANG")) == NULL) + language = appleLangDefault(); + + DEBUG_printf(("cupsLangGet: language=\"%s\"\n", language)); + } #else /* @@ -406,14 +501,6 @@ cupsLangGet(const char *language) /* I - Language or locale */ *ptr = '\0'; } - else - { - /* - * Default to UTF-8... - */ - - strcpy(charset, "UTF8"); - } /* * Get the locale for messages from the LC_MESSAGES locale setting... @@ -430,8 +517,14 @@ cupsLangGet(const char *language) /* I - Language or locale */ strlcpy(locale, ptr, sizeof(locale)); language = locale; - DEBUG_printf(("cupsLangGet: new language value is \"%s\"\n", - language ? language : "(null)")); + /* + * CUPS STR #2575: Map "nb" to "no" for back-compatibility... + */ + + if (!strncmp(locale, "nb", 2)) + locale[1] = 'o'; + + DEBUG_printf(("cupsLangGet: new language value is \"%s\"\n", language)); } } #endif /* __APPLE__ */ @@ -473,6 +566,13 @@ cupsLangGet(const char *language) /* I - Language or locale */ } #endif /* CODESET */ + /* + * If we don't have a character set by now, default to UTF-8... + */ + + if (!charset[0]) + strcpy(charset, "UTF8"); + /* * Parse the language string passed in to a locale string. "C" is the * standard POSIX locale and is copied unchanged. Otherwise the @@ -560,6 +660,23 @@ cupsLangGet(const char *language) /* I - Language or locale */ encoding = (cups_encoding_t)i; break; } + + if (encoding == CUPS_AUTO_ENCODING) + { + /* + * Map alternate names for various character sets... + */ + + if (!strcasecmp(charset, "iso-2022-jp") || + !strcasecmp(charset, "sjis")) + encoding = CUPS_WINDOWS_932; + else if (!strcasecmp(charset, "iso-2022-cn")) + encoding = CUPS_WINDOWS_936; + else if (!strcasecmp(charset, "iso-2022-kr")) + encoding = CUPS_WINDOWS_949; + else if (!strcasecmp(charset, "big5")) + encoding = CUPS_WINDOWS_950; + } } DEBUG_printf(("cupsLangGet: encoding=%d(%s)\n", encoding, @@ -587,12 +704,14 @@ cupsLangGet(const char *language) /* I - Language or locale */ pthread_mutex_lock(&lang_mutex); #endif /* HAVE_PTHREAD_H */ - if ((lang = cups_cache_lookup(langname, encoding)) != NULL) + if ((lang = cups_cache_lookup(real, encoding)) != NULL) { #ifdef HAVE_PTHREAD_H pthread_mutex_unlock(&lang_mutex); #endif /* HAVE_PTHREAD_H */ + DEBUG_printf(("cupsLangGet: Using cached copy of \"%s\"...\n", real)); + return (lang); } @@ -611,7 +730,8 @@ cupsLangGet(const char *language) /* I - Language or locale */ * No generic localization, so use POSIX... */ - DEBUG_printf(("access(\"%s\", 0): %s\n", filename, strerror(errno))); + DEBUG_printf(("cupsLangGet: access(\"%s\", 0): %s\n", filename, + strerror(errno))); snprintf(filename, sizeof(filename), "%s/C/cups_C.po", cg->localedir); } @@ -779,14 +899,21 @@ _cupsMessageLoad(const char *filename) /* I - Message catalog to load */ */ if ((a = cupsArrayNew((cups_array_func_t)cups_message_compare, NULL)) == NULL) + { + DEBUG_puts("_cupsMessageLoad: Unable to allocate array!"); return (NULL); + } /* * Open the message catalog file... */ if ((fp = cupsFileOpen(filename, "r")) == NULL) + { + DEBUG_printf(("_cupsMessageLoad: Unable to open file: %s\n", + strerror(errno))); return (a); + } /* * Read messages from the catalog file until EOF... @@ -863,7 +990,12 @@ _cupsMessageLoad(const char *filename) /* I - Message catalog to load */ return (a); } - m->id = strdup(ptr); + if ((m->id = strdup(ptr)) == NULL) + { + free(m); + cupsFileClose(fp); + return (a); + } } else if (s[0] == '\"' && m) { @@ -871,7 +1003,7 @@ _cupsMessageLoad(const char *filename) /* I - Message catalog to load */ * Append to current string... */ - length = strlen(m->str ? m->str : m->id); + length = (int)strlen(m->str ? m->str : m->id); if ((temp = realloc(m->str ? m->str : m->id, length + strlen(ptr) + 1)) == NULL) @@ -911,7 +1043,11 @@ _cupsMessageLoad(const char *filename) /* I - Message catalog to load */ * Set the string... */ - m->str = strdup(ptr); + if ((m->str = strdup(ptr)) == NULL) + { + cupsFileClose(fp); + return (a); + } } } @@ -928,6 +1064,9 @@ _cupsMessageLoad(const char *filename) /* I - Message catalog to load */ cupsFileClose(fp); + DEBUG_printf(("_cupsMessageLoad: Returning %d messages...\n", + cupsArrayCount(a))); + return (a); } @@ -960,14 +1099,6 @@ _cupsMessageLookup(cups_array_t *a, /* I - Message array */ #ifdef __APPLE__ -/* - * Code & data to translate OSX's language names to their ISO 639-1 locale. - * - * The first version uses the new CoreFoundation API added in 10.3 (Panther), - * the second is for 10.2 (Jaguar). - */ - -# ifdef HAVE_CF_LOCALE_ID /* * 'appleLangDefault()' - Get the default locale string. */ @@ -975,10 +1106,14 @@ _cupsMessageLookup(cups_array_t *a, /* I - Message array */ static const char * /* O - Locale string */ appleLangDefault(void) { + int i; /* Looping var */ + CFBundleRef bundle; /* Main bundle (if any) */ + CFArrayRef bundleList; /* List of localizations in bundle */ CFPropertyListRef localizationList; /* List of localization data */ CFStringRef languageName; /* Current name */ CFStringRef localeName; /* Canonical from of name */ + char *lang; /* LANG environment variable */ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ @@ -989,185 +1124,74 @@ appleLangDefault(void) if (!cg->language[0]) { - localizationList = - CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), - kCFPreferencesCurrentApplication); + if ((lang = getenv("LANG"))) + { + strlcpy(cg->language, lang, sizeof(cg->language)); + return (cg->language); + } + else if ((bundle = CFBundleGetMainBundle()) != NULL && + (bundleList = CFBundleCopyBundleLocalizations(bundle)) != NULL) + { + localizationList = + CFBundleCopyPreferredLocalizationsFromArray(bundleList); + + CFRelease(bundleList); + } + else + localizationList = + CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), + kCFPreferencesCurrentApplication); - if (localizationList != NULL) + if (localizationList) { if (CFGetTypeID(localizationList) == CFArrayGetTypeID() && CFArrayGetCount(localizationList) > 0) { - languageName = CFArrayGetValueAtIndex(localizationList, 0); + languageName = CFArrayGetValueAtIndex(localizationList, 0); - if (languageName != NULL && - CFGetTypeID(languageName) == CFStringGetTypeID()) - { + if (languageName && + CFGetTypeID(languageName) == CFStringGetTypeID()) + { localeName = CFLocaleCreateCanonicalLocaleIdentifierFromString( - kCFAllocatorDefault, languageName); + kCFAllocatorDefault, languageName); - if (localeName != NULL) + if (localeName) { CFStringGetCString(localeName, cg->language, sizeof(cg->language), kCFStringEncodingASCII); CFRelease(localeName); - if (!strcmp(cg->language, "en")) - strlcpy(cg->language, "en_US.UTF-8", sizeof(cg->language)); - else if (strchr(cg->language, '.') == NULL) - strlcat(cg->language, ".UTF-8", sizeof(cg->language)); - } - } - } + DEBUG_printf(("appleLangDefault: cg->language=\"%s\"\n", + cg->language)); - CFRelease(localizationList); - } - - /* - * If we didn't find the language, default to en_US... - */ - - if (!cg->language[0]) - strlcpy(cg->language, "en_US.UTF-8", sizeof(cg->language)); - } - - /* - * Return the cached locale... - */ - - return (cg->language); -} -# else -/* - * Code & data to translate OSX 10.2's language names to their ISO 639-1 - * locale. - */ - -typedef struct -{ - const char * const name; /* Language name */ - const char * const locale; /* Locale name */ -} _apple_name_locale_t; - -static const _apple_name_locale_t apple_name_locale[] = -{ - { "English" , "en_US.UTF-8" }, { "French" , "fr.UTF-8" }, - { "German" , "de.UTF-8" }, { "Italian" , "it.UTF-8" }, - { "Dutch" , "nl.UTF-8" }, { "Swedish" , "sv.UTF-8" }, - { "Spanish" , "es.UTF-8" }, { "Danish" , "da.UTF-8" }, - { "Portuguese" , "pt.UTF-8" }, { "Norwegian" , "no.UTF-8" }, - { "Hebrew" , "he.UTF-8" }, { "Japanese" , "ja.UTF-8" }, - { "Arabic" , "ar.UTF-8" }, { "Finnish" , "fi.UTF-8" }, - { "Greek" , "el.UTF-8" }, { "Icelandic" , "is.UTF-8" }, - { "Maltese" , "mt.UTF-8" }, { "Turkish" , "tr.UTF-8" }, - { "Croatian" , "hr.UTF-8" }, { "Chinese" , "zh.UTF-8" }, - { "Urdu" , "ur.UTF-8" }, { "Hindi" , "hi.UTF-8" }, - { "Thai" , "th.UTF-8" }, { "Korean" , "ko.UTF-8" }, - { "Lithuanian" , "lt.UTF-8" }, { "Polish" , "pl.UTF-8" }, - { "Hungarian" , "hu.UTF-8" }, { "Estonian" , "et.UTF-8" }, - { "Latvian" , "lv.UTF-8" }, { "Sami" , "se.UTF-8" }, - { "Faroese" , "fo.UTF-8" }, { "Farsi" , "fa.UTF-8" }, - { "Russian" , "ru.UTF-8" }, { "Chinese" , "zh.UTF-8" }, - { "Dutch" , "nl.UTF-8" }, { "Irish" , "ga.UTF-8" }, - { "Albanian" , "sq.UTF-8" }, { "Romanian" , "ro.UTF-8" }, - { "Czech" , "cs.UTF-8" }, { "Slovak" , "sk.UTF-8" }, - { "Slovenian" , "sl.UTF-8" }, { "Yiddish" , "yi.UTF-8" }, - { "Serbian" , "sr.UTF-8" }, { "Macedonian" , "mk.UTF-8" }, - { "Bulgarian" , "bg.UTF-8" }, { "Ukrainian" , "uk.UTF-8" }, - { "Byelorussian", "be.UTF-8" }, { "Uzbek" , "uz.UTF-8" }, - { "Kazakh" , "kk.UTF-8" }, { "Azerbaijani", "az.UTF-8" }, - { "Azerbaijani" , "az.UTF-8" }, { "Armenian" , "hy.UTF-8" }, - { "Georgian" , "ka.UTF-8" }, { "Moldavian" , "mo.UTF-8" }, - { "Kirghiz" , "ky.UTF-8" }, { "Tajiki" , "tg.UTF-8" }, - { "Turkmen" , "tk.UTF-8" }, { "Mongolian" , "mn.UTF-8" }, - { "Mongolian" , "mn.UTF-8" }, { "Pashto" , "ps.UTF-8" }, - { "Kurdish" , "ku.UTF-8" }, { "Kashmiri" , "ks.UTF-8" }, - { "Sindhi" , "sd.UTF-8" }, { "Tibetan" , "bo.UTF-8" }, - { "Nepali" , "ne.UTF-8" }, { "Sanskrit" , "sa.UTF-8" }, - { "Marathi" , "mr.UTF-8" }, { "Bengali" , "bn.UTF-8" }, - { "Assamese" , "as.UTF-8" }, { "Gujarati" , "gu.UTF-8" }, - { "Punjabi" , "pa.UTF-8" }, { "Oriya" , "or.UTF-8" }, - { "Malayalam" , "ml.UTF-8" }, { "Kannada" , "kn.UTF-8" }, - { "Tamil" , "ta.UTF-8" }, { "Telugu" , "te.UTF-8" }, - { "Sinhalese" , "si.UTF-8" }, { "Burmese" , "my.UTF-8" }, - { "Khmer" , "km.UTF-8" }, { "Lao" , "lo.UTF-8" }, - { "Vietnamese" , "vi.UTF-8" }, { "Indonesian" , "id.UTF-8" }, - { "Tagalog" , "tl.UTF-8" }, { "Malay" , "ms.UTF-8" }, - { "Malay" , "ms.UTF-8" }, { "Amharic" , "am.UTF-8" }, - { "Tigrinya" , "ti.UTF-8" }, { "Oromo" , "om.UTF-8" }, - { "Somali" , "so.UTF-8" }, { "Swahili" , "sw.UTF-8" }, - { "Kinyarwanda" , "rw.UTF-8" }, { "Rundi" , "rn.UTF-8" }, - { "Nyanja" , "" }, { "Malagasy" , "mg.UTF-8" }, - { "Esperanto" , "eo.UTF-8" }, { "Welsh" , "cy.UTF-8" }, - { "Basque" , "eu.UTF-8" }, { "Catalan" , "ca.UTF-8" }, - { "Latin" , "la.UTF-8" }, { "Quechua" , "qu.UTF-8" }, - { "Guarani" , "gn.UTF-8" }, { "Aymara" , "ay.UTF-8" }, - { "Tatar" , "tt.UTF-8" }, { "Uighur" , "ug.UTF-8" }, - { "Dzongkha" , "dz.UTF-8" }, { "Javanese" , "jv.UTF-8" }, - { "Sundanese" , "su.UTF-8" }, { "Galician" , "gl.UTF-8" }, - { "Afrikaans" , "af.UTF-8" }, { "Breton" , "br.UTF-8" }, - { "Inuktitut" , "iu.UTF-8" }, { "Scottish" , "gd.UTF-8" }, - { "Manx" , "gv.UTF-8" }, { "Irish" , "ga.UTF-8" }, - { "Tongan" , "to.UTF-8" }, { "Greek" , "el.UTF-8" }, - { "Greenlandic" , "kl.UTF-8" }, { "Azerbaijani", "az.UTF-8" } -}; - - -/* - * 'appleLangDefault()' - Get the default locale string. - */ - -static const char * /* O - Locale string */ -appleLangDefault(void) -{ - int i; /* Looping var */ - CFPropertyListRef localizationList; - /* List of localization data */ - CFStringRef localizationName; - /* Current name */ - char buff[256]; /* Temporary buffer */ - _cups_globals_t *cg = _cupsGlobals(); - /* Pointer to library globals */ - - - /* - * Only do the lookup and translation the first time. - */ - - if (cg->language == NULL) - { - localizationList = - CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), - kCFPreferencesCurrentApplication); - - if (localizationList != NULL) - { - if (CFGetTypeID(localizationList) == CFArrayGetTypeID() && - CFArrayGetCount(localizationList) > 0) - { - localizationName = CFArrayGetValueAtIndex(localizationList, 0); - - if (localizationName != NULL && - CFGetTypeID(localizationName) == CFStringGetTypeID()) - { - CFIndex length = CFStringGetLength(localizationName); - - if (length <= sizeof(buff) && - CFStringGetCString(localizationName, buff, sizeof(buff), - kCFStringEncodingASCII)) - { - buff[sizeof(buff) - 1] = '\0'; + /* + * Map new language identifiers to locales... + */ for (i = 0; - i < sizeof(apple_name_locale) / sizeof(apple_name_locale[0]); - i++) + i < (int)(sizeof(apple_language_locale) / + sizeof(apple_language_locale[0])); + i ++) { - if (!strcasecmp(buff, apple_name_locale[i].name)) + if (!strcmp(cg->language, apple_language_locale[i].language)) { - cg->language = apple_name_locale[i].locale; + DEBUG_printf(("appleLangDefault: mapping \"%s\" to \"%s\"...\n", + cg->language, apple_language_locale[i].locale)); + strlcpy(cg->language, apple_language_locale[i].locale, + sizeof(cg->language)); break; } } + + /* + * Convert language subtag into region subtag... + */ + + if (cg->language[2] == '-') + cg->language[2] = '_'; + + if (!strchr(cg->language, '.')) + strlcat(cg->language, ".UTF-8", sizeof(cg->language)); } } } @@ -1179,8 +1203,8 @@ appleLangDefault(void) * If we didn't find the language, default to en_US... */ - if (cg->language == NULL) - cg->language = apple_name_locale[0].locale; + if (!cg->language[0]) + strlcpy(cg->language, "en_US.UTF-8", sizeof(cg->language)); } /* @@ -1189,7 +1213,6 @@ appleLangDefault(void) return (cg->language); } -# endif /* HAVE_CF_LOCALE_ID */ #endif /* __APPLE__ */ @@ -1271,6 +1294,8 @@ cups_unquote(char *d, /* O - Unquoted string */ *d = *d * 8 + *s - '0'; s ++; } + + d ++; } else { @@ -1295,5 +1320,5 @@ cups_unquote(char *d, /* O - Unquoted string */ /* - * End of "$Id$". + * End of "$Id: language.c 7558 2008-05-12 23:46:44Z mike $". */