1/*
2 * Localized printf/puts functions for CUPS.
3 *
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 2002-2007 by Easy Software Products.
6 *
7 * These coded instructions, statements, and computer programs are the
8 * property of Apple Inc. and are protected by Federal copyright
9 * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
10 * which should have been included with this file.  If this file is
11 * missing or damaged, see the license at "http://www.cups.org/".
12 *
13 * This file is subject to the Apple OS-Developed Software exception.
14 */
15
16/*
17 * Include necessary headers...
18 */
19
20#include "cups-private.h"
21
22
23/*
24 * '_cupsLangPrintError()' - Print a message followed by a standard error.
25 */
26
27void
28_cupsLangPrintError(const char *prefix,	/* I - Non-localized message prefix */
29                    const char *message)/* I - Message */
30{
31  ssize_t	bytes;			/* Number of bytes formatted */
32  int		last_errno;		/* Last error */
33  char		buffer[2048],		/* Message buffer */
34		*bufptr,		/* Pointer into buffer */
35		output[8192];		/* Output buffer */
36  _cups_globals_t *cg;			/* Global data */
37
38
39 /*
40  * Range check...
41  */
42
43  if (!message)
44    return;
45
46 /*
47  * Save the errno value...
48  */
49
50  last_errno = errno;
51
52 /*
53  * Get the message catalog...
54  */
55
56  cg = _cupsGlobals();
57
58  if (!cg->lang_default)
59    cg->lang_default = cupsLangDefault();
60
61 /*
62  * Format the message...
63  */
64
65  if (prefix)
66  {
67    snprintf(buffer, sizeof(buffer), "%s:", prefix);
68    bufptr = buffer + strlen(buffer);
69  }
70  else
71    bufptr = buffer;
72
73  snprintf(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer),
74	   /* TRANSLATORS: Message is "subject: error" */
75	   _cupsLangString(cg->lang_default, _("%s: %s")),
76	   _cupsLangString(cg->lang_default, message), strerror(last_errno));
77  strlcat(buffer, "\n", sizeof(buffer));
78
79 /*
80  * Convert and write to stderr...
81  */
82
83  bytes = cupsUTF8ToCharset(output, (cups_utf8_t *)buffer, sizeof(output),
84                            cg->lang_default->encoding);
85
86  if (bytes > 0)
87    fwrite(output, 1, (size_t)bytes, stderr);
88}
89
90
91/*
92 * '_cupsLangPrintFilter()' - Print a formatted filter message string to a file.
93 */
94
95int					/* O - Number of bytes written */
96_cupsLangPrintFilter(
97    FILE       *fp,			/* I - File to write to */
98    const char *prefix,			/* I - Non-localized message prefix */
99    const char *message,		/* I - Message string to use */
100    ...)				/* I - Additional arguments as needed */
101{
102  ssize_t	bytes;			/* Number of bytes formatted */
103  char		temp[2048],		/* Temporary format buffer */
104		buffer[2048],		/* Message buffer */
105		output[8192];		/* Output buffer */
106  va_list 	ap;			/* Pointer to additional arguments */
107  _cups_globals_t *cg;			/* Global data */
108
109
110 /*
111  * Range check...
112  */
113
114  if (!fp || !message)
115    return (-1);
116
117  cg = _cupsGlobals();
118
119  if (!cg->lang_default)
120    cg->lang_default = cupsLangDefault();
121
122 /*
123  * Format the string...
124  */
125
126  va_start(ap, message);
127  snprintf(temp, sizeof(temp), "%s: %s\n", prefix,
128	   _cupsLangString(cg->lang_default, message));
129  vsnprintf(buffer, sizeof(buffer), temp, ap);
130  va_end(ap);
131
132 /*
133  * Transcode to the destination charset...
134  */
135
136  bytes = cupsUTF8ToCharset(output, (cups_utf8_t *)buffer, sizeof(output),
137                            cg->lang_default->encoding);
138
139 /*
140  * Write the string and return the number of bytes written...
141  */
142
143  if (bytes > 0)
144    return ((int)fwrite(output, 1, (size_t)bytes, fp));
145  else
146    return ((int)bytes);
147}
148
149
150/*
151 * '_cupsLangPrintf()' - Print a formatted message string to a file.
152 */
153
154int					/* O - Number of bytes written */
155_cupsLangPrintf(FILE       *fp,		/* I - File to write to */
156		const char *message,	/* I - Message string to use */
157	        ...)			/* I - Additional arguments as needed */
158{
159  ssize_t	bytes;			/* Number of bytes formatted */
160  char		buffer[2048],		/* Message buffer */
161		output[8192];		/* Output buffer */
162  va_list 	ap;			/* Pointer to additional arguments */
163  _cups_globals_t *cg;			/* Global data */
164
165
166 /*
167  * Range check...
168  */
169
170  if (!fp || !message)
171    return (-1);
172
173  cg = _cupsGlobals();
174
175  if (!cg->lang_default)
176    cg->lang_default = cupsLangDefault();
177
178 /*
179  * Format the string...
180  */
181
182  va_start(ap, message);
183  vsnprintf(buffer, sizeof(buffer) - 1,
184	    _cupsLangString(cg->lang_default, message), ap);
185  va_end(ap);
186
187  strlcat(buffer, "\n", sizeof(buffer));
188
189 /*
190  * Transcode to the destination charset...
191  */
192
193  bytes = cupsUTF8ToCharset(output, (cups_utf8_t *)buffer, sizeof(output),
194                            cg->lang_default->encoding);
195
196 /*
197  * Write the string and return the number of bytes written...
198  */
199
200  if (bytes > 0)
201    return ((int)fwrite(output, 1, (size_t)bytes, fp));
202  else
203    return ((int)bytes);
204}
205
206
207/*
208 * '_cupsLangPuts()' - Print a static message string to a file.
209 */
210
211int					/* O - Number of bytes written */
212_cupsLangPuts(FILE       *fp,		/* I - File to write to */
213              const char *message)	/* I - Message string to use */
214{
215  ssize_t	bytes;			/* Number of bytes formatted */
216  char		output[8192];		/* Message buffer */
217  _cups_globals_t *cg;			/* Global data */
218
219
220 /*
221  * Range check...
222  */
223
224  if (!fp || !message)
225    return (-1);
226
227  cg = _cupsGlobals();
228
229  if (!cg->lang_default)
230    cg->lang_default = cupsLangDefault();
231
232 /*
233  * Transcode to the destination charset...
234  */
235
236  bytes = cupsUTF8ToCharset(output,
237			    (cups_utf8_t *)_cupsLangString(cg->lang_default,
238							   message),
239			    sizeof(output) - 4, cg->lang_default->encoding);
240  bytes += cupsUTF8ToCharset(output + bytes, (cups_utf8_t *)"\n", (int)(sizeof(output) - (size_t)bytes), cg->lang_default->encoding);
241
242 /*
243  * Write the string and return the number of bytes written...
244  */
245
246  if (bytes > 0)
247    return ((int)fwrite(output, 1, (size_t)bytes, fp));
248  else
249    return ((int)bytes);
250}
251
252
253/*
254 * '_cupsSetLocale()' - Set the current locale and transcode the command-line.
255 */
256
257void
258_cupsSetLocale(char *argv[])		/* IO - Command-line arguments */
259{
260  int		i;			/* Looping var */
261  char		buffer[8192];		/* Command-line argument buffer */
262  _cups_globals_t *cg;			/* Global data */
263#ifdef LC_TIME
264  const char	*lc_time;		/* Current LC_TIME value */
265  char		new_lc_time[255],	/* New LC_TIME value */
266		*charset;		/* Pointer to character set */
267#endif /* LC_TIME */
268
269
270 /*
271  * Set the locale so that times, etc. are displayed properly.
272  *
273  * Unfortunately, while we need the localized time value, we *don't*
274  * want to use the localized charset for the time value, so we need
275  * to set LC_TIME to the locale name with .UTF-8 on the end (if
276  * the locale includes a character set specifier...)
277  */
278
279  setlocale(LC_ALL, "");
280
281#ifdef LC_TIME
282  if ((lc_time = setlocale(LC_TIME, NULL)) == NULL)
283    lc_time = setlocale(LC_ALL, NULL);
284
285  if (lc_time)
286  {
287    strlcpy(new_lc_time, lc_time, sizeof(new_lc_time));
288    if ((charset = strchr(new_lc_time, '.')) == NULL)
289      charset = new_lc_time + strlen(new_lc_time);
290
291    strlcpy(charset, ".UTF-8", sizeof(new_lc_time) - (size_t)(charset - new_lc_time));
292  }
293  else
294    strlcpy(new_lc_time, "C", sizeof(new_lc_time));
295
296  setlocale(LC_TIME, new_lc_time);
297#endif /* LC_TIME */
298
299 /*
300  * Initialize the default language info...
301  */
302
303  cg = _cupsGlobals();
304
305  if (!cg->lang_default)
306    cg->lang_default = cupsLangDefault();
307
308 /*
309  * Transcode the command-line arguments from the locale charset to
310  * UTF-8...
311  */
312
313  if (cg->lang_default->encoding != CUPS_US_ASCII &&
314      cg->lang_default->encoding != CUPS_UTF8)
315  {
316    for (i = 1; argv[i]; i ++)
317    {
318     /*
319      * Try converting from the locale charset to UTF-8...
320      */
321
322      if (cupsCharsetToUTF8((cups_utf8_t *)buffer, argv[i], sizeof(buffer),
323                            cg->lang_default->encoding) < 0)
324        continue;
325
326     /*
327      * Save the new string if it differs from the original...
328      */
329
330      if (strcmp(buffer, argv[i]))
331        argv[i] = strdup(buffer);
332    }
333  }
334}
335