fccfg.c 56.4 KB
Newer Older
Keith Packard's avatar
Keith Packard committed
1
/*
2
 * fontconfig/src/fccfg.c
Keith Packard's avatar
Keith Packard committed
3
 *
4
 * Copyright © 2000 Keith Packard
Keith Packard's avatar
Keith Packard committed
5 6 7 8 9
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
10
 * documentation, and that the name of the author(s) not be used in
Keith Packard's avatar
Keith Packard committed
11
 * advertising or publicity pertaining to distribution of the software without
12
 * specific, written prior permission.  The authors make no
Keith Packard's avatar
Keith Packard committed
13 14 15
 * representations about the suitability of this software for any purpose.  It
 * is provided "as is" without express or implied warranty.
 *
16
 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
Keith Packard's avatar
Keith Packard committed
17
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18
 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
Keith Packard's avatar
Keith Packard committed
19 20 21 22 23 24
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

25 26
/* Objects MT-safe for readonly access. */

27
#include "fcint.h"
28 29
#include <dirent.h>
#include <sys/types.h>
Keith Packard's avatar
Keith Packard committed
30

31 32 33 34
#if defined (_WIN32) && !defined (R_OK)
#define R_OK 4
#endif

35
static FcConfig    *_fcConfig; /* MT-safe */
36

37 38
static FcConfig *
FcConfigEnsure (void)
39 40
{
    FcConfig	*config;
41
retry:
42
    config = fc_atomic_ptr_get (&_fcConfig);
43
    if (!config)
44 45 46 47 48
    {
	config = FcInitLoadConfigAndFonts ();

	if (!fc_atomic_ptr_cmpexch (&_fcConfig, NULL, config)) {
	    FcConfigDestroy (config);
49
	    goto retry;
50 51 52 53 54
	}
    }
    return config;
}

Tom Anderson's avatar
Tom Anderson committed
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
static FcChar32
FcHashAsStrIgnoreCase (const void *data)
{
    return FcStrHashIgnoreCase (data);
}

static int
FcCompareAsStr (const void *v1, const void *v2)
{
    return FcStrCmp (v1, v2);
}

static void
FcDestroyAsRule (void *data)
{
    FcRuleDestroy (data);
}

static void
FcDestroyAsRuleSet (void *data)
{
    FcRuleSetDestroy (data);
}

static void
FcDestroyAsStr (void *data)
{
    FcStrFree (data);
}

85 86 87 88
FcBool
FcConfigInit (void)
{
  return FcConfigEnsure () ? FcTrue : FcFalse;
89 90 91 92 93
}

void
FcConfigFini (void)
{
94 95 96
    FcConfig *cfg = fc_atomic_ptr_get (&_fcConfig);
    if (cfg && fc_atomic_ptr_cmpexch (&_fcConfig, cfg, NULL))
	FcConfigDestroy (cfg);
97 98
}

Keith Packard's avatar
Keith Packard committed
99 100 101 102 103 104

