]> git.wh0rd.org - fontconfig.git/blobdiff - src/fcformat.c
Replace 'KEITH PACKARD' with 'THE AUTHOR(S)' in license text in all files
[fontconfig.git] / src / fcformat.c
index 5aa1977b8a22ec9cf0a0a3c4cc5f4c26b5ee6e86..99c4f858fcd31cd4c8643739863f899f2363d35d 100644 (file)
@@ -13,9 +13,9 @@
  * 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)
  */
@@ -39,6 +73,7 @@
 
 #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
@@ -268,6 +303,7 @@ interpret_builtin (FcFormatContext *c,
        ret = FcPatternFormatToBuf (pat, (const FcChar8 *) format, buf)
     BUILTIN ("fcmatch",  FCMATCH_FORMAT);
     BUILTIN ("fclist",   FCLIST_FORMAT);
+    BUILTIN ("pkgkit",   PKGKIT_FORMAT);
 #undef BUILTIN
     else
        ret = FcFalse;
@@ -540,6 +576,7 @@ interpret_array (FcFormatContext *c,
     const FcChar8 *format_save;
     int            idx;
     FcBool         ret, done;
+    FcStrList      *lang_strs;
 
     if (!expect_char (c, '[') ||
        !expect_char (c, ']'))
@@ -562,6 +599,22 @@ interpret_array (FcFormatContext *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;
@@ -574,22 +627,36 @@ interpret_array (FcFormatContext *c,
 
        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)
        {
@@ -602,9 +669,14 @@ interpret_array (FcFormatContext *c,
        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;