OSDN Git Service

Enhance all settings encryption.
[ffftp/ffftp.git] / contrib / putty / CHARSET / FROMUCS.C
1 /*\r
2  * fromucs.c - convert Unicode to other character sets.\r
3  */\r
4 \r
5 #include "charset.h"\r
6 #include "internal.h"\r
7 \r
8 struct charset_emit_param {\r
9     char *output;\r
10     int outlen;\r
11     const char *errstr;\r
12     int errlen;\r
13     int stopped;\r
14 };\r
15 \r
16 static void charset_emit(void *ctx, long int output)\r
17 {\r
18     struct charset_emit_param *param = (struct charset_emit_param *)ctx;\r
19     char outval;\r
20     char const *p;\r
21     int outlen;\r
22 \r
23     if (output == ERROR) {\r
24         p = param->errstr;\r
25         outlen = param->errlen;\r
26     } else {\r
27         outval = output;\r
28         p = &outval;\r
29         outlen = 1;\r
30     }\r
31 \r
32     if (param->outlen >= outlen) {\r
33         while (outlen > 0) {\r
34             *param->output++ = *p++;\r
35             param->outlen--;\r
36             outlen--;\r
37         }\r
38     } else {\r
39         param->stopped = 1;\r
40     }\r
41 }\r
42 \r
43 int charset_from_unicode(const wchar_t **input, int *inlen,\r
44                          char *output, int outlen,\r
45                          int charset, charset_state *state,\r
46                          const char *errstr, int errlen)\r
47 {\r
48     charset_spec const *spec = charset_find_spec(charset);\r
49     charset_state localstate;\r
50     struct charset_emit_param param;\r
51 \r
52     param.output = output;\r
53     param.outlen = outlen;\r
54     param.stopped = 0;\r
55 \r
56     /*\r
57      * charset_emit will expect a valid errstr.\r
58      */\r
59     if (!errstr) {\r
60         /* *shrug* this is good enough, and consistent across all SBCS... */\r
61         param.errstr = ".";\r
62         param.errlen = 1;\r
63     }\r
64     param.errstr = errstr;\r
65     param.errlen = errlen;\r
66 \r
67     if (!state) {\r
68         localstate.s0 = 0;\r
69     } else {\r
70         localstate = *state;           /* structure copy */\r
71     }\r
72     state = &localstate;\r
73 \r
74     while (*inlen > 0) {\r
75         int lenbefore = param.output - output;\r
76         spec->write(spec, **input, &localstate, charset_emit, &param);\r
77         if (param.stopped) {\r
78             /*\r
79              * The emit function has _tried_ to output some\r
80              * characters, but ran up against the end of the\r
81              * buffer. Leave immediately, and return what happened\r
82              * _before_ attempting to process this character.\r
83              */\r
84             return lenbefore;\r
85         }\r
86         if (state)\r
87             *state = localstate;       /* structure copy */\r
88         (*input)++;\r
89         (*inlen)--;\r
90     }\r
91     return param.output - output;\r
92 }\r