]> git.wh0rd.org - fontconfig.git/blobdiff - src/fcxml.c
Implement new semantics for Contains and LISTING:
[fontconfig.git] / src / fcxml.c
index 5962b8dc753ba49e6b0a2db4256ba1bbe06ebb4a..65af5039b99f1ead14d8d4085e1e623122fa0ef8 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * $XFree86: xc/lib/fontconfig/src/fcxml.c,v 1.20 2002/08/20 23:17:03 keithp Exp $
+ * $RCSId: xc/lib/fontconfig/src/fcxml.c,v 1.21 2002/08/22 18:53:22 keithp Exp $
  *
- * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
+ * Copyright © 2002 Keith Packard
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 #include <expat.h>
 #endif
 
+#ifdef _WIN32
+#define STRICT
+#include <windows.h>
+#undef STRICT
+#endif
+
 FcTest *
 FcTestCreate (FcMatchKind   kind, 
              FcQual        qual,
@@ -46,6 +52,7 @@ FcTestCreate (FcMatchKind   kind,
 
     if (test)
     {
+       FcMemAlloc (FC_MEM_TEST, sizeof (FcTest));
        test->next = 0;
        test->kind = kind;
        test->qual = qual;
@@ -63,6 +70,7 @@ FcTestDestroy (FcTest *test)
        FcTestDestroy (test->next);
     FcExprDestroy (test->expr);
     FcStrFree ((FcChar8 *) test->field);
+    FcMemFree (FC_MEM_TEST, sizeof (FcTest));
     free (test);
 }
 
@@ -73,6 +81,7 @@ FcExprCreateInteger (int i)
 
     if (e)
     {
+       FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
        e->op = FcOpInteger;
        e->u.ival = i;
     }
@@ -86,6 +95,7 @@ FcExprCreateDouble (double d)
 
     if (e)
     {
+       FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
        e->op = FcOpDouble;
        e->u.dval = d;
     }
@@ -99,6 +109,7 @@ FcExprCreateString (const FcChar8 *s)
 
     if (e)
     {
+       FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
        e->op = FcOpString;
        e->u.sval = FcStrCopy (s);
     }
@@ -112,6 +123,7 @@ FcExprCreateMatrix (const FcMatrix *m)
 
     if (e)
     {
+       FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
        e->op = FcOpMatrix;
        e->u.mval = FcMatrixCopy (m);
     }
@@ -125,6 +137,7 @@ FcExprCreateBool (FcBool b)
 
     if (e)
     {
+       FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
        e->op = FcOpBool;
        e->u.bval = b;
     }
@@ -138,6 +151,7 @@ FcExprCreateNil (void)
 
     if (e)
     {
+       FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
        e->op = FcOpNil;
     }
     return e;
@@ -150,6 +164,7 @@ FcExprCreateField (const char *field)
 
     if (e)
     {
+       FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
        e->op = FcOpField;
        e->u.field = (char *) FcStrCopy ((FcChar8 *) field);
     }
@@ -163,6 +178,7 @@ FcExprCreateConst (const FcChar8 *constant)
 
     if (e)
     {
+       FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
        e->op = FcOpConst;
        e->u.constant = FcStrCopy (constant);
     }
@@ -176,6 +192,7 @@ FcExprCreateOp (FcExpr *left, FcOp op, FcExpr *right)
 
     if (e)
     {
+       FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
        e->op = op;
        e->u.tree.left = left;
        e->u.tree.right = right;
@@ -186,6 +203,8 @@ FcExprCreateOp (FcExpr *left, FcOp op, FcExpr *right)
 void
 FcExprDestroy (FcExpr *e)
 {
+    if (!e)
+       return;
     switch (e->op) {
     case FcOpInteger:
        break;
@@ -224,6 +243,7 @@ FcExprDestroy (FcExpr *e)
     case FcOpMore:
     case FcOpMoreEqual:
     case FcOpContains:
+    case FcOpListing:
     case FcOpNotContains:
     case FcOpPlus:
     case FcOpMinus:
@@ -234,12 +254,17 @@ FcExprDestroy (FcExpr *e)
        FcExprDestroy (e->u.tree.right);
        /* fall through */
     case FcOpNot:
+    case FcOpFloor:
+    case FcOpCeil:
+    case FcOpRound:
+    case FcOpTrunc:
        FcExprDestroy (e->u.tree.left);
        break;
     case FcOpNil:
     case FcOpInvalid:
        break;
     }
+    FcMemFree (FC_MEM_EXPR, sizeof (FcExpr));
     free (e);
 }
 
@@ -293,6 +318,11 @@ typedef enum _FcElement {
     FcElementDefault,
     FcElementFamily,
 
+    FcElementSelectfont,
+    FcElementAcceptfont,
+    FcElementRejectfont,
+    FcElementGlob,
+
     FcElementTest,
     FcElementEdit,
     FcElementInt,
@@ -319,6 +349,10 @@ typedef enum _FcElement {
     FcElementDivide,
     FcElementNot,
     FcElementIf,
+    FcElementFloor,
+    FcElementCeil,
+    FcElementRound,
+    FcElementTrunc,
     FcElementUnknown
 } FcElement;
 
@@ -345,6 +379,11 @@ FcElementMap (const XML_Char *name)
        { "default",    FcElementDefault },
        { "family",     FcElementFamily },
 
+       { "selectfont", FcElementSelectfont },
+       { "acceptfont", FcElementAcceptfont },
+       { "rejectfont", FcElementRejectfont },
+       { "glob",       FcElementGlob },
+
        { "test",       FcElementTest },
        { "edit",       FcElementEdit },
        { "int",        FcElementInt },
@@ -371,6 +410,10 @@ FcElementMap (const XML_Char *name)
        { "divide",     FcElementDivide },
        { "not",        FcElementNot },
        { "if",         FcElementIf },
+       { "floor",      FcElementFloor },
+       { "ceil",       FcElementCeil },
+       { "round",      FcElementRound },
+       { "trunc",      FcElementTrunc },
        
        { 0,            0 }
     };
@@ -396,6 +439,7 @@ typedef enum _FcVStackTag {
     FcVStackFamily,
     FcVStackField,
     FcVStackConstant,
+    FcVStackGlob,
     
     FcVStackPrefer,
     FcVStackAccept,
@@ -491,6 +535,7 @@ FcVStackCreate (void)
     new = malloc (sizeof (FcVStack));
     if (!new)
        return 0;
+    FcMemAlloc (FC_MEM_VSTACK, sizeof (FcVStack));
     new->tag = FcVStackNone;
     new->prev = 0;
     return new;
@@ -511,6 +556,7 @@ FcVStackDestroy (FcVStack *vstack)
        case FcVStackFamily:
        case FcVStackField:
        case FcVStackConstant:
+       case FcVStackGlob:
            FcStrFree (vstack->u.string);
            break;
        case FcVStackInteger:
@@ -534,6 +580,7 @@ FcVStackDestroy (FcVStack *vstack)
            FcEditDestroy (vstack->u.edit);
            break;
        }
+       FcMemFree (FC_MEM_VSTACK, sizeof (FcVStack));
        free (vstack);
     }
 }
@@ -704,6 +751,7 @@ FcConfigSaveAttr (const XML_Char **attr)
     new = malloc ((i + 1) * sizeof (FcChar8 *) + slen);
     if (!new)
        return 0;
+    FcMemAlloc (FC_MEM_ATTR, 1);    /* size is too expensive */
     s = (FcChar8 *) (new + (i + 1));
     for (i = 0; attr[i]; i++)
     {
@@ -722,6 +770,7 @@ FcPStackPush (FcConfigParse *parse, FcElement element, const XML_Char **attr)
 
     if (!new)
        return FcFalse;
+    FcMemAlloc (FC_MEM_PSTACK, sizeof (FcPStack));
     new->prev = parse->pstack;
     new->element = element;
     if (attr)
@@ -752,7 +801,11 @@ FcPStackPop (FcConfigParse *parse)
     parse->pstack = old->prev;
     FcStrBufDestroy (&old->str);
     if (old->attr)
+    {
+       FcMemFree (FC_MEM_ATTR, 1); /* size is to expensive */
        free (old->attr);
+    }
+    FcMemFree (FC_MEM_PSTACK, sizeof (FcPStack));
     free (old);
     return FcTrue;
 }
@@ -922,7 +975,7 @@ FcStrtod (char *s, char **end)
            buf_end = 0;
            v = strtod (buf, &buf_end);
            if (buf_end)
-               buf_end = s + (buf_end - buf);
+               buf_end = s + (buf_end - buf) + 1 - dlen;
            if (end)
                *end = buf_end;
        }
@@ -1266,8 +1319,17 @@ FcPopExpr (FcConfigParse *parse)
     return expr;
 }
 
+/*
+ * 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.
+ */
 static FcExpr *
-FcPopExprs (FcConfigParse *parse, FcOp op)
+FcPopBinary (FcConfigParse *parse, FcOp op)
 {
     FcExpr  *left, *expr = 0, *new;
 
@@ -1292,9 +1354,39 @@ FcPopExprs (FcConfigParse *parse, FcOp op)
 }
 
 static void
-FcParseExpr (FcConfigParse *parse, FcOp op)
+FcParseBinary (FcConfigParse *parse, FcOp op)
 {
-    FcExpr  *expr = FcPopExprs (parse, 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)))
+    {
+       new = FcExprCreateOp (operand, op, 0);
+       if (!new)
+       {
+           FcExprDestroy (operand);
+           FcConfigMessage (parse, FcSevereError, "out of memory");
+       }
+    }
+    return new;
+}
+
+static void
+FcParseUnary (FcConfigParse *parse, FcOp op)
+{
+    FcExpr  *expr = FcPopUnary (parse, op);
     if (expr)
        FcVStackPushExpr (parse, FcVStackExpr, expr);
 }
@@ -1317,7 +1409,7 @@ FcParseInclude (FcConfigParse *parse)
        ignore_missing = FcTrue;
     if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing))
        parse->error = FcTrue;
