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