13da084b3Smrg/*
23da084b3SmrgCopyright (c) 1998-2001 by Juliusz Chroboczek
33da084b3Smrg
43da084b3SmrgPermission is hereby granted, free of charge, to any person obtaining a copy
53da084b3Smrgof this software and associated documentation files (the "Software"), to deal
63da084b3Smrgin the Software without restriction, including without limitation the rights
73da084b3Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
83da084b3Smrgcopies of the Software, and to permit persons to whom the Software is
93da084b3Smrgfurnished to do so, subject to the following conditions:
103da084b3Smrg
113da084b3SmrgThe above copyright notice and this permission notice shall be included in
123da084b3Smrgall copies or substantial portions of the Software.
133da084b3Smrg
143da084b3SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
153da084b3SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
163da084b3SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
173da084b3SmrgAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
183da084b3SmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
193da084b3SmrgOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
203da084b3SmrgTHE SOFTWARE.
213da084b3Smrg*/
223da084b3Smrg
233da084b3Smrg/* Backend-independent encoding code */
243da084b3Smrg
252a53b785Smrg#ifdef HAVE_CONFIG_H
262a53b785Smrg#include <config.h>
272a53b785Smrg#endif
282a53b785Smrg
293da084b3Smrg#include <string.h>
303da084b3Smrg#include <strings.h>
313da084b3Smrg#include <stdlib.h>
3255acc8fcSmrg
333da084b3Smrg#define FALSE 0
343da084b3Smrg#define TRUE 1
353da084b3Smrg#define MAXFONTNAMELEN 1024
363da084b3Smrg#define MAXFONTFILENAMELEN 1024
373da084b3Smrg
383da084b3Smrg#include <X11/fonts/fontenc.h>
393da084b3Smrg#include "fontencI.h"
402a53b785Smrg#include "reallocarray.h"
413da084b3Smrg
423da084b3Smrg/* Functions local to this file */
433da084b3Smrg
44e1c0d025Smrgstatic FontEncPtr FontEncLoad(const char *, const char *);
453da084b3Smrg
463da084b3Smrg/* Early versions of this code only knew about hardwired encodings,
473da084b3Smrg   hence the following data.  Now that the code knows how to load an
483da084b3Smrg   encoding from a file, most of these tables could go away. */
493da084b3Smrg
503da084b3Smrg/* At any rate, no new hardcoded encodings will be added. */
513da084b3Smrg
52e1c0d025Smrgstatic FontMapRec iso10646[] = {
53e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, NULL, NULL, NULL, NULL, NULL},
54e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
553da084b3Smrg};
563da084b3Smrg
573da084b3Smrg/* Notice that the Apple encodings do not have all the characters in
583da084b3Smrg   the corresponding ISO 8859, and therefore the table has some holes.
593da084b3Smrg   There's not much more we can do with fonts without a Unicode cmap
603da084b3Smrg   unless we are willing to combine cmaps (which we are not). */
613da084b3Smrg
6248c85eb7Smrgstatic const unsigned short
63e1c0d025Smrg iso8859_1_apple_roman[] = {
64e1c0d025Smrg    0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0x00, 0xA4,
65e1c0d025Smrg    0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0x00, 0xA8, 0xF8,
66e1c0d025Smrg    0xA1, 0xB1, 0x00, 0x00, 0xAB, 0xB5, 0xA6, 0xE1,
67e1c0d025Smrg    0xFC, 0x00, 0xBC, 0xC8, 0x00, 0x00, 0x00, 0xC0,
68e1c0d025Smrg    0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82,
69e1c0d025Smrg    0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC,
70e1c0d025Smrg    0x00, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0x00,
71e1c0d025Smrg    0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0x00, 0x00, 0xA7,
72e1c0d025Smrg    0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D,
73e1c0d025Smrg    0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
74e1c0d025Smrg    0x00, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6,
75e1c0d025Smrg    0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0x00, 0x00, 0xD8
76e1c0d025Smrg};
773da084b3Smrg
783da084b3Smrg/* Cannot use simple_recode because need to eliminate 0x80<=code<0xA0 */
793da084b3Smrgstatic unsigned
803da084b3Smrgiso8859_1_to_apple_roman(unsigned isocode, void *client_data)
813da084b3Smrg{
82e1c0d025Smrg    if (isocode <= 0x80)
833da084b3Smrg        return isocode;
84e1c0d025Smrg    else if (isocode >= 0xA0)
85e1c0d025Smrg        return iso8859_1_apple_roman[isocode - 0xA0];
863da084b3Smrg    else
873da084b3Smrg        return 0;
883da084b3Smrg}
893da084b3Smrg
90e1c0d025Smrgstatic FontMapRec iso8859_1[] = {
91e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 2, 2, NULL, NULL, NULL, NULL, NULL},       /* ISO 8859-1 */
92e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, NULL, NULL, NULL, NULL, NULL},        /* ISO 8859-1 coincides with Unicode */
93e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 1, 0, iso8859_1_to_apple_roman, NULL, NULL, NULL,
94e1c0d025Smrg     NULL},
95e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
963da084b3Smrg};
973da084b3Smrg
98e1c0d025Smrgstatic const unsigned short iso8859_2_tophalf[] = {
99e1c0d025Smrg    0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
100e1c0d025Smrg    0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
101e1c0d025Smrg    0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
102e1c0d025Smrg    0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
103e1c0d025Smrg    0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
104e1c0d025Smrg    0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
105e1c0d025Smrg    0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
106e1c0d025Smrg    0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
107e1c0d025Smrg    0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
108e1c0d025Smrg    0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
109e1c0d025Smrg    0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
110e1c0d025Smrg    0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
111e1c0d025Smrg};
112e1c0d025Smrg
113e1c0d025Smrgstatic FontEncSimpleMapRec iso8859_2_to_unicode_map =
114e1c0d025Smrg    { 0x60, 0, 0xA0, iso8859_2_tophalf };
115e1c0d025Smrg
116e1c0d025Smrgstatic const unsigned short iso8859_2_apple_centeuro[] = {
117e1c0d025Smrg    0xCA, 0x84, 0x00, 0xFC, 0x00, 0xBB, 0xE5, 0xA4,
118e1c0d025Smrg    0xAC, 0xE1, 0x00, 0xE8, 0x8F, 0x00, 0xEB, 0xFB,
119e1c0d025Smrg    0xA1, 0x88, 0x00, 0xB8, 0x00, 0xBC, 0xE6, 0xFF,
120e1c0d025Smrg    0x00, 0xE4, 0x00, 0xE9, 0x90, 0x00, 0xEC, 0xFD,
121e1c0d025Smrg    0xD9, 0xE7, 0x00, 0x00, 0x80, 0xBD, 0x8C, 0x00,
122e1c0d025Smrg    0x89, 0x83, 0xA2, 0x00, 0x9D, 0xEA, 0x00, 0x91,
123e1c0d025Smrg    0x00, 0xC1, 0xC5, 0xEE, 0xEF, 0xCC, 0x85, 0x00,
124e1c0d025Smrg    0xDB, 0xF1, 0xF2, 0xF4, 0x86, 0xF8, 0x00, 0xA7,
125e1c0d025Smrg    0xDA, 0x87, 0x00, 0x00, 0x8A, 0xBE, 0x8D, 0x00,
126e1c0d025Smrg    0x8B, 0x8E, 0xAB, 0x00, 0x9E, 0x92, 0x00, 0x93,
127e1c0d025Smrg    0x00, 0xC4, 0xCB, 0x97, 0x99, 0xCE, 0x9A, 0xD6,
128e1c0d025Smrg    0xDE, 0xF3, 0x9C, 0xF5, 0x9F, 0xF9, 0x00, 0x00
129e1c0d025Smrg};
1303da084b3Smrg
1313da084b3Smrgstatic unsigned
1323da084b3Smrgiso8859_2_to_apple_centeuro(unsigned isocode, void *client_data)
1333da084b3Smrg{
134e1c0d025Smrg    if (isocode <= 0x80)
1353da084b3Smrg        return isocode;
136e1c0d025Smrg    else if (isocode >= 0xA0)
137e1c0d025Smrg        return iso8859_2_apple_centeuro[isocode - 0xA0];
1383da084b3Smrg    else
1393da084b3Smrg        return 0;
1403da084b3Smrg}
1413da084b3Smrg
142e1c0d025Smrgstatic FontMapRec iso8859_2[] = {
143e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0,
144e1c0d025Smrg     FontEncSimpleRecode, NULL, &iso8859_2_to_unicode_map, NULL, NULL},
145e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 1, 29, iso8859_2_to_apple_centeuro, NULL, NULL,
146e1c0d025Smrg     NULL, NULL},
147e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
1483da084b3Smrg};
1493da084b3Smrg
150e1c0d025Smrgstatic const unsigned short iso8859_3_tophalf[] = {
151e1c0d025Smrg    0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0x0000, 0x0124, 0x00A7,
152e1c0d025Smrg    0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0x0000, 0x017B,
153e1c0d025Smrg    0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7,
154e1c0d025Smrg    0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0x0000, 0x017C,
155e1c0d025Smrg    0x00C0, 0x00C1, 0x00C2, 0x0000, 0x00C4, 0x010A, 0x0108, 0x00C7,
156e1c0d025Smrg    0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
157e1c0d025Smrg    0x0000, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7,
158e1c0d025Smrg    0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF,
159e1c0d025Smrg    0x00E0, 0x00E1, 0x00E2, 0x0000, 0x00E4, 0x010B, 0x0109, 0x00E7,
160e1c0d025Smrg    0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
161e1c0d025Smrg    0x0000, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7,
162e1c0d025Smrg    0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9
1633da084b3Smrg};
1643da084b3Smrg
165e1c0d025Smrgstatic FontEncSimpleMapRec iso8859_3_to_unicode_map =
166e1c0d025Smrg    { 0x60, 0, 0xA0, iso8859_3_tophalf };
1673da084b3Smrg
168e1c0d025Smrgstatic FontMapRec iso8859_3[] = {
169e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0,
170e1c0d025Smrg     FontEncSimpleRecode, NULL, &iso8859_3_to_unicode_map, NULL, NULL},
171e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
1723da084b3Smrg};
1733da084b3Smrg
174e1c0d025Smrgstatic const unsigned short iso8859_4_tophalf[] = {
175e1c0d025Smrg    0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7,
176e1c0d025Smrg    0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF,
177e1c0d025Smrg    0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7,
178e1c0d025Smrg    0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B,
179e1c0d025Smrg    0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
180e1c0d025Smrg    0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A,
181e1c0d025Smrg    0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
182e1c0d025Smrg    0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF,
183e1c0d025Smrg    0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
184e1c0d025Smrg    0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B,
185e1c0d025Smrg    0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
186e1c0d025Smrg    0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9,
187e1c0d025Smrg};
1883da084b3Smrg
189e1c0d025Smrgstatic FontEncSimpleMapRec iso8859_4_to_unicode_map =
190e1c0d025Smrg    { 0x60, 0, 0xA0, iso8859_4_tophalf };
191e1c0d025Smrg
192e1c0d025Smrgstatic FontMapRec iso8859_4[] = {
193e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, FontEncSimpleRecode, NULL,
194e1c0d025Smrg     &iso8859_4_to_unicode_map, NULL, NULL},
195e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
1963da084b3Smrg};
1973da084b3Smrg
198e1c0d025Smrgstatic const unsigned short iso8859_5_tophalf[] = {
199e1c0d025Smrg    0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
200e1c0d025Smrg    0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
201e1c0d025Smrg    0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
202e1c0d025Smrg    0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
203e1c0d025Smrg    0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
204e1c0d025Smrg    0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
205e1c0d025Smrg    0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
206e1c0d025Smrg    0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
207e1c0d025Smrg    0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
208e1c0d025Smrg    0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
209e1c0d025Smrg    0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
210e1c0d025Smrg    0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F
211e1c0d025Smrg};
2123da084b3Smrg
213e1c0d025Smrgstatic FontEncSimpleMapRec iso8859_5_to_unicode_map =
214e1c0d025Smrg    { 0x60, 0, 0xA0, iso8859_5_tophalf };
215e1c0d025Smrg
216e1c0d025Smrgstatic const unsigned short iso8859_5_apple_cyrillic[] = {
217e1c0d025Smrg    0xCA, 0xDD, 0xAB, 0xAE, 0xB8, 0xC1, 0xA7, 0xBA,
218e1c0d025Smrg    0xB7, 0xBC, 0xBE, 0xCB, 0xCD, 0x00, 0xD8, 0xDA,
219e1c0d025Smrg    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
220e1c0d025Smrg    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
221e1c0d025Smrg    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
222e1c0d025Smrg    0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
223e1c0d025Smrg    0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
224e1c0d025Smrg    0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
225e1c0d025Smrg    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
226e1c0d025Smrg    0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF,
227e1c0d025Smrg    0xDC, 0xDE, 0xAC, 0xAF, 0xB9, 0xCF, 0xB4, 0xBB,
228e1c0d025Smrg    0xC0, 0xBD, 0xBF, 0xCC, 0xCE, 0xA4, 0xD9, 0xDB
229e1c0d025Smrg};
2303da084b3Smrg
2313da084b3Smrgstatic unsigned
2323da084b3Smrgiso8859_5_to_apple_cyrillic(unsigned isocode, void *client_data)
2333da084b3Smrg{
234e1c0d025Smrg    if (isocode <= 0x80)
2353da084b3Smrg        return isocode;
236e1c0d025Smrg    else if (isocode >= 0xA0)
237e1c0d025Smrg        return iso8859_5_apple_cyrillic[isocode - 0x80];
238e1c0d025Smrg    else
239e1c0d025Smrg        return 0;
2403da084b3Smrg}
2413da084b3Smrg
242e1c0d025Smrgstatic FontMapRec iso8859_5[] = {
243e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, FontEncSimpleRecode, NULL,
244e1c0d025Smrg     &iso8859_5_to_unicode_map, NULL, NULL},
245e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 1, 7, iso8859_5_to_apple_cyrillic, NULL, NULL,
246e1c0d025Smrg     NULL, NULL},
247e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
2483da084b3Smrg};
2493da084b3Smrg
2503da084b3Smrg/* ISO 8859-6 seems useless for serving fonts (not enough presentation
2513da084b3Smrg * forms).  What do Arabic-speakers use? */
2523da084b3Smrg
2533da084b3Smrgstatic unsigned
2543da084b3Smrgiso8859_6_to_unicode(unsigned isocode, void *client_data)
2553da084b3Smrg{
256e1c0d025Smrg    if (isocode <= 0xA0 || isocode == 0xA4 || isocode == 0xAD)
2573da084b3Smrg        return isocode;
258e1c0d025Smrg    else if (isocode == 0xAC || isocode == 0xBB ||
259e1c0d025Smrg             isocode == 0xBF ||
260e1c0d025Smrg             (isocode >= 0xC1 && isocode <= 0xDA) ||
261e1c0d025Smrg             (isocode >= 0xE0 && isocode <= 0xEF) ||
262e1c0d025Smrg             (isocode >= 0xF0 && isocode <= 0xF2))
263e1c0d025Smrg        return isocode - 0xA0 + 0x0600;
2643da084b3Smrg    else
2653da084b3Smrg        return 0;
2663da084b3Smrg}
2673da084b3Smrg
268e1c0d025Smrgstatic FontMapRec iso8859_6[] = {
269e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, iso8859_6_to_unicode, NULL, NULL, NULL, NULL},
270e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
2713da084b3Smrg};
2723da084b3Smrg
27348c85eb7Smrgstatic unsigned
2743da084b3Smrgiso8859_7_to_unicode(unsigned isocode, void *client_data)
2753da084b3Smrg{
276e1c0d025Smrg    if (isocode <= 0xA0 ||
277e1c0d025Smrg        (isocode >= 0xA3 && isocode <= 0xAD) ||
278e1c0d025Smrg        (isocode >= 0xB0 && isocode <= 0xB3) ||
279e1c0d025Smrg        isocode == 0xB7 || isocode == 0xBB || isocode == 0xBD)
2803da084b3Smrg        return isocode;
281e1c0d025Smrg    else if (isocode == 0xA1)
28252fd71cdSmrg        return 0x2018;
283e1c0d025Smrg    else if (isocode == 0xA2)
28452fd71cdSmrg        return 0x2019;
285e1c0d025Smrg    else if (isocode == 0xAF)
2863da084b3Smrg        return 0x2015;
287e1c0d025Smrg    else if (isocode == 0xD2)   /* unassigned */
28848c85eb7Smrg        return 0;
28952fd71cdSmrg    else if (isocode >= 0xB4 && isocode <= 0xFE)
290e1c0d025Smrg        return isocode - 0xA0 + 0x0370;
2913da084b3Smrg    else
2923da084b3Smrg        return 0;
2933da084b3Smrg}
2943da084b3Smrg
295e1c0d025Smrgstatic FontMapRec iso8859_7[] = {
296e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, iso8859_7_to_unicode, NULL, NULL, NULL, NULL},
297e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
2983da084b3Smrg};
2993da084b3Smrg
3003da084b3Smrgstatic unsigned
3013da084b3Smrgiso8859_8_to_unicode(unsigned isocode, void *client_data)
3023da084b3Smrg{
303e1c0d025Smrg    if (isocode == 0xA1)
3043da084b3Smrg        return 0;
305e1c0d025Smrg    else if (isocode < 0xBF)
3063da084b3Smrg        return isocode;
307e1c0d025Smrg    else if (isocode == 0xDF)
3083da084b3Smrg        return 0x2017;
309e1c0d025Smrg    else if (isocode >= 0xE0 && isocode <= 0xFA)
310e1c0d025Smrg        return isocode + 0x04F0;
31148c85eb7Smrg    else
3123da084b3Smrg        return 0;
3133da084b3Smrg}
3143da084b3Smrg
315e1c0d025Smrgstatic FontMapRec iso8859_8[] = {
316e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, iso8859_8_to_unicode, NULL, NULL, NULL, NULL},
317e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
3183da084b3Smrg};
3193da084b3Smrg
3203da084b3Smrgstatic unsigned
3213da084b3Smrgiso8859_9_to_unicode(unsigned isocode, void *client_data)
3223da084b3Smrg{
323e1c0d025Smrg    switch (isocode) {
324e1c0d025Smrg    case 0xD0:
325e1c0d025Smrg        return 0x011E;
326e1c0d025Smrg    case 0xDD:
327e1c0d025Smrg        return 0x0130;
328e1c0d025Smrg    case 0xDE:
329e1c0d025Smrg        return 0x015E;
330e1c0d025Smrg    case 0xF0:
331e1c0d025Smrg        return 0x011F;
332e1c0d025Smrg    case 0xFD:
333e1c0d025Smrg        return 0x0131;
334e1c0d025Smrg    case 0xFE:
335e1c0d025Smrg        return 0x015F;
336e1c0d025Smrg    default:
337e1c0d025Smrg        return isocode;
3383da084b3Smrg    }
3393da084b3Smrg}
3403da084b3Smrg
341e1c0d025Smrgstatic FontMapRec iso8859_9[] = {
342e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, iso8859_9_to_unicode, NULL, NULL, NULL, NULL},
343e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
3443da084b3Smrg};
3453da084b3Smrg
346e1c0d025Smrgstatic const unsigned short iso8859_10_tophalf[] = {
347e1c0d025Smrg    0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7,
348e1c0d025Smrg    0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
349e1c0d025Smrg    0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7,
350e1c0d025Smrg    0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2014, 0x016B, 0x014B,
351e1c0d025Smrg    0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
352e1c0d025Smrg    0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF,
353e1c0d025Smrg    0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168,
354e1c0d025Smrg    0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
355e1c0d025Smrg    0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
356e1c0d025Smrg    0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF,
357e1c0d025Smrg    0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169,
358e1c0d025Smrg    0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138
359e1c0d025Smrg};
360e1c0d025Smrg
361e1c0d025Smrgstatic FontEncSimpleMapRec iso8859_10_to_unicode_map =
362e1c0d025Smrg    { 0x60, 0, 0xA0, iso8859_10_tophalf };
363e1c0d025Smrg
364e1c0d025Smrgstatic FontMapRec iso8859_10[] = {
365e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, FontEncSimpleRecode, NULL,
366e1c0d025Smrg     &iso8859_10_to_unicode_map, NULL, NULL},
367e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
3683da084b3Smrg};
3693da084b3Smrg
3703da084b3Smrgstatic unsigned
3713da084b3Smrgiso8859_15_to_unicode(unsigned isocode, void *client_data)
3723da084b3Smrg{
373e1c0d025Smrg    switch (isocode) {
374e1c0d025Smrg    case 0xA4:
375e1c0d025Smrg        return 0x20AC;
376e1c0d025Smrg    case 0xA6:
377e1c0d025Smrg        return 0x0160;
378e1c0d025Smrg    case 0xA8:
379e1c0d025Smrg        return 0x0161;
380e1c0d025Smrg    case 0xB4:
381e1c0d025Smrg        return 0x017D;
382e1c0d025Smrg    case 0xB8:
383e1c0d025Smrg        return 0x017E;
384e1c0d025Smrg    case 0xBC:
385e1c0d025Smrg        return 0x0152;
386e1c0d025Smrg    case 0xBD:
387e1c0d025Smrg        return 0x0153;
388e1c0d025Smrg    case 0xBE:
389e1c0d025Smrg        return 0x0178;
390e1c0d025Smrg    default:
391e1c0d025Smrg        return isocode;
3923da084b3Smrg    }
3933da084b3Smrg}
3943da084b3Smrg
395e1c0d025Smrgstatic FontMapRec iso8859_15[] = {
396e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, iso8859_15_to_unicode, NULL, NULL, NULL,
397e1c0d025Smrg     NULL},
398e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
3993da084b3Smrg};
4003da084b3Smrg
401e1c0d025Smrgstatic const unsigned short koi8_r_tophalf[] = {
402e1c0d025Smrg    0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
403e1c0d025Smrg    0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
404e1c0d025Smrg    0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2022, 0x221A, 0x2248,
405e1c0d025Smrg    0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,
406e1c0d025Smrg    0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556,
407e1c0d025Smrg    0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E,
408e1c0d025Smrg    0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565,
409e1c0d025Smrg    0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9,
410e1c0d025Smrg    0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
411e1c0d025Smrg    0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
412e1c0d025Smrg    0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
413e1c0d025Smrg    0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
414e1c0d025Smrg    0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
415e1c0d025Smrg    0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
416e1c0d025Smrg    0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
417e1c0d025Smrg    0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A
418e1c0d025Smrg};
419e1c0d025Smrg
420e1c0d025Smrgstatic FontEncSimpleMapRec koi8_r_to_unicode_map =
421e1c0d025Smrg    { 0x80, 0, 0x80, koi8_r_tophalf };
422e1c0d025Smrg
423e1c0d025Smrgstatic FontMapRec koi8_r[] = {
424e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, FontEncSimpleRecode, NULL,
425e1c0d025Smrg     &koi8_r_to_unicode_map, NULL, NULL},
426e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
4273da084b3Smrg};
4283da084b3Smrg
42948c85eb7Smrgstatic unsigned
4303da084b3Smrgkoi8_ru_to_unicode(unsigned koicode, void *client_data)
4313da084b3Smrg{
432e1c0d025Smrg    switch (koicode) {
433e1c0d025Smrg    case 0x93:
434e1c0d025Smrg        return 0x201C;
435e1c0d025Smrg    case 0x96:
436e1c0d025Smrg        return 0x201D;
437e1c0d025Smrg    case 0x97:
438e1c0d025Smrg        return 0x2014;
439e1c0d025Smrg    case 0x98:
440e1c0d025Smrg        return 0x2116;
441e1c0d025Smrg    case 0x99:
442e1c0d025Smrg        return 0x2122;
443e1c0d025Smrg    case 0x9B:
444e1c0d025Smrg        return 0x00BB;
445e1c0d025Smrg    case 0x9C:
446e1c0d025Smrg        return 0x00AE;
447e1c0d025Smrg    case 0x9D:
448e1c0d025Smrg        return 0x00AB;
449e1c0d025Smrg    case 0x9F:
450e1c0d025Smrg        return 0x00A4;
451e1c0d025Smrg    case 0xA4:
452e1c0d025Smrg        return 0x0454;
453e1c0d025Smrg    case 0xA6:
454e1c0d025Smrg        return 0x0456;
455e1c0d025Smrg    case 0xA7:
456e1c0d025Smrg        return 0x0457;
457e1c0d025Smrg    case 0xAD:
458e1c0d025Smrg        return 0x0491;
459e1c0d025Smrg    case 0xAE:
460e1c0d025Smrg        return 0x045E;
461e1c0d025Smrg    case 0xB4:
462e1c0d025Smrg        return 0x0404;
463e1c0d025Smrg    case 0xB6:
464e1c0d025Smrg        return 0x0406;
465e1c0d025Smrg    case 0xB7:
466e1c0d025Smrg        return 0x0407;
467e1c0d025Smrg    case 0xBD:
468e1c0d025Smrg        return 0x0490;
469e1c0d025Smrg    case 0xBE:
470e1c0d025Smrg        return 0x040E;
471e1c0d025Smrg    default:
472e1c0d025Smrg        return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
473e1c0d025Smrg    }
4743da084b3Smrg}
4753da084b3Smrg
476e1c0d025Smrgstatic FontMapRec koi8_ru[] = {
477e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, koi8_ru_to_unicode, NULL, NULL, NULL, NULL},
478e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
4793da084b3Smrg};
4803da084b3Smrg
4813da084b3Smrg/* koi8-e, ISO-IR-111 or ECMA-Cyrillic */
4823da084b3Smrg
483e1c0d025Smrgstatic const unsigned short koi8_e_A0_BF[] = {
484e1c0d025Smrg    0x00A0, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
485e1c0d025Smrg    0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00AD, 0x045E, 0x045F,
486e1c0d025Smrg    0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
487e1c0d025Smrg    0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00A4, 0x040E, 0x040F
488e1c0d025Smrg};
4893da084b3Smrg
4903da084b3Smrgstatic unsigned
4913da084b3Smrgkoi8_e_to_unicode(unsigned koicode, void *client_data)
4923da084b3Smrg{
493e1c0d025Smrg    if (koicode < 0xA0)
4943da084b3Smrg        return koicode;
495e1c0d025Smrg    else if (koicode < 0xC0)
496e1c0d025Smrg        return koi8_e_A0_BF[koicode - 0xA0];
49748c85eb7Smrg    else
4983da084b3Smrg        return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
4993da084b3Smrg}
5003da084b3Smrg
501e1c0d025Smrgstatic FontMapRec koi8_e[] = {
502e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, koi8_e_to_unicode, NULL, NULL, NULL, NULL},
503e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
5043da084b3Smrg};
5053da084b3Smrg
5063da084b3Smrg/* Koi8 unified */
5073da084b3Smrg
508e1c0d025Smrgstatic const unsigned short koi8_uni_80_BF[] = {
509e1c0d025Smrg    0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
510e1c0d025Smrg    0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
511e1c0d025Smrg    0x2591, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
512e1c0d025Smrg    0x00A9, 0x2122, 0x00A0, 0x00BB, 0x00AE, 0x00AB, 0x00B7, 0x00A4,
513e1c0d025Smrg    0x00A0, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
514e1c0d025Smrg    0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x0491, 0x045E, 0x045F,
515e1c0d025Smrg    0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
516e1c0d025Smrg    0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x0490, 0x040E, 0x040F
517e1c0d025Smrg};
5183da084b3Smrg
51948c85eb7Smrgstatic unsigned
5203da084b3Smrgkoi8_uni_to_unicode(unsigned koicode, void *client_data)
5213da084b3Smrg{
522e1c0d025Smrg    if (koicode < 0x80)
5233da084b3Smrg        return koicode;
524e1c0d025Smrg    else if (koicode < 0xC0)
525e1c0d025Smrg        return koi8_uni_80_BF[koicode - 0x80];
5263da084b3Smrg    else
5273da084b3Smrg        return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
5283da084b3Smrg}
5293da084b3Smrg
530e1c0d025Smrgstatic FontMapRec koi8_uni[] = {
531e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, koi8_uni_to_unicode, NULL, NULL, NULL, NULL},
532e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
5333da084b3Smrg};
5343da084b3Smrg
5353da084b3Smrg/* Ukrainian variant of Koi8-R; see RFC 2319 */
5363da084b3Smrg
53748c85eb7Smrgstatic unsigned
5383da084b3Smrgkoi8_u_to_unicode(unsigned koicode, void *client_data)
5393da084b3Smrg{
540e1c0d025Smrg    switch (koicode) {
541e1c0d025Smrg    case 0xA4:
542e1c0d025Smrg        return 0x0454;
543e1c0d025Smrg    case 0xA6:
544e1c0d025Smrg        return 0x0456;
545e1c0d025Smrg    case 0xA7:
546e1c0d025Smrg        return 0x0457;
547e1c0d025Smrg    case 0xAD:
548e1c0d025Smrg        return 0x0491;
549e1c0d025Smrg    case 0xB4:
550e1c0d025Smrg        return 0x0404;
551e1c0d025Smrg    case 0xB6:
552e1c0d025Smrg        return 0x0406;
553e1c0d025Smrg    case 0xB7:
554e1c0d025Smrg        return 0x0407;
555e1c0d025Smrg    case 0xBD:
556e1c0d025Smrg        return 0x0490;
557e1c0d025Smrg    default:
558e1c0d025Smrg        return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
5593da084b3Smrg    }
5603da084b3Smrg}
5613da084b3Smrg
562e1c0d025Smrgstatic FontMapRec koi8_u[] = {
563e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, koi8_u_to_unicode, NULL, NULL, NULL},
564e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
5653da084b3Smrg};
5663da084b3Smrg
5673da084b3Smrg/* Microsoft Symbol, which is only meaningful for TrueType fonts, is
5683da084b3Smrg   treated specially in ftenc.c, where we add usFirstCharIndex-0x20 to
5693da084b3Smrg   the glyph index before applying the cmap.  Lovely design. */
5703da084b3Smrg
571e1c0d025Smrgstatic FontMapRec microsoft_symbol[] = {
572e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 3, 0, NULL, NULL, NULL, NULL, NULL},
573e1c0d025Smrg    /* You never know */
574e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 3, 1, NULL, NULL, NULL, NULL, NULL},
575e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
576e1c0d025Smrg};
5773da084b3Smrg
578e1c0d025Smrgstatic FontMapRec apple_roman[] = {
579e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 1, 0, NULL, NULL, NULL, NULL, NULL},
580e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
581e1c0d025Smrg};
5823da084b3Smrg
5833da084b3Smrg/* The data for recodings */
5843da084b3Smrg
5853da084b3Smrg/* For compatibility with X11R6.4.  Losers. */
586e1c0d025Smrgstatic char *iso8859_15_aliases[2] = { "fcd8859-15", NULL };
587e1c0d025Smrg
588e1c0d025Smrgstatic FontEncRec initial_encodings[] = {
589e1c0d025Smrg    {"iso10646-1", NULL, 256 * 256, 0, iso10646, NULL, 0, 0},   /* Unicode */
590e1c0d025Smrg    {"iso8859-1", NULL, 256, 0, iso8859_1, NULL, 0, 0}, /* Latin 1 (West European) */
591e1c0d025Smrg    {"iso8859-2", NULL, 256, 0, iso8859_2, NULL, 0, 0}, /* Latin 2 (East European) */
592e1c0d025Smrg    {"iso8859-3", NULL, 256, 0, iso8859_3, NULL, 0, 0}, /* Latin 3 (South European) */
593e1c0d025Smrg    {"iso8859-4", NULL, 256, 0, iso8859_4, NULL, 0, 0}, /* Latin 4 (North European) */
594e1c0d025Smrg    {"iso8859-5", NULL, 256, 0, iso8859_5, NULL, 0, 0}, /* Cyrillic */
595e1c0d025Smrg    {"iso8859-6", NULL, 256, 0, iso8859_6, NULL, 0, 0}, /* Arabic */
596e1c0d025Smrg    {"iso8859-7", NULL, 256, 0, iso8859_7, NULL, 0, 0}, /* Greek */
597e1c0d025Smrg    {"iso8859-8", NULL, 256, 0, iso8859_8, NULL, 0, 0}, /* Hebrew */
598e1c0d025Smrg    {"iso8859-9", NULL, 256, 0, iso8859_9, NULL, 0, 0}, /* Latin 5 (Turkish) */
599e1c0d025Smrg    {"iso8859-10", NULL, 256, 0, iso8859_10, NULL, 0, 0},       /* Latin 6 (Nordic) */
600e1c0d025Smrg    {"iso8859-15", iso8859_15_aliases, 256, 0, iso8859_15, NULL, 0, 0}, /* Latin 9 */
601e1c0d025Smrg    {"koi8-r", NULL, 256, 0, koi8_r, NULL, 0, 0},       /* Russian */
602e1c0d025Smrg    {"koi8-ru", NULL, 256, 0, koi8_ru, NULL, 0, 0},     /* Ukrainian */
603e1c0d025Smrg    {"koi8-uni", NULL, 256, 0, koi8_uni, NULL, 0, 0},   /* Russian/Ukrainian/Bielorussian */
604e1c0d025Smrg    {"koi8-e", NULL, 256, 0, koi8_e, NULL, 0, 0},       /* ``European'' */
605e1c0d025Smrg    {"koi8-u", NULL, 256, 0, koi8_u, NULL, 0, 0},       /* Ukrainian too */
606e1c0d025Smrg    {"microsoft-symbol", NULL, 256, 0, microsoft_symbol, NULL, 0, 0},
607e1c0d025Smrg    {"apple-roman", NULL, 256, 0, apple_roman, NULL, 0, 0},
608e1c0d025Smrg    {NULL, NULL, 0, 0, NULL, NULL, 0, 0}
6093da084b3Smrg};
6103da084b3Smrg
611e1c0d025Smrgstatic FontEncPtr font_encodings = NULL;
6123da084b3Smrg
6133da084b3Smrgstatic void
6143da084b3Smrgdefine_initial_encoding_info(void)
6153da084b3Smrg{
6163da084b3Smrg    FontEncPtr encoding;
6173da084b3Smrg    FontMapPtr mapping;
6183da084b3Smrg
6193da084b3Smrg    font_encodings = initial_encodings;
620e1c0d025Smrg    for (encoding = font_encodings; ; encoding++) {
6213da084b3Smrg        encoding->next = encoding + 1;
622e1c0d025Smrg        for (mapping = encoding->mappings; ; mapping++) {
623e1c0d025Smrg            mapping->next = mapping + 1;
6243da084b3Smrg            mapping->encoding = encoding;
625e1c0d025Smrg            if (mapping->next->type == 0) {
6263da084b3Smrg                mapping->next = NULL;
6273da084b3Smrg                break;
6283da084b3Smrg            }
6293da084b3Smrg        }
630e1c0d025Smrg        if (!encoding->next->name) {
6313da084b3Smrg            encoding->next = NULL;
6323da084b3Smrg            break;
6333da084b3Smrg        }
6343da084b3Smrg    }
6353da084b3Smrg}
6363da084b3Smrg
637e1c0d025Smrgchar *
6383da084b3SmrgFontEncFromXLFD(const char *name, int length)
6393da084b3Smrg{
6403da084b3Smrg    const char *p;
6413da084b3Smrg    char *q;
6423da084b3Smrg    static char charset[MAXFONTNAMELEN];
6433da084b3Smrg    int len;
6443da084b3Smrg
645e1c0d025Smrg    if (length > MAXFONTNAMELEN - 1)
6463da084b3Smrg        return NULL;
6473da084b3Smrg
648e1c0d025Smrg    if (name == NULL)
6493da084b3Smrg        p = NULL;
6503da084b3Smrg    else {
6513da084b3Smrg        p = name + length - 1;
652e1c0d025Smrg        while (p > name && *p != '-')
6533da084b3Smrg            p--;
6543da084b3Smrg        p--;
655e1c0d025Smrg        while (p >= name && *p != '-')
6563da084b3Smrg            p--;
657e1c0d025Smrg        if (p <= name)
6583da084b3Smrg            p = NULL;
6593da084b3Smrg    }
6603da084b3Smrg
6613da084b3Smrg    /* now p either is null or points at the '-' before the charset registry */
662d63fdb69Smrg
663e1c0d025Smrg    if (p == NULL)
6643da084b3Smrg        return NULL;
66548c85eb7Smrg
6663da084b3Smrg    len = length - (p - name) - 1;
667e1c0d025Smrg    memcpy(charset, p + 1, len);
6683da084b3Smrg    charset[len] = 0;
66948c85eb7Smrg
6703da084b3Smrg    /* check for a subset specification */
671e1c0d025Smrg    if ((q = strchr(charset, (int) '[')))
6723da084b3Smrg        *q = 0;
67348c85eb7Smrg
6743da084b3Smrg    return charset;
6753da084b3Smrg}
6763da084b3Smrg
6773da084b3Smrgunsigned
678e1c0d025SmrgFontEncRecode(unsigned code, FontMapPtr mapping)
6793da084b3Smrg{
6803da084b3Smrg    FontEncPtr encoding = mapping->encoding;
681e1c0d025Smrg
682e1c0d025Smrg    if (encoding && mapping->recode) {
683e1c0d025Smrg        if (encoding->row_size == 0) {
6843da084b3Smrg            /* linear encoding */
685e1c0d025Smrg            if (code < encoding->first || code >= encoding->size)
6863da084b3Smrg                return 0;
687e1c0d025Smrg        }
688e1c0d025Smrg        else {
6893da084b3Smrg            /* matrix encoding */
690e1c0d025Smrg            int row = code / 0x100, col = code & 0xFF;
691e1c0d025Smrg
692e1c0d025Smrg            if (row < encoding->first || row >= encoding->size ||
693e1c0d025Smrg                col < encoding->first_col || col >= encoding->row_size)
6943da084b3Smrg                return 0;
6953da084b3Smrg        }
696e1c0d025Smrg        return (*mapping->recode) (code, mapping->client_data);
697e1c0d025Smrg    }
698e1c0d025Smrg    else
6993da084b3Smrg        return code;
7003da084b3Smrg}
7013da084b3Smrg
702e1c0d025Smrgchar *
7033da084b3SmrgFontEncName(unsigned code, FontMapPtr mapping)
7043da084b3Smrg{
7053da084b3Smrg    FontEncPtr encoding = mapping->encoding;
706e1c0d025Smrg
707e1c0d025Smrg    if (encoding && mapping->name) {
708e1c0d025Smrg        if ((encoding->row_size == 0 && code >= encoding->size) ||
709e1c0d025Smrg            (encoding->row_size != 0 &&
710e1c0d025Smrg             (code / 0x100 >= encoding->size ||
711e1c0d025Smrg              (code & 0xFF) >= encoding->row_size)))
7123da084b3Smrg            return NULL;
713e1c0d025Smrg        return (*mapping->name) (code, mapping->client_data);
714e1c0d025Smrg    }
715e1c0d025Smrg    else
7163da084b3Smrg        return NULL;
7173da084b3Smrg}
7183da084b3Smrg
7193da084b3SmrgFontEncPtr
7203da084b3SmrgFontEncFind(const char *encoding_name, const char *filename)
7213da084b3Smrg{
7223da084b3Smrg    FontEncPtr encoding;
7233da084b3Smrg    char **alias;
72448c85eb7Smrg
725e1c0d025Smrg    if (font_encodings == NULL)
726e1c0d025Smrg        define_initial_encoding_info();
72748c85eb7Smrg
728e1c0d025Smrg    for (encoding = font_encodings; encoding; encoding = encoding->next) {
729e1c0d025Smrg        if (!strcasecmp(encoding->name, encoding_name))
7303da084b3Smrg            return encoding;
731e1c0d025Smrg        if (encoding->aliases)
732e1c0d025Smrg            for (alias = encoding->aliases; *alias; alias++)
733e1c0d025Smrg                if (!strcasecmp(*alias, encoding_name))
7343da084b3Smrg                    return encoding;
735e1c0d025Smrg    }
7363da084b3Smrg
737e1c0d025Smrg    /* Unknown charset, try to load a definition file */
7383da084b3Smrg    return FontEncLoad(encoding_name, filename);
7393da084b3Smrg}
7403da084b3Smrg
7413da084b3SmrgFontMapPtr
7423da084b3SmrgFontMapFind(FontEncPtr encoding, int type, int pid, int eid)
7433da084b3Smrg{
7443da084b3Smrg    FontMapPtr mapping;
745e1c0d025Smrg
746e1c0d025Smrg    if (encoding == NULL)
7473da084b3Smrg        return NULL;
7483da084b3Smrg
749e1c0d025Smrg    for (mapping = encoding->mappings; mapping; mapping = mapping->next) {
750e1c0d025Smrg        if (mapping->type != type)
7513da084b3Smrg            continue;
752e1c0d025Smrg        if (pid > 0 && mapping->pid != pid)
7533da084b3Smrg            continue;
754e1c0d025Smrg        if (eid > 0 && mapping->eid != eid)
7553da084b3Smrg            continue;
7563da084b3Smrg        return mapping;
7573da084b3Smrg    }
7583da084b3Smrg    return NULL;
7593da084b3Smrg}
7603da084b3Smrg
7613da084b3SmrgFontMapPtr
7623da084b3SmrgFontEncMapFind(const char *encoding_name, int type, int pid, int eid,
7633da084b3Smrg               const char *filename)
7643da084b3Smrg{
7653da084b3Smrg    FontEncPtr encoding;
7663da084b3Smrg    FontMapPtr mapping;
7673da084b3Smrg
7683da084b3Smrg    encoding = FontEncFind(encoding_name, filename);
769e1c0d025Smrg    if (encoding == NULL)
7703da084b3Smrg        return NULL;
7713da084b3Smrg    mapping = FontMapFind(encoding, type, pid, eid);
7723da084b3Smrg    return mapping;
7733da084b3Smrg}
7743da084b3Smrg
7753da084b3Smrgstatic FontEncPtr
7763da084b3SmrgFontEncLoad(const char *encoding_name, const char *filename)
7773da084b3Smrg{
7783da084b3Smrg    FontEncPtr encoding;
77948c85eb7Smrg
7803da084b3Smrg    encoding = FontEncReallyLoad(encoding_name, filename);
7813da084b3Smrg    if (encoding == NULL) {
7823da084b3Smrg        return NULL;
783e1c0d025Smrg    }
784e1c0d025Smrg    else {
7853da084b3Smrg        char **alias;
7863da084b3Smrg        int found = 0;
78748c85eb7Smrg
7883da084b3Smrg        /* Check whether the name is already known for this encoding */
789e1c0d025Smrg        if (strcasecmp(encoding->name, encoding_name) == 0) {
7903da084b3Smrg            found = 1;
791e1c0d025Smrg        }
792e1c0d025Smrg        else {
793e1c0d025Smrg            if (encoding->aliases) {
794e1c0d025Smrg                for (alias = encoding->aliases; *alias; alias++)
795e1c0d025Smrg                    if (!strcasecmp(*alias, encoding_name)) {
7963da084b3Smrg                        found = 1;
7973da084b3Smrg                        break;
7983da084b3Smrg                    }
7993da084b3Smrg            }
8003da084b3Smrg        }
80148c85eb7Smrg
802e1c0d025Smrg        if (!found) {
8033da084b3Smrg            /* Add a new alias.  This works because we know that this
8043da084b3Smrg               particular encoding has been allocated dynamically */
8053da084b3Smrg            char **new_aliases;
8063da084b3Smrg            char *new_name;
8073da084b3Smrg            int numaliases = 0;
80848c85eb7Smrg
80955acc8fcSmrg            new_name = strdup(encoding_name);
810e1c0d025Smrg            if (new_name == NULL)
8113da084b3Smrg                return NULL;
812e1c0d025Smrg            if (encoding->aliases) {
813e1c0d025Smrg                for (alias = encoding->aliases; *alias; alias++)
8143da084b3Smrg                    numaliases++;
8153da084b3Smrg            }
8162a53b785Smrg            new_aliases = Xmallocarray(numaliases + 2, sizeof(char *));
817e1c0d025Smrg            if (new_aliases == NULL) {
81855acc8fcSmrg                free(new_name);
8193da084b3Smrg                return NULL;
8203da084b3Smrg            }
821e1c0d025Smrg            if (encoding->aliases) {
822e1c0d025Smrg                memcpy(new_aliases, encoding->aliases,
823e1c0d025Smrg                       numaliases * sizeof(char *));
82455acc8fcSmrg                free(encoding->aliases);
8253da084b3Smrg            }
8263da084b3Smrg            new_aliases[numaliases] = new_name;
827e1c0d025Smrg            new_aliases[numaliases + 1] = NULL;
8283da084b3Smrg            encoding->aliases = new_aliases;
8293da084b3Smrg        }
83048c85eb7Smrg
8313da084b3Smrg        /* register the new encoding */
832e1c0d025Smrg        encoding->next = font_encodings;
833e1c0d025Smrg        font_encodings = encoding;
83448c85eb7Smrg
8353da084b3Smrg        return encoding;
8363da084b3Smrg    }
8373da084b3Smrg}
8383da084b3Smrg
8393da084b3Smrgunsigned
8403da084b3SmrgFontEncSimpleRecode(unsigned code, void *client_data)
8413da084b3Smrg{
8423da084b3Smrg    FontEncSimpleMapPtr map;
8433da084b3Smrg    unsigned index;
8443da084b3Smrg
8453da084b3Smrg    map = client_data;
8463da084b3Smrg
847e1c0d025Smrg    if (code > 0xFFFF || (map->row_size && (code & 0xFF) >= map->row_size))
8483da084b3Smrg        return 0;
8493da084b3Smrg
850e1c0d025Smrg    if (map->row_size)
851e1c0d025Smrg        index = (code & 0xFF) + (code >> 8) * map->row_size;
8523da084b3Smrg    else
8533da084b3Smrg        index = code;
8543da084b3Smrg
855e1c0d025Smrg    if (map->map && index >= map->first && index < map->first + map->len)
856e1c0d025Smrg        return map->map[index - map->first];
857e1c0d025Smrg    else
858e1c0d025Smrg        return code;
8593da084b3Smrg}
8603da084b3Smrg
8613da084b3Smrgchar *
8623da084b3SmrgFontEncSimpleName(unsigned code, void *client_data)
8633da084b3Smrg{
8643da084b3Smrg    FontEncSimpleNamePtr map;
8653da084b3Smrg
8663da084b3Smrg    map = client_data;
867e1c0d025Smrg    if (map && code >= map->first && code < map->first + map->len)
868e1c0d025Smrg        return map->map[code - map->first];
8693da084b3Smrg    else
8703da084b3Smrg        return NULL;
8713da084b3Smrg}
8723da084b3Smrg
8733da084b3Smrgunsigned
8743da084b3SmrgFontEncUndefinedRecode(unsigned code, void *client_data)
8753da084b3Smrg{
8763da084b3Smrg    return code;
8773da084b3Smrg}
8783da084b3Smrg
8793da084b3Smrgchar *
8803da084b3SmrgFontEncUndefinedName(unsigned code, void *client_data)
8813da084b3Smrg{
8823da084b3Smrg    return NULL;
8833da084b3Smrg}
8843da084b3Smrg
8853da084b3Smrg#define FONTENC_SEGMENT_SIZE 256
8863da084b3Smrg#define FONTENC_SEGMENTS 256
8873da084b3Smrg#define FONTENC_INVERSE_CODES (FONTENC_SEGMENT_SIZE * FONTENC_SEGMENTS)
8883da084b3Smrg
8893da084b3Smrgstatic unsigned int
890e1c0d025Smrgreverse_reverse(unsigned i, void *data)
8913da084b3Smrg{
8923da084b3Smrg    int s, j;
893e1c0d025Smrg    unsigned **map = (unsigned **) data;
8943da084b3Smrg
895e1c0d025Smrg    if (i >= FONTENC_INVERSE_CODES)
8963da084b3Smrg        return 0;
8973da084b3Smrg
898e1c0d025Smrg    if (map == NULL)
8993da084b3Smrg        return 0;
9003da084b3Smrg
9013da084b3Smrg    s = i / FONTENC_SEGMENT_SIZE;
9023da084b3Smrg    j = i % FONTENC_SEGMENT_SIZE;
9033da084b3Smrg
904e1c0d025Smrg    if (map[s] == NULL)
9053da084b3Smrg        return 0;
9063da084b3Smrg    else
9073da084b3Smrg        return map[s][j];
9083da084b3Smrg}
9093da084b3Smrg
9103da084b3Smrgstatic int
9113da084b3Smrgtree_set(unsigned int **map, unsigned int i, unsigned int j)
9123da084b3Smrg{
9133da084b3Smrg    int s, c;
9143da084b3Smrg
915e1c0d025Smrg    if (i >= FONTENC_INVERSE_CODES)
9163da084b3Smrg        return FALSE;
9173da084b3Smrg
9183da084b3Smrg    s = i / FONTENC_SEGMENT_SIZE;
9193da084b3Smrg    c = i % FONTENC_SEGMENT_SIZE;
9203da084b3Smrg
921e1c0d025Smrg    if (map[s] == NULL) {
92248c85eb7Smrg        map[s] = calloc(FONTENC_SEGMENT_SIZE, sizeof(int));
923e1c0d025Smrg        if (map[s] == NULL)
9243da084b3Smrg            return FALSE;
925e1c0d025Smrg    }
9263da084b3Smrg
9273da084b3Smrg    map[s][c] = j;
9283da084b3Smrg    return TRUE;
9293da084b3Smrg}
9303da084b3Smrg
9313da084b3SmrgFontMapReversePtr
9323da084b3SmrgFontMapReverse(FontMapPtr mapping)
9333da084b3Smrg{
9343da084b3Smrg    FontEncPtr encoding = mapping->encoding;
9353da084b3Smrg    FontMapReversePtr reverse = NULL;
9363da084b3Smrg    unsigned int **map = NULL;
9373da084b3Smrg    int i, j, k;
9383da084b3Smrg
939e1c0d025Smrg    if (encoding == NULL)
940e1c0d025Smrg        goto bail;
9413da084b3Smrg
942e1c0d025Smrg    map = calloc(FONTENC_SEGMENTS, sizeof(int *));
943e1c0d025Smrg    if (map == NULL)
944e1c0d025Smrg        goto bail;
9453da084b3Smrg
946e1c0d025Smrg    if (encoding->row_size == 0) {
947e1c0d025Smrg        for (i = encoding->first; i < encoding->size; i++) {
9483da084b3Smrg            k = FontEncRecode(i, mapping);
949e1c0d025Smrg            if (k != 0)
950e1c0d025Smrg                if (!tree_set(map, k, i))
9513da084b3Smrg                    goto bail;
9523da084b3Smrg        }
953e1c0d025Smrg    }
954e1c0d025Smrg    else {
955e1c0d025Smrg        for (i = encoding->first; i < encoding->size; i++) {
956e1c0d025Smrg            for (j = encoding->first_col; j < encoding->row_size; j++) {
957e1c0d025Smrg                k = FontEncRecode(i * 256 + j, mapping);
958e1c0d025Smrg                if (k != 0)
959e1c0d025Smrg                    if (!tree_set(map, k, i * 256 + j))
9603da084b3Smrg                        goto bail;
9613da084b3Smrg            }
9623da084b3Smrg        }
9633da084b3Smrg    }
9643da084b3Smrg
9653da084b3Smrg    reverse = malloc(sizeof(FontMapReverseRec));
966e1c0d025Smrg    if (!reverse)
967e1c0d025Smrg        goto bail;
9683da084b3Smrg
9693da084b3Smrg    reverse->reverse = reverse_reverse;
9703da084b3Smrg    reverse->data = map;
9713da084b3Smrg    return reverse;
9723da084b3Smrg
973e1c0d025Smrg bail:
97455acc8fcSmrg    free(map);
97555acc8fcSmrg    free(reverse);
9763da084b3Smrg    return NULL;
9773da084b3Smrg}
9783da084b3Smrg
9793da084b3Smrgvoid
9803da084b3SmrgFontMapReverseFree(FontMapReversePtr delendum)
9813da084b3Smrg{
982e1c0d025Smrg    unsigned int **map = (unsigned int **) delendum;
9833da084b3Smrg    int i;
98448c85eb7Smrg
985e1c0d025Smrg    if (map == NULL)
9863da084b3Smrg        return;
9873da084b3Smrg
988e1c0d025Smrg    for (i = 0; i < FONTENC_SEGMENTS; i++)
989e1c0d025Smrg        free(map[i]);
9903da084b3Smrg
99155acc8fcSmrg    free(map);
9923da084b3Smrg    return;
9933da084b3Smrg}
994