~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/lib/fontconfig/src/fccfg.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $XFree86: xc/lib/fontconfig/src/fccfg.c,v 1.24 2002/12/21 02:31:53 dawes Exp $
 
3
 *
 
4
 * Copyright � 2000 Keith Packard, member of The XFree86 Project, Inc.
 
5
 *
 
6
 * Permission to use, copy, modify, distribute, and sell this software and its
 
7
 * documentation for any purpose is hereby granted without fee, provided that
 
8
 * the above copyright notice appear in all copies and that both that
 
9
 * copyright notice and this permission notice appear in supporting
 
10
 * documentation, and that the name of Keith Packard not be used in
 
11
 * advertising or publicity pertaining to distribution of the software without
 
12
 * specific, written prior permission.  Keith Packard makes no
 
13
 * representations about the suitability of this software for any purpose.  It
 
14
 * is provided "as is" without express or implied warranty.
 
15
 *
 
16
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
17
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
18
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
19
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
20
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
21
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
22
 * PERFORMANCE OF THIS SOFTWARE.
 
23
 */
 
24
 
 
25
#include "fcint.h"
 
26
 
 
27
FcConfig    *_fcConfig;
 
28
 
 
29
FcConfig *
 
30
FcConfigCreate (void)
 
31
{
 
32
    FcSetName   set;
 
33
    FcConfig    *config;
 
34
 
 
35
    config = malloc (sizeof (FcConfig));
 
36
    if (!config)
 
37
        goto bail0;
 
38
    FcMemAlloc (FC_MEM_CONFIG, sizeof (FcConfig));
 
39
    
 
40
    config->configDirs = FcStrSetCreate ();
 
41
    if (!config->configDirs)
 
42
        goto bail1;
 
43
    
 
44
    config->configFiles = FcStrSetCreate ();
 
45
    if (!config->configFiles)
 
46
        goto bail2;
 
47
    
 
48
    config->fontDirs = FcStrSetCreate ();
 
49
    if (!config->fontDirs)
 
50
        goto bail3;
 
51
    
 
52
    config->cache = 0;
 
53
    if (!FcConfigSetCache (config, (FcChar8 *) ("~/" FC_USER_CACHE_FILE)))
 
54
        goto bail4;
 
55
 
 
56
    config->blanks = 0;
 
57
 
 
58
    config->substPattern = 0;
 
59
    config->substFont = 0;
 
60
    config->maxObjects = 0;
 
61
    for (set = FcSetSystem; set <= FcSetApplication; set++)
 
62
        config->fonts[set] = 0;
 
63
 
 
64
    config->rescanTime = time(0);
 
65
    config->rescanInterval = 30;    
 
66
    
 
67
    return config;
 
68
 
 
69
bail4:
 
70
    FcStrSetDestroy (config->fontDirs);
 
71
bail3:
 
72
    FcStrSetDestroy (config->configFiles);
 
73
bail2:
 
74
    FcStrSetDestroy (config->configDirs);
 
75
bail1:
 
76
    free (config);
 
77
    FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
 
78
bail0:
 
79
    return 0;
 
80
}
 
81
 
 
82
typedef struct _FcFileTime {
 
83
    time_t  time;
 
84
    FcBool  set;
 
85
} FcFileTime;
 
86
 
 
87
static FcFileTime
 
88
FcConfigNewestFile (FcStrSet *files)
 
89
{
 
90
    FcStrList       *list = FcStrListCreate (files);
 
91
    FcFileTime      newest = { 0, FcFalse };
 
92
    FcChar8         *file;
 
93
    struct  stat    statb;
 
94
 
 
95
    if (list)
 
96
    {
 
97
        while ((file = FcStrListNext (list)))
 
98
            if (stat ((char *) file, &statb) == 0)
 
99
                if (!newest.set || statb.st_mtime - newest.time > 0)
 
100
                    newest.time = statb.st_mtime;
 
101
        FcStrListDone (list);
 
102
    }
 
103
    return newest;
 
104
}
 
105
 
 
106
FcBool
 
107
FcConfigUptoDate (FcConfig *config)
 
108
{
 
109
    FcFileTime  config_time, font_time;
 
110
    time_t      now = time(0);
 
111
    if (!config)
 
112
    {
 
113
        config = FcConfigGetCurrent ();
 
114
        if (!config)
 
115
            return FcFalse;
 
116
    }
 
117
    config_time = FcConfigNewestFile (config->configFiles);
 
118
    font_time = FcConfigNewestFile (config->configDirs);
 
119
    if ((config_time.set && config_time.time - config->rescanTime > 0) ||
 
120
        (font_time.set && font_time.time - config->rescanTime) > 0)
 
121
    {
 
122
        return FcFalse;
 
123
    }
 
124
    config->rescanTime = now;
 
125
    return FcTrue;
 
126
}
 
127
 
 
128
static void
 
129
FcSubstDestroy (FcSubst *s)
 
130
{
 
131
    FcSubst *n;
 
132
    
 
133
    while (s)
 
134
    {
 
135
        n = s->next;
 
136
        FcTestDestroy (s->test);
 
137
        FcEditDestroy (s->edit);
 
138
        s = n;
 
139
    }
 
140
}
 
141
 
 
142
void
 
143
FcConfigDestroy (FcConfig *config)
 
144
{
 
145
    FcSetName   set;
 
146
 
 
147
    if (config == _fcConfig)
 
148
        _fcConfig = 0;
 
149
 
 
150
    FcStrSetDestroy (config->configDirs);
 
151
    FcStrSetDestroy (config->fontDirs);
 
152
    FcStrSetDestroy (config->configFiles);
 
153
 
 
154
    FcStrFree (config->cache);
 
155
 
 
156
    FcSubstDestroy (config->substPattern);
 
157
    FcSubstDestroy (config->substFont);
 
158
    for (set = FcSetSystem; set <= FcSetApplication; set++)
 
159
        if (config->fonts[set])
 
160
            FcFontSetDestroy (config->fonts[set]);
 
161
    free (config);
 
162
    FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
 
163
}
 
164
 
 
165
/*
 
166
 * Scan the current list of directories in the configuration
 
167
 * and build the set of available fonts. Update the
 
168
 * per-user cache file to reflect the new configuration
 
169
 */
 
170
 
 
171
FcBool
 
172
FcConfigBuildFonts (FcConfig *config)
 
