1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * I18N/language support for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright 2007-2017 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright 1997-2007 by Easy Software Products.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8*5e7646d2SAndroid Build Coastguard Worker */
9*5e7646d2SAndroid Build Coastguard Worker
10*5e7646d2SAndroid Build Coastguard Worker /*
11*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers...
12*5e7646d2SAndroid Build Coastguard Worker */
13*5e7646d2SAndroid Build Coastguard Worker
14*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
15*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
16*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LANGINFO_H
17*5e7646d2SAndroid Build Coastguard Worker # include <langinfo.h>
18*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LANGINFO_H */
19*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
20*5e7646d2SAndroid Build Coastguard Worker # include <io.h>
21*5e7646d2SAndroid Build Coastguard Worker #else
22*5e7646d2SAndroid Build Coastguard Worker # include <unistd.h>
23*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
24*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_COREFOUNDATION_H
25*5e7646d2SAndroid Build Coastguard Worker # include <CoreFoundation/CoreFoundation.h>
26*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_COREFOUNDATION_H */
27*5e7646d2SAndroid Build Coastguard Worker
28*5e7646d2SAndroid Build Coastguard Worker
29*5e7646d2SAndroid Build Coastguard Worker /*
30*5e7646d2SAndroid Build Coastguard Worker * Local globals...
31*5e7646d2SAndroid Build Coastguard Worker */
32*5e7646d2SAndroid Build Coastguard Worker
33*5e7646d2SAndroid Build Coastguard Worker static _cups_mutex_t lang_mutex = _CUPS_MUTEX_INITIALIZER;
34*5e7646d2SAndroid Build Coastguard Worker /* Mutex to control access to cache */
35*5e7646d2SAndroid Build Coastguard Worker static cups_lang_t *lang_cache = NULL;
36*5e7646d2SAndroid Build Coastguard Worker /* Language string cache */
37*5e7646d2SAndroid Build Coastguard Worker static const char * const lang_encodings[] =
38*5e7646d2SAndroid Build Coastguard Worker { /* Encoding strings */
39*5e7646d2SAndroid Build Coastguard Worker "us-ascii", "iso-8859-1",
40*5e7646d2SAndroid Build Coastguard Worker "iso-8859-2", "iso-8859-3",
41*5e7646d2SAndroid Build Coastguard Worker "iso-8859-4", "iso-8859-5",
42*5e7646d2SAndroid Build Coastguard Worker "iso-8859-6", "iso-8859-7",
43*5e7646d2SAndroid Build Coastguard Worker "iso-8859-8", "iso-8859-9",
44*5e7646d2SAndroid Build Coastguard Worker "iso-8859-10", "utf-8",
45*5e7646d2SAndroid Build Coastguard Worker "iso-8859-13", "iso-8859-14",
46*5e7646d2SAndroid Build Coastguard Worker "iso-8859-15", "cp874",
47*5e7646d2SAndroid Build Coastguard Worker "cp1250", "cp1251",
48*5e7646d2SAndroid Build Coastguard Worker "cp1252", "cp1253",
49*5e7646d2SAndroid Build Coastguard Worker "cp1254", "cp1255",
50*5e7646d2SAndroid Build Coastguard Worker "cp1256", "cp1257",
51*5e7646d2SAndroid Build Coastguard Worker "cp1258", "koi8-r",
52*5e7646d2SAndroid Build Coastguard Worker "koi8-u", "iso-8859-11",
53*5e7646d2SAndroid Build Coastguard Worker "iso-8859-16", "mac",
54*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
55*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
56*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
57*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
58*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
59*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
60*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
61*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
62*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
63*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
64*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
65*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
66*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
67*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
68*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
69*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
70*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
71*5e7646d2SAndroid Build Coastguard Worker "cp932", "cp936",
72*5e7646d2SAndroid Build Coastguard Worker "cp949", "cp950",
73*5e7646d2SAndroid Build Coastguard Worker "cp1361", "unknown",
74*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
75*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
76*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
77*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
78*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
79*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
80*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
81*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
82*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
83*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
84*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
85*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
86*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
87*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
88*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
89*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
90*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
91*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
92*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
93*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
94*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
95*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
96*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
97*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
98*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
99*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
100*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
101*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
102*5e7646d2SAndroid Build Coastguard Worker "unknown", "unknown",
103*5e7646d2SAndroid Build Coastguard Worker "euc-cn", "euc-jp",
104*5e7646d2SAndroid Build Coastguard Worker "euc-kr", "euc-tw",
105*5e7646d2SAndroid Build Coastguard Worker "shift_jisx0213"
106*5e7646d2SAndroid Build Coastguard Worker };
107*5e7646d2SAndroid Build Coastguard Worker
108*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
109*5e7646d2SAndroid Build Coastguard Worker typedef struct
110*5e7646d2SAndroid Build Coastguard Worker {
111*5e7646d2SAndroid Build Coastguard Worker const char * const language; /* Language ID */
112*5e7646d2SAndroid Build Coastguard Worker const char * const locale; /* Locale ID */
113*5e7646d2SAndroid Build Coastguard Worker } _apple_language_locale_t;
114*5e7646d2SAndroid Build Coastguard Worker
115*5e7646d2SAndroid Build Coastguard Worker static const _apple_language_locale_t apple_language_locale[] =
116*5e7646d2SAndroid Build Coastguard Worker { /* Language to locale ID LUT */
117*5e7646d2SAndroid Build Coastguard Worker { "en", "en_US" },
118*5e7646d2SAndroid Build Coastguard Worker { "nb", "no" },
119*5e7646d2SAndroid Build Coastguard Worker { "nb_NO", "no" },
120*5e7646d2SAndroid Build Coastguard Worker { "zh-Hans", "zh_CN" },
121*5e7646d2SAndroid Build Coastguard Worker { "zh_HANS", "zh_CN" },
122*5e7646d2SAndroid Build Coastguard Worker { "zh-Hant", "zh_TW" },
123*5e7646d2SAndroid Build Coastguard Worker { "zh_HANT", "zh_TW" },
124*5e7646d2SAndroid Build Coastguard Worker { "zh-Hant_CN", "zh_TW" }
125*5e7646d2SAndroid Build Coastguard Worker };
126*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
127*5e7646d2SAndroid Build Coastguard Worker
128*5e7646d2SAndroid Build Coastguard Worker
129*5e7646d2SAndroid Build Coastguard Worker /*
130*5e7646d2SAndroid Build Coastguard Worker * Local functions...
131*5e7646d2SAndroid Build Coastguard Worker */
132*5e7646d2SAndroid Build Coastguard Worker
133*5e7646d2SAndroid Build Coastguard Worker
134*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
135*5e7646d2SAndroid Build Coastguard Worker static const char *appleLangDefault(void);
136*5e7646d2SAndroid Build Coastguard Worker # ifdef CUPS_BUNDLEDIR
137*5e7646d2SAndroid Build Coastguard Worker # ifndef CF_RETURNS_RETAINED
138*5e7646d2SAndroid Build Coastguard Worker # if __has_feature(attribute_cf_returns_retained)
139*5e7646d2SAndroid Build Coastguard Worker # define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
140*5e7646d2SAndroid Build Coastguard Worker # else
141*5e7646d2SAndroid Build Coastguard Worker # define CF_RETURNS_RETAINED
142*5e7646d2SAndroid Build Coastguard Worker # endif /* __has_feature(attribute_cf_returns_retained) */
143*5e7646d2SAndroid Build Coastguard Worker # endif /* !CF_RETURNED_RETAINED */
144*5e7646d2SAndroid Build Coastguard Worker static cups_array_t *appleMessageLoad(const char *locale) CF_RETURNS_RETAINED;
145*5e7646d2SAndroid Build Coastguard Worker # endif /* CUPS_BUNDLEDIR */
146*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
147*5e7646d2SAndroid Build Coastguard Worker static cups_lang_t *cups_cache_lookup(const char *name, cups_encoding_t encoding);
148*5e7646d2SAndroid Build Coastguard Worker static int cups_message_compare(_cups_message_t *m1, _cups_message_t *m2);
149*5e7646d2SAndroid Build Coastguard Worker static void cups_message_free(_cups_message_t *m);
150*5e7646d2SAndroid Build Coastguard Worker static void cups_message_load(cups_lang_t *lang);
151*5e7646d2SAndroid Build Coastguard Worker static void cups_message_puts(cups_file_t *fp, const char *s);
152*5e7646d2SAndroid Build Coastguard Worker static int cups_read_strings(cups_file_t *fp, int flags, cups_array_t *a);
153*5e7646d2SAndroid Build Coastguard Worker static void cups_unquote(char *d, const char *s);
154*5e7646d2SAndroid Build Coastguard Worker
155*5e7646d2SAndroid Build Coastguard Worker
156*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
157*5e7646d2SAndroid Build Coastguard Worker /*
158*5e7646d2SAndroid Build Coastguard Worker * '_cupsAppleLanguage()' - Get the Apple language identifier associated with a
159*5e7646d2SAndroid Build Coastguard Worker * locale ID.
160*5e7646d2SAndroid Build Coastguard Worker */
161*5e7646d2SAndroid Build Coastguard Worker
162*5e7646d2SAndroid Build Coastguard Worker const char * /* O - Language ID */
_cupsAppleLanguage(const char * locale,char * language,size_t langsize)163*5e7646d2SAndroid Build Coastguard Worker _cupsAppleLanguage(const char *locale, /* I - Locale ID */
164*5e7646d2SAndroid Build Coastguard Worker char *language,/* I - Language ID buffer */
165*5e7646d2SAndroid Build Coastguard Worker size_t langsize) /* I - Size of language ID buffer */
166*5e7646d2SAndroid Build Coastguard Worker {
167*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
168*5e7646d2SAndroid Build Coastguard Worker CFStringRef localeid, /* CF locale identifier */
169*5e7646d2SAndroid Build Coastguard Worker langid; /* CF language identifier */
170*5e7646d2SAndroid Build Coastguard Worker
171*5e7646d2SAndroid Build Coastguard Worker
172*5e7646d2SAndroid Build Coastguard Worker /*
173*5e7646d2SAndroid Build Coastguard Worker * Copy the locale name and convert, as needed, to the Apple-specific
174*5e7646d2SAndroid Build Coastguard Worker * locale identifier...
175*5e7646d2SAndroid Build Coastguard Worker */
176*5e7646d2SAndroid Build Coastguard Worker
177*5e7646d2SAndroid Build Coastguard Worker switch (strlen(locale))
178*5e7646d2SAndroid Build Coastguard Worker {
179*5e7646d2SAndroid Build Coastguard Worker default :
180*5e7646d2SAndroid Build Coastguard Worker /*
181*5e7646d2SAndroid Build Coastguard Worker * Invalid locale...
182*5e7646d2SAndroid Build Coastguard Worker */
183*5e7646d2SAndroid Build Coastguard Worker
184*5e7646d2SAndroid Build Coastguard Worker strlcpy(language, "en", langsize);
185*5e7646d2SAndroid Build Coastguard Worker break;
186*5e7646d2SAndroid Build Coastguard Worker
187*5e7646d2SAndroid Build Coastguard Worker case 2 :
188*5e7646d2SAndroid Build Coastguard Worker strlcpy(language, locale, langsize);
189*5e7646d2SAndroid Build Coastguard Worker break;
190*5e7646d2SAndroid Build Coastguard Worker
191*5e7646d2SAndroid Build Coastguard Worker case 5 :
192*5e7646d2SAndroid Build Coastguard Worker strlcpy(language, locale, langsize);
193*5e7646d2SAndroid Build Coastguard Worker
194*5e7646d2SAndroid Build Coastguard Worker if (language[2] == '-')
195*5e7646d2SAndroid Build Coastguard Worker {
196*5e7646d2SAndroid Build Coastguard Worker /*
197*5e7646d2SAndroid Build Coastguard Worker * Convert ll-cc to ll_CC...
198*5e7646d2SAndroid Build Coastguard Worker */
199*5e7646d2SAndroid Build Coastguard Worker
200*5e7646d2SAndroid Build Coastguard Worker language[2] = '_';
201*5e7646d2SAndroid Build Coastguard Worker language[3] = (char)toupper(language[3] & 255);
202*5e7646d2SAndroid Build Coastguard Worker language[4] = (char)toupper(language[4] & 255);
203*5e7646d2SAndroid Build Coastguard Worker }
204*5e7646d2SAndroid Build Coastguard Worker break;
205*5e7646d2SAndroid Build Coastguard Worker }
206*5e7646d2SAndroid Build Coastguard Worker
207*5e7646d2SAndroid Build Coastguard Worker for (i = 0;
208*5e7646d2SAndroid Build Coastguard Worker i < (int)(sizeof(apple_language_locale) /
209*5e7646d2SAndroid Build Coastguard Worker sizeof(apple_language_locale[0]));
210*5e7646d2SAndroid Build Coastguard Worker i ++)
211*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(locale, apple_language_locale[i].locale))
212*5e7646d2SAndroid Build Coastguard Worker {
213*5e7646d2SAndroid Build Coastguard Worker strlcpy(language, apple_language_locale[i].language, sizeof(language));
214*5e7646d2SAndroid Build Coastguard Worker break;
215*5e7646d2SAndroid Build Coastguard Worker }
216*5e7646d2SAndroid Build Coastguard Worker
217*5e7646d2SAndroid Build Coastguard Worker /*
218*5e7646d2SAndroid Build Coastguard Worker * Attempt to map the locale ID to a language ID...
219*5e7646d2SAndroid Build Coastguard Worker */
220*5e7646d2SAndroid Build Coastguard Worker
221*5e7646d2SAndroid Build Coastguard Worker if ((localeid = CFStringCreateWithCString(kCFAllocatorDefault, language,
222*5e7646d2SAndroid Build Coastguard Worker kCFStringEncodingASCII)) != NULL)
223*5e7646d2SAndroid Build Coastguard Worker {
224*5e7646d2SAndroid Build Coastguard Worker if ((langid = CFLocaleCreateCanonicalLanguageIdentifierFromString(
225*5e7646d2SAndroid Build Coastguard Worker kCFAllocatorDefault, localeid)) != NULL)
226*5e7646d2SAndroid Build Coastguard Worker {
227*5e7646d2SAndroid Build Coastguard Worker CFStringGetCString(langid, language, (CFIndex)langsize, kCFStringEncodingASCII);
228*5e7646d2SAndroid Build Coastguard Worker CFRelease(langid);
229*5e7646d2SAndroid Build Coastguard Worker }
230*5e7646d2SAndroid Build Coastguard Worker
231*5e7646d2SAndroid Build Coastguard Worker CFRelease(localeid);
232*5e7646d2SAndroid Build Coastguard Worker }
233*5e7646d2SAndroid Build Coastguard Worker
234*5e7646d2SAndroid Build Coastguard Worker /*
235*5e7646d2SAndroid Build Coastguard Worker * Return what we got...
236*5e7646d2SAndroid Build Coastguard Worker */
237*5e7646d2SAndroid Build Coastguard Worker
238*5e7646d2SAndroid Build Coastguard Worker return (language);
239*5e7646d2SAndroid Build Coastguard Worker }
240*5e7646d2SAndroid Build Coastguard Worker
241*5e7646d2SAndroid Build Coastguard Worker
242*5e7646d2SAndroid Build Coastguard Worker /*
243*5e7646d2SAndroid Build Coastguard Worker * '_cupsAppleLocale()' - Get the locale associated with an Apple language ID.
244*5e7646d2SAndroid Build Coastguard Worker */
245*5e7646d2SAndroid Build Coastguard Worker
246*5e7646d2SAndroid Build Coastguard Worker const char * /* O - Locale */
_cupsAppleLocale(CFStringRef languageName,char * locale,size_t localesize)247*5e7646d2SAndroid Build Coastguard Worker _cupsAppleLocale(CFStringRef languageName, /* I - Apple language ID */
248*5e7646d2SAndroid Build Coastguard Worker char *locale, /* I - Buffer for locale */
249*5e7646d2SAndroid Build Coastguard Worker size_t localesize) /* I - Size of buffer */
250*5e7646d2SAndroid Build Coastguard Worker {
251*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
252*5e7646d2SAndroid Build Coastguard Worker CFStringRef localeName; /* Locale as a CF string */
253*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
254*5e7646d2SAndroid Build Coastguard Worker char temp[1024]; /* Temporary string */
255*5e7646d2SAndroid Build Coastguard Worker
256*5e7646d2SAndroid Build Coastguard Worker
257*5e7646d2SAndroid Build Coastguard Worker if (!CFStringGetCString(languageName, temp, (CFIndex)sizeof(temp), kCFStringEncodingASCII))
258*5e7646d2SAndroid Build Coastguard Worker temp[0] = '\0';
259*5e7646d2SAndroid Build Coastguard Worker
260*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_cupsAppleLocale(languageName=%p(%s), locale=%p, localsize=%d)", (void *)languageName, temp, (void *)locale, (int)localesize));
261*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
262*5e7646d2SAndroid Build Coastguard Worker
263*5e7646d2SAndroid Build Coastguard Worker localeName = CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorDefault, languageName);
264*5e7646d2SAndroid Build Coastguard Worker
265*5e7646d2SAndroid Build Coastguard Worker if (localeName)
266*5e7646d2SAndroid Build Coastguard Worker {
267*5e7646d2SAndroid Build Coastguard Worker /*
268*5e7646d2SAndroid Build Coastguard Worker * Copy the locale name and tweak as needed...
269*5e7646d2SAndroid Build Coastguard Worker */
270*5e7646d2SAndroid Build Coastguard Worker
271*5e7646d2SAndroid Build Coastguard Worker if (!CFStringGetCString(localeName, locale, (CFIndex)localesize, kCFStringEncodingASCII))
272*5e7646d2SAndroid Build Coastguard Worker *locale = '\0';
273*5e7646d2SAndroid Build Coastguard Worker
274*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_cupsAppleLocale: locale=\"%s\"", locale));
275*5e7646d2SAndroid Build Coastguard Worker
276*5e7646d2SAndroid Build Coastguard Worker CFRelease(localeName);
277*5e7646d2SAndroid Build Coastguard Worker
278*5e7646d2SAndroid Build Coastguard Worker /*
279*5e7646d2SAndroid Build Coastguard Worker * Map new language identifiers to locales...
280*5e7646d2SAndroid Build Coastguard Worker */
281*5e7646d2SAndroid Build Coastguard Worker
282*5e7646d2SAndroid Build Coastguard Worker for (i = 0;
283*5e7646d2SAndroid Build Coastguard Worker i < (int)(sizeof(apple_language_locale) /
284*5e7646d2SAndroid Build Coastguard Worker sizeof(apple_language_locale[0]));
285*5e7646d2SAndroid Build Coastguard Worker i ++)
286*5e7646d2SAndroid Build Coastguard Worker {
287*5e7646d2SAndroid Build Coastguard Worker size_t len = strlen(apple_language_locale[i].language);
288*5e7646d2SAndroid Build Coastguard Worker
289*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(locale, apple_language_locale[i].language) ||
290*5e7646d2SAndroid Build Coastguard Worker (!strncmp(locale, apple_language_locale[i].language, len) && (locale[len] == '_' || locale[len] == '-')))
291*5e7646d2SAndroid Build Coastguard Worker {
292*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_cupsAppleLocale: Updating locale to \"%s\".", apple_language_locale[i].locale));
293*5e7646d2SAndroid Build Coastguard Worker strlcpy(locale, apple_language_locale[i].locale, localesize);
294*5e7646d2SAndroid Build Coastguard Worker break;
295*5e7646d2SAndroid Build Coastguard Worker }
296*5e7646d2SAndroid Build Coastguard Worker }
297*5e7646d2SAndroid Build Coastguard Worker }
298*5e7646d2SAndroid Build Coastguard Worker else
299*5e7646d2SAndroid Build Coastguard Worker {
300*5e7646d2SAndroid Build Coastguard Worker /*
301*5e7646d2SAndroid Build Coastguard Worker * Just try the Apple language name...
302*5e7646d2SAndroid Build Coastguard Worker */
303*5e7646d2SAndroid Build Coastguard Worker
304*5e7646d2SAndroid Build Coastguard Worker if (!CFStringGetCString(languageName, locale, (CFIndex)localesize, kCFStringEncodingASCII))
305*5e7646d2SAndroid Build Coastguard Worker *locale = '\0';
306*5e7646d2SAndroid Build Coastguard Worker }
307*5e7646d2SAndroid Build Coastguard Worker
308*5e7646d2SAndroid Build Coastguard Worker if (!*locale)
309*5e7646d2SAndroid Build Coastguard Worker {
310*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("_cupsAppleLocale: Returning NULL.");
311*5e7646d2SAndroid Build Coastguard Worker return (NULL);
312*5e7646d2SAndroid Build Coastguard Worker }
313*5e7646d2SAndroid Build Coastguard Worker
314*5e7646d2SAndroid Build Coastguard Worker /*
315*5e7646d2SAndroid Build Coastguard Worker * Convert language subtag into region subtag...
316*5e7646d2SAndroid Build Coastguard Worker */
317*5e7646d2SAndroid Build Coastguard Worker
318*5e7646d2SAndroid Build Coastguard Worker if (locale[2] == '-')
319*5e7646d2SAndroid Build Coastguard Worker locale[2] = '_';
320*5e7646d2SAndroid Build Coastguard Worker else if (locale[3] == '-')
321*5e7646d2SAndroid Build Coastguard Worker locale[3] = '_';
322*5e7646d2SAndroid Build Coastguard Worker
323*5e7646d2SAndroid Build Coastguard Worker if (!strchr(locale, '.'))
324*5e7646d2SAndroid Build Coastguard Worker strlcat(locale, ".UTF-8", localesize);
325*5e7646d2SAndroid Build Coastguard Worker
326*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_cupsAppleLocale: Returning \"%s\".", locale));
327*5e7646d2SAndroid Build Coastguard Worker
328*5e7646d2SAndroid Build Coastguard Worker return (locale);
329*5e7646d2SAndroid Build Coastguard Worker }
330*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
331*5e7646d2SAndroid Build Coastguard Worker
332*5e7646d2SAndroid Build Coastguard Worker
333*5e7646d2SAndroid Build Coastguard Worker /*
334*5e7646d2SAndroid Build Coastguard Worker * '_cupsEncodingName()' - Return the character encoding name string
335*5e7646d2SAndroid Build Coastguard Worker * for the given encoding enumeration.
336*5e7646d2SAndroid Build Coastguard Worker */
337*5e7646d2SAndroid Build Coastguard Worker
338*5e7646d2SAndroid Build Coastguard Worker const char * /* O - Character encoding */
_cupsEncodingName(cups_encoding_t encoding)339*5e7646d2SAndroid Build Coastguard Worker _cupsEncodingName(
340*5e7646d2SAndroid Build Coastguard Worker cups_encoding_t encoding) /* I - Encoding value */
341*5e7646d2SAndroid Build Coastguard Worker {
342*5e7646d2SAndroid Build Coastguard Worker if (encoding < CUPS_US_ASCII ||
343*5e7646d2SAndroid Build Coastguard Worker encoding >= (cups_encoding_t)(sizeof(lang_encodings) / sizeof(lang_encodings[0])))
344*5e7646d2SAndroid Build Coastguard Worker {
345*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1_cupsEncodingName(encoding=%d) = out of range (\"%s\")",
346*5e7646d2SAndroid Build Coastguard Worker encoding, lang_encodings[0]));
347*5e7646d2SAndroid Build Coastguard Worker return (lang_encodings[0]);
348*5e7646d2SAndroid Build Coastguard Worker }
349*5e7646d2SAndroid Build Coastguard Worker else
350*5e7646d2SAndroid Build Coastguard Worker {
351*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1_cupsEncodingName(encoding=%d) = \"%s\"",
352*5e7646d2SAndroid Build Coastguard Worker encoding, lang_encodings[encoding]));
353*5e7646d2SAndroid Build Coastguard Worker return (lang_encodings[encoding]);
354*5e7646d2SAndroid Build Coastguard Worker }
355*5e7646d2SAndroid Build Coastguard Worker }
356*5e7646d2SAndroid Build Coastguard Worker
357*5e7646d2SAndroid Build Coastguard Worker
358*5e7646d2SAndroid Build Coastguard Worker /*
359*5e7646d2SAndroid Build Coastguard Worker * 'cupsLangDefault()' - Return the default language.
360*5e7646d2SAndroid Build Coastguard Worker */
361*5e7646d2SAndroid Build Coastguard Worker
362*5e7646d2SAndroid Build Coastguard Worker cups_lang_t * /* O - Language data */
cupsLangDefault(void)363*5e7646d2SAndroid Build Coastguard Worker cupsLangDefault(void)
364*5e7646d2SAndroid Build Coastguard Worker {
365*5e7646d2SAndroid Build Coastguard Worker return (cupsLangGet(NULL));
366*5e7646d2SAndroid Build Coastguard Worker }
367*5e7646d2SAndroid Build Coastguard Worker
368*5e7646d2SAndroid Build Coastguard Worker
369*5e7646d2SAndroid Build Coastguard Worker /*
370*5e7646d2SAndroid Build Coastguard Worker * 'cupsLangEncoding()' - Return the character encoding (us-ascii, etc.)
371*5e7646d2SAndroid Build Coastguard Worker * for the given language.
372*5e7646d2SAndroid Build Coastguard Worker */
373*5e7646d2SAndroid Build Coastguard Worker
374*5e7646d2SAndroid Build Coastguard Worker const char * /* O - Character encoding */
cupsLangEncoding(cups_lang_t * lang)375*5e7646d2SAndroid Build Coastguard Worker cupsLangEncoding(cups_lang_t *lang) /* I - Language data */
376*5e7646d2SAndroid Build Coastguard Worker {
377*5e7646d2SAndroid Build Coastguard Worker if (lang == NULL)
378*5e7646d2SAndroid Build Coastguard Worker return ((char*)lang_encodings[0]);
379*5e7646d2SAndroid Build Coastguard Worker else
380*5e7646d2SAndroid Build Coastguard Worker return ((char*)lang_encodings[lang->encoding]);
381*5e7646d2SAndroid Build Coastguard Worker }
382*5e7646d2SAndroid Build Coastguard Worker
383*5e7646d2SAndroid Build Coastguard Worker
384*5e7646d2SAndroid Build Coastguard Worker /*
385*5e7646d2SAndroid Build Coastguard Worker * 'cupsLangFlush()' - Flush all language data out of the cache.
386*5e7646d2SAndroid Build Coastguard Worker */
387*5e7646d2SAndroid Build Coastguard Worker
388*5e7646d2SAndroid Build Coastguard Worker void
cupsLangFlush(void)389*5e7646d2SAndroid Build Coastguard Worker cupsLangFlush(void)
390*5e7646d2SAndroid Build Coastguard Worker {
391*5e7646d2SAndroid Build Coastguard Worker cups_lang_t *lang, /* Current language */
392*5e7646d2SAndroid Build Coastguard Worker *next; /* Next language */
393*5e7646d2SAndroid Build Coastguard Worker
394*5e7646d2SAndroid Build Coastguard Worker
395*5e7646d2SAndroid Build Coastguard Worker /*
396*5e7646d2SAndroid Build Coastguard Worker * Free all languages in the cache...
397*5e7646d2SAndroid Build Coastguard Worker */
398*5e7646d2SAndroid Build Coastguard Worker
399*5e7646d2SAndroid Build Coastguard Worker _cupsMutexLock(&lang_mutex);
400*5e7646d2SAndroid Build Coastguard Worker
401*5e7646d2SAndroid Build Coastguard Worker for (lang = lang_cache; lang != NULL; lang = next)
402*5e7646d2SAndroid Build Coastguard Worker {
403*5e7646d2SAndroid Build Coastguard Worker /*
404*5e7646d2SAndroid Build Coastguard Worker * Free all messages...
405*5e7646d2SAndroid Build Coastguard Worker */
406*5e7646d2SAndroid Build Coastguard Worker
407*5e7646d2SAndroid Build Coastguard Worker _cupsMessageFree(lang->strings);
408*5e7646d2SAndroid Build Coastguard Worker
409*5e7646d2SAndroid Build Coastguard Worker /*
410*5e7646d2SAndroid Build Coastguard Worker * Then free the language structure itself...
411*5e7646d2SAndroid Build Coastguard Worker */
412*5e7646d2SAndroid Build Coastguard Worker
413*5e7646d2SAndroid Build Coastguard Worker next = lang->next;
414*5e7646d2SAndroid Build Coastguard Worker free(lang);
415*5e7646d2SAndroid Build Coastguard Worker }
416*5e7646d2SAndroid Build Coastguard Worker
417*5e7646d2SAndroid Build Coastguard Worker lang_cache = NULL;
418*5e7646d2SAndroid Build Coastguard Worker
419*5e7646d2SAndroid Build Coastguard Worker _cupsMutexUnlock(&lang_mutex);
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 * 'cupsLangFree()' - Free language data.
425*5e7646d2SAndroid Build Coastguard Worker *
426*5e7646d2SAndroid Build Coastguard Worker * This does not actually free anything; use @link cupsLangFlush@ for that.
427*5e7646d2SAndroid Build Coastguard Worker */
428*5e7646d2SAndroid Build Coastguard Worker
429*5e7646d2SAndroid Build Coastguard Worker void
cupsLangFree(cups_lang_t * lang)430*5e7646d2SAndroid Build Coastguard Worker cupsLangFree(cups_lang_t *lang) /* I - Language to free */
431*5e7646d2SAndroid Build Coastguard Worker {
432*5e7646d2SAndroid Build Coastguard Worker _cupsMutexLock(&lang_mutex);
433*5e7646d2SAndroid Build Coastguard Worker
434*5e7646d2SAndroid Build Coastguard Worker if (lang != NULL && lang->used > 0)
435*5e7646d2SAndroid Build Coastguard Worker lang->used --;
436*5e7646d2SAndroid Build Coastguard Worker
437*5e7646d2SAndroid Build Coastguard Worker _cupsMutexUnlock(&lang_mutex);
438*5e7646d2SAndroid Build Coastguard Worker }
439*5e7646d2SAndroid Build Coastguard Worker
440*5e7646d2SAndroid Build Coastguard Worker
441*5e7646d2SAndroid Build Coastguard Worker /*
442*5e7646d2SAndroid Build Coastguard Worker * 'cupsLangGet()' - Get a language.
443*5e7646d2SAndroid Build Coastguard Worker */
444*5e7646d2SAndroid Build Coastguard Worker
445*5e7646d2SAndroid Build Coastguard Worker cups_lang_t * /* O - Language data */
cupsLangGet(const char * language)446*5e7646d2SAndroid Build Coastguard Worker cupsLangGet(const char *language) /* I - Language or locale */
447*5e7646d2SAndroid Build Coastguard Worker {
448*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
449*5e7646d2SAndroid Build Coastguard Worker #ifndef __APPLE__
450*5e7646d2SAndroid Build Coastguard Worker char locale[255]; /* Copy of locale name */
451*5e7646d2SAndroid Build Coastguard Worker #endif /* !__APPLE__ */
452*5e7646d2SAndroid Build Coastguard Worker char langname[16], /* Requested language name */
453*5e7646d2SAndroid Build Coastguard Worker country[16], /* Country code */
454*5e7646d2SAndroid Build Coastguard Worker charset[16], /* Character set */
455*5e7646d2SAndroid Build Coastguard Worker *csptr, /* Pointer to CODESET string */
456*5e7646d2SAndroid Build Coastguard Worker *ptr, /* Pointer into language/charset */
457*5e7646d2SAndroid Build Coastguard Worker real[48]; /* Real language name */
458*5e7646d2SAndroid Build Coastguard Worker cups_encoding_t encoding; /* Encoding to use */
459*5e7646d2SAndroid Build Coastguard Worker cups_lang_t *lang; /* Current language... */
460*5e7646d2SAndroid Build Coastguard Worker static const char * const locale_encodings[] =
461*5e7646d2SAndroid Build Coastguard Worker { /* Locale charset names */
462*5e7646d2SAndroid Build Coastguard Worker "ASCII", "ISO88591", "ISO88592", "ISO88593",
463*5e7646d2SAndroid Build Coastguard Worker "ISO88594", "ISO88595", "ISO88596", "ISO88597",
464*5e7646d2SAndroid Build Coastguard Worker "ISO88598", "ISO88599", "ISO885910", "UTF8",
465*5e7646d2SAndroid Build Coastguard Worker "ISO885913", "ISO885914", "ISO885915", "CP874",
466*5e7646d2SAndroid Build Coastguard Worker "CP1250", "CP1251", "CP1252", "CP1253",
467*5e7646d2SAndroid Build Coastguard Worker "CP1254", "CP1255", "CP1256", "CP1257",
468*5e7646d2SAndroid Build Coastguard Worker "CP1258", "KOI8R", "KOI8U", "ISO885911",
469*5e7646d2SAndroid Build Coastguard Worker "ISO885916", "MACROMAN", "", "",
470*5e7646d2SAndroid Build Coastguard Worker
471*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
472*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
473*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
474*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
475*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
476*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
477*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
478*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
479*5e7646d2SAndroid Build Coastguard Worker
480*5e7646d2SAndroid Build Coastguard Worker "CP932", "CP936", "CP949", "CP950",
481*5e7646d2SAndroid Build Coastguard Worker "CP1361", "", "", "",
482*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
483*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
484*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
485*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
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 "", "", "", "",
491*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
492*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
493*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
494*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
495*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
496*5e7646d2SAndroid Build Coastguard Worker "", "", "", "",
497*5e7646d2SAndroid Build Coastguard Worker
498*5e7646d2SAndroid Build Coastguard Worker "EUCCN", "EUCJP", "EUCKR", "EUCTW",
499*5e7646d2SAndroid Build Coastguard Worker "SHIFT_JISX0213"
500*5e7646d2SAndroid Build Coastguard Worker };
501*5e7646d2SAndroid Build Coastguard Worker
502*5e7646d2SAndroid Build Coastguard Worker
503*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2cupsLangGet(language=\"%s\")", language));
504*5e7646d2SAndroid Build Coastguard Worker
505*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
506*5e7646d2SAndroid Build Coastguard Worker /*
507*5e7646d2SAndroid Build Coastguard Worker * Set the character set to UTF-8...
508*5e7646d2SAndroid Build Coastguard Worker */
509*5e7646d2SAndroid Build Coastguard Worker
510*5e7646d2SAndroid Build Coastguard Worker strlcpy(charset, "UTF8", sizeof(charset));
511*5e7646d2SAndroid Build Coastguard Worker
512*5e7646d2SAndroid Build Coastguard Worker /*
513*5e7646d2SAndroid Build Coastguard Worker * Apple's setlocale doesn't give us the user's localization
514*5e7646d2SAndroid Build Coastguard Worker * preference so we have to look it up this way...
515*5e7646d2SAndroid Build Coastguard Worker */
516*5e7646d2SAndroid Build Coastguard Worker
517*5e7646d2SAndroid Build Coastguard Worker if (!language)
518*5e7646d2SAndroid Build Coastguard Worker {
519*5e7646d2SAndroid Build Coastguard Worker if (!getenv("SOFTWARE") || (language = getenv("LANG")) == NULL)
520*5e7646d2SAndroid Build Coastguard Worker language = appleLangDefault();
521*5e7646d2SAndroid Build Coastguard Worker
522*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4cupsLangGet: language=\"%s\"", language));
523*5e7646d2SAndroid Build Coastguard Worker }
524*5e7646d2SAndroid Build Coastguard Worker
525*5e7646d2SAndroid Build Coastguard Worker #else
526*5e7646d2SAndroid Build Coastguard Worker /*
527*5e7646d2SAndroid Build Coastguard Worker * Set the charset to "unknown"...
528*5e7646d2SAndroid Build Coastguard Worker */
529*5e7646d2SAndroid Build Coastguard Worker
530*5e7646d2SAndroid Build Coastguard Worker charset[0] = '\0';
531*5e7646d2SAndroid Build Coastguard Worker
532*5e7646d2SAndroid Build Coastguard Worker /*
533*5e7646d2SAndroid Build Coastguard Worker * Use setlocale() to determine the currently set locale, and then
534*5e7646d2SAndroid Build Coastguard Worker * fallback to environment variables to avoid setting the locale,
535*5e7646d2SAndroid Build Coastguard Worker * since setlocale() is not thread-safe!
536*5e7646d2SAndroid Build Coastguard Worker */
537*5e7646d2SAndroid Build Coastguard Worker
538*5e7646d2SAndroid Build Coastguard Worker if (!language)
539*5e7646d2SAndroid Build Coastguard Worker {
540*5e7646d2SAndroid Build Coastguard Worker /*
541*5e7646d2SAndroid Build Coastguard Worker * First see if the locale has been set; if it is still "C" or
542*5e7646d2SAndroid Build Coastguard Worker * "POSIX", use the environment to get the default...
543*5e7646d2SAndroid Build Coastguard Worker */
544*5e7646d2SAndroid Build Coastguard Worker
545*5e7646d2SAndroid Build Coastguard Worker # ifdef LC_MESSAGES
546*5e7646d2SAndroid Build Coastguard Worker ptr = setlocale(LC_MESSAGES, NULL);
547*5e7646d2SAndroid Build Coastguard Worker # else
548*5e7646d2SAndroid Build Coastguard Worker ptr = setlocale(LC_ALL, NULL);
549*5e7646d2SAndroid Build Coastguard Worker # endif /* LC_MESSAGES */
550*5e7646d2SAndroid Build Coastguard Worker
551*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4cupsLangGet: current locale is \"%s\"", ptr));
552*5e7646d2SAndroid Build Coastguard Worker
553*5e7646d2SAndroid Build Coastguard Worker if (!ptr || !strcmp(ptr, "C") || !strcmp(ptr, "POSIX"))
554*5e7646d2SAndroid Build Coastguard Worker {
555*5e7646d2SAndroid Build Coastguard Worker /*
556*5e7646d2SAndroid Build Coastguard Worker * Get the character set from the LC_CTYPE locale setting...
557*5e7646d2SAndroid Build Coastguard Worker */
558*5e7646d2SAndroid Build Coastguard Worker
559*5e7646d2SAndroid Build Coastguard Worker if ((ptr = getenv("LC_CTYPE")) == NULL)
560*5e7646d2SAndroid Build Coastguard Worker if ((ptr = getenv("LC_ALL")) == NULL)
561*5e7646d2SAndroid Build Coastguard Worker if ((ptr = getenv("LANG")) == NULL)
562*5e7646d2SAndroid Build Coastguard Worker ptr = "en_US";
563*5e7646d2SAndroid Build Coastguard Worker
564*5e7646d2SAndroid Build Coastguard Worker if ((csptr = strchr(ptr, '.')) != NULL)
565*5e7646d2SAndroid Build Coastguard Worker {
566*5e7646d2SAndroid Build Coastguard Worker /*
567*5e7646d2SAndroid Build Coastguard Worker * Extract the character set from the environment...
568*5e7646d2SAndroid Build Coastguard Worker */
569*5e7646d2SAndroid Build Coastguard Worker
570*5e7646d2SAndroid Build Coastguard Worker for (ptr = charset, csptr ++; *csptr; csptr ++)
571*5e7646d2SAndroid Build Coastguard Worker if (ptr < (charset + sizeof(charset) - 1) && _cups_isalnum(*csptr))
572*5e7646d2SAndroid Build Coastguard Worker *ptr++ = *csptr;
573*5e7646d2SAndroid Build Coastguard Worker
574*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
575*5e7646d2SAndroid Build Coastguard Worker }
576*5e7646d2SAndroid Build Coastguard Worker
577*5e7646d2SAndroid Build Coastguard Worker /*
578*5e7646d2SAndroid Build Coastguard Worker * Get the locale for messages from the LC_MESSAGES locale setting...
579*5e7646d2SAndroid Build Coastguard Worker */
580*5e7646d2SAndroid Build Coastguard Worker
581*5e7646d2SAndroid Build Coastguard Worker if ((ptr = getenv("LC_MESSAGES")) == NULL)
582*5e7646d2SAndroid Build Coastguard Worker if ((ptr = getenv("LC_ALL")) == NULL)
583*5e7646d2SAndroid Build Coastguard Worker if ((ptr = getenv("LANG")) == NULL)
584*5e7646d2SAndroid Build Coastguard Worker ptr = "en_US";
585*5e7646d2SAndroid Build Coastguard Worker }
586*5e7646d2SAndroid Build Coastguard Worker
587*5e7646d2SAndroid Build Coastguard Worker if (ptr)
588*5e7646d2SAndroid Build Coastguard Worker {
589*5e7646d2SAndroid Build Coastguard Worker strlcpy(locale, ptr, sizeof(locale));
590*5e7646d2SAndroid Build Coastguard Worker language = locale;
591*5e7646d2SAndroid Build Coastguard Worker
592*5e7646d2SAndroid Build Coastguard Worker /*
593*5e7646d2SAndroid Build Coastguard Worker * CUPS STR #2575: Map "nb" to "no" for back-compatibility...
594*5e7646d2SAndroid Build Coastguard Worker */
595*5e7646d2SAndroid Build Coastguard Worker
596*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(locale, "nb", 2))
597*5e7646d2SAndroid Build Coastguard Worker locale[1] = 'o';
598*5e7646d2SAndroid Build Coastguard Worker
599*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4cupsLangGet: new language value is \"%s\"", language));
600*5e7646d2SAndroid Build Coastguard Worker }
601*5e7646d2SAndroid Build Coastguard Worker }
602*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
603*5e7646d2SAndroid Build Coastguard Worker
604*5e7646d2SAndroid Build Coastguard Worker /*
605*5e7646d2SAndroid Build Coastguard Worker * If "language" is NULL at this point, then chances are we are using
606*5e7646d2SAndroid Build Coastguard Worker * a language that is not installed for the base OS.
607*5e7646d2SAndroid Build Coastguard Worker */
608*5e7646d2SAndroid Build Coastguard Worker
609*5e7646d2SAndroid Build Coastguard Worker if (!language)
610*5e7646d2SAndroid Build Coastguard Worker {
611*5e7646d2SAndroid Build Coastguard Worker /*
612*5e7646d2SAndroid Build Coastguard Worker * Switch to the POSIX ("C") locale...
613*5e7646d2SAndroid Build Coastguard Worker */
614*5e7646d2SAndroid Build Coastguard Worker
615*5e7646d2SAndroid Build Coastguard Worker language = "C";
616*5e7646d2SAndroid Build Coastguard Worker }
617*5e7646d2SAndroid Build Coastguard Worker
618*5e7646d2SAndroid Build Coastguard Worker #ifdef CODESET
619*5e7646d2SAndroid Build Coastguard Worker /*
620*5e7646d2SAndroid Build Coastguard Worker * On systems that support the nl_langinfo(CODESET) call, use
621*5e7646d2SAndroid Build Coastguard Worker * this value as the character set...
622*5e7646d2SAndroid Build Coastguard Worker */
623*5e7646d2SAndroid Build Coastguard Worker
624*5e7646d2SAndroid Build Coastguard Worker if (!charset[0] && (csptr = nl_langinfo(CODESET)) != NULL)
625*5e7646d2SAndroid Build Coastguard Worker {
626*5e7646d2SAndroid Build Coastguard Worker /*
627*5e7646d2SAndroid Build Coastguard Worker * Copy all of the letters and numbers in the CODESET string...
628*5e7646d2SAndroid Build Coastguard Worker */
629*5e7646d2SAndroid Build Coastguard Worker
630*5e7646d2SAndroid Build Coastguard Worker for (ptr = charset; *csptr; csptr ++)
631*5e7646d2SAndroid Build Coastguard Worker if (_cups_isalnum(*csptr) && ptr < (charset + sizeof(charset) - 1))
632*5e7646d2SAndroid Build Coastguard Worker *ptr++ = *csptr;
633*5e7646d2SAndroid Build Coastguard Worker
634*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
635*5e7646d2SAndroid Build Coastguard Worker
636*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4cupsLangGet: charset set to \"%s\" via "
637*5e7646d2SAndroid Build Coastguard Worker "nl_langinfo(CODESET)...", charset));
638*5e7646d2SAndroid Build Coastguard Worker }
639*5e7646d2SAndroid Build Coastguard Worker #endif /* CODESET */
640*5e7646d2SAndroid Build Coastguard Worker
641*5e7646d2SAndroid Build Coastguard Worker /*
642*5e7646d2SAndroid Build Coastguard Worker * If we don't have a character set by now, default to UTF-8...
643*5e7646d2SAndroid Build Coastguard Worker */
644*5e7646d2SAndroid Build Coastguard Worker
645*5e7646d2SAndroid Build Coastguard Worker if (!charset[0])
646*5e7646d2SAndroid Build Coastguard Worker strlcpy(charset, "UTF8", sizeof(charset));
647*5e7646d2SAndroid Build Coastguard Worker
648*5e7646d2SAndroid Build Coastguard Worker /*
649*5e7646d2SAndroid Build Coastguard Worker * Parse the language string passed in to a locale string. "C" is the
650*5e7646d2SAndroid Build Coastguard Worker * standard POSIX locale and is copied unchanged. Otherwise the
651*5e7646d2SAndroid Build Coastguard Worker * language string is converted from ll-cc[.charset] (language-country)
652*5e7646d2SAndroid Build Coastguard Worker * to ll_CC[.CHARSET] to match the file naming convention used by all
653*5e7646d2SAndroid Build Coastguard Worker * POSIX-compliant operating systems. Invalid language names are mapped
654*5e7646d2SAndroid Build Coastguard Worker * to the POSIX locale.
655*5e7646d2SAndroid Build Coastguard Worker */
656*5e7646d2SAndroid Build Coastguard Worker
657*5e7646d2SAndroid Build Coastguard Worker country[0] = '\0';
658*5e7646d2SAndroid Build Coastguard Worker
659*5e7646d2SAndroid Build Coastguard Worker if (language == NULL || !language[0] ||
660*5e7646d2SAndroid Build Coastguard Worker !strcmp(language, "POSIX"))
661*5e7646d2SAndroid Build Coastguard Worker strlcpy(langname, "C", sizeof(langname));
662*5e7646d2SAndroid Build Coastguard Worker else
663*5e7646d2SAndroid Build Coastguard Worker {
664*5e7646d2SAndroid Build Coastguard Worker /*
665*5e7646d2SAndroid Build Coastguard Worker * Copy the parts of the locale string over safely...
666*5e7646d2SAndroid Build Coastguard Worker */
667*5e7646d2SAndroid Build Coastguard Worker
668*5e7646d2SAndroid Build Coastguard Worker for (ptr = langname; *language; language ++)
669*5e7646d2SAndroid Build Coastguard Worker if (*language == '_' || *language == '-' || *language == '.')
670*5e7646d2SAndroid Build Coastguard Worker break;
671*5e7646d2SAndroid Build Coastguard Worker else if (ptr < (langname + sizeof(langname) - 1))
672*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)tolower(*language & 255);
673*5e7646d2SAndroid Build Coastguard Worker
674*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
675*5e7646d2SAndroid Build Coastguard Worker
676*5e7646d2SAndroid Build Coastguard Worker if (*language == '_' || *language == '-')
677*5e7646d2SAndroid Build Coastguard Worker {
678*5e7646d2SAndroid Build Coastguard Worker /*
679*5e7646d2SAndroid Build Coastguard Worker * Copy the country code...
680*5e7646d2SAndroid Build Coastguard Worker */
681*5e7646d2SAndroid Build Coastguard Worker
682*5e7646d2SAndroid Build Coastguard Worker for (language ++, ptr = country; *language; language ++)
683*5e7646d2SAndroid Build Coastguard Worker if (*language == '.')
684*5e7646d2SAndroid Build Coastguard Worker break;
685*5e7646d2SAndroid Build Coastguard Worker else if (ptr < (country + sizeof(country) - 1))
686*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)toupper(*language & 255);
687*5e7646d2SAndroid Build Coastguard Worker
688*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
689*5e7646d2SAndroid Build Coastguard Worker
690*5e7646d2SAndroid Build Coastguard Worker /*
691*5e7646d2SAndroid Build Coastguard Worker * Map Chinese region codes to legacy country codes.
692*5e7646d2SAndroid Build Coastguard Worker */
693*5e7646d2SAndroid Build Coastguard Worker
694*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(language, "zh") && !strcmp(country, "HANS"))
695*5e7646d2SAndroid Build Coastguard Worker strlcpy(country, "CN", sizeof(country));
696*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(language, "zh") && !strcmp(country, "HANT"))
697*5e7646d2SAndroid Build Coastguard Worker strlcpy(country, "TW", sizeof(country));
698*5e7646d2SAndroid Build Coastguard Worker }
699*5e7646d2SAndroid Build Coastguard Worker
700*5e7646d2SAndroid Build Coastguard Worker if (*language == '.' && !charset[0])
701*5e7646d2SAndroid Build Coastguard Worker {
702*5e7646d2SAndroid Build Coastguard Worker /*
703*5e7646d2SAndroid Build Coastguard Worker * Copy the encoding...
704*5e7646d2SAndroid Build Coastguard Worker */
705*5e7646d2SAndroid Build Coastguard Worker
706*5e7646d2SAndroid Build Coastguard Worker for (language ++, ptr = charset; *language; language ++)
707*5e7646d2SAndroid Build Coastguard Worker if (_cups_isalnum(*language) && ptr < (charset + sizeof(charset) - 1))
708*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)toupper(*language & 255);
709*5e7646d2SAndroid Build Coastguard Worker
710*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
711*5e7646d2SAndroid Build Coastguard Worker }
712*5e7646d2SAndroid Build Coastguard Worker
713*5e7646d2SAndroid Build Coastguard Worker /*
714*5e7646d2SAndroid Build Coastguard Worker * Force a POSIX locale for an invalid language name...
715*5e7646d2SAndroid Build Coastguard Worker */
716*5e7646d2SAndroid Build Coastguard Worker
717*5e7646d2SAndroid Build Coastguard Worker if (strlen(langname) != 2 && strlen(langname) != 3)
718*5e7646d2SAndroid Build Coastguard Worker {
719*5e7646d2SAndroid Build Coastguard Worker strlcpy(langname, "C", sizeof(langname));
720*5e7646d2SAndroid Build Coastguard Worker country[0] = '\0';
721*5e7646d2SAndroid Build Coastguard Worker charset[0] = '\0';
722*5e7646d2SAndroid Build Coastguard Worker }
723*5e7646d2SAndroid Build Coastguard Worker }
724*5e7646d2SAndroid Build Coastguard Worker
725*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4cupsLangGet: langname=\"%s\", country=\"%s\", charset=\"%s\"",
726*5e7646d2SAndroid Build Coastguard Worker langname, country, charset));
727*5e7646d2SAndroid Build Coastguard Worker
728*5e7646d2SAndroid Build Coastguard Worker /*
729*5e7646d2SAndroid Build Coastguard Worker * Figure out the desired encoding...
730*5e7646d2SAndroid Build Coastguard Worker */
731*5e7646d2SAndroid Build Coastguard Worker
732*5e7646d2SAndroid Build Coastguard Worker encoding = CUPS_AUTO_ENCODING;
733*5e7646d2SAndroid Build Coastguard Worker
734*5e7646d2SAndroid Build Coastguard Worker if (charset[0])
735*5e7646d2SAndroid Build Coastguard Worker {
736*5e7646d2SAndroid Build Coastguard Worker for (i = 0;
737*5e7646d2SAndroid Build Coastguard Worker i < (int)(sizeof(locale_encodings) / sizeof(locale_encodings[0]));
738*5e7646d2SAndroid Build Coastguard Worker i ++)
739*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(charset, locale_encodings[i]))
740*5e7646d2SAndroid Build Coastguard Worker {
741*5e7646d2SAndroid Build Coastguard Worker encoding = (cups_encoding_t)i;
742*5e7646d2SAndroid Build Coastguard Worker break;
743*5e7646d2SAndroid Build Coastguard Worker }
744*5e7646d2SAndroid Build Coastguard Worker
745*5e7646d2SAndroid Build Coastguard Worker if (encoding == CUPS_AUTO_ENCODING)
746*5e7646d2SAndroid Build Coastguard Worker {
747*5e7646d2SAndroid Build Coastguard Worker /*
748*5e7646d2SAndroid Build Coastguard Worker * Map alternate names for various character sets...
749*5e7646d2SAndroid Build Coastguard Worker */
750*5e7646d2SAndroid Build Coastguard Worker
751*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(charset, "iso-2022-jp") ||
752*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(charset, "sjis"))
753*5e7646d2SAndroid Build Coastguard Worker encoding = CUPS_WINDOWS_932;
754*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(charset, "iso-2022-cn"))
755*5e7646d2SAndroid Build Coastguard Worker encoding = CUPS_WINDOWS_936;
756*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(charset, "iso-2022-kr"))
757*5e7646d2SAndroid Build Coastguard Worker encoding = CUPS_WINDOWS_949;
758*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(charset, "big5"))
759*5e7646d2SAndroid Build Coastguard Worker encoding = CUPS_WINDOWS_950;
760*5e7646d2SAndroid Build Coastguard Worker }
761*5e7646d2SAndroid Build Coastguard Worker }
762*5e7646d2SAndroid Build Coastguard Worker
763*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4cupsLangGet: encoding=%d(%s)", encoding,
764*5e7646d2SAndroid Build Coastguard Worker encoding == CUPS_AUTO_ENCODING ? "auto" :
765*5e7646d2SAndroid Build Coastguard Worker lang_encodings[encoding]));
766*5e7646d2SAndroid Build Coastguard Worker
767*5e7646d2SAndroid Build Coastguard Worker /*
768*5e7646d2SAndroid Build Coastguard Worker * See if we already have this language/country loaded...
769*5e7646d2SAndroid Build Coastguard Worker */
770*5e7646d2SAndroid Build Coastguard Worker
771*5e7646d2SAndroid Build Coastguard Worker if (country[0])
772*5e7646d2SAndroid Build Coastguard Worker snprintf(real, sizeof(real), "%s_%s", langname, country);
773*5e7646d2SAndroid Build Coastguard Worker else
774*5e7646d2SAndroid Build Coastguard Worker strlcpy(real, langname, sizeof(real));
775*5e7646d2SAndroid Build Coastguard Worker
776*5e7646d2SAndroid Build Coastguard Worker _cupsMutexLock(&lang_mutex);
777*5e7646d2SAndroid Build Coastguard Worker
778*5e7646d2SAndroid Build Coastguard Worker if ((lang = cups_cache_lookup(real, encoding)) != NULL)
779*5e7646d2SAndroid Build Coastguard Worker {
780*5e7646d2SAndroid Build Coastguard Worker _cupsMutexUnlock(&lang_mutex);
781*5e7646d2SAndroid Build Coastguard Worker
782*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("3cupsLangGet: Using cached copy of \"%s\"...", real));
783*5e7646d2SAndroid Build Coastguard Worker
784*5e7646d2SAndroid Build Coastguard Worker return (lang);
785*5e7646d2SAndroid Build Coastguard Worker }
786*5e7646d2SAndroid Build Coastguard Worker
787*5e7646d2SAndroid Build Coastguard Worker /*
788*5e7646d2SAndroid Build Coastguard Worker * See if there is a free language available; if so, use that
789*5e7646d2SAndroid Build Coastguard Worker * record...
790*5e7646d2SAndroid Build Coastguard Worker */
791*5e7646d2SAndroid Build Coastguard Worker
792*5e7646d2SAndroid Build Coastguard Worker for (lang = lang_cache; lang != NULL; lang = lang->next)
793*5e7646d2SAndroid Build Coastguard Worker if (lang->used == 0)
794*5e7646d2SAndroid Build Coastguard Worker break;
795*5e7646d2SAndroid Build Coastguard Worker
796*5e7646d2SAndroid Build Coastguard Worker if (lang == NULL)
797*5e7646d2SAndroid Build Coastguard Worker {
798*5e7646d2SAndroid Build Coastguard Worker /*
799*5e7646d2SAndroid Build Coastguard Worker * Allocate memory for the language and add it to the cache.
800*5e7646d2SAndroid Build Coastguard Worker */
801*5e7646d2SAndroid Build Coastguard Worker
802*5e7646d2SAndroid Build Coastguard Worker if ((lang = calloc(sizeof(cups_lang_t), 1)) == NULL)
803*5e7646d2SAndroid Build Coastguard Worker {
804*5e7646d2SAndroid Build Coastguard Worker _cupsMutexUnlock(&lang_mutex);
805*5e7646d2SAndroid Build Coastguard Worker
806*5e7646d2SAndroid Build Coastguard Worker return (NULL);
807*5e7646d2SAndroid Build Coastguard Worker }
808*5e7646d2SAndroid Build Coastguard Worker
809*5e7646d2SAndroid Build Coastguard Worker lang->next = lang_cache;
810*5e7646d2SAndroid Build Coastguard Worker lang_cache = lang;
811*5e7646d2SAndroid Build Coastguard Worker }
812*5e7646d2SAndroid Build Coastguard Worker else
813*5e7646d2SAndroid Build Coastguard Worker {
814*5e7646d2SAndroid Build Coastguard Worker /*
815*5e7646d2SAndroid Build Coastguard Worker * Free all old strings as needed...
816*5e7646d2SAndroid Build Coastguard Worker */
817*5e7646d2SAndroid Build Coastguard Worker
818*5e7646d2SAndroid Build Coastguard Worker _cupsMessageFree(lang->strings);
819*5e7646d2SAndroid Build Coastguard Worker lang->strings = NULL;
820*5e7646d2SAndroid Build Coastguard Worker }
821*5e7646d2SAndroid Build Coastguard Worker
822*5e7646d2SAndroid Build Coastguard Worker /*
823*5e7646d2SAndroid Build Coastguard Worker * Then assign the language and encoding fields...
824*5e7646d2SAndroid Build Coastguard Worker */
825*5e7646d2SAndroid Build Coastguard Worker
826*5e7646d2SAndroid Build Coastguard Worker lang->used ++;
827*5e7646d2SAndroid Build Coastguard Worker strlcpy(lang->language, real, sizeof(lang->language));
828*5e7646d2SAndroid Build Coastguard Worker
829*5e7646d2SAndroid Build Coastguard Worker if (encoding != CUPS_AUTO_ENCODING)
830*5e7646d2SAndroid Build Coastguard Worker lang->encoding = encoding;
831*5e7646d2SAndroid Build Coastguard Worker else
832*5e7646d2SAndroid Build Coastguard Worker lang->encoding = CUPS_UTF8;
833*5e7646d2SAndroid Build Coastguard Worker
834*5e7646d2SAndroid Build Coastguard Worker /*
835*5e7646d2SAndroid Build Coastguard Worker * Return...
836*5e7646d2SAndroid Build Coastguard Worker */
837*5e7646d2SAndroid Build Coastguard Worker
838*5e7646d2SAndroid Build Coastguard Worker _cupsMutexUnlock(&lang_mutex);
839*5e7646d2SAndroid Build Coastguard Worker
840*5e7646d2SAndroid Build Coastguard Worker return (lang);
841*5e7646d2SAndroid Build Coastguard Worker }
842*5e7646d2SAndroid Build Coastguard Worker
843*5e7646d2SAndroid Build Coastguard Worker
844*5e7646d2SAndroid Build Coastguard Worker /*
845*5e7646d2SAndroid Build Coastguard Worker * '_cupsLangString()' - Get a message string.
846*5e7646d2SAndroid Build Coastguard Worker *
847*5e7646d2SAndroid Build Coastguard Worker * The returned string is UTF-8 encoded; use cupsUTF8ToCharset() to
848*5e7646d2SAndroid Build Coastguard Worker * convert the string to the language encoding.
849*5e7646d2SAndroid Build Coastguard Worker */
850*5e7646d2SAndroid Build Coastguard Worker
851*5e7646d2SAndroid Build Coastguard Worker const char * /* O - Localized message */
_cupsLangString(cups_lang_t * lang,const char * message)852*5e7646d2SAndroid Build Coastguard Worker _cupsLangString(cups_lang_t *lang, /* I - Language */
853*5e7646d2SAndroid Build Coastguard Worker const char *message) /* I - Message */
854*5e7646d2SAndroid Build Coastguard Worker {
855*5e7646d2SAndroid Build Coastguard Worker const char *s; /* Localized message */
856*5e7646d2SAndroid Build Coastguard Worker
857*5e7646d2SAndroid Build Coastguard Worker
858*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_cupsLangString(lang=%p, message=\"%s\")", (void *)lang, message));
859*5e7646d2SAndroid Build Coastguard Worker
860*5e7646d2SAndroid Build Coastguard Worker /*
861*5e7646d2SAndroid Build Coastguard Worker * Range check input...
862*5e7646d2SAndroid Build Coastguard Worker */
863*5e7646d2SAndroid Build Coastguard Worker
864*5e7646d2SAndroid Build Coastguard Worker if (!lang || !message || !*message)
865*5e7646d2SAndroid Build Coastguard Worker return (message);
866*5e7646d2SAndroid Build Coastguard Worker
867*5e7646d2SAndroid Build Coastguard Worker _cupsMutexLock(&lang_mutex);
868*5e7646d2SAndroid Build Coastguard Worker
869*5e7646d2SAndroid Build Coastguard Worker /*
870*5e7646d2SAndroid Build Coastguard Worker * Load the message catalog if needed...
871*5e7646d2SAndroid Build Coastguard Worker */
872*5e7646d2SAndroid Build Coastguard Worker
873*5e7646d2SAndroid Build Coastguard Worker if (!lang->strings)
874*5e7646d2SAndroid Build Coastguard Worker cups_message_load(lang);
875*5e7646d2SAndroid Build Coastguard Worker
876*5e7646d2SAndroid Build Coastguard Worker s = _cupsMessageLookup(lang->strings, message);
877*5e7646d2SAndroid Build Coastguard Worker
878*5e7646d2SAndroid Build Coastguard Worker _cupsMutexUnlock(&lang_mutex);
879*5e7646d2SAndroid Build Coastguard Worker
880*5e7646d2SAndroid Build Coastguard Worker return (s);
881*5e7646d2SAndroid Build Coastguard Worker }
882*5e7646d2SAndroid Build Coastguard Worker
883*5e7646d2SAndroid Build Coastguard Worker
884*5e7646d2SAndroid Build Coastguard Worker /*
885*5e7646d2SAndroid Build Coastguard Worker * '_cupsMessageFree()' - Free a messages array.
886*5e7646d2SAndroid Build Coastguard Worker */
887*5e7646d2SAndroid Build Coastguard Worker
888*5e7646d2SAndroid Build Coastguard Worker void
_cupsMessageFree(cups_array_t * a)889*5e7646d2SAndroid Build Coastguard Worker _cupsMessageFree(cups_array_t *a) /* I - Message array */
890*5e7646d2SAndroid Build Coastguard Worker {
891*5e7646d2SAndroid Build Coastguard Worker #if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
892*5e7646d2SAndroid Build Coastguard Worker /*
893*5e7646d2SAndroid Build Coastguard Worker * Release the cups.strings dictionary as needed...
894*5e7646d2SAndroid Build Coastguard Worker */
895*5e7646d2SAndroid Build Coastguard Worker
896*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayUserData(a))
897*5e7646d2SAndroid Build Coastguard Worker CFRelease((CFDictionaryRef)cupsArrayUserData(a));
898*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ && CUPS_BUNDLEDIR */
899*5e7646d2SAndroid Build Coastguard Worker
900*5e7646d2SAndroid Build Coastguard Worker /*
901*5e7646d2SAndroid Build Coastguard Worker * Free the array...
902*5e7646d2SAndroid Build Coastguard Worker */
903*5e7646d2SAndroid Build Coastguard Worker
904*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(a);
905*5e7646d2SAndroid Build Coastguard Worker }
906*5e7646d2SAndroid Build Coastguard Worker
907*5e7646d2SAndroid Build Coastguard Worker
908*5e7646d2SAndroid Build Coastguard Worker /*
909*5e7646d2SAndroid Build Coastguard Worker * '_cupsMessageLoad()' - Load a .po or .strings file into a messages array.
910*5e7646d2SAndroid Build Coastguard Worker */
911*5e7646d2SAndroid Build Coastguard Worker
912*5e7646d2SAndroid Build Coastguard Worker cups_array_t * /* O - New message array */
_cupsMessageLoad(const char * filename,int flags)913*5e7646d2SAndroid Build Coastguard Worker _cupsMessageLoad(const char *filename, /* I - Message catalog to load */
914*5e7646d2SAndroid Build Coastguard Worker int flags) /* I - Load flags */
915*5e7646d2SAndroid Build Coastguard Worker {
916*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; /* Message file */
917*5e7646d2SAndroid Build Coastguard Worker cups_array_t *a; /* Message array */
918*5e7646d2SAndroid Build Coastguard Worker _cups_message_t *m; /* Current message */
919*5e7646d2SAndroid Build Coastguard Worker char s[4096], /* String buffer */
920*5e7646d2SAndroid Build Coastguard Worker *ptr, /* Pointer into buffer */
921*5e7646d2SAndroid Build Coastguard Worker *temp; /* New string */
922*5e7646d2SAndroid Build Coastguard Worker size_t length, /* Length of combined strings */
923*5e7646d2SAndroid Build Coastguard Worker ptrlen; /* Length of string */
924*5e7646d2SAndroid Build Coastguard Worker
925*5e7646d2SAndroid Build Coastguard Worker
926*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_cupsMessageLoad(filename=\"%s\")", filename));
927*5e7646d2SAndroid Build Coastguard Worker
928*5e7646d2SAndroid Build Coastguard Worker /*
929*5e7646d2SAndroid Build Coastguard Worker * Create an array to hold the messages...
930*5e7646d2SAndroid Build Coastguard Worker */
931*5e7646d2SAndroid Build Coastguard Worker
932*5e7646d2SAndroid Build Coastguard Worker if ((a = _cupsMessageNew(NULL)) == NULL)
933*5e7646d2SAndroid Build Coastguard Worker {
934*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_cupsMessageLoad: Unable to allocate array!");
935*5e7646d2SAndroid Build Coastguard Worker return (NULL);
936*5e7646d2SAndroid Build Coastguard Worker }
937*5e7646d2SAndroid Build Coastguard Worker
938*5e7646d2SAndroid Build Coastguard Worker /*
939*5e7646d2SAndroid Build Coastguard Worker * Open the message catalog file...
940*5e7646d2SAndroid Build Coastguard Worker */
941*5e7646d2SAndroid Build Coastguard Worker
942*5e7646d2SAndroid Build Coastguard Worker if ((fp = cupsFileOpen(filename, "r")) == NULL)
943*5e7646d2SAndroid Build Coastguard Worker {
944*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_cupsMessageLoad: Unable to open file: %s",
945*5e7646d2SAndroid Build Coastguard Worker strerror(errno)));
946*5e7646d2SAndroid Build Coastguard Worker return (a);
947*5e7646d2SAndroid Build Coastguard Worker }
948*5e7646d2SAndroid Build Coastguard Worker
949*5e7646d2SAndroid Build Coastguard Worker if (flags & _CUPS_MESSAGE_STRINGS)
950*5e7646d2SAndroid Build Coastguard Worker {
951*5e7646d2SAndroid Build Coastguard Worker while (cups_read_strings(fp, flags, a));
952*5e7646d2SAndroid Build Coastguard Worker }
953*5e7646d2SAndroid Build Coastguard Worker else
954*5e7646d2SAndroid Build Coastguard Worker {
955*5e7646d2SAndroid Build Coastguard Worker /*
956*5e7646d2SAndroid Build Coastguard Worker * Read messages from the catalog file until EOF...
957*5e7646d2SAndroid Build Coastguard Worker *
958*5e7646d2SAndroid Build Coastguard Worker * The format is the GNU gettext .po format, which is fairly simple:
959*5e7646d2SAndroid Build Coastguard Worker *
960*5e7646d2SAndroid Build Coastguard Worker * msgid "some text"
961*5e7646d2SAndroid Build Coastguard Worker * msgstr "localized text"
962*5e7646d2SAndroid Build Coastguard Worker *
963*5e7646d2SAndroid Build Coastguard Worker * The ID and localized text can span multiple lines using the form:
964*5e7646d2SAndroid Build Coastguard Worker *
965*5e7646d2SAndroid Build Coastguard Worker * msgid ""
966*5e7646d2SAndroid Build Coastguard Worker * "some long text"
967*5e7646d2SAndroid Build Coastguard Worker * msgstr ""
968*5e7646d2SAndroid Build Coastguard Worker * "localized text spanning "
969*5e7646d2SAndroid Build Coastguard Worker * "multiple lines"
970*5e7646d2SAndroid Build Coastguard Worker */
971*5e7646d2SAndroid Build Coastguard Worker
972*5e7646d2SAndroid Build Coastguard Worker m = NULL;
973*5e7646d2SAndroid Build Coastguard Worker
974*5e7646d2SAndroid Build Coastguard Worker while (cupsFileGets(fp, s, sizeof(s)) != NULL)
975*5e7646d2SAndroid Build Coastguard Worker {
976*5e7646d2SAndroid Build Coastguard Worker /*
977*5e7646d2SAndroid Build Coastguard Worker * Skip blank and comment lines...
978*5e7646d2SAndroid Build Coastguard Worker */
979*5e7646d2SAndroid Build Coastguard Worker
980*5e7646d2SAndroid Build Coastguard Worker if (s[0] == '#' || !s[0])
981*5e7646d2SAndroid Build Coastguard Worker continue;
982*5e7646d2SAndroid Build Coastguard Worker
983*5e7646d2SAndroid Build Coastguard Worker /*
984*5e7646d2SAndroid Build Coastguard Worker * Strip the trailing quote...
985*5e7646d2SAndroid Build Coastguard Worker */
986*5e7646d2SAndroid Build Coastguard Worker
987*5e7646d2SAndroid Build Coastguard Worker if ((ptr = strrchr(s, '\"')) == NULL)
988*5e7646d2SAndroid Build Coastguard Worker continue;
989*5e7646d2SAndroid Build Coastguard Worker
990*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
991*5e7646d2SAndroid Build Coastguard Worker
992*5e7646d2SAndroid Build Coastguard Worker /*
993*5e7646d2SAndroid Build Coastguard Worker * Find start of value...
994*5e7646d2SAndroid Build Coastguard Worker */
995*5e7646d2SAndroid Build Coastguard Worker
996*5e7646d2SAndroid Build Coastguard Worker if ((ptr = strchr(s, '\"')) == NULL)
997*5e7646d2SAndroid Build Coastguard Worker continue;
998*5e7646d2SAndroid Build Coastguard Worker
999*5e7646d2SAndroid Build Coastguard Worker ptr ++;
1000*5e7646d2SAndroid Build Coastguard Worker
1001*5e7646d2SAndroid Build Coastguard Worker /*
1002*5e7646d2SAndroid Build Coastguard Worker * Unquote the text...
1003*5e7646d2SAndroid Build Coastguard Worker */
1004*5e7646d2SAndroid Build Coastguard Worker
1005*5e7646d2SAndroid Build Coastguard Worker if (flags & _CUPS_MESSAGE_UNQUOTE)
1006*5e7646d2SAndroid Build Coastguard Worker cups_unquote(ptr, ptr);
1007*5e7646d2SAndroid Build Coastguard Worker
1008*5e7646d2SAndroid Build Coastguard Worker /*
1009*5e7646d2SAndroid Build Coastguard Worker * Create or add to a message...
1010*5e7646d2SAndroid Build Coastguard Worker */
1011*5e7646d2SAndroid Build Coastguard Worker
1012*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(s, "msgid", 5))
1013*5e7646d2SAndroid Build Coastguard Worker {
1014*5e7646d2SAndroid Build Coastguard Worker /*
1015*5e7646d2SAndroid Build Coastguard Worker * Add previous message as needed...
1016*5e7646d2SAndroid Build Coastguard Worker */
1017*5e7646d2SAndroid Build Coastguard Worker
1018*5e7646d2SAndroid Build Coastguard Worker if (m)
1019*5e7646d2SAndroid Build Coastguard Worker {
1020*5e7646d2SAndroid Build Coastguard Worker if (m->str && (m->str[0] || (flags & _CUPS_MESSAGE_EMPTY)))
1021*5e7646d2SAndroid Build Coastguard Worker {
1022*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(a, m);
1023*5e7646d2SAndroid Build Coastguard Worker }
1024*5e7646d2SAndroid Build Coastguard Worker else
1025*5e7646d2SAndroid Build Coastguard Worker {
1026*5e7646d2SAndroid Build Coastguard Worker /*
1027*5e7646d2SAndroid Build Coastguard Worker * Translation is empty, don't add it... (STR #4033)
1028*5e7646d2SAndroid Build Coastguard Worker */
1029*5e7646d2SAndroid Build Coastguard Worker
1030*5e7646d2SAndroid Build Coastguard Worker free(m->msg);
1031*5e7646d2SAndroid Build Coastguard Worker if (m->str)
1032*5e7646d2SAndroid Build Coastguard Worker free(m->str);
1033*5e7646d2SAndroid Build Coastguard Worker free(m);
1034*5e7646d2SAndroid Build Coastguard Worker }
1035*5e7646d2SAndroid Build Coastguard Worker }
1036*5e7646d2SAndroid Build Coastguard Worker
1037*5e7646d2SAndroid Build Coastguard Worker /*
1038*5e7646d2SAndroid Build Coastguard Worker * Create a new message with the given msgid string...
1039*5e7646d2SAndroid Build Coastguard Worker */
1040*5e7646d2SAndroid Build Coastguard Worker
1041*5e7646d2SAndroid Build Coastguard Worker if ((m = (_cups_message_t *)calloc(1, sizeof(_cups_message_t))) == NULL)
1042*5e7646d2SAndroid Build Coastguard Worker break;
1043*5e7646d2SAndroid Build Coastguard Worker
1044*5e7646d2SAndroid Build Coastguard Worker if ((m->msg = strdup(ptr)) == NULL)
1045*5e7646d2SAndroid Build Coastguard Worker {
1046*5e7646d2SAndroid Build Coastguard Worker free(m);
1047*5e7646d2SAndroid Build Coastguard Worker m = NULL;
1048*5e7646d2SAndroid Build Coastguard Worker break;
1049*5e7646d2SAndroid Build Coastguard Worker }
1050*5e7646d2SAndroid Build Coastguard Worker }
1051*5e7646d2SAndroid Build Coastguard Worker else if (s[0] == '\"' && m)
1052*5e7646d2SAndroid Build Coastguard Worker {
1053*5e7646d2SAndroid Build Coastguard Worker /*
1054*5e7646d2SAndroid Build Coastguard Worker * Append to current string...
1055*5e7646d2SAndroid Build Coastguard Worker */
1056*5e7646d2SAndroid Build Coastguard Worker
1057*5e7646d2SAndroid Build Coastguard Worker length = strlen(m->str ? m->str : m->msg);
1058*5e7646d2SAndroid Build Coastguard Worker ptrlen = strlen(ptr);
1059*5e7646d2SAndroid Build Coastguard Worker
1060*5e7646d2SAndroid Build Coastguard Worker if ((temp = realloc(m->str ? m->str : m->msg, length + ptrlen + 1)) == NULL)
1061*5e7646d2SAndroid Build Coastguard Worker {
1062*5e7646d2SAndroid Build Coastguard Worker if (m->str)
1063*5e7646d2SAndroid Build Coastguard Worker free(m->str);
1064*5e7646d2SAndroid Build Coastguard Worker free(m->msg);
1065*5e7646d2SAndroid Build Coastguard Worker free(m);
1066*5e7646d2SAndroid Build Coastguard Worker m = NULL;
1067*5e7646d2SAndroid Build Coastguard Worker break;
1068*5e7646d2SAndroid Build Coastguard Worker }
1069*5e7646d2SAndroid Build Coastguard Worker
1070*5e7646d2SAndroid Build Coastguard Worker if (m->str)
1071*5e7646d2SAndroid Build Coastguard Worker {
1072*5e7646d2SAndroid Build Coastguard Worker /*
1073*5e7646d2SAndroid Build Coastguard Worker * Copy the new portion to the end of the msgstr string - safe
1074*5e7646d2SAndroid Build Coastguard Worker * to use memcpy because the buffer is allocated to the correct
1075*5e7646d2SAndroid Build Coastguard Worker * size...
1076*5e7646d2SAndroid Build Coastguard Worker */
1077*5e7646d2SAndroid Build Coastguard Worker
1078*5e7646d2SAndroid Build Coastguard Worker m->str = temp;
1079*5e7646d2SAndroid Build Coastguard Worker
1080*5e7646d2SAndroid Build Coastguard Worker memcpy(m->str + length, ptr, ptrlen + 1);
1081*5e7646d2SAndroid Build Coastguard Worker }
1082*5e7646d2SAndroid Build Coastguard Worker else
1083*5e7646d2SAndroid Build Coastguard Worker {
1084*5e7646d2SAndroid Build Coastguard Worker /*
1085*5e7646d2SAndroid Build Coastguard Worker * Copy the new portion to the end of the msgid string - safe
1086*5e7646d2SAndroid Build Coastguard Worker * to use memcpy because the buffer is allocated to the correct
1087*5e7646d2SAndroid Build Coastguard Worker * size...
1088*5e7646d2SAndroid Build Coastguard Worker */
1089*5e7646d2SAndroid Build Coastguard Worker
1090*5e7646d2SAndroid Build Coastguard Worker m->msg = temp;
1091*5e7646d2SAndroid Build Coastguard Worker
1092*5e7646d2SAndroid Build Coastguard Worker memcpy(m->msg + length, ptr, ptrlen + 1);
1093*5e7646d2SAndroid Build Coastguard Worker }
1094*5e7646d2SAndroid Build Coastguard Worker }
1095*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(s, "msgstr", 6) && m)
1096*5e7646d2SAndroid Build Coastguard Worker {
1097*5e7646d2SAndroid Build Coastguard Worker /*
1098*5e7646d2SAndroid Build Coastguard Worker * Set the string...
1099*5e7646d2SAndroid Build Coastguard Worker */
1100*5e7646d2SAndroid Build Coastguard Worker
1101*5e7646d2SAndroid Build Coastguard Worker if ((m->str = strdup(ptr)) == NULL)
1102*5e7646d2SAndroid Build Coastguard Worker {
1103*5e7646d2SAndroid Build Coastguard Worker free(m->msg);
1104*5e7646d2SAndroid Build Coastguard Worker free(m);
1105*5e7646d2SAndroid Build Coastguard Worker m = NULL;
1106*5e7646d2SAndroid Build Coastguard Worker break;
1107*5e7646d2SAndroid Build Coastguard Worker }
1108*5e7646d2SAndroid Build Coastguard Worker }
1109*5e7646d2SAndroid Build Coastguard Worker }
1110*5e7646d2SAndroid Build Coastguard Worker
1111*5e7646d2SAndroid Build Coastguard Worker /*
1112*5e7646d2SAndroid Build Coastguard Worker * Add the last message string to the array as needed...
1113*5e7646d2SAndroid Build Coastguard Worker */
1114*5e7646d2SAndroid Build Coastguard Worker
1115*5e7646d2SAndroid Build Coastguard Worker if (m)
1116*5e7646d2SAndroid Build Coastguard Worker {
1117*5e7646d2SAndroid Build Coastguard Worker if (m->str && (m->str[0] || (flags & _CUPS_MESSAGE_EMPTY)))
1118*5e7646d2SAndroid Build Coastguard Worker {
1119*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(a, m);
1120*5e7646d2SAndroid Build Coastguard Worker }
1121*5e7646d2SAndroid Build Coastguard Worker else
1122*5e7646d2SAndroid Build Coastguard Worker {
1123*5e7646d2SAndroid Build Coastguard Worker /*
1124*5e7646d2SAndroid Build Coastguard Worker * Translation is empty, don't add it... (STR #4033)
1125*5e7646d2SAndroid Build Coastguard Worker */
1126*5e7646d2SAndroid Build Coastguard Worker
1127*5e7646d2SAndroid Build Coastguard Worker free(m->msg);
1128*5e7646d2SAndroid Build Coastguard Worker if (m->str)
1129*5e7646d2SAndroid Build Coastguard Worker free(m->str);
1130*5e7646d2SAndroid Build Coastguard Worker free(m);
1131*5e7646d2SAndroid Build Coastguard Worker }
1132*5e7646d2SAndroid Build Coastguard Worker }
1133*5e7646d2SAndroid Build Coastguard Worker }
1134*5e7646d2SAndroid Build Coastguard Worker
1135*5e7646d2SAndroid Build Coastguard Worker /*
1136*5e7646d2SAndroid Build Coastguard Worker * Close the message catalog file and return the new array...
1137*5e7646d2SAndroid Build Coastguard Worker */
1138*5e7646d2SAndroid Build Coastguard Worker
1139*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
1140*5e7646d2SAndroid Build Coastguard Worker
1141*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_cupsMessageLoad: Returning %d messages...", cupsArrayCount(a)));
1142*5e7646d2SAndroid Build Coastguard Worker
1143*5e7646d2SAndroid Build Coastguard Worker return (a);
1144*5e7646d2SAndroid Build Coastguard Worker }
1145*5e7646d2SAndroid Build Coastguard Worker
1146*5e7646d2SAndroid Build Coastguard Worker
1147*5e7646d2SAndroid Build Coastguard Worker /*
1148*5e7646d2SAndroid Build Coastguard Worker * '_cupsMessageLookup()' - Lookup a message string.
1149*5e7646d2SAndroid Build Coastguard Worker */
1150*5e7646d2SAndroid Build Coastguard Worker
1151*5e7646d2SAndroid Build Coastguard Worker const char * /* O - Localized message */
_cupsMessageLookup(cups_array_t * a,const char * m)1152*5e7646d2SAndroid Build Coastguard Worker _cupsMessageLookup(cups_array_t *a, /* I - Message array */
1153*5e7646d2SAndroid Build Coastguard Worker const char *m) /* I - Message */
1154*5e7646d2SAndroid Build Coastguard Worker {
1155*5e7646d2SAndroid Build Coastguard Worker _cups_message_t key, /* Search key */
1156*5e7646d2SAndroid Build Coastguard Worker *match; /* Matching message */
1157*5e7646d2SAndroid Build Coastguard Worker
1158*5e7646d2SAndroid Build Coastguard Worker
1159*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_cupsMessageLookup(a=%p, m=\"%s\")", (void *)a, m));
1160*5e7646d2SAndroid Build Coastguard Worker
1161*5e7646d2SAndroid Build Coastguard Worker /*
1162*5e7646d2SAndroid Build Coastguard Worker * Lookup the message string; if it doesn't exist in the catalog,
1163*5e7646d2SAndroid Build Coastguard Worker * then return the message that was passed to us...
1164*5e7646d2SAndroid Build Coastguard Worker */
1165*5e7646d2SAndroid Build Coastguard Worker
1166*5e7646d2SAndroid Build Coastguard Worker key.msg = (char *)m;
1167*5e7646d2SAndroid Build Coastguard Worker match = (_cups_message_t *)cupsArrayFind(a, &key);
1168*5e7646d2SAndroid Build Coastguard Worker
1169*5e7646d2SAndroid Build Coastguard Worker #if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
1170*5e7646d2SAndroid Build Coastguard Worker if (!match && cupsArrayUserData(a))
1171*5e7646d2SAndroid Build Coastguard Worker {
1172*5e7646d2SAndroid Build Coastguard Worker /*
1173*5e7646d2SAndroid Build Coastguard Worker * Try looking the string up in the cups.strings dictionary...
1174*5e7646d2SAndroid Build Coastguard Worker */
1175*5e7646d2SAndroid Build Coastguard Worker
1176*5e7646d2SAndroid Build Coastguard Worker CFDictionaryRef dict; /* cups.strings dictionary */
1177*5e7646d2SAndroid Build Coastguard Worker CFStringRef cfm, /* Message as a CF string */
1178*5e7646d2SAndroid Build Coastguard Worker cfstr; /* Localized text as a CF string */
1179*5e7646d2SAndroid Build Coastguard Worker
1180*5e7646d2SAndroid Build Coastguard Worker dict = (CFDictionaryRef)cupsArrayUserData(a);
1181*5e7646d2SAndroid Build Coastguard Worker cfm = CFStringCreateWithCString(kCFAllocatorDefault, m, kCFStringEncodingUTF8);
1182*5e7646d2SAndroid Build Coastguard Worker match = calloc(1, sizeof(_cups_message_t));
1183*5e7646d2SAndroid Build Coastguard Worker match->msg = strdup(m);
1184*5e7646d2SAndroid Build Coastguard Worker cfstr = cfm ? CFDictionaryGetValue(dict, cfm) : NULL;
1185*5e7646d2SAndroid Build Coastguard Worker
1186*5e7646d2SAndroid Build Coastguard Worker if (cfstr)
1187*5e7646d2SAndroid Build Coastguard Worker {
1188*5e7646d2SAndroid Build Coastguard Worker char buffer[1024]; /* Message buffer */
1189*5e7646d2SAndroid Build Coastguard Worker
1190*5e7646d2SAndroid Build Coastguard Worker CFStringGetCString(cfstr, buffer, sizeof(buffer), kCFStringEncodingUTF8);
1191*5e7646d2SAndroid Build Coastguard Worker match->str = strdup(buffer);
1192*5e7646d2SAndroid Build Coastguard Worker
1193*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1_cupsMessageLookup: Found \"%s\" as \"%s\"...", m, buffer));
1194*5e7646d2SAndroid Build Coastguard Worker }
1195*5e7646d2SAndroid Build Coastguard Worker else
1196*5e7646d2SAndroid Build Coastguard Worker {
1197*5e7646d2SAndroid Build Coastguard Worker match->str = strdup(m);
1198*5e7646d2SAndroid Build Coastguard Worker
1199*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1_cupsMessageLookup: Did not find \"%s\"...", m));
1200*5e7646d2SAndroid Build Coastguard Worker }
1201*5e7646d2SAndroid Build Coastguard Worker
1202*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(a, match);
1203*5e7646d2SAndroid Build Coastguard Worker
1204*5e7646d2SAndroid Build Coastguard Worker if (cfm)
1205*5e7646d2SAndroid Build Coastguard Worker CFRelease(cfm);
1206*5e7646d2SAndroid Build Coastguard Worker }
1207*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ && CUPS_BUNDLEDIR */
1208*5e7646d2SAndroid Build Coastguard Worker
1209*5e7646d2SAndroid Build Coastguard Worker if (match && match->str)
1210*5e7646d2SAndroid Build Coastguard Worker return (match->str);
1211*5e7646d2SAndroid Build Coastguard Worker else
1212*5e7646d2SAndroid Build Coastguard Worker return (m);
1213*5e7646d2SAndroid Build Coastguard Worker }
1214*5e7646d2SAndroid Build Coastguard Worker
1215*5e7646d2SAndroid Build Coastguard Worker
1216*5e7646d2SAndroid Build Coastguard Worker /*
1217*5e7646d2SAndroid Build Coastguard Worker * '_cupsMessageNew()' - Make a new message catalog array.
1218*5e7646d2SAndroid Build Coastguard Worker */
1219*5e7646d2SAndroid Build Coastguard Worker
1220*5e7646d2SAndroid Build Coastguard Worker cups_array_t * /* O - Array */
_cupsMessageNew(void * context)1221*5e7646d2SAndroid Build Coastguard Worker _cupsMessageNew(void *context) /* I - User data */
1222*5e7646d2SAndroid Build Coastguard Worker {
1223*5e7646d2SAndroid Build Coastguard Worker return (cupsArrayNew3((cups_array_func_t)cups_message_compare, context,
1224*5e7646d2SAndroid Build Coastguard Worker (cups_ahash_func_t)NULL, 0,
1225*5e7646d2SAndroid Build Coastguard Worker (cups_acopy_func_t)NULL,
1226*5e7646d2SAndroid Build Coastguard Worker (cups_afree_func_t)cups_message_free));
1227*5e7646d2SAndroid Build Coastguard Worker }
1228*5e7646d2SAndroid Build Coastguard Worker
1229*5e7646d2SAndroid Build Coastguard Worker
1230*5e7646d2SAndroid Build Coastguard Worker /*
1231*5e7646d2SAndroid Build Coastguard Worker * '_cupsMessageSave()' - Save a message catalog array.
1232*5e7646d2SAndroid Build Coastguard Worker */
1233*5e7646d2SAndroid Build Coastguard Worker
1234*5e7646d2SAndroid Build Coastguard Worker int /* O - 0 on success, -1 on failure */
_cupsMessageSave(const char * filename,int flags,cups_array_t * a)1235*5e7646d2SAndroid Build Coastguard Worker _cupsMessageSave(const char *filename,/* I - Output filename */
1236*5e7646d2SAndroid Build Coastguard Worker int flags, /* I - Format flags */
1237*5e7646d2SAndroid Build Coastguard Worker cups_array_t *a) /* I - Message array */
1238*5e7646d2SAndroid Build Coastguard Worker {
1239*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; /* Output file */
1240*5e7646d2SAndroid Build Coastguard Worker _cups_message_t *m; /* Current message */
1241*5e7646d2SAndroid Build Coastguard Worker
1242*5e7646d2SAndroid Build Coastguard Worker
1243*5e7646d2SAndroid Build Coastguard Worker /*
1244*5e7646d2SAndroid Build Coastguard Worker * Output message catalog file...
1245*5e7646d2SAndroid Build Coastguard Worker */
1246*5e7646d2SAndroid Build Coastguard Worker
1247*5e7646d2SAndroid Build Coastguard Worker if ((fp = cupsFileOpen(filename, "w")) == NULL)
1248*5e7646d2SAndroid Build Coastguard Worker return (-1);
1249*5e7646d2SAndroid Build Coastguard Worker
1250*5e7646d2SAndroid Build Coastguard Worker /*
1251*5e7646d2SAndroid Build Coastguard Worker * Write each message...
1252*5e7646d2SAndroid Build Coastguard Worker */
1253*5e7646d2SAndroid Build Coastguard Worker
1254*5e7646d2SAndroid Build Coastguard Worker if (flags & _CUPS_MESSAGE_STRINGS)
1255*5e7646d2SAndroid Build Coastguard Worker {
1256*5e7646d2SAndroid Build Coastguard Worker for (m = (_cups_message_t *)cupsArrayFirst(a); m; m = (_cups_message_t *)cupsArrayNext(a))
1257*5e7646d2SAndroid Build Coastguard Worker {
1258*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\"");
1259*5e7646d2SAndroid Build Coastguard Worker cups_message_puts(fp, m->msg);
1260*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\" = \"");
1261*5e7646d2SAndroid Build Coastguard Worker cups_message_puts(fp, m->str);
1262*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\";\n");
1263*5e7646d2SAndroid Build Coastguard Worker }
1264*5e7646d2SAndroid Build Coastguard Worker }
1265*5e7646d2SAndroid Build Coastguard Worker else
1266*5e7646d2SAndroid Build Coastguard Worker {
1267*5e7646d2SAndroid Build Coastguard Worker for (m = (_cups_message_t *)cupsArrayFirst(a); m; m = (_cups_message_t *)cupsArrayNext(a))
1268*5e7646d2SAndroid Build Coastguard Worker {
1269*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "msgid \"");
1270*5e7646d2SAndroid Build Coastguard Worker cups_message_puts(fp, m->msg);
1271*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\"\nmsgstr \"");
1272*5e7646d2SAndroid Build Coastguard Worker cups_message_puts(fp, m->str);
1273*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\"\n");
1274*5e7646d2SAndroid Build Coastguard Worker }
1275*5e7646d2SAndroid Build Coastguard Worker }
1276*5e7646d2SAndroid Build Coastguard Worker
1277*5e7646d2SAndroid Build Coastguard Worker return (cupsFileClose(fp));
1278*5e7646d2SAndroid Build Coastguard Worker }
1279*5e7646d2SAndroid Build Coastguard Worker
1280*5e7646d2SAndroid Build Coastguard Worker
1281*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
1282*5e7646d2SAndroid Build Coastguard Worker /*
1283*5e7646d2SAndroid Build Coastguard Worker * 'appleLangDefault()' - Get the default locale string.
1284*5e7646d2SAndroid Build Coastguard Worker */
1285*5e7646d2SAndroid Build Coastguard Worker
1286*5e7646d2SAndroid Build Coastguard Worker static const char * /* O - Locale string */
appleLangDefault(void)1287*5e7646d2SAndroid Build Coastguard Worker appleLangDefault(void)
1288*5e7646d2SAndroid Build Coastguard Worker {
1289*5e7646d2SAndroid Build Coastguard Worker CFBundleRef bundle; /* Main bundle (if any) */
1290*5e7646d2SAndroid Build Coastguard Worker CFArrayRef bundleList; /* List of localizations in bundle */
1291*5e7646d2SAndroid Build Coastguard Worker CFPropertyListRef localizationList = NULL;
1292*5e7646d2SAndroid Build Coastguard Worker /* List of localization data */
1293*5e7646d2SAndroid Build Coastguard Worker CFStringRef languageName; /* Current name */
1294*5e7646d2SAndroid Build Coastguard Worker char *lang; /* LANG environment variable */
1295*5e7646d2SAndroid Build Coastguard Worker _cups_globals_t *cg = _cupsGlobals();
1296*5e7646d2SAndroid Build Coastguard Worker /* Pointer to library globals */
1297*5e7646d2SAndroid Build Coastguard Worker
1298*5e7646d2SAndroid Build Coastguard Worker
1299*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("2appleLangDefault()");
1300*5e7646d2SAndroid Build Coastguard Worker
1301*5e7646d2SAndroid Build Coastguard Worker /*
1302*5e7646d2SAndroid Build Coastguard Worker * Only do the lookup and translation the first time.
1303*5e7646d2SAndroid Build Coastguard Worker */
1304*5e7646d2SAndroid Build Coastguard Worker
1305*5e7646d2SAndroid Build Coastguard Worker if (!cg->language[0])
1306*5e7646d2SAndroid Build Coastguard Worker {
1307*5e7646d2SAndroid Build Coastguard Worker if (getenv("SOFTWARE") != NULL && (lang = getenv("LANG")) != NULL)
1308*5e7646d2SAndroid Build Coastguard Worker {
1309*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("3appleLangDefault: Using LANG=%s", lang));
1310*5e7646d2SAndroid Build Coastguard Worker strlcpy(cg->language, lang, sizeof(cg->language));
1311*5e7646d2SAndroid Build Coastguard Worker return (cg->language);
1312*5e7646d2SAndroid Build Coastguard Worker }
1313*5e7646d2SAndroid Build Coastguard Worker else if ((bundle = CFBundleGetMainBundle()) != NULL &&
1314*5e7646d2SAndroid Build Coastguard Worker (bundleList = CFBundleCopyBundleLocalizations(bundle)) != NULL)
1315*5e7646d2SAndroid Build Coastguard Worker {
1316*5e7646d2SAndroid Build Coastguard Worker CFURLRef resources = CFBundleCopyResourcesDirectoryURL(bundle);
1317*5e7646d2SAndroid Build Coastguard Worker
1318*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("3appleLangDefault: Getting localizationList from bundle.");
1319*5e7646d2SAndroid Build Coastguard Worker
1320*5e7646d2SAndroid Build Coastguard Worker if (resources)
1321*5e7646d2SAndroid Build Coastguard Worker {
1322*5e7646d2SAndroid Build Coastguard Worker CFStringRef cfpath = CFURLCopyPath(resources);
1323*5e7646d2SAndroid Build Coastguard Worker char path[1024];
1324*5e7646d2SAndroid Build Coastguard Worker
1325*5e7646d2SAndroid Build Coastguard Worker if (cfpath)
1326*5e7646d2SAndroid Build Coastguard Worker {
1327*5e7646d2SAndroid Build Coastguard Worker /*
1328*5e7646d2SAndroid Build Coastguard Worker * See if we have an Info.plist file in the bundle...
1329*5e7646d2SAndroid Build Coastguard Worker */
1330*5e7646d2SAndroid Build Coastguard Worker
1331*5e7646d2SAndroid Build Coastguard Worker CFStringGetCString(cfpath, path, sizeof(path), kCFStringEncodingUTF8);
1332*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("3appleLangDefault: Got a resource URL (\"%s\")", path));
1333*5e7646d2SAndroid Build Coastguard Worker strlcat(path, "Contents/Info.plist", sizeof(path));
1334*5e7646d2SAndroid Build Coastguard Worker
1335*5e7646d2SAndroid Build Coastguard Worker if (!access(path, R_OK))
1336*5e7646d2SAndroid Build Coastguard Worker localizationList = CFBundleCopyPreferredLocalizationsFromArray(bundleList);
1337*5e7646d2SAndroid Build Coastguard Worker else
1338*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("3appleLangDefault: No Info.plist, ignoring resource URL...");
1339*5e7646d2SAndroid Build Coastguard Worker
1340*5e7646d2SAndroid Build Coastguard Worker CFRelease(cfpath);
1341*5e7646d2SAndroid Build Coastguard Worker }
1342*5e7646d2SAndroid Build Coastguard Worker
1343*5e7646d2SAndroid Build Coastguard Worker CFRelease(resources);
1344*5e7646d2SAndroid Build Coastguard Worker }
1345*5e7646d2SAndroid Build Coastguard Worker else
1346*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("3appleLangDefault: No resource URL.");
1347*5e7646d2SAndroid Build Coastguard Worker
1348*5e7646d2SAndroid Build Coastguard Worker CFRelease(bundleList);
1349*5e7646d2SAndroid Build Coastguard Worker }
1350*5e7646d2SAndroid Build Coastguard Worker
1351*5e7646d2SAndroid Build Coastguard Worker if (!localizationList)
1352*5e7646d2SAndroid Build Coastguard Worker {
1353*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("3appleLangDefault: Getting localizationList from preferences.");
1354*5e7646d2SAndroid Build Coastguard Worker
1355*5e7646d2SAndroid Build Coastguard Worker localizationList =
1356*5e7646d2SAndroid Build Coastguard Worker CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
1357*5e7646d2SAndroid Build Coastguard Worker kCFPreferencesCurrentApplication);
1358*5e7646d2SAndroid Build Coastguard Worker }
1359*5e7646d2SAndroid Build Coastguard Worker
1360*5e7646d2SAndroid Build Coastguard Worker if (localizationList)
1361*5e7646d2SAndroid Build Coastguard Worker {
1362*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
1363*5e7646d2SAndroid Build Coastguard Worker if (CFGetTypeID(localizationList) == CFArrayGetTypeID())
1364*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("3appleLangDefault: Got localizationList, %d entries.",
1365*5e7646d2SAndroid Build Coastguard Worker (int)CFArrayGetCount(localizationList)));
1366*5e7646d2SAndroid Build Coastguard Worker else
1367*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("3appleLangDefault: Got localizationList but not an array.");
1368*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
1369*5e7646d2SAndroid Build Coastguard Worker
1370*5e7646d2SAndroid Build Coastguard Worker if (CFGetTypeID(localizationList) == CFArrayGetTypeID() &&
1371*5e7646d2SAndroid Build Coastguard Worker CFArrayGetCount(localizationList) > 0)
1372*5e7646d2SAndroid Build Coastguard Worker {
1373*5e7646d2SAndroid Build Coastguard Worker languageName = CFArrayGetValueAtIndex(localizationList, 0);
1374*5e7646d2SAndroid Build Coastguard Worker
1375*5e7646d2SAndroid Build Coastguard Worker if (languageName &&
1376*5e7646d2SAndroid Build Coastguard Worker CFGetTypeID(languageName) == CFStringGetTypeID())
1377*5e7646d2SAndroid Build Coastguard Worker {
1378*5e7646d2SAndroid Build Coastguard Worker if (_cupsAppleLocale(languageName, cg->language, sizeof(cg->language)))
1379*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("3appleLangDefault: cg->language=\"%s\"",
1380*5e7646d2SAndroid Build Coastguard Worker cg->language));
1381*5e7646d2SAndroid Build Coastguard Worker else
1382*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("3appleLangDefault: Unable to get locale.");
1383*5e7646d2SAndroid Build Coastguard Worker }
1384*5e7646d2SAndroid Build Coastguard Worker }
1385*5e7646d2SAndroid Build Coastguard Worker
1386*5e7646d2SAndroid Build Coastguard Worker CFRelease(localizationList);
1387*5e7646d2SAndroid Build Coastguard Worker }
1388*5e7646d2SAndroid Build Coastguard Worker
1389*5e7646d2SAndroid Build Coastguard Worker /*
1390*5e7646d2SAndroid Build Coastguard Worker * If we didn't find the language, default to en_US...
1391*5e7646d2SAndroid Build Coastguard Worker */
1392*5e7646d2SAndroid Build Coastguard Worker
1393*5e7646d2SAndroid Build Coastguard Worker if (!cg->language[0])
1394*5e7646d2SAndroid Build Coastguard Worker {
1395*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("3appleLangDefault: Defaulting to en_US.");
1396*5e7646d2SAndroid Build Coastguard Worker strlcpy(cg->language, "en_US.UTF-8", sizeof(cg->language));
1397*5e7646d2SAndroid Build Coastguard Worker }
1398*5e7646d2SAndroid Build Coastguard Worker }
1399*5e7646d2SAndroid Build Coastguard Worker else
1400*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("3appleLangDefault: Using previous locale \"%s\".", cg->language));
1401*5e7646d2SAndroid Build Coastguard Worker
1402*5e7646d2SAndroid Build Coastguard Worker /*
1403*5e7646d2SAndroid Build Coastguard Worker * Return the cached locale...
1404*5e7646d2SAndroid Build Coastguard Worker */
1405*5e7646d2SAndroid Build Coastguard Worker
1406*5e7646d2SAndroid Build Coastguard Worker return (cg->language);
1407*5e7646d2SAndroid Build Coastguard Worker }
1408*5e7646d2SAndroid Build Coastguard Worker
1409*5e7646d2SAndroid Build Coastguard Worker
1410*5e7646d2SAndroid Build Coastguard Worker # ifdef CUPS_BUNDLEDIR
1411*5e7646d2SAndroid Build Coastguard Worker /*
1412*5e7646d2SAndroid Build Coastguard Worker * 'appleMessageLoad()' - Load a message catalog from a localizable bundle.
1413*5e7646d2SAndroid Build Coastguard Worker */
1414*5e7646d2SAndroid Build Coastguard Worker
1415*5e7646d2SAndroid Build Coastguard Worker static cups_array_t * /* O - Message catalog */
appleMessageLoad(const char * locale)1416*5e7646d2SAndroid Build Coastguard Worker appleMessageLoad(const char *locale) /* I - Locale ID */
1417*5e7646d2SAndroid Build Coastguard Worker {
1418*5e7646d2SAndroid Build Coastguard Worker char filename[1024], /* Path to cups.strings file */
1419*5e7646d2SAndroid Build Coastguard Worker applelang[256], /* Apple language ID */
1420*5e7646d2SAndroid Build Coastguard Worker baselang[4]; /* Base language */
1421*5e7646d2SAndroid Build Coastguard Worker CFURLRef url; /* URL to cups.strings file */
1422*5e7646d2SAndroid Build Coastguard Worker CFReadStreamRef stream = NULL; /* File stream */
1423*5e7646d2SAndroid Build Coastguard Worker CFPropertyListRef plist = NULL; /* Localization file */
1424*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
1425*5e7646d2SAndroid Build Coastguard Worker const char *cups_strings = getenv("CUPS_STRINGS");
1426*5e7646d2SAndroid Build Coastguard Worker /* Test strings file */
1427*5e7646d2SAndroid Build Coastguard Worker CFErrorRef error = NULL; /* Error when opening file */
1428*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
1429*5e7646d2SAndroid Build Coastguard Worker
1430*5e7646d2SAndroid Build Coastguard Worker
1431*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("appleMessageLoad(locale=\"%s\")", locale));
1432*5e7646d2SAndroid Build Coastguard Worker
1433*5e7646d2SAndroid Build Coastguard Worker /*
1434*5e7646d2SAndroid Build Coastguard Worker * Load the cups.strings file...
1435*5e7646d2SAndroid Build Coastguard Worker */
1436*5e7646d2SAndroid Build Coastguard Worker
1437*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
1438*5e7646d2SAndroid Build Coastguard Worker if (cups_strings)
1439*5e7646d2SAndroid Build Coastguard Worker {
1440*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("1appleMessageLoad: Using debug CUPS_STRINGS file.");
1441*5e7646d2SAndroid Build Coastguard Worker strlcpy(filename, cups_strings, sizeof(filename));
1442*5e7646d2SAndroid Build Coastguard Worker }
1443*5e7646d2SAndroid Build Coastguard Worker else
1444*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
1445*5e7646d2SAndroid Build Coastguard Worker
1446*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename),
1447*5e7646d2SAndroid Build Coastguard Worker CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings",
1448*5e7646d2SAndroid Build Coastguard Worker _cupsAppleLanguage(locale, applelang, sizeof(applelang)));
1449*5e7646d2SAndroid Build Coastguard Worker
1450*5e7646d2SAndroid Build Coastguard Worker if (access(filename, 0))
1451*5e7646d2SAndroid Build Coastguard Worker {
1452*5e7646d2SAndroid Build Coastguard Worker /*
1453*5e7646d2SAndroid Build Coastguard Worker * <rdar://problem/22086642>
1454*5e7646d2SAndroid Build Coastguard Worker *
1455*5e7646d2SAndroid Build Coastguard Worker * Try with original locale string...
1456*5e7646d2SAndroid Build Coastguard Worker */
1457*5e7646d2SAndroid Build Coastguard Worker
1458*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1appleMessageLoad: \"%s\": %s", filename, strerror(errno)));
1459*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings", locale);
1460*5e7646d2SAndroid Build Coastguard Worker }
1461*5e7646d2SAndroid Build Coastguard Worker
1462*5e7646d2SAndroid Build Coastguard Worker if (access(filename, 0))
1463*5e7646d2SAndroid Build Coastguard Worker {
1464*5e7646d2SAndroid Build Coastguard Worker /*
1465*5e7646d2SAndroid Build Coastguard Worker * <rdar://problem/25292403>
1466*5e7646d2SAndroid Build Coastguard Worker *
1467*5e7646d2SAndroid Build Coastguard Worker * Try with just the language code...
1468*5e7646d2SAndroid Build Coastguard Worker */
1469*5e7646d2SAndroid Build Coastguard Worker
1470*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1appleMessageLoad: \"%s\": %s", filename, strerror(errno)));
1471*5e7646d2SAndroid Build Coastguard Worker
1472*5e7646d2SAndroid Build Coastguard Worker strlcpy(baselang, locale, sizeof(baselang));
1473*5e7646d2SAndroid Build Coastguard Worker if (baselang[3] == '-' || baselang[3] == '_')
1474*5e7646d2SAndroid Build Coastguard Worker baselang[3] = '\0';
1475*5e7646d2SAndroid Build Coastguard Worker
1476*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings", baselang);
1477*5e7646d2SAndroid Build Coastguard Worker }
1478*5e7646d2SAndroid Build Coastguard Worker
1479*5e7646d2SAndroid Build Coastguard Worker if (access(filename, 0))
1480*5e7646d2SAndroid Build Coastguard Worker {
1481*5e7646d2SAndroid Build Coastguard Worker /*
1482*5e7646d2SAndroid Build Coastguard Worker * Try alternate lproj directory names...
1483*5e7646d2SAndroid Build Coastguard Worker */
1484*5e7646d2SAndroid Build Coastguard Worker
1485*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1appleMessageLoad: \"%s\": %s", filename, strerror(errno)));
1486*5e7646d2SAndroid Build Coastguard Worker
1487*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(locale, "en", 2))
1488*5e7646d2SAndroid Build Coastguard Worker locale = "English";
1489*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(locale, "nb", 2))
1490*5e7646d2SAndroid Build Coastguard Worker locale = "no";
1491*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(locale, "nl", 2))
1492*5e7646d2SAndroid Build Coastguard Worker locale = "Dutch";
1493*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(locale, "fr", 2))
1494*5e7646d2SAndroid Build Coastguard Worker locale = "French";
1495*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(locale, "de", 2))
1496*5e7646d2SAndroid Build Coastguard Worker locale = "German";
1497*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(locale, "it", 2))
1498*5e7646d2SAndroid Build Coastguard Worker locale = "Italian";
1499*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(locale, "ja", 2))
1500*5e7646d2SAndroid Build Coastguard Worker locale = "Japanese";
1501*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(locale, "es", 2))
1502*5e7646d2SAndroid Build Coastguard Worker locale = "Spanish";
1503*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(locale, "zh_HK") || !strncasecmp(locale, "zh-Hant", 7) || !strncasecmp(locale, "zh_Hant", 7))
1504*5e7646d2SAndroid Build Coastguard Worker {
1505*5e7646d2SAndroid Build Coastguard Worker /*
1506*5e7646d2SAndroid Build Coastguard Worker * <rdar://problem/22130168>
1507*5e7646d2SAndroid Build Coastguard Worker * <rdar://problem/27245567>
1508*5e7646d2SAndroid Build Coastguard Worker *
1509*5e7646d2SAndroid Build Coastguard Worker * Try zh_TW first, then zh... Sigh...
1510*5e7646d2SAndroid Build Coastguard Worker */
1511*5e7646d2SAndroid Build Coastguard Worker
1512*5e7646d2SAndroid Build Coastguard Worker if (!access(CUPS_BUNDLEDIR "/Resources/zh_TW.lproj/cups.strings", 0))
1513*5e7646d2SAndroid Build Coastguard Worker locale = "zh_TW";
1514*5e7646d2SAndroid Build Coastguard Worker else
1515*5e7646d2SAndroid Build Coastguard Worker locale = "zh";
1516*5e7646d2SAndroid Build Coastguard Worker }
1517*5e7646d2SAndroid Build Coastguard Worker else if (strstr(locale, "_") != NULL || strstr(locale, "-") != NULL)
1518*5e7646d2SAndroid Build Coastguard Worker {
1519*5e7646d2SAndroid Build Coastguard Worker /*
1520*5e7646d2SAndroid Build Coastguard Worker * Drop country code, just try language...
1521*5e7646d2SAndroid Build Coastguard Worker */
1522*5e7646d2SAndroid Build Coastguard Worker
1523*5e7646d2SAndroid Build Coastguard Worker strlcpy(baselang, locale, sizeof(baselang));
1524*5e7646d2SAndroid Build Coastguard Worker if (baselang[2] == '-' || baselang[2] == '_')
1525*5e7646d2SAndroid Build Coastguard Worker baselang[2] = '\0';
1526*5e7646d2SAndroid Build Coastguard Worker
1527*5e7646d2SAndroid Build Coastguard Worker locale = baselang;
1528*5e7646d2SAndroid Build Coastguard Worker }
1529*5e7646d2SAndroid Build Coastguard Worker
1530*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename),
1531*5e7646d2SAndroid Build Coastguard Worker CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings", locale);
1532*5e7646d2SAndroid Build Coastguard Worker }
1533*5e7646d2SAndroid Build Coastguard Worker
1534*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1appleMessageLoad: filename=\"%s\"", filename));
1535*5e7646d2SAndroid Build Coastguard Worker
1536*5e7646d2SAndroid Build Coastguard Worker url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
1537*5e7646d2SAndroid Build Coastguard Worker (UInt8 *)filename,
1538*5e7646d2SAndroid Build Coastguard Worker (CFIndex)strlen(filename), false);
1539*5e7646d2SAndroid Build Coastguard Worker if (url)
1540*5e7646d2SAndroid Build Coastguard Worker {
1541*5e7646d2SAndroid Build Coastguard Worker stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
1542*5e7646d2SAndroid Build Coastguard Worker if (stream)
1543*5e7646d2SAndroid Build Coastguard Worker {
1544*5e7646d2SAndroid Build Coastguard Worker /*
1545*5e7646d2SAndroid Build Coastguard Worker * Read the property list containing the localization data.
1546*5e7646d2SAndroid Build Coastguard Worker *
1547*5e7646d2SAndroid Build Coastguard Worker * NOTE: This code currently generates a clang "potential leak"
1548*5e7646d2SAndroid Build Coastguard Worker * warning, but the object is released in _cupsMessageFree().
1549*5e7646d2SAndroid Build Coastguard Worker */
1550*5e7646d2SAndroid Build Coastguard Worker
1551*5e7646d2SAndroid Build Coastguard Worker CFReadStreamOpen(stream);
1552*5e7646d2SAndroid Build Coastguard Worker
1553*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
1554*5e7646d2SAndroid Build Coastguard Worker plist = CFPropertyListCreateWithStream(kCFAllocatorDefault, stream, 0,
1555*5e7646d2SAndroid Build Coastguard Worker kCFPropertyListImmutable, NULL,
1556*5e7646d2SAndroid Build Coastguard Worker &error);
1557*5e7646d2SAndroid Build Coastguard Worker if (error)
1558*5e7646d2SAndroid Build Coastguard Worker {
1559*5e7646d2SAndroid Build Coastguard Worker CFStringRef msg = CFErrorCopyDescription(error);
1560*5e7646d2SAndroid Build Coastguard Worker /* Error message */
1561*5e7646d2SAndroid Build Coastguard Worker
1562*5e7646d2SAndroid Build Coastguard Worker CFStringGetCString(msg, filename, sizeof(filename),
1563*5e7646d2SAndroid Build Coastguard Worker kCFStringEncodingUTF8);
1564*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1appleMessageLoad: %s", filename));
1565*5e7646d2SAndroid Build Coastguard Worker
1566*5e7646d2SAndroid Build Coastguard Worker CFRelease(msg);
1567*5e7646d2SAndroid Build Coastguard Worker CFRelease(error);
1568*5e7646d2SAndroid Build Coastguard Worker }
1569*5e7646d2SAndroid Build Coastguard Worker
1570*5e7646d2SAndroid Build Coastguard Worker #else
1571*5e7646d2SAndroid Build Coastguard Worker plist = CFPropertyListCreateWithStream(kCFAllocatorDefault, stream, 0,
1572*5e7646d2SAndroid Build Coastguard Worker kCFPropertyListImmutable, NULL,
1573*5e7646d2SAndroid Build Coastguard Worker NULL);
1574*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
1575*5e7646d2SAndroid Build Coastguard Worker
1576*5e7646d2SAndroid Build Coastguard Worker if (plist && CFGetTypeID(plist) != CFDictionaryGetTypeID())
1577*5e7646d2SAndroid Build Coastguard Worker {
1578*5e7646d2SAndroid Build Coastguard Worker CFRelease(plist);
1579*5e7646d2SAndroid Build Coastguard Worker plist = NULL;
1580*5e7646d2SAndroid Build Coastguard Worker }
1581*5e7646d2SAndroid Build Coastguard Worker
1582*5e7646d2SAndroid Build Coastguard Worker CFRelease(stream);
1583*5e7646d2SAndroid Build Coastguard Worker }
1584*5e7646d2SAndroid Build Coastguard Worker
1585*5e7646d2SAndroid Build Coastguard Worker CFRelease(url);
1586*5e7646d2SAndroid Build Coastguard Worker }
1587*5e7646d2SAndroid Build Coastguard Worker
1588*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1appleMessageLoad: url=%p, stream=%p, plist=%p", url, stream,
1589*5e7646d2SAndroid Build Coastguard Worker plist));
1590*5e7646d2SAndroid Build Coastguard Worker
1591*5e7646d2SAndroid Build Coastguard Worker /*
1592*5e7646d2SAndroid Build Coastguard Worker * Create and return an empty array to act as a cache for messages, passing the
1593*5e7646d2SAndroid Build Coastguard Worker * plist as the user data.
1594*5e7646d2SAndroid Build Coastguard Worker */
1595*5e7646d2SAndroid Build Coastguard Worker
1596*5e7646d2SAndroid Build Coastguard Worker return (_cupsMessageNew((void *)plist));
1597*5e7646d2SAndroid Build Coastguard Worker }
1598*5e7646d2SAndroid Build Coastguard Worker # endif /* CUPS_BUNDLEDIR */
1599*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
1600*5e7646d2SAndroid Build Coastguard Worker
1601*5e7646d2SAndroid Build Coastguard Worker
1602*5e7646d2SAndroid Build Coastguard Worker /*
1603*5e7646d2SAndroid Build Coastguard Worker * 'cups_cache_lookup()' - Lookup a language in the cache...
1604*5e7646d2SAndroid Build Coastguard Worker */
1605*5e7646d2SAndroid Build Coastguard Worker
1606*5e7646d2SAndroid Build Coastguard Worker static cups_lang_t * /* O - Language data or NULL */
cups_cache_lookup(const char * name,cups_encoding_t encoding)1607*5e7646d2SAndroid Build Coastguard Worker cups_cache_lookup(
1608*5e7646d2SAndroid Build Coastguard Worker const char *name, /* I - Name of locale */
1609*5e7646d2SAndroid Build Coastguard Worker cups_encoding_t encoding) /* I - Encoding of locale */
1610*5e7646d2SAndroid Build Coastguard Worker {
1611*5e7646d2SAndroid Build Coastguard Worker cups_lang_t *lang; /* Current language */
1612*5e7646d2SAndroid Build Coastguard Worker
1613*5e7646d2SAndroid Build Coastguard Worker
1614*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("7cups_cache_lookup(name=\"%s\", encoding=%d(%s))", name,
1615*5e7646d2SAndroid Build Coastguard Worker encoding, encoding == CUPS_AUTO_ENCODING ? "auto" :
1616*5e7646d2SAndroid Build Coastguard Worker lang_encodings[encoding]));
1617*5e7646d2SAndroid Build Coastguard Worker
1618*5e7646d2SAndroid Build Coastguard Worker /*
1619*5e7646d2SAndroid Build Coastguard Worker * Loop through the cache and return a match if found...
1620*5e7646d2SAndroid Build Coastguard Worker */
1621*5e7646d2SAndroid Build Coastguard Worker
1622*5e7646d2SAndroid Build Coastguard Worker for (lang = lang_cache; lang != NULL; lang = lang->next)
1623*5e7646d2SAndroid Build Coastguard Worker {
1624*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("9cups_cache_lookup: lang=%p, language=\"%s\", "
1625*5e7646d2SAndroid Build Coastguard Worker "encoding=%d(%s)", (void *)lang, lang->language, lang->encoding,
1626*5e7646d2SAndroid Build Coastguard Worker lang_encodings[lang->encoding]));
1627*5e7646d2SAndroid Build Coastguard Worker
1628*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(lang->language, name) &&
1629*5e7646d2SAndroid Build Coastguard Worker (encoding == CUPS_AUTO_ENCODING || encoding == lang->encoding))
1630*5e7646d2SAndroid Build Coastguard Worker {
1631*5e7646d2SAndroid Build Coastguard Worker lang->used ++;
1632*5e7646d2SAndroid Build Coastguard Worker
1633*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("8cups_cache_lookup: returning match!");
1634*5e7646d2SAndroid Build Coastguard Worker
1635*5e7646d2SAndroid Build Coastguard Worker return (lang);
1636*5e7646d2SAndroid Build Coastguard Worker }
1637*5e7646d2SAndroid Build Coastguard Worker }
1638*5e7646d2SAndroid Build Coastguard Worker
1639*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("8cups_cache_lookup: returning NULL!");
1640*5e7646d2SAndroid Build Coastguard Worker
1641*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1642*5e7646d2SAndroid Build Coastguard Worker }
1643*5e7646d2SAndroid Build Coastguard Worker
1644*5e7646d2SAndroid Build Coastguard Worker
1645*5e7646d2SAndroid Build Coastguard Worker /*
1646*5e7646d2SAndroid Build Coastguard Worker * 'cups_message_compare()' - Compare two messages.
1647*5e7646d2SAndroid Build Coastguard Worker */
1648*5e7646d2SAndroid Build Coastguard Worker
1649*5e7646d2SAndroid Build Coastguard Worker static int /* O - Result of comparison */
cups_message_compare(_cups_message_t * m1,_cups_message_t * m2)1650*5e7646d2SAndroid Build Coastguard Worker cups_message_compare(
1651*5e7646d2SAndroid Build Coastguard Worker _cups_message_t *m1, /* I - First message */
1652*5e7646d2SAndroid Build Coastguard Worker _cups_message_t *m2) /* I - Second message */
1653*5e7646d2SAndroid Build Coastguard Worker {
1654*5e7646d2SAndroid Build Coastguard Worker return (strcmp(m1->msg, m2->msg));
1655*5e7646d2SAndroid Build Coastguard Worker }
1656*5e7646d2SAndroid Build Coastguard Worker
1657*5e7646d2SAndroid Build Coastguard Worker
1658*5e7646d2SAndroid Build Coastguard Worker /*
1659*5e7646d2SAndroid Build Coastguard Worker * 'cups_message_free()' - Free a message.
1660*5e7646d2SAndroid Build Coastguard Worker */
1661*5e7646d2SAndroid Build Coastguard Worker
1662*5e7646d2SAndroid Build Coastguard Worker static void
cups_message_free(_cups_message_t * m)1663*5e7646d2SAndroid Build Coastguard Worker cups_message_free(_cups_message_t *m) /* I - Message */
1664*5e7646d2SAndroid Build Coastguard Worker {
1665*5e7646d2SAndroid Build Coastguard Worker if (m->msg)
1666*5e7646d2SAndroid Build Coastguard Worker free(m->msg);
1667*5e7646d2SAndroid Build Coastguard Worker
1668*5e7646d2SAndroid Build Coastguard Worker if (m->str)
1669*5e7646d2SAndroid Build Coastguard Worker free(m->str);
1670*5e7646d2SAndroid Build Coastguard Worker
1671*5e7646d2SAndroid Build Coastguard Worker free(m);
1672*5e7646d2SAndroid Build Coastguard Worker }
1673*5e7646d2SAndroid Build Coastguard Worker
1674*5e7646d2SAndroid Build Coastguard Worker
1675*5e7646d2SAndroid Build Coastguard Worker /*
1676*5e7646d2SAndroid Build Coastguard Worker * 'cups_message_load()' - Load the message catalog for a language.
1677*5e7646d2SAndroid Build Coastguard Worker */
1678*5e7646d2SAndroid Build Coastguard Worker
1679*5e7646d2SAndroid Build Coastguard Worker static void
cups_message_load(cups_lang_t * lang)1680*5e7646d2SAndroid Build Coastguard Worker cups_message_load(cups_lang_t *lang) /* I - Language */
1681*5e7646d2SAndroid Build Coastguard Worker {
1682*5e7646d2SAndroid Build Coastguard Worker #if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
1683*5e7646d2SAndroid Build Coastguard Worker lang->strings = appleMessageLoad(lang->language);
1684*5e7646d2SAndroid Build Coastguard Worker
1685*5e7646d2SAndroid Build Coastguard Worker #else
1686*5e7646d2SAndroid Build Coastguard Worker char filename[1024]; /* Filename for language locale file */
1687*5e7646d2SAndroid Build Coastguard Worker _cups_globals_t *cg = _cupsGlobals();
1688*5e7646d2SAndroid Build Coastguard Worker /* Pointer to library globals */
1689*5e7646d2SAndroid Build Coastguard Worker
1690*5e7646d2SAndroid Build Coastguard Worker
1691*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/%s/cups_%s.po", cg->localedir,
1692*5e7646d2SAndroid Build Coastguard Worker lang->language, lang->language);
1693*5e7646d2SAndroid Build Coastguard Worker
1694*5e7646d2SAndroid Build Coastguard Worker if (strchr(lang->language, '_') && access(filename, 0))
1695*5e7646d2SAndroid Build Coastguard Worker {
1696*5e7646d2SAndroid Build Coastguard Worker /*
1697*5e7646d2SAndroid Build Coastguard Worker * Country localization not available, look for generic localization...
1698*5e7646d2SAndroid Build Coastguard Worker */
1699*5e7646d2SAndroid Build Coastguard Worker
1700*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/%.2s/cups_%.2s.po", cg->localedir,
1701*5e7646d2SAndroid Build Coastguard Worker lang->language, lang->language);
1702*5e7646d2SAndroid Build Coastguard Worker
1703*5e7646d2SAndroid Build Coastguard Worker if (access(filename, 0))
1704*5e7646d2SAndroid Build Coastguard Worker {
1705*5e7646d2SAndroid Build Coastguard Worker /*
1706*5e7646d2SAndroid Build Coastguard Worker * No generic localization, so use POSIX...
1707*5e7646d2SAndroid Build Coastguard Worker */
1708*5e7646d2SAndroid Build Coastguard Worker
1709*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4cups_message_load: access(\"%s\", 0): %s", filename,
1710*5e7646d2SAndroid Build Coastguard Worker strerror(errno)));
1711*5e7646d2SAndroid Build Coastguard Worker
1712*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/C/cups_C.po", cg->localedir);
1713*5e7646d2SAndroid Build Coastguard Worker }
1714*5e7646d2SAndroid Build Coastguard Worker }
1715*5e7646d2SAndroid Build Coastguard Worker
1716*5e7646d2SAndroid Build Coastguard Worker /*
1717*5e7646d2SAndroid Build Coastguard Worker * Read the strings from the file...
1718*5e7646d2SAndroid Build Coastguard Worker */
1719*5e7646d2SAndroid Build Coastguard Worker
1720*5e7646d2SAndroid Build Coastguard Worker lang->strings = _cupsMessageLoad(filename, _CUPS_MESSAGE_UNQUOTE);
1721*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ && CUPS_BUNDLEDIR */
1722*5e7646d2SAndroid Build Coastguard Worker }
1723*5e7646d2SAndroid Build Coastguard Worker
1724*5e7646d2SAndroid Build Coastguard Worker
1725*5e7646d2SAndroid Build Coastguard Worker /*
1726*5e7646d2SAndroid Build Coastguard Worker * 'cups_message_puts()' - Write a message string with quoting.
1727*5e7646d2SAndroid Build Coastguard Worker */
1728*5e7646d2SAndroid Build Coastguard Worker
1729*5e7646d2SAndroid Build Coastguard Worker static void
cups_message_puts(cups_file_t * fp,const char * s)1730*5e7646d2SAndroid Build Coastguard Worker cups_message_puts(cups_file_t *fp, /* I - File to write to */
1731*5e7646d2SAndroid Build Coastguard Worker const char *s) /* I - String to write */
1732*5e7646d2SAndroid Build Coastguard Worker {
1733*5e7646d2SAndroid Build Coastguard Worker const char *start, /* Start of substring */
1734*5e7646d2SAndroid Build Coastguard Worker *ptr; /* Pointer into string */
1735*5e7646d2SAndroid Build Coastguard Worker
1736*5e7646d2SAndroid Build Coastguard Worker
1737*5e7646d2SAndroid Build Coastguard Worker for (start = s, ptr = s; *ptr; ptr ++)
1738*5e7646d2SAndroid Build Coastguard Worker {
1739*5e7646d2SAndroid Build Coastguard Worker if (strchr("\\\"\n\t", *ptr))
1740*5e7646d2SAndroid Build Coastguard Worker {
1741*5e7646d2SAndroid Build Coastguard Worker if (ptr > start)
1742*5e7646d2SAndroid Build Coastguard Worker {
1743*5e7646d2SAndroid Build Coastguard Worker cupsFileWrite(fp, start, (size_t)(ptr - start));
1744*5e7646d2SAndroid Build Coastguard Worker start = ptr + 1;
1745*5e7646d2SAndroid Build Coastguard Worker }
1746*5e7646d2SAndroid Build Coastguard Worker
1747*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '\\')
1748*5e7646d2SAndroid Build Coastguard Worker cupsFileWrite(fp, "\\\\", 2);
1749*5e7646d2SAndroid Build Coastguard Worker else if (*ptr == '\"')
1750*5e7646d2SAndroid Build Coastguard Worker cupsFileWrite(fp, "\\\"", 2);
1751*5e7646d2SAndroid Build Coastguard Worker else if (*ptr == '\n')
1752*5e7646d2SAndroid Build Coastguard Worker cupsFileWrite(fp, "\\n", 2);
1753*5e7646d2SAndroid Build Coastguard Worker else /* if (*ptr == '\t') */
1754*5e7646d2SAndroid Build Coastguard Worker cupsFileWrite(fp, "\\t", 2);
1755*5e7646d2SAndroid Build Coastguard Worker }
1756*5e7646d2SAndroid Build Coastguard Worker }
1757*5e7646d2SAndroid Build Coastguard Worker
1758*5e7646d2SAndroid Build Coastguard Worker if (ptr > start)
1759*5e7646d2SAndroid Build Coastguard Worker cupsFileWrite(fp, start, (size_t)(ptr - start));
1760*5e7646d2SAndroid Build Coastguard Worker }
1761*5e7646d2SAndroid Build Coastguard Worker
1762*5e7646d2SAndroid Build Coastguard Worker
1763*5e7646d2SAndroid Build Coastguard Worker /*
1764*5e7646d2SAndroid Build Coastguard Worker * 'cups_read_strings()' - Read a pair of strings from a .strings file.
1765*5e7646d2SAndroid Build Coastguard Worker */
1766*5e7646d2SAndroid Build Coastguard Worker
1767*5e7646d2SAndroid Build Coastguard Worker static int /* O - 1 on success, 0 on failure */
cups_read_strings(cups_file_t * fp,int flags,cups_array_t * a)1768*5e7646d2SAndroid Build Coastguard Worker cups_read_strings(cups_file_t *fp, /* I - .strings file */
1769*5e7646d2SAndroid Build Coastguard Worker int flags, /* I - CUPS_MESSAGE_xxx flags */
1770*5e7646d2SAndroid Build Coastguard Worker cups_array_t *a) /* I - Message catalog array */
1771*5e7646d2SAndroid Build Coastguard Worker {
1772*5e7646d2SAndroid Build Coastguard Worker char buffer[8192], /* Line buffer */
1773*5e7646d2SAndroid Build Coastguard Worker *bufptr, /* Pointer into buffer */
1774*5e7646d2SAndroid Build Coastguard Worker *msg, /* Pointer to start of message */
1775*5e7646d2SAndroid Build Coastguard Worker *str; /* Pointer to start of translation string */
1776*5e7646d2SAndroid Build Coastguard Worker _cups_message_t *m; /* New message */
1777*5e7646d2SAndroid Build Coastguard Worker
1778*5e7646d2SAndroid Build Coastguard Worker
1779*5e7646d2SAndroid Build Coastguard Worker while (cupsFileGets(fp, buffer, sizeof(buffer)))
1780*5e7646d2SAndroid Build Coastguard Worker {
1781*5e7646d2SAndroid Build Coastguard Worker /*
1782*5e7646d2SAndroid Build Coastguard Worker * Skip any line (comments, blanks, etc.) that isn't:
1783*5e7646d2SAndroid Build Coastguard Worker *
1784*5e7646d2SAndroid Build Coastguard Worker * "message" = "translation";
1785*5e7646d2SAndroid Build Coastguard Worker */
1786*5e7646d2SAndroid Build Coastguard Worker
1787*5e7646d2SAndroid Build Coastguard Worker for (bufptr = buffer; *bufptr && isspace(*bufptr & 255); bufptr ++);
1788*5e7646d2SAndroid Build Coastguard Worker
1789*5e7646d2SAndroid Build Coastguard Worker if (*bufptr != '\"')
1790*5e7646d2SAndroid Build Coastguard Worker continue;
1791*5e7646d2SAndroid Build Coastguard Worker
1792*5e7646d2SAndroid Build Coastguard Worker /*
1793*5e7646d2SAndroid Build Coastguard Worker * Find the end of the message...
1794*5e7646d2SAndroid Build Coastguard Worker */
1795*5e7646d2SAndroid Build Coastguard Worker
1796*5e7646d2SAndroid Build Coastguard Worker bufptr ++;
1797*5e7646d2SAndroid Build Coastguard Worker for (msg = bufptr; *bufptr && *bufptr != '\"'; bufptr ++)
1798*5e7646d2SAndroid Build Coastguard Worker if (*bufptr == '\\' && bufptr[1])
1799*5e7646d2SAndroid Build Coastguard Worker bufptr ++;
1800*5e7646d2SAndroid Build Coastguard Worker
1801*5e7646d2SAndroid Build Coastguard Worker if (!*bufptr)
1802*5e7646d2SAndroid Build Coastguard Worker continue;
1803*5e7646d2SAndroid Build Coastguard Worker
1804*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = '\0';
1805*5e7646d2SAndroid Build Coastguard Worker
1806*5e7646d2SAndroid Build Coastguard Worker if (flags & _CUPS_MESSAGE_UNQUOTE)
1807*5e7646d2SAndroid Build Coastguard Worker cups_unquote(msg, msg);
1808*5e7646d2SAndroid Build Coastguard Worker
1809*5e7646d2SAndroid Build Coastguard Worker /*
1810*5e7646d2SAndroid Build Coastguard Worker * Find the start of the translation...
1811*5e7646d2SAndroid Build Coastguard Worker */
1812*5e7646d2SAndroid Build Coastguard Worker
1813*5e7646d2SAndroid Build Coastguard Worker while (*bufptr && isspace(*bufptr & 255))
1814*5e7646d2SAndroid Build Coastguard Worker bufptr ++;
1815*5e7646d2SAndroid Build Coastguard Worker
1816*5e7646d2SAndroid Build Coastguard Worker if (*bufptr != '=')
1817*5e7646d2SAndroid Build Coastguard Worker continue;
1818*5e7646d2SAndroid Build Coastguard Worker
1819*5e7646d2SAndroid Build Coastguard Worker bufptr ++;
1820*5e7646d2SAndroid Build Coastguard Worker while (*bufptr && isspace(*bufptr & 255))
1821*5e7646d2SAndroid Build Coastguard Worker bufptr ++;
1822*5e7646d2SAndroid Build Coastguard Worker
1823*5e7646d2SAndroid Build Coastguard Worker if (*bufptr != '\"')
1824*5e7646d2SAndroid Build Coastguard Worker continue;
1825*5e7646d2SAndroid Build Coastguard Worker
1826*5e7646d2SAndroid Build Coastguard Worker /*
1827*5e7646d2SAndroid Build Coastguard Worker * Find the end of the translation...
1828*5e7646d2SAndroid Build Coastguard Worker */
1829*5e7646d2SAndroid Build Coastguard Worker
1830*5e7646d2SAndroid Build Coastguard Worker bufptr ++;
1831*5e7646d2SAndroid Build Coastguard Worker for (str = bufptr; *bufptr && *bufptr != '\"'; bufptr ++)
1832*5e7646d2SAndroid Build Coastguard Worker if (*bufptr == '\\' && bufptr[1])
1833*5e7646d2SAndroid Build Coastguard Worker bufptr ++;
1834*5e7646d2SAndroid Build Coastguard Worker
1835*5e7646d2SAndroid Build Coastguard Worker if (!*bufptr)
1836*5e7646d2SAndroid Build Coastguard Worker continue;
1837*5e7646d2SAndroid Build Coastguard Worker
1838*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = '\0';
1839*5e7646d2SAndroid Build Coastguard Worker
1840*5e7646d2SAndroid Build Coastguard Worker if (flags & _CUPS_MESSAGE_UNQUOTE)
1841*5e7646d2SAndroid Build Coastguard Worker cups_unquote(str, str);
1842*5e7646d2SAndroid Build Coastguard Worker
1843*5e7646d2SAndroid Build Coastguard Worker /*
1844*5e7646d2SAndroid Build Coastguard Worker * If we get this far we have a valid pair of strings, add them...
1845*5e7646d2SAndroid Build Coastguard Worker */
1846*5e7646d2SAndroid Build Coastguard Worker
1847*5e7646d2SAndroid Build Coastguard Worker if ((m = malloc(sizeof(_cups_message_t))) == NULL)
1848*5e7646d2SAndroid Build Coastguard Worker break;
1849*5e7646d2SAndroid Build Coastguard Worker
1850*5e7646d2SAndroid Build Coastguard Worker m->msg = strdup(msg);
1851*5e7646d2SAndroid Build Coastguard Worker m->str = strdup(str);
1852*5e7646d2SAndroid Build Coastguard Worker
1853*5e7646d2SAndroid Build Coastguard Worker if (m->msg && m->str)
1854*5e7646d2SAndroid Build Coastguard Worker {
1855*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(a, m);
1856*5e7646d2SAndroid Build Coastguard Worker }
1857*5e7646d2SAndroid Build Coastguard Worker else
1858*5e7646d2SAndroid Build Coastguard Worker {
1859*5e7646d2SAndroid Build Coastguard Worker if (m->msg)
1860*5e7646d2SAndroid Build Coastguard Worker free(m->msg);
1861*5e7646d2SAndroid Build Coastguard Worker
1862*5e7646d2SAndroid Build Coastguard Worker if (m->str)
1863*5e7646d2SAndroid Build Coastguard Worker free(m->str);
1864*5e7646d2SAndroid Build Coastguard Worker
1865*5e7646d2SAndroid Build Coastguard Worker free(m);
1866*5e7646d2SAndroid Build Coastguard Worker break;
1867*5e7646d2SAndroid Build Coastguard Worker }
1868*5e7646d2SAndroid Build Coastguard Worker
1869*5e7646d2SAndroid Build Coastguard Worker return (1);
1870*5e7646d2SAndroid Build Coastguard Worker }
1871*5e7646d2SAndroid Build Coastguard Worker
1872*5e7646d2SAndroid Build Coastguard Worker /*
1873*5e7646d2SAndroid Build Coastguard Worker * No more strings...
1874*5e7646d2SAndroid Build Coastguard Worker */
1875*5e7646d2SAndroid Build Coastguard Worker
1876*5e7646d2SAndroid Build Coastguard Worker return (0);
1877*5e7646d2SAndroid Build Coastguard Worker }
1878*5e7646d2SAndroid Build Coastguard Worker
1879*5e7646d2SAndroid Build Coastguard Worker
1880*5e7646d2SAndroid Build Coastguard Worker /*
1881*5e7646d2SAndroid Build Coastguard Worker * 'cups_unquote()' - Unquote characters in strings...
1882*5e7646d2SAndroid Build Coastguard Worker */
1883*5e7646d2SAndroid Build Coastguard Worker
1884*5e7646d2SAndroid Build Coastguard Worker static void
cups_unquote(char * d,const char * s)1885*5e7646d2SAndroid Build Coastguard Worker cups_unquote(char *d, /* O - Unquoted string */
1886*5e7646d2SAndroid Build Coastguard Worker const char *s) /* I - Original string */
1887*5e7646d2SAndroid Build Coastguard Worker {
1888*5e7646d2SAndroid Build Coastguard Worker while (*s)
1889*5e7646d2SAndroid Build Coastguard Worker {
1890*5e7646d2SAndroid Build Coastguard Worker if (*s == '\\')
1891*5e7646d2SAndroid Build Coastguard Worker {
1892*5e7646d2SAndroid Build Coastguard Worker s ++;
1893*5e7646d2SAndroid Build Coastguard Worker if (isdigit(*s))
1894*5e7646d2SAndroid Build Coastguard Worker {
1895*5e7646d2SAndroid Build Coastguard Worker *d = 0;
1896*5e7646d2SAndroid Build Coastguard Worker
1897*5e7646d2SAndroid Build Coastguard Worker while (isdigit(*s))
1898*5e7646d2SAndroid Build Coastguard Worker {
1899*5e7646d2SAndroid Build Coastguard Worker *d = *d * 8 + *s - '0';
1900*5e7646d2SAndroid Build Coastguard Worker s ++;
1901*5e7646d2SAndroid Build Coastguard Worker }
1902*5e7646d2SAndroid Build Coastguard Worker
1903*5e7646d2SAndroid Build Coastguard Worker d ++;
1904*5e7646d2SAndroid Build Coastguard Worker }
1905*5e7646d2SAndroid Build Coastguard Worker else
1906*5e7646d2SAndroid Build Coastguard Worker {
1907*5e7646d2SAndroid Build Coastguard Worker if (*s == 'n')
1908*5e7646d2SAndroid Build Coastguard Worker *d ++ = '\n';
1909*5e7646d2SAndroid Build Coastguard Worker else if (*s == 'r')
1910*5e7646d2SAndroid Build Coastguard Worker *d ++ = '\r';
1911*5e7646d2SAndroid Build Coastguard Worker else if (*s == 't')
1912*5e7646d2SAndroid Build Coastguard Worker *d ++ = '\t';
1913*5e7646d2SAndroid Build Coastguard Worker else
1914*5e7646d2SAndroid Build Coastguard Worker *d++ = *s;
1915*5e7646d2SAndroid Build Coastguard Worker
1916*5e7646d2SAndroid Build Coastguard Worker s ++;
1917*5e7646d2SAndroid Build Coastguard Worker }
1918*5e7646d2SAndroid Build Coastguard Worker }
1919*5e7646d2SAndroid Build Coastguard Worker else
1920*5e7646d2SAndroid Build Coastguard Worker *d++ = *s++;
1921*5e7646d2SAndroid Build Coastguard Worker }
1922*5e7646d2SAndroid Build Coastguard Worker
1923*5e7646d2SAndroid Build Coastguard Worker *d = '\0';
1924*5e7646d2SAndroid Build Coastguard Worker }
1925