*** empty log message ***
[midnight-commander.git] / src / charsets.c
blob56102c0a047121505434dc79b86de59a52d7b830
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <config.h>
22 #ifdef HAVE_CHARSET
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <iconv.h>
28 #include "global.h"
29 #include "charsets.h"
31 int n_codepages = 0;
33 struct codepage_desc *codepages;
35 uchar conv_displ[256];
36 uchar conv_input[256];
38 int load_codepages_list(void)
40 int result = -1;
41 FILE *f;
42 char *fname;
43 char buf[256];
44 extern char* mc_home;
45 extern int display_codepage;
46 char * default_codepage = NULL;
48 fname = concat_dir_and_file (mc_home, CHARSETS_INDEX);
49 if ( !( f = fopen( fname, "r" ) ) ) {
50 fprintf (stderr, _("Warning: file %s not found\n"), fname);
51 g_free (fname);
52 return -1;
54 g_free (fname);
56 for ( n_codepages=0; fgets( buf, sizeof (buf), f ); )
57 if ( buf[0] != '\n' && buf[0] != '\0' && buf [0] != '#' )
58 ++n_codepages;
59 rewind( f );
61 codepages = g_new0 ( struct codepage_desc, n_codepages + 1 );
63 for( n_codepages = 0; fgets( buf, sizeof buf, f ); ) {
64 /* split string into id and cpname */
65 char *p = buf;
66 int buflen = strlen( buf );
68 if ( *p == '\n' || *p == '\0' || *p == '#')
69 continue;
71 if ( buflen > 0 && buf[ buflen - 1 ] == '\n' )
72 buf[ buflen - 1 ] = '\0';
73 while ( *p != '\t' && *p != ' ' && *p != '\0' )
74 ++p;
75 if ( *p == '\0' )
76 goto fail;
78 *p++ = 0;
80 while ( *p == '\t' || *p == ' ' )
81 ++p;
82 if ( *p == '\0' )
83 goto fail;
85 if (strcmp (buf, "default") == 0) {
86 default_codepage = g_strdup (p);
87 continue;
90 codepages[n_codepages].id = g_strdup( buf );
91 codepages[n_codepages].name = g_strdup( p );
92 ++n_codepages;
95 if (default_codepage) {
96 display_codepage = get_codepage_index (default_codepage);
97 g_free (default_codepage);
100 result = n_codepages;
101 fail:
102 fclose( f );
103 return result;
106 void free_codepages_list (void)
108 if (n_codepages > 0) {
109 int i;
110 for (i = 0; i < n_codepages; i++) {
111 g_free (codepages[i].id);
112 g_free (codepages[i].name);
114 n_codepages = 0;
115 g_free (codepages);
116 codepages = 0;
120 #define OTHER_8BIT "Other_8_bit"
122 char *get_codepage_id( int n )
124 return (n < 0) ? OTHER_8BIT : codepages[ n ].id;
127 int get_codepage_index( const char *id )
129 int i;
130 if (strcmp( id, OTHER_8BIT ) == 0)
131 return -1;
132 for ( i=0; codepages[ i ].id; ++i )
133 if (strcmp( id, codepages[ i ].id ) == 0)
134 return i;
135 return -1;
138 static char translate_character( iconv_t cd, char c )
140 char outbuf[4], *obuf;
141 size_t ibuflen, obuflen, count;
143 ICONV_CONST char *ibuf = &c;
144 obuf = outbuf;
145 ibuflen = 1; obuflen = 4;
147 count = iconv(cd, &ibuf, &ibuflen, &obuf, &obuflen);
148 if (count >= 0 && ibuflen == 0)
149 return outbuf[0];
151 return UNKNCHAR;
154 char errbuf[255];
157 * FIXME: This assumes that ASCII is always the first encoding
158 * in mc.charsets
160 #define CP_ASCII 0
162 char* init_translation_table( int cpsource, int cpdisplay )
164 int i;
165 iconv_t cd;
166 char *cpsour, *cpdisp;
168 /* Fill inpit <-> display tables */
170 if (cpsource < 0 || cpdisplay < 0 || cpsource == cpdisplay) {
171 for (i=0; i<=255; ++i) {
172 conv_displ[i] = i;
173 conv_input[i] = i;
175 return NULL;
178 for (i=0; i<=127; ++i) {
179 conv_displ[i] = i;
180 conv_input[i] = i;
183 cpsour = codepages[ cpsource ].id;
184 cpdisp = codepages[ cpdisplay ].id;
186 /* display <- inpit table */
188 cd = iconv_open( cpdisp, cpsour );
189 if (cd == (iconv_t) -1) {
190 sprintf( errbuf, _("Cannot translate from %s to %s"), cpsour, cpdisp );
191 return errbuf;
194 for (i=128; i<=255; ++i)
195 conv_displ[i] = translate_character( cd, i );
197 iconv_close( cd );
199 /* inpit <- display table */
201 cd = iconv_open( cpsour, cpdisp );
202 if (cd == (iconv_t) -1) {
203 sprintf( errbuf, _("Cannot translate from %s to %s"), cpdisp, cpsour );
204 return errbuf;
207 for (i=128; i<=255; ++i) {
208 uchar ch;
209 ch = translate_character( cd, i );
210 conv_input[i] = (ch == UNKNCHAR) ? i : ch;
213 iconv_close( cd );
215 return NULL;
218 void convert_to_display( char *str )
220 while ((*str = conv_displ[ (uchar) *str ]))
221 str++;
224 void convert_from_input( char *str )
226 while ((*str = conv_input[ (uchar) *str ]))
227 str++;
229 #endif /* HAVE_CHARSET */