2 /* Copyright (C) 2002 Olivier Chapuis */
3 /* This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 /* Some code (convert_charsets) inspired by the glib-2 (gutf8.c) copyrighted
19 * by Tom Tromey & Red Hat, Inc. */
21 /* ---------------------------- included header files ---------------------- */
29 #include "FlocaleCharset.h"
35 #if defined(USE_LIBICONV) && !defined (_LIBICONV_H)
36 #error libiconv in use but included iconv.h not from libiconv
38 #if !defined(USE_LIBICONV) && defined (_LIBICONV_H)
39 #error libiconv not in use but included iconv.h is from libiconv
41 #endif /* FiconvSupport */
43 /* ---------------------------- local definitions -------------------------- */
45 /* ---------------------------- local macros ------------------------------- */
47 /* ---------------------------- imports ------------------------------------ */
49 /* ---------------------------- included code files ------------------------ */
51 /* ---------------------------- local types -------------------------------- */
53 /* ---------------------------- forward declarations ----------------------- */
55 /* ---------------------------- local variables ---------------------------- */
57 static Bool FiconvInitialized
= False
;
58 static FlocaleCharset
*FLCIconvUtf8Charset
= NULL
; /* UTF-8 charset */
59 static FlocaleCharset
*FLCIconvDefaultCharset
= NULL
;
61 /* ---------------------------- exported variables (globals) --------------- */
63 /* ---------------------------- local functions ---------------------------- */
66 Bool
is_iconv_supported(char *c1
, char *c2
)
72 if (!FiconvSupport
|| !c1
|| !c2
)
75 cd1
= Ficonv_open(c1
, c2
);
76 cd2
= Ficonv_open(c2
, c1
);
77 if (cd1
!= (Ficonv_t
) -1 && cd2
!= (Ficonv_t
) -1)
79 if (cd1
!= (Ficonv_t
) -1)
80 dummy
= Ficonv_close(cd1
);
81 if (cd2
!= (Ficonv_t
) -1)
82 dummy
= Ficonv_close(cd2
);
87 int set_default_iconv_charsets(FlocaleCharset
*fc
)
91 if (!FiconvSupport
|| FLCIconvUtf8Charset
== NULL
|| fc
== NULL
)
94 while(FLC_GET_LOCALE_CHARSET(FLCIconvUtf8Charset
,i
) != NULL
)
97 while(FLC_GET_LOCALE_CHARSET(fc
,j
) != NULL
)
99 if (is_iconv_supported(
100 FLC_GET_LOCALE_CHARSET(
101 FLCIconvUtf8Charset
,i
),
102 FLC_GET_LOCALE_CHARSET(fc
,j
)))
104 FLC_SET_ICONV_INDEX(FLCIconvUtf8Charset
,i
);
105 FLC_SET_ICONV_INDEX(fc
,j
);
112 FLC_SET_ICONV_INDEX(FLCIconvUtf8Charset
,
113 FLC_INDEX_ICONV_CHARSET_NOT_FOUND
);
114 FLC_SET_ICONV_INDEX(fc
, FLC_INDEX_ICONV_CHARSET_NOT_FOUND
);
119 void set_iconv_charset_index(FlocaleCharset
*fc
)
123 if (!FiconvSupport
|| fc
== NULL
)
126 if (FLC_DO_ICONV_CHARSET_INITIALIZED(fc
))
127 return; /* already set */
128 if (FLCIconvUtf8Charset
== NULL
||
129 !FLC_DO_ICONV_CHARSET_INITIALIZED(FLCIconvUtf8Charset
))
131 FLC_SET_ICONV_INDEX(fc
, FLC_INDEX_ICONV_CHARSET_NOT_FOUND
);
134 while(FLC_GET_LOCALE_CHARSET(fc
,i
) != NULL
)
136 if (is_iconv_supported(
137 FLC_GET_ICONV_CHARSET(FLCIconvUtf8Charset
),
138 FLC_GET_LOCALE_CHARSET(fc
,i
)))
140 FLC_SET_ICONV_INDEX(fc
,i
);
145 FLC_SET_ICONV_INDEX(fc
, FLC_INDEX_ICONV_CHARSET_NOT_FOUND
);
149 char *convert_charsets(const char *in_charset
, const char *out_charset
,
150 const char *in
, unsigned int in_size
)
152 static int error_count
= 0;
157 size_t insize
,outbuf_size
,outbytes_remaining
,len
;
162 if (in
== NULL
|| !FiconvSupport
)
165 cd
= Ficonv_open(out_charset
, in_charset
);
166 if (cd
== (Ficonv_t
) -1)
168 /* Something went wrong. */
169 if (error_count
> FICONV_CONVERSION_MAX_NUMBER_OF_WARNING
)
176 "[fvwm][convert_charsets]: WARNING -\n\t");
179 "conversion from `%s' to `%s' not available\n",
180 in_charset
,out_charset
);
186 "[fvwm][convert_charsets]: WARNING -\n\t");
189 "conversion from `%s' to `%s' fail (init)\n",
190 in_charset
,out_charset
);
192 /* Terminate the output string. */
196 /* in maybe a none terminate string */
199 outbuf_size
= len
+ 1;
200 outbytes_remaining
= outbuf_size
- 1;
202 outp
= dest
= safemalloc(outbuf_size
);
206 for (is_finished
= 0; is_finished
== 0; )
209 cd
, (ICONV_ARG_CONST
char **)&inptr
, &insize
, &outp
,
210 &outbytes_remaining
);
212 if (nconv
== (size_t) - 1)
217 /* Incomplete text, do not report an error */
221 size_t used
= outp
- dest
;
224 dest
= realloc (dest
, outbuf_size
);
228 outbytes_remaining
= outbuf_size
- used
- 1;
234 /* Something went wrong. */
236 FICONV_CONVERSION_MAX_NUMBER_OF_WARNING
)
240 "[fvwm][convert_charsets]:"
244 "Invalid byte sequence during"
245 " conversion from %s to %s\n",
246 in_charset
,out_charset
);
253 FICONV_CONVERSION_MAX_NUMBER_OF_WARNING
)
257 "[fvwm][convert_charsets]:"
261 "Error during conversion from"
262 " %s to %s\n", in_charset
,
271 /* Terminate the output string */
274 if (Ficonv_close (cd
) != 0)
278 "[fvwm][convert_charsets]: WARNING - iconv_close"
295 void FiconvInit(Display
*dpy
, const char *module
)
299 if (!FiconvSupport
|| FiconvInitialized
)
302 FiconvInitialized
= True
;
303 FlocaleCharsetInit(dpy
, module
);
304 FLCIconvUtf8Charset
= FlocaleCharsetGetUtf8Charset();
305 FLCIconvDefaultCharset
= FlocaleCharsetGetFLCXOMCharset();
307 suc
= set_default_iconv_charsets(FLCIconvDefaultCharset
);
310 FLCIconvDefaultCharset
= FlocaleCharsetGetLocaleCharset();
311 suc
= set_default_iconv_charsets(FLCIconvDefaultCharset
);
316 "[%s][FiconvInit]: WARN -- Cannot get default "
317 "iconv charset for default charsets '%s' and '%s'\n",
319 FLC_DEBUG_GET_X_CHARSET(
320 FlocaleCharsetGetFLCXOMCharset()),
321 FLC_DEBUG_GET_X_CHARSET(FLCIconvDefaultCharset
));
322 FLCIconvUtf8Charset
= NULL
;
323 FLCIconvDefaultCharset
= NULL
;
326 #if FLOCALE_DEBUG_CHARSET
327 fprintf(stderr
,"[FiconvInit] iconv charset: x:%s, iconv:%s\n",
328 FLC_DEBUG_GET_X_CHARSET(FLCIconvDefaultCharset
),
329 FLC_DEBUG_GET_ICONV_CHARSET(FLCIconvDefaultCharset
));
330 fprintf(stderr
,"[FiconvInit] UTF-8 charset: x:%s, iconv:%s\n",
331 FLC_DEBUG_GET_X_CHARSET(FLCIconvUtf8Charset
),
332 FLC_DEBUG_GET_ICONV_CHARSET(FLCIconvUtf8Charset
));
338 FlocaleCharset
*FiconvSetupConversion(Display
*dpy
, FlocaleCharset
*fc
)
340 FlocaleCharset
*my_fc
= NULL
;
347 if (!FiconvInitialized
)
349 FiconvInit(dpy
, "fvwm");
352 if (FLCIconvUtf8Charset
== NULL
)
359 my_fc
= FLCIconvDefaultCharset
;
370 if (!FLC_DO_ICONV_CHARSET_INITIALIZED(my_fc
))
372 set_iconv_charset_index(my_fc
);
373 #if FLOCALE_DEBUG_CHARSET
374 fprintf(stderr
, "[Flocale] set up iconv charset: "
375 "x: %s, iconv: %s\n",
376 FLC_DEBUG_GET_X_CHARSET(my_fc
),
377 FLC_DEBUG_GET_ICONV_CHARSET(my_fc
));
379 if (!FLC_HAVE_ICONV_CHARSET(my_fc
))
383 "[fvwmlibs] cannot get iconv converter "
385 FLC_DEBUG_GET_X_CHARSET(my_fc
));
389 if (!FLC_HAVE_ICONV_CHARSET(my_fc
))
397 /* ---------------------------- interface functions ------------------------ */
399 /* conversion from UTF8 to the "current" charset */
400 char *FiconvUtf8ToCharset(Display
*dpy
, FlocaleCharset
*fc
,
401 const char *in
, unsigned int in_size
)
404 FlocaleCharset
*my_fc
= NULL
;
411 my_fc
= FiconvSetupConversion(dpy
, fc
);
417 #if FLOCALE_DEBUG_ICONV
418 fprintf(stderr
, "[FiconvUtf8ToCharset] conversion from %s to %s\n",
419 FLC_DEBUG_GET_ICONV_CHARSET(FLCIconvUtf8Charset
),
420 FLC_DEBUG_GET_ICONV_CHARSET(my_fc
));
423 if (FLC_ENCODING_TYPE_IS_UTF_8(my_fc
))
425 /* in can be a none terminate string so do not use CopyString
427 out
= safemalloc(in_size
+1);
428 strncpy(out
, in
, in_size
);
433 out
= convert_charsets(
434 FLC_GET_ICONV_CHARSET(FLCIconvUtf8Charset
),
435 FLC_GET_ICONV_CHARSET(my_fc
),
442 /* conversion from the current charset to UTF8 */
443 char *FiconvCharsetToUtf8(Display
*dpy
, FlocaleCharset
*fc
,
444 const char *in
, unsigned int in_size
)
447 FlocaleCharset
*my_fc
= NULL
;
454 my_fc
= FiconvSetupConversion(dpy
, fc
);
460 #if FLOCALE_DEBUG_ICONV
461 fprintf(stderr
, "[FiconvCharsetToUtf8] conversion from %s to %s\n",
462 FLC_DEBUG_GET_ICONV_CHARSET(my_fc
),
463 FLC_DEBUG_GET_ICONV_CHARSET(FLCIconvUtf8Charset
));
466 if (FLC_ENCODING_TYPE_IS_UTF_8(my_fc
))
468 /* in can be a non terminate string so do not use CopyString */
469 out
= safemalloc(in_size
+1);
470 strncpy(out
, in
, in_size
);
475 out
= convert_charsets(
476 FLC_GET_ICONV_CHARSET(my_fc
),
477 FLC_GET_ICONV_CHARSET(FLCIconvUtf8Charset
),
483 /* conversion from charset to charset */
484 char *FiconvCharsetToCharset(
485 Display
*dpy
, FlocaleCharset
*in_fc
, FlocaleCharset
*out_fc
,
486 const char *in
, unsigned int in_size
)
491 Bool free_tmp
= False
;
492 FlocaleCharset
*my_in_fc
;
493 FlocaleCharset
*my_out_fc
;
495 if (!FiconvSupport
||
496 (my_in_fc
= FiconvSetupConversion(dpy
, in_fc
)) == NULL
)
500 if (!FiconvSupport
||
501 (my_out_fc
= FiconvSetupConversion(dpy
, out_fc
)) == NULL
)
508 if (!FLC_ENCODING_TYPE_IS_UTF_8(my_in_fc
))
510 tmp
= FiconvCharsetToUtf8(
511 dpy
, my_in_fc
, (const char *)in
, in_size
);
515 tmp_len
= strlen(tmp
);
519 /* fail to convert */
525 if (!FLC_ENCODING_TYPE_IS_UTF_8(my_out_fc
))
527 out
= FiconvUtf8ToCharset(
528 dpy
, my_out_fc
, (const char *)tmp
, tmp_len
);