iconv: Bail out of the loop when an illegal sequence of bytes occurs.
[elinks/elinks-j605.git] / src / intl / gettext / libintl.h
blob15d6804b8943d65fc18065b9e6d03428aaa7104d
2 #ifndef EL__INTL_GETTEXT_LIBINTL_H
3 #define EL__INTL_GETTEXT_LIBINTL_H
5 /* This header file provides an interface between ELinks and GNU libintl. I was
6 * astonished that there is no libintl.h but libgnuintl.h (and that name seemed
7 * ugly ;-), and I also decided that it will be better to introduce a clean
8 * interface instead of digging to libgnuintl.h too much. */
10 /* Contrary to a standard gettext interface, we pass destination charset and
11 * language (in form of struct terminal) directly with each call, allowing to
12 * easily multiplex between several terminals. */
14 #include "intl/gettext/libgettext.h"
16 #include "config/options.h"
17 #include "intl/charsets.h"
18 #include "terminal/terminal.h"
20 /* no-op - just for marking */
21 #define N_(msg) (gettext_noop(msg))
23 #ifndef CONFIG_SMALL
24 #define N__(msg) (gettext_noop(msg))
25 #else
26 #define N__(msg) (NULL)
27 #endif
30 /* The intl/gettext/libgettext.h header nukes gettext functions but not the _()
31 * function so make sure it is also just a noop when NLS is disabled. */
32 #ifndef CONFIG_NLS
34 /* In order to make it able to compile using -Werror this has to be a function
35 * so that local @term variables will not be reported as unused. */
36 static inline unsigned char *
37 _(unsigned char *msg, struct terminal *term)
39 return gettext_noop(msg);
42 static inline unsigned char *
43 n_(unsigned char *msg1, unsigned char *msg2, unsigned long int n, struct terminal *term)
45 return gettext_noop(msg1);
48 static inline void
49 intl_set_charset_by_index(int new_charset)
53 #else
55 /* The number of the charset to which the "elinks" domain was last
56 * bound with bind_textdomain_codeset(), or -1 if none yet. This
57 * cannot be a static variable in _(), because then it would get
58 * duplicated in every translation unit, even though the actual
59 * binding is global. */
60 extern int current_charset;
62 /* Define it to find redundant useless calls */
63 /* #define DEBUG_IT */
65 static inline void
66 intl_set_charset_by_index(int new_charset)
68 /* Prevent useless switching. */
69 if (current_charset != new_charset) {
70 bind_textdomain_codeset( /* PACKAGE */ "elinks",
71 get_cp_mime_name(new_charset));
72 current_charset = new_charset;
76 static inline void
77 intl_set_charset(struct terminal *term)
79 int new_charset = get_terminal_codepage(term);
81 intl_set_charset_by_index(new_charset);
84 /* TODO: Ideally, we should internally work only in Unicode - then the need for
85 * charsets multiplexing would cease. That'll take some work yet, though.
86 * --pasky */
88 #ifndef DEBUG_IT
90 /* Wraps around gettext(), employing charset multiplexing. If you don't care
91 * about charset (usually during initialization or when you don't use terminals
92 * at all), use gettext() directly. */
93 static inline unsigned char *
94 _(unsigned char *msg, struct terminal *term)
96 /* Prevent useless (and possibly dangerous) calls. */
97 if (!msg || !*msg)
98 return msg;
100 if (term) intl_set_charset(term);
102 return (unsigned char *) gettext(msg);
105 #else
107 #include "util/error.h"
109 /* This one will emit errors on null/empty msgs and when multiple calls are
110 * done for the same result in the same function. Some noise is possible,
111 * when a function is called twice or more, but then we should cache msg,
112 * in function caller. --Zas */
114 /* __FUNCTION__ isn't supported by all, but it's debugging code. */
115 #define _(m, t) __(__FILE__, __LINE__, __FUNCTION__, m, t)
117 /* Overflows are theorically possible here. Debug purpose only. */
118 static inline unsigned char *
119 __(unsigned char *file, unsigned int line, unsigned char *func,
120 unsigned char *msg, struct terminal *term)
122 static unsigned char last_file[512] = "";
123 static unsigned int last_line = 0;
124 static unsigned char last_func[1024] = "";
125 static unsigned char last_result[16384] = "";
126 unsigned char *result;
128 /* Prevent useless (and possibly dangerous) calls. */
129 if (!msg || !*msg) {
130 ERROR("%s:%u %s msg parameter", file, line, msg ? "empty": "NULL");
131 return msg;
134 if (term) intl_set_charset(term);
136 result = (unsigned char *) gettext(msg);
138 if (!strcmp(result, last_result)
139 && !strcmp(file, last_file)
140 && !strcmp(func, last_func)) {
141 ERROR("%s:%u Duplicate call to _() in %s() (previous at line %u)",
142 file, line, func, last_line);
145 /* Risky ;) */
146 strcpy(last_file, file);
147 strcpy(last_func, func);
148 strcpy(last_result, result);
149 last_line = line;
151 return result;
154 #endif
156 /* For plural handling. */
157 /* Wraps around ngettext(), employing charset multiplexing. If you don't care
158 * about charset (usually during initialization or when you don't use terminals
159 * at all), use ngettext() directly. */
160 static inline unsigned char *
161 n_(unsigned char *msg1, unsigned char *msg2, unsigned long int n, struct terminal *term)
163 /* Prevent useless (and possibly dangerous) calls. */
164 if (!msg1 || !*msg1)
165 return msg1;
167 if (term) intl_set_charset(term);
169 return (unsigned char *) ngettext(msg1, msg2, n);
173 /* Languages table lookups. */
175 struct language {
176 unsigned char *name;
177 unsigned char *iso639;
180 extern struct language languages[];
182 /* These two calls return 1 (english) if the code/name wasn't found. */
183 extern int name_to_language(const unsigned char *name);
184 extern int iso639_to_language(unsigned char *iso639);
186 extern unsigned char *language_to_name(int language);
187 extern unsigned char *language_to_iso639(int language);
189 extern int get_system_language_index(void);
191 /* The current state. The state should be initialized by a set_language(0)
192 * call. */
194 extern int current_language, system_language;
195 extern void set_language(int language);
197 #endif /* CONFIG_NLS */
199 #endif