FcConfig *
FcConfigCreate (void)
{
    FcSetName	set;
    FcConfig	*config;
105 106
    FcMatchKind	k;
    FcBool	err = FcFalse;
Keith Packard's avatar
Keith Packard committed
107 108 109 110

    config = malloc (sizeof (FcConfig));
    if (!config)
	goto bail0;
111

112 113
    config->configDirs = FcStrSetCreate ();
    if (!config->configDirs)
Keith Packard's avatar
Keith Packard committed
114
	goto bail1;
115

116
    config->configFiles = FcStrSetCreate ();
Keith Packard's avatar
Keith Packard committed
117 118
    if (!config->configFiles)
	goto bail2;
119

120 121 122
    config->fontDirs = FcStrSetCreate ();
    if (!config->fontDirs)
	goto bail3;
123

124 125 126 127 128 129 130 131
    config->acceptGlobs = FcStrSetCreate ();
    if (!config->acceptGlobs)
	goto bail4;

    config->rejectGlobs = FcStrSetCreate ();
    if (!config->rejectGlobs)
	goto bail5;

132 133 134
    config->acceptPatterns = FcFontSetCreate ();
    if (!config->acceptPatterns)
	goto bail6;
135

136 137 138 139
    config->rejectPatterns = FcFontSetCreate ();
    if (!config->rejectPatterns)
	goto bail7;

140 141
    config->cacheDirs = FcStrSetCreate ();
    if (!config->cacheDirs)
142
	goto bail8;
143

144 145
    for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
    {
Tom Anderson's avatar
Tom Anderson committed
146
	config->subst[k] = FcPtrListCreate (FcDestroyAsRuleSet);
147 148 149 150 151 152
	if (!config->subst[k])
	    err = FcTrue;
    }
    if (err)
	goto bail9;

Keith Packard's avatar
Keith Packard committed
153 154 155
    config->maxObjects = 0;
    for (set = FcSetSystem; set <= FcSetApplication; set++)
	config->fonts[set] = 0;
156 157

    config->rescanTime = time(0);
158
    config->rescanInterval = 30;
159

160 161
    config->expr_pool = NULL;

162 163
    config->sysRoot = NULL;

Tom Anderson's avatar
Tom Anderson committed
164
    config->rulesetList = FcPtrListCreate (FcDestroyAsRuleSet);
165 166 167 168 169 170
    if (!config->rulesetList)
	goto bail9;
    config->availConfigFiles = FcStrSetCreate ();
    if (!config->availConfigFiles)
	goto bail10;

Tom Anderson's avatar
Tom Anderson committed
171 172
    config->uuid_table = FcHashTableCreate (FcHashAsStrIgnoreCase,
					    FcCompareAsStr,
Akira TAGOH's avatar
Akira TAGOH committed
173 174
					    FcHashStrCopy,
					    FcHashUuidCopy,
Tom Anderson's avatar
Tom Anderson committed
175
					    FcDestroyAsStr,
Akira TAGOH's avatar
Akira TAGOH committed
176 177
					    FcHashUuidFree);

178
    FcRefInit (&config->ref, 1);
179

Keith Packard's avatar
Keith Packard committed
180 181
    return config;

182 183 184 185 186 187 188
bail10:
    FcPtrListDestroy (config->rulesetList);
bail9:
    for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
	if (config->subst[k])
	    FcPtrListDestroy (config->subst[k]);
    FcStrSetDestroy (config->cacheDirs);
189 190 191 192
bail8:
    FcFontSetDestroy (config->rejectPatterns);
bail7:
    FcFontSetDestroy (config->acceptPatterns);
193 194 195 196
bail6:
    FcStrSetDestroy (config->rejectGlobs);
bail5:
    FcStrSetDestroy (config->acceptGlobs);
197 198
bail4:
    FcStrSetDestroy (config->fontDirs);
Keith Packard's avatar
Keith Packard committed
199
bail3:
200
    FcStrSetDestroy (config->configFiles);
Keith Packard's avatar
Keith Packard committed
201
bail2:
202
    FcStrSetDestroy (config->configDirs);
Keith Packard's avatar
Keith Packard committed
203 204 205 206 207 208
bail1:
    free (config);
bail0:
    return 0;
}

209
static FcFileTime
210 211 212
FcConfigNewestFile (FcStrSet *files)
{
    FcStrList	    *list = FcStrListCreate (files);
213
    FcFileTime	    newest = { 0, FcFalse };
214 215 216 217 218 219
    FcChar8	    *file;
    struct  stat    statb;

    if (list)
    {
	while ((file = FcStrListNext (list)))
220
	    if (FcStat (file, &statb) == 0)
221
		if (!newest.set || statb.st_mtime - newest.time > 0)
222 223
		{
		    newest.set = FcTrue;
224
		    newest.time = statb.st_mtime;
225
		}
226 227 228 229 230 231 232 233
	FcStrListDone (list);
    }
    return newest;
}

FcBool
FcConfigUptoDate (FcConfig *config)
{
234
    FcFileTime	config_time, config_dir_time, font_time;
235
    time_t	now = time(0);
236 237 238 239 240 241 242
    if (!config)
    {
	config = FcConfigGetCurrent ();
	if (!config)
	    return FcFalse;
    }
    config_time = FcConfigNewestFile (config->configFiles);
243
    config_dir_time = FcConfigNewestFile (config->configDirs);
244
    font_time = FcConfigNewestFile (config->fontDirs);
245
    if ((config_time.set && config_time.time - config->rescanTime > 0) ||
246
	(config_dir_time.set && (config_dir_time.time - config->rescanTime) > 0) ||
247
	(font_time.set && (font_time.time - config->rescanTime) > 0))
248
    {
249 250 251 252 253 254
	/* We need to check for potential clock problems here (OLPC ticket #6046) */
	if ((config_time.set && (config_time.time - now) > 0) ||
    	(config_dir_time.set && (config_dir_time.time - now) > 0) ||
        (font_time.set && (font_time.time - now) > 0))
	{
	    fprintf (stderr,
255
                    "Fontconfig warning: Directory/file mtime in the future. New fonts may not be detected.\n");
256 257 258 259 260
	    config->rescanTime = now;
	    return FcTrue;
	}
	else
	    return FcFalse;
261 262 263 264 265
    }
    config->rescanTime = now;
    return FcTrue;
}

