Change to the linux kernel coding style
[wmaker-crm.git] / util / fontconv.c
1
2 #include <string.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <WINGs/WUtil.h>
6
7 #include "../src/wconfig.h"
8
9 #define DEFAULT_FONT "sans serif:pixelsize=12"
10
11 static int countChar(char *str, char c)
12 {
13 int count = 0;
14
15 if (!str)
16 return 0;
17
18 for (; *str != 0; str++) {
19 if (*str == c) {
20 count++;
21 }
22 }
23
24 return count;
25 }
26
27 typedef struct str {
28 char *str;
29 int len;
30 } str;
31
32 #define XLFD_TOKENS 14
33
34 static str *getXLFDTokens(char *xlfd)
35 {
36 static str tokens[XLFD_TOKENS];
37 int i, len, size;
38 char *ptr;
39
40 if (!xlfd || *xlfd != '-' || countChar(xlfd, '-') < XLFD_TOKENS)
41 return NULL;
42
43 memset(tokens, 0, sizeof(str) * XLFD_TOKENS);
44
45 len = strlen(xlfd);
46
47 for (ptr = xlfd, i = 0; i < XLFD_TOKENS && len > 0; i++) {
48 /* skip one '-' */
49 ptr++;
50 len--;
51 if (len <= 0)
52 break;
53 size = strcspn(ptr, "-,");
54 tokens[i].str = ptr;
55 tokens[i].len = size;
56 ptr += size;
57 len -= size;
58 }
59
60 return tokens;
61 }
62
63 static int strToInt(str * token)
64 {
65 int res = 0, pos, c;
66
67 if (token->len == 0 || token->str[0] == '*') {
68 return -1;
69 } else {
70 for (res = 0, pos = 0; pos < token->len; pos++) {
71 c = token->str[pos] - '0';
72 if (c < 0 || c > 9)
73 break;
74 res = res * 10 + c;
75 }
76 }
77 return res;
78 }
79
80 static char *mapWeightToName(str * weight)
81 {
82 char *normalNames[] = { "medium", "normal", "regular" };
83 static char buf[32];
84 int i;
85
86 if (weight->len == 0)
87 return "";
88
89 for (i = 0; i < sizeof(normalNames) / sizeof(char *); i++) {
90 if (strlen(normalNames[i]) == weight->len && strncmp(normalNames[i], weight->str, weight->len)) {
91 return "";
92 }
93 }
94
95 snprintf(buf, sizeof(buf), ":%.*s", weight->len, weight->str);
96
97 return buf;
98 }
99
100 static char *mapSlantToName(str * slant)
101 {
102 if (slant->len == 0)
103 return "";
104
105 switch (slant->str[0]) {
106 case 'i':
107 return ":italic";
108 case 'o':
109 return ":oblique";
110 case 'r':
111 default:
112 return "";
113 }
114 }
115
116 char *xlfdToFc(char *xlfd, char *useFamily, Bool keepXLFD)
117 {
118 str *tokens, *family, *weight, *slant;
119 char *name, buf[64];
120 int size, pixelsize;
121
122 tokens = getXLFDTokens(xlfd);
123 if (!tokens)
124 return wstrdup(DEFAULT_FONT);
125
126 family = &(tokens[1]);
127 weight = &(tokens[2]);
128 slant = &(tokens[3]);
129 pixelsize = strToInt(&tokens[6]);
130 size = strToInt(&tokens[7]);
131
132 if (useFamily) {
133 name = wstrdup(useFamily);
134 } else {
135 if (family->len == 0 || family->str[0] == '*')
136 return wstrdup(DEFAULT_FONT);
137
138 snprintf(buf, sizeof(buf), "%.*s", family->len, family->str);
139 name = wstrdup(buf);
140 }
141
142 if (size > 0 && pixelsize <= 0) {
143 snprintf(buf, sizeof(buf), "-%d", size / 10);
144 name = wstrappend(name, buf);
145 }
146
147 name = wstrappend(name, mapWeightToName(weight));
148 name = wstrappend(name, mapSlantToName(slant));
149
150 if (size <= 0 && pixelsize <= 0) {
151 name = wstrappend(name, ":pixelsize=12");
152 } else if (pixelsize > 0) {
153 /* if pixelsize is present size will be ignored so we skip it */
154 snprintf(buf, sizeof(buf), ":pixelsize=%d", pixelsize);
155 name = wstrappend(name, buf);
156 }
157
158 if (keepXLFD) {
159 name = wstrappend(name, ":xlfd=");
160 name = wstrappend(name, xlfd);
161 }
162
163 return name;
164 }
165
166 /* return converted font (if conversion is needed) else the original font */
167 char *convertFont(char *font, Bool keepXLFD)
168 {
169 if (font[0] == '-') {
170 if (MB_CUR_MAX < 2) {
171 return xlfdToFc(font, NULL, keepXLFD);
172 } else {
173 return xlfdToFc(font, "sans serif", keepXLFD);
174 }
175 } else {
176 return font;
177 }
178 }