Include libcharset into both the Timber and Halibut checkouts.
[sgt/charset] / fromucs.c
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 int stopped;
12 };
13
14 static void charset_emit(void *ctx, long int output)
15 {
16 struct charset_emit_param *param = (struct charset_emit_param *)ctx;
17
18 if (param->outlen > 0) {
19 *param->output++ = output;
20 param->outlen--;
21 } else {
22 param->stopped = 1;
23 }
24 }
25
26 int charset_from_unicode(const wchar_t **input, int *inlen,
27 char *output, int outlen,
28 int charset, charset_state *state, int *error)
29 {
30 charset_spec const *spec = charset_find_spec(charset);
31 charset_state localstate = CHARSET_INIT_STATE;
32 struct charset_emit_param param;
33 int locallen;
34
35 if (!input) {
36 locallen = 1;
37 inlen = &locallen;
38 }
39
40 param.output = output;
41 param.outlen = outlen;
42 param.stopped = 0;
43
44 if (state)
45 localstate = *state; /* structure copy */
46 if (error)
47 *error = FALSE;
48
49 while (*inlen > 0) {
50 int lenbefore = param.output - output;
51 int ret;
52
53 if (input)
54 ret = spec->write(spec, **input, &localstate,
55 charset_emit, &param);
56 else
57 ret = spec->write(spec, -1, &localstate, charset_emit, &param);
58 if (error && !ret) {
59 /*
60 * We have hit a difficult character, which the user
61 * wants to know about. Leave now.
62 */
63 *error = TRUE;
64 return lenbefore;
65 }
66 if (param.stopped) {
67 /*
68 * The emit function has _tried_ to output some
69 * characters, but ran up against the end of the
70 * buffer. Leave immediately, and return what happened
71 * _before_ attempting to process this character.
72 */
73 return lenbefore;
74 }
75 if (state)
76 *state = localstate; /* structure copy */
77 if (input)
78 (*input)++;
79 (*inlen)--;
80 }
81 return param.output - output;
82 }