fontset name guess when using multibyte
[wmaker-crm.git] / WINGs / wfont.c
bloba750cd0bad4d985c4201345b5c36623ca7d898a6
2 #include "WINGsP.h"
5 #include <wraster.h>
6 #include <assert.h>
7 #include <X11/Xlocale.h>
9 static char *makeFontSetOfSize(char *fontset, int size);
13 /* XLFD pattern matching */
14 static char*
15 xlfd_get_element (const char *xlfd, int index)
17 const char *p = xlfd;
18 while (*p != 0) {
19 if (*p == '-' && --index == 0) {
20 const char *end = strchr(p + 1, '-');
21 char *buf;
22 size_t len;
23 if (end == 0) end = p + strlen(p);
24 len = end - (p + 1);
25 buf = wmalloc(len);
26 memcpy(buf, p + 1, len);
27 buf[len] = 0;
28 return buf;
30 p++;
32 return strdup("*");
35 /* XLFD pattern matching */
36 static char*
37 generalize_xlfd (const char *xlfd)
39 char *buf;
40 int len;
41 char *weight = xlfd_get_element(xlfd, 3);
42 char *slant = xlfd_get_element(xlfd, 4);
43 char *pxlsz = xlfd_get_element(xlfd, 7);
45 len = snprintf(NULL, 0, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
46 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
47 xlfd, weight, slant, pxlsz, pxlsz);
48 buf = wmalloc(len + 1);
49 snprintf(buf, len + 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
50 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
51 xlfd, weight, slant, pxlsz, pxlsz);
53 free(pxlsz);
54 free(slant);
55 free(weight);
57 return buf;
60 /* XLFD pattern matching */
61 static XFontSet
62 W_CreateFontSetWithGuess(Display *dpy, char *xlfd, char ***missing,
63 int *nmissing, char **def_string)
65 XFontSet fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
67 if (fs != NULL && *nmissing == 0) return fs;
69 /* for non-iso8859-1 language and iso8859-1 specification
70 (this fontset is only for pattern analysis) */
71 if (fs == NULL) {
72 char *old_locale = setlocale(LC_CTYPE, NULL);
73 if (*nmissing != 0) XFreeStringList(*missing);
74 setlocale(LC_CTYPE, "C");
75 fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
76 setlocale(LC_CTYPE, old_locale);
79 /* make XLFD font name for pattern analysis */
80 if (fs != NULL) {
81 XFontStruct **fontstructs;
82 char **fontnames;
83 if (XFontsOfFontSet(fs, &fontstructs, &fontnames) > 0)
84 xlfd = fontnames[0];
87 xlfd = generalize_xlfd (xlfd);
89 if (*nmissing != 0) XFreeStringList(*missing);
90 if (fs != 0) XFreeFontSet(dpy, fs);
92 fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
94 free(xlfd);
95 return fs;
98 WMFont*
99 WMCreateFontSet(WMScreen *scrPtr, char *fontName)
101 WMFont *font;
102 Display *display = scrPtr->display;
103 char **missing;
104 int nmissing = 0;
105 char *defaultString;
106 XFontSetExtents *extents;
108 font = WMHashGet(scrPtr->fontCache, fontName);
109 if (font) {
110 WMRetainFont(font);
111 return font;
114 font = malloc(sizeof(WMFont));
115 if (!font)
116 return NULL;
117 memset(font, 0, sizeof(WMFont));
119 font->notFontSet = 0;
121 font->screen = scrPtr;
123 font->font.set = W_CreateFontSetWithGuess(display, fontName, &missing,
124 &nmissing, &defaultString);
125 if (nmissing > 0 && font->font.set) {
126 int i;
128 wwarning("the following character sets are missing in %s:",
129 fontName);
130 for (i = 0; i < nmissing; i++) {
131 wwarning(missing[i]);
133 XFreeStringList(missing);
134 if (defaultString)
135 wwarning("the string \"%s\" will be used in place of any characters from those sets.",
136 defaultString);
138 if (!font->font.set) {
139 wfree(font);
140 return NULL;
143 extents = XExtentsOfFontSet(font->font.set);
145 font->height = extents->max_logical_extent.height;
146 font->y = font->height - (font->height + extents->max_logical_extent.y);
148 font->refCount = 1;
150 font->name = wstrdup(fontName);
152 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
154 return font;
159 WMFont*
160 WMCreateNormalFont(WMScreen *scrPtr, char *fontName)
162 WMFont *font;
163 Display *display = scrPtr->display;
164 char *fname, *ptr;
166 if ((ptr = strchr(fontName, ','))) {
167 fname = wmalloc(ptr - fontName + 1);
168 strncpy(fname, fontName, ptr - fontName);
169 fname[ptr - fontName] = 0;
170 } else {
171 fname = wstrdup(fontName);
174 font = WMHashGet(scrPtr->fontCache, fname);
175 if (font) {
176 WMRetainFont(font);
177 wfree(fname);
178 return font;
181 font = malloc(sizeof(WMFont));
182 if (!font) {
183 wfree(fname);
184 return NULL;
186 memset(font, 0, sizeof(WMFont));
188 font->notFontSet = 1;
190 font->screen = scrPtr;
192 font->font.normal = XLoadQueryFont(display, fname);
193 if (!font->font.normal) {
194 wfree(font);
195 return NULL;
198 font->height = font->font.normal->ascent+font->font.normal->descent;
199 font->y = font->font.normal->ascent;
201 font->refCount = 1;
203 font->name = fname;
205 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
207 return font;
212 WMFont*
213 WMCreateFont(WMScreen *scrPtr, char *fontName)
215 if (scrPtr->useMultiByte)
216 return WMCreateFontSet(scrPtr, fontName);
217 else
218 return WMCreateNormalFont(scrPtr, fontName);
223 WMFont*
224 WMRetainFont(WMFont *font)
226 wassertrv(font!=NULL, NULL);
228 font->refCount++;
230 return font;
234 void
235 WMReleaseFont(WMFont *font)
237 wassertr(font!=NULL);
239 font->refCount--;
240 if (font->refCount < 1) {
241 if (font->notFontSet)
242 XFreeFont(font->screen->display, font->font.normal);
243 else {
244 XFreeFontSet(font->screen->display, font->font.set);
246 if (font->name) {
247 WMHashRemove(font->screen->fontCache, font->name);
248 wfree(font->name);
250 wfree(font);
256 unsigned int
257 WMFontHeight(WMFont *font)
259 wassertrv(font!=NULL, 0);
261 return font->height;
266 WMFont*
267 WMSystemFontOfSize(WMScreen *scrPtr, int size)
269 WMFont *font;
270 char *fontSpec;
272 fontSpec = makeFontSetOfSize(WINGsConfiguration.systemFont, size);
274 if (scrPtr->useMultiByte)
275 font = WMCreateFontSet(scrPtr, fontSpec);
276 else
277 font = WMCreateNormalFont(scrPtr, fontSpec);
279 if (!font) {
280 if (scrPtr->useMultiByte) {
281 wwarning("could not load font set %s. Trying fixed.", fontSpec);
282 font = WMCreateFontSet(scrPtr, "fixed");
283 if (!font) {
284 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
286 } else {
287 wwarning("could not load font %s. Trying fixed.", fontSpec);
288 font = WMCreateNormalFont(scrPtr, "fixed");
290 if (!font) {
291 wwarning("could not load fixed font!");
292 wfree(fontSpec);
293 return NULL;
296 wfree(fontSpec);
298 return font;
302 WMFont*
303 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
305 WMFont *font;
306 char *fontSpec;
308 fontSpec = makeFontSetOfSize(WINGsConfiguration.boldSystemFont, size);
310 if (scrPtr->useMultiByte)
311 font = WMCreateFontSet(scrPtr, fontSpec);
312 else
313 font = WMCreateNormalFont(scrPtr, fontSpec);
315 if (!font) {
316 if (scrPtr->useMultiByte) {
317 wwarning("could not load font set %s. Trying fixed.", fontSpec);
318 font = WMCreateFontSet(scrPtr, "fixed");
319 if (!font) {
320 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
322 } else {
323 wwarning("could not load font %s. Trying fixed.", fontSpec);
324 font = WMCreateNormalFont(scrPtr, "fixed");
326 if (!font) {
327 wwarning("could not load fixed font!");
328 wfree(fontSpec);
329 return NULL;
332 wfree(fontSpec);
334 return font;
338 XFontSet
339 WMGetFontFontSet(WMFont *font)
341 wassertrv(font!=NULL, NULL);
343 if (font->notFontSet)
344 return NULL;
345 else
346 return font->font.set;
351 WMWidthOfString(WMFont *font, char *text, int length)
353 wassertrv(font!=NULL, 0);
354 wassertrv(text!=NULL, 0);
356 if (font->notFontSet)
357 return XTextWidth(font->font.normal, text, length);
358 else {
359 XRectangle rect;
360 XRectangle AIXsucks;
362 XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
364 return rect.width;
370 void
371 WMDrawString(WMScreen *scr, Drawable d, GC gc, WMFont *font, int x, int y,
372 char *text, int length)
374 wassertr(font!=NULL);
376 if (font->notFontSet) {
377 XSetFont(scr->display, gc, font->font.normal->fid);
378 XDrawString(scr->display, d, gc, x, y + font->y, text, length);
379 } else {
380 XmbDrawString(scr->display, d, font->font.set, gc, x, y + font->y,
381 text, length);
386 void
387 WMDrawImageString(WMScreen *scr, Drawable d, GC gc, WMFont *font, int x, int y,
388 char *text, int length)
390 wassertr(font != NULL);
392 if (font->notFontSet) {
393 XSetFont(scr->display, gc, font->font.normal->fid);
394 XDrawImageString(scr->display, d, gc, x, y + font->y, text, length);
395 } else {
396 XmbDrawImageString(scr->display, d, font->font.set, gc, x, y + font->y,
397 text, length);
404 static char*
405 makeFontSetOfSize(char *fontset, int size)
407 char font[300], *f;
408 char *newfs = NULL;
409 char *ptr;
411 do {
412 char *tmp;
413 int end;
416 f = fontset;
417 ptr = strchr(fontset, ',');
418 if (ptr) {
419 int count = ptr-fontset;
421 if (count > 255) {
422 wwarning("font description %s is too large.", fontset);
423 } else {
424 memcpy(font, fontset, count);
425 font[count] = 0;
426 f = (char*)font;
430 if (newfs)
431 end = strlen(newfs);
432 else
433 end = 0;
435 tmp = wmalloc(end + strlen(f) + 8);
436 if (end != 0) {
437 sprintf(tmp, "%s,", newfs);
438 sprintf(tmp + end + 1, f, size);
439 } else {
440 sprintf(tmp + end, f, size);
443 if (newfs)
444 wfree(newfs);
445 newfs = tmp;
447 fontset = ptr+1;
448 } while (ptr!=NULL);
450 return newfs;