Git init
[framework/uifw/xorg/lib/libfontenc.git] / src / fontenc.c
1 /*
2 Copyright (c) 1998-2001 by Juliusz Chroboczek
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22
23 /* Backend-independent encoding code */
24
25 #include <string.h>
26
27 #if defined(__SCO__) || defined(__UNIXWARE__)
28 #include <strings.h>
29 #endif
30
31 #include <stdlib.h>
32
33 #define FALSE 0
34 #define TRUE 1
35 #define MAXFONTNAMELEN 1024
36 #define MAXFONTFILENAMELEN 1024
37
38 #include <X11/fonts/fontenc.h>
39 #include "fontencI.h"
40
41 /* Functions local to this file */
42
43 static FontEncPtr FontEncLoad(const char*, const char*);
44
45 /* Early versions of this code only knew about hardwired encodings,
46    hence the following data.  Now that the code knows how to load an
47    encoding from a file, most of these tables could go away. */
48
49 /* At any rate, no new hardcoded encodings will be added. */
50
51 static FontMapRec iso10646[]=
52 {
53     {FONT_ENCODING_UNICODE,0,0,NULL,NULL,NULL,NULL,NULL},
54     {0,0,0,NULL,NULL,NULL,NULL,NULL}
55 };
56
57 /* Notice that the Apple encodings do not have all the characters in
58    the corresponding ISO 8859, and therefore the table has some holes.
59    There's not much more we can do with fonts without a Unicode cmap
60    unless we are willing to combine cmaps (which we are not). */
61
62 static const unsigned short 
63 iso8859_1_apple_roman[]=
64 { 0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0x00, 0xA4,
65   0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0x00, 0xA8, 0xF8,
66   0xA1, 0xB1, 0x00, 0x00, 0xAB, 0xB5, 0xA6, 0xE1,
67   0xFC, 0x00, 0xBC, 0xC8, 0x00, 0x00, 0x00, 0xC0,
68   0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82,
69   0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC,
70   0x00, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0x00,
71   0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0x00, 0x00, 0xA7,
72   0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D,
73   0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
74   0x00, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6,
75   0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0x00, 0x00, 0xD8 };
76
77 /* Cannot use simple_recode because need to eliminate 0x80<=code<0xA0 */
78 static unsigned
79 iso8859_1_to_apple_roman(unsigned isocode, void *client_data)
80 {
81     if(isocode<=0x80)
82         return isocode;
83     else if(isocode>=0xA0)
84         return iso8859_1_apple_roman[isocode-0xA0];
85     else
86         return 0;
87 }
88
89 static FontMapRec iso8859_1[]=
90 {
91     {FONT_ENCODING_TRUETYPE,2,2,NULL,NULL,NULL,NULL,NULL}, /* ISO 8859-1 */
92     {FONT_ENCODING_UNICODE,0,0,NULL,NULL,NULL,NULL,NULL}, /* ISO 8859-1 coincides with Unicode*/
93     {FONT_ENCODING_TRUETYPE,1,0,iso8859_1_to_apple_roman,NULL,NULL,NULL,NULL},
94     {0,0,0,NULL,NULL,NULL,NULL,NULL}
95 };
96
97 static const unsigned short iso8859_2_tophalf[]=
98 { 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
99   0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
100   0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
101   0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
102   0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
103   0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
104   0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
105   0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
106   0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
107   0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
108   0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
109   0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 };
110
111 static FontEncSimpleMapRec iso8859_2_to_unicode_map=
112 {0x60, 0, 0xA0, iso8859_2_tophalf };
113
114 static const unsigned short iso8859_2_apple_centeuro[]=
115 { 0xCA, 0x84, 0x00, 0xFC, 0x00, 0xBB, 0xE5, 0xA4,
116   0xAC, 0xE1, 0x00, 0xE8, 0x8F, 0x00, 0xEB, 0xFB,
117   0xA1, 0x88, 0x00, 0xB8, 0x00, 0xBC, 0xE6, 0xFF,
118   0x00, 0xE4, 0x00, 0xE9, 0x90, 0x00, 0xEC, 0xFD,
119   0xD9, 0xE7, 0x00, 0x00, 0x80, 0xBD, 0x8C, 0x00,
120   0x89, 0x83, 0xA2, 0x00, 0x9D, 0xEA, 0x00, 0x91,
121   0x00, 0xC1, 0xC5, 0xEE, 0xEF, 0xCC, 0x85, 0x00,
122   0xDB, 0xF1, 0xF2, 0xF4, 0x86, 0xF8, 0x00, 0xA7,
123   0xDA, 0x87, 0x00, 0x00, 0x8A, 0xBE, 0x8D, 0x00,
124   0x8B, 0x8E, 0xAB, 0x00, 0x9E, 0x92, 0x00, 0x93,
125   0x00, 0xC4, 0xCB, 0x97, 0x99, 0xCE, 0x9A, 0xD6,
126   0xDE, 0xF3, 0x9C, 0xF5, 0x9F, 0xF9, 0x00, 0x00 };
127
128 static unsigned
129 iso8859_2_to_apple_centeuro(unsigned isocode, void *client_data)
130 {
131     if(isocode<=0x80)
132         return isocode;
133     else if(isocode>=0xA0)
134         return iso8859_2_apple_centeuro[isocode-0xA0];
135     else
136         return 0;
137 }
138
139
140 static FontMapRec iso8859_2[]=
141 {
142     {FONT_ENCODING_UNICODE,0,0,
143      FontEncSimpleRecode,NULL,&iso8859_2_to_unicode_map,NULL,NULL},
144     {FONT_ENCODING_TRUETYPE,1,29,iso8859_2_to_apple_centeuro,NULL,NULL,NULL,NULL},
145     {0,0,0,NULL,NULL,NULL,NULL,NULL}
146 };
147
148 static const unsigned short iso8859_3_tophalf[]=
149 { 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0x0000, 0x0124, 0x00A7,
150   0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0x0000, 0x017B,
151   0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7,
152   0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0x0000, 0x017C,
153   0x00C0, 0x00C1, 0x00C2, 0x0000, 0x00C4, 0x010A, 0x0108, 0x00C7,
154   0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
155   0x0000, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7,
156   0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF,
157   0x00E0, 0x00E1, 0x00E2, 0x0000, 0x00E4, 0x010B, 0x0109, 0x00E7,
158   0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
159   0x0000, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7,
160   0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9};
161
162 static FontEncSimpleMapRec iso8859_3_to_unicode_map=
163 { 0x60, 0, 0xA0, iso8859_3_tophalf };
164
165 static FontMapRec iso8859_3[]=
166 {
167     {FONT_ENCODING_UNICODE,0,0,
168      FontEncSimpleRecode,NULL,&iso8859_3_to_unicode_map,NULL,NULL},
169     {0,0,0,NULL,NULL,NULL,NULL,NULL}
170 };
171
172
173 static const unsigned short iso8859_4_tophalf[]=
174 { 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7,
175   0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF,
176   0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7,
177   0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B,
178   0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
179   0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A,
180   0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
181   0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF,
182   0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
183   0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B,
184   0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
185   0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9,
186 };
187
188 static FontEncSimpleMapRec iso8859_4_to_unicode_map=
189 { 0x60, 0, 0xA0, iso8859_4_tophalf };
190
191 static FontMapRec iso8859_4[]=
192 {
193     {FONT_ENCODING_UNICODE,0,0,FontEncSimpleRecode,NULL,
194      &iso8859_4_to_unicode_map,NULL,NULL},
195     {0,0,0,NULL,NULL,NULL,NULL,NULL}
196 };
197
198 static const unsigned short iso8859_5_tophalf[]=
199 { 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
200   0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
201   0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
202   0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
203   0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
204   0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
205   0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
206   0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
207   0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
208   0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
209   0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
210   0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F};
211
212 static FontEncSimpleMapRec iso8859_5_to_unicode_map=
213 { 0x60, 0, 0xA0, iso8859_5_tophalf };
214
215 static const unsigned short 
216 iso8859_5_apple_cyrillic[]=
217 { 0xCA, 0xDD, 0xAB, 0xAE, 0xB8, 0xC1, 0xA7, 0xBA,
218   0xB7, 0xBC, 0xBE, 0xCB, 0xCD, 0x00, 0xD8, 0xDA,
219   0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
220   0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
221   0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
222   0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
223   0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
224   0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
225   0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
226   0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF,
227   0xDC, 0xDE, 0xAC, 0xAF, 0xB9, 0xCF, 0xB4, 0xBB,
228   0xC0, 0xBD, 0xBF, 0xCC, 0xCE, 0xA4, 0xD9, 0xDB };
229
230 static unsigned
231 iso8859_5_to_apple_cyrillic(unsigned isocode, void *client_data)
232 {
233     if(isocode<=0x80)
234         return isocode;
235     else if(isocode>=0xA0)
236         return iso8859_5_apple_cyrillic[isocode-0x80];
237     else return 0;
238 }
239
240 static FontMapRec iso8859_5[]=
241 {
242     {FONT_ENCODING_UNICODE,0,0,FontEncSimpleRecode,NULL,
243      &iso8859_5_to_unicode_map,NULL,NULL},
244     {FONT_ENCODING_TRUETYPE,1,7,iso8859_5_to_apple_cyrillic,NULL,NULL,NULL,NULL},
245     {0,0,0,NULL,NULL,NULL,NULL,NULL}
246 };
247
248 /* ISO 8859-6 seems useless for serving fonts (not enough presentation
249  * forms).  What do Arabic-speakers use? */
250
251 static unsigned
252 iso8859_6_to_unicode(unsigned isocode, void *client_data)
253 {
254     if(isocode<=0xA0 || isocode==0xA4 || isocode==0xAD)
255         return isocode;
256     else if(isocode==0xAC || isocode==0xBB || 
257             (isocode>=0xBF && isocode<=0xDA) ||
258             (isocode>=0xE0 && isocode<=0xEF) ||
259             (isocode>=0xF0 && isocode<=0xF2))
260         return isocode-0xA0+0x0600;
261     else
262         return 0;
263 }
264
265 static FontMapRec iso8859_6[]=
266 {
267     {FONT_ENCODING_UNICODE,0,0,iso8859_6_to_unicode,NULL,NULL,NULL,NULL},
268     {0,0,0,NULL,NULL,NULL,NULL,NULL}
269 };
270
271 static unsigned 
272 iso8859_7_to_unicode(unsigned isocode, void *client_data)
273 {
274     if(isocode<=0xA0 ||
275        (isocode>=0xA3 && isocode<=0xAD) ||
276        (isocode>=0xB0 && isocode<=0xB3) ||
277        isocode==0xB7 || isocode==0xBB || isocode==0xBD)
278         return isocode;
279     else if(isocode==0xA1)
280         return 0x02BD;
281     else if(isocode==0xA2)
282         return 0x02BC;
283     else if(isocode==0xAF)
284         return 0x2015;
285     else if(isocode>=0xB4)
286         return isocode-0xA0+0x0370;
287     else
288         return 0;
289 }
290
291 static FontMapRec iso8859_7[]=
292 {
293     {FONT_ENCODING_UNICODE,0,0,iso8859_7_to_unicode,NULL,NULL,NULL,NULL},
294     {0,0,0,NULL,NULL,NULL,NULL,NULL}
295 };
296
297 static unsigned
298 iso8859_8_to_unicode(unsigned isocode, void *client_data)
299 {
300     if(isocode==0xA1)
301         return 0;
302     else if(isocode<0xBF)
303         return isocode;
304     else if(isocode==0xDF)
305         return 0x2017;
306     else if(isocode>=0xE0 && isocode<=0xFA)
307         return isocode+0x04F0;
308     else 
309         return 0;
310 }
311
312 static FontMapRec iso8859_8[]=
313 {
314     {FONT_ENCODING_UNICODE,0,0,iso8859_8_to_unicode,NULL,NULL,NULL,NULL},
315     {0,0,0,NULL,NULL,NULL,NULL,NULL}
316 };
317
318 static unsigned
319 iso8859_9_to_unicode(unsigned isocode, void *client_data)
320 {
321     switch(isocode) {
322     case 0xD0: return 0x011E;
323     case 0xDD: return 0x0130;
324     case 0xDE: return 0x015E;
325     case 0xF0: return 0x011F;
326     case 0xFD: return 0x0131;
327     case 0xFE: return 0x015F;
328     default: return isocode;
329     }
330 }
331
332 static FontMapRec iso8859_9[]=
333 {
334     {FONT_ENCODING_UNICODE,0,0,iso8859_9_to_unicode,NULL,NULL,NULL,NULL},
335     {0,0,0,NULL,NULL,NULL,NULL,NULL}
336 };
337
338 static const unsigned short iso8859_10_tophalf[]=
339 { 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7,
340   0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
341   0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7,
342   0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2014, 0x016B, 0x014B,
343   0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
344   0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF,
345   0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168,
346   0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
347   0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
348   0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF,
349   0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169,
350   0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138};
351
352 static FontEncSimpleMapRec iso8859_10_to_unicode_map=
353 { 0x60, 0, 0xA0, iso8859_10_tophalf };
354
355 static FontMapRec iso8859_10[]=
356 {
357     {FONT_ENCODING_UNICODE,0,0,FontEncSimpleRecode,NULL,
358      &iso8859_10_to_unicode_map,NULL,NULL},
359     {0,0,0,NULL,NULL,NULL,NULL,NULL}
360 };
361
362 static unsigned
363 iso8859_15_to_unicode(unsigned isocode, void *client_data)
364 {
365     switch(isocode) {
366     case 0xA4: return 0x20AC;
367     case 0xA6: return 0x0160;
368     case 0xA8: return 0x0161;
369     case 0xB4: return 0x017D;
370     case 0xB8: return 0x017E;
371     case 0xBC: return 0x0152;
372     case 0xBD: return 0x0153;
373     case 0xBE: return 0x0178;
374     default: return isocode;
375     }
376 }
377
378 static FontMapRec iso8859_15[]=
379 {
380     {FONT_ENCODING_UNICODE,0,0,iso8859_15_to_unicode,NULL,NULL,NULL,NULL},
381     {0,0,0,NULL,NULL,NULL,NULL,NULL}
382 };
383
384 static const unsigned short koi8_r_tophalf[]=
385 { 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
386   0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
387   0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2022, 0x221A, 0x2248,
388   0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,
389   0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556,
390   0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E,
391   0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565,
392   0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9,
393   0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
394   0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
395   0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
396   0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
397   0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
398   0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
399   0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
400   0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A};
401
402 static FontEncSimpleMapRec koi8_r_to_unicode_map=
403 { 0x80, 0, 0x80, koi8_r_tophalf };
404
405
406 static FontMapRec koi8_r[]=
407 {
408     {FONT_ENCODING_UNICODE,0,0,FontEncSimpleRecode,NULL,
409      &koi8_r_to_unicode_map,NULL,NULL},
410     {0,0,0,NULL,NULL,NULL,NULL,NULL}
411 };
412
413 static unsigned 
414 koi8_ru_to_unicode(unsigned koicode, void *client_data)
415 {
416     switch(koicode) {
417     case 0x93: return 0x201C;
418     case 0x96: return 0x201D;
419     case 0x97: return 0x2014;
420     case 0x98: return 0x2116;
421     case 0x99: return 0x2122;
422     case 0x9B: return 0x00BB;
423     case 0x9C: return 0x00AE;
424     case 0x9D: return 0x00AB;
425     case 0x9F: return 0x00A4;
426     case 0xA4: return 0x0454;
427     case 0xA6: return 0x0456;
428     case 0xA7: return 0x0457;
429     case 0xAD: return 0x0491;
430     case 0xAE: return 0x045E;
431     case 0xB4: return 0x0404;
432     case 0xB6: return 0x0406;
433     case 0xB7: return 0x0407;
434     case 0xBD: return 0x0490;
435     case 0xBE: return 0x040E;
436     default: return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
437   }
438 }
439
440 static FontMapRec koi8_ru[]=
441 {
442     {FONT_ENCODING_UNICODE,0,0,koi8_ru_to_unicode,NULL,NULL,NULL,NULL},
443     {0,0,0,NULL,NULL,NULL,NULL,NULL}
444 };
445
446 /* koi8-e, ISO-IR-111 or ECMA-Cyrillic */
447
448 static const unsigned short koi8_e_A0_BF[]=
449 { 0x00A0, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
450   0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00AD, 0x045E, 0x045F,
451   0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
452   0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00A4, 0x040E, 0x040F };
453
454 static unsigned
455 koi8_e_to_unicode(unsigned koicode, void *client_data)
456 {
457     if(koicode<0xA0)
458         return koicode;
459     else if(koicode<0xC0)
460         return koi8_e_A0_BF[koicode-0xA0];
461     else 
462         return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
463 }
464
465 static FontMapRec koi8_e[]=
466 {
467     {FONT_ENCODING_UNICODE,0,0,koi8_e_to_unicode,NULL,NULL,NULL,NULL},
468     {0,0,0,NULL,NULL,NULL,NULL,NULL}
469 };
470
471 /* Koi8 unified */
472
473 static const unsigned short koi8_uni_80_BF[]=
474 { 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
475   0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
476   0x2591, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
477   0x00A9, 0x2122, 0x00A0, 0x00BB, 0x00AE, 0x00AB, 0x00B7, 0x00A4,
478   0x00A0, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
479   0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x0491, 0x045E, 0x045F,
480   0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
481   0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x0490, 0x040E, 0x040F };
482
483 static unsigned 
484 koi8_uni_to_unicode(unsigned koicode, void *client_data)
485 {
486     if(koicode<0x80)
487         return koicode;
488     else if(koicode<0xC0)
489         return koi8_uni_80_BF[koicode-0x80];
490     else
491         return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
492 }
493
494 static FontMapRec koi8_uni[]=
495 {
496     {FONT_ENCODING_UNICODE,0,0,koi8_uni_to_unicode,NULL,NULL,NULL,NULL},
497     {0,0,0,NULL,NULL,NULL,NULL,NULL}
498 };
499
500 /* Ukrainian variant of Koi8-R; see RFC 2319 */
501
502 static unsigned 
503 koi8_u_to_unicode(unsigned koicode, void *client_data)
504 {
505     switch(koicode) {
506     case 0xA4: return 0x0454;
507     case 0xA6: return 0x0456;
508     case 0xA7: return 0x0457;
509     case 0xAD: return 0x0491;
510     case 0xB4: return 0x0404;
511     case 0xB6: return 0x0406;
512     case 0xB7: return 0x0407;
513     case 0xBD: return 0x0490;
514     default: return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
515     }
516 }
517
518 static FontMapRec koi8_u[]=
519 {
520     {FONT_ENCODING_UNICODE,0,0,koi8_u_to_unicode,NULL,NULL,NULL},
521     {0,0,0,NULL,NULL,NULL,NULL,NULL}
522 };
523
524 /* Microsoft Symbol, which is only meaningful for TrueType fonts, is
525    treated specially in ftenc.c, where we add usFirstCharIndex-0x20 to
526    the glyph index before applying the cmap.  Lovely design. */
527
528 static FontMapRec microsoft_symbol[]=
529 {{FONT_ENCODING_TRUETYPE,3,0,NULL,NULL,NULL,NULL,NULL}, 
530  /* You never know */
531  {FONT_ENCODING_TRUETYPE,3,1,NULL,NULL,NULL,NULL,NULL}, 
532  {0,0,0,NULL,NULL,NULL,NULL,NULL}};
533
534 static FontMapRec apple_roman[]=
535 {{FONT_ENCODING_TRUETYPE,1,0,NULL,NULL,NULL,NULL,NULL},
536  {0,0,0,NULL,NULL,NULL,NULL,NULL}};
537
538 /* The data for recodings */
539
540 /* For compatibility with X11R6.4.  Losers. */
541 static char *iso8859_15_aliases[2]={"fcd8859-15",NULL};
542
543 static FontEncRec initial_encodings[]=
544 {
545     {"iso10646-1",NULL,256*256,0,iso10646,NULL,0,0}, /* Unicode */
546     {"iso8859-1",NULL,256,0,iso8859_1,NULL,0,0}, /* Latin 1 (West European) */
547     {"iso8859-2",NULL,256,0,iso8859_2,NULL,0,0}, /* Latin 2 (East European) */
548     {"iso8859-3",NULL,256,0,iso8859_3,NULL,0,0}, /* Latin 3 (South European) */
549     {"iso8859-4",NULL,256,0,iso8859_4,NULL,0,0}, /* Latin 4 (North European) */
550     {"iso8859-5",NULL,256,0,iso8859_5,NULL,0,0}, /* Cyrillic */
551     {"iso8859-6",NULL,256,0,iso8859_6,NULL,0,0}, /* Arabic */
552     {"iso8859-7",NULL,256,0,iso8859_7,NULL,0,0}, /* Greek */
553     {"iso8859-8",NULL,256,0,iso8859_8,NULL,0,0}, /* Hebrew */
554     {"iso8859-9",NULL,256,0,iso8859_9,NULL,0,0}, /* Latin 5 (Turkish) */
555     {"iso8859-10",NULL,256,0,iso8859_10,NULL,0,0}, /* Latin 6 (Nordic) */
556     {"iso8859-15",iso8859_15_aliases,256,0,iso8859_15,NULL,0,0}, /* Latin 9 */
557     {"koi8-r",NULL,256,0,koi8_r,NULL,0,0},       /* Russian */
558     {"koi8-ru",NULL,256,0,koi8_ru,NULL,0,0},     /* Ukrainian */
559     {"koi8-uni",NULL,256,0,koi8_uni,NULL,0,0},   /* Russian/Ukrainian/Bielorussian */
560     {"koi8-e",NULL,256,0,koi8_e,NULL,0,0},       /* ``European'' */
561     {"koi8-u",NULL,256,0,koi8_u,NULL,0,0},       /* Ukrainian too */
562     {"microsoft-symbol",NULL,256,0,microsoft_symbol,NULL,0,0},
563     {"apple-roman",NULL,256,0,apple_roman,NULL,0,0},
564     {NULL,NULL,0,0,NULL,NULL,0,0}
565 };
566
567 static FontEncPtr font_encodings=NULL;
568
569 static void
570 define_initial_encoding_info(void)
571 {
572     FontEncPtr encoding;
573     FontMapPtr mapping;
574
575     font_encodings = initial_encodings;
576     for(encoding = font_encodings; ; encoding++) {
577         encoding->next = encoding + 1;
578         for(mapping = encoding->mappings; ; mapping++) {
579             mapping->next = mapping+1;
580             mapping->encoding = encoding;
581             if(mapping->next->type == 0) {
582                 mapping->next = NULL;
583                 break;
584             }
585         }
586         if(!encoding->next->name) {
587             encoding->next = NULL;
588             break;
589         }
590     }
591 }
592
593
594 char*
595 FontEncFromXLFD(const char *name, int length)
596 {
597     const char *p;
598     char *q;
599     static char charset[MAXFONTNAMELEN];
600     int len;
601
602     if(length > MAXFONTNAMELEN - 1)
603         return NULL;
604
605     if(name == NULL)
606         p = NULL;
607     else {
608         p = name + length - 1;
609         while(p > name && *p != '-')
610             p--;
611         p--;
612         while(p >= name && *p != '-')
613             p--;
614         if(p <= name)
615             p = NULL;
616     }
617
618     /* now p either is null or points at the '-' before the charset registry */
619
620     if(p == NULL)
621         return NULL;
622     
623     len = length - (p - name) - 1;
624     memcpy(charset, p+1, len);
625     charset[len] = 0;
626     
627     /* check for a subset specification */
628     if((q = strchr(charset, (int)'[')))
629         *q = 0;
630     
631     return charset;
632 }
633
634 unsigned
635 FontEncRecode(unsigned code,  FontMapPtr mapping)
636 {
637     FontEncPtr encoding = mapping->encoding;
638     if(encoding && mapping->recode) {
639         if(encoding->row_size == 0) {
640             /* linear encoding */
641             if(code < encoding->first || code>=encoding->size)
642                 return 0;
643         } else {
644             /* matrix encoding */
645             int row = code/0x100, col = code&0xFF;
646             if(row < encoding->first || row >= encoding->size ||
647                col < encoding->first_col || col >= encoding->row_size)
648                 return 0;
649         }
650         return (*mapping->recode)(code, mapping->client_data);
651     } else
652         return code;
653 }
654
655 char*
656 FontEncName(unsigned code, FontMapPtr mapping)
657 {
658     FontEncPtr encoding = mapping->encoding;
659     if(encoding && mapping->name) {
660         if((encoding->row_size == 0 && code >= encoding->size) ||
661            (encoding->row_size != 0 &&
662             (code/0x100 >= encoding->size || 
663              (code&0xFF) >= encoding->row_size)))
664             return NULL;
665         return (*mapping->name)(code, mapping->client_data);
666     } else
667         return NULL;
668 }
669
670 FontEncPtr
671 FontEncFind(const char *encoding_name, const char *filename)
672 {
673     FontEncPtr encoding;
674     char **alias;
675     
676     if(font_encodings == NULL) define_initial_encoding_info();
677     
678     for(encoding = font_encodings; encoding; encoding = encoding->next) {
679         if(!strcasecmp(encoding->name, encoding_name))
680             return encoding;
681         if(encoding->aliases)
682             for(alias=encoding->aliases; *alias; alias++)
683                 if(!strcasecmp(*alias, encoding_name))
684                     return encoding;
685   }
686
687   /* Unknown charset, try to load a definition file */
688     return FontEncLoad(encoding_name, filename);
689 }
690
691 FontMapPtr
692 FontMapFind(FontEncPtr encoding, int type, int pid, int eid)
693 {
694     FontMapPtr mapping;
695     if(encoding == NULL)
696         return NULL;
697
698     for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
699         if(mapping->type != type)
700             continue;
701         if(pid > 0 && mapping->pid != pid)
702             continue;
703         if(eid > 0 && mapping->eid != eid)
704             continue;
705         return mapping;
706     }
707     return NULL;
708 }
709
710 FontMapPtr
711 FontEncMapFind(const char *encoding_name, int type, int pid, int eid,
712                const char *filename)
713 {
714     FontEncPtr encoding;
715     FontMapPtr mapping;
716
717     encoding = FontEncFind(encoding_name, filename);
718     if(encoding == NULL)
719         return NULL;
720     mapping = FontMapFind(encoding, type, pid, eid);
721     return mapping;
722 }
723
724 static FontEncPtr
725 FontEncLoad(const char *encoding_name, const char *filename)
726 {
727     FontEncPtr encoding;
728     
729     encoding = FontEncReallyLoad(encoding_name, filename);
730     if (encoding == NULL) {
731         return NULL;
732     } else {
733         char **alias;
734         int found = 0;
735         
736         /* Check whether the name is already known for this encoding */
737         if(strcasecmp(encoding->name, encoding_name) == 0) {
738             found = 1;
739         } else {
740             if(encoding->aliases) {
741                 for(alias=encoding->aliases; *alias; alias++)
742                     if(!strcasecmp(*alias, encoding_name)) {
743                         found = 1;
744                         break;
745                     }
746             }
747         }
748         
749         if(!found) {
750             /* Add a new alias.  This works because we know that this
751                particular encoding has been allocated dynamically */
752             char **new_aliases;
753             char *new_name;
754             int numaliases = 0;
755             
756             new_name = strdup(encoding_name);
757             if(new_name == NULL)
758                 return NULL;
759             if(encoding->aliases) {
760                 for(alias = encoding->aliases; *alias; alias++)
761                     numaliases++;
762             }
763             new_aliases = malloc((numaliases+2)*sizeof(char*));
764             if(new_aliases == NULL) {
765                 free(new_name);
766                 return NULL;
767             }
768             if(encoding->aliases) {
769                 memcpy(new_aliases, encoding->aliases, numaliases*sizeof(char*));
770                 free(encoding->aliases);
771             }
772             new_aliases[numaliases] = new_name;
773             new_aliases[numaliases+1] = NULL;
774             encoding->aliases = new_aliases;
775         }
776         
777         /* register the new encoding */
778         encoding->next=font_encodings;
779         font_encodings=encoding;
780         
781         return encoding;
782     }
783 }
784
785 unsigned
786 FontEncSimpleRecode(unsigned code, void *client_data)
787 {
788     FontEncSimpleMapPtr map;
789     unsigned index;
790
791     map = client_data;
792
793     if(code > 0xFFFF || (map->row_size && (code&0xFF) >= map->row_size))
794         return 0;
795
796     if(map->row_size)
797         index = (code&0xFF)+(code>>8)*map->row_size;
798     else
799         index = code;
800
801   if(map->map && index>=map->first && index<map->first+map->len)    
802     return map->map[index-map->first];
803   else
804     return code;
805 }
806
807 char *
808 FontEncSimpleName(unsigned code, void *client_data)
809 {
810     FontEncSimpleNamePtr map;
811
812     map = client_data;
813     if(map && code >= map->first && code<map->first+map->len)
814         return map->map[code-map->first];
815     else
816         return NULL;
817 }
818
819 unsigned
820 FontEncUndefinedRecode(unsigned code, void *client_data)
821 {
822     return code;
823 }
824
825 char *
826 FontEncUndefinedName(unsigned code, void *client_data)
827 {
828     return NULL;
829 }
830
831 #define FONTENC_SEGMENT_SIZE 256
832 #define FONTENC_SEGMENTS 256
833 #define FONTENC_INVERSE_CODES (FONTENC_SEGMENT_SIZE * FONTENC_SEGMENTS)
834
835 static unsigned int
836 reverse_reverse(unsigned i, void* data)
837 {
838     int s, j;
839     unsigned **map = (unsigned**)data;
840
841     if(i >= FONTENC_INVERSE_CODES)
842         return 0;
843
844     if(map == NULL)
845         return 0;
846
847     s = i / FONTENC_SEGMENT_SIZE;
848     j = i % FONTENC_SEGMENT_SIZE;
849
850     if(map[s] == NULL)
851         return 0;
852     else
853         return map[s][j];
854 }
855
856 static int
857 tree_set(unsigned int **map, unsigned int i, unsigned int j)
858 {
859     int s, c;
860
861     if(i >= FONTENC_INVERSE_CODES)
862         return FALSE;
863
864     s = i / FONTENC_SEGMENT_SIZE;
865     c = i % FONTENC_SEGMENT_SIZE;
866
867     if(map[s] == NULL) {
868         map[s] = calloc(FONTENC_SEGMENT_SIZE, sizeof(int)); 
869         if(map[s] == NULL)
870             return FALSE;
871   }
872
873     map[s][c] = j;
874     return TRUE;
875 }
876
877 FontMapReversePtr
878 FontMapReverse(FontMapPtr mapping)
879 {
880     FontEncPtr encoding = mapping->encoding;
881     FontMapReversePtr reverse = NULL;
882     unsigned int **map = NULL;
883     int i, j, k;
884
885     if(encoding == NULL) goto bail;
886
887     map = calloc(FONTENC_SEGMENTS, sizeof(int*));
888     if(map == NULL) goto bail;
889
890     if(encoding->row_size == 0) {
891         for(i = encoding->first; i < encoding->size; i++) {
892             k = FontEncRecode(i, mapping);
893             if(k != 0)
894                 if(!tree_set(map, k, i))
895                     goto bail;
896         }
897     } else {
898         for(i = encoding->first; i < encoding->size; i++) {
899             for(j = encoding->first_col; j < encoding->row_size; j++) {
900                 k = FontEncRecode(i*256 + j, mapping);
901                 if(k != 0)
902                     if(!tree_set(map, k, i*256+j))
903                         goto bail;
904             }
905         }
906     }
907
908     reverse = malloc(sizeof(FontMapReverseRec));
909     if(!reverse) goto bail;
910
911     reverse->reverse = reverse_reverse;
912     reverse->data = map;
913     return reverse;
914
915   bail:
916     free(map);
917     free(reverse);
918     return NULL;
919 }
920
921 void
922 FontMapReverseFree(FontMapReversePtr delendum)
923 {
924     unsigned int **map = (unsigned int**)delendum;
925     int i;
926     
927     if(map == NULL)
928         return;
929
930     for(i = 0; i < FONTENC_SEGMENTS; i++)
931         free(map[i]);
932
933     free(map);
934     return;
935 }