- s/sprintf/snprintf
[wmaker-crm.git] / WINGs / wfont.c
blob4fc20d48efe6ba4cb641e794b83e0229e8c134ca
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+50;
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->fontCache, 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->fontCache, 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 return NULL;
199 font->height = font->font.normal->ascent+font->font.normal->descent;
200 font->y = font->font.normal->ascent;
202 font->refCount = 1;
204 font->name = fname;
206 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
208 return font;
213 WMFont*
214 WMCreateFont(WMScreen *scrPtr, char *fontName)
216 if (scrPtr->useMultiByte)
217 return WMCreateFontSet(scrPtr, fontName);
218 else
219 return WMCreateNormalFont(scrPtr, fontName);
224 WMFont*
225 WMRetainFont(WMFont *font)
227 wassertrv(font!=NULL, NULL);
229 font->refCount++;
231 return font;
235 void
236 WMReleaseFont(WMFont *font)
238 wassertr(font!=NULL);
240 font->refCount--;
241 if (font->refCount < 1) {
242 if (font->notFontSet)
243 XFreeFont(font->screen->display, font->font.normal);
244 else {
245 XFreeFontSet(font->screen->display, font->font.set);
247 if (font->name) {
248 WMHashRemove(font->screen->fontCache, font->name);
249 wfree(font->name);
251 wfree(font);
257 unsigned int
258 WMFontHeight(WMFont *font)
260 wassertrv(font!=NULL, 0);
262 return font->height;
267 WMFont*
268 WMSystemFontOfSize(WMScreen *scrPtr, int size)
270 WMFont *font;
271 char *fontSpec;
273 fontSpec = makeFontSetOfSize(WINGsConfiguration.systemFont, size);
275 if (scrPtr->useMultiByte)
276 font = WMCreateFontSet(scrPtr, fontSpec);
277 else
278 font = WMCreateNormalFont(scrPtr, fontSpec);
280 if (!font) {
281 if (scrPtr->useMultiByte) {
282 wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
283 font = WMCreateFontSet(scrPtr, "fixed");
284 if (!font) {
285 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
287 } else {
288 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
289 font = WMCreateNormalFont(scrPtr, "fixed");
291 if (!font) {
292 wwarning(_("could not load fixed font!"));
293 wfree(fontSpec);
294 return NULL;
297 wfree(fontSpec);
299 return font;
303 WMFont*
304 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
306 WMFont *font;
307 char *fontSpec;
309 fontSpec = makeFontSetOfSize(WINGsConfiguration.boldSystemFont, size);
311 if (scrPtr->useMultiByte)
312 font = WMCreateFontSet(scrPtr, fontSpec);
313 else
314 font = WMCreateNormalFont(scrPtr, fontSpec);
316 if (!font) {
317 if (scrPtr->useMultiByte) {
318 wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
319 font = WMCreateFontSet(scrPtr, "fixed");
320 if (!font) {
321 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
323 } else {
324 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
325 font = WMCreateNormalFont(scrPtr, "fixed");
327 if (!font) {
328 wwarning(_("could not load fixed font!"));
329 wfree(fontSpec);
330 return NULL;
333 wfree(fontSpec);
335 return font;
339 XFontSet
340 WMGetFontFontSet(WMFont *font)
342 wassertrv(font!=NULL, NULL);
344 if (font->notFontSet)
345 return NULL;
346 else
347 return font->font.set;
352 WMWidthOfString(WMFont *font, char *text, int length)
354 wassertrv(font!=NULL, 0);
355 wassertrv(text!=NULL, 0);
357 if (font->notFontSet)
358 return XTextWidth(font->font.normal, text, length);
359 else {
360 XRectangle rect;
361 XRectangle AIXsucks;
363 XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
365 return rect.width;
371 void
372 WMDrawString(WMScreen *scr, Drawable d, GC gc, WMFont *font, int x, int y,
373 char *text, int length)
375 wassertr(font!=NULL);
377 if (font->notFontSet) {
378 XSetFont(scr->display, gc, font->font.normal->fid);
379 XDrawString(scr->display, d, gc, x, y + font->y, text, length);
380 } else {
381 XmbDrawString(scr->display, d, font->font.set, gc, x, y + font->y,
382 text, length);
387 void
388 WMDrawImageString(WMScreen *scr, Drawable d, GC gc, WMFont *font, int x, int y,
389 char *text, int length)
391 wassertr(font != NULL);
393 if (font->notFontSet) {
394 XSetFont(scr->display, gc, font->font.normal->fid);
395 XDrawImageString(scr->display, d, gc, x, y + font->y, text, length);
396 } else {
397 XmbDrawImageString(scr->display, d, font->font.set, gc, x, y + font->y,
398 text, length);
405 static char*
406 makeFontSetOfSize(char *fontset, int size)
408 char font[300], *f;
409 char *newfs = NULL;
410 char *ptr;
412 do {
413 char *tmp;
414 int end;
417 f = fontset;
418 ptr = strchr(fontset, ',');
419 if (ptr) {
420 int count = ptr-fontset;
422 if (count > 255) {
423 wwarning(_("font description %s is too large."), fontset);
424 } else {
425 memcpy(font, fontset, count);
426 font[count] = 0;
427 f = (char*)font;
431 if (newfs)
432 end = strlen(newfs);
433 else
434 end = 0;
436 tmp = wmalloc(end + strlen(f) + 8);
437 if (end != 0) {
438 sprintf(tmp, "%s,", newfs);
439 sprintf(tmp + end + 1, f, size);
440 } else {
441 sprintf(tmp + end, f, size);
444 if (newfs)
445 wfree(newfs);
446 newfs = tmp;
448 fontset = ptr+1;
449 } while (ptr!=NULL);
451 return newfs;
455 static void
456 changeFontProp(char *fname, char *newprop, int which)
458 char before[128], prop[128], after[128];
459 char *ptr, *bptr;
460 int part=0;
462 if(!fname || !prop)
463 return;
465 ptr = fname;
466 bptr = before;
467 while (*ptr) {
468 if(*ptr == '-') {
469 *bptr = 0;
470 if(part==which) bptr = prop;
471 else if(part==which+1) bptr = after;
472 *bptr++ = *ptr;
473 part++;
474 } else {
475 *bptr++ = *ptr;
476 } ptr++;
477 }*bptr = 0;
478 snprintf(fname, 255, "%s-%s%s", before, newprop, after);
482 WMFont *
483 WMNormalizeFont(WMScreen *scr, WMFont *font)
485 WMFont *newfont=NULL;
486 char fname[256];
488 if(!scr || !font)
489 return NULL;
491 snprintf(fname, 255, font->name);
492 changeFontProp(fname, "medium", 2);
493 changeFontProp(fname, "r", 3);
494 newfont = WMCreateNormalFont(scr, fname);
496 if(!newfont)
497 return NULL;
499 return newfont;
503 WMFont *
504 WMStrengthenFont(WMScreen *scr, WMFont *font)
506 WMFont *newfont=NULL;
507 char fname[256];
509 if(!scr || !font)
510 return NULL;
512 snprintf(fname, 255, font->name);
513 changeFontProp(fname, "bold", 2);
514 newfont = WMCreateNormalFont(scr, fname);
516 if(!newfont)
517 return NULL;
519 return newfont;
523 WMFont *
524 WMUnstrengthenFont(WMScreen *scr, WMFont *font)
526 WMFont *newfont=NULL;
527 char fname[256];
529 if(!scr || !font)
530 return NULL;
532 snprintf(fname, 255, font->name);
533 changeFontProp(fname, "medium", 2);
534 newfont = WMCreateNormalFont(scr, fname);
536 if(!newfont)
537 return NULL;
539 return newfont;
543 WMFont *
544 WMEmphasizeFont(WMScreen *scr, WMFont *font)
546 WMFont *newfont=NULL;
547 char fname[256];
549 if(!scr || !font)
550 return NULL;
552 snprintf(fname, 255, font->name);
553 changeFontProp(fname, "o", 3);
554 newfont = WMCreateNormalFont(scr, fname);
556 if(!newfont)
557 return NULL;
559 return newfont;
563 WMFont *
564 WMUnemphasizeFont(WMScreen *scr, WMFont *font)
566 WMFont *newfont=NULL;
567 char fname[256];
569 if(!scr || !font)
570 return NULL;
572 snprintf(fname, 255, font->name);
573 changeFontProp(fname, "r", 3);
574 newfont = WMCreateNormalFont(scr, fname);
576 if(!newfont)
577 return NULL;
579 return newfont;
582 WMFont *
583 WMGetFontOfSize(WMScreen *scr, WMFont *font, int size)
585 if(!scr || !font || size<1)
586 return NULL;
588 return font;