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