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