266 267 268
FcExpr *
FcConfigAllocExpr (FcConfig *config)
{
269 270 271 272 273 274 275 276 277 278 279 280
    if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end)
    {
	FcExprPage *new_page;

	new_page = malloc (sizeof (FcExprPage));
	if (!new_page)
	    return 0;

	new_page->next_page = config->expr_pool;
	new_page->next = new_page->exprs;
	config->expr_pool = new_page;
    }
281

282
    return config->expr_pool->next++;
283 284
}

285 286 287 288 289 290 291 292 293 294
FcConfig *
FcConfigReference (FcConfig *config)
{
    if (!config)
    {
	config = FcConfigGetCurrent ();
	if (!config)
	    return 0;
    }

295
    FcRefInc (&config->ref);
296 297 298 299

    return config;
}

Keith Packard's avatar
Keith Packard committed
300 301 302 303
void
FcConfigDestroy (FcConfig *config)
{
    FcSetName	set;
304
    FcExprPage	*page;
305
    FcMatchKind	k;
Keith Packard's avatar
Keith Packard committed
306

307
    if (FcRefDec (&config->ref) != 1)
308 309
	return;

310
    (void) fc_atomic_ptr_cmpexch (&_fcConfig, config, NULL);
311 312 313

    FcStrSetDestroy (config->configDirs);
    FcStrSetDestroy (config->fontDirs);
314
    FcStrSetDestroy (config->cacheDirs);
315
    FcStrSetDestroy (config->configFiles);
316 317
    FcStrSetDestroy (config->acceptGlobs);
    FcStrSetDestroy (config->rejectGlobs);
318 319
    FcFontSetDestroy (config->acceptPatterns);
    FcFontSetDestroy (config->rejectPatterns);
320

321 322 323 324
    for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
	FcPtrListDestroy (config->subst[k]);
    FcPtrListDestroy (config->rulesetList);
    FcStrSetDestroy (config->availConfigFiles);
Keith Packard's avatar
Keith Packard committed
325 326 327
    for (set = FcSetSystem; set <= FcSetApplication; set++)
	if (config->fonts[set])
	    FcFontSetDestroy (config->fonts[set]);
328

329 330 331 332 333 334 335
    page = config->expr_pool;
    while (page)
    {
      FcExprPage *next = page->next_page;
      free (page);
      page = next;
    }
336 337
    if (config->sysRoot)
	FcStrFree (config->sysRoot);
338

Akira TAGOH's avatar
Akira TAGOH committed
339 340
    FcHashTableDestroy (config->uuid_table);

341
    free (config);
Keith Packard's avatar
Keith Packard committed
342 343 344
}

/*
345
 * Add cache to configuration, adding fonts and directories
Keith Packard's avatar
Keith Packard committed
346 347 348
 */

FcBool
349
FcConfigAddCache (FcConfig *config, FcCache *cache,
350
		  FcSetName set, FcStrSet *dirSet, FcChar8 *forDir)
