* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
#include <stdarg.h>
+/* XXX Document the language.
+ *
+ * These are mostly the features implemented but not documented:
+ *
+ * width %[[-]width]{tag}
+ * index %{tag[ids]}
+ * name= %{tag=|decorator}
+ * :name= %{:tag=|decorator}
+ * subexpr %{{expr}|decorator1|decorator2}
+ * delete %{-charset,lang{expr}|decorator}
+ * filter %{+family,familylang{expr}|decorator}
+ * cond %{?tag1,tag2,!tag3{}{}}
+ * decorat %{tag|decorator1|decorator2}
+ * default %{parameter:-word}
+ * array %{[]family,familylang{expr}|decorator}
+ * langset enumeration using the same syntax as arrays
+ *
+ * filters:
+ * basename FcStrBasename
+ * dirname FcStrDirname
+ * downcase FcStrDowncase
+ * shescape
+ * cescape
+ * xmlescape
+ * delete delete chars
+ * escape escape chars
+ * translate translate chars
+ *
+ * builtins:
+ * unparse
+ * fcmatch
+ * fclist
+ * pkgkit
+ */
+
/*
* Some ideas for future syntax extensions:
*
- * - langset enumeration using same syntax as array enumeration
* - allow indexing subexprs using '%{[idx]elt1,elt2{subexpr}}'
* - conditional/filtering/deletion on binding (using '(w)'/'(s)'/'(=)' notation)
*/
#define FCMATCH_FORMAT "%{file:-<unknown filename>|basename}: \"%{family[0]:-<unknown family>}\" \"%{style[0]:-<unknown style>}\""
#define FCLIST_FORMAT "%{?file{%{file}: }}%{=unparse}"
+#define PKGKIT_FORMAT "%{[]family{font(%{family|downcase|delete( )})\n}}%{[]lang{font(:lang=%{lang|downcase|translate(_,-)})\n}}"
static void
ret = FcPatternFormatToBuf (pat, (const FcChar8 *) format, buf)
BUILTIN ("fcmatch", FCMATCH_FORMAT);
BUILTIN ("fclist", FCLIST_FORMAT);
+ BUILTIN ("pkgkit", PKGKIT_FORMAT);
#undef BUILTIN
else
ret = FcFalse;
const FcChar8 *format_save;
int idx;
FcBool ret, done;
+ FcStrList *lang_strs;
if (!expect_char (c, '[') ||
!expect_char (c, ']'))
}
while (consume_char (c, ','));
+ /* If we have one element and it's of type FcLangSet, we want
+ * to enumerate the languages in it. */
+ lang_strs = NULL;
+ if (os->nobject == 1)
+ {
+ FcLangSet *langset;
+ if (FcResultMatch ==
+ FcPatternGetLangSet (pat, os->objects[0], idx, &langset))
+ {
+ FcStrSet *ss;
+ if (!(ss = FcLangSetGetLangs (langset)) ||
+ !(lang_strs = FcStrListCreate (ss)))
+ goto bail0;
+ }
+ }
+
subpat = FcPatternDuplicate (pat);
if (!subpat)
goto bail0;
done = FcTrue;
- for (i = 0; i < os->nobject; i++)
+ if (lang_strs)
{
- FcValue v;
-
- /* XXX this can be optimized by accessing valuelist linked lists
- * directly and remembering where we were. Most (all) value lists
- * in normal uses are pretty short though (language tags are
- * stored as a LangSet, not separate values.). */
- FcPatternDel (subpat, os->objects[i]);
- if (FcResultMatch ==
- FcPatternGet (pat, os->objects[i], idx, &v))
+ FcChar8 *lang;
+
+ FcPatternDel (subpat, os->objects[0]);
+ if ((lang = FcStrListNext (lang_strs)))
{
- FcPatternAdd (subpat, os->objects[i], v, FcFalse);
+ FcPatternAddString (subpat, os->objects[0], lang);
done = FcFalse;
}
}
+ else
+ {
+ for (i = 0; i < os->nobject; i++)
+ {
+ FcValue v;
+
+ /* XXX this can be optimized by accessing valuelist linked lists
+ * directly and remembering where we were. Most (all) value lists
+ * in normal uses are pretty short though (language tags are
+ * stored as a LangSet, not separate values.). */
+ FcPatternDel (subpat, os->objects[i]);
+ if (FcResultMatch ==
+ FcPatternGet (pat, os->objects[i], idx, &v))
+ {
+ FcPatternAdd (subpat, os->objects[i], v, FcFalse);
+ done = FcFalse;
+ }
+ }
+ }
if (!done)
{
idx++;
} while (!done);
+ if (c->format == format_save)
+ skip_subexpr (c);
+
bail:
FcPatternDestroy (subpat);
bail0:
+ if (lang_strs)
+ FcStrListDone (lang_strs);
FcObjectSetDestroy (os);
return ret;