[fcformat] Add support for subexpressions

The syntax is '{{expr}}'.  Can be used for aligning/justifying an entire
subexpr for example.
This commit is contained in:
Behdad Esfahbod 2009-02-09 20:49:45 -05:00
parent 27b3e2dddf
commit d6506ff6ee
1 changed files with 125 additions and 26 deletions

View File

@ -33,9 +33,9 @@ message (const char *fmt, ...)
{ {
va_list args; va_list args;
va_start (args, fmt); va_start (args, fmt);
fprintf (stderr, "Fontconfig: "); fprintf (stderr, "Fontconfig: Pattern format error:");
vfprintf (stderr, fmt, args); vfprintf (stderr, fmt, args);
fprintf (stderr, "\n"); fprintf (stderr, ".\n");
va_end (args); va_end (args);
} }
@ -71,31 +71,107 @@ consume_char (FcFormatContext *c,
FcChar8 term) FcChar8 term)
{ {
if (*c->format != term) if (*c->format != term)
{
message ("Pattern format error: expected '%c' at %d",
term, c->format - c->format_orig + 1);
return FcFalse; return FcFalse;
}
c->format++; c->format++;
return FcTrue; 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 ("expected element name at %d",
c->format - c->format_orig + 1);
return FcFalse;
}
return FcTrue;
}
static void
interpret (FcFormatContext *c,
FcPattern *pat,
FcStrBuf *buf,
FcChar8 term);
static void static void
interpret_percent (FcFormatContext *c, interpret_percent (FcFormatContext *c,
FcPattern *pat, FcPattern *pat,
FcStrBuf *buf) FcStrBuf *buf)
{ {
int width, before; int width, before;
FcChar8 *p; FcChar8 *p;
FcPatternElt *e; FcPatternElt *e;
if (!consume_char (c, '%')) FcPattern *subpat = pat;
FcBool add_colon = FcFalse;
FcBool add_elt_name = FcFalse;
if (!expect_char (c, '%'))
return; return;
if (*c->format == '%') /* "%%" */ if (consume_char (c, '%')) /* "%%" */
{ {
FcStrBufChar (buf, *c->format++); FcStrBufChar (buf, '%');
return; return;
} }
@ -104,29 +180,50 @@ interpret_percent (FcFormatContext *c,
before = buf->len; before = buf->len;
if (!consume_char (c, '{')) if (!expect_char (c, '{'))
return; goto bail;
p = (FcChar8 *) strpbrk ((const char *) c->format, "}" /* "=?:}" */); if (consume_char (c, '{'))
if (!p)
{ {
message ("Pattern format missing closing brace for opening brace at %d", /* it's just a subexpression. no tag involved */
c->format-1 - c->format_orig + 1); interpret (c, pat, buf, '}');
return; 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) if (e)
{ {
FcValueListPtr l; FcValueListPtr l;
if (add_colon)
FcStrBufChar (buf, ':');
if (add_elt_name)
{
FcStrBufString (buf, c->scratch);
FcStrBufChar (buf, '=');
}
l = FcPatternEltValues(e); l = FcPatternEltValues(e);
FcNameUnparseValueList (buf, l, '\0'); FcNameUnparseValueList (buf, l, '\0');
} }
filter:
/* handle filters, if any */ /* handle filters, if any */
/* XXX */ /* 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) static char escaped_char(const char ch)
@ -198,8 +299,6 @@ interpret (FcFormatContext *c,
} }
FcStrBufChar (buf, *c->format++); FcStrBufChar (buf, *c->format++);
} }
if (*c->format != term)
message ("Pattern format ended while looking for '%c'", term);
} }
FcChar8 * FcChar8 *