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"
36 #if defined(USE_LIBICONV) && !defined (_LIBICONV_H)
37 #error libiconv in use but included iconv.h not from libiconv
39 #if !defined(USE_LIBICONV) && defined (_LIBICONV_H)
40 #error libiconv not in use but included iconv.h is from libiconv
42 #endif /* FiconvSupport */
44 /* ---------------------------- local definitions -------------------------- */
46 /* ---------------------------- local macros ------------------------------- */
48 /* ---------------------------- imports ------------------------------------ */
50 /* ---------------------------- included code files ------------------------ */
52 /* ---------------------------- local types -------------------------------- */
54 /* ---------------------------- forward declarations ----------------------- */
56 /* ---------------------------- local variables ---------------------------- */
58 static Bool FiconvInitialized
= False
;
59 static FlocaleCharset
*FLCIconvUtf8Charset
= NULL
; /* UTF-8 charset */
60 static FlocaleCharset
*FLCIconvDefaultCharset
= NULL
;
61 static int do_transliterate_utf8
= 0;
63 /* ---------------------------- exported variables (globals) --------------- */
65 /* ---------------------------- local functions ---------------------------- */
68 Bool
is_iconv_supported(char *c1
, char *c2
)
74 if (!FiconvSupport
|| !c1
|| !c2
)
77 cd1
= Ficonv_open(c1
, c2
);
78 cd2
= Ficonv_open(c2
, c1
);
79 if (cd1
!= (Ficonv_t
) -1 && cd2
!= (Ficonv_t
) -1)
81 if (cd1
!= (Ficonv_t
) -1)
82 dummy
= Ficonv_close(cd1
);
83 if (cd2
!= (Ficonv_t
) -1)
84 dummy
= Ficonv_close(cd2
);
88 #define TRANSLIT_SUFFIX "//TRANSLIT"
90 char *translit_csname(char *cs
)
92 return CatString2(cs
, TRANSLIT_SUFFIX
);
96 int is_translit_supported(char *c1
, char *c2
)
100 if (!FiconvSupport
|| !c1
|| !c2
)
103 cd
= Ficonv_open(translit_csname(c1
),c2
);
104 if (cd
== (Ficonv_t
) -1)
109 cd
= Ficonv_open(translit_csname(c2
),c1
);
110 if (cd
== (Ficonv_t
) -1)
120 int set_default_iconv_charsets(FlocaleCharset
*fc
)
124 if (!FiconvSupport
|| FLCIconvUtf8Charset
== NULL
|| fc
== NULL
)
127 while(FLC_GET_LOCALE_CHARSET(FLCIconvUtf8Charset
,i
) != NULL
)
130 while(FLC_GET_LOCALE_CHARSET(fc
,j
) != NULL
)
132 if (is_iconv_supported(
133 FLC_GET_LOCALE_CHARSET(
134 FLCIconvUtf8Charset
,i
),
135 FLC_GET_LOCALE_CHARSET(fc
,j
)))
137 FLC_SET_ICONV_INDEX(FLCIconvUtf8Charset
,i
);
138 FLC_SET_ICONV_INDEX(fc
,j
);
140 if (is_translit_supported(
141 FLC_GET_LOCALE_CHARSET(
142 FLCIconvUtf8Charset
,i
),
143 FLC_GET_LOCALE_CHARSET(fc
,j
)))
145 FLC_SET_ICONV_TRANSLIT_CHARSET(
146 fc
, safestrdup(translit_csname(
147 FLC_GET_LOCALE_CHARSET(
150 FLC_SET_ICONV_TRANSLIT_CHARSET(
151 fc
, FLC_TRANSLIT_NOT_SUPPORTED
);
160 FLC_SET_ICONV_INDEX(FLCIconvUtf8Charset
,
161 FLC_INDEX_ICONV_CHARSET_NOT_FOUND
);
162 FLC_SET_ICONV_INDEX(fc
, FLC_INDEX_ICONV_CHARSET_NOT_FOUND
);
167 void set_iconv_charset_index(FlocaleCharset
*fc
)
171 if (!FiconvSupport
|| fc
== NULL
)
174 if (FLC_DO_ICONV_CHARSET_INITIALIZED(fc
))
175 return; /* already set */
176 if (FLCIconvUtf8Charset
== NULL
||
177 !FLC_DO_ICONV_CHARSET_INITIALIZED(FLCIconvUtf8Charset
))
179 FLC_SET_ICONV_INDEX(fc
, FLC_INDEX_ICONV_CHARSET_NOT_FOUND
);
182 while(FLC_GET_LOCALE_CHARSET(fc
,i
) != NULL
)
184 if (is_iconv_supported(
185 FLC_GET_ICONV_CHARSET(FLCIconvUtf8Charset
),
186 FLC_GET_LOCALE_CHARSET(fc
,i
)))
188 FLC_SET_ICONV_INDEX(fc
,i
);
189 if (is_translit_supported(
190 FLC_GET_ICONV_CHARSET(FLCIconvUtf8Charset
),
191 FLC_GET_LOCALE_CHARSET(fc
,i
)))
193 FLC_SET_ICONV_TRANSLIT_CHARSET(
196 FLC_GET_LOCALE_CHARSET(
199 FLC_SET_ICONV_TRANSLIT_CHARSET(
200 fc
, FLC_TRANSLIT_NOT_SUPPORTED
);
206 FLC_SET_ICONV_INDEX(fc
, FLC_INDEX_ICONV_CHARSET_NOT_FOUND
);
210 char *convert_charsets(const char *in_charset
, const char *out_charset
,
211 const char *in
, unsigned int in_size
)
213 static int error_count
= 0;
218 size_t insize
,outbuf_size
,outbytes_remaining
,len
;
223 if (in
== NULL
|| !FiconvSupport
)
226 cd
= Ficonv_open(out_charset
, in_charset
);
227 if (cd
== (Ficonv_t
) -1)
229 /* Something went wrong. */
230 if (error_count
> FICONV_CONVERSION_MAX_NUMBER_OF_WARNING
)
237 "[fvwm][convert_charsets]: WARNING -\n\t");
240 "conversion from `%s' to `%s' not available\n",
241 in_charset
,out_charset
);
247 "[fvwm][convert_charsets]: WARNING -\n\t");
250 "conversion from `%s' to `%s' fail (init)\n",
251 in_charset
,out_charset
);
253 /* Terminate the output string. */
257 /* in maybe a none terminate string */
260 outbuf_size
= len
+ 1;
261 outbytes_remaining
= outbuf_size
- 1;
263 outp
= dest
= safemalloc(outbuf_size
);
267 for (is_finished
= 0; is_finished
== 0; )
270 cd
, (ICONV_ARG_CONST
char **)&inptr
, &insize
, &outp
,
271 &outbytes_remaining
);
273 if (nconv
== (size_t) - 1)
278 /* Incomplete text, do not report an error */
282 size_t used
= outp
- dest
;
285 dest
= realloc (dest
, outbuf_size
);
289 outbytes_remaining
= outbuf_size
- used
- 1;
295 /* Something went wrong. */
297 FICONV_CONVERSION_MAX_NUMBER_OF_WARNING
)
301 "[fvwm][convert_charsets]:"
305 "Invalid byte sequence during"
306 " conversion from %s to %s\n",
307 in_charset
,out_charset
);
314 FICONV_CONVERSION_MAX_NUMBER_OF_WARNING
)
318 "[fvwm][convert_charsets]:"
322 "Error during conversion from"
323 " %s to %s\n", in_charset
,
332 /* Terminate the output string */
335 if (Ficonv_close (cd
) != 0)
339 "[fvwm][convert_charsets]: WARNING - iconv_close"
356 void FiconvInit(Display
*dpy
, const char *module
)
360 if (!FiconvSupport
|| FiconvInitialized
)
363 FiconvInitialized
= True
;
364 FlocaleCharsetInit(dpy
, module
);
365 FLCIconvUtf8Charset
= FlocaleCharsetGetUtf8Charset();
366 FLCIconvDefaultCharset
= FlocaleCharsetGetFLCXOMCharset();
368 suc
= set_default_iconv_charsets(FLCIconvDefaultCharset
);
371 FLCIconvDefaultCharset
= FlocaleCharsetGetLocaleCharset();
372 suc
= set_default_iconv_charsets(FLCIconvDefaultCharset
);
377 "[%s][FiconvInit]: WARN -- Cannot get default "
378 "iconv charset for default charsets '%s' and '%s'\n",
380 FLC_DEBUG_GET_X_CHARSET(
381 FlocaleCharsetGetFLCXOMCharset()),
382 FLC_DEBUG_GET_X_CHARSET(FLCIconvDefaultCharset
));
383 FLCIconvUtf8Charset
= NULL
;
384 FLCIconvDefaultCharset
= NULL
;
387 #if FLOCALE_DEBUG_CHARSET
388 fprintf(stderr
,"[FiconvInit] iconv charset: x:%s, iconv:%s\n",
389 FLC_DEBUG_GET_X_CHARSET(FLCIconvDefaultCharset
),
390 FLC_DEBUG_GET_ICONV_CHARSET(FLCIconvDefaultCharset
));
391 fprintf(stderr
,"[FiconvInit] UTF-8 charset: x:%s, iconv:%s\n",
392 FLC_DEBUG_GET_X_CHARSET(FLCIconvUtf8Charset
),
393 FLC_DEBUG_GET_ICONV_CHARSET(FLCIconvUtf8Charset
));
399 FlocaleCharset
*FiconvSetupConversion(Display
*dpy
, FlocaleCharset
*fc
)
401 FlocaleCharset
*my_fc
= NULL
;
408 if (!FiconvInitialized
)
410 FiconvInit(dpy
, "fvwm");
413 if (FLCIconvUtf8Charset
== NULL
)
420 my_fc
= FLCIconvDefaultCharset
;
431 if (!FLC_DO_ICONV_CHARSET_INITIALIZED(my_fc
))
433 set_iconv_charset_index(my_fc
);
434 #if FLOCALE_DEBUG_CHARSET
435 fprintf(stderr
, "[Flocale] set up iconv charset: "
436 "x: %s, iconv: %s\n",
437 FLC_DEBUG_GET_X_CHARSET(my_fc
),
438 FLC_DEBUG_GET_ICONV_CHARSET(my_fc
));
440 if (!FLC_HAVE_ICONV_CHARSET(my_fc
))
444 "[fvwmlibs] cannot get iconv converter "
446 FLC_DEBUG_GET_X_CHARSET(my_fc
));
450 if (!FLC_HAVE_ICONV_CHARSET(my_fc
))
458 /* ---------------------------- interface functions ------------------------ */
460 /* set transliteration state */
461 void FiconvSetTransliterateUtf8(int toggle
)
466 do_transliterate_utf8
^= 1;
470 do_transliterate_utf8
= toggle
;
473 do_transliterate_utf8
= 0;
479 /* conversion from UTF8 to the "current" charset */
480 char *FiconvUtf8ToCharset(Display
*dpy
, FlocaleCharset
*fc
,
481 const char *in
, unsigned int in_size
)
484 FlocaleCharset
*my_fc
= NULL
;
491 my_fc
= FiconvSetupConversion(dpy
, fc
);
497 #if FLOCALE_DEBUG_ICONV
498 fprintf(stderr
, "[FiconvUtf8ToCharset] conversion from %s to %s\n",
499 FLC_DEBUG_GET_ICONV_CHARSET(FLCIconvUtf8Charset
),
500 FLC_DEBUG_GET_ICONV_CHARSET(my_fc
));
503 if (FLC_ENCODING_TYPE_IS_UTF_8(my_fc
))
505 /* in can be a none terminate string so do not use CopyString
507 out
= safemalloc(in_size
+1);
508 strncpy(out
, in
, in_size
);
514 if (do_transliterate_utf8
&& FLC_IS_TRANSLIT_SUPPORTED(my_fc
))
516 to_cs
= FLC_GET_ICONV_TRANSLIT_CHARSET(my_fc
);
520 to_cs
= FLC_GET_ICONV_CHARSET(my_fc
);
522 out
= convert_charsets(
523 FLC_GET_ICONV_CHARSET(FLCIconvUtf8Charset
),
531 /* conversion from the current charset to UTF8 */
532 char *FiconvCharsetToUtf8(Display
*dpy
, FlocaleCharset
*fc
,
533 const char *in
, unsigned int in_size
)
536 FlocaleCharset
*my_fc
= NULL
;
543 my_fc
= FiconvSetupConversion(dpy
, fc
);
549 #if FLOCALE_DEBUG_ICONV
550 fprintf(stderr
, "[FiconvCharsetToUtf8] conversion from %s to %s\n",
551 FLC_DEBUG_GET_ICONV_CHARSET(my_fc
),
552 FLC_DEBUG_GET_ICONV_CHARSET(FLCIconvUtf8Charset
));
555 if (FLC_ENCODING_TYPE_IS_UTF_8(my_fc
))
557 /* in can be a non terminate string so do not use CopyString */
558 out
= safemalloc(in_size
+1);
559 strncpy(out
, in
, in_size
);
564 out
= convert_charsets(
565 FLC_GET_ICONV_CHARSET(my_fc
),
566 FLC_GET_ICONV_CHARSET(FLCIconvUtf8Charset
),
572 /* conversion from charset to charset */
573 char *FiconvCharsetToCharset(
574 Display
*dpy
, FlocaleCharset
*in_fc
, FlocaleCharset
*out_fc
,
575 const char *in
, unsigned int in_size
)
580 Bool free_tmp
= False
;
581 FlocaleCharset
*my_in_fc
;
582 FlocaleCharset
*my_out_fc
;
584 if (!FiconvSupport
||
585 (my_in_fc
= FiconvSetupConversion(dpy
, in_fc
)) == NULL
)
589 if (!FiconvSupport
||
590 (my_out_fc
= FiconvSetupConversion(dpy
, out_fc
)) == NULL
)
597 if (!FLC_ENCODING_TYPE_IS_UTF_8(my_in_fc
))
599 tmp
= FiconvCharsetToUtf8(
600 dpy
, my_in_fc
, (const char *)in
, in_size
);
604 tmp_len
= strlen(tmp
);
608 /* fail to convert */
614 if (!FLC_ENCODING_TYPE_IS_UTF_8(my_out_fc
))
616 out
= FiconvUtf8ToCharset(
617 dpy
, my_out_fc
, (const char *)tmp
, tmp_len
);