changed indentation to use spaces only
[wmaker-crm.git] / WINGs / wfont_noxft.c
blobaf7990b062ac1d550f6a66435db9901af64b3e9d
3 #include "wconfig.h"
5 #ifndef XFT
7 #include "WINGsP.h"
9 #include <wraster.h>
10 #include <assert.h>
11 #include <X11/Xlocale.h>
14 static char *makeFontSetOfSize(char *fontset, int size);
17 /* XLFD pattern matching */
18 static char*
19 getElementFromXLFD(const char *xlfd, int index)
21 const char *p = xlfd;
22 while (*p != 0) {
23 if (*p == '-' && --index == 0) {
24 const char *end = strchr(p + 1, '-');
25 char *buf;
26 size_t len;
27 if (end == 0) end = p + strlen(p);
28 len = end - (p + 1);
29 buf = wmalloc(len);
30 memcpy(buf, p + 1, len);
31 buf[len] = 0;
32 return buf;
34 p++;
36 return strdup("*");
40 /* XLFD pattern matching */
41 static char*
42 generalizeXLFD(const char *xlfd)
44 char *buf;
45 int len;
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;
52 #undef Xstrlen
54 buf = wmalloc(len + 1);
55 snprintf(buf, len + 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*,"
56 "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*",
57 xlfd, weight, slant, pxlsz, pxlsz);
59 wfree(pxlsz);
60 wfree(slant);
61 wfree(weight);
63 return buf;
66 /* XLFD pattern matching */
67 static XFontSet
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) */
77 if (fs == NULL) {
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 */
85 if (fs != NULL) {
86 XFontStruct **fontstructs;
87 char **fontnames;
88 if (XFontsOfFontSet(fs, &fontstructs, &fontnames) > 0)
89 xlfd = 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);
99 wfree(xlfd);
100 return fs;
104 static char*
105 xlfdFromFontName(char *fontName)
107 char *systemFont, *boldSystemFont;
108 char *font;
109 int size;
111 systemFont = WINGsConfiguration.systemFont;
112 boldSystemFont = WINGsConfiguration.boldSystemFont;
114 size = WINGsConfiguration.defaultFontSize;
116 if (strcmp(fontName, "SystemFont")==0) {
117 font = systemFont;
118 } else if (strncmp(fontName, "SystemFont-", 11)==0) {
119 font = systemFont;
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);
134 } else {
135 font = NULL;
138 return (font!=NULL ? makeFontSetOfSize(font, size) : wstrdup(fontName));
142 WMFont*
143 WMCreateFontSet(WMScreen *scrPtr, char *fontName)
145 WMFont *font;
146 Display *display = scrPtr->display;
147 char **missing;
148 int nmissing = 0;
149 char *defaultString;
150 char *fname;
151 XFontSetExtents *extents;
153 fname = xlfdFromFontName(fontName);
155 font = WMHashGet(scrPtr->fontSetCache, fname);
156 if (font) {
157 WMRetainFont(font);
158 wfree(fname);
159 return font;
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) {
172 int i;
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);
179 if (defaultString)
180 wwarning(_("the string \"%s\" will be used in place of any characters from those sets."),
181 defaultString);
183 if (!font->font.set) {
184 wfree(font);
185 wfree(fname);
186 return NULL;
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);
194 font->refCount = 1;
196 font->name = fname;
198 assert(WMHashInsert(scrPtr->fontSetCache, font->name, font)==NULL);
200 return font;
205 WMFont*
206 WMCreateNormalFont(WMScreen *scrPtr, char *fontName)
208 WMFont *font;
209 Display *display = scrPtr->display;
210 char *fname, *ptr;
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;
218 } else {
219 fname = wstrdup(fontName);
222 wfree(fontName);
224 font = WMHashGet(scrPtr->fontCache, fname);
225 if (font) {
226 WMRetainFont(font);
227 wfree(fname);
228 return font;
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) {
240 wfree(font);
241 wfree(fname);
242 return NULL;
244 font->height = font->font.normal->ascent+font->font.normal->descent;
245 font->y = font->font.normal->ascent;
247 font->refCount = 1;
249 font->name = fname;
251 assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL);
253 return font;
257 WMFont*
258 WMCreateFont(WMScreen *scrPtr, char *fontName)
260 return WMCreateFontWithFlags(scrPtr, fontName, WFDefaultFont);
264 WMFont*
265 WMCreateFontWithFlags(WMScreen *scrPtr, char *fontName, WMFontFlags flags)
267 Bool multiByte = scrPtr->useMultiByte;
268 WMFont *font;
270 if (flags & WFFontSet) {
271 multiByte = True;
272 } else if (flags & WFNormalFont) {
273 multiByte = False;
276 if (multiByte) {
277 font = WMCreateFontSet(scrPtr, fontName);
278 } else {
279 font = WMCreateNormalFont(scrPtr, fontName);
282 return font;
286 WMFont*
287 WMRetainFont(WMFont *font)
289 wassertrv(font!=NULL, NULL);
291 font->refCount++;
293 return font;
297 void
298 WMReleaseFont(WMFont *font)
300 wassertr(font!=NULL);
302 font->refCount--;
303 if (font->refCount < 1) {
304 if (font->notFontSet) {
305 XFreeFont(font->screen->display, font->font.normal);
306 } else {
307 XFreeFontSet(font->screen->display, font->font.set);
310 if (font->name) {
311 if (font->notFontSet) {
312 WMHashRemove(font->screen->fontCache, font->name);
313 } else {
314 WMHashRemove(font->screen->fontSetCache, font->name);
316 wfree(font->name);
318 wfree(font);
323 Bool
324 WMIsAntialiasingEnabled(WMScreen *scrPtr)
326 return False;
330 unsigned int
331 WMFontHeight(WMFont *font)
333 wassertrv(font!=NULL, 0);
335 return font->height;
339 char*
340 WMGetFontName(WMFont *font)
342 wassertrv(font!=NULL, NULL);
344 return font->name;
348 WMFont*
349 WMDefaultSystemFont(WMScreen *scrPtr)
351 return WMRetainFont(scrPtr->normalFont);
355 WMFont*
356 WMDefaultBoldSystemFont(WMScreen *scrPtr)
358 return WMRetainFont(scrPtr->boldFont);
362 static WMFont*
363 makeSystemFontOfSize(WMScreen *scrPtr, int size, Bool bold)
365 WMFont *font;
366 char *fontSpec;
368 #define WConf WINGsConfiguration
369 if (bold) {
370 fontSpec = makeFontSetOfSize(WConf.boldSystemFont, size);
371 } else {
372 fontSpec = makeFontSetOfSize(WConf.systemFont, size);
374 #undef WConf
376 if (scrPtr->useMultiByte) {
377 font = WMCreateFontSet(scrPtr, fontSpec);
378 } else {
379 font = WMCreateNormalFont(scrPtr, fontSpec);
382 if (!font) {
383 if (scrPtr->useMultiByte) {
384 wwarning(_("could not load font set %s. Trying fixed."), fontSpec);
385 font = WMCreateFontSet(scrPtr, "fixed");
386 if (!font) {
387 font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
389 } else {
390 wwarning(_("could not load font %s. Trying fixed."), fontSpec);
391 font = WMCreateNormalFont(scrPtr, "fixed");
393 if (!font) {
394 wwarning(_("could not load fixed font!"));
395 wfree(fontSpec);
396 return NULL;
399 wfree(fontSpec);
401 return font;
405 WMFont*
406 WMSystemFontOfSize(WMScreen *scrPtr, int size)
408 return makeSystemFontOfSize(scrPtr, size, False);
412 WMFont*
413 WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
415 return makeSystemFontOfSize(scrPtr, size, True);
419 XFontSet
420 WMGetFontFontSet(WMFont *font)
422 wassertrv(font!=NULL, NULL);
424 if (!font->notFontSet && !font->antialiased)
425 return font->font.set;
427 return NULL;
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);
439 } else {
440 XRectangle rect;
441 XRectangle AIXsucks;
443 XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
445 return rect.width;
451 void
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,
461 text, length);
462 } else {
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);
470 void
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);
482 } else {
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);
493 static char*
494 makeFontSetOfSize(char *fontset, int size)
496 char font[300], *f;
497 char *newfs = NULL;
498 char *ptr;
500 do {
501 char *tmp;
502 int end;
505 f = fontset;
506 ptr = strchr(fontset, ',');
507 if (ptr) {
508 int count = ptr-fontset;
510 if (count > 255) {
511 wwarning(_("font description %s is too large."), fontset);
512 } else {
513 memcpy(font, fontset, count);
514 font[count] = 0;
515 f = (char*)font;
519 if (newfs)
520 end = strlen(newfs);
521 else
522 end = 0;
524 tmp = wmalloc(end + strlen(f) + 8);
525 if (end != 0) {
526 sprintf(tmp, "%s,", newfs);
527 sprintf(tmp + end + 1, f, size);
528 } else {
529 sprintf(tmp + end, f, size);
532 if (newfs)
533 wfree(newfs);
534 newfs = tmp;
536 fontset = ptr+1;
537 } while (ptr!=NULL);
539 return newfs;
543 #define FONT_PROPS 14
545 typedef struct {
546 char *props[FONT_PROPS];
547 } W_FontAttributes;
550 static void
551 changeFontProp(char *buf, char *newprop, int position)
553 char buf2[512];
554 char *ptr, *pptr, *rptr;
555 int count;
557 if (buf[0]!='-') {
558 /* // remove warning later. or maybe not */
559 wwarning(_("Invalid font specification: '%s'\n"), buf);
560 return;
563 ptr = pptr = rptr = buf;
564 count = 0;
565 while (*ptr && *ptr!=',') {
566 if (*ptr == '-') {
567 count++;
568 if (count-1==position+1) {
569 rptr = ptr;
570 break;
572 if (count-1==position) {
573 pptr = ptr+1;
576 ptr++;
578 if (position==FONT_PROPS-1) {
579 rptr = ptr;
582 *pptr = 0;
583 snprintf(buf2, 512, "%s%s%s", buf, newprop, rptr);
584 strcpy(buf, buf2);
588 static WMArray*
589 getOptions(char *options)
591 char *ptr, *ptr2, *str;
592 WMArray *result;
593 int count;
595 result = WMCreateArrayWithDestructor(2, (WMFreeDataProc*)wfree);
597 ptr = options;
598 while (1) {
599 ptr2 = strchr(ptr, ',');
600 if (!ptr2) {
601 WMAddToArray(result, wstrdup(ptr));
602 break;
603 } else {
604 count = ptr2 - ptr;
605 str = wmalloc(count+1);
606 memcpy(str, ptr, count);
607 str[count] = 0;
608 WMAddToArray(result, str);
609 ptr = ptr2 + 1;
613 return result;
617 #define WFAUnchanged (NULL)
618 /* Struct for font change operations */
619 typedef struct WMFontAttributes {
620 char *foundry;
621 char *family;
622 char *weight;
623 char *slant;
624 char *setWidth;
625 char *addStyle;
626 char *pixelSize;
627 char *pointSize;
628 char *resolutionX;
629 char *resolutionY;
630 char *spacing;
631 char *averageWidth;
632 char *registry;
633 char *encoding;
634 } WMFontAttributes;
636 WMFont*
637 WMCopyFontWithChanges(WMScreen *scrPtr, WMFont *font,
638 const WMFontAttributes *changes)
640 int index[FONT_PROPS], count[FONT_PROPS];
641 int totalProps, i, j, carry;
642 char fname[512];
643 WMFontFlags fFlags;
644 WMBag *props;
645 WMArray *options;
646 WMFont *result;
647 char *prop;
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);
656 totalProps = 0;
657 for (i=0; i<FONT_PROPS; i++) {
658 prop = ((W_FontAttributes*)changes)->props[i];
659 count[i] = index[i] = 0;
660 if (!prop) {
661 /* No change for this property */
662 continue;
663 } else if (strchr(prop, ',')==NULL) {
664 /* Simple option */
665 changeFontProp(fname, prop, i);
666 } else {
667 /* Option with fallback alternatives */
668 if ((changes==WFAEmphasized || changes==WFABoldEmphasized) &&
669 font->antialiased && strcmp(prop, "o,i")==0) {
670 options = getOptions("i,o");
671 } else {
672 options = getOptions(prop);
674 WMInsertInBag(props, i, options);
675 count[i] = WMGetArrayItemCount(options);
676 if (totalProps==0)
677 totalProps = 1;
678 totalProps = totalProps * count[i];
682 if (totalProps == 0) {
683 /* No options with fallback alternatives at all */
684 WMFreeBag(props);
685 return WMCreateFontWithFlags(scrPtr, fname, fFlags);
688 for (i=0; i<totalProps; i++) {
689 for (j=0; j<FONT_PROPS; j++) {
690 if (count[j]!=0) {
691 options = WMGetFromBag(props, j);
692 prop = WMGetFromArray(options, index[j]);
693 if (prop) {
694 changeFontProp(fname, prop, j);
698 result = WMCreateFontWithFlags(scrPtr, fname, fFlags);
699 if (result) {
700 WMFreeBag(props);
701 return result;
703 for (j=FONT_PROPS-1, carry=1; j>=0; j--) {
704 if (count[j]!=0) {
705 index[j] += carry;
706 carry = (index[j]==count[j]);
707 index[j] %= count[j];
712 WMFreeBag(props);
714 return NULL;
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;
768 #endif