/*
* Some ideas for future syntax extensions:
*
- * - allow indexing subexprs using '%{[idx]elt1,elt2{subexpr}}'
+ * - array enumeration using '%{[]family,familylang{expr}|decorator}'
+ * - langset enumeration using same syntax as array enumeration
* - allow indexing simple tags using '%{elt[idx]}'
+ * - allow indexing subexprs using '%{[idx]elt1,elt2{subexpr}}'
* - conditional/filtering/deletion on binding (using '(w)'/'(s)'/'(=)' notation)
*/
+
+/* fc-match needs '<unknown filename>', etc handling, as well as printing
+ * printing first value only. */
+#define FCMATCH_FORMAT "%{file|basename}: \"%{family}\" \"%{style}\""
+#define FCLIST_FORMAT "%{?file{%{file}: }}%{=unparse}"
+
+
static void
message (const char *fmt, ...)
{
return FcTrue;
}
+static FcBool
+FcPatternFormatToBuf (FcPattern *pat,
+ const FcChar8 *format,
+ FcStrBuf *buf);
+
static FcBool
interpret_builtin (FcFormatContext *c,
FcPattern *pat,
FcStrBuf *buf)
{
- if (!expect_char (c, '='))
- return FcFalse;
+ FcChar8 *new_str;
+ FcBool ret;
- if (!read_word (c))
+ if (!expect_char (c, '=') ||
+ !read_word (c))
return FcFalse;
+
+ /* try simple builtins first */
+ if (0) { }
#define BUILTIN(name, func) \
else if (0 == strcmp ((const char *) c->word, name))\
- return func (c, pat, buf)
-#if 0
- BUILTIN ("unparse", FcNameUnparse);
- BUILTIN ("verbose", FcPatternPrint);
- BUILTIN2 ("fcmatch", FcStrDirname);
- BUILTIN2 ("fclist", FcStrDirname);
- BUILTIN2 ("pkgkit", FcStrDirname);
-#endif
-
- message ("unknown builtin \"%s\"",
- c->word);
- return FcFalse;
+ do { new_str = func (pat); ret = FcTrue; } while (0)
+ BUILTIN ("unparse", FcNameUnparse);
+ /* BUILTIN ("verbose", FcPatternPrint); */
+#undef BUILTIN
+ else
+ ret = FcFalse;
+
+ if (ret)
+ {
+ if (new_str)
+ {
+ FcStrBufString (buf, new_str);
+ free (new_str);
+ return FcTrue;
+ }
+ else
+ return FcFalse;
+ }
+
+ /* now try our custom formats */
+ if (0) { }
+#define BUILTIN(name, format) \
+ else if (0 == strcmp ((const char *) c->word, name))\
+ ret = FcPatternFormatToBuf (pat, (const FcChar8 *) format, buf)
+ BUILTIN ("fcmatch", FCMATCH_FORMAT);
+ BUILTIN ("fclist", FCLIST_FORMAT);
+#undef BUILTIN
+ else
+ ret = FcFalse;
+
+ if (!ret)
+ message ("unknown builtin \"%s\"",
+ c->word);
+
+ return ret;
}
static FcBool
static FcBool
cescape (FcFormatContext *c,
- FcStrBuf *buf,
- const FcChar8 *str)
+ const FcChar8 *str,
+ FcStrBuf *buf)
{
while(*str)
{
static FcBool
shescape (FcFormatContext *c,
- FcStrBuf *buf,
- const FcChar8 *str)
+ const FcChar8 *str,
+ FcStrBuf *buf)
{
FcStrBufChar (buf, '\'');
while(*str)
static FcBool
xmlescape (FcFormatContext *c,
- FcStrBuf *buf,
- const FcChar8 *str)
+ const FcChar8 *str,
+ FcStrBuf *buf)
{
while(*str)
{
static FcBool
delete_chars (FcFormatContext *c,
- FcStrBuf *buf,
- const FcChar8 *str)
+ const FcChar8 *str,
+ FcStrBuf *buf)
{
/* XXX not UTF-8 aware */
static FcBool
escape_chars (FcFormatContext *c,
- FcStrBuf *buf,
- const FcChar8 *str)
+ const FcChar8 *str,
+ FcStrBuf *buf)
{
/* XXX not UTF-8 aware */
static FcBool
translate_chars (FcFormatContext *c,
- FcStrBuf *buf,
- const FcChar8 *str)
+ const FcChar8 *str,
+ FcStrBuf *buf)
{
char *from, *to, repeat;
int from_len, to_len;
FcChar8 buf_static[8192];
FcBool ret;
- if (!expect_char (c, '|'))
+ if (!expect_char (c, '|') ||
+ !read_word (c))
return FcFalse;
- /* nul-terminate the buffer */
+ /* prepare the buffer */
FcStrBufChar (buf, '\0');
if (buf->failed)
return FcFalse;
str = buf->buf + start;
buf->len = start;
- if (!read_word (c))
- return FcFalse;
-
/* try simple converters first */
if (0) { }
#define CONVERTER(name, func) \
{
if (new_str)
{
- /* replace in the buffer */
FcStrBufString (buf, new_str);
free (new_str);
return FcTrue;
if (0) { }
#define CONVERTER(name, func) \
else if (0 == strcmp ((const char *) c->word, name))\
- ret = func (c, &new_buf, str)
+ ret = func (c, str, &new_buf)
CONVERTER ("cescape", cescape);
CONVERTER ("shescape", shescape);
CONVERTER ("xmlescape", xmlescape);
return FcTrue;
}
+static FcBool
+FcPatternFormatToBuf (FcPattern *pat,
+ const FcChar8 *format,
+ FcStrBuf *buf)
+{
+ FcFormatContext c;
+ FcChar8 word_static[1024];
+ FcBool ret;
+
+ if (!FcFormatContextInit (&c, format, word_static, sizeof (word_static)))
+ return FcFalse;
+
+ ret = interpret_expr (&c, pat, buf, '\0');
+
+ FcFormatContextDone (&c);
+
+ return ret;
+}
+
FcChar8 *
-FcPatternFormat (FcPattern *pat, const FcChar8 *format)
+FcPatternFormat (FcPattern *pat,
+ const FcChar8 *format)
{
FcStrBuf buf;
- FcChar8 word_static[1024];
FcChar8 buf_static[8192 - 1024];
- FcFormatContext c;
FcBool ret;
FcStrBufInit (&buf, buf_static, sizeof (buf_static));
- if (!FcFormatContextInit (&c, format, word_static, sizeof (word_static)))
- return NULL;
- ret = interpret_expr (&c, pat, &buf, '\0');
+ ret = FcPatternFormatToBuf (pat, format, &buf);
- FcFormatContextDone (&c);
if (ret)
return FcStrBufDone (&buf);
else