Keith Packard's avatar
Keith Packard committed
351
{
352 353 354
    FcFontSet	*fs;
    intptr_t	*dirs;
    int		i;
355 356 357 358
    FcBool      relocated = FcFalse;

    if (strcmp ((char *)FcCacheDir(cache), (char *)forDir) != 0)
      relocated = FcTrue;
Keith Packard's avatar
Keith Packard committed
359

360 361 362 363 364
    /*
     * Add fonts
     */
    fs = FcCacheSet (cache);
    if (fs)
365
    {
366 367
	int	nref = 0;
	
368
	for (i = 0; i < fs->nfont; i++)
369
	{
370 371
	    FcPattern	*font = FcFontSetFont (fs, i);
	    FcChar8	*font_file;
372
	    FcChar8	*relocated_font_file = NULL;
373 374

	    if (FcPatternObjectGetString (font, FC_FILE_OBJECT,
375
					  0, &font_file) == FcResultMatch)
376
	    {
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
		if (relocated)
		  {
		    FcChar8 *slash = FcStrLastSlash (font_file);
		    relocated_font_file = FcStrBuildFilename (forDir, slash + 1, NULL);
		    font_file = relocated_font_file;
		  }

		/*
		 * Check to see if font is banned by filename
		 */
		if (!FcConfigAcceptFilename (config, font_file))
		{
		    free (relocated_font_file);
		    continue;
		}
392
	    }
393

394 395 396 397
	    /*
	     * Check to see if font is banned by pattern
	     */
	    if (!FcConfigAcceptFont (config, font))
398 399
	    {
		free (relocated_font_file);
400
		continue;
401 402 403 404 405 406 407 408
	    }

	    if (relocated_font_file)
	    {
	      font = FcPatternCacheRewriteFile (font, cache, relocated_font_file);
	      free (relocated_font_file);
	    }

409 410
	    if (FcFontSetAdd (config->fonts[set], font))
		nref++;
411
	}
412
	FcDirCacheReference (cache, nref);
413
    }
414 415 416 417 418 419

    /*
     * Add directories
     */
    dirs = FcCacheDirs (cache);
    if (dirs)
Keith Packard's avatar
Keith Packard committed
420
    {
421 422
	for (i = 0; i < cache->dirs_count; i++)
	{
423 424 425
	    const FcChar8 *dir = FcCacheSubdir (cache, i);
	    FcChar8 *s = NULL;

Alexander Larsson's avatar
Alexander Larsson committed
426
	    if (relocated)
427
	    {
428
		FcChar8 *base = FcStrBasename (dir);
Alexander Larsson's avatar
Alexander Larsson committed
429
		dir = s = FcStrBuildFilename (forDir, base, NULL);
430
		FcStrFree (base);
431
	    }
432
	    if (FcConfigAcceptFilename (config, dir))
433
		FcStrSetAddFilename (dirSet, dir);
434 435
	    if (s)
		FcStrFree (s);
436
	}
437 438 439
    }
    return FcTrue;
}
440

441 442 443 444 445 446
static FcBool
FcConfigAddDirList (FcConfig *config, FcSetName set, FcStrSet *dirSet)
{
    FcStrList	    *dirlist;
    FcChar8	    *dir;
    FcCache	    *cache;
447

448 449 450 451 452 453 454
    dirlist = FcStrListCreate (dirSet);
    if (!dirlist)
        return FcFalse;
	
    while ((dir = FcStrListNext (dirlist)))
    {
	if (FcDebug () & FC_DBG_FONTSET)
455
	    printf ("adding fonts from %s\n", dir);
456 457 458
	cache = FcDirCacheRead (dir, FcFalse, config);
	if (!cache)
	    continue;
459
	FcConfigAddCache (config, cache, set, dirSet, dir);
460 461 462
	FcDirCacheUnload (cache);
    }
    FcStrListDone (dirlist);
463
    return FcTrue;
464 465
}

466 467 468 469
/*
 * Scan the current list of directories in the configuration
 * and build the set of available fonts.
 */
Patrick Lam's avatar
Patrick Lam committed
470

471 472 473 474
FcBool
FcConfigBuildFonts (FcConfig *config)
{
    FcFontSet	    *fonts;
475

476 477 478 479 480
    if (!config)
    {
	config = FcConfigGetCurrent ();
	if (!config)
	    return FcFalse;
Keith Packard's avatar
Keith Packard committed
481
    }
482 483 484
	
    fonts = FcFontSetCreate ();
    if (!fonts)
485
	return FcFalse;
486

487
    FcConfigSetFonts (config, fonts, FcSetSystem);
488

489 490
    if (!FcConfigAddDirList (config, FcSetSystem, config->fontDirs))
	return FcFalse;
Keith Packard's avatar
Keith Packard committed
491 492 493 494 495 496 497 498
    if (FcDebug () & FC_DBG_FONTSET)
	FcFontSetPrint (fonts);
    return FcTrue;
}