173
{
 
174
    FcFontSet       *fonts;
 
175
    FcGlobalCache   *cache;
 
176
    FcStrList       *list;
 
177
    FcChar8         *dir;
 
178
 
 
179
    fonts = FcFontSetCreate ();
 
180
    if (!fonts)
 
181
        goto bail0;
 
182
    
 
183
    cache = FcGlobalCacheCreate ();
 
184
    if (!cache)
 
185
        goto bail1;
 
186
 
 
187
    FcGlobalCacheLoad (cache, config->cache);
 
188
 
 
189
    list = FcConfigGetFontDirs (config);
 
190
    if (!list)
 
191
        goto bail1;
 
192
 
 
193
    while ((dir = FcStrListNext (list)))
 
194
    {
 
195
        if (FcDebug () & FC_DBG_FONTSET)
 
196
            printf ("scan dir %s\n", dir);
 
197
        FcDirScan (fonts, config->fontDirs, cache, config->blanks, dir, FcFalse);
 
198
    }
 
199
    
 
200
    FcStrListDone (list);
 
201
    
 
202
    if (FcDebug () & FC_DBG_FONTSET)
 
203
        FcFontSetPrint (fonts);
 
204
 
 
205
    FcGlobalCacheSave (cache, config->cache);
 
206
    FcGlobalCacheDestroy (cache);
 
207
 
 
208
    FcConfigSetFonts (config, fonts, FcSetSystem);
 
209
    
 
210
    return FcTrue;
 
211
bail1:
 
212
    FcFontSetDestroy (fonts);
 
213
bail0:
 
214
    return FcFalse;
 
215
}
 
216
 
 
217
FcBool
 
218
FcConfigSetCurrent (FcConfig *config)
 
219
{
 
220
    if (!config->fonts)
 
221
        if (!FcConfigBuildFonts (config))
 
222
            return FcFalse;
 
223
 
 
224
    if (_fcConfig)
 
225
        FcConfigDestroy (_fcConfig);
 
226
    _fcConfig = config;
 
227
    return FcTrue;
 
228
}
 
229
 
 
230
FcConfig *
 
231
FcConfigGetCurrent (void)
 
232
{
 
233
    if (!_fcConfig)
 
234
        if (!FcInit ())
 
235
            return 0;
 
236
    return _fcConfig;
 
237
}
 
238
 
 
239
FcBool
 
240
FcConfigAddConfigDir (FcConfig      *config,
 
241
                      const FcChar8 *d)
 
242
{
 
243
    return FcStrSetAddFilename (config->configDirs, d);
 
244
}
 
245
 
 
246
FcStrList *
 
247
FcConfigGetConfigDirs (FcConfig   *config)
 
248
{
 
249
    if (!config)
 
250
    {
 
251
        config = FcConfigGetCurrent ();
 
252
        if (!config)
 
253
            return 0;
 
254
    }
 
255
    return FcStrListCreate (config->configDirs);
 
256
}
 
257
 
 
258
FcBool
 
259
FcConfigAddFontDir (FcConfig        *config,
 
260
                    const FcChar8   *d)
 
261
{
 
262
    return FcStrSetAddFilename (config->fontDirs, d);
 
263
}
 
264
 
 
265
FcBool
 
266
FcConfigAddDir (FcConfig            *config,
 
267
                const FcChar8       *d)
 
268
{
 
269
    return (FcConfigAddConfigDir (config, d) && 
 
270
            FcConfigAddFontDir (config, d));
 
271
}
 
272
 
 
273
FcStrList *
 
274
FcConfigGetFontDirs (FcConfig   *config)
 
275
{
 
276
    if (!config)
 
277
    {
 
278
        config = FcConfigGetCurrent ();
 
279
        if (!config)
 
280
            return 0;
 
281
    }
 
282
    return FcStrListCreate (config->fontDirs);
 
283
}
 
284
 
 
285
FcBool
 
286
FcConfigAddConfigFile (FcConfig     *config,
 
287
                       const FcChar8   *f)
 
288
{
 
289
    FcBool      ret;
 
290
    FcChar8     *file = FcConfigFilename (f);
 
291
    
 
292
    if (!file)
 
293
        return FcFalse;
 
294
    
 
295
    ret = FcStrSetAdd (config->configFiles, file);
 
296
    FcStrFree (file);
 
297
    return ret;
 
298
}
 
299
 
 
300
FcStrList *
 
301
FcConfigGetConfigFiles (FcConfig    *config)
 
302
{
 
303
    if (!config)
 
304
    {
 
305
        config = FcConfigGetCurrent ();
 
306
        if (!config)
 
307
            return 0;
 
308
    }
 
309
    return FcStrListCreate (config->configFiles);
 
310
}
 
311
 
 
312
FcBool
 
313
FcConfigSetCache (FcConfig      *config,
 
314
                  const FcChar8 *c)
 
315
{
 
316
    FcChar8    *new = FcStrCopyFilename (c);
 
317
    
 
318
    if (!new)
 
319
        return FcFalse;
 
320
    if (config->cache)
 
321
        FcStrFree (config->cache);
 
322
    config->cache = new;
 
323
    return FcTrue;
 
324
}
 
325
 
 
326
FcChar8 *
 
327
FcConfigGetCache (FcConfig  *config)
 
328
{
 
329
    if (!config)
 
330
    {
 
331
        config = FcConfigGetCurrent ();
 
332
        if (!config)
 
333
            return 0;
 
334
    }
 
335
    return config->cache;
 
336
}
 
337
 
 
338
FcFontSet *
 
339
FcConfigGetFonts (FcConfig      *config,
 
340
                  FcSetName     set)
 
341
{
 
342
    if (!config)
 
343
    {
 
344
        config = FcConfigGetCurrent ();
 
345
        if (!config)
 
346
            return 0;
 
347
    }
 
348
    return config->fonts[set];
 
349
}
 
350
 
 
351
void
 
352
FcConfigSetFonts (FcConfig      *config,
 
353
                  FcFontSet     *fonts,
 
354
                  FcSetName     set)
 
355
{
 
356
    if (config->fonts[set])
 
357
        FcFontSetDestroy (config->fonts[set]);
 
358
    config->fonts[set] = fonts;
 
359
}
 
360
 
 
361
 
 
362
 
 
363
FcBlanks *
 
364
FcConfigGetBlanks (FcConfig     *config)
 
365
{
 
366
    if (!config)
 
367
    {
 
368
        config = FcConfigGetCurrent ();
 
369
        if (!config)
 
370
            return 0;
 
371
    }
 
372
    return config->blanks;
 
373
}
 
374
 
 
375
FcBool
 
376
FcConfigAddBlank (FcConfig      *config,
 
377
                  FcChar32      blank)
 
378
{
 
379
    FcBlanks    *b;
 
380
    
 
381
    b = config->blanks;
 
382
    if (!b)
 
383
    {
 
384
        b = FcBlanksCreate ();
 
385
        if (!b)
 
386
            return FcFalse;
 
387
    }
 
388
    if (!FcBlanksAdd (b, blank))
 
389
        return FcFalse;
 
390
    config->blanks = b;
 
391
    return FcTrue;
 
392
}
 
