]> git.wh0rd.org - fontconfig.git/blame - src/fcformat.c
[fcformat] Refactor and restructure code for upcoming changes
[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
27b3e2dd 43typedef struct _FcFormatContext
0c93b91d 44{
27b3e2dd
BE
45 const FcChar8 *format_orig;
46 const FcChar8 *format;
47 int format_len;
48 FcChar8 *scratch;
49} FcFormatContext;
c493c3b7 50
27b3e2dd
BE
51static void
52FcFormatContextInit (FcFormatContext *c,
53 const FcChar8 *format)
54{
55 c->format_orig = c->format = format;
56 c->format_len = strlen ((const char *) format);
57 c->scratch = malloc (c->format_len + 1);
58}
c493c3b7 59
27b3e2dd
BE
60static void
61FcFormatContextDone (FcFormatContext *c)
62{
63 if (c)
64 {
65 free (c->scratch);
66 }
67}
c493c3b7 68
27b3e2dd
BE
69static FcBool
70consume_char (FcFormatContext *c,
71 FcChar8 term)
72{
73 if (*c->format != term)
0c93b91d 74 {
27b3e2dd
BE
75 message ("Pattern format error: expected '%c' at %d",
76 term, c->format - c->format_orig + 1);
77 return FcFalse;
78 }
0c93b91d 79
27b3e2dd
BE
80 c->format++;
81 return FcTrue;
82}
0c93b91d 83
27b3e2dd
BE
84static void
85interpret_percent (FcFormatContext *c,
86 FcPattern *pat,
87 FcStrBuf *buf)
88{
89 int width, before;
90 FcChar8 *p;
91 FcPatternElt *e;
0c93b91d 92
27b3e2dd
BE
93 if (!consume_char (c, '%'))
94 return;
95
96 if (*c->format == '%') /* "%%" */
97 {
98 FcStrBufChar (buf, *c->format++);
99 return;
100 }
101
102 /* parse an optional width specifier */
103 width = strtol ((const char *) c->format, (char **) &c->format, 10);
104
105 before = buf->len;
106
107 if (!consume_char (c, '{'))
108 return;
0c93b91d 109
27b3e2dd
BE
110 p = (FcChar8 *) strpbrk ((const char *) c->format, "}" /* "=?:}" */);
111 if (!p)
112 {
113 message ("Pattern format missing closing brace for opening brace at %d",
114 c->format-1 - c->format_orig + 1);
115 return;
0c93b91d 116 }
27b3e2dd
BE
117 /* extract the element name */
118 memcpy (c->scratch, c->format, p - c->format);
119 c->scratch[p - c->format] = '\0';
120 c->format = p;
121
122 e = FcPatternObjectFindElt (pat, FcObjectFromName ((const char *) c->scratch));
123 if (e)
124 {
125 FcValueListPtr l;
126 l = FcPatternEltValues(e);
127 FcNameUnparseValueList (buf, l, '\0');
c493c3b7
BE
128 }
129
27b3e2dd
BE
130 /* handle filters, if any */
131 /* XXX */
132
c493c3b7
BE
133 /* align to width */
134 if (!buf->failed)
135 {
136 int after, len;
137
138 after = buf->len;
139
140 len = after - before;
141
142 if (len < -width)
143 {
144 /* left align */
145 while (len++ < -width)
146 FcStrBufChar (buf, ' ');
147 }
148 else if (len < width)
149 {
150 /* right align */
151 while (len++ < width)
152 FcStrBufChar (buf, ' ');
153 len = after - before;
154 memmove (buf->buf + buf->len - len,
155 buf->buf + buf->len - width,
156 len);
157 memset (buf->buf + buf->len - width,
158 ' ',
159 width - len);
160 }
0c93b91d 161 }
c493c3b7 162
27b3e2dd 163 consume_char (c, '}');
0c93b91d
BE
164}
165
166static char escaped_char(const char ch)
167{
168 switch (ch) {
169 case 'a': return '\a';
170 case 'b': return '\b';
171 case 'f': return '\f';
172 case 'n': return '\n';
173 case 'r': return '\r';
174 case 't': return '\t';
175 case 'v': return '\v';
176 default: return ch;
177 }
178}
179
27b3e2dd
BE
180static void
181interpret (FcFormatContext *c,
182 FcPattern *pat,
183 FcStrBuf *buf,
184 FcChar8 term)
0c93b91d 185{
27b3e2dd 186 for (; *c->format && *c->format != term;)
0c93b91d 187 {
27b3e2dd 188 switch (*c->format)
0c93b91d
BE
189 {
190 case '\\':
27b3e2dd
BE
191 c->format++; /* skip over '\\' */
192 if (*c->format)
193 FcStrBufChar (buf, escaped_char (*c->format++));
0c93b91d
BE
194 continue;
195 case '%':
27b3e2dd 196 interpret_percent (c, pat, buf);
0c93b91d
BE
197 continue;
198 }
27b3e2dd 199 FcStrBufChar (buf, *c->format++);
0c93b91d 200 }
27b3e2dd 201 if (*c->format != term)
0c93b91d 202 message ("Pattern format ended while looking for '%c'", term);
0c93b91d
BE
203}
204
205FcChar8 *
206FcPatternFormat (FcPattern *pat, const FcChar8 *format)
207{
0c93b91d 208 FcStrBuf buf;
27b3e2dd 209 FcFormatContext c;
0c93b91d
BE
210
211 FcStrBufInit (&buf, 0, 0);
27b3e2dd 212 FcFormatContextInit (&c, format);
0c93b91d 213
27b3e2dd 214 interpret (&c, pat, &buf, '\0');
0c93b91d 215
27b3e2dd 216 FcFormatContextDone (&c);
0c93b91d
BE
217 return FcStrBufDone (&buf);
218}
219
220#define __fcformat__
221#include "fcaliastail.h"
222#undef __fcformat__