fontenc.c revision 52fd71cd
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
253da084b3Smrg#include <string.h>
263da084b3Smrg#include <strings.h>
273da084b3Smrg#include <stdlib.h>
2855acc8fcSmrg
293da084b3Smrg#define FALSE 0
303da084b3Smrg#define TRUE 1
313da084b3Smrg#define MAXFONTNAMELEN 1024
323da084b3Smrg#define MAXFONTFILENAMELEN 1024
333da084b3Smrg
343da084b3Smrg#include <X11/fonts/fontenc.h>
353da084b3Smrg#include "fontencI.h"
363da084b3Smrg
373da084b3Smrg/* Functions local to this file */
383da084b3Smrg
39e1c0d025Smrgstatic FontEncPtr FontEncLoad(const char *, const char *);
403da084b3Smrg
413da084b3Smrg/* Early versions of this code only knew about hardwired encodings,
423da084b3Smrg   hence the following data.  Now that the code knows how to load an
433da084b3Smrg   encoding from a file, most of these tables could go away. */
443da084b3Smrg
453da084b3Smrg/* At any rate, no new hardcoded encodings will be added. */
463da084b3Smrg
47e1c0d025Smrgstatic FontMapRec iso10646[] = {
48e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, NULL, NULL, NULL, NULL, NULL},
49e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
503da084b3Smrg};
513da084b3Smrg
523da084b3Smrg/* Notice that the Apple encodings do not have all the characters in
533da084b3Smrg   the corresponding ISO 8859, and therefore the table has some holes.
543da084b3Smrg   There's not much more we can do with fonts without a Unicode cmap
553da084b3Smrg   unless we are willing to combine cmaps (which we are not). */
563da084b3Smrg
5748c85eb7Smrgstatic const unsigned short
58e1c0d025Smrg iso8859_1_apple_roman[] = {
59e1c0d025Smrg    0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0x00, 0xA4,
60e1c0d025Smrg    0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0x00, 0xA8, 0xF8,
61e1c0d025Smrg    0xA1, 0xB1, 0x00, 0x00, 0xAB, 0xB5, 0xA6, 0xE1,
62e1c0d025Smrg    0xFC, 0x00, 0xBC, 0xC8, 0x00, 0x00, 0x00, 0xC0,
63e1c0d025Smrg    0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82,
64e1c0d025Smrg    0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC,
65e1c0d025Smrg    0x00, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0x00,
66e1c0d025Smrg    0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0x00, 0x00, 0xA7,
67e1c0d025Smrg    0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D,
68e1c0d025Smrg    0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
69e1c0d025Smrg    0x00, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6,
70e1c0d025Smrg    0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0x00, 0x00, 0xD8
71e1c0d025Smrg};
723da084b3Smrg
733da084b3Smrg/* Cannot use simple_recode because need to eliminate 0x80<=code<0xA0 */
743da084b3Smrgstatic unsigned
753da084b3Smrgiso8859_1_to_apple_roman(unsigned isocode, void *client_data)
763da084b3Smrg{
77e1c0d025Smrg    if (isocode <= 0x80)
783da084b3Smrg        return isocode;
79e1c0d025Smrg    else if (isocode >= 0xA0)
80e1c0d025Smrg        return iso8859_1_apple_roman[isocode - 0xA0];
813da084b3Smrg    else
823da084b3Smrg        return 0;
833da084b3Smrg}
843da084b3Smrg
85e1c0d025Smrgstatic FontMapRec iso8859_1[] = {
86e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 2, 2, NULL, NULL, NULL, NULL, NULL},       /* ISO 8859-1 */
87e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, NULL, NULL, NULL, NULL, NULL},        /* ISO 8859-1 coincides with Unicode */
88e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 1, 0, iso8859_1_to_apple_roman, NULL, NULL, NULL,
89e1c0d025Smrg     NULL},
90e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
913da084b3Smrg};
923da084b3Smrg
93e1c0d025Smrgstatic const unsigned short iso8859_2_tophalf[] = {
94e1c0d025Smrg    0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
95e1c0d025Smrg    0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
96e1c0d025Smrg    0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
97e1c0d025Smrg    0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
98e1c0d025Smrg    0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
99e1c0d025Smrg    0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
100e1c0d025Smrg    0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
101e1c0d025Smrg    0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
102e1c0d025Smrg    0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
103e1c0d025Smrg    0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
104e1c0d025Smrg    0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
105e1c0d025Smrg    0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
106e1c0d025Smrg};
107e1c0d025Smrg
108e1c0d025Smrgstatic FontEncSimpleMapRec iso8859_2_to_unicode_map =
109e1c0d025Smrg    { 0x60, 0, 0xA0, iso8859_2_tophalf };
110e1c0d025Smrg
111e1c0d025Smrgstatic const unsigned short iso8859_2_apple_centeuro[] = {
112e1c0d025Smrg    0xCA, 0x84, 0x00, 0xFC, 0x00, 0xBB, 0xE5, 0xA4,
113e1c0d025Smrg    0xAC, 0xE1, 0x00, 0xE8, 0x8F, 0x00, 0xEB, 0xFB,
114e1c0d025Smrg    0xA1, 0x88, 0x00, 0xB8, 0x00, 0xBC, 0xE6, 0xFF,
115e1c0d025Smrg    0x00, 0xE4, 0x00, 0xE9, 0x90, 0x00, 0xEC, 0xFD,
116e1c0d025Smrg    0xD9, 0xE7, 0x00, 0x00, 0x80, 0xBD, 0x8C, 0x00,
117e1c0d025Smrg    0x89, 0x83, 0xA2, 0x00, 0x9D, 0xEA, 0x00, 0x91,
118e1c0d025Smrg    0x00, 0xC1, 0xC5, 0xEE, 0xEF, 0xCC, 0x85, 0x00,
119e1c0d025Smrg    0xDB, 0xF1, 0xF2, 0xF4, 0x86, 0xF8, 0x00, 0xA7,
120e1c0d025Smrg    0xDA, 0x87, 0x00, 0x00, 0x8A, 0xBE, 0x8D, 0x00,
121e1c0d025Smrg    0x8B, 0x8E, 0xAB, 0x00, 0x9E, 0x92, 0x00, 0x93,
122e1c0d025Smrg    0x00, 0xC4, 0xCB, 0x97, 0x99, 0xCE, 0x9A, 0xD6,
123e1c0d025Smrg    0xDE, 0xF3, 0x9C, 0xF5, 0x9F, 0xF9, 0x00, 0x00
124e1c0d025Smrg};
1253da084b3Smrg
1263da084b3Smrgstatic unsigned
1273da084b3Smrgiso8859_2_to_apple_centeuro(unsigned isocode, void *client_data)
1283da084b3Smrg{
129e1c0d025Smrg    if (isocode <= 0x80)
1303da084b3Smrg        return isocode;
131e1c0d025Smrg    else if (isocode >= 0xA0)
132e1c0d025Smrg        return iso8859_2_apple_centeuro[isocode - 0xA0];
1333da084b3Smrg    else
1343da084b3Smrg        return 0;
1353da084b3Smrg}
1363da084b3Smrg
137e1c0d025Smrgstatic FontMapRec iso8859_2[] = {
138e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0,
139e1c0d025Smrg     FontEncSimpleRecode, NULL, &iso8859_2_to_unicode_map, NULL, NULL},
140e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 1, 29, iso8859_2_to_apple_centeuro, NULL, NULL,
141e1c0d025Smrg     NULL, NULL},
142e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
1433da084b3Smrg};
1443da084b3Smrg
145e1c0d025Smrgstatic const unsigned short iso8859_3_tophalf[] = {
146e1c0d025Smrg    0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0x0000, 0x0124, 0x00A7,
147e1c0d025Smrg    0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0x0000, 0x017B,
148e1c0d025Smrg    0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7,
149e1c0d025Smrg    0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0x0000, 0x017C,
150e1c0d025Smrg    0x00C0, 0x00C1, 0x00C2, 0x0000, 0x00C4, 0x010A, 0x0108, 0x00C7,
151e1c0d025Smrg    0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
152e1c0d025Smrg    0x0000, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7,
153e1c0d025Smrg    0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF,
154e1c0d025Smrg    0x00E0, 0x00E1, 0x00E2, 0x0000, 0x00E4, 0x010B, 0x0109, 0x00E7,
155e1c0d025Smrg    0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
156e1c0d025Smrg    0x0000, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7,
157e1c0d025Smrg    0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9
1583da084b3Smrg};
1593da084b3Smrg
160e1c0d025Smrgstatic FontEncSimpleMapRec iso8859_3_to_unicode_map =
161e1c0d025Smrg    { 0x60, 0, 0xA0, iso8859_3_tophalf };
1623da084b3Smrg
163e1c0d025Smrgstatic FontMapRec iso8859_3[] = {
164e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0,
165e1c0d025Smrg     FontEncSimpleRecode, NULL, &iso8859_3_to_unicode_map, NULL, NULL},
166e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
1673da084b3Smrg};
1683da084b3Smrg
169e1c0d025Smrgstatic const unsigned short iso8859_4_tophalf[] = {
170e1c0d025Smrg    0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7,
171e1c0d025Smrg    0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF,
172e1c0d025Smrg    0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7,
173e1c0d025Smrg    0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B,
174e1c0d025Smrg    0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
175e1c0d025Smrg    0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A,
176e1c0d025Smrg    0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
177e1c0d025Smrg    0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF,
178e1c0d025Smrg    0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
179e1c0d025Smrg    0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B,
180e1c0d025Smrg    0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
181e1c0d025Smrg    0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9,
182e1c0d025Smrg};
1833da084b3Smrg
184e1c0d025Smrgstatic FontEncSimpleMapRec iso8859_4_to_unicode_map =
185e1c0d025Smrg    { 0x60, 0, 0xA0, iso8859_4_tophalf };
186e1c0d025Smrg
187e1c0d025Smrgstatic FontMapRec iso8859_4[] = {
188e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, FontEncSimpleRecode, NULL,
189e1c0d025Smrg     &iso8859_4_to_unicode_map, NULL, NULL},
190e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
1913da084b3Smrg};
1923da084b3Smrg
193e1c0d025Smrgstatic const unsigned short iso8859_5_tophalf[] = {
194e1c0d025Smrg    0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
195e1c0d025Smrg    0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
196e1c0d025Smrg    0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
197e1c0d025Smrg    0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
198e1c0d025Smrg    0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
199e1c0d025Smrg    0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
200e1c0d025Smrg    0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
201e1c0d025Smrg    0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
202e1c0d025Smrg    0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
203e1c0d025Smrg    0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
204e1c0d025Smrg    0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
205e1c0d025Smrg    0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F
206e1c0d025Smrg};
2073da084b3Smrg
208e1c0d025Smrgstatic FontEncSimpleMapRec iso8859_5_to_unicode_map =
209e1c0d025Smrg    { 0x60, 0, 0xA0, iso8859_5_tophalf };
210e1c0d025Smrg
211e1c0d025Smrgstatic const unsigned short iso8859_5_apple_cyrillic[] = {
212e1c0d025Smrg    0xCA, 0xDD, 0xAB, 0xAE, 0xB8, 0xC1, 0xA7, 0xBA,
213e1c0d025Smrg    0xB7, 0xBC, 0xBE, 0xCB, 0xCD, 0x00, 0xD8, 0xDA,
214e1c0d025Smrg    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
215e1c0d025Smrg    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
216e1c0d025Smrg    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
217e1c0d025Smrg    0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
218e1c0d025Smrg    0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
219e1c0d025Smrg    0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
220e1c0d025Smrg    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
221e1c0d025Smrg    0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF,
222e1c0d025Smrg    0xDC, 0xDE, 0xAC, 0xAF, 0xB9, 0xCF, 0xB4, 0xBB,
223e1c0d025Smrg    0xC0, 0xBD, 0xBF, 0xCC, 0xCE, 0xA4, 0xD9, 0xDB
224e1c0d025Smrg};
2253da084b3Smrg
2263da084b3Smrgstatic unsigned
2273da084b3Smrgiso8859_5_to_apple_cyrillic(unsigned isocode, void *client_data)
2283da084b3Smrg{
229e1c0d025Smrg    if (isocode <= 0x80)
2303da084b3Smrg        return isocode;
231e1c0d025Smrg    else if (isocode >= 0xA0)
232e1c0d025Smrg        return iso8859_5_apple_cyrillic[isocode - 0x80];
233e1c0d025Smrg    else
234e1c0d025Smrg        return 0;
2353da084b3Smrg}
2363da084b3Smrg
237e1c0d025Smrgstatic FontMapRec iso8859_5[] = {
238e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, FontEncSimpleRecode, NULL,
239e1c0d025Smrg     &iso8859_5_to_unicode_map, NULL, NULL},
240e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 1, 7, iso8859_5_to_apple_cyrillic, NULL, NULL,
241e1c0d025Smrg     NULL, NULL},
242e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
2433da084b3Smrg};
2443da084b3Smrg
2453da084b3Smrg/* ISO 8859-6 seems useless for serving fonts (not enough presentation
2463da084b3Smrg * forms).  What do Arabic-speakers use? */
2473da084b3Smrg
2483da084b3Smrgstatic unsigned
2493da084b3Smrgiso8859_6_to_unicode(unsigned isocode, void *client_data)
2503da084b3Smrg{
251e1c0d025Smrg    if (isocode <= 0xA0 || isocode == 0xA4 || isocode == 0xAD)
2523da084b3Smrg        return isocode;
253e1c0d025Smrg    else if (isocode == 0xAC || isocode == 0xBB ||
254e1c0d025Smrg             isocode == 0xBF ||
255e1c0d025Smrg             (isocode >= 0xC1 && isocode <= 0xDA) ||
256e1c0d025Smrg             (isocode >= 0xE0 && isocode <= 0xEF) ||
257e1c0d025Smrg             (isocode >= 0xF0 && isocode <= 0xF2))
258e1c0d025Smrg        return isocode - 0xA0 + 0x0600;
2593da084b3Smrg    else
2603da084b3Smrg        return 0;
2613da084b3Smrg}
2623da084b3Smrg
263e1c0d025Smrgstatic FontMapRec iso8859_6[] = {
264e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, iso8859_6_to_unicode, NULL, NULL, NULL, NULL},
265e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
2663da084b3Smrg};
2673da084b3Smrg
26848c85eb7Smrgstatic unsigned
2693da084b3Smrgiso8859_7_to_unicode(unsigned isocode, void *client_data)
2703da084b3Smrg{
271e1c0d025Smrg    if (isocode <= 0xA0 ||
272e1c0d025Smrg        (isocode >= 0xA3 && isocode <= 0xAD) ||
273e1c0d025Smrg        (isocode >= 0xB0 && isocode <= 0xB3) ||
274e1c0d025Smrg        isocode == 0xB7 || isocode == 0xBB || isocode == 0xBD)
2753da084b3Smrg        return isocode;
276e1c0d025Smrg    else if (isocode == 0xA1)
27752fd71cdSmrg        return 0x2018;
278e1c0d025Smrg    else if (isocode == 0xA2)
27952fd71cdSmrg        return 0x2019;
280e1c0d025Smrg    else if (isocode == 0xAF)
2813da084b3Smrg        return 0x2015;
282e1c0d025Smrg    else if (isocode == 0xD2)   /* unassigned */
28348c85eb7Smrg        return 0;
28452fd71cdSmrg    else if (isocode >= 0xB4 && isocode <= 0xFE)
285e1c0d025Smrg        return isocode - 0xA0 + 0x0370;
2863da084b3Smrg    else
2873da084b3Smrg        return 0;
2883da084b3Smrg}
2893da084b3Smrg
290e1c0d025Smrgstatic FontMapRec iso8859_7[] = {
291e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, iso8859_7_to_unicode, NULL, NULL, NULL, NULL},
292e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
2933da084b3Smrg};
2943da084b3Smrg
2953da084b3Smrgstatic unsigned
2963da084b3Smrgiso8859_8_to_unicode(unsigned isocode, void *client_data)
2973da084b3Smrg{
298e1c0d025Smrg    if (isocode == 0xA1)
2993da084b3Smrg        return 0;
300e1c0d025Smrg    else if (isocode < 0xBF)
3013da084b3Smrg        return isocode;
302e1c0d025Smrg    else if (isocode == 0xDF)
3033da084b3Smrg        return 0x2017;
304e1c0d025Smrg    else if (isocode >= 0xE0 && isocode <= 0xFA)
305e1c0d025Smrg        return isocode + 0x04F0;
30648c85eb7Smrg    else
3073da084b3Smrg        return 0;
3083da084b3Smrg}
3093da084b3Smrg
310e1c0d025Smrgstatic FontMapRec iso8859_8[] = {
311e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, iso8859_8_to_unicode, NULL, NULL, NULL, NULL},
312e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
3133da084b3Smrg};
3143da084b3Smrg
3153da084b3Smrgstatic unsigned
3163da084b3Smrgiso8859_9_to_unicode(unsigned isocode, void *client_data)
3173da084b3Smrg{
318e1c0d025Smrg    switch (isocode) {
319e1c0d025Smrg    case 0xD0:
320e1c0d025Smrg        return 0x011E;
321e1c0d025Smrg    case 0xDD:
322e1c0d025Smrg        return 0x0130;
323e1c0d025Smrg    case 0xDE:
324e1c0d025Smrg        return 0x015E;
325e1c0d025Smrg    case 0xF0:
326e1c0d025Smrg        return 0x011F;
327e1c0d025Smrg    case 0xFD:
328e1c0d025Smrg        return 0x0131;
329e1c0d025Smrg    case 0xFE:
330e1c0d025Smrg        return 0x015F;
331e1c0d025Smrg    default:
332e1c0d025Smrg        return isocode;
3333da084b3Smrg    }
3343da084b3Smrg}
3353da084b3Smrg
336e1c0d025Smrgstatic FontMapRec iso8859_9[] = {
337e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, iso8859_9_to_unicode, NULL, NULL, NULL, NULL},
338e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
3393da084b3Smrg};
3403da084b3Smrg
341e1c0d025Smrgstatic const unsigned short iso8859_10_tophalf[] = {
342e1c0d025Smrg    0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7,
343e1c0d025Smrg    0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
344e1c0d025Smrg    0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7,
345e1c0d025Smrg    0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2014, 0x016B, 0x014B,
346e1c0d025Smrg    0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
347e1c0d025Smrg    0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF,
348e1c0d025Smrg    0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168,
349e1c0d025Smrg    0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
350e1c0d025Smrg    0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
351e1c0d025Smrg    0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF,
352e1c0d025Smrg    0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169,
353e1c0d025Smrg    0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138
354e1c0d025Smrg};
355e1c0d025Smrg
356e1c0d025Smrgstatic FontEncSimpleMapRec iso8859_10_to_unicode_map =
357e1c0d025Smrg    { 0x60, 0, 0xA0, iso8859_10_tophalf };
358e1c0d025Smrg
359e1c0d025Smrgstatic FontMapRec iso8859_10[] = {
360e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, FontEncSimpleRecode, NULL,
361e1c0d025Smrg     &iso8859_10_to_unicode_map, NULL, NULL},
362e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
3633da084b3Smrg};
3643da084b3Smrg
3653da084b3Smrgstatic unsigned
3663da084b3Smrgiso8859_15_to_unicode(unsigned isocode, void *client_data)
3673da084b3Smrg{
368e1c0d025Smrg    switch (isocode) {
369e1c0d025Smrg    case 0xA4:
370e1c0d025Smrg        return 0x20AC;
371e1c0d025Smrg    case 0xA6:
372e1c0d025Smrg        return 0x0160;
373e1c0d025Smrg    case 0xA8:
374e1c0d025Smrg        return 0x0161;
375e1c0d025Smrg    case 0xB4:
376e1c0d025Smrg        return 0x017D;
377e1c0d025Smrg    case 0xB8:
378e1c0d025Smrg        return 0x017E;
379e1c0d025Smrg    case 0xBC:
380e1c0d025Smrg        return 0x0152;
381e1c0d025Smrg    case 0xBD:
382e1c0d025Smrg        return 0x0153;
383e1c0d025Smrg    case 0xBE:
384e1c0d025Smrg        return 0x0178;
385e1c0d025Smrg    default:
386e1c0d025Smrg        return isocode;
3873da084b3Smrg    }
3883da084b3Smrg}
3893da084b3Smrg
390e1c0d025Smrgstatic FontMapRec iso8859_15[] = {
391e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, iso8859_15_to_unicode, NULL, NULL, NULL,
392e1c0d025Smrg     NULL},
393e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
3943da084b3Smrg};
3953da084b3Smrg
396e1c0d025Smrgstatic const unsigned short koi8_r_tophalf[] = {
397e1c0d025Smrg    0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
398e1c0d025Smrg    0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
399e1c0d025Smrg    0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2022, 0x221A, 0x2248,
400e1c0d025Smrg    0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,
401e1c0d025Smrg    0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556,
402e1c0d025Smrg    0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E,
403e1c0d025Smrg    0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565,
404e1c0d025Smrg    0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9,
405e1c0d025Smrg    0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
406e1c0d025Smrg    0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
407e1c0d025Smrg    0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
408e1c0d025Smrg    0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
409e1c0d025Smrg    0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
410e1c0d025Smrg    0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
411e1c0d025Smrg    0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
412e1c0d025Smrg    0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A
413e1c0d025Smrg};
414e1c0d025Smrg
415e1c0d025Smrgstatic FontEncSimpleMapRec koi8_r_to_unicode_map =
416e1c0d025Smrg    { 0x80, 0, 0x80, koi8_r_tophalf };
417e1c0d025Smrg
418e1c0d025Smrgstatic FontMapRec koi8_r[] = {
419e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, FontEncSimpleRecode, NULL,
420e1c0d025Smrg     &koi8_r_to_unicode_map, NULL, NULL},
421e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
4223da084b3Smrg};
4233da084b3Smrg
42448c85eb7Smrgstatic unsigned
4253da084b3Smrgkoi8_ru_to_unicode(unsigned koicode, void *client_data)
4263da084b3Smrg{
427e1c0d025Smrg    switch (koicode) {
428e1c0d025Smrg    case 0x93:
429e1c0d025Smrg        return 0x201C;
430e1c0d025Smrg    case 0x96:
431e1c0d025Smrg        return 0x201D;
432e1c0d025Smrg    case 0x97:
433e1c0d025Smrg        return 0x2014;
434e1c0d025Smrg    case 0x98:
435e1c0d025Smrg        return 0x2116;
436e1c0d025Smrg    case 0x99:
437e1c0d025Smrg        return 0x2122;
438e1c0d025Smrg    case 0x9B:
439e1c0d025Smrg        return 0x00BB;
440e1c0d025Smrg    case 0x9C:
441e1c0d025Smrg        return 0x00AE;
442e1c0d025Smrg    case 0x9D:
443e1c0d025Smrg        return 0x00AB;
444e1c0d025Smrg    case 0x9F:
445e1c0d025Smrg        return 0x00A4;
446e1c0d025Smrg    case 0xA4:
447e1c0d025Smrg        return 0x0454;
448e1c0d025Smrg    case 0xA6:
449e1c0d025Smrg        return 0x0456;
450e1c0d025Smrg    case 0xA7:
451e1c0d025Smrg        return 0x0457;
452e1c0d025Smrg    case 0xAD:
453e1c0d025Smrg        return 0x0491;
454e1c0d025Smrg    case 0xAE:
455e1c0d025Smrg        return 0x045E;
456e1c0d025Smrg    case 0xB4:
457e1c0d025Smrg        return 0x0404;
458e1c0d025Smrg    case 0xB6:
459e1c0d025Smrg        return 0x0406;
460e1c0d025Smrg    case 0xB7:
461e1c0d025Smrg        return 0x0407;
462e1c0d025Smrg    case 0xBD:
463e1c0d025Smrg        return 0x0490;
464e1c0d025Smrg    case 0xBE:
465e1c0d025Smrg        return 0x040E;
466e1c0d025Smrg    default:
467e1c0d025Smrg        return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
468e1c0d025Smrg    }
4693da084b3Smrg}
4703da084b3Smrg
471e1c0d025Smrgstatic FontMapRec koi8_ru[] = {
472e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, koi8_ru_to_unicode, NULL, NULL, NULL, NULL},
473e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
4743da084b3Smrg};
4753da084b3Smrg
4763da084b3Smrg/* koi8-e, ISO-IR-111 or ECMA-Cyrillic */
4773da084b3Smrg
478e1c0d025Smrgstatic const unsigned short koi8_e_A0_BF[] = {
479e1c0d025Smrg    0x00A0, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
480e1c0d025Smrg    0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00AD, 0x045E, 0x045F,
481e1c0d025Smrg    0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
482e1c0d025Smrg    0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00A4, 0x040E, 0x040F
483e1c0d025Smrg};
4843da084b3Smrg
4853da084b3Smrgstatic unsigned
4863da084b3Smrgkoi8_e_to_unicode(unsigned koicode, void *client_data)
4873da084b3Smrg{
488e1c0d025Smrg    if (koicode < 0xA0)
4893da084b3Smrg        return koicode;
490e1c0d025Smrg    else if (koicode < 0xC0)
491e1c0d025Smrg        return koi8_e_A0_BF[koicode - 0xA0];
49248c85eb7Smrg    else
4933da084b3Smrg        return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
4943da084b3Smrg}
4953da084b3Smrg
496e1c0d025Smrgstatic FontMapRec koi8_e[] = {
497e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, koi8_e_to_unicode, NULL, NULL, NULL, NULL},
498e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
4993da084b3Smrg};
5003da084b3Smrg
5013da084b3Smrg/* Koi8 unified */
5023da084b3Smrg
503e1c0d025Smrgstatic const unsigned short koi8_uni_80_BF[] = {
504e1c0d025Smrg    0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
505e1c0d025Smrg    0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
506e1c0d025Smrg    0x2591, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
507e1c0d025Smrg    0x00A9, 0x2122, 0x00A0, 0x00BB, 0x00AE, 0x00AB, 0x00B7, 0x00A4,
508e1c0d025Smrg    0x00A0, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
509e1c0d025Smrg    0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x0491, 0x045E, 0x045F,
510e1c0d025Smrg    0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
511e1c0d025Smrg    0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x0490, 0x040E, 0x040F
512e1c0d025Smrg};
5133da084b3Smrg
51448c85eb7Smrgstatic unsigned
5153da084b3Smrgkoi8_uni_to_unicode(unsigned koicode, void *client_data)
5163da084b3Smrg{
517e1c0d025Smrg    if (koicode < 0x80)
5183da084b3Smrg        return koicode;
519e1c0d025Smrg    else if (koicode < 0xC0)
520e1c0d025Smrg        return koi8_uni_80_BF[koicode - 0x80];
5213da084b3Smrg    else
5223da084b3Smrg        return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
5233da084b3Smrg}
5243da084b3Smrg
525e1c0d025Smrgstatic FontMapRec koi8_uni[] = {
526e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, koi8_uni_to_unicode, NULL, NULL, NULL, NULL},
527e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
5283da084b3Smrg};
5293da084b3Smrg
5303da084b3Smrg/* Ukrainian variant of Koi8-R; see RFC 2319 */
5313da084b3Smrg
53248c85eb7Smrgstatic unsigned
5333da084b3Smrgkoi8_u_to_unicode(unsigned koicode, void *client_data)
5343da084b3Smrg{
535e1c0d025Smrg    switch (koicode) {
536e1c0d025Smrg    case 0xA4:
537e1c0d025Smrg        return 0x0454;
538e1c0d025Smrg    case 0xA6:
539e1c0d025Smrg        return 0x0456;
540e1c0d025Smrg    case 0xA7:
541e1c0d025Smrg        return 0x0457;
542e1c0d025Smrg    case 0xAD:
543e1c0d025Smrg        return 0x0491;
544e1c0d025Smrg    case 0xB4:
545e1c0d025Smrg        return 0x0404;
546e1c0d025Smrg    case 0xB6:
547e1c0d025Smrg        return 0x0406;
548e1c0d025Smrg    case 0xB7:
549e1c0d025Smrg        return 0x0407;
550e1c0d025Smrg    case 0xBD:
551e1c0d025Smrg        return 0x0490;
552e1c0d025Smrg    default:
553e1c0d025Smrg        return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
5543da084b3Smrg    }
5553da084b3Smrg}
5563da084b3Smrg
557e1c0d025Smrgstatic FontMapRec koi8_u[] = {
558e1c0d025Smrg    {FONT_ENCODING_UNICODE, 0, 0, koi8_u_to_unicode, NULL, NULL, NULL},
559e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
5603da084b3Smrg};
5613da084b3Smrg
5623da084b3Smrg/* Microsoft Symbol, which is only meaningful for TrueType fonts, is
5633da084b3Smrg   treated specially in ftenc.c, where we add usFirstCharIndex-0x20 to
5643da084b3Smrg   the glyph index before applying the cmap.  Lovely design. */
5653da084b3Smrg
566e1c0d025Smrgstatic FontMapRec microsoft_symbol[] = {
567e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 3, 0, NULL, NULL, NULL, NULL, NULL},
568e1c0d025Smrg    /* You never know */
569e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 3, 1, NULL, NULL, NULL, NULL, NULL},
570e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
571e1c0d025Smrg};
5723da084b3Smrg
573e1c0d025Smrgstatic FontMapRec apple_roman[] = {
574e1c0d025Smrg    {FONT_ENCODING_TRUETYPE, 1, 0, NULL, NULL, NULL, NULL, NULL},
575e1c0d025Smrg    {0, 0, 0, NULL, NULL, NULL, NULL, NULL}
576e1c0d025Smrg};
5773da084b3Smrg
5783da084b3Smrg/* The data for recodings */
5793da084b3Smrg
5803da084b3Smrg/* For compatibility with X11R6.4.  Losers. */
581e1c0d025Smrgstatic char *iso8859_15_aliases[2] = { "fcd8859-15", NULL };
582e1c0d025Smrg
583e1c0d025Smrgstatic FontEncRec initial_encodings[] = {
584e1c0d025Smrg    {"iso10646-1", NULL, 256 * 256, 0, iso10646, NULL, 0, 0},   /* Unicode */
585e1c0d025Smrg    {"iso8859-1", NULL, 256, 0, iso8859_1, NULL, 0, 0}, /* Latin 1 (West European) */
586e1c0d025Smrg    {"iso8859-2", NULL, 256, 0, iso8859_2, NULL, 0, 0}, /* Latin 2 (East European) */
587e1c0d025Smrg    {"iso8859-3", NULL, 256, 0, iso8859_3, NULL, 0, 0}, /* Latin 3 (South European) */
588e1c0d025Smrg    {"iso8859-4", NULL, 256, 0, iso8859_4, NULL, 0, 0}, /* Latin 4 (North European) */
589e1c0d025Smrg    {"iso8859-5", NULL, 256, 0, iso8859_5, NULL, 0, 0}, /* Cyrillic */
590e1c0d025Smrg    {"iso8859-6", NULL, 256, 0, iso8859_6, NULL, 0, 0}, /* Arabic */
591e1c0d025Smrg    {"iso8859-7", NULL, 256, 0, iso8859_7, NULL, 0, 0}, /* Greek */
592e1c0d025Smrg    {"iso8859-8", NULL, 256, 0, iso8859_8, NULL, 0, 0}, /* Hebrew */
593e1c0d025Smrg    {"iso8859-9", NULL, 256, 0, iso8859_9, NULL, 0, 0}, /* Latin 5 (Turkish) */
594e1c0d025Smrg    {"iso8859-10", NULL, 256, 0, iso8859_10, NULL, 0, 0},       /* Latin 6 (Nordic) */
595e1c0d025Smrg    {"iso8859-15", iso8859_15_aliases, 256, 0, iso8859_15, NULL, 0, 0}, /* Latin 9 */
596e1c0d025Smrg    {"koi8-r", NULL, 256, 0, koi8_r, NULL, 0, 0},       /* Russian */
597e1c0d025Smrg    {"koi8-ru", NULL, 256, 0, koi8_ru, NULL, 0, 0},     /* Ukrainian */
598e1c0d025Smrg    {"koi8-uni", NULL, 256, 0, koi8_uni, NULL, 0, 0},   /* Russian/Ukrainian/Bielorussian */
599e1c0d025Smrg    {"koi8-e", NULL, 256, 0, koi8_e, NULL, 0, 0},       /* ``European'' */
600e1c0d025Smrg    {"koi8-u", NULL, 256, 0, koi8_u, NULL, 0, 0},       /* Ukrainian too */
601e1c0d025Smrg    {"microsoft-symbol", NULL, 256, 0, microsoft_symbol, NULL, 0, 0},
602e1c0d025Smrg    {"apple-roman", NULL, 256, 0, apple_roman, NULL, 0, 0},
603e1c0d025Smrg    {NULL, NULL, 0, 0, NULL, NULL, 0, 0}
6043da084b3Smrg};
6053da084b3Smrg
606e1c0d025Smrgstatic FontEncPtr font_encodings = NULL;
6073da084b3Smrg
6083da084b3Smrgstatic void
6093da084b3Smrgdefine_initial_encoding_info(void)
6103da084b3Smrg{
6113da084b3Smrg    FontEncPtr encoding;
6123da084b3Smrg    FontMapPtr mapping;
6133da084b3Smrg
6143da084b3Smrg    font_encodings = initial_encodings;
615e1c0d025Smrg    for (encoding = font_encodings; ; encoding++) {
6163da084b3Smrg        encoding->next = encoding + 1;
617e1c0d025Smrg        for (mapping = encoding->mappings; ; mapping++) {
618e1c0d025Smrg            mapping->next = mapping + 1;
6193da084b3Smrg            mapping->encoding = encoding;
620e1c0d025Smrg            if (mapping->next->type == 0) {
6213da084b3Smrg                mapping->next = NULL;
6223da084b3Smrg                break;
6233da084b3Smrg            }
6243da084b3Smrg        }
625e1c0d025Smrg        if (!encoding->next->name) {
6263da084b3Smrg            encoding->next = NULL;
6273da084b3Smrg            break;
6283da084b3Smrg        }
6293da084b3Smrg    }
6303da084b3Smrg}
6313da084b3Smrg
632e1c0d025Smrgchar *
6333da084b3SmrgFontEncFromXLFD(const char *name, int length)
6343da084b3Smrg{
6353da084b3Smrg    const char *p;
6363da084b3Smrg    char *q;
6373da084b3Smrg    static char charset[MAXFONTNAMELEN];
6383da084b3Smrg    int len;
6393da084b3Smrg
640e1c0d025Smrg    if (length > MAXFONTNAMELEN - 1)
6413da084b3Smrg        return NULL;
6423da084b3Smrg
643e1c0d025Smrg    if (name == NULL)
6443da084b3Smrg        p = NULL;
6453da084b3Smrg    else {
6463da084b3Smrg        p = name + length - 1;
647e1c0d025Smrg        while (p > name && *p != '-')
6483da084b3Smrg            p--;
6493da084b3Smrg        p--;
650e1c0d025Smrg        while (p >= name && *p != '-')
6513da084b3Smrg            p--;
652e1c0d025Smrg        if (p <= name)
6533da084b3Smrg            p = NULL;
6543da084b3Smrg    }
6553da084b3Smrg
6563da084b3Smrg    /* now p either is null or points at the '-' before the charset registry */
657d63fdb69Smrg
658e1c0d025Smrg    if (p == NULL)
6593da084b3Smrg        return NULL;
66048c85eb7Smrg
6613da084b3Smrg    len = length - (p - name) - 1;
662e1c0d025Smrg    memcpy(charset, p + 1, len);
6633da084b3Smrg    charset[len] = 0;
66448c85eb7Smrg
6653da084b3Smrg    /* check for a subset specification */
666e1c0d025Smrg    if ((q = strchr(charset, (int) '[')))
6673da084b3Smrg        *q = 0;
66848c85eb7Smrg
6693da084b3Smrg    return charset;
6703da084b3Smrg}
6713da084b3Smrg
6723da084b3Smrgunsigned
673e1c0d025SmrgFontEncRecode(unsigned code, FontMapPtr mapping)
6743da084b3Smrg{
6753da084b3Smrg    FontEncPtr encoding = mapping->encoding;
676e1c0d025Smrg
677e1c0d025Smrg    if (encoding && mapping->recode) {
678e1c0d025Smrg        if (encoding->row_size == 0) {
6793da084b3Smrg            /* linear encoding */
680e1c0d025Smrg            if (code < encoding->first || code >= encoding->size)
6813da084b3Smrg                return 0;
682e1c0d025Smrg        }
683e1c0d025Smrg        else {
6843da084b3Smrg            /* matrix encoding */
685e1c0d025Smrg            int row = code / 0x100, col = code & 0xFF;
686e1c0d025Smrg
687e1c0d025Smrg            if (row < encoding->first || row >= encoding->size ||
688e1c0d025Smrg                col < encoding->first_col || col >= encoding->row_size)
6893da084b3Smrg                return 0;
6903da084b3Smrg        }
691e1c0d025Smrg        return (*mapping->recode) (code, mapping->client_data);
692e1c0d025Smrg    }
693e1c0d025Smrg    else
6943da084b3Smrg        return code;
6953da084b3Smrg}
6963da084b3Smrg
697e1c0d025Smrgchar *
6983da084b3SmrgFontEncName(unsigned code, FontMapPtr mapping)
6993da084b3Smrg{
7003da084b3Smrg    FontEncPtr encoding = mapping->encoding;
701e1c0d025Smrg
702e1c0d025Smrg    if (encoding && mapping->name) {
703e1c0d025Smrg        if ((encoding->row_size == 0 && code >= encoding->size) ||
704e1c0d025Smrg            (encoding->row_size != 0 &&
705e1c0d025Smrg             (code / 0x100 >= encoding->size ||
706e1c0d025Smrg              (code & 0xFF) >= encoding->row_size)))
7073da084b3Smrg            return NULL;
708e1c0d025Smrg        return (*mapping->name) (code, mapping->client_data);
709e1c0d025Smrg    }
710e1c0d025Smrg    else
7113da084b3Smrg        return NULL;
7123da084b3Smrg}
7133da084b3Smrg
7143da084b3SmrgFontEncPtr
7153da084b3SmrgFontEncFind(const char *encoding_name, const char *filename)
7163da084b3Smrg{
7173da084b3Smrg    FontEncPtr encoding;
7183da084b3Smrg    char **alias;
71948c85eb7Smrg
720e1c0d025Smrg    if (font_encodings == NULL)
721e1c0d025Smrg        define_initial_encoding_info();
72248c85eb7Smrg
723e1c0d025Smrg    for (encoding = font_encodings; encoding; encoding = encoding->next) {
724e1c0d025Smrg        if (!strcasecmp(encoding->name, encoding_name))
7253da084b3Smrg            return encoding;
726e1c0d025Smrg        if (encoding->aliases)
727e1c0d025Smrg            for (alias = encoding->aliases; *alias; alias++)
728e1c0d025Smrg                if (!strcasecmp(*alias, encoding_name))
7293da084b3Smrg                    return encoding;
730e1c0d025Smrg    }
7313da084b3Smrg
732e1c0d025Smrg    /* Unknown charset, try to load a definition file */
7333da084b3Smrg    return FontEncLoad(encoding_name, filename);
7343da084b3Smrg}
7353da084b3Smrg
7363da084b3SmrgFontMapPtr
7373da084b3SmrgFontMapFind(FontEncPtr encoding, int type, int pid, int eid)
7383da084b3Smrg{
7393da084b3Smrg    FontMapPtr mapping;
740e1c0d025Smrg
741e1c0d025Smrg    if (encoding == NULL)
7423da084b3Smrg        return NULL;
7433da084b3Smrg
744e1c0d025Smrg    for (mapping = encoding->mappings; mapping; mapping = mapping->next) {
745e1c0d025Smrg        if (mapping->type != type)
7463da084b3Smrg            continue;
747e1c0d025Smrg        if (pid > 0 && mapping->pid != pid)
7483da084b3Smrg            continue;
749e1c0d025Smrg        if (eid > 0 && mapping->eid != eid)
7503da084b3Smrg            continue;
7513da084b3Smrg        return mapping;
7523da084b3Smrg    }
7533da084b3Smrg    return NULL;
7543da084b3Smrg}
7553da084b3Smrg
7563da084b3SmrgFontMapPtr
7573da084b3SmrgFontEncMapFind(const char *encoding_name, int type, int pid, int eid,
7583da084b3Smrg               const char *filename)
7593da084b3Smrg{
7603da084b3Smrg    FontEncPtr encoding;
7613da084b3Smrg    FontMapPtr mapping;
7623da084b3Smrg
7633da084b3Smrg    encoding = FontEncFind(encoding_name, filename);
764e1c0d025Smrg    if (encoding == NULL)
7653da084b3Smrg        return NULL;
7663da084b3Smrg    mapping = FontMapFind(encoding, type, pid, eid);
7673da084b3Smrg    return mapping;
7683da084b3Smrg}
7693da084b3Smrg
7703da084b3Smrgstatic FontEncPtr
7713da084b3SmrgFontEncLoad(const char *encoding_name, const char *filename)
7723da084b3Smrg{
7733da084b3Smrg    FontEncPtr encoding;
77448c85eb7Smrg
7753da084b3Smrg    encoding = FontEncReallyLoad(encoding_name, filename);
7763da084b3Smrg    if (encoding == NULL) {
7773da084b3Smrg        return NULL;
778e1c0d025Smrg    }
779e1c0d025Smrg    else {
7803da084b3Smrg        char **alias;
7813da084b3Smrg        int found = 0;
78248c85eb7Smrg
7833da084b3Smrg        /* Check whether the name is already known for this encoding */
784e1c0d025Smrg        if (strcasecmp(encoding->name, encoding_name) == 0) {
7853da084b3Smrg            found = 1;
786e1c0d025Smrg        }
787e1c0d025Smrg        else {
788e1c0d025Smrg            if (encoding->aliases) {
789e1c0d025Smrg                for (alias = encoding->aliases; *alias; alias++)
790e1c0d025Smrg                    if (!strcasecmp(*alias, encoding_name)) {
7913da084b3Smrg                        found = 1;
7923da084b3Smrg                        break;
7933da084b3Smrg                    }
7943da084b3Smrg            }
7953da084b3Smrg        }
79648c85eb7Smrg
797e1c0d025Smrg        if (!found) {
7983da084b3Smrg            /* Add a new alias.  This works because we know that this
7993da084b3Smrg               particular encoding has been allocated dynamically */
8003da084b3Smrg            char **new_aliases;
8013da084b3Smrg            char *new_name;
8023da084b3Smrg            int numaliases = 0;
80348c85eb7Smrg
80455acc8fcSmrg            new_name = strdup(encoding_name);
805e1c0d025Smrg            if (new_name == NULL)
8063da084b3Smrg                return NULL;
807e1c0d025Smrg            if (encoding->aliases) {
808e1c0d025Smrg                for (alias = encoding->aliases; *alias; alias++)
8093da084b3Smrg                    numaliases++;
8103da084b3Smrg            }
811e1c0d025Smrg            new_aliases = malloc((numaliases + 2) * sizeof(char *));
812e1c0d025Smrg            if (new_aliases == NULL) {
81355acc8fcSmrg                free(new_name);
8143da084b3Smrg                return NULL;
8153da084b3Smrg            }
816e1c0d025Smrg            if (encoding->aliases) {
817e1c0d025Smrg                memcpy(new_aliases, encoding->aliases,
818e1c0d025Smrg                       numaliases * sizeof(char *));
81955acc8fcSmrg                free(encoding->aliases);
8203da084b3Smrg            }
8213da084b3Smrg            new_aliases[numaliases] = new_name;
822e1c0d025Smrg            new_aliases[numaliases + 1] = NULL;
8233da084b3Smrg            encoding->aliases = new_aliases;
8243da084b3Smrg        }
82548c85eb7Smrg
8263da084b3Smrg        /* register the new encoding */
827e1c0d025Smrg        encoding->next = font_encodings;
828e1c0d025Smrg        font_encodings = encoding;
82948c85eb7Smrg
8303da084b3Smrg        return encoding;
8313da084b3Smrg    }
8323da084b3Smrg}
8333da084b3Smrg
8343da084b3Smrgunsigned
8353da084b3SmrgFontEncSimpleRecode(unsigned code, void *client_data)
8363da084b3Smrg{
8373da084b3Smrg    FontEncSimpleMapPtr map;
8383da084b3Smrg    unsigned index;
8393da084b3Smrg
8403da084b3Smrg    map = client_data;
8413da084b3Smrg
842e1c0d025Smrg    if (code > 0xFFFF || (map->row_size && (code & 0xFF) >= map->row_size))
8433da084b3Smrg        return 0;
8443da084b3Smrg
845e1c0d025Smrg    if (map->row_size)
846e1c0d025Smrg        index = (code & 0xFF) + (code >> 8) * map->row_size;
8473da084b3Smrg    else
8483da084b3Smrg        index = code;
8493da084b3Smrg
850e1c0d025Smrg    if (map->map && index >= map->first && index < map->first + map->len)
851e1c0d025Smrg        return map->map[index - map->first];
852e1c0d025Smrg    else
853e1c0d025Smrg        return code;
8543da084b3Smrg}
8553da084b3Smrg
8563da084b3Smrgchar *
8573da084b3SmrgFontEncSimpleName(unsigned code, void *client_data)
8583da084b3Smrg{
8593da084b3Smrg    FontEncSimpleNamePtr map;
8603da084b3Smrg
8613da084b3Smrg    map = client_data;
862e1c0d025Smrg    if (map && code >= map->first && code < map->first + map->len)
863e1c0d025Smrg        return map->map[code - map->first];
8643da084b3Smrg    else
8653da084b3Smrg        return NULL;
8663da084b3Smrg}
8673da084b3Smrg
8683da084b3Smrgunsigned
8693da084b3SmrgFontEncUndefinedRecode(unsigned code, void *client_data)
8703da084b3Smrg{
8713da084b3Smrg    return code;
8723da084b3Smrg}
8733da084b3Smrg
8743da084b3Smrgchar *
8753da084b3SmrgFontEncUndefinedName(unsigned code, void *client_data)
8763da084b3Smrg{
8773da084b3Smrg    return NULL;
8783da084b3Smrg}
8793da084b3Smrg
8803da084b3Smrg#define FONTENC_SEGMENT_SIZE 256
8813da084b3Smrg#define FONTENC_SEGMENTS 256
8823da084b3Smrg#define FONTENC_INVERSE_CODES (FONTENC_SEGMENT_SIZE * FONTENC_SEGMENTS)
8833da084b3Smrg
8843da084b3Smrgstatic unsigned int
885e1c0d025Smrgreverse_reverse(unsigned i, void *data)
8863da084b3Smrg{
8873da084b3Smrg    int s, j;
888e1c0d025Smrg    unsigned **map = (unsigned **) data;
8893da084b3Smrg
890e1c0d025Smrg    if (i >= FONTENC_INVERSE_CODES)
8913da084b3Smrg        return 0;
8923da084b3Smrg
893e1c0d025Smrg    if (map == NULL)
8943da084b3Smrg        return 0;
8953da084b3Smrg
8963da084b3Smrg    s = i / FONTENC_SEGMENT_SIZE;
8973da084b3Smrg    j = i % FONTENC_SEGMENT_SIZE;
8983da084b3Smrg
899e1c0d025Smrg    if (map[s] == NULL)
9003da084b3Smrg        return 0;
9013da084b3Smrg    else
9023da084b3Smrg        return map[s][j];
9033da084b3Smrg}
9043da084b3Smrg
9053da084b3Smrgstatic int
9063da084b3Smrgtree_set(unsigned int **map, unsigned int i, unsigned int j)
9073da084b3Smrg{
9083da084b3Smrg    int s, c;
9093da084b3Smrg
910e1c0d025Smrg    if (i >= FONTENC_INVERSE_CODES)
9113da084b3Smrg        return FALSE;
9123da084b3Smrg
9133da084b3Smrg    s = i / FONTENC_SEGMENT_SIZE;
9143da084b3Smrg    c = i % FONTENC_SEGMENT_SIZE;
9153da084b3Smrg
916e1c0d025Smrg    if (map[s] == NULL) {
91748c85eb7Smrg        map[s] = calloc(FONTENC_SEGMENT_SIZE, sizeof(int));
918e1c0d025Smrg        if (map[s] == NULL)
9193da084b3Smrg            return FALSE;
920e1c0d025Smrg    }
9213da084b3Smrg
9223da084b3Smrg    map[s][c] = j;
9233da084b3Smrg    return TRUE;
9243da084b3Smrg}
9253da084b3Smrg
9263da084b3SmrgFontMapReversePtr
9273da084b3SmrgFontMapReverse(FontMapPtr mapping)
9283da084b3Smrg{
9293da084b3Smrg    FontEncPtr encoding = mapping->encoding;
9303da084b3Smrg    FontMapReversePtr reverse = NULL;
9313da084b3Smrg    unsigned int **map = NULL;
9323da084b3Smrg    int i, j, k;
9333da084b3Smrg
934e1c0d025Smrg    if (encoding == NULL)
935e1c0d025Smrg        goto bail;
9363da084b3Smrg
937e1c0d025Smrg    map = calloc(FONTENC_SEGMENTS, sizeof(int *));
938e1c0d025Smrg    if (map == NULL)
939e1c0d025Smrg        goto bail;
9403da084b3Smrg
941e1c0d025Smrg    if (encoding->row_size == 0) {
942e1c0d025Smrg        for (i = encoding->first; i < encoding->size; i++) {
9433da084b3Smrg            k = FontEncRecode(i, mapping);
944e1c0d025Smrg            if (k != 0)
945e1c0d025Smrg                if (!tree_set(map, k, i))
9463da084b3Smrg                    goto bail;
9473da084b3Smrg        }
948e1c0d025Smrg    }
949e1c0d025Smrg    else {
950e1c0d025Smrg        for (i = encoding->first; i < encoding->size; i++) {
951e1c0d025Smrg            for (j = encoding->first_col; j < encoding->row_size; j++) {
952e1c0d025Smrg                k = FontEncRecode(i * 256 + j, mapping);
953e1c0d025Smrg                if (k != 0)
954e1c0d025Smrg                    if (!tree_set(map, k, i * 256 + j))
9553da084b3Smrg                        goto bail;
9563da084b3Smrg            }
9573da084b3Smrg        }
9583da084b3Smrg    }
9593da084b3Smrg
9603da084b3Smrg    reverse = malloc(sizeof(FontMapReverseRec));
961e1c0d025Smrg    if (!reverse)
962e1c0d025Smrg        goto bail;
9633da084b3Smrg
9643da084b3Smrg    reverse->reverse = reverse_reverse;
9653da084b3Smrg    reverse->data = map;
9663da084b3Smrg    return reverse;
9673da084b3Smrg
968e1c0d025Smrg bail:
96955acc8fcSmrg    free(map);
97055acc8fcSmrg    free(reverse);
9713da084b3Smrg    return NULL;
9723da084b3Smrg}
9733da084b3Smrg
9743da084b3Smrgvoid
9753da084b3SmrgFontMapReverseFree(FontMapReversePtr delendum)
9763da084b3Smrg{
977e1c0d025Smrg    unsigned int **map = (unsigned int **) delendum;
9783da084b3Smrg    int i;
97948c85eb7Smrg
980e1c0d025Smrg    if (map == NULL)
9813da084b3Smrg        return;
9823da084b3Smrg
983e1c0d025Smrg    for (i = 0; i < FONTENC_SEGMENTS; i++)
984e1c0d025Smrg        free(map[i]);
9853da084b3Smrg
98655acc8fcSmrg    free(map);
9873da084b3Smrg    return;
9883da084b3Smrg}
989