~ubuntu-branches/ubuntu/precise/libxfont/precise-updates

« back to all changes in this revision

Viewing changes to src/fontfile/fontdir.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Stone
  • Date: 2005-09-09 15:39:57 UTC
  • Revision ID: james.westby@ubuntu.com-20050909153957-o0ltjssizusljf72
Tags: upstream-0.99.0+cvs.20050909
ImportĀ upstreamĀ versionĀ 0.99.0+cvs.20050909

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XdotOrg: xc/lib/font/fontfile/fontdir.c,v 1.4 2005/07/03 07:01:00 daniels Exp $ */
 
2
/* $Xorg: fontdir.c,v 1.4 2001/02/09 02:04:03 xorgcvs Exp $ */
 
3
 
 
4
/*
 
5
 
 
6
Copyright 1991, 1998  The Open Group
 
7
 
 
8
Permission to use, copy, modify, distribute, and sell this software and its
 
9
documentation for any purpose is hereby granted without fee, provided that
 
10
the above copyright notice appear in all copies and that both that
 
11
copyright notice and this permission notice appear in supporting
 
12
documentation.
 
13
 
 
14
The above copyright notice and this permission notice shall be included in
 
15
all copies or substantial portions of the Software.
 
16
 
 
17
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
18
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
19
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
20
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
21
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
22
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 
 
24
Except as contained in this notice, the name of The Open Group shall not be
 
25
used in advertising or otherwise to promote the sale, use or other dealings
 
26
in this Software without prior written authorization from The Open Group.
 
27
 
 
28
*/
 
29
/* $XFree86: xc/lib/font/fontfile/fontdir.c,v 3.22 2003/07/07 16:40:11 eich Exp $ */
 
30
 
 
31
/*
 
32
 * Author:  Keith Packard, MIT X Consortium
 
33
 */
 
34
 
 
35
#ifdef HAVE_CONFIG_H
 
36
#include <config.h>
 
37
#endif
 
38
#include    <X11/fonts/fntfilst.h>
 
39
#include    <X11/keysym.h>
 
40
 
 
41
Bool
 
42
FontFileInitTable (FontTablePtr table, int size)
 
43
{
 
44
    if (size)
 
45
    {
 
46
        table->entries = (FontEntryPtr) xalloc(sizeof(FontEntryRec) * size);
 
47
        if (!table->entries)
 
48
            return FALSE;
 
49
    }
 
50
    else
 
51
        table->entries = 0;
 
52
    table->used = 0;
 
53
    table->size = size;
 
54
    table->sorted = FALSE;
 
55
    return TRUE;
 
56
}
 
57
 
 
58
void
 
59
FontFileFreeEntry (FontEntryPtr entry)
 
60
{
 
61
    FontScalableExtraPtr   extra;
 
62
    int i;
 
63
 
 
64
    if (entry->name.name)
 
65
        xfree(entry->name.name);
 
66
    entry->name.name = NULL;
 
67
 
 
68
    switch (entry->type)
 
69
    {
 
70
    case FONT_ENTRY_SCALABLE:
 
71
        xfree (entry->u.scalable.fileName);
 
72
        extra = entry->u.scalable.extra;
 
73
        for (i = 0; i < extra->numScaled; i++)
 
74
            if (extra->scaled[i].vals.ranges)
 
75
                xfree (extra->scaled[i].vals.ranges);
 
76
        xfree (extra->scaled);
 
77
        xfree (extra);
 
78
        break;
 
79
    case FONT_ENTRY_BITMAP:
 
80
        xfree (entry->u.bitmap.fileName);
 
81
        entry->u.bitmap.fileName = NULL;
 
82
        break;
 
83
    case FONT_ENTRY_ALIAS:
 
84
        xfree (entry->u.alias.resolved);
 
85
        entry->u.alias.resolved = NULL;
 
86
        break;
 
87
#ifdef NOTYET
 
88
    case FONT_ENTRY_BC:
 
89
        break;
 
90
#endif
 
91
    }
 
92
}
 
93
 
 
94
void
 
95
FontFileFreeTable (FontTablePtr table)
 
96
{
 
97
    int i;
 
98
 
 
99
    for (i = 0; i < table->used; i++)
 
100
        FontFileFreeEntry (&table->entries[i]);
 
101
    xfree (table->entries);
 
102
}
 
