/* * Copyright © 2008 Red Hat, Inc. * * Red Hat Author(s): Behdad Esfahbod * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Keith Packard not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Keith Packard makes no * 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, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL KEITH PACKARD 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 * PERFORMANCE OF THIS SOFTWARE. */ #include "fcint.h" #include #include #include static void message (const char *fmt, ...) { va_list args; va_start (args, fmt); fprintf (stderr, "Fontconfig: "); vfprintf (stderr, fmt, args); fprintf (stderr, "\n"); va_end (args); } static FcChar8 *scratch1; static FcChar8 *scratch2; static const FcChar8 *format_orig; static const FcChar8 * interpret_percent (FcPattern *pat, FcStrBuf *buf, const FcChar8 *format) { switch (*format) { case '{': { FcChar8 *p; FcPatternElt *e; format++; /* skip over '{' */ p = (FcChar8 *) strpbrk ((const char *) format, "}"); if (!p) { message ("Pattern format missing closing brace"); return format; } /* extract the element name */ memcpy (scratch1, format, p - format); scratch1[p - format] = '\0'; e = FcPatternObjectFindElt (pat, FcObjectFromName ((const char *) scratch1)); if (e) { FcValueListPtr l; l = FcPatternEltValues(e); FcNameUnparseValueList (buf, l, '\0'); } p++; /* skip over '}' */ return p; } default: message ("Pattern format has invalid character after '%%' at %d", format - format_orig); return format; } } static char escaped_char(const char ch) { switch (ch) { case 'a': return '\a'; case 'b': return '\b'; case 'f': return '\f'; case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; case 'v': return '\v'; default: return ch; } } static const FcChar8 * interpret (FcPattern *pat, FcStrBuf *buf, const FcChar8 *format, FcChar8 term) { const FcChar8 *end; for (end = format; *end && *end != term;) { switch (*end) { case '\\': end++; /* skip over '\\' */ FcStrBufChar (buf, escaped_char (*end++)); continue; case '%': end++; /* skip over '%' */ if (*end == '%') break; end = interpret_percent (pat, buf, end); continue; } FcStrBufChar (buf, *end); end++; } if (*end != term) message ("Pattern format ended while looking for '%c'", term); return end; } FcChar8 * FcPatternFormat (FcPattern *pat, const FcChar8 *format) { int len; FcStrBuf buf; FcStrBufInit (&buf, 0, 0); len = strlen ((const char *) format); scratch1 = malloc (len); scratch2 = malloc (len); format_orig = format; interpret (pat, &buf, format, '\0'); free (scratch1); free (scratch2); return FcStrBufDone (&buf); } #define __fcformat__ #include "fcaliastail.h" #undef __fcformat__