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