Fixed some focus related problems when switching workspaces, including the
[wmaker-crm.git] / WINGs / wfont.c
blob6a583a968c2109504b14440a95af2316868194e2
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;
272 WMFont*
273 WMSystemFontOfSize(WMScreen *scrPtr, int size)
275 WMFont *font;
276 char *fontSpec;
278 fontSpec = makeFontSetOfSize(WINGsConfiguration.systemFont, size);
280 if (scrPtr->useMultiByte)
281 font = WMCreateFontSet(scrPtr, fontSpec);
282 else
283 font = WMCreateNormalFont(scrPtr, fontSpec);
285 if (!font) {
286 if (scrPtr->useMultiByte) {
287 wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
288 font = WMCreateFontSet(scrPtr, "fixed");
289 if (!font) {
290 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
292 } else {
293 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
294 font = WMCreateNormalFont(scrPtr, "fixed");
296 if (!font) {
297 wwarning(_("could not load fixed font!"));
298 wfree(fontSpec);
299 return NULL;
302 wfree(fontSpec);
304 return font;
308 WMFont*
309 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
311 WMFont *font;
312 char *fontSpec;
314 fontSpec = makeFontSetOfSize(WINGsConfiguration.boldSystemFont, size);
316 if (scrPtr->useMultiByte)
317 font = WMCreateFontSet(scrPtr, fontSpec);
318 else
319 font = WMCreateNormalFont(scrPtr, fontSpec);
321 if (!font) {
322 if (scrPtr->useMultiByte) {
323 wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
324 font = WMCreateFontSet(scrPtr, "fixed");
325 if (!font) {
326 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
328 } else {
329 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
330 font = WMCreateNormalFont(scrPtr, "fixed");
332 if (!font) {
333 wwarning(_("could not load fixed font!"));
334 wfree(fontSpec);
335 return NULL;
338 wfree(fontSpec);
340 return font;
344 XFontSet
345 WMGetFontFontSet(WMFont *font)
347 wassertrv(font!=NULL, NULL);
349 if (font->notFontSet)
350 return NULL;
351 else
352 return font->font.set;
357 WMWidthOfString(WMFont *font, char *text, int length)
359 wassertrv(font!=NULL, 0);
360 wassertrv(text!=NULL, 0);
362 if (font->notFontSet)
363 return XTextWidth(font->font.normal, text, length);
364 else {
365 XRectangle rect;
366 XRectangle AIXsucks;
368 XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
370 return rect.width;
376 void
377 WMDrawString(WMScreen *scr, Drawable d, GC gc, WMFont *font, int x, int y,
378 char *text, int length)
380 wassertr(font!=NULL);
382 if (font->notFontSet) {
383 XSetFont(scr->display, gc, font->font.normal->fid);
384 XDrawString(scr->display, d, gc, x, y + font->y, text, length);
385 } else {
386 XmbDrawString(scr->display, d, font->font.set, gc, x, y + font->y,
387 text, length);
392 void
393 WMDrawImageString(WMScreen *scr, Drawable d, GC gc, WMFont *font, int x, int y,
394 char *text, int length)
396 wassertr(font != NULL);
398 if (font->notFontSet) {
399 XSetFont(scr->display, gc, font->font.normal->fid);
400 XDrawImageString(scr->display, d, gc, x, y + font->y, text, length);
401 } else {
402 XmbDrawImageString(scr->display, d, font->font.set, gc, x, y + font->y,
403 text, length);
410 static char*
411 makeFontSetOfSize(char *fontset, int size)
413 char font[300], *f;
414 char *newfs = NULL;
415 char *ptr;
417 do {
418 char *tmp;
419 int end;
422 f = fontset;
423 ptr = strchr(fontset, ',');
424 if (ptr) {
425 int count = ptr-fontset;
427 if (count > 255) {
428 wwarning(_("font description %s is too large."), fontset);
429 } else {
430 memcpy(font, fontset, count);
431 font[count] = 0;
432 f = (char*)font;
436 if (newfs)
437 end = strlen(newfs);
438 else
439 end = 0;
441 tmp = wmalloc(end + strlen(f) + 8);
442 if (end != 0) {
443 sprintf(tmp, "%s,", newfs);
444 sprintf(tmp + end + 1, f, size);
445 } else {
446 sprintf(tmp + end, f, size);
449 if (newfs)
450 wfree(newfs);
451 newfs = tmp;
453 fontset = ptr+1;
454 } while (ptr!=NULL);
456 return newfs;
460 static void
461 changeFontProp(char *fname, char *newprop, int which)
463 char before[128], prop[128], after[128];
464 char *ptr, *bptr;
465 int part=0;
467 if(!fname || !prop)
468 return;
470 ptr = fname;
471 bptr = before;
472 while (*ptr) {
473 if(*ptr == '-') {
474 *bptr = 0;
475 if(part==which) bptr = prop;
476 else if(part==which+1) bptr = after;
477 *bptr++ = *ptr;
478 part++;
479 } else {
480 *bptr++ = *ptr;
481 } ptr++;
482 }*bptr = 0;
483 snprintf(fname, 255, "%s-%s%s", before, newprop, after);
487 WMFont *
488 WMNormalizeFont(WMScreen *scr, WMFont *font)
490 WMFont *newfont=NULL;
491 char fname[256];
493 if(!scr || !font)
494 return NULL;
496 snprintf(fname, 255, font->name);
497 changeFontProp(fname, "medium", 2);
498 changeFontProp(fname, "r", 3);
499 newfont = WMCreateNormalFont(scr, fname);
501 if(!newfont)
502 return NULL;
504 return newfont;
508 WMFont *
509 WMStrengthenFont(WMScreen *scr, WMFont *font)
511 WMFont *newfont=NULL;
512 char fname[256];
514 if(!scr || !font)
515 return NULL;
517 snprintf(fname, 255, font->name);
518 changeFontProp(fname, "bold", 2);
519 newfont = WMCreateNormalFont(scr, fname);
521 if(!newfont)
522 return NULL;
524 return newfont;
528 WMFont *
529 WMUnstrengthenFont(WMScreen *scr, WMFont *font)
531 WMFont *newfont=NULL;
532 char fname[256];
534 if(!scr || !font)
535 return NULL;
537 snprintf(fname, 255, font->name);
538 changeFontProp(fname, "medium", 2);
539 newfont = WMCreateNormalFont(scr, fname);
541 if(!newfont)
542 return NULL;
544 return newfont;
548 WMFont *
549 WMEmphasizeFont(WMScreen *scr, WMFont *font)
551 WMFont *newfont=NULL;
552 char fname[256];
554 if(!scr || !font)
555 return NULL;
557 snprintf(fname, 255, font->name);
558 changeFontProp(fname, "o", 3);
559 newfont = WMCreateNormalFont(scr, fname);
561 if(!newfont)
562 return NULL;
564 return newfont;
568 WMFont *
569 WMUnemphasizeFont(WMScreen *scr, WMFont *font)
571 WMFont *newfont=NULL;
572 char fname[256];
574 if(!scr || !font)
575 return NULL;
577 snprintf(fname, 255, font->name);
578 changeFontProp(fname, "r", 3);
579 newfont = WMCreateNormalFont(scr, fname);
581 if(!newfont)
582 return NULL;
584 return newfont;
587 WMFont *
588 WMGetFontOfSize(WMScreen *scr, WMFont *font, int size)
590 if(!scr || !font || size<1)
591 return NULL;
593 return font;