1/*
2 * XFontName.c
3 *
4 * build/parse X Font name strings
5 */
6#ifdef HAVE_CONFIG_H
7# include "config.h"
8#endif
9
10#include	<X11/Xlib.h>
11#include	<X11/Intrinsic.h>
12#include	"XFontName.h"
13#include	<ctype.h>
14
15static const char *
16extractStringField(const char *name, char *buffer, int size,
17                   unsigned int *attrp, unsigned int bit)
18{
19    char *buf = buffer;
20
21    if (!*name)
22        return NULL;
23    while (*name && *name != '-' && size > 0) {
24        *buf++ = *name++;
25        --size;
26    }
27    if (size <= 0)
28        return NULL;
29    *buf = '\0';
30    if (buffer[0] != '*' || buffer[1] != '\0')
31        *attrp |= bit;
32    if (*name == '-')
33        return name + 1;
34    return name;
35}
36
37static const char *
38extractUnsignedField(const char *name, unsigned int *result,
39                     unsigned int *attrp, unsigned int bit)
40{
41    char buf[256];
42    unsigned int i;
43
44    name = extractStringField(name, buf, sizeof(buf), attrp, bit);
45    if (!name)
46        return NULL;
47    if (!(*attrp & bit))
48        return name;
49    i = 0;
50    for (char *c = buf; *c; c++) {
51        if (!isdigit(*c))
52            return NULL;
53        i = i * 10 + (*c - '0');
54    }
55    *result = i;
56    return name;
57}
58
59Bool
60XParseFontName(const char *fontNameString, XFontName *fontName,
61               unsigned int *fontNameAttributes)
62{
63    const char *name = fontNameString;
64    XFontName temp;
65    unsigned int attributes = 0;
66
67#define GetString(field,bit)  do { \
68	if (!(name = extractStringField \
69		(name, temp.field, sizeof (temp.field),\
70		&attributes, bit))) \
71		return False; \
72    } while(0)
73
74#define GetUnsigned(field,bit)  do { \
75	if (!(name = extractUnsignedField \
76		(name, &temp.field, \
77		&attributes, bit))) \
78		return False; \
79    } while(0)
80
81    GetString(Registry, FontNameRegistry);
82    GetString(Foundry, FontNameFoundry);
83    GetString(FamilyName, FontNameFamilyName);
84    GetString(WeightName, FontNameWeightName);
85    GetString(Slant, FontNameSlant);
86    GetString(SetwidthName, FontNameSetwidthName);
87    GetString(AddStyleName, FontNameAddStyleName);
88    GetUnsigned(PixelSize, FontNamePixelSize);
89    GetUnsigned(PointSize, FontNamePointSize);
90    GetUnsigned(ResolutionX, FontNameResolutionX);
91    GetUnsigned(ResolutionY, FontNameResolutionY);
92    GetString(Spacing, FontNameSpacing);
93    GetUnsigned(AverageWidth, FontNameAverageWidth);
94    GetString(CharSetRegistry, FontNameCharSetRegistry);
95    if (!*name) {
96        temp.CharSetEncoding[0] = '\0';
97        attributes |= FontNameCharSetEncoding;
98    }
99    else {
100        GetString(CharSetEncoding, FontNameCharSetEncoding);
101    }
102    *fontName = temp;
103    *fontNameAttributes = attributes;
104    return True;
105}
106
107static char *
108utoa(unsigned int u, char *s, int size)
109{
110    char *t;
111
112    t = s + size;
113    *--t = '\0';
114    do
115        *--t = (u % 10) + '0';
116    while (u /= 10);
117    return t;
118}
119
120Bool
121XFormatFontName(XFontName *fontName, unsigned int fontNameAttributes,
122                XFontNameString fontNameString)
123{
124    XFontNameString tmp;
125    char *name = tmp;
126    const char *f;
127    int left = sizeof(tmp) - 1;
128    char number[32];
129
130#define PutString(field, bit) do { \
131	f = (fontNameAttributes & bit) ? \
132		fontName->field \
133		: "*"; \
134	if ((left -= strlen (f)) < 0) \
135		return False; \
136	while (*f) \
137		if ((*name++ = *f++) == '-') \
138			return False; \
139    } while(0)
140
141#define PutHyphen() do { \
142	if (--left < 0) \
143		return False; \
144	*name++ = '-'; \
145    } while(0)
146
147#define PutUnsigned(field, bit) do { \
148	f = (fontNameAttributes & bit) ? \
149		utoa (fontName->field, number, sizeof (number)) \
150		: "*"; \
151	if ((left -= strlen (f)) < 0) \
152		return False; \
153	while (*f) \
154		*name++ = *f++; \
155    } while(0)
156
157    PutString(Registry, FontNameRegistry);
158    PutHyphen();
159    PutString(Foundry, FontNameFoundry);
160    PutHyphen();
161    PutString(FamilyName, FontNameFamilyName);
162    PutHyphen();
163    PutString(WeightName, FontNameWeightName);
164    PutHyphen();
165    PutString(Slant, FontNameSlant);
166    PutHyphen();
167    PutString(SetwidthName, FontNameSetwidthName);
168    PutHyphen();
169    PutString(AddStyleName, FontNameAddStyleName);
170    PutHyphen();
171    PutUnsigned(PixelSize, FontNamePixelSize);
172    PutHyphen();
173    PutUnsigned(PointSize, FontNamePointSize);
174    PutHyphen();
175    PutUnsigned(ResolutionX, FontNameResolutionX);
176    PutHyphen();
177    PutUnsigned(ResolutionY, FontNameResolutionY);
178    PutHyphen();
179    PutString(Spacing, FontNameSpacing);
180    PutHyphen();
181    PutUnsigned(AverageWidth, FontNameAverageWidth);
182    PutHyphen();
183    PutString(CharSetRegistry, FontNameCharSetRegistry);
184    PutHyphen();
185    PutString(CharSetEncoding, FontNameCharSetEncoding);
186    *name = '\0';
187    strncpy (fontNameString, tmp, sizeof(XFontNameString));
188    fontNameString[sizeof(XFontNameString) - 1] = '\0';
189    return True;
190}
191