- Added support for antialiased text with multibyte languages too.
[wmaker-crm.git] / WINGs / wfont.c
blob541f472e9cc56fcc6bd9c1249a5e991b35f8e74f
2 #include "wconfig.h"
4 #ifdef XFT
5 # include <X11/Xft/Xft.h>
6 #endif
8 #include "WINGsP.h"
11 #include <wraster.h>
12 #include <assert.h>
13 #include <X11/Xlocale.h>
16 static char *makeFontSetOfSize(char *fontset, int size);
20 /* XLFD pattern matching */
21 static char*
22 getElementFromXLFD(const char *xlfd, int index)
24 const char *p = xlfd;
25 while (*p != 0) {
26 if (*p == '-' && --index == 0) {
27 const char *end = strchr(p + 1, '-');
28 char *buf;
29 size_t len;
30 if (end == 0) end = p + strlen(p);
31 len = end - (p + 1);
32 buf = wmalloc(len);
33 memcpy(buf, p + 1, len);
34 buf[len] = 0;
35 return buf;
37 p++;
39 return strdup("*");
43 /* XLFD pattern matching */
44 static char*
45 generalizeXLFD(const char *xlfd)
47 char *buf;
48 int len;
49 char *weight = getElementFromXLFD(xlfd, 3);
50 char *slant = getElementFromXLFD(xlfd, 4);
51 char *pxlsz = getElementFromXLFD(xlfd, 7);
53 #define Xstrlen(A) ((A)?strlen(A):0)
54 len = Xstrlen(xlfd)+Xstrlen(weight)+Xstrlen(slant)+Xstrlen(pxlsz)*2+60;
55 #undef Xstrlen
57 buf = wmalloc(len + 1);
58 snprintf(buf, len + 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
59 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
60 xlfd, weight, slant, pxlsz, pxlsz);
62 wfree(pxlsz);
63 wfree(slant);
64 wfree(weight);
66 return buf;
69 /* XLFD pattern matching */
70 static XFontSet
71 W_CreateFontSetWithGuess(Display *dpy, char *xlfd, char ***missing,
72 int *nmissing, char **def_string)
74 XFontSet fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
76 if (fs != NULL && *nmissing == 0) return fs;
78 /* for non-iso8859-1 language and iso8859-1 specification
79 (this fontset is only for pattern analysis) */
80 if (fs == NULL) {
81 if (*nmissing != 0) XFreeStringList(*missing);
82 setlocale(LC_CTYPE, "C");
83 fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
84 setlocale(LC_CTYPE, "");
87 /* make XLFD font name for pattern analysis */
88 if (fs != NULL) {
89 XFontStruct **fontstructs;
90 char **fontnames;
91 if (XFontsOfFontSet(fs, &fontstructs, &fontnames) > 0)
92 xlfd = fontnames[0];
95 xlfd = generalizeXLFD(xlfd);
97 if (*nmissing != 0) XFreeStringList(*missing);
98 if (fs != NULL) XFreeFontSet(dpy, fs);
100 fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
102 wfree(xlfd);
103 return fs;
107 static char*
108 xlfdFromFontName(char *fontName, Bool antialiased)
110 char *systemFont, *boldSystemFont;
111 char *font;
112 int size;
114 if (antialiased) {
115 systemFont = WINGsConfiguration.antialiasedSystemFont;
116 boldSystemFont = WINGsConfiguration.antialiasedBoldSystemFont;
117 } else {
118 systemFont = WINGsConfiguration.systemFont;
119 boldSystemFont = WINGsConfiguration.boldSystemFont;
122 size = WINGsConfiguration.defaultFontSize;
124 if (strcmp(fontName, "SystemFont")==0) {
125 font = systemFont;
126 size = WINGsConfiguration.defaultFontSize;
127 } else if (strncmp(fontName, "SystemFont-", 11)==0) {
128 font = systemFont;
129 if (sscanf(&fontName[11], "%i", &size)!=1) {
130 size = WINGsConfiguration.defaultFontSize;
131 wwarning(_("Invalid size specification '%s' in %s. "
132 "Using default %d\n"), &fontName[11], fontName, size);
134 } else if (strcmp(fontName, "BoldSystemFont")==0) {
135 font = boldSystemFont;
136 size = WINGsConfiguration.defaultFontSize;
137 } else if (strncmp(fontName, "BoldSystemFont-", 15)==0) {
138 font = boldSystemFont;
139 if (sscanf(&fontName[15], "%i", &size)!=1) {
140 size = WINGsConfiguration.defaultFontSize;
141 wwarning(_("Invalid size specification '%s' in %s. "
142 "Using default %d\n"), &fontName[15], fontName, size);
144 } else {
145 font = NULL;
148 return (font!=NULL ? makeFontSetOfSize(font, size) : wstrdup(fontName));
152 WMFont*
153 WMCreateFontSet(WMScreen *scrPtr, char *fontName)
155 WMFont *font;
156 Display *display = scrPtr->display;
157 char **missing;
158 int nmissing = 0;
159 char *defaultString;
160 char *fname;
161 XFontSetExtents *extents;
163 fname = xlfdFromFontName(fontName, False);
165 font = WMHashGet(scrPtr->fontSetCache, fname);
166 if (font) {
167 WMRetainFont(font);
168 wfree(fname);
169 return font;
172 font = wmalloc(sizeof(WMFont));
173 memset(font, 0, sizeof(WMFont));
175 font->notFontSet = 0;
176 font->antialiased = 0;
178 font->screen = scrPtr;
180 font->font.set = W_CreateFontSetWithGuess(display, fname, &missing,
181 &nmissing, &defaultString);
182 if (nmissing > 0 && font->font.set) {
183 int i;
185 wwarning(_("the following character sets are missing in %s:"), fname);
186 for (i = 0; i < nmissing; i++) {
187 wwarning(missing[i]);
189 XFreeStringList(missing);
190 if (defaultString)
191 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
192 defaultString);
194 if (!font->font.set) {
195 wfree(font);
196 wfree(fname);
197 return NULL;
200 extents = XExtentsOfFontSet(font->font.set);
202 font->height = extents->max_logical_extent.height;
203 font->y = font->height - (font->height + extents->max_logical_extent.y);
205 font->refCount = 1;
207 font->name = fname;
209 assert(WMHashInsert(scrPtr->fontSetCache, font->name, font)==NULL);
211 return font;
216 WMFont*
217 WMCreateNormalFont(WMScreen *scrPtr, char *fontName)
219 WMFont *font;
220 Display *display = scrPtr->display;
221 char *fname, *ptr;
223 fontName = xlfdFromFontName(fontName, False);
225 if ((ptr = strchr(fontName, ','))) {
226 fname = wmalloc(ptr - fontName + 1);
227 strncpy(fname, fontName, ptr - fontName);
228 fname[ptr - fontName] = 0;
229 } else {
230 fname = wstrdup(fontName);
233 wfree(fontName);
235 font = WMHashGet(scrPtr->fontCache, fname);
236 if (font) {
237 WMRetainFont(font);
238 wfree(fname);
239 return font;
242 font = wmalloc(sizeof(WMFont));
243 memset(font, 0, sizeof(WMFont));
245 font->notFontSet = 1;
246 font->antialiased = 0;
248 font->screen = scrPtr;
250 font->font.normal = XLoadQueryFont(display, fname);
251 if (!font->font.normal) {
252 wfree(font);
253 wfree(fname);
254 return NULL;
256 font->height = font->font.normal->ascent+font->font.normal->descent;
257 font->y = font->font.normal->ascent;
259 font->refCount = 1;
261 font->name = fname;
263 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
265 return font;
269 WMFont*
270 WMCreateAntialiasedFont(WMScreen *scrPtr, char *fontName)
272 #ifdef XFT
273 WMFont *font;
274 Display *display = scrPtr->display;
275 char *fname, *ptr;
277 if (!scrPtr->hasXftSupport)
278 return NULL;
280 fontName = xlfdFromFontName(fontName, True);
282 if ((ptr = strchr(fontName, ','))) {
283 fname = wmalloc(ptr - fontName + 1);
284 strncpy(fname, fontName, ptr - fontName);
285 fname[ptr - fontName] = 0;
286 } else {
287 fname = wstrdup(fontName);
290 wfree(fontName);
292 font = WMHashGet(scrPtr->xftFontCache, fname);
293 if (font) {
294 WMRetainFont(font);
295 wfree(fname);
296 return font;
299 font = wmalloc(sizeof(WMFont));
300 memset(font, 0, sizeof(WMFont));
302 font->notFontSet = 1;
303 font->antialiased = 1;
305 font->screen = scrPtr;
307 #if 0
308 /* // Xft sux. Loading a font that doesn't exist will load the default
309 * defined in XftConfig without any warning or error */
310 font->font.normal = XLoadQueryFont(display, fname);
311 if (!font->font.normal) {
312 wfree(font);
313 wfree(fname);
314 return NULL;
316 XFreeFont(display, font->font.normal);
317 #endif
319 font->font.xft = XftFontOpenXlfd(display, scrPtr->screen, fname);
320 if (!font->font.xft) {
321 wfree(font);
322 wfree(fname);
323 return NULL;
325 font->height = font->font.xft->ascent+font->font.xft->descent;
326 font->y = font->font.xft->ascent;
328 font->refCount = 1;
330 font->name = fname;
332 assert(WMHashInsert(scrPtr->xftFontCache, font->name, font)==NULL);
334 return font;
335 #else
336 return NULL;
337 #endif
341 WMFont*
342 WMCreateAntialiasedFontSet(WMScreen *scrPtr, char *fontName)
344 #ifdef XFT
345 WMFont *font;
346 Display *display = scrPtr->display;
347 char *fname, *ptr;
349 if (!scrPtr->hasXftSupport)
350 return NULL;
352 fontName = xlfdFromFontName(fontName, True);
354 // use the second in list if available, instead of first?
355 if ((ptr = strchr(fontName, ','))) {
356 fname = wmalloc(ptr - fontName + 1);
357 strncpy(fname, fontName, ptr - fontName);
358 fname[ptr - fontName] = 0;
359 } else {
360 fname = wstrdup(fontName);
363 wfree(fontName);
365 font = WMHashGet(scrPtr->xftFontSetCache, fname);
366 if (font) {
367 WMRetainFont(font);
368 wfree(fname);
369 return font;
372 font = wmalloc(sizeof(WMFont));
373 memset(font, 0, sizeof(WMFont));
375 font->notFontSet = 0;
376 font->antialiased = 1;
378 font->screen = scrPtr;
380 #if 0
381 /* // Xft sux. Loading a font that doesn't exist will load the default
382 * defined in XftConfig without any warning or error */
383 font->font.normal = XLoadQueryFont(display, fname);
384 if (!font->font.normal) {
385 wfree(font);
386 wfree(fname);
387 return NULL;
389 XFreeFont(display, font->font.normal);
390 #endif
392 font->font.xft = XftFontOpenXlfd(display, scrPtr->screen, fname);
393 if (!font->font.xft) {
394 wfree(font);
395 wfree(fname);
396 return NULL;
398 font->height = font->font.xft->ascent+font->font.xft->descent;
399 font->y = font->font.xft->ascent;
401 font->refCount = 1;
403 font->name = fname;
405 assert(WMHashInsert(scrPtr->xftFontSetCache, font->name, font)==NULL);
407 return font;
408 #else
409 return NULL;
410 #endif
414 WMFont*
415 WMCreateFont(WMScreen *scrPtr, char *fontName)
417 return WMCreateFontWithFlags(scrPtr, fontName, WFDefaultFont);
421 WMFont*
422 WMCreateFontWithFlags(WMScreen *scrPtr, char *fontName, WMFontFlags flags)
424 Bool multiByte = scrPtr->useMultiByte;
425 Bool antialiased = scrPtr->antialiasedText;
426 WMFont *font;
428 if (flags & WFFontSet) {
429 multiByte = True;
430 } else if (flags & WFNormalFont) {
431 multiByte = False;
433 if (flags & WFAntialiased) {
434 antialiased = True;
435 } else if (flags & WFNotAntialiased) {
436 antialiased = False;
439 if (antialiased && multiByte) {
440 font = WMCreateAntialiasedFontSet(scrPtr, fontName);
441 /* If we cannot create an antialiased font set and antialiasing is
442 * not explicitly requested in flags, fallback to standard font sets */
443 if (!font && (flags & WFAntialiased)==0) {
444 font = WMCreateFontSet(scrPtr, fontName);
446 } else if (antialiased) {
447 font = WMCreateAntialiasedFont(scrPtr, fontName);
448 /* If we cannot create an antialiased font and antialiasing is
449 * not explicitly requested in flags, fallback to normal font */
450 if (!font && (flags & WFAntialiased)==0) {
451 font = WMCreateNormalFont(scrPtr, fontName);
453 } else if (multiByte) {
454 font = WMCreateFontSet(scrPtr, fontName);
455 } else {
456 font = WMCreateNormalFont(scrPtr, fontName);
459 return font;
463 WMFont*
464 WMRetainFont(WMFont *font)
466 wassertrv(font!=NULL, NULL);
468 font->refCount++;
470 return font;
474 void
475 WMReleaseFont(WMFont *font)
477 wassertr(font!=NULL);
479 font->refCount--;
480 if (font->refCount < 1) {
481 if (font->antialiased) {
482 #ifdef XFT
483 XftFontClose(font->screen->display, font->font.xft);
484 #else
485 assert(False);
486 #endif
487 } else if (font->notFontSet) {
488 XFreeFont(font->screen->display, font->font.normal);
489 } else {
490 XFreeFontSet(font->screen->display, font->font.set);
493 if (font->name) {
494 if (font->antialiased && !font->notFontSet) {
495 WMHashRemove(font->screen->xftFontSetCache, font->name);
496 } else if (font->antialiased) {
497 WMHashRemove(font->screen->xftFontCache, font->name);
498 } else if (font->notFontSet) {
499 WMHashRemove(font->screen->fontCache, font->name);
500 } else {
501 WMHashRemove(font->screen->fontSetCache, font->name);
503 wfree(font->name);
505 wfree(font);
510 Bool
511 WMHasAntialiasingSupport(WMScreen *scrPtr)
513 return scrPtr->hasXftSupport;
517 Bool
518 WMIsAntialiasingEnabled(WMScreen *scrPtr)
520 return scrPtr->antialiasedText;
524 Bool
525 WMIsAntialiasedFont(WMFont *font)
527 return font->antialiased;
531 unsigned int
532 WMFontHeight(WMFont *font)
534 wassertrv(font!=NULL, 0);
536 return font->height;
540 WMFont*
541 WMDefaultSystemFont(WMScreen *scrPtr)
543 return WMRetainFont(scrPtr->normalFont);
547 WMFont*
548 WMDefaultBoldSystemFont(WMScreen *scrPtr)
550 return WMRetainFont(scrPtr->boldFont);
554 static WMFont*
555 makeSystemFontOfSize(WMScreen *scrPtr, int size, Bool bold)
557 WMFont *font;
558 char *fontSpec, *xftFontSpec;
560 #define WConf WINGsConfiguration
561 if (bold) {
562 fontSpec = makeFontSetOfSize(WConf.boldSystemFont, size);
563 xftFontSpec = makeFontSetOfSize(WConf.antialiasedBoldSystemFont, size);
564 } else {
565 fontSpec = makeFontSetOfSize(WConf.systemFont, size);
566 xftFontSpec = makeFontSetOfSize(WConf.antialiasedSystemFont, size);
568 #undef WConf
570 if (scrPtr->antialiasedText && scrPtr->useMultiByte) {
571 font = WMCreateAntialiasedFontSet(scrPtr, xftFontSpec);
572 } else if (scrPtr->antialiasedText) {
573 font = WMCreateAntialiasedFont(scrPtr, xftFontSpec);
574 } else if (scrPtr->useMultiByte) {
575 font = WMCreateFontSet(scrPtr, fontSpec);
576 } else {
577 font = WMCreateNormalFont(scrPtr, fontSpec);
580 if (!font) {
581 if (scrPtr->antialiasedText && scrPtr->useMultiByte) {
582 // is arial a good fallback for multibyte?
583 wwarning(_("could not load font %s. Trying arial."), xftFontSpec);
584 if (bold) {
585 font = WMCreateAntialiasedFontSet(scrPtr, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
586 } else {
587 font = WMCreateAntialiasedFontSet(scrPtr, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
589 if (!font) {
590 wwarning(_("could not load antialiased font set. Reverting to standard font sets."));
591 font = WMCreateFontSet(scrPtr, fontSpec);
592 if (!font) {
593 wwarning(_("could not load FontSet %s. Trying fixed."), fontSpec);
594 font = WMCreateFontSet(scrPtr, "fixed");
597 } else if (scrPtr->antialiasedText) {
598 wwarning(_("could not load font %s. Trying arial."), xftFontSpec);
599 if (bold) {
600 font = WMCreateAntialiasedFont(scrPtr, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
601 } else {
602 font = WMCreateAntialiasedFont(scrPtr, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
604 if (!font) {
605 wwarning(_("could not load antialiased fonts. Reverting to normal fonts."));
606 font = WMCreateNormalFont(scrPtr, fontSpec);
607 if (!font) {
608 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
609 font = WMCreateNormalFont(scrPtr, "fixed");
612 } else if (scrPtr->useMultiByte) {
613 wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
614 font = WMCreateFontSet(scrPtr, "fixed");
615 if (!font) {
616 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
618 } else {
619 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
620 font = WMCreateNormalFont(scrPtr, "fixed");
622 if (!font) {
623 wwarning(_("could not load fixed font!"));
624 wfree(fontSpec);
625 wfree(xftFontSpec);
626 return NULL;
629 wfree(fontSpec);
630 wfree(xftFontSpec);
632 return font;
636 WMFont*
637 WMSystemFontOfSize(WMScreen *scrPtr, int size)
639 return makeSystemFontOfSize(scrPtr, size, False);
643 WMFont*
644 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
646 return makeSystemFontOfSize(scrPtr, size, True);
650 XFontSet
651 WMGetFontFontSet(WMFont *font)
653 wassertrv(font!=NULL, NULL);
655 if (!font->notFontSet && !font->antialiased)
656 return font->font.set;
658 return NULL;
663 WMWidthOfString(WMFont *font, char *text, int length)
665 wassertrv(font!=NULL, 0);
666 wassertrv(text!=NULL, 0);
668 if (font->antialiased) {
669 #ifdef XFT
670 XGlyphInfo extents;
672 if (!font->notFontSet) {
673 wchar_t *wtext;
674 char *mtext;
676 /* Use mtext instead of text, because mbstrtowcs() alters it */
677 mtext = text;
678 wtext = (wchar_t *)wmalloc(4*length+4);
679 // pass a real ps instead of NULL below? for multithread safety as
680 // from manual
681 if (mbsrtowcs(wtext, &mtext, length, NULL)==length) {
682 XftTextExtents32(font->screen->display, font->font.xft,
683 (XftChar32 *)wtext, length, &extents);
684 } else {
685 // - should rather say that conversion to widechar failed?
686 // - use mtext instead of text so that the position of the
687 // invalid sequence is shown?
688 wwarning(_("Invalid multibyte sequence: '%s'\n"), text);
689 XftTextExtents8(font->screen->display, font->font.xft,
690 (XftChar8 *)text, length, &extents);
692 wfree(wtext);
693 } else {
694 XftTextExtents8(font->screen->display, font->font.xft,
695 (XftChar8 *)text, length, &extents);
698 return extents.xOff; /* don't ask :P */
699 #else
700 wassertrv(False, 0);
701 #endif
702 } else if (font->notFontSet) {
703 return XTextWidth(font->font.normal, text, length);
704 } else {
705 XRectangle rect;
706 XRectangle AIXsucks;
708 XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
710 return rect.width;
716 void
717 WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font,
718 int x, int y, char *text, int length)
720 wassertr(font!=NULL);
722 if (font->antialiased) {
723 #ifdef XFT
724 XftColor xftcolor;
726 xftcolor.color.red = color->color.red;
727 xftcolor.color.green = color->color.green;
728 xftcolor.color.blue = color->color.blue;
729 xftcolor.color.alpha = color->alpha;;
730 xftcolor.pixel = W_PIXEL(color);
732 XftDrawChange(scr->xftdraw, d);
734 if (!font->notFontSet) {
735 wchar_t *wtext;
736 char *mtext;
738 /* Use mtext instead of text, because mbstrtowcs() alters it */
739 mtext = text;
740 wtext = (wchar_t *)wmalloc(4*length+4);
741 if (mbsrtowcs(wtext, &mtext, length, NULL)==length) {
742 XftDrawString32(scr->xftdraw, &xftcolor, font->font.xft,
743 x, y + font->y, (XftChar32*)wtext, length);
744 } else {
745 // - should rather say that conversion to widechar failed?
746 // - use mtext instead of text so that the position of the
747 // invalid sequence is shown?
748 wwarning(_("Invalid multibyte sequence: '%s'\n"), text);
749 XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
750 x, y + font->y, (XftChar8*)text, length);
752 wfree(wtext);
753 } else {
754 XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
755 x, y + font->y, (XftChar8*)text, length);
757 #else
758 wassertr(False);
759 #endif
760 } else if (font->notFontSet) {
761 XSetFont(scr->display, scr->drawStringGC, font->font.normal->fid);
762 XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color));
763 XDrawString(scr->display, d, scr->drawStringGC, x, y + font->y,
764 text, length);
765 } else {
766 XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color));
767 XmbDrawString(scr->display, d, font->font.set, scr->drawStringGC,
768 x, y + font->y, text, length);
773 void
774 WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background,
775 WMFont *font, int x, int y, char *text, int length)
777 wassertr(font!=NULL);
779 if (font->antialiased) {
780 #ifdef XFT
781 XftColor textColor;
782 XftColor bgColor;
784 textColor.color.red = color->color.red;
785 textColor.color.green = color->color.green;
786 textColor.color.blue = color->color.blue;
787 textColor.color.alpha = color->alpha;;
788 textColor.pixel = W_PIXEL(color);
790 bgColor.color.red = background->color.red;
791 bgColor.color.green = background->color.green;
792 bgColor.color.blue = background->color.blue;
793 bgColor.color.alpha = background->alpha;;
794 bgColor.pixel = W_PIXEL(background);
797 XftDrawChange(scr->xftdraw, d);
799 XftDrawRect(scr->xftdraw, &bgColor, x, y,
800 WMWidthOfString(font, text, length), font->height);
802 if (!font->notFontSet) {
803 wchar_t *wtext;
804 char *mtext;
806 /* Use mtext instead of text, because mbstrtowcs() alters it */
807 mtext = text;
808 wtext = (wchar_t *)wmalloc(4*length+4);
809 if (mbsrtowcs(wtext, &mtext, length, NULL)==length) {
810 XftDrawString32(scr->xftdraw, &textColor, font->font.xft,
811 x, y + font->y, (XftChar32*)wtext, length);
812 } else {
813 // - should rather say that conversion to widechar failed?
814 // - use mtext instead of text so that the position of the
815 // invalid sequence is shown?
816 wwarning(_("Invalid multibyte sequence: '%s'\n"), text);
817 XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
818 x, y + font->y, (XftChar8*)text, length);
820 wfree(wtext);
821 } else {
822 XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
823 x, y + font->y, (XftChar8*)text, length);
825 #else
826 wassertr(False);
827 #endif
828 } else if (font->notFontSet) {
829 XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color));
830 XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background));
831 XSetFont(scr->display, scr->drawImStringGC, font->font.normal->fid);
832 XDrawImageString(scr->display, d, scr->drawImStringGC,
833 x, y + font->y, text, length);
834 } else {
835 XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color));
836 XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background));
837 XmbDrawImageString(scr->display, d, font->font.set, scr->drawImStringGC,
838 x, y + font->y, text, length);
845 static char*
846 makeFontSetOfSize(char *fontset, int size)
848 char font[300], *f;
849 char *newfs = NULL;
850 char *ptr;
852 do {
853 char *tmp;
854 int end;
857 f = fontset;
858 ptr = strchr(fontset, ',');
859 if (ptr) {
860 int count = ptr-fontset;
862 if (count > 255) {
863 wwarning(_("font description %s is too large."), fontset);
864 } else {
865 memcpy(font, fontset, count);
866 font[count] = 0;
867 f = (char*)font;
871 if (newfs)
872 end = strlen(newfs);
873 else
874 end = 0;
876 tmp = wmalloc(end + strlen(f) + 8);
877 if (end != 0) {
878 sprintf(tmp, "%s,", newfs);
879 sprintf(tmp + end + 1, f, size);
880 } else {
881 sprintf(tmp + end, f, size);
884 if (newfs)
885 wfree(newfs);
886 newfs = tmp;
888 fontset = ptr+1;
889 } while (ptr!=NULL);
891 return newfs;
895 static void
896 changeFontProp(char *fname, char *newprop, int which)
898 char before[128], prop[128], after[128];
899 char *ptr, *bptr;
900 int part=0;
902 if (!fname || !prop)
903 return;
905 ptr = fname;
906 bptr = before;
907 while (*ptr) {
908 if(*ptr == '-') {
909 *bptr = 0;
910 if (part==which)
911 bptr = prop;
912 else if (part==which+1)
913 bptr = after;
914 *bptr++ = *ptr;
915 part++;
916 } else {
917 *bptr++ = *ptr;
919 ptr++;
921 *bptr = 0;
922 snprintf(fname, 255, "%s-%s%s", before, newprop, after);
926 WMFont*
927 WMNormalizeFont(WMScreen *scr, WMFont *font)
929 char fname[256];
930 WMFontFlags flag;
932 if (!scr || !font)
933 return NULL;
935 snprintf(fname, 255, "%s", font->name);
936 changeFontProp(fname, "medium", 2);
937 changeFontProp(fname, "r", 3);
938 flag = (font->antialiased ? WFAntialiased : WFNotAntialiased);
939 return WMCreateFontWithFlags(scr, fname, flag);
943 WMFont*
944 WMStrengthenFont(WMScreen *scr, WMFont *font)
946 char fname[256];
947 WMFontFlags flag;
949 if (!scr || !font)
950 return NULL;
952 snprintf(fname, 255, "%s", font->name);
953 changeFontProp(fname, "bold", 2);
954 flag = (font->antialiased ? WFAntialiased : WFNotAntialiased);
955 return WMCreateFontWithFlags(scr, fname, flag);
959 WMFont*
960 WMUnstrengthenFont(WMScreen *scr, WMFont *font)
962 char fname[256];
963 WMFontFlags flag;
965 if (!scr || !font)
966 return NULL;
968 snprintf(fname, 255, "%s", font->name);
969 changeFontProp(fname, "medium", 2);
970 flag = (font->antialiased ? WFAntialiased : WFNotAntialiased);
971 return WMCreateFontWithFlags(scr, fname, flag);
975 WMFont*
976 WMEmphasizeFont(WMScreen *scr, WMFont *font)
978 char fname[256];
979 WMFontFlags flag;
981 if (!scr || !font)
982 return NULL;
984 snprintf(fname, 255, "%s", font->name);
985 if (font->antialiased)
986 changeFontProp(fname, "i", 3);
987 else
988 changeFontProp(fname, "o", 3);
990 flag = (font->antialiased ? WFAntialiased : WFNotAntialiased);
991 return WMCreateFontWithFlags(scr, fname, flag);
995 WMFont*
996 WMUnemphasizeFont(WMScreen *scr, WMFont *font)
998 char fname[256];
999 WMFontFlags flag;
1001 if (!scr || !font)
1002 return NULL;
1004 snprintf(fname, 255, "%s", font->name);
1005 changeFontProp(fname, "r", 3);
1006 flag = (font->antialiased ? WFAntialiased : WFNotAntialiased);
1007 return WMCreateFontWithFlags(scr, fname, flag);