-    free (s);
+    FcStrFree (s);
 }
 
 typedef struct _FcOpMap {
@@ -1423,7 +1515,7 @@ FcParseTest (FcConfigParse *parse)
            return;
        }
     }
-    expr = FcPopExprs (parse, FcOpComma);
+    expr = FcPopBinary (parse, FcOpComma);
     if (!expr)
     {
        FcConfigMessage (parse, FcSevereWarning, "missing test expression");
@@ -1493,13 +1585,15 @@ FcParseEdit (FcConfigParse *parse)
            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 edit binding \"%s\"", binding_string);
            return;
        }
     }
-    expr = FcPopExprs (parse, FcOpComma);
+    expr = FcPopBinary (parse, FcOpComma);
     edit = FcEditCreate ((char *) FcStrCopy (name), mode, expr, binding);
     if (!edit)
     {
@@ -1558,6 +1652,30 @@ FcParseMatch (FcConfigParse *parse)
        FcConfigMessage (parse, FcSevereError, "out of memory");
 }
 
+static void
+FcParseAcceptRejectFont (FcConfigParse *parse, FcElement element)
+{
+    FcVStack   *vstack;
+
+    while ((vstack = FcVStackPop (parse)))
+    {
+       switch (vstack->tag) {
+       case FcVStackGlob:
+           if (!FcConfigGlobAdd (parse->config, 
+                                 vstack->u.string,
+                                 element == FcElementAcceptfont))
+           {
+               FcConfigMessage (parse, FcSevereError, "out of memory");
+           }
+           break;
+       default:
+           FcConfigMessage (parse, FcSevereWarning, "bad font selector");
+           break;
+       }
+       FcVStackDestroy (vstack);
+    }
+}
+
 static void
 FcEndElement(void *userData, const XML_Char *name)
 {
@@ -1578,9 +1696,36 @@ FcEndElement(void *userData, const XML_Char *name)
            FcConfigMessage (parse, FcSevereError, "out of memory");
            break;
        }
-       if (!FcConfigAddDir (parse->config, data))
-           FcConfigMessage (parse, FcSevereError, "out of memory");
-       free (data);
+#ifdef _WIN32
+       if (strcmp (data, "WINDOWSFONTDIR") == 0)
+       {
+           int rc;
+           FcStrFree (data);
+           data = malloc (1000);
+           if (!data)
+           {
+               FcConfigMessage (parse, FcSevereError, "out of memory");
+               break;
+           }
+           FcMemAlloc (FC_MEM_STRING, 1000);
+           rc = GetWindowsDirectory (data, 800);
+           if (rc == 0 || rc > 800)
+           {
+               FcConfigMessage (parse, FcSevereError, "GetWindowsDirectory failed");
+               FcStrFree (data);
+               break;
+           }
+           if (data [strlen (data) - 1] != '\\')
+               strcat (data, "\\");
+           strcat (data, "fonts");
+       }
+#endif
+       if (!FcStrUsesHome (data) || FcConfigHome ())
+       {
+           if (!FcConfigAddDir (parse->config, data))
+               FcConfigMessage (parse, FcSevereError, "out of memory");
+       }
+       FcStrFree (data);
        break;
     case FcElementCache:
        data = FcStrBufDone (&parse->pstack->str);
@@ -1589,9 +1734,12 @@ FcEndElement(void *userData, const XML_Char *name)
            FcConfigMessage (parse, FcSevereError, "out of memory");
            break;
        }
-       if (!FcConfigSetCache (parse->config, data))
-           FcConfigMessage (parse, FcSevereError, "out of memory");
-       free (data);
+       if (!FcStrUsesHome (data) || FcConfigHome ())
+       {
+           if (!FcConfigSetCache (parse->config, data))
+               FcConfigMessage (parse, FcSevereError, "out of memory");
+       }
+       FcStrFree (data);
        break;
     case FcElementInclude:
        FcParseInclude (parse);
@@ -1650,7 +1798,15 @@ FcEndElement(void *userData, const XML_Char *name)
     case FcElementCharset:
 /*     FcParseCharset (parse); */
        break;
-
+    case FcElementSelectfont:
+       break;
+    case FcElementAcceptfont:
+    case FcElementRejectfont:
+       FcParseAcceptRejectFont (parse, parse->pstack->element);
+       break;
+    case FcElementGlob:
+       FcParseString (parse, FcVStackGlob);
+       break;
     case FcElementName:
        FcParseString (parse, FcVStackField);
        break;
@@ -1658,52 +1814,64 @@ FcEndElement(void *userData, const XML_Char *name)
        FcParseString (parse, FcVStackConstant);
        break;
     case FcElementOr:
-       FcParseExpr (parse, FcOpOr);
+       FcParseBinary (parse, FcOpOr);
        break;
     case FcElementAnd:
-       FcParseExpr (parse, FcOpAnd);
+       FcParseBinary (parse, FcOpAnd);
        break;
     case FcElementEq:
-       FcParseExpr (parse, FcOpEqual);
+       FcParseBinary (parse, FcOpEqual);
        break;
     case FcElementNotEq:
-       FcParseExpr (parse, FcOpNotEqual);
+       FcParseBinary (parse, FcOpNotEqual);
        break;
     case FcElementLess:
-       FcParseExpr (parse, FcOpLess);
+       FcParseBinary (parse, FcOpLess);
        break;
     case FcElementLessEq:
-       FcParseExpr (parse, FcOpLessEqual);
+       FcParseBinary (parse, FcOpLessEqual);
        break;
     case FcElementMore:
-       FcParseExpr (parse, FcOpMore);
+       FcParseBinary (parse, FcOpMore);
        break;
     case FcElementMoreEq:
-       FcParseExpr (parse, FcOpMoreEqual);
+       FcParseBinary (parse, FcOpMoreEqual);
        break;
     case FcElementContains:
-       FcParseExpr (parse, FcOpContains);
+       FcParseBinary (parse, FcOpContains);
        break;
     case FcElementNotContains:
-       FcParseExpr (parse, FcOpNotContains);
+       FcParseBinary (parse, FcOpNotContains);
        break;
     case FcElementPlus:
-       FcParseExpr (parse, FcOpPlus);
+       FcParseBinary (parse, FcOpPlus);
        break;
     case FcElementMinus:
-       FcParseExpr (parse, FcOpMinus);
+       FcParseBinary (parse, FcOpMinus);
        break;
     case FcElementTimes:
-       FcParseExpr (parse, FcOpTimes);
+       FcParseBinary (parse, FcOpTimes);
        break;
     case FcElementDivide:
-       FcParseExpr (parse, FcOpDivide);
+       FcParseBinary (parse, FcOpDivide);
        break;
     case FcElementNot:
-       FcParseExpr (parse, FcOpNot);
+       FcParseUnary (parse, FcOpNot);
        break;
     case FcElementIf:
-       FcParseExpr (parse, FcOpQuest);
+       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);
        break;
     case FcElementUnknown:
        break;
@@ -1759,10 +1927,13 @@ FcConfigParseAndLoad (FcConfig      *config,
        goto bail0;
     
     if (!FcStrSetAdd (config->configFiles, filename))
+    {
+       FcStrFree (filename);
        goto bail0;
+    }
 
     f = fopen ((char *) filename, "r");
-    free (filename);
+    FcStrFree (filename);
     if (!f)
        goto bail0;