FcBool
FcConfigSetCurrent (FcConfig *config)
{
499 500 501 502 503 504
    FcConfig *cfg;

retry:
    cfg = fc_atomic_ptr_get (&_fcConfig);

    if (config == cfg)
505 506
	return FcTrue;

507
    if (config && !config->fonts[FcSetSystem])
Keith Packard's avatar
Keith Packard committed
508 509 510
	if (!FcConfigBuildFonts (config))
	    return FcFalse;

511 512 513
    if (!fc_atomic_ptr_cmpexch (&_fcConfig, cfg, config))
	goto retry;

514
    FcConfigReference (config);
515 516 517
    if (cfg)
	FcConfigDestroy (cfg);

Keith Packard's avatar
Keith Packard committed
518 519 520 521 522 523
    return FcTrue;
}

FcConfig *
FcConfigGetCurrent (void)
{
524
    return FcConfigEnsure ();
Keith Packard's avatar
Keith Packard committed
525 526 527
}

FcBool
528 529
FcConfigAddConfigDir (FcConfig	    *config,
		      const FcChar8 *d)
Keith Packard's avatar
Keith Packard committed
530
{
531 532
    return FcStrSetAddFilename (config->configDirs, d);
}
Keith Packard's avatar
Keith Packard committed
533

534 535 536 537
FcStrList *
FcConfigGetConfigDirs (FcConfig   *config)
{
    if (!config)
Keith Packard's avatar
Keith Packard committed
538
    {
539 540 541
	config = FcConfigGetCurrent ();
	if (!config)
	    return 0;
Keith Packard's avatar
Keith Packard committed
542
    }
543 544 545 546 547 548 549 550
    return FcStrListCreate (config->configDirs);
}

FcBool
FcConfigAddFontDir (FcConfig	    *config,
		    const FcChar8   *d)
{
    return FcStrSetAddFilename (config->fontDirs, d);
Keith Packard's avatar
Keith Packard committed
551 552
}

553 554
FcStrList *
FcConfigGetFontDirs (FcConfig	*config)
Keith Packard's avatar
Keith Packard committed
555 556 557 558 559 560 561
{
    if (!config)
    {
	config = FcConfigGetCurrent ();
	if (!config)
	    return 0;
    }
562
    return FcStrListCreate (config->fontDirs);
Keith Packard's avatar
Keith Packard committed
563 564
}

565 566 567 568 569 570 571 572
FcBool
FcConfigAddCacheDir (FcConfig	    *config,
		     const FcChar8  *d)
{
    return FcStrSetAddFilename (config->cacheDirs, d);
}

FcStrList *
573
FcConfigGetCacheDirs (const FcConfig *config)
574 575 576 577 578 579 580 581 582
{
    if (!config)
    {
	config = FcConfigGetCurrent ();
	if (!config)
	    return 0;
    }
    return FcStrListCreate (config->cacheDirs);
}
583

Keith Packard's avatar
Keith Packard committed
584 585
FcBool
FcConfigAddConfigFile (FcConfig	    *config,
586
		       const FcChar8   *f)
Keith Packard's avatar
Keith Packard committed
587
{
588 589
    FcBool	ret;
    FcChar8	*file = FcConfigFilename (f);
590

Keith Packard's avatar
Keith Packard committed
591 592
    if (!file)
	return FcFalse;
593

594 595 596
    ret = FcStrSetAdd (config->configFiles, file);
    FcStrFree (file);
    return ret;
Keith Packard's avatar
Keith Packard committed
597 598
}

599
FcStrList *
Keith Packard's avatar
Keith Packard committed
600 601 602 603 604 605 606 607
FcConfigGetConfigFiles (FcConfig    *config)
{
    if (!config)
    {
	config = FcConfigGetCurrent ();
	if (!config)
	    return 0;
    }
608
    return FcStrListCreate (config->configFiles);
Keith Packard's avatar
Keith Packard committed
609 610
}

611
FcChar8 *
612
FcConfigGetCache (FcConfig  *config FC_UNUSED)
Keith Packard's avatar
Keith Packard committed
613
{
614
    return NULL;
Keith Packard's avatar
Keith Packard committed
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
}

FcFontSet *
FcConfigGetFonts (FcConfig	*config,
		  FcSetName	set)
{
    if (!config)
    {
	config = FcConfigGetCurrent ();
	if (!config)
	    return 0;
    }
    return config->fonts[set];
}

