fontconfig/src/fcformat.c

196 lines
4.3 KiB
C
Raw Normal View History

/*
* 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)
{
int width, before;
/* parse an optional width specifier */
width = strtol (format, (char **) &format, 10);
before = buf->len;
switch (*format) {
case '{':
{
FcChar8 *p;
FcPatternElt *e;
format++; /* skip over '{' */
p = (FcChar8 *) strpbrk ((const char *) format, "}");
if (!p)
{
message ("Pattern format missing closing brace");
break;
}
/* 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 '}' */
format = p;
break;
}
default:
message ("Pattern format has invalid character after '%%' at %d",
format - format_orig);
break;
}
/* align to width */
if (!buf->failed)
{
int after, len;
after = buf->len;
len = after - before;
if (len < -width)
{
/* left align */
while (len++ < -width)
FcStrBufChar (buf, ' ');
}
else if (len < width)
{
/* right align */
while (len++ < width)
FcStrBufChar (buf, ' ');
len = after - before;
memmove (buf->buf + buf->len - len,
buf->buf + buf->len - width,
len);
memset (buf->buf + buf->len - width,
' ',
width - len);
}
}
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__