]> git.wh0rd.org - fontconfig.git/blame - src/fcformat.c
[fcformat] Add support for width modifiers
[fontconfig.git] / src / fcformat.c
CommitLineData
0c93b91d
BE
1/*
2 * Copyright © 2008 Red Hat, Inc.
3 *
4 * Red Hat Author(s): Behdad Esfahbod
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
15 *
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25#include "fcint.h"
26#include <stdlib.h>
27#include <string.h>
28#include <stdarg.h>
29
30
31static void
32message (const char *fmt, ...)
33{
34 va_list args;
35 va_start (args, fmt);
36 fprintf (stderr, "Fontconfig: ");
37 vfprintf (stderr, fmt, args);
38 fprintf (stderr, "\n");
39 va_end (args);
40}
41
42
43static FcChar8 *scratch1;
44static FcChar8 *scratch2;
45static const FcChar8 *format_orig;
46
47static const FcChar8 *
48interpret_percent (FcPattern *pat,
49 FcStrBuf *buf,
50 const FcChar8 *format)
51{
c493c3b7
BE
52 int width, before;
53
54 /* parse an optional width specifier */
55 width = strtol (format, (char **) &format, 10);
56
57 before = buf->len;
58
0c93b91d
BE
59 switch (*format) {
60 case '{':
61 {
62 FcChar8 *p;
63 FcPatternElt *e;
64
65 format++; /* skip over '{' */
66
67 p = (FcChar8 *) strpbrk ((const char *) format, "}");
68 if (!p)
69 {
70 message ("Pattern format missing closing brace");
c493c3b7 71 break;
0c93b91d
BE
72 }
73 /* extract the element name */
74 memcpy (scratch1, format, p - format);
75 scratch1[p - format] = '\0';
76
77 e = FcPatternObjectFindElt (pat, FcObjectFromName ((const char *) scratch1));
78 if (e)
79 {
80 FcValueListPtr l;
81 l = FcPatternEltValues(e);
82 FcNameUnparseValueList (buf, l, '\0');
83 }
84
85 p++; /* skip over '}' */
c493c3b7
BE
86 format = p;
87 break;
0c93b91d
BE
88 }
89 default:
90 message ("Pattern format has invalid character after '%%' at %d",
91 format - format_orig);
c493c3b7
BE
92 break;
93 }
94
95 /* align to width */
96 if (!buf->failed)
97 {
98 int after, len;
99
100 after = buf->len;
101
102 len = after - before;
103
104 if (len < -width)
105 {
106 /* left align */
107 while (len++ < -width)
108 FcStrBufChar (buf, ' ');
109 }
110 else if (len < width)
111 {
112 /* right align */
113 while (len++ < width)
114 FcStrBufChar (buf, ' ');
115 len = after - before;
116 memmove (buf->buf + buf->len - len,
117 buf->buf + buf->len - width,
118 len);
119 memset (buf->buf + buf->len - width,
120 ' ',
121 width - len);
122 }
0c93b91d 123 }
c493c3b7
BE
124
125 return format;
0c93b91d
BE
126}
127
128static char escaped_char(const char ch)
129{
130 switch (ch) {
131 case 'a': return '\a';
132 case 'b': return '\b';
133 case 'f': return '\f';
134 case 'n': return '\n';
135 case 'r': return '\r';
136 case 't': return '\t';
137 case 'v': return '\v';
138 default: return ch;
139 }
140}
141
142static const FcChar8 *
143interpret (FcPattern *pat,
144 FcStrBuf *buf,
145 const FcChar8 *format,
146 FcChar8 term)
147{
148 const FcChar8 *end;
149
150 for (end = format; *end && *end != term;)
151 {
152 switch (*end)
153 {
154 case '\\':
155 end++; /* skip over '\\' */
156 FcStrBufChar (buf, escaped_char (*end++));
157 continue;
158 case '%':
159 end++; /* skip over '%' */
160 if (*end == '%')
161 break;
162 end = interpret_percent (pat, buf, end);
163 continue;
164 }
165 FcStrBufChar (buf, *end);
166 end++;
167 }
168 if (*end != term)
169 message ("Pattern format ended while looking for '%c'", term);
170
171 return end;
172}
173
174FcChar8 *
175FcPatternFormat (FcPattern *pat, const FcChar8 *format)
176{
177 int len;
178 FcStrBuf buf;
179
180 FcStrBufInit (&buf, 0, 0);
181 len = strlen ((const char *) format);
182 scratch1 = malloc (len);
183 scratch2 = malloc (len);
184 format_orig = format;
185
186 interpret (pat, &buf, format, '\0');
187
188 free (scratch1);
189 free (scratch2);
190 return FcStrBufDone (&buf);
191}
192
193#define __fcformat__
194#include "fcaliastail.h"
195#undef __fcformat__