103
 
 
104
FontDirectoryPtr
 
105
FontFileMakeDir(char *dirName, int size)
 
106
{
 
107
    FontDirectoryPtr    dir;
 
108
    int                 dirlen;
 
109
    int                 needslash = 0;
 
110
#ifdef FONTDIRATTRIB
 
111
    char                *attrib;
 
112
    int                 attriblen;
 
113
#endif
 
114
 
 
115
#ifdef FONTDIRATTRIB
 
116
#if !defined(__UNIXOS2__) && !defined(WIN32)
 
117
    attrib = strchr(dirName, ':');
 
118
#else
 
119
    /* OS/2 uses the colon in the drive letter descriptor, skip this */
 
120
    attrib = strchr(dirName+2, ':');
 
121
#endif
 
122
    if (attrib) {
 
123
        dirlen = attrib - dirName;
 
124
        attriblen = strlen(attrib);
 
125
    } else {
 
126
        dirlen = strlen(dirName);
 
127
        attriblen = 0;
 
128
    }
 
129
#else
 
130
    dirlen = strlen(dirName);
 
131
#endif
 
132
    if (dirName[dirlen - 1] != '/')
 
133
#ifdef NCD
 
134
    if (dirlen)     /* leave out slash for builtins */
 
135
#endif
 
136
        needslash = 1;
 
137
#ifdef FONTDIRATTRIB
 
138
    dir = (FontDirectoryPtr) xalloc(sizeof *dir + dirlen + needslash + 1 +
 
139
                                    (attriblen ? attriblen + 1 : 0));
 
140
#else
 
141
    dir = (FontDirectoryPtr) xalloc(sizeof *dir + dirlen + needslash + 1);
 
142
#endif
 
143
    if (!dir)
 
144
        return (FontDirectoryPtr)0;
 
145
    if (!FontFileInitTable (&dir->scalable, 0))
 
146
    {
 
147
        xfree (dir);
 
148
        return (FontDirectoryPtr)0;
 
149
    }
 
150
    if (!FontFileInitTable (&dir->nonScalable, size))
 
151
    {
 
152
        FontFileFreeTable (&dir->scalable);
 
153
        xfree (dir);
 
154
        return (FontDirectoryPtr)0;
 
155
    }
 
156
    dir->directory = (char *) (dir + 1);
 
157
    dir->dir_mtime = 0;
 
158
    dir->alias_mtime = 0;
 
159
#ifdef FONTDIRATTRIB
 
160
    if (attriblen)
 
161
        dir->attributes = dir->directory + dirlen + needslash + 1;
 
162
    else
 
163
        dir->attributes = NULL;
 
164
    strncpy(dir->directory, dirName, dirlen);
 
165
    dir->directory[dirlen] = '\0';
 
166
    if (dir->attributes)
 
167
        strcpy(dir->attributes, attrib);
 
168
#else
 
169
    strcpy(dir->directory, dirName);
 
170
#endif
 
171
    if (needslash)
 
172
        strcat(dir->directory, "/");
 
173
    return dir;
 
174
}
 
175
 
 
176
void
 
177
FontFileFreeDir (FontDirectoryPtr dir)
 
178
{
 
179
    FontFileFreeTable (&dir->scalable);
 
180
    FontFileFreeTable (&dir->nonScalable);
 
181
    xfree(dir);
 
182
}
 
183
 
 
184
FontEntryPtr
 
185
FontFileAddEntry(FontTablePtr table, FontEntryPtr prototype)
 
186
{
 
187
    FontEntryPtr    entry;
 
188
    int             newsize;
 
189
 
 
190
    /* can't add entries to a sorted table, pointers get broken! */
 
191
    if (table->sorted)
 
192
        return (FontEntryPtr) 0;    /* "cannot" happen */
 
193
    if (table->used == table->size) {
 
194
        newsize = table->size + 100;
 
195
        entry = (FontEntryPtr) xrealloc(table->entries,
 
196
                                           newsize * sizeof(FontEntryRec));
 
197
        if (!entry)
 
198
            return (FontEntryPtr)0;
 
199
        table->size = newsize;
 
200
        table->entries = entry;
 
201
    }
 
202
    entry = &table->entries[table->used];
 
203
    *entry = *prototype;
 
204
    entry->name.name = (char *) xalloc(prototype->name.length + 1);
 
205
    if (!entry->name.name)
 
206
        return (FontEntryPtr)0;
 
207
    memcpy (entry->name.name, prototype->name.name, prototype->name.length);
 
208
    entry->name.name[entry->name.length] = '\0';
 
209
    table->used++;
 
210
    return entry;
 
211
}
 
