wide char support
[wmaker-crm.git] / WINGs / wfont.c
blobec0df59a8dd09c7a86b5b2e66cdb8758ab0148f8
2 #include "wconfig.h"
4 #ifdef XFT
5 # include <X11/Xft/Xft.h>
6 # ifdef HAVE_WCHAR_H
7 # include <wchar.h>
8 # endif
9 # include <stdlib.h>
10 #endif
12 #include "WINGsP.h"
14 #include <wraster.h>
15 #include <assert.h>
16 #include <X11/Xlocale.h>
19 #ifdef XFT
21 #if defined(HAVE_MBSNRTOWCS1)
23 static size_t
24 wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len)
26 mbstate_t ps;
27 size_t n;
29 memset(&ps, 0, sizeof(mbstate_t));
30 n = mbsnrtowcs(dest, src, nbytes, len, &ps);
31 if (n!=(size_t)-1 && *src) {
32 *src -= ps.__count;
35 return n;
38 #elif defined(HAVE_MBRTOWC)
40 // This is 8 times slower than the version above.
41 static size_t
42 wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len)
44 mbstate_t ps;
45 const char *ptr;
46 size_t n;
47 int nb;
49 if (nbytes==0)
50 return 0;
52 ptr = *src;
53 n = 0;
55 memset(&ps, 0, sizeof(mbstate_t));
57 if (dest == NULL) {
58 for (;;) {
59 nb = mbrtowc(NULL, ptr, nbytes, &ps);
60 if (nb < 0) {
61 return ((size_t)-1);
62 } else if (nb==0 || nb>nbytes) {
63 return n;
65 ptr += nb;
66 nbytes -= nb;
67 n++;
71 while (len-- > 0) {
72 nb = mbrtowc(dest, ptr, nbytes, &ps);
73 if (nb == -2) {
74 *src = ptr;
75 return n;
76 } else if (nb == -1) {
77 *src = ptr;
78 return ((size_t)-1);
79 } else if (nb == 0) {
80 *src = NULL;
81 return n;
83 ptr += nb;
84 nbytes -= nb;
85 n++;
86 dest++;
89 *src = ptr;
90 return n;
93 #else
94 # error No mbsnrtowcs. You loose.
95 #endif
98 WMFont*
99 WMCreateFont(WMScreen *scrPtr, char *fontName)
101 WMFont *font;
102 Display *display = scrPtr->display;
103 char *fname, *ptr;
105 /* This is for back-compat (to allow reading of old xlfd descriptions) */
106 if (fontName[0]=='-' && (ptr = strchr(fontName, ','))) {
107 fname = wmalloc(ptr - fontName + 1);
108 strncpy(fname, fontName, ptr - fontName);
109 fname[ptr - fontName] = 0;
110 } else {
111 fname = wstrdup(fontName);
114 font = WMHashGet(scrPtr->fontCache, fname);
115 if (font) {
116 WMRetainFont(font);
117 wfree(fname);
118 return font;
121 font = wmalloc(sizeof(WMFont));
122 memset(font, 0, sizeof(WMFont));
124 font->screen = scrPtr;
126 printf("%s\n", fname);
127 if (fname[0] == '-') {
128 /* Backward compat thing. Remove in a later version */
129 font->font = XftFontOpenXlfd(display, scrPtr->screen, fname);
130 } else {
131 font->font = XftFontOpenName(display, scrPtr->screen, fname);
133 if (!font->font) {
134 wfree(font);
135 wfree(fname);
136 return NULL;
138 font->height = font->font->ascent+font->font->descent;
139 font->y = font->font->ascent;
141 font->refCount = 1;
143 font->name = fname;
145 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
147 return font;
151 WMFont*
152 WMRetainFont(WMFont *font)
154 wassertrv(font!=NULL, NULL);
156 font->refCount++;
158 return font;
162 void
163 WMReleaseFont(WMFont *font)
165 wassertr(font!=NULL);
167 font->refCount--;
168 if (font->refCount < 1) {
169 XftFontClose(font->screen->display, font->font);
170 if (font->name) {
171 WMHashRemove(font->screen->fontCache, font->name);
172 wfree(font->name);
174 wfree(font);
179 Bool
180 WMIsAntialiasingEnabled(WMScreen *scrPtr)
182 return scrPtr->antialiasedText;
186 unsigned int
187 WMFontHeight(WMFont *font)
189 wassertrv(font!=NULL, 0);
191 return font->height;
195 char*
196 WMGetFontName(WMFont *font)
198 wassertrv(font!=NULL, NULL);
200 return font->name;
204 WMFont*
205 WMDefaultSystemFont(WMScreen *scrPtr)
207 return WMRetainFont(scrPtr->normalFont);
211 WMFont*
212 WMDefaultBoldSystemFont(WMScreen *scrPtr)
214 return WMRetainFont(scrPtr->boldFont);
218 WMFont*
219 WMSystemFontOfSize(WMScreen *scrPtr, int size)
221 WMFont *font;
222 char *fontSpec;
224 // we can here use fontnames like arial,times,sans-8:...
225 // which allow automatic fallback to times if arial is not available
226 // then sans if times is also unavailable.
227 fontSpec = makeFontSetOfSize(WINGsConfiguration.systemFont, size);
229 font = WMCreateFont(scrPtr, fontSpec);
231 if (!font) {
232 wwarning(_("could not load font %s. Trying sans."), fontSpec);
233 font = WMCreateFont(scrPtr, "sans:pixelsize=12");
235 wfree(fontSpec);
237 return font;
241 WMFont*
242 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
244 WMFont *font;
245 char *fontSpec;
247 // we can here use fontnames like arial,times,sans-8:...
248 // which allow automatic fallback to times if arial is not available
249 // then sans if times is also unavailable.
250 fontSpec = makeFontSetOfSize(WINGsConfiguration.boldSystemFont, size);
252 font = WMCreateFont(scrPtr, fontSpec);
254 if (!font) {
255 wwarning(_("could not load font %s. Trying sans."), fontSpec);
256 font = WMCreateFont(scrPtr, "sans:bold:pixelsize=12");
258 wfree(fontSpec);
260 return font;
265 WMWidthOfString(WMFont *font, char *text, int length)
267 XGlyphInfo extents;
269 wassertrv(font!=NULL, 0);
270 wassertrv(text!=NULL, 0);
272 if (!font->notFontSet) {
273 wchar_t *wtext;
274 char *mtext;
275 int len;
277 wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1));
278 mtext = text;
279 len = wmbsnrtowcs(wtext, &mtext, length, length);
280 if (len>0) {
281 wtext[len] = L'\0'; /* not really necessary here */
282 XftTextExtents32(font->screen->display, font->font,
283 (XftChar32 *)wtext, len, &extents);
284 } else {
285 if (len==-1) {
286 wwarning(_("Conversion to widechar failed (possible "
287 "invalid multibyte sequence): '%s':(pos %d)\n"),
288 text, mtext-text+1);
290 extents.xOff = 0;
292 wfree(wtext);
293 } else {
294 XftTextExtents8(font->screen->display, font->font,
295 (XftChar8 *)text, length, &extents);
298 return extents.xOff; /* don't ask :P */
303 void
304 WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font,
305 int x, int y, char *text, int length)
307 XftColor xftcolor;
309 wassertr(font!=NULL);
311 xftcolor.color.red = color->color.red;
312 xftcolor.color.green = color->color.green;
313 xftcolor.color.blue = color->color.blue;
314 xftcolor.color.alpha = color->alpha;;
315 xftcolor.pixel = W_PIXEL(color);
317 XftDrawChange(scr->xftdraw, d);
319 if (!font->notFontSet) {
320 wchar_t *wtext;
321 char *mtext;
322 int len;
324 wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1));
325 mtext = text;
326 len = wmbsnrtowcs(wtext, &mtext, length, length);
327 if (len>0) {
328 XftDrawString32(scr->xftdraw, &xftcolor, font->font,
329 x, y + font->y, (XftChar32*)wtext, len);
330 } else if (len==-1) {
331 wwarning(_("Conversion to widechar failed (possible invalid "
332 "multibyte sequence): '%s':(pos %d)\n"),
333 text, mtext-text+1);
334 /* we can draw normal text, or we can draw as much widechar
335 * text as was already converted until the error. go figure */
336 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font,
337 x, y + font->y, (XftChar8*)text, length);*/
339 wfree(wtext);
340 } else {
341 XftDrawString8(scr->xftdraw, &xftcolor, font->font,
342 x, y + font->y, (XftChar8*)text, length);
347 void
348 WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background,
349 WMFont *font, int x, int y, char *text, int length)
351 XftColor textColor;
352 XftColor bgColor;
354 wassertr(font!=NULL);
356 textColor.color.red = color->color.red;
357 textColor.color.green = color->color.green;
358 textColor.color.blue = color->color.blue;
359 textColor.color.alpha = color->alpha;;
360 textColor.pixel = W_PIXEL(color);
362 bgColor.color.red = background->color.red;
363 bgColor.color.green = background->color.green;
364 bgColor.color.blue = background->color.blue;
365 bgColor.color.alpha = background->alpha;;
366 bgColor.pixel = W_PIXEL(background);
368 XftDrawChange(scr->xftdraw, d);
370 XftDrawRect(scr->xftdraw, &bgColor, x, y,
371 WMWidthOfString(font, text, length),
372 font->height);
374 if (!font->notFontSet) {
375 wchar_t *wtext;
376 char *mtext;
377 int len;
379 mtext = text;
380 wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1));
381 len = wmbsnrtowcs(wtext, &mtext, length, length);
382 if (len>0) {
383 XftDrawString32(scr->xftdraw, &textColor, font->font,
384 x, y + font->y, (XftChar32*)wtext, len);
385 } else if (len==-1) {
386 wwarning(_("Conversion to widechar failed (possible invalid "
387 "multibyte sequence): '%s':(pos %d)\n"),
388 text, mtext-text+1);
389 /* we can draw normal text, or we can draw as much widechar
390 * text as was already converted until the error. go figure */
391 /*XftDrawString8(scr->xftdraw, &textColor, font->font,
392 x, y + font->y, (XftChar8*)text, length);*/
394 wfree(wtext);
395 } else {
396 XftDrawString8(scr->xftdraw, &textColor, font->font,
397 x, y + font->y, (XftChar8*)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;
454 #define FONT_PROPS 14
456 typedef struct {
457 char *props[FONT_PROPS];
458 } W_FontAttributes;
461 static void
462 changeFontProp(char *buf, char *newprop, int position)
464 char buf2[512];
465 char *ptr, *pptr, *rptr;
466 int count;
468 if (buf[0]!='-') {
469 /* // remove warning later. or maybe not */
470 wwarning(_("Invalid font specification: '%s'\n"), buf);
471 return;
474 ptr = pptr = rptr = buf;
475 count = 0;
476 while (*ptr && *ptr!=',') {
477 if (*ptr == '-') {
478 count++;
479 if (count-1==position+1) {
480 rptr = ptr;
481 break;
483 if (count-1==position) {
484 pptr = ptr+1;
487 ptr++;
489 if (position==FONT_PROPS-1) {
490 rptr = ptr;
493 *pptr = 0;
494 snprintf(buf2, 512, "%s%s%s", buf, newprop, rptr);
495 strcpy(buf, buf2);
499 static WMArray*
500 getOptions(char *options)
502 char *ptr, *ptr2, *str;
503 WMArray *result;
504 int count;
506 result = WMCreateArrayWithDestructor(2, (WMFreeDataProc*)wfree);
508 ptr = options;
509 while (1) {
510 ptr2 = strchr(ptr, ',');
511 if (!ptr2) {
512 WMAddToArray(result, wstrdup(ptr));
513 break;
514 } else {
515 count = ptr2 - ptr;
516 str = wmalloc(count+1);
517 memcpy(str, ptr, count);
518 str[count] = 0;
519 WMAddToArray(result, str);
520 ptr = ptr2 + 1;
524 return result;
528 WMFont*
529 WMCopyFontWithChanges(WMScreen *scrPtr, WMFont *font,
530 const WMFontAttributes *changes)
532 int index[FONT_PROPS], count[FONT_PROPS];
533 int totalProps, i, j, carry;
534 char fname[512];
535 WMFontFlags fFlags;
536 WMBag *props;
537 WMArray *options;
538 WMFont *result;
539 char *prop;
541 snprintf(fname, 512, "%s", font->name);
543 fFlags = (font->antialiased ? WFAntialiased : WFNotAntialiased);
544 fFlags |= (font->notFontSet ? WFNormalFont : WFFontSet);
546 props = WMCreateBagWithDestructor(1, (WMFreeDataProc*)WMFreeArray);
548 totalProps = 0;
549 for (i=0; i<FONT_PROPS; i++) {
550 prop = ((W_FontAttributes*)changes)->props[i];
551 count[i] = index[i] = 0;
552 if (!prop) {
553 /* No change for this property */
554 continue;
555 } else if (strchr(prop, ',')==NULL) {
556 /* Simple option */
557 changeFontProp(fname, prop, i);
558 } else {
559 /* Option with fallback alternatives */
560 if ((changes==WFAEmphasized || changes==WFABoldEmphasized) &&
561 font->antialiased && strcmp(prop, "o,i")==0) {
562 options = getOptions("i,o");
563 } else {
564 options = getOptions(prop);
566 WMInsertInBag(props, i, options);
567 count[i] = WMGetArrayItemCount(options);
568 if (totalProps==0)
569 totalProps = 1;
570 totalProps = totalProps * count[i];
574 if (totalProps == 0) {
575 /* No options with fallback alternatives at all */
576 WMFreeBag(props);
577 return WMCreateFontWithFlags(scrPtr, fname, fFlags);
580 for (i=0; i<totalProps; i++) {
581 for (j=0; j<FONT_PROPS; j++) {
582 if (count[j]!=0) {
583 options = WMGetFromBag(props, j);
584 prop = WMGetFromArray(options, index[j]);
585 if (prop) {
586 changeFontProp(fname, prop, j);
590 result = WMCreateFontWithFlags(scrPtr, fname, fFlags);
591 if (result) {
592 WMFreeBag(props);
593 return result;
595 for (j=FONT_PROPS-1, carry=1; j>=0; j--) {
596 if (count[j]!=0) {
597 index[j] += carry;
598 carry = (index[j]==count[j]);
599 index[j] %= count[j];
604 WMFreeBag(props);
606 return NULL;
610 #else /* No XFT support */
613 static char *makeFontSetOfSize(char *fontset, int size);
617 /* XLFD pattern matching */
618 static char*
619 getElementFromXLFD(const char *xlfd, int index)
621 const char *p = xlfd;
622 while (*p != 0) {
623 if (*p == '-' && --index == 0) {
624 const char *end = strchr(p + 1, '-');
625 char *buf;
626 size_t len;
627 if (end == 0) end = p + strlen(p);
628 len = end - (p + 1);
629 buf = wmalloc(len);
630 memcpy(buf, p + 1, len);
631 buf[len] = 0;
632 return buf;
634 p++;
636 return strdup("*");
640 /* XLFD pattern matching */
641 static char*
642 generalizeXLFD(const char *xlfd)
644 char *buf;
645 int len;
646 char *weight = getElementFromXLFD(xlfd, 3);
647 char *slant = getElementFromXLFD(xlfd, 4);
648 char *pxlsz = getElementFromXLFD(xlfd, 7);
650 #define Xstrlen(A) ((A)?strlen(A):0)
651 len = Xstrlen(xlfd)+Xstrlen(weight)+Xstrlen(slant)+Xstrlen(pxlsz)*2+60;
652 #undef Xstrlen
654 buf = wmalloc(len + 1);
655 snprintf(buf, len + 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
656 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
657 xlfd, weight, slant, pxlsz, pxlsz);
659 wfree(pxlsz);
660 wfree(slant);
661 wfree(weight);
663 return buf;
666 /* XLFD pattern matching */
667 static XFontSet
668 W_CreateFontSetWithGuess(Display *dpy, char *xlfd, char ***missing,
669 int *nmissing, char **def_string)
671 XFontSet fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
673 if (fs != NULL && *nmissing == 0) return fs;
675 /* for non-iso8859-1 language and iso8859-1 specification
676 (this fontset is only for pattern analysis) */
677 if (fs == NULL) {
678 if (*nmissing != 0) XFreeStringList(*missing);
679 setlocale(LC_CTYPE, "C");
680 fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
681 setlocale(LC_CTYPE, "");
684 /* make XLFD font name for pattern analysis */
685 if (fs != NULL) {
686 XFontStruct **fontstructs;
687 char **fontnames;
688 if (XFontsOfFontSet(fs, &fontstructs, &fontnames) > 0)
689 xlfd = fontnames[0];
692 xlfd = generalizeXLFD(xlfd);
694 if (*nmissing != 0) XFreeStringList(*missing);
695 if (fs != NULL) XFreeFontSet(dpy, fs);
697 fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
699 wfree(xlfd);
700 return fs;
704 static char*
705 xlfdFromFontName(char *fontName, Bool antialiased)
707 char *systemFont, *boldSystemFont;
708 char *font;
709 int size;
711 if (antialiased) {
712 systemFont = WINGsConfiguration.antialiasedSystemFont;
713 boldSystemFont = WINGsConfiguration.antialiasedBoldSystemFont;
714 } else {
715 systemFont = WINGsConfiguration.systemFont;
716 boldSystemFont = WINGsConfiguration.boldSystemFont;
719 size = WINGsConfiguration.defaultFontSize;
721 if (strcmp(fontName, "SystemFont")==0) {
722 font = systemFont;
723 size = WINGsConfiguration.defaultFontSize;
724 } else if (strncmp(fontName, "SystemFont-", 11)==0) {
725 font = systemFont;
726 if (sscanf(&fontName[11], "%i", &size)!=1) {
727 size = WINGsConfiguration.defaultFontSize;
728 wwarning(_("Invalid size specification '%s' in %s. "
729 "Using default %d\n"), &fontName[11], fontName, size);
731 } else if (strcmp(fontName, "BoldSystemFont")==0) {
732 font = boldSystemFont;
733 size = WINGsConfiguration.defaultFontSize;
734 } else if (strncmp(fontName, "BoldSystemFont-", 15)==0) {
735 font = boldSystemFont;
736 if (sscanf(&fontName[15], "%i", &size)!=1) {
737 size = WINGsConfiguration.defaultFontSize;
738 wwarning(_("Invalid size specification '%s' in %s. "
739 "Using default %d\n"), &fontName[15], fontName, size);
741 } else {
742 font = NULL;
745 return (font!=NULL ? makeFontSetOfSize(font, size) : wstrdup(fontName));
749 WMFont*
750 WMCreateFontSet(WMScreen *scrPtr, char *fontName)
752 WMFont *font;
753 Display *display = scrPtr->display;
754 char **missing;
755 int nmissing = 0;
756 char *defaultString;
757 char *fname;
758 XFontSetExtents *extents;
760 fname = xlfdFromFontName(fontName, False);
762 font = WMHashGet(scrPtr->fontSetCache, fname);
763 if (font) {
764 WMRetainFont(font);
765 wfree(fname);
766 return font;
769 font = wmalloc(sizeof(WMFont));
770 memset(font, 0, sizeof(WMFont));
772 font->notFontSet = 0;
773 font->antialiased = 0;
775 font->screen = scrPtr;
777 font->font.set = W_CreateFontSetWithGuess(display, fname, &missing,
778 &nmissing, &defaultString);
779 if (nmissing > 0 && font->font.set) {
780 int i;
782 wwarning(_("the following character sets are missing in %s:"), fname);
783 for (i = 0; i < nmissing; i++) {
784 wwarning(missing[i]);
786 XFreeStringList(missing);
787 if (defaultString)
788 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
789 defaultString);
791 if (!font->font.set) {
792 wfree(font);
793 wfree(fname);
794 return NULL;
797 extents = XExtentsOfFontSet(font->font.set);
799 font->height = extents->max_logical_extent.height;
800 font->y = font->height - (font->height + extents->max_logical_extent.y);
802 font->refCount = 1;
804 font->name = fname;
806 assert(WMHashInsert(scrPtr->fontSetCache, font->name, font)==NULL);
808 return font;
813 WMFont*
814 WMCreateNormalFont(WMScreen *scrPtr, char *fontName)
816 WMFont *font;
817 Display *display = scrPtr->display;
818 char *fname, *ptr;
820 fontName = xlfdFromFontName(fontName, False);
822 if ((ptr = strchr(fontName, ','))) {
823 fname = wmalloc(ptr - fontName + 1);
824 strncpy(fname, fontName, ptr - fontName);
825 fname[ptr - fontName] = 0;
826 } else {
827 fname = wstrdup(fontName);
830 wfree(fontName);
832 font = WMHashGet(scrPtr->fontCache, fname);
833 if (font) {
834 WMRetainFont(font);
835 wfree(fname);
836 return font;
839 font = wmalloc(sizeof(WMFont));
840 memset(font, 0, sizeof(WMFont));
842 font->notFontSet = 1;
843 font->antialiased = 0;
845 font->screen = scrPtr;
847 font->font.normal = XLoadQueryFont(display, fname);
848 if (!font->font.normal) {
849 wfree(font);
850 wfree(fname);
851 return NULL;
853 font->height = font->font.normal->ascent+font->font.normal->descent;
854 font->y = font->font.normal->ascent;
856 font->refCount = 1;
858 font->name = fname;
860 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
862 return font;
866 WMFont*
867 WMCreateAntialiasedFont(WMScreen *scrPtr, char *fontName)
869 #ifdef XFT
870 WMFont *font;
871 Display *display = scrPtr->display;
872 char *fname, *ptr;
874 fontName = xlfdFromFontName(fontName, True);
876 if ((ptr = strchr(fontName, ','))) {
877 fname = wmalloc(ptr - fontName + 1);
878 strncpy(fname, fontName, ptr - fontName);
879 fname[ptr - fontName] = 0;
880 } else {
881 fname = wstrdup(fontName);
884 wfree(fontName);
886 font = WMHashGet(scrPtr->xftFontCache, fname);
887 if (font) {
888 WMRetainFont(font);
889 wfree(fname);
890 return font;
893 font = wmalloc(sizeof(WMFont));
894 memset(font, 0, sizeof(WMFont));
896 font->notFontSet = 1;
897 font->antialiased = 1;
899 font->screen = scrPtr;
901 /* Xft sux. Loading a font with an invalid XLFD will give strange results
902 * sometimes without returning any warning or error.
903 * However Xft's idea of what font is invalid is quite strange:
904 * 1. If the XLFD doesn't have all its fields present will fail and
905 * return NULL.
906 * 2. If all fields are present, but hold invalid values then it will:
907 * a. If family is invalid, will load a default font without warning.
908 * b. If the font size is invalid (non-numerical) it will fail and
909 * return NULL.
910 * c. If other fields are invalid, will load the font specified by
911 * the valid family name, ignoring any invalid fields. It will
912 * use a default medium weight and a default roman slant if they
913 * are invalid.
915 printf("%s\n", fname);
916 if (fname[0] == '-') {
917 font->font.xft = XftFontOpenXlfd(display, scrPtr->screen, fname);
918 } else {
919 font->font.xft = XftFontOpenName(display, scrPtr->screen, fname);
921 if (!font->font.xft) {
922 wfree(font);
923 wfree(fname);
924 return NULL;
926 font->height = font->font.xft->ascent+font->font.xft->descent;
927 font->y = font->font.xft->ascent;
929 font->refCount = 1;
931 font->name = fname;
933 assert(WMHashInsert(scrPtr->xftFontCache, font->name, font)==NULL);
935 return font;
936 #else
937 return NULL;
938 #endif
942 WMFont*
943 WMCreateAntialiasedFontSet(WMScreen *scrPtr, char *fontName)
945 #ifdef XFT
946 WMFont *font;
947 Display *display = scrPtr->display;
948 char *fname, *ptr;
950 fontName = xlfdFromFontName(fontName, True);
952 if ((ptr = strchr(fontName, ','))) {
953 fname = wmalloc(ptr - fontName + 1);
954 strncpy(fname, fontName, ptr - fontName);
955 fname[ptr - fontName] = 0;
956 } else {
957 fname = wstrdup(fontName);
960 wfree(fontName);
962 font = WMHashGet(scrPtr->xftFontSetCache, fname);
963 if (font) {
964 WMRetainFont(font);
965 wfree(fname);
966 return font;
969 font = wmalloc(sizeof(WMFont));
970 memset(font, 0, sizeof(WMFont));
972 font->notFontSet = 0;
973 font->antialiased = 1;
975 font->screen = scrPtr;
977 /* Xft sux. Loading a font with an invalid XLFD will give strange results
978 * sometimes without returning any warning or error.
979 * However Xft's idea of what font is invalid is quite strange:
980 * 1. If the XLFD doesn't have all its fields present will fail and
981 * return NULL.
982 * 2. If all fields are present, but hold invalid values then it will:
983 * a. If family is invalid, will load a default font without warning.
984 * b. If the font size is invalid (non-numerical) it will fail and
985 * return NULL.
986 * c. If other fields are invalid, will load the font specified by
987 * the valid family name, ignoring any invalid fields. It will
988 * use a default medium weight and a default roman slant if they
989 * are invalid.
991 if (fname[0] == '-') {
992 font->font.xft = XftFontOpenXlfd(display, scrPtr->screen, fname);
993 } else {
994 font->font.xft = XftFontOpenName(display, scrPtr->screen, fname);
996 if (!font->font.xft) {
997 wfree(font);
998 wfree(fname);
999 return NULL;
1001 font->height = font->font.xft->ascent+font->font.xft->descent;
1002 font->y = font->font.xft->ascent;
1004 font->refCount = 1;
1006 font->name = fname;
1008 assert(WMHashInsert(scrPtr->xftFontSetCache, font->name, font)==NULL);
1010 return font;
1011 #else
1012 return NULL;
1013 #endif
1017 WMFont*
1018 WMCreateFont(WMScreen *scrPtr, char *fontName)
1020 return WMCreateFontWithFlags(scrPtr, fontName, WFDefaultFont);
1024 WMFont*
1025 WMCreateFontWithFlags(WMScreen *scrPtr, char *fontName, WMFontFlags flags)
1027 Bool multiByte = scrPtr->useMultiByte;
1028 Bool antialiased = scrPtr->antialiasedText;
1029 WMFont *font;
1031 if (flags & WFFontSet) {
1032 multiByte = True;
1033 } else if (flags & WFNormalFont) {
1034 multiByte = False;
1036 if (flags & WFAntialiased) {
1037 antialiased = True;
1038 } else if (flags & WFNotAntialiased) {
1039 antialiased = False;
1042 if (antialiased && multiByte) {
1043 font = WMCreateAntialiasedFontSet(scrPtr, fontName);
1044 /* If we cannot create an antialiased font set and antialiasing is
1045 * not explicitly requested in flags, fallback to standard font sets */
1046 if (!font && (flags & WFAntialiased)==0) {
1047 font = WMCreateFontSet(scrPtr, fontName);
1049 } else if (antialiased) {
1050 font = WMCreateAntialiasedFont(scrPtr, fontName);
1051 /* If we cannot create an antialiased font and antialiasing is
1052 * not explicitly requested in flags, fallback to normal font */
1053 if (!font && (flags & WFAntialiased)==0) {
1054 font = WMCreateNormalFont(scrPtr, fontName);
1056 } else if (multiByte) {
1057 font = WMCreateFontSet(scrPtr, fontName);
1058 } else {
1059 font = WMCreateNormalFont(scrPtr, fontName);
1062 return font;
1066 WMFont*
1067 WMRetainFont(WMFont *font)
1069 wassertrv(font!=NULL, NULL);
1071 font->refCount++;
1073 return font;
1077 void
1078 WMReleaseFont(WMFont *font)
1080 wassertr(font!=NULL);
1082 font->refCount--;
1083 if (font->refCount < 1) {
1084 if (font->antialiased) {
1085 #ifdef XFT
1086 XftFontClose(font->screen->display, font->font.xft);
1087 #else
1088 assert(False);
1089 #endif
1090 } else if (font->notFontSet) {
1091 XFreeFont(font->screen->display, font->font.normal);
1092 } else {
1093 XFreeFontSet(font->screen->display, font->font.set);
1096 if (font->name) {
1097 if (font->antialiased && !font->notFontSet) {
1098 WMHashRemove(font->screen->xftFontSetCache, font->name);
1099 } else if (font->antialiased) {
1100 WMHashRemove(font->screen->xftFontCache, font->name);
1101 } else if (font->notFontSet) {
1102 WMHashRemove(font->screen->fontCache, font->name);
1103 } else {
1104 WMHashRemove(font->screen->fontSetCache, font->name);
1106 wfree(font->name);
1108 wfree(font);
1113 Bool
1114 WMIsAntialiasingEnabled(WMScreen *scrPtr)
1116 return scrPtr->antialiasedText;
1120 Bool
1121 WMIsAntialiasedFont(WMFont *font)
1123 wassertrv(font!=NULL, False);
1125 return font->antialiased;
1129 unsigned int
1130 WMFontHeight(WMFont *font)
1132 wassertrv(font!=NULL, 0);
1134 return font->height;
1138 char*
1139 WMGetFontName(WMFont *font)
1141 wassertrv(font!=NULL, NULL);
1143 return font->name;
1147 WMFont*
1148 WMDefaultSystemFont(WMScreen *scrPtr)
1150 return WMRetainFont(scrPtr->normalFont);
1154 WMFont*
1155 WMDefaultBoldSystemFont(WMScreen *scrPtr)
1157 return WMRetainFont(scrPtr->boldFont);
1161 static WMFont*
1162 makeSystemFontOfSize(WMScreen *scrPtr, int size, Bool bold)
1164 WMFont *font;
1165 char *fontSpec, *xftFontSpec;
1167 #define WConf WINGsConfiguration
1168 if (bold) {
1169 fontSpec = makeFontSetOfSize(WConf.boldSystemFont, size);
1170 xftFontSpec = makeFontSetOfSize(WConf.antialiasedBoldSystemFont, size);
1171 } else {
1172 fontSpec = makeFontSetOfSize(WConf.systemFont, size);
1173 xftFontSpec = makeFontSetOfSize(WConf.antialiasedSystemFont, size);
1175 #undef WConf
1177 if (scrPtr->antialiasedText && scrPtr->useMultiByte) {
1178 font = WMCreateAntialiasedFontSet(scrPtr, xftFontSpec);
1179 } else if (scrPtr->antialiasedText) {
1180 font = WMCreateAntialiasedFont(scrPtr, xftFontSpec);
1181 } else if (scrPtr->useMultiByte) {
1182 font = WMCreateFontSet(scrPtr, fontSpec);
1183 } else {
1184 font = WMCreateNormalFont(scrPtr, fontSpec);
1187 if (!font) {
1188 if (scrPtr->antialiasedText && scrPtr->useMultiByte) {
1189 // is arial a good fallback for multibyte?
1190 wwarning(_("could not load font %s. Trying arial."), xftFontSpec);
1191 if (bold) {
1192 font = WMCreateAntialiasedFontSet(scrPtr, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1193 } else {
1194 font = WMCreateAntialiasedFontSet(scrPtr, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1196 if (!font) {
1197 wwarning(_("could not load antialiased font set. Reverting to standard font sets."));
1198 font = WMCreateFontSet(scrPtr, fontSpec);
1199 if (!font) {
1200 wwarning(_("could not load FontSet %s. Trying fixed."), fontSpec);
1201 font = WMCreateFontSet(scrPtr, "fixed");
1204 } else if (scrPtr->antialiasedText) {
1205 wwarning(_("could not load font %s. Trying arial."), xftFontSpec);
1206 if (bold) {
1207 font = WMCreateAntialiasedFont(scrPtr, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1208 } else {
1209 font = WMCreateAntialiasedFont(scrPtr, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1211 if (!font) {
1212 wwarning(_("could not load antialiased fonts. Reverting to normal fonts."));
1213 font = WMCreateNormalFont(scrPtr, fontSpec);
1214 if (!font) {
1215 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
1216 font = WMCreateNormalFont(scrPtr, "fixed");
1219 } else if (scrPtr->useMultiByte) {
1220 wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
1221 font = WMCreateFontSet(scrPtr, "fixed");
1222 if (!font) {
1223 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
1225 } else {
1226 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
1227 font = WMCreateNormalFont(scrPtr, "fixed");
1229 if (!font) {
1230 wwarning(_("could not load fixed font!"));
1231 wfree(fontSpec);
1232 wfree(xftFontSpec);
1233 return NULL;
1236 wfree(fontSpec);
1237 wfree(xftFontSpec);
1239 return font;
1243 WMFont*
1244 WMSystemFontOfSize(WMScreen *scrPtr, int size)
1246 return makeSystemFontOfSize(scrPtr, size, False);
1250 WMFont*
1251 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
1253 return makeSystemFontOfSize(scrPtr, size, True);
1257 XFontSet
1258 WMGetFontFontSet(WMFont *font)
1260 wassertrv(font!=NULL, NULL);
1262 if (!font->notFontSet && !font->antialiased)
1263 return font->font.set;
1265 return NULL;
1270 WMWidthOfString(WMFont *font, char *text, int length)
1272 wassertrv(font!=NULL, 0);
1273 wassertrv(text!=NULL, 0);
1275 if (font->antialiased) {
1276 #ifdef XFT
1277 XGlyphInfo extents;
1279 if (!font->notFontSet) {
1280 wchar_t *wtext;
1281 char *mtext;
1282 int len;
1284 /* Use mtext instead of text, because mbstrtowcs() alters it */
1285 mtext = text;
1286 wtext = (wchar_t *)wmalloc(4*length+4);
1287 /* pass a real ps instead of NULL below? for multithread safety
1288 * as from manual page */
1289 len = mbsrtowcs(wtext, (const char **) &mtext, length, NULL);
1290 if (len>0) {
1291 XftTextExtents32(font->screen->display, font->font.xft,
1292 (XftChar32 *)wtext, len, &extents);
1293 } else {
1294 if (len==-1) {
1295 wwarning(_("Conversion to widechar failed (possible "
1296 "invalid multibyte sequence): '%s':(pos %d)\n"),
1297 text, mtext-text+1);
1299 extents.xOff = 0;
1301 wfree(wtext);
1302 } else {
1303 XftTextExtents8(font->screen->display, font->font.xft,
1304 (XftChar8 *)text, length, &extents);
1307 return extents.xOff; /* don't ask :P */
1308 #else
1309 wassertrv(False, 0);
1310 #endif
1311 } else if (font->notFontSet) {
1312 return XTextWidth(font->font.normal, text, length);
1313 } else {
1314 XRectangle rect;
1315 XRectangle AIXsucks;
1317 XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
1319 return rect.width;
1325 void
1326 WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font,
1327 int x, int y, char *text, int length)
1329 wassertr(font!=NULL);
1331 if (font->antialiased) {
1332 #ifdef XFT
1333 XftColor xftcolor;
1335 xftcolor.color.red = color->color.red;
1336 xftcolor.color.green = color->color.green;
1337 xftcolor.color.blue = color->color.blue;
1338 xftcolor.color.alpha = color->alpha;;
1339 xftcolor.pixel = W_PIXEL(color);
1341 XftDrawChange(scr->xftdraw, d);
1343 if (!font->notFontSet) {
1344 wchar_t *wtext;
1345 char *mtext;
1346 int len;
1348 /* Use mtext instead of text, because mbstrtowcs() alters it */
1349 mtext = text;
1350 wtext = (wchar_t *)wmalloc(4*length+4);
1351 len = mbsrtowcs(wtext, (const char **) &mtext, length, NULL);
1352 if (len>0) {
1353 XftDrawString32(scr->xftdraw, &xftcolor, font->font.xft,
1354 x, y + font->y, (XftChar32*)wtext, len);
1355 } else if (len==-1) {
1356 wwarning(_("Conversion to widechar failed (possible invalid "
1357 "multibyte sequence): '%s':(pos %d)\n"),
1358 text, mtext-text+1);
1359 /* we can draw normal text, or we can draw as much widechar
1360 * text as was already converted until the error. go figure */
1361 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
1362 x, y + font->y, (XftChar8*)text, length);*/
1364 wfree(wtext);
1365 } else {
1366 XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
1367 x, y + font->y, (XftChar8*)text, length);
1369 #else
1370 wassertr(False);
1371 #endif
1372 } else if (font->notFontSet) {
1373 XSetFont(scr->display, scr->drawStringGC, font->font.normal->fid);
1374 XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color));
1375 XDrawString(scr->display, d, scr->drawStringGC, x, y + font->y,
1376 text, length);
1377 } else {
1378 XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color));
1379 XmbDrawString(scr->display, d, font->font.set, scr->drawStringGC,
1380 x, y + font->y, text, length);
1385 void
1386 WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background,
1387 WMFont *font, int x, int y, char *text, int length)
1389 wassertr(font!=NULL);
1391 if (font->antialiased) {
1392 #ifdef XFT
1393 XftColor textColor;
1394 XftColor bgColor;
1396 textColor.color.red = color->color.red;
1397 textColor.color.green = color->color.green;
1398 textColor.color.blue = color->color.blue;
1399 textColor.color.alpha = color->alpha;;
1400 textColor.pixel = W_PIXEL(color);
1402 bgColor.color.red = background->color.red;
1403 bgColor.color.green = background->color.green;
1404 bgColor.color.blue = background->color.blue;
1405 bgColor.color.alpha = background->alpha;;
1406 bgColor.pixel = W_PIXEL(background);
1409 XftDrawChange(scr->xftdraw, d);
1411 XftDrawRect(scr->xftdraw, &bgColor, x, y,
1412 WMWidthOfString(font, text, length), font->height);
1414 if (!font->notFontSet) {
1415 wchar_t *wtext;
1416 char *mtext;
1417 int len;
1419 /* Use mtext instead of text, because mbstrtowcs() alters it */
1420 mtext = text;
1421 wtext = (wchar_t *)wmalloc(4*length+4);
1422 len = mbsrtowcs(wtext, (const char **) &mtext, length, NULL);
1423 if (len>0) {
1424 XftDrawString32(scr->xftdraw, &textColor, font->font.xft,
1425 x, y + font->y, (XftChar32*)wtext, len);
1426 } else if (len==-1) {
1427 wwarning(_("Conversion to widechar failed (possible invalid "
1428 "multibyte sequence): '%s':(pos %d)\n"),
1429 text, mtext-text+1);
1430 /* we can draw normal text, or we can draw as much widechar
1431 * text as was already converted until the error. go figure */
1432 /*XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
1433 x, y + font->y, (XftChar8*)text, length);*/
1435 wfree(wtext);
1436 } else {
1437 XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
1438 x, y + font->y, (XftChar8*)text, length);
1440 #else
1441 wassertr(False);
1442 #endif
1443 } else if (font->notFontSet) {
1444 XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color));
1445 XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background));
1446 XSetFont(scr->display, scr->drawImStringGC, font->font.normal->fid);
1447 XDrawImageString(scr->display, d, scr->drawImStringGC,
1448 x, y + font->y, text, length);
1449 } else {
1450 XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color));
1451 XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background));
1452 XmbDrawImageString(scr->display, d, font->font.set, scr->drawImStringGC,
1453 x, y + font->y, text, length);
1460 static char*
1461 makeFontSetOfSize(char *fontset, int size)
1463 char font[300], *f;
1464 char *newfs = NULL;
1465 char *ptr;
1467 do {
1468 char *tmp;
1469 int end;
1472 f = fontset;
1473 ptr = strchr(fontset, ',');
1474 if (ptr) {
1475 int count = ptr-fontset;
1477 if (count > 255) {
1478 wwarning(_("font description %s is too large."), fontset);
1479 } else {
1480 memcpy(font, fontset, count);
1481 font[count] = 0;
1482 f = (char*)font;
1486 if (newfs)
1487 end = strlen(newfs);
1488 else
1489 end = 0;
1491 tmp = wmalloc(end + strlen(f) + 8);
1492 if (end != 0) {
1493 sprintf(tmp, "%s,", newfs);
1494 sprintf(tmp + end + 1, f, size);
1495 } else {
1496 sprintf(tmp + end, f, size);
1499 if (newfs)
1500 wfree(newfs);
1501 newfs = tmp;
1503 fontset = ptr+1;
1504 } while (ptr!=NULL);
1506 return newfs;
1510 #define FONT_PROPS 14
1512 typedef struct {
1513 char *props[FONT_PROPS];
1514 } W_FontAttributes;
1517 static void
1518 changeFontProp(char *buf, char *newprop, int position)
1520 char buf2[512];
1521 char *ptr, *pptr, *rptr;
1522 int count;
1524 if (buf[0]!='-') {
1525 /* // remove warning later. or maybe not */
1526 wwarning(_("Invalid font specification: '%s'\n"), buf);
1527 return;
1530 ptr = pptr = rptr = buf;
1531 count = 0;
1532 while (*ptr && *ptr!=',') {
1533 if (*ptr == '-') {
1534 count++;
1535 if (count-1==position+1) {
1536 rptr = ptr;
1537 break;
1539 if (count-1==position) {
1540 pptr = ptr+1;
1543 ptr++;
1545 if (position==FONT_PROPS-1) {
1546 rptr = ptr;
1549 *pptr = 0;
1550 snprintf(buf2, 512, "%s%s%s", buf, newprop, rptr);
1551 strcpy(buf, buf2);
1555 static WMArray*
1556 getOptions(char *options)
1558 char *ptr, *ptr2, *str;
1559 WMArray *result;
1560 int count;
1562 result = WMCreateArrayWithDestructor(2, (WMFreeDataProc*)wfree);
1564 ptr = options;
1565 while (1) {
1566 ptr2 = strchr(ptr, ',');
1567 if (!ptr2) {
1568 WMAddToArray(result, wstrdup(ptr));
1569 break;
1570 } else {
1571 count = ptr2 - ptr;
1572 str = wmalloc(count+1);
1573 memcpy(str, ptr, count);
1574 str[count] = 0;
1575 WMAddToArray(result, str);
1576 ptr = ptr2 + 1;
1580 return result;
1584 WMFont*
1585 WMCopyFontWithChanges(WMScreen *scrPtr, WMFont *font,
1586 const WMFontAttributes *changes)
1588 int index[FONT_PROPS], count[FONT_PROPS];
1589 int totalProps, i, j, carry;
1590 char fname[512];
1591 WMFontFlags fFlags;
1592 WMBag *props;
1593 WMArray *options;
1594 WMFont *result;
1595 char *prop;
1597 snprintf(fname, 512, "%s", font->name);
1599 fFlags = (font->antialiased ? WFAntialiased : WFNotAntialiased);
1600 fFlags |= (font->notFontSet ? WFNormalFont : WFFontSet);
1602 props = WMCreateBagWithDestructor(1, (WMFreeDataProc*)WMFreeArray);
1604 totalProps = 0;
1605 for (i=0; i<FONT_PROPS; i++) {
1606 prop = ((W_FontAttributes*)changes)->props[i];
1607 count[i] = index[i] = 0;
1608 if (!prop) {
1609 /* No change for this property */
1610 continue;
1611 } else if (strchr(prop, ',')==NULL) {
1612 /* Simple option */
1613 changeFontProp(fname, prop, i);
1614 } else {
1615 /* Option with fallback alternatives */
1616 if ((changes==WFAEmphasized || changes==WFABoldEmphasized) &&
1617 font->antialiased && strcmp(prop, "o,i")==0) {
1618 options = getOptions("i,o");
1619 } else {
1620 options = getOptions(prop);
1622 WMInsertInBag(props, i, options);
1623 count[i] = WMGetArrayItemCount(options);
1624 if (totalProps==0)
1625 totalProps = 1;
1626 totalProps = totalProps * count[i];
1630 if (totalProps == 0) {
1631 /* No options with fallback alternatives at all */
1632 WMFreeBag(props);
1633 return WMCreateFontWithFlags(scrPtr, fname, fFlags);
1636 for (i=0; i<totalProps; i++) {
1637 for (j=0; j<FONT_PROPS; j++) {
1638 if (count[j]!=0) {
1639 options = WMGetFromBag(props, j);
1640 prop = WMGetFromArray(options, index[j]);
1641 if (prop) {
1642 changeFontProp(fname, prop, j);
1646 result = WMCreateFontWithFlags(scrPtr, fname, fFlags);
1647 if (result) {
1648 WMFreeBag(props);
1649 return result;
1651 for (j=FONT_PROPS-1, carry=1; j>=0; j--) {
1652 if (count[j]!=0) {
1653 index[j] += carry;
1654 carry = (index[j]==count[j]);
1655 index[j] %= count[j];
1660 WMFreeBag(props);
1662 return NULL;
1665 #endif
1668 // should WFANormal also set "normal" or leave it alone?
1669 static const WMFontAttributes W_FANormal = {
1670 WFAUnchanged, WFAUnchanged, "medium,normal,regular", "r", "normal",
1671 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged,
1672 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged
1676 static const WMFontAttributes W_FABold = {
1677 WFAUnchanged, WFAUnchanged, "bold", WFAUnchanged,
1678 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged,
1679 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged
1683 static const WMFontAttributes W_FANotBold = {
1684 WFAUnchanged, WFAUnchanged, "medium,normal,regular", WFAUnchanged,
1685 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged,
1686 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged
1690 static const WMFontAttributes W_FAEmphasized = {
1691 WFAUnchanged, WFAUnchanged, WFAUnchanged, "o,i",
1692 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged,
1693 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged
1697 static const WMFontAttributes W_FANotEmphasized = {
1698 WFAUnchanged, WFAUnchanged, WFAUnchanged, "r",
1699 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged,
1700 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged
1704 static const WMFontAttributes W_FABoldEmphasized = {
1705 WFAUnchanged, WFAUnchanged, "bold", "o,i",
1706 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged,
1707 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged
1711 const WMFontAttributes *WFANormal = &W_FANormal;
1712 const WMFontAttributes *WFABold = &W_FABold;
1713 const WMFontAttributes *WFANotBold = &W_FANotBold;
1714 const WMFontAttributes *WFAEmphasized = &W_FAEmphasized;
1715 const WMFontAttributes *WFANotEmphasized = &W_FANotEmphasized;
1716 const WMFontAttributes *WFABoldEmphasized = &W_FABoldEmphasized;