fontenc.c revision 3da084b3
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/* $XdotOrg: xc/lib/font/fontfile/fontenc.c,v 1.3 2005/07/03 07:01:00 daniels Exp $ */
243da084b3Smrg/* $XFree86: xc/lib/font/fontfile/fontenc.c,v 1.15 2003/02/20 03:25:19 dawes Exp $ */
253da084b3Smrg
263da084b3Smrg/* Backend-independent encoding code */
273da084b3Smrg
283da084b3Smrg#include <string.h>
293da084b3Smrg
303da084b3Smrg#if defined(__SCO__) || defined(__UNIXWARE__)
313da084b3Smrg#include <strings.h>
323da084b3Smrg#endif
333da084b3Smrg
343da084b3Smrg#ifndef FONTENC_NO_LIBFONT
353da084b3Smrg
363da084b3Smrg#include <X11/fonts/fontmisc.h>           /* defines xalloc and friends */
373da084b3Smrg#include <X11/fonts/fntfilst.h>
383da084b3Smrg
393da084b3Smrg#else
403da084b3Smrg
413da084b3Smrg#include <stdlib.h>
423da084b3Smrg#define xalloc(n) malloc(n)
433da084b3Smrg#define xrealloc(p, n) realloc(p, n)
443da084b3Smrg#define xfree(p) free(p)
453da084b3Smrg#define FALSE 0
463da084b3Smrg#define TRUE 1
473da084b3Smrg#define MAXFONTNAMELEN 1024
483da084b3Smrg#define MAXFONTFILENAMELEN 1024
493da084b3Smrg
503da084b3Smrg#endif /* FONTENC_NO_FONTFILE */
513da084b3Smrg
523da084b3Smrg#include <X11/fonts/fontenc.h>
533da084b3Smrg#include "fontencI.h"
543da084b3Smrg
553da084b3Smrg/* Functions local to this file */
563da084b3Smrg
573da084b3Smrgstatic FontEncPtr FontEncLoad(const char*, const char*);
583da084b3Smrg
593da084b3Smrg/* Early versions of this code only knew about hardwired encodings,
603da084b3Smrg   hence the following data.  Now that the code knows how to load an
613da084b3Smrg   encoding from a file, most of these tables could go away. */
623da084b3Smrg
633da084b3Smrg/* At any rate, no new hardcoded encodings will be added. */
643da084b3Smrg
653da084b3Smrgstatic FontMapRec iso10646[]=
663da084b3Smrg{
673da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,NULL,NULL,NULL,NULL,NULL},
683da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
693da084b3Smrg};
703da084b3Smrg
713da084b3Smrg/* Notice that the Apple encodings do not have all the characters in
723da084b3Smrg   the corresponding ISO 8859, and therefore the table has some holes.
733da084b3Smrg   There's not much more we can do with fonts without a Unicode cmap
743da084b3Smrg   unless we are willing to combine cmaps (which we are not). */
753da084b3Smrg
763da084b3Smrgstatic const unsigned short
773da084b3Smrgiso8859_1_apple_roman[]=
783da084b3Smrg{ 0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0x00, 0xA4,
793da084b3Smrg  0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0x00, 0xA8, 0xF8,
803da084b3Smrg  0xA1, 0xB1, 0x00, 0x00, 0xAB, 0xB5, 0xA6, 0xE1,
813da084b3Smrg  0xFC, 0x00, 0xBC, 0xC8, 0x00, 0x00, 0x00, 0xC0,
823da084b3Smrg  0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82,
833da084b3Smrg  0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC,
843da084b3Smrg  0x00, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0x00,
853da084b3Smrg  0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0x00, 0x00, 0xA7,
863da084b3Smrg  0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D,
873da084b3Smrg  0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
883da084b3Smrg  0x00, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6,
893da084b3Smrg  0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0x00, 0x00, 0xD8 };
903da084b3Smrg
913da084b3Smrg/* Cannot use simple_recode because need to eliminate 0x80<=code<0xA0 */
923da084b3Smrgstatic unsigned
933da084b3Smrgiso8859_1_to_apple_roman(unsigned isocode, void *client_data)
943da084b3Smrg{
953da084b3Smrg    if(isocode<=0x80)
963da084b3Smrg        return isocode;
973da084b3Smrg    else if(isocode>=0xA0)
983da084b3Smrg        return iso8859_1_apple_roman[isocode-0xA0];
993da084b3Smrg    else
1003da084b3Smrg        return 0;
1013da084b3Smrg}
1023da084b3Smrg
1033da084b3Smrgstatic FontMapRec iso8859_1[]=
1043da084b3Smrg{
1053da084b3Smrg    {FONT_ENCODING_TRUETYPE,2,2,NULL,NULL,NULL,NULL,NULL}, /* ISO 8859-1 */
1063da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,NULL,NULL,NULL,NULL,NULL}, /* ISO 8859-1 coincides with Unicode*/
1073da084b3Smrg    {FONT_ENCODING_TRUETYPE,1,0,iso8859_1_to_apple_roman,NULL,NULL,NULL,NULL},
1083da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
1093da084b3Smrg};
1103da084b3Smrg
1113da084b3Smrgstatic const unsigned short iso8859_2_tophalf[]=
1123da084b3Smrg{ 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
1133da084b3Smrg  0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
1143da084b3Smrg  0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
1153da084b3Smrg  0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
1163da084b3Smrg  0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
1173da084b3Smrg  0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
1183da084b3Smrg  0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
1193da084b3Smrg  0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
1203da084b3Smrg  0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
1213da084b3Smrg  0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
1223da084b3Smrg  0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
1233da084b3Smrg  0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 };
1243da084b3Smrg
1253da084b3Smrgstatic FontEncSimpleMapRec iso8859_2_to_unicode_map=
1263da084b3Smrg{0x60, 0, 0xA0, iso8859_2_tophalf };
1273da084b3Smrg
1283da084b3Smrgstatic const unsigned short iso8859_2_apple_centeuro[]=
1293da084b3Smrg{ 0xCA, 0x84, 0x00, 0xFC, 0x00, 0xBB, 0xE5, 0xA4,
1303da084b3Smrg  0xAC, 0xE1, 0x00, 0xE8, 0x8F, 0x00, 0xEB, 0xFB,
1313da084b3Smrg  0xA1, 0x88, 0x00, 0xB8, 0x00, 0xBC, 0xE6, 0xFF,
1323da084b3Smrg  0x00, 0xE4, 0x00, 0xE9, 0x90, 0x00, 0xEC, 0xFD,
1333da084b3Smrg  0xD9, 0xE7, 0x00, 0x00, 0x80, 0xBD, 0x8C, 0x00,
1343da084b3Smrg  0x89, 0x83, 0xA2, 0x00, 0x9D, 0xEA, 0x00, 0x91,
1353da084b3Smrg  0x00, 0xC1, 0xC5, 0xEE, 0xEF, 0xCC, 0x85, 0x00,
1363da084b3Smrg  0xDB, 0xF1, 0xF2, 0xF4, 0x86, 0xF8, 0x00, 0xA7,
1373da084b3Smrg  0xDA, 0x87, 0x00, 0x00, 0x8A, 0xBE, 0x8D, 0x00,
1383da084b3Smrg  0x8B, 0x8E, 0xAB, 0x00, 0x9E, 0x92, 0x00, 0x93,
1393da084b3Smrg  0x00, 0xC4, 0xCB, 0x97, 0x99, 0xCE, 0x9A, 0xD6,
1403da084b3Smrg  0xDE, 0xF3, 0x9C, 0xF5, 0x9F, 0xF9, 0x00, 0x00 };
1413da084b3Smrg
1423da084b3Smrgstatic unsigned
1433da084b3Smrgiso8859_2_to_apple_centeuro(unsigned isocode, void *client_data)
1443da084b3Smrg{
1453da084b3Smrg    if(isocode<=0x80)
1463da084b3Smrg        return isocode;
1473da084b3Smrg    else if(isocode>=0xA0)
1483da084b3Smrg        return iso8859_2_apple_centeuro[isocode-0xA0];
1493da084b3Smrg    else
1503da084b3Smrg        return 0;
1513da084b3Smrg}
1523da084b3Smrg
1533da084b3Smrg
1543da084b3Smrgstatic FontMapRec iso8859_2[]=
1553da084b3Smrg{
1563da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,
1573da084b3Smrg     FontEncSimpleRecode,NULL,&iso8859_2_to_unicode_map,NULL,NULL},
1583da084b3Smrg    {FONT_ENCODING_TRUETYPE,1,29,iso8859_2_to_apple_centeuro,NULL,NULL,NULL,NULL},
1593da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
1603da084b3Smrg};
1613da084b3Smrg
1623da084b3Smrgstatic const unsigned short iso8859_3_tophalf[]=
1633da084b3Smrg{ 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0x0000, 0x0124, 0x00A7,
1643da084b3Smrg  0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0x0000, 0x017B,
1653da084b3Smrg  0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7,
1663da084b3Smrg  0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0x0000, 0x017C,
1673da084b3Smrg  0x00C0, 0x00C1, 0x00C2, 0x0000, 0x00C4, 0x010A, 0x0108, 0x00C7,
1683da084b3Smrg  0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
1693da084b3Smrg  0x0000, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7,
1703da084b3Smrg  0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF,
1713da084b3Smrg  0x00E0, 0x00E1, 0x00E2, 0x0000, 0x00E4, 0x010B, 0x0109, 0x00E7,
1723da084b3Smrg  0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
1733da084b3Smrg  0x0000, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7,
1743da084b3Smrg  0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9};
1753da084b3Smrg
1763da084b3Smrgstatic FontEncSimpleMapRec iso8859_3_to_unicode_map=
1773da084b3Smrg{ 0x60, 0, 0xA0, iso8859_3_tophalf };
1783da084b3Smrg
1793da084b3Smrgstatic FontMapRec iso8859_3[]=
1803da084b3Smrg{
1813da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,
1823da084b3Smrg     FontEncSimpleRecode,NULL,&iso8859_3_to_unicode_map,NULL,NULL},
1833da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
1843da084b3Smrg};
1853da084b3Smrg
1863da084b3Smrg
1873da084b3Smrgstatic const unsigned short iso8859_4_tophalf[]=
1883da084b3Smrg{ 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7,
1893da084b3Smrg  0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF,
1903da084b3Smrg  0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7,
1913da084b3Smrg  0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B,
1923da084b3Smrg  0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
1933da084b3Smrg  0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A,
1943da084b3Smrg  0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
1953da084b3Smrg  0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF,
1963da084b3Smrg  0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
1973da084b3Smrg  0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B,
1983da084b3Smrg  0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
1993da084b3Smrg  0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9,
2003da084b3Smrg};
2013da084b3Smrg
2023da084b3Smrgstatic FontEncSimpleMapRec iso8859_4_to_unicode_map=
2033da084b3Smrg{ 0x60, 0, 0xA0, iso8859_4_tophalf };
2043da084b3Smrg
2053da084b3Smrgstatic FontMapRec iso8859_4[]=
2063da084b3Smrg{
2073da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,FontEncSimpleRecode,NULL,
2083da084b3Smrg     &iso8859_4_to_unicode_map,NULL,NULL},
2093da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
2103da084b3Smrg};
2113da084b3Smrg
2123da084b3Smrgstatic const unsigned short iso8859_5_tophalf[]=
2133da084b3Smrg{ 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
2143da084b3Smrg  0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
2153da084b3Smrg  0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
2163da084b3Smrg  0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
2173da084b3Smrg  0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
2183da084b3Smrg  0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
2193da084b3Smrg  0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
2203da084b3Smrg  0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
2213da084b3Smrg  0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
2223da084b3Smrg  0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
2233da084b3Smrg  0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
2243da084b3Smrg  0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F};
2253da084b3Smrg
2263da084b3Smrgstatic FontEncSimpleMapRec iso8859_5_to_unicode_map=
2273da084b3Smrg{ 0x60, 0, 0xA0, iso8859_5_tophalf };
2283da084b3Smrg
2293da084b3Smrgstatic const unsigned short
2303da084b3Smrgiso8859_5_apple_cyrillic[]=
2313da084b3Smrg{ 0xCA, 0xDD, 0xAB, 0xAE, 0xB8, 0xC1, 0xA7, 0xBA,
2323da084b3Smrg  0xB7, 0xBC, 0xBE, 0xCB, 0xCD, 0x00, 0xD8, 0xDA,
2333da084b3Smrg  0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
2343da084b3Smrg  0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
2353da084b3Smrg  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
2363da084b3Smrg  0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
2373da084b3Smrg  0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
2383da084b3Smrg  0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
2393da084b3Smrg  0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
2403da084b3Smrg  0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF,
2413da084b3Smrg  0xDC, 0xDE, 0xAC, 0xAF, 0xB9, 0xCF, 0xB4, 0xBB,
2423da084b3Smrg  0xC0, 0xBD, 0xBF, 0xCC, 0xCE, 0xA4, 0xD9, 0xDB };
2433da084b3Smrg
2443da084b3Smrgstatic unsigned
2453da084b3Smrgiso8859_5_to_apple_cyrillic(unsigned isocode, void *client_data)
2463da084b3Smrg{
2473da084b3Smrg    if(isocode<=0x80)
2483da084b3Smrg        return isocode;
2493da084b3Smrg    else if(isocode>=0xA0)
2503da084b3Smrg        return iso8859_5_apple_cyrillic[isocode-0x80];
2513da084b3Smrg    else return 0;
2523da084b3Smrg}
2533da084b3Smrg
2543da084b3Smrgstatic FontMapRec iso8859_5[]=
2553da084b3Smrg{
2563da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,FontEncSimpleRecode,NULL,
2573da084b3Smrg     &iso8859_5_to_unicode_map,NULL,NULL},
2583da084b3Smrg    {FONT_ENCODING_TRUETYPE,1,7,iso8859_5_to_apple_cyrillic,NULL,NULL,NULL,NULL},
2593da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
2603da084b3Smrg};
2613da084b3Smrg
2623da084b3Smrg/* ISO 8859-6 seems useless for serving fonts (not enough presentation
2633da084b3Smrg * forms).  What do Arabic-speakers use? */
2643da084b3Smrg
2653da084b3Smrgstatic unsigned
2663da084b3Smrgiso8859_6_to_unicode(unsigned isocode, void *client_data)
2673da084b3Smrg{
2683da084b3Smrg    if(isocode<=0xA0 || isocode==0xA4 || isocode==0xAD)
2693da084b3Smrg        return isocode;
2703da084b3Smrg    else if(isocode==0xAC || isocode==0xBB ||
2713da084b3Smrg            (isocode>=0xBF && isocode<=0xDA) ||
2723da084b3Smrg            (isocode>=0xE0 && isocode<=0xEF) ||
2733da084b3Smrg            (isocode>=0xF0 && isocode<=0xF2))
2743da084b3Smrg        return isocode-0xA0+0x0600;
2753da084b3Smrg    else
2763da084b3Smrg        return 0;
2773da084b3Smrg}
2783da084b3Smrg
2793da084b3Smrgstatic FontMapRec iso8859_6[]=
2803da084b3Smrg{
2813da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,iso8859_6_to_unicode,NULL,NULL,NULL,NULL},
2823da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
2833da084b3Smrg};
2843da084b3Smrg
2853da084b3Smrgstatic unsigned
2863da084b3Smrgiso8859_7_to_unicode(unsigned isocode, void *client_data)
2873da084b3Smrg{
2883da084b3Smrg    if(isocode<=0xA0 ||
2893da084b3Smrg       (isocode>=0xA3 && isocode<=0xAD) ||
2903da084b3Smrg       (isocode>=0xB0 && isocode<=0xB3) ||
2913da084b3Smrg       isocode==0xB7 || isocode==0xBB || isocode==0xBD)
2923da084b3Smrg        return isocode;
2933da084b3Smrg    else if(isocode==0xA1)
2943da084b3Smrg        return 0x02BD;
2953da084b3Smrg    else if(isocode==0xA2)
2963da084b3Smrg        return 0x02BC;
2973da084b3Smrg    else if(isocode==0xAF)
2983da084b3Smrg        return 0x2015;
2993da084b3Smrg    else if(isocode>=0xB4)
3003da084b3Smrg        return isocode-0xA0+0x0370;
3013da084b3Smrg    else
3023da084b3Smrg        return 0;
3033da084b3Smrg}
3043da084b3Smrg
3053da084b3Smrgstatic FontMapRec iso8859_7[]=
3063da084b3Smrg{
3073da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,iso8859_7_to_unicode,NULL,NULL,NULL,NULL},
3083da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
3093da084b3Smrg};
3103da084b3Smrg
3113da084b3Smrgstatic unsigned
3123da084b3Smrgiso8859_8_to_unicode(unsigned isocode, void *client_data)
3133da084b3Smrg{
3143da084b3Smrg    if(isocode==0xA1)
3153da084b3Smrg        return 0;
3163da084b3Smrg    else if(isocode<0xBF)
3173da084b3Smrg        return isocode;
3183da084b3Smrg    else if(isocode==0xDF)
3193da084b3Smrg        return 0x2017;
3203da084b3Smrg    else if(isocode>=0xE0 && isocode<=0xFA)
3213da084b3Smrg        return isocode+0x04F0;
3223da084b3Smrg    else
3233da084b3Smrg        return 0;
3243da084b3Smrg}
3253da084b3Smrg
3263da084b3Smrgstatic FontMapRec iso8859_8[]=
3273da084b3Smrg{
3283da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,iso8859_8_to_unicode,NULL,NULL,NULL,NULL},
3293da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
3303da084b3Smrg};
3313da084b3Smrg
3323da084b3Smrgstatic unsigned
3333da084b3Smrgiso8859_9_to_unicode(unsigned isocode, void *client_data)
3343da084b3Smrg{
3353da084b3Smrg    switch(isocode) {
3363da084b3Smrg    case 0xD0: return 0x011E;
3373da084b3Smrg    case 0xDD: return 0x0130;
3383da084b3Smrg    case 0xDE: return 0x015E;
3393da084b3Smrg    case 0xF0: return 0x011F;
3403da084b3Smrg    case 0xFD: return 0x0131;
3413da084b3Smrg    case 0xFE: return 0x015F;
3423da084b3Smrg    default: return isocode;
3433da084b3Smrg    }
3443da084b3Smrg}
3453da084b3Smrg
3463da084b3Smrgstatic FontMapRec iso8859_9[]=
3473da084b3Smrg{
3483da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,iso8859_9_to_unicode,NULL,NULL,NULL,NULL},
3493da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
3503da084b3Smrg};
3513da084b3Smrg
3523da084b3Smrgstatic const unsigned short iso8859_10_tophalf[]=
3533da084b3Smrg{ 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7,
3543da084b3Smrg  0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A,
3553da084b3Smrg  0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7,
3563da084b3Smrg  0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2014, 0x016B, 0x014B,
3573da084b3Smrg  0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E,
3583da084b3Smrg  0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF,
3593da084b3Smrg  0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168,
3603da084b3Smrg  0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
3613da084b3Smrg  0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F,
3623da084b3Smrg  0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF,
3633da084b3Smrg  0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169,
3643da084b3Smrg  0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138};
3653da084b3Smrg
3663da084b3Smrgstatic FontEncSimpleMapRec iso8859_10_to_unicode_map=
3673da084b3Smrg{ 0x60, 0, 0xA0, iso8859_10_tophalf };
3683da084b3Smrg
3693da084b3Smrgstatic FontMapRec iso8859_10[]=
3703da084b3Smrg{
3713da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,FontEncSimpleRecode,NULL,
3723da084b3Smrg     &iso8859_10_to_unicode_map,NULL,NULL},
3733da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
3743da084b3Smrg};
3753da084b3Smrg
3763da084b3Smrgstatic unsigned
3773da084b3Smrgiso8859_15_to_unicode(unsigned isocode, void *client_data)
3783da084b3Smrg{
3793da084b3Smrg    switch(isocode) {
3803da084b3Smrg    case 0xA4: return 0x20AC;
3813da084b3Smrg    case 0xA6: return 0x0160;
3823da084b3Smrg    case 0xA8: return 0x0161;
3833da084b3Smrg    case 0xB4: return 0x017D;
3843da084b3Smrg    case 0xB8: return 0x017E;
3853da084b3Smrg    case 0xBC: return 0x0152;
3863da084b3Smrg    case 0xBD: return 0x0153;
3873da084b3Smrg    case 0xBE: return 0x0178;
3883da084b3Smrg    default: return isocode;
3893da084b3Smrg    }
3903da084b3Smrg}
3913da084b3Smrg
3923da084b3Smrgstatic FontMapRec iso8859_15[]=
3933da084b3Smrg{
3943da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,iso8859_15_to_unicode,NULL,NULL,NULL,NULL},
3953da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
3963da084b3Smrg};
3973da084b3Smrg
3983da084b3Smrgstatic const unsigned short koi8_r_tophalf[]=
3993da084b3Smrg{ 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
4003da084b3Smrg  0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
4013da084b3Smrg  0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2022, 0x221A, 0x2248,
4023da084b3Smrg  0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,
4033da084b3Smrg  0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556,
4043da084b3Smrg  0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E,
4053da084b3Smrg  0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565,
4063da084b3Smrg  0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9,
4073da084b3Smrg  0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
4083da084b3Smrg  0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
4093da084b3Smrg  0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
4103da084b3Smrg  0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
4113da084b3Smrg  0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
4123da084b3Smrg  0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
4133da084b3Smrg  0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
4143da084b3Smrg  0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A};
4153da084b3Smrg
4163da084b3Smrgstatic FontEncSimpleMapRec koi8_r_to_unicode_map=
4173da084b3Smrg{ 0x80, 0, 0x80, koi8_r_tophalf };
4183da084b3Smrg
4193da084b3Smrg
4203da084b3Smrgstatic FontMapRec koi8_r[]=
4213da084b3Smrg{
4223da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,FontEncSimpleRecode,NULL,
4233da084b3Smrg     &koi8_r_to_unicode_map,NULL,NULL},
4243da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
4253da084b3Smrg};
4263da084b3Smrg
4273da084b3Smrgstatic unsigned
4283da084b3Smrgkoi8_ru_to_unicode(unsigned koicode, void *client_data)
4293da084b3Smrg{
4303da084b3Smrg    switch(koicode) {
4313da084b3Smrg    case 0x93: return 0x201C;
4323da084b3Smrg    case 0x96: return 0x201D;
4333da084b3Smrg    case 0x97: return 0x2014;
4343da084b3Smrg    case 0x98: return 0x2116;
4353da084b3Smrg    case 0x99: return 0x2122;
4363da084b3Smrg    case 0x9B: return 0x00BB;
4373da084b3Smrg    case 0x9C: return 0x00AE;
4383da084b3Smrg    case 0x9D: return 0x00AB;
4393da084b3Smrg    case 0x9F: return 0x00A4;
4403da084b3Smrg    case 0xA4: return 0x0454;
4413da084b3Smrg    case 0xA6: return 0x0456;
4423da084b3Smrg    case 0xA7: return 0x0457;
4433da084b3Smrg    case 0xAD: return 0x0491;
4443da084b3Smrg    case 0xAE: return 0x045E;
4453da084b3Smrg    case 0xB4: return 0x0404;
4463da084b3Smrg    case 0xB6: return 0x0406;
4473da084b3Smrg    case 0xB7: return 0x0407;
4483da084b3Smrg    case 0xBD: return 0x0490;
4493da084b3Smrg    case 0xBE: return 0x040E;
4503da084b3Smrg    default: return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
4513da084b3Smrg  }
4523da084b3Smrg}
4533da084b3Smrg
4543da084b3Smrgstatic FontMapRec koi8_ru[]=
4553da084b3Smrg{
4563da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,koi8_ru_to_unicode,NULL,NULL,NULL,NULL},
4573da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
4583da084b3Smrg};
4593da084b3Smrg
4603da084b3Smrg/* koi8-e, ISO-IR-111 or ECMA-Cyrillic */
4613da084b3Smrg
4623da084b3Smrgstatic const unsigned short koi8_e_A0_BF[]=
4633da084b3Smrg{ 0x00A0, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
4643da084b3Smrg  0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00AD, 0x045E, 0x045F,
4653da084b3Smrg  0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
4663da084b3Smrg  0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00A4, 0x040E, 0x040F };
4673da084b3Smrg
4683da084b3Smrgstatic unsigned
4693da084b3Smrgkoi8_e_to_unicode(unsigned koicode, void *client_data)
4703da084b3Smrg{
4713da084b3Smrg    if(koicode<0xA0)
4723da084b3Smrg        return koicode;
4733da084b3Smrg    else if(koicode<0xC0)
4743da084b3Smrg        return koi8_e_A0_BF[koicode-0xA0];
4753da084b3Smrg    else
4763da084b3Smrg        return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
4773da084b3Smrg}
4783da084b3Smrg
4793da084b3Smrgstatic FontMapRec koi8_e[]=
4803da084b3Smrg{
4813da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,koi8_e_to_unicode,NULL,NULL,NULL,NULL},
4823da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
4833da084b3Smrg};
4843da084b3Smrg
4853da084b3Smrg/* Koi8 unified */
4863da084b3Smrg
4873da084b3Smrgstatic const unsigned short koi8_uni_80_BF[]=
4883da084b3Smrg{ 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
4893da084b3Smrg  0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
4903da084b3Smrg  0x2591, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
4913da084b3Smrg  0x00A9, 0x2122, 0x00A0, 0x00BB, 0x00AE, 0x00AB, 0x00B7, 0x00A4,
4923da084b3Smrg  0x00A0, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
4933da084b3Smrg  0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x0491, 0x045E, 0x045F,
4943da084b3Smrg  0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
4953da084b3Smrg  0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x0490, 0x040E, 0x040F };
4963da084b3Smrg
4973da084b3Smrgstatic unsigned
4983da084b3Smrgkoi8_uni_to_unicode(unsigned koicode, void *client_data)
4993da084b3Smrg{
5003da084b3Smrg    if(koicode<0x80)
5013da084b3Smrg        return koicode;
5023da084b3Smrg    else if(koicode<0xC0)
5033da084b3Smrg        return koi8_uni_80_BF[koicode-0x80];
5043da084b3Smrg    else
5053da084b3Smrg        return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
5063da084b3Smrg}
5073da084b3Smrg
5083da084b3Smrgstatic FontMapRec koi8_uni[]=
5093da084b3Smrg{
5103da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,koi8_uni_to_unicode,NULL,NULL,NULL,NULL},
5113da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
5123da084b3Smrg};
5133da084b3Smrg
5143da084b3Smrg/* Ukrainian variant of Koi8-R; see RFC 2319 */
5153da084b3Smrg
5163da084b3Smrgstatic unsigned
5173da084b3Smrgkoi8_u_to_unicode(unsigned koicode, void *client_data)
5183da084b3Smrg{
5193da084b3Smrg    switch(koicode) {
5203da084b3Smrg    case 0xA4: return 0x0454;
5213da084b3Smrg    case 0xA6: return 0x0456;
5223da084b3Smrg    case 0xA7: return 0x0457;
5233da084b3Smrg    case 0xAD: return 0x0491;
5243da084b3Smrg    case 0xB4: return 0x0404;
5253da084b3Smrg    case 0xB6: return 0x0406;
5263da084b3Smrg    case 0xB7: return 0x0407;
5273da084b3Smrg    case 0xBD: return 0x0490;
5283da084b3Smrg    default: return FontEncSimpleRecode(koicode, &koi8_r_to_unicode_map);
5293da084b3Smrg    }
5303da084b3Smrg}
5313da084b3Smrg
5323da084b3Smrgstatic FontMapRec koi8_u[]=
5333da084b3Smrg{
5343da084b3Smrg    {FONT_ENCODING_UNICODE,0,0,koi8_u_to_unicode,NULL,NULL,NULL},
5353da084b3Smrg    {0,0,0,NULL,NULL,NULL,NULL,NULL}
5363da084b3Smrg};
5373da084b3Smrg
5383da084b3Smrg/* Microsoft Symbol, which is only meaningful for TrueType fonts, is
5393da084b3Smrg   treated specially in ftenc.c, where we add usFirstCharIndex-0x20 to
5403da084b3Smrg   the glyph index before applying the cmap.  Lovely design. */
5413da084b3Smrg
5423da084b3Smrgstatic FontMapRec microsoft_symbol[]=
5433da084b3Smrg{{FONT_ENCODING_TRUETYPE,3,0,NULL,NULL,NULL,NULL,NULL},
5443da084b3Smrg /* You never know */
5453da084b3Smrg {FONT_ENCODING_TRUETYPE,3,1,NULL,NULL,NULL,NULL,NULL},
5463da084b3Smrg {0,0,0,NULL,NULL,NULL,NULL,NULL}};
5473da084b3Smrg
5483da084b3Smrgstatic FontMapRec apple_roman[]=
5493da084b3Smrg{{FONT_ENCODING_TRUETYPE,1,0,NULL,NULL,NULL,NULL,NULL},
5503da084b3Smrg {0,0,0,NULL,NULL,NULL,NULL,NULL}};
5513da084b3Smrg
5523da084b3Smrg/* The data for recodings */
5533da084b3Smrg
5543da084b3Smrg/* For compatibility with X11R6.4.  Losers. */
5553da084b3Smrgstatic char *iso8859_15_aliases[2]={"fcd8859-15",NULL};
5563da084b3Smrg
5573da084b3Smrgstatic FontEncRec initial_encodings[]=
5583da084b3Smrg{
5593da084b3Smrg    {"iso10646-1",NULL,256*256,0,iso10646,NULL,0,0}, /* Unicode */
5603da084b3Smrg    {"iso8859-1",NULL,256,0,iso8859_1,NULL,0,0}, /* Latin 1 (West European) */
5613da084b3Smrg    {"iso8859-2",NULL,256,0,iso8859_2,NULL,0,0}, /* Latin 2 (East European) */
5623da084b3Smrg    {"iso8859-3",NULL,256,0,iso8859_3,NULL,0,0}, /* Latin 3 (South European) */
5633da084b3Smrg    {"iso8859-4",NULL,256,0,iso8859_4,NULL,0,0}, /* Latin 4 (North European) */
5643da084b3Smrg    {"iso8859-5",NULL,256,0,iso8859_5,NULL,0,0}, /* Cyrillic */
5653da084b3Smrg    {"iso8859-6",NULL,256,0,iso8859_6,NULL,0,0}, /* Arabic */
5663da084b3Smrg    {"iso8859-7",NULL,256,0,iso8859_7,NULL,0,0}, /* Greek */
5673da084b3Smrg    {"iso8859-8",NULL,256,0,iso8859_8,NULL,0,0}, /* Hebrew */
5683da084b3Smrg    {"iso8859-9",NULL,256,0,iso8859_9,NULL,0,0}, /* Latin 5 (Turkish) */
5693da084b3Smrg    {"iso8859-10",NULL,256,0,iso8859_10,NULL,0,0}, /* Latin 6 (Nordic) */
5703da084b3Smrg    {"iso8859-15",iso8859_15_aliases,256,0,iso8859_15,NULL,0,0}, /* Latin 9 */
5713da084b3Smrg    {"koi8-r",NULL,256,0,koi8_r,NULL,0,0},       /* Russian */
5723da084b3Smrg    {"koi8-ru",NULL,256,0,koi8_ru,NULL,0,0},     /* Ukrainian */
5733da084b3Smrg    {"koi8-uni",NULL,256,0,koi8_uni,NULL,0,0},   /* Russian/Ukrainian/Bielorussian */
5743da084b3Smrg    {"koi8-e",NULL,256,0,koi8_e,NULL,0,0},       /* ``European'' */
5753da084b3Smrg    {"koi8-u",NULL,256,0,koi8_u,NULL,0,0},       /* Ukrainian too */
5763da084b3Smrg    {"microsoft-symbol",NULL,256,0,microsoft_symbol,NULL,0,0},
5773da084b3Smrg    {"apple-roman",NULL,256,0,apple_roman,NULL,0,0},
5783da084b3Smrg    {NULL,NULL,0,0,NULL,NULL,0,0}
5793da084b3Smrg};
5803da084b3Smrg
5813da084b3Smrgstatic FontEncPtr font_encodings=NULL;
5823da084b3Smrg
5833da084b3Smrgstatic void
5843da084b3Smrgdefine_initial_encoding_info(void)
5853da084b3Smrg{
5863da084b3Smrg    FontEncPtr encoding;
5873da084b3Smrg    FontMapPtr mapping;
5883da084b3Smrg
5893da084b3Smrg    font_encodings = initial_encodings;
5903da084b3Smrg    for(encoding = font_encodings; ; encoding++) {
5913da084b3Smrg        encoding->next = encoding + 1;
5923da084b3Smrg        for(mapping = encoding->mappings; ; mapping++) {
5933da084b3Smrg            mapping->next = mapping+1;
5943da084b3Smrg            mapping->encoding = encoding;
5953da084b3Smrg            if(mapping->next->type == 0) {
5963da084b3Smrg                mapping->next = NULL;
5973da084b3Smrg                break;
5983da084b3Smrg            }
5993da084b3Smrg        }
6003da084b3Smrg        if(!encoding->next->name) {
6013da084b3Smrg            encoding->next = NULL;
6023da084b3Smrg            break;
6033da084b3Smrg        }
6043da084b3Smrg    }
6053da084b3Smrg}
6063da084b3Smrg
6073da084b3Smrg
6083da084b3Smrgchar*
6093da084b3SmrgFontEncFromXLFD(const char *name, int length)
6103da084b3Smrg{
6113da084b3Smrg    const char *p;
6123da084b3Smrg    char *q;
6133da084b3Smrg    static char charset[MAXFONTNAMELEN];
6143da084b3Smrg    int len;
6153da084b3Smrg
6163da084b3Smrg    if(length > MAXFONTNAMELEN - 1)
6173da084b3Smrg        return NULL;
6183da084b3Smrg
6193da084b3Smrg    if(name == NULL)
6203da084b3Smrg        p = NULL;
6213da084b3Smrg    else {
6223da084b3Smrg        p = name + length - 1;
6233da084b3Smrg        while(p > name && *p != '-')
6243da084b3Smrg            p--;
6253da084b3Smrg        p--;
6263da084b3Smrg        while(p >= name && *p != '-')
6273da084b3Smrg            p--;
6283da084b3Smrg        if(p <= name)
6293da084b3Smrg            p = NULL;
6303da084b3Smrg    }
6313da084b3Smrg
6323da084b3Smrg    /* now p either is null or points at the '-' before the charset registry */
6333da084b3Smrg
6343da084b3Smrg    if(p == 0)
6353da084b3Smrg        return NULL;
6363da084b3Smrg
6373da084b3Smrg    len = length - (p - name) - 1;
6383da084b3Smrg    memcpy(charset, p+1, len);
6393da084b3Smrg    charset[len] = 0;
6403da084b3Smrg
6413da084b3Smrg    /* check for a subset specification */
6423da084b3Smrg    if((q = strchr(charset, (int)'[')))
6433da084b3Smrg        *q = 0;
6443da084b3Smrg
6453da084b3Smrg    return charset;
6463da084b3Smrg}
6473da084b3Smrg
6483da084b3Smrgunsigned
6493da084b3SmrgFontEncRecode(unsigned code,  FontMapPtr mapping)
6503da084b3Smrg{
6513da084b3Smrg    FontEncPtr encoding = mapping->encoding;
6523da084b3Smrg    if(encoding && mapping->recode) {
6533da084b3Smrg        if(encoding->row_size == 0) {
6543da084b3Smrg            /* linear encoding */
6553da084b3Smrg            if(code < encoding->first || code>=encoding->size)
6563da084b3Smrg                return 0;
6573da084b3Smrg        } else {
6583da084b3Smrg            /* matrix encoding */
6593da084b3Smrg            int row = code/0x100, col = code&0xFF;
6603da084b3Smrg            if(row < encoding->first || row >= encoding->size ||
6613da084b3Smrg               col < encoding->first_col || col >= encoding->row_size)
6623da084b3Smrg                return 0;
6633da084b3Smrg        }
6643da084b3Smrg        return (*mapping->recode)(code, mapping->client_data);
6653da084b3Smrg    } else
6663da084b3Smrg        return code;
6673da084b3Smrg}
6683da084b3Smrg
6693da084b3Smrgchar*
6703da084b3SmrgFontEncName(unsigned code, FontMapPtr mapping)
6713da084b3Smrg{
6723da084b3Smrg    FontEncPtr encoding = mapping->encoding;
6733da084b3Smrg    if(encoding && mapping->name) {
6743da084b3Smrg        if((encoding->row_size == 0 && code >= encoding->size) ||
6753da084b3Smrg           (encoding->row_size != 0 &&
6763da084b3Smrg            (code/0x100 >= encoding->size ||
6773da084b3Smrg             (code&0xFF) >= encoding->row_size)))
6783da084b3Smrg            return NULL;
6793da084b3Smrg        return (*mapping->name)(code, mapping->client_data);
6803da084b3Smrg    } else
6813da084b3Smrg        return NULL;
6823da084b3Smrg}
6833da084b3Smrg
6843da084b3SmrgFontEncPtr
6853da084b3SmrgFontEncFind(const char *encoding_name, const char *filename)
6863da084b3Smrg{
6873da084b3Smrg    FontEncPtr encoding;
6883da084b3Smrg    char **alias;
6893da084b3Smrg
6903da084b3Smrg    if(font_encodings == NULL) define_initial_encoding_info();
6913da084b3Smrg
6923da084b3Smrg    for(encoding = font_encodings; encoding; encoding = encoding->next) {
6933da084b3Smrg        if(!strcasecmp(encoding->name, encoding_name))
6943da084b3Smrg            return encoding;
6953da084b3Smrg        if(encoding->aliases)
6963da084b3Smrg            for(alias=encoding->aliases; *alias; alias++)
6973da084b3Smrg                if(!strcasecmp(*alias, encoding_name))
6983da084b3Smrg                    return encoding;
6993da084b3Smrg  }
7003da084b3Smrg
7013da084b3Smrg  /* Unknown charset, try to load a definition file */
7023da084b3Smrg    return FontEncLoad(encoding_name, filename);
7033da084b3Smrg}
7043da084b3Smrg
7053da084b3SmrgFontMapPtr
7063da084b3SmrgFontMapFind(FontEncPtr encoding, int type, int pid, int eid)
7073da084b3Smrg{
7083da084b3Smrg    FontMapPtr mapping;
7093da084b3Smrg    if(encoding == NULL)
7103da084b3Smrg        return NULL;
7113da084b3Smrg
7123da084b3Smrg    for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
7133da084b3Smrg        if(mapping->type != type)
7143da084b3Smrg            continue;
7153da084b3Smrg        if(pid > 0 && mapping->pid != pid)
7163da084b3Smrg            continue;
7173da084b3Smrg        if(eid > 0 && mapping->eid != eid)
7183da084b3Smrg            continue;
7193da084b3Smrg        return mapping;
7203da084b3Smrg    }
7213da084b3Smrg    return NULL;
7223da084b3Smrg}
7233da084b3Smrg
7243da084b3SmrgFontMapPtr
7253da084b3SmrgFontEncMapFind(const char *encoding_name, int type, int pid, int eid,
7263da084b3Smrg               const char *filename)
7273da084b3Smrg{
7283da084b3Smrg    FontEncPtr encoding;
7293da084b3Smrg    FontMapPtr mapping;
7303da084b3Smrg
7313da084b3Smrg    encoding = FontEncFind(encoding_name, filename);
7323da084b3Smrg    if(encoding == NULL)
7333da084b3Smrg        return NULL;
7343da084b3Smrg    mapping = FontMapFind(encoding, type, pid, eid);
7353da084b3Smrg    return mapping;
7363da084b3Smrg}
7373da084b3Smrg
7383da084b3Smrgstatic FontEncPtr
7393da084b3SmrgFontEncLoad(const char *encoding_name, const char *filename)
7403da084b3Smrg{
7413da084b3Smrg    FontEncPtr encoding;
7423da084b3Smrg
7433da084b3Smrg    encoding = FontEncReallyLoad(encoding_name, filename);
7443da084b3Smrg    if (encoding == NULL) {
7453da084b3Smrg        return NULL;
7463da084b3Smrg    } else {
7473da084b3Smrg        char **alias;
7483da084b3Smrg        int found = 0;
7493da084b3Smrg
7503da084b3Smrg        /* Check whether the name is already known for this encoding */
7513da084b3Smrg        if(strcasecmp(encoding->name, encoding_name) == 0) {
7523da084b3Smrg            found = 1;
7533da084b3Smrg        } else {
7543da084b3Smrg            if(encoding->aliases) {
7553da084b3Smrg                for(alias=encoding->aliases; *alias; alias++)
7563da084b3Smrg                    if(!strcasecmp(*alias, encoding_name)) {
7573da084b3Smrg                        found = 1;
7583da084b3Smrg                        break;
7593da084b3Smrg                    }
7603da084b3Smrg            }
7613da084b3Smrg        }
7623da084b3Smrg
7633da084b3Smrg        if(!found) {
7643da084b3Smrg            /* Add a new alias.  This works because we know that this
7653da084b3Smrg               particular encoding has been allocated dynamically */
7663da084b3Smrg            char **new_aliases;
7673da084b3Smrg            char *new_name;
7683da084b3Smrg            int numaliases = 0;
7693da084b3Smrg
7703da084b3Smrg            new_name = xalloc(strlen(encoding_name) + 1);
7713da084b3Smrg            if(new_name == NULL)
7723da084b3Smrg                return NULL;
7733da084b3Smrg            strcpy(new_name, encoding_name);
7743da084b3Smrg            if(encoding->aliases) {
7753da084b3Smrg                for(alias = encoding->aliases; *alias; alias++)
7763da084b3Smrg                    numaliases++;
7773da084b3Smrg            }
7783da084b3Smrg            new_aliases = (char**)xalloc((numaliases+2)*sizeof(char*));
7793da084b3Smrg            if(new_aliases == NULL) {
7803da084b3Smrg                xfree(new_name);
7813da084b3Smrg                return NULL;
7823da084b3Smrg            }
7833da084b3Smrg            if(encoding->aliases) {
7843da084b3Smrg                memcpy(new_aliases, encoding->aliases, numaliases*sizeof(char*));
7853da084b3Smrg                xfree(encoding->aliases);
7863da084b3Smrg            }
7873da084b3Smrg            new_aliases[numaliases] = new_name;
7883da084b3Smrg            new_aliases[numaliases+1] = NULL;
7893da084b3Smrg            encoding->aliases = new_aliases;
7903da084b3Smrg        }
7913da084b3Smrg
7923da084b3Smrg        /* register the new encoding */
7933da084b3Smrg        encoding->next=font_encodings;
7943da084b3Smrg        font_encodings=encoding;
7953da084b3Smrg
7963da084b3Smrg        return encoding;
7973da084b3Smrg    }
7983da084b3Smrg}
7993da084b3Smrg
8003da084b3Smrgunsigned
8013da084b3SmrgFontEncSimpleRecode(unsigned code, void *client_data)
8023da084b3Smrg{
8033da084b3Smrg    FontEncSimpleMapPtr map;
8043da084b3Smrg    unsigned index;
8053da084b3Smrg
8063da084b3Smrg    map = client_data;
8073da084b3Smrg
8083da084b3Smrg    if(code > 0xFFFF || (map->row_size && (code&0xFF) >= map->row_size))
8093da084b3Smrg        return 0;
8103da084b3Smrg
8113da084b3Smrg    if(map->row_size)
8123da084b3Smrg        index = (code&0xFF)+(code>>8)*map->row_size;
8133da084b3Smrg    else
8143da084b3Smrg        index = code;
8153da084b3Smrg
8163da084b3Smrg  if(map->map && index>=map->first && index<map->first+map->len)
8173da084b3Smrg    return map->map[index-map->first];
8183da084b3Smrg  else
8193da084b3Smrg    return code;
8203da084b3Smrg}
8213da084b3Smrg
8223da084b3Smrgchar *
8233da084b3SmrgFontEncSimpleName(unsigned code, void *client_data)
8243da084b3Smrg{
8253da084b3Smrg    FontEncSimpleNamePtr map;
8263da084b3Smrg
8273da084b3Smrg    map = client_data;
8283da084b3Smrg    if(map && code >= map->first && code<map->first+map->len)
8293da084b3Smrg        return map->map[code-map->first];
8303da084b3Smrg    else
8313da084b3Smrg        return NULL;
8323da084b3Smrg}
8333da084b3Smrg
8343da084b3Smrgunsigned
8353da084b3SmrgFontEncUndefinedRecode(unsigned code, void *client_data)
8363da084b3Smrg{
8373da084b3Smrg    return code;
8383da084b3Smrg}
8393da084b3Smrg
8403da084b3Smrgchar *
8413da084b3SmrgFontEncUndefinedName(unsigned code, void *client_data)
8423da084b3Smrg{
8433da084b3Smrg    return NULL;
8443da084b3Smrg}
8453da084b3Smrg
8463da084b3Smrg#define FONTENC_SEGMENT_SIZE 256
8473da084b3Smrg#define FONTENC_SEGMENTS 256
8483da084b3Smrg#define FONTENC_INVERSE_CODES (FONTENC_SEGMENT_SIZE * FONTENC_SEGMENTS)
8493da084b3Smrg
8503da084b3Smrgstatic unsigned int
8513da084b3Smrgreverse_reverse(unsigned i, void* data)
8523da084b3Smrg{
8533da084b3Smrg    int s, j;
8543da084b3Smrg    unsigned **map = (unsigned**)data;
8553da084b3Smrg
8563da084b3Smrg    if(i >= FONTENC_INVERSE_CODES)
8573da084b3Smrg        return 0;
8583da084b3Smrg
8593da084b3Smrg    if(map == NULL)
8603da084b3Smrg        return 0;
8613da084b3Smrg
8623da084b3Smrg    s = i / FONTENC_SEGMENT_SIZE;
8633da084b3Smrg    j = i % FONTENC_SEGMENT_SIZE;
8643da084b3Smrg
8653da084b3Smrg    if(map[s] == NULL)
8663da084b3Smrg        return 0;
8673da084b3Smrg    else
8683da084b3Smrg        return map[s][j];
8693da084b3Smrg}
8703da084b3Smrg
8713da084b3Smrgstatic int
8723da084b3Smrgtree_set(unsigned int **map, unsigned int i, unsigned int j)
8733da084b3Smrg{
8743da084b3Smrg    int s, c;
8753da084b3Smrg
8763da084b3Smrg    if(i >= FONTENC_INVERSE_CODES)
8773da084b3Smrg        return FALSE;
8783da084b3Smrg
8793da084b3Smrg    s = i / FONTENC_SEGMENT_SIZE;
8803da084b3Smrg    c = i % FONTENC_SEGMENT_SIZE;
8813da084b3Smrg
8823da084b3Smrg    if(map[s] == NULL) {
8833da084b3Smrg        map[s] = calloc(FONTENC_SEGMENT_SIZE, sizeof(int));
8843da084b3Smrg        if(map[s] == NULL)
8853da084b3Smrg            return FALSE;
8863da084b3Smrg  }
8873da084b3Smrg
8883da084b3Smrg    map[s][c] = j;
8893da084b3Smrg    return TRUE;
8903da084b3Smrg}
8913da084b3Smrg
8923da084b3SmrgFontMapReversePtr
8933da084b3SmrgFontMapReverse(FontMapPtr mapping)
8943da084b3Smrg{
8953da084b3Smrg    FontEncPtr encoding = mapping->encoding;
8963da084b3Smrg    FontMapReversePtr reverse = NULL;
8973da084b3Smrg    unsigned int **map = NULL;
8983da084b3Smrg    int i, j, k;
8993da084b3Smrg
9003da084b3Smrg    if(encoding == NULL) goto bail;
9013da084b3Smrg
9023da084b3Smrg    map = calloc(FONTENC_SEGMENTS, sizeof(int*));
9033da084b3Smrg    if(map == NULL) goto bail;
9043da084b3Smrg
9053da084b3Smrg    if(encoding->row_size == 0) {
9063da084b3Smrg        for(i = encoding->first; i < encoding->size; i++) {
9073da084b3Smrg            k = FontEncRecode(i, mapping);
9083da084b3Smrg            if(k != 0)
9093da084b3Smrg                if(!tree_set(map, k, i))
9103da084b3Smrg                    goto bail;
9113da084b3Smrg        }
9123da084b3Smrg    } else {
9133da084b3Smrg        for(i = encoding->first; i < encoding->size; i++) {
9143da084b3Smrg            for(j = encoding->first_col; j < encoding->row_size; j++) {
9153da084b3Smrg                k = FontEncRecode(i*256 + j, mapping);
9163da084b3Smrg                if(k != 0)
9173da084b3Smrg                    if(!tree_set(map, k, i*256+j))
9183da084b3Smrg                        goto bail;
9193da084b3Smrg            }
9203da084b3Smrg        }
9213da084b3Smrg    }
9223da084b3Smrg
9233da084b3Smrg    reverse = malloc(sizeof(FontMapReverseRec));
9243da084b3Smrg    if(!reverse) goto bail;
9253da084b3Smrg
9263da084b3Smrg    reverse->reverse = reverse_reverse;
9273da084b3Smrg    reverse->data = map;
9283da084b3Smrg    return reverse;
9293da084b3Smrg
9303da084b3Smrg  bail:
9313da084b3Smrg    if(map)
9323da084b3Smrg        xfree(map);
9333da084b3Smrg    if(reverse)
9343da084b3Smrg        xfree(reverse);
9353da084b3Smrg    return NULL;
9363da084b3Smrg}
9373da084b3Smrg
9383da084b3Smrgvoid
9393da084b3SmrgFontMapReverseFree(FontMapReversePtr delendum)
9403da084b3Smrg{
9413da084b3Smrg    unsigned int **map = (unsigned int**)delendum;
9423da084b3Smrg    int i;
9433da084b3Smrg
9443da084b3Smrg    if(map == NULL)
9453da084b3Smrg        return;
9463da084b3Smrg
9473da084b3Smrg    for(i = 0; i < FONTENC_SEGMENTS; i++)
9483da084b3Smrg        if(map[i] != NULL)
9493da084b3Smrg            xfree(map[i]);
9503da084b3Smrg
9513da084b3Smrg    xfree(map);
9523da084b3Smrg    return;
9533da084b3Smrg}
954