1*5e7646d2SAndroid Build Coastguard Worker //
2*5e7646d2SAndroid Build Coastguard Worker // Shared message catalog class for the CUPS PPD Compiler.
3*5e7646d2SAndroid Build Coastguard Worker //
4*5e7646d2SAndroid Build Coastguard Worker // Copyright 2007-2017 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker // Copyright 2002-2006 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 "ppdc-private.h"
15*5e7646d2SAndroid Build Coastguard Worker
16*5e7646d2SAndroid Build Coastguard Worker
17*5e7646d2SAndroid Build Coastguard Worker //
18*5e7646d2SAndroid Build Coastguard Worker // Character encodings...
19*5e7646d2SAndroid Build Coastguard Worker //
20*5e7646d2SAndroid Build Coastguard Worker
21*5e7646d2SAndroid Build Coastguard Worker typedef enum
22*5e7646d2SAndroid Build Coastguard Worker {
23*5e7646d2SAndroid Build Coastguard Worker PPDC_CS_AUTO,
24*5e7646d2SAndroid Build Coastguard Worker PPDC_CS_UTF8,
25*5e7646d2SAndroid Build Coastguard Worker PPDC_CS_UTF16BE,
26*5e7646d2SAndroid Build Coastguard Worker PPDC_CS_UTF16LE
27*5e7646d2SAndroid Build Coastguard Worker } ppdc_cs_t;
28*5e7646d2SAndroid Build Coastguard Worker
29*5e7646d2SAndroid Build Coastguard Worker
30*5e7646d2SAndroid Build Coastguard Worker //
31*5e7646d2SAndroid Build Coastguard Worker // Local functions...
32*5e7646d2SAndroid Build Coastguard Worker //
33*5e7646d2SAndroid Build Coastguard Worker
34*5e7646d2SAndroid Build Coastguard Worker #if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
35*5e7646d2SAndroid Build Coastguard Worker static void apple_add_message(CFStringRef key, CFStringRef val, ppdcCatalog *c);
36*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ && CUPS_BUNDLEDIR */
37*5e7646d2SAndroid Build Coastguard Worker static int get_utf8(char *&ptr);
38*5e7646d2SAndroid Build Coastguard Worker static int get_utf16(cups_file_t *fp, ppdc_cs_t &cs);
39*5e7646d2SAndroid Build Coastguard Worker static int put_utf8(int ch, char *&ptr, char *end);
40*5e7646d2SAndroid Build Coastguard Worker static int put_utf16(cups_file_t *fp, int ch);
41*5e7646d2SAndroid Build Coastguard Worker
42*5e7646d2SAndroid Build Coastguard Worker
43*5e7646d2SAndroid Build Coastguard Worker //
44*5e7646d2SAndroid Build Coastguard Worker // 'ppdcCatalog::ppdcCatalog()' - Create a shared message catalog.
45*5e7646d2SAndroid Build Coastguard Worker //
46*5e7646d2SAndroid Build Coastguard Worker
ppdcCatalog(const char * l,const char * f)47*5e7646d2SAndroid Build Coastguard Worker ppdcCatalog::ppdcCatalog(const char *l, // I - Locale
48*5e7646d2SAndroid Build Coastguard Worker const char *f) // I - Message catalog file
49*5e7646d2SAndroid Build Coastguard Worker : ppdcShared()
50*5e7646d2SAndroid Build Coastguard Worker {
51*5e7646d2SAndroid Build Coastguard Worker PPDC_NEW;
52*5e7646d2SAndroid Build Coastguard Worker
53*5e7646d2SAndroid Build Coastguard Worker locale = new ppdcString(l);
54*5e7646d2SAndroid Build Coastguard Worker filename = new ppdcString(f);
55*5e7646d2SAndroid Build Coastguard Worker messages = new ppdcArray();
56*5e7646d2SAndroid Build Coastguard Worker
57*5e7646d2SAndroid Build Coastguard Worker if (l && strcmp(l, "en"))
58*5e7646d2SAndroid Build Coastguard Worker {
59*5e7646d2SAndroid Build Coastguard Worker // Try loading the base messages for this locale...
60*5e7646d2SAndroid Build Coastguard Worker char pofile[1024]; // Message catalog file
61*5e7646d2SAndroid Build Coastguard Worker
62*5e7646d2SAndroid Build Coastguard Worker
63*5e7646d2SAndroid Build Coastguard Worker #if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
64*5e7646d2SAndroid Build Coastguard Worker char applelang[256]; // Apple language ID
65*5e7646d2SAndroid Build Coastguard Worker CFURLRef url; // URL to cups.strings file
66*5e7646d2SAndroid Build Coastguard Worker CFReadStreamRef stream = NULL; // File stream
67*5e7646d2SAndroid Build Coastguard Worker CFPropertyListRef plist = NULL; // Localization file
68*5e7646d2SAndroid Build Coastguard Worker
69*5e7646d2SAndroid Build Coastguard Worker snprintf(pofile, sizeof(pofile), CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings", _cupsAppleLanguage(l, applelang, sizeof(applelang)));
70*5e7646d2SAndroid Build Coastguard Worker if (access(pofile, 0))
71*5e7646d2SAndroid Build Coastguard Worker {
72*5e7646d2SAndroid Build Coastguard Worker // Try alternate lproj directory names...
73*5e7646d2SAndroid Build Coastguard Worker const char *tl = l; // Temporary locale string
74*5e7646d2SAndroid Build Coastguard Worker
75*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(l, "en", 2))
76*5e7646d2SAndroid Build Coastguard Worker tl = "English";
77*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(l, "nb", 2))
78*5e7646d2SAndroid Build Coastguard Worker tl = "no";
79*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(l, "nl", 2))
80*5e7646d2SAndroid Build Coastguard Worker tl = "Dutch";
81*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(l, "fr", 2))
82*5e7646d2SAndroid Build Coastguard Worker tl = "French";
83*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(l, "de", 2))
84*5e7646d2SAndroid Build Coastguard Worker tl = "German";
85*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(l, "it", 2))
86*5e7646d2SAndroid Build Coastguard Worker tl = "Italian";
87*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(l, "ja", 2))
88*5e7646d2SAndroid Build Coastguard Worker tl = "Japanese";
89*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(l, "es", 2))
90*5e7646d2SAndroid Build Coastguard Worker tl = "Spanish";
91*5e7646d2SAndroid Build Coastguard Worker
92*5e7646d2SAndroid Build Coastguard Worker snprintf(pofile, sizeof(pofile), CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings", tl);
93*5e7646d2SAndroid Build Coastguard Worker }
94*5e7646d2SAndroid Build Coastguard Worker
95*5e7646d2SAndroid Build Coastguard Worker url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)pofile, (CFIndex)strlen(pofile), false);
96*5e7646d2SAndroid Build Coastguard Worker if (url)
97*5e7646d2SAndroid Build Coastguard Worker {
98*5e7646d2SAndroid Build Coastguard Worker stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
99*5e7646d2SAndroid Build Coastguard Worker
100*5e7646d2SAndroid Build Coastguard Worker if (stream)
101*5e7646d2SAndroid Build Coastguard Worker {
102*5e7646d2SAndroid Build Coastguard Worker /*
103*5e7646d2SAndroid Build Coastguard Worker * Read the property list containing the localization data.
104*5e7646d2SAndroid Build Coastguard Worker */
105*5e7646d2SAndroid Build Coastguard Worker
106*5e7646d2SAndroid Build Coastguard Worker CFReadStreamOpen(stream);
107*5e7646d2SAndroid Build Coastguard Worker
108*5e7646d2SAndroid Build Coastguard Worker plist = CFPropertyListCreateWithStream(kCFAllocatorDefault, stream, 0, kCFPropertyListImmutable, NULL, NULL);
109*5e7646d2SAndroid Build Coastguard Worker
110*5e7646d2SAndroid Build Coastguard Worker if (plist && CFGetTypeID(plist) == CFDictionaryGetTypeID())
111*5e7646d2SAndroid Build Coastguard Worker CFDictionaryApplyFunction((CFDictionaryRef)plist, (CFDictionaryApplierFunction)apple_add_message, this);
112*5e7646d2SAndroid Build Coastguard Worker
113*5e7646d2SAndroid Build Coastguard Worker if (plist)
114*5e7646d2SAndroid Build Coastguard Worker CFRelease(plist);
115*5e7646d2SAndroid Build Coastguard Worker
116*5e7646d2SAndroid Build Coastguard Worker CFRelease(stream);
117*5e7646d2SAndroid Build Coastguard Worker }
118*5e7646d2SAndroid Build Coastguard Worker
119*5e7646d2SAndroid Build Coastguard Worker CFRelease(url);
120*5e7646d2SAndroid Build Coastguard Worker }
121*5e7646d2SAndroid Build Coastguard Worker
122*5e7646d2SAndroid Build Coastguard Worker #else
123*5e7646d2SAndroid Build Coastguard Worker _cups_globals_t *cg = _cupsGlobals();
124*5e7646d2SAndroid Build Coastguard Worker // Global information
125*5e7646d2SAndroid Build Coastguard Worker
126*5e7646d2SAndroid Build Coastguard Worker snprintf(pofile, sizeof(pofile), "%s/%s/cups_%s.po", cg->localedir, l, l);
127*5e7646d2SAndroid Build Coastguard Worker
128*5e7646d2SAndroid Build Coastguard Worker if (load_messages(pofile) && strchr(l, '_'))
129*5e7646d2SAndroid Build Coastguard Worker {
130*5e7646d2SAndroid Build Coastguard Worker // Try the base locale...
131*5e7646d2SAndroid Build Coastguard Worker char baseloc[3]; // Base locale...
132*5e7646d2SAndroid Build Coastguard Worker
133*5e7646d2SAndroid Build Coastguard Worker
134*5e7646d2SAndroid Build Coastguard Worker strlcpy(baseloc, l, sizeof(baseloc));
135*5e7646d2SAndroid Build Coastguard Worker snprintf(pofile, sizeof(pofile), "%s/%s/cups_%s.po", cg->localedir,
136*5e7646d2SAndroid Build Coastguard Worker baseloc, baseloc);
137*5e7646d2SAndroid Build Coastguard Worker
138*5e7646d2SAndroid Build Coastguard Worker load_messages(pofile);
139*5e7646d2SAndroid Build Coastguard Worker }
140*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ && CUPS_BUNDLEDIR */
141*5e7646d2SAndroid Build Coastguard Worker }
142*5e7646d2SAndroid Build Coastguard Worker
143*5e7646d2SAndroid Build Coastguard Worker if (f && *f)
144*5e7646d2SAndroid Build Coastguard Worker load_messages(f);
145*5e7646d2SAndroid Build Coastguard Worker }
146*5e7646d2SAndroid Build Coastguard Worker
147*5e7646d2SAndroid Build Coastguard Worker
148*5e7646d2SAndroid Build Coastguard Worker //
149*5e7646d2SAndroid Build Coastguard Worker // 'ppdcCatalog::~ppdcCatalog()' - Destroy a shared message catalog.
150*5e7646d2SAndroid Build Coastguard Worker //
151*5e7646d2SAndroid Build Coastguard Worker
~ppdcCatalog()152*5e7646d2SAndroid Build Coastguard Worker ppdcCatalog::~ppdcCatalog()
153*5e7646d2SAndroid Build Coastguard Worker {
154*5e7646d2SAndroid Build Coastguard Worker PPDC_DELETE;
155*5e7646d2SAndroid Build Coastguard Worker
156*5e7646d2SAndroid Build Coastguard Worker locale->release();
157*5e7646d2SAndroid Build Coastguard Worker filename->release();
158*5e7646d2SAndroid Build Coastguard Worker messages->release();
159*5e7646d2SAndroid Build Coastguard Worker }
160*5e7646d2SAndroid Build Coastguard Worker
161*5e7646d2SAndroid Build Coastguard Worker
162*5e7646d2SAndroid Build Coastguard Worker //
163*5e7646d2SAndroid Build Coastguard Worker // 'ppdcCatalog::add_message()' - Add a new message.
164*5e7646d2SAndroid Build Coastguard Worker //
165*5e7646d2SAndroid Build Coastguard Worker
166*5e7646d2SAndroid Build Coastguard Worker void
add_message(const char * id,const char * string)167*5e7646d2SAndroid Build Coastguard Worker ppdcCatalog::add_message(
168*5e7646d2SAndroid Build Coastguard Worker const char *id, // I - Message ID to add
169*5e7646d2SAndroid Build Coastguard Worker const char *string) // I - Translation string
170*5e7646d2SAndroid Build Coastguard Worker {
171*5e7646d2SAndroid Build Coastguard Worker ppdcMessage *m; // Current message
172*5e7646d2SAndroid Build Coastguard Worker char text[1024]; // Text to translate
173*5e7646d2SAndroid Build Coastguard Worker
174*5e7646d2SAndroid Build Coastguard Worker
175*5e7646d2SAndroid Build Coastguard Worker // Range check input...
176*5e7646d2SAndroid Build Coastguard Worker if (!id)
177*5e7646d2SAndroid Build Coastguard Worker return;
178*5e7646d2SAndroid Build Coastguard Worker
179*5e7646d2SAndroid Build Coastguard Worker // Verify that we don't already have the message ID...
180*5e7646d2SAndroid Build Coastguard Worker for (m = (ppdcMessage *)messages->first();
181*5e7646d2SAndroid Build Coastguard Worker m;
182*5e7646d2SAndroid Build Coastguard Worker m = (ppdcMessage *)messages->next())
183*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(m->id->value, id))
184*5e7646d2SAndroid Build Coastguard Worker {
185*5e7646d2SAndroid Build Coastguard Worker if (string)
186*5e7646d2SAndroid Build Coastguard Worker {
187*5e7646d2SAndroid Build Coastguard Worker m->string->release();
188*5e7646d2SAndroid Build Coastguard Worker m->string = new ppdcString(string);
189*5e7646d2SAndroid Build Coastguard Worker }
190*5e7646d2SAndroid Build Coastguard Worker return;
191*5e7646d2SAndroid Build Coastguard Worker }
192*5e7646d2SAndroid Build Coastguard Worker
193*5e7646d2SAndroid Build Coastguard Worker // Add the message...
194*5e7646d2SAndroid Build Coastguard Worker if (!string)
195*5e7646d2SAndroid Build Coastguard Worker {
196*5e7646d2SAndroid Build Coastguard Worker snprintf(text, sizeof(text), "TRANSLATE %s", id);
197*5e7646d2SAndroid Build Coastguard Worker string = text;
198*5e7646d2SAndroid Build Coastguard Worker }
199*5e7646d2SAndroid Build Coastguard Worker
200*5e7646d2SAndroid Build Coastguard Worker messages->add(new ppdcMessage(id, string));
201*5e7646d2SAndroid Build Coastguard Worker }
202*5e7646d2SAndroid Build Coastguard Worker
203*5e7646d2SAndroid Build Coastguard Worker
204*5e7646d2SAndroid Build Coastguard Worker //
205*5e7646d2SAndroid Build Coastguard Worker // 'ppdcCatalog::find_message()' - Find a message in a catalog...
206*5e7646d2SAndroid Build Coastguard Worker //
207*5e7646d2SAndroid Build Coastguard Worker
208*5e7646d2SAndroid Build Coastguard Worker const char * // O - Message text
find_message(const char * id)209*5e7646d2SAndroid Build Coastguard Worker ppdcCatalog::find_message(
210*5e7646d2SAndroid Build Coastguard Worker const char *id) // I - Message ID
211*5e7646d2SAndroid Build Coastguard Worker {
212*5e7646d2SAndroid Build Coastguard Worker ppdcMessage *m; // Current message
213*5e7646d2SAndroid Build Coastguard Worker
214*5e7646d2SAndroid Build Coastguard Worker
215*5e7646d2SAndroid Build Coastguard Worker if (!*id)
216*5e7646d2SAndroid Build Coastguard Worker return (id);
217*5e7646d2SAndroid Build Coastguard Worker
218*5e7646d2SAndroid Build Coastguard Worker for (m = (ppdcMessage *)messages->first();
219*5e7646d2SAndroid Build Coastguard Worker m;
220*5e7646d2SAndroid Build Coastguard Worker m = (ppdcMessage *)messages->next())
221*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(m->id->value, id))
222*5e7646d2SAndroid Build Coastguard Worker return (m->string->value);
223*5e7646d2SAndroid Build Coastguard Worker
224*5e7646d2SAndroid Build Coastguard Worker return (id);
225*5e7646d2SAndroid Build Coastguard Worker }
226*5e7646d2SAndroid Build Coastguard Worker
227*5e7646d2SAndroid Build Coastguard Worker
228*5e7646d2SAndroid Build Coastguard Worker //
229*5e7646d2SAndroid Build Coastguard Worker // 'ppdcCatalog::load_messages()' - Load messages from a .po file.
230*5e7646d2SAndroid Build Coastguard Worker //
231*5e7646d2SAndroid Build Coastguard Worker
232*5e7646d2SAndroid Build Coastguard Worker int // O - 0 on success, -1 on failure
load_messages(const char * f)233*5e7646d2SAndroid Build Coastguard Worker ppdcCatalog::load_messages(
234*5e7646d2SAndroid Build Coastguard Worker const char *f) // I - Message catalog file
235*5e7646d2SAndroid Build Coastguard Worker {
236*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; // Message file
237*5e7646d2SAndroid Build Coastguard Worker char line[4096], // Line buffer
238*5e7646d2SAndroid Build Coastguard Worker *ptr, // Pointer into buffer
239*5e7646d2SAndroid Build Coastguard Worker id[4096], // Translation ID
240*5e7646d2SAndroid Build Coastguard Worker str[4096]; // Translation string
241*5e7646d2SAndroid Build Coastguard Worker int linenum; // Line number
242*5e7646d2SAndroid Build Coastguard Worker
243*5e7646d2SAndroid Build Coastguard Worker
244*5e7646d2SAndroid Build Coastguard Worker // Open the message catalog file...
245*5e7646d2SAndroid Build Coastguard Worker if ((fp = cupsFileOpen(f, "r")) == NULL)
246*5e7646d2SAndroid Build Coastguard Worker return (-1);
247*5e7646d2SAndroid Build Coastguard Worker
248*5e7646d2SAndroid Build Coastguard Worker if ((ptr = (char *)strrchr(f, '.')) == NULL)
249*5e7646d2SAndroid Build Coastguard Worker goto unknown_load_format;
250*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ptr, ".strings"))
251*5e7646d2SAndroid Build Coastguard Worker {
252*5e7646d2SAndroid Build Coastguard Worker /*
253*5e7646d2SAndroid Build Coastguard Worker * Read messages in macOS ".strings" format, which are either UTF-8/UTF-16
254*5e7646d2SAndroid Build Coastguard Worker * text files of the format:
255*5e7646d2SAndroid Build Coastguard Worker *
256*5e7646d2SAndroid Build Coastguard Worker * "id" = "str";
257*5e7646d2SAndroid Build Coastguard Worker *
258*5e7646d2SAndroid Build Coastguard Worker * Strings files can also contain C-style comments.
259*5e7646d2SAndroid Build Coastguard Worker */
260*5e7646d2SAndroid Build Coastguard Worker
261*5e7646d2SAndroid Build Coastguard Worker ppdc_cs_t cs = PPDC_CS_AUTO; // Character set for file
262*5e7646d2SAndroid Build Coastguard Worker int ch; // Current character from file
263*5e7646d2SAndroid Build Coastguard Worker char *end; // End of buffer
264*5e7646d2SAndroid Build Coastguard Worker
265*5e7646d2SAndroid Build Coastguard Worker
266*5e7646d2SAndroid Build Coastguard Worker id[0] = '\0';
267*5e7646d2SAndroid Build Coastguard Worker str[0] = '\0';
268*5e7646d2SAndroid Build Coastguard Worker ptr = NULL;
269*5e7646d2SAndroid Build Coastguard Worker end = NULL;
270*5e7646d2SAndroid Build Coastguard Worker
271*5e7646d2SAndroid Build Coastguard Worker while ((ch = get_utf16(fp, cs)) != 0)
272*5e7646d2SAndroid Build Coastguard Worker {
273*5e7646d2SAndroid Build Coastguard Worker if (ptr)
274*5e7646d2SAndroid Build Coastguard Worker {
275*5e7646d2SAndroid Build Coastguard Worker if (ch == '\\')
276*5e7646d2SAndroid Build Coastguard Worker {
277*5e7646d2SAndroid Build Coastguard Worker if ((ch = get_utf16(fp, cs)) == 0)
278*5e7646d2SAndroid Build Coastguard Worker break;
279*5e7646d2SAndroid Build Coastguard Worker
280*5e7646d2SAndroid Build Coastguard Worker if (ch == 'n')
281*5e7646d2SAndroid Build Coastguard Worker ch = '\n';
282*5e7646d2SAndroid Build Coastguard Worker else if (ch == 't')
283*5e7646d2SAndroid Build Coastguard Worker ch = '\t';
284*5e7646d2SAndroid Build Coastguard Worker }
285*5e7646d2SAndroid Build Coastguard Worker else if (ch == '\"')
286*5e7646d2SAndroid Build Coastguard Worker {
287*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
288*5e7646d2SAndroid Build Coastguard Worker ptr = NULL;
289*5e7646d2SAndroid Build Coastguard Worker }
290*5e7646d2SAndroid Build Coastguard Worker
291*5e7646d2SAndroid Build Coastguard Worker if (ptr)
292*5e7646d2SAndroid Build Coastguard Worker put_utf8(ch, ptr, end);
293*5e7646d2SAndroid Build Coastguard Worker }
294*5e7646d2SAndroid Build Coastguard Worker else if (ch == '/')
295*5e7646d2SAndroid Build Coastguard Worker {
296*5e7646d2SAndroid Build Coastguard Worker // Start of a comment?
297*5e7646d2SAndroid Build Coastguard Worker if ((ch = get_utf16(fp, cs)) == 0)
298*5e7646d2SAndroid Build Coastguard Worker break;
299*5e7646d2SAndroid Build Coastguard Worker
300*5e7646d2SAndroid Build Coastguard Worker if (ch == '*')
301*5e7646d2SAndroid Build Coastguard Worker {
302*5e7646d2SAndroid Build Coastguard Worker // Skip C comment...
303*5e7646d2SAndroid Build Coastguard Worker int lastch = 0;
304*5e7646d2SAndroid Build Coastguard Worker
305*5e7646d2SAndroid Build Coastguard Worker while ((ch = get_utf16(fp, cs)) != 0)
306*5e7646d2SAndroid Build Coastguard Worker {
307*5e7646d2SAndroid Build Coastguard Worker if (ch == '/' && lastch == '*')
308*5e7646d2SAndroid Build Coastguard Worker break;
309*5e7646d2SAndroid Build Coastguard Worker
310*5e7646d2SAndroid Build Coastguard Worker lastch = ch;
311*5e7646d2SAndroid Build Coastguard Worker }
312*5e7646d2SAndroid Build Coastguard Worker }
313*5e7646d2SAndroid Build Coastguard Worker else if (ch == '/')
314*5e7646d2SAndroid Build Coastguard Worker {
315*5e7646d2SAndroid Build Coastguard Worker // Skip C++ comment...
316*5e7646d2SAndroid Build Coastguard Worker while ((ch = get_utf16(fp, cs)) != 0)
317*5e7646d2SAndroid Build Coastguard Worker if (ch == '\n')
318*5e7646d2SAndroid Build Coastguard Worker break;
319*5e7646d2SAndroid Build Coastguard Worker }
320*5e7646d2SAndroid Build Coastguard Worker }
321*5e7646d2SAndroid Build Coastguard Worker else if (ch == '\"')
322*5e7646d2SAndroid Build Coastguard Worker {
323*5e7646d2SAndroid Build Coastguard Worker // Start quoted string...
324*5e7646d2SAndroid Build Coastguard Worker if (id[0])
325*5e7646d2SAndroid Build Coastguard Worker {
326*5e7646d2SAndroid Build Coastguard Worker ptr = str;
327*5e7646d2SAndroid Build Coastguard Worker end = str + sizeof(str) - 1;
328*5e7646d2SAndroid Build Coastguard Worker }
329*5e7646d2SAndroid Build Coastguard Worker else
330*5e7646d2SAndroid Build Coastguard Worker {
331*5e7646d2SAndroid Build Coastguard Worker ptr = id;
332*5e7646d2SAndroid Build Coastguard Worker end = id + sizeof(id) - 1;
333*5e7646d2SAndroid Build Coastguard Worker }
334*5e7646d2SAndroid Build Coastguard Worker }
335*5e7646d2SAndroid Build Coastguard Worker else if (ch == ';')
336*5e7646d2SAndroid Build Coastguard Worker {
337*5e7646d2SAndroid Build Coastguard Worker // Add string...
338*5e7646d2SAndroid Build Coastguard Worker add_message(id, str);
339*5e7646d2SAndroid Build Coastguard Worker id[0] = '\0';
340*5e7646d2SAndroid Build Coastguard Worker }
341*5e7646d2SAndroid Build Coastguard Worker }
342*5e7646d2SAndroid Build Coastguard Worker }
343*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ptr, ".po") || !strcmp(ptr, ".gz"))
344*5e7646d2SAndroid Build Coastguard Worker {
345*5e7646d2SAndroid Build Coastguard Worker /*
346*5e7646d2SAndroid Build Coastguard Worker * Read messages from the catalog file until EOF...
347*5e7646d2SAndroid Build Coastguard Worker *
348*5e7646d2SAndroid Build Coastguard Worker * The format is the GNU gettext .po format, which is fairly simple:
349*5e7646d2SAndroid Build Coastguard Worker *
350*5e7646d2SAndroid Build Coastguard Worker * msgid "some text"
351*5e7646d2SAndroid Build Coastguard Worker * msgstr "localized text"
352*5e7646d2SAndroid Build Coastguard Worker *
353*5e7646d2SAndroid Build Coastguard Worker * The ID and localized text can span multiple lines using the form:
354*5e7646d2SAndroid Build Coastguard Worker *
355*5e7646d2SAndroid Build Coastguard Worker * msgid ""
356*5e7646d2SAndroid Build Coastguard Worker * "some long text"
357*5e7646d2SAndroid Build Coastguard Worker * msgstr ""
358*5e7646d2SAndroid Build Coastguard Worker * "localized text spanning "
359*5e7646d2SAndroid Build Coastguard Worker * "multiple lines"
360*5e7646d2SAndroid Build Coastguard Worker */
361*5e7646d2SAndroid Build Coastguard Worker
362*5e7646d2SAndroid Build Coastguard Worker int which, // In msgid?
363*5e7646d2SAndroid Build Coastguard Worker haveid, // Did we get a msgid string?
364*5e7646d2SAndroid Build Coastguard Worker havestr; // Did we get a msgstr string?
365*5e7646d2SAndroid Build Coastguard Worker
366*5e7646d2SAndroid Build Coastguard Worker linenum = 0;
367*5e7646d2SAndroid Build Coastguard Worker id[0] = '\0';
368*5e7646d2SAndroid Build Coastguard Worker str[0] = '\0';
369*5e7646d2SAndroid Build Coastguard Worker haveid = 0;
370*5e7646d2SAndroid Build Coastguard Worker havestr = 0;
371*5e7646d2SAndroid Build Coastguard Worker which = 0;
372*5e7646d2SAndroid Build Coastguard Worker
373*5e7646d2SAndroid Build Coastguard Worker while (cupsFileGets(fp, line, sizeof(line)))
374*5e7646d2SAndroid Build Coastguard Worker {
375*5e7646d2SAndroid Build Coastguard Worker linenum ++;
376*5e7646d2SAndroid Build Coastguard Worker
377*5e7646d2SAndroid Build Coastguard Worker // Skip blank and comment lines...
378*5e7646d2SAndroid Build Coastguard Worker if (line[0] == '#' || !line[0])
379*5e7646d2SAndroid Build Coastguard Worker continue;
380*5e7646d2SAndroid Build Coastguard Worker
381*5e7646d2SAndroid Build Coastguard Worker // Strip the trailing quote...
382*5e7646d2SAndroid Build Coastguard Worker if ((ptr = (char *)strrchr(line, '\"')) == NULL)
383*5e7646d2SAndroid Build Coastguard Worker {
384*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
385*5e7646d2SAndroid Build Coastguard Worker _("ppdc: Expected quoted string on line %d of %s."),
386*5e7646d2SAndroid Build Coastguard Worker linenum, f);
387*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
388*5e7646d2SAndroid Build Coastguard Worker return (-1);
389*5e7646d2SAndroid Build Coastguard Worker }
390*5e7646d2SAndroid Build Coastguard Worker
391*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
392*5e7646d2SAndroid Build Coastguard Worker
393*5e7646d2SAndroid Build Coastguard Worker // Find start of value...
394*5e7646d2SAndroid Build Coastguard Worker if ((ptr = strchr(line, '\"')) == NULL)
395*5e7646d2SAndroid Build Coastguard Worker {
396*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
397*5e7646d2SAndroid Build Coastguard Worker _("ppdc: Expected quoted string on line %d of %s."),
398*5e7646d2SAndroid Build Coastguard Worker linenum, f);
399*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
400*5e7646d2SAndroid Build Coastguard Worker return (-1);
401*5e7646d2SAndroid Build Coastguard Worker }
402*5e7646d2SAndroid Build Coastguard Worker
403*5e7646d2SAndroid Build Coastguard Worker ptr ++;
404*5e7646d2SAndroid Build Coastguard Worker
405*5e7646d2SAndroid Build Coastguard Worker // Unquote the text...
406*5e7646d2SAndroid Build Coastguard Worker char *sptr, *dptr; // Source/destination pointers
407*5e7646d2SAndroid Build Coastguard Worker
408*5e7646d2SAndroid Build Coastguard Worker for (sptr = ptr, dptr = ptr; *sptr;)
409*5e7646d2SAndroid Build Coastguard Worker {
410*5e7646d2SAndroid Build Coastguard Worker if (*sptr == '\\')
411*5e7646d2SAndroid Build Coastguard Worker {
412*5e7646d2SAndroid Build Coastguard Worker sptr ++;
413*5e7646d2SAndroid Build Coastguard Worker if (isdigit(*sptr))
414*5e7646d2SAndroid Build Coastguard Worker {
415*5e7646d2SAndroid Build Coastguard Worker *dptr = 0;
416*5e7646d2SAndroid Build Coastguard Worker
417*5e7646d2SAndroid Build Coastguard Worker while (isdigit(*sptr))
418*5e7646d2SAndroid Build Coastguard Worker {
419*5e7646d2SAndroid Build Coastguard Worker *dptr = *dptr * 8 + *sptr - '0';
420*5e7646d2SAndroid Build Coastguard Worker sptr ++;
421*5e7646d2SAndroid Build Coastguard Worker }
422*5e7646d2SAndroid Build Coastguard Worker
423*5e7646d2SAndroid Build Coastguard Worker dptr ++;
424*5e7646d2SAndroid Build Coastguard Worker }
425*5e7646d2SAndroid Build Coastguard Worker else
426*5e7646d2SAndroid Build Coastguard Worker {
427*5e7646d2SAndroid Build Coastguard Worker if (*sptr == 'n')
428*5e7646d2SAndroid Build Coastguard Worker *dptr++ = '\n';
429*5e7646d2SAndroid Build Coastguard Worker else if (*sptr == 'r')
430*5e7646d2SAndroid Build Coastguard Worker *dptr++ = '\r';
431*5e7646d2SAndroid Build Coastguard Worker else if (*sptr == 't')
432*5e7646d2SAndroid Build Coastguard Worker *dptr++ = '\t';
433*5e7646d2SAndroid Build Coastguard Worker else
434*5e7646d2SAndroid Build Coastguard Worker *dptr++ = *sptr;
435*5e7646d2SAndroid Build Coastguard Worker
436*5e7646d2SAndroid Build Coastguard Worker sptr ++;
437*5e7646d2SAndroid Build Coastguard Worker }
438*5e7646d2SAndroid Build Coastguard Worker }
439*5e7646d2SAndroid Build Coastguard Worker else
440*5e7646d2SAndroid Build Coastguard Worker *dptr++ = *sptr++;
441*5e7646d2SAndroid Build Coastguard Worker }
442*5e7646d2SAndroid Build Coastguard Worker
443*5e7646d2SAndroid Build Coastguard Worker *dptr = '\0';
444*5e7646d2SAndroid Build Coastguard Worker
445*5e7646d2SAndroid Build Coastguard Worker // Create or add to a message...
446*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(line, "msgid", 5))
447*5e7646d2SAndroid Build Coastguard Worker {
448*5e7646d2SAndroid Build Coastguard Worker if (haveid && havestr)
449*5e7646d2SAndroid Build Coastguard Worker add_message(id, str);
450*5e7646d2SAndroid Build Coastguard Worker
451*5e7646d2SAndroid Build Coastguard Worker strlcpy(id, ptr, sizeof(id));
452*5e7646d2SAndroid Build Coastguard Worker str[0] = '\0';
453*5e7646d2SAndroid Build Coastguard Worker haveid = 1;
454*5e7646d2SAndroid Build Coastguard Worker havestr = 0;
455*5e7646d2SAndroid Build Coastguard Worker which = 1;
456*5e7646d2SAndroid Build Coastguard Worker }
457*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(line, "msgstr", 6))
458*5e7646d2SAndroid Build Coastguard Worker {
459*5e7646d2SAndroid Build Coastguard Worker if (!haveid)
460*5e7646d2SAndroid Build Coastguard Worker {
461*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
462*5e7646d2SAndroid Build Coastguard Worker _("ppdc: Need a msgid line before any "
463*5e7646d2SAndroid Build Coastguard Worker "translation strings on line %d of %s."),
464*5e7646d2SAndroid Build Coastguard Worker linenum, f);
465*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
466*5e7646d2SAndroid Build Coastguard Worker return (-1);
467*5e7646d2SAndroid Build Coastguard Worker }
468*5e7646d2SAndroid Build Coastguard Worker
469*5e7646d2SAndroid Build Coastguard Worker strlcpy(str, ptr, sizeof(str));
470*5e7646d2SAndroid Build Coastguard Worker havestr = 1;
471*5e7646d2SAndroid Build Coastguard Worker which = 2;
472*5e7646d2SAndroid Build Coastguard Worker }
473*5e7646d2SAndroid Build Coastguard Worker else if (line[0] == '\"' && which == 2)
474*5e7646d2SAndroid Build Coastguard Worker strlcat(str, ptr, sizeof(str));
475*5e7646d2SAndroid Build Coastguard Worker else if (line[0] == '\"' && which == 1)
476*5e7646d2SAndroid Build Coastguard Worker strlcat(id, ptr, sizeof(id));
477*5e7646d2SAndroid Build Coastguard Worker else
478*5e7646d2SAndroid Build Coastguard Worker {
479*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr, _("ppdc: Unexpected text on line %d of %s."),
480*5e7646d2SAndroid Build Coastguard Worker linenum, f);
481*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
482*5e7646d2SAndroid Build Coastguard Worker return (-1);
483*5e7646d2SAndroid Build Coastguard Worker }
484*5e7646d2SAndroid Build Coastguard Worker }
485*5e7646d2SAndroid Build Coastguard Worker
486*5e7646d2SAndroid Build Coastguard Worker if (haveid && havestr)
487*5e7646d2SAndroid Build Coastguard Worker add_message(id, str);
488*5e7646d2SAndroid Build Coastguard Worker }
489*5e7646d2SAndroid Build Coastguard Worker else
490*5e7646d2SAndroid Build Coastguard Worker goto unknown_load_format;
491*5e7646d2SAndroid Build Coastguard Worker
492*5e7646d2SAndroid Build Coastguard Worker /*
493*5e7646d2SAndroid Build Coastguard Worker * Close the file and return...
494*5e7646d2SAndroid Build Coastguard Worker */
495*5e7646d2SAndroid Build Coastguard Worker
496*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
497*5e7646d2SAndroid Build Coastguard Worker
498*5e7646d2SAndroid Build Coastguard Worker return (0);
499*5e7646d2SAndroid Build Coastguard Worker
500*5e7646d2SAndroid Build Coastguard Worker /*
501*5e7646d2SAndroid Build Coastguard Worker * Unknown format error...
502*5e7646d2SAndroid Build Coastguard Worker */
503*5e7646d2SAndroid Build Coastguard Worker
504*5e7646d2SAndroid Build Coastguard Worker unknown_load_format:
505*5e7646d2SAndroid Build Coastguard Worker
506*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
507*5e7646d2SAndroid Build Coastguard Worker _("ppdc: Unknown message catalog format for \"%s\"."), f);
508*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
509*5e7646d2SAndroid Build Coastguard Worker return (-1);
510*5e7646d2SAndroid Build Coastguard Worker }
511*5e7646d2SAndroid Build Coastguard Worker
512*5e7646d2SAndroid Build Coastguard Worker
513*5e7646d2SAndroid Build Coastguard Worker //
514*5e7646d2SAndroid Build Coastguard Worker // 'ppdcCatalog::save_messages()' - Save the messages to a .po file.
515*5e7646d2SAndroid Build Coastguard Worker //
516*5e7646d2SAndroid Build Coastguard Worker
517*5e7646d2SAndroid Build Coastguard Worker int // O - 0 on success, -1 on error
save_messages(const char * f)518*5e7646d2SAndroid Build Coastguard Worker ppdcCatalog::save_messages(
519*5e7646d2SAndroid Build Coastguard Worker const char *f) // I - File to save to
520*5e7646d2SAndroid Build Coastguard Worker {
521*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; // Message file
522*5e7646d2SAndroid Build Coastguard Worker ppdcMessage *m; // Current message
523*5e7646d2SAndroid Build Coastguard Worker char *ptr; // Pointer into string
524*5e7646d2SAndroid Build Coastguard Worker int utf16; // Output UTF-16 .strings file?
525*5e7646d2SAndroid Build Coastguard Worker int ch; // Current character
526*5e7646d2SAndroid Build Coastguard Worker
527*5e7646d2SAndroid Build Coastguard Worker
528*5e7646d2SAndroid Build Coastguard Worker // Open the file...
529*5e7646d2SAndroid Build Coastguard Worker if ((ptr = (char *)strrchr(f, '.')) == NULL)
530*5e7646d2SAndroid Build Coastguard Worker return (-1);
531*5e7646d2SAndroid Build Coastguard Worker
532*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(ptr, ".gz"))
533*5e7646d2SAndroid Build Coastguard Worker fp = cupsFileOpen(f, "w9");
534*5e7646d2SAndroid Build Coastguard Worker else
535*5e7646d2SAndroid Build Coastguard Worker fp = cupsFileOpen(f, "w");
536*5e7646d2SAndroid Build Coastguard Worker
537*5e7646d2SAndroid Build Coastguard Worker if (!fp)
538*5e7646d2SAndroid Build Coastguard Worker return (-1);
539*5e7646d2SAndroid Build Coastguard Worker
540*5e7646d2SAndroid Build Coastguard Worker // For .strings files, write a BOM for big-endian output...
541*5e7646d2SAndroid Build Coastguard Worker utf16 = !strcmp(ptr, ".strings");
542*5e7646d2SAndroid Build Coastguard Worker
543*5e7646d2SAndroid Build Coastguard Worker if (utf16)
544*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, 0xfeff);
545*5e7646d2SAndroid Build Coastguard Worker
546*5e7646d2SAndroid Build Coastguard Worker // Loop through all of the messages...
547*5e7646d2SAndroid Build Coastguard Worker for (m = (ppdcMessage *)messages->first();
548*5e7646d2SAndroid Build Coastguard Worker m;
549*5e7646d2SAndroid Build Coastguard Worker m = (ppdcMessage *)messages->next())
550*5e7646d2SAndroid Build Coastguard Worker {
551*5e7646d2SAndroid Build Coastguard Worker if (utf16)
552*5e7646d2SAndroid Build Coastguard Worker {
553*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\"');
554*5e7646d2SAndroid Build Coastguard Worker
555*5e7646d2SAndroid Build Coastguard Worker ptr = m->id->value;
556*5e7646d2SAndroid Build Coastguard Worker while ((ch = get_utf8(ptr)) != 0)
557*5e7646d2SAndroid Build Coastguard Worker switch (ch)
558*5e7646d2SAndroid Build Coastguard Worker {
559*5e7646d2SAndroid Build Coastguard Worker case '\n' :
560*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\\');
561*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, 'n');
562*5e7646d2SAndroid Build Coastguard Worker break;
563*5e7646d2SAndroid Build Coastguard Worker case '\\' :
564*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\\');
565*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\\');
566*5e7646d2SAndroid Build Coastguard Worker break;
567*5e7646d2SAndroid Build Coastguard Worker case '\"' :
568*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\\');
569*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\"');
570*5e7646d2SAndroid Build Coastguard Worker break;
571*5e7646d2SAndroid Build Coastguard Worker default :
572*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, ch);
573*5e7646d2SAndroid Build Coastguard Worker break;
574*5e7646d2SAndroid Build Coastguard Worker }
575*5e7646d2SAndroid Build Coastguard Worker
576*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\"');
577*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, ' ');
578*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '=');
579*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, ' ');
580*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\"');
581*5e7646d2SAndroid Build Coastguard Worker
582*5e7646d2SAndroid Build Coastguard Worker ptr = m->string->value;
583*5e7646d2SAndroid Build Coastguard Worker while ((ch = get_utf8(ptr)) != 0)
584*5e7646d2SAndroid Build Coastguard Worker switch (ch)
585*5e7646d2SAndroid Build Coastguard Worker {
586*5e7646d2SAndroid Build Coastguard Worker case '\n' :
587*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\\');
588*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, 'n');
589*5e7646d2SAndroid Build Coastguard Worker break;
590*5e7646d2SAndroid Build Coastguard Worker case '\\' :
591*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\\');
592*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\\');
593*5e7646d2SAndroid Build Coastguard Worker break;
594*5e7646d2SAndroid Build Coastguard Worker case '\"' :
595*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\\');
596*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\"');
597*5e7646d2SAndroid Build Coastguard Worker break;
598*5e7646d2SAndroid Build Coastguard Worker default :
599*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, ch);
600*5e7646d2SAndroid Build Coastguard Worker break;
601*5e7646d2SAndroid Build Coastguard Worker }
602*5e7646d2SAndroid Build Coastguard Worker
603*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\"');
604*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, ';');
605*5e7646d2SAndroid Build Coastguard Worker put_utf16(fp, '\n');
606*5e7646d2SAndroid Build Coastguard Worker }
607*5e7646d2SAndroid Build Coastguard Worker else
608*5e7646d2SAndroid Build Coastguard Worker {
609*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "msgid \"");
610*5e7646d2SAndroid Build Coastguard Worker for (ptr = m->id->value; *ptr; ptr ++)
611*5e7646d2SAndroid Build Coastguard Worker switch (*ptr)
612*5e7646d2SAndroid Build Coastguard Worker {
613*5e7646d2SAndroid Build Coastguard Worker case '\n' :
614*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\\n");
615*5e7646d2SAndroid Build Coastguard Worker break;
616*5e7646d2SAndroid Build Coastguard Worker case '\\' :
617*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\\\\");
618*5e7646d2SAndroid Build Coastguard Worker break;
619*5e7646d2SAndroid Build Coastguard Worker case '\"' :
620*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\\\"");
621*5e7646d2SAndroid Build Coastguard Worker break;
622*5e7646d2SAndroid Build Coastguard Worker default :
623*5e7646d2SAndroid Build Coastguard Worker cupsFilePutChar(fp, *ptr);
624*5e7646d2SAndroid Build Coastguard Worker break;
625*5e7646d2SAndroid Build Coastguard Worker }
626*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\"\n");
627*5e7646d2SAndroid Build Coastguard Worker
628*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "msgstr \"");
629*5e7646d2SAndroid Build Coastguard Worker for (ptr = m->string->value; *ptr; ptr ++)
630*5e7646d2SAndroid Build Coastguard Worker switch (*ptr)
631*5e7646d2SAndroid Build Coastguard Worker {
632*5e7646d2SAndroid Build Coastguard Worker case '\n' :
633*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\\n");
634*5e7646d2SAndroid Build Coastguard Worker break;
635*5e7646d2SAndroid Build Coastguard Worker case '\\' :
636*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\\\\");
637*5e7646d2SAndroid Build Coastguard Worker break;
638*5e7646d2SAndroid Build Coastguard Worker case '\"' :
639*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\\\"");
640*5e7646d2SAndroid Build Coastguard Worker break;
641*5e7646d2SAndroid Build Coastguard Worker default :
642*5e7646d2SAndroid Build Coastguard Worker cupsFilePutChar(fp, *ptr);
643*5e7646d2SAndroid Build Coastguard Worker break;
644*5e7646d2SAndroid Build Coastguard Worker }
645*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "\"\n");
646*5e7646d2SAndroid Build Coastguard Worker
647*5e7646d2SAndroid Build Coastguard Worker cupsFilePutChar(fp, '\n');
648*5e7646d2SAndroid Build Coastguard Worker }
649*5e7646d2SAndroid Build Coastguard Worker }
650*5e7646d2SAndroid Build Coastguard Worker
651*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
652*5e7646d2SAndroid Build Coastguard Worker
653*5e7646d2SAndroid Build Coastguard Worker return (0);
654*5e7646d2SAndroid Build Coastguard Worker }
655*5e7646d2SAndroid Build Coastguard Worker
656*5e7646d2SAndroid Build Coastguard Worker
657*5e7646d2SAndroid Build Coastguard Worker #if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
658*5e7646d2SAndroid Build Coastguard Worker //
659*5e7646d2SAndroid Build Coastguard Worker // 'apple_add_message()' - Add a message from a localization dictionary.
660*5e7646d2SAndroid Build Coastguard Worker //
661*5e7646d2SAndroid Build Coastguard Worker
662*5e7646d2SAndroid Build Coastguard Worker static void
apple_add_message(CFStringRef key,CFStringRef val,ppdcCatalog * c)663*5e7646d2SAndroid Build Coastguard Worker apple_add_message(CFStringRef key, // I - Localization key
664*5e7646d2SAndroid Build Coastguard Worker CFStringRef val, // I - Localized value
665*5e7646d2SAndroid Build Coastguard Worker ppdcCatalog *c) // I - Message catalog
666*5e7646d2SAndroid Build Coastguard Worker {
667*5e7646d2SAndroid Build Coastguard Worker char id[1024], // Message id
668*5e7646d2SAndroid Build Coastguard Worker str[1024]; // Localized message
669*5e7646d2SAndroid Build Coastguard Worker
670*5e7646d2SAndroid Build Coastguard Worker
671*5e7646d2SAndroid Build Coastguard Worker if (CFStringGetCString(key, id, sizeof(id), kCFStringEncodingUTF8) &&
672*5e7646d2SAndroid Build Coastguard Worker CFStringGetCString(val, str, sizeof(str), kCFStringEncodingUTF8))
673*5e7646d2SAndroid Build Coastguard Worker c->add_message(id, str);
674*5e7646d2SAndroid Build Coastguard Worker }
675*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ && CUPS_BUNDLEDIR */
676*5e7646d2SAndroid Build Coastguard Worker
677*5e7646d2SAndroid Build Coastguard Worker
678*5e7646d2SAndroid Build Coastguard Worker //
679*5e7646d2SAndroid Build Coastguard Worker // 'get_utf8()' - Get a UTF-8 character.
680*5e7646d2SAndroid Build Coastguard Worker //
681*5e7646d2SAndroid Build Coastguard Worker
682*5e7646d2SAndroid Build Coastguard Worker static int // O - Unicode character or 0 on EOF
get_utf8(char * & ptr)683*5e7646d2SAndroid Build Coastguard Worker get_utf8(char *&ptr) // IO - Pointer to character
684*5e7646d2SAndroid Build Coastguard Worker {
685*5e7646d2SAndroid Build Coastguard Worker int ch; // Current character
686*5e7646d2SAndroid Build Coastguard Worker
687*5e7646d2SAndroid Build Coastguard Worker
688*5e7646d2SAndroid Build Coastguard Worker if ((ch = *ptr++ & 255) < 0xc0)
689*5e7646d2SAndroid Build Coastguard Worker return (ch);
690*5e7646d2SAndroid Build Coastguard Worker
691*5e7646d2SAndroid Build Coastguard Worker if ((ch & 0xe0) == 0xc0)
692*5e7646d2SAndroid Build Coastguard Worker {
693*5e7646d2SAndroid Build Coastguard Worker // Two-byte UTF-8...
694*5e7646d2SAndroid Build Coastguard Worker if ((*ptr & 0xc0) != 0x80)
695*5e7646d2SAndroid Build Coastguard Worker return (0);
696*5e7646d2SAndroid Build Coastguard Worker
697*5e7646d2SAndroid Build Coastguard Worker ch = ((ch & 0x1f) << 6) | (*ptr++ & 0x3f);
698*5e7646d2SAndroid Build Coastguard Worker }
699*5e7646d2SAndroid Build Coastguard Worker else if ((ch & 0xf0) == 0xe0)
700*5e7646d2SAndroid Build Coastguard Worker {
701*5e7646d2SAndroid Build Coastguard Worker // Three-byte UTF-8...
702*5e7646d2SAndroid Build Coastguard Worker if ((*ptr & 0xc0) != 0x80)
703*5e7646d2SAndroid Build Coastguard Worker return (0);
704*5e7646d2SAndroid Build Coastguard Worker
705*5e7646d2SAndroid Build Coastguard Worker ch = ((ch & 0x0f) << 6) | (*ptr++ & 0x3f);
706*5e7646d2SAndroid Build Coastguard Worker
707*5e7646d2SAndroid Build Coastguard Worker if ((*ptr & 0xc0) != 0x80)
708*5e7646d2SAndroid Build Coastguard Worker return (0);
709*5e7646d2SAndroid Build Coastguard Worker
710*5e7646d2SAndroid Build Coastguard Worker ch = (ch << 6) | (*ptr++ & 0x3f);
711*5e7646d2SAndroid Build Coastguard Worker }
712*5e7646d2SAndroid Build Coastguard Worker else if ((ch & 0xf8) == 0xf0)
713*5e7646d2SAndroid Build Coastguard Worker {
714*5e7646d2SAndroid Build Coastguard Worker // Four-byte UTF-8...
715*5e7646d2SAndroid Build Coastguard Worker if ((*ptr & 0xc0) != 0x80)
716*5e7646d2SAndroid Build Coastguard Worker return (0);
717*5e7646d2SAndroid Build Coastguard Worker
718*5e7646d2SAndroid Build Coastguard Worker ch = ((ch & 0x07) << 6) | (*ptr++ & 0x3f);
719*5e7646d2SAndroid Build Coastguard Worker
720*5e7646d2SAndroid Build Coastguard Worker if ((*ptr & 0xc0) != 0x80)
721*5e7646d2SAndroid Build Coastguard Worker return (0);
722*5e7646d2SAndroid Build Coastguard Worker
723*5e7646d2SAndroid Build Coastguard Worker ch = (ch << 6) | (*ptr++ & 0x3f);
724*5e7646d2SAndroid Build Coastguard Worker
725*5e7646d2SAndroid Build Coastguard Worker if ((*ptr & 0xc0) != 0x80)
726*5e7646d2SAndroid Build Coastguard Worker return (0);
727*5e7646d2SAndroid Build Coastguard Worker
728*5e7646d2SAndroid Build Coastguard Worker ch = (ch << 6) | (*ptr++ & 0x3f);
729*5e7646d2SAndroid Build Coastguard Worker }
730*5e7646d2SAndroid Build Coastguard Worker
731*5e7646d2SAndroid Build Coastguard Worker return (ch);
732*5e7646d2SAndroid Build Coastguard Worker }
733*5e7646d2SAndroid Build Coastguard Worker
734*5e7646d2SAndroid Build Coastguard Worker
735*5e7646d2SAndroid Build Coastguard Worker //
736*5e7646d2SAndroid Build Coastguard Worker // 'get_utf16()' - Get a UTF-16 character...
737*5e7646d2SAndroid Build Coastguard Worker //
738*5e7646d2SAndroid Build Coastguard Worker
739*5e7646d2SAndroid Build Coastguard Worker static int // O - Unicode character or 0 on EOF
get_utf16(cups_file_t * fp,ppdc_cs_t & cs)740*5e7646d2SAndroid Build Coastguard Worker get_utf16(cups_file_t *fp, // I - File to read from
741*5e7646d2SAndroid Build Coastguard Worker ppdc_cs_t &cs) // IO - Character set of file
742*5e7646d2SAndroid Build Coastguard Worker {
743*5e7646d2SAndroid Build Coastguard Worker int ch; // Current character
744*5e7646d2SAndroid Build Coastguard Worker unsigned char buffer[3]; // Bytes
745*5e7646d2SAndroid Build Coastguard Worker
746*5e7646d2SAndroid Build Coastguard Worker
747*5e7646d2SAndroid Build Coastguard Worker if (cs == PPDC_CS_AUTO)
748*5e7646d2SAndroid Build Coastguard Worker {
749*5e7646d2SAndroid Build Coastguard Worker // Get byte-order-mark, if present...
750*5e7646d2SAndroid Build Coastguard Worker if (cupsFileRead(fp, (char *)buffer, 2) != 2)
751*5e7646d2SAndroid Build Coastguard Worker return (0);
752*5e7646d2SAndroid Build Coastguard Worker
753*5e7646d2SAndroid Build Coastguard Worker if (buffer[0] == 0xfe && buffer[1] == 0xff)
754*5e7646d2SAndroid Build Coastguard Worker {
755*5e7646d2SAndroid Build Coastguard Worker // Big-endian UTF-16...
756*5e7646d2SAndroid Build Coastguard Worker cs = PPDC_CS_UTF16BE;
757*5e7646d2SAndroid Build Coastguard Worker
758*5e7646d2SAndroid Build Coastguard Worker if (cupsFileRead(fp, (char *)buffer, 2) != 2)
759*5e7646d2SAndroid Build Coastguard Worker return (0);
760*5e7646d2SAndroid Build Coastguard Worker }
761*5e7646d2SAndroid Build Coastguard Worker else if (buffer[0] == 0xff && buffer[1] == 0xfe)
762*5e7646d2SAndroid Build Coastguard Worker {
763*5e7646d2SAndroid Build Coastguard Worker // Little-endian UTF-16...
764*5e7646d2SAndroid Build Coastguard Worker cs = PPDC_CS_UTF16LE;
765*5e7646d2SAndroid Build Coastguard Worker
766*5e7646d2SAndroid Build Coastguard Worker if (cupsFileRead(fp, (char *)buffer, 2) != 2)
767*5e7646d2SAndroid Build Coastguard Worker return (0);
768*5e7646d2SAndroid Build Coastguard Worker }
769*5e7646d2SAndroid Build Coastguard Worker else if (buffer[0] == 0x00 && buffer[1] != 0x00)
770*5e7646d2SAndroid Build Coastguard Worker {
771*5e7646d2SAndroid Build Coastguard Worker // No BOM, assume big-endian UTF-16...
772*5e7646d2SAndroid Build Coastguard Worker cs = PPDC_CS_UTF16BE;
773*5e7646d2SAndroid Build Coastguard Worker }
774*5e7646d2SAndroid Build Coastguard Worker else if (buffer[0] != 0x00 && buffer[1] == 0x00)
775*5e7646d2SAndroid Build Coastguard Worker {
776*5e7646d2SAndroid Build Coastguard Worker // No BOM, assume little-endian UTF-16...
777*5e7646d2SAndroid Build Coastguard Worker cs = PPDC_CS_UTF16LE;
778*5e7646d2SAndroid Build Coastguard Worker }
779*5e7646d2SAndroid Build Coastguard Worker else
780*5e7646d2SAndroid Build Coastguard Worker {
781*5e7646d2SAndroid Build Coastguard Worker // No BOM, assume UTF-8...
782*5e7646d2SAndroid Build Coastguard Worker cs = PPDC_CS_UTF8;
783*5e7646d2SAndroid Build Coastguard Worker
784*5e7646d2SAndroid Build Coastguard Worker cupsFileRewind(fp);
785*5e7646d2SAndroid Build Coastguard Worker }
786*5e7646d2SAndroid Build Coastguard Worker }
787*5e7646d2SAndroid Build Coastguard Worker else if (cs != PPDC_CS_UTF8)
788*5e7646d2SAndroid Build Coastguard Worker {
789*5e7646d2SAndroid Build Coastguard Worker if (cupsFileRead(fp, (char *)buffer, 2) != 2)
790*5e7646d2SAndroid Build Coastguard Worker return (0);
791*5e7646d2SAndroid Build Coastguard Worker }
792*5e7646d2SAndroid Build Coastguard Worker
793*5e7646d2SAndroid Build Coastguard Worker if (cs == PPDC_CS_UTF8)
794*5e7646d2SAndroid Build Coastguard Worker {
795*5e7646d2SAndroid Build Coastguard Worker // UTF-8 character...
796*5e7646d2SAndroid Build Coastguard Worker if ((ch = cupsFileGetChar(fp)) < 0)
797*5e7646d2SAndroid Build Coastguard Worker return (0);
798*5e7646d2SAndroid Build Coastguard Worker
799*5e7646d2SAndroid Build Coastguard Worker if ((ch & 0xe0) == 0xc0)
800*5e7646d2SAndroid Build Coastguard Worker {
801*5e7646d2SAndroid Build Coastguard Worker // Two-byte UTF-8...
802*5e7646d2SAndroid Build Coastguard Worker if (cupsFileRead(fp, (char *)buffer, 1) != 1)
803*5e7646d2SAndroid Build Coastguard Worker return (0);
804*5e7646d2SAndroid Build Coastguard Worker
805*5e7646d2SAndroid Build Coastguard Worker if ((buffer[0] & 0xc0) != 0x80)
806*5e7646d2SAndroid Build Coastguard Worker return (0);
807*5e7646d2SAndroid Build Coastguard Worker
808*5e7646d2SAndroid Build Coastguard Worker ch = ((ch & 0x1f) << 6) | (buffer[0] & 0x3f);
809*5e7646d2SAndroid Build Coastguard Worker }
810*5e7646d2SAndroid Build Coastguard Worker else if ((ch & 0xf0) == 0xe0)
811*5e7646d2SAndroid Build Coastguard Worker {
812*5e7646d2SAndroid Build Coastguard Worker // Three-byte UTF-8...
813*5e7646d2SAndroid Build Coastguard Worker if (cupsFileRead(fp, (char *)buffer, 2) != 2)
814*5e7646d2SAndroid Build Coastguard Worker return (0);
815*5e7646d2SAndroid Build Coastguard Worker
816*5e7646d2SAndroid Build Coastguard Worker if ((buffer[0] & 0xc0) != 0x80 ||
817*5e7646d2SAndroid Build Coastguard Worker (buffer[1] & 0xc0) != 0x80)
818*5e7646d2SAndroid Build Coastguard Worker return (0);
819*5e7646d2SAndroid Build Coastguard Worker
820*5e7646d2SAndroid Build Coastguard Worker ch = ((((ch & 0x0f) << 6) | (buffer[0] & 0x3f)) << 6) |
821*5e7646d2SAndroid Build Coastguard Worker (buffer[1] & 0x3f);
822*5e7646d2SAndroid Build Coastguard Worker }
823*5e7646d2SAndroid Build Coastguard Worker else if ((ch & 0xf8) == 0xf0)
824*5e7646d2SAndroid Build Coastguard Worker {
825*5e7646d2SAndroid Build Coastguard Worker // Four-byte UTF-8...
826*5e7646d2SAndroid Build Coastguard Worker if (cupsFileRead(fp, (char *)buffer, 3) != 3)
827*5e7646d2SAndroid Build Coastguard Worker return (0);
828*5e7646d2SAndroid Build Coastguard Worker
829*5e7646d2SAndroid Build Coastguard Worker if ((buffer[0] & 0xc0) != 0x80 ||
830*5e7646d2SAndroid Build Coastguard Worker (buffer[1] & 0xc0) != 0x80 ||
831*5e7646d2SAndroid Build Coastguard Worker (buffer[2] & 0xc0) != 0x80)
832*5e7646d2SAndroid Build Coastguard Worker return (0);
833*5e7646d2SAndroid Build Coastguard Worker
834*5e7646d2SAndroid Build Coastguard Worker ch = ((((((ch & 0x07) << 6) | (buffer[0] & 0x3f)) << 6) |
835*5e7646d2SAndroid Build Coastguard Worker (buffer[1] & 0x3f)) << 6) | (buffer[2] & 0x3f);
836*5e7646d2SAndroid Build Coastguard Worker }
837*5e7646d2SAndroid Build Coastguard Worker }
838*5e7646d2SAndroid Build Coastguard Worker else
839*5e7646d2SAndroid Build Coastguard Worker {
840*5e7646d2SAndroid Build Coastguard Worker // UTF-16 character...
841*5e7646d2SAndroid Build Coastguard Worker if (cs == PPDC_CS_UTF16BE)
842*5e7646d2SAndroid Build Coastguard Worker ch = (buffer[0] << 8) | buffer[1];
843*5e7646d2SAndroid Build Coastguard Worker else
844*5e7646d2SAndroid Build Coastguard Worker ch = (buffer[1] << 8) | buffer[0];
845*5e7646d2SAndroid Build Coastguard Worker
846*5e7646d2SAndroid Build Coastguard Worker if (ch >= 0xd800 && ch <= 0xdbff)
847*5e7646d2SAndroid Build Coastguard Worker {
848*5e7646d2SAndroid Build Coastguard Worker // Handle multi-word encoding...
849*5e7646d2SAndroid Build Coastguard Worker int lch;
850*5e7646d2SAndroid Build Coastguard Worker
851*5e7646d2SAndroid Build Coastguard Worker if (cupsFileRead(fp, (char *)buffer, 2) != 2)
852*5e7646d2SAndroid Build Coastguard Worker return (0);
853*5e7646d2SAndroid Build Coastguard Worker
854*5e7646d2SAndroid Build Coastguard Worker if (cs == PPDC_CS_UTF16BE)
855*5e7646d2SAndroid Build Coastguard Worker lch = (buffer[0] << 8) | buffer[1];
856*5e7646d2SAndroid Build Coastguard Worker else
857*5e7646d2SAndroid Build Coastguard Worker lch = (buffer[1] << 8) | buffer[0];
858*5e7646d2SAndroid Build Coastguard Worker
859*5e7646d2SAndroid Build Coastguard Worker if (lch < 0xdc00 || lch >= 0xdfff)
860*5e7646d2SAndroid Build Coastguard Worker return (0);
861*5e7646d2SAndroid Build Coastguard Worker
862*5e7646d2SAndroid Build Coastguard Worker ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
863*5e7646d2SAndroid Build Coastguard Worker }
864*5e7646d2SAndroid Build Coastguard Worker }
865*5e7646d2SAndroid Build Coastguard Worker
866*5e7646d2SAndroid Build Coastguard Worker return (ch);
867*5e7646d2SAndroid Build Coastguard Worker }
868*5e7646d2SAndroid Build Coastguard Worker
869*5e7646d2SAndroid Build Coastguard Worker
870*5e7646d2SAndroid Build Coastguard Worker //
871*5e7646d2SAndroid Build Coastguard Worker // 'put_utf8()' - Add a UTF-8 character to a string.
872*5e7646d2SAndroid Build Coastguard Worker //
873*5e7646d2SAndroid Build Coastguard Worker
874*5e7646d2SAndroid Build Coastguard Worker static int // O - 0 on success, -1 on failure
put_utf8(int ch,char * & ptr,char * end)875*5e7646d2SAndroid Build Coastguard Worker put_utf8(int ch, // I - Unicode character
876*5e7646d2SAndroid Build Coastguard Worker char *&ptr, // IO - String pointer
877*5e7646d2SAndroid Build Coastguard Worker char *end) // I - End of buffer
878*5e7646d2SAndroid Build Coastguard Worker {
879*5e7646d2SAndroid Build Coastguard Worker if (ch < 0x80)
880*5e7646d2SAndroid Build Coastguard Worker {
881*5e7646d2SAndroid Build Coastguard Worker // One-byte ASCII...
882*5e7646d2SAndroid Build Coastguard Worker if (ptr >= end)
883*5e7646d2SAndroid Build Coastguard Worker return (-1);
884*5e7646d2SAndroid Build Coastguard Worker
885*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)ch;
886*5e7646d2SAndroid Build Coastguard Worker }
887*5e7646d2SAndroid Build Coastguard Worker else if (ch < 0x800)
888*5e7646d2SAndroid Build Coastguard Worker {
889*5e7646d2SAndroid Build Coastguard Worker // Two-byte UTF-8...
890*5e7646d2SAndroid Build Coastguard Worker if ((ptr + 1) >= end)
891*5e7646d2SAndroid Build Coastguard Worker return (-1);
892*5e7646d2SAndroid Build Coastguard Worker
893*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)(0xc0 | (ch >> 6));
894*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)(0x80 | (ch & 0x3f));
895*5e7646d2SAndroid Build Coastguard Worker }
896*5e7646d2SAndroid Build Coastguard Worker else if (ch < 0x10000)
897*5e7646d2SAndroid Build Coastguard Worker {
898*5e7646d2SAndroid Build Coastguard Worker // Three-byte UTF-8...
899*5e7646d2SAndroid Build Coastguard Worker if ((ptr + 2) >= end)
900*5e7646d2SAndroid Build Coastguard Worker return (-1);
901*5e7646d2SAndroid Build Coastguard Worker
902*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)(0xe0 | (ch >> 12));
903*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)(0x80 | ((ch >> 6) & 0x3f));
904*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)(0x80 | (ch & 0x3f));
905*5e7646d2SAndroid Build Coastguard Worker }
906*5e7646d2SAndroid Build Coastguard Worker else
907*5e7646d2SAndroid Build Coastguard Worker {
908*5e7646d2SAndroid Build Coastguard Worker // Four-byte UTF-8...
909*5e7646d2SAndroid Build Coastguard Worker if ((ptr + 3) >= end)
910*5e7646d2SAndroid Build Coastguard Worker return (-1);
911*5e7646d2SAndroid Build Coastguard Worker
912*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)(0xf0 | (ch >> 18));
913*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)(0x80 | ((ch >> 12) & 0x3f));
914*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)(0x80 | ((ch >> 6) & 0x3f));
915*5e7646d2SAndroid Build Coastguard Worker *ptr++ = (char)(0x80 | (ch & 0x3f));
916*5e7646d2SAndroid Build Coastguard Worker }
917*5e7646d2SAndroid Build Coastguard Worker
918*5e7646d2SAndroid Build Coastguard Worker return (0);
919*5e7646d2SAndroid Build Coastguard Worker }
920*5e7646d2SAndroid Build Coastguard Worker
921*5e7646d2SAndroid Build Coastguard Worker
922*5e7646d2SAndroid Build Coastguard Worker //
923*5e7646d2SAndroid Build Coastguard Worker // 'put_utf16()' - Write a UTF-16 character to a file.
924*5e7646d2SAndroid Build Coastguard Worker //
925*5e7646d2SAndroid Build Coastguard Worker
926*5e7646d2SAndroid Build Coastguard Worker static int // O - 0 on success, -1 on failure
put_utf16(cups_file_t * fp,int ch)927*5e7646d2SAndroid Build Coastguard Worker put_utf16(cups_file_t *fp, // I - File to write to
928*5e7646d2SAndroid Build Coastguard Worker int ch) // I - Unicode character
929*5e7646d2SAndroid Build Coastguard Worker {
930*5e7646d2SAndroid Build Coastguard Worker unsigned char buffer[4]; // Output buffer
931*5e7646d2SAndroid Build Coastguard Worker
932*5e7646d2SAndroid Build Coastguard Worker
933*5e7646d2SAndroid Build Coastguard Worker if (ch < 0x10000)
934*5e7646d2SAndroid Build Coastguard Worker {
935*5e7646d2SAndroid Build Coastguard Worker // One-word UTF-16 big-endian...
936*5e7646d2SAndroid Build Coastguard Worker buffer[0] = (unsigned char)(ch >> 8);
937*5e7646d2SAndroid Build Coastguard Worker buffer[1] = (unsigned char)ch;
938*5e7646d2SAndroid Build Coastguard Worker
939*5e7646d2SAndroid Build Coastguard Worker if (cupsFileWrite(fp, (char *)buffer, 2) == 2)
940*5e7646d2SAndroid Build Coastguard Worker return (0);
941*5e7646d2SAndroid Build Coastguard Worker }
942*5e7646d2SAndroid Build Coastguard Worker else
943*5e7646d2SAndroid Build Coastguard Worker {
944*5e7646d2SAndroid Build Coastguard Worker // Two-word UTF-16 big-endian...
945*5e7646d2SAndroid Build Coastguard Worker ch -= 0x10000;
946*5e7646d2SAndroid Build Coastguard Worker
947*5e7646d2SAndroid Build Coastguard Worker buffer[0] = (unsigned char)(0xd8 | (ch >> 18));
948*5e7646d2SAndroid Build Coastguard Worker buffer[1] = (unsigned char)(ch >> 10);
949*5e7646d2SAndroid Build Coastguard Worker buffer[2] = (unsigned char)(0xdc | ((ch >> 8) & 0x03));
950*5e7646d2SAndroid Build Coastguard Worker buffer[3] = (unsigned char)ch;
951*5e7646d2SAndroid Build Coastguard Worker
952*5e7646d2SAndroid Build Coastguard Worker if (cupsFileWrite(fp, (char *)buffer, 4) == 4)
953*5e7646d2SAndroid Build Coastguard Worker return (0);
954*5e7646d2SAndroid Build Coastguard Worker }
955*5e7646d2SAndroid Build Coastguard Worker
956*5e7646d2SAndroid Build Coastguard Worker return (-1);
957*5e7646d2SAndroid Build Coastguard Worker }
958