5 # include <X11/Xft/Xft.h>
13 #include <X11/Xlocale.h>
18 static char *makeFontSetOfSize(char *fontset
, int size
);
22 /* XLFD pattern matching */
24 getElementFromXLFD(const char *xlfd
, int index
)
28 if (*p
== '-' && --index
== 0) {
29 const char *end
= strchr(p
+ 1, '-');
32 if (end
== 0) end
= p
+ strlen(p
);
35 memcpy(buf
, p
+ 1, len
);
45 /* XLFD pattern matching */
47 generalizeXLFD(const char *xlfd
)
51 char *weight
= getElementFromXLFD(xlfd
, 3);
52 char *slant
= getElementFromXLFD(xlfd
, 4);
53 char *pxlsz
= getElementFromXLFD(xlfd
, 7);
55 #define Xstrlen(A) ((A)?strlen(A):0)
56 len
= Xstrlen(xlfd
)+Xstrlen(weight
)+Xstrlen(slant
)+Xstrlen(pxlsz
)*2+60;
59 buf
= wmalloc(len
+ 1);
60 snprintf(buf
, len
+ 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
61 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
62 xlfd
, weight
, slant
, pxlsz
, pxlsz
);
71 /* XLFD pattern matching */
73 W_CreateFontSetWithGuess(Display
*dpy
, char *xlfd
, char ***missing
,
74 int *nmissing
, char **def_string
)
76 XFontSet fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
78 if (fs
!= NULL
&& *nmissing
== 0) return fs
;
80 /* for non-iso8859-1 language and iso8859-1 specification
81 (this fontset is only for pattern analysis) */
83 if (*nmissing
!= 0) XFreeStringList(*missing
);
84 setlocale(LC_CTYPE
, "C");
85 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
86 setlocale(LC_CTYPE
, "");
89 /* make XLFD font name for pattern analysis */
91 XFontStruct
**fontstructs
;
93 if (XFontsOfFontSet(fs
, &fontstructs
, &fontnames
) > 0)
97 xlfd
= generalizeXLFD(xlfd
);
99 if (*nmissing
!= 0) XFreeStringList(*missing
);
100 if (fs
!= NULL
) XFreeFontSet(dpy
, fs
);
102 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
110 xlfdFromFontName(char *fontName
, Bool antialiased
)
112 char *systemFont
, *boldSystemFont
;
117 systemFont
= WINGsConfiguration
.antialiasedSystemFont
;
118 boldSystemFont
= WINGsConfiguration
.antialiasedBoldSystemFont
;
120 systemFont
= WINGsConfiguration
.systemFont
;
121 boldSystemFont
= WINGsConfiguration
.boldSystemFont
;
124 size
= WINGsConfiguration
.defaultFontSize
;
126 if (strcmp(fontName
, "SystemFont")==0) {
128 size
= WINGsConfiguration
.defaultFontSize
;
129 } else if (strncmp(fontName
, "SystemFont-", 11)==0) {
131 if (sscanf(&fontName
[11], "%i", &size
)!=1) {
132 size
= WINGsConfiguration
.defaultFontSize
;
133 wwarning(_("Invalid size specification '%s' in %s. "
134 "Using default %d\n"), &fontName
[11], fontName
, size
);
136 } else if (strcmp(fontName
, "BoldSystemFont")==0) {
137 font
= boldSystemFont
;
138 size
= WINGsConfiguration
.defaultFontSize
;
139 } else if (strncmp(fontName
, "BoldSystemFont-", 15)==0) {
140 font
= boldSystemFont
;
141 if (sscanf(&fontName
[15], "%i", &size
)!=1) {
142 size
= WINGsConfiguration
.defaultFontSize
;
143 wwarning(_("Invalid size specification '%s' in %s. "
144 "Using default %d\n"), &fontName
[15], fontName
, size
);
150 return (font
!=NULL
? makeFontSetOfSize(font
, size
) : wstrdup(fontName
));
155 WMCreateFontSet(WMScreen
*scrPtr
, char *fontName
)
158 Display
*display
= scrPtr
->display
;
163 XFontSetExtents
*extents
;
165 fname
= xlfdFromFontName(fontName
, False
);
167 font
= WMHashGet(scrPtr
->fontSetCache
, fname
);
174 font
= wmalloc(sizeof(WMFont
));
175 memset(font
, 0, sizeof(WMFont
));
177 font
->notFontSet
= 0;
178 font
->antialiased
= 0;
180 font
->screen
= scrPtr
;
182 font
->font
.set
= W_CreateFontSetWithGuess(display
, fname
, &missing
,
183 &nmissing
, &defaultString
);
184 if (nmissing
> 0 && font
->font
.set
) {
187 wwarning(_("the following character sets are missing in %s:"), fname
);
188 for (i
= 0; i
< nmissing
; i
++) {
189 wwarning(missing
[i
]);
191 XFreeStringList(missing
);
193 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
196 if (!font
->font
.set
) {
202 extents
= XExtentsOfFontSet(font
->font
.set
);
204 font
->height
= extents
->max_logical_extent
.height
;
205 font
->y
= font
->height
- (font
->height
+ extents
->max_logical_extent
.y
);
211 assert(WMHashInsert(scrPtr
->fontSetCache
, font
->name
, font
)==NULL
);
219 WMCreateNormalFont(WMScreen
*scrPtr
, char *fontName
)
222 Display
*display
= scrPtr
->display
;
225 fontName
= xlfdFromFontName(fontName
, False
);
227 if ((ptr
= strchr(fontName
, ','))) {
228 fname
= wmalloc(ptr
- fontName
+ 1);
229 strncpy(fname
, fontName
, ptr
- fontName
);
230 fname
[ptr
- fontName
] = 0;
232 fname
= wstrdup(fontName
);
237 font
= WMHashGet(scrPtr
->fontCache
, fname
);
244 font
= wmalloc(sizeof(WMFont
));
245 memset(font
, 0, sizeof(WMFont
));
247 font
->notFontSet
= 1;
248 font
->antialiased
= 0;
250 font
->screen
= scrPtr
;
252 font
->font
.normal
= XLoadQueryFont(display
, fname
);
253 if (!font
->font
.normal
) {
258 font
->height
= font
->font
.normal
->ascent
+font
->font
.normal
->descent
;
259 font
->y
= font
->font
.normal
->ascent
;
265 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
)==NULL
);
272 WMCreateAntialiasedFont(WMScreen
*scrPtr
, char *fontName
)
276 Display
*display
= scrPtr
->display
;
279 if (!scrPtr
->hasXftSupport
)
282 fontName
= xlfdFromFontName(fontName
, True
);
284 if ((ptr
= strchr(fontName
, ','))) {
285 fname
= wmalloc(ptr
- fontName
+ 1);
286 strncpy(fname
, fontName
, ptr
- fontName
);
287 fname
[ptr
- fontName
] = 0;
289 fname
= wstrdup(fontName
);
294 font
= WMHashGet(scrPtr
->xftFontCache
, fname
);
301 font
= wmalloc(sizeof(WMFont
));
302 memset(font
, 0, sizeof(WMFont
));
304 font
->notFontSet
= 1;
305 font
->antialiased
= 1;
307 font
->screen
= scrPtr
;
309 /* Xft sux. Loading a font with an invalid XLFD will give strange results
310 * sometimes without returning any warning or error.
311 * However Xft's idea of what font is invalid is quite strange:
312 * 1. If the XLFD doesn't have all its fields present will fail and
314 * 2. If all fields are present, but hold invalid values then it will:
315 * a. If family is invalid, will load a default font without warning.
316 * b. If the font size is invalid (non-numerical) it will fail and
318 * c. If other fields are invalid, will load the font specified by
319 * the valid family name, ignoring any invalid fields. It will
320 * use a default medium weight and a default roman slant if they
323 font
->font
.xft
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
324 if (!font
->font
.xft
) {
329 font
->height
= font
->font
.xft
->ascent
+font
->font
.xft
->descent
;
330 font
->y
= font
->font
.xft
->ascent
;
336 assert(WMHashInsert(scrPtr
->xftFontCache
, font
->name
, font
)==NULL
);
346 WMCreateAntialiasedFontSet(WMScreen
*scrPtr
, char *fontName
)
350 Display
*display
= scrPtr
->display
;
353 if (!scrPtr
->hasXftSupport
)
356 fontName
= xlfdFromFontName(fontName
, True
);
358 if ((ptr
= strchr(fontName
, ','))) {
359 fname
= wmalloc(ptr
- fontName
+ 1);
360 strncpy(fname
, fontName
, ptr
- fontName
);
361 fname
[ptr
- fontName
] = 0;
363 fname
= wstrdup(fontName
);
368 font
= WMHashGet(scrPtr
->xftFontSetCache
, fname
);
375 font
= wmalloc(sizeof(WMFont
));
376 memset(font
, 0, sizeof(WMFont
));
378 font
->notFontSet
= 0;
379 font
->antialiased
= 1;
381 font
->screen
= scrPtr
;
383 /* Xft sux. Loading a font with an invalid XLFD will give strange results
384 * sometimes without returning any warning or error.
385 * However Xft's idea of what font is invalid is quite strange:
386 * 1. If the XLFD doesn't have all its fields present will fail and
388 * 2. If all fields are present, but hold invalid values then it will:
389 * a. If family is invalid, will load a default font without warning.
390 * b. If the font size is invalid (non-numerical) it will fail and
392 * c. If other fields are invalid, will load the font specified by
393 * the valid family name, ignoring any invalid fields. It will
394 * use a default medium weight and a default roman slant if they
397 font
->font
.xft
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
398 if (!font
->font
.xft
) {
403 font
->height
= font
->font
.xft
->ascent
+font
->font
.xft
->descent
;
404 font
->y
= font
->font
.xft
->ascent
;
410 assert(WMHashInsert(scrPtr
->xftFontSetCache
, font
->name
, font
)==NULL
);
420 WMCreateFont(WMScreen
*scrPtr
, char *fontName
)
422 return WMCreateFontWithFlags(scrPtr
, fontName
, WFDefaultFont
);
427 WMCreateFontWithFlags(WMScreen
*scrPtr
, char *fontName
, WMFontFlags flags
)
429 Bool multiByte
= scrPtr
->useMultiByte
;
430 Bool antialiased
= scrPtr
->antialiasedText
;
433 if (flags
& WFFontSet
) {
435 } else if (flags
& WFNormalFont
) {
438 if (flags
& WFAntialiased
) {
440 } else if (flags
& WFNotAntialiased
) {
444 if (antialiased
&& multiByte
) {
445 font
= WMCreateAntialiasedFontSet(scrPtr
, fontName
);
446 /* If we cannot create an antialiased font set and antialiasing is
447 * not explicitly requested in flags, fallback to standard font sets */
448 if (!font
&& (flags
& WFAntialiased
)==0) {
449 font
= WMCreateFontSet(scrPtr
, fontName
);
451 } else if (antialiased
) {
452 font
= WMCreateAntialiasedFont(scrPtr
, fontName
);
453 /* If we cannot create an antialiased font and antialiasing is
454 * not explicitly requested in flags, fallback to normal font */
455 if (!font
&& (flags
& WFAntialiased
)==0) {
456 font
= WMCreateNormalFont(scrPtr
, fontName
);
458 } else if (multiByte
) {
459 font
= WMCreateFontSet(scrPtr
, fontName
);
461 font
= WMCreateNormalFont(scrPtr
, fontName
);
469 WMRetainFont(WMFont
*font
)
471 wassertrv(font
!=NULL
, NULL
);
480 WMReleaseFont(WMFont
*font
)
482 wassertr(font
!=NULL
);
485 if (font
->refCount
< 1) {
486 if (font
->antialiased
) {
488 XftFontClose(font
->screen
->display
, font
->font
.xft
);
492 } else if (font
->notFontSet
) {
493 XFreeFont(font
->screen
->display
, font
->font
.normal
);
495 XFreeFontSet(font
->screen
->display
, font
->font
.set
);
499 if (font
->antialiased
&& !font
->notFontSet
) {
500 WMHashRemove(font
->screen
->xftFontSetCache
, font
->name
);
501 } else if (font
->antialiased
) {
502 WMHashRemove(font
->screen
->xftFontCache
, font
->name
);
503 } else if (font
->notFontSet
) {
504 WMHashRemove(font
->screen
->fontCache
, font
->name
);
506 WMHashRemove(font
->screen
->fontSetCache
, font
->name
);
516 WMHasAntialiasingSupport(WMScreen
*scrPtr
)
518 return scrPtr
->hasXftSupport
;
523 WMIsAntialiasingEnabled(WMScreen
*scrPtr
)
525 return scrPtr
->antialiasedText
;
530 WMIsAntialiasedFont(WMFont
*font
)
532 wassertrv(font
!=NULL
, False
);
534 return font
->antialiased
;
539 WMFontHeight(WMFont
*font
)
541 wassertrv(font
!=NULL
, 0);
548 WMGetFontName(WMFont
*font
)
550 wassertrv(font
!=NULL
, NULL
);
557 WMDefaultSystemFont(WMScreen
*scrPtr
)
559 return WMRetainFont(scrPtr
->normalFont
);
564 WMDefaultBoldSystemFont(WMScreen
*scrPtr
)
566 return WMRetainFont(scrPtr
->boldFont
);
571 makeSystemFontOfSize(WMScreen
*scrPtr
, int size
, Bool bold
)
574 char *fontSpec
, *xftFontSpec
;
576 #define WConf WINGsConfiguration
578 fontSpec
= makeFontSetOfSize(WConf
.boldSystemFont
, size
);
579 xftFontSpec
= makeFontSetOfSize(WConf
.antialiasedBoldSystemFont
, size
);
581 fontSpec
= makeFontSetOfSize(WConf
.systemFont
, size
);
582 xftFontSpec
= makeFontSetOfSize(WConf
.antialiasedSystemFont
, size
);
586 if (scrPtr
->antialiasedText
&& scrPtr
->useMultiByte
) {
587 font
= WMCreateAntialiasedFontSet(scrPtr
, xftFontSpec
);
588 } else if (scrPtr
->antialiasedText
) {
589 font
= WMCreateAntialiasedFont(scrPtr
, xftFontSpec
);
590 } else if (scrPtr
->useMultiByte
) {
591 font
= WMCreateFontSet(scrPtr
, fontSpec
);
593 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
597 if (scrPtr
->antialiasedText
&& scrPtr
->useMultiByte
) {
598 // is arial a good fallback for multibyte?
599 wwarning(_("could not load font %s. Trying arial."), xftFontSpec
);
601 font
= WMCreateAntialiasedFontSet(scrPtr
, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
603 font
= WMCreateAntialiasedFontSet(scrPtr
, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
606 wwarning(_("could not load antialiased font set. Reverting to standard font sets."));
607 font
= WMCreateFontSet(scrPtr
, fontSpec
);
609 wwarning(_("could not load FontSet %s. Trying fixed."), fontSpec
);
610 font
= WMCreateFontSet(scrPtr
, "fixed");
613 } else if (scrPtr
->antialiasedText
) {
614 wwarning(_("could not load font %s. Trying arial."), xftFontSpec
);
616 font
= WMCreateAntialiasedFont(scrPtr
, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
618 font
= WMCreateAntialiasedFont(scrPtr
, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
621 wwarning(_("could not load antialiased fonts. Reverting to normal fonts."));
622 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
624 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
625 font
= WMCreateNormalFont(scrPtr
, "fixed");
628 } else if (scrPtr
->useMultiByte
) {
629 wwarning(_("could not load font set %s. Trying fixed."), fontSpec
);
630 font
= WMCreateFontSet(scrPtr
, "fixed");
632 font
= WMCreateFontSet(scrPtr
, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
635 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
636 font
= WMCreateNormalFont(scrPtr
, "fixed");
639 wwarning(_("could not load fixed font!"));
653 WMSystemFontOfSize(WMScreen
*scrPtr
, int size
)
655 return makeSystemFontOfSize(scrPtr
, size
, False
);
660 WMBoldSystemFontOfSize(WMScreen
*scrPtr
, int size
)
662 return makeSystemFontOfSize(scrPtr
, size
, True
);
667 WMGetFontFontSet(WMFont
*font
)
669 wassertrv(font
!=NULL
, NULL
);
671 if (!font
->notFontSet
&& !font
->antialiased
)
672 return font
->font
.set
;
679 WMWidthOfString(WMFont
*font
, char *text
, int length
)
681 wassertrv(font
!=NULL
, 0);
682 wassertrv(text
!=NULL
, 0);
684 if (font
->antialiased
) {
688 if (!font
->notFontSet
) {
693 /* Use mtext instead of text, because mbstrtowcs() alters it */
695 wtext
= (wchar_t *)wmalloc(4*length
+4);
696 /* pass a real ps instead of NULL below? for multithread safety
697 * as from manual page */
698 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
700 XftTextExtents32(font
->screen
->display
, font
->font
.xft
,
701 (XftChar32
*)wtext
, len
, &extents
);
704 wwarning(_("Conversion to widechar failed (possible "
705 "invalid multibyte sequence): '%s':(pos %d)\n"),
712 XftTextExtents8(font
->screen
->display
, font
->font
.xft
,
713 (XftChar8
*)text
, length
, &extents
);
716 return extents
.xOff
; /* don't ask :P */
720 } else if (font
->notFontSet
) {
721 return XTextWidth(font
->font
.normal
, text
, length
);
726 XmbTextExtents(font
->font
.set
, text
, length
, &AIXsucks
, &rect
);
735 WMDrawString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMFont
*font
,
736 int x
, int y
, char *text
, int length
)
738 wassertr(font
!=NULL
);
740 if (font
->antialiased
) {
744 xftcolor
.color
.red
= color
->color
.red
;
745 xftcolor
.color
.green
= color
->color
.green
;
746 xftcolor
.color
.blue
= color
->color
.blue
;
747 xftcolor
.color
.alpha
= color
->alpha
;;
748 xftcolor
.pixel
= W_PIXEL(color
);
750 XftDrawChange(scr
->xftdraw
, d
);
752 if (!font
->notFontSet
) {
757 /* Use mtext instead of text, because mbstrtowcs() alters it */
759 wtext
= (wchar_t *)wmalloc(4*length
+4);
760 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
762 XftDrawString32(scr
->xftdraw
, &xftcolor
, font
->font
.xft
,
763 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
764 } else if (len
==-1) {
765 wwarning(_("Conversion to widechar failed (possible invalid "
766 "multibyte sequence): '%s':(pos %d)\n"),
768 /* we can draw normal text, or we can draw as much widechar
769 * text as was already converted until the error. go figure */
770 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
771 x, y + font->y, (XftChar8*)text, length);*/
775 XftDrawString8(scr
->xftdraw
, &xftcolor
, font
->font
.xft
,
776 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
781 } else if (font
->notFontSet
) {
782 XSetFont(scr
->display
, scr
->drawStringGC
, font
->font
.normal
->fid
);
783 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
784 XDrawString(scr
->display
, d
, scr
->drawStringGC
, x
, y
+ font
->y
,
787 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
788 XmbDrawString(scr
->display
, d
, font
->font
.set
, scr
->drawStringGC
,
789 x
, y
+ font
->y
, text
, length
);
795 WMDrawImageString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMColor
*background
,
796 WMFont
*font
, int x
, int y
, char *text
, int length
)
798 wassertr(font
!=NULL
);
800 if (font
->antialiased
) {
805 textColor
.color
.red
= color
->color
.red
;
806 textColor
.color
.green
= color
->color
.green
;
807 textColor
.color
.blue
= color
->color
.blue
;
808 textColor
.color
.alpha
= color
->alpha
;;
809 textColor
.pixel
= W_PIXEL(color
);
811 bgColor
.color
.red
= background
->color
.red
;
812 bgColor
.color
.green
= background
->color
.green
;
813 bgColor
.color
.blue
= background
->color
.blue
;
814 bgColor
.color
.alpha
= background
->alpha
;;
815 bgColor
.pixel
= W_PIXEL(background
);
818 XftDrawChange(scr
->xftdraw
, d
);
820 XftDrawRect(scr
->xftdraw
, &bgColor
, x
, y
,
821 WMWidthOfString(font
, text
, length
), font
->height
);
823 if (!font
->notFontSet
) {
828 /* Use mtext instead of text, because mbstrtowcs() alters it */
830 wtext
= (wchar_t *)wmalloc(4*length
+4);
831 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
833 XftDrawString32(scr
->xftdraw
, &textColor
, font
->font
.xft
,
834 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
835 } else if (len
==-1) {
836 wwarning(_("Conversion to widechar failed (possible invalid "
837 "multibyte sequence): '%s':(pos %d)\n"),
839 /* we can draw normal text, or we can draw as much widechar
840 * text as was already converted until the error. go figure */
841 /*XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
842 x, y + font->y, (XftChar8*)text, length);*/
846 XftDrawString8(scr
->xftdraw
, &textColor
, font
->font
.xft
,
847 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
852 } else if (font
->notFontSet
) {
853 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
854 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
855 XSetFont(scr
->display
, scr
->drawImStringGC
, font
->font
.normal
->fid
);
856 XDrawImageString(scr
->display
, d
, scr
->drawImStringGC
,
857 x
, y
+ font
->y
, text
, length
);
859 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
860 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
861 XmbDrawImageString(scr
->display
, d
, font
->font
.set
, scr
->drawImStringGC
,
862 x
, y
+ font
->y
, text
, length
);
870 makeFontSetOfSize(char *fontset
, int size
)
882 ptr
= strchr(fontset
, ',');
884 int count
= ptr
-fontset
;
887 wwarning(_("font description %s is too large."), fontset
);
889 memcpy(font
, fontset
, count
);
900 tmp
= wmalloc(end
+ strlen(f
) + 8);
902 sprintf(tmp
, "%s,", newfs
);
903 sprintf(tmp
+ end
+ 1, f
, size
);
905 sprintf(tmp
+ end
, f
, size
);
919 #define FONT_PROPS 14
922 char *props
[FONT_PROPS
];
927 changeFontProp(char *buf
, char *newprop
, int position
)
930 char *ptr
, *pptr
, *rptr
;
934 /* // remove warning later. or maybe not */
935 wwarning(_("Invalid font specification: '%s'\n"), buf
);
939 ptr
= pptr
= rptr
= buf
;
941 while (*ptr
&& *ptr
!=',') {
944 if (count
-1==position
+1) {
948 if (count
-1==position
) {
954 if (position
==FONT_PROPS
-1) {
959 snprintf(buf2
, 512, "%s%s%s", buf
, newprop
, rptr
);
965 getOptions(char *options
)
967 char *ptr
, *ptr2
, *str
;
971 result
= WMCreateArrayWithDestructor(2, (WMFreeDataProc
*)wfree
);
975 ptr2
= strchr(ptr
, ',');
977 WMAddToArray(result
, wstrdup(ptr
));
981 str
= wmalloc(count
+1);
982 memcpy(str
, ptr
, count
);
984 WMAddToArray(result
, str
);
994 WMCopyFontWithChanges(WMScreen
*scrPtr
, WMFont
*font
,
995 const WMFontAttributes
*changes
)
997 int index
[FONT_PROPS
], count
[FONT_PROPS
];
998 int totalProps
, i
, j
, carry
;
1006 snprintf(fname
, 512, "%s", font
->name
);
1008 fFlags
= (font
->antialiased
? WFAntialiased
: WFNotAntialiased
);
1009 fFlags
|= (font
->notFontSet
? WFNormalFont
: WFFontSet
);
1011 props
= WMCreateBagWithDestructor(1, (WMFreeDataProc
*)WMFreeArray
);
1014 for (i
=0; i
<FONT_PROPS
; i
++) {
1015 prop
= ((W_FontAttributes
*)changes
)->props
[i
];
1016 count
[i
] = index
[i
] = 0;
1018 /* No change for this property */
1020 } else if (strchr(prop
, ',')==NULL
) {
1022 changeFontProp(fname
, prop
, i
);
1024 /* Option with fallback alternatives */
1025 if ((changes
==WFAEmphasized
|| changes
==WFABoldEmphasized
) &&
1026 font
->antialiased
&& strcmp(prop
, "o,i")==0) {
1027 options
= getOptions("i,o");
1029 options
= getOptions(prop
);
1031 WMInsertInBag(props
, i
, options
);
1032 count
[i
] = WMGetArrayItemCount(options
);
1035 totalProps
= totalProps
* count
[i
];
1039 if (totalProps
== 0) {
1040 /* No options with fallback alternatives at all */
1042 return WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
1045 for (i
=0; i
<totalProps
; i
++) {
1046 for (j
=0; j
<FONT_PROPS
; j
++) {
1048 options
= WMGetFromBag(props
, j
);
1049 prop
= WMGetFromArray(options
, index
[j
]);
1051 changeFontProp(fname
, prop
, j
);
1055 result
= WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
1060 for (j
=FONT_PROPS
-1, carry
=1; j
>=0; j
--) {
1063 carry
= (index
[j
]==count
[j
]);
1064 index
[j
] %= count
[j
];
1076 // should WFANormal also set "normal" or leave it alone?
1077 static const WMFontAttributes W_FANormal
= {
1078 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", "r", "normal",
1079 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1080 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1084 static const WMFontAttributes W_FABold
= {
1085 WFAUnchanged
, WFAUnchanged
, "bold", WFAUnchanged
,
1086 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1087 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1091 static const WMFontAttributes W_FANotBold
= {
1092 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", WFAUnchanged
,
1093 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1094 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1098 static const WMFontAttributes W_FAEmphasized
= {
1099 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "o,i",
1100 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1101 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1105 static const WMFontAttributes W_FANotEmphasized
= {
1106 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "r",
1107 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1108 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1112 static const WMFontAttributes W_FABoldEmphasized
= {
1113 WFAUnchanged
, WFAUnchanged
, "bold", "o,i",
1114 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1115 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1119 const WMFontAttributes
*WFANormal
= &W_FANormal
;
1120 const WMFontAttributes
*WFABold
= &W_FABold
;
1121 const WMFontAttributes
*WFANotBold
= &W_FANotBold
;
1122 const WMFontAttributes
*WFAEmphasized
= &W_FAEmphasized
;
1123 const WMFontAttributes
*WFANotEmphasized
= &W_FANotEmphasized
;
1124 const WMFontAttributes
*WFABoldEmphasized
= &W_FABoldEmphasized
;