#include "cups-private.h"
#ifdef HAVE_LANGINFO_H
# include <langinfo.h>
#endif
#ifdef WIN32
# include <io.h>
#else
# include <unistd.h>
#endif
#ifdef HAVE_COREFOUNDATION_H
# include <CoreFoundation/CoreFoundation.h>
#endif
static _cups_mutex_t lang_mutex = _CUPS_MUTEX_INITIALIZER;
static cups_lang_t *lang_cache = NULL;
static const char * const 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", "cp874",
"cp1250", "cp1251",
"cp1252", "cp1253",
"cp1254", "cp1255",
"cp1256", "cp1257",
"cp1258", "koi8-r",
"koi8-u", "iso-8859-11",
"iso-8859-16", "mac-roman",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"cp932", "cp936",
"cp949", "cp950",
"cp1361", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"unknown", "unknown",
"euc-cn", "euc-jp",
"euc-kr", "euc-tw",
"jis-x0213"
};
#ifdef __APPLE__
typedef struct
{
const char * const language;
const char * const locale;
} _apple_language_locale_t;
static const _apple_language_locale_t apple_language_locale[] =
{
{ "en", "en_US" },
{ "nb", "no" },
{ "zh-Hans", "zh_CN" },
{ "zh-Hant", "zh_TW" }
};
#endif
#ifdef __APPLE__
static const char *appleLangDefault(void);
# ifdef CUPS_BUNDLEDIR
# ifndef CF_RETURNS_RETAINED
# if __has_feature(attribute_cf_returns_retained)
# define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
# else
# define CF_RETURNS_RETAINED
# endif
# endif
static cups_array_t *appleMessageLoad(const char *locale)
CF_RETURNS_RETAINED;
# endif
#endif
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_message_free(_cups_message_t *m);
static void cups_unquote(char *d, const char *s);
#ifdef __APPLE__
const char *
_cupsAppleLanguage(const char *locale,
char *language,
size_t langsize)
{
int i;
CFStringRef localeid,
langid;
switch (strlen(locale))
{
default :
strlcpy(language, "en", langsize);
break;
case 2 :
strlcpy(language, locale, langsize);
break;
case 5 :
strlcpy(language, locale, langsize);
if (language[2] == '-')
{
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;
}
if ((localeid = CFStringCreateWithCString(kCFAllocatorDefault, language,
kCFStringEncodingASCII)) != NULL)
{
if ((langid = CFLocaleCreateCanonicalLanguageIdentifierFromString(
kCFAllocatorDefault, localeid)) != NULL)
{
CFStringGetCString(langid, language, langsize, kCFStringEncodingASCII);
CFRelease(langid);
}
CFRelease(localeid);
}
return (language);
}
#endif
const char *
_cupsEncodingName(
cups_encoding_t encoding)
{
if (encoding < 0 ||
encoding >= (sizeof(lang_encodings) / sizeof(const char *)))
{
DEBUG_printf(("1_cupsEncodingName(encoding=%d) = out of range (\"%s\")",
encoding, lang_encodings[0]));
return (lang_encodings[0]);
}
else
{
DEBUG_printf(("1_cupsEncodingName(encoding=%d) = \"%s\"",
encoding, lang_encodings[encoding]));
return (lang_encodings[encoding]);
}
}
cups_lang_t *
cupsLangDefault(void)
{
return (cupsLangGet(NULL));
}
const char *
cupsLangEncoding(cups_lang_t *lang)
{
if (lang == NULL)
return ((char*)lang_encodings[0]);
else
return ((char*)lang_encodings[lang->encoding]);
}
void
cupsLangFlush(void)
{
cups_lang_t *lang,
*next;
_cupsMutexLock(&lang_mutex);
for (lang = lang_cache; lang != NULL; lang = next)
{
_cupsMessageFree(lang->strings);
next = lang->next;
free(lang);
}
lang_cache = NULL;
_cupsMutexUnlock(&lang_mutex);
}
void
cupsLangFree(cups_lang_t *lang)
{
_cupsMutexLock(&lang_mutex);
if (lang != NULL && lang->used > 0)
lang->used --;
_cupsMutexUnlock(&lang_mutex);
}
cups_lang_t *
cupsLangGet(const char *language)
{
int i;
#ifndef __APPLE__
char locale[255];
#endif
char langname[16],
country[16],
charset[16],
*csptr,
*ptr,
real[48];
cups_encoding_t encoding;
cups_lang_t *lang;
#if !defined(__APPLE__) || !defined(CUPS_BUNDLEDIR)
char filename[1024];
_cups_globals_t *cg = _cupsGlobals();
#endif
static const char * const locale_encodings[] =
{
"ASCII", "ISO88591", "ISO88592", "ISO88593",
"ISO88594", "ISO88595", "ISO88596", "ISO88597",
"ISO88598", "ISO88599", "ISO885910", "UTF8",
"ISO885913", "ISO885914", "ISO885915", "CP874",
"CP1250", "CP1251", "CP1252", "CP1253",
"CP1254", "CP1255", "CP1256", "CP1257",
"CP1258", "KOI8R", "KOI8U", "ISO885911",
"ISO885916", "MACROMAN", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"CP932", "CP936", "CP949", "CP950",
"CP1361", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"EUCCN", "EUCJP", "EUCKR", "EUCTW",
"SHIFT_JISX0213"
};
DEBUG_printf(("2cupsLangGet(language=\"%s\")", language));
#ifdef __APPLE__
strcpy(charset, "UTF8");
if (!language)
{
if (!getenv("SOFTWARE") || (language = getenv("LANG")) == NULL)
language = appleLangDefault();
DEBUG_printf(("4cupsLangGet: language=\"%s\"", language));
}
#else
charset[0] = '\0';
if (!language)
{
# ifdef LC_MESSAGES
ptr = setlocale(LC_MESSAGES, NULL);
# else
ptr = setlocale(LC_ALL, NULL);
# endif
DEBUG_printf(("4cupsLangGet: current locale is \"%s\"", ptr));
if (!ptr || !strcmp(ptr, "C") || !strcmp(ptr, "POSIX"))
{
if ((ptr = getenv("LC_CTYPE")) == NULL)
if ((ptr = getenv("LC_ALL")) == NULL)
if ((ptr = getenv("LANG")) == NULL)
ptr = "en_US";
if ((csptr = strchr(ptr, '.')) != NULL)
{
for (ptr = charset, csptr ++; *csptr; csptr ++)
if (ptr < (charset + sizeof(charset) - 1) && _cups_isalnum(*csptr))
*ptr++ = *csptr;
*ptr = '\0';
}
if ((ptr = getenv("LC_MESSAGES")) == NULL)
if ((ptr = getenv("LC_ALL")) == NULL)
if ((ptr = getenv("LANG")) == NULL)
ptr = "en_US";
}
if (ptr)
{
strlcpy(locale, ptr, sizeof(locale));
language = locale;
if (!strncmp(locale, "nb", 2))
locale[1] = 'o';
DEBUG_printf(("4cupsLangGet: new language value is \"%s\"", language));
}
}
#endif
if (!language)
{
language = "C";
}
#ifdef CODESET
if (!charset[0] && (csptr = nl_langinfo(CODESET)) != NULL)
{
for (ptr = charset; *csptr; csptr ++)
if (_cups_isalnum(*csptr) && ptr < (charset + sizeof(charset) - 1))
*ptr++ = *csptr;
*ptr = '\0';
DEBUG_printf(("4cupsLangGet: charset set to \"%s\" via "
"nl_langinfo(CODESET)...", charset));
}
#endif
if (!charset[0])
strcpy(charset, "UTF8");
country[0] = '\0';
if (language == NULL || !language[0] ||
!strcmp(language, "POSIX"))
strcpy(langname, "C");
else
{
for (ptr = langname; *language; language ++)
if (*language == '_' || *language == '-' || *language == '.')
break;
else if (ptr < (langname + sizeof(langname) - 1))
*ptr++ = tolower(*language & 255);
*ptr = '\0';
if (*language == '_' || *language == '-')
{
for (language ++, ptr = country; *language; language ++)
if (*language == '.')
break;
else if (ptr < (country + sizeof(country) - 1))
*ptr++ = toupper(*language & 255);
*ptr = '\0';
}
if (*language == '.' && !charset[0])
{
for (language ++, ptr = charset; *language; language ++)
if (_cups_isalnum(*language) && ptr < (charset + sizeof(charset) - 1))
*ptr++ = toupper(*language & 255);
*ptr = '\0';
}
if (strlen(langname) != 2)
{
strcpy(langname, "C");
country[0] = '\0';
charset[0] = '\0';
}
}
DEBUG_printf(("4cupsLangGet: langname=\"%s\", country=\"%s\", charset=\"%s\"",
langname, country, charset));
encoding = CUPS_AUTO_ENCODING;
if (charset[0])
{
for (i = 0;
i < (int)(sizeof(locale_encodings) / sizeof(locale_encodings[0]));
i ++)
if (!_cups_strcasecmp(charset, locale_encodings[i]))
{
encoding = (cups_encoding_t)i;
break;
}
if (encoding == CUPS_AUTO_ENCODING)
{
if (!_cups_strcasecmp(charset, "iso-2022-jp") ||
!_cups_strcasecmp(charset, "sjis"))
encoding = CUPS_WINDOWS_932;
else if (!_cups_strcasecmp(charset, "iso-2022-cn"))
encoding = CUPS_WINDOWS_936;
else if (!_cups_strcasecmp(charset, "iso-2022-kr"))
encoding = CUPS_WINDOWS_949;
else if (!_cups_strcasecmp(charset, "big5"))
encoding = CUPS_WINDOWS_950;
}
}
DEBUG_printf(("4cupsLangGet: encoding=%d(%s)", encoding,
encoding == CUPS_AUTO_ENCODING ? "auto" :
lang_encodings[encoding]));
if (country[0])
{
snprintf(real, sizeof(real), "%s_%s", langname, country);
#if !defined(__APPLE__) || !defined(CUPS_BUNDLEDIR)
snprintf(filename, sizeof(filename), "%s/%s/cups_%s.po", cg->localedir,
real, real);
#endif
}
else
{
strcpy(real, langname);
#if !defined(__APPLE__) || !defined(CUPS_BUNDLEDIR)
filename[0] = '\0';
#endif
}
_cupsMutexLock(&lang_mutex);
if ((lang = cups_cache_lookup(real, encoding)) != NULL)
{
_cupsMutexUnlock(&lang_mutex);
DEBUG_printf(("3cupsLangGet: Using cached copy of \"%s\"...", real));
return (lang);
}
#if !defined(__APPLE__) || !defined(CUPS_BUNDLEDIR)
if (!country[0] || access(filename, 0))
{
snprintf(filename, sizeof(filename), "%s/%s/cups_%s.po", cg->localedir,
langname, langname);
if (access(filename, 0))
{
DEBUG_printf(("4cupsLangGet: access(\"%s\", 0): %s", filename,
strerror(errno)));
snprintf(filename, sizeof(filename), "%s/C/cups_C.po", cg->localedir);
}
}
#endif
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)
{
_cupsMutexUnlock(&lang_mutex);
return (NULL);
}
lang->next = lang_cache;
lang_cache = lang;
}
else
{
_cupsMessageFree(lang->strings);
}
lang->used ++;
strlcpy(lang->language, real, sizeof(lang->language));
if (encoding != CUPS_AUTO_ENCODING)
lang->encoding = encoding;
else
lang->encoding = CUPS_UTF8;
#if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
lang->strings = appleMessageLoad(lang->language);
#else
lang->strings = _cupsMessageLoad(filename, 1);
#endif
_cupsMutexUnlock(&lang_mutex);
return (lang);
}
const char *
_cupsLangString(cups_lang_t *lang,
const char *message)
{
const char *s;
if (!lang || !message)
return (message);
_cupsMutexLock(&lang_mutex);
s = _cupsMessageLookup(lang->strings, message);
_cupsMutexUnlock(&lang_mutex);
return (s);
}
void
_cupsMessageFree(cups_array_t *a)
{
#if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
if (cupsArrayUserData(a))
CFRelease((CFDictionaryRef)cupsArrayUserData(a));
#endif
cupsArrayDelete(a);
}
cups_array_t *
_cupsMessageLoad(const char *filename,
int unquote)
{
cups_file_t *fp;
cups_array_t *a;
_cups_message_t *m;
char s[4096],
*ptr,
*temp;
int length;
DEBUG_printf(("4_cupsMessageLoad(filename=\"%s\")", filename));
if ((a = cupsArrayNew3((cups_array_func_t)cups_message_compare, NULL,
(cups_ahash_func_t)NULL, 0,
(cups_acopy_func_t)NULL,
(cups_afree_func_t)cups_message_free)) == NULL)
{
DEBUG_puts("5_cupsMessageLoad: Unable to allocate array!");
return (NULL);
}
if ((fp = cupsFileOpen(filename, "r")) == NULL)
{
DEBUG_printf(("5_cupsMessageLoad: Unable to open file: %s",
strerror(errno)));
return (a);
}
m = NULL;
while (cupsFileGets(fp, s, sizeof(s)) != NULL)
{
if (s[0] == '#' || !s[0])
continue;
if ((ptr = strrchr(s, '\"')) == NULL)
continue;
*ptr = '\0';
if ((ptr = strchr(s, '\"')) == NULL)
continue;
ptr ++;
if (unquote)
cups_unquote(ptr, ptr);
if (!strncmp(s, "msgid", 5))
{
if (m)
cupsArrayAdd(a, m);
if ((m = (_cups_message_t *)calloc(1, sizeof(_cups_message_t))) == NULL)
{
cupsFileClose(fp);
return (a);
}
if ((m->id = strdup(ptr)) == NULL)
{
free(m);
cupsFileClose(fp);
return (a);
}
}
else if (s[0] == '\"' && m)
{
length = (int)strlen(m->str ? m->str : m->id);
if ((temp = realloc(m->str ? m->str : m->id,
length + strlen(ptr) + 1)) == NULL)
{
cupsFileClose(fp);
return (a);
}
if (m->str)
{
m->str = temp;
strcpy(m->str + length, ptr);
}
else
{
m->id = temp;
strcpy(m->id + length, ptr);
}
}
else if (!strncmp(s, "msgstr", 6) && m)
{
if ((m->str = strdup(ptr)) == NULL)
{
cupsFileClose(fp);
return (a);
}
}
}
if (m)
cupsArrayAdd(a, m);
cupsFileClose(fp);
DEBUG_printf(("5_cupsMessageLoad: Returning %d messages...",
cupsArrayCount(a)));
return (a);
}
const char *
_cupsMessageLookup(cups_array_t *a,
const char *m)
{
_cups_message_t key,
*match;
key.id = (char *)m;
match = (_cups_message_t *)cupsArrayFind(a, &key);
#if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
if (!match && cupsArrayUserData(a))
{
CFDictionaryRef dict;
CFStringRef cfm,
cfstr;
dict = (CFDictionaryRef)cupsArrayUserData(a);
cfm = CFStringCreateWithCString(kCFAllocatorDefault, m,
kCFStringEncodingUTF8);
match = calloc(1, sizeof(_cups_message_t));
match->id = strdup(m);
cfstr = cfm ? CFDictionaryGetValue(dict, cfm) : NULL;
if (cfstr)
{
char buffer[1024];
CFStringGetCString(cfstr, buffer, sizeof(buffer), kCFStringEncodingUTF8);
match->str = strdup(buffer);
DEBUG_printf(("1_cupsMessageLookup: Found \"%s\" as \"%s\"...",
m, buffer));
}
else
{
match->str = strdup(m);
DEBUG_printf(("1_cupsMessageLookup: Did not find \"%s\"...", m));
}
cupsArrayAdd(a, match);
if (cfm)
CFRelease(cfm);
}
#endif
if (match && match->str)
return (match->str);
else
return (m);
}
#ifdef __APPLE__
static const char *
appleLangDefault(void)
{
int i;
CFBundleRef bundle;
CFArrayRef bundleList;
CFPropertyListRef localizationList;
CFStringRef languageName;
CFStringRef localeName;
char *lang;
_cups_globals_t *cg = _cupsGlobals();
DEBUG_puts("2appleLangDefault()");
if (!cg->language[0])
{
if (getenv("SOFTWARE") != NULL && (lang = getenv("LANG")) != NULL)
{
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)
{
if (CFGetTypeID(localizationList) == CFArrayGetTypeID() &&
CFArrayGetCount(localizationList) > 0)
{
languageName = CFArrayGetValueAtIndex(localizationList, 0);
if (languageName &&
CFGetTypeID(languageName) == CFStringGetTypeID())
{
localeName = CFLocaleCreateCanonicalLocaleIdentifierFromString(
kCFAllocatorDefault, languageName);
if (localeName)
{
CFStringGetCString(localeName, cg->language, sizeof(cg->language),
kCFStringEncodingASCII);
CFRelease(localeName);
DEBUG_printf(("9appleLangDefault: cg->language=\"%s\"",
cg->language));
for (i = 0;
i < (int)(sizeof(apple_language_locale) /
sizeof(apple_language_locale[0]));
i ++)
{
if (!strcmp(cg->language, apple_language_locale[i].language))
{
DEBUG_printf(("9appleLangDefault: mapping \"%s\" to \"%s\"...",
cg->language, apple_language_locale[i].locale));
strlcpy(cg->language, apple_language_locale[i].locale,
sizeof(cg->language));
break;
}
}
if (cg->language[2] == '-')
cg->language[2] = '_';
if (!strchr(cg->language, '.'))
strlcat(cg->language, ".UTF-8", sizeof(cg->language));
}
}
}
CFRelease(localizationList);
}
if (!cg->language[0])
strlcpy(cg->language, "en_US.UTF-8", sizeof(cg->language));
}
return (cg->language);
}
# ifdef CUPS_BUNDLEDIR
static cups_array_t *
appleMessageLoad(const char *locale)
{
char filename[1024],
applelang[256];
CFURLRef url;
CFReadStreamRef stream = NULL;
CFPropertyListRef plist = NULL;
#ifdef DEBUG
CFErrorRef error = NULL;
#endif
DEBUG_printf(("appleMessageLoad(locale=\"%s\")", locale));
snprintf(filename, sizeof(filename),
CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings",
_cupsAppleLanguage(locale, applelang, sizeof(applelang)));
DEBUG_printf(("1appleMessageLoad: filename=\"%s\"", filename));
if (access(filename, 0))
{
if (!strncmp(locale, "en", 2))
locale = "English";
else if (!strncmp(locale, "nb", 2) || !strncmp(locale, "nl", 2))
locale = "Dutch";
else if (!strncmp(locale, "fr", 2))
locale = "French";
else if (!strncmp(locale, "de", 2))
locale = "German";
else if (!strncmp(locale, "it", 2))
locale = "Italian";
else if (!strncmp(locale, "ja", 2))
locale = "Japanese";
else if (!strncmp(locale, "es", 2))
locale = "Spanish";
snprintf(filename, sizeof(filename),
CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings", locale);
DEBUG_printf(("1appleMessageLoad: alternate filename=\"%s\"", filename));
}
url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
(UInt8 *)filename,
strlen(filename), false);
if (url)
{
stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
if (stream)
{
CFReadStreamOpen(stream);
#ifdef DEBUG
plist = CFPropertyListCreateWithStream(kCFAllocatorDefault, stream, 0,
kCFPropertyListImmutable, NULL,
&error);
if (error)
{
CFStringRef msg = CFErrorCopyDescription(error);
CFStringGetCString(msg, filename, sizeof(filename),
kCFStringEncodingUTF8);
DEBUG_printf(("1appleMessageLoad: %s", filename));
CFRelease(msg);
CFRelease(error);
}
#else
plist = CFPropertyListCreateWithStream(kCFAllocatorDefault, stream, 0,
kCFPropertyListImmutable, NULL,
NULL);
#endif
if (plist && CFGetTypeID(plist) != CFDictionaryGetTypeID())
{
CFRelease(plist);
plist = NULL;
}
CFRelease(stream);
}
CFRelease(url);
}
DEBUG_printf(("1appleMessageLoad: url=%p, stream=%p, plist=%p", url, stream,
plist));
return (cupsArrayNew3((cups_array_func_t)cups_message_compare, (void *)plist,
(cups_ahash_func_t)NULL, 0,
(cups_acopy_func_t)NULL,
(cups_afree_func_t)cups_message_free));
}
# endif
#endif
static cups_lang_t *
cups_cache_lookup(
const char *name,
cups_encoding_t encoding)
{
cups_lang_t *lang;
DEBUG_printf(("7cups_cache_lookup(name=\"%s\", encoding=%d(%s))", name,
encoding, encoding == CUPS_AUTO_ENCODING ? "auto" :
lang_encodings[encoding]));
for (lang = lang_cache; lang != NULL; lang = lang->next)
{
DEBUG_printf(("9cups_cache_lookup: lang=%p, language=\"%s\", "
"encoding=%d(%s)", lang, lang->language, lang->encoding,
lang_encodings[lang->encoding]));
if (!strcmp(lang->language, name) &&
(encoding == CUPS_AUTO_ENCODING || encoding == lang->encoding))
{
lang->used ++;
DEBUG_puts("8cups_cache_lookup: returning match!");
return (lang);
}
}
DEBUG_puts("8cups_cache_lookup: returning NULL!");
return (NULL);
}
static int
cups_message_compare(
_cups_message_t *m1,
_cups_message_t *m2)
{
return (strcmp(m1->id, m2->id));
}
static void
cups_message_free(_cups_message_t *m)
{
if (m->id)
free(m->id);
if (m->str)
free(m->str);
free(m);
}
static void
cups_unquote(char *d,
const char *s)
{
while (*s)
{
if (*s == '\\')
{
s ++;
if (isdigit(*s))
{
*d = 0;
while (isdigit(*s))
{
*d = *d * 8 + *s - '0';
s ++;
}
d ++;
}
else
{
if (*s == 'n')
*d ++ = '\n';
else if (*s == 'r')
*d ++ = '\r';
else if (*s == 't')
*d ++ = '\t';
else
*d++ = *s;
s ++;
}
}
else
*d++ = *s++;
}
*d = '\0';
}