5 # include <X11/Xft/Xft.h>
16 #include <X11/Xlocale.h>
20 static char *makeFontSetOfSize(char *fontset
, int size
);
24 /* XLFD pattern matching */
26 getElementFromXLFD(const char *xlfd
, int index
)
30 if (*p
== '-' && --index
== 0) {
31 const char *end
= strchr(p
+ 1, '-');
34 if (end
== 0) end
= p
+ strlen(p
);
37 memcpy(buf
, p
+ 1, len
);
47 /* XLFD pattern matching */
49 generalizeXLFD(const char *xlfd
)
53 char *weight
= getElementFromXLFD(xlfd
, 3);
54 char *slant
= getElementFromXLFD(xlfd
, 4);
55 char *pxlsz
= getElementFromXLFD(xlfd
, 7);
57 #define Xstrlen(A) ((A)?strlen(A):0)
58 len
= Xstrlen(xlfd
)+Xstrlen(weight
)+Xstrlen(slant
)+Xstrlen(pxlsz
)*2+60;
61 buf
= wmalloc(len
+ 1);
62 snprintf(buf
, len
+ 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
63 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
64 xlfd
, weight
, slant
, pxlsz
, pxlsz
);
73 /* XLFD pattern matching */
75 W_CreateFontSetWithGuess(Display
*dpy
, char *xlfd
, char ***missing
,
76 int *nmissing
, char **def_string
)
78 XFontSet fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
80 if (fs
!= NULL
&& *nmissing
== 0) return fs
;
82 /* for non-iso8859-1 language and iso8859-1 specification
83 (this fontset is only for pattern analysis) */
85 if (*nmissing
!= 0) XFreeStringList(*missing
);
86 setlocale(LC_CTYPE
, "C");
87 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
88 setlocale(LC_CTYPE
, "");
91 /* make XLFD font name for pattern analysis */
93 XFontStruct
**fontstructs
;
95 if (XFontsOfFontSet(fs
, &fontstructs
, &fontnames
) > 0)
99 xlfd
= generalizeXLFD(xlfd
);
101 if (*nmissing
!= 0) XFreeStringList(*missing
);
102 if (fs
!= NULL
) XFreeFontSet(dpy
, fs
);
104 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
112 xlfdFromFontName(char *fontName
, Bool antialiased
)
114 char *systemFont
, *boldSystemFont
;
119 systemFont
= WINGsConfiguration
.antialiasedSystemFont
;
120 boldSystemFont
= WINGsConfiguration
.antialiasedBoldSystemFont
;
122 systemFont
= WINGsConfiguration
.systemFont
;
123 boldSystemFont
= WINGsConfiguration
.boldSystemFont
;
126 size
= WINGsConfiguration
.defaultFontSize
;
128 if (strcmp(fontName
, "SystemFont")==0) {
130 size
= WINGsConfiguration
.defaultFontSize
;
131 } else if (strncmp(fontName
, "SystemFont-", 11)==0) {
133 if (sscanf(&fontName
[11], "%i", &size
)!=1) {
134 size
= WINGsConfiguration
.defaultFontSize
;
135 wwarning(_("Invalid size specification '%s' in %s. "
136 "Using default %d\n"), &fontName
[11], fontName
, size
);
138 } else if (strcmp(fontName
, "BoldSystemFont")==0) {
139 font
= boldSystemFont
;
140 size
= WINGsConfiguration
.defaultFontSize
;
141 } else if (strncmp(fontName
, "BoldSystemFont-", 15)==0) {
142 font
= boldSystemFont
;
143 if (sscanf(&fontName
[15], "%i", &size
)!=1) {
144 size
= WINGsConfiguration
.defaultFontSize
;
145 wwarning(_("Invalid size specification '%s' in %s. "
146 "Using default %d\n"), &fontName
[15], fontName
, size
);
152 return (font
!=NULL
? makeFontSetOfSize(font
, size
) : wstrdup(fontName
));
157 WMCreateFontSet(WMScreen
*scrPtr
, char *fontName
)
160 Display
*display
= scrPtr
->display
;
165 XFontSetExtents
*extents
;
167 fname
= xlfdFromFontName(fontName
, False
);
169 font
= WMHashGet(scrPtr
->fontSetCache
, fname
);
176 font
= wmalloc(sizeof(WMFont
));
177 memset(font
, 0, sizeof(WMFont
));
179 font
->notFontSet
= 0;
180 font
->antialiased
= 0;
182 font
->screen
= scrPtr
;
184 font
->font
.set
= W_CreateFontSetWithGuess(display
, fname
, &missing
,
185 &nmissing
, &defaultString
);
186 if (nmissing
> 0 && font
->font
.set
) {
189 wwarning(_("the following character sets are missing in %s:"), fname
);
190 for (i
= 0; i
< nmissing
; i
++) {
191 wwarning(missing
[i
]);
193 XFreeStringList(missing
);
195 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
198 if (!font
->font
.set
) {
204 extents
= XExtentsOfFontSet(font
->font
.set
);
206 font
->height
= extents
->max_logical_extent
.height
;
207 font
->y
= font
->height
- (font
->height
+ extents
->max_logical_extent
.y
);
213 assert(WMHashInsert(scrPtr
->fontSetCache
, font
->name
, font
)==NULL
);
221 WMCreateNormalFont(WMScreen
*scrPtr
, char *fontName
)
224 Display
*display
= scrPtr
->display
;
227 fontName
= xlfdFromFontName(fontName
, False
);
229 if ((ptr
= strchr(fontName
, ','))) {
230 fname
= wmalloc(ptr
- fontName
+ 1);
231 strncpy(fname
, fontName
, ptr
- fontName
);
232 fname
[ptr
- fontName
] = 0;
234 fname
= wstrdup(fontName
);
239 font
= WMHashGet(scrPtr
->fontCache
, fname
);
246 font
= wmalloc(sizeof(WMFont
));
247 memset(font
, 0, sizeof(WMFont
));
249 font
->notFontSet
= 1;
250 font
->antialiased
= 0;
252 font
->screen
= scrPtr
;
254 font
->font
.normal
= XLoadQueryFont(display
, fname
);
255 if (!font
->font
.normal
) {
260 font
->height
= font
->font
.normal
->ascent
+font
->font
.normal
->descent
;
261 font
->y
= font
->font
.normal
->ascent
;
267 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
)==NULL
);
274 WMCreateAntialiasedFont(WMScreen
*scrPtr
, char *fontName
)
278 Display
*display
= scrPtr
->display
;
281 fontName
= xlfdFromFontName(fontName
, True
);
283 if ((ptr
= strchr(fontName
, ','))) {
284 fname
= wmalloc(ptr
- fontName
+ 1);
285 strncpy(fname
, fontName
, ptr
- fontName
);
286 fname
[ptr
- fontName
] = 0;
288 fname
= wstrdup(fontName
);
293 font
= WMHashGet(scrPtr
->xftFontCache
, fname
);
300 font
= wmalloc(sizeof(WMFont
));
301 memset(font
, 0, sizeof(WMFont
));
303 font
->notFontSet
= 1;
304 font
->antialiased
= 1;
306 font
->screen
= scrPtr
;
308 /* Xft sux. Loading a font with an invalid XLFD will give strange results
309 * sometimes without returning any warning or error.
310 * However Xft's idea of what font is invalid is quite strange:
311 * 1. If the XLFD doesn't have all its fields present will fail and
313 * 2. If all fields are present, but hold invalid values then it will:
314 * a. If family is invalid, will load a default font without warning.
315 * b. If the font size is invalid (non-numerical) it will fail and
317 * c. If other fields are invalid, will load the font specified by
318 * the valid family name, ignoring any invalid fields. It will
319 * use a default medium weight and a default roman slant if they
322 printf("%s\n", fname
);
323 if (fname
[0] == '-') {
324 font
->font
.xft
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
326 font
->font
.xft
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
328 if (!font
->font
.xft
) {
333 font
->height
= font
->font
.xft
->ascent
+font
->font
.xft
->descent
;
334 font
->y
= font
->font
.xft
->ascent
;
340 assert(WMHashInsert(scrPtr
->xftFontCache
, font
->name
, font
)==NULL
);
350 WMCreateAntialiasedFontSet(WMScreen
*scrPtr
, char *fontName
)
354 Display
*display
= scrPtr
->display
;
357 fontName
= xlfdFromFontName(fontName
, True
);
359 if ((ptr
= strchr(fontName
, ','))) {
360 fname
= wmalloc(ptr
- fontName
+ 1);
361 strncpy(fname
, fontName
, ptr
- fontName
);
362 fname
[ptr
- fontName
] = 0;
364 fname
= wstrdup(fontName
);
369 font
= WMHashGet(scrPtr
->xftFontSetCache
, fname
);
376 font
= wmalloc(sizeof(WMFont
));
377 memset(font
, 0, sizeof(WMFont
));
379 font
->notFontSet
= 0;
380 font
->antialiased
= 1;
382 font
->screen
= scrPtr
;
384 /* Xft sux. Loading a font with an invalid XLFD will give strange results
385 * sometimes without returning any warning or error.
386 * However Xft's idea of what font is invalid is quite strange:
387 * 1. If the XLFD doesn't have all its fields present will fail and
389 * 2. If all fields are present, but hold invalid values then it will:
390 * a. If family is invalid, will load a default font without warning.
391 * b. If the font size is invalid (non-numerical) it will fail and
393 * c. If other fields are invalid, will load the font specified by
394 * the valid family name, ignoring any invalid fields. It will
395 * use a default medium weight and a default roman slant if they
398 if (fname
[0] == '-') {
399 font
->font
.xft
= XftFontOpenXlfd(display
, scrPtr
->screen
, fname
);
401 font
->font
.xft
= XftFontOpenName(display
, scrPtr
->screen
, fname
);
403 if (!font
->font
.xft
) {
408 font
->height
= font
->font
.xft
->ascent
+font
->font
.xft
->descent
;
409 font
->y
= font
->font
.xft
->ascent
;
415 assert(WMHashInsert(scrPtr
->xftFontSetCache
, font
->name
, font
)==NULL
);
425 WMCreateFont(WMScreen
*scrPtr
, char *fontName
)
427 return WMCreateFontWithFlags(scrPtr
, fontName
, WFDefaultFont
);
432 WMCreateFontWithFlags(WMScreen
*scrPtr
, char *fontName
, WMFontFlags flags
)
434 Bool multiByte
= scrPtr
->useMultiByte
;
435 Bool antialiased
= scrPtr
->antialiasedText
;
438 if (flags
& WFFontSet
) {
440 } else if (flags
& WFNormalFont
) {
443 if (flags
& WFAntialiased
) {
445 } else if (flags
& WFNotAntialiased
) {
449 if (antialiased
&& multiByte
) {
450 font
= WMCreateAntialiasedFontSet(scrPtr
, fontName
);
451 /* If we cannot create an antialiased font set and antialiasing is
452 * not explicitly requested in flags, fallback to standard font sets */
453 if (!font
&& (flags
& WFAntialiased
)==0) {
454 font
= WMCreateFontSet(scrPtr
, fontName
);
456 } else if (antialiased
) {
457 font
= WMCreateAntialiasedFont(scrPtr
, fontName
);
458 /* If we cannot create an antialiased font and antialiasing is
459 * not explicitly requested in flags, fallback to normal font */
460 if (!font
&& (flags
& WFAntialiased
)==0) {
461 font
= WMCreateNormalFont(scrPtr
, fontName
);
463 } else if (multiByte
) {
464 font
= WMCreateFontSet(scrPtr
, fontName
);
466 font
= WMCreateNormalFont(scrPtr
, fontName
);
474 WMRetainFont(WMFont
*font
)
476 wassertrv(font
!=NULL
, NULL
);
485 WMReleaseFont(WMFont
*font
)
487 wassertr(font
!=NULL
);
490 if (font
->refCount
< 1) {
491 if (font
->antialiased
) {
493 XftFontClose(font
->screen
->display
, font
->font
.xft
);
497 } else if (font
->notFontSet
) {
498 XFreeFont(font
->screen
->display
, font
->font
.normal
);
500 XFreeFontSet(font
->screen
->display
, font
->font
.set
);
504 if (font
->antialiased
&& !font
->notFontSet
) {
505 WMHashRemove(font
->screen
->xftFontSetCache
, font
->name
);
506 } else if (font
->antialiased
) {
507 WMHashRemove(font
->screen
->xftFontCache
, font
->name
);
508 } else if (font
->notFontSet
) {
509 WMHashRemove(font
->screen
->fontCache
, font
->name
);
511 WMHashRemove(font
->screen
->fontSetCache
, font
->name
);
521 WMIsAntialiasingEnabled(WMScreen
*scrPtr
)
523 return scrPtr
->antialiasedText
;
528 WMIsAntialiasedFont(WMFont
*font
)
530 wassertrv(font
!=NULL
, False
);
532 return font
->antialiased
;
537 WMFontHeight(WMFont
*font
)
539 wassertrv(font
!=NULL
, 0);
546 WMGetFontName(WMFont
*font
)
548 wassertrv(font
!=NULL
, NULL
);
555 WMDefaultSystemFont(WMScreen
*scrPtr
)
557 return WMRetainFont(scrPtr
->normalFont
);
562 WMDefaultBoldSystemFont(WMScreen
*scrPtr
)
564 return WMRetainFont(scrPtr
->boldFont
);
569 makeSystemFontOfSize(WMScreen
*scrPtr
, int size
, Bool bold
)
572 char *fontSpec
, *xftFontSpec
;
574 #define WConf WINGsConfiguration
576 fontSpec
= makeFontSetOfSize(WConf
.boldSystemFont
, size
);
577 xftFontSpec
= makeFontSetOfSize(WConf
.antialiasedBoldSystemFont
, size
);
579 fontSpec
= makeFontSetOfSize(WConf
.systemFont
, size
);
580 xftFontSpec
= makeFontSetOfSize(WConf
.antialiasedSystemFont
, size
);
584 if (scrPtr
->antialiasedText
&& scrPtr
->useMultiByte
) {
585 font
= WMCreateAntialiasedFontSet(scrPtr
, xftFontSpec
);
586 } else if (scrPtr
->antialiasedText
) {
587 font
= WMCreateAntialiasedFont(scrPtr
, xftFontSpec
);
588 } else if (scrPtr
->useMultiByte
) {
589 font
= WMCreateFontSet(scrPtr
, fontSpec
);
591 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
595 if (scrPtr
->antialiasedText
&& scrPtr
->useMultiByte
) {
596 // is arial a good fallback for multibyte?
597 wwarning(_("could not load font %s. Trying arial."), xftFontSpec
);
599 font
= WMCreateAntialiasedFontSet(scrPtr
, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
601 font
= WMCreateAntialiasedFontSet(scrPtr
, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
604 wwarning(_("could not load antialiased font set. Reverting to standard font sets."));
605 font
= WMCreateFontSet(scrPtr
, fontSpec
);
607 wwarning(_("could not load FontSet %s. Trying fixed."), fontSpec
);
608 font
= WMCreateFontSet(scrPtr
, "fixed");
611 } else if (scrPtr
->antialiasedText
) {
612 wwarning(_("could not load font %s. Trying arial."), xftFontSpec
);
614 font
= WMCreateAntialiasedFont(scrPtr
, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*");
616 font
= WMCreateAntialiasedFont(scrPtr
, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*");
619 wwarning(_("could not load antialiased fonts. Reverting to normal fonts."));
620 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
622 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
623 font
= WMCreateNormalFont(scrPtr
, "fixed");
626 } else if (scrPtr
->useMultiByte
) {
627 wwarning(_("could not load font set %s. Trying fixed."), fontSpec
);
628 font
= WMCreateFontSet(scrPtr
, "fixed");
630 font
= WMCreateFontSet(scrPtr
, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
633 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
634 font
= WMCreateNormalFont(scrPtr
, "fixed");
637 wwarning(_("could not load fixed font!"));
651 WMSystemFontOfSize(WMScreen
*scrPtr
, int size
)
653 return makeSystemFontOfSize(scrPtr
, size
, False
);
658 WMBoldSystemFontOfSize(WMScreen
*scrPtr
, int size
)
660 return makeSystemFontOfSize(scrPtr
, size
, True
);
665 WMGetFontFontSet(WMFont
*font
)
667 wassertrv(font
!=NULL
, NULL
);
669 if (!font
->notFontSet
&& !font
->antialiased
)
670 return font
->font
.set
;
677 WMWidthOfString(WMFont
*font
, char *text
, int length
)
679 wassertrv(font
!=NULL
, 0);
680 wassertrv(text
!=NULL
, 0);
682 if (font
->antialiased
) {
686 if (!font
->notFontSet
) {
691 /* Use mtext instead of text, because mbstrtowcs() alters it */
693 wtext
= (wchar_t *)wmalloc(4*length
+4);
694 /* pass a real ps instead of NULL below? for multithread safety
695 * as from manual page */
696 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
698 XftTextExtents32(font
->screen
->display
, font
->font
.xft
,
699 (XftChar32
*)wtext
, len
, &extents
);
702 wwarning(_("Conversion to widechar failed (possible "
703 "invalid multibyte sequence): '%s':(pos %d)\n"),
710 XftTextExtents8(font
->screen
->display
, font
->font
.xft
,
711 (XftChar8
*)text
, length
, &extents
);
714 return extents
.xOff
; /* don't ask :P */
718 } else if (font
->notFontSet
) {
719 return XTextWidth(font
->font
.normal
, text
, length
);
724 XmbTextExtents(font
->font
.set
, text
, length
, &AIXsucks
, &rect
);
733 WMDrawString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMFont
*font
,
734 int x
, int y
, char *text
, int length
)
736 wassertr(font
!=NULL
);
738 if (font
->antialiased
) {
742 xftcolor
.color
.red
= color
->color
.red
;
743 xftcolor
.color
.green
= color
->color
.green
;
744 xftcolor
.color
.blue
= color
->color
.blue
;
745 xftcolor
.color
.alpha
= color
->alpha
;;
746 xftcolor
.pixel
= W_PIXEL(color
);
748 XftDrawChange(scr
->xftdraw
, d
);
750 if (!font
->notFontSet
) {
755 /* Use mtext instead of text, because mbstrtowcs() alters it */
757 wtext
= (wchar_t *)wmalloc(4*length
+4);
758 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
760 XftDrawString32(scr
->xftdraw
, &xftcolor
, font
->font
.xft
,
761 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
762 } else if (len
==-1) {
763 wwarning(_("Conversion to widechar failed (possible invalid "
764 "multibyte sequence): '%s':(pos %d)\n"),
766 /* we can draw normal text, or we can draw as much widechar
767 * text as was already converted until the error. go figure */
768 /*XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft,
769 x, y + font->y, (XftChar8*)text, length);*/
773 XftDrawString8(scr
->xftdraw
, &xftcolor
, font
->font
.xft
,
774 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
779 } else if (font
->notFontSet
) {
780 XSetFont(scr
->display
, scr
->drawStringGC
, font
->font
.normal
->fid
);
781 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
782 XDrawString(scr
->display
, d
, scr
->drawStringGC
, x
, y
+ font
->y
,
785 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
786 XmbDrawString(scr
->display
, d
, font
->font
.set
, scr
->drawStringGC
,
787 x
, y
+ font
->y
, text
, length
);
793 WMDrawImageString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMColor
*background
,
794 WMFont
*font
, int x
, int y
, char *text
, int length
)
796 wassertr(font
!=NULL
);
798 if (font
->antialiased
) {
803 textColor
.color
.red
= color
->color
.red
;
804 textColor
.color
.green
= color
->color
.green
;
805 textColor
.color
.blue
= color
->color
.blue
;
806 textColor
.color
.alpha
= color
->alpha
;;
807 textColor
.pixel
= W_PIXEL(color
);
809 bgColor
.color
.red
= background
->color
.red
;
810 bgColor
.color
.green
= background
->color
.green
;
811 bgColor
.color
.blue
= background
->color
.blue
;
812 bgColor
.color
.alpha
= background
->alpha
;;
813 bgColor
.pixel
= W_PIXEL(background
);
816 XftDrawChange(scr
->xftdraw
, d
);
818 XftDrawRect(scr
->xftdraw
, &bgColor
, x
, y
,
819 WMWidthOfString(font
, text
, length
), font
->height
);
821 if (!font
->notFontSet
) {
826 /* Use mtext instead of text, because mbstrtowcs() alters it */
828 wtext
= (wchar_t *)wmalloc(4*length
+4);
829 len
= mbsrtowcs(wtext
, (const char **) &mtext
, length
, NULL
);
831 XftDrawString32(scr
->xftdraw
, &textColor
, font
->font
.xft
,
832 x
, y
+ font
->y
, (XftChar32
*)wtext
, len
);
833 } else if (len
==-1) {
834 wwarning(_("Conversion to widechar failed (possible invalid "
835 "multibyte sequence): '%s':(pos %d)\n"),
837 /* we can draw normal text, or we can draw as much widechar
838 * text as was already converted until the error. go figure */
839 /*XftDrawString8(scr->xftdraw, &textColor, font->font.xft,
840 x, y + font->y, (XftChar8*)text, length);*/
844 XftDrawString8(scr
->xftdraw
, &textColor
, font
->font
.xft
,
845 x
, y
+ font
->y
, (XftChar8
*)text
, length
);
850 } else if (font
->notFontSet
) {
851 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
852 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
853 XSetFont(scr
->display
, scr
->drawImStringGC
, font
->font
.normal
->fid
);
854 XDrawImageString(scr
->display
, d
, scr
->drawImStringGC
,
855 x
, y
+ font
->y
, text
, length
);
857 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
858 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
859 XmbDrawImageString(scr
->display
, d
, font
->font
.set
, scr
->drawImStringGC
,
860 x
, y
+ font
->y
, text
, length
);
868 makeFontSetOfSize(char *fontset
, int size
)
880 ptr
= strchr(fontset
, ',');
882 int count
= ptr
-fontset
;
885 wwarning(_("font description %s is too large."), fontset
);
887 memcpy(font
, fontset
, count
);
898 tmp
= wmalloc(end
+ strlen(f
) + 8);
900 sprintf(tmp
, "%s,", newfs
);
901 sprintf(tmp
+ end
+ 1, f
, size
);
903 sprintf(tmp
+ end
, f
, size
);
917 #define FONT_PROPS 14
920 char *props
[FONT_PROPS
];
925 changeFontProp(char *buf
, char *newprop
, int position
)
928 char *ptr
, *pptr
, *rptr
;
932 /* // remove warning later. or maybe not */
933 wwarning(_("Invalid font specification: '%s'\n"), buf
);
937 ptr
= pptr
= rptr
= buf
;
939 while (*ptr
&& *ptr
!=',') {
942 if (count
-1==position
+1) {
946 if (count
-1==position
) {
952 if (position
==FONT_PROPS
-1) {
957 snprintf(buf2
, 512, "%s%s%s", buf
, newprop
, rptr
);
963 getOptions(char *options
)
965 char *ptr
, *ptr2
, *str
;
969 result
= WMCreateArrayWithDestructor(2, (WMFreeDataProc
*)wfree
);
973 ptr2
= strchr(ptr
, ',');
975 WMAddToArray(result
, wstrdup(ptr
));
979 str
= wmalloc(count
+1);
980 memcpy(str
, ptr
, count
);
982 WMAddToArray(result
, str
);
992 WMCopyFontWithChanges(WMScreen
*scrPtr
, WMFont
*font
,
993 const WMFontAttributes
*changes
)
995 int index
[FONT_PROPS
], count
[FONT_PROPS
];
996 int totalProps
, i
, j
, carry
;
1004 snprintf(fname
, 512, "%s", font
->name
);
1006 fFlags
= (font
->antialiased
? WFAntialiased
: WFNotAntialiased
);
1007 fFlags
|= (font
->notFontSet
? WFNormalFont
: WFFontSet
);
1009 props
= WMCreateBagWithDestructor(1, (WMFreeDataProc
*)WMFreeArray
);
1012 for (i
=0; i
<FONT_PROPS
; i
++) {
1013 prop
= ((W_FontAttributes
*)changes
)->props
[i
];
1014 count
[i
] = index
[i
] = 0;
1016 /* No change for this property */
1018 } else if (strchr(prop
, ',')==NULL
) {
1020 changeFontProp(fname
, prop
, i
);
1022 /* Option with fallback alternatives */
1023 if ((changes
==WFAEmphasized
|| changes
==WFABoldEmphasized
) &&
1024 font
->antialiased
&& strcmp(prop
, "o,i")==0) {
1025 options
= getOptions("i,o");
1027 options
= getOptions(prop
);
1029 WMInsertInBag(props
, i
, options
);
1030 count
[i
] = WMGetArrayItemCount(options
);
1033 totalProps
= totalProps
* count
[i
];
1037 if (totalProps
== 0) {
1038 /* No options with fallback alternatives at all */
1040 return WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
1043 for (i
=0; i
<totalProps
; i
++) {
1044 for (j
=0; j
<FONT_PROPS
; j
++) {
1046 options
= WMGetFromBag(props
, j
);
1047 prop
= WMGetFromArray(options
, index
[j
]);
1049 changeFontProp(fname
, prop
, j
);
1053 result
= WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
1058 for (j
=FONT_PROPS
-1, carry
=1; j
>=0; j
--) {
1061 carry
= (index
[j
]==count
[j
]);
1062 index
[j
] %= count
[j
];
1074 // should WFANormal also set "normal" or leave it alone?
1075 static const WMFontAttributes W_FANormal
= {
1076 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", "r", "normal",
1077 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1078 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1082 static const WMFontAttributes W_FABold
= {
1083 WFAUnchanged
, WFAUnchanged
, "bold", WFAUnchanged
,
1084 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1085 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1089 static const WMFontAttributes W_FANotBold
= {
1090 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", WFAUnchanged
,
1091 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1092 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1096 static const WMFontAttributes W_FAEmphasized
= {
1097 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "o,i",
1098 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1099 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1103 static const WMFontAttributes W_FANotEmphasized
= {
1104 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "r",
1105 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1106 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1110 static const WMFontAttributes W_FABoldEmphasized
= {
1111 WFAUnchanged
, WFAUnchanged
, "bold", "o,i",
1112 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
1113 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
1117 const WMFontAttributes
*WFANormal
= &W_FANormal
;
1118 const WMFontAttributes
*WFABold
= &W_FABold
;
1119 const WMFontAttributes
*WFANotBold
= &W_FANotBold
;
1120 const WMFontAttributes
*WFAEmphasized
= &W_FAEmphasized
;
1121 const WMFontAttributes
*WFANotEmphasized
= &W_FANotEmphasized
;
1122 const WMFontAttributes
*WFABoldEmphasized
= &W_FABoldEmphasized
;