393
 
 
394
int
 
395
FcConfigGetRescanInverval (FcConfig *config)
 
396
{
 
397
    if (!config)
 
398
    {
 
399
        config = FcConfigGetCurrent ();
 
400
        if (!config)
 
401
            return 0;
 
402
    }
 
403
    return config->rescanInterval;
 
404
}
 
405
 
 
406
FcBool
 
407
FcConfigSetRescanInverval (FcConfig *config, int rescanInterval)
 
408
{
 
409
    if (!config)
 
410
    {
 
411
        config = FcConfigGetCurrent ();
 
412
        if (!config)
 
413
            return FcFalse;
 
414
    }
 
415
    config->rescanInterval = rescanInterval;
 
416
    return FcTrue;
 
417
}
 
418
 
 
419
FcBool
 
420
FcConfigAddEdit (FcConfig       *config,
 
421
                 FcTest         *test,
 
422
                 FcEdit         *edit,
 
423
                 FcMatchKind    kind)
 
424
{
 
425
    FcSubst     *subst, **prev;
 
426
    FcTest      *t;
 
427
    int         num;
 
428
 
 
429
    subst = (FcSubst *) malloc (sizeof (FcSubst));
 
430
    if (!subst)
 
431
        return FcFalse;
 
432
    FcMemAlloc (FC_MEM_SUBST, sizeof (FcSubst));
 
433
    if (kind == FcMatchPattern)
 
434
        prev = &config->substPattern;
 
435
    else
 
436
        prev = &config->substFont;
 
437
    for (; *prev; prev = &(*prev)->next);
 
438
    *prev = subst;
 
439
    subst->next = 0;
 
440
    subst->test = test;
 
441
    subst->edit = edit;
 
442
    num = 0;
 
443
    for (t = test; t; t = t->next)
 
444
    {
 
445
        if (t->kind == FcMatchDefault)
 
446
            t->kind = kind;
 
447
        num++;
 
448
    }
 
449
    if (config->maxObjects < num)
 
450
        config->maxObjects = num;
 
451
    if (FcDebug () & FC_DBG_EDIT)
 
452
    {
 
453
        printf ("Add Subst ");
 
454
        FcSubstPrint (subst);
 
455
    }
 
456
    return FcTrue;
 
457
}
 
458
 
 
459
typedef struct _FcSubState {
 
460
    FcPatternElt   *elt;
 
461
    FcValueList    *value;
 
462
} FcSubState;
 
463
 
 
464
static FcValue
 
465
FcConfigPromote (FcValue v, FcValue u)
 
466
{
 
467
    if (v.type == FcTypeInteger)
 
468
    {
 
469
        v.type = FcTypeDouble;
 
470
        v.u.d = (double) v.u.i;
 
471
    }
 
472
    else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
 
473
    {
 
474
        v.u.m = &FcIdentityMatrix;
 
475
        v.type = FcTypeMatrix;
 
476
    }
 
477
    else if (v.type == FcTypeString && u.type == FcTypeLangSet)
 
478
    {
 
479
        v.u.l = FcLangSetPromote (v.u.s);
 
480
        v.type = FcTypeLangSet;
 
481
    }
 
482
    return v;
 
483
}
 
484
 
 
485
FcBool
 
486
FcConfigCompareValue (FcValue   m,
 
487
                      FcOp      op,
 
488
                      FcValue   v)
 
489
{
 
490
    FcBool    ret = FcFalse;
 
491
    
 
492
    m = FcConfigPromote (m, v);
 
493
    v = FcConfigPromote (v, m);
 
494
    if (m.type == v.type) 
 
495
    {
 
496
        switch (m.type) {
 
497
        case FcTypeInteger:
 
498
            break;      /* FcConfigPromote prevents this from happening */
 
499
        case FcTypeDouble:
 
500
            switch (op) {
 
501
            case FcOpEqual:
 
502
            case FcOpContains:
 
503
                ret = m.u.d == v.u.d;
 
504
                break;
 
505
            case FcOpNotEqual:
 
506
            case FcOpNotContains:
 
507
                ret = m.u.d != v.u.d;
 
508
                break;
 
509
            case FcOpLess:    
 
510
                ret = m.u.d < v.u.d;
 
511
                break;
 
512
            case FcOpLessEqual:    
 
513
                ret = m.u.d <= v.u.d;
 
514
                break;
 
515
            case FcOpMore:    
 
516
                ret = m.u.d > v.u.d;
 
517
                break;
 
518
            case FcOpMoreEqual:    
 
519
                ret = m.u.d >= v.u.d;
 
520
                break;
 
521
            default:
 
522
                break;
 
523
            }
 
524
            break;
 
525
        case FcTypeBool:
 
526
            switch (op) {
 
527
            case FcOpEqual:    
 
528
            case FcOpContains:
 
529
                ret = m.u.b == v.u.b;
 
530
                break;
 
531
            case FcOpNotEqual:
 
532
            case FcOpNotContains:
 
533
                ret = m.u.b != v.u.b;
 
534
                break;
 
535
            default:
 
536
                break;
 
537
            }
 
538
            break;
 
539
        case FcTypeString:
 
540
            switch (op) {
 
541
            case FcOpEqual:    
 
542
            case FcOpContains:
 
543
                ret = FcStrCmpIgnoreCase (m.u.s, v.u.s) == 0;
 
544
                break;
 
545
            case FcOpNotEqual:
 
546
            case FcOpNotContains:
 
547
                ret = FcStrCmpIgnoreCase (m.u.s, v.u.s) != 0;
 
548
                break;
 
549
            default:
 
550
                break;
 
551
            }
 
552
            break;
 
553
        case FcTypeMatrix:
 
554
            switch (op) {
 
555
            case FcOpEqual:
 
556
            case FcOpContains:
 
557
                ret = FcMatrixEqual (m.u.m, v.u.m);
 
558
                break;
 
559
            case FcOpNotEqual:
 
560
            case FcOpNotContains:
 
561
                ret = !FcMatrixEqual (m.u.m, v.u.m);
 
562
                break;
 
563
            default:
 
564
                break;
 
565
            }
 
566
            break;
 
567
        case FcTypeCharSet:
 
568
            switch (op) {
 
569
            case FcOpContains:
 
570
                /* m contains v if v is a subset of m */
 
571
                ret = FcCharSetIsSubset (v.u.c, m.u.c);
 
572
                break;
 
573
            case FcOpNotContains:
 
574
                /* m contains v if v is a subset of m */
 
575
                ret = !FcCharSetIsSubset (v.u.c, m.u.c);
 
576
                break;
 
577
            case FcOpEqual:
 
578
                ret = FcCharSetEqual (m.u.c, v.u.c);
 
579
                break;
 
580
            case FcOpNotEqual:
 
581
                ret = !FcCharSetEqual (m.u.c, v.u.c);
 
582
                break;
 
583
            default:
 
584
                break;
 
585
            }
 
586
            break;
 
587
        case FcTypeLangSet:
 
588
            switch (op) {
 
589
            case FcOpContains:
 
590
                ret = FcLangSetCompare (v.u.l, m.u.l) != FcLangDifferentLang;
 
591
                break;
 
592
            case FcOpNotContains:
 
593
                ret = FcLangSetCompare (v.u.l, m.u.l) == FcLangDifferentLang;
 
594
                break;
 
595
            case FcOpEqual:
 
596
                ret = FcLangSetEqual (v.u.l, m.u.l);
 
597
                break;
 
598
            case FcOpNotEqual:
 
599
                ret = !FcLangSetEqual (v.u.l, m.u.l);
 
600
                break;
 
601
            default:
 
602
                break;
 
603
            }
 
604
            break;
 
605
        case FcTypeVoid:
 
606
            switch (op) {
 
607
            case FcOpEqual:
 
608
            case FcOpContains:
 
609
                ret = FcTrue;
 
610
                break;
 
611
            default:
 
612
                break;
 
613
            }
 
614
            break;
 
615
        case FcTypeFTFace:
 
616
            switch (op) {
 
617
            case FcOpEqual:
 
618
            case FcOpContains:
 
619
                ret = m.u.f == v.u.f;
 
620
                break;
 
621
            case FcOpNotEqual:
 
622
            case FcOpNotContains:
 
623
                ret = m.u.f != v.u.f;
 
624
                break;
 
625
            default:
 
626
                break;
 
627
            }
 
628
            break;
 
629
        }
 
630
    }
 
631
    else
 
632
    {
 
633
        if (op == FcOpNotEqual || op == FcOpNotContains)
 
634
            ret = FcTrue;
 
635
    }
 
636
    return ret;
 
637
}
 
