+static FcChar8 *
+convert (FcFormatContext *c,
+ const FcChar8 *str)
+{
+ if (!read_word (c))
+ return NULL;
+ else if (0 == strcmp ((const char *) c->word, "downcase"))
+ return FcStrDowncase (str);
+ else if (0 == strcmp ((const char *) c->word, "basename"))
+ return FcStrBasename (str);
+ else if (0 == strcmp ((const char *) c->word, "dirname"))
+ return FcStrDirname (str);
+
+ message ("unknown converter \"%s\"",
+ c->word);
+ return NULL;
+}
+
+static FcBool
+maybe_interpret_converts (FcFormatContext *c,
+ FcStrBuf *buf,
+ int start)
+{
+ while (consume_char (c, '|'))
+ {
+ const FcChar8 *str;
+ FcChar8 *new_str;
+
+ /* nul-terminate the buffer */
+ FcStrBufChar (buf, '\0');
+ if (buf->failed)
+ return FcFalse;
+ str = buf->buf + start;
+
+ if (!(new_str = convert (c, str)))
+ return FcFalse;
+
+ /* replace in the buffer */
+ buf->len = start;
+ FcStrBufString (buf, new_str);
+ free (new_str);
+ }
+
+ return FcTrue;
+}
+
+static FcBool
+align_to_width (FcStrBuf *buf,
+ int start,
+ int width)
+{
+ int len;
+
+ if (buf->failed)
+ return FcFalse;
+
+ len = buf->len - start;
+ if (len < -width)
+ {
+ /* left align */
+ while (len++ < -width)
+ FcStrBufChar (buf, ' ');
+ }
+ else if (len < width)
+ {
+ int old_len;
+ old_len = len;
+ /* right align */
+ while (len++ < width)
+ FcStrBufChar (buf, ' ');
+ if (buf->failed)
+ return FcFalse;
+ len = old_len;
+ memmove (buf->buf + buf->len - len,
+ buf->buf + buf->len - width,
+ len);
+ memset (buf->buf + buf->len - width,
+ ' ',
+ width - len);
+ }
+
+ return !buf->failed;
+}