mkfontscale.c revision 40cc5db4
1ea6ae205Smrg/*
2ea6ae205Smrg  Copyright (c) 2002-2003 by Juliusz Chroboczek
3ea6ae205Smrg
4ea6ae205Smrg  Permission is hereby granted, free of charge, to any person obtaining a copy
5ea6ae205Smrg  of this software and associated documentation files (the "Software"), to deal
6ea6ae205Smrg  in the Software without restriction, including without limitation the rights
7ea6ae205Smrg  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8ea6ae205Smrg  copies of the Software, and to permit persons to whom the Software is
9ea6ae205Smrg  furnished to do so, subject to the following conditions:
10ea6ae205Smrg
11ea6ae205Smrg  The above copyright notice and this permission notice shall be included in
12ea6ae205Smrg  all copies or substantial portions of the Software.
13ea6ae205Smrg
14ea6ae205Smrg  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15ea6ae205Smrg  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16ea6ae205Smrg  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17ea6ae205Smrg  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18ea6ae205Smrg  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19ea6ae205Smrg  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20ea6ae205Smrg  THE SOFTWARE.
21ea6ae205Smrg*/
22ea6ae205Smrg
2340cc5db4Smrg#ifdef HAVE_CONFIG_H
242d6e8b77Smrg#include "config.h"
2540cc5db4Smrg#endif
262d6e8b77Smrg
27ea6ae205Smrg#include <stdio.h>
28ea6ae205Smrg#include <stdlib.h>
29ea6ae205Smrg#include <string.h>
30ea6ae205Smrg
31ea6ae205Smrg#include <sys/types.h>
322d6e8b77Smrg#include <sys/stat.h>
33ea6ae205Smrg#include <dirent.h>
34ea6ae205Smrg#include <unistd.h>
35ea6ae205Smrg#include <errno.h>
36ea6ae205Smrg#include <ctype.h>
37ea6ae205Smrg
38ea6ae205Smrg#include <X11/Xos.h>
39ea6ae205Smrg#include <X11/fonts/fontenc.h>
40ea6ae205Smrg#include <ft2build.h>
41ea6ae205Smrg#include FT_FREETYPE_H
42ea6ae205Smrg#include FT_SFNT_NAMES_H
43ea6ae205Smrg#include FT_TRUETYPE_TABLES_H
44ea6ae205Smrg#include FT_TRUETYPE_IDS_H
45ea6ae205Smrg#include FT_TYPE1_TABLES_H
46ea6ae205Smrg#include FT_BDF_H
47ea6ae205Smrg#include FT_XFREE86_H
48ea6ae205Smrg
49ea6ae205Smrg#include "list.h"
50ea6ae205Smrg#include "hash.h"
51ea6ae205Smrg#include "data.h"
52ea6ae205Smrg#include "ident.h"
53ea6ae205Smrg
54ea6ae205Smrg#define NPREFIX 1024
55ea6ae205Smrg
56ea6ae205Smrg#ifndef MAXFONTFILENAMELEN
57ea6ae205Smrg#define MAXFONTFILENAMELEN 1024
58ea6ae205Smrg#endif
59ea6ae205Smrg#ifndef MAXFONTNAMELEN
60ea6ae205Smrg#define MAXFONTNAMELEN 1024
61ea6ae205Smrg#endif
62ea6ae205Smrg
63245f6787Smrg/* Two levels of macro calls are needed so that we stringify the value
64245f6787Smrg   of MAXFONT... and not the string "MAXFONT..." */
65245f6787Smrg#define QUOTE(x)	#x
66245f6787Smrg#define STRINGIFY(x)	QUOTE(x)
67245f6787Smrg
6814734546Smrgstatic char *encodings_array[] =
69ea6ae205Smrg    { "ascii-0",
70ea6ae205Smrg      "iso8859-1", "iso8859-2", "iso8859-3", "iso8859-4", "iso8859-5",
71ea6ae205Smrg      "iso8859-6", "iso8859-6.8", "iso8859-6.8x", "iso8859-6.16",
72ea6ae205Smrg      "iso8859-7", "iso8859-8", "iso8859-9", "iso8859-10",
73ea6ae205Smrg      "iso8859-11", "iso8859-12", "iso8859-13", "iso8859-14",
74ea6ae205Smrg      "iso8859-15", "iso8859-16",
75ea6ae205Smrg      "ansi-1251", "koi8-r", "koi8-u", "koi8-ru", "koi8-e", "koi8-uni",
76ea6ae205Smrg      "tis620-2",
77ea6ae205Smrg      "sun.unicode.india-0", "suneu-greek",
78ea6ae205Smrg      "adobe-standard", "adobe-symbol",
79ea6ae205Smrg      "ibm-cp437", "ibm-cp850", "ibm-cp852", "ibm-cp866", "microsoft-cp1252",
80ea6ae205Smrg      /* But not "adobe-dingbats", as it uses generic glyph names. */
81ea6ae205Smrg      "cns11643-1", "cns11643-2", "cns11643-3",
82ea6ae205Smrg      "jisx0201.1976-0", "jisx0208.1983-0", "jisx0208.1990-0",
83ea6ae205Smrg      "jisx0212.1990-0", "big5-0", "big5.eten-0", "big5hkscs-0",
84ea6ae205Smrg      "gb2312.1980-0", "gb18030.2000-0", "gb18030.2000-1",
85ea6ae205Smrg      "ksc5601.1987-0", "ksc5601.1992-3"};
86ea6ae205Smrg
8714734546Smrgstatic char *extra_encodings_array[] =
88ea6ae205Smrg    { "iso10646-1", "adobe-fontspecific", "microsoft-symbol" };
89ea6ae205Smrg
90e83ac88aSmrgstatic ListPtr encodings, extra_encodings;
91663cdc11Smrgstatic const char *outfilename;
92ea6ae205Smrg
93ea6ae205Smrg#define countof(_a) (sizeof(_a)/sizeof((_a)[0]))
94ea6ae205Smrg
95663cdc11Smrgstatic int doDirectory(const char*, int, ListPtr);
96ea6ae205Smrgstatic int checkEncoding(FT_Face face, char *encoding_name);
97ea6ae205Smrgstatic int checkExtraEncoding(FT_Face face, char *encoding_name, int found);
98ea6ae205Smrgstatic int find_cmap(int type, int pid, int eid, FT_Face face);
99663cdc11Smrgstatic const char* notice_foundry(const char *notice);
100663cdc11Smrgstatic const char* vendor_foundry(const signed char *vendor);
101ea6ae205Smrgstatic int readFontScale(HashTablePtr entries, char *dirname);
102ea6ae205SmrgListPtr makeXLFD(char *filename, FT_Face face, int);
103ea6ae205Smrgstatic int readEncodings(ListPtr encodings, char *dirname);
104ea6ae205Smrg
105ea6ae205Smrgstatic FT_Library ft_library;
106ea6ae205Smrgstatic float bigEncodingFuzz = 0.02;
107ea6ae205Smrg
108ea6ae205Smrgstatic int relative;
109ea6ae205Smrgstatic int doScalable;
110ea6ae205Smrgstatic int doBitmaps;
111ea6ae205Smrgstatic int doISO10646_1_encoding;
112ea6ae205Smrgstatic int onlyEncodings;
113ea6ae205Smrgstatic ListPtr encodingsToDo;
114ea6ae205Smrgstatic int reencodeLegacy;
115ea6ae205Smrgstatic char *encodingPrefix;
116ea6ae205Smrgstatic char *exclusionSuffix;
117ea6ae205Smrg
118ea6ae205Smrgstatic void
119ea6ae205Smrgusage(void)
120ea6ae205Smrg{
121663cdc11Smrg    fprintf(stderr,
122ea6ae205Smrg            "mkfontscale [ -b ] [ -s ] [ -o filename ] [-x suffix ]\n"
123ea6ae205Smrg            "            [ -a encoding ] [ -f fuzz ] [ -l ] "
124ea6ae205Smrg            "            [ -e directory ] [ -p prefix ] [ -n ] [ -r ] \n"
125ea6ae205Smrg            "            [-u] [-U] [ directory ]...\n");
126ea6ae205Smrg}
127ea6ae205Smrg
128ea6ae205Smrgint
129ea6ae205Smrgmain(int argc, char **argv)
130ea6ae205Smrg{
131ea6ae205Smrg    int argn;
132ea6ae205Smrg    FT_Error ftrc;
133ea6ae205Smrg    int rc, ll = 0;
134ea6ae205Smrg    char prefix[NPREFIX];
135ea6ae205Smrg
136ea6ae205Smrg    encodingPrefix = NULL;
137ea6ae205Smrg    exclusionSuffix = NULL;
138ea6ae205Smrg
139ea6ae205Smrg    if(getcwd(prefix, NPREFIX - 1) == NULL) {
140ea6ae205Smrg        perror("Couldn't get cwd");
141ea6ae205Smrg        exit(1);
142ea6ae205Smrg    }
143ea6ae205Smrg    if(prefix[strlen(prefix) - 1] != '/')
144ea6ae205Smrg        strcat(prefix, "/");
145ea6ae205Smrg    encodingPrefix = dsprintf("%s", prefix);
146ea6ae205Smrg
147ea6ae205Smrg    outfilename = NULL;
148ea6ae205Smrg
149ea6ae205Smrg    encodings = makeList(encodings_array, countof(encodings_array), NULL, 0);
150ea6ae205Smrg
151663cdc11Smrg    extra_encodings = makeList(extra_encodings_array,
152ea6ae205Smrg                               countof(extra_encodings_array),
153ea6ae205Smrg                               NULL, 0);
154ea6ae205Smrg    doBitmaps = 0;
155ea6ae205Smrg    doISO10646_1_encoding = 1;
156ea6ae205Smrg    doScalable = 1;
157ea6ae205Smrg    onlyEncodings = 0;
158ea6ae205Smrg    relative = 0;
159ea6ae205Smrg    reencodeLegacy = 1;
160ea6ae205Smrg    encodingsToDo = NULL;
161ea6ae205Smrg
162ea6ae205Smrg    argn = 1;
163ea6ae205Smrg    while(argn < argc) {
164ea6ae205Smrg        if(argv[argn][0] == '\0' || argv[argn][0] != '-')
165ea6ae205Smrg            break;
166ea6ae205Smrg        if(argv[argn][1] == '-') {
167ea6ae205Smrg            argn++;
168ea6ae205Smrg            break;
169ea6ae205Smrg        } else if (strcmp(argv[argn], "-x") == 0) {
170ea6ae205Smrg            if(argn >= argc - 1) {
171ea6ae205Smrg                usage();
172ea6ae205Smrg                exit(1);
173ea6ae205Smrg            }
174ea6ae205Smrg            exclusionSuffix = argv[argn + 1];
175ea6ae205Smrg            argn += 2;
176ea6ae205Smrg        } else if(strcmp(argv[argn], "-a") == 0) {
177ea6ae205Smrg            if(argn >= argc - 1) {
178ea6ae205Smrg                usage();
179ea6ae205Smrg                exit(1);
180ea6ae205Smrg            }
181ea6ae205Smrg            makeList(&argv[argn + 1], 1, encodings, 0);
182ea6ae205Smrg            argn += 2;
183ea6ae205Smrg        } else if(strcmp(argv[argn], "-p") == 0) {
184ea6ae205Smrg            if(argn >= argc - 1) {
185ea6ae205Smrg                usage();
186ea6ae205Smrg                exit(1);
187ea6ae205Smrg            }
188ea6ae205Smrg            if(strlen(argv[argn + 1]) > NPREFIX - 1) {
189ea6ae205Smrg                usage();
190ea6ae205Smrg                exit(1);
191ea6ae205Smrg            }
192ea6ae205Smrg            free(encodingPrefix);
193ea6ae205Smrg            encodingPrefix = dsprintf("%s", argv[argn + 1]);
194ea6ae205Smrg            argn += 2;
195ea6ae205Smrg        } else if(strcmp(argv[argn], "-e") == 0) {
196ea6ae205Smrg            if(argn >= argc - 1) {
197ea6ae205Smrg                usage();
198ea6ae205Smrg                exit(1);
199ea6ae205Smrg            }
200ea6ae205Smrg            rc = readEncodings(encodingsToDo, argv[argn + 1]);
201ea6ae205Smrg            if(rc < 0)
202ea6ae205Smrg                exit(1);
203ea6ae205Smrg            argn += 2;
204ea6ae205Smrg        } else if(strcmp(argv[argn], "-b") == 0) {
205ea6ae205Smrg            doBitmaps = 1;
206ea6ae205Smrg            argn++;
207ea6ae205Smrg        } else if(strcmp(argv[argn], "-u") == 0) {
208ea6ae205Smrg            doISO10646_1_encoding = 0;
209ea6ae205Smrg            argn++;
210ea6ae205Smrg        } else if(strcmp(argv[argn], "-U") == 0) {
211ea6ae205Smrg            doISO10646_1_encoding = 1;
212663cdc11Smrg            argn++;
213ea6ae205Smrg        } else if(strcmp(argv[argn], "-s") == 0) {
214ea6ae205Smrg            doScalable = 0;
215ea6ae205Smrg            argn++;
216ea6ae205Smrg        } else if(strcmp(argv[argn], "-n") == 0) {
217ea6ae205Smrg            onlyEncodings = 1;
218ea6ae205Smrg            argn++;
219ea6ae205Smrg        } else if(strcmp(argv[argn], "-r") == 0) {
220ea6ae205Smrg            relative = 1;
221ea6ae205Smrg            argn++;
222ea6ae205Smrg        } else if(strcmp(argv[argn], "-l") == 0) {
223ea6ae205Smrg            reencodeLegacy = !reencodeLegacy;
224ea6ae205Smrg            argn++;
225ea6ae205Smrg        } else if(strcmp(argv[argn], "-o") == 0) {
226ea6ae205Smrg            if(argn >= argc - 1) {
227ea6ae205Smrg                usage();
228ea6ae205Smrg                exit(1);
229ea6ae205Smrg            }
230ea6ae205Smrg            outfilename = argv[argn + 1];
231ea6ae205Smrg            argn += 2;
232ea6ae205Smrg        } else if(strcmp(argv[argn], "-f") == 0) {
233ea6ae205Smrg            if(argn >= argc - 1) {
234ea6ae205Smrg                usage();
235ea6ae205Smrg                exit(1);
236ea6ae205Smrg            }
237ea6ae205Smrg            bigEncodingFuzz = atof(argv[argn + 1]) / 100.0;
238ea6ae205Smrg            argn += 2;
239ea6ae205Smrg        } else if (strcmp(argv[argn], "-r") == 0) { /* ignore for now */
240ea6ae205Smrg	    argn++;
241ea6ae205Smrg	} else if (strcmp(argv[argn], "-n") == 0) {
242ea6ae205Smrg	    argn++;
243ea6ae205Smrg	} else {
244ea6ae205Smrg            usage();
245ea6ae205Smrg            exit(1);
246ea6ae205Smrg        }
247ea6ae205Smrg    }
248ea6ae205Smrg
249ea6ae205Smrg    if(outfilename == NULL) {
250ea6ae205Smrg        if(doBitmaps)
251ea6ae205Smrg            outfilename = "fonts.dir";
252663cdc11Smrg        else
253ea6ae205Smrg            outfilename = "fonts.scale";
254ea6ae205Smrg    }
255ea6ae205Smrg
256ea6ae205Smrg    ftrc = FT_Init_FreeType(&ft_library);
257ea6ae205Smrg    if(ftrc) {
258ea6ae205Smrg        fprintf(stderr, "Could not initialise FreeType library: %d\n", ftrc);
259ea6ae205Smrg        exit(1);
260ea6ae205Smrg    }
261ea6ae205Smrg
262ea6ae205Smrg    ll = listLength(encodingsToDo);
263ea6ae205Smrg
264ea6ae205Smrg    if (argn == argc)
265ea6ae205Smrg        doDirectory(".", ll, encodingsToDo);
266ea6ae205Smrg    else
267ea6ae205Smrg        while(argn < argc) {
268ea6ae205Smrg            doDirectory(argv[argn], ll, encodingsToDo);
269ea6ae205Smrg            argn++;
270ea6ae205Smrg        }
271ea6ae205Smrg    return 0;
272ea6ae205Smrg}
273ea6ae205Smrg
274ea6ae205Smrgstatic int
275ea6ae205SmrggetNameHelper(FT_Face face, int nid, int pid, int eid,
276ea6ae205Smrg              FT_SfntName *name_return)
277ea6ae205Smrg{
278ea6ae205Smrg    FT_SfntName name;
279ea6ae205Smrg    int n, i;
280ea6ae205Smrg
281ea6ae205Smrg    n = FT_Get_Sfnt_Name_Count(face);
282ea6ae205Smrg    if(n <= 0)
283ea6ae205Smrg        return 0;
284ea6ae205Smrg
285ea6ae205Smrg    for(i = 0; i < n; i++) {
286ea6ae205Smrg        if(FT_Get_Sfnt_Name(face, i, &name))
287ea6ae205Smrg            continue;
288ea6ae205Smrg        if(name.name_id == nid &&
289ea6ae205Smrg           name.platform_id == pid &&
290ea6ae205Smrg           (eid < 0 || name.encoding_id == eid)) {
291ea6ae205Smrg            switch(name.platform_id) {
292ea6ae205Smrg            case TT_PLATFORM_APPLE_UNICODE:
293ea6ae205Smrg            case TT_PLATFORM_MACINTOSH:
294ea6ae205Smrg                if(name.language_id != TT_MAC_LANGID_ENGLISH)
295ea6ae205Smrg                    continue;
296ea6ae205Smrg                break;
297ea6ae205Smrg            case TT_PLATFORM_MICROSOFT:
298ea6ae205Smrg                if(name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES &&
299ea6ae205Smrg                   name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM)
300ea6ae205Smrg                    continue;
301ea6ae205Smrg                break;
302ea6ae205Smrg            default:
303ea6ae205Smrg                continue;
304ea6ae205Smrg            }
305ea6ae205Smrg            if(name.string_len > 0) {
306ea6ae205Smrg                *name_return = name;
307ea6ae205Smrg                return 1;
308ea6ae205Smrg            }
309ea6ae205Smrg        }
310ea6ae205Smrg    }
311ea6ae205Smrg    return 0;
312ea6ae205Smrg}
313ea6ae205Smrg
314ea6ae205Smrgstatic char *
315ea6ae205SmrggetName(FT_Face face, int nid)
316ea6ae205Smrg{
317ea6ae205Smrg    FT_SfntName name;
318ea6ae205Smrg    char *string;
319ea6ae205Smrg    int i;
320ea6ae205Smrg
321663cdc11Smrg    if(getNameHelper(face, nid,
322ea6ae205Smrg                     TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, &name) ||
323663cdc11Smrg       getNameHelper(face, nid,
324ea6ae205Smrg                     TT_PLATFORM_APPLE_UNICODE, -1, &name)) {
325ea6ae205Smrg        string = malloc(name.string_len / 2 + 1);
326ea6ae205Smrg        if(string == NULL) {
327ea6ae205Smrg            fprintf(stderr, "Couldn't allocate name\n");
328ea6ae205Smrg            exit(1);
329ea6ae205Smrg        }
330ea6ae205Smrg        for(i = 0; i < name.string_len / 2; i++) {
331ea6ae205Smrg            if(name.string[2 * i] != 0)
332ea6ae205Smrg                string[i] = '?';
333ea6ae205Smrg            else
334ea6ae205Smrg                string[i] = name.string[2 * i + 1];
335ea6ae205Smrg        }
336ea6ae205Smrg        string[i] = '\0';
337ea6ae205Smrg        return string;
338ea6ae205Smrg    }
339ea6ae205Smrg
340ea6ae205Smrg    /* Pretend that Apple Roman is ISO 8859-1. */
341ea6ae205Smrg    if(getNameHelper(face, nid, TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN,
342ea6ae205Smrg                     &name)) {
343ea6ae205Smrg        string = malloc(name.string_len + 1);
344ea6ae205Smrg        if(string == NULL) {
345ea6ae205Smrg            fprintf(stderr, "Couldn't allocate name\n");
346ea6ae205Smrg            exit(1);
347ea6ae205Smrg        }
348ea6ae205Smrg        memcpy(string, name.string, name.string_len);
349ea6ae205Smrg        string[name.string_len] = '\0';
350ea6ae205Smrg        return string;
351ea6ae205Smrg    }
352ea6ae205Smrg
353ea6ae205Smrg    return NULL;
354ea6ae205Smrg}
355ea6ae205Smrg
356663cdc11Smrgstatic const char*
357ea6ae205Smrgos2Weight(int weight)
358ea6ae205Smrg{
359ea6ae205Smrg    if(weight < 150)
360ea6ae205Smrg        return "thin";
361ea6ae205Smrg    else if(weight < 250)
362ea6ae205Smrg        return "extralight";
363ea6ae205Smrg    else if(weight < 350)
364ea6ae205Smrg        return "light";
365ea6ae205Smrg    else if(weight < 450)
366ea6ae205Smrg        return "medium";        /* officially "normal" */
367ea6ae205Smrg    else if(weight < 550)
368ea6ae205Smrg        return "medium";
369ea6ae205Smrg    else if(weight < 650)
370ea6ae205Smrg        return "semibold";
371ea6ae205Smrg    else if(weight < 750)
372ea6ae205Smrg        return "bold";
373ea6ae205Smrg    else if(weight < 850)
374ea6ae205Smrg        return "extrabold";
375663cdc11Smrg    else
376ea6ae205Smrg        return "black";
377ea6ae205Smrg}
378ea6ae205Smrg
379663cdc11Smrgstatic const char*
380ea6ae205Smrgos2Width(int width)
381ea6ae205Smrg{
382ea6ae205Smrg    if(width <= 1)
383ea6ae205Smrg        return "ultracondensed";
384ea6ae205Smrg    else if(width <= 2)
385ea6ae205Smrg        return "extracondensed";
386ea6ae205Smrg    else if(width <= 3)
387ea6ae205Smrg        return "condensed";
388ea6ae205Smrg    else if(width <= 4)
389ea6ae205Smrg        return "semicondensed";
390ea6ae205Smrg    else if(width <= 5)
391ea6ae205Smrg        return "normal";
392ea6ae205Smrg    else if(width <= 6)
393ea6ae205Smrg        return "semiexpanded";
394ea6ae205Smrg    else if(width <= 7)
395ea6ae205Smrg        return "expanded";
396ea6ae205Smrg    else if(width <= 8)
397ea6ae205Smrg        return "extraexpanded";
398ea6ae205Smrg    else
399ea6ae205Smrg        return "ultraexpanded";
400ea6ae205Smrg}
401ea6ae205Smrg
402663cdc11Smrgstatic const char *widths[] = {
403ea6ae205Smrg    "ultracondensed", "extracondensed", "condensed", "semicondensed",
404663cdc11Smrg    "normal", "semiexpanded", "expanded", "extraexpanded", "ultraexpanded"
405ea6ae205Smrg};
406ea6ae205Smrg
407ea6ae205Smrg#define NUMWIDTHS (sizeof(widths) / sizeof(widths[0]))
408ea6ae205Smrg
409663cdc11Smrgstatic const char*
410663cdc11SmrgnameWidth(const char *name)
411ea6ae205Smrg{
412ea6ae205Smrg    char buf[500];
413ea6ae205Smrg    int i;
414ea6ae205Smrg    int n = strlen(name);
415ea6ae205Smrg
416ea6ae205Smrg    if(n >= 499) return NULL;
417ea6ae205Smrg    for(i = 0; i < n; i++)
418ea6ae205Smrg        buf[i] = tolower(name[i]);
419ea6ae205Smrg    buf[i] = '\0';
420ea6ae205Smrg
421ea6ae205Smrg    for(i = 0; i < NUMWIDTHS; i++)
422ea6ae205Smrg        if(strstr(buf, widths[i]))
423ea6ae205Smrg            return widths[i];
424ea6ae205Smrg    return NULL;
425ea6ae205Smrg}
426ea6ae205Smrg
427663cdc11Smrgstatic const char*
428663cdc11Smrgt1Weight(const char *weight)
429ea6ae205Smrg{
430ea6ae205Smrg    if(!weight)
431ea6ae205Smrg        return NULL;
432ea6ae205Smrg    if(strcmp(weight, "Thin") == 0)
433ea6ae205Smrg        return "thin";
434663cdc11Smrg    if(strcmp(weight, "ExtraLight") == 0) /* FontForge uses this for 200*/
435663cdc11Smrg        return "extralight";
436ea6ae205Smrg    if(strcmp(weight, "Light") == 0)
437ea6ae205Smrg        return "light";
438ea6ae205Smrg    if(strcmp(weight, "Regular") == 0)
439ea6ae205Smrg        return "medium";
440ea6ae205Smrg    if(strcmp(weight, "Normal") == 0)
441ea6ae205Smrg        return "medium";
442ea6ae205Smrg    if(strcmp(weight, "Medium") == 0)
443ea6ae205Smrg        return "medium";
444ea6ae205Smrg    if(strcmp(weight, "Book") == 0)
445ea6ae205Smrg        return "medium";
446ea6ae205Smrg    if(strcmp(weight, "Roman") == 0) /* Some URW++ fonts do that! */
447ea6ae205Smrg        return "medium";
448ea6ae205Smrg    if(strcmp(weight, "Demi") == 0)
449ea6ae205Smrg        return "semibold";
450ea6ae205Smrg    if(strcmp(weight, "DemiBold") == 0)
451ea6ae205Smrg        return "semibold";
452ea6ae205Smrg    if(strcmp(weight, "SemiBold") == 0) /* some TeX fonts apparently do that */
453ea6ae205Smrg        return "semibold";
454ea6ae205Smrg    else if(strcmp(weight, "Bold") == 0)
455ea6ae205Smrg        return "bold";
456663cdc11Smrg    else if(strcmp(weight, "Heavy") == 0) /* FontForge uses this for 800*/
457663cdc11Smrg        return "extrabold";
458ea6ae205Smrg    else if(strcmp(weight, "Black") == 0)
459ea6ae205Smrg        return "black";
460ea6ae205Smrg    else {
461ea6ae205Smrg        fprintf(stderr, "Unknown Type 1 weight \"%s\"\n", weight);
462ea6ae205Smrg        return NULL;
463ea6ae205Smrg    }
464ea6ae205Smrg}
465ea6ae205Smrg
466ea6ae205Smrgstatic int
467ea6ae205Smrgunsafe(char c)
468ea6ae205Smrg{
469663cdc11Smrg    return
470ea6ae205Smrg        c < 0x20 || c > 0x7E ||
471ea6ae205Smrg        c == '[' || c == ']' || c == '(' || c == ')' || c == '\\' || c == '-';
472ea6ae205Smrg}
473ea6ae205Smrg
474663cdc11Smrgstatic const char *
475663cdc11Smrgsafe(const char* s)
476ea6ae205Smrg{
477ea6ae205Smrg    int i, len, safe_flag = 1;
478ea6ae205Smrg    char *t;
479ea6ae205Smrg
480ea6ae205Smrg    i = 0;
481ea6ae205Smrg    while(s[i] != '\0') {
482ea6ae205Smrg        if(unsafe(s[i]))
483ea6ae205Smrg            safe_flag = 0;
484ea6ae205Smrg        i++;
485ea6ae205Smrg    }
486ea6ae205Smrg
487ea6ae205Smrg    if(safe_flag) return s;
488ea6ae205Smrg
489ea6ae205Smrg    len = i;
490ea6ae205Smrg    t = malloc(len + 1);
491ea6ae205Smrg    if(t == NULL) {
492ea6ae205Smrg        perror("Couldn't allocate string");
493ea6ae205Smrg        exit(1);
494ea6ae205Smrg    }
495ea6ae205Smrg
496ea6ae205Smrg    for(i = 0; i < len; i++) {
497ea6ae205Smrg        if(unsafe(s[i]))
498ea6ae205Smrg            t[i] = ' ';
499ea6ae205Smrg        else
500ea6ae205Smrg            t[i] = s[i];
501ea6ae205Smrg    }
502ea6ae205Smrg    t[i] = '\0';
503ea6ae205Smrg    return t;
504ea6ae205Smrg}
505ea6ae205Smrg
506ea6ae205SmrgListPtr
507ea6ae205SmrgmakeXLFD(char *filename, FT_Face face, int isBitmap)
508ea6ae205Smrg{
509ea6ae205Smrg    ListPtr xlfd = NULL;
510663cdc11Smrg    const char *foundry, *family, *weight, *slant, *sWidth, *adstyle,
511ea6ae205Smrg        *spacing, *full_name;
512ea6ae205Smrg    TT_Header *head;
513ea6ae205Smrg    TT_HoriHeader *hhea;
514ea6ae205Smrg    TT_OS2 *os2;
515ea6ae205Smrg    TT_Postscript *post;
516ea6ae205Smrg    PS_FontInfoRec *t1info, t1info_rec;
517ea6ae205Smrg    int rc;
518ea6ae205Smrg
519ea6ae205Smrg    foundry = NULL;
520ea6ae205Smrg    family = NULL;
521ea6ae205Smrg    weight = NULL;
522ea6ae205Smrg    slant = NULL;
523ea6ae205Smrg    sWidth = NULL;
524ea6ae205Smrg    adstyle = NULL;
525ea6ae205Smrg    spacing = NULL;
526ea6ae205Smrg    full_name = NULL;
527ea6ae205Smrg
528ea6ae205Smrg    head = FT_Get_Sfnt_Table(face, ft_sfnt_head);
529ea6ae205Smrg    hhea = FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
530ea6ae205Smrg    os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
531ea6ae205Smrg    post = FT_Get_Sfnt_Table(face, ft_sfnt_post);
532ea6ae205Smrg
533ea6ae205Smrg    rc = FT_Get_PS_Font_Info(face, &t1info_rec);
534ea6ae205Smrg    if(rc == 0)
535ea6ae205Smrg        t1info = &t1info_rec;
536ea6ae205Smrg    else
537ea6ae205Smrg        t1info = NULL;
538663cdc11Smrg
539ea6ae205Smrg    if(!family)
540ea6ae205Smrg        family = getName(face, TT_NAME_ID_FONT_FAMILY);
541ea6ae205Smrg    if(!family)
542ea6ae205Smrg        family = getName(face, TT_NAME_ID_FULL_NAME);
543ea6ae205Smrg    if(!family)
544ea6ae205Smrg        family = getName(face, TT_NAME_ID_PS_NAME);
545ea6ae205Smrg
546ea6ae205Smrg    if(!full_name)
547ea6ae205Smrg        full_name = getName(face, TT_NAME_ID_FULL_NAME);
548ea6ae205Smrg    if(!full_name)
549ea6ae205Smrg        full_name = getName(face, TT_NAME_ID_PS_NAME);
550ea6ae205Smrg
551ea6ae205Smrg    if(os2 && os2->version != 0xFFFF) {
552ea6ae205Smrg        if(!weight)
553ea6ae205Smrg            weight = os2Weight(os2->usWeightClass);
554ea6ae205Smrg        if(!sWidth)
555ea6ae205Smrg            sWidth = os2Width(os2->usWidthClass);
556ea6ae205Smrg        if(!foundry)
557ea6ae205Smrg            foundry = vendor_foundry(os2->achVendID);
558ea6ae205Smrg        if(!slant)
559ea6ae205Smrg            slant = os2->fsSelection & 1 ? "i" : "r";
560ea6ae205Smrg    }
561ea6ae205Smrg
562ea6ae205Smrg    if(post) {
563ea6ae205Smrg        if(!spacing) {
564ea6ae205Smrg            if(post->isFixedPitch) {
565ea6ae205Smrg                if(hhea->min_Left_Side_Bearing >= 0 &&
566ea6ae205Smrg                   hhea->xMax_Extent <= hhea->advance_Width_Max) {
567ea6ae205Smrg                    spacing = "c";
568ea6ae205Smrg                } else {
569ea6ae205Smrg                    spacing = "m";
570ea6ae205Smrg                }
571ea6ae205Smrg            } else {
572ea6ae205Smrg                spacing = "p";
573ea6ae205Smrg            }
574ea6ae205Smrg        }
575ea6ae205Smrg    }
576663cdc11Smrg
577ea6ae205Smrg    if(t1info) {
578ea6ae205Smrg        if(!family)
579ea6ae205Smrg            family = t1info->family_name;
580ea6ae205Smrg        if(!family)
581ea6ae205Smrg            family = t1info->full_name;
582ea6ae205Smrg        if(!full_name)
583ea6ae205Smrg            full_name = t1info->full_name;
584ea6ae205Smrg        if(!foundry)
585ea6ae205Smrg            foundry = notice_foundry(t1info->notice);
586ea6ae205Smrg        if(!weight)
587ea6ae205Smrg            weight = t1Weight(t1info->weight);
588ea6ae205Smrg        if(!spacing)
589ea6ae205Smrg            spacing = t1info->is_fixed_pitch ? "m" : "p";
590ea6ae205Smrg        if(!slant) {
591ea6ae205Smrg            /* Bitstream fonts have positive italic angle. */
592ea6ae205Smrg            slant =
593ea6ae205Smrg                t1info->italic_angle <= -4 || t1info->italic_angle >= 4 ?
594ea6ae205Smrg                "i" : "r";
595ea6ae205Smrg        }
596ea6ae205Smrg    }
597ea6ae205Smrg
598ea6ae205Smrg    if(!full_name) {
599ea6ae205Smrg        fprintf(stderr, "Couldn't determine full name for %s\n", filename);
600ea6ae205Smrg        full_name = filename;
601ea6ae205Smrg    }
602ea6ae205Smrg
603ea6ae205Smrg    if(head) {
604ea6ae205Smrg        if(!slant)
605ea6ae205Smrg            slant = head->Mac_Style & 2 ? "i" : "r";
606ea6ae205Smrg        if(!weight)
607ea6ae205Smrg            weight = head->Mac_Style & 1 ? "bold" : "medium";
608ea6ae205Smrg    }
609ea6ae205Smrg
610ea6ae205Smrg    if(!slant) {
611ea6ae205Smrg        fprintf(stderr, "Couldn't determine slant for %s\n", filename);
612ea6ae205Smrg        slant = "r";
613ea6ae205Smrg    }
614ea6ae205Smrg
615ea6ae205Smrg    if(!weight) {
616ea6ae205Smrg        fprintf(stderr, "Couldn't determine weight for %s\n", filename);
617ea6ae205Smrg        weight = "medium";
618ea6ae205Smrg    }
619ea6ae205Smrg
620ea6ae205Smrg    if(!foundry) {
621ea6ae205Smrg        char *notice;
622ea6ae205Smrg        notice = getName(face, TT_NAME_ID_TRADEMARK);
623ea6ae205Smrg        if(notice) {
624ea6ae205Smrg            foundry = notice_foundry(notice);
625ea6ae205Smrg        }
626ea6ae205Smrg        if(!foundry) {
627ea6ae205Smrg            notice = getName(face, TT_NAME_ID_MANUFACTURER);
628ea6ae205Smrg            if(notice) {
629ea6ae205Smrg                foundry = notice_foundry(notice);
630ea6ae205Smrg            }
631ea6ae205Smrg        }
632ea6ae205Smrg    }
633ea6ae205Smrg
634ea6ae205Smrg    if(strcmp(slant, "i") == 0) {
635ea6ae205Smrg        if(strstr(full_name, "Oblique"))
636ea6ae205Smrg            slant = "o";
637ea6ae205Smrg        if(strstr(full_name, "Slanted"))
638ea6ae205Smrg            slant = "o";
639ea6ae205Smrg    }
640ea6ae205Smrg
641ea6ae205Smrg    if(!sWidth)
642ea6ae205Smrg        sWidth = nameWidth(full_name);
643ea6ae205Smrg
644ea6ae205Smrg    if(!foundry) foundry = "misc";
645ea6ae205Smrg    if(!family) {
646ea6ae205Smrg        fprintf(stderr, "Couldn't get family name for %s\n", filename);
647ea6ae205Smrg        family = filename;
648ea6ae205Smrg    }
649ea6ae205Smrg
650ea6ae205Smrg    if(!weight) weight = "medium";
651ea6ae205Smrg    if(!slant) slant = "r";
652ea6ae205Smrg    if(!sWidth) sWidth = "normal";
653ea6ae205Smrg    if(!adstyle) adstyle = "";
654ea6ae205Smrg    if(!spacing) spacing = "p";
655ea6ae205Smrg
656ea6ae205Smrg    /* Yes, it's a memory leak. */
657ea6ae205Smrg    foundry = safe(foundry);
658ea6ae205Smrg    family = safe(family);
659ea6ae205Smrg
660ea6ae205Smrg    if(!isBitmap) {
661ea6ae205Smrg        xlfd = listConsF(xlfd,
662ea6ae205Smrg                         "-%s-%s-%s-%s-%s-%s-0-0-0-0-%s-0",
663ea6ae205Smrg                         foundry, family,
664ea6ae205Smrg                         weight, slant, sWidth, adstyle, spacing);
665ea6ae205Smrg    } else {
666ea6ae205Smrg        int i, w, h, xres, yres;
667ea6ae205Smrg        for(i = 0; i < face->num_fixed_sizes; i++) {
668ea6ae205Smrg            w = face->available_sizes[i].width;
669ea6ae205Smrg            h = face->available_sizes[i].height;
670ea6ae205Smrg            xres = 75;
671ea6ae205Smrg            yres = (double)h / w * xres;
672ea6ae205Smrg            xlfd = listConsF(xlfd,
673ea6ae205Smrg                             "-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d",
674ea6ae205Smrg                             foundry, family,
675ea6ae205Smrg                             weight, slant, sWidth, adstyle,
676ea6ae205Smrg                             h, (int)(h / (double)yres * 72.27 * 10 + 0.5),
677ea6ae205Smrg                             xres, yres,
678ea6ae205Smrg                             spacing, 60);
679ea6ae205Smrg        }
680ea6ae205Smrg    }
681ea6ae205Smrg    return xlfd;
682ea6ae205Smrg}
683ea6ae205Smrg
684ea6ae205Smrgstatic int
685ea6ae205SmrgreadFontScale(HashTablePtr entries, char *dirname)
686ea6ae205Smrg{
687ea6ae205Smrg    int n = strlen(dirname);
688ea6ae205Smrg    char *filename;
689ea6ae205Smrg    FILE *in;
690ea6ae205Smrg    int rc, count, i;
691245f6787Smrg    char file[MAXFONTFILENAMELEN+1], font[MAXFONTNAMELEN+1];
692ea6ae205Smrg
693ea6ae205Smrg    if(dirname[n - 1] == '/')
694ea6ae205Smrg        filename = dsprintf("%sfonts.scale", dirname);
695ea6ae205Smrg    else
696ea6ae205Smrg        filename = dsprintf("%s/fonts.scale", dirname);
697ea6ae205Smrg    if(filename == NULL)
698ea6ae205Smrg        return -1;
699ea6ae205Smrg
700ea6ae205Smrg    in = fopen(filename, "r");
701ea6ae205Smrg    free(filename);
702ea6ae205Smrg    if(in == NULL) {
703ea6ae205Smrg        if(errno != ENOENT)
704ea6ae205Smrg            perror("open(fonts.scale)");
705ea6ae205Smrg        return -1;
706ea6ae205Smrg    }
707ea6ae205Smrg
708ea6ae205Smrg    rc = fscanf(in, "%d\n", &count);
709ea6ae205Smrg    if(rc != 1) {
710ea6ae205Smrg        fprintf(stderr, "Invalid fonts.scale in %s.\n", dirname);
711ea6ae205Smrg        fclose(in);
712ea6ae205Smrg        return -1;
713ea6ae205Smrg    }
714ea6ae205Smrg
715ea6ae205Smrg    for(i = 0; i < count; i++) {
716245f6787Smrg        rc = fscanf(in,
717245f6787Smrg		    "%" STRINGIFY(MAXFONTFILENAMELEN) "s "
718245f6787Smrg		    "%" STRINGIFY(MAXFONTNAMELEN) "[^\n]\n",
719245f6787Smrg		    file, font);
720ea6ae205Smrg        if(rc != 2)
721ea6ae205Smrg            break;
722ea6ae205Smrg        putHash(entries, font, file, 100);
723ea6ae205Smrg    }
724ea6ae205Smrg    fclose(in);
725ea6ae205Smrg    return 1;
726ea6ae205Smrg}
727ea6ae205Smrg
728ea6ae205Smrgstatic int
729ea6ae205SmrgfilePrio(char *filename)
730ea6ae205Smrg{
731ea6ae205Smrg    int n = strlen(filename);
732ea6ae205Smrg    if(n < 4)
733ea6ae205Smrg        return 0;
734ea6ae205Smrg    if(strcmp(filename + n - 4, ".otf") == 0)
735ea6ae205Smrg        return 6;
736ea6ae205Smrg    if(strcmp(filename + n - 4, ".OTF") == 0)
737ea6ae205Smrg        return 6;
738ea6ae205Smrg    if(strcmp(filename + n - 4, ".ttf") == 0)
739ea6ae205Smrg        return 5;
740ea6ae205Smrg    if(strcmp(filename + n - 4, ".TTF") == 0)
741ea6ae205Smrg        return 5;
742ea6ae205Smrg    if(strcmp(filename + n - 4, ".pcf") == 0)
743ea6ae205Smrg        return 4;
744ea6ae205Smrg    if(strcmp(filename + n - 4, ".PCF") == 0)
745ea6ae205Smrg        return 4;
746ea6ae205Smrg    if(strcmp(filename + n - 3, ".gz") == 0)
747ea6ae205Smrg        return 3;
7487978d3cdSmrg#ifdef X_BZIP2_FONT_COMPRESSION
7497978d3cdSmrg    if(strcmp(filename + n - 4, ".bz2") == 0)
7507978d3cdSmrg        return 2;
7517978d3cdSmrg#endif
752ea6ae205Smrg    if(strcmp(filename + n - 2, ".Z") == 0)
753ea6ae205Smrg        return 2;
754ea6ae205Smrg    if(strcmp(filename + n - 4, ".bdf") == 0)
755ea6ae205Smrg        return 1;
756ea6ae205Smrg    if(strcmp(filename + n - 4, ".BDF") == 0)
757ea6ae205Smrg        return 1;
758ea6ae205Smrg    return 0;
759ea6ae205Smrg}
760ea6ae205Smrg
761ea6ae205Smrgstatic int
762663cdc11SmrgdoDirectory(const char *dirname_given, int numEncodings, ListPtr encodingsToDo)
763ea6ae205Smrg{
764ea6ae205Smrg    char *dirname, *fontscale_name, *filename, *encdir;
765ea6ae205Smrg    FILE *fontscale, *encfile;
766ea6ae205Smrg    DIR *dirp;
767ea6ae205Smrg    struct dirent *entry;
768ea6ae205Smrg    FT_Error ftrc;
769ea6ae205Smrg    FT_Face face;
770ea6ae205Smrg    ListPtr encoding, xlfd, lp;
771ea6ae205Smrg    HashTablePtr entries;
772ea6ae205Smrg    HashBucketPtr *array;
773ea6ae205Smrg    int i, n, found, rc;
774ea6ae205Smrg    int isBitmap=0,xl=0;
775ea6ae205Smrg
776ea6ae205Smrg    if (exclusionSuffix)
777ea6ae205Smrg        xl = strlen (exclusionSuffix);
778ea6ae205Smrg
779ea6ae205Smrg    i = strlen(dirname_given);
780ea6ae205Smrg    if(i == 0)
781ea6ae205Smrg        dirname = dsprintf("./");
782ea6ae205Smrg    else if(dirname_given[i - 1] != '/')
783ea6ae205Smrg        dirname = dsprintf("%s/", dirname_given);
784ea6ae205Smrg    else
785ea6ae205Smrg        dirname = dsprintf("%s", dirname_given);
786ea6ae205Smrg
787ea6ae205Smrg    if(dirname == NULL) {
788ea6ae205Smrg        perror("dirname");
789ea6ae205Smrg        exit(1);
790ea6ae205Smrg    }
791ea6ae205Smrg
792663cdc11Smrg    if (onlyEncodings)
793ea6ae205Smrg	goto encodings;
794663cdc11Smrg
795ea6ae205Smrg    entries = makeHashTable();
796ea6ae205Smrg    if(doBitmaps && !doScalable) {
797ea6ae205Smrg        readFontScale(entries, dirname);
798ea6ae205Smrg    }
799ea6ae205Smrg
800ea6ae205Smrg    if(strcmp(outfilename, "-") == 0)
801ea6ae205Smrg        fontscale_name = NULL;
802ea6ae205Smrg    else {
803ea6ae205Smrg        if(outfilename[0] == '/')
804ea6ae205Smrg            fontscale_name = dsprintf("%s", outfilename);
805ea6ae205Smrg        else
806ea6ae205Smrg            fontscale_name = dsprintf("%s%s", dirname, outfilename);
807ea6ae205Smrg        if(fontscale_name == NULL) {
808ea6ae205Smrg            perror("fontscale_name");
809ea6ae205Smrg            exit(1);
810ea6ae205Smrg        }
811ea6ae205Smrg    }
812ea6ae205Smrg
813ea6ae205Smrg    dirp = opendir(dirname);
814ea6ae205Smrg    if(dirp == NULL) {
815ea6ae205Smrg        fprintf(stderr, "%s: ", dirname);
816ea6ae205Smrg        perror("opendir");
817ea6ae205Smrg        return 0;
818ea6ae205Smrg    }
819ea6ae205Smrg
820ea6ae205Smrg    if(fontscale_name == NULL)
821ea6ae205Smrg        fontscale = stdout;
822ea6ae205Smrg    else
823ea6ae205Smrg        fontscale = fopen(fontscale_name, "wb");
824ea6ae205Smrg
825ea6ae205Smrg    if(fontscale == NULL) {
826ea6ae205Smrg        fprintf(stderr, "%s: ", fontscale_name);
827ea6ae205Smrg        perror("fopen(w)");
828ea6ae205Smrg        return 0;
829ea6ae205Smrg    }
830ea6ae205Smrg
831ea6ae205Smrg    while((entry = readdir(dirp)) != NULL) {
832ea6ae205Smrg        int have_face = 0;
833ea6ae205Smrg        char *xlfd_name = NULL;
8342d6e8b77Smrg	struct stat f_stat;
8352d6e8b77Smrg	int tprio = 1;
8362d6e8b77Smrg
837ea6ae205Smrg        xlfd = NULL;
838ea6ae205Smrg
839ea6ae205Smrg	if (xl) {
840ea6ae205Smrg	    int dl = strlen (entry->d_name);
841ea6ae205Smrg	    if (strcmp (entry->d_name + dl - xl, exclusionSuffix) == 0)
842ea6ae205Smrg		continue;
843ea6ae205Smrg	}
844ea6ae205Smrg
845ea6ae205Smrg        filename = dsprintf("%s%s", dirname, entry->d_name);
846ea6ae205Smrg
8472d6e8b77Smrg#define PRIO(x) ((x << 1) + tprio)
8482d6e8b77Smrg#ifdef DT_LNK
8492d6e8b77Smrg	if (entry->d_type != DT_UNKNOWN) {
8502d6e8b77Smrg	    if (entry->d_type == DT_LNK)
8512d6e8b77Smrg		tprio = 0;
8522d6e8b77Smrg	} else
8532d6e8b77Smrg#endif
8542d6e8b77Smrg#ifdef S_ISLNK
8552d6e8b77Smrg	{
8562d6e8b77Smrg	    if (lstat(filename, &f_stat))
8572d6e8b77Smrg		goto done;
8582d6e8b77Smrg	    if (S_ISLNK(f_stat.st_mode))
8592d6e8b77Smrg		tprio = 0;
8602d6e8b77Smrg	}
8612d6e8b77Smrg#else
8622d6e8b77Smrg	;
8632d6e8b77Smrg#endif
864ea6ae205Smrg        if(doBitmaps)
865ea6ae205Smrg            rc = bitmapIdentify(filename, &xlfd_name);
866ea6ae205Smrg        else
867ea6ae205Smrg            rc = 0;
868ea6ae205Smrg
869ea6ae205Smrg        if(rc < 0)
870ea6ae205Smrg            goto done;
871ea6ae205Smrg
872ea6ae205Smrg        if(rc == 0) {
873ea6ae205Smrg            ftrc = FT_New_Face(ft_library, filename, 0, &face);
874ea6ae205Smrg            if(ftrc)
875ea6ae205Smrg                goto done;
876ea6ae205Smrg            have_face = 1;
877ea6ae205Smrg
878ea6ae205Smrg            isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
879ea6ae205Smrg
880ea6ae205Smrg            if(!isBitmap) {
881ea6ae205Smrg                /* Workaround for bitmap-only SFNT fonts */
882ea6ae205Smrg                if(FT_IS_SFNT(face) && face->num_fixed_sizes > 0 &&
883ea6ae205Smrg                   strcmp(FT_Get_X11_Font_Format(face), "TrueType") == 0) {
884ea6ae205Smrg                    TT_MaxProfile *maxp;
885ea6ae205Smrg                    maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
886ea6ae205Smrg                    if(maxp != NULL && maxp->maxContours == 0)
887ea6ae205Smrg                        isBitmap = 1;
888ea6ae205Smrg                }
889ea6ae205Smrg            }
890663cdc11Smrg
891ea6ae205Smrg            if(isBitmap) {
892ea6ae205Smrg                if(!doBitmaps)
893ea6ae205Smrg                    goto done;
894ea6ae205Smrg            } else {
895ea6ae205Smrg                if(!doScalable)
896ea6ae205Smrg                    goto done;
897ea6ae205Smrg            }
898ea6ae205Smrg
899ea6ae205Smrg            if(isBitmap) {
900ea6ae205Smrg                BDF_PropertyRec prop;
901ea6ae205Smrg                rc = FT_Get_BDF_Property(face, "FONT", &prop);
902ea6ae205Smrg                if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) {
9032d6e8b77Smrg                    xlfd_name = strdup(prop.u.atom);
904ea6ae205Smrg                    if(xlfd_name == NULL)
905ea6ae205Smrg                        goto done;
906ea6ae205Smrg                }
907ea6ae205Smrg            }
908ea6ae205Smrg        }
909ea6ae205Smrg
910ea6ae205Smrg        if(xlfd_name) {
911ea6ae205Smrg            /* We know it's a bitmap font, and we know its XLFD */
912ea6ae205Smrg            int n = strlen(xlfd_name);
913ea6ae205Smrg            if(reencodeLegacy &&
914ea6ae205Smrg               n >= 12 && strcasecmp(xlfd_name + n - 11, "-iso10646-1") == 0) {
915ea6ae205Smrg                char *s;
916ea6ae205Smrg
917ea6ae205Smrg                s = malloc(n - 10);
918ea6ae205Smrg                memcpy(s, xlfd_name, n - 11);
919ea6ae205Smrg                s[n - 11] = '\0';
920ea6ae205Smrg                xlfd = listCons(s, xlfd);
921ea6ae205Smrg            } else {
922ea6ae205Smrg                /* Not a reencodable font -- skip all the rest of the loop body */
9232d6e8b77Smrg                putHash(entries, xlfd_name, entry->d_name, PRIO(filePrio(entry->d_name)));
924ea6ae205Smrg                goto done;
925ea6ae205Smrg            }
926ea6ae205Smrg        }
927ea6ae205Smrg
928ea6ae205Smrg        if(!have_face) {
929ea6ae205Smrg            ftrc = FT_New_Face(ft_library, filename, 0, &face);
930ea6ae205Smrg            if(ftrc)
931ea6ae205Smrg                goto done;
932ea6ae205Smrg            have_face = 1;
933ea6ae205Smrg            isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
934ea6ae205Smrg
935ea6ae205Smrg            if(!isBitmap) {
936ea6ae205Smrg                if(face->num_fixed_sizes > 0) {
937ea6ae205Smrg                    TT_MaxProfile *maxp;
938ea6ae205Smrg                    maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
939ea6ae205Smrg                    if(maxp != NULL && maxp->maxContours == 0)
940ea6ae205Smrg                        isBitmap = 1;
941ea6ae205Smrg                }
942ea6ae205Smrg            }
943ea6ae205Smrg        }
944ea6ae205Smrg
945ea6ae205Smrg        if(xlfd == NULL)
946ea6ae205Smrg            xlfd = makeXLFD(entry->d_name, face, isBitmap);
947ea6ae205Smrg
948ea6ae205Smrg        found = 0;
949ea6ae205Smrg
950ea6ae205Smrg        for(lp = xlfd; lp; lp = lp->next) {
951ea6ae205Smrg            char buf[MAXFONTNAMELEN];
952ea6ae205Smrg            for(encoding = encodings; encoding; encoding = encoding->next) {
953ea6ae205Smrg                if(checkEncoding(face, encoding->value)) {
954ea6ae205Smrg                    found = 1;
955ea6ae205Smrg                    snprintf(buf, MAXFONTNAMELEN, "%s-%s",
956ea6ae205Smrg                            lp->value, encoding->value);
9572d6e8b77Smrg                    putHash(entries, buf, entry->d_name, PRIO(filePrio(entry->d_name)));
958ea6ae205Smrg                }
959ea6ae205Smrg            }
960663cdc11Smrg            for(encoding = extra_encodings; encoding;
961ea6ae205Smrg                encoding = encoding->next) {
962ea6ae205Smrg                if(checkExtraEncoding(face, encoding->value, found)) {
963ea6ae205Smrg                    /* Do not set found! */
964ea6ae205Smrg                    snprintf(buf, MAXFONTNAMELEN, "%s-%s",
965ea6ae205Smrg                            lp->value, encoding->value);
9662d6e8b77Smrg                    putHash(entries, buf, entry->d_name, PRIO(filePrio(entry->d_name)));
967ea6ae205Smrg                }
968ea6ae205Smrg            }
969ea6ae205Smrg        }
970ea6ae205Smrg    done:
971245f6787Smrg        if(have_face)
972ea6ae205Smrg            FT_Done_Face(face);
973ea6ae205Smrg        deepDestroyList(xlfd);
974ea6ae205Smrg        xlfd = NULL;
975ea6ae205Smrg        free(filename);
9762d6e8b77Smrg#undef PRIO
977ea6ae205Smrg    }
978ea6ae205Smrg
979ea6ae205Smrg    closedir(dirp);
980ea6ae205Smrg    n = hashElements(entries);
981ea6ae205Smrg    fprintf(fontscale, "%d\n", n);
982ea6ae205Smrg    array = hashArray(entries, 1);
983ea6ae205Smrg    for(i = 0; i < n; i++)
984ea6ae205Smrg        fprintf(fontscale, "%s %s\n", array[i]->value, array[i]->key);
985ea6ae205Smrg    destroyHashArray(array);
986ea6ae205Smrg    entries = NULL;
987ea6ae205Smrg    if(fontscale_name) {
988ea6ae205Smrg        fclose(fontscale);
989ea6ae205Smrg        free(fontscale_name);
990ea6ae205Smrg    }
991ea6ae205Smrg
992ea6ae205Smrg encodings:
993ea6ae205Smrg    encdir = dsprintf("%s%s", dirname, "encodings.dir");
994ea6ae205Smrg
995ea6ae205Smrg    if(encdir == NULL) {
996ea6ae205Smrg	perror("encodings");
997ea6ae205Smrg	exit(1);
998ea6ae205Smrg    }
999ea6ae205Smrg    unlink(encdir);
1000ea6ae205Smrg
1001ea6ae205Smrg    if (numEncodings) {
1002ea6ae205Smrg	encfile = fopen(encdir, "w");
1003ea6ae205Smrg	if(encfile == NULL) {
1004ea6ae205Smrg	    perror("open(encodings.dir)");
1005ea6ae205Smrg	    exit(1);
1006ea6ae205Smrg	}
1007ea6ae205Smrg        fprintf(encfile, "%d\n", numEncodings);
1008245f6787Smrg        encodingsToDo = sortList(encodingsToDo);
1009ea6ae205Smrg        for(lp = encodingsToDo; lp; lp = lp->next) {
1010ea6ae205Smrg            fprintf(encfile, "%s\n", lp->value);
1011ea6ae205Smrg        }
1012ea6ae205Smrg	fclose (encfile);
1013ea6ae205Smrg    }
1014ea6ae205Smrg
1015ea6ae205Smrg    free(dirname);
1016ea6ae205Smrg    return 1;
1017ea6ae205Smrg}
1018ea6ae205Smrg
1019ea6ae205Smrg#define CODE_IGNORED(c) ((c) < 0x20 || \
1020ea6ae205Smrg                         ((c) >= 0x7F && (c) <= 0xA0) || \
1021ea6ae205Smrg                         (c) == 0xAD || (c) == 0xF71B)
1022663cdc11Smrg
1023ea6ae205Smrgstatic int
1024ea6ae205SmrgcheckEncoding(FT_Face face, char *encoding_name)
1025ea6ae205Smrg{
1026ea6ae205Smrg    FontEncPtr encoding;
1027ea6ae205Smrg    FontMapPtr mapping;
1028ea6ae205Smrg    int i, j, c, koi8;
1029ea6ae205Smrg    char *n;
1030ea6ae205Smrg
1031ea6ae205Smrg    encoding = FontEncFind(encoding_name, NULL);
1032ea6ae205Smrg    if(!encoding)
1033ea6ae205Smrg        return 0;
1034ea6ae205Smrg
1035ea6ae205Smrg    /* An encoding is ``small'' if one of the following is true:
1036ea6ae205Smrg         - it is linear and has no more than 256 codepoints; or
1037ea6ae205Smrg         - it is a matrix encoding and has no more than one column.
1038663cdc11Smrg
1039ea6ae205Smrg       For small encodings using Unicode indices, we require perfect
1040ea6ae205Smrg       coverage except for CODE_IGNORED and KOI-8 IBM-PC compatibility.
1041ea6ae205Smrg
1042ea6ae205Smrg       For large encodings, we require coverage up to bigEncodingFuzz.
1043ea6ae205Smrg
1044ea6ae205Smrg       For encodings using PS names (currently Adobe Standard and
1045ea6ae205Smrg       Adobe Symbol only), we require perfect coverage. */
1046ea6ae205Smrg
1047ea6ae205Smrg
1048ea6ae205Smrg    if(FT_Has_PS_Glyph_Names(face)) {
1049ea6ae205Smrg        for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
1050ea6ae205Smrg            if(mapping->type == FONT_ENCODING_POSTSCRIPT) {
1051ea6ae205Smrg                if(encoding->row_size > 0) {
1052ea6ae205Smrg                    for(i = encoding->first; i < encoding->size; i++) {
1053663cdc11Smrg                        for(j = encoding->first_col;
1054663cdc11Smrg                            j < encoding->row_size;
1055ea6ae205Smrg                            j++) {
1056ea6ae205Smrg                            n = FontEncName((i<<8) | j, mapping);
1057ea6ae205Smrg                            if(n && FT_Get_Name_Index(face, n) == 0) {
1058ea6ae205Smrg                                return 0;
1059ea6ae205Smrg                            }
1060ea6ae205Smrg                        }
1061ea6ae205Smrg                    }
1062ea6ae205Smrg                    return 1;
1063ea6ae205Smrg                } else {
1064ea6ae205Smrg                    for(i = encoding->first; i < encoding->size; i++) {
1065ea6ae205Smrg                        n = FontEncName(i, mapping);
1066ea6ae205Smrg                        if(n && FT_Get_Name_Index(face, n) == 0) {
1067ea6ae205Smrg                            return 0;
1068ea6ae205Smrg                        }
1069ea6ae205Smrg                    }
1070ea6ae205Smrg                    return 1;
1071ea6ae205Smrg                }
1072ea6ae205Smrg            }
1073ea6ae205Smrg        }
1074ea6ae205Smrg    }
1075ea6ae205Smrg
1076ea6ae205Smrg    for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
1077ea6ae205Smrg        if(find_cmap(mapping->type, mapping->pid, mapping->eid, face)) {
1078ea6ae205Smrg            int total = 0, failed = 0;
1079ea6ae205Smrg            if(encoding->row_size > 0) {
1080663cdc11Smrg                int estimate =
1081ea6ae205Smrg                    (encoding->size - encoding->first) *
1082ea6ae205Smrg                    (encoding->row_size - encoding->first_col);
1083ea6ae205Smrg                for(i = encoding->first; i < encoding->size; i++) {
1084663cdc11Smrg                    for(j = encoding->first_col;
1085663cdc11Smrg                        j < encoding->row_size;
1086ea6ae205Smrg                        j++) {
1087ea6ae205Smrg                        c = FontEncRecode((i<<8) | j, mapping);
1088ea6ae205Smrg                        if(CODE_IGNORED(c)) {
1089ea6ae205Smrg                            continue;
1090ea6ae205Smrg                        } else {
1091ea6ae205Smrg                            if(FT_Get_Char_Index(face, c) == 0) {
1092ea6ae205Smrg                                failed++;
1093ea6ae205Smrg                            }
1094ea6ae205Smrg                            total++;
1095ea6ae205Smrg                            if((encoding->size <= 1 && failed > 0) ||
1096ea6ae205Smrg                               ((float)failed >= bigEncodingFuzz * estimate)) {
1097ea6ae205Smrg                                return 0;
1098ea6ae205Smrg                            }
1099ea6ae205Smrg                        }
1100ea6ae205Smrg                    }
1101ea6ae205Smrg                }
1102ea6ae205Smrg                if((float)failed >= total * bigEncodingFuzz)
1103ea6ae205Smrg                    return 0;
1104ea6ae205Smrg                else
1105ea6ae205Smrg                    return 1;
1106ea6ae205Smrg            } else {
1107ea6ae205Smrg                int estimate = encoding->size - encoding->first;
1108ea6ae205Smrg                /* For the KOI8 encodings, we ignore the lack of
1109ea6ae205Smrg                   linedrawing and pseudo-math characters */
1110ea6ae205Smrg                if(strncmp(encoding->name, "koi8-", 5) == 0)
1111ea6ae205Smrg                    koi8 = 1;
1112ea6ae205Smrg                else
1113ea6ae205Smrg                    koi8 = 0;
1114ea6ae205Smrg                for(i = encoding->first; i < encoding->size; i++) {
1115ea6ae205Smrg                    c = FontEncRecode(i, mapping);
1116ea6ae205Smrg                    if(CODE_IGNORED(c) ||
1117ea6ae205Smrg                       (koi8 && ((c >= 0x2200 && c < 0x2600) || c == 0x00b2))) {
1118ea6ae205Smrg                        continue;
1119ea6ae205Smrg                    } else {
1120ea6ae205Smrg                        if(FT_Get_Char_Index(face, c) == 0) {
1121ea6ae205Smrg                            failed++;
1122ea6ae205Smrg                        }
1123ea6ae205Smrg                        total++;
1124ea6ae205Smrg                        if((encoding->size <= 256 && failed > 0) ||
1125ea6ae205Smrg                           ((float)failed >= bigEncodingFuzz * estimate)) {
1126ea6ae205Smrg                            return 0;
1127ea6ae205Smrg                        }
1128ea6ae205Smrg                    }
1129ea6ae205Smrg                }
1130ea6ae205Smrg                if((float)failed >= total * bigEncodingFuzz)
1131ea6ae205Smrg                    return 0;
1132ea6ae205Smrg                else
1133ea6ae205Smrg                    return 1;
1134ea6ae205Smrg            }
1135ea6ae205Smrg        }
1136ea6ae205Smrg    }
1137ea6ae205Smrg    return 0;
1138ea6ae205Smrg}
1139ea6ae205Smrg
1140663cdc11Smrgstatic int
1141ea6ae205Smrgfind_cmap(int type, int pid, int eid, FT_Face face)
1142ea6ae205Smrg{
1143ea6ae205Smrg    int i, n, rc;
1144ea6ae205Smrg    FT_CharMap cmap = NULL;
1145ea6ae205Smrg
1146ea6ae205Smrg    n = face->num_charmaps;
1147ea6ae205Smrg
1148ea6ae205Smrg    switch(type) {
1149ea6ae205Smrg    case FONT_ENCODING_TRUETYPE:  /* specific cmap */
1150ea6ae205Smrg        for(i=0; i<n; i++) {
1151ea6ae205Smrg            cmap = face->charmaps[i];
1152ea6ae205Smrg            if(cmap->platform_id == pid && cmap->encoding_id == eid) {
1153ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1154ea6ae205Smrg                if(rc == 0)
1155ea6ae205Smrg                    return 1;
1156ea6ae205Smrg            }
1157ea6ae205Smrg        }
1158ea6ae205Smrg        break;
1159ea6ae205Smrg    case FONT_ENCODING_UNICODE:   /* any Unicode cmap */
1160ea6ae205Smrg        /* prefer Microsoft Unicode */
1161ea6ae205Smrg        for(i=0; i<n; i++) {
1162ea6ae205Smrg            cmap = face->charmaps[i];
1163663cdc11Smrg            if(cmap->platform_id == TT_PLATFORM_MICROSOFT &&
1164ea6ae205Smrg               cmap->encoding_id == TT_MS_ID_UNICODE_CS) {
1165ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1166ea6ae205Smrg                if(rc == 0)
1167ea6ae205Smrg                    return 1;
1168ea6ae205Smrg            }
1169ea6ae205Smrg        }
1170ea6ae205Smrg        /* Try Apple Unicode */
1171ea6ae205Smrg        for(i=0; i<n; i++) {
1172ea6ae205Smrg            cmap = face->charmaps[i];
1173ea6ae205Smrg            if(cmap->platform_id == TT_PLATFORM_APPLE_UNICODE) {
1174ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1175ea6ae205Smrg                if(rc == 0)
1176ea6ae205Smrg                    return 1;
1177ea6ae205Smrg            }
1178ea6ae205Smrg        }
1179ea6ae205Smrg        /* ISO Unicode? */
1180ea6ae205Smrg        for(i=0; i<n; i++) {
1181ea6ae205Smrg            cmap = face->charmaps[i];
1182ea6ae205Smrg            if(cmap->platform_id == TT_PLATFORM_ISO) {
1183ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1184ea6ae205Smrg                if(rc == 0)
1185ea6ae205Smrg                    return 1;
1186ea6ae205Smrg            }
1187ea6ae205Smrg        }
1188ea6ae205Smrg        break;
1189ea6ae205Smrg    default:
1190ea6ae205Smrg        return 0;
1191ea6ae205Smrg    }
1192ea6ae205Smrg    return 0;
1193ea6ae205Smrg}
1194ea6ae205Smrg
1195ea6ae205Smrgstatic int
1196ea6ae205SmrgcheckExtraEncoding(FT_Face face, char *encoding_name, int found)
1197ea6ae205Smrg{
1198ea6ae205Smrg    int c;
1199ea6ae205Smrg
1200ea6ae205Smrg    if(strcasecmp(encoding_name, "iso10646-1") == 0) {
1201ea6ae205Smrg        if(doISO10646_1_encoding && find_cmap(FONT_ENCODING_UNICODE, -1, -1, face)) {
1202ea6ae205Smrg            int found = 0;
1203ea6ae205Smrg             /* Export as Unicode if there are at least 15 BMP
1204ea6ae205Smrg               characters that are not a space or ignored. */
1205ea6ae205Smrg            for(c = 0x21; c < 0x10000; c++) {
1206ea6ae205Smrg                if(CODE_IGNORED(c))
1207ea6ae205Smrg                    continue;
1208ea6ae205Smrg                if(FT_Get_Char_Index(face, c) > 0)
1209ea6ae205Smrg                    found++;
1210ea6ae205Smrg                if(found >= 15)
1211ea6ae205Smrg                    return 1;
1212ea6ae205Smrg            }
1213ea6ae205Smrg            return 0;
1214ea6ae205Smrg        } else
1215ea6ae205Smrg            return 0;
1216ea6ae205Smrg    } else if(strcasecmp(encoding_name, "microsoft-symbol") == 0) {
1217ea6ae205Smrg        if(find_cmap(FONT_ENCODING_TRUETYPE,
1218ea6ae205Smrg                     TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS,
1219ea6ae205Smrg                     face))
1220ea6ae205Smrg            return 1;
1221ea6ae205Smrg        else
1222ea6ae205Smrg            return 0;
1223ea6ae205Smrg    } else if(strcasecmp(encoding_name, "adobe-fontspecific") == 0) {
1224ea6ae205Smrg        if(!found) {
1225ea6ae205Smrg            if(FT_Has_PS_Glyph_Names(face))
1226ea6ae205Smrg                return 1;
1227ea6ae205Smrg            else
1228ea6ae205Smrg                return 0;
1229ea6ae205Smrg        } else
1230ea6ae205Smrg            return 0;
1231ea6ae205Smrg    } else {
1232ea6ae205Smrg        fprintf(stderr, "Unknown extra encoding %s\n", encoding_name);
1233ea6ae205Smrg        return 0;
1234ea6ae205Smrg    }
1235ea6ae205Smrg}
1236ea6ae205Smrg
1237663cdc11Smrgstatic const char*
1238663cdc11Smrgnotice_foundry(const char *notice)
1239ea6ae205Smrg{
1240ea6ae205Smrg    int i;
1241ea6ae205Smrg    for(i = 0; i < countof(notice_foundries); i++)
1242ea6ae205Smrg        if(notice && strstr(notice, notice_foundries[i][0]))
1243ea6ae205Smrg            return notice_foundries[i][1];
1244ea6ae205Smrg    return NULL;
1245ea6ae205Smrg}
1246ea6ae205Smrg
1247ea6ae205Smrgstatic int
1248663cdc11Smrgvendor_match(const signed char *vendor, const char *vendor_string)
1249ea6ae205Smrg{
1250ea6ae205Smrg    /* vendor is not necessarily NUL-terminated. */
1251ea6ae205Smrg    int i, len;
1252ea6ae205Smrg    len = strlen(vendor_string);
1253ea6ae205Smrg    if(memcmp(vendor, vendor_string, len) != 0)
1254ea6ae205Smrg        return 0;
1255ea6ae205Smrg    for(i = len; i < 4; i++)
1256ea6ae205Smrg        if(vendor[i] != ' ' && vendor[i] != '\0')
1257ea6ae205Smrg            return 0;
1258ea6ae205Smrg    return 1;
1259ea6ae205Smrg}
1260ea6ae205Smrg
1261663cdc11Smrgstatic const char*
1262663cdc11Smrgvendor_foundry(const signed char *vendor)
1263ea6ae205Smrg{
1264ea6ae205Smrg    int i;
1265ea6ae205Smrg    for(i = 0; i < countof(vendor_foundries); i++)
1266ea6ae205Smrg        if(vendor_match(vendor, vendor_foundries[i][0]))
1267ea6ae205Smrg            return vendor_foundries[i][1];
1268ea6ae205Smrg    return NULL;
1269ea6ae205Smrg}
1270ea6ae205Smrg
1271ea6ae205Smrgstatic int
1272ea6ae205SmrgreadEncodings(ListPtr encodings, char *dirname)
1273ea6ae205Smrg{
1274ea6ae205Smrg    char *fullname;
1275ea6ae205Smrg    DIR *dirp;
1276ea6ae205Smrg    struct dirent *file;
1277ea6ae205Smrg    char **names, **name;
1278ea6ae205Smrg
1279ea6ae205Smrg    if(strlen(dirname) > 1 && dirname[strlen(dirname) - 1] == '/')
1280ea6ae205Smrg        dirname[strlen(dirname) - 1] = '\0';
1281ea6ae205Smrg
1282ea6ae205Smrg    dirp = opendir(dirname);
1283ea6ae205Smrg    if(dirp == NULL) {
1284ea6ae205Smrg        perror("opendir");
1285ea6ae205Smrg        return -1;
1286ea6ae205Smrg    }
1287ea6ae205Smrg
1288ea6ae205Smrg    while((file = readdir(dirp)) != NULL) {
1289ea6ae205Smrg        fullname = dsprintf("%s/%s", dirname, file->d_name);
1290ea6ae205Smrg        if(fullname == NULL) {
1291ea6ae205Smrg            fprintf(stderr, "Couldn't allocate fullname\n");
1292ea6ae205Smrg            closedir(dirp);
1293ea6ae205Smrg            return -1;
1294ea6ae205Smrg        }
1295663cdc11Smrg
1296ea6ae205Smrg        names = FontEncIdentify(fullname);
1297ea6ae205Smrg        if(!names)
1298ea6ae205Smrg            continue;
1299ea6ae205Smrg
1300ea6ae205Smrg        for(name = names; *name; name++) {
1301ea6ae205Smrg            if(fullname[0] != '/' && !relative) {
1302ea6ae205Smrg                char *n;
1303ea6ae205Smrg                n = dsprintf("%s%s", encodingPrefix, fullname);
1304ea6ae205Smrg                if(n == NULL) {
1305ea6ae205Smrg                    fprintf(stderr, "Couldn't allocate name\n");
1306ea6ae205Smrg                    closedir(dirp);
1307ea6ae205Smrg                    return -1;
1308ea6ae205Smrg                }
1309ea6ae205Smrg                encodingsToDo = listConsF(encodingsToDo, "%s %s", *name, n);
1310ea6ae205Smrg                free(n);
1311ea6ae205Smrg            } else {
1312663cdc11Smrg                encodingsToDo =
1313ea6ae205Smrg                    listConsF(encodingsToDo, "%s %s", *name, fullname);
1314ea6ae205Smrg            }
1315ea6ae205Smrg            if(encodingsToDo == NULL) {
1316ea6ae205Smrg                fprintf(stderr, "Couldn't allocate encodings\n");
1317ea6ae205Smrg                closedir(dirp);
1318ea6ae205Smrg                return -1;
1319ea6ae205Smrg            }
1320ea6ae205Smrg        }
1321ea6ae205Smrg        free(names);            /* only the spine */
1322ea6ae205Smrg    }
1323ea6ae205Smrg    closedir(dirp);
1324ea6ae205Smrg    return 0;
1325ea6ae205Smrg}
1326