void
FcConfigSetFonts (FcConfig	*config,
		  FcFontSet	*fonts,
		  FcSetName	set)
{
    if (config->fonts[set])
	FcFontSetDestroy (config->fonts[set]);
    config->fonts[set] = fonts;
}

640 641 642 643 644 645 646 647 648

FcBlanks *
FcBlanksCreate (void)
{
    /* Deprecated. */
    return NULL;
}

void
649
FcBlanksDestroy (FcBlanks *b FC_UNUSED)
650 651 652 653 654
{
    /* Deprecated. */
}

FcBool
655
FcBlanksAdd (FcBlanks *b FC_UNUSED, FcChar32 ucs4 FC_UNUSED)
656 657 658 659 660 661
{
    /* Deprecated. */
    return FcFalse;
}

FcBool
662
FcBlanksIsMember (FcBlanks *b FC_UNUSED, FcChar32 ucs4 FC_UNUSED)
663 664 665 666 667
{
    /* Deprecated. */
    return FcFalse;
}

Keith Packard's avatar
Keith Packard committed
668
FcBlanks *
669
FcConfigGetBlanks (FcConfig	*config FC_UNUSED)
Keith Packard's avatar
Keith Packard committed
670
{
671 672
    /* Deprecated. */
    return NULL;
Keith Packard's avatar
Keith Packard committed
673 674 675
}

FcBool
676 677
FcConfigAddBlank (FcConfig	*config FC_UNUSED,
		  FcChar32    	blank FC_UNUSED)
Keith Packard's avatar
Keith Packard committed
678
{
679 680
    /* Deprecated. */
    return FcFalse;
Keith Packard's avatar
Keith Packard committed
681 682
}

683

684
int
685
FcConfigGetRescanInterval (FcConfig *config)
686 687 688 689 690 691 692 693 694 695 696
{
    if (!config)
    {
	config = FcConfigGetCurrent ();
	if (!config)
	    return 0;
    }
    return config->rescanInterval;
}

FcBool
697
FcConfigSetRescanInterval (FcConfig *config, int rescanInterval)
698 699 700 701 702 703 704 705 706 707 708
{
    if (!config)
    {
	config = FcConfigGetCurrent ();
	if (!config)
	    return FcFalse;
    }
    config->rescanInterval = rescanInterval;
    return FcTrue;
}

709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
/*
 * A couple of typos escaped into the library
 */
int
FcConfigGetRescanInverval (FcConfig *config)
{
    return FcConfigGetRescanInterval (config);
}

FcBool
FcConfigSetRescanInverval (FcConfig *config, int rescanInterval)
{
    return FcConfigSetRescanInterval (config, rescanInterval);
}

Keith Packard's avatar
Keith Packard committed
724
FcBool
725 726
FcConfigAddRule (FcConfig	*config,
		 FcRule		*rule,
Keith Packard's avatar
Keith Packard committed
727 728
		 FcMatchKind	kind)
{
729 730
    /* deprecated */
    return FcFalse;
Keith Packard's avatar
Keith Packard committed
731 732 733
}

static FcValue
734
FcConfigPromote (FcValue v, FcValue u, FcValuePromotionBuffer *buf)
Keith Packard's avatar
Keith Packard committed
735 736 737 738 739 740 741 742
{
    if (v.type == FcTypeInteger)
    {
	v.type = FcTypeDouble;
	v.u.d = (double) v.u.i;
    }
    else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
    {
743
	v.u.m = &FcIdentityMatrix;
744
	v.type = FcTypeMatrix;
Keith Packard's avatar
Keith Packard committed
745
    }
746
    else if (buf && v.type == FcTypeString && u.type == FcTypeLangSet)
747
    {
748
	v.u.l = FcLangSetPromote (v.u.s, buf);
749 750
	v.type = FcTypeLangSet;
    }
751
    else if (buf && v.type == FcTypeVoid && u.type == FcTypeLangSet)
752 753 754 755
    {
	v.u.l = FcLangSetPromote (NULL, buf);
	v.type = FcTypeLangSet;
    }
756
    else if (buf && v.type == FcTypeVoid && u.type == FcTypeCharSet)
757 758 759 760
    {
	v.u.c = FcCharSetPromote (buf);
	v.type = FcTypeCharSet;
    }
761 762 763 764 765
    if (buf && v.type == FcTypeDouble && u.type == FcTypeRange)
    {
	v.u.r = FcRangePromote (v.u.d, buf);
	v.type = FcTypeRange;
    }
Keith Packard's avatar
Keith Packard committed
766 767 768 769
    return v;
}

