1 /* Copyright (C) 2000-2008 by George Williams */
2 /*
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are met:
5 
6  * Redistributions of source code must retain the above copyright notice, this
7  * list of conditions and the following disclaimer.
8 
9  * Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12 
13  * The name of the author may not be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15 
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "fontforgevw.h"
29 #include <ustring.h>
30 #include <utype.h>
31 #include <math.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <dirent.h>
35 #include <gfile.h>
36 #include "plugins.h"
37 #include "encoding.h"
38 
39 Encoding *default_encoding = NULL;
40 
41 static int32 tex_base_encoding[] = {
42     0x0000, 0x02d9, 0xfb01, 0xfb02, 0x2044, 0x02dd, 0x0141, 0x0142,
43     0x02db, 0x02da, 0x000a, 0x02d8, 0x2212, 0x000d, 0x017d, 0x017e,
44     0x02c7, 0x0131, 0xf6be, 0xfb00, 0xfb03, 0xfb04, 0x2260, 0x221e,
45     0x2264, 0x2265, 0x2202, 0x2211, 0x220f, 0x03c0, 0x0060, 0x0027,
46     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2019,
47     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
48     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
49     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
50     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
51     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
52     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
53     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
54     0x2018, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
55     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
56     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
57     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
58     0x20ac, 0x222b, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
59     0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x2126, 0x221a, 0x2248,
60     0x0090, 0x0091, 0x0092, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
61     0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x2206, 0x25ca, 0x0178,
62     0x0000, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
63     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x002d, 0x00ae, 0x00af,
64     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
65     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
66     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
67     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
68     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
69     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
70     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
71     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
72     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
73     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
74 };
75 
76 static int32 unicode_from_MacSymbol[] = {
77   0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
78   0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
79   0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
80   0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
81   0x0020, 0x0021, 0x2200, 0x0023, 0x2203, 0x0025, 0x0026, 0x220d,
82   0x0028, 0x0029, 0x2217, 0x002b, 0x002c, 0x2212, 0x002e, 0x002f,
83   0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
84   0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
85   0x2245, 0x0391, 0x0392, 0x03a7, 0x0394, 0x0395, 0x03a6, 0x0393,
86   0x0397, 0x0399, 0x03d1, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f,
87   0x03a0, 0x0398, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03c2, 0x03a9,
88   0x039e, 0x03a8, 0x0396, 0x005b, 0x2234, 0x005d, 0x22a5, 0x005f,
89   0xf8e5, 0x03b1, 0x03b2, 0x03c7, 0x03b4, 0x03b5, 0x03c6, 0x03b3,
90   0x03b7, 0x03b9, 0x03d5, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf,
91   0x03c0, 0x03b8, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03d6, 0x03c9,
92   0x03be, 0x03c8, 0x03b6, 0x007b, 0x007c, 0x007d, 0x223c, 0x007f,
93   0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
94   0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
95   0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
96   0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
97   0x0000, 0x03d2, 0x2032, 0x2264, 0x2044, 0x221e, 0x0192, 0x2663,
98   0x2666, 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193,
99   0x00b0, 0x00b1, 0x2033, 0x2265, 0x00d7, 0x221d, 0x2202, 0x2022,
100   0x00f7, 0x2260, 0x2261, 0x2248, 0x2026, 0xf8e6, 0xf8e7, 0x21b5,
101   0x2135, 0x2111, 0x211c, 0x2118, 0x2297, 0x2295, 0x2205, 0x2229,
102   0x222a, 0x2283, 0x2287, 0x2284, 0x2282, 0x2286, 0x2208, 0x2209,
103   0x2220, 0x2207, 0x00ae, 0x00a9, 0x2122, 0x220f, 0x221a, 0x22c5,
104   0x00ac, 0x2227, 0x2228, 0x21d4, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
105   0x22c4, 0x2329, 0xf8e8, 0xf8e9, 0xf8ea, 0x2211, 0xf8eb, 0xf8ec,
106   0xf8ed, 0xf8ee, 0xf8ef, 0xf8f0, 0xf8f1, 0xf8f2, 0xf8f3, 0xf8f4,
107   0xf8ff, 0x232a, 0x222b, 0x2320, 0xf8f5, 0x2321, 0xf8f6, 0xf8f7,
108   0xf8f8, 0xf8f9, 0xf8fa, 0xf8fb, 0xf8fc, 0xf8fd, 0xf8fe, 0x02c7
109 };
110 
111 /* I don't think iconv provides encodings for zapfdingbats nor jis201 */
112 /*  Perhaps I should list them here for compatability, but I think I'll just */
113 /*  leave them out. I doubt they get used.				     */
114 static Encoding texbase = { "TeX-Base-Encoding", 256, tex_base_encoding, NULL, NULL, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0 }, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 0, 0  };
115        Encoding custom = { "Custom", 0, NULL, NULL, &texbase,			  1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, { 0, 0 }, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 0, 0 };
116 static Encoding original = { "Original", 0, NULL, NULL, &custom,		  1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, { 0, 0 }, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 0, 0  };
117 static Encoding unicodebmp = { "UnicodeBmp", 65536, NULL, NULL, &original, 	  1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0 }, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 0, 0  };
118 static Encoding unicodefull = { "UnicodeFull", 17*65536, NULL, NULL, &unicodebmp, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, { 0, 0 }, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 0, 0  };
119 static Encoding adobestd = { "AdobeStandard", 256, unicode_from_adobestd, AdobeStandardEncoding, &unicodefull,
120 										  1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0 }, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 0, 0  };
121 static Encoding symbol = { "Symbol", 256, unicode_from_MacSymbol, NULL, &adobestd,1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0 }, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 0, 0  };
122 
123 Encoding *enclist = &symbol;
124 
FindUnicharName(void)125 const char *FindUnicharName(void) {
126     /* Iconv and libiconv use different names for UCS2. Just great. Perhaps */
127     /*  different versions of each use still different names? */
128     /* Even worse, both accept UCS-2, but under iconv it means native byte */
129     /*  ordering and under libiconv it means big-endian */
130     iconv_t test;
131     static char *goodname = NULL;
132 #ifdef UNICHAR_16
133     static char *names[] = { "UCS-2-INTERNAL", "UCS-2", "UCS2", "ISO-10646/UCS2", "UNICODE", NULL };
134     static char *namesle[] = { "UCS-2LE", "UNICODELITTLE", NULL };
135     static char *namesbe[] = { "UCS-2BE", "UNICODEBIG", NULL };
136 #else
137     static char *names[] = { "UCS-4-INTERNAL", "UCS-4", "UCS4", "ISO-10646-UCS-4", "UTF-32", NULL };
138     static char *namesle[] = { "UCS-4LE", "UTF-32LE", NULL };
139     static char *namesbe[] = { "UCS-4BE", "UTF-32BE", NULL };
140 #endif
141     char **testnames;
142     int i;
143     union {
144 	short s;
145 	char c[2];
146     } u;
147 
148     if ( goodname!=NULL )
149 return( goodname );
150 
151     u.c[0] = 0x1; u.c[1] = 0x2;
152     if ( u.s==0x201 ) {		/* Little endian */
153 	testnames = namesle;
154     } else {
155 	testnames = namesbe;
156     }
157     for ( i=0; testnames[i]!=NULL; ++i ) {
158 	test = iconv_open(testnames[i],"ISO-8859-1");
159 	if ( test!=(iconv_t) -1 && test!=NULL ) {
160 	    iconv_close(test);
161 	    goodname = testnames[i];
162     break;
163 	}
164     }
165 
166     if ( goodname==NULL ) {
167 	for ( i=0; names[i]!=NULL; ++i ) {
168 	    test = iconv_open(names[i],"ISO-8859-1");
169 	    if ( test!=(iconv_t) -1 && test!=NULL ) {
170 		iconv_close(test);
171 		goodname = names[i];
172 	break;
173 	    }
174 	}
175     }
176 
177     if ( goodname==NULL ) {
178 #ifdef UNICHAR_16
179 	IError( "I can't figure out your version of iconv(). I need a name for the UCS-2 encoding and I can't find one. Reconfigure --without-iconv. Bye.");
180 #else
181 	IError( "I can't figure out your version of iconv(). I need a name for the UCS-4 encoding and I can't find one. Reconfigure --without-iconv. Bye.");
182 #endif
183 	exit( 1 );
184     }
185 
186     test = iconv_open(goodname,"Mac");
187     if ( test==(iconv_t) -1 || test==NULL ) {
188 	IError( "Your version of iconv does not support the \"Mac Roman\" encoding.\nIf this causes problems, reconfigure --without-iconv." );
189     } else
190 	iconv_close(test);
191 
192     /* I really should check for ISO-2022-JP, KR, CN, and all the other encodings */
193     /*  I might find in a ttf 'name' table. But those tables take too long to build */
194 return( goodname );
195 }
196 
TryEscape(Encoding * enc,char * escape_sequence)197 static int TryEscape( Encoding *enc,char *escape_sequence ) {
198     char from[20], ucs[20];
199     size_t fromlen, tolen;
200     ICONV_CONST char *fpt;
201     char *upt;
202     int i, j, low;
203     int esc_len = strlen(escape_sequence);
204 
205     strcpy(from,escape_sequence);
206 
207     enc->has_2byte = false;
208     low = -1;
209     for ( i=0; i<256; ++i ) if ( i!=escape_sequence[0] ) {
210 	for ( j=0; j<256; ++j ) {
211 	    from[esc_len] = i; from[esc_len+1] = j; from[esc_len+2] = 0;
212 	    fromlen = esc_len+2;
213 	    fpt = from;
214 	    upt = ucs;
215 	    tolen = sizeof(ucs);
216 	    if ( iconv( enc->tounicode , &fpt, &fromlen, &upt, &tolen )!= (size_t) (-1) &&
217 		    upt-ucs==sizeof(unichar_t) /* Exactly one character */ ) {
218 		if ( low==-1 ) {
219 		    enc->low_page = low = i;
220 		    enc->has_2byte = true;
221 		}
222 		enc->high_page = i;
223 	break;
224 	    }
225 	}
226     }
227     if ( enc->low_page==enc->high_page )
228 	enc->has_2byte = false;
229     if ( enc->has_2byte ) {
230 	strcpy(enc->iso_2022_escape, escape_sequence);
231 	enc->iso_2022_escape_len = esc_len;
232     }
233 return( enc->has_2byte );
234 }
235 
_FindOrMakeEncoding(const char * name,int make_it)236 Encoding *_FindOrMakeEncoding(const char *name,int make_it) {
237     Encoding *enc;
238     char buffer[20];
239     const char *iconv_name;
240     Encoding temp;
241     uint8 good[256];
242     int i, j, any, all;
243     char from[8], ucs[20];
244     size_t fromlen, tolen;
245     ICONV_CONST char *fpt;
246     char *upt;
247     /* iconv is not case sensitive */
248 
249     if ( strncasecmp(name,"iso8859_",8)==0 || strncasecmp(name,"koi8_",5)==0 ) {
250 	/* Fixup for old naming conventions */
251 	strncpy(buffer,name,sizeof(buffer));
252 	*strchr(buffer,'_') = '-';
253 	name = buffer;
254     } else if ( strcasecmp(name,"iso-8859")==0 ) {
255 	/* Fixup for old naming conventions */
256 	strncpy(buffer,name,3);
257 	strncpy(buffer+3,name+4,sizeof(buffer)-3);
258 	name = buffer;
259     } else if ( strcasecmp(name,"isolatin1")==0 ) {
260         name = "iso8859-1";
261     } else if ( strcasecmp(name,"isocyrillic")==0 ) {
262         name = "iso8859-5";
263     } else if ( strcasecmp(name,"isoarabic")==0 ) {
264         name = "iso8859-6";
265     } else if ( strcasecmp(name,"isogreek")==0 ) {
266         name = "iso8859-7";
267     } else if ( strcasecmp(name,"isohebrew")==0 ) {
268         name = "iso8859-8";
269     } else if ( strcasecmp(name,"isothai")==0 ) {
270         name = "tis-620";	/* TIS doesn't define non-breaking space in 0xA0 */
271     } else if ( strcasecmp(name,"latin0")==0 || strcasecmp(name,"latin9")==0 ) {
272         name = "iso8859-15";	/* "latin-9" is supported (libiconv bug?) */
273     } else if ( strcasecmp(name,"koi8r")==0 ) {
274         name = "koi8-r";
275     } else if ( strncasecmp(name,"jis201",6)==0 || strncasecmp(name,"jisx0201",8)==0 ) {
276         name = "jis_x0201";
277     } else if ( strcasecmp(name,"AdobeStandardEncoding")==0 || strcasecmp(name,"Adobe")==0 )
278 	name = "AdobeStandard";
279     for ( enc=enclist; enc!=NULL; enc=enc->next )
280 	if ( strmatch(name,enc->enc_name)==0 ||
281 		(enc->iconv_name!=NULL && strmatch(name,enc->iconv_name)==0))
282 return( enc );
283     if ( strmatch(name,"unicode")==0 || strmatch(name,"iso10646")==0 || strmatch(name,"iso10646-1")==0 )
284 return( &unicodebmp );
285     if ( strmatch(name,"unicode4")==0 || strmatch(name,"ucs4")==0 )
286 return( &unicodefull );
287 
288     iconv_name = name;
289     /* Mac seems to work ok */
290     if ( strcasecmp(name,"win")==0 || strcasecmp(name,"ansi")==0 )
291 	iconv_name = "MS-ANSI";		/* "WINDOWS-1252";*/
292     else if ( strcasecmp(name,"gb2312pk")==0 || strcasecmp(name,"gb2312packed")==0 )
293     iconv_name = "EUC-CN";
294     else if ( strcasecmp(name,"wansung")==0 )
295 	iconv_name = "EUC-KR";
296     else if ( strcasecmp(name,"EUC-CN")==0 ) {
297 	iconv_name = name;
298 	name = "gb2312pk";
299     } else if ( strcasecmp(name,"EUC-KR")==0 ) {
300 	iconv_name = name;
301 	name = "wansung";
302     }
303 
304 /* Escape sequences:					*/
305 /*	ISO-2022-CN:     \e $ ) A ^N			*/
306 /*	ISO-2022-KR:     \e $ ) C ^N			*/
307 /*	ISO-2022-JP:     \e $ B				*/
308 /*	ISO-2022-JP-2:   \e $ ( D			*/
309 /*	ISO-2022-JP-3:   \e $ ( O			*/ /* Capital "O", not zero */
310 /*	ISO-2022-CN-EXT: \e $ ) E ^N			*/ /* Not sure about this, also uses CN escape */
311 
312     memset(&temp,0,sizeof(temp));
313     temp.builtin = true;
314     temp.tounicode = iconv_open(FindUnicharName(),iconv_name);
315     if ( temp.tounicode==(iconv_t) -1 || temp.tounicode==NULL )
316 return( NULL );			/* Iconv doesn't recognize this name */
317     temp.fromunicode = iconv_open(iconv_name,FindUnicharName());
318     if ( temp.fromunicode==(iconv_t) -1 || temp.fromunicode==NULL ) {
319 	/* This should never happen, but if it does... */
320 	iconv_close(temp.tounicode);
321 return( NULL );
322     }
323 
324     memset(good,0,sizeof(good));
325     any = false; all = true;
326     for ( i=1; i<256; ++i ) {
327 	from[0] = i; from[1] = 0;
328 	fromlen = 1;
329 	fpt = from;
330 	upt = ucs;
331 	tolen = sizeof(ucs);
332 	if ( iconv( temp.tounicode , &fpt, &fromlen, &upt, &tolen )!= (size_t) (-1)) {
333 	    good[i] = true;
334 	    any = true;
335 	} else
336 	    all = false;
337     }
338     if ( any )
339 	temp.has_1byte = true;
340     if ( all )
341 	temp.only_1byte = true;
342 
343     if ( !all ) {
344 	if ( strstr(iconv_name,"2022")==NULL ) {
345 	    for ( i=temp.has_1byte; i<256; ++i ) if ( !good[i] ) {
346 		for ( j=0; j<256; ++j ) {
347 		    from[0] = i; from[1] = j; from[2] = 0;
348 		    fromlen = 2;
349 		    fpt = from;
350 		    upt = ucs;
351 		    tolen = sizeof(ucs);
352 		    if ( iconv( temp.tounicode , &fpt, &fromlen, &upt, &tolen )!= (size_t) (-1) &&
353 			    upt-ucs==sizeof(unichar_t) /* Exactly one character */ ) {
354 			if ( temp.low_page==-1 )
355 			    temp.low_page = i;
356 			temp.high_page = i;
357 			temp.has_2byte = true;
358 		break;
359 		    }
360 		}
361 	    }
362 	    if ( temp.low_page==temp.high_page ) {
363 		temp.has_2byte = false;
364 		temp.low_page = temp.high_page = -1;
365 	    }
366 	}
367 	if ( !temp.has_2byte && !good[033]/* escape */ ) {
368 	    if ( strstr(iconv_name,"2022")!=NULL &&
369 		    strstr(iconv_name,"JP3")!=NULL &&
370                       TryEscape( &temp,"\33$(O" )) {
371 		;
372 	    }
373 	    else if ( strstr(iconv_name,"2022")!=NULL &&
374 		    strstr(iconv_name,"JP2")!=NULL &&
375 		      TryEscape( &temp,"\33$(D" )) {
376 		;
377 	    }
378 	    else if ( strstr(iconv_name,"2022")!=NULL &&
379 		    strstr(iconv_name,"JP")!=NULL &&
380 		      TryEscape( &temp,"\33$B" )) {
381 		;
382 	    }
383 	    else if ( strstr(iconv_name,"2022")!=NULL &&
384 		    strstr(iconv_name,"KR")!=NULL &&
385 		      TryEscape( &temp,"\33$)C\16" )) {
386 		;
387 	    }
388 	    else if ( strstr(iconv_name,"2022")!=NULL &&
389 		    strstr(iconv_name,"CN")!=NULL &&
390 		      TryEscape( &temp,"\33$)A\16" )) {
391 		;
392 	    }
393 	}
394     }
395     if ( !temp.has_1byte && !temp.has_2byte )
396 return( NULL );
397     if ( !make_it )
398 return( NULL );
399 
400     enc = chunkalloc(sizeof(Encoding));
401     *enc = temp;
402     enc->enc_name = copy(name);
403     if ( iconv_name!=name )
404 	enc->iconv_name = copy(iconv_name);
405     enc->next = enclist;
406     enc->builtin = true;
407     enclist = enc;
408     if ( enc->has_2byte )
409 	enc->char_cnt = (enc->high_page<<8) + 256;
410     else {
411 	enc->char_cnt = 256;
412 	enc->only_1byte = true;
413     }
414     if ( strstrmatch(iconv_name,"JP")!=NULL ||
415 	    strstrmatch(iconv_name,"sjis")!=NULL ||
416 	    strstrmatch(iconv_name,"cp932")!=NULL )
417 	enc->is_japanese = true;
418     else if ( strstrmatch(iconv_name,"KR")!=NULL )
419 	enc->is_korean = true;
420     else if ( strstrmatch(iconv_name,"CN")!=NULL )
421 	enc->is_simplechinese = true;
422     else if ( strstrmatch(iconv_name,"BIG")!=NULL && strstrmatch(iconv_name,"5")!=NULL )
423 	enc->is_tradchinese = true;
424 
425     if ( strstrmatch(name,"ISO8859")!=NULL &&
426 	    strtol(name+strlen(name)-2,NULL,10)>=16 )
427 	/* Not in our menu, don't hide */;
428     else if ( iconv_name!=name || strmatch(name,"mac")==0 || strstrmatch(name,"ISO8859")!=NULL ||
429 	    strmatch(name,"koi8-r")==0 || strmatch(name,"sjis")==0 ||
430 	    strmatch(name,"big5")==0 || strmatch(name,"big5hkscs")==0 )
431 	enc->hidden = true;
432 
433 return( enc );
434 }
435 
FindOrMakeEncoding(const char * name)436 Encoding *FindOrMakeEncoding(const char *name) {
437 return( _FindOrMakeEncoding(name,true));
438 }
439 
440 
441 /* ************************************************************************** */
442 /* ****************************** CID Encodings ***************************** */
443 /* ************************************************************************** */
444 struct cidmap *cidmaps = NULL;
445 
CID2NameUni(struct cidmap * map,int cid,char * buffer,int len)446 int CID2NameUni(struct cidmap *map,int cid, char *buffer, int len) {
447     int enc = -1;
448     const char *temp;
449 
450 #if defined( _NO_SNPRINTF ) || defined( __VMS )
451     if ( map==NULL )
452 	sprintf(buffer,"cid-%d", cid);
453     else if ( cid<map->namemax && map->name[cid]!=NULL )
454 	strncpy(buffer,map->name[cid],len);
455     else if ( cid==0 || (cid<map->namemax && map->unicode[cid]!=0 )) {
456 	if ( map->unicode==NULL || map->namemax==0 )
457 	    enc = 0;
458 	else
459 	    enc = map->unicode[cid];
460 	temp = StdGlyphName(buffer,enc,ui_none,(NameList *) -1);
461 	if ( temp!=buffer )
462 	    strcpy(buffer,temp);
463     } else
464 	sprintf(buffer,"%s.%d", map->ordering, cid);
465 #else
466     if ( map==NULL )
467 	snprintf(buffer,len,"cid-%d", cid);
468     else if ( cid<map->namemax && map->name[cid]!=NULL )
469 	strncpy(buffer,map->name[cid],len);
470     else if ( cid==0 )
471 	strcpy(buffer,".notdef");
472     else if ( cid<map->namemax && map->unicode[cid]!=0 ) {
473 	if ( map->unicode==NULL || map->namemax==0 )
474 	    enc = 0;
475 	else
476 	    enc = map->unicode[cid];
477 	temp = StdGlyphName(buffer,enc,ui_none,(NameList *) -1);
478 	if ( temp!=buffer )
479 	    strcpy(buffer,temp);
480     } else
481 	snprintf(buffer,len,"%s.%d", map->ordering, cid);
482 #endif
483 return( enc );
484 }
485 
NameUni2CID(struct cidmap * map,int uni,const char * name)486 int NameUni2CID(struct cidmap *map,int uni, const char *name) {
487     int i;
488 
489     if ( map==NULL )
490 return( -1 );
491     if ( uni!=-1 ) {
492 	for ( i=0; i<map->namemax; ++i )
493 	  if ( map->unicode[i]==(unsigned)uni )
494 return( i );
495     } else {
496 	for ( i=0; i<map->namemax; ++i )
497 	    if ( map->name[i]!=NULL && strcmp(map->name[i],name)==0 )
498 return( i );
499     }
500 return( -1 );
501 }
502 
MaxCID(struct cidmap * map)503 int MaxCID(struct cidmap *map) {
504 return( map->cidmax );
505 }
506 
MakeDummyMap(char * registry,char * ordering,int supplement)507 static struct cidmap *MakeDummyMap(char *registry,char *ordering,int supplement) {
508     struct cidmap *ret = galloc(sizeof(struct cidmap));
509 
510     ret->registry = copy(registry);
511     ret->ordering = copy(ordering);
512     ret->supplement = ret->maxsupple = supplement;
513     ret->cidmax = ret->namemax = 0;
514     ret->unicode = NULL; ret->name = NULL;
515     ret->next = cidmaps;
516     cidmaps = ret;
517 return( ret );
518 }
519 
FindCidMap(char * registry,char * ordering,int supplement,SplineFont * sf)520 struct cidmap *FindCidMap(char *registry,char *ordering,int supplement,SplineFont *sf) {
521 return( MakeDummyMap(registry,ordering,supplement));
522 }
523 
524 /* ************************** Reencoding  routines ************************** */
525 
526 
EncMapFromEncoding(SplineFont * sf,Encoding * enc)527 EncMap *EncMapFromEncoding(SplineFont *sf,Encoding *enc) {
528     int i,j, extras, found, base, unmax;
529     int *encoded, *unencoded;
530     EncMap *map;
531     struct altuni *altuni;
532     SplineChar *sc;
533 
534     if ( enc==NULL )
535 return( NULL );
536 
537     base = enc->char_cnt;
538     if ( enc->is_original )
539 	base = 0;
540     else if ( enc->char_cnt<=256 )
541 	base = 256;
542     else if ( enc->char_cnt<=0x10000 )
543 	base = 0x10000;
544     encoded = galloc(base*sizeof(int));
545     memset(encoded,-1,base*sizeof(int));
546     unencoded = galloc(sf->glyphcnt*sizeof(int));
547     unmax = sf->glyphcnt;
548 
549     for ( i=extras=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
550 	found = false;
551 	if ( enc->psnames!=NULL ) {
552 	    for ( j=enc->char_cnt-1; j>=0; --j ) {
553 		if ( enc->psnames[j]!=NULL &&
554 			strcmp(enc->psnames[j],sc->name)==0 ) {
555 		    found = true;
556 		    encoded[j] = i;
557 		}
558 	    }
559 	}
560 	if ( !found ) {
561 	    if ( sc->unicodeenc!=-1 &&
562 		     sc->unicodeenc<unicode4_size &&
563 		     (j = EncFromUni(sc->unicodeenc,enc))!= -1 )
564 		encoded[j] = i;
565 	    else {
566 		/* I don't think extras can surpass unmax now, but it doesn't */
567 		/*  hurt to leave the code (it's from when we encoded duplicates see below) */
568 		if ( extras>=unmax ) unencoded = grealloc(unencoded,(unmax+=300)*sizeof(int));
569 		unencoded[extras++] = i;
570 	    }
571 	    for ( altuni=sc->altuni; altuni!=NULL; altuni=altuni->next ) {
572 		if ( altuni->unienc!=-1 &&
573 			 altuni->unienc<unicode4_size &&
574 			 altuni->vs==-1 &&
575 			 altuni->fid==0 &&
576 			 (j = EncFromUni(altuni->unienc,enc))!= -1 )
577 		    encoded[j] = i;
578 		/* I used to have code here to add these unencoded duplicates */
579 		/*  but I don't really see any reason to do so. The main unicode */
580 		/*  will occur, and any encoded duplicates so the glyph won't */
581 		/*  vanish */
582 	    }
583 	}
584     }
585 
586     /* Some glyphs have both a pua encoding and an encoding in a non-bmp */
587     /*  plane. Big5HK does and the AMS glyphs do */
588     if ( enc->is_unicodefull && (sf->uni_interp == ui_trad_chinese ||
589 				 sf->uni_interp == ui_ams )) {
590 	extern const int cns14pua[], amspua[];
591 	const int *pua = sf->uni_interp == ui_ams? amspua : cns14pua;
592 	for ( i=0xe000; i<0xf8ff; ++i ) {
593 	    if ( pua[i-0xe000]!=0 )
594 		encoded[pua[i-0xe000]] = encoded[i];
595 	}
596     }
597 
598     if ( enc->psnames != NULL ) {
599 	/* Names are more important than unicode code points for some encodings */
600 	/*  AdobeStandard for instance which won't work if you have a glyph  */
601 	/*  named "f_i" (must be "fi") even though the code point is correct */
602 	/* The code above would match f_i where AS requires fi, so force the */
603 	/*  names to be correct. */
604 	for ( j=0; j<enc->char_cnt; ++j ) {
605 	    if ( encoded[j]!=-1 && enc->psnames[j]!=NULL &&
606 		    strcmp(sf->glyphs[encoded[j]]->name,enc->psnames[j])!=0 ) {
607 		free(sf->glyphs[encoded[j]]->name);
608 		sf->glyphs[encoded[j]]->name = copy(enc->psnames[j]);
609 	    }
610 	}
611     }
612 
613     map = chunkalloc(sizeof(EncMap));
614     map->enccount = map->encmax = base + extras;
615     map->map = galloc(map->enccount*sizeof(int));
616     memcpy(map->map,encoded,base*sizeof(int));
617     memcpy(map->map+base,unencoded,extras*sizeof(int));
618     map->backmax = sf->glyphcnt;
619     map->backmap = galloc(sf->glyphcnt*sizeof(int));
620     memset(map->backmap,-1,sf->glyphcnt*sizeof(int));	/* Just in case there are some unencoded glyphs (duplicates perhaps) */
621     for ( i = map->enccount-1; i>=0; --i ) if ( map->map[i]!=-1 )
622 	map->backmap[map->map[i]] = i;
623     map->enc = enc;
624 
625     free(encoded);
626     free(unencoded);
627 
628 return( map );
629 }
630 
CompactEncMap(EncMap * map,SplineFont * sf)631 EncMap *CompactEncMap(EncMap *map, SplineFont *sf) {
632     int i, inuse, gid;
633     int32 *newmap;
634 
635     for ( i=inuse=0; i<map->enccount ; ++i )
636 	if ( (gid = map->map[i])!=-1 && SCWorthOutputting(sf->glyphs[gid]))
637 	    ++inuse;
638     newmap = galloc(inuse*sizeof(int32));
639     for ( i=inuse=0; i<map->enccount ; ++i )
640 	if ( (gid = map->map[i])!=-1 && SCWorthOutputting(sf->glyphs[gid]))
641 	    newmap[inuse++] = gid;
642     free(map->map);
643     map->map = newmap;
644     map->enccount = inuse;
645     map->encmax = inuse;
646     map->enc = &custom;
647     memset(map->backmap,-1,sf->glyphcnt*sizeof(int));
648     for ( i=inuse-1; i>=0; --i )
649 	if ( (gid=map->map[i])!=-1 )
650 	    map->backmap[gid] = i;
651 return( map );
652 }
653 
654 
MapAddEncodingSlot(EncMap * map,int gid)655 static int MapAddEncodingSlot(EncMap *map,int gid) {
656     int enc;
657 
658     if ( map->enccount>=map->encmax )
659 	map->map = grealloc(map->map,(map->encmax+=10)*sizeof(int));
660     enc = map->enccount++;
661     map->map[enc] = gid;
662     map->backmap[gid] = enc;
663 return( enc );
664 }
665 
FVAddEncodingSlot(FontViewBase * fv,int gid)666 void FVAddEncodingSlot(FontViewBase *fv,int gid) {
667     EncMap *map = fv->map;
668     int enc;
669 
670     enc = MapAddEncodingSlot(map,gid);
671 
672     fv->selected = grealloc(fv->selected,map->enccount);
673     fv->selected[enc] = 0;
674     FVAdjustScrollBarRows(fv,enc);
675 }
676 
MapAddEnc(SplineFont * sf,SplineChar * sc,EncMap * basemap,EncMap * map,int baseenc,int gid,FontViewBase * fv)677 static int MapAddEnc(SplineFont *sf,SplineChar *sc,EncMap *basemap, EncMap *map,int baseenc, int gid, FontViewBase *fv) {
678     int any = false, enc;
679 
680     if ( gid>=map->backmax ) {
681 	map->backmap = grealloc(map->backmap,(map->backmax+=10)*sizeof(int));
682 	memset(map->backmap+map->backmax-10,-1,10*sizeof(int));
683     }
684     if ( map->enc->psnames!=NULL ) {
685 	/* Check for multiple encodings */
686 	for ( enc = map->enc->char_cnt-1; enc>=0; --enc ) {
687 	    if ( map->enc->psnames[enc]!=NULL && strcmp(sc->name,map->enc->psnames[enc])==0 ) {
688 		if ( !any ) {
689 		    map->backmap[gid] = enc;
690 		    any = true;
691 		}
692 		map->map[enc] = gid;
693 	    }
694 	}
695     } else {
696 	enc = SFFindSlot(sf,map,sc->unicodeenc,sc->name);
697 	if ( enc!=-1 ) {
698 	    map->map[enc] = gid;
699 	    map->backmap[gid] = enc;
700 	    any = true;
701 	}
702     }
703     if ( basemap!=NULL && map->enc==basemap->enc && baseenc!=-1 ) {
704 	if ( baseenc>=map->enccount ) {
705 	    if ( map==fv->map )
706 		FVAddEncodingSlot(fv,gid);
707 	    else
708 		MapAddEncodingSlot(map,gid);
709 	} else {
710 	    map->map[baseenc] = gid;
711 	    if ( map->backmap[gid]==-1 )
712 		map->backmap[gid] = baseenc;
713 	}
714 	any = true;
715     }
716 return( any );
717 }
718 
SFAddGlyphAndEncode(SplineFont * sf,SplineChar * sc,EncMap * basemap,int baseenc)719 void SFAddGlyphAndEncode(SplineFont *sf,SplineChar *sc,EncMap *basemap, int baseenc) {
720     int gid, mapfound = false;
721     FontViewBase *fv;
722     BDFFont *bdf;
723 
724     if ( sf->cidmaster==NULL ) {
725 	if ( sf->glyphcnt+1>=sf->glyphmax )
726 	    sf->glyphs = grealloc(sf->glyphs,(sf->glyphmax+=10)*sizeof(SplineChar *));
727 	gid = sf->glyphcnt++;
728 	for ( bdf = sf->bitmaps; bdf!=NULL; bdf=bdf->next ) {
729 	    if ( sf->glyphcnt+1>=bdf->glyphmax )
730 		bdf->glyphs = grealloc(bdf->glyphs,(bdf->glyphmax=sf->glyphmax)*sizeof(BDFChar *));
731 	    if ( sf->glyphcnt>bdf->glyphcnt ) {
732 		memset(bdf->glyphs+bdf->glyphcnt,0,(sf->glyphcnt-bdf->glyphcnt)*sizeof(BDFChar *));
733 		bdf->glyphcnt = sf->glyphcnt;
734 	    }
735 	}
736 	for ( fv=sf->fv; fv!=NULL; fv = fv->nextsame ) {
737 	    EncMap *map = fv->map;
738 	    if ( gid>=map->backmax )
739 		map->backmap = grealloc(map->backmap,(map->backmax=gid+10)*sizeof(int));
740 	    map->backmap[gid] = -1;
741 	}
742     } else {
743 	gid = baseenc;
744 	if ( baseenc+1>=sf->glyphmax )
745 	    sf->glyphs = grealloc(sf->glyphs,(sf->glyphmax = baseenc+10)*sizeof(SplineChar *));
746 	if ( baseenc>=sf->glyphcnt ) {
747 	    memset(sf->glyphs+sf->glyphcnt,0,(baseenc+1-sf->glyphcnt)*sizeof(SplineChar *));
748 	    sf->glyphcnt = baseenc+1;
749 	    for ( bdf = sf->cidmaster->bitmaps; bdf!=NULL; bdf=bdf->next ) {
750 		if ( baseenc+1>=bdf->glyphmax )
751 		    bdf->glyphs = grealloc(bdf->glyphs,(bdf->glyphmax=baseenc+10)*sizeof(BDFChar *));
752 		if ( baseenc+1>bdf->glyphcnt ) {
753 		    memset(bdf->glyphs+bdf->glyphcnt,0,(baseenc+1-bdf->glyphcnt)*sizeof(BDFChar *));
754 		    bdf->glyphcnt = baseenc+1;
755 		}
756 	    }
757 	    for ( fv=sf->fv; fv!=NULL; fv = fv->nextsame ) if ( fv->sf==sf ) {
758 		EncMap *map = fv->map;
759 		if ( gid>=map->backmax )
760 		    map->backmap = grealloc(map->backmap,(map->backmax=gid+10)*sizeof(int));
761 		map->backmap[gid] = -1;
762 	    }
763 	}
764     }
765     sf->glyphs[gid] = NULL;
766     for ( fv=sf->fv; fv!=NULL; fv = fv->nextsame ) {
767 	EncMap *map = fv->map;
768 
769 	FVBiggerGlyphCache(fv,gid);
770 
771 	if ( !MapAddEnc(sf,sc,basemap,map,baseenc,gid,fv) )
772 	    FVAddEncodingSlot(fv,gid);
773 	if ( map==basemap ) mapfound = true;
774 	if ( fv->normal!=NULL ) {
775 	    if ( !MapAddEnc(sf,sc,basemap,fv->normal,baseenc,gid,fv))
776 		MapAddEncodingSlot(fv->normal,gid);
777 	}
778     }
779     if ( !mapfound && basemap!=NULL )
780 	MapAddEnc(sf,sc,basemap,basemap,baseenc,gid,fv);
781     sf->glyphs[gid] = sc;
782     sc->orig_pos = gid;
783     sc->parent = sf;
784     SFHashGlyph(sf,sc);
785 }
786 
787 
UniFromEnc(int enc,Encoding * encname)788 int32 UniFromEnc(int enc, Encoding *encname) {
789     char from[20];
790     unichar_t to[20];
791     ICONV_CONST char *fpt;
792     char *tpt;
793     size_t fromlen, tolen;
794 
795     if ( encname->is_custom || encname->is_original )
796 return( -1 );
797     if ( enc>=encname->char_cnt )
798 return( -1 );
799     if ( encname->is_unicodebmp || encname->is_unicodefull )
800 return( enc );
801     if ( encname->unicode!=NULL )
802 return( encname->unicode[enc] );
803     else if ( encname->tounicode ) {
804 	/* To my surprise, on RH9, doing a reset on conversion of CP1258->UCS2 */
805 	/* causes subsequent calls to return garbage */
806 	if ( encname->iso_2022_escape_len ) {
807 	    tolen = sizeof(to); fromlen = 0;
808 	    iconv(encname->tounicode,NULL,&fromlen,NULL,&tolen);	/* Reset state */
809 	}
810 	fpt = from; tpt = (char *) to; tolen = sizeof(to);
811 	if ( encname->has_1byte && enc<256 ) {
812 	    *(char *) fpt = enc;
813 	    fromlen = 1;
814 	} else if ( encname->has_2byte ) {
815 	    if ( encname->iso_2022_escape_len )
816 		strncpy(from,encname->iso_2022_escape,encname->iso_2022_escape_len );
817 	    fromlen = encname->iso_2022_escape_len;
818 	    from[fromlen++] = enc>>8;
819 	    from[fromlen++] = enc&0xff;
820 	}
821 	if ( iconv(encname->tounicode,&fpt,&fromlen,&tpt,&tolen)==(size_t) -1 )
822 return( -1 );
823 	if ( tpt-(char *) to == 0 ) {
824 	    /* This strange call appears to be what we need to make CP1258->UCS2 */
825 	    /*  work.  It's supposed to reset the state and give us the shift */
826 	    /*  out. As there is no state, and no shift out I have no idea why*/
827 	    /*  this works, but it does. */
828 	    if ( iconv(encname->tounicode,NULL,&fromlen,&tpt,&tolen)==(size_t) -1 )
829 return( -1 );
830 	}
831 	if ( tpt-(char *) to == sizeof(unichar_t) )
832 return( to[0] );
833 #ifdef UNICHAR_16
834 	else if ( tpt-(char *) to == 4 && to[0]>=0xd800 && to[0]<0xdc00 && to[1]>=0xdc00 )
835 return( ((to[0]-0xd800)<<10) + (to[1]-0xdc00) + 0x10000 );
836 #endif
837     } else if ( encname->tounicode_func!=NULL ) {
838 return( (encname->tounicode_func)(enc) );
839     }
840 return( -1 );
841 }
842 
EncFromUni(int32 uni,Encoding * enc)843 int32 EncFromUni(int32 uni, Encoding *enc) {
844     unichar_t from[20];
845     unsigned char to[20];
846     ICONV_CONST char *fpt;
847     char *tpt;
848     size_t fromlen, tolen;
849     int i;
850 
851     if ( enc->is_custom || enc->is_original || enc->is_compact || uni==-1 )
852 return( -1 );
853     if ( enc->is_unicodebmp || enc->is_unicodefull )
854 return( uni<enc->char_cnt ? uni : -1 );
855 
856     if ( enc->unicode!=NULL ) {
857 	for ( i=0; i<enc->char_cnt; ++i ) {
858 	    if ( enc->unicode[i]==uni )
859 return( i );
860 	}
861 return( -1 );
862     } else if ( enc->fromunicode!=NULL ) {
863 	/* I don't see how there can be any state to reset in this direction */
864 	/*  So I don't reset it */
865 #ifdef UNICHAR_16
866 	if ( uni<0x10000 ) {
867 	    from[0] = uni;
868 	    fromlen = sizeof(unichar_t);
869 	} else {
870 	    uni -= 0x10000;
871 	    from[0] = 0xd800 + (uni>>10);
872 	    from[1] = 0xdc00 + (uni&0x3ff);
873 	    fromlen = 2*sizeof(unichar_t);
874 	}
875 #else
876 	from[0] = uni;
877 	fromlen = sizeof(unichar_t);
878 #endif
879 	fpt = (char *) from; tpt = (char *) to; tolen = sizeof(to);
880 	iconv(enc->fromunicode,NULL,NULL,NULL,NULL);	/* reset shift in/out, etc. */
881 	if ( iconv(enc->fromunicode,&fpt,&fromlen,&tpt,&tolen)==(size_t) -1 )
882 return( -1 );
883 	if ( tpt-(char *) to == 1 )
884 return( to[0] );
885 	if ( enc->iso_2022_escape_len!=0 ) {
886 	    if ( tpt-(char *) to == enc->iso_2022_escape_len+2 &&
887 		    strncmp((char *) to,enc->iso_2022_escape,enc->iso_2022_escape_len)==0 )
888 return( (to[enc->iso_2022_escape_len]<<8) | to[enc->iso_2022_escape_len+1] );
889 	} else {
890 	    if ( tpt-(char *) to == sizeof(unichar_t) )
891 return( (to[0]<<8) | to[1] );
892 	}
893     } else if ( enc->fromunicode_func!=NULL ) {
894 return( (enc->fromunicode_func)(uni) );
895     }
896 return( -1 );
897 }
898 
EncFromName(const char * name,enum uni_interp interp,Encoding * encname)899 int32 EncFromName(const char *name,enum uni_interp interp,Encoding *encname) {
900     int i;
901     if ( encname->psnames!=NULL ) {
902 	for ( i=0; i<encname->char_cnt; ++i )
903 	    if ( encname->psnames[i]!=NULL && strcmp(name,encname->psnames[i])==0 )
904 return( i );
905     }
906     i = UniFromName(name,interp,encname);
907     if ( i==-1 && strlen(name)==4 ) {
908 	/* MS says use this kind of name, Adobe says use the one above */
909 	char *end;
910 	i = strtol(name,&end,16);
911 	if ( i<0 || i>0xffff || *end!='\0' )
912 return( -1 );
913     }
914 return( EncFromUni(i,encname));
915 }
916 
SFExpandGlyphCount(SplineFont * sf,int newcnt)917 void SFExpandGlyphCount(SplineFont *sf, int newcnt) {
918     int old = sf->glyphcnt;
919     FontViewBase *fv;
920 
921     if ( old>=newcnt )
922 return;
923     if ( sf->glyphmax<newcnt ) {
924 	sf->glyphs = grealloc(sf->glyphs,newcnt*sizeof(SplineChar *));
925 	sf->glyphmax = newcnt;
926     }
927     memset(sf->glyphs+sf->glyphcnt,0,(newcnt-sf->glyphcnt)*sizeof(SplineChar *));
928     sf->glyphcnt = newcnt;
929 
930     for ( fv=sf->fv; fv!=NULL; fv=fv->nextsame ) {
931 	if ( fv->sf==sf ) {	/* Beware of cid keyed fonts which might look at a different subfont */
932 	    if ( fv->normal!=NULL )
933     continue;			/* If compacted then we haven't added any glyphs so haven't changed anything */
934 	    /* Don't display any of these guys, so not mapped. */
935 	    /*  No change to selection, or to map->map, but change to backmap */
936 	    if ( newcnt>fv->map->backmax )
937 		fv->map->backmap = grealloc(fv->map->backmap,(fv->map->backmax = newcnt+5)*sizeof(int32));
938 	    memset(fv->map->backmap+old,-1,(newcnt-old)*sizeof(int32));
939 	}
940     }
941 }
942