10 #include <X11/Xlocale.h>
12 static char *makeFontSetOfSize(char *fontset
, int size
);
14 /* XLFD pattern matching */
15 static char *getElementFromXLFD(const char *xlfd
, int index
)
19 if (*p
== '-' && --index
== 0) {
20 const char *end
= strchr(p
+ 1, '-');
27 memcpy(buf
, p
+ 1, len
);
36 /* XLFD pattern matching */
37 static char *generalizeXLFD(const char *xlfd
)
41 char *weight
= getElementFromXLFD(xlfd
, 3);
42 char *slant
= getElementFromXLFD(xlfd
, 4);
43 char *pxlsz
= getElementFromXLFD(xlfd
, 7);
45 #define Xstrlen(A) ((A)?strlen(A):0)
46 len
= Xstrlen(xlfd
) + Xstrlen(weight
) + Xstrlen(slant
) + Xstrlen(pxlsz
) * 2 + 60;
49 buf
= wmalloc(len
+ 1);
50 snprintf(buf
, len
+ 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
51 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*", xlfd
, weight
, slant
, pxlsz
, pxlsz
);
60 /* XLFD pattern matching */
62 W_CreateFontSetWithGuess(Display
* dpy
, char *xlfd
, char ***missing
, int *nmissing
, char **def_string
)
64 XFontSet fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
66 if (fs
!= NULL
&& *nmissing
== 0)
69 /* for non-iso8859-1 language and iso8859-1 specification
70 (this fontset is only for pattern analysis) */
73 XFreeStringList(*missing
);
74 setlocale(LC_CTYPE
, "C");
75 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
76 setlocale(LC_CTYPE
, "");
79 /* make XLFD font name for pattern analysis */
81 XFontStruct
**fontstructs
;
83 if (XFontsOfFontSet(fs
, &fontstructs
, &fontnames
) > 0)
87 xlfd
= generalizeXLFD(xlfd
);
90 XFreeStringList(*missing
);
92 XFreeFontSet(dpy
, fs
);
94 fs
= XCreateFontSet(dpy
, xlfd
, missing
, nmissing
, def_string
);
100 static char *xlfdFromFontName(char *fontName
)
102 char *systemFont
, *boldSystemFont
;
106 systemFont
= WINGsConfiguration
.systemFont
;
107 boldSystemFont
= WINGsConfiguration
.boldSystemFont
;
109 size
= WINGsConfiguration
.defaultFontSize
;
111 if (strcmp(fontName
, "SystemFont") == 0) {
113 } else if (strncmp(fontName
, "SystemFont-", 11) == 0) {
115 if (sscanf(&fontName
[11], "%i", &size
) != 1) {
116 size
= WINGsConfiguration
.defaultFontSize
;
117 wwarning(_("Invalid size specification '%s' in %s. "
118 "Using default %d\n"), &fontName
[11], fontName
, size
);
120 } else if (strcmp(fontName
, "BoldSystemFont") == 0) {
121 font
= boldSystemFont
;
122 } else if (strncmp(fontName
, "BoldSystemFont-", 15) == 0) {
123 font
= boldSystemFont
;
124 if (sscanf(&fontName
[15], "%i", &size
) != 1) {
125 size
= WINGsConfiguration
.defaultFontSize
;
126 wwarning(_("Invalid size specification '%s' in %s. "
127 "Using default %d\n"), &fontName
[15], fontName
, size
);
133 return (font
!= NULL
? makeFontSetOfSize(font
, size
) : wstrdup(fontName
));
136 WMFont
*WMCreateFontSet(WMScreen
* scrPtr
, char *fontName
)
139 Display
*display
= scrPtr
->display
;
144 XFontSetExtents
*extents
;
146 fname
= xlfdFromFontName(fontName
);
148 font
= WMHashGet(scrPtr
->fontSetCache
, fname
);
155 font
= wmalloc(sizeof(WMFont
));
156 memset(font
, 0, sizeof(WMFont
));
158 font
->notFontSet
= 0;
160 font
->screen
= scrPtr
;
162 font
->font
.set
= W_CreateFontSetWithGuess(display
, fname
, &missing
, &nmissing
, &defaultString
);
163 if (nmissing
> 0 && font
->font
.set
) {
166 wwarning(_("the following character sets are missing in %s:"), fname
);
167 for (i
= 0; i
< nmissing
; i
++) {
168 wwarning(missing
[i
]);
170 XFreeStringList(missing
);
172 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
175 if (!font
->font
.set
) {
181 extents
= XExtentsOfFontSet(font
->font
.set
);
183 font
->height
= extents
->max_logical_extent
.height
;
184 font
->y
= font
->height
- (font
->height
+ extents
->max_logical_extent
.y
);
190 assert(WMHashInsert(scrPtr
->fontSetCache
, font
->name
, font
) == NULL
);
195 WMFont
*WMCreateNormalFont(WMScreen
* scrPtr
, char *fontName
)
198 Display
*display
= scrPtr
->display
;
201 fontName
= xlfdFromFontName(fontName
);
203 if ((ptr
= strchr(fontName
, ','))) {
204 fname
= wmalloc(ptr
- fontName
+ 1);
205 strncpy(fname
, fontName
, ptr
- fontName
);
206 fname
[ptr
- fontName
] = 0;
208 fname
= wstrdup(fontName
);
213 font
= WMHashGet(scrPtr
->fontCache
, fname
);
220 font
= wmalloc(sizeof(WMFont
));
221 memset(font
, 0, sizeof(WMFont
));
223 font
->notFontSet
= 1;
225 font
->screen
= scrPtr
;
227 font
->font
.normal
= XLoadQueryFont(display
, fname
);
228 if (!font
->font
.normal
) {
233 font
->height
= font
->font
.normal
->ascent
+ font
->font
.normal
->descent
;
234 font
->y
= font
->font
.normal
->ascent
;
240 assert(WMHashInsert(scrPtr
->fontCache
, font
->name
, font
) == NULL
);
245 WMFont
*WMCreateFont(WMScreen
* scrPtr
, char *fontName
)
247 return WMCreateFontWithFlags(scrPtr
, fontName
, WFDefaultFont
);
250 WMFont
*WMCreateFontWithFlags(WMScreen
* scrPtr
, char *fontName
, WMFontFlags flags
)
252 Bool multiByte
= scrPtr
->useMultiByte
;
255 if (flags
& WFFontSet
) {
257 } else if (flags
& WFNormalFont
) {
262 font
= WMCreateFontSet(scrPtr
, fontName
);
264 font
= WMCreateNormalFont(scrPtr
, fontName
);
270 WMFont
*WMRetainFont(WMFont
* font
)
272 wassertrv(font
!= NULL
, NULL
);
279 void WMReleaseFont(WMFont
* font
)
281 wassertr(font
!= NULL
);
284 if (font
->refCount
< 1) {
285 if (font
->notFontSet
) {
286 XFreeFont(font
->screen
->display
, font
->font
.normal
);
288 XFreeFontSet(font
->screen
->display
, font
->font
.set
);
292 if (font
->notFontSet
) {
293 WMHashRemove(font
->screen
->fontCache
, font
->name
);
295 WMHashRemove(font
->screen
->fontSetCache
, font
->name
);
303 Bool
WMIsAntialiasingEnabled(WMScreen
* scrPtr
)
308 unsigned int WMFontHeight(WMFont
* font
)
310 wassertrv(font
!= NULL
, 0);
315 char *WMGetFontName(WMFont
* font
)
317 wassertrv(font
!= NULL
, NULL
);
322 WMFont
*WMDefaultSystemFont(WMScreen
* scrPtr
)
324 return WMRetainFont(scrPtr
->normalFont
);
327 WMFont
*WMDefaultBoldSystemFont(WMScreen
* scrPtr
)
329 return WMRetainFont(scrPtr
->boldFont
);
332 static WMFont
*makeSystemFontOfSize(WMScreen
* scrPtr
, int size
, Bool bold
)
337 #define WConf WINGsConfiguration
339 fontSpec
= makeFontSetOfSize(WConf
.boldSystemFont
, size
);
341 fontSpec
= makeFontSetOfSize(WConf
.systemFont
, size
);
345 if (scrPtr
->useMultiByte
) {
346 font
= WMCreateFontSet(scrPtr
, fontSpec
);
348 font
= WMCreateNormalFont(scrPtr
, fontSpec
);
352 if (scrPtr
->useMultiByte
) {
353 wwarning(_("could not load font set %s. Trying fixed."), fontSpec
);
354 font
= WMCreateFontSet(scrPtr
, "fixed");
356 font
= WMCreateFontSet(scrPtr
, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
359 wwarning(_("could not load font %s. Trying fixed."), fontSpec
);
360 font
= WMCreateNormalFont(scrPtr
, "fixed");
363 wwarning(_("could not load fixed font!"));
373 WMFont
*WMSystemFontOfSize(WMScreen
* scrPtr
, int size
)
375 return makeSystemFontOfSize(scrPtr
, size
, False
);
378 WMFont
*WMBoldSystemFontOfSize(WMScreen
* scrPtr
, int size
)
380 return makeSystemFontOfSize(scrPtr
, size
, True
);
383 XFontSet
WMGetFontFontSet(WMFont
* font
)
385 wassertrv(font
!= NULL
, NULL
);
387 if (!font
->notFontSet
&& !font
->antialiased
)
388 return font
->font
.set
;
393 int WMWidthOfString(WMFont
* font
, char *text
, int length
)
395 wassertrv(font
!= NULL
, 0);
396 wassertrv(text
!= NULL
, 0);
398 if (font
->notFontSet
) {
399 return XTextWidth(font
->font
.normal
, text
, length
);
404 XmbTextExtents(font
->font
.set
, text
, length
, &AIXsucks
, &rect
);
410 void WMDrawString(WMScreen
* scr
, Drawable d
, WMColor
* color
, WMFont
* font
, int x
, int y
, char *text
, int length
)
412 wassertr(font
!= NULL
);
414 if (font
->notFontSet
) {
415 XSetFont(scr
->display
, scr
->drawStringGC
, font
->font
.normal
->fid
);
416 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
417 XDrawString(scr
->display
, d
, scr
->drawStringGC
, x
, y
+ font
->y
, text
, length
);
419 XSetForeground(scr
->display
, scr
->drawStringGC
, W_PIXEL(color
));
420 XmbDrawString(scr
->display
, d
, font
->font
.set
, scr
->drawStringGC
, x
, y
+ font
->y
, text
, length
);
425 WMDrawImageString(WMScreen
* scr
, Drawable d
, WMColor
* color
, WMColor
* background
,
426 WMFont
* font
, int x
, int y
, char *text
, int length
)
428 wassertr(font
!= NULL
);
430 if (font
->notFontSet
) {
431 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
432 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
433 XSetFont(scr
->display
, scr
->drawImStringGC
, font
->font
.normal
->fid
);
434 XDrawImageString(scr
->display
, d
, scr
->drawImStringGC
, x
, y
+ font
->y
, text
, length
);
436 XSetForeground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(color
));
437 XSetBackground(scr
->display
, scr
->drawImStringGC
, W_PIXEL(background
));
438 XmbDrawImageString(scr
->display
, d
, font
->font
.set
, scr
->drawImStringGC
,
439 x
, y
+ font
->y
, text
, length
);
443 static char *makeFontSetOfSize(char *fontset
, int size
)
454 ptr
= strchr(fontset
, ',');
456 int count
= ptr
- fontset
;
459 wwarning(_("font description %s is too large."), fontset
);
461 memcpy(font
, fontset
, count
);
472 tmp
= wmalloc(end
+ strlen(f
) + 8);
474 sprintf(tmp
, "%s,", newfs
);
475 sprintf(tmp
+ end
+ 1, f
, size
);
477 sprintf(tmp
+ end
, f
, size
);
485 } while (ptr
!= NULL
);
490 #define FONT_PROPS 14
493 char *props
[FONT_PROPS
];
496 static void changeFontProp(char *buf
, char *newprop
, int position
)
499 char *ptr
, *pptr
, *rptr
;
503 /* // remove warning later. or maybe not */
504 wwarning(_("Invalid font specification: '%s'\n"), buf
);
508 ptr
= pptr
= rptr
= buf
;
510 while (*ptr
&& *ptr
!= ',') {
513 if (count
- 1 == position
+ 1) {
517 if (count
- 1 == position
) {
523 if (position
== FONT_PROPS
- 1) {
528 snprintf(buf2
, 512, "%s%s%s", buf
, newprop
, rptr
);
532 static WMArray
*getOptions(char *options
)
534 char *ptr
, *ptr2
, *str
;
538 result
= WMCreateArrayWithDestructor(2, (WMFreeDataProc
*) wfree
);
542 ptr2
= strchr(ptr
, ',');
544 WMAddToArray(result
, wstrdup(ptr
));
548 str
= wmalloc(count
+ 1);
549 memcpy(str
, ptr
, count
);
551 WMAddToArray(result
, str
);
559 #define WFAUnchanged (NULL)
560 /* Struct for font change operations */
561 typedef struct WMFontAttributes
{
578 WMFont
*WMCopyFontWithChanges(WMScreen
* scrPtr
, WMFont
* font
, const WMFontAttributes
* changes
)
580 int index
[FONT_PROPS
], count
[FONT_PROPS
];
581 int totalProps
, i
, j
, carry
;
589 snprintf(fname
, 512, "%s", font
->name
);
591 fFlags
= (font
->antialiased
? WFAntialiased
: WFNotAntialiased
);
592 fFlags
|= (font
->notFontSet
? WFNormalFont
: WFFontSet
);
594 props
= WMCreateBagWithDestructor(1, (WMFreeDataProc
*) WMFreeArray
);
597 for (i
= 0; i
< FONT_PROPS
; i
++) {
598 prop
= ((W_FontAttributes
*) changes
)->props
[i
];
599 count
[i
] = index
[i
] = 0;
601 /* No change for this property */
603 } else if (strchr(prop
, ',') == NULL
) {
605 changeFontProp(fname
, prop
, i
);
607 /* Option with fallback alternatives */
608 if ((changes
== WFAEmphasized
|| changes
== WFABoldEmphasized
) &&
609 font
->antialiased
&& strcmp(prop
, "o,i") == 0) {
610 options
= getOptions("i,o");
612 options
= getOptions(prop
);
614 WMInsertInBag(props
, i
, options
);
615 count
[i
] = WMGetArrayItemCount(options
);
618 totalProps
= totalProps
* count
[i
];
622 if (totalProps
== 0) {
623 /* No options with fallback alternatives at all */
625 return WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
628 for (i
= 0; i
< totalProps
; i
++) {
629 for (j
= 0; j
< FONT_PROPS
; j
++) {
631 options
= WMGetFromBag(props
, j
);
632 prop
= WMGetFromArray(options
, index
[j
]);
634 changeFontProp(fname
, prop
, j
);
638 result
= WMCreateFontWithFlags(scrPtr
, fname
, fFlags
);
643 for (j
= FONT_PROPS
- 1, carry
= 1; j
>= 0; j
--) {
646 carry
= (index
[j
] == count
[j
]);
647 index
[j
] %= count
[j
];
657 // should WFANormal also set "normal" or leave it alone?
658 static const WMFontAttributes W_FANormal
= {
659 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", "r", "normal",
660 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
661 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
664 static const WMFontAttributes W_FABold
= {
665 WFAUnchanged
, WFAUnchanged
, "bold", WFAUnchanged
,
666 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
667 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
670 static const WMFontAttributes W_FANotBold
= {
671 WFAUnchanged
, WFAUnchanged
, "medium,normal,regular", WFAUnchanged
,
672 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
673 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
676 static const WMFontAttributes W_FAEmphasized
= {
677 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "o,i",
678 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
679 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
682 static const WMFontAttributes W_FANotEmphasized
= {
683 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, "r",
684 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
685 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
688 static const WMFontAttributes W_FABoldEmphasized
= {
689 WFAUnchanged
, WFAUnchanged
, "bold", "o,i",
690 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
,
691 WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
, WFAUnchanged
694 const WMFontAttributes
*WFANormal
= &W_FANormal
;
695 const WMFontAttributes
*WFABold
= &W_FABold
;
696 const WMFontAttributes
*WFANotBold
= &W_FANotBold
;
697 const WMFontAttributes
*WFAEmphasized
= &W_FAEmphasized
;
698 const WMFontAttributes
*WFANotEmphasized
= &W_FANotEmphasized
;
699 const WMFontAttributes
*WFABoldEmphasized
= &W_FABoldEmphasized
;