2002-02-15 00:34:13 +01:00
|
|
|
/*
|
2008-08-12 22:34:24 +02:00
|
|
|
* fontconfig/src/fcxml.c
|
2002-02-15 00:34:13 +01:00
|
|
|
*
|
2004-12-07 02:14:46 +01:00
|
|
|
* Copyright © 2002 Keith Packard
|
2002-02-15 00:34:13 +01:00
|
|
|
*
|
|
|
|
* 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
|
2010-11-10 22:45:42 +01:00
|
|
|
* documentation, and that the name of the author(s) not be used in
|
2002-02-15 00:34:13 +01:00
|
|
|
* advertising or publicity pertaining to distribution of the software without
|
2010-11-10 22:45:42 +01:00
|
|
|
* specific, written prior permission. The authors make no
|
2002-02-15 00:34:13 +01:00
|
|
|
* representations about the suitability of this software for any purpose. It
|
|
|
|
* is provided "as is" without express or implied warranty.
|
|
|
|
*
|
2009-03-12 21:00:08 +01:00
|
|
|
* THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
2002-02-15 00:34:13 +01:00
|
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
2009-03-12 21:00:08 +01:00
|
|
|
* EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
2002-02-15 00:34:13 +01:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2006-04-25 07:57:41 +02:00
|
|
|
#include "fcint.h"
|
2005-12-21 04:31:19 +01:00
|
|
|
#include <fcntl.h>
|
2002-02-15 00:34:13 +01:00
|
|
|
#include <stdarg.h>
|
2004-12-05 06:03:52 +01:00
|
|
|
#include <dirent.h>
|
2002-05-22 06:37:07 +02:00
|
|
|
|
2006-04-06 06:33:11 +02:00
|
|
|
#ifdef ENABLE_LIBXML2
|
2005-09-29 22:53:30 +02:00
|
|
|
|
|
|
|
#include <libxml/parser.h>
|
|
|
|
|
|
|
|
#define XML_Char xmlChar
|
|
|
|
#define XML_Parser xmlParserCtxtPtr
|
|
|
|
#define XML_ParserFree xmlFreeParserCtxt
|
|
|
|
#define XML_GetCurrentLineNumber xmlSAX2GetLineNumber
|
|
|
|
#define XML_GetErrorCode xmlCtxtGetLastError
|
|
|
|
#define XML_ErrorString(Error) (Error)->message
|
|
|
|
|
|
|
|
#else /* ENABLE_LIBXML2 */
|
|
|
|
|
2002-06-08 19:32:05 +02:00
|
|
|
#ifndef HAVE_XMLPARSE_H
|
|
|
|
#define HAVE_XMLPARSE_H 0
|
|
|
|
#endif
|
2002-08-19 21:32:05 +02:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
#if HAVE_XMLPARSE_H
|
|
|
|
#include <xmlparse.h>
|
|
|
|
#else
|
|
|
|
#include <expat.h>
|
|
|
|
#endif
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2005-09-29 22:53:30 +02:00
|
|
|
#endif /* ENABLE_LIBXML2 */
|
|
|
|
|
2003-03-22 22:25:34 +01:00
|
|
|
#ifdef _WIN32
|
2009-08-13 23:16:18 +02:00
|
|
|
#include <mbstring.h>
|
2003-03-22 22:25:34 +01:00
|
|
|
#endif
|
|
|
|
|
2009-06-06 03:37:01 +02:00
|
|
|
static void
|
|
|
|
FcExprDestroy (FcExpr *e);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
|
|
void
|
|
|
|
FcTestDestroy (FcTest *test)
|
|
|
|
{
|
|
|
|
FcExprDestroy (test->expr);
|
|
|
|
free (test);
|
|
|
|
}
|
|
|
|
|
2013-07-04 12:51:03 +02:00
|
|
|
void
|
|
|
|
FcRuleDestroy (FcRule *rule)
|
|
|
|
{
|
2013-07-09 09:43:26 +02:00
|
|
|
FcRule *n = rule->next;
|
|
|
|
|
2013-07-04 12:51:03 +02:00
|
|
|
switch (rule->type) {
|
|
|
|
case FcRuleTest:
|
|
|
|
FcTestDestroy (rule->u.test);
|
|
|
|
break;
|
|
|
|
case FcRuleEdit:
|
|
|
|
FcEditDestroy (rule->u.edit);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
free (rule);
|
2013-07-09 09:43:26 +02:00
|
|
|
if (n)
|
|
|
|
FcRuleDestroy (n);
|
2013-07-04 12:51:03 +02:00
|
|
|
}
|
|
|
|
|
2009-06-06 00:40:46 +02:00
|
|
|
static FcExpr *
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExprCreateInteger (FcConfig *config, int i)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExpr *e = FcConfigAllocExpr (config);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
e->op = FcOpInteger;
|
|
|
|
e->u.ival = i;
|
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2009-06-06 03:37:01 +02:00
|
|
|
static FcExpr *
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExprCreateDouble (FcConfig *config, double d)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExpr *e = FcConfigAllocExpr (config);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
e->op = FcOpDouble;
|
|
|
|
e->u.dval = d;
|
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2009-06-06 03:37:01 +02:00
|
|
|
static FcExpr *
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExprCreateString (FcConfig *config, const FcChar8 *s)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExpr *e = FcConfigAllocExpr (config);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
e->op = FcOpString;
|
2013-01-02 09:06:15 +01:00
|
|
|
e->u.sval = FcStrdup (s);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2012-12-30 03:39:06 +01:00
|
|
|
static FcExprMatrix *
|
|
|
|
FcExprMatrixCopyShallow (const FcExprMatrix *matrix)
|
|
|
|
{
|
|
|
|
FcExprMatrix *m = malloc (sizeof (FcExprMatrix));
|
|
|
|
if (m)
|
|
|
|
{
|
|
|
|
*m = *matrix;
|
|
|
|
}
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcExprMatrixFreeShallow (FcExprMatrix *m)
|
|
|
|
{
|
|
|
|
if (!m)
|
|
|
|
return;
|
|
|
|
|
|
|
|
free (m);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcExprMatrixFree (FcExprMatrix *m)
|
|
|
|
{
|
|
|
|
if (!m)
|
|
|
|
return;
|
|
|
|
|
|
|
|
FcExprDestroy (m->xx);
|
|
|
|
FcExprDestroy (m->xy);
|
|
|
|
FcExprDestroy (m->yx);
|
|
|
|
FcExprDestroy (m->yy);
|
|
|
|
|
|
|
|
free (m);
|
|
|
|
}
|
|
|
|
|
2009-06-06 03:37:01 +02:00
|
|
|
static FcExpr *
|
2012-12-30 03:39:06 +01:00
|
|
|
FcExprCreateMatrix (FcConfig *config, const FcExprMatrix *matrix)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExpr *e = FcConfigAllocExpr (config);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
e->op = FcOpMatrix;
|
2012-12-30 03:39:06 +01:00
|
|
|
e->u.mexpr = FcExprMatrixCopyShallow (matrix);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2009-06-06 03:37:01 +02:00
|
|
|
static FcExpr *
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExprCreateBool (FcConfig *config, FcBool b)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExpr *e = FcConfigAllocExpr (config);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
e->op = FcOpBool;
|
|
|
|
e->u.bval = b;
|
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2010-12-06 04:10:17 +01:00
|
|
|
static FcExpr *
|
|
|
|
FcExprCreateCharSet (FcConfig *config, FcCharSet *charset)
|
|
|
|
{
|
|
|
|
FcExpr *e = FcConfigAllocExpr (config);
|
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
e->op = FcOpCharSet;
|
|
|
|
e->u.cval = FcCharSetCopy (charset);
|
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2010-12-06 04:38:18 +01:00
|
|
|
static FcExpr *
|
|
|
|
FcExprCreateLangSet (FcConfig *config, FcLangSet *langset)
|
|
|
|
{
|
|
|
|
FcExpr *e = FcConfigAllocExpr (config);
|
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
e->op = FcOpLangSet;
|
|
|
|
e->u.lval = FcLangSetCopy (langset);
|
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2009-06-06 03:37:01 +02:00
|
|
|
static FcExpr *
|
2012-12-30 05:58:38 +01:00
|
|
|
FcExprCreateName (FcConfig *config, FcExprName name)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExpr *e = FcConfigAllocExpr (config);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
e->op = FcOpField;
|
2012-12-30 05:58:38 +01:00
|
|
|
e->u.name = name;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2009-06-06 03:37:01 +02:00
|
|
|
static FcExpr *
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExprCreateConst (FcConfig *config, const FcChar8 *constant)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExpr *e = FcConfigAllocExpr (config);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
e->op = FcOpConst;
|
2013-01-02 09:06:15 +01:00
|
|
|
e->u.constant = FcStrdup (constant);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2009-06-06 03:37:01 +02:00
|
|
|
static FcExpr *
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExprCreateOp (FcConfig *config, FcExpr *left, FcOp op, FcExpr *right)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExpr *e = FcConfigAllocExpr (config);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
e->op = op;
|
|
|
|
e->u.tree.left = left;
|
|
|
|
e->u.tree.right = right;
|
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2009-06-06 03:37:01 +02:00
|
|
|
static void
|
2002-02-15 00:34:13 +01:00
|
|
|
FcExprDestroy (FcExpr *e)
|
|
|
|
{
|
2003-04-16 01:38:06 +02:00
|
|
|
if (!e)
|
|
|
|
return;
|
2012-04-11 12:52:35 +02:00
|
|
|
switch (FC_OP_GET_OP (e->op)) {
|
2002-02-15 00:34:13 +01:00
|
|
|
case FcOpInteger:
|
|
|
|
break;
|
|
|
|
case FcOpDouble:
|
|
|
|
break;
|
|
|
|
case FcOpString:
|
2013-01-02 09:06:15 +01:00
|
|
|
FcFree (e->u.sval);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
case FcOpMatrix:
|
2012-12-30 03:39:06 +01:00
|
|
|
FcExprMatrixFree (e->u.mexpr);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
2010-12-06 04:10:17 +01:00
|
|
|
case FcOpRange:
|
|
|
|
break;
|
2002-02-15 00:34:13 +01:00
|
|
|
case FcOpCharSet:
|
|
|
|
FcCharSetDestroy (e->u.cval);
|
|
|
|
break;
|
2010-12-06 04:38:18 +01:00
|
|
|
case FcOpLangSet:
|
|
|
|
FcLangSetDestroy (e->u.lval);
|
|
|
|
break;
|
2002-02-15 00:34:13 +01:00
|
|
|
case FcOpBool:
|
|
|
|
break;
|
|
|
|
case FcOpField:
|
|
|
|
break;
|
|
|
|
case FcOpConst:
|
2013-01-02 09:06:15 +01:00
|
|
|
FcFree (e->u.constant);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
case FcOpAssign:
|
|
|
|
case FcOpAssignReplace:
|
|
|
|
case FcOpPrepend:
|
|
|
|
case FcOpPrependFirst:
|
|
|
|
case FcOpAppend:
|
|
|
|
case FcOpAppendLast:
|
2013-01-29 12:19:36 +01:00
|
|
|
case FcOpDelete:
|
|
|
|
case FcOpDeleteAll:
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
case FcOpOr:
|
|
|
|
case FcOpAnd:
|
|
|
|
case FcOpEqual:
|
|
|
|
case FcOpNotEqual:
|
|
|
|
case FcOpLess:
|
|
|
|
case FcOpLessEqual:
|
|
|
|
case FcOpMore:
|
|
|
|
case FcOpMoreEqual:
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcOpContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
case FcOpListing:
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcOpNotContains:
|
2002-02-15 00:34:13 +01:00
|
|
|
case FcOpPlus:
|
|
|
|
case FcOpMinus:
|
|
|
|
case FcOpTimes:
|
|
|
|
case FcOpDivide:
|
|
|
|
case FcOpQuest:
|
|
|
|
case FcOpComma:
|
|
|
|
FcExprDestroy (e->u.tree.right);
|
|
|
|
/* fall through */
|
|
|
|
case FcOpNot:
|
2003-04-16 01:38:06 +02:00
|
|
|
case FcOpFloor:
|
|
|
|
case FcOpCeil:
|
|
|
|
case FcOpRound:
|
|
|
|
case FcOpTrunc:
|
2002-02-15 00:34:13 +01:00
|
|
|
FcExprDestroy (e->u.tree.left);
|
|
|
|
break;
|
|
|
|
case FcOpNil:
|
|
|
|
case FcOpInvalid:
|
|
|
|
break;
|
|
|
|
}
|
2009-06-06 04:32:31 +02:00
|
|
|
|
|
|
|
e->op = FcOpNil;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FcEditDestroy (FcEdit *e)
|
|
|
|
{
|
|
|
|
if (e->expr)
|
|
|
|
FcExprDestroy (e->expr);
|
2003-08-15 21:45:20 +02:00
|
|
|
free (e);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
typedef enum _FcElement {
|
|
|
|
FcElementNone,
|
|
|
|
FcElementFontconfig,
|
|
|
|
FcElementDir,
|
2006-08-04 18:13:00 +02:00
|
|
|
FcElementCacheDir,
|
2002-02-18 23:29:28 +01:00
|
|
|
FcElementCache,
|
|
|
|
FcElementInclude,
|
|
|
|
FcElementConfig,
|
|
|
|
FcElementMatch,
|
|
|
|
FcElementAlias,
|
|
|
|
|
|
|
|
FcElementBlank,
|
2002-05-21 19:06:22 +02:00
|
|
|
FcElementRescan,
|
2002-02-18 23:29:28 +01:00
|
|
|
|
|
|
|
FcElementPrefer,
|
|
|
|
FcElementAccept,
|
|
|
|
FcElementDefault,
|
|
|
|
FcElementFamily,
|
|
|
|
|
2003-05-07 18:13:24 +02:00
|
|
|
FcElementSelectfont,
|
|
|
|
FcElementAcceptfont,
|
|
|
|
FcElementRejectfont,
|
|
|
|
FcElementGlob,
|
2004-12-04 20:41:10 +01:00
|
|
|
FcElementPattern,
|
|
|
|
FcElementPatelt,
|
2003-05-07 18:13:24 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
FcElementTest,
|
|
|
|
FcElementEdit,
|
|
|
|
FcElementInt,
|
|
|
|
FcElementDouble,
|
|
|
|
FcElementString,
|
|
|
|
FcElementMatrix,
|
2010-12-06 04:10:17 +01:00
|
|
|
FcElementRange,
|
2002-02-18 23:29:28 +01:00
|
|
|
FcElementBool,
|
2010-12-06 04:10:17 +01:00
|
|
|
FcElementCharSet,
|
2010-12-06 04:38:18 +01:00
|
|
|
FcElementLangSet,
|
2002-02-18 23:29:28 +01:00
|
|
|
FcElementName,
|
|
|
|
FcElementConst,
|
|
|
|
FcElementOr,
|
|
|
|
FcElementAnd,
|
|
|
|
FcElementEq,
|
|
|
|
FcElementNotEq,
|
|
|
|
FcElementLess,
|
|
|
|
FcElementLessEq,
|
|
|
|
FcElementMore,
|
|
|
|
FcElementMoreEq,
|
2002-08-22 20:53:22 +02:00
|
|
|
FcElementContains,
|
|
|
|
FcElementNotContains,
|
2002-02-18 23:29:28 +01:00
|
|
|
FcElementPlus,
|
|
|
|
FcElementMinus,
|
|
|
|
FcElementTimes,
|
|
|
|
FcElementDivide,
|
|
|
|
FcElementNot,
|
|
|
|
FcElementIf,
|
2003-04-16 01:38:06 +02:00
|
|
|
FcElementFloor,
|
|
|
|
FcElementCeil,
|
|
|
|
FcElementRound,
|
|
|
|
FcElementTrunc,
|
2002-02-18 23:29:28 +01:00
|
|
|
FcElementUnknown
|
|
|
|
} FcElement;
|
|
|
|
|
2006-04-06 06:52:21 +02:00
|
|
|
static const struct {
|
2005-09-23 01:45:53 +02:00
|
|
|
const char name[16];
|
|
|
|
FcElement element;
|
|
|
|
} fcElementMap[] = {
|
|
|
|
{ "fontconfig", FcElementFontconfig },
|
|
|
|
{ "dir", FcElementDir },
|
2006-08-04 18:13:00 +02:00
|
|
|
{ "cachedir", FcElementCacheDir },
|
2005-09-23 01:45:53 +02:00
|
|
|
{ "cache", FcElementCache },
|
|
|
|
{ "include", FcElementInclude },
|
|
|
|
{ "config", FcElementConfig },
|
|
|
|
{ "match", FcElementMatch },
|
|
|
|
{ "alias", FcElementAlias },
|
2010-04-12 17:52:09 +02:00
|
|
|
|
2005-09-23 01:45:53 +02:00
|
|
|
{ "blank", FcElementBlank },
|
|
|
|
{ "rescan", FcElementRescan },
|
|
|
|
|
|
|
|
{ "prefer", FcElementPrefer },
|
|
|
|
{ "accept", FcElementAccept },
|
|
|
|
{ "default", FcElementDefault },
|
|
|
|
{ "family", FcElementFamily },
|
|
|
|
|
|
|
|
{ "selectfont", FcElementSelectfont },
|
|
|
|
{ "acceptfont", FcElementAcceptfont },
|
|
|
|
{ "rejectfont", FcElementRejectfont },
|
|
|
|
{ "glob", FcElementGlob },
|
|
|
|
{ "pattern", FcElementPattern },
|
|
|
|
{ "patelt", FcElementPatelt },
|
|
|
|
|
|
|
|
{ "test", FcElementTest },
|
|
|
|
{ "edit", FcElementEdit },
|
|
|
|
{ "int", FcElementInt },
|
|
|
|
{ "double", FcElementDouble },
|
|
|
|
{ "string", FcElementString },
|
|
|
|
{ "matrix", FcElementMatrix },
|
2010-12-06 04:10:17 +01:00
|
|
|
{ "range", FcElementRange },
|
2005-09-23 01:45:53 +02:00
|
|
|
{ "bool", FcElementBool },
|
2010-12-06 04:10:17 +01:00
|
|
|
{ "charset", FcElementCharSet },
|
2010-12-06 04:38:18 +01:00
|
|
|
{ "langset", FcElementLangSet },
|
2005-09-23 01:45:53 +02:00
|
|
|
{ "name", FcElementName },
|
|
|
|
{ "const", FcElementConst },
|
|
|
|
{ "or", FcElementOr },
|
|
|
|
{ "and", FcElementAnd },
|
|
|
|
{ "eq", FcElementEq },
|
|
|
|
{ "not_eq", FcElementNotEq },
|
|
|
|
{ "less", FcElementLess },
|
|
|
|
{ "less_eq", FcElementLessEq },
|
|
|
|
{ "more", FcElementMore },
|
|
|
|
{ "more_eq", FcElementMoreEq },
|
|
|
|
{ "contains", FcElementContains },
|
|
|
|
{ "not_contains", FcElementNotContains },
|
|
|
|
{ "plus", FcElementPlus },
|
|
|
|
{ "minus", FcElementMinus },
|
|
|
|
{ "times", FcElementTimes },
|
|
|
|
{ "divide", FcElementDivide },
|
|
|
|
{ "not", FcElementNot },
|
|
|
|
{ "if", FcElementIf },
|
|
|
|
{ "floor", FcElementFloor },
|
|
|
|
{ "ceil", FcElementCeil },
|
|
|
|
{ "round", FcElementRound },
|
|
|
|
{ "trunc", FcElementTrunc },
|
|
|
|
};
|
|
|
|
#define NUM_ELEMENT_MAPS (int) (sizeof fcElementMap / sizeof fcElementMap[0])
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static FcElement
|
|
|
|
FcElementMap (const XML_Char *name)
|
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
2005-09-23 01:45:53 +02:00
|
|
|
for (i = 0; i < NUM_ELEMENT_MAPS; i++)
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!strcmp ((char *) name, fcElementMap[i].name))
|
|
|
|
return fcElementMap[i].element;
|
|
|
|
return FcElementUnknown;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct _FcPStack {
|
|
|
|
struct _FcPStack *prev;
|
|
|
|
FcElement element;
|
|
|
|
FcChar8 **attr;
|
|
|
|
FcStrBuf str;
|
2009-03-12 17:31:57 +01:00
|
|
|
FcChar8 *attr_buf_static[16];
|
2002-02-18 23:29:28 +01:00
|
|
|
} FcPStack;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
typedef enum _FcVStackTag {
|
|
|
|
FcVStackNone,
|
|
|
|
|
|
|
|
FcVStackString,
|
|
|
|
FcVStackFamily,
|
|
|
|
FcVStackConstant,
|
2003-05-07 18:13:24 +02:00
|
|
|
FcVStackGlob,
|
2012-12-30 05:58:38 +01:00
|
|
|
FcVStackName,
|
2004-12-04 20:41:10 +01:00
|
|
|
FcVStackPattern,
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStackPrefer,
|
|
|
|
FcVStackAccept,
|
|
|
|
FcVStackDefault,
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStackInteger,
|
|
|
|
FcVStackDouble,
|
|
|
|
FcVStackMatrix,
|
2010-12-06 04:10:17 +01:00
|
|
|
FcVStackRange,
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStackBool,
|
2010-12-06 04:10:17 +01:00
|
|
|
FcVStackCharSet,
|
2010-12-06 04:38:18 +01:00
|
|
|
FcVStackLangSet,
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStackTest,
|
|
|
|
FcVStackExpr,
|
|
|
|
FcVStackEdit
|
|
|
|
} FcVStackTag;
|
|
|
|
|
|
|
|
typedef struct _FcVStack {
|
|
|
|
struct _FcVStack *prev;
|
|
|
|
FcPStack *pstack; /* related parse element */
|
|
|
|
FcVStackTag tag;
|
|
|
|
union {
|
|
|
|
FcChar8 *string;
|
|
|
|
|
|
|
|
int integer;
|
|
|
|
double _double;
|
2012-12-30 03:39:06 +01:00
|
|
|
FcExprMatrix *matrix;
|
2010-12-06 04:10:17 +01:00
|
|
|
FcRange range;
|
2008-12-28 09:23:58 +01:00
|
|
|
FcBool bool_;
|
2010-12-06 04:10:17 +01:00
|
|
|
FcCharSet *charset;
|
2010-12-06 04:38:18 +01:00
|
|
|
FcLangSet *langset;
|
2012-12-30 05:58:38 +01:00
|
|
|
FcExprName name;
|
2002-02-18 23:29:28 +01:00
|
|
|
|
|
|
|
FcTest *test;
|
|
|
|
FcQual qual;
|
|
|
|
FcOp op;
|
|
|
|
FcExpr *expr;
|
|
|
|
FcEdit *edit;
|
2004-12-04 20:41:10 +01:00
|
|
|
|
|
|
|
FcPattern *pattern;
|
2002-02-18 23:29:28 +01:00
|
|
|
} u;
|
|
|
|
} FcVStack;
|
|
|
|
|
|
|
|
typedef struct _FcConfigParse {
|
|
|
|
FcPStack *pstack;
|
|
|
|
FcVStack *vstack;
|
|
|
|
FcBool error;
|
|
|
|
const FcChar8 *name;
|
|
|
|
FcConfig *config;
|
|
|
|
XML_Parser parser;
|
2012-12-30 04:47:49 +01:00
|
|
|
unsigned int pstack_static_used;
|
2009-03-12 16:58:04 +01:00
|
|
|
FcPStack pstack_static[8];
|
2012-12-30 04:47:49 +01:00
|
|
|
unsigned int vstack_static_used;
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack vstack_static[64];
|
2002-02-18 23:29:28 +01:00
|
|
|
} FcConfigParse;
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
typedef enum _FcConfigSeverity {
|
|
|
|
FcSevereInfo, FcSevereWarning, FcSevereError
|
|
|
|
} FcConfigSeverity;
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
static void
|
2005-09-23 01:45:53 +02:00
|
|
|
FcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, const char *fmt, ...)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2005-09-23 01:45:53 +02:00
|
|
|
const char *s = "unknown";
|
2002-02-15 00:34:13 +01:00
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start (args, fmt);
|
2002-05-21 19:06:22 +02:00
|
|
|
|
|
|
|
switch (severe) {
|
|
|
|
case FcSevereInfo: s = "info"; break;
|
|
|
|
case FcSevereWarning: s = "warning"; break;
|
|
|
|
case FcSevereError: s = "error"; break;
|
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
if (parse)
|
|
|
|
{
|
|
|
|
if (parse->name)
|
2002-05-21 19:06:22 +02:00
|
|
|
fprintf (stderr, "Fontconfig %s: \"%s\", line %d: ", s,
|
2006-02-05 03:57:21 +01:00
|
|
|
parse->name, (int)XML_GetCurrentLineNumber (parse->parser));
|
2002-02-18 23:29:28 +01:00
|
|
|
else
|
2002-05-21 19:06:22 +02:00
|
|
|
fprintf (stderr, "Fontconfig %s: line %d: ", s,
|
2006-02-05 03:57:21 +01:00
|
|
|
(int)XML_GetCurrentLineNumber (parse->parser));
|
2002-05-21 19:06:22 +02:00
|
|
|
if (severe >= FcSevereError)
|
|
|
|
parse->error = FcTrue;
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
else
|
2002-05-21 19:06:22 +02:00
|
|
|
fprintf (stderr, "Fontconfig %s: ", s);
|
2002-02-15 00:34:13 +01:00
|
|
|
vfprintf (stderr, fmt, args);
|
|
|
|
fprintf (stderr, "\n");
|
|
|
|
va_end (args);
|
|
|
|
}
|
|
|
|
|
2005-01-29 00:55:14 +01:00
|
|
|
|
2012-12-30 03:39:06 +01:00
|
|
|
static FcExpr *
|
|
|
|
FcPopExpr (FcConfigParse *parse);
|
|
|
|
|
|
|
|
|
2005-09-23 01:45:53 +02:00
|
|
|
static const char *
|
2005-01-29 00:55:14 +01:00
|
|
|
FcTypeName (FcType type)
|
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case FcTypeVoid:
|
|
|
|
return "void";
|
|
|
|
case FcTypeInteger:
|
|
|
|
case FcTypeDouble:
|
|
|
|
return "number";
|
|
|
|
case FcTypeString:
|
|
|
|
return "string";
|
|
|
|
case FcTypeBool:
|
|
|
|
return "bool";
|
|
|
|
case FcTypeMatrix:
|
|
|
|
return "matrix";
|
|
|
|
case FcTypeCharSet:
|
|
|
|
return "charset";
|
|
|
|
case FcTypeFTFace:
|
|
|
|
return "FT_Face";
|
|
|
|
case FcTypeLangSet:
|
|
|
|
return "langset";
|
|
|
|
default:
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcTypecheckValue (FcConfigParse *parse, FcType value, FcType type)
|
|
|
|
{
|
|
|
|
if (value == FcTypeInteger)
|
|
|
|
value = FcTypeDouble;
|
|
|
|
if (type == FcTypeInteger)
|
|
|
|
type = FcTypeDouble;
|
|
|
|
if (value != type)
|
|
|
|
{
|
|
|
|
if ((value == FcTypeLangSet && type == FcTypeString) ||
|
|
|
|
(value == FcTypeString && type == FcTypeLangSet))
|
|
|
|
return;
|
2006-09-04 21:46:01 +02:00
|
|
|
if (type == (FcType) -1)
|
|
|
|
return;
|
2012-12-31 02:08:42 +01:00
|
|
|
/* It's perfectly fine to use user-define elements in expressions,
|
|
|
|
* so don't warn in that case. */
|
|
|
|
if (value == (FcType) -1)
|
|
|
|
return;
|
2005-01-29 00:55:14 +01:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "saw %s, expected %s",
|
|
|
|
FcTypeName (value), FcTypeName (type));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type)
|
|
|
|
{
|
|
|
|
const FcObjectType *o;
|
|
|
|
const FcConstant *c;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2007-10-18 14:44:28 +02:00
|
|
|
/* If parsing the expression failed, some nodes may be NULL */
|
|
|
|
if (!expr)
|
|
|
|
return;
|
|
|
|
|
2012-04-11 12:52:35 +02:00
|
|
|
switch (FC_OP_GET_OP (expr->op)) {
|
2005-01-29 00:55:14 +01:00
|
|
|
case FcOpInteger:
|
|
|
|
case FcOpDouble:
|
|
|
|
FcTypecheckValue (parse, FcTypeDouble, type);
|
|
|
|
break;
|
|
|
|
case FcOpString:
|
|
|
|
FcTypecheckValue (parse, FcTypeString, type);
|
|
|
|
break;
|
|
|
|
case FcOpMatrix:
|
|
|
|
FcTypecheckValue (parse, FcTypeMatrix, type);
|
|
|
|
break;
|
|
|
|
case FcOpBool:
|
|
|
|
FcTypecheckValue (parse, FcTypeBool, type);
|
|
|
|
break;
|
|
|
|
case FcOpCharSet:
|
|
|
|
FcTypecheckValue (parse, FcTypeCharSet, type);
|
|
|
|
break;
|
2010-12-06 04:38:18 +01:00
|
|
|
case FcOpLangSet:
|
|
|
|
FcTypecheckValue (parse, FcTypeLangSet, type);
|
|
|
|
break;
|
2005-01-29 00:55:14 +01:00
|
|
|
case FcOpNil:
|
|
|
|
break;
|
|
|
|
case FcOpField:
|
2012-12-30 05:58:38 +01:00
|
|
|
o = FcNameGetObjectType (FcObjectName (expr->u.name.object));
|
2005-01-29 00:55:14 +01:00
|
|
|
if (o)
|
|
|
|
FcTypecheckValue (parse, o->type, type);
|
|
|
|
break;
|
|
|
|
case FcOpConst:
|
|
|
|
c = FcNameGetConstant (expr->u.constant);
|
|
|
|
if (c)
|
|
|
|
{
|
|
|
|
o = FcNameGetObjectType (c->object);
|
|
|
|
if (o)
|
|
|
|
FcTypecheckValue (parse, o->type, type);
|
|
|
|
}
|
2010-04-12 18:10:05 +02:00
|
|
|
else
|
|
|
|
FcConfigMessage (parse, FcSevereWarning,
|
2005-11-17 17:17:05 +01:00
|
|
|
"invalid constant used : %s",
|
|
|
|
expr->u.constant);
|
2005-01-29 00:55:14 +01:00
|
|
|
break;
|
|
|
|
case FcOpQuest:
|
|
|
|
FcTypecheckExpr (parse, expr->u.tree.left, FcTypeBool);
|
|
|
|
FcTypecheckExpr (parse, expr->u.tree.right->u.tree.left, type);
|
|
|
|
FcTypecheckExpr (parse, expr->u.tree.right->u.tree.right, type);
|
|
|
|
break;
|
|
|
|
case FcOpAssign:
|
|
|
|
case FcOpAssignReplace:
|
|
|
|
break;
|
|
|
|
case FcOpEqual:
|
|
|
|
case FcOpNotEqual:
|
|
|
|
case FcOpLess:
|
|
|
|
case FcOpLessEqual:
|
|
|
|
case FcOpMore:
|
|
|
|
case FcOpMoreEqual:
|
|
|
|
case FcOpContains:
|
|
|
|
case FcOpNotContains:
|
|
|
|
case FcOpListing:
|
|
|
|
FcTypecheckValue (parse, FcTypeBool, type);
|
|
|
|
break;
|
|
|
|
case FcOpComma:
|
|
|
|
case FcOpOr:
|
|
|
|
case FcOpAnd:
|
|
|
|
case FcOpPlus:
|
|
|
|
case FcOpMinus:
|
|
|
|
case FcOpTimes:
|
|
|
|
case FcOpDivide:
|
|
|
|
FcTypecheckExpr (parse, expr->u.tree.left, type);
|
|
|
|
FcTypecheckExpr (parse, expr->u.tree.right, type);
|
|
|
|
break;
|
|
|
|
case FcOpNot:
|
|
|
|
FcTypecheckValue (parse, FcTypeBool, type);
|
|
|
|
FcTypecheckExpr (parse, expr->u.tree.left, FcTypeBool);
|
|
|
|
break;
|
|
|
|
case FcOpFloor:
|
|
|
|
case FcOpCeil:
|
|
|
|
case FcOpRound:
|
|
|
|
case FcOpTrunc:
|
|
|
|
FcTypecheckValue (parse, FcTypeDouble, type);
|
|
|
|
FcTypecheckExpr (parse, expr->u.tree.left, FcTypeDouble);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static FcTest *
|
|
|
|
FcTestCreate (FcConfigParse *parse,
|
2010-04-12 18:10:05 +02:00
|
|
|
FcMatchKind kind,
|
2005-01-29 00:55:14 +01:00
|
|
|
FcQual qual,
|
|
|
|
const FcChar8 *field,
|
2013-06-28 08:04:11 +02:00
|
|
|
unsigned int compare,
|
2005-01-29 00:55:14 +01:00
|
|
|
FcExpr *expr)
|
|
|
|
{
|
|
|
|
FcTest *test = (FcTest *) malloc (sizeof (FcTest));
|
|
|
|
|
|
|
|
if (test)
|
|
|
|
{
|
|
|
|
const FcObjectType *o;
|
|
|
|
|
|
|
|
test->kind = kind;
|
|
|
|
test->qual = qual;
|
2006-08-30 13:16:22 +02:00
|
|
|
test->object = FcObjectFromName ((const char *) field);
|
2005-01-29 00:55:14 +01:00
|
|
|
test->op = compare;
|
|
|
|
test->expr = expr;
|
2006-08-30 13:16:22 +02:00
|
|
|
o = FcNameGetObjectType (FcObjectName (test->object));
|
2005-01-29 00:55:14 +01:00
|
|
|
if (o)
|
|
|
|
FcTypecheckExpr (parse, expr, o->type);
|
|
|
|
}
|
|
|
|
return test;
|
|
|
|
}
|
|
|
|
|
|
|
|
static FcEdit *
|
|
|
|
FcEditCreate (FcConfigParse *parse,
|
2006-08-31 06:59:53 +02:00
|
|
|
FcObject object,
|
2005-01-29 00:55:14 +01:00
|
|
|
FcOp op,
|
|
|
|
FcExpr *expr,
|
|
|
|
FcValueBinding binding)
|
|
|
|
{
|
|
|
|
FcEdit *e = (FcEdit *) malloc (sizeof (FcEdit));
|
|
|
|
|
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
const FcObjectType *o;
|
|
|
|
|
2006-08-31 06:59:53 +02:00
|
|
|
e->object = object;
|
2005-01-29 00:55:14 +01:00
|
|
|
e->op = op;
|
|
|
|
e->expr = expr;
|
|
|
|
e->binding = binding;
|
2006-08-30 13:16:22 +02:00
|
|
|
o = FcNameGetObjectType (FcObjectName (e->object));
|
2005-01-29 00:55:14 +01:00
|
|
|
if (o)
|
|
|
|
FcTypecheckExpr (parse, expr, o->type);
|
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2013-07-04 12:51:03 +02:00
|
|
|
static FcRule *
|
|
|
|
FcRuleCreate (FcRuleType type,
|
|
|
|
void *p)
|
|
|
|
{
|
|
|
|
FcRule *r = (FcRule *) malloc (sizeof (FcRule));
|
|
|
|
|
|
|
|
if (!r)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
r->next = NULL;
|
|
|
|
r->type = type;
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case FcRuleTest:
|
|
|
|
r->u.test = (FcTest *) p;
|
|
|
|
break;
|
|
|
|
case FcRuleEdit:
|
|
|
|
r->u.edit = (FcEdit *) p;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
free (r);
|
|
|
|
r = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static FcVStack *
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStackCreateAndPush (FcConfigParse *parse)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStack *new;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2009-03-12 17:22:37 +01:00
|
|
|
if (parse->vstack_static_used < sizeof (parse->vstack_static) / sizeof (parse->vstack_static[0]))
|
|
|
|
new = &parse->vstack_static[parse->vstack_static_used++];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new = malloc (sizeof (FcVStack));
|
|
|
|
if (!new)
|
|
|
|
return 0;
|
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
new->tag = FcVStackNone;
|
|
|
|
new->prev = 0;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2009-03-12 17:22:37 +01:00
|
|
|
new->prev = parse->vstack;
|
|
|
|
new->pstack = parse->pstack ? parse->pstack->prev : 0;
|
|
|
|
parse->vstack = new;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2009-03-12 17:22:37 +01:00
|
|
|
return new;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static FcBool
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStackPushString (FcConfigParse *parse, FcVStackTag tag, FcChar8 *string)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack *vstack = FcVStackCreateAndPush (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!vstack)
|
|
|
|
return FcFalse;
|
|
|
|
vstack->u.string = string;
|
|
|
|
vstack->tag = tag;
|
|
|
|
return FcTrue;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static FcBool
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStackPushInteger (FcConfigParse *parse, int integer)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack *vstack = FcVStackCreateAndPush (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!vstack)
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcFalse;
|
2002-02-18 23:29:28 +01:00
|
|
|
vstack->u.integer = integer;
|
|
|
|
vstack->tag = FcVStackInteger;
|
|
|
|
return FcTrue;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static FcBool
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStackPushDouble (FcConfigParse *parse, double _double)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack *vstack = FcVStackCreateAndPush (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!vstack)
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcFalse;
|
2002-02-18 23:29:28 +01:00
|
|
|
vstack->u._double = _double;
|
|
|
|
vstack->tag = FcVStackDouble;
|
|
|
|
return FcTrue;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static FcBool
|
2012-12-30 03:39:06 +01:00
|
|
|
FcVStackPushMatrix (FcConfigParse *parse, FcExprMatrix *matrix)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack *vstack;
|
|
|
|
vstack = FcVStackCreateAndPush (parse);
|
|
|
|
if (!vstack)
|
|
|
|
return FcFalse;
|
2012-12-30 03:39:06 +01:00
|
|
|
vstack->u.matrix = FcExprMatrixCopyShallow (matrix);
|
2002-02-18 23:29:28 +01:00
|
|
|
vstack->tag = FcVStackMatrix;
|
|
|
|
return FcTrue;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2010-12-06 04:10:17 +01:00
|
|
|
static FcBool
|
|
|
|
FcVStackPushRange (FcConfigParse *parse, FcRange *range)
|
|
|
|
{
|
|
|
|
FcVStack *vstack = FcVStackCreateAndPush (parse);
|
|
|
|
if (!vstack)
|
|
|
|
return FcFalse;
|
|
|
|
vstack->u.range.begin = range->begin;
|
|
|
|
vstack->u.range.end = range->end;
|
|
|
|
vstack->tag = FcVStackRange;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
static FcBool
|
2008-12-28 09:23:58 +01:00
|
|
|
FcVStackPushBool (FcConfigParse *parse, FcBool bool_)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack *vstack = FcVStackCreateAndPush (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!vstack)
|
|
|
|
return FcFalse;
|
2008-12-28 09:23:58 +01:00
|
|
|
vstack->u.bool_ = bool_;
|
2002-02-18 23:29:28 +01:00
|
|
|
vstack->tag = FcVStackBool;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2010-12-06 04:10:17 +01:00
|
|
|
static FcBool
|
|
|
|
FcVStackPushCharSet (FcConfigParse *parse, FcCharSet *charset)
|
|
|
|
{
|
|
|
|
FcVStack *vstack;
|
|
|
|
if (!charset)
|
|
|
|
return FcFalse;
|
|
|
|
vstack = FcVStackCreateAndPush (parse);
|
|
|
|
if (!vstack)
|
|
|
|
return FcFalse;
|
|
|
|
vstack->u.charset = charset;
|
|
|
|
vstack->tag = FcVStackCharSet;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2010-12-06 04:38:18 +01:00
|
|
|
static FcBool
|
|
|
|
FcVStackPushLangSet (FcConfigParse *parse, FcLangSet *langset)
|
|
|
|
{
|
|
|
|
FcVStack *vstack;
|
|
|
|
if (!langset)
|
|
|
|
return FcFalse;
|
|
|
|
vstack = FcVStackCreateAndPush (parse);
|
|
|
|
if (!vstack)
|
|
|
|
return FcFalse;
|
|
|
|
vstack->u.langset = langset;
|
|
|
|
vstack->tag = FcVStackLangSet;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2012-12-30 05:58:38 +01:00
|
|
|
static FcBool
|
|
|
|
FcVStackPushName (FcConfigParse *parse, FcMatchKind kind, FcObject object)
|
|
|
|
{
|
|
|
|
FcVStack *vstack = FcVStackCreateAndPush (parse);
|
|
|
|
if (!vstack)
|
|
|
|
return FcFalse;
|
|
|
|
vstack->u.name.object = object;
|
|
|
|
vstack->u.name.kind = kind;
|
|
|
|
vstack->tag = FcVStackName;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static FcBool
|
|
|
|
FcVStackPushTest (FcConfigParse *parse, FcTest *test)
|
|
|
|
{
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack *vstack = FcVStackCreateAndPush (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!vstack)
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcFalse;
|
2002-02-18 23:29:28 +01:00
|
|
|
vstack->u.test = test;
|
|
|
|
vstack->tag = FcVStackTest;
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
static FcBool
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStackPushExpr (FcConfigParse *parse, FcVStackTag tag, FcExpr *expr)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack *vstack = FcVStackCreateAndPush (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!vstack)
|
|
|
|
return FcFalse;
|
|
|
|
vstack->u.expr = expr;
|
|
|
|
vstack->tag = tag;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static FcBool
|
|
|
|
FcVStackPushEdit (FcConfigParse *parse, FcEdit *edit)
|
|
|
|
{
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack *vstack = FcVStackCreateAndPush (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!vstack)
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcFalse;
|
2002-02-18 23:29:28 +01:00
|
|
|
vstack->u.edit = edit;
|
|
|
|
vstack->tag = FcVStackEdit;
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2004-12-04 20:41:10 +01:00
|
|
|
static FcBool
|
|
|
|
FcVStackPushPattern (FcConfigParse *parse, FcPattern *pattern)
|
|
|
|
{
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack *vstack = FcVStackCreateAndPush (parse);
|
2004-12-04 20:41:10 +01:00
|
|
|
if (!vstack)
|
|
|
|
return FcFalse;
|
|
|
|
vstack->u.pattern = pattern;
|
|
|
|
vstack->tag = FcVStackPattern;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static FcVStack *
|
|
|
|
FcVStackFetch (FcConfigParse *parse, int off)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStack *vstack;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
for (vstack = parse->vstack; vstack && off-- > 0; vstack = vstack->prev);
|
|
|
|
return vstack;
|
|
|
|
}
|
|
|
|
|
2009-03-12 17:22:37 +01:00
|
|
|
static FcVStack *
|
|
|
|
FcVStackPeek (FcConfigParse *parse)
|
2002-02-18 23:29:28 +01:00
|
|
|
{
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack *vstack = parse->vstack;
|
|
|
|
|
|
|
|
return vstack && vstack->pstack == parse->pstack ? vstack : 0;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2009-03-12 17:22:37 +01:00
|
|
|
static void
|
|
|
|
FcVStackPopAndDestroy (FcConfigParse *parse)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStack *vstack = parse->vstack;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!vstack || vstack->pstack != parse->pstack)
|
2009-03-12 17:22:37 +01:00
|
|
|
return;
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
parse->vstack = vstack->prev;
|
2009-03-12 17:22:37 +01:00
|
|
|
|
|
|
|
switch (vstack->tag) {
|
|
|
|
case FcVStackNone:
|
|
|
|
break;
|
2012-12-30 05:58:38 +01:00
|
|
|
case FcVStackName:
|
|
|
|
break;
|
2009-03-12 17:22:37 +01:00
|
|
|
case FcVStackFamily:
|
2009-06-06 04:59:06 +02:00
|
|
|
break;
|
2009-07-20 22:30:12 +02:00
|
|
|
case FcVStackString:
|
2009-03-12 17:22:37 +01:00
|
|
|
case FcVStackConstant:
|
|
|
|
case FcVStackGlob:
|
|
|
|
FcStrFree (vstack->u.string);
|
|
|
|
break;
|
|
|
|
case FcVStackPattern:
|
|
|
|
FcPatternDestroy (vstack->u.pattern);
|
|
|
|
break;
|
|
|
|
case FcVStackInteger:
|
|
|
|
case FcVStackDouble:
|
|
|
|
break;
|
|
|
|
case FcVStackMatrix:
|
2012-12-30 03:39:06 +01:00
|
|
|
FcExprMatrixFreeShallow (vstack->u.matrix);
|
2009-03-12 17:22:37 +01:00
|
|
|
break;
|
2010-12-06 04:10:17 +01:00
|
|
|
case FcVStackRange:
|
2009-03-12 17:22:37 +01:00
|
|
|
case FcVStackBool:
|
|
|
|
break;
|
2010-12-06 04:10:17 +01:00
|
|
|
case FcVStackCharSet:
|
|
|
|
FcCharSetDestroy (vstack->u.charset);
|
|
|
|
break;
|
2010-12-06 04:38:18 +01:00
|
|
|
case FcVStackLangSet:
|
|
|
|
FcLangSetDestroy (vstack->u.langset);
|
|
|
|
break;
|
2009-03-12 17:22:37 +01:00
|
|
|
case FcVStackTest:
|
|
|
|
FcTestDestroy (vstack->u.test);
|
|
|
|
break;
|
|
|
|
case FcVStackExpr:
|
|
|
|
case FcVStackPrefer:
|
|
|
|
case FcVStackAccept:
|
|
|
|
case FcVStackDefault:
|
|
|
|
FcExprDestroy (vstack->u.expr);
|
|
|
|
break;
|
|
|
|
case FcVStackEdit:
|
|
|
|
FcEditDestroy (vstack->u.edit);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vstack == &parse->vstack_static[parse->vstack_static_used - 1])
|
|
|
|
parse->vstack_static_used--;
|
|
|
|
else
|
|
|
|
free (vstack);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcVStackClear (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
while (FcVStackPeek (parse))
|
|
|
|
FcVStackPopAndDestroy (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
FcVStackElements (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
int h = 0;
|
|
|
|
FcVStack *vstack = parse->vstack;
|
|
|
|
while (vstack && vstack->pstack == parse->pstack)
|
|
|
|
{
|
|
|
|
h++;
|
|
|
|
vstack = vstack->prev;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
return h;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static FcChar8 **
|
2009-03-12 17:31:57 +01:00
|
|
|
FcConfigSaveAttr (const XML_Char **attr, FcChar8 **buf, int size_bytes)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
int slen;
|
|
|
|
int i;
|
|
|
|
FcChar8 **new;
|
|
|
|
FcChar8 *s;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!attr)
|
|
|
|
return 0;
|
|
|
|
slen = 0;
|
|
|
|
for (i = 0; attr[i]; i++)
|
2005-11-18 21:32:30 +01:00
|
|
|
slen += strlen ((char *) attr[i]) + 1;
|
2009-03-12 14:27:20 +01:00
|
|
|
if (i == 0)
|
|
|
|
return 0;
|
2009-03-12 17:31:57 +01:00
|
|
|
slen += (i + 1) * sizeof (FcChar8 *);
|
|
|
|
if (slen <= size_bytes)
|
|
|
|
new = buf;
|
|
|
|
else
|
2009-03-12 14:27:20 +01:00
|
|
|
{
|
2009-03-12 17:31:57 +01:00
|
|
|
new = malloc (slen);
|
|
|
|
if (!new)
|
|
|
|
{
|
|
|
|
FcConfigMessage (0, FcSevereError, "out of memory");
|
|
|
|
return 0;
|
|
|
|
}
|
2009-03-12 14:27:20 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
s = (FcChar8 *) (new + (i + 1));
|
|
|
|
for (i = 0; attr[i]; i++)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
new[i] = s;
|
|
|
|
strcpy ((char *) s, (char *) attr[i]);
|
|
|
|
s += strlen ((char *) s) + 1;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
new[i] = 0;
|
|
|
|
return new;
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static FcBool
|
|
|
|
FcPStackPush (FcConfigParse *parse, FcElement element, const XML_Char **attr)
|
|
|
|
{
|
2009-03-12 16:58:04 +01:00
|
|
|
FcPStack *new;
|
|
|
|
|
|
|
|
if (parse->pstack_static_used < sizeof (parse->pstack_static) / sizeof (parse->pstack_static[0]))
|
|
|
|
new = &parse->pstack_static[parse->pstack_static_used++];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new = malloc (sizeof (FcPStack));
|
|
|
|
if (!new)
|
|
|
|
return FcFalse;
|
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
|
|
|
|
new->prev = parse->pstack;
|
|
|
|
new->element = element;
|
2009-03-12 17:31:57 +01:00
|
|
|
new->attr = FcConfigSaveAttr (attr, new->attr_buf_static, sizeof (new->attr_buf_static));
|
2002-02-18 23:29:28 +01:00
|
|
|
FcStrBufInit (&new->str, 0, 0);
|
|
|
|
parse->pstack = new;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static FcBool
|
|
|
|
FcPStackPop (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
FcPStack *old;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
|
|
|
if (!parse->pstack)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "mismatching element");
|
2002-02-18 23:29:28 +01:00
|
|
|
return FcFalse;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2013-01-02 08:31:34 +01:00
|
|
|
|
|
|
|
if (parse->pstack->attr)
|
|
|
|
{
|
|
|
|
/* Warn about unused attrs. */
|
|
|
|
FcChar8 **attrs = parse->pstack->attr;
|
|
|
|
while (*attrs)
|
|
|
|
{
|
|
|
|
if (attrs[0][0])
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "invalid attribute '%s'", attrs[0]);
|
|
|
|
}
|
|
|
|
attrs += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStackClear (parse);
|
|
|
|
old = parse->pstack;
|
|
|
|
parse->pstack = old->prev;
|
|
|
|
FcStrBufDestroy (&old->str);
|
2013-01-02 08:31:34 +01:00
|
|
|
|
2009-03-12 17:31:57 +01:00
|
|
|
if (old->attr && old->attr != old->attr_buf_static)
|
2002-02-18 23:29:28 +01:00
|
|
|
free (old->attr);
|
2009-03-12 16:58:04 +01:00
|
|
|
|
|
|
|
if (old == &parse->pstack_static[parse->pstack_static_used - 1])
|
|
|
|
parse->pstack_static_used--;
|
|
|
|
else
|
|
|
|
free (old);
|
2002-02-18 23:29:28 +01:00
|
|
|
return FcTrue;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static FcBool
|
2012-10-07 22:37:03 +02:00
|
|
|
FcConfigParseInit (FcConfigParse *parse, const FcChar8 *name, FcConfig *config, XML_Parser parser)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
parse->pstack = 0;
|
2009-03-12 16:58:04 +01:00
|
|
|
parse->pstack_static_used = 0;
|
2002-02-18 23:29:28 +01:00
|
|
|
parse->vstack = 0;
|
2009-03-12 17:22:37 +01:00
|
|
|
parse->vstack_static_used = 0;
|
2002-02-18 23:29:28 +01:00
|
|
|
parse->error = FcFalse;
|
|
|
|
parse->name = name;
|
|
|
|
parse->config = config;
|
|
|
|
parse->parser = parser;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcConfigCleanup (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
while (parse->pstack)
|
|
|
|
FcPStackPop (parse);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const FcChar8 *
|
2005-09-23 01:45:53 +02:00
|
|
|
FcConfigGetAttribute (FcConfigParse *parse, const char *attr)
|
2002-02-18 23:29:28 +01:00
|
|
|
{
|
|
|
|
FcChar8 **attrs;
|
|
|
|
if (!parse->pstack)
|
2002-02-15 00:34:13 +01:00
|
|
|
return 0;
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
attrs = parse->pstack->attr;
|
2005-12-12 14:20:41 +01:00
|
|
|
if (!attrs)
|
|
|
|
return 0;
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
while (*attrs)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!strcmp ((char *) *attrs, attr))
|
2013-01-02 08:31:34 +01:00
|
|
|
{
|
|
|
|
attrs[0][0] = '\0'; /* Mark as used. */
|
2002-02-18 23:29:28 +01:00
|
|
|
return attrs[1];
|
2013-01-02 08:31:34 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
attrs += 2;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static void
|
|
|
|
FcStartElement(void *userData, const XML_Char *name, const XML_Char **attr)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
FcConfigParse *parse = userData;
|
|
|
|
FcElement element;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
element = FcElementMap (name);
|
|
|
|
if (element == FcElementUnknown)
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "unknown element \"%s\"", name);
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!FcPStackPush (parse, element, attr))
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
return;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
return;
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static void
|
|
|
|
FcParseBlank (FcConfigParse *parse)
|
|
|
|
{
|
2010-12-06 04:18:23 +01:00
|
|
|
int n = FcVStackElements (parse);
|
|
|
|
FcChar32 i;
|
2002-02-18 23:29:28 +01:00
|
|
|
while (n-- > 0)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStack *v = FcVStackFetch (parse, n);
|
2010-12-06 04:18:23 +01:00
|
|
|
if (!parse->config->blanks)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2010-12-06 04:18:23 +01:00
|
|
|
parse->config->blanks = FcBlanksCreate ();
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!parse->config->blanks)
|
2010-12-06 04:18:23 +01:00
|
|
|
goto bail;
|
|
|
|
}
|
2012-12-30 04:11:09 +01:00
|
|
|
switch ((int) v->tag) {
|
2010-12-06 04:18:23 +01:00
|
|
|
case FcVStackInteger:
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!FcBlanksAdd (parse->config->blanks, v->u.integer))
|
2010-12-06 04:18:23 +01:00
|
|
|
goto bail;
|
|
|
|
break;
|
|
|
|
case FcVStackRange:
|
2010-12-28 09:55:31 +01:00
|
|
|
if (v->u.range.begin <= v->u.range.end)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2010-12-28 09:55:31 +01:00
|
|
|
for (i = v->u.range.begin; i <= v->u.range.end; i++)
|
|
|
|
{
|
|
|
|
if (!FcBlanksAdd (parse->config->blanks, i))
|
|
|
|
goto bail;
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2010-12-06 04:18:23 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FcConfigMessage (parse, FcSevereError, "invalid element in blank");
|
|
|
|
break;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
}
|
2010-12-06 04:18:23 +01:00
|
|
|
return;
|
|
|
|
bail:
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
static void
|
|
|
|
FcParseRescan (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
int n = FcVStackElements (parse);
|
|
|
|
while (n-- > 0)
|
|
|
|
{
|
|
|
|
FcVStack *v = FcVStackFetch (parse, n);
|
|
|
|
if (v->tag != FcVStackInteger)
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "non-integer rescan");
|
|
|
|
else
|
|
|
|
parse->config->rescanInterval = v->u.integer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static void
|
|
|
|
FcParseInt (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
FcChar8 *s, *end;
|
|
|
|
int l;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!parse->pstack)
|
|
|
|
return;
|
2009-03-11 19:07:15 +01:00
|
|
|
s = FcStrBufDoneStatic (&parse->pstack->str);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!s)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
return;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
end = 0;
|
|
|
|
l = (int) strtol ((char *) s, (char **)&end, 0);
|
|
|
|
if (end != s + strlen ((char *) s))
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid integer", s);
|
2002-02-18 23:29:28 +01:00
|
|
|
else
|
|
|
|
FcVStackPushInteger (parse, l);
|
2009-03-11 19:07:15 +01:00
|
|
|
FcStrBufDestroy (&parse->pstack->str);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2002-06-26 18:11:29 +02:00
|
|
|
/*
|
2010-04-12 18:10:05 +02:00
|
|
|
* idea copied from glib g_ascii_strtod with
|
|
|
|
* permission of the author (Alexander Larsson)
|
2002-06-26 18:11:29 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <locale.h>
|
|
|
|
|
2010-04-12 18:10:05 +02:00
|
|
|
static double
|
2002-06-26 18:11:29 +02:00
|
|
|
FcStrtod (char *s, char **end)
|
|
|
|
{
|
|
|
|
struct lconv *locale_data;
|
|
|
|
char *dot;
|
|
|
|
double v;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Have to swap the decimal point to match the current locale
|
|
|
|
* if that locale doesn't use 0x2e
|
|
|
|
*/
|
|
|
|
if ((dot = strchr (s, 0x2e)) &&
|
|
|
|
(locale_data = localeconv ()) &&
|
|
|
|
(locale_data->decimal_point[0] != 0x2e ||
|
|
|
|
locale_data->decimal_point[1] != 0))
|
|
|
|
{
|
|
|
|
char buf[128];
|
|
|
|
int slen = strlen (s);
|
|
|
|
int dlen = strlen (locale_data->decimal_point);
|
|
|
|
|
2005-09-23 01:45:53 +02:00
|
|
|
if (slen + dlen > (int) sizeof (buf))
|
2002-06-26 18:11:29 +02:00
|
|
|
{
|
|
|
|
if (end)
|
|
|
|
*end = s;
|
|
|
|
v = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *buf_end;
|
|
|
|
/* mantissa */
|
|
|
|
strncpy (buf, s, dot - s);
|
|
|
|
/* decimal point */
|
|
|
|
strcpy (buf + (dot - s), locale_data->decimal_point);
|
|
|
|
/* rest of number */
|
|
|
|
strcpy (buf + (dot - s) + dlen, dot + 1);
|
|
|
|
buf_end = 0;
|
|
|
|
v = strtod (buf, &buf_end);
|
2003-11-10 18:34:36 +01:00
|
|
|
if (buf_end) {
|
|
|
|
buf_end = s + (buf_end - buf);
|
|
|
|
if (buf_end > dot)
|
|
|
|
buf_end -= dlen - 1;
|
|
|
|
}
|
2002-06-26 18:11:29 +02:00
|
|
|
if (end)
|
|
|
|
*end = buf_end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
v = strtod (s, end);
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static void
|
|
|
|
FcParseDouble (FcConfigParse *parse)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
FcChar8 *s, *end;
|
|
|
|
double d;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!parse->pstack)
|
|
|
|
return;
|
2009-03-11 19:07:15 +01:00
|
|
|
s = FcStrBufDoneStatic (&parse->pstack->str);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!s)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
return;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
end = 0;
|
2002-06-26 18:11:29 +02:00
|
|
|
d = FcStrtod ((char *) s, (char **)&end);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (end != s + strlen ((char *) s))
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid double", s);
|
2002-02-15 00:34:13 +01:00
|
|
|
else
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStackPushDouble (parse, d);
|
2009-03-11 19:07:15 +01:00
|
|
|
FcStrBufDestroy (&parse->pstack->str);
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static void
|
|
|
|
FcParseString (FcConfigParse *parse, FcVStackTag tag)
|
|
|
|
{
|
|
|
|
FcChar8 *s;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!parse->pstack)
|
|
|
|
return;
|
|
|
|
s = FcStrBufDone (&parse->pstack->str);
|
|
|
|
if (!s)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!FcVStackPushString (parse, tag, s))
|
|
|
|
FcStrFree (s);
|
|
|
|
}
|
|
|
|
|
2012-12-30 05:58:38 +01:00
|
|
|
static void
|
|
|
|
FcParseName (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
const FcChar8 *kind_string;
|
|
|
|
FcMatchKind kind;
|
|
|
|
FcChar8 *s;
|
|
|
|
FcObject object;
|
|
|
|
|
|
|
|
kind_string = FcConfigGetAttribute (parse, "target");
|
|
|
|
if (!kind_string)
|
|
|
|
kind = FcMatchDefault;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!strcmp ((char *) kind_string, "pattern"))
|
|
|
|
kind = FcMatchPattern;
|
|
|
|
else if (!strcmp ((char *) kind_string, "font"))
|
|
|
|
kind = FcMatchFont;
|
|
|
|
else if (!strcmp ((char *) kind_string, "default"))
|
|
|
|
kind = FcMatchDefault;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "invalid name target \"%s\"", kind_string);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!parse->pstack)
|
|
|
|
return;
|
|
|
|
s = FcStrBufDone (&parse->pstack->str);
|
|
|
|
if (!s)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
object = FcObjectFromName ((const char *) s);
|
|
|
|
|
|
|
|
FcVStackPushName (parse, kind, object);
|
|
|
|
|
|
|
|
FcStrFree (s);
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static void
|
|
|
|
FcParseMatrix (FcConfigParse *parse)
|
|
|
|
{
|
2012-12-30 03:39:06 +01:00
|
|
|
FcExprMatrix m;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2012-12-30 03:39:06 +01:00
|
|
|
m.yy = FcPopExpr (parse);
|
|
|
|
m.yx = FcPopExpr (parse);
|
|
|
|
m.xy = FcPopExpr (parse);
|
|
|
|
m.xx = FcPopExpr (parse);
|
|
|
|
|
|
|
|
if (FcPopExpr (parse))
|
|
|
|
FcConfigMessage (parse, FcSevereError, "wrong number of matrix elements");
|
2002-02-18 23:29:28 +01:00
|
|
|
else
|
2012-12-30 03:39:06 +01:00
|
|
|
FcVStackPushMatrix (parse, &m);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2010-12-06 04:10:17 +01:00
|
|
|
static void
|
|
|
|
FcParseRange (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
FcVStack *vstack;
|
2013-01-03 00:35:56 +01:00
|
|
|
FcRange r = {0, 0};
|
2010-12-06 04:10:17 +01:00
|
|
|
FcChar32 n;
|
|
|
|
int count = 1;
|
|
|
|
|
|
|
|
while ((vstack = FcVStackPeek (parse)))
|
|
|
|
{
|
|
|
|
if (count < 0)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "too many elements in range");
|
|
|
|
return;
|
|
|
|
}
|
2012-12-30 04:11:09 +01:00
|
|
|
switch ((int) vstack->tag) {
|
2010-12-06 04:10:17 +01:00
|
|
|
case FcVStackInteger:
|
|
|
|
n = vstack->u.integer;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FcConfigMessage (parse, FcSevereError, "invalid element in range");
|
2012-06-01 12:06:17 +02:00
|
|
|
n = 0;
|
2010-12-06 04:10:17 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (count == 1)
|
|
|
|
r.end = n;
|
|
|
|
else
|
|
|
|
r.begin = n;
|
|
|
|
count--;
|
|
|
|
FcVStackPopAndDestroy (parse);
|
|
|
|
}
|
|
|
|
if (count < 0)
|
|
|
|
{
|
|
|
|
if (r.begin > r.end)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "invalid range");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
FcVStackPushRange (parse, &r);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
FcConfigMessage (parse, FcSevereError, "invalid range");
|
|
|
|
}
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
static FcBool
|
2008-12-28 09:23:58 +01:00
|
|
|
FcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool_)
|
2002-02-18 23:29:28 +01:00
|
|
|
{
|
2005-01-29 00:55:14 +01:00
|
|
|
FcBool result = FcFalse;
|
|
|
|
|
2008-12-28 09:23:58 +01:00
|
|
|
if (!FcNameBool (bool_, &result))
|
2005-01-29 00:55:14 +01:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "\"%s\" is not known boolean",
|
2008-12-28 09:23:58 +01:00
|
|
|
bool_);
|
2005-01-29 00:55:14 +01:00
|
|
|
return result;
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcParseBool (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
FcChar8 *s;
|
|
|
|
|
|
|
|
if (!parse->pstack)
|
|
|
|
return;
|
2009-03-11 19:07:15 +01:00
|
|
|
s = FcStrBufDoneStatic (&parse->pstack->str);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!s)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-01-29 00:55:14 +01:00
|
|
|
FcVStackPushBool (parse, FcConfigLexBool (parse, s));
|
2009-03-11 19:07:15 +01:00
|
|
|
FcStrBufDestroy (&parse->pstack->str);
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
|
2010-12-06 04:10:17 +01:00
|
|
|
static void
|
|
|
|
FcParseCharSet (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
FcVStack *vstack;
|
|
|
|
FcCharSet *charset = FcCharSetCreate ();
|
|
|
|
FcChar32 i;
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
while ((vstack = FcVStackPeek (parse)))
|
|
|
|
{
|
2012-12-30 04:11:09 +01:00
|
|
|
switch ((int) vstack->tag) {
|
2010-12-06 04:10:17 +01:00
|
|
|
case FcVStackInteger:
|
|
|
|
if (!FcCharSetAddChar (charset, vstack->u.integer))
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "invalid character: 0x%04x", vstack->u.integer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
n++;
|
|
|
|
break;
|
|
|
|
case FcVStackRange:
|
2010-12-28 09:55:31 +01:00
|
|
|
if (vstack->u.range.begin <= vstack->u.range.end)
|
2010-12-06 04:10:17 +01:00
|
|
|
{
|
2010-12-28 09:55:31 +01:00
|
|
|
for (i = vstack->u.range.begin; i <= vstack->u.range.end; i++)
|
|
|
|
{
|
|
|
|
if (!FcCharSetAddChar (charset, i))
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "invalid character: 0x%04x", i);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
n++;
|
|
|
|
}
|
2010-12-06 04:10:17 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FcConfigMessage (parse, FcSevereError, "invalid element in charset");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
FcVStackPopAndDestroy (parse);
|
|
|
|
}
|
|
|
|
if (n > 0)
|
|
|
|
FcVStackPushCharSet (parse, charset);
|
|
|
|
else
|
|
|
|
FcCharSetDestroy (charset);
|
|
|
|
}
|
|
|
|
|
2010-12-06 04:38:18 +01:00
|
|
|
static void
|
|
|
|
FcParseLangSet (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
FcVStack *vstack;
|
|
|
|
FcLangSet *langset = FcLangSetCreate ();
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
while ((vstack = FcVStackPeek (parse)))
|
|
|
|
{
|
2012-12-30 04:11:09 +01:00
|
|
|
switch ((int) vstack->tag) {
|
2010-12-06 04:38:18 +01:00
|
|
|
case FcVStackString:
|
|
|
|
if (!FcLangSetAdd (langset, vstack->u.string))
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "invalid langset: %s", vstack->u.string);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
n++;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FcConfigMessage (parse, FcSevereError, "invalid element in langset");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
FcVStackPopAndDestroy (parse);
|
|
|
|
}
|
|
|
|
if (n > 0)
|
|
|
|
FcVStackPushLangSet (parse, langset);
|
|
|
|
else
|
|
|
|
FcLangSetDestroy (langset);
|
|
|
|
}
|
|
|
|
|
2007-10-26 07:30:49 +02:00
|
|
|
static FcBool
|
|
|
|
FcConfigLexBinding (FcConfigParse *parse,
|
|
|
|
const FcChar8 *binding_string,
|
|
|
|
FcValueBinding *binding_ret)
|
|
|
|
{
|
|
|
|
FcValueBinding binding;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2007-10-26 07:30:49 +02:00
|
|
|
if (!binding_string)
|
|
|
|
binding = FcValueBindingWeak;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!strcmp ((char *) binding_string, "weak"))
|
|
|
|
binding = FcValueBindingWeak;
|
|
|
|
else if (!strcmp ((char *) binding_string, "strong"))
|
|
|
|
binding = FcValueBindingStrong;
|
|
|
|
else if (!strcmp ((char *) binding_string, "same"))
|
|
|
|
binding = FcValueBindingSame;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "invalid binding \"%s\"", binding_string);
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*binding_ret = binding;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static void
|
|
|
|
FcParseFamilies (FcConfigParse *parse, FcVStackTag tag)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStack *vstack;
|
|
|
|
FcExpr *left, *expr = 0, *new;
|
|
|
|
|
2009-03-12 17:22:37 +01:00
|
|
|
while ((vstack = FcVStackPeek (parse)))
|
2002-02-18 23:29:28 +01:00
|
|
|
{
|
|
|
|
if (vstack->tag != FcVStackFamily)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "non-family");
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStackPopAndDestroy (parse);
|
2002-05-21 19:06:22 +02:00
|
|
|
continue;
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
left = vstack->u.expr;
|
|
|
|
vstack->tag = FcVStackNone;
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStackPopAndDestroy (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (expr)
|
|
|
|
{
|
2009-06-06 04:32:31 +02:00
|
|
|
new = FcExprCreateOp (parse->config, left, FcOpComma, expr);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!new)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
FcExprDestroy (left);
|
|
|
|
FcExprDestroy (expr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
expr = new;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
expr = left;
|
|
|
|
}
|
|
|
|
if (expr)
|
|
|
|
{
|
|
|
|
if (!FcVStackPushExpr (parse, tag, expr))
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2006-02-21 16:50:19 +01:00
|
|
|
FcExprDestroy (expr);
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcParseFamily (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
FcChar8 *s;
|
|
|
|
FcExpr *expr;
|
|
|
|
|
|
|
|
if (!parse->pstack)
|
|
|
|
return;
|
2009-03-11 19:07:15 +01:00
|
|
|
s = FcStrBufDoneStatic (&parse->pstack->str);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!s)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
return;
|
|
|
|
}
|
2009-06-06 04:32:31 +02:00
|
|
|
expr = FcExprCreateString (parse->config, s);
|
2009-03-11 19:07:15 +01:00
|
|
|
FcStrBufDestroy (&parse->pstack->str);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (expr)
|
|
|
|
FcVStackPushExpr (parse, FcVStackFamily, expr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcParseAlias (FcConfigParse *parse)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0;
|
2013-07-04 12:51:03 +02:00
|
|
|
FcEdit *edit = 0;
|
2002-02-18 23:29:28 +01:00
|
|
|
FcVStack *vstack;
|
2013-07-04 12:51:03 +02:00
|
|
|
FcRule *rule = NULL, *r;
|
2007-10-26 07:30:49 +02:00
|
|
|
FcValueBinding binding;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2007-10-26 07:30:49 +02:00
|
|
|
if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
|
|
|
|
return;
|
2009-03-12 17:22:37 +01:00
|
|
|
while ((vstack = FcVStackPeek (parse)))
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2012-12-30 04:11:09 +01:00
|
|
|
switch ((int) vstack->tag) {
|
2002-02-18 23:29:28 +01:00
|
|
|
case FcVStackFamily:
|
|
|
|
if (family)
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
2012-08-16 13:33:12 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "Having multiple <family> in <alias> isn't supported and may not work as expected");
|
2009-06-06 04:32:31 +02:00
|
|
|
new = FcExprCreateOp (parse->config, vstack->u.expr, FcOpComma, family);
|
2002-05-21 19:06:22 +02:00
|
|
|
if (!new)
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
|
|
|
else
|
|
|
|
family = new;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
new = vstack->u.expr;
|
|
|
|
if (new)
|
|
|
|
{
|
|
|
|
family = new;
|
|
|
|
vstack->tag = FcVStackNone;
|
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcVStackPrefer:
|
|
|
|
if (prefer)
|
|
|
|
FcExprDestroy (prefer);
|
|
|
|
prefer = vstack->u.expr;
|
|
|
|
vstack->tag = FcVStackNone;
|
|
|
|
break;
|
|
|
|
case FcVStackAccept:
|
|
|
|
if (accept)
|
|
|
|
FcExprDestroy (accept);
|
|
|
|
accept = vstack->u.expr;
|
|
|
|
vstack->tag = FcVStackNone;
|
|
|
|
break;
|
|
|
|
case FcVStackDefault:
|
|
|
|
if (def)
|
|
|
|
FcExprDestroy (def);
|
|
|
|
def = vstack->u.expr;
|
|
|
|
vstack->tag = FcVStackNone;
|
|
|
|
break;
|
2012-04-04 07:47:57 +02:00
|
|
|
case FcVStackTest:
|
2013-07-04 12:51:03 +02:00
|
|
|
if (rule)
|
|
|
|
{
|
|
|
|
r = FcRuleCreate (FcRuleTest, vstack->u.test);
|
|
|
|
r->next = rule;
|
|
|
|
rule = r;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rule = FcRuleCreate (FcRuleTest, vstack->u.test);
|
2012-04-04 07:47:57 +02:00
|
|
|
vstack->tag = FcVStackNone;
|
|
|
|
break;
|
2002-02-18 23:29:28 +01:00
|
|
|
default:
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "bad alias");
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
}
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStackPopAndDestroy (parse);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-15 07:01:28 +01:00
|
|
|
if (!family)
|
2002-02-18 23:29:28 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "missing family in alias");
|
|
|
|
if (prefer)
|
|
|
|
FcExprDestroy (prefer);
|
|
|
|
if (accept)
|
|
|
|
FcExprDestroy (accept);
|
|
|
|
if (def)
|
|
|
|
FcExprDestroy (def);
|
2013-07-04 12:51:03 +02:00
|
|
|
if (rule)
|
|
|
|
FcRuleDestroy (rule);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!prefer &&
|
|
|
|
!accept &&
|
|
|
|
!def)
|
|
|
|
{
|
|
|
|
FcExprDestroy (family);
|
2002-02-18 23:29:28 +01:00
|
|
|
return;
|
|
|
|
}
|
2013-07-04 12:51:03 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
FcTest *t = FcTestCreate (parse, FcMatchPattern,
|
|
|
|
FcQualAny,
|
|
|
|
(FcChar8 *) FC_FAMILY,
|
|
|
|
FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks),
|
|
|
|
family);
|
|
|
|
if (rule)
|
|
|
|
{
|
|
|
|
for (r = rule; r->next; r = r->next);
|
|
|
|
r->next = FcRuleCreate (FcRuleTest, t);
|
|
|
|
r = r->next;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
r = rule = FcRuleCreate (FcRuleTest, t);
|
|
|
|
}
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
if (prefer)
|
|
|
|
{
|
2010-04-12 18:10:05 +02:00
|
|
|
edit = FcEditCreate (parse,
|
2006-08-31 06:59:53 +02:00
|
|
|
FC_FAMILY_OBJECT,
|
2002-02-15 00:34:13 +01:00
|
|
|
FcOpPrepend,
|
2002-07-31 03:36:37 +02:00
|
|
|
prefer,
|
2007-10-26 07:30:49 +02:00
|
|
|
binding);
|
2013-07-04 12:51:03 +02:00
|
|
|
if (!edit)
|
2002-02-18 23:29:28 +01:00
|
|
|
FcExprDestroy (prefer);
|
2013-07-04 12:51:03 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
r->next = FcRuleCreate (FcRuleEdit, edit);
|
|
|
|
r = r->next;
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
if (accept)
|
|
|
|
{
|
2005-01-29 00:55:14 +01:00
|
|
|
edit = FcEditCreate (parse,
|
2006-08-31 06:59:53 +02:00
|
|
|
FC_FAMILY_OBJECT,
|
2002-02-15 00:34:13 +01:00
|
|
|
FcOpAppend,
|
2002-07-31 03:36:37 +02:00
|
|
|
accept,
|
2007-10-26 07:30:49 +02:00
|
|
|
binding);
|
2013-07-04 12:51:03 +02:00
|
|
|
if (!edit)
|
2002-02-18 23:29:28 +01:00
|
|
|
FcExprDestroy (accept);
|
2013-07-04 12:51:03 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
r->next = FcRuleCreate (FcRuleEdit, edit);
|
|
|
|
r = r->next;
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
if (def)
|
|
|
|
{
|
2005-01-29 00:55:14 +01:00
|
|
|
edit = FcEditCreate (parse,
|
2006-08-31 06:59:53 +02:00
|
|
|
FC_FAMILY_OBJECT,
|
2002-07-31 03:36:37 +02:00
|
|
|
FcOpAppendLast,
|
|
|
|
def,
|
2007-10-26 07:30:49 +02:00
|
|
|
binding);
|
2013-07-04 12:51:03 +02:00
|
|
|
if (!edit)
|
2002-02-18 23:29:28 +01:00
|
|
|
FcExprDestroy (def);
|
2013-07-04 12:51:03 +02:00
|
|
|
else
|
2012-04-04 07:47:57 +02:00
|
|
|
{
|
2013-07-04 12:51:03 +02:00
|
|
|
r->next = FcRuleCreate (FcRuleEdit, edit);
|
|
|
|
r = r->next;
|
2012-04-04 07:47:57 +02:00
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2013-07-04 12:51:03 +02:00
|
|
|
if (!FcConfigAddRule (parse->config, rule, FcMatchPattern))
|
|
|
|
FcRuleDestroy (rule);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static FcExpr *
|
|
|
|
FcPopExpr (FcConfigParse *parse)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack *vstack = FcVStackPeek (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
FcExpr *expr = 0;
|
|
|
|
if (!vstack)
|
|
|
|
return 0;
|
2012-12-30 04:11:09 +01:00
|
|
|
switch ((int) vstack->tag) {
|
2002-02-18 23:29:28 +01:00
|
|
|
case FcVStackNone:
|
|
|
|
break;
|
|
|
|
case FcVStackString:
|
|
|
|
case FcVStackFamily:
|
2009-06-06 04:32:31 +02:00
|
|
|
expr = FcExprCreateString (parse->config, vstack->u.string);
|
2002-02-22 19:54:07 +01:00
|
|
|
break;
|
2012-12-30 05:58:38 +01:00
|
|
|
case FcVStackName:
|
|
|
|
expr = FcExprCreateName (parse->config, vstack->u.name);
|
2002-02-22 19:54:07 +01:00
|
|
|
break;
|
2002-02-18 23:29:28 +01:00
|
|
|
case FcVStackConstant:
|
2009-06-06 04:32:31 +02:00
|
|
|
expr = FcExprCreateConst (parse->config, vstack->u.string);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
2003-08-15 21:45:20 +02:00
|
|
|
case FcVStackGlob:
|
|
|
|
/* XXX: What's the correct action here? (CDW) */
|
|
|
|
break;
|
2002-02-18 23:29:28 +01:00
|
|
|
case FcVStackPrefer:
|
|
|
|
case FcVStackAccept:
|
|
|
|
case FcVStackDefault:
|
|
|
|
expr = vstack->u.expr;
|
|
|
|
vstack->tag = FcVStackNone;
|
|
|
|
break;
|
|
|
|
case FcVStackInteger:
|
2009-06-06 04:32:31 +02:00
|
|
|
expr = FcExprCreateInteger (parse->config, vstack->u.integer);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcVStackDouble:
|
2009-06-06 04:32:31 +02:00
|
|
|
expr = FcExprCreateDouble (parse->config, vstack->u._double);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcVStackMatrix:
|
2009-06-06 04:32:31 +02:00
|
|
|
expr = FcExprCreateMatrix (parse->config, vstack->u.matrix);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
2010-12-06 04:10:17 +01:00
|
|
|
case FcVStackRange:
|
|
|
|
break;
|
2002-02-18 23:29:28 +01:00
|
|
|
case FcVStackBool:
|
2009-06-06 04:32:31 +02:00
|
|
|
expr = FcExprCreateBool (parse->config, vstack->u.bool_);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
2010-12-06 04:10:17 +01:00
|
|
|
case FcVStackCharSet:
|
|
|
|
expr = FcExprCreateCharSet (parse->config, vstack->u.charset);
|
|
|
|
break;
|
2010-12-06 04:38:18 +01:00
|
|
|
case FcVStackLangSet:
|
|
|
|
expr = FcExprCreateLangSet (parse->config, vstack->u.langset);
|
|
|
|
break;
|
2002-02-18 23:29:28 +01:00
|
|
|
case FcVStackTest:
|
|
|
|
break;
|
|
|
|
case FcVStackExpr:
|
|
|
|
expr = vstack->u.expr;
|
2002-06-02 21:51:36 +02:00
|
|
|
vstack->tag = FcVStackNone;
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcVStackEdit:
|
|
|
|
break;
|
2004-12-04 20:41:10 +01:00
|
|
|
default:
|
|
|
|
break;
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStackPopAndDestroy (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2003-04-16 01:38:06 +02:00
|
|
|
/*
|
|
|
|
* This builds a tree of binary operations. Note
|
|
|
|
* that every operator is defined so that if only
|
|
|
|
* a single operand is contained, the value of the
|
|
|
|
* whole expression is the value of the operand.
|
|
|
|
*
|
|
|
|
* This code reduces in that case to returning that
|
|
|
|
* operand.
|
|
|
|
*/
|
2002-02-18 23:29:28 +01:00
|
|
|
static FcExpr *
|
2003-04-16 01:38:06 +02:00
|
|
|
FcPopBinary (FcConfigParse *parse, FcOp op)
|
2002-02-18 23:29:28 +01:00
|
|
|
{
|
|
|
|
FcExpr *left, *expr = 0, *new;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
while ((left = FcPopExpr (parse)))
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
if (expr)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2009-06-06 04:32:31 +02:00
|
|
|
new = FcExprCreateOp (parse->config, left, op, expr);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!new)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
FcExprDestroy (left);
|
|
|
|
FcExprDestroy (expr);
|
2006-04-11 18:54:24 +02:00
|
|
|
return 0;
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
expr = new;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
else
|
|
|
|
expr = left;
|
|
|
|
}
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (FcConfigParse *parse, FcOp op)
|
|
|
|
{
|
|
|
|
FcExpr *expr = FcPopBinary (parse, op);
|
|
|
|
if (expr)
|
|
|
|
FcVStackPushExpr (parse, FcVStackExpr, expr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This builds a a unary operator, it consumes only
|
|
|
|
* a single operand
|
|
|
|
*/
|
|
|
|
|
|
|
|
static FcExpr *
|
|
|
|
FcPopUnary (FcConfigParse *parse, FcOp op)
|
|
|
|
{
|
|
|
|
FcExpr *operand, *new = 0;
|
|
|
|
|
|
|
|
if ((operand = FcPopExpr (parse)))
|
|
|
|
{
|
2009-06-06 04:32:31 +02:00
|
|
|
new = FcExprCreateOp (parse->config, operand, op, 0);
|
2003-04-16 01:38:06 +02:00
|
|
|
if (!new)
|
|
|
|
{
|
|
|
|
FcExprDestroy (operand);
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcParseUnary (FcConfigParse *parse, FcOp op)
|
2002-02-18 23:29:28 +01:00
|
|
|
{
|
2003-04-16 01:38:06 +02:00
|
|
|
FcExpr *expr = FcPopUnary (parse, op);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (expr)
|
|
|
|
FcVStackPushExpr (parse, FcVStackExpr, expr);
|
|
|
|
}
|
|
|
|
|
2012-03-12 11:18:19 +01:00
|
|
|
static void
|
|
|
|
FcParseDir (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
const FcChar8 *attr, *data;
|
2012-12-07 11:09:36 +01:00
|
|
|
FcChar8 *prefix = NULL, *p;
|
2012-06-11 13:13:02 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
FcChar8 buffer[1000];
|
|
|
|
#endif
|
2012-03-12 11:18:19 +01:00
|
|
|
|
|
|
|
attr = FcConfigGetAttribute (parse, "prefix");
|
|
|
|
if (attr && FcStrCmp (attr, (const FcChar8 *)"xdg") == 0)
|
|
|
|
prefix = FcConfigXdgDataHome ();
|
|
|
|
data = FcStrBufDoneStatic (&parse->pstack->str);
|
|
|
|
if (!data)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2012-12-11 04:38:42 +01:00
|
|
|
data = prefix;
|
2012-03-12 11:18:19 +01:00
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
if (prefix)
|
|
|
|
{
|
|
|
|
size_t plen = strlen ((const char *)prefix);
|
|
|
|
size_t dlen = strlen ((const char *)data);
|
|
|
|
|
2012-12-07 11:09:36 +01:00
|
|
|
p = realloc (prefix, plen + 1 + dlen + 1);
|
|
|
|
if (!p)
|
2012-03-12 11:18:19 +01:00
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
|
|
|
goto bail;
|
|
|
|
}
|
2012-12-07 11:09:36 +01:00
|
|
|
prefix = p;
|
2012-03-12 11:18:19 +01:00
|
|
|
prefix[plen] = FC_DIR_SEPARATOR;
|
|
|
|
memcpy (&prefix[plen + 1], data, dlen);
|
|
|
|
prefix[plen + 1 + dlen] = 0;
|
|
|
|
data = prefix;
|
|
|
|
}
|
|
|
|
#ifdef _WIN32
|
2012-06-13 13:01:30 +02:00
|
|
|
if (strcmp ((const char *) data, "CUSTOMFONTDIR") == 0)
|
2012-03-12 11:18:19 +01:00
|
|
|
{
|
2013-01-03 00:35:56 +01:00
|
|
|
FcChar8 *p;
|
2012-03-12 11:18:19 +01:00
|
|
|
data = buffer;
|
2012-06-13 13:01:30 +02:00
|
|
|
if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
|
2012-03-12 11:18:19 +01:00
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
|
2012-06-11 13:13:02 +02:00
|
|
|
goto bail;
|
2012-03-12 11:18:19 +01:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Must use the multi-byte aware function to search
|
|
|
|
* for backslash because East Asian double-byte code
|
|
|
|
* pages have characters with backslash as the second
|
|
|
|
* byte.
|
|
|
|
*/
|
|
|
|
p = _mbsrchr (data, '\\');
|
|
|
|
if (p) *p = '\0';
|
2013-01-03 00:35:56 +01:00
|
|
|
strcat ((char *) data, "\\fonts");
|
2012-03-12 11:18:19 +01:00
|
|
|
}
|
2012-06-13 13:01:30 +02:00
|
|
|
else if (strcmp ((const char *) data, "APPSHAREFONTDIR") == 0)
|
2012-03-12 11:18:19 +01:00
|
|
|
{
|
2013-01-03 00:35:56 +01:00
|
|
|
FcChar8 *p;
|
2012-03-12 11:18:19 +01:00
|
|
|
data = buffer;
|
2012-06-13 13:01:30 +02:00
|
|
|
if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
|
2012-03-12 11:18:19 +01:00
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
|
2012-06-11 13:13:02 +02:00
|
|
|
goto bail;
|
2012-03-12 11:18:19 +01:00
|
|
|
}
|
|
|
|
p = _mbsrchr (data, '\\');
|
|
|
|
if (p) *p = '\0';
|
2013-01-03 00:35:56 +01:00
|
|
|
strcat ((char *) data, "\\..\\share\\fonts");
|
2012-03-12 11:18:19 +01:00
|
|
|
}
|
2012-06-13 13:01:30 +02:00
|
|
|
else if (strcmp ((const char *) data, "WINDOWSFONTDIR") == 0)
|
2012-03-12 11:18:19 +01:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
data = buffer;
|
2012-06-13 13:01:30 +02:00
|
|
|
rc = pGetSystemWindowsDirectory ((LPSTR) buffer, sizeof (buffer) - 20);
|
2012-03-12 11:18:19 +01:00
|
|
|
if (rc == 0 || rc > sizeof (buffer) - 20)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "GetSystemWindowsDirectory failed");
|
2012-06-11 13:13:02 +02:00
|
|
|
goto bail;
|
2012-03-12 11:18:19 +01:00
|
|
|
}
|
2012-06-13 13:01:30 +02:00
|
|
|
if (data [strlen ((const char *) data) - 1] != '\\')
|
2013-01-03 00:35:56 +01:00
|
|
|
strcat ((char *) data, "\\");
|
|
|
|
strcat ((char *) data, "fonts");
|
2012-03-12 11:18:19 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (strlen ((char *) data) == 0)
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored");
|
|
|
|
else if (!FcStrUsesHome (data) || FcConfigHome ())
|
|
|
|
{
|
|
|
|
if (!FcConfigAddDir (parse->config, data))
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", data);
|
|
|
|
}
|
|
|
|
FcStrBufDestroy (&parse->pstack->str);
|
|
|
|
|
|
|
|
bail:
|
|
|
|
if (prefix)
|
2012-06-01 12:06:17 +02:00
|
|
|
FcStrFree (prefix);
|
2012-03-12 11:18:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcParseCacheDir (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
const FcChar8 *attr;
|
2012-12-07 11:09:36 +01:00
|
|
|
FcChar8 *prefix = NULL, *p, *data;
|
2012-03-12 11:18:19 +01:00
|
|
|
|
|
|
|
attr = FcConfigGetAttribute (parse, "prefix");
|
|
|
|
if (attr && FcStrCmp (attr, (const FcChar8 *)"xdg") == 0)
|
|
|
|
prefix = FcConfigXdgCacheHome ();
|
|
|
|
data = FcStrBufDone (&parse->pstack->str);
|
|
|
|
if (!data)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
if (prefix)
|
|
|
|
{
|
|
|
|
size_t plen = strlen ((const char *)prefix);
|
|
|
|
size_t dlen = strlen ((const char *)data);
|
|
|
|
|
2012-12-07 11:09:36 +01:00
|
|
|
p = realloc (prefix, plen + 1 + dlen + 1);
|
|
|
|
if (!p)
|
2012-03-12 11:18:19 +01:00
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2012-12-07 11:09:36 +01:00
|
|
|
data = prefix;
|
2012-03-12 11:18:19 +01:00
|
|
|
goto bail;
|
|
|
|
}
|
2012-12-07 11:09:36 +01:00
|
|
|
prefix = p;
|
2012-03-12 11:18:19 +01:00
|
|
|
prefix[plen] = FC_DIR_SEPARATOR;
|
|
|
|
memcpy (&prefix[plen + 1], data, dlen);
|
|
|
|
prefix[plen + 1 + dlen] = 0;
|
|
|
|
FcStrFree (data);
|
|
|
|
data = prefix;
|
|
|
|
}
|
|
|
|
#ifdef _WIN32
|
2012-06-13 13:01:30 +02:00
|
|
|
if (strcmp ((const char *) data, "WINDOWSTEMPDIR_FONTCONFIG_CACHE") == 0)
|
2012-03-12 11:18:19 +01:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
FcStrFree (data);
|
|
|
|
data = malloc (1000);
|
|
|
|
if (!data)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
|
|
|
goto bail;
|
|
|
|
}
|
2012-06-13 13:01:30 +02:00
|
|
|
rc = GetTempPath (800, (LPSTR) data);
|
2012-03-12 11:18:19 +01:00
|
|
|
if (rc == 0 || rc > 800)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "GetTempPath failed");
|
|
|
|
goto bail;
|
|
|
|
}
|
2012-06-13 13:01:30 +02:00
|
|
|
if (data [strlen ((const char *) data) - 1] != '\\')
|
2013-01-03 00:35:56 +01:00
|
|
|
strcat ((char *) data, "\\");
|
|
|
|
strcat ((char *) data, "fontconfig\\cache");
|
2012-03-12 11:18:19 +01:00
|
|
|
}
|
2012-06-13 13:01:30 +02:00
|
|
|
else if (strcmp ((const char *) data, "LOCAL_APPDATA_FONTCONFIG_CACHE") == 0)
|
2012-03-12 11:18:19 +01:00
|
|
|
{
|
|
|
|
char szFPath[MAX_PATH + 1];
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
if (!(pSHGetFolderPathA && SUCCEEDED(pSHGetFolderPathA(NULL, /* CSIDL_LOCAL_APPDATA */ 28, NULL, 0, szFPath))))
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "SHGetFolderPathA failed");
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
strncat(szFPath, "\\fontconfig\\cache", MAX_PATH - 1 - strlen(szFPath));
|
|
|
|
len = strlen(szFPath) + 1;
|
|
|
|
FcStrFree (data);
|
|
|
|
data = malloc(len);
|
|
|
|
if (!data)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
|
|
|
goto bail;
|
|
|
|
}
|
2012-06-13 13:01:30 +02:00
|
|
|
strncpy((char *) data, szFPath, len);
|
2012-03-12 11:18:19 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (strlen ((char *) data) == 0)
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "empty cache directory name ignored");
|
|
|
|
else if (!FcStrUsesHome (data) || FcConfigHome ())
|
|
|
|
{
|
|
|
|
if (!FcConfigAddCacheDir (parse->config, data))
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory; cannot add cache directory %s", data);
|
|
|
|
}
|
|
|
|
FcStrBufDestroy (&parse->pstack->str);
|
|
|
|
|
|
|
|
bail:
|
|
|
|
if (data)
|
|
|
|
FcStrFree (data);
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static void
|
|
|
|
FcParseInclude (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
FcChar8 *s;
|
2012-03-12 11:18:19 +01:00
|
|
|
const FcChar8 *attr;
|
2002-02-18 23:29:28 +01:00
|
|
|
FcBool ignore_missing = FcFalse;
|
2012-06-21 21:01:10 +02:00
|
|
|
FcBool deprecated = FcFalse;
|
2012-12-07 11:09:36 +01:00
|
|
|
FcChar8 *prefix = NULL, *p;
|
2013-08-07 04:57:19 +02:00
|
|
|
static FcChar8 *userdir = NULL;
|
|
|
|
static FcChar8 *userconf = NULL;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2009-03-11 19:07:15 +01:00
|
|
|
s = FcStrBufDoneStatic (&parse->pstack->str);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!s)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2012-03-12 11:18:19 +01:00
|
|
|
goto bail;
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
2012-03-12 11:18:19 +01:00
|
|
|
attr = FcConfigGetAttribute (parse, "ignore_missing");
|
|
|
|
if (attr && FcConfigLexBool (parse, (FcChar8 *) attr) == FcTrue)
|
2002-02-18 23:29:28 +01:00
|
|
|
ignore_missing = FcTrue;
|
2012-06-21 21:01:10 +02:00
|
|
|
attr = FcConfigGetAttribute (parse, "deprecated");
|
|
|
|
if (attr && FcConfigLexBool (parse, (FcChar8 *) attr) == FcTrue)
|
|
|
|
deprecated = FcTrue;
|
2012-03-12 11:18:19 +01:00
|
|
|
attr = FcConfigGetAttribute (parse, "prefix");
|
|
|
|
if (attr && FcStrCmp (attr, (const FcChar8 *)"xdg") == 0)
|
|
|
|
prefix = FcConfigXdgConfigHome ();
|
|
|
|
if (prefix)
|
|
|
|
{
|
|
|
|
size_t plen = strlen ((const char *)prefix);
|
|
|
|
size_t dlen = strlen ((const char *)s);
|
|
|
|
|
2012-12-07 11:09:36 +01:00
|
|
|
p = realloc (prefix, plen + 1 + dlen + 1);
|
|
|
|
if (!p)
|
2012-03-12 11:18:19 +01:00
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
|
|
|
goto bail;
|
|
|
|
}
|
2012-12-07 11:09:36 +01:00
|
|
|
prefix = p;
|
2012-03-12 11:18:19 +01:00
|
|
|
prefix[plen] = FC_DIR_SEPARATOR;
|
|
|
|
memcpy (&prefix[plen + 1], s, dlen);
|
|
|
|
prefix[plen + 1 + dlen] = 0;
|
|
|
|
s = prefix;
|
2013-08-07 04:57:19 +02:00
|
|
|
if (FcFileIsDir (s))
|
|
|
|
{
|
|
|
|
userdir:
|
|
|
|
if (!userdir)
|
|
|
|
userdir = FcStrdup (s);
|
|
|
|
}
|
|
|
|
else if (FcFileIsFile (s))
|
|
|
|
{
|
|
|
|
userconf:
|
|
|
|
if (!userconf)
|
|
|
|
userconf = FcStrdup (s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* No config dir nor file on the XDG directory spec compliant place
|
|
|
|
* so need to guess what it is supposed to be.
|
|
|
|
*/
|
|
|
|
FcChar8 *parent = FcStrDirname (s);
|
|
|
|
|
|
|
|
if (!FcFileIsDir (parent))
|
|
|
|
FcMakeDirectory (parent);
|
|
|
|
FcStrFree (parent);
|
|
|
|
if (FcStrStr (s, (const FcChar8 *)"conf.d") != NULL)
|
|
|
|
goto userdir;
|
|
|
|
else
|
|
|
|
goto userconf;
|
|
|
|
}
|
2012-03-12 11:18:19 +01:00
|
|
|
}
|
2002-02-20 01:32:30 +01:00
|
|
|
if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing))
|
2002-02-18 23:29:28 +01:00
|
|
|
parse->error = FcTrue;
|
2013-08-07 04:57:19 +02:00
|
|
|
#ifndef _WIN32
|
2012-03-12 11:18:19 +01:00
|
|
|
else
|
|
|
|
{
|
2012-06-21 21:01:10 +02:00
|
|
|
FcChar8 *filename;
|
2013-08-07 04:57:19 +02:00
|
|
|
static FcBool warn_conf = FcFalse, warn_confd = FcFalse;
|
2012-06-21 21:01:10 +02:00
|
|
|
|
|
|
|
filename = FcConfigFilename(s);
|
2012-12-05 10:13:25 +01:00
|
|
|
if (deprecated == FcTrue &&
|
|
|
|
filename != NULL &&
|
|
|
|
!FcFileIsLink (filename))
|
|
|
|
{
|
2013-08-07 04:57:19 +02:00
|
|
|
if (FcFileIsDir (filename))
|
|
|
|
{
|
|
|
|
if (FcFileIsDir (userdir) ||
|
|
|
|
rename ((const char *)filename, (const char *)userdir) != 0 ||
|
|
|
|
symlink ((const char *)userdir, (const char *)filename) != 0)
|
|
|
|
{
|
|
|
|
if (!warn_confd)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated. please move it to %s manually", s, userdir);
|
|
|
|
warn_confd = FcTrue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (FcFileIsFile (userconf) ||
|
|
|
|
rename ((const char *)filename, (const char *)userconf) != 0 ||
|
|
|
|
symlink ((const char *)userconf, (const char *)filename) != 0)
|
|
|
|
{
|
|
|
|
if (!warn_conf)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated. please move it to %s manually", s, userconf);
|
|
|
|
warn_conf = FcTrue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-06-21 21:01:10 +02:00
|
|
|
}
|
|
|
|
if(filename)
|
|
|
|
FcStrFree(filename);
|
2012-03-12 11:18:19 +01:00
|
|
|
}
|
2013-08-07 04:57:19 +02:00
|
|
|
#endif
|
2009-03-11 19:07:15 +01:00
|
|
|
FcStrBufDestroy (&parse->pstack->str);
|
2012-03-12 11:18:19 +01:00
|
|
|
|
|
|
|
bail:
|
|
|
|
if (prefix)
|
2012-06-01 12:06:17 +02:00
|
|
|
FcStrFree (prefix);
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct _FcOpMap {
|
2005-09-23 01:45:53 +02:00
|
|
|
char name[16];
|
2002-02-18 23:29:28 +01:00
|
|
|
FcOp op;
|
|
|
|
} FcOpMap;
|
|
|
|
|
|
|
|
static FcOp
|
|
|
|
FcConfigLexOp (const FcChar8 *op, const FcOpMap *map, int nmap)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < nmap; i++)
|
2010-04-12 18:10:05 +02:00
|
|
|
if (!strcmp ((char *) op, map[i].name))
|
2002-02-18 23:29:28 +01:00
|
|
|
return map[i].op;
|
|
|
|
return FcOpInvalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const FcOpMap fcCompareOps[] = {
|
|
|
|
{ "eq", FcOpEqual },
|
|
|
|
{ "not_eq", FcOpNotEqual },
|
|
|
|
{ "less", FcOpLess },
|
|
|
|
{ "less_eq", FcOpLessEqual },
|
|
|
|
{ "more", FcOpMore },
|
2002-08-22 20:53:22 +02:00
|
|
|
{ "more_eq", FcOpMoreEqual },
|
|
|
|
{ "contains", FcOpContains },
|
|
|
|
{ "not_contains", FcOpNotContains }
|
2002-02-18 23:29:28 +01:00
|
|
|
};
|
|
|
|
|
2005-09-23 01:45:53 +02:00
|
|
|
#define NUM_COMPARE_OPS (int) (sizeof fcCompareOps / sizeof fcCompareOps[0])
|
2002-02-18 23:29:28 +01:00
|
|
|
|
|
|
|
static FcOp
|
|
|
|
FcConfigLexCompare (const FcChar8 *compare)
|
|
|
|
{
|
|
|
|
return FcConfigLexOp (compare, fcCompareOps, NUM_COMPARE_OPS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcParseTest (FcConfigParse *parse)
|
|
|
|
{
|
2002-08-11 20:11:04 +02:00
|
|
|
const FcChar8 *kind_string;
|
|
|
|
FcMatchKind kind;
|
2002-02-18 23:29:28 +01:00
|
|
|
const FcChar8 *qual_string;
|
|
|
|
FcQual qual;
|
|
|
|
const FcChar8 *name;
|
|
|
|
const FcChar8 *compare_string;
|
|
|
|
FcOp compare;
|
|
|
|
FcExpr *expr;
|
|
|
|
FcTest *test;
|
2012-04-11 12:52:35 +02:00
|
|
|
const FcChar8 *iblanks_string;
|
|
|
|
int flags = 0;
|
2002-02-18 23:29:28 +01:00
|
|
|
|
2002-08-11 20:11:04 +02:00
|
|
|
kind_string = FcConfigGetAttribute (parse, "target");
|
|
|
|
if (!kind_string)
|
|
|
|
kind = FcMatchDefault;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!strcmp ((char *) kind_string, "pattern"))
|
|
|
|
kind = FcMatchPattern;
|
|
|
|
else if (!strcmp ((char *) kind_string, "font"))
|
|
|
|
kind = FcMatchFont;
|
2006-09-03 02:52:12 +02:00
|
|
|
else if (!strcmp ((char *) kind_string, "scan"))
|
|
|
|
kind = FcMatchScan;
|
2002-08-11 20:11:04 +02:00
|
|
|
else if (!strcmp ((char *) kind_string, "default"))
|
|
|
|
kind = FcMatchDefault;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "invalid test target \"%s\"", kind_string);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
qual_string = FcConfigGetAttribute (parse, "qual");
|
|
|
|
if (!qual_string)
|
|
|
|
qual = FcQualAny;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!strcmp ((char *) qual_string, "any"))
|
|
|
|
qual = FcQualAny;
|
|
|
|
else if (!strcmp ((char *) qual_string, "all"))
|
|
|
|
qual = FcQualAll;
|
2002-06-19 22:08:22 +02:00
|
|
|
else if (!strcmp ((char *) qual_string, "first"))
|
|
|
|
qual = FcQualFirst;
|
|
|
|
else if (!strcmp ((char *) qual_string, "not_first"))
|
|
|
|
qual = FcQualNotFirst;
|
2002-02-18 23:29:28 +01:00
|
|
|
else
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "invalid test qual \"%s\"", qual_string);
|
2002-07-12 21:19:16 +02:00
|
|
|
return;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
name = FcConfigGetAttribute (parse, "name");
|
|
|
|
if (!name)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "missing test name");
|
2002-07-12 21:19:16 +02:00
|
|
|
return;
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
compare_string = FcConfigGetAttribute (parse, "compare");
|
|
|
|
if (!compare_string)
|
|
|
|
compare = FcOpEqual;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
compare = FcConfigLexCompare (compare_string);
|
|
|
|
if (compare == FcOpInvalid)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "invalid test compare \"%s\"", compare_string);
|
2002-07-12 21:19:16 +02:00
|
|
|
return;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
2012-04-11 12:52:35 +02:00
|
|
|
iblanks_string = FcConfigGetAttribute (parse, "ignore-blanks");
|
|
|
|
if (iblanks_string)
|
|
|
|
{
|
|
|
|
FcBool f = FcFalse;
|
|
|
|
|
|
|
|
if (!FcNameBool (iblanks_string, &f))
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse,
|
|
|
|
FcSevereWarning,
|
|
|
|
"invalid test ignore-blanks \"%s\"", iblanks_string);
|
|
|
|
}
|
|
|
|
if (f)
|
|
|
|
flags |= FcOpFlagIgnoreBlanks;
|
|
|
|
}
|
2003-04-16 01:38:06 +02:00
|
|
|
expr = FcPopBinary (parse, FcOpComma);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!expr)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "missing test expression");
|
2002-02-18 23:29:28 +01:00
|
|
|
return;
|
|
|
|
}
|
2012-05-21 06:43:20 +02:00
|
|
|
if (expr->op == FcOpComma)
|
|
|
|
{
|
2012-08-16 13:33:12 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "Having multiple values in <test> isn't supported and may not work as expected");
|
2012-05-21 06:43:20 +02:00
|
|
|
}
|
2012-04-11 12:52:35 +02:00
|
|
|
test = FcTestCreate (parse, kind, qual, name, FC_OP (compare, flags), expr);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!test)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
FcVStackPushTest (parse, test);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const FcOpMap fcModeOps[] = {
|
|
|
|
{ "assign", FcOpAssign },
|
|
|
|
{ "assign_replace", FcOpAssignReplace },
|
|
|
|
{ "prepend", FcOpPrepend },
|
|
|
|
{ "prepend_first", FcOpPrependFirst },
|
|
|
|
{ "append", FcOpAppend },
|
|
|
|
{ "append_last", FcOpAppendLast },
|
2013-01-29 12:19:36 +01:00
|
|
|
{ "delete", FcOpDelete },
|
|
|
|
{ "delete_all", FcOpDeleteAll },
|
2002-02-18 23:29:28 +01:00
|
|
|
};
|
|
|
|
|
2005-09-23 01:45:53 +02:00
|
|
|
#define NUM_MODE_OPS (int) (sizeof fcModeOps / sizeof fcModeOps[0])
|
2002-02-18 23:29:28 +01:00
|
|
|
|
|
|
|
static FcOp
|
|
|
|
FcConfigLexMode (const FcChar8 *mode)
|
|
|
|
{
|
|
|
|
return FcConfigLexOp (mode, fcModeOps, NUM_MODE_OPS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcParseEdit (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
const FcChar8 *name;
|
|
|
|
const FcChar8 *mode_string;
|
|
|
|
FcOp mode;
|
2002-07-31 03:36:37 +02:00
|
|
|
FcValueBinding binding;
|
2002-02-18 23:29:28 +01:00
|
|
|
FcExpr *expr;
|
|
|
|
FcEdit *edit;
|
|
|
|
|
|
|
|
name = FcConfigGetAttribute (parse, "name");
|
|
|
|
if (!name)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "missing edit name");
|
2002-07-12 21:19:16 +02:00
|
|
|
return;
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
mode_string = FcConfigGetAttribute (parse, "mode");
|
|
|
|
if (!mode_string)
|
2002-06-02 21:51:36 +02:00
|
|
|
mode = FcOpAssign;
|
2002-02-18 23:29:28 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
mode = FcConfigLexMode (mode_string);
|
|
|
|
if (mode == FcOpInvalid)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "invalid edit mode \"%s\"", mode_string);
|
2002-07-12 21:19:16 +02:00
|
|
|
return;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
2007-10-26 07:30:49 +02:00
|
|
|
if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
|
|
|
|
return;
|
|
|
|
|
2003-04-16 01:38:06 +02:00
|
|
|
expr = FcPopBinary (parse, FcOpComma);
|
2013-01-29 12:19:36 +01:00
|
|
|
if ((mode == FcOpDelete || mode == FcOpDeleteAll) &&
|
|
|
|
expr != NULL)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "Expression doesn't take any effects for delete and delete_all");
|
|
|
|
FcExprDestroy (expr);
|
|
|
|
expr = NULL;
|
|
|
|
}
|
2006-08-31 06:59:53 +02:00
|
|
|
edit = FcEditCreate (parse, FcObjectFromName ((char *) name),
|
|
|
|
mode, expr, binding);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!edit)
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
FcExprDestroy (expr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!FcVStackPushEdit (parse, edit))
|
|
|
|
FcEditDestroy (edit);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcParseMatch (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
const FcChar8 *kind_name;
|
|
|
|
FcMatchKind kind;
|
|
|
|
FcEdit *edit = 0;
|
|
|
|
FcVStack *vstack;
|
2013-07-04 12:51:03 +02:00
|
|
|
FcRule *rule = NULL, *r;
|
2002-02-18 23:29:28 +01:00
|
|
|
|
|
|
|
kind_name = FcConfigGetAttribute (parse, "target");
|
|
|
|
if (!kind_name)
|
|
|
|
kind = FcMatchPattern;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!strcmp ((char *) kind_name, "pattern"))
|
|
|
|
kind = FcMatchPattern;
|
|
|
|
else if (!strcmp ((char *) kind_name, "font"))
|
|
|
|
kind = FcMatchFont;
|
2006-09-03 02:52:12 +02:00
|
|
|
else if (!strcmp ((char *) kind_name, "scan"))
|
|
|
|
kind = FcMatchScan;
|
2002-02-18 23:29:28 +01:00
|
|
|
else
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "invalid match target \"%s\"", kind_name);
|
2002-07-12 21:19:16 +02:00
|
|
|
return;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
2009-03-12 17:22:37 +01:00
|
|
|
while ((vstack = FcVStackPeek (parse)))
|
2002-02-18 23:29:28 +01:00
|
|
|
{
|
2012-12-30 04:11:09 +01:00
|
|
|
switch ((int) vstack->tag) {
|
2002-02-18 23:29:28 +01:00
|
|
|
case FcVStackTest:
|
2013-07-04 12:51:03 +02:00
|
|
|
r = FcRuleCreate (FcRuleTest, vstack->u.test);
|
|
|
|
if (rule)
|
|
|
|
r->next = rule;
|
|
|
|
rule = r;
|
2002-02-18 23:29:28 +01:00
|
|
|
vstack->tag = FcVStackNone;
|
|
|
|
break;
|
|
|
|
case FcVStackEdit:
|
2013-07-04 12:51:03 +02:00
|
|
|
if (kind == FcMatchScan && vstack->u.edit->object > FC_MAX_BASE_OBJECT)
|
2006-12-02 22:57:45 +01:00
|
|
|
{
|
2010-04-12 18:10:05 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError,
|
2006-12-02 22:57:45 +01:00
|
|
|
"<match target=\"scan\"> cannot edit user-defined object \"%s\"",
|
|
|
|
FcObjectName(edit->object));
|
2013-07-04 12:51:03 +02:00
|
|
|
break;
|
2006-12-02 22:57:45 +01:00
|
|
|
}
|
2013-07-04 12:51:03 +02:00
|
|
|
r = FcRuleCreate (FcRuleEdit, vstack->u.edit);
|
|
|
|
if (rule)
|
|
|
|
r->next = rule;
|
|
|
|
rule = r;
|
|
|
|
vstack->tag = FcVStackNone;
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
default:
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "invalid match element");
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
}
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStackPopAndDestroy (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
2013-07-04 12:51:03 +02:00
|
|
|
if (!FcConfigAddRule (parse->config, rule, kind))
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
|
2003-05-07 18:13:24 +02:00
|
|
|
static void
|
|
|
|
FcParseAcceptRejectFont (FcConfigParse *parse, FcElement element)
|
|
|
|
{
|
|
|
|
FcVStack *vstack;
|
|
|
|
|
2009-03-12 17:22:37 +01:00
|
|
|
while ((vstack = FcVStackPeek (parse)))
|
2003-05-07 18:13:24 +02:00
|
|
|
{
|
2012-12-30 04:11:09 +01:00
|
|
|
switch ((int) vstack->tag) {
|
2003-05-07 18:13:24 +02:00
|
|
|
case FcVStackGlob:
|
2010-04-12 18:10:05 +02:00
|
|
|
if (!FcConfigGlobAdd (parse->config,
|
2003-05-07 18:13:24 +02:00
|
|
|
vstack->u.string,
|
|
|
|
element == FcElementAcceptfont))
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
|
|
|
}
|
|
|
|
break;
|
2004-12-04 20:41:10 +01:00
|
|
|
case FcVStackPattern:
|
|
|
|
if (!FcConfigPatternsAdd (parse->config,
|
|
|
|
vstack->u.pattern,
|
|
|
|
element == FcElementAcceptfont))
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
vstack->tag = FcVStackNone;
|
|
|
|
break;
|
2003-05-07 18:13:24 +02:00
|
|
|
default:
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "bad font selector");
|
|
|
|
break;
|
|
|
|
}
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStackPopAndDestroy (parse);
|
2003-05-07 18:13:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-12-04 20:41:10 +01:00
|
|
|
|
|
|
|
static FcValue
|
|
|
|
FcPopValue (FcConfigParse *parse)
|
|
|
|
{
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStack *vstack = FcVStackPeek (parse);
|
2004-12-04 20:41:10 +01:00
|
|
|
FcValue value;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2004-12-04 20:41:10 +01:00
|
|
|
value.type = FcTypeVoid;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2004-12-04 20:41:10 +01:00
|
|
|
if (!vstack)
|
|
|
|
return value;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2012-12-30 04:11:09 +01:00
|
|
|
switch ((int) vstack->tag) {
|
2004-12-04 20:41:10 +01:00
|
|
|
case FcVStackString:
|
2013-01-02 09:06:15 +01:00
|
|
|
value.u.s = FcStrdup (vstack->u.string);
|
2005-08-24 08:21:30 +02:00
|
|
|
if (value.u.s)
|
2004-12-04 20:41:10 +01:00
|
|
|
value.type = FcTypeString;
|
|
|
|
break;
|
|
|
|
case FcVStackConstant:
|
|
|
|
if (FcNameConstant (vstack->u.string, &value.u.i))
|
|
|
|
value.type = FcTypeInteger;
|
|
|
|
break;
|
|
|
|
case FcVStackInteger:
|
|
|
|
value.u.i = vstack->u.integer;
|
|
|
|
value.type = FcTypeInteger;
|
|
|
|
break;
|
|
|
|
case FcVStackDouble:
|
|
|
|
value.u.d = vstack->u._double;
|
2012-12-30 02:14:07 +01:00
|
|
|
value.type = FcTypeDouble;
|
2004-12-04 20:41:10 +01:00
|
|
|
break;
|
|
|
|
case FcVStackBool:
|
2008-12-28 09:23:58 +01:00
|
|
|
value.u.b = vstack->u.bool_;
|
2004-12-04 20:41:10 +01:00
|
|
|
value.type = FcTypeBool;
|
|
|
|
break;
|
2010-12-06 04:10:17 +01:00
|
|
|
case FcVStackCharSet:
|
|
|
|
value.u.c = FcCharSetCopy (vstack->u.charset);
|
|
|
|
if (value.u.c)
|
|
|
|
value.type = FcTypeCharSet;
|
|
|
|
break;
|
2010-12-06 04:38:18 +01:00
|
|
|
case FcVStackLangSet:
|
|
|
|
value.u.l = FcLangSetCopy (vstack->u.langset);
|
|
|
|
if (value.u.l)
|
|
|
|
value.type = FcTypeLangSet;
|
|
|
|
break;
|
2004-12-04 20:41:10 +01:00
|
|
|
default:
|
2010-04-12 18:10:05 +02:00
|
|
|
FcConfigMessage (parse, FcSevereWarning, "unknown pattern element %d",
|
2004-12-04 20:41:10 +01:00
|
|
|
vstack->tag);
|
|
|
|
break;
|
|
|
|
}
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStackPopAndDestroy (parse);
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2004-12-04 20:41:10 +01:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcParsePatelt (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
FcValue value;
|
|
|
|
FcPattern *pattern = FcPatternCreate ();
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
if (!pattern)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-09-11 04:16:09 +02:00
|
|
|
name = (char *) FcConfigGetAttribute (parse, "name");
|
2004-12-04 20:41:10 +01:00
|
|
|
if (!name)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "missing pattern element name");
|
2006-04-11 18:54:24 +02:00
|
|
|
FcPatternDestroy (pattern);
|
2004-12-04 20:41:10 +01:00
|
|
|
return;
|
|
|
|
}
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2004-12-04 20:41:10 +01:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
value = FcPopValue (parse);
|
|
|
|
if (value.type == FcTypeVoid)
|
|
|
|
break;
|
|
|
|
if (!FcPatternAdd (pattern, name, value, FcTrue))
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2008-09-23 00:16:30 +02:00
|
|
|
FcValueDestroy(value);
|
2004-12-04 20:41:10 +01:00
|
|
|
break;
|
|
|
|
}
|
2008-09-23 00:16:30 +02:00
|
|
|
FcValueDestroy(value);
|
2004-12-04 20:41:10 +01:00
|
|
|
}
|
|
|
|
|
2006-04-27 09:54:07 +02:00
|
|
|
FcVStackPushPattern (parse, pattern);
|
2004-12-04 20:41:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcParsePattern (FcConfigParse *parse)
|
|
|
|
{
|
|
|
|
FcVStack *vstack;
|
|
|
|
FcPattern *pattern = FcPatternCreate ();
|
|
|
|
|
|
|
|
if (!pattern)
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-03-12 17:22:37 +01:00
|
|
|
while ((vstack = FcVStackPeek (parse)))
|
2004-12-04 20:41:10 +01:00
|
|
|
{
|
2012-12-30 04:11:09 +01:00
|
|
|
switch ((int) vstack->tag) {
|
2004-12-04 20:41:10 +01:00
|
|
|
case FcVStackPattern:
|
|
|
|
if (!FcPatternAppend (pattern, vstack->u.pattern))
|
|
|
|
{
|
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2006-04-11 18:54:24 +02:00
|
|
|
FcPatternDestroy (pattern);
|
2004-12-04 20:41:10 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FcConfigMessage (parse, FcSevereWarning, "unknown pattern element");
|
|
|
|
break;
|
|
|
|
}
|
2009-03-12 17:22:37 +01:00
|
|
|
FcVStackPopAndDestroy (parse);
|
2004-12-04 20:41:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FcVStackPushPattern (parse, pattern);
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static void
|
2012-12-30 04:32:56 +01:00
|
|
|
FcEndElement(void *userData, const XML_Char *name FC_UNUSED)
|
2002-02-18 23:29:28 +01:00
|
|
|
{
|
|
|
|
FcConfigParse *parse = userData;
|
|
|
|
FcChar8 *data;
|
2009-08-13 23:08:17 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!parse->pstack)
|
|
|
|
return;
|
|
|
|
switch (parse->pstack->element) {
|
|
|
|
case FcElementNone:
|
|
|
|
break;
|
|
|
|
case FcElementFontconfig:
|
|
|
|
break;
|
|
|
|
case FcElementDir:
|
2012-03-12 11:18:19 +01:00
|
|
|
FcParseDir (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
2006-08-04 18:13:00 +02:00
|
|
|
case FcElementCacheDir:
|
2012-03-12 11:18:19 +01:00
|
|
|
FcParseCacheDir (parse);
|
2006-08-04 18:13:00 +02:00
|
|
|
break;
|
2002-02-18 23:29:28 +01:00
|
|
|
case FcElementCache:
|
2009-03-11 19:07:15 +01:00
|
|
|
data = FcStrBufDoneStatic (&parse->pstack->str);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!data)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
2006-08-31 06:59:53 +02:00
|
|
|
/* discard this data; no longer used */
|
2009-03-11 19:07:15 +01:00
|
|
|
FcStrBufDestroy (&parse->pstack->str);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementInclude:
|
|
|
|
FcParseInclude (parse);
|
|
|
|
break;
|
|
|
|
case FcElementConfig:
|
|
|
|
break;
|
|
|
|
case FcElementMatch:
|
|
|
|
FcParseMatch (parse);
|
|
|
|
break;
|
|
|
|
case FcElementAlias:
|
|
|
|
FcParseAlias (parse);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FcElementBlank:
|
|
|
|
FcParseBlank (parse);
|
|
|
|
break;
|
2002-05-21 19:06:22 +02:00
|
|
|
case FcElementRescan:
|
|
|
|
FcParseRescan (parse);
|
|
|
|
break;
|
2002-02-18 23:29:28 +01:00
|
|
|
|
|
|
|
case FcElementPrefer:
|
|
|
|
FcParseFamilies (parse, FcVStackPrefer);
|
|
|
|
break;
|
|
|
|
case FcElementAccept:
|
|
|
|
FcParseFamilies (parse, FcVStackAccept);
|
|
|
|
break;
|
|
|
|
case FcElementDefault:
|
|
|
|
FcParseFamilies (parse, FcVStackDefault);
|
|
|
|
break;
|
|
|
|
case FcElementFamily:
|
|
|
|
FcParseFamily (parse);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FcElementTest:
|
|
|
|
FcParseTest (parse);
|
|
|
|
break;
|
|
|
|
case FcElementEdit:
|
|
|
|
FcParseEdit (parse);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FcElementInt:
|
|
|
|
FcParseInt (parse);
|
|
|
|
break;
|
|
|
|
case FcElementDouble:
|
|
|
|
FcParseDouble (parse);
|
|
|
|
break;
|
|
|
|
case FcElementString:
|
|
|
|
FcParseString (parse, FcVStackString);
|
|
|
|
break;
|
|
|
|
case FcElementMatrix:
|
|
|
|
FcParseMatrix (parse);
|
|
|
|
break;
|
2010-12-06 04:10:17 +01:00
|
|
|
case FcElementRange:
|
|
|
|
FcParseRange (parse);
|
|
|
|
break;
|
2002-02-18 23:29:28 +01:00
|
|
|
case FcElementBool:
|
|
|
|
FcParseBool (parse);
|
|
|
|
break;
|
2010-12-06 04:10:17 +01:00
|
|
|
case FcElementCharSet:
|
|
|
|
FcParseCharSet (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
2010-12-06 04:38:18 +01:00
|
|
|
case FcElementLangSet:
|
|
|
|
FcParseLangSet (parse);
|
|
|
|
break;
|
2003-05-07 18:13:24 +02:00
|
|
|
case FcElementSelectfont:
|
|
|
|
break;
|
|
|
|
case FcElementAcceptfont:
|
|
|
|
case FcElementRejectfont:
|
|
|
|
FcParseAcceptRejectFont (parse, parse->pstack->element);
|
|
|
|
break;
|
|
|
|
case FcElementGlob:
|
|
|
|
FcParseString (parse, FcVStackGlob);
|
|
|
|
break;
|
2004-12-04 20:41:10 +01:00
|
|
|
case FcElementPattern:
|
|
|
|
FcParsePattern (parse);
|
|
|
|
break;
|
|
|
|
case FcElementPatelt:
|
|
|
|
FcParsePatelt (parse);
|
|
|
|
break;
|
2002-02-18 23:29:28 +01:00
|
|
|
case FcElementName:
|
2012-12-30 05:58:38 +01:00
|
|
|
FcParseName (parse);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementConst:
|
|
|
|
FcParseString (parse, FcVStackConstant);
|
|
|
|
break;
|
|
|
|
case FcElementOr:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpOr);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementAnd:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpAnd);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementEq:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpEqual);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementNotEq:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpNotEqual);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementLess:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpLess);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementLessEq:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpLessEqual);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementMore:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpMore);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementMoreEq:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpMoreEqual);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcElementContains:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpContains);
|
2002-08-22 20:53:22 +02:00
|
|
|
break;
|
|
|
|
case FcElementNotContains:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpNotContains);
|
2002-08-22 20:53:22 +02:00
|
|
|
break;
|
2002-02-18 23:29:28 +01:00
|
|
|
case FcElementPlus:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpPlus);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementMinus:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpMinus);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementTimes:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpTimes);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementDivide:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpDivide);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementNot:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseUnary (parse, FcOpNot);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementIf:
|
2003-04-16 01:38:06 +02:00
|
|
|
FcParseBinary (parse, FcOpQuest);
|
|
|
|
break;
|
|
|
|
case FcElementFloor:
|
|
|
|
FcParseUnary (parse, FcOpFloor);
|
|
|
|
break;
|
|
|
|
case FcElementCeil:
|
|
|
|
FcParseUnary (parse, FcOpCeil);
|
|
|
|
break;
|
|
|
|
case FcElementRound:
|
|
|
|
FcParseUnary (parse, FcOpRound);
|
|
|
|
break;
|
|
|
|
case FcElementTrunc:
|
|
|
|
FcParseUnary (parse, FcOpTrunc);
|
2002-02-18 23:29:28 +01:00
|
|
|
break;
|
|
|
|
case FcElementUnknown:
|
|
|
|
break;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
(void) FcPStackPop (parse);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcCharacterData (void *userData, const XML_Char *s, int len)
|
|
|
|
{
|
|
|
|
FcConfigParse *parse = userData;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!parse->pstack)
|
|
|
|
return;
|
|
|
|
if (!FcStrBufData (&parse->pstack->str, (FcChar8 *) s, len))
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "out of memory");
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcStartDoctypeDecl (void *userData,
|
|
|
|
const XML_Char *doctypeName,
|
2012-12-30 04:32:56 +01:00
|
|
|
const XML_Char *sysid FC_UNUSED,
|
|
|
|
const XML_Char *pubid FC_UNUSED,
|
|
|
|
int has_internal_subset FC_UNUSED)
|
2002-02-18 23:29:28 +01:00
|
|
|
{
|
|
|
|
FcConfigParse *parse = userData;
|
|
|
|
|
|
|
|
if (strcmp ((char *) doctypeName, "fontconfig") != 0)
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (parse, FcSevereError, "invalid doctype \"%s\"", doctypeName);
|
2002-02-18 23:29:28 +01:00
|
|
|
}
|
|
|
|
|
2006-04-06 06:33:11 +02:00
|
|
|
#ifdef ENABLE_LIBXML2
|
2005-09-29 22:53:30 +02:00
|
|
|
|
|
|
|
static void
|
|
|
|
FcInternalSubsetDecl (void *userData,
|
|
|
|
const XML_Char *doctypeName,
|
|
|
|
const XML_Char *sysid,
|
|
|
|
const XML_Char *pubid)
|
|
|
|
{
|
|
|
|
FcStartDoctypeDecl (userData, doctypeName, sysid, pubid, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcExternalSubsetDecl (void *userData,
|
|
|
|
const XML_Char *doctypeName,
|
|
|
|
const XML_Char *sysid,
|
|
|
|
const XML_Char *pubid)
|
|
|
|
{
|
|
|
|
FcStartDoctypeDecl (userData, doctypeName, sysid, pubid, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* ENABLE_LIBXML2 */
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
static void
|
2012-12-30 04:32:56 +01:00
|
|
|
FcEndDoctypeDecl (void *userData FC_UNUSED)
|
2002-02-18 23:29:28 +01:00
|
|
|
{
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2005-09-29 22:53:30 +02:00
|
|
|
#endif /* ENABLE_LIBXML2 */
|
|
|
|
|
2006-09-10 06:21:01 +02:00
|
|
|
static int
|
|
|
|
FcSortCmpStr (const void *a, const void *b)
|
|
|
|
{
|
|
|
|
const FcChar8 *as = *((FcChar8 **) a);
|
|
|
|
const FcChar8 *bs = *((FcChar8 **) b);
|
|
|
|
return FcStrCmp (as, bs);
|
|
|
|
}
|
|
|
|
|
2004-12-05 06:03:52 +01:00
|
|
|
static FcBool
|
|
|
|
FcConfigParseAndLoadDir (FcConfig *config,
|
|
|
|
const FcChar8 *name,
|
|
|
|
const FcChar8 *dir,
|
|
|
|
FcBool complain)
|
|
|
|
{
|
|
|
|
DIR *d;
|
|
|
|
struct dirent *e;
|
|
|
|
FcBool ret = FcTrue;
|
|
|
|
FcChar8 *file;
|
|
|
|
FcChar8 *base;
|
|
|
|
FcStrSet *files;
|
|
|
|
|
|
|
|
d = opendir ((char *) dir);
|
|
|
|
if (!d)
|
|
|
|
{
|
|
|
|
if (complain)
|
|
|
|
FcConfigMessage (0, FcSevereError, "Cannot open config dir \"%s\"",
|
|
|
|
name);
|
|
|
|
ret = FcFalse;
|
|
|
|
goto bail0;
|
|
|
|
}
|
|
|
|
/* freed below */
|
|
|
|
file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
|
|
|
|
if (!file)
|
|
|
|
{
|
|
|
|
ret = FcFalse;
|
|
|
|
goto bail1;
|
|
|
|
}
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2004-12-05 06:03:52 +01:00
|
|
|
strcpy ((char *) file, (char *) dir);
|
|
|
|
strcat ((char *) file, "/");
|
|
|
|
base = file + strlen ((char *) file);
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2004-12-05 06:03:52 +01:00
|
|
|
files = FcStrSetCreate ();
|
|
|
|
if (!files)
|
|
|
|
{
|
|
|
|
ret = FcFalse;
|
|
|
|
goto bail2;
|
|
|
|
}
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2004-12-05 06:03:52 +01:00
|
|
|
if (FcDebug () & FC_DBG_CONFIG)
|
|
|
|
printf ("\tScanning config dir %s\n", dir);
|
|
|
|
|
|
|
|
while (ret && (e = readdir (d)))
|
|
|
|
{
|
2005-09-11 04:16:09 +02:00
|
|
|
int d_len;
|
|
|
|
#define TAIL ".conf"
|
|
|
|
#define TAIL_LEN 5
|
2004-12-05 06:03:52 +01:00
|
|
|
/*
|
2005-09-11 04:16:09 +02:00
|
|
|
* Add all files of the form [0-9]*.conf
|
2004-12-05 06:03:52 +01:00
|
|
|
*/
|
|
|
|
if ('0' <= e->d_name[0] && e->d_name[0] <= '9' &&
|
2005-09-11 04:16:09 +02:00
|
|
|
(d_len = strlen (e->d_name)) < FC_MAX_FILE_LEN &&
|
|
|
|
d_len > TAIL_LEN &&
|
|
|
|
strcmp (e->d_name + d_len - TAIL_LEN, TAIL) == 0)
|
2004-12-05 06:03:52 +01:00
|
|
|
{
|
|
|
|
strcpy ((char *) base, (char *) e->d_name);
|
|
|
|
if (!FcStrSetAdd (files, file))
|
|
|
|
{
|
|
|
|
ret = FcFalse;
|
|
|
|
goto bail3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
int i;
|
2010-04-12 18:10:05 +02:00
|
|
|
qsort (files->strs, files->num, sizeof (FcChar8 *),
|
2006-09-10 06:21:01 +02:00
|
|
|
(int (*)(const void *, const void *)) FcSortCmpStr);
|
2004-12-05 06:03:52 +01:00
|
|
|
for (i = 0; ret && i < files->num; i++)
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = FcConfigParseAndLoad (config, files->strs[i], complain);
|
2004-12-05 06:03:52 +01:00
|
|
|
}
|
|
|
|
bail3:
|
|
|
|
FcStrSetDestroy (files);
|
|
|
|
bail2:
|
|
|
|
free (file);
|
|
|
|
bail1:
|
|
|
|
closedir (d);
|
|
|
|
bail0:
|
|
|
|
return ret || !complain;
|
|
|
|
}
|
|
|
|
|
2012-04-12 07:01:25 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
pfnGetSystemWindowsDirectory pGetSystemWindowsDirectory = NULL;
|
|
|
|
pfnSHGetFolderPathA pSHGetFolderPathA = NULL;
|
|
|
|
#endif
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
FcBool
|
|
|
|
FcConfigParseAndLoad (FcConfig *config,
|
2002-02-18 23:29:28 +01:00
|
|
|
const FcChar8 *name,
|
2002-02-15 00:34:13 +01:00
|
|
|
FcBool complain)
|
|
|
|
{
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
XML_Parser p;
|
|
|
|
FcChar8 *filename;
|
2005-12-21 04:31:19 +01:00
|
|
|
int fd;
|
2002-02-18 23:29:28 +01:00
|
|
|
int len;
|
|
|
|
FcConfigParse parse;
|
|
|
|
FcBool error = FcTrue;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2006-04-06 06:33:11 +02:00
|
|
|
#ifdef ENABLE_LIBXML2
|
2005-09-29 22:53:30 +02:00
|
|
|
xmlSAXHandler sax;
|
|
|
|
char buf[BUFSIZ];
|
|
|
|
#else
|
|
|
|
void *buf;
|
|
|
|
#endif
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2012-04-12 07:01:25 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
if (!pGetSystemWindowsDirectory)
|
|
|
|
{
|
|
|
|
HMODULE hk32 = GetModuleHandleA("kernel32.dll");
|
|
|
|
if (!(pGetSystemWindowsDirectory = (pfnGetSystemWindowsDirectory) GetProcAddress(hk32, "GetSystemWindowsDirectoryA")))
|
|
|
|
pGetSystemWindowsDirectory = (pfnGetSystemWindowsDirectory) GetWindowsDirectory;
|
|
|
|
}
|
|
|
|
if (!pSHGetFolderPathA)
|
|
|
|
{
|
|
|
|
HMODULE hSh = LoadLibraryA("shfolder.dll");
|
|
|
|
/* the check is done later, because there is no provided fallback */
|
|
|
|
if (hSh)
|
|
|
|
pSHGetFolderPathA = (pfnSHGetFolderPathA) GetProcAddress(hSh, "SHGetFolderPathA");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
filename = FcConfigFilename (name);
|
|
|
|
if (!filename)
|
|
|
|
goto bail0;
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2005-11-30 23:13:21 +01:00
|
|
|
if (FcStrSetMember (config->configFiles, filename))
|
|
|
|
{
|
|
|
|
FcStrFree (filename);
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2002-06-21 09:01:11 +02:00
|
|
|
if (!FcStrSetAdd (config->configFiles, filename))
|
2002-09-01 00:17:32 +02:00
|
|
|
{
|
|
|
|
FcStrFree (filename);
|
2002-06-21 09:01:11 +02:00
|
|
|
goto bail0;
|
2002-09-01 00:17:32 +02:00
|
|
|
}
|
2002-06-21 09:01:11 +02:00
|
|
|
|
2004-12-05 06:03:52 +01:00
|
|
|
if (FcFileIsDir (filename))
|
|
|
|
{
|
|
|
|
FcBool ret = FcConfigParseAndLoadDir (config, name, filename, complain);
|
|
|
|
FcStrFree (filename);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FcDebug () & FC_DBG_CONFIG)
|
|
|
|
printf ("\tLoading config file %s\n", filename);
|
|
|
|
|
2012-12-06 12:01:52 +01:00
|
|
|
fd = FcOpen ((char *) filename, O_RDONLY);
|
2010-04-12 18:10:05 +02:00
|
|
|
if (fd == -1) {
|
2005-11-18 21:32:30 +01:00
|
|
|
FcStrFree (filename);
|
2002-02-18 23:29:28 +01:00
|
|
|
goto bail0;
|
2005-11-18 21:32:30 +01:00
|
|
|
}
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2006-04-06 06:33:11 +02:00
|
|
|
#ifdef ENABLE_LIBXML2
|
2005-09-29 22:53:30 +02:00
|
|
|
memset(&sax, 0, sizeof(sax));
|
|
|
|
|
|
|
|
sax.internalSubset = FcInternalSubsetDecl;
|
|
|
|
sax.externalSubset = FcExternalSubsetDecl;
|
|
|
|
sax.startElement = FcStartElement;
|
|
|
|
sax.endElement = FcEndElement;
|
|
|
|
sax.characters = FcCharacterData;
|
|
|
|
|
2005-11-18 21:32:30 +01:00
|
|
|
p = xmlCreatePushParserCtxt (&sax, &parse, NULL, 0, (const char *) filename);
|
2005-09-29 22:53:30 +02:00
|
|
|
#else
|
2002-02-18 23:29:28 +01:00
|
|
|
p = XML_ParserCreate ("UTF-8");
|
2005-09-29 22:53:30 +02:00
|
|
|
#endif
|
2005-11-18 21:32:30 +01:00
|
|
|
FcStrFree (filename);
|
2005-09-29 22:53:30 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!p)
|
|
|
|
goto bail1;
|
|
|
|
|
2012-10-07 22:37:03 +02:00
|
|
|
if (!FcConfigParseInit (&parse, name, config, p))
|
2002-02-18 23:29:28 +01:00
|
|
|
goto bail2;
|
|
|
|
|
2006-04-06 06:33:11 +02:00
|
|
|
#ifndef ENABLE_LIBXML2
|
2005-09-29 22:53:30 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
XML_SetUserData (p, &parse);
|
2010-04-12 18:10:05 +02:00
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
XML_SetDoctypeDeclHandler (p, FcStartDoctypeDecl, FcEndDoctypeDecl);
|
|
|
|
XML_SetElementHandler (p, FcStartElement, FcEndElement);
|
|
|
|
XML_SetCharacterDataHandler (p, FcCharacterData);
|
|
|
|
|
2005-09-29 22:53:30 +02:00
|
|
|
#endif /* ENABLE_LIBXML2 */
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
do {
|
2006-04-06 06:33:11 +02:00
|
|
|
#ifndef ENABLE_LIBXML2
|
2002-02-18 23:29:28 +01:00
|
|
|
buf = XML_GetBuffer (p, BUFSIZ);
|
|
|
|
if (!buf)
|
2002-02-28 17:51:48 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (&parse, FcSevereError, "cannot get parse buffer");
|
2002-02-18 23:29:28 +01:00
|
|
|
goto bail3;
|
2002-02-28 17:51:48 +01:00
|
|
|
}
|
2005-09-29 22:53:30 +02:00
|
|
|
#endif
|
2005-12-21 04:31:19 +01:00
|
|
|
len = read (fd, buf, BUFSIZ);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (len < 0)
|
2002-02-28 17:51:48 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (&parse, FcSevereError, "failed reading config file");
|
2002-02-18 23:29:28 +01:00
|
|
|
goto bail3;
|
2002-02-28 17:51:48 +01:00
|
|
|
}
|
2005-09-29 22:53:30 +02:00
|
|
|
|
2006-04-06 06:33:11 +02:00
|
|
|
#ifdef ENABLE_LIBXML2
|
2005-09-29 22:53:30 +02:00
|
|
|
if (xmlParseChunk (p, buf, len, len == 0))
|
|
|
|
#else
|
2002-02-18 23:29:28 +01:00
|
|
|
if (!XML_ParseBuffer (p, len, len == 0))
|
2005-09-29 22:53:30 +02:00
|
|
|
#endif
|
2002-02-28 17:51:48 +01:00
|
|
|
{
|
2010-04-12 18:10:05 +02:00
|
|
|
FcConfigMessage (&parse, FcSevereError, "%s",
|
2002-02-28 17:51:48 +01:00
|
|
|
XML_ErrorString (XML_GetErrorCode (p)));
|
2002-02-18 23:29:28 +01:00
|
|
|
goto bail3;
|
2002-02-28 17:51:48 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
} while (len != 0);
|
|
|
|
error = parse.error;
|
|
|
|
bail3:
|
|
|
|
FcConfigCleanup (&parse);
|
|
|
|
bail2:
|
|
|
|
XML_ParserFree (p);
|
|
|
|
bail1:
|
2005-12-21 04:31:19 +01:00
|
|
|
close (fd);
|
|
|
|
fd = -1;
|
2002-02-18 23:29:28 +01:00
|
|
|
bail0:
|
|
|
|
if (error && complain)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-18 23:29:28 +01:00
|
|
|
if (name)
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (0, FcSevereError, "Cannot load config file \"%s\"", name);
|
2002-02-15 00:34:13 +01:00
|
|
|
else
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigMessage (0, FcSevereError, "Cannot load default config file");
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
return FcTrue;
|
|
|
|
}
|
2006-09-05 11:24:01 +02:00
|
|
|
#define __fcxml__
|
|
|
|
#include "fcaliastail.h"
|
|
|
|
#undef __fcxml__
|