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