212
 
 
213
/*
 
214
 * Compare two strings just like strcmp, but preserve decimal integer
 
215
 * sorting order, i.e. "2" < "10" or "iso8859-2" < "iso8859-10" <
 
216
 * "iso10646-1". Strings are sorted as if sequences of digits were
 
217
 * prefixed by a length indicator (i.e., does not ignore leading zeroes).
 
218
 *
 
219
 * Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk>
 
220
 */
 
221
#define Xisdigit(c) ('\060' <= (c) && (c) <= '\071')
 
222
 
 
223
static int strcmpn(const char *s1, const char *s2)
 
224
{
 
225
    int digits, predigits = 0;
 
226
    const char *ss1, *ss2;
 
227
 
 
228
    while (1) {
 
229
        if (*s1 == 0 && *s2 == 0)
 
230
            return 0;
 
231
        digits = Xisdigit(*s1) && Xisdigit(*s2);
 
232
        if (digits && !predigits) {
 
233
            ss1 = s1;
 
234
            ss2 = s2;
 
235
            while (Xisdigit(*ss1) && Xisdigit(*ss2))
 
236
                ss1++, ss2++;
 
237
            if (!Xisdigit(*ss1) && Xisdigit(*ss2))
 
238
                return -1;
 
239
            if (Xisdigit(*ss1) && !Xisdigit(*ss2))
 
240
                return 1;
 
241
        }
 
242
        if ((unsigned char)*s1 < (unsigned char)*s2)
 
243
            return -1;
 
244
        if ((unsigned char)*s1 > (unsigned char)*s2)
 
245
            return 1;
 
246
        predigits = digits;
 
247
        s1++, s2++;
 
248
    }
 
249
}
 
250
 
 
251
 
 
252
static int
 
253
FontFileNameCompare(const void* a, const void* b)
 
254
{
 
255
    FontEntryPtr    a_name = (FontEntryPtr) a,
 
256
                    b_name = (FontEntryPtr) b;
 
257
 
 
258
    return strcmpn(a_name->name.name, b_name->name.name);
 
259
}
 
260
 
 
261
void
 
262
FontFileSortTable (FontTablePtr table)
 
263
{
 
264
    if (!table->sorted) {
 
265
        qsort((char *) table->entries, table->used, sizeof(FontEntryRec),
 
266
              FontFileNameCompare);
 
267
        table->sorted = TRUE;
 
268
    }
 
269
}
 
270
 
 
271
void
 
272
FontFileSortDir(FontDirectoryPtr dir)
 
273
{
 
274
    FontFileSortTable (&dir->scalable);
 
275
    FontFileSortTable (&dir->nonScalable);
 
276
    /* now that the table is fixed in size, swizzle the pointers */
 
277
    FontFileSwitchStringsToBitmapPointers (dir);
 
278
}
 
279
 
 
280
/*
 
281
  Given a Font Table, SetupWildMatch() sets up various pointers and state
 
282
  information so the table can be searched for name(s) that match a given
 
283
  fontname pattern -- which may contain wildcards.  Under certain
 
284
  circumstances, SetupWildMatch() will find the one table entry that
 
285
  matches the pattern.  If those circumstances do not pertain,
 
286
  SetupWildMatch() returns a range within the the table that should be
 
287
  searched for matching name(s).  With the information established by
 
288
  SetupWildMatch(), including state information in "private", the
 
289
  PatternMatch() procedure is then used to test names in the range for a
 
290
  match.
 
291
*/
 
292
 
 
293
#define isWild(c)   ((c) == XK_asterisk || (c) == XK_question)
 
294
#define isDigit(c)  (XK_0 <= (c) && (c) <= XK_9)
 
295
 
 
296
static int
 
297
SetupWildMatch(FontTablePtr table, FontNamePtr pat, 
 
298
               int *leftp, int *rightp, int *privatep)
 
