Highlight selected item of WRadio using widget width not item width.
[pantumic.git] / src / charsets.c
blob8b3e8d5a35086eb903f2d02eedde8bfb72c00a44
1 /* Text conversion from one charset to another.
3 Copyright (C) 2001 Walery Studennikov <despair@sama.ru>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 /** \file charsets.c
21 * \brief Source: Text conversion from one charset to another
24 #include <config.h>
26 #ifdef HAVE_CHARSET
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
32 #include "lib/global.h"
33 #include "lib/strutil.h" /* utf-8 functions */
34 #include "lib/fileloc.h"
36 #include "charsets.h"
37 #include "main.h"
39 int n_codepages = 0;
41 struct codepage_desc *codepages;
43 unsigned char conv_displ[256];
44 unsigned char conv_input[256];
46 const char *cp_display = NULL;
47 const char *cp_source = NULL;
50 int
51 load_codepages_list (void)
53 int result = -1;
54 FILE *f;
55 char *fname;
56 char buf[BUF_MEDIUM];
57 char *default_codepage = NULL;
59 fname = concat_dir_and_file (mc_home, CHARSETS_INDEX);
60 f = fopen (fname, "r");
61 if (f == NULL) {
62 fprintf (stderr, _("Warning: file %s not found\n"), fname);
63 g_free (fname);
65 fname = concat_dir_and_file (mc_home_alt, CHARSETS_INDEX);
66 f = fopen (fname, "r");
67 if (f == NULL) {
68 fprintf (stderr, _("Warning: file %s not found\n"), fname);
69 g_free (fname);
71 /* file is not found, add defaullt codepage */
72 n_codepages = 1;
73 codepages = g_new0 (struct codepage_desc, n_codepages + 1);
74 codepages[0].id = g_strdup ("ASCII");
75 codepages[0].name = g_strdup (_("7-bit ASCII"));
76 return n_codepages;
79 g_free (fname);
81 for (n_codepages = 0; fgets (buf, sizeof (buf), f);)
82 if (buf[0] != '\n' && buf[0] != '\0' && buf[0] != '#')
83 ++n_codepages;
84 rewind (f);
86 codepages = g_new0 (struct codepage_desc, n_codepages + 1);
88 for (n_codepages = 0; fgets (buf, sizeof buf, f);) {
89 /* split string into id and cpname */
90 char *p = buf;
91 size_t buflen = strlen (buf);
93 if (*p == '\n' || *p == '\0' || *p == '#')
94 continue;
96 if (buflen > 0 && buf[buflen - 1] == '\n')
97 buf[buflen - 1] = '\0';
98 while (*p != '\t' && *p != ' ' && *p != '\0')
99 ++p;
100 if (*p == '\0')
101 goto fail;
103 *p++ = '\0';
104 g_strstrip (p);
105 if (*p == '\0')
106 goto fail;
108 if (strcmp (buf, "default") == 0)
109 default_codepage = g_strdup (p);
110 else {
111 codepages[n_codepages].id = g_strdup (buf);
112 codepages[n_codepages].name = g_strdup (p);
113 ++n_codepages;
117 if (default_codepage != NULL) {
118 display_codepage = get_codepage_index (default_codepage);
119 g_free (default_codepage);
122 result = n_codepages;
123 fail:
124 fclose (f);
125 return result;
128 void
129 free_codepages_list (void)
131 if (n_codepages > 0) {
132 int i;
133 for (i = 0; i < n_codepages; i++) {
134 g_free (codepages[i].id);
135 g_free (codepages[i].name);
137 n_codepages = 0;
138 g_free (codepages);
139 codepages = 0;
143 #define OTHER_8BIT "Other_8_bit"
145 const char *
146 get_codepage_id (const int n)
148 return (n < 0) ? OTHER_8BIT : codepages[n].id;
152 get_codepage_index (const char *id)
154 int i;
155 if (strcmp (id, OTHER_8BIT) == 0)
156 return -1;
157 if (codepages == NULL)
158 return -1;
159 for (i = 0; i < n_codepages; i++)
160 if (strcmp (id, codepages[i].id) == 0)
161 return i;
162 return -1;
165 /** Check if specified encoding can be used in mc.
166 * @param encoding name of encoding
167 * @returns TRUE if encoding has supported by mc, FALSE otherwise
169 gboolean
170 is_supported_encoding (const char *encoding)
172 gboolean result = FALSE;
173 size_t t;
175 for (t = 0; t < (size_t) n_codepages; t++)
176 result |= (g_ascii_strncasecmp (encoding, codepages[t].id,
177 strlen (codepages[t].id)) == 0);
179 return result;
182 static char
183 translate_character (GIConv cd, char c)
185 gchar *tmp_buff = NULL;
186 gsize bytes_read, bytes_written = 0;
187 const char *ibuf = &c;
188 char ch = UNKNCHAR;
190 int ibuflen = 1;
192 tmp_buff = g_convert_with_iconv (ibuf, ibuflen, cd, &bytes_read, &bytes_written, NULL);
193 if ( tmp_buff )
194 ch = tmp_buff[0];
195 g_free (tmp_buff);
196 return ch;
200 * FIXME: This assumes that ASCII is always the first encoding
201 * in mc.charsets
203 #define CP_ASCII 0
205 char *
206 init_translation_table (int cpsource, int cpdisplay)
208 int i;
209 GIConv cd;
211 /* Fill inpit <-> display tables */
213 if (cpsource < 0 || cpdisplay < 0 || cpsource == cpdisplay) {
214 for (i = 0; i <= 255; ++i) {
215 conv_displ[i] = i;
216 conv_input[i] = i;
217 cp_source = cp_display;
219 return NULL;
222 for (i = 0; i <= 127; ++i) {
223 conv_displ[i] = i;
224 conv_input[i] = i;
226 cp_source = (char *) codepages[cpsource].id;
227 cp_display = (char *) codepages[cpdisplay].id;
229 /* display <- inpit table */
231 cd = g_iconv_open (cp_display, cp_source);
232 if (cd == INVALID_CONV)
233 return g_strdup_printf (_("Cannot translate from %s to %s"), cp_source, cp_display);
235 for (i = 128; i <= 255; ++i)
236 conv_displ[i] = translate_character (cd, i);
238 g_iconv_close (cd);
240 /* inpit <- display table */
242 cd = g_iconv_open (cp_source, cp_display);
243 if (cd == INVALID_CONV)
244 return g_strdup_printf (_("Cannot translate from %s to %s"), cp_display, cp_source);
246 for (i = 128; i <= 255; ++i) {
247 unsigned char ch;
248 ch = translate_character (cd, i);
249 conv_input[i] = (ch == UNKNCHAR) ? i : ch;
252 g_iconv_close (cd);
254 return NULL;
257 void
258 convert_to_display (char *str)
260 if (!str)
261 return;
263 while (*str) {
264 *str = conv_displ[(unsigned char) *str];
265 str++;
269 GString *
270 str_convert_to_display (char *str)
272 return str_nconvert_to_display (str, -1);
276 GString *
277 str_nconvert_to_display (char *str, int len)
279 GString *buff;
280 GIConv conv;
282 if (!str)
283 return g_string_new("");
285 if (cp_display == cp_source)
286 return g_string_new(str);
288 conv = str_crt_conv_from (cp_source);
290 buff = g_string_new("");
291 str_nconvert (conv, str, len, buff);
292 str_close_conv (conv);
293 return buff;
296 void
297 convert_from_input (char *str)
299 if (!str)
300 return;
302 while (*str) {
303 *str = conv_input[(unsigned char) *str];
304 str++;
308 GString *
309 str_convert_to_input (char *str)
311 return str_nconvert_to_input (str, -1);
314 GString *
315 str_nconvert_to_input (char *str, int len)
317 GString *buff;
318 GIConv conv;
320 if (!str)
321 return g_string_new("");
323 if (cp_display == cp_source)
324 return g_string_new(str);
326 conv = str_crt_conv_to (cp_source);
328 buff = g_string_new("");
329 str_nconvert (conv, str, len, buff);
330 str_close_conv (conv);
331 return buff;
334 unsigned char
335 convert_from_utf_to_current (const char *str)
337 unsigned char buf_ch[6 + 1];
338 unsigned char ch = '.';
339 GIConv conv;
340 const char *cp_to;
342 if (!str)
343 return '.';
345 cp_to = get_codepage_id ( source_codepage );
346 conv = str_crt_conv_to ( cp_to );
348 if (conv != INVALID_CONV) {
349 switch (str_translate_char (conv, str, -1, (char *)buf_ch, sizeof(buf_ch))) {
350 case ESTR_SUCCESS:
351 ch = buf_ch[0];
352 break;
353 case ESTR_PROBLEM:
354 case ESTR_FAILURE:
355 ch = '.';
356 break;
358 str_close_conv (conv);
361 return ch;
365 unsigned char
366 convert_from_utf_to_current_c (const int input_char, GIConv conv)
368 unsigned char str[6 + 1];
369 unsigned char buf_ch[6 + 1];
370 unsigned char ch = '.';
372 int res = 0;
374 res = g_unichar_to_utf8 (input_char, (char *)str);
375 if ( res == 0 ) {
376 return ch;
378 str[res] = '\0';
380 switch (str_translate_char (conv, (char *)str, -1, (char *)buf_ch, sizeof(buf_ch))) {
381 case ESTR_SUCCESS:
382 ch = buf_ch[0];
383 break;
384 case ESTR_PROBLEM:
385 case ESTR_FAILURE:
386 ch = '.';
387 break;
389 return ch;
393 convert_from_8bit_to_utf_c (const char input_char, GIConv conv)
395 unsigned char str[2];
396 unsigned char buf_ch[6 + 1];
397 int ch = '.';
398 int res = 0;
400 str[0] = (unsigned char) input_char;
401 str[1] = '\0';
403 switch (str_translate_char (conv, (char *)str, -1, (char *)buf_ch, sizeof(buf_ch))) {
404 case ESTR_SUCCESS:
405 res = g_utf8_get_char_validated ((char *)buf_ch, -1);
406 if ( res < 0 ) {
407 ch = buf_ch[0];
408 } else {
409 ch = res;
411 break;
412 case ESTR_PROBLEM:
413 case ESTR_FAILURE:
414 ch = '.';
415 break;
417 return ch;
421 convert_from_8bit_to_utf_c2 (const char input_char)
423 unsigned char str[2];
424 unsigned char buf_ch[6 + 1];
425 int ch = '.';
426 int res = 0;
427 GIConv conv;
428 const char *cp_from;
430 str[0] = (unsigned char) input_char;
431 str[1] = '\0';
433 cp_from = get_codepage_id ( source_codepage );
434 conv = str_crt_conv_to (cp_from);
436 if (conv != INVALID_CONV) {
437 switch (str_translate_char (conv, (char *) str, -1, (char *) buf_ch, sizeof(buf_ch))) {
438 case ESTR_SUCCESS:
439 res = g_utf8_get_char_validated ((char *) buf_ch, -1);
440 if ( res < 0 ) {
441 ch = buf_ch[0];
442 } else {
443 ch = res;
445 break;
446 case ESTR_PROBLEM:
447 case ESTR_FAILURE:
448 ch = '.';
449 break;
451 str_close_conv (conv);
453 return ch;
456 #endif /* HAVE_CHARSET */