*** empty log message ***
[midnight-commander.git] / src / charsets.c
blob83a3f63ee1f588d6832eab5b75352ad25aef6ee7
1 #include <config.h>
3 #ifdef HAVE_CHARSET
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <iconv.h>
9 #include "global.h"
10 #include "charsets.h"
12 int n_codepages = 0;
14 struct codepage_desc *codepages;
16 uchar conv_displ[256];
17 uchar conv_input[256];
19 int load_codepages_list(void)
21 int result = -1;
22 FILE *f;
23 char *fname;
24 char buf[256];
25 extern char* mc_home;
26 extern int display_codepage;
27 char * default_codepage = NULL;
29 fname = concat_dir_and_file (mc_home, CHARSETS_INDEX);
30 if ( !( f = fopen( fname, "r" ) ) ) {
31 fprintf (stderr, _("Warning: file %s not found\n"), fname);
32 g_free (fname);
33 return -1;
35 g_free (fname);
37 for ( n_codepages=0; fgets( buf, sizeof (buf), f ); )
38 if ( buf[0] != '\n' && buf[0] != '\0' && buf [0] != '#' )
39 ++n_codepages;
40 rewind( f );
42 codepages = g_new0 ( struct codepage_desc, n_codepages + 1 );
44 for( n_codepages = 0; fgets( buf, sizeof buf, f ); ) {
45 /* split string into id and cpname */
46 char *p = buf;
47 int buflen = strlen( buf );
49 if ( *p == '\n' || *p == '\0' || *p == '#')
50 continue;
52 if ( buflen > 0 && buf[ buflen - 1 ] == '\n' )
53 buf[ buflen - 1 ] = '\0';
54 while ( *p != '\t' && *p != ' ' && *p != '\0' )
55 ++p;
56 if ( *p == '\0' )
57 goto fail;
59 *p++ = 0;
61 while ( *p == '\t' || *p == ' ' )
62 ++p;
63 if ( *p == '\0' )
64 goto fail;
66 if (strcmp (buf, "default") == 0) {
67 default_codepage = g_strdup (p);
68 continue;
71 codepages[n_codepages].id = g_strdup( buf );
72 codepages[n_codepages].name = g_strdup( p );
73 ++n_codepages;
76 if (default_codepage) {
77 display_codepage = get_codepage_index (default_codepage);
78 g_free (default_codepage);
81 result = n_codepages;
82 fail:
83 fclose( f );
84 return result;
87 void free_codepages_list (void)
89 if (n_codepages > 0) {
90 int i;
91 for (i = 0; i < n_codepages; i++) {
92 g_free (codepages[i].id);
93 g_free (codepages[i].name);
95 n_codepages = 0;
96 g_free (codepages);
97 codepages = 0;
101 #define OTHER_8BIT "Other_8_bit"
103 char *get_codepage_id( int n )
105 return (n < 0) ? OTHER_8BIT : codepages[ n ].id;
108 int get_codepage_index( const char *id )
110 int i;
111 if (strcmp( id, OTHER_8BIT ) == 0)
112 return -1;
113 for ( i=0; codepages[ i ].id; ++i )
114 if (strcmp( id, codepages[ i ].id ) == 0)
115 return i;
116 return -1;
119 static char translate_character( iconv_t cd, char c )
121 char outbuf[4], *obuf;
122 size_t ibuflen, obuflen, count;
124 ICONV_CONST char *ibuf = &c;
125 obuf = outbuf;
126 ibuflen = 1; obuflen = 4;
128 count = iconv(cd, &ibuf, &ibuflen, &obuf, &obuflen);
129 if (count >= 0 && ibuflen == 0)
130 return outbuf[0];
132 return UNKNCHAR;
135 char errbuf[255];
138 * FIXME: This assumes that ASCII is always the first encoding
139 * in mc.charsets
141 #define CP_ASCII 0
143 char* init_translation_table( int cpsource, int cpdisplay )
145 int i;
146 iconv_t cd;
147 char *cpsour, *cpdisp;
149 /* Fill inpit <-> display tables */
151 if (cpsource < 0 || cpdisplay < 0 || cpsource == cpdisplay) {
152 for (i=0; i<=255; ++i) {
153 conv_displ[i] = i;
154 conv_input[i] = i;
156 return NULL;
159 for (i=0; i<=127; ++i) {
160 conv_displ[i] = i;
161 conv_input[i] = i;
164 cpsour = codepages[ cpsource ].id;
165 cpdisp = codepages[ cpdisplay ].id;
167 /* display <- inpit table */
169 cd = iconv_open( cpdisp, cpsour );
170 if (cd == (iconv_t) -1) {
171 sprintf( errbuf, _("Cannot translate from %s to %s"), cpsour, cpdisp );
172 return errbuf;
175 for (i=128; i<=255; ++i)
176 conv_displ[i] = translate_character( cd, i );
178 iconv_close( cd );
180 /* inpit <- display table */
182 cd = iconv_open( cpsour, cpdisp );
183 if (cd == (iconv_t) -1) {
184 sprintf( errbuf, _("Cannot translate from %s to %s"), cpdisp, cpsour );
185 return errbuf;
188 for (i=128; i<=255; ++i) {
189 uchar ch;
190 ch = translate_character( cd, i );
191 conv_input[i] = (ch == UNKNCHAR) ? i : ch;
194 iconv_close( cd );
196 return NULL;
199 void convert_to_display( char *str )
201 while ((*str = conv_displ[ (uchar) *str ]))
202 str++;
205 void convert_from_input( char *str )
207 while ((*str = conv_input[ (uchar) *str ]))
208 str++;
210 #endif /* HAVE_CHARSET */