11 #include <X11/Xlocale.h>
14 static char *makeFontSetOfSize(char *fontset
, int size
);
17 /* XLFD pattern matching */
19 getElementFromXLFD(const char *xlfd
, int index
)
23 if (*p
== '-' && --index
== 0) {
24 const char *end
= strchr(p
+ 1, '-');
27 if (end
== 0) end
= p
+ strlen(p
);
30 memcpy(buf
, p
+ 1, len
);
40 /* XLFD pattern matching */
42 generalizeXLFD(const char *xlfd
)
46 char *weight
= getElementFromXLFD(xlfd
, 3);
47 char *slant
= getElementFromXLFD(xlfd
, 4);
48 char *pxlsz
= getElementFromXLFD(xlfd
, 7);
50 #define Xstrlen(A) ((A)?strlen(A):0)
51 len
= Xstrlen(xlfd
)+Xstrlen(weight
)+Xstrlen(slant
)+Xstrlen(pxlsz
)*2+60;
54 buf
= wmalloc(len
+ 1);
55 snprintf(buf
, len
+ 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
56 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
57 xlfd
, weight
, slant
, pxlsz
, pxlsz
);
66 /* XLFD pattern matching */
68 W_CreateFontSetWithGuess(Display
*dpy
, char *xlfd
, char ***missing
,
69 int *nmissing
, char **def_string
)
71 XFontSet fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
73 if (fs
!= NULL
&& *nmissing
== 0) return fs
;
75 /* for non-iso8859-1 language and iso8859-1 specification
76 (this fontset is only for pattern analysis) */
78 if (*nmissing
!= 0) XFreeStringList(*missing
);
79 setlocale(LC_CTYPE
, "C");
80 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
81 setlocale(LC_CTYPE
, "");
84 /* make XLFD font name for pattern analysis */
86 XFontStruct
**fontstructs
;
88 if (XFontsOfFontSet(fs
, &fontstructs
, &fontnames
) > 0)
92 xlfd
= generalizeXLFD(xlfd
);
94 if (*nmissing
!= 0) XFreeStringList(*missing
);
95 if (fs
!= NULL
) XFreeFontSet(dpy
, fs
);
97 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
105 xlfdFromFontName(char *fontName
)
107 char *systemFont
, *boldSystemFont
;
111 systemFont
= WINGsConfiguration
.systemFont
;
112 boldSystemFont
= WINGsConfiguration
.boldSystemFont
;
114 size
= WINGsConfiguration
.defaultFontSize
;
116 if (strcmp(fontName
, "SystemFont")==0) {
118 } else if (strncmp(fontName
, "SystemFont-", 11)==0) {
120 if (sscanf(&fontName
[11], "%i", &size
)!=1) {
121 size
= WINGsConfiguration
.defaultFontSize
;
122 wwarning(_("Invalid size specification '%s' in %s. "
123 "Using default %d\n"), &fontName
[11], fontName
, size
);
125 } else if (strcmp(fontName
, "BoldSystemFont")==0) {
126 font
= boldSystemFont
;
127 } else if (strncmp(fontName
, "BoldSystemFont-", 15)==0) {
128 font
= boldSystemFont
;
129 if (sscanf(&fontName
[15], "%i", &size
)!=1) {
130 size
= WINGsConfiguration
.defaultFontSize
;
131 wwarning(_("Invalid size specification '%s' in %s. "
132 "Using default %d\n"), &fontName
[15], fontName
, size
);
138 return (font
!=NULL
? makeFontSetOfSize(font
, size
) : wstrdup(fontName
));
143 WMCreateFontSet(WMScreen
*scrPtr
, char *fontName
)
146 Display
*display
= scrPtr
->display
;
151 XFontSetExtents
*extents
;
153 fname
= xlfdFromFontName(fontName
);
155 font
= WMHashGet(scrPtr
->fontSetCache
, fname
);
162 font
= wmalloc(sizeof(WMFont
));
163 memset(font
, 0, sizeof(WMFont
));
165 font
->notFontSet
= 0;
167 font
->screen
= scrPtr
;
169 font
->font
.set
= W_CreateFontSetWithGuess(display
, fname
, &missing
,
170 &nmissing
, &defaultString
);
171 if (nmissing
> 0 && font
->font
.set
) {
174 wwarning(_("the following character sets are missing in %s:"), fname
);
175 for (i
= 0; i
< nmissing
; i
++) {
176 wwarning(missing
[i
]);
178 XFreeStringList(missing
);
180 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
183 if (!font
->font
.set
) {
189 extents
= XExtentsOfFontSet(font
->font
.set
);
191 font
->height
= extents
->max_logical_extent
.height
;
192 font
->y
= font
->height
- (font
->height
+ extents
->max_logical_extent
.y
);
198 assert(WMHashInsert(scrPtr
->fontSetCache
, font
->name
, font
)==NULL
);
206 WMCreateNormalFont(WMScreen
*scrPtr
, char *fontName
)
209 Display
*display
= scrPtr
->display
;
212 fontName
= xlfdFromFontName(fontName
);
214 if ((ptr
= strchr(fontName
, ','))) {
215 fname
= wmalloc(ptr
- fontName
+ 1);
216 strncpy(fname
, fontName
, ptr
- fontName
);
217 fname
[ptr
- fontName
] = 0;
219 fname
= wstrdup(fontName
);
224 font
= WMHashGet(scrPtr
->fontCache
, fname
);
231 font
= wmalloc(sizeof(WMFont
));
232 memset(font
, 0, sizeof(WMFont
));
234 font
->notFontSet
= 1;
236 font
->screen
= scrPtr
;
238 font
->font
.normal
= XLoadQueryFont(display
, fname
);
239 if (!font
->font
.normal
) {
244 font
->height
= font
->font
.normal
->ascent
+font
->font
.normal
->descent
;
245 font
->y
= font
->font
.normal
->ascent
;
251 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
)==NULL
);
258 WMCreateFont(WMScreen
*scrPtr
, char *fontName
)
260 return WMCreateFontWithFlags(scrPtr
, fontName
, WFDefaultFont
);
265 WMCreateFontWithFlags(WMScreen
*scrPtr
, char *fontName
, WMFontFlags flags
)
267 Bool multiByte
= scrPtr
->useMultiByte
;
270 if (flags
& WFFontSet
) {
272 } else if (flags
& WFNormalFont
) {
277 font
= WMCreateFontSet(scrPtr
, fontName
);
279 font
= WMCreateNormalFont(scrPtr
, fontName
);
287 WMRetainFont(WMFont
*font
)
289 wassertrv(font
!=NULL
, NULL
);
298 WMReleaseFont(WMFont
*font
)
300 wassertr(font
!=NULL
);
303 if (font
->refCount
< 1) {
304 if (font
->notFontSet
) {
305 XFreeFont(font
->screen
->display
, font
->font
.normal
);
307 XFreeFontSet(font
->screen
->display
, font
->font
.set
);
311 if (font
->notFontSet
) {
312 WMHashRemove(font
->screen
->fontCache
, font
->name
);
314 WMHashRemove(font
->screen
->fontSetCache
, font
->name
);
324 WMIsAntialiasingEnabled(WMScreen
*scrPtr
)
331 WMFontHeight(WMFont
*font
)
333 wassertrv(font
!=NULL
, 0);
340 WMGetFontName(WMFont
*font
)
342 wassertrv(font
!=NULL
, NULL
);
349 WMDefaultSystemFont(WMScreen
*scrPtr
)
351 return WMRetainFont(scrPtr
->normalFont
);
356 WMDefaultBoldSystemFont(WMScreen
*scrPtr
)
358 return WMRetainFont(scrPtr
->boldFont
);
363 makeSystemFontOfSize(WMScreen
*scrPtr
, int size
, Bool bold
)
368 #define WConf WINGsConfiguration
370 fontSpec
= makeFontSetOfSize(WConf
.boldSystemFont
, size
);
372 fontSpec
= makeFontSetOfSize(WConf
.systemFont
, size
);
376 if (scrPtr
->useMultiByte
) {
377 font
= WMCreateFontSet(scrPtr
, fontSpec
);
379 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
383 if (scrPtr
->useMultiByte
) {
384 wwarning(_("could not load font set %s. Trying fixed."), fontSpec
);
385 font
= WMCreateFontSet(scrPtr
, "fixed");
387 font
= WMCreateFontSet(scrPtr
, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
390 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
391 font
= WMCreateNormalFont(scrPtr
, "fixed");
394 wwarning(_("could not load fixed font!"));
406 WMSystemFontOfSize(WMScreen
*scrPtr
, int size
)
408 return makeSystemFontOfSize(scrPtr
, size
, False
);
413 WMBoldSystemFontOfSize(WMScreen
*scrPtr
, int size
)
415 return makeSystemFontOfSize(scrPtr
, size
, True
);
420 WMGetFontFontSet(WMFont
*font
)
422 wassertrv(font
!=NULL
, NULL
);
424 if (!font
->notFontSet
&& !font
->antialiased
)
425 return font
->font
.set
;
432 WMWidthOfString(WMFont
*font
, char *text
, int length
)
434 wassertrv(font
!=NULL
, 0);
435 wassertrv(text
!=NULL
, 0);
437 if (font
->notFontSet
) {
438 return XTextWidth(font
->font
.normal
, text
, length
);
443 XmbTextExtents(font
->font
.set
, text
, length
, &AIXsucks
, &rect
);
452 WMDrawString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMFont
*font
,
453 int x
, int y
, char *text
, int length
)
455 wassertr(font
!=NULL
);
457 if (font
->notFontSet
) {
458 XSetFont(scr
->display
, scr
->drawStringGC
, font
->font
.normal
->fid
);
459 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
460 XDrawString(scr
->display
, d
, scr
->drawStringGC
, x
, y
+ font
->y
,
463 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
464 XmbDrawString(scr
->display
, d
, font
->font
.set
, scr
->drawStringGC
,
465 x
, y
+ font
->y
, text
, length
);
471 WMDrawImageString(WMScreen
*scr
, Drawable d
, WMColor
*color
, WMColor
*background
,
472 WMFont
*font
, int x
, int y
, char *text
, int length
)
474 wassertr(font
!=NULL
);
476 if (font
->notFontSet
) {
477 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
478 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
479 XSetFont(scr
->display
, scr
->drawImStringGC
, font
->font
.normal
->fid
);
480 XDrawImageString(scr
->display
, d
, scr
->drawImStringGC
,
481 x
, y
+ font
->y
, text
, length
);
483 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
484 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
485 XmbDrawImageString(scr
->display
, d
, font
->font
.set
, scr
->drawImStringGC
,
486 x
, y
+ font
->y
, text
, length
);
494 makeFontSetOfSize(char *fontset
, int size
)
506 ptr
= strchr(fontset
, ',');
508 int count
= ptr
-fontset
;
511 wwarning(_("font description %s is too large."), fontset
);
513 memcpy(font
, fontset
, count
);
524 tmp
= wmalloc(end
+ strlen(f
) + 8);
526 sprintf(tmp
, "%s,", newfs
);
527 sprintf(tmp
+ end
+ 1, f
, size
);
529 sprintf(tmp
+ end
, f
, size
);
543 #define FONT_PROPS 14
546 char *props
[FONT_PROPS
];
551 changeFontProp(char *buf
, char *newprop
, int position
)
554 char *ptr
, *pptr
, *rptr
;
558 /* // remove warning later. or maybe not */
559 wwarning(_("Invalid font specification: '%s'\n"), buf
);
563 ptr
= pptr
= rptr
= buf
;
565 while (*ptr
&& *ptr
!=',') {
568 if (count
-1==position
+1) {
572 if (count
-1==position
) {
578 if (position
==FONT_PROPS
-1) {
583 snprintf(buf2
, 512, "%s%s%s", buf
, newprop
, rptr
);
589 getOptions(char *options
)
591 char *ptr
, *ptr2
, *str
;
595 result
= WMCreateArrayWithDestructor(2, (WMFreeDataProc
*)wfree
);
599 ptr2
= strchr(ptr
, ',');
601 WMAddToArray(result
, wstrdup(ptr
));
605 str
= wmalloc(count
+1);
606 memcpy(str
, ptr
, count
);
608 WMAddToArray(result
, str
);
617 #define WFAUnchanged (NULL)
618 /* Struct for font change operations */
619 typedef struct WMFontAttributes
{
637 WMCopyFontWithChanges(WMScreen
*scrPtr
, WMFont
*font
,
638 const WMFontAttributes
*changes
)
640 int index
[FONT_PROPS
], count
[FONT_PROPS
];
641 int totalProps
, i
, j
, carry
;
649 snprintf(fname
, 512, "%s", font
->name
);
651 fFlags
= (font
->antialiased
? WFAntialiased
: WFNotAntialiased
);
652 fFlags
|= (font
->notFontSet
? WFNormalFont
: WFFontSet
);
654 props
= WMCreateBagWithDestructor(1, (WMFreeDataProc
*)WMFreeArray
);
657 for (i
=0; i
<FONT_PROPS
; i
++) {
658 prop
= ((W_FontAttributes
*)changes
)->props
[i
];
659 count
[i
] = index
[i
] = 0;
661 /* No change for this property */
663 } else if (strchr(prop
, ',')==NULL
) {
665 changeFontProp(fname
, prop
, i
);
667 /* Option with fallback alternatives */
668 if ((changes
==WFAEmphasized
|| changes
==WFABoldEmphasized
) &&
669 font
->antialiased
&& strcmp(prop
, "o,i")==0) {
670 options
= getOptions("i,o");
672 options
= getOptions(prop
);
674 WMInsertInBag(props
, i
, options
);
675 count
[i
] = WMGetArrayItemCount(options
);
678 totalProps
= totalProps
* count
[i
];
682 if (totalProps
== 0) {
683 /* No options with fallback alternatives at all */
685 return WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
688 for (i
=0; i
<totalProps
; i
++) {
689 for (j
=0; j
<FONT_PROPS
; j
++) {
691 options
= WMGetFromBag(props
, j
);
692 prop
= WMGetFromArray(options
, index
[j
]);
694 changeFontProp(fname
, prop
, j
);
698 result
= WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
703 for (j
=FONT_PROPS
-1, carry
=1; j
>=0; j
--) {
706 carry
= (index
[j
]==count
[j
]);
707 index
[j
] %= count
[j
];
717 // should WFANormal also set "normal" or leave it alone?
718 static const WMFontAttributes W_FANormal
= {
719 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", "r", "normal",
720 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
721 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
725 static const WMFontAttributes W_FABold
= {
726 WFAUnchanged
, WFAUnchanged
, "bold", WFAUnchanged
,
727 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
728 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
732 static const WMFontAttributes W_FANotBold
= {
733 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", WFAUnchanged
,
734 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
735 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
739 static const WMFontAttributes W_FAEmphasized
= {
740 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "o,i",
741 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
742 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
746 static const WMFontAttributes W_FANotEmphasized
= {
747 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "r",
748 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
749 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
753 static const WMFontAttributes W_FABoldEmphasized
= {
754 WFAUnchanged
, WFAUnchanged
, "bold", "o,i",
755 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
756 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
760 const WMFontAttributes
*WFANormal
= &W_FANormal
;
761 const WMFontAttributes
*WFABold
= &W_FABold
;
762 const WMFontAttributes
*WFANotBold
= &W_FANotBold
;
763 const WMFontAttributes
*WFAEmphasized
= &W_FAEmphasized
;
764 const WMFontAttributes
*WFANotEmphasized
= &W_FANotEmphasized
;
765 const WMFontAttributes
*WFABoldEmphasized
= &W_FABoldEmphasized
;