[fcformat] Add conditionals
The conditional '%{?elt1,elt2,!elt3{expr1}{expr2}}' will evaluate expr1 if elt1 and elt2 exist in pattern and elt3 doesn't exist, and expr2 otherwise. The '{expr2}' part is optional.
This commit is contained in:
parent
8c31a2434d
commit
7717b25ffd
146
src/fcformat.c
146
src/fcformat.c
|
@ -150,7 +150,7 @@ read_elt_name_to_scratch (FcFormatContext *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
interpret (FcFormatContext *c,
|
interpret_expr (FcFormatContext *c,
|
||||||
FcPattern *pat,
|
FcPattern *pat,
|
||||||
FcStrBuf *buf,
|
FcStrBuf *buf,
|
||||||
FcChar8 term);
|
FcChar8 term);
|
||||||
|
@ -161,10 +161,94 @@ interpret_subexpr (FcFormatContext *c,
|
||||||
FcStrBuf *buf)
|
FcStrBuf *buf)
|
||||||
{
|
{
|
||||||
return expect_char (c, '{') &&
|
return expect_char (c, '{') &&
|
||||||
interpret (c, pat, buf, '}') &&
|
interpret_expr (c, pat, buf, '}') &&
|
||||||
expect_char (c, '}');
|
expect_char (c, '}');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FcBool
|
||||||
|
maybe_interpret_subexpr (FcFormatContext *c,
|
||||||
|
FcPattern *pat,
|
||||||
|
FcStrBuf *buf)
|
||||||
|
{
|
||||||
|
return (*c->format == '{') ?
|
||||||
|
interpret_subexpr (c, pat, buf) :
|
||||||
|
FcTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FcBool
|
||||||
|
skip_subexpr (FcFormatContext *c);
|
||||||
|
|
||||||
|
static FcBool
|
||||||
|
skip_percent (FcFormatContext *c)
|
||||||
|
{
|
||||||
|
if (!expect_char (c, '%'))
|
||||||
|
return FcFalse;
|
||||||
|
|
||||||
|
/* skip an optional width specifier */
|
||||||
|
strtol ((const char *) c->format, (char **) &c->format, 10);
|
||||||
|
|
||||||
|
if (!expect_char (c, '{'))
|
||||||
|
return FcFalse;
|
||||||
|
|
||||||
|
while(*c->format && *c->format != '}')
|
||||||
|
{
|
||||||
|
switch (*c->format)
|
||||||
|
{
|
||||||
|
case '\\':
|
||||||
|
c->format++; /* skip over '\\' */
|
||||||
|
if (*c->format)
|
||||||
|
c->format++;
|
||||||
|
continue;
|
||||||
|
case '{':
|
||||||
|
if (!skip_subexpr (c))
|
||||||
|
return FcFalse;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
c->format++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return expect_char (c, '}');
|
||||||
|
}
|
||||||
|
|
||||||
|
static FcBool
|
||||||
|
skip_expr (FcFormatContext *c)
|
||||||
|
{
|
||||||
|
while(*c->format && *c->format != '}')
|
||||||
|
{
|
||||||
|
switch (*c->format)
|
||||||
|
{
|
||||||
|
case '\\':
|
||||||
|
c->format++; /* skip over '\\' */
|
||||||
|
if (*c->format)
|
||||||
|
c->format++;
|
||||||
|
continue;
|
||||||
|
case '%':
|
||||||
|
if (!skip_percent (c))
|
||||||
|
return FcFalse;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
c->format++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FcTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FcBool
|
||||||
|
skip_subexpr (FcFormatContext *c)
|
||||||
|
{
|
||||||
|
return expect_char (c, '{') &&
|
||||||
|
skip_expr (c) &&
|
||||||
|
expect_char (c, '}');
|
||||||
|
}
|
||||||
|
|
||||||
|
static FcBool
|
||||||
|
maybe_skip_subexpr (FcFormatContext *c)
|
||||||
|
{
|
||||||
|
return (*c->format == '{') ?
|
||||||
|
skip_subexpr (c) :
|
||||||
|
FcTrue;
|
||||||
|
}
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
interpret_simple_tag (FcFormatContext *c,
|
interpret_simple_tag (FcFormatContext *c,
|
||||||
FcPattern *pat,
|
FcPattern *pat,
|
||||||
|
@ -274,6 +358,52 @@ interpret_delete (FcFormatContext *c,
|
||||||
return FcTrue;
|
return FcTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FcBool
|
||||||
|
interpret_conditional (FcFormatContext *c,
|
||||||
|
FcPattern *pat,
|
||||||
|
FcStrBuf *buf)
|
||||||
|
{
|
||||||
|
FcBool pass;
|
||||||
|
|
||||||
|
if (!expect_char (c, '?'))
|
||||||
|
return FcFalse;
|
||||||
|
|
||||||
|
pass = FcTrue;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
FcBool negate;
|
||||||
|
FcValue v;
|
||||||
|
|
||||||
|
negate = consume_char (c, '!');
|
||||||
|
|
||||||
|
if (!read_elt_name_to_scratch (c))
|
||||||
|
return FcFalse;
|
||||||
|
|
||||||
|
pass = pass &&
|
||||||
|
(negate ^
|
||||||
|
FcResultMatch == FcPatternGet (pat,
|
||||||
|
(const char *) c->scratch,
|
||||||
|
0, &v));
|
||||||
|
}
|
||||||
|
while (consume_char (c, ','));
|
||||||
|
|
||||||
|
if (pass)
|
||||||
|
{
|
||||||
|
if (!interpret_subexpr (c, pat, buf) ||
|
||||||
|
!maybe_skip_subexpr (c))
|
||||||
|
return FcFalse;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!skip_subexpr (c) ||
|
||||||
|
!maybe_interpret_subexpr (c, pat, buf))
|
||||||
|
return FcFalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FcTrue;
|
||||||
|
}
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
interpret_percent (FcFormatContext *c,
|
interpret_percent (FcFormatContext *c,
|
||||||
FcPattern *pat,
|
FcPattern *pat,
|
||||||
|
@ -318,6 +448,12 @@ interpret_percent (FcFormatContext *c,
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
/* conditional on pattern elements */
|
||||||
|
if (!interpret_conditional (c, pat, buf))
|
||||||
|
return FcFalse;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* simple tag */
|
/* simple tag */
|
||||||
if (!interpret_simple_tag (c, pat, buf))
|
if (!interpret_simple_tag (c, pat, buf))
|
||||||
|
@ -377,12 +513,12 @@ static char escaped_char(const char ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
interpret (FcFormatContext *c,
|
interpret_expr (FcFormatContext *c,
|
||||||
FcPattern *pat,
|
FcPattern *pat,
|
||||||
FcStrBuf *buf,
|
FcStrBuf *buf,
|
||||||
FcChar8 term)
|
FcChar8 term)
|
||||||
{
|
{
|
||||||
for (; *c->format && *c->format != term;)
|
while (*c->format && *c->format != term)
|
||||||
{
|
{
|
||||||
switch (*c->format)
|
switch (*c->format)
|
||||||
{
|
{
|
||||||
|
@ -412,7 +548,7 @@ FcPatternFormat (FcPattern *pat, const FcChar8 *format)
|
||||||
if (!FcFormatContextInit (&c, format))
|
if (!FcFormatContextInit (&c, format))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret = interpret (&c, pat, &buf, '\0');
|
ret = interpret_expr (&c, pat, &buf, '\0');
|
||||||
if (buf.failed)
|
if (buf.failed)
|
||||||
ret = FcFalse;
|
ret = FcFalse;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue