]> git.wh0rd.org - fontconfig.git/blob - src/fcformat.c
[fcformat] Add support for width modifiers
[fontconfig.git] / src / fcformat.c
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
31 static void
32 message (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
43 static FcChar8 *scratch1;
44 static FcChar8 *scratch2;
45 static const FcChar8 *format_orig;
46
47 static const FcChar8 *
48 interpret_percent (FcPattern *pat,
49 FcStrBuf *buf,
50 const FcChar8 *format)
51 {
52 int width, before;
53
54 /* parse an optional width specifier */
55 width = strtol (format, (char **) &format, 10);
56
57 before = buf->len;
58
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");
71 break;
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 '}' */
86 format = p;
87 break;
88 }
89 default:
90 message ("Pattern format has invalid character after '%%' at %d",
91 format - format_orig);
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 }
123 }
124
125 return format;
126 }
127
128 static 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
142 static const FcChar8 *
143 interpret (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
174 FcChar8 *
175 FcPatternFormat (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__