156 lines
3.7 KiB
C
156 lines
3.7 KiB
C
|
/*
|
||
|
* 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 <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <stdarg.h>
|
||
|
|
||
|
|
||
|
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__
|