diff options
author | Behdad Esfahbod <behdad@behdad.org> | 2009-02-09 20:49:45 -0500 |
---|---|---|
committer | Behdad Esfahbod <behdad@behdad.org> | 2009-02-15 13:40:26 -0800 |
commit | d6506ff6eeb4a4cb0bfe827174e474c7b91ff045 (patch) | |
tree | ae5eb3d5389263dad82134bfa518e0e82cec5413 | |
parent | 27b3e2dddf6a89c66e8d79f4a28b1a0653e8e100 (diff) |
[fcformat] Add support for subexpressions
The syntax is '{{expr}}'. Can be used for aligning/justifying an entire
subexpr for example.
-rw-r--r-- | src/fcformat.c | 149 |
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 * |