]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - charset/toucs.c
First draft of Unicode support in pterm. It's pretty complete: it
[PuTTY.git] / charset / toucs.c
1 /*
2  * toucs.c - convert charsets to Unicode.
3  */
4
5 #include "charset.h"
6 #include "internal.h"
7
8 struct unicode_emit_param {
9     wchar_t *output;
10     int outlen;
11     const wchar_t *errstr;
12     int errlen;
13     int stopped;
14 };
15
16 static void unicode_emit(void *ctx, long int output)
17 {
18     struct unicode_emit_param *param = (struct unicode_emit_param *)ctx;
19     wchar_t outval;
20     wchar_t const *p;
21     int outlen;
22
23     if (output == ERROR) {
24         if (param->errstr) {
25             p = param->errstr;
26             outlen = param->errlen;
27         } else {
28             outval = 0xFFFD;           /* U+FFFD REPLACEMENT CHARACTER */
29             p = &outval;
30             outlen = 1;
31         }
32     } else {
33         outval = output;
34         p = &outval;
35         outlen = 1;
36     }
37
38     if (param->outlen >= outlen) {
39         while (outlen > 0) {
40             *param->output++ = *p++;
41             param->outlen--;
42             outlen--;
43         }
44     } else {
45         param->stopped = 1;
46     }
47 }
48
49 int charset_to_unicode(char **input, int *inlen, wchar_t *output, int outlen,
50                        int charset, charset_state *state,
51                        const wchar_t *errstr, int errlen)
52 {
53     charset_spec const *spec = charset_find_spec(charset);
54     charset_state localstate;
55     struct unicode_emit_param param;
56
57     param.output = output;
58     param.outlen = outlen;
59     param.errstr = errstr;
60     param.errlen = errlen;
61     param.stopped = 0;
62
63     if (!state) {
64         localstate.s0 = 0;
65     } else {
66         localstate = *state;           /* structure copy */
67     }
68
69     while (*inlen > 0) {
70         int lenbefore = param.output - output;
71         spec->read(spec, (unsigned char)**input, &localstate,
72                    unicode_emit, &param);
73         if (param.stopped) {
74             /*
75              * The emit function has _tried_ to output some
76              * characters, but ran up against the end of the
77              * buffer. Leave immediately, and return what happened
78              * _before_ attempting to process this character.
79              */
80             return lenbefore;
81         }
82         if (state)
83             *state = localstate;   /* structure copy */
84         (*input)++;
85         (*inlen)--;
86     }
87
88     return param.output - output;
89 }