- API change in WINGs for WMDraw*String().
[wmaker-crm.git] / WINGs / wfont.c
blob050f3c02d5fd308664a3f11dcd23e9e64f608c3c
2 #include "WINGsP.h"
3 #include "wconfig.h"
6 #include <wraster.h>
7 #include <assert.h>
8 #include <X11/Xlocale.h>
10 static char *makeFontSetOfSize(char *fontset, int size);
14 /* XLFD pattern matching */
15 static char*
16 xlfd_get_element (const char *xlfd, int index)
18 const char *p = xlfd;
19 while (*p != 0) {
20 if (*p == '-' && --index == 0) {
21 const char *end = strchr(p + 1, '-');
22 char *buf;
23 size_t len;
24 if (end == 0) end = p + strlen(p);
25 len = end - (p + 1);
26 buf = wmalloc(len);
27 memcpy(buf, p + 1, len);
28 buf[len] = 0;
29 return buf;
31 p++;
33 return strdup("*");
36 /* XLFD pattern matching */
37 static char*
38 generalize_xlfd (const char *xlfd)
40 char *buf;
41 int len;
42 char *weight = xlfd_get_element(xlfd, 3);
43 char *slant = xlfd_get_element(xlfd, 4);
44 char *pxlsz = xlfd_get_element(xlfd, 7);
46 #define Xstrlen(A) ((A)?strlen(A):0)
47 len = Xstrlen(xlfd)+Xstrlen(weight)+Xstrlen(slant)+Xstrlen(pxlsz)*2+60;
48 #undef Xstrlen
50 buf = wmalloc(len + 1);
51 snprintf(buf, len + 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
52 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
53 xlfd, weight, slant, pxlsz, pxlsz);
55 wfree(pxlsz);
56 wfree(slant);
57 wfree(weight);
59 return buf;
62 /* XLFD pattern matching */
63 static XFontSet
64 W_CreateFontSetWithGuess(Display *dpy, char *xlfd, char ***missing,
65 int *nmissing, char **def_string)
67 XFontSet fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
69 if (fs != NULL && *nmissing == 0) return fs;
71 /* for non-iso8859-1 language and iso8859-1 specification
72 (this fontset is only for pattern analysis) */
73 if (fs == NULL) {
74 if (*nmissing != 0) XFreeStringList(*missing);
75 setlocale(LC_CTYPE, "C");
76 fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
77 setlocale(LC_CTYPE, "");
80 /* make XLFD font name for pattern analysis */
81 if (fs != NULL) {
82 XFontStruct **fontstructs;
83 char **fontnames;
84 if (XFontsOfFontSet(fs, &fontstructs, &fontnames) > 0)
85 xlfd = fontnames[0];
88 xlfd = generalize_xlfd (xlfd);
90 if (*nmissing != 0) XFreeStringList(*missing);
91 if (fs != NULL) XFreeFontSet(dpy, fs);
93 fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string);
95 wfree(xlfd);
96 return fs;
99 WMFont*
100 WMCreateFontSet(WMScreen *scrPtr, char *fontName)
102 WMFont *font;
103 Display *display = scrPtr->display;
104 char **missing;
105 int nmissing = 0;
106 char *defaultString;
107 XFontSetExtents *extents;
109 font = WMHashGet(scrPtr->fontSetCache, fontName);
110 if (font) {
111 WMRetainFont(font);
112 return font;
115 font = malloc(sizeof(WMFont));
116 if (!font)
117 return NULL;
118 memset(font, 0, sizeof(WMFont));
120 font->notFontSet = 0;
122 font->screen = scrPtr;
124 font->font.set = W_CreateFontSetWithGuess(display, fontName, &missing,
125 &nmissing, &defaultString);
126 if (nmissing > 0 && font->font.set) {
127 int i;
129 wwarning(_("the following character sets are missing in %s:"),
130 fontName);
131 for (i = 0; i < nmissing; i++) {
132 wwarning(missing[i]);
134 XFreeStringList(missing);
135 if (defaultString)
136 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
137 defaultString);
139 if (!font->font.set) {
140 wfree(font);
141 return NULL;
144 extents = XExtentsOfFontSet(font->font.set);
146 font->height = extents->max_logical_extent.height;
147 font->y = font->height - (font->height + extents->max_logical_extent.y);
149 font->refCount = 1;
151 font->name = wstrdup(fontName);
153 assert(WMHashInsert(scrPtr->fontSetCache, font->name, font)==NULL);
155 return font;
160 WMFont*
161 WMCreateNormalFont(WMScreen *scrPtr, char *fontName)
163 WMFont *font;
164 Display *display = scrPtr->display;
165 char *fname, *ptr;
167 if ((ptr = strchr(fontName, ','))) {
168 fname = wmalloc(ptr - fontName + 1);
169 strncpy(fname, fontName, ptr - fontName);
170 fname[ptr - fontName] = 0;
171 } else {
172 fname = wstrdup(fontName);
175 font = WMHashGet(scrPtr->fontCache, fname);
176 if (font) {
177 WMRetainFont(font);
178 wfree(fname);
179 return font;
182 font = malloc(sizeof(WMFont));
183 if (!font) {
184 wfree(fname);
185 return NULL;
187 memset(font, 0, sizeof(WMFont));
189 font->notFontSet = 1;
191 font->screen = scrPtr;
193 font->font.normal = XLoadQueryFont(display, fname);
194 if (!font->font.normal) {
195 wfree(font);
196 wfree(fname);
197 return NULL;
200 font->height = font->font.normal->ascent+font->font.normal->descent;
201 font->y = font->font.normal->ascent;
203 font->refCount = 1;
205 font->name = fname;
207 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
209 return font;
214 WMFont*
215 WMCreateFont(WMScreen *scrPtr, char *fontName)
217 if (scrPtr->useMultiByte)
218 return WMCreateFontSet(scrPtr, fontName);
219 else
220 return WMCreateNormalFont(scrPtr, fontName);
225 WMFont*
226 WMRetainFont(WMFont *font)
228 wassertrv(font!=NULL, NULL);
230 font->refCount++;
232 return font;
236 void
237 WMReleaseFont(WMFont *font)
239 wassertr(font!=NULL);
241 font->refCount--;
242 if (font->refCount < 1) {
243 if (font->notFontSet)
244 XFreeFont(font->screen->display, font->font.normal);
245 else {
246 XFreeFontSet(font->screen->display, font->font.set);
248 if (font->name) {
249 if (font->notFontSet) {
250 WMHashRemove(font->screen->fontCache, font->name);
251 } else {
252 WMHashRemove(font->screen->fontSetCache, font->name);
254 wfree(font->name);
256 wfree(font);
262 unsigned int
263 WMFontHeight(WMFont *font)
265 wassertrv(font!=NULL, 0);
267 return font->height;
271 WMFont*
272 WMDefaultSystemFont(WMScreen *scrPtr)
274 return WMRetainFont(scrPtr->normalFont);
278 WMFont*
279 WMDefaultBoldSystemFont(WMScreen *scrPtr)
281 return WMRetainFont(scrPtr->boldFont);
285 WMFont*
286 WMSystemFontOfSize(WMScreen *scrPtr, int size)
288 WMFont *font;
289 char *fontSpec;
291 fontSpec = makeFontSetOfSize(WINGsConfiguration.systemFont, size);
293 if (scrPtr->useMultiByte)
294 font = WMCreateFontSet(scrPtr, fontSpec);
295 else
296 font = WMCreateNormalFont(scrPtr, fontSpec);
298 if (!font) {
299 if (scrPtr->useMultiByte) {
300 wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
301 font = WMCreateFontSet(scrPtr, "fixed");
302 if (!font) {
303 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
305 } else {
306 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
307 font = WMCreateNormalFont(scrPtr, "fixed");
309 if (!font) {
310 wwarning(_("could not load fixed font!"));
311 wfree(fontSpec);
312 return NULL;
315 wfree(fontSpec);
317 return font;
321 WMFont*
322 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
324 WMFont *font;
325 char *fontSpec;
327 fontSpec = makeFontSetOfSize(WINGsConfiguration.boldSystemFont, size);
329 if (scrPtr->useMultiByte)
330 font = WMCreateFontSet(scrPtr, fontSpec);
331 else
332 font = WMCreateNormalFont(scrPtr, fontSpec);
334 if (!font) {
335 if (scrPtr->useMultiByte) {
336 wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
337 font = WMCreateFontSet(scrPtr, "fixed");
338 if (!font) {
339 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
341 } else {
342 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
343 font = WMCreateNormalFont(scrPtr, "fixed");
345 if (!font) {
346 wwarning(_("could not load fixed font!"));
347 wfree(fontSpec);
348 return NULL;
351 wfree(fontSpec);
353 return font;
357 XFontSet
358 WMGetFontFontSet(WMFont *font)
360 wassertrv(font!=NULL, NULL);
362 if (font->notFontSet)
363 return NULL;
364 else
365 return font->font.set;
370 WMWidthOfString(WMFont *font, char *text, int length)
372 wassertrv(font!=NULL, 0);
373 wassertrv(text!=NULL, 0);
375 if (font->notFontSet)
376 return XTextWidth(font->font.normal, text, length);
377 else {
378 XRectangle rect;
379 XRectangle AIXsucks;
381 XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
383 return rect.width;
389 void
390 WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font,
391 int x, int y, char *text, int length)
393 wassertr(font!=NULL);
395 XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color));
396 if (font->notFontSet) {
397 XSetFont(scr->display, scr->drawStringGC, font->font.normal->fid);
398 XDrawString(scr->display, d, scr->drawStringGC, x, y + font->y, text,
399 length);
400 } else {
401 XmbDrawString(scr->display, d, font->font.set, scr->drawStringGC,
402 x, y + font->y, text, length);
407 void
408 WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background,
409 WMFont *font, int x, int y, char *text, int length)
411 wassertr(font != NULL);
413 XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color));
414 XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background));
415 if (font->notFontSet) {
416 XSetFont(scr->display, scr->drawImStringGC, font->font.normal->fid);
417 XDrawImageString(scr->display, d, scr->drawImStringGC, x, y + font->y,
418 text, length);
419 } else {
420 XmbDrawImageString(scr->display, d, font->font.set, scr->drawImStringGC,
421 x, y + font->y, text, length);
428 static char*
429 makeFontSetOfSize(char *fontset, int size)
431 char font[300], *f;
432 char *newfs = NULL;
433 char *ptr;
435 do {
436 char *tmp;
437 int end;
440 f = fontset;
441 ptr = strchr(fontset, ',');
442 if (ptr) {
443 int count = ptr-fontset;
445 if (count > 255) {
446 wwarning(_("font description %s is too large."), fontset);
447 } else {
448 memcpy(font, fontset, count);
449 font[count] = 0;
450 f = (char*)font;
454 if (newfs)
455 end = strlen(newfs);
456 else
457 end = 0;
459 tmp = wmalloc(end + strlen(f) + 8);
460 if (end != 0) {
461 sprintf(tmp, "%s,", newfs);
462 sprintf(tmp + end + 1, f, size);
463 } else {
464 sprintf(tmp + end, f, size);
467 if (newfs)
468 wfree(newfs);
469 newfs = tmp;
471 fontset = ptr+1;
472 } while (ptr!=NULL);
474 return newfs;
478 static void
479 changeFontProp(char *fname, char *newprop, int which)
481 char before[128], prop[128], after[128];
482 char *ptr, *bptr;
483 int part=0;
485 if(!fname || !prop)
486 return;
488 ptr = fname;
489 bptr = before;
490 while (*ptr) {
491 if(*ptr == '-') {
492 *bptr = 0;
493 if(part==which)
494 bptr = prop;
495 else if(part==which+1)
496 bptr = after;
497 *bptr++ = *ptr;
498 part++;
499 } else {
500 *bptr++ = *ptr;
502 ptr++;
504 *bptr = 0;
505 snprintf(fname, 255, "%s-%s%s", before, newprop, after);
509 WMFont*
510 WMNormalizeFont(WMScreen *scr, WMFont *font)
512 WMFont *newfont=NULL;
513 char fname[256];
515 if(!scr || !font)
516 return NULL;
518 snprintf(fname, 255, font->name);
519 changeFontProp(fname, "medium", 2);
520 changeFontProp(fname, "r", 3);
521 newfont = WMCreateNormalFont(scr, fname);
523 if(!newfont)
524 return NULL;
526 return newfont;
530 WMFont*
531 WMStrengthenFont(WMScreen *scr, WMFont *font)
533 WMFont *newfont=NULL;
534 char fname[256];
536 if(!scr || !font)
537 return NULL;
539 snprintf(fname, 255, font->name);
540 changeFontProp(fname, "bold", 2);
541 newfont = WMCreateNormalFont(scr, fname);
543 if(!newfont)
544 return NULL;
546 return newfont;
550 WMFont*
551 WMUnstrengthenFont(WMScreen *scr, WMFont *font)
553 WMFont *newfont=NULL;
554 char fname[256];
556 if(!scr || !font)
557 return NULL;
559 snprintf(fname, 255, font->name);
560 changeFontProp(fname, "medium", 2);
561 newfont = WMCreateNormalFont(scr, fname);
563 if(!newfont)
564 return NULL;
566 return newfont;
570 WMFont*
571 WMEmphasizeFont(WMScreen *scr, WMFont *font)
573 WMFont *newfont=NULL;
574 char fname[256];
576 if(!scr || !font)
577 return NULL;
579 snprintf(fname, 255, font->name);
580 changeFontProp(fname, "o", 3);
581 newfont = WMCreateNormalFont(scr, fname);
583 if(!newfont)
584 return NULL;
586 return newfont;
590 WMFont*
591 WMUnemphasizeFont(WMScreen *scr, WMFont *font)
593 WMFont *newfont=NULL;
594 char fname[256];
596 if(!scr || !font)
597 return NULL;
599 snprintf(fname, 255, font->name);
600 changeFontProp(fname, "r", 3);
601 newfont = WMCreateNormalFont(scr, fname);
603 if(!newfont)
604 return NULL;
606 return newfont;
610 WMFont*
611 WMGetFontOfSize(WMScreen *scr, WMFont *font, int size)
613 if(!scr || !font || size<1)
614 return NULL;
616 return font;