FcBool
770
FcConfigCompareValue (const FcValue	*left_o,
771
		      unsigned int      op_,
772
		      const FcValue	*right_o)
Keith Packard's avatar
Keith Packard committed
773
{
774 775
    FcValue	left = FcValueCanonicalize(left_o);
    FcValue	right = FcValueCanonicalize(right_o);
776
    FcBool	ret = FcFalse;
777 778
    FcOp	op = FC_OP_GET_OP (op_);
    int		flags = FC_OP_GET_FLAGS (op_);
779
    FcValuePromotionBuffer buf1, buf2;
780

781 782
    left = FcConfigPromote (left, right, &buf1);
    right = FcConfigPromote (right, left, &buf2);
783
    if (left.type == right.type)
Keith Packard's avatar
Keith Packard committed
784
    {
785
	switch (left.type) {
786 787
	case FcTypeUnknown:
	    break;	/* No way to guess how to compare for this object */
Keith Packard's avatar
Keith Packard committed
788 789 790
	case FcTypeInteger:
	    break;	/* FcConfigPromote prevents this from happening */
	case FcTypeDouble:
Behdad Esfahbod's avatar
Behdad Esfahbod committed
791
	    switch ((int) op) {
Keith Packard's avatar
Keith Packard committed
792 793
	    case FcOpEqual:
	    case FcOpContains:
794 795
	    case FcOpListing:
		ret = left.u.d == right.u.d;
Keith Packard's avatar
Keith Packard committed
796
		break;
797 798
	    case FcOpNotEqual:
	    case FcOpNotContains:
799
		ret = left.u.d != right.u.d;
Keith Packard's avatar
Keith Packard committed
800
		break;
801
	    case FcOpLess:
802
		ret = left.u.d < right.u.d;
Keith Packard's avatar
Keith Packard committed
803
		break;
804
	    case FcOpLessEqual:
805
		ret = left.u.d <= right.u.d;
Keith Packard's avatar
Keith Packard committed
806
		break;
807
	    case FcOpMore:
808
		ret = left.u.d > right.u.d;
Keith Packard's avatar
Keith Packard committed
809
		break;
810
	    case FcOpMoreEqual:
811
		ret = left.u.d >= right.u.d;
Keith Packard's avatar
Keith Packard committed
812 813 814 815 816 817
		break;
	    default:
		break;
	    }
	    break;
	case FcTypeBool:
Behdad Esfahbod's avatar
Behdad Esfahbod committed
818
	    switch ((int) op) {
819
	    case FcOpEqual:
820 821
		ret = left.u.b == right.u.b;
		break;
Keith Packard's avatar
Keith Packard committed
822
	    case FcOpContains:
823
	    case FcOpListing:
824
		ret = left.u.b == right.u.b || left.u.b == FcDontCare;
Keith Packard's avatar
Keith Packard committed
825
		break;
826
	    case FcOpNotEqual:
827
		ret = left.u.b != right.u.b;
Keith Packard's avatar
Keith Packard committed
828
		break;
829 830 831
	    case FcOpNotContains:
		ret = !(left.u.b == right.u.b || left.u.b == FcDontCare);
		break;
832 833 834 835 836 837 838 839 840 841 842 843
	    case FcOpLess:
		ret = left.u.b != right.u.b && right.u.b == FcDontCare;
		break;
	    case FcOpLessEqual:
		ret = left.u.b == right.u.b || right.u.b == FcDontCare;
		break;
	    case FcOpMore:
		ret = left.u.b != right.u.b && left.u.b == FcDontCare;
		break;
	    case FcOpMoreEqual:
		ret = left.u.b == right.u.b || left.u.b == FcDontCare;
		break;
Keith Packard's avatar
Keith Packard committed
844 845 846 847 848
	    default:
		break;
	    }
	    break;
	case FcTypeString:
Behdad Esfahbod's avatar
Behdad Esfahbod committed
849
	    switch ((int) op) {
850
	    case FcOpEqual:
851
	    case FcOpListing:
852 853 854 855
		if (flags & FcOpFlagIgnoreBlanks)
		    ret = FcStrCmpIgnoreBlanksAndCase (left.u.s, right.u.s) == 0;
		else
		    ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
Keith Packard's avatar
Keith Packard committed
856
		break;
857
	    case FcOpContains:
858
		ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0;
859
		break;
860
	    case FcOpNotEqual:
861 862 863 864
		if (flags & FcOpFlagIgnoreBlanks)
		    ret = FcStrCmpIgnoreBlanksAndCase (left.u.s, right.u.s) != 0;
		else
		    ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
865
		break;
866
	    case FcOpNotContains:
867
		ret = FcStrStrIgnoreCase (left.u.s, right.u.s) == 0;
868
		break;
Keith Packard's avatar
Keith Packard committed
869 870 871 872 873
	    default:
		break;
	    }
	    break;
	case FcTypeMatrix:
Behdad Esfahbod's avatar
Behdad Esfahbod committed
874
	    switch ((int) op) {
Keith Packard's avatar
Keith Packard committed
875 876
	    case FcOpEqual:
	    case FcOpContains:
877
	    case FcOpListing:
878
		ret = FcMatrixEqual (left.u.m, right.u.m);
Keith Packard's avatar
Keith Packard committed
879 880
		break;
	    case FcOpNotEqual:
881
	    case FcOpNotContains:
882
		ret = !FcMatrixEqual (left.u.m, right.u.m);
Keith Packard's avatar
Keith Packard committed
883 884 885 886 887 888
		break;
	    default:
		break;
	    }
	    break;
	case FcTypeCharSet:
Behdad Esfahbod's avatar
Behdad Esfahbod committed
889
	    switch ((int) op) {
Keith Packard's avatar
Keith Packard committed
890
	    case FcOpContains:
891 892
	    case FcOpListing:
		/* left contains right if right is a subset of left */
893
		ret = FcCharSetIsSubset (right.u.c, left.u.c);
Keith Packard's avatar
Keith Packard committed
894
		break;
895
	    case FcOpNotContains:
896
		/* left contains right if right is a subset of left */
897
		ret = !FcCharSetIsSubset (right.u.c, left.u.c);
898
		break;
Keith Packard's avatar
Keith Packard committed
899
	    case FcOpEqual:
900
		ret = FcCharSetEqual (left.u.c, right.u.c);
Keith Packard's avatar
Keith Packard committed
901 902
		break;
	    case FcOpNotEqual:
903
		ret = !FcCharSetEqual (left.u.c, right.u.c);
Keith Packard's avatar
Keith Packard committed
904 905 906 907 908
		break;
	    default:
		break;
	    }
	    break;
909
	case FcTypeLangSet:
Behdad Esfahbod's avatar
Behdad Esfahbod committed
910
	    switch ((int) op) {
911
	    case FcOpContains:
912
	    case FcOpListing:
913
		ret = FcLangSetContains (left.u.l, right.u.l);
914
		break;
915
	    case FcOpNotContains:
916
		ret = !FcLangSetContains (left.u.l, right.u.l);
917
		break;
918
	    case FcOpEqual:
919
		ret = FcLangSetEqual (left.u.l, right.u.l);
920 921
		break;
	    case FcOpNotEqual:
922
		ret = !FcLangSetEqual (left.u.l, right.u.l);
923 924 925 926 927
		break;
	    default:
		break;
	    }
	    break;
Keith Packard's avatar
Keith Packard committed
928
	case FcTypeVoid:
Behdad Esfahbod's avatar
Behdad Esfahbod committed
929
	    switch ((int) op) {
Keith Packard's avatar
Keith Packard committed
930 931
	    case FcOpEqual:
	    case FcOpContains:
932
	    case FcOpListing:
Keith Packard's avatar
Keith Packard committed
933 934 935 936 937 938
		ret = FcTrue;
		break;
	    default:
		break;
	    }
	    break;
939
	case FcTypeFTFace:
Behdad Esfahbod's avatar
Behdad Esfahbod committed
940
	    switch ((int) op) {
941
	    case FcOpEqual:
942
	    case FcOpContains:
943 944
	    case FcOpListing:
		ret = left.u.f == right.u.f;
945 946
		break;
	    case FcOpNotEqual:
947
	    case FcOpNotContains:
948
		ret = left.u.f != right.u.f;
949 950