small 'remember todo' comment
[wmaker-crm.git] / WINGs / wfont.c
bloba625d32905a4d683693079b54163036316e945f1
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_MBSNRTOWCS)
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 memset(&ps, 0, sizeof(mbstate_t));
54 if (dest == NULL) {
55 for (ptr=*src, n=0; nbytes>0; n++) {
56 nb = mbrtowc(NULL, ptr, nbytes, &ps);
57 if (nb == -1) {
58 return ((size_t)-1);
59 } else if (nb==0 || nb==-2) {
60 return n;
62 ptr += nb;
63 nbytes -= nb;
67 for (ptr=*src, n=0; n<len && nbytes>0; n++, dest++) {
68 nb = mbrtowc(dest, ptr, nbytes, &ps);
69 if (nb == -2) {
70 *src = ptr;
71 return n;
72 } else if (nb == -1) {
73 *src = ptr;
74 return ((size_t)-1);
75 } else if (nb == 0) {
76 *src = NULL;
77 return n;
79 ptr += nb;
80 nbytes -= nb;
83 *src = ptr;
84 return n;
87 #else
89 // Not only 8 times slower than the version based on mbsnrtowcs
90 // but also this version is not thread safe nor reentrant
92 static size_t
93 wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len)
95 const char *ptr;
96 size_t n;
97 int nb;
99 if (nbytes==0)
100 return 0;
102 mbtowc(NULL, NULL, 0); /* reset shift state */
104 if (dest == NULL) {
105 for (ptr=*src, n=0; nbytes>0; n++) {
106 nb = mbtowc(NULL, ptr, nbytes);
107 if (nb == -1) {
108 mbtowc(NULL, NULL, 0);
109 nb = mbtowc(NULL, ptr, strlen(ptr));
110 return (nb == -1 ? (size_t)-1 : n);
111 } else if (nb==0) {
112 return n;
114 ptr += nb;
115 nbytes -= nb;
119 for (ptr=*src, n=0; n<len && nbytes>0; n++, dest++) {
120 nb = mbtowc(dest, ptr, nbytes);
121 if (nb == -1) {
122 mbtowc(NULL, NULL, 0);
123 nb = mbtowc(NULL, ptr, strlen(ptr));
124 *src = ptr;
125 return (nb == -1 ? (size_t)-1 : n);
126 } else if (nb == 0) {
127 *src = NULL;
128 return n;
130 ptr += nb;
131 nbytes -= nb;
134 *src = ptr;
135 return n;
138 #endif
141 static Bool
142 alreadyHasStringValue(XftPattern *pattern, const char *object, char *value)
144 XftResult r;
145 char *s;
146 int id;
148 if (!value || value[0]==0)
149 return True;
151 id = 0;
152 while ((r=XftPatternGetString(pattern, object, id, &s))!=XftResultNoId) {
153 if (r == XftResultMatch && strcasecmp(value, s) == 0) {
154 return True;
156 id++;
159 return False;
163 // check if to add a fallback size too. -Dan
164 // also handle an xlfd with %d for size?
165 static char*
166 makeFontOfSize(char *font, int size, char *fallback)
168 XftPattern *pattern;
169 char *result;
170 int len;
172 len = strlen(font) + 64;
173 pattern = XftNameParse(font);
174 XftPatternDel(pattern, "pixelsize");
175 XftPatternAddDouble(pattern, "pixelsize", (double)size);
176 if (fallback) {
177 if (!alreadyHasStringValue(pattern, "family", fallback)) {
178 len += strlen(fallback);
179 XftPatternAddString(pattern, "family", fallback);
182 result = wmalloc(len);
183 XftNameUnparse(pattern, result, len);
184 XftPatternDestroy(pattern);
186 return result;
190 WMFont*
191 WMCreateFont(WMScreen *scrPtr, char *fontName)
193 WMFont *font;
194 Display *display = scrPtr->display;
195 char *fname, *ptr;
197 /* This is for back-compat (to allow reading of old xlfd descriptions) */
198 if (fontName[0]=='-' && (ptr = strchr(fontName, ','))) {
199 fname = wmalloc(ptr - fontName + 1);
200 strncpy(fname, fontName, ptr - fontName);
201 fname[ptr - fontName] = 0;
202 } else {
203 fname = wstrdup(fontName);
206 font = WMHashGet(scrPtr->fontCache, fname);
207 if (font) {
208 WMRetainFont(font);
209 wfree(fname);
210 return font;
213 font = wmalloc(sizeof(WMFont));
214 memset(font, 0, sizeof(WMFont));
216 font->screen = scrPtr;
218 printf("%s\n", fname);
219 if (fname[0] == '-') {
220 /* Backward compat thing. Remove in a later version */
221 font->font = XftFontOpenXlfd(display, scrPtr->screen, fname);
222 } else {
223 font->font = XftFontOpenName(display, scrPtr->screen, fname);
225 if (!font->font) {
226 wfree(font);
227 wfree(fname);
228 return NULL;
230 font->height = font->font->ascent+font->font->descent;
231 font->y = font->font->ascent;
233 font->refCount = 1;
235 font->name = fname;
237 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
239 return font;
243 WMFont*
244 WMRetainFont(WMFont *font)
246 wassertrv(font!=NULL, NULL);
248 font->refCount++;
250 return font;
254 void
255 WMReleaseFont(WMFont *font)
257 wassertr(font!=NULL);
259 font->refCount--;
260 if (font->refCount < 1) {
261 XftFontClose(font->screen->display, font->font);
262 if (font->name) {
263 WMHashRemove(font->screen->fontCache, font->name);
264 wfree(font->name);
266 wfree(font);
271 Bool
272 WMIsAntialiasingEnabled(WMScreen *scrPtr)
274 return scrPtr->antialiasedText;
278 unsigned int
279 WMFontHeight(WMFont *font)
281 wassertrv(font!=NULL, 0);
283 return font->height;
287 char*
288 WMGetFontName(WMFont *font)
290 wassertrv(font!=NULL, NULL);
292 return font->name;
296 WMFont*
297 WMDefaultSystemFont(WMScreen *scrPtr)
299 return WMRetainFont(scrPtr->normalFont);
303 WMFont*
304 WMDefaultBoldSystemFont(WMScreen *scrPtr)
306 return WMRetainFont(scrPtr->boldFont);
310 WMFont*
311 WMSystemFontOfSize(WMScreen *scrPtr, int size)
313 WMFont *font;
314 char *fontSpec;
316 fontSpec = makeFontOfSize(WINGsConfiguration.systemFont, size, "sans");
318 font = WMCreateFont(scrPtr, fontSpec);
320 if (!font) {
321 wwarning(_("could not load font %s."), fontSpec);
324 wfree(fontSpec);
326 return font;
330 WMFont*
331 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
333 WMFont *font;
334 char *fontSpec;
336 fontSpec = makeFontOfSize(WINGsConfiguration.boldSystemFont, size, "sans");
338 font = WMCreateFont(scrPtr, fontSpec);
340 if (!font) {
341 wwarning(_("could not load font %s."), fontSpec);
344 wfree(fontSpec);
346 return font;
351 WMWidthOfString(WMFont *font, char *text, int length)
353 XGlyphInfo extents;
355 wassertrv(font!=NULL, 0);
356 wassertrv(text!=NULL, 0);
358 if (font->screen->useWideChar) {
359 wchar_t *wtext;
360 const char *mtext;
361 int len;
363 wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1));
364 mtext = text;
365 len = wmbsnrtowcs(wtext, &mtext, length, length);
366 if (len>0) {
367 wtext[len] = L'\0'; /* not really necessary here */
368 XftTextExtents32(font->screen->display, font->font,
369 (XftChar32 *)wtext, len, &extents);
370 } else {
371 if (len==-1) {
372 wwarning(_("Conversion to widechar failed (possible "
373 "invalid multibyte sequence): '%s':(pos %d)\n"),
374 text, mtext-text+1);
376 extents.xOff = 0;
378 wfree(wtext);
379 } else {
380 XftTextExtents8(font->screen->display, font->font,
381 (XftChar8 *)text, length, &extents);
384 return extents.xOff; /* don't ask :P */
389 void
390 WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font,
391 int x, int y, char *text, int length)
393 XftColor xftcolor;
395 wassertr(font!=NULL);
397 xftcolor.color.red = color->color.red;
398 xftcolor.color.green = color->color.green;
399 xftcolor.color.blue = color->color.blue;
400 xftcolor.color.alpha = color->alpha;;
401 xftcolor.pixel = W_PIXEL(color);
403 XftDrawChange(scr->xftdraw, d);
405 if (font->screen->useWideChar) {
406 wchar_t *wtext;
407 const char *mtext;
408 int len;
410 wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1));
411 mtext = text;
412 len = wmbsnrtowcs(wtext, &mtext, length, length);
413 if (len>0) {
414 XftDrawString32(scr->xftdraw, &xftcolor, font->font,
415 x, y + font->y, (XftChar32*)wtext, len);
416 } else if (len==-1) {
417 wwarning(_("Conversion to widechar failed (possible invalid "
418 "multibyte sequence): '%s':(pos %d)\n"),
419 text, mtext-text+1);
420 /* we can draw normal text, or we can draw as much widechar
421 * text as was already converted until the error. go figure */
422 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font,
423 x, y + font->y, (XftChar8*)text, length);*/
425 wfree(wtext);
426 } else {
427 XftDrawString8(scr->xftdraw, &xftcolor, font->font,
428 x, y + font->y, (XftChar8*)text, length);
433 void
434 WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background,
435 WMFont *font, int x, int y, char *text, int length)
437 XftColor textColor;
438 XftColor bgColor;
440 wassertr(font!=NULL);
442 textColor.color.red = color->color.red;
443 textColor.color.green = color->color.green;
444 textColor.color.blue = color->color.blue;
445 textColor.color.alpha = color->alpha;;
446 textColor.pixel = W_PIXEL(color);
448 bgColor.color.red = background->color.red;
449 bgColor.color.green = background->color.green;
450 bgColor.color.blue = background->color.blue;
451 bgColor.color.alpha = background->alpha;;
452 bgColor.pixel = W_PIXEL(background);
454 XftDrawChange(scr->xftdraw, d);
456 XftDrawRect(scr->xftdraw, &bgColor, x, y,
457 WMWidthOfString(font, text, length),
458 font->height);
460 if (font->screen->useWideChar) {
461 wchar_t *wtext;
462 const char *mtext;
463 int len;
465 mtext = text;
466 wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1));
467 len = wmbsnrtowcs(wtext, &mtext, length, length);
468 if (len>0) {
469 XftDrawString32(scr->xftdraw, &textColor, font->font,
470 x, y + font->y, (XftChar32*)wtext, len);
471 } else if (len==-1) {
472 wwarning(_("Conversion to widechar failed (possible invalid "
473 "multibyte sequence): '%s':(pos %d)\n"),
474 text, mtext-text+1);
475 /* we can draw normal text, or we can draw as much widechar
476 * text as was already converted until the error. go figure */
477 /*XftDrawString8(scr->xftdraw, &textColor, font->font,
478 x, y + font->y, (XftChar8*)text, length);*/
480 wfree(wtext);
481 } else {
482 XftDrawString8(scr->xftdraw, &textColor, font->font,
483 x, y + font->y, (XftChar8*)text, length);
488 WMFont*
489 WMCopyFontWithChanges(WMScreen *scrPtr, WMFont *font,
490 const WMFontAttributes *changes)
492 int index[FONT_PROPS], count[FONT_PROPS];
493 int totalProps, i, j, carry;
494 char fname[512];
495 WMFontFlags fFlags;
496 WMBag *props;
497 WMArray *options;
498 WMFont *result;
499 char *prop;
501 snprintf(fname, 512, "%s", font->name);
503 fFlags = (font->antialiased ? WFAntialiased : WFNotAntialiased);
504 fFlags |= (font->notFontSet ? WFNormalFont : WFFontSet);
506 props = WMCreateBagWithDestructor(1, (WMFreeDataProc*)WMFreeArray);
508 totalProps = 0;
509 for (i=0; i<FONT_PROPS; i++) {
510 prop = ((W_FontAttributes*)changes)->props[i];
511 count[i] = index[i] = 0;
512 if (!prop) {
513 /* No change for this property */
514 continue;
515 } else if (strchr(prop, ',')==NULL) {
516 /* Simple option */
517 changeFontProp(fname, prop, i);
518 } else {
519 /* Option with fallback alternatives */
520 if ((changes==WFAEmphasized || changes==WFABoldEmphasized) &&
521 font->antialiased && strcmp(prop, "o,i")==0) {
522 options = getOptions("i,o");
523 } else {
524 options = getOptions(prop);
526 WMInsertInBag(props, i, options);
527 count[i] = WMGetArrayItemCount(options);
528 if (totalProps==0)
529 totalProps = 1;
530 totalProps = totalProps * count[i];
534 if (totalProps == 0) {
535 /* No options with fallback alternatives at all */
536 WMFreeBag(props);
537 return WMCreateFontWithFlags(scrPtr, fname, fFlags);
540 for (i=0; i<totalProps; i++) {
541 for (j=0; j<FONT_PROPS; j++) {
542 if (count[j]!=0) {
543 options = WMGetFromBag(props, j);
544 prop = WMGetFromArray(options, index[j]);
545 if (prop) {
546 changeFontProp(fname, prop, j);
550 result = WMCreateFontWithFlags(scrPtr, fname, fFlags);
551 if (result) {
552 WMFreeBag(props);
553 return result;
555 for (j=FONT_PROPS-1, carry=1; j>=0; j--) {
556 if (count[j]!=0) {
557 index[j] += carry;
558 carry = (index[j]==count[j]);
559 index[j] %= count[j];
564 WMFreeBag(props);
566 return NULL;
570 #if 0
572 #define FONT_PROPS 14
574 typedef struct {
575 char *props[FONT_PROPS];
576 } W_FontAttributes;
579 static void
580 changeFontProp(char *buf, char *newprop, int position)
582 char buf2[512];
583 char *ptr, *pptr, *rptr;
584 int count;
586 if (buf[0]!='-') {
587 /* // remove warning later. or maybe not */
588 wwarning(_("Invalid font specification: '%s'\n"), buf);
589 return;
592 ptr = pptr = rptr = buf;
593 count = 0;
594 while (*ptr && *ptr!=',') {
595 if (*ptr == '-') {
596 count++;
597 if (count-1==position+1) {
598 rptr = ptr;
599 break;
601 if (count-1==position) {
602 pptr = ptr+1;
605 ptr++;
607 if (position==FONT_PROPS-1) {
608 rptr = ptr;
611 *pptr = 0;
612 snprintf(buf2, 512, "%s%s%s", buf, newprop, rptr);
613 strcpy(buf, buf2);
617 static WMArray*
618 getOptions(char *options)
620 char *ptr, *ptr2, *str;
621 WMArray *result;
622 int count;
624 result = WMCreateArrayWithDestructor(2, (WMFreeDataProc*)wfree);
626 ptr = options;
627 while (1) {
628 ptr2 = strchr(ptr, ',');
629 if (!ptr2) {
630 WMAddToArray(result, wstrdup(ptr));
631 break;
632 } else {
633 count = ptr2 - ptr;
634 str = wmalloc(count+1);
635 memcpy(str, ptr, count);
636 str[count] = 0;
637 WMAddToArray(result, str);
638 ptr = ptr2 + 1;
642 return result;
646 #endif
649 #else /* No XFT support */
652 static char *makeFontSetOfSize(char *fontset, int size);
656 /* XLFD pattern matching */
657 static char*
658 getElementFromXLFD(const char *xlfd, int index)
660 const char *p = xlfd;
661 while (*p != 0) {
662 if (*p == '-' && --index == 0) {
663 const char *end = strchr(p + 1, '-');
664 char *buf;
665 size_t len;
666 if (end == 0) end = p + strlen(p);
667 len = end - (p + 1);
668 buf = wmalloc(len);
669 memcpy(buf, p + 1, len);
670 buf[len] = 0;
671 return buf;
673 p++;
675 return strdup("*");
679 /* XLFD pattern matching */
680 static char*
681 generalizeXLFD(const char *xlfd)
683 char *buf;
684 int len;
685 char *weight = getElementFromXLFD(xlfd, 3);
686 char *slant = getElementFromXLFD(xlfd, 4);
687 char *pxlsz = getElementFromXLFD(xlfd, 7);
689 #define Xstrlen(A) ((A)?strlen(A):0)
690 len = Xstrlen(xlfd)+Xstrlen(weight)+Xstrlen(slant)+Xstrlen(pxlsz)*2+60;
691 #undef Xstrlen
693 buf = wmalloc(len + 1);
694 snprintf(buf, len + 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
695 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
696 xlfd, weight, slant, pxlsz, pxlsz);
698 wfree(pxlsz);
699 wfree(slant);
700 wfree(weight);
702 return buf;
705 /* XLFD pattern matching */
706 static XFontSet
707 W_CreateFontSetWithGuess(Display *dpy, char *xlfd, char ***missing,
708 int *nmissing, char **def_string)
710 XFontSet fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
712 if (fs != NULL && *nmissing == 0) return fs;
714 /* for non-iso8859-1 language and iso8859-1 specification
715 (this fontset is only for pattern analysis) */
716 if (fs == NULL) {
717 if (*nmissing != 0) XFreeStringList(*missing);
718 setlocale(LC_CTYPE, "C");
719 fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
720 setlocale(LC_CTYPE, "");
723 /* make XLFD font name for pattern analysis */
724 if (fs != NULL) {
725 XFontStruct **fontstructs;
726 char **fontnames;
727 if (XFontsOfFontSet(fs, &fontstructs, &fontnames) > 0)
728 xlfd = fontnames[0];
731 xlfd = generalizeXLFD(xlfd);
733 if (*nmissing != 0) XFreeStringList(*missing);
734 if (fs != NULL) XFreeFontSet(dpy, fs);
736 fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
738 wfree(xlfd);
739 return fs;
743 static char*
744 xlfdFromFontName(char *fontName, Bool antialiased)
746 char *systemFont, *boldSystemFont;
747 char *font;
748 int size;
750 if (antialiased) {
751 systemFont = WINGsConfiguration.antialiasedSystemFont;
752 boldSystemFont = WINGsConfiguration.antialiasedBoldSystemFont;
753 } else {
754 systemFont = WINGsConfiguration.systemFont;
755 boldSystemFont = WINGsConfiguration.boldSystemFont;
758 size = WINGsConfiguration.defaultFontSize;
760 if (strcmp(fontName, "SystemFont")==0) {
761 font = systemFont;
762 size = WINGsConfiguration.defaultFontSize;
763 } else if (strncmp(fontName, "SystemFont-", 11)==0) {
764 font = systemFont;
765 if (sscanf(&fontName[11], "%i", &size)!=1) {
766 size = WINGsConfiguration.defaultFontSize;
767 wwarning(_("Invalid size specification '%s' in %s. "
768 "Using default %d\n"), &fontName[11], fontName, size);
770 } else if (strcmp(fontName, "BoldSystemFont")==0) {
771 font = boldSystemFont;
772 size = WINGsConfiguration.defaultFontSize;
773 } else if (strncmp(fontName, "BoldSystemFont-", 15)==0) {
774 font = boldSystemFont;
775 if (sscanf(&fontName[15], "%i", &size)!=1) {
776 size = WINGsConfiguration.defaultFontSize;
777 wwarning(_("Invalid size specification '%s' in %s. "
778 "Using default %d\n"), &fontName[15], fontName, size);
780 } else {
781 font = NULL;
784 return (font!=NULL ? makeFontSetOfSize(font, size) : wstrdup(fontName));
788 WMFont*
789 WMCreateFontSet(WMScreen *scrPtr, char *fontName)
791 WMFont *font;
792 Display *display = scrPtr->display;
793 char **missing;
794 int nmissing = 0;
795 char *defaultString;
796 char *fname;
797 XFontSetExtents *extents;
799 fname = xlfdFromFontName(fontName, False);
801 font = WMHashGet(scrPtr->fontSetCache, fname);
802 if (font) {
803 WMRetainFont(font);
804 wfree(fname);
805 return font;
808 font = wmalloc(sizeof(WMFont));
809 memset(font, 0, sizeof(WMFont));
811 font->notFontSet = 0;
812 font->antialiased = 0;
814 font->screen = scrPtr;
816 font->font.set = W_CreateFontSetWithGuess(display, fname, &missing,
817 &nmissing, &defaultString);
818 if (nmissing > 0 && font->font.set) {
819 int i;
821 wwarning(_("the following character sets are missing in %s:"), fname);
822 for (i = 0; i < nmissing; i++) {
823 wwarning(missing[i]);
825 XFreeStringList(missing);
826 if (defaultString)
827 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
828 defaultString);
830 if (!font->font.set) {
831 wfree(font);
832 wfree(fname);
833 return NULL;
836 extents = XExtentsOfFontSet(font->font.set);
838 font->height = extents->max_logical_extent.height;
839 font->y = font->height - (font->height + extents->max_logical_extent.y);
841 font->refCount = 1;
843 font->name = fname;
845 assert(WMHashInsert(scrPtr->fontSetCache, font->name, font)==NULL);
847 return font;
852 WMFont*
853 WMCreateNormalFont(WMScreen *scrPtr, char *fontName)
855 WMFont *font;
856 Display *display = scrPtr->display;
857 char *fname, *ptr;
859 fontName = xlfdFromFontName(fontName, False);
861 if ((ptr = strchr(fontName, ','))) {
862 fname = wmalloc(ptr - fontName + 1);
863 strncpy(fname, fontName, ptr - fontName);
864 fname[ptr - fontName] = 0;
865 } else {
866 fname = wstrdup(fontName);
869 wfree(fontName);
871 font = WMHashGet(scrPtr->fontCache, fname);
872 if (font) {
873 WMRetainFont(font);
874 wfree(fname);
875 return font;
878 font = wmalloc(sizeof(WMFont));
879 memset(font, 0, sizeof(WMFont));
881 font->notFontSet = 1;
882 font->antialiased = 0;
884 font->screen = scrPtr;
886 font->font.normal = XLoadQueryFont(display, fname);
887 if (!font->font.normal) {
888 wfree(font);
889 wfree(fname);
890 return NULL;
892 font->height = font->font.normal->ascent+font->font.normal->descent;
893 font->y = font->font.normal->ascent;
895 font->refCount = 1;
897 font->name = fname;
899 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
901 return font;
905 WMFont*
906 WMCreateAntialiasedFont(WMScreen *scrPtr, char *fontName)
908 #ifdef XFT
909 WMFont *font;
910 Display *display = scrPtr->display;
911 char *fname, *ptr;
913 fontName = xlfdFromFontName(fontName, True);
915 if ((ptr = strchr(fontName, ','))) {
916 fname = wmalloc(ptr - fontName + 1);
917 strncpy(fname, fontName, ptr - fontName);
918 fname[ptr - fontName] = 0;
919 } else {
920 fname = wstrdup(fontName);
923 wfree(fontName);
925 font = WMHashGet(scrPtr->xftFontCache, fname);
926 if (font) {
927 WMRetainFont(font);
928 wfree(fname);
929 return font;
932 font = wmalloc(sizeof(WMFont));
933 memset(font, 0, sizeof(WMFont));
935 font->notFontSet = 1;
936 font->antialiased = 1;
938 font->screen = scrPtr;
940 /* Xft sux. Loading a font with an invalid XLFD will give strange results
941 * sometimes without returning any warning or error.
942 * However Xft's idea of what font is invalid is quite strange:
943 * 1. If the XLFD doesn't have all its fields present will fail and
944 * return NULL.
945 * 2. If all fields are present, but hold invalid values then it will:
946 * a. If family is invalid, will load a default font without warning.
947 * b. If the font size is invalid (non-numerical) it will fail and
948 * return NULL.
949 * c. If other fields are invalid, will load the font specified by
950 * the valid family name, ignoring any invalid fields. It will
951 * use a default medium weight and a default roman slant if they
952 * are invalid.
954 printf("%s\n", fname);
955 if (fname[0] == '-') {
956 font->font.xft = XftFontOpenXlfd(display, scrPtr->screen, fname);
957 } else {
958 font->font.xft = XftFontOpenName(display, scrPtr->screen, fname);
960 if (!font->font.xft) {
961 wfree(font);
962 wfree(fname);
963 return NULL;
965 font->height = font->font.xft->ascent+font->font.xft->descent;
966 font->y = font->font.xft->ascent;
968 font->refCount = 1;
970 font->name = fname;
972 assert(WMHashInsert(scrPtr->xftFontCache, font->name, font)==NULL);
974 return font;
975 #else
976 return NULL;
977 #endif
981 WMFont*
982 WMCreateAntialiasedFontSet(WMScreen *scrPtr, char *fontName)
984 #ifdef XFT
985 WMFont *font;
986 Display *display = scrPtr->display;
987 char *fname, *ptr;
989 fontName = xlfdFromFontName(fontName, True);
991 if ((ptr = strchr(fontName, ','))) {
992 fname = wmalloc(ptr - fontName + 1);
993 strncpy(fname, fontName, ptr - fontName);
994 fname[ptr - fontName] = 0;
995 } else {
996 fname = wstrdup(fontName);
999 wfree(fontName);
1001 font = WMHashGet(scrPtr->xftFontSetCache, fname);
1002 if (font) {
1003 WMRetainFont(font);
1004 wfree(fname);
1005 return font;
1008 font = wmalloc(sizeof(WMFont));
1009 memset(font, 0, sizeof(WMFont));
1011 font->notFontSet = 0;
1012 font->antialiased = 1;
1014 font->screen = scrPtr;
1016 /* Xft sux. Loading a font with an invalid XLFD will give strange results
1017 * sometimes without returning any warning or error.
1018 * However Xft's idea of what font is invalid is quite strange:
1019 * 1. If the XLFD doesn't have all its fields present will fail and
1020 * return NULL.
1021 * 2. If all fields are present, but hold invalid values then it will:
1022 * a. If family is invalid, will load a default font without warning.
1023 * b. If the font size is invalid (non-numerical) it will fail and
1024 * return NULL.
1025 * c. If other fields are invalid, will load the font specified by
1026 * the valid family name, ignoring any invalid fields. It will
1027 * use a default medium weight and a default roman slant if they
1028 * are invalid.
1030 if (fname[0] == '-') {
1031 font->font.xft = XftFontOpenXlfd(display, scrPtr->screen, fname);
1032 } else {
1033 font->font.xft = XftFontOpenName(display, scrPtr->screen, fname);
1035 if (!font->font.xft) {
1036 wfree(font);
1037 wfree(fname);
1038 return NULL;
1040 font->height = font->font.xft->ascent+font->font.xft->descent;
1041 font->y = font->font.xft->ascent;
1043 font->refCount = 1;
1045 font->name = fname;
1047 assert(WMHashInsert(scrPtr->xftFontSetCache, font->name, font)==NULL);
1049 return font;
1050 #else
1051 return NULL;
1052 #endif
1056 WMFont*
1057 WMCreateFont(WMScreen *scrPtr, char *fontName)
1059 return WMCreateFontWithFlags(scrPtr, fontName, WFDefaultFont);
1063 WMFont*
1064 WMCreateFontWithFlags(WMScreen *scrPtr, char *fontName, WMFontFlags flags)
1066 Bool multiByte = scrPtr->useMultiByte;
1067 Bool antialiased = scrPtr->antialiasedText;
1068 WMFont *font;
1070 if (flags & WFFontSet) {
1071 multiByte = True;
1072 } else if (flags & WFNormalFont) {
1073 multiByte = False;
1075 if (flags & WFAntialiased) {
1076 antialiased = True;
1077 } else if (flags & WFNotAntialiased) {
1078 antialiased = False;
1081 if (antialiased && multiByte) {
1082 font = WMCreateAntialiasedFontSet(scrPtr, fontName);
1083 /* If we cannot create an antialiased font set and antialiasing is
1084 * not explicitly requested in flags, fallback to standard font sets */
1085 if (!font && (flags & WFAntialiased)==0) {
1086 font = WMCreateFontSet(scrPtr, fontName);
1088 } else if (antialiased) {
1089 font = WMCreateAntialiasedFont(scrPtr, fontName);
1090 /* If we cannot create an antialiased font and antialiasing is
1091 * not explicitly requested in flags, fallback to normal font */
1092 if (!font && (flags & WFAntialiased)==0) {
1093 font = WMCreateNormalFont(scrPtr, fontName);
1095 } else if (multiByte) {
1096 font = WMCreateFontSet(scrPtr, fontName);
1097 } else {
1098 font = WMCreateNormalFont(scrPtr, fontName);
1101 return font;
1105 WMFont*
1106 WMRetainFont(WMFont *font)
1108 wassertrv(font!=NULL, NULL);
1110 font->refCount++;
1112 return font;
1116 void
1117 WMReleaseFont(WMFont *font)
1119 wassertr(font!=NULL);
1121 font->refCount--;
1122 if (font->refCount < 1) {
1123 if (font->antialiased) {
1124 #ifdef XFT
1125 XftFontClose(font->screen->display, font->font.xft);
1126 #else
1127 assert(False);
1128 #endif
1129 } else if (font->notFontSet) {
1130 XFreeFont(font->screen->display, font->font.normal);
1131 } else {
1132 XFreeFontSet(font->screen->display, font->font.set);
1135 if (font->name) {
1136 if (font->antialiased && !font->notFontSet) {
1137 WMHashRemove(font->screen->xftFontSetCache, font->name);
1138 } else if (font->antialiased) {
1139 WMHashRemove(font->screen->xftFontCache, font->name);
1140 } else if (font->notFontSet) {
1141 WMHashRemove(font->screen->fontCache, font->name);
1142 } else {
1143 WMHashRemove(font->screen->fontSetCache, font->name);
1145 wfree(font->name);
1147 wfree(font);
1152 Bool
1153 WMIsAntialiasingEnabled(WMScreen *scrPtr)
1155 return scrPtr->antialiasedText;
1159 Bool
1160 WMIsAntialiasedFont(WMFont *font)
1162 wassertrv(font!=NULL, False);
1164 return font->antialiased;
1168 unsigned int
1169 WMFontHeight(WMFont *font)
1171 wassertrv(font!=NULL, 0);
1173 return font->height;
1177 char*
1178 WMGetFontName(WMFont *font)
1180 wassertrv(font!=NULL, NULL);
1182 return font->name;
1186 WMFont*
1187 WMDefaultSystemFont(WMScreen *scrPtr)
1189 return WMRetainFont(scrPtr->normalFont);
1193 WMFont*
1194 WMDefaultBoldSystemFont(WMScreen *scrPtr)
1196 return WMRetainFont(scrPtr->boldFont);
1200 static WMFont*
1201 makeSystemFontOfSize(WMScreen *scrPtr, int size, Bool bold)
1203 WMFont *font;
1204 char *fontSpec, *xftFontSpec;
1206 #define WConf WINGsConfiguration
1207 if (bold) {
1208 fontSpec = makeFontSetOfSize(WConf.boldSystemFont, size);
1209 xftFontSpec = makeFontSetOfSize(WConf.antialiasedBoldSystemFont, size);
1210 } else {
1211 fontSpec = makeFontSetOfSize(WConf.systemFont, size);
1212 xftFontSpec = makeFontSetOfSize(WConf.antialiasedSystemFont, size);
1214 #undef WConf
1216 if (scrPtr->antialiasedText && scrPtr->useMultiByte) {
1217 font = WMCreateAntialiasedFontSet(scrPtr, xftFontSpec);
1218 } else if (scrPtr->antialiasedText) {
1219 font = WMCreateAntialiasedFont(scrPtr, xftFontSpec);
1220 } else if (scrPtr->useMultiByte) {
1221 font = WMCreateFontSet(scrPtr, fontSpec);
1222 } else {
1223 font = WMCreateNormalFont(scrPtr, fontSpec);
1226 if (!font) {
1227 if (scrPtr->antialiasedText && scrPtr->useMultiByte) {
1228 // is arial a good fallback for multibyte?
1229 wwarning(_("could not load font %s. Trying arial."), xftFontSpec);
1230 if (bold) {
1231 font = WMCreateAntialiasedFontSet(scrPtr, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1232 } else {
1233 font = WMCreateAntialiasedFontSet(scrPtr, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1235 if (!font) {
1236 wwarning(_("could not load antialiased font set. Reverting to standard font sets."));
1237 font = WMCreateFontSet(scrPtr, fontSpec);
1238 if (!font) {
1239 wwarning(_("could not load FontSet %s. Trying fixed."), fontSpec);
1240 font = WMCreateFontSet(scrPtr, "fixed");
1243 } else if (scrPtr->antialiasedText) {
1244 wwarning(_("could not load font %s. Trying arial."), xftFontSpec);
1245 if (bold) {
1246 font = WMCreateAntialiasedFont(scrPtr, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
1247 } else {
1248 font = WMCreateAntialiasedFont(scrPtr, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
1250 if (!font) {
1251 wwarning(_("could not load antialiased fonts. Reverting to normal fonts."));
1252 font = WMCreateNormalFont(scrPtr, fontSpec);
1253 if (!font) {
1254 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
1255 font = WMCreateNormalFont(scrPtr, "fixed");
1258 } else if (scrPtr->useMultiByte) {
1259 wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
1260 font = WMCreateFontSet(scrPtr, "fixed");
1261 if (!font) {
1262 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
1264 } else {
1265 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
1266 font = WMCreateNormalFont(scrPtr, "fixed");
1268 if (!font) {
1269 wwarning(_("could not load fixed font!"));
1270 wfree(fontSpec);
1271 wfree(xftFontSpec);
1272 return NULL;
1275 wfree(fontSpec);
1276 wfree(xftFontSpec);
1278 return font;
1282 WMFont*
1283 WMSystemFontOfSize(WMScreen *scrPtr, int size)
1285 return makeSystemFontOfSize(scrPtr, size, False);
1289 WMFont*
1290 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
1292 return makeSystemFontOfSize(scrPtr, size, True);
1296 XFontSet
1297 WMGetFontFontSet(WMFont *font)
1299 wassertrv(font!=NULL, NULL);
1301 if (!font->notFontSet && !font->antialiased)
1302 return font->font.set;
1304 return NULL;
1309 WMWidthOfString(WMFont *font, char *text, int length)
1311 wassertrv(font!=NULL, 0);
1312 wassertrv(text!=NULL, 0);
1314 if (font->antialiased) {
1315 #ifdef XFT
1316 XGlyphInfo extents;
1318 if (!font->notFontSet) {
1319 wchar_t *wtext;
1320 char *mtext;
1321 int len;
1323 /* Use mtext instead of text, because mbstrtowcs() alters it */
1324 mtext = text;
1325 wtext = (wchar_t *)wmalloc(4*length+4);
1326 /* pass a real ps instead of NULL below? for multithread safety
1327 * as from manual page */
1328 len = mbsrtowcs(wtext, (const char **) &mtext, length, NULL);
1329 if (len>0) {
1330 XftTextExtents32(font->screen->display, font->font.xft,
1331 (XftChar32 *)wtext, len, &extents);
1332 } else {
1333 if (len==-1) {
1334 wwarning(_("Conversion to widechar failed (possible "
1335 "invalid multibyte sequence): '%s':(pos %d)\n"),
1336 text, mtext-text+1);
1338 extents.xOff = 0;
1340 wfree(wtext);
1341 } else {
1342 XftTextExtents8(font->screen->display, font->font.xft,
1343 (XftChar8 *)text, length, &extents);
1346 return extents.xOff; /* don't ask :P */
1347 #else
1348 wassertrv(False, 0);
1349 #endif
1350 } else if (font->notFontSet) {
1351 return XTextWidth(font->font.normal, text, length);
1352 } else {
1353 XRectangle rect;
1354 XRectangle AIXsucks;
1356 XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
1358 return rect.width;
1364 void
1365 WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font,
1366 int x, int y, char *text, int length)
1368 wassertr(font!=NULL);
1370 if (font->antialiased) {
1371 #ifdef XFT
1372 XftColor xftcolor;
1374 xftcolor.color.red = color->color.red;
1375 xftcolor.color.green = color->color.green;
1376 xftcolor.color.blue = color->color.blue;
1377 xftcolor.color.alpha = color->alpha;;
1378 xftcolor.pixel = W_PIXEL(color);
1380 XftDrawChange(scr->xftdraw, d);
1382 if (!font->notFontSet) {
1383 wchar_t *wtext;
1384 char *mtext;
1385 int len;
1387 /* Use mtext instead of text, because mbstrtowcs() alters it */
1388 mtext = text;
1389 wtext = (wchar_t *)wmalloc(4*length+4);
1390 len = mbsrtowcs(wtext, (const char **) &mtext, length, NULL);
1391 if (len>0) {
1392 XftDrawString32(scr->xftdraw, &xftcolor, font->font.xft,
1393 x, y + font->y, (XftChar32*)wtext, len);
1394 } else if (len==-1) {
1395 wwarning(_("Conversion to widechar failed (possible invalid "
1396 "multibyte sequence): '%s':(pos %d)\n"),
1397 text, mtext-text+1);
1398 /* we can draw normal text, or we can draw as much widechar
1399 * text as was already converted until the error. go figure */
1400 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
1401 x, y + font->y, (XftChar8*)text, length);*/
1403 wfree(wtext);
1404 } else {
1405 XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
1406 x, y + font->y, (XftChar8*)text, length);
1408 #else
1409 wassertr(False);
1410 #endif
1411 } else if (font->notFontSet) {
1412 XSetFont(scr->display, scr->drawStringGC, font->font.normal->fid);
1413 XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color));
1414 XDrawString(scr->display, d, scr->drawStringGC, x, y + font->y,
1415 text, length);
1416 } else {
1417 XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color));
1418 XmbDrawString(scr->display, d, font->font.set, scr->drawStringGC,
1419 x, y + font->y, text, length);
1424 void
1425 WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background,
1426 WMFont *font, int x, int y, char *text, int length)
1428 wassertr(font!=NULL);
1430 if (font->antialiased) {
1431 #ifdef XFT
1432 XftColor textColor;
1433 XftColor bgColor;
1435 textColor.color.red = color->color.red;
1436 textColor.color.green = color->color.green;
1437 textColor.color.blue = color->color.blue;
1438 textColor.color.alpha = color->alpha;;
1439 textColor.pixel = W_PIXEL(color);
1441 bgColor.color.red = background->color.red;
1442 bgColor.color.green = background->color.green;
1443 bgColor.color.blue = background->color.blue;
1444 bgColor.color.alpha = background->alpha;;
1445 bgColor.pixel = W_PIXEL(background);
1448 XftDrawChange(scr->xftdraw, d);
1450 XftDrawRect(scr->xftdraw, &bgColor, x, y,
1451 WMWidthOfString(font, text, length), font->height);
1453 if (!font->notFontSet) {
1454 wchar_t *wtext;
1455 char *mtext;
1456 int len;
1458 /* Use mtext instead of text, because mbstrtowcs() alters it */
1459 mtext = text;
1460 wtext = (wchar_t *)wmalloc(4*length+4);
1461 len = mbsrtowcs(wtext, (const char **) &mtext, length, NULL);
1462 if (len>0) {
1463 XftDrawString32(scr->xftdraw, &textColor, font->font.xft,
1464 x, y + font->y, (XftChar32*)wtext, len);
1465 } else if (len==-1) {
1466 wwarning(_("Conversion to widechar failed (possible invalid "
1467 "multibyte sequence): '%s':(pos %d)\n"),
1468 text, mtext-text+1);
1469 /* we can draw normal text, or we can draw as much widechar
1470 * text as was already converted until the error. go figure */
1471 /*XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
1472 x, y + font->y, (XftChar8*)text, length);*/
1474 wfree(wtext);
1475 } else {
1476 XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
1477 x, y + font->y, (XftChar8*)text, length);
1479 #else
1480 wassertr(False);
1481 #endif
1482 } else if (font->notFontSet) {
1483 XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color));
1484 XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background));
1485 XSetFont(scr->display, scr->drawImStringGC, font->font.normal->fid);
1486 XDrawImageString(scr->display, d, scr->drawImStringGC,
1487 x, y + font->y, text, length);
1488 } else {
1489 XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color));
1490 XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background));
1491 XmbDrawImageString(scr->display, d, font->font.set, scr->drawImStringGC,
1492 x, y + font->y, text, length);
1499 static char*
1500 makeFontSetOfSize(char *fontset, int size)
1502 char font[300], *f;
1503 char *newfs = NULL;
1504 char *ptr;
1506 do {
1507 char *tmp;
1508 int end;
1511 f = fontset;
1512 ptr = strchr(fontset, ',');
1513 if (ptr) {
1514 int count = ptr-fontset;
1516 if (count > 255) {
1517 wwarning(_("font description %s is too large."), fontset);
1518 } else {
1519 memcpy(font, fontset, count);
1520 font[count] = 0;
1521 f = (char*)font;
1525 if (newfs)
1526 end = strlen(newfs);
1527 else
1528 end = 0;
1530 tmp = wmalloc(end + strlen(f) + 8);
1531 if (end != 0) {
1532 sprintf(tmp, "%s,", newfs);
1533 sprintf(tmp + end + 1, f, size);
1534 } else {
1535 sprintf(tmp + end, f, size);
1538 if (newfs)
1539 wfree(newfs);
1540 newfs = tmp;
1542 fontset = ptr+1;
1543 } while (ptr!=NULL);
1545 return newfs;
1549 #define FONT_PROPS 14
1551 typedef struct {
1552 char *props[FONT_PROPS];
1553 } W_FontAttributes;
1556 static void
1557 changeFontProp(char *buf, char *newprop, int position)
1559 char buf2[512];
1560 char *ptr, *pptr, *rptr;
1561 int count;
1563 if (buf[0]!='-') {
1564 /* // remove warning later. or maybe not */
1565 wwarning(_("Invalid font specification: '%s'\n"), buf);
1566 return;
1569 ptr = pptr = rptr = buf;
1570 count = 0;
1571 while (*ptr && *ptr!=',') {
1572 if (*ptr == '-') {
1573 count++;
1574 if (count-1==position+1) {
1575 rptr = ptr;
1576 break;
1578 if (count-1==position) {
1579 pptr = ptr+1;
1582 ptr++;
1584 if (position==FONT_PROPS-1) {
1585 rptr = ptr;
1588 *pptr = 0;
1589 snprintf(buf2, 512, "%s%s%s", buf, newprop, rptr);
1590 strcpy(buf, buf2);
1594 static WMArray*
1595 getOptions(char *options)
1597 char *ptr, *ptr2, *str;
1598 WMArray *result;
1599 int count;
1601 result = WMCreateArrayWithDestructor(2, (WMFreeDataProc*)wfree);
1603 ptr = options;
1604 while (1) {
1605 ptr2 = strchr(ptr, ',');
1606 if (!ptr2) {
1607 WMAddToArray(result, wstrdup(ptr));
1608 break;
1609 } else {
1610 count = ptr2 - ptr;
1611 str = wmalloc(count+1);
1612 memcpy(str, ptr, count);
1613 str[count] = 0;
1614 WMAddToArray(result, str);
1615 ptr = ptr2 + 1;
1619 return result;
1623 WMFont*
1624 WMCopyFontWithChanges(WMScreen *scrPtr, WMFont *font,
1625 const WMFontAttributes *changes)
1627 int index[FONT_PROPS], count[FONT_PROPS];
1628 int totalProps, i, j, carry;
1629 char fname[512];
1630 WMFontFlags fFlags;
1631 WMBag *props;
1632 WMArray *options;
1633 WMFont *result;
1634 char *prop;
1636 snprintf(fname, 512, "%s", font->name);
1638 fFlags = (font->antialiased ? WFAntialiased : WFNotAntialiased);
1639 fFlags |= (font->notFontSet ? WFNormalFont : WFFontSet);
1641 props = WMCreateBagWithDestructor(1, (WMFreeDataProc*)WMFreeArray);
1643 totalProps = 0;
1644 for (i=0; i<FONT_PROPS; i++) {
1645 prop = ((W_FontAttributes*)changes)->props[i];
1646 count[i] = index[i] = 0;
1647 if (!prop) {
1648 /* No change for this property */
1649 continue;
1650 } else if (strchr(prop, ',')==NULL) {
1651 /* Simple option */
1652 changeFontProp(fname, prop, i);
1653 } else {
1654 /* Option with fallback alternatives */
1655 if ((changes==WFAEmphasized || changes==WFABoldEmphasized) &&
1656 font->antialiased && strcmp(prop, "o,i")==0) {
1657 options = getOptions("i,o");
1658 } else {
1659 options = getOptions(prop);
1661 WMInsertInBag(props, i, options);
1662 count[i] = WMGetArrayItemCount(options);
1663 if (totalProps==0)
1664 totalProps = 1;
1665 totalProps = totalProps * count[i];
1669 if (totalProps == 0) {
1670 /* No options with fallback alternatives at all */
1671 WMFreeBag(props);
1672 return WMCreateFontWithFlags(scrPtr, fname, fFlags);
1675 for (i=0; i<totalProps; i++) {
1676 for (j=0; j<FONT_PROPS; j++) {
1677 if (count[j]!=0) {
1678 options = WMGetFromBag(props, j);
1679 prop = WMGetFromArray(options, index[j]);
1680 if (prop) {
1681 changeFontProp(fname, prop, j);
1685 result = WMCreateFontWithFlags(scrPtr, fname, fFlags);
1686 if (result) {
1687 WMFreeBag(props);
1688 return result;
1690 for (j=FONT_PROPS-1, carry=1; j>=0; j--) {
1691 if (count[j]!=0) {
1692 index[j] += carry;
1693 carry = (index[j]==count[j]);
1694 index[j] %= count[j];
1699 WMFreeBag(props);
1701 return NULL;
1704 #endif
1707 // should WFANormal also set "normal" or leave it alone?
1708 static const WMFontAttributes W_FANormal = {
1709 WFAUnchanged, WFAUnchanged, "medium,normal,regular", "r", "normal",
1710 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged,
1711 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged
1715 static const WMFontAttributes W_FABold = {
1716 WFAUnchanged, WFAUnchanged, "bold", WFAUnchanged,
1717 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged,
1718 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged
1722 static const WMFontAttributes W_FANotBold = {
1723 WFAUnchanged, WFAUnchanged, "medium,normal,regular", WFAUnchanged,
1724 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged,
1725 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged
1729 static const WMFontAttributes W_FAEmphasized = {
1730 WFAUnchanged, WFAUnchanged, WFAUnchanged, "o,i",
1731 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged,
1732 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged
1736 static const WMFontAttributes W_FANotEmphasized = {
1737 WFAUnchanged, WFAUnchanged, WFAUnchanged, "r",
1738 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged,
1739 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged
1743 static const WMFontAttributes W_FABoldEmphasized = {
1744 WFAUnchanged, WFAUnchanged, "bold", "o,i",
1745 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged,
1746 WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged
1750 const WMFontAttributes *WFANormal = &W_FANormal;
1751 const WMFontAttributes *WFABold = &W_FABold;
1752 const WMFontAttributes *WFANotBold = &W_FANotBold;
1753 const WMFontAttributes *WFAEmphasized = &W_FAEmphasized;
1754 const WMFontAttributes *WFANotEmphasized = &W_FANotEmphasized;
1755 const WMFontAttributes *WFABoldEmphasized = &W_FABoldEmphasized;