wmaker-check: rewrote parsing of structure fields for callback checker
[wmaker-crm.git] / util / fontconv.c
blob142c4c414d53af3352d562e3ad3c5bf58f6efe42
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
6 #include <WINGs/WUtil.h>
8 #include "../src/wconfig.h"
10 #include "common.h"
13 #define DEFAULT_FONT "sans serif:pixelsize=12"
15 /* X Font Name Suffix field names */
16 enum {
17 FOUNDRY,
18 FAMILY_NAME,
19 WEIGHT_NAME,
20 SLANT,
21 SETWIDTH_NAME,
22 ADD_STYLE_NAME,
23 PIXEL_SIZE,
24 POINT_SIZE,
25 RESOLUTION_X,
26 RESOLUTION_Y,
27 SPACING,
28 AVERAGE_WIDTH,
29 CHARSET_REGISTRY,
30 CHARSET_ENCODING
33 static int countChar(const char *str, char c)
35 int count = 0;
37 if (!str)
38 return 0;
40 for (; *str != 0; str++) {
41 if (*str == c) {
42 count++;
46 return count;
49 typedef struct str {
50 const char *str;
51 int len;
52 } str;
54 #define XLFD_TOKENS 14
56 static str *getXLFDTokens(const char *xlfd)
58 static str tokens[XLFD_TOKENS];
59 int i, len, size;
60 const char *ptr;
62 /* XXX: why does this assume there can't ever be XFNextPrefix? */
63 if (!xlfd || *xlfd != '-' || countChar(xlfd, '-') != XLFD_TOKENS)
64 return NULL;
66 memset(tokens, 0, sizeof(str) * XLFD_TOKENS);
68 len = strlen(xlfd);
70 for (ptr = xlfd, i = 0; i < XLFD_TOKENS && len > 0; i++) {
71 /* skip one '-' */
72 ptr++;
73 len--;
74 if (len <= 0)
75 break;
76 size = strcspn(ptr, "-,");
77 tokens[i].str = ptr;
78 tokens[i].len = size;
79 ptr += size;
80 len -= size;
83 return tokens;
86 static int strToInt(str * token)
88 static char buf[32]; /* enough for an Incredibly Big Number */
90 if (token->len == 0 ||
91 token->str[0] == '*' ||
92 token->len >= sizeof(buf))
93 return -1;
95 memset(buf, 0, sizeof(buf));
96 strncpy(buf, token->str, token->len);
98 /* the code using this will gracefully handle overflows */
99 return (int)strtol(buf, NULL, 10);
102 static char *mapWeightToName(str * weight)
104 static const char *normalNames[] = { "medium", "normal", "regular" };
105 static char buf[32];
106 size_t i;
108 if (weight->len == 0)
109 return "";
111 for (i = 0; i < wlengthof(normalNames); i++) {
112 if (strlen(normalNames[i]) == weight->len && strncmp(normalNames[i], weight->str, weight->len)) {
113 return "";
117 snprintf(buf, sizeof(buf), ":%.*s", weight->len, weight->str);
119 return buf;
122 static char *mapSlantToName(str * slant)
124 if (slant->len == 0)
125 return "";
127 switch (slant->str[0]) {
128 case 'i':
129 return ":italic";
130 case 'o':
131 return ":oblique";
132 case 'r':
133 default:
134 return "";
138 static char *xlfdToFc(const char *xlfd, const char *useFamily, Bool keepXLFD)
140 str *tokens, *family, *weight, *slant;
141 char *name, buf[64];
142 int size, pixelsize;
144 tokens = getXLFDTokens(xlfd);
145 if (!tokens)
146 return wstrdup(DEFAULT_FONT);
148 family = &(tokens[FAMILY_NAME]);
149 weight = &(tokens[WEIGHT_NAME]);
150 slant = &(tokens[SLANT]);
151 pixelsize = strToInt(&tokens[PIXEL_SIZE]);
152 size = strToInt(&tokens[POINT_SIZE]);
154 if (useFamily) {
155 name = wstrdup(useFamily);
156 } else {
157 if (family->len == 0 || family->str[0] == '*')
158 return wstrdup(DEFAULT_FONT);
160 snprintf(buf, sizeof(buf), "%.*s", family->len, family->str);
161 name = wstrdup(buf);
164 if (size > 0 && pixelsize <= 0) {
165 snprintf(buf, sizeof(buf), "-%d", size / 10);
166 name = wstrappend(name, buf);
169 name = wstrappend(name, mapWeightToName(weight));
170 name = wstrappend(name, mapSlantToName(slant));
172 if (size <= 0 && pixelsize <= 0) {
173 name = wstrappend(name, ":pixelsize=12");
174 } else if (pixelsize > 0) {
175 /* if pixelsize is present size will be ignored so we skip it */
176 snprintf(buf, sizeof(buf), ":pixelsize=%d", pixelsize);
177 name = wstrappend(name, buf);
180 if (keepXLFD) {
181 name = wstrappend(name, ":xlfd=");
182 name = wstrappend(name, xlfd);
185 return name;
188 /* return converted font (if conversion is needed) else the original font */
189 char *convertFont(char *font, Bool keepXLFD)
191 if (font[0] == '-') {
192 if (MB_CUR_MAX < 2) {
193 return xlfdToFc(font, NULL, keepXLFD);
194 } else {
195 return xlfdToFc(font, "sans serif", keepXLFD);
197 } else {
198 return font;