299
{
 
300
    int         nDashes;
 
301
    char        c;
 
302
    char       *t;
 
303
    char       *firstWild;
 
304
    char       *firstDigit;
 
305
    int         first;
 
306
    int         center,
 
307
                left,
 
308
                right;
 
309
    int         result;
 
310
    char        *name;
 
311
 
 
312
    name = pat->name;
 
313
    nDashes = pat->ndashes;
 
314
    firstWild = 0;
 
315
    firstDigit = 0;
 
316
    t = name;
 
317
    while ((c = *t++)) {
 
318
        if (isWild(c)) {
 
319
            if (!firstWild)
 
320
                firstWild = t - 1;
 
321
        }
 
322
        if (isDigit(c)) {
 
323
            if (!firstDigit)
 
324
                firstDigit = t - 1;
 
325
        }
 
326
    }
 
327
    left = 0;
 
328
    right = table->used;
 
329
    if (firstWild)
 
330
        *privatep = nDashes;
 
331
    else
 
332
        *privatep = -1;
 
333
    if (!table->sorted) {
 
334
        *leftp = left;
 
335
        *rightp = right;
 
336
        return -1;
 
337
    } else if (firstWild) {
 
338
        if (firstDigit && firstDigit < firstWild)
 
339
            first = firstDigit - name;
 
340
        else
 
341
            first = firstWild - name;
 
342
        while (left < right) {
 
343
            center = (left + right) / 2;
 
344
            result = strncmp(name, table->entries[center].name.name, first);
 
345
            if (result == 0)
 
346
                break;
 
347
            if (result < 0)
 
348
                right = center;
 
349
            else
 
350
                left = center + 1;
 
351
        }
 
352
        *leftp = left;
 
353
        *rightp = right;
 
354
        return -1;
 
355
    } else {
 
356
        while (left < right) {
 
357
            center = (left + right) / 2;
 
358
            result = strcmpn(name, table->entries[center].name.name);
 
359
            if (result == 0)
 
360
                return center;
 
361
            if (result < 0)
 
362
                right = center;
 
363
            else
 
364
                left = center + 1;
 
365
        }
 
366
        *leftp = 1;
 
367
        *rightp = 0;
 
368
        return -1;
 
369
    }
 
370
}
 
371
 
 
372
static int
 
373
PatternMatch(char *pat, int patdashes, char *string, int stringdashes)
 
374
{
 
375
    char        c,
 
376
                t;
 
377
 
 
378
    if (stringdashes < patdashes)
 
379
        return 0;
 
380
    for (;;) {
 
381
        switch (c = *pat++) {
 
382
        case '*':
 
383
            if (!(c = *pat++))
 
384
                return 1;
 
385
            if (c == XK_minus) {
 
386
                patdashes--;
 
387
                for (;;) {
 
388
                    while ((t = *string++) != XK_minus)
 
389
                        if (!t)
 
390
                            return 0;
 
391
                    stringdashes--;
 
392
                    if (PatternMatch(pat, patdashes, string, stringdashes))
 
393
                        return 1;
 
394
                    if (stringdashes == patdashes)
 
395
                        return 0;
 
396
                }
 
397
            } else {
 
398
                for (;;) {
 
399
                    while ((t = *string++) != c) {
 
400
                        if (!t)
 
401
                            return 0;
 
402
                        if (t == XK_minus) {
 
403
                            if (stringdashes-- < patdashes)
 
404
                                return 0;
 
405
                        }
 
406
                    }
 
407
                    if (PatternMatch(pat, patdashes, string, stringdashes))
 
408
                        return 1;
 
409
                }
 
410
            }
 
411
        case '?':
 
412
            if (*string++ == XK_minus)
 
413
                stringdashes--;
 
414
            break;
 
415
        case '\0':
 
416
            return (*string == '\0');
 
417
        case XK_minus:
 
418
            if (*string++ == XK_minus) {
 
419
                patdashes--;
 
420
                stringdashes--;
 
421
                break;
 
422
            }
 
423
            return 0;
 
424
        default:
 
425
            if (c == *string++)
 
426
                break;
 
427
            return 0;
 
428
        }
 
429
    }
 
430
}
 
431
 
 
432
int
 
433
FontFileCountDashes (char *name, int namelen)
 
434
{
 
435
    int ndashes = 0;
 
436
 
 
437
    while (namelen--)
 
438
        if (*name++ == '\055')  /* avoid non ascii systems */
 
439
            ++ndashes;
 
440
    return ndashes;
 
441
}
 
442
 
 
443
char *
 
444
FontFileSaveString (char *s)
 
