#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "string.h"
#include "language.h"
#if defined(__APPLE__)
# include <CoreFoundation/CoreFoundation.h>
static const char *appleLangDefault(void);
#endif
static cups_lang_t *lang_cache = NULL;
static char *lang_blank = "";
static char *lang_encodings[] =
{
"us-ascii",
"iso-8859-1",
"iso-8859-2",
"iso-8859-3",
"iso-8859-4",
"iso-8859-5",
"iso-8859-6",
"iso-8859-7",
"iso-8859-8",
"iso-8859-9",
"iso-8859-10",
"utf-8",
"iso-8859-13",
"iso-8859-14",
"iso-8859-15",
"windows-874",
"windows-1250",
"windows-1251",
"windows-1252",
"windows-1253",
"windows-1254",
"windows-1255",
"windows-1256",
"windows-1257",
"windows-1258",
"koi8-r",
"koi8-u"
};
static char *lang_default[] =
{
#include "cups_C.h"
NULL
};
char *
cupsLangEncoding(cups_lang_t *lang)
{
if (lang == NULL)
return (lang_encodings[0]);
else
return (lang_encodings[lang->encoding]);
}
void
cupsLangFlush(void)
{
int i;
cups_lang_t *lang,
*next;
for (lang = lang_cache; lang != NULL; lang = next)
{
for (i = 0; i < CUPS_MSG_MAX; i ++)
if (lang->messages[i] != NULL && lang->messages[i] != lang_blank)
free(lang->messages[i]);
next = lang->next;
free(lang);
}
}
void
cupsLangFree(cups_lang_t *lang)
{
if (lang != NULL && lang->used > 0)
lang->used --;
}
cups_lang_t *
cupsLangGet(const char *language)
{
int i, count;
char langname[32],
*langptr,
real[32],
*realptr,
filename[1024],
*localedir;
FILE *fp;
char line[1024];
cups_msg_t msg;
char *text;
cups_lang_t *lang;
#ifdef __APPLE__
if (language == NULL)
{
language = appleLangDefault();
setlocale(LC_ALL, language);
}
#elif defined(LC_MESSAGES)
if (language == NULL)
language = setlocale(LC_MESSAGES, "");
#else
if (language == NULL)
language = setlocale(LC_ALL, "");
#endif
if (language == NULL || language[0] == '\0' ||
strcmp(language, "POSIX") == 0)
strcpy(langname, "C");
else
{
strlcpy(langname, language, sizeof(langname));
}
if (strlen(langname) < 2)
strcpy(real, "C");
else
{
real[0] = tolower(langname[0]);
real[1] = tolower(langname[1]);
realptr = real + 2;
langptr = langname + 2;
if (*langptr == '_' || *langptr == '-')
{
*realptr++ = '_';
langptr ++;
*realptr++ = toupper(*langptr++);
*realptr++ = toupper(*langptr++);
}
if (*langptr == '.')
{
*langptr++ = '\0';
*realptr++ = '.';
while (*langptr)
{
if ((realptr - real) < (sizeof(real) - 1) &&
*langptr != '-' && *langptr != '_')
*realptr++ = tolower(*langptr++);
else
langptr ++;
}
}
*realptr = '\0';
}
for (lang = lang_cache; lang != NULL; lang = lang->next)
if (strcmp(lang->language, langname) == 0)
{
lang->used ++;
return (lang);
}
if ((localedir = getenv("LOCALEDIR")) == NULL)
localedir = CUPS_LOCALEDIR;
for (fp = NULL; fp == NULL;)
{
snprintf(filename, sizeof(filename), "%s/%s/cups_%s", localedir,
real, real);
if ((fp = fopen(filename, "r")) == NULL)
{
if ((realptr = strchr(real, '.')) != NULL)
*realptr = '\0';
else if ((realptr = strchr(real, '_')) != NULL)
*realptr = '\0';
else
break;
}
}
if (fp == NULL)
strlcpy(line, lang_default[0], sizeof(line));
else if (fgets(line, sizeof(line), fp) == NULL)
{
fclose(fp);
return (NULL);
}
i = strlen(line) - 1;
if (line[i] == '\n')
line[i] = '\0';
for (lang = lang_cache; lang != NULL; lang = lang->next)
if (lang->used == 0)
break;
if (lang == NULL)
{
if ((lang = calloc(sizeof(cups_lang_t), 1)) == NULL)
{
fclose(fp);
return (NULL);
}
lang->next = lang_cache;
lang_cache = lang;
}
for (i = 0; i < CUPS_MSG_MAX; i ++)
{
if (lang->messages[i] != NULL && lang->messages[i] != lang_blank)
free(lang->messages[i]);
lang->messages[i] = lang_blank;
}
lang->used ++;
strlcpy(lang->language, langname, sizeof(lang->language));
for (i = 0; i < (sizeof(lang_encodings) / sizeof(lang_encodings[0])); i ++)
if (strcmp(lang_encodings[i], line) == 0)
{
lang->encoding = (cups_encoding_t)i;
break;
}
msg = (cups_msg_t)-1;
count = 1;
for (;;)
{
if (fp == NULL)
{
if (lang_default[count] == NULL)
break;
strlcpy(line, lang_default[count], sizeof(line));
}
else if (fgets(line, sizeof(line), fp) == NULL)
break;
count ++;
i = strlen(line) - 1;
if (line[i] == '\n')
line[i] = '\0';
if (line[0] == '\0')
continue;
if (isdigit(line[0]))
msg = (cups_msg_t)atoi(line);
else
msg ++;
if (msg < 0 || msg >= CUPS_MSG_MAX)
continue;
text = line;
while (isdigit(*text))
text ++;
while (isspace(*text))
text ++;
lang->messages[msg] = strdup(text);
}
if (fp != NULL)
fclose(fp);
return (lang);
}
#ifdef __APPLE__
typedef struct
{
const char * const name;
const char * const locale;
} apple_name_locale_t;
static const apple_name_locale_t apple_name_locale[] =
{
{ "English" , "en_US" },{ "French" , "fr" }, { "German" , "de" }, { "Italian" , "it" },
{ "Dutch" , "nl" }, { "Swedish" , "sv" }, { "Spanish" , "es" }, { "Danish" , "da" },
{ "Portuguese" , "pt" }, { "Norwegian" , "no" }, { "Hebrew" , "he" }, { "Japanese" , "ja" },
{ "Arabic" , "ar" }, { "Finnish" , "fi" }, { "Greek" , "el" }, { "Icelandic" , "is" },
{ "Maltese" , "mt" }, { "Turkish" , "tr" }, { "Croatian" , "hr" }, { "Chinese" , "zh" },
{ "Urdu" , "ur" }, { "Hindi" , "hi" }, { "Thai" , "th" }, { "Korean" , "ko" },
{ "Lithuanian" , "lt" }, { "Polish" , "pl" }, { "Hungarian" , "hu" }, { "Estonian" , "et" },
{ "Latvian" , "lv" }, { "Sami" , "se" }, { "Faroese" , "fo" }, { "Farsi" , "fa" },
{ "Russian" , "ru" }, { "Chinese" , "zh" }, { "Dutch" , "nl" }, { "Irish" , "ga" },
{ "Albanian" , "sq" }, { "Romanian" , "ro" }, { "Czech" , "cs" }, { "Slovak" , "sk" },
{ "Slovenian" , "sl" }, { "Yiddish" , "yi" }, { "Serbian" , "sr" }, { "Macedonian", "mk" },
{ "Bulgarian" , "bg" }, { "Ukrainian" , "uk" }, { "Byelorussian", "be" }, { "Uzbek" , "uz" },
{ "Kazakh" , "kk" }, { "Azerbaijani", "az" }, { "Azerbaijani" , "az" }, { "Armenian" , "hy" },
{ "Georgian" , "ka" }, { "Moldavian" , "mo" }, { "Kirghiz" , "ky" }, { "Tajiki" , "tg" },
{ "Turkmen" , "tk" }, { "Mongolian" , "mn" }, { "Mongolian" , "mn" }, { "Pashto" , "ps" },
{ "Kurdish" , "ku" }, { "Kashmiri" , "ks" }, { "Sindhi" , "sd" }, { "Tibetan" , "bo" },
{ "Nepali" , "ne" }, { "Sanskrit" , "sa" }, { "Marathi" , "mr" }, { "Bengali" , "bn" },
{ "Assamese" , "as" }, { "Gujarati" , "gu" }, { "Punjabi" , "pa" }, { "Oriya" , "or" },
{ "Malayalam" , "ml" }, { "Kannada" , "kn" }, { "Tamil" , "ta" }, { "Telugu" , "te" },
{ "Sinhalese" , "si" }, { "Burmese" , "my" }, { "Khmer" , "km" }, { "Lao" , "lo" },
{ "Vietnamese" , "vi" }, { "Indonesian" , "id" }, { "Tagalog" , "tl" }, { "Malay" , "ms" },
{ "Malay" , "ms" }, { "Amharic" , "am" }, { "Tigrinya" , "ti" }, { "Oromo" , "om" },
{ "Somali" , "so" }, { "Swahili" , "sw" }, { "Kinyarwanda" , "rw" }, { "Rundi" , "rn" },
{ "Nyanja" , "" }, { "Malagasy" , "mg" }, { "Esperanto" , "eo" }, { "Welsh" , "cy" },
{ "Basque" , "eu" }, { "Catalan" , "ca" }, { "Latin" , "la" }, { "Quechua" , "qu" },
{ "Guarani" , "gn" }, { "Aymara" , "ay" }, { "Tatar" , "tt" }, { "Uighur" , "ug" },
{ "Dzongkha" , "dz" }, { "Javanese" , "jv" }, { "Sundanese" , "su" }, { "Galician" , "gl" },
{ "Afrikaans" , "af" }, { "Breton" , "br" }, { "Inuktitut" , "iu" }, { "Scottish" , "gd" },
{ "Manx" , "gv" }, { "Irish" , "ga" }, { "Tongan" , "to" }, { "Greek" , "el" },
{ "Greenlandic", "kl" }, { "Azerbaijani", "az" }
};
static const char *
appleLangDefault(void)
{
int i;
CFPropertyListRef localizationList;
CFStringRef localizationName;
char buff[256];
static const char *language = NULL;
if (language == NULL)
{
localizationList = CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
kCFPreferencesCurrentApplication);
if (localizationList != NULL &&
CFGetTypeID(localizationList) == CFArrayGetTypeID())
{
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';
for (i = 0;
i < sizeof(apple_name_locale) / sizeof(apple_name_locale[0]);
i++)
{
if (strcasecmp(buff, apple_name_locale[i].name) == 0)
{
language = apple_name_locale[i].locale;
break;
}
}
}
}
CFRelease(localizationList);
}
if (language == NULL)
language = apple_name_locale[0].locale;
}
return (language);
}
#endif