OSDN Git Service

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