445
{
 
446
    char    *n;
 
447
 
 
448
    n = (char *) xalloc (strlen (s) + 1);
 
449
    if (!n)
 
450
        return 0;
 
451
    strcpy (n, s);
 
452
    return n;
 
453
}
 
454
 
 
455
FontEntryPtr
 
456
FontFileFindNameInScalableDir(FontTablePtr table, FontNamePtr pat, 
 
457
                              FontScalablePtr vals)
 
458
{
 
459
    int         i,
 
460
                start,
 
461
                stop,
 
462
                res,
 
463
                private;
 
464
    FontNamePtr name;
 
465
 
 
466
    if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0)
 
467
        return &table->entries[i];
 
468
    for (i = start; i < stop; i++) {
 
469
        name = &table->entries[i].name;
 
470
        res = PatternMatch(pat->name, private, name->name, name->ndashes);
 
471
        if (res > 0)
 
472
        {
 
473
            /* Check to see if enhancements requested are available */
 
474
            if (vals)
 
475
            {
 
476
                int vs = vals->values_supplied;
 
477
                int cap;
 
478
 
 
479
                if (table->entries[i].type == FONT_ENTRY_SCALABLE)
 
480
                    cap = table->entries[i].u.scalable.renderer->capabilities;
 
481
                else if (table->entries[i].type == FONT_ENTRY_ALIAS)
 
482
                    cap = ~0;   /* Calling code will have to see if true */
 
483
                else
 
484
                    cap = 0;
 
485
                if ((((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
 
486
                      (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) &&
 
487
                     !(cap & CAP_MATRIX)) ||
 
488
                    ((vs & CHARSUBSET_SPECIFIED) &&
 
489
                     !(cap & CAP_CHARSUBSETTING)))
 
490
                    continue;
 
491
            }
 
492
            return &table->entries[i];
 
493
        }
 
494
        if (res < 0)
 
495
            break;
 
496
    }
 
497
    return (FontEntryPtr)0;
 
498
}
 
499
 
 
500
FontEntryPtr
 
501
FontFileFindNameInDir(FontTablePtr table, FontNamePtr pat)
 
502
{
 
503
    return FontFileFindNameInScalableDir(table, pat, (FontScalablePtr)0);
 
504
}
 
505
 
 
506
int
 
507
FontFileFindNamesInScalableDir(FontTablePtr table, FontNamePtr pat, int max, 
 
508
                               FontNamesPtr names, FontScalablePtr vals,
 
509
                               int alias_behavior, int *newmax)
 
510
{
 
511
    int             i,
 
512
                    start,
 
513
                    stop,
 
514
                    res,
 
515
                    private;
 
516
    int             ret = Successful;
 
517
    FontEntryPtr    fname;
 
518
    FontNamePtr     name;
 
519
 
 
520
    if (max <= 0)
 
521
        return Successful;
 
522
    if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0) {
 
523
        if (alias_behavior == NORMAL_ALIAS_BEHAVIOR ||
 
524
            table->entries[i].type != FONT_ENTRY_ALIAS)
 
525
        {
 
526
            name = &table->entries[i].name;
 
527
            if (newmax) *newmax = max - 1;
 
528
            return AddFontNamesName(names, name->name, name->length);
 
529
        }
 
530
        start = i;
 
531
        stop = i + 1;
 
532
    }
 
533
    for (i = start, fname = &table->entries[start]; i < stop; i++, fname++) {
 
534
        res = PatternMatch(pat->name, private, fname->name.name, fname->name.ndashes);
 
535
        if (res > 0) {
 
536
            if (vals)
 
537
            {
 
538
                int vs = vals->values_supplied;
 
539
                int cap;
 
540
 
 
541
                if (fname->type == FONT_ENTRY_SCALABLE)
 
542
                    cap = fname->u.scalable.renderer->capabilities;
 
543
                else if (fname->type == FONT_ENTRY_ALIAS)
 
544
                    cap = ~0;   /* Calling code will have to see if true */
 
545
                else
 
546
                    cap = 0;
 
547
                if ((((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
 
548
                     (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) &&
 
549
                    !(cap & CAP_MATRIX)) ||
 
550
                    ((vs & CHARSUBSET_SPECIFIED) &&
 
551
                    !(cap & CAP_CHARSUBSETTING)))
 
552
                    continue;
 
553
            }
 
554
 
 
555
            if ((alias_behavior & IGNORE_SCALABLE_ALIASES) &&
 
556
                fname->type == FONT_ENTRY_ALIAS)
 
557
            {
 
558
                FontScalableRec tmpvals;
 
559
                if (FontParseXLFDName (fname->name.name, &tmpvals,
 
560
                                       FONT_XLFD_REPLACE_NONE) &&
 
561
                    !(tmpvals.values_supplied & SIZE_SPECIFY_MASK))
 
562
                    continue;
 
563
            }
 
564
 
 
565
            ret = AddFontNamesName(names, fname->name.name, fname->name.length);
 
566
            if (ret != Successful)
 
567
                goto bail;
 
568
 
 
569
            /* If alias_behavior is LIST_ALIASES_AND_TARGET_NAMES, mark
 
570
               this entry as an alias by negating its length and follow
 
571
               it by the resolved name */
 
572
            if ((alias_behavior & LIST_ALIASES_AND_TARGET_NAMES) &&
 
573
                fname->type == FONT_ENTRY_ALIAS)
 
574
            {
 
575
                names->length[names->nnames - 1] =
 
576
                    -names->length[names->nnames - 1];
 
577
                ret = AddFontNamesName(names, fname->u.alias.resolved,
 
578
                                       strlen(fname->u.alias.resolved));
 
579
                if (ret != Successful)
 
580
                    goto bail;
 
581
            }
 
582
 
 
583
            if (--max <= 0)
 
584
                break;
 
585
        } else if (res < 0)
 
586
            break;
 
587
    }
 
588
  bail: ;
 
589
    if (newmax) *newmax = max;
 
590
    return ret;
 
591
}
 
592
 
 
593
int
 
594
FontFileFindNamesInDir(FontTablePtr table, FontNamePtr pat, 
 
595
                       int max, FontNamesPtr names)
 
596
{
 
597
    return FontFileFindNamesInScalableDir(table, pat, max, names,
 
598
                                          (FontScalablePtr)0,
 
599
                                          NORMAL_ALIAS_BEHAVIOR, (int *)0);
 
600
}
 
601
 
 
602
Bool
 
603
FontFileMatchName(char *name, int length, FontNamePtr pat)
 
604
{
 
605
    /* Perform a fontfile-type name match on a single name */
 
606
    FontTableRec table;
 
607
    FontEntryRec entries[1];
 
608
 
 
609
    /* Dummy up a table */
 
610
    table.used = 1;
 
611
    table.size = 1;
 
612
    table.sorted = TRUE;
 
613
    table.entries = entries;
 
614
    entries[0].name.name = name;
 
615
    entries[0].name.length = length;
 
616
    entries[0].name.ndashes = FontFileCountDashes(name, length);
 
617
 
 
618
    return FontFileFindNameInDir(&table, pat) != (FontEntryPtr)0;
 
619
}
 
620
 
 
621
/*
 
622
 * Add a font file to a directory.  This handles bitmap and
 
623
 * scalable names both
 
624
 */
 
625
 
 
626
Bool
 
627
FontFileAddFontFile (FontDirectoryPtr dir, char *fontName, char *fileName)
 
628
{
 
629
    FontEntryRec            entry;
 
630
    FontScalableRec         vals, zeroVals;
 
631
    FontRendererPtr         renderer;
 
632
    FontEntryPtr            existing;
 
633
    FontScalableExtraPtr    extra;
 
634
    FontEntryPtr            bitmap = 0, scalable;
 
635
    Bool                    isscale;
 
636
#ifdef FONTDIRATTRIB
 
637
    Bool                    scalable_xlfd;
 
638
#endif
 
639
 
 
640
    renderer = FontFileMatchRenderer (fileName);
 
641
    if (!renderer)
 
642
        return FALSE;
 
643
    entry.name.length = strlen (fontName);
 
644
    if (entry.name.length > MAXFONTNAMELEN)
 
645
        entry.name.length = MAXFONTNAMELEN;
 
646
    entry.name.name = fontName;
 
647
    CopyISOLatin1Lowered (entry.name.name, fontName, entry.name.length);
 
648
    entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length);
 
649
    entry.name.name[entry.name.length] = '\0';
 
650
    /*
 
651
     * Add a bitmap name if the incoming name isn't an XLFD name, or
 
652
     * if it isn't a scalable name (i.e. non-zero scalable fields)
 
653
     *
 
654
     * If name of bitmapped font contains XLFD enhancements, do not add
 
655
     * a scalable version of the name... this can lead to confusion and
 
656
     * ambiguity between the font name and the field enhancements.
 
657
     */
 
658
    isscale = entry.name.ndashes == 14 &&
 
659
              FontParseXLFDName(entry.name.name,
 
660
                                &vals, FONT_XLFD_REPLACE_NONE) &&
 
661
              (vals.values_supplied & PIXELSIZE_MASK) != PIXELSIZE_ARRAY &&
 
662
              (vals.values_supplied & POINTSIZE_MASK) != POINTSIZE_ARRAY &&
 
663
              !(vals.values_supplied & ENHANCEMENT_SPECIFY_MASK);
 
664
#ifdef FONTDIRATTRIB
 
665
#define UNSCALED_ATTRIB "unscaled"
 
666
    scalable_xlfd = (isscale &&
 
667
                (((vals.values_supplied & PIXELSIZE_MASK) == 0) ||
 
668
                 ((vals.values_supplied & POINTSIZE_MASK) == 0)));
 
669
    /*
 
670
     * For scalable fonts without a scalable XFLD, check if the "unscaled"
 
671
     * attribute is present.
 
672
     */
 
673
    if (isscale && !scalable_xlfd &&
 
674
            dir->attributes && dir->attributes[0] == ':') {
 
675
        char *ptr1 = dir->attributes + 1;
 
676
        char *ptr2;
 
677
        int length;
 
678
        int uslength = strlen(UNSCALED_ATTRIB);
 
679
 
 
680
        do {
 
681
            ptr2 = strchr(ptr1, ':');
 
682
            if (ptr2)
 
683
                length = ptr2 - ptr1;
 
684
            else
 
685
                length = dir->attributes + strlen(dir->attributes) - ptr1;
 
686
            if (length == uslength && !strncmp(ptr1, UNSCALED_ATTRIB, uslength))
 
687
                isscale = FALSE;
 
688
            if (ptr2)
 
689
                ptr1 = ptr2 + 1;
 
690
        } while (ptr2);
 
691
    }
 
692
#endif
 
693
    if (!isscale || (vals.values_supplied & SIZE_SPECIFY_MASK))
 
694
    {
 
695
      /*
 
696
       * If the renderer doesn't support OpenBitmap, FontFileOpenFont
 
697
       * will still do the right thing.
 
698
       */
 
699
        entry.type = FONT_ENTRY_BITMAP;
 
700
        entry.u.bitmap.renderer = renderer;
 
701
        entry.u.bitmap.pFont = NullFont;
 
702
        if (!(entry.u.bitmap.fileName = FontFileSaveString (fileName)))
 
703
            return FALSE;
 
704
        if (!(bitmap = FontFileAddEntry (&dir->nonScalable, &entry)))
 
705
        {
 
706
            xfree (entry.u.bitmap.fileName);
 
707
            return FALSE;
 
708
        }
 
709
    }
 
710
    /*
 
711
     * Parse out scalable fields from XLFD names - a scalable name
 
712
     * just gets inserted, a scaled name has more things to do.
 
713
     */
 
714
    if (isscale)
 
715
    {
 
716
        if (vals.values_supplied & SIZE_SPECIFY_MASK)
 
717
        {
 
718
            bzero((char *)&zeroVals, sizeof(zeroVals));
 
719
            zeroVals.x = vals.x;
 
720
            zeroVals.y = vals.y;
 
721
            zeroVals.values_supplied = PIXELSIZE_SCALAR | POINTSIZE_SCALAR;
 
722
            FontParseXLFDName (entry.name.name, &zeroVals,
 
723
                               FONT_XLFD_REPLACE_VALUE);
 
724
            entry.name.length = strlen (entry.name.name);
 
725
            existing = FontFileFindNameInDir (&dir->scalable, &entry.name);
 
726
            if (existing)
 
727
            {
 
728
                if ((vals.values_supplied & POINTSIZE_MASK) ==
 
729
                        POINTSIZE_SCALAR &&
 
730
                    (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize())
 
731
                {
 
732
                    existing->u.scalable.extra->defaults = vals;
 
733
 
 
734
                    xfree (existing->u.scalable.fileName);
 
735
                    if (!(existing->u.scalable.fileName = FontFileSaveString (fileName)))
 
736
                        return FALSE;
 
737
                }
 
738
                if(bitmap)
 
739
                {
 
740
                    FontFileCompleteXLFD(&vals, &vals);
 
741
                    FontFileAddScaledInstance (existing, &vals, NullFont,
 
742
                                               bitmap->name.name);
 
743
                    return TRUE;
 
744
                }
 
745
            }
 
746
        }
 
747
        if (!(entry.u.scalable.fileName = FontFileSaveString (fileName)))
 
748
            return FALSE;
 
749
        extra = (FontScalableExtraPtr) xalloc (sizeof (FontScalableExtraRec));
 
750
        if (!extra)
 
751
        {
 
752
            xfree (entry.u.scalable.fileName);
 
753
            return FALSE;
 
754
        }
 
755
        bzero((char *)&extra->defaults, sizeof(extra->defaults));
 
756
        if ((vals.values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR &&
 
757
            (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize())
 
758
            extra->defaults = vals;
 
759
        else
 
760
        {
 
761
            FontResolutionPtr resolution;
 
762
            int num;
 
763
 
 
764
            extra->defaults.point_matrix[0] =
 
765
                extra->defaults.point_matrix[3] =
 
766
                    (double)GetDefaultPointSize() / 10.0;
 
767
            extra->defaults.point_matrix[1] =
 
768
                extra->defaults.point_matrix[2] = 0.0;
 
769
            extra->defaults.values_supplied =
 
770
                POINTSIZE_SCALAR | PIXELSIZE_UNDEFINED;
 
771
            extra->defaults.width = -1;
 
772
            if (vals.x <= 0 || vals.y <= 0)
 
773
            {
 
774
                resolution = GetClientResolutions (&num);
 
775
                if (resolution && num > 0)
 
776
                {
 
777
                    extra->defaults.x = resolution->x_resolution;
 
778
                    extra->defaults.y = resolution->y_resolution;
 
779
                }
 
780
                else
 
781
                {
 
782
                    extra->defaults.x = 75;
 
783
                    extra->defaults.y = 75;
 
784
                }
 
785
             }
 
786
             else 
 
787
             {
 
788
                extra->defaults.x = vals.x;
 
789
                extra->defaults.y = vals.y;
 
790
             }
 
791
             FontFileCompleteXLFD (&extra->defaults, &extra->defaults);
 
792
        }
 
793
        extra->numScaled = 0;
 
794
        extra->sizeScaled = 0;
 
795
        extra->scaled = 0;
 
796
        extra->private = 0;
 
797
        entry.type = FONT_ENTRY_SCALABLE;
 
798
        entry.u.scalable.renderer = renderer;
 
799
        entry.u.scalable.extra = extra;
 
800
        if (!(scalable = FontFileAddEntry (&dir->scalable, &entry)))
 
801
        {
 
802
            xfree (extra);
 
803
            xfree (entry.u.scalable.fileName);
 
804
            return FALSE;
 
805
        }
 
806
        if (vals.values_supplied & SIZE_SPECIFY_MASK)
 
807
        {
 
808
            if(bitmap)
 
809
            {
 
810
                FontFileCompleteXLFD(&vals, &vals);
 
811
                FontFileAddScaledInstance (scalable, &vals, NullFont,
 
812
                                           bitmap->name.name);
 
813
            }
 
814
        }
 
815
    }
 
816
    return TRUE;
 
817
}
 
818
 
 
819
Bool
 
820
FontFileAddFontAlias (FontDirectoryPtr dir, char *aliasName, char *fontName)
 
821
{
 
822
    FontEntryRec        entry;
 
823
 
 
824
    entry.name.length = strlen (aliasName);
 
825
    CopyISOLatin1Lowered (aliasName, aliasName, entry.name.length);
 
826
    entry.name.name = aliasName;
 
827
    entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length);
 
828
    entry.type = FONT_ENTRY_ALIAS;
 
829
    if (!(entry.u.alias.resolved = FontFileSaveString (fontName)))
 
830
        return FALSE;
 
831
    if (!FontFileAddEntry (&dir->nonScalable, &entry))
 
832
    {
 
833
        xfree (entry.u.alias.resolved);
 
834
        return FALSE;
 
835
    }
 
836
    return TRUE;
 
837
}