chiark / gitweb /
*** empty log message ***
[sympathy.git] / src / utf8.c
1 /*
2  * utf8.c:
3  *
4  * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
5  * All rights reserved.
6  *
7  */
8
9 static char rcsid[] = "$Id$";
10
11 /*
12  * $Log$
13  * Revision 1.9  2008/02/27 01:31:14  james
14  * *** empty log message ***
15  *
16  * Revision 1.8  2008/02/27 00:54:16  james
17  * *** empty log message ***
18  *
19  * Revision 1.7  2008/02/26 23:56:12  james
20  * *** empty log message ***
21  *
22  * Revision 1.6  2008/02/26 23:23:17  james
23  * *** empty log message ***
24  *
25  * Revision 1.5  2008/02/24 00:42:53  james
26  * *** empty log message ***
27  *
28  * Revision 1.4  2008/02/23 13:05:58  staffcvs
29  * *** empty log message ***
30  *
31  * Revision 1.3  2008/02/23 11:48:37  james
32  * *** empty log message ***
33  *
34  * Revision 1.2  2008/02/22 23:39:27  james
35  * *** empty log message ***
36  *
37  * Revision 1.1  2008/02/22 19:12:05  james
38  * *** empty log message ***
39  *
40  */
41
42 #include "project.h"
43
44
45 void
46 utf8_flush (Context * c)
47 {
48   UTF8 *u = c->u;
49   int i;
50
51   switch (u->utf_ptr)
52     {
53     case 1:
54       log_f (c->l, "<invalid utf-8 sequence: \\%03o>", u->utf_buf[0]);
55       break;
56     case 2:
57       log_f (c->l, "<invalid utf-8 sequence: \\%03o \\%03o>",
58              u->utf_buf[0], u->utf_buf[1]);
59       break;
60     case 3:
61       log_f (c->l, "<invalid utf-8 sequence: \\%03o \\%03o \\%03o>",
62              u->utf_buf[0], u->utf_buf[1], u->utf_buf[2]);
63       break;
64     case 4:
65       log_f (c->l,
66              "<invalid utf-8 sequence: \\%03o \\%03o \\%03o \\%03o>",
67              u->utf_buf[0], u->utf_buf[1], u->utf_buf[2], u->utf_buf[3]);
68       break;
69     }
70
71   for (i = 0; i < u->utf_ptr; ++i)
72     vt102_parse_char (c, u->utf_buf[i]);
73
74   u->utf_ptr = 0;
75   u->in_utf8 = 0;
76 }
77
78 void
79 utf8_parse (Context * c, uint32_t ch)
80 {
81   UTF8 *u = c->u;
82
83   if (ch == SYM_CHAR_RESET)
84     {
85       u->in_utf8 = 0;
86       vt102_parse_char (c, ch);
87       return;
88     }
89
90   if (!u->in_utf8)
91     {
92       /*FIXME: for the moment we bodge utf8 support - need to do */
93       /* L->R and R->L and double width characters */
94       if (ch == 0xb9)
95         {                       /*CSI, not a valid utf8 start char */
96           vt102_parse_char (c, ch);
97         }
98       else if ((ch & 0xe0) == 0xc0)
99         {                       /*Start of two byte unicode sequence */
100           u->in_utf8 = 1;
101           u->utf_ptr = 0;
102           u->utf_buf[u->utf_ptr++] = ch;
103           u->ch = (ch & 0x1f) << 6;
104           u->sh = 0;
105         }
106       else if ((ch & 0xf0) == 0xe0)
107         {                       /*Start of three byte unicode sequence */
108           u->in_utf8 = 2;
109           u->utf_ptr = 0;
110           u->utf_buf[u->utf_ptr++] = ch;
111           u->ch = (ch & 0x0f) << 12;
112           u->sh = 6;
113         }
114       else if ((ch & 0xf8) == 0xf0)
115         {
116           u->in_utf8 = 3;
117           u->utf_ptr = 0;
118           u->utf_buf[u->utf_ptr++] = ch;
119           u->ch = (ch & 0x07) << 18;
120           u->sh = 12;
121         }
122       else
123         {
124           vt102_parse_char (c, ch);
125         }
126     }
127   else
128     {
129       if ((ch & 0xc0) != 0x80)
130         {
131           utf8_flush (c);
132           vt102_parse_char (c, ch);
133         }
134       else
135         {
136           u->utf_buf[u->utf_ptr++] = ch;
137           u->ch |= (ch & 0x3f) << u->sh;
138           u->sh -= 6;
139           u->in_utf8--;
140
141           if (!u->in_utf8)
142             vt102_parse_char (c, u->ch);
143         }
144     }
145 }
146
147
148
149 UTF8 *
150 utf8_new (void)
151 {
152   UTF8 *ret;
153
154   ret = (UTF8 *) malloc (sizeof (UTF8));
155
156   ret->in_utf8 = 0;
157
158 }
159
160 int
161 utf8_encode (char *ptr, int ch)
162 {
163
164   if (ch < 0x80)
165     {
166       ptr[0] = ch;
167       return 1;
168     }
169   else if (ch < 0x800)
170     {
171       ptr[0] = 0xc0 | (ch >> 6);
172       ptr[1] = 0x80 | (ch & 0x3f);
173       return 2;
174     }
175   else if (ch < 0x10000)
176     {
177       ptr[0] = 0xe0 | (ch >> 12);
178       ptr[1] = 0x80 | ((ch >> 6) & 0x3f);
179       ptr[2] = 0x80 | (ch & 0x3f);
180       return 3;
181     }
182   else if (ch < 0x1fffff)
183     {
184       ptr[0] = 0xf0 | (ch >> 18);
185       ptr[1] = 0x80 | ((ch >> 12) & 0x3f);
186       ptr[2] = 0x80 | ((ch >> 6) & 0x3f);
187       ptr[3] = 0x80 | (ch & 0x3f);
188       return 4;
189     }
190   return 0;
191 }
192
193 void
194 utf8_emit (TTY * t, int ch)
195 {
196   uint8_t buf[4];
197   int i;
198   i = utf8_encode (buf, ch);
199   if (!i)
200     return;
201
202   t->xmit (t, buf, i);
203 }