Added 2 functions to retrieve the default system fonts:
[wmaker-crm.git] / WINGs / wfont.c
blob1636af1d77e7e467b77d8ed81519f0a80b157ece
2 #include "WINGsP.h"
3 #include "wconfig.h"
6 #include <wraster.h>
7 #include <assert.h>
8 #include <X11/Xlocale.h>
10 static char *makeFontSetOfSize(char *fontset, int size);
14 /* XLFD pattern matching */
15 static char*
16 xlfd_get_element (const char *xlfd, int index)
18 const char *p = xlfd;
19 while (*p != 0) {
20 if (*p == '-' && --index == 0) {
21 const char *end = strchr(p + 1, '-');
22 char *buf;
23 size_t len;
24 if (end == 0) end = p + strlen(p);
25 len = end - (p + 1);
26 buf = wmalloc(len);
27 memcpy(buf, p + 1, len);
28 buf[len] = 0;
29 return buf;
31 p++;
33 return strdup("*");
36 /* XLFD pattern matching */
37 static char*
38 generalize_xlfd (const char *xlfd)
40 char *buf;
41 int len;
42 char *weight = xlfd_get_element(xlfd, 3);
43 char *slant = xlfd_get_element(xlfd, 4);
44 char *pxlsz = xlfd_get_element(xlfd, 7);
46 #define Xstrlen(A) ((A)?strlen(A):0)
47 len = Xstrlen(xlfd)+Xstrlen(weight)+Xstrlen(slant)+Xstrlen(pxlsz)*2+60;
48 #undef Xstrlen
50 buf = wmalloc(len + 1);
51 snprintf(buf, len + 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
52 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
53 xlfd, weight, slant, pxlsz, pxlsz);
55 wfree(pxlsz);
56 wfree(slant);
57 wfree(weight);
59 return buf;
62 /* XLFD pattern matching */
63 static XFontSet
64 W_CreateFontSetWithGuess(Display *dpy, char *xlfd, char ***missing,
65 int *nmissing, char **def_string)
67 XFontSet fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
69 if (fs != NULL && *nmissing == 0) return fs;
71 /* for non-iso8859-1 language and iso8859-1 specification
72 (this fontset is only for pattern analysis) */
73 if (fs == NULL) {
74 if (*nmissing != 0) XFreeStringList(*missing);
75 setlocale(LC_CTYPE, "C");
76 fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
77 setlocale(LC_CTYPE, "");
80 /* make XLFD font name for pattern analysis */
81 if (fs != NULL) {
82 XFontStruct **fontstructs;
83 char **fontnames;
84 if (XFontsOfFontSet(fs, &fontstructs, &fontnames) > 0)
85 xlfd = fontnames[0];
88 xlfd = generalize_xlfd (xlfd);
90 if (*nmissing != 0) XFreeStringList(*missing);
91 if (fs != NULL) XFreeFontSet(dpy, fs);
93 fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
95 wfree(xlfd);
96 return fs;
99 WMFont*
100 WMCreateFontSet(WMScreen *scrPtr, char *fontName)
102 WMFont *font;
103 Display *display = scrPtr->display;
104 char **missing;
105 int nmissing = 0;
106 char *defaultString;
107 XFontSetExtents *extents;
109 font = WMHashGet(scrPtr->fontSetCache, fontName);
110 if (font) {
111 WMRetainFont(font);
112 return font;
115 font = malloc(sizeof(WMFont));
116 if (!font)
117 return NULL;
118 memset(font, 0, sizeof(WMFont));
120 font->notFontSet = 0;
122 font->screen = scrPtr;
124 font->font.set = W_CreateFontSetWithGuess(display, fontName, &missing,
125 &nmissing, &defaultString);
126 if (nmissing > 0 && font->font.set) {
127 int i;
129 wwarning(_("the following character sets are missing in %s:"),
130 fontName);
131 for (i = 0; i < nmissing; i++) {
132 wwarning(missing[i]);
134 XFreeStringList(missing);
135 if (defaultString)
136 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
137 defaultString);
139 if (!font->font.set) {
140 wfree(font);
141 return NULL;
144 extents = XExtentsOfFontSet(font->font.set);
146 font->height = extents->max_logical_extent.height;
147 font->y = font->height - (font->height + extents->max_logical_extent.y);
149 font->refCount = 1;
151 font->name = wstrdup(fontName);
153 assert(WMHashInsert(scrPtr->fontSetCache, font->name, font)==NULL);
155 return font;
160 WMFont*
161 WMCreateNormalFont(WMScreen *scrPtr, char *fontName)
163 WMFont *font;
164 Display *display = scrPtr->display;
165 char *fname, *ptr;
167 if ((ptr = strchr(fontName, ','))) {
168 fname = wmalloc(ptr - fontName + 1);
169 strncpy(fname, fontName, ptr - fontName);
170 fname[ptr - fontName] = 0;
171 } else {
172 fname = wstrdup(fontName);
175 font = WMHashGet(scrPtr->fontCache, fname);
176 if (font) {
177 WMRetainFont(font);
178 wfree(fname);
179 return font;
182 font = malloc(sizeof(WMFont));
183 if (!font) {
184 wfree(fname);
185 return NULL;
187 memset(font, 0, sizeof(WMFont));
189 font->notFontSet = 1;
191 font->screen = scrPtr;
193 font->font.normal = XLoadQueryFont(display, fname);
194 if (!font->font.normal) {
195 wfree(font);
196 wfree(fname);
197 return NULL;
200 font->height = font->font.normal->ascent+font->font.normal->descent;
201 font->y = font->font.normal->ascent;
203 font->refCount = 1;
205 font->name = fname;
207 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
209 return font;
214 WMFont*
215 WMCreateFont(WMScreen *scrPtr, char *fontName)
217 if (scrPtr->useMultiByte)
218 return WMCreateFontSet(scrPtr, fontName);
219 else
220 return WMCreateNormalFont(scrPtr, fontName);
225 WMFont*
226 WMRetainFont(WMFont *font)
228 wassertrv(font!=NULL, NULL);
230 font->refCount++;
232 return font;
236 void
237 WMReleaseFont(WMFont *font)
239 wassertr(font!=NULL);
241 font->refCount--;
242 if (font->refCount < 1) {
243 if (font->notFontSet)
244 XFreeFont(font->screen->display, font->font.normal);
245 else {
246 XFreeFontSet(font->screen->display, font->font.set);
248 if (font->name) {
249 if (font->notFontSet) {
250 WMHashRemove(font->screen->fontCache, font->name);
251 } else {
252 WMHashRemove(font->screen->fontSetCache, font->name);
254 wfree(font->name);
256 wfree(font);
262 unsigned int
263 WMFontHeight(WMFont *font)
265 wassertrv(font!=NULL, 0);
267 return font->height;
271 WMFont*
272 WMDefaultSystemFont(WMScreen *scrPtr)
274 return WMRetainFont(scrPtr->normalFont);
278 WMFont*
279 WMDefaultBoldSystemFont(WMScreen *scrPtr)
281 return WMRetainFont(scrPtr->boldFont);
285 WMFont*
286 WMSystemFontOfSize(WMScreen *scrPtr, int size)
288 WMFont *font;
289 char *fontSpec;
291 fontSpec = makeFontSetOfSize(WINGsConfiguration.systemFont, size);
293 if (scrPtr->useMultiByte)
294 font = WMCreateFontSet(scrPtr, fontSpec);
295 else
296 font = WMCreateNormalFont(scrPtr, fontSpec);
298 if (!font) {
299 if (scrPtr->useMultiByte) {
300 wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
301 font = WMCreateFontSet(scrPtr, "fixed");
302 if (!font) {
303 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
305 } else {
306 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
307 font = WMCreateNormalFont(scrPtr, "fixed");
309 if (!font) {
310 wwarning(_("could not load fixed font!"));
311 wfree(fontSpec);
312 return NULL;
315 wfree(fontSpec);
317 return font;
321 WMFont*
322 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
324 WMFont *font;
325 char *fontSpec;
327 fontSpec = makeFontSetOfSize(WINGsConfiguration.boldSystemFont, size);
329 if (scrPtr->useMultiByte)
330 font = WMCreateFontSet(scrPtr, fontSpec);
331 else
332 font = WMCreateNormalFont(scrPtr, fontSpec);
334 if (!font) {
335 if (scrPtr->useMultiByte) {
336 wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
337 font = WMCreateFontSet(scrPtr, "fixed");
338 if (!font) {
339 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
341 } else {
342 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
343 font = WMCreateNormalFont(scrPtr, "fixed");
345 if (!font) {
346 wwarning(_("could not load fixed font!"));
347 wfree(fontSpec);
348 return NULL;
351 wfree(fontSpec);
353 return font;
357 XFontSet
358 WMGetFontFontSet(WMFont *font)
360 wassertrv(font!=NULL, NULL);
362 if (font->notFontSet)
363 return NULL;
364 else
365 return font->font.set;
370 WMWidthOfString(WMFont *font, char *text, int length)
372 wassertrv(font!=NULL, 0);
373 wassertrv(text!=NULL, 0);
375 if (font->notFontSet)
376 return XTextWidth(font->font.normal, text, length);
377 else {
378 XRectangle rect;
379 XRectangle AIXsucks;
381 XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
383 return rect.width;
389 void
390 WMDrawString(WMScreen *scr, Drawable d, GC gc, WMFont *font, int x, int y,
391 char *text, int length)
393 wassertr(font!=NULL);
395 if (font->notFontSet) {
396 XSetFont(scr->display, gc, font->font.normal->fid);
397 XDrawString(scr->display, d, gc, x, y + font->y, text, length);
398 } else {
399 XmbDrawString(scr->display, d, font->font.set, gc, x, y + font->y,
400 text, length);
405 void
406 WMDrawImageString(WMScreen *scr, Drawable d, GC gc, WMFont *font, int x, int y,
407 char *text, int length)
409 wassertr(font != NULL);
411 if (font->notFontSet) {
412 XSetFont(scr->display, gc, font->font.normal->fid);
413 XDrawImageString(scr->display, d, gc, x, y + font->y, text, length);
414 } else {
415 XmbDrawImageString(scr->display, d, font->font.set, gc, x, y + font->y,
416 text, length);
423 static char*
424 makeFontSetOfSize(char *fontset, int size)
426 char font[300], *f;
427 char *newfs = NULL;
428 char *ptr;
430 do {
431 char *tmp;
432 int end;
435 f = fontset;
436 ptr = strchr(fontset, ',');
437 if (ptr) {
438 int count = ptr-fontset;
440 if (count > 255) {
441 wwarning(_("font description %s is too large."), fontset);
442 } else {
443 memcpy(font, fontset, count);
444 font[count] = 0;
445 f = (char*)font;
449 if (newfs)
450 end = strlen(newfs);
451 else
452 end = 0;
454 tmp = wmalloc(end + strlen(f) + 8);
455 if (end != 0) {
456 sprintf(tmp, "%s,", newfs);
457 sprintf(tmp + end + 1, f, size);
458 } else {
459 sprintf(tmp + end, f, size);
462 if (newfs)
463 wfree(newfs);
464 newfs = tmp;
466 fontset = ptr+1;
467 } while (ptr!=NULL);
469 return newfs;
473 static void
474 changeFontProp(char *fname, char *newprop, int which)
476 char before[128], prop[128], after[128];
477 char *ptr, *bptr;
478 int part=0;
480 if(!fname || !prop)
481 return;
483 ptr = fname;
484 bptr = before;
485 while (*ptr) {
486 if(*ptr == '-') {
487 *bptr = 0;
488 if(part==which)
489 bptr = prop;
490 else if(part==which+1)
491 bptr = after;
492 *bptr++ = *ptr;
493 part++;
494 } else {
495 *bptr++ = *ptr;
497 ptr++;
499 *bptr = 0;
500 snprintf(fname, 255, "%s-%s%s", before, newprop, after);
504 WMFont*
505 WMNormalizeFont(WMScreen *scr, WMFont *font)
507 WMFont *newfont=NULL;
508 char fname[256];
510 if(!scr || !font)
511 return NULL;
513 snprintf(fname, 255, font->name);
514 changeFontProp(fname, "medium", 2);
515 changeFontProp(fname, "r", 3);
516 newfont = WMCreateNormalFont(scr, fname);
518 if(!newfont)
519 return NULL;
521 return newfont;
525 WMFont*
526 WMStrengthenFont(WMScreen *scr, WMFont *font)
528 WMFont *newfont=NULL;
529 char fname[256];
531 if(!scr || !font)
532 return NULL;
534 snprintf(fname, 255, font->name);
535 changeFontProp(fname, "bold", 2);
536 newfont = WMCreateNormalFont(scr, fname);
538 if(!newfont)
539 return NULL;
541 return newfont;
545 WMFont*
546 WMUnstrengthenFont(WMScreen *scr, WMFont *font)
548 WMFont *newfont=NULL;
549 char fname[256];
551 if(!scr || !font)
552 return NULL;
554 snprintf(fname, 255, font->name);
555 changeFontProp(fname, "medium", 2);
556 newfont = WMCreateNormalFont(scr, fname);
558 if(!newfont)
559 return NULL;
561 return newfont;
565 WMFont*
566 WMEmphasizeFont(WMScreen *scr, WMFont *font)
568 WMFont *newfont=NULL;
569 char fname[256];
571 if(!scr || !font)
572 return NULL;
574 snprintf(fname, 255, font->name);
575 changeFontProp(fname, "o", 3);
576 newfont = WMCreateNormalFont(scr, fname);
578 if(!newfont)
579 return NULL;
581 return newfont;
585 WMFont*
586 WMUnemphasizeFont(WMScreen *scr, WMFont *font)
588 WMFont *newfont=NULL;
589 char fname[256];
591 if(!scr || !font)
592 return NULL;
594 snprintf(fname, 255, font->name);
595 changeFontProp(fname, "r", 3);
596 newfont = WMCreateNormalFont(scr, fname);
598 if(!newfont)
599 return NULL;
601 return newfont;
605 WMFont*
606 WMGetFontOfSize(WMScreen *scr, WMFont *font, int size)
608 if(!scr || !font || size<1)
609 return NULL;
611 return font;