ca69b73ec31998b62fa4194ff9bdf5f1cc7ab2f4
[silc.git] / apps / irssi / src / core / recode.c
1 /*
2  recode.c : irssi
3
4     Copyright (C) 1999-2000 Timo Sirainen
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License along
17     with this program; if not, write to the Free Software Foundation, Inc.,
18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "module.h"
22 #include "settings.h"
23 #include "servers.h"
24 #include "signals.h"
25 #include "lib-config/iconfig.h"
26 #include "misc.h"
27
28 static char *translit_charset;
29 static gboolean term_is_utf8;
30
31 gboolean is_utf8(void)
32 {
33         return term_is_utf8;
34 }
35
36 static gboolean is_translit(const char *charset)
37 {
38         char *pos;
39
40         pos = stristr(charset, "//translit");
41         return (pos != NULL);
42 }
43
44 gboolean is_valid_charset(const char *charset)
45 {
46         GIConv cd;
47         char *to = NULL;
48
49         if (!charset || *charset == '\0')
50                 return FALSE;
51
52         if (settings_get_bool("recode_transliterate") && !is_translit(charset))
53                 charset = to = g_strconcat(charset, "//TRANSLIT", NULL);
54
55         cd = g_iconv_open(charset, "UTF-8");
56         g_free(to);
57         if (cd != (GIConv)-1) {
58                 g_iconv_close(cd);
59                 return TRUE;
60         }
61         return FALSE;
62 }
63
64 static char *find_conversion(const SERVER_REC *server, const char *target)
65 {
66         char *conv = NULL;
67
68         if (server != NULL && target != NULL) {
69                 char *tagtarget = g_strdup_printf("%s/%s", server->tag, target);
70                 conv = iconfig_get_str("conversions", tagtarget, NULL);
71                 g_free(tagtarget);
72         }
73         if (conv == NULL && target != NULL)
74                 conv = iconfig_get_str("conversions", target, NULL);
75         if (conv == NULL && server != NULL)
76                 conv = iconfig_get_str("conversions", server->tag, NULL);
77         return conv;
78 }
79
80 static int str_is_ascii(const char *str)
81 {
82         int i;
83
84         for (i = 0; str[i] != '\0'; i++)
85                 if (str[i] & 0x80)
86                         return 0;
87         return 1;
88 }
89
90 char *recode_in(const SERVER_REC *server, const char *str, const char *target)
91 {
92         const char *from = NULL;
93         const char *to = translit_charset;
94         char *recoded = NULL;
95         gboolean str_is_utf8, recode, autodetect;
96         int len;
97
98         if (!str)
99                 return NULL;
100
101         recode = settings_get_bool("recode");
102         if (!recode)
103                 return g_strdup(str);
104
105         len = strlen(str);
106
107         /* Only validate for UTF-8 if an 8-bit encoding. */
108         str_is_utf8 = 0;
109         if (!str_is_ascii(str))
110                 str_is_utf8 = g_utf8_validate(str, len, NULL);
111         else if (!strchr(str, '\e'))
112                 str_is_utf8 = 1;
113         autodetect = settings_get_bool("recode_autodetect_utf8");
114
115         if (autodetect && str_is_utf8)
116                 if (term_is_utf8)
117                         return g_strdup(str);
118                 else
119                         from = "UTF-8";
120         else
121                 from = find_conversion(server, target);
122
123         if (from)
124                 recoded = g_convert_with_fallback(str, len, to, from, NULL, NULL, NULL, NULL);
125
126         if (!recoded) {
127                 if (str_is_utf8)
128                         if (term_is_utf8)
129                                 return g_strdup(str);
130                         else
131                                 from = "UTF-8";
132                 else
133                         if (term_is_utf8)
134                                 from = settings_get_str("recode_fallback");
135                         else
136                                 from = NULL;
137
138                 if (from)
139                         recoded = g_convert_with_fallback(str, len, to, from, NULL, NULL, NULL, NULL);
140
141                 if (!recoded)
142                         recoded = g_strdup(str);
143         }
144         return recoded;
145 }
146
147 char *recode_out(const SERVER_REC *server, const char *str, const char *target)
148 {
149         char *recoded = NULL;
150         const char *from = translit_charset;
151         const char *to = NULL;
152         char *translit_to = NULL;
153         gboolean translit, recode;
154         int len;
155
156         if (!str)
157                 return NULL;
158
159         recode = settings_get_bool("recode");
160         if (!recode)
161                 return g_strdup(str);
162
163         len = strlen(str);
164
165         translit = settings_get_bool("recode_transliterate");
166
167         to = find_conversion(server, target);
168         if (to == NULL)
169                 /* default outgoing charset if set */
170                 to = settings_get_str("recode_out_default_charset");
171
172         if (to && *to != '\0') {
173                 if (translit && !is_translit(to))
174                         to = translit_to = g_strconcat(to ,"//TRANSLIT", NULL);
175
176                 recoded = g_convert(str, len, to, from, NULL, NULL, NULL);
177         }
178         g_free(translit_to);
179         if (!recoded)
180                 recoded = g_strdup(str);
181
182         return recoded;
183 }
184
185 void recode_update_charset(void)
186 {
187         const char *charset = settings_get_str("term_charset");
188         term_is_utf8 = !g_ascii_strcasecmp(charset, "UTF-8");
189         g_free(translit_charset);
190         if (settings_get_bool("recode_transliterate") && !is_translit(charset))
191                 translit_charset = g_strconcat(charset, "//TRANSLIT", NULL);
192         else
193                 translit_charset = g_strdup(charset);
194 }
195
196 void recode_init(void)
197 {
198         settings_add_bool("misc", "recode", TRUE);
199         settings_add_str("misc", "recode_fallback", "CP1252");
200         settings_add_str("misc", "recode_out_default_charset", "");
201         settings_add_bool("misc", "recode_transliterate", TRUE);
202         settings_add_bool("misc", "recode_autodetect_utf8", TRUE);
203 }
204
205 void recode_deinit(void)
206 {
207         g_free(translit_charset);
208 }