summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2009-02-09 20:49:45 -0500
committerBehdad Esfahbod <behdad@behdad.org>2009-02-15 13:40:26 -0800
commitd6506ff6eeb4a4cb0bfe827174e474c7b91ff045 (patch)
treeae5eb3d5389263dad82134bfa518e0e82cec5413 /src
parent27b3e2dddf6a89c66e8d79f4a28b1a0653e8e100 (diff)
[fcformat] Add support for subexpressions
The syntax is '{{expr}}'. Can be used for aligning/justifying an entire subexpr for example.
Diffstat (limited to 'src')
-rw-r--r--src/fcformat.c149
1 files changed, 124 insertions, 25 deletions
diff --git a/src/fcformat.c b/src/fcformat.c
index 415114b..30c5a8d 100644
--- a/src/fcformat.c
+++ b/src/fcformat.c
@@ -33,9 +33,9 @@ message (const char *fmt, ...)
{
va_list args;
va_start (args, fmt);
- fprintf (stderr, "Fontconfig: ");
+ fprintf (stderr, "Fontconfig: Pattern format error:");
vfprintf (stderr, fmt, args);
- fprintf (stderr, "\n");
+ fprintf (stderr, ".\n");
va_end (args);
}
@@ -71,31 +71,107 @@ consume_char (FcFormatContext *c,
FcChar8 term)
{
if (*c->format != term)
+ return FcFalse;
+
+ c->format++;
+ return FcTrue;
+}
+
+static FcBool
+expect_char (FcFormatContext *c,
+ FcChar8 term)
+{
+ FcBool res = consume_char (c, term);
+ if (!res)
+ {
+ if (c->format == c->format_orig + c->format_len)
+ message ("format ended while expecting '%c'",
+ term);
+ else
+ message ("expected '%c' at %d",
+ term, c->format - c->format_orig + 1);
+ }
+ return res;
+}
+
+static FcBool
+FcCharIsPunct (const FcChar8 c)
+{
+ if (c < '0')
+ return FcTrue;
+ if (c <= '9')
+ return FcFalse;
+ if (c < 'A')
+ return FcTrue;
+ if (c <= 'Z')
+ return FcFalse;
+ if (c < 'a')
+ return FcTrue;
+ if (c <= 'z')
+ return FcFalse;
+ if (c <= '~')
+ return FcTrue;
+ return FcFalse;
+}
+
+static FcBool
+read_elt_name_to_scratch (FcFormatContext *c)
+{
+ FcChar8 *p;
+
+ p = c->scratch;
+
+ while (*c->format)
+ {
+ if (*c->format == '\\')
+ {
+ c->format++;
+ if (*c->format)
+ c->format++;
+ continue;
+ }
+ else if (FcCharIsPunct (*c->format))
+ break;
+
+ *p++ = *c->format++;
+ }
+ *p = '\0';
+
+ if (p == c->scratch)
{
- message ("Pattern format error: expected '%c' at %d",
- term, c->format - c->format_orig + 1);
+ message ("expected element name at %d",
+ c->format - c->format_orig + 1);
return FcFalse;
}
- c->format++;
return FcTrue;
}
static void
+interpret (FcFormatContext *c,
+ FcPattern *pat,
+ FcStrBuf *buf,
+ FcChar8 term);
+
+static void
interpret_percent (FcFormatContext *c,
FcPattern *pat,
FcStrBuf *buf)
{
- int width, before;
- FcChar8 *p;
+ int width, before;
+ FcChar8 *p;
FcPatternElt *e;
- if (!consume_char (c, '%'))
+ FcPattern *subpat = pat;
+ FcBool add_colon = FcFalse;
+ FcBool add_elt_name = FcFalse;
+
+ if (!expect_char (c, '%'))
return;
- if (*c->format == '%') /* "%%" */
+ if (consume_char (c, '%')) /* "%%" */
{
- FcStrBufChar (buf, *c->format++);
+ FcStrBufChar (buf, '%');
return;
}
@@ -104,29 +180,50 @@ interpret_percent (FcFormatContext *c,
before = buf->len;
- if (!consume_char (c, '{'))
- return;
+ if (!expect_char (c, '{'))
+ goto bail;
- p = (FcChar8 *) strpbrk ((const char *) c->format, "}" /* "=?:}" */);
- if (!p)
+ if (consume_char (c, '{'))
{
- message ("Pattern format missing closing brace for opening brace at %d",
- c->format-1 - c->format_orig + 1);
- return;
+ /* it's just a subexpression. no tag involved */
+ interpret (c, pat, buf, '}');
+ expect_char (c, '}');
+ goto filter;
}
- /* extract the element name */
- memcpy (c->scratch, c->format, p - c->format);
- c->scratch[p - c->format] = '\0';
- c->format = p;
- e = FcPatternObjectFindElt (pat, FcObjectFromName ((const char *) c->scratch));
+ switch (*c->format) {
+ case ':':
+ add_colon = FcTrue;
+ consume_char (c, ':');
+ break;
+ }
+
+parse_tag:
+ if (!read_elt_name_to_scratch (c))
+ goto bail;
+
+ if (consume_char (c, '='))
+ add_elt_name = FcTrue;
+
+ e = FcPatternObjectFindElt (pat,
+ FcObjectFromName ((const char *) c->scratch));
if (e)
{
FcValueListPtr l;
+
+ if (add_colon)
+ FcStrBufChar (buf, ':');
+ if (add_elt_name)
+ {
+ FcStrBufString (buf, c->scratch);
+ FcStrBufChar (buf, '=');
+ }
+
l = FcPatternEltValues(e);
FcNameUnparseValueList (buf, l, '\0');
}
+filter:
/* handle filters, if any */
/* XXX */
@@ -160,7 +257,11 @@ interpret_percent (FcFormatContext *c,
}
}
- consume_char (c, '}');
+ expect_char (c, '}');
+
+bail:
+ if (subpat != pat)
+ FcPatternDestroy (subpat);
}
static char escaped_char(const char ch)
@@ -198,8 +299,6 @@ interpret (FcFormatContext *c,
}
FcStrBufChar (buf, *c->format++);
}
- if (*c->format != term)
- message ("Pattern format ended while looking for '%c'", term);
}
FcChar8 *