]> git.lyx.org Git - lyx.git/blob - 3rdparty/libiconv/1.15/lib/cp1258.h
Implement auto-nesting.
[lyx.git] / 3rdparty / libiconv / 1.15 / lib / cp1258.h
1 /*
2  * Copyright (C) 1999-2001, 2004, 2016 Free Software Foundation, Inc.
3  * This file is part of the GNU LIBICONV Library.
4  *
5  * The GNU LIBICONV Library is free software; you can redistribute it
6  * and/or modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * The GNU LIBICONV Library is distributed in the hope that it will be
11  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with the GNU LIBICONV Library; see the file COPYING.LIB.
17  * If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /*
21  * CP1258
22  */
23
24 #include "flushwc.h"
25 #include "vietcomb.h"
26
27 static const unsigned char cp1258_comb_table[] = {
28   0xcc, 0xec, 0xde, 0xd2, 0xf2,
29 };
30
31 /* The possible bases in viet_comp_table_data:
32    0x0041..0x0045, 0x0047..0x0049, 0x004B..0x0050, 0x0052..0x0057,
33    0x0059..0x005A, 0x0061..0x0065, 0x0067..0x0069, 0x006B..0x0070,
34    0x0072..0x0077, 0x0079..0x007A, 0x00A5, 0x00A8, 0x00C2, 0x00C5..0x00C7,
35    0x00CA, 0x00CF, 0x00D3..0x00D4, 0x00D6, 0x00D8, 0x00DA, 0x00DC, 0x00E2,
36    0x00E5..0x00E7, 0x00EA, 0x00EF, 0x00F3..0x00F4, 0x00F6, 0x00F8, 0x00FA,
37    0x00FC, 0x0102..0x0103, 0x01A0..0x01A1, 0x01AF..0x01B0. */
38 static const unsigned int cp1258_comp_bases[] = {
39   0x06fdfbbe, 0x06fdfbbe, 0x00000000, 0x00000120, 0x155884e4, 0x155884e4,
40   0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00018003
41 };
42
43 static const unsigned short cp1258_2uni[128] = {
44   /* 0x80 */
45   0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
46   0x02c6, 0x2030, 0xfffd, 0x2039, 0x0152, 0xfffd, 0xfffd, 0xfffd,
47   /* 0x90 */
48   0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
49   0x02dc, 0x2122, 0xfffd, 0x203a, 0x0153, 0xfffd, 0xfffd, 0x0178,
50   /* 0xa0 */
51   0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
52   0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
53   /* 0xb0 */
54   0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
55   0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
56   /* 0xc0 */
57   0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
58   0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x0300, 0x00cd, 0x00ce, 0x00cf,
59   /* 0xd0 */
60   0x0110, 0x00d1, 0x0309, 0x00d3, 0x00d4, 0x01a0, 0x00d6, 0x00d7,
61   0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x01af, 0x0303, 0x00df,
62   /* 0xe0 */
63   0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
64   0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0301, 0x00ed, 0x00ee, 0x00ef,
65   /* 0xf0 */
66   0x0111, 0x00f1, 0x0323, 0x00f3, 0x00f4, 0x01a1, 0x00f6, 0x00f7,
67   0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x01b0, 0x20ab, 0x00ff,
68 };
69
70 /* In the CP1258 to Unicode direction, the state contains a buffered
71    character, or 0 if none. */
72
73 static int
74 cp1258_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, size_t n)
75 {
76   unsigned char c = *s;
77   unsigned short wc;
78   unsigned short last_wc;
79   if (c < 0x80) {
80     wc = c;
81   } else {
82     wc = cp1258_2uni[c-0x80];
83     if (wc == 0xfffd)
84       return RET_ILSEQ;
85   }
86   last_wc = conv->istate;
87   if (last_wc) {
88     if (wc >= 0x0300 && wc < 0x0340) {
89       /* See whether last_wc and wc can be combined. */
90       unsigned int k;
91       unsigned int i1, i2;
92       switch (wc) {
93         case 0x0300: k = 0; break;
94         case 0x0301: k = 1; break;
95         case 0x0303: k = 2; break;
96         case 0x0309: k = 3; break;
97         case 0x0323: k = 4; break;
98         default: abort();
99       }
100       i1 = viet_comp_table[k].idx;
101       i2 = i1 + viet_comp_table[k].len-1;
102       if (last_wc >= viet_comp_table_data[i1].base
103           && last_wc <= viet_comp_table_data[i2].base) {
104         unsigned int i;
105         for (;;) {
106           i = (i1+i2)>>1;
107           if (last_wc == viet_comp_table_data[i].base)
108             break;
109           if (last_wc < viet_comp_table_data[i].base) {
110             if (i1 == i)
111               goto not_combining;
112             i2 = i;
113           } else {
114             if (i1 != i)
115               i1 = i;
116             else {
117               i = i2;
118               if (last_wc == viet_comp_table_data[i].base)
119                 break;
120               goto not_combining;
121             }
122           }
123         }
124         last_wc = viet_comp_table_data[i].composed;
125         /* Output the combined character. */
126         conv->istate = 0;
127         *pwc = (ucs4_t) last_wc;
128         return 1;
129       }
130     }
131   not_combining:
132     /* Output the buffered character. */
133     conv->istate = 0;
134     *pwc = (ucs4_t) last_wc;
135     return 0; /* Don't advance the input pointer. */
136   }
137   if (wc >= 0x0041 && wc <= 0x01b0
138       && ((cp1258_comp_bases[(wc - 0x0040) >> 5] >> (wc & 0x1f)) & 1)) {
139     /* wc is a possible match in viet_comp_table_data. Buffer it. */
140     conv->istate = wc;
141     return RET_TOOFEW(1);
142   } else {
143     /* Output wc immediately. */
144     *pwc = (ucs4_t) wc;
145     return 1;
146   }
147 }
148
149 #define cp1258_flushwc normal_flushwc
150
151 static const unsigned char cp1258_page00[88] = {
152   0xc0, 0xc1, 0xc2, 0x00, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
153   0xc8, 0xc9, 0xca, 0xcb, 0x00, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
154   0x00, 0xd1, 0x00, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */
155   0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
156   0xe0, 0xe1, 0xe2, 0x00, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
157   0xe8, 0xe9, 0xea, 0xeb, 0x00, 0xed, 0xee, 0xef, /* 0xe8-0xef */
158   0x00, 0xf1, 0x00, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, /* 0xf0-0xf7 */
159   0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0xff, /* 0xf8-0xff */
160   /* 0x0100 */
161   0x00, 0x00, 0xc3, 0xe3, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
162   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
163   0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
164 };
165 static const unsigned char cp1258_page01[104] = {
166   0x00, 0x00, 0x8c, 0x9c, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
167   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
168   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
169   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
170   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
171   0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
172   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
173   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
174   0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
175   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
176   0xd5, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
177   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, /* 0xa8-0xaf */
178   0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
179 };
180 static const unsigned char cp1258_page02[32] = {
181   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, /* 0xc0-0xc7 */
182   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
183   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
184   0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
185 };
186 static const unsigned char cp1258_page03[40] = {
187   0xcc, 0xec, 0x00, 0xde, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
188   0x00, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
189   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
190   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
191   0x00, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
192 };
193 static const unsigned char cp1258_page20[48] = {
194   0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
195   0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */
196   0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */
197   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
198   0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
199   0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
200 };
201
202 static int
203 cp1258_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, size_t n)
204 {
205   unsigned char c = 0;
206   if (wc < 0x0080) {
207     *r = wc;
208     return 1;
209   }
210   else if (wc >= 0x00a0 && wc < 0x00c0)
211     c = wc;
212   else if (wc >= 0x00c0 && wc < 0x0118)
213     c = cp1258_page00[wc-0x00c0];
214   else if (wc >= 0x0150 && wc < 0x01b8)
215     c = cp1258_page01[wc-0x0150];
216   else if (wc >= 0x02c0 && wc < 0x02e0)
217     c = cp1258_page02[wc-0x02c0];
218   else if (wc >= 0x0300 && wc < 0x0328)
219     c = cp1258_page03[wc-0x0300];
220   else if (wc >= 0x0340 && wc < 0x0342) /* deprecated Vietnamese tone marks */
221     c = cp1258_page03[wc-0x0340];
222   else if (wc >= 0x2010 && wc < 0x2040)
223     c = cp1258_page20[wc-0x2010];
224   else if (wc == 0x20ab)
225     c = 0xfe;
226   else if (wc == 0x20ac)
227     c = 0x80;
228   else if (wc == 0x2122)
229     c = 0x99;
230   if (c != 0) {
231     *r = c;
232     return 1;
233   }
234   /* Try canonical decomposition. */
235   {
236     /* Binary search through viet_decomp_table. */
237     unsigned int i1 = 0;
238     unsigned int i2 = sizeof(viet_decomp_table)/sizeof(viet_decomp_table[0])-1;
239     if (wc >= viet_decomp_table[i1].composed
240         && wc <= viet_decomp_table[i2].composed) {
241       unsigned int i;
242       for (;;) {
243         /* Here i2 - i1 > 0. */
244         i = (i1+i2)>>1;
245         if (wc == viet_decomp_table[i].composed)
246           break;
247         if (wc < viet_decomp_table[i].composed) {
248           if (i1 == i)
249             return RET_ILUNI;
250           /* Here i1 < i < i2. */
251           i2 = i;
252         } else {
253           /* Here i1 <= i < i2. */
254           if (i1 != i)
255             i1 = i;
256           else {
257             /* Here i2 - i1 = 1. */
258             i = i2;
259             if (wc == viet_decomp_table[i].composed)
260               break;
261             else
262               return RET_ILUNI;
263           }
264         }
265       }
266       /* Found a canonical decomposition. */
267       wc = viet_decomp_table[i].base;
268       /* wc is one of 0x0020, 0x0041..0x005a, 0x0061..0x007a, 0x00a5, 0x00a8,
269          0x00c2, 0x00c5..0x00c7, 0x00ca, 0x00cf, 0x00d3, 0x00d4, 0x00d6,
270          0x00d8, 0x00da, 0x00dc, 0x00e2, 0x00e5..0x00e7, 0x00ea, 0x00ef,
271          0x00f3, 0x00f4, 0x00f6, 0x00f8, 0x00fc, 0x0102, 0x0103, 0x01a0,
272          0x01a1, 0x01af, 0x01b0. */
273       if (wc < 0x0100)
274         c = wc;
275       else if (wc < 0x0118)
276         c = cp1258_page00[wc-0x00c0];
277       else
278         c = cp1258_page01[wc-0x0150];
279       if (n < 2)
280         return RET_TOOSMALL;
281       r[0] = c;
282       r[1] = cp1258_comb_table[viet_decomp_table[i].comb1];
283       return 2;
284     }
285   }
286   return RET_ILUNI;
287 }