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