638
 
 
639
 
 
640
static FcValue
 
641
FcConfigEvaluate (FcPattern *p, FcExpr *e)
 
642
{
 
643
    FcValue     v, vl, vr;
 
644
    FcResult    r;
 
645
    FcMatrix    *m;
 
646
    
 
647
    switch (e->op) {
 
648
    case FcOpInteger:
 
649
        v.type = FcTypeInteger;
 
650
        v.u.i = e->u.ival;
 
651
        break;
 
652
    case FcOpDouble:
 
653
        v.type = FcTypeDouble;
 
654
        v.u.d = e->u.dval;
 
655
        break;
 
656
    case FcOpString:
 
657
        v.type = FcTypeString;
 
658
        v.u.s = e->u.sval;
 
659
        v = FcValueSave (v);
 
660
        break;
 
661
    case FcOpMatrix:
 
662
        v.type = FcTypeMatrix;
 
663
        v.u.m = e->u.mval;
 
664
        v = FcValueSave (v);
 
665
        break;
 
666
    case FcOpCharSet:
 
667
        v.type = FcTypeCharSet;
 
668
        v.u.c = e->u.cval;
 
669
        v = FcValueSave (v);
 
670
        break;
 
671
    case FcOpBool:
 
672
        v.type = FcTypeBool;
 
673
        v.u.b = e->u.bval;
 
674
        break;
 
675
    case FcOpField:
 
676
        r = FcPatternGet (p, e->u.field, 0, &v);
 
677
        if (r != FcResultMatch)
 
678
            v.type = FcTypeVoid;
 
679
        break;
 
680
    case FcOpConst:
 
681
        if (FcNameConstant (e->u.constant, &v.u.i))
 
682
            v.type = FcTypeInteger;
 
683
        else
 
684
            v.type = FcTypeVoid;
 
685
        break;
 
686
    case FcOpQuest:
 
687
        vl = FcConfigEvaluate (p, e->u.tree.left);
 
688
        if (vl.type == FcTypeBool)
 
689
        {
 
690
            if (vl.u.b)
 
691
                v = FcConfigEvaluate (p, e->u.tree.right->u.tree.left);
 
692
            else
 
693
                v = FcConfigEvaluate (p, e->u.tree.right->u.tree.right);
 
694
        }
 
695
        else
 
696
            v.type = FcTypeVoid;
 
697
        FcValueDestroy (vl);
 
698
        break;
 
699
    case FcOpEqual:
 
700
    case FcOpNotEqual:
 
701
    case FcOpLess:
 
702
    case FcOpLessEqual:
 
703
    case FcOpMore:
 
704
    case FcOpMoreEqual:
 
705
    case FcOpContains:
 
706
    case FcOpNotContains:
 
707
        vl = FcConfigEvaluate (p, e->u.tree.left);
 
708
        vr = FcConfigEvaluate (p, e->u.tree.right);
 
709
        v.type = FcTypeBool;
 
710
        v.u.b = FcConfigCompareValue (vl, e->op, vr);
 
711
        FcValueDestroy (vl);
 
712
        FcValueDestroy (vr);
 
713
        break;  
 
714
    case FcOpOr:
 
715
    case FcOpAnd:
 
716
    case FcOpPlus:
 
717
    case FcOpMinus:
 
718
    case FcOpTimes:
 
719
    case FcOpDivide:
 
720
        vl = FcConfigEvaluate (p, e->u.tree.left);
 
721
        vr = FcConfigEvaluate (p, e->u.tree.right);
 
722
        vl = FcConfigPromote (vl, vr);
 
723
        vr = FcConfigPromote (vr, vl);
 
724
        if (vl.type == vr.type)
 
725
        {
 
726
            switch (vl.type) {
 
727
            case FcTypeDouble:
 
728
                switch (e->op) {
 
729
                case FcOpPlus:     
 
730
                    v.type = FcTypeDouble;
 
731
                    v.u.d = vl.u.d + vr.u.d; 
 
732
                    break;
 
733
                case FcOpMinus:
 
734
                    v.type = FcTypeDouble;
 
735
                    v.u.d = vl.u.d - vr.u.d; 
 
736
                    break;
 
737
                case FcOpTimes:
 
738
                    v.type = FcTypeDouble;
 
739
                    v.u.d = vl.u.d * vr.u.d; 
 
740
                    break;
 
741
                case FcOpDivide:
 
742
                    v.type = FcTypeDouble;
 
743
                    v.u.d = vl.u.d / vr.u.d; 
 
744
                    break;
 
745
                default:
 
746
                    v.type = FcTypeVoid; 
 
747
                    break;
 
748
                }
 
749
                if (v.type == FcTypeDouble &&
 
750
                    v.u.d == (double) (int) v.u.d)
 
751
                {
 
752
                    v.type = FcTypeInteger;
 
753
                    v.u.i = (int) v.u.d;
 
754
                }
 
755
                break;
 
756
            case FcTypeBool:
 
757
                switch (e->op) {
 
758
                case FcOpOr:
 
759
                    v.type = FcTypeBool;
 
760
                    v.u.b = vl.u.b || vr.u.b;
 
761
                    break;
 
762
                case FcOpAnd:
 
763
                    v.type = FcTypeBool;
 
764
                    v.u.b = vl.u.b && vr.u.b;
 
765
                    break;
 
766
                default:
 
767
                    v.type = FcTypeVoid; 
 
768
                    break;
 
769
                }
 
770
                break;
 
771
            case FcTypeString:
 
772
                switch (e->op) {
 
773
                case FcOpPlus:
 
774
                    v.type = FcTypeString;
 
775
                    v.u.s = FcStrPlus (vl.u.s, vr.u.s);
 
776
                    if (!v.u.s)
 
777
                        v.type = FcTypeVoid;
 
778
                    break;
 
779
                default:
 
780
                    v.type = FcTypeVoid;
 
781
                    break;
 
782
                }
 
783
                break;
 
784
            case FcTypeMatrix:
 
785
                switch (e->op) {
 
786
                case FcOpTimes:
 
787
                    v.type = FcTypeMatrix;
 
788
                    m = malloc (sizeof (FcMatrix));
 
789
                    if (m)
 
790
                    {
 
791
                        FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix));
 
792
                        FcMatrixMultiply (m, vl.u.m, vr.u.m);
 
793
                        v.u.m = m;
 
794
                    }
 
795
                    else
 
796
                    {
 
797
                        v.type = FcTypeVoid;
 
798
                    }
 
799
                    break;
 
800
                default:
 
801
                    v.type = FcTypeVoid;
 
802
                    break;
 
803
                }
 
804
                break;
 
805
            default:
 
806
                v.type = FcTypeVoid;
 
807
                break;
 
808
            }
 
809
        }
 
810
        else
 
811
            v.type = FcTypeVoid;
 
812
        FcValueDestroy (vl);
 
813
        FcValueDestroy (vr);
 
814
        break;
 
815
    case FcOpNot:
 
816
        vl = FcConfigEvaluate (p, e->u.tree.left);
 
817
        switch (vl.type) {
 
818
        case FcTypeBool:
 
819
            v.type = FcTypeBool;
 
820
            v.u.b = !vl.u.b;
 
821
            break;
 
822
        default:
 
823
            v.type = FcTypeVoid;
 
824
            break;
 
825
        }
 
826
        FcValueDestroy (vl);
 
827
        break;
 
828
    default:
 
829
        v.type = FcTypeVoid;
 
830
        break;
 
831
    }
 
832
    return v;
 
833
}
 
834
 
 
835
static FcValueList *
 
836
FcConfigMatchValueList (FcPattern       *p,
 
837
                        FcTest          *t,
 
838
                        FcValueList     *values)
 
839
{
 
840
    FcValueList     *ret = 0;
 
841
    FcExpr          *e = t->expr;
 
842
    FcValue         value;
 
843
    FcValueList     *v;
 
844
    
 
845
    while (e)
 
846
    {
 
847
        if (e->op == FcOpComma)
 
848
        {
 
849
            value = FcConfigEvaluate (p, e->u.tree.left);
 
850
            e = e->u.tree.right;
 
851
        }
 
852
        else
 
853
        {
 
854
            value = FcConfigEvaluate (p, e);
 
855
            e = 0;
 
856
        }
 
857
 
 
858
        for (v = values; v; v = v->next)
 
859
        {
 
860
            if (FcConfigCompareValue (v->value, t->op, value))
 
861
            {
 
862
                if (!ret)
 
863
                    ret = v;
 
864
            }
 
865
            else
 
866
            {
 
867
                if (t->qual == FcQualAll)
 
868
                {
 
869
                    ret = 0;
 
870
                    break;
 
871
                }
 
872
            }
 
873
        }
 
874
        FcValueDestroy (value);
 
875
    }
 
876
    return ret;
 
877
}
 
878
 
 
879
static FcValueList *
 
880
FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding)
 
881
{
 
882
    FcValueList *l;
 
883
    
 
884
    if (!e)
 
885
        return 0;
 
886
    l = (FcValueList *) malloc (sizeof (FcValueList));
 
887
    if (!l)
 
888
        return 0;
 
889
    FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
 
890
    if (e->op == FcOpComma)
 
891
    {
 
892
        l->value = FcConfigEvaluate (p, e->u.tree.left);
 
893
        l->next  = FcConfigValues (p, e->u.tree.right, binding);
 
894
    }
 
895
    else
 
896
    {
 
897
        l->value = FcConfigEvaluate (p, e);
 
898
        l->next  = 0;
 
899
    }
 
900
    l->binding = binding;
 
901
    while (l && l->value.type == FcTypeVoid)
 
902
    {
 
903
        FcValueList     *next = l->next;
 
904
        
 
905
        FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
 
906
        free (l);
 
907
        l = next;
 
908
    }
 
909
    return l;
 
910
}
 
911
 
 
912
static FcBool
 
913
FcConfigAdd (FcValueList    **head,
 
914
             FcValueList    *position,
 
915
             FcBool         append,
 
916
             FcValueList    *new)
 
917
{
 
918
    FcValueList    **prev, *last;
 
919
    
 
920
    if (append)
 
921
    {
 
922
        if (position)
 
923
            prev = &position->next;
 
924
        else
 
925
            for (prev = head; *prev; prev = &(*prev)->next)
 
926
                ;
 
927
    }
 
928
    else
 
929
    {
 
930
        if (position)
 
931
        {
 
932
            for (prev = head; *prev; prev = &(*prev)->next)
 
933
            {
 
934
                if (*prev == position)
 
935
                    break;
 
936
            }
 
937
        }
 
938
        else
 
939
            prev = head;
 
940
 
 
941
        if (FcDebug () & FC_DBG_EDIT)
 
942
        {
 
943
            if (!*prev)
 
944
                printf ("position not on list\n");
 
945
        }
 
946
    }
 
947
 
 
948
    if (FcDebug () & FC_DBG_EDIT)
 
949
    {
 
950
        printf ("%s list before ", append ? "Append" : "Prepend");
 
951
        FcValueListPrint (*head);
 
952
        printf ("\n");
 
953
    }
 
954
    
 
955
    if (new)
 
956
    {
 
957
        last = new;
 
958
        while (last->next)
 
959
            last = last->next;
 
960
    
 
961
        last->next = *prev;
 
962
        *prev = new;
 
963
    }
 
964
    
 
965
    if (FcDebug () & FC_DBG_EDIT)
 
966
    {
 
967
        printf ("%s list after ", append ? "Append" : "Prepend");
 
968
        FcValueListPrint (*head);
 
969
        printf ("\n");
 
970
    }
 
971
    
 
972
    return FcTrue;
 
973
}
 
974
 
 
975
static void
 
976
FcConfigDel (FcValueList    **head,
 
977
             FcValueList    *position)
 
978
{
 
979
    FcValueList    **prev;
 
980
 
 
981
    for (prev = head; *prev; prev = &(*prev)->next)
 
982
    {
 
983
        if (*prev == position)
 
984
        {
 
985
            *prev = position->next;
 
986
            position->next = 0;
 
987
            FcValueListDestroy (position);
 
988
            break;
 
989
        }
 
990
    }
 
991
}
 
992
 
 
993
static void
 
994
FcConfigPatternAdd (FcPattern   *p,
 
995
                    const char  *object,
 
996
                    FcValueList *list,
 
997
                    FcBool      append)
 
998
{
 
999
    if (list)
 
1000
    {
 
1001
        FcPatternElt    *e = FcPatternInsertElt (p, object);
 
1002
    
 
1003
        if (!e)
 
1004
            return;
 
1005
        FcConfigAdd (&e->values, 0, append, list);
 
1006
    }
 
1007
}
 
1008
 
 
1009
/*
 
1010
 * Delete all values associated with a field
 
1011
 */
 
1012
static void
 
1013
FcConfigPatternDel (FcPattern   *p,
 
1014
                    const char  *object)
 
1015
{
 
1016
    FcPatternElt    *e = FcPatternFindElt (p, object);
 
1017
    if (!e)
 
1018
        return;
 
1019
    while (e->values)
 
1020
        FcConfigDel (&e->values, e->values);
 
1021
}
 
1022
 
 
1023
static void
 
1024
FcConfigPatternCanon (FcPattern     *p,
 
1025
                      const char    *object)
 
1026
{
 
1027
    FcPatternElt    *e = FcPatternFindElt (p, object);
 
1028
    if (!e)
 
1029
        return;
 
1030
    if (!e->values)
 
1031
        FcPatternDel (p, object);
 
1032
}
 
1033
 
 
1034
FcBool
 
1035
FcConfigSubstituteWithPat (FcConfig    *config,
 
1036
                           FcPattern   *p,
 
1037
                           FcPattern   *p_pat,
 
1038
                           FcMatchKind kind)
 
1039
{
 
1040
    FcSubst         *s;
 
1041
    FcSubState      *st;
 
1042
    int             i;
 
1043
    FcTest          *t;
 
1044
    FcEdit          *e;
 
1045
    FcValueList     *l;
 
1046
    FcPattern       *m;
 
1047
 
 
1048
    if (!config)
 
1049
    {
 
1050
        config = FcConfigGetCurrent ();
 
1051
        if (!config)
 
1052
            return FcFalse;
 
1053
    }
 
1054
 
 
1055
    st = (FcSubState *) malloc (config->maxObjects * sizeof (FcSubState));
 
1056
    if (!st && config->maxObjects)
 
1057
        return FcFalse;
 
1058
    FcMemAlloc (FC_MEM_SUBSTATE, config->maxObjects * sizeof (FcSubState));
 
1059
 
 
1060
    if (FcDebug () & FC_DBG_EDIT)
 
1061
    {
 
1062
        printf ("FcConfigSubstitute ");
 
1063
        FcPatternPrint (p);
 
1064
    }
 
1065
    if (kind == FcMatchPattern)
 
1066
        s = config->substPattern;
 
1067
    else
 
1068
        s = config->substFont;
 
1069
    for (; s; s = s->next)
 
1070
    {
 
1071
        /*
 
1072
         * Check the tests to see if
 
1073
         * they all match the pattern
 
1074
         */
 
1075
        for (t = s->test, i = 0; t; t = t->next, i++)
 
1076
        {
 
1077
            if (FcDebug () & FC_DBG_EDIT)
 
1078
            {
 
1079
                printf ("FcConfigSubstitute test ");
 
1080
                FcTestPrint (t);
 
1081
            }
 
1082
            st[i].elt = 0;
 
1083
            if (kind == FcMatchFont && t->kind == FcMatchPattern)
 
1084
                m = p_pat;
 
1085
            else
 
1086
                m = p;
 
1087
            if (m)
 
1088
                st[i].elt = FcPatternFindElt (m, t->field);
 
1089
            else
 
1090
                st[i].elt = 0;
 
1091
            /*
 
1092
             * If there's no such field in the font,
 
1093
             * then FcQualAll matches while FcQualAny does not
 
1094
             */
 
1095
            if (!st[i].elt)
 
1096
            {
 
1097
                if (t->qual == FcQualAll)
 
1098
                {
 
1099
                    st[i].value = 0;
 
1100
                    continue;
 
1101
                }
 
1102
                else
 
1103
                    break;
 
1104
            }
 
1105
            /*
 
1106
             * Check to see if there is a match, mark the location
 
1107
             * to apply match-relative edits
 
1108
             */
 
1109
            st[i].value = FcConfigMatchValueList (m, t, st[i].elt->values);
 
1110
            if (!st[i].value)
 
1111
                break;
 
1112
            if (t->qual == FcQualFirst && st[i].value != st[i].elt->values)
 
1113
                break;
 
1114
            if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values)
 
1115
                break;
 
1116
        }
 
1117
        if (t)
 
1118
        {
 
1119
            if (FcDebug () & FC_DBG_EDIT)
 
1120
                printf ("No match\n");
 
1121
            continue;
 
1122
        }
 
1123
        if (FcDebug () & FC_DBG_EDIT)
 
1124
        {
 
1125
            printf ("Substitute ");
 
1126
            FcSubstPrint (s);
 
1127
        }
 
1128
        for (e = s->edit; e; e = e->next)
 
1129
        {
 
1130
            /*
 
1131
             * Evaluate the list of expressions
 
1132
             */
 
1133
            l = FcConfigValues (p, e->expr, e->binding);
 
1134
            /*
 
1135
             * Locate any test associated with this field, skipping
 
1136
             * tests associated with the pattern when substituting in
 
1137
             * the font
 
1138
             */
 
1139
            for (t = s->test, i = 0; t; t = t->next, i++)
 
1140
            {
 
1141
                if ((t->kind == FcMatchFont || kind == FcMatchPattern) &&
 
1142
                    !FcStrCmpIgnoreCase ((FcChar8 *) t->field, 
 
1143
                                         (FcChar8 *) e->field))
 
1144
                {
 
1145
                    if (!st[i].elt)
 
1146
                        t = 0;
 
1147
                    break;
 
1148
                }
 
1149
            }
 
1150
            switch (e->op) {
 
1151
            case FcOpAssign:
 
1152
                /*
 
1153
                 * If there was a test, then replace the matched
 
1154
                 * value with the new list of values
 
1155
                 */
 
1156
                if (t)
 
1157
                {
 
1158
                    FcValueList *thisValue = st[i].value;
 
1159
                    FcValueList *nextValue = thisValue ? thisValue->next : 0;
 
1160
                    
 
1161
                    /*
 
1162
                     * Append the new list of values after the current value
 
1163
                     */
 
1164
                    FcConfigAdd (&st[i].elt->values, thisValue, FcTrue, l);
 
1165
                    /*
 
1166
                     * Delete the marked value
 
1167
                     */
 
1168
                    FcConfigDel (&st[i].elt->values, thisValue);
 
1169
                    /*
 
1170
                     * Adjust any pointers into the value list to ensure
 
1171
                     * future edits occur at the same place
 
1172
                     */
 
1173
                    for (t = s->test, i = 0; t; t = t->next, i++)
 
1174
                    {
 
1175
                        if (st[i].value == thisValue)
 
1176
                            st[i].value = nextValue;
 
1177
                    }
 
1178
                    break;
 
1179
                }
 
1180
                /* fall through ... */
 
1181
            case FcOpAssignReplace:
 
1182
                /*
 
1183
                 * Delete all of the values and insert
 
1184
                 * the new set
 
1185
                 */
 
1186
                FcConfigPatternDel (p, e->field);
 
1187
                FcConfigPatternAdd (p, e->field, l, FcTrue);
 
1188
                /*
 
1189
                 * Adjust any pointers into the value list as they no
 
1190
                 * longer point to anything valid
 
1191
                 */
 
1192
                if (t)
 
1193
                {
 
1194
                    FcPatternElt    *thisElt = st[i].elt;
 
1195
                    for (t = s->test, i = 0; t; t = t->next, i++)
 
1196
                    {
 
1197
                        if (st[i].elt == thisElt)
 
1198
                            st[i].value = 0;
 
1199
                    }
 
1200
                }
 
1201
                break;
 
1202
            case FcOpPrepend:
 
1203
                if (t)
 
1204
                {
 
1205
                    FcConfigAdd (&st[i].elt->values, st[i].value, FcFalse, l);
 
1206
                    break;
 
1207
                }
 
1208
                /* fall through ... */
 
1209
            case FcOpPrependFirst:
 
1210
                FcConfigPatternAdd (p, e->field, l, FcFalse);
 
1211
                break;
 
1212
            case FcOpAppend:
 
1213
                if (t)
 
1214
                {
 
1215
                    FcConfigAdd (&st[i].elt->values, st[i].value, FcTrue, l);
 
1216
                    break;
 
1217
                }
 
1218
                /* fall through ... */
 
1219
            case FcOpAppendLast:
 
1220
                FcConfigPatternAdd (p, e->field, l, FcTrue);
 
1221
                break;
 
1222
            default:
 
1223
                break;
 
1224
            }
 
1225
        }
 
1226
        /*
 
1227
         * Now go through the pattern and eliminate
 
1228
         * any properties without data
 
1229
         */
 
1230
        for (e = s->edit; e; e = e->next)
 
1231
            FcConfigPatternCanon (p, e->field);
 
1232
 
 
1233
        if (FcDebug () & FC_DBG_EDIT)
 
1234
        {
 
1235
            printf ("FcConfigSubstitute edit");
 
1236
            FcPatternPrint (p);
 
1237
        }
 
1238
    }
 
1239
    FcMemFree (FC_MEM_SUBSTATE, config->maxObjects * sizeof (FcSubState));
 
1240
    free (st);
 
1241
    if (FcDebug () & FC_DBG_EDIT)
 
1242
    {
 
1243
        printf ("FcConfigSubstitute done");
 
1244
        FcPatternPrint (p);
 
1245
    }
 
1246
    return FcTrue;
 
1247
}
 
1248
 
 
1249
FcBool
 
1250
FcConfigSubstitute (FcConfig    *config,
 
1251
                    FcPattern   *p,
 
1252
                    FcMatchKind kind)
 
1253
{
 
1254
    return FcConfigSubstituteWithPat (config, p, 0, kind);
 
1255
}
 
1256
 
 
1257
#ifndef FONTCONFIG_PATH
 
1258
#define FONTCONFIG_PATH "/etc/fonts"
 
1259
#endif
 
1260
 
 
1261
#ifndef FONTCONFIG_FILE
 
1262
#define FONTCONFIG_FILE "fonts.conf"
 
1263
#endif
 
1264
 
 
1265
static FcChar8 *
 
1266
FcConfigFileExists (const FcChar8 *dir, const FcChar8 *file)
 
1267
{
 
1268
    FcChar8    *path;
 
1269
 
 
1270
    if (!dir)
 
1271
        dir = (FcChar8 *) "";
 
1272
    path = malloc (strlen ((char *) dir) + 1 + strlen ((char *) file) + 1);
 
1273
    if (!path)
 
1274
        return 0;
 
1275
 
 
1276
    strcpy ((char *) path, (const char *) dir);
 
1277
    /* make sure there's a single separating / */
 
1278
    if ((!path[0] || path[strlen((char *) path)-1] != '/') && file[0] != '/')
 
1279
        strcat ((char *) path, "/");
 
1280
    strcat ((char *) path, (char *) file);
 
1281
 
 
1282
    FcMemAlloc (FC_MEM_STRING, strlen ((char *) path) + 1);
 
1283
    if (access ((char *) path, R_OK) == 0)
 
1284
        return path;
 
1285
    
 
1286
    FcStrFree (path);
 
1287
    return 0;
 
1288
}
 
1289
 
 
1290
static FcChar8 **
 
1291
FcConfigGetPath (void)
 
1292
{
 
1293
    FcChar8    **path;
 
1294
    FcChar8    *env, *e, *colon;
 
1295
    FcChar8    *dir;
 
1296
    int     npath;
 
1297
    int     i;
 
1298
 
 
1299
    npath = 2;  /* default dir + null */
 
1300
    env = (FcChar8 *) getenv ("FONTCONFIG_PATH");
 
1301
    if (env)
 
1302
    {
 
1303
        e = env;
 
1304
        npath++;
 
1305
        while (*e)
 
1306
            if (*e++ == ':')
 
1307
                npath++;
 
1308
    }
 
1309
    path = calloc (npath, sizeof (FcChar8 *));
 
1310
    if (!path)
 
1311
        goto bail0;
 
1312
    i = 0;
 
1313
 
 
1314
    if (env)
 
1315
    {
 
1316
        e = env;
 
1317
        while (*e) 
 
1318
        {
 
1319
            colon = (FcChar8 *) strchr ((char *) e, ':');
 
1320
            if (!colon)
 
1321
                colon = e + strlen ((char *) e);
 
1322
            path[i] = malloc (colon - e + 1);
 
1323
            if (!path[i])
 
1324
                goto bail1;
 
1325
            strncpy ((char *) path[i], (const char *) e, colon - e);
 
1326
            path[i][colon - e] = '\0';
 
1327
            if (*colon)
 
1328
                e = colon + 1;
 
1329
            else
 
1330
                e = colon;
 
1331
            i++;
 
1332
        }
 
1333
    }
 
1334
    
 
1335
    dir = (FcChar8 *) FONTCONFIG_PATH;
 
1336
    path[i] = malloc (strlen ((char *) dir) + 1);
 
1337
    if (!path[i])
 
1338
        goto bail1;
 
1339
    strcpy ((char *) path[i], (const char *) dir);
 
1340
    return path;
 
1341
 
 
1342
bail1:
 
1343
    for (i = 0; path[i]; i++)
 
1344
        free (path[i]);
 
1345
    free (path);
 
1346
bail0:
 
1347
    return 0;
 
1348
}
 
1349
 
 
1350
static void
 
1351
FcConfigFreePath (FcChar8 **path)
 
1352
{
 
1353
    FcChar8    **p;
 
1354
 
 
1355
    for (p = path; *p; p++)
 
1356
        free (*p);
 
1357
    free (path);
 
1358
}
 
1359
 
 
1360
FcChar8 *
 
1361
FcConfigFilename (const FcChar8 *url)
 
1362
{
 
1363
    FcChar8    *file, *dir, **path, **p;
 
1364
    
 
1365
    if (!url || !*url)
 
1366
    {
 
1367
        url = (FcChar8 *) getenv ("FONTCONFIG_FILE");
 
1368
        if (!url)
 
1369
            url = (FcChar8 *) FONTCONFIG_FILE;
 
1370
    }
 
1371
    file = 0;
 
1372
    switch (*url) {
 
1373
    case '~':
 
1374
        dir = (FcChar8 *) getenv ("HOME");
 
1375
        if (dir)
 
1376
            file = FcConfigFileExists (dir, url + 1);
 
1377
        else
 
1378
            file = 0;
 
1379
        break;
 
1380
    case '/':
 
1381
        file = FcConfigFileExists (0, url);
 
1382
        break;
 
1383
    default:
 
1384
        path = FcConfigGetPath ();
 
1385
        if (!path)
 
1386
            return 0;
 
1387
        for (p = path; *p; p++)
 
1388
        {
 
1389
            file = FcConfigFileExists (*p, url);
 
1390
            if (file)
 
1391
                break;
 
1392
        }
 
1393
        FcConfigFreePath (path);
 
1394
        break;
 
1395
    }
 
1396
    return file;
 
1397
}
 
1398
 
 
1399
/*
 
1400
 * Manage the application-specific fonts
 
1401
 */
 
1402
 
 
1403
FcBool
 
1404
FcConfigAppFontAddFile (FcConfig    *config,
 
1405
                        const FcChar8  *file)
 
1406
{
 
1407
    FcFontSet   *set;
 
1408
    FcStrSet    *subdirs;
 
1409
    FcStrList   *sublist;
 
1410
    FcChar8     *subdir;
 
1411
 
 
1412
    if (!config)
 
1413
    {
 
1414
        config = FcConfigGetCurrent ();
 
1415
        if (!config)
 
1416
            return FcFalse;
 
1417
    }
 
1418
 
 
1419
    subdirs = FcStrSetCreate ();
 
1420
    if (!subdirs)
 
1421
        return FcFalse;
 
1422
    
 
1423
    set = FcConfigGetFonts (config, FcSetApplication);
 
1424
    if (!set)
 
1425
    {
 
1426
        set = FcFontSetCreate ();
 
1427
        if (!set)
 
1428
        {
 
1429
            FcStrSetDestroy (subdirs);
 
1430
            return FcFalse;
 
1431
        }
 
1432
        FcConfigSetFonts (config, set, FcSetApplication);
 
1433
    }
 
1434
        
 
1435
    if (!FcFileScan (set, subdirs, 0, config->blanks, file, FcFalse))
 
1436
    {
 
1437
        FcStrSetDestroy (subdirs);
 
1438
        return FcFalse;
 
1439
    }
 
1440
    if ((sublist = FcStrListCreate (subdirs)))
 
1441
    {
 
1442
        while ((subdir = FcStrListNext (sublist)))
 
1443
        {
 
1444
            FcConfigAppFontAddDir (config, subdir);
 
1445
        }
 
1446
        FcStrListDone (sublist);
 
1447
    }
 
1448
    return FcTrue;
 
1449
}
 
1450
 
 
1451
FcBool
 
1452
FcConfigAppFontAddDir (FcConfig     *config,
 
1453
                       const FcChar8   *dir)
 
1454
{
 
1455
    FcFontSet   *set;
 
1456
    FcStrSet    *subdirs;
 
1457
    FcStrList   *sublist;
 
1458
    FcChar8     *subdir;
 
1459
    
 
1460
    if (!config)
 
1461
    {
 
1462
        config = FcConfigGetCurrent ();
 
1463
        if (!config)
 
1464
            return FcFalse;
 
1465
    }
 
1466
    subdirs = FcStrSetCreate ();
 
1467
    if (!subdirs)
 
1468
        return FcFalse;
 
1469
    
 
1470
    set = FcConfigGetFonts (config, FcSetApplication);
 
1471
    if (!set)
 
1472
    {
 
1473
        set = FcFontSetCreate ();
 
1474
        if (!set)
 
1475
        {
 
1476
            FcStrSetDestroy (subdirs);
 
1477
            return FcFalse;
 
1478
        }
 
1479
        FcConfigSetFonts (config, set, FcSetApplication);
 
1480
    }
 
1481
    
 
1482
    if (!FcDirScan (set, subdirs, 0, config->blanks, dir, FcFalse))
 
1483
    {
 
1484
        FcStrSetDestroy (subdirs);
 
1485
        return FcFalse;
 
1486
    }
 
1487
    if ((sublist = FcStrListCreate (subdirs)))
 
1488
    {
 
1489
        while ((subdir = FcStrListNext (sublist)))
 
1490
        {
 
1491
            FcConfigAppFontAddDir (config, subdir);
 
1492
        }
 
1493
        FcStrListDone (sublist);
 
1494
    }
 
1495
    return FcTrue;
 
1496
}
 
1497
 
 
1498
void
 
1499
FcConfigAppFontClear (FcConfig      *config)
 
1500
{
 
1501
    FcConfigSetFonts (config, 0, FcSetApplication);
 
1502
}