X-Git-Url: https://repo.or.cz/w/wmaker-crm.git/blobdiff_plain/59fc927dc9f183802621138534fa6eaafe5593ba..688a56e8ab67b56550e2874d9d7423f0d435bfd9:/WINGs/wfont_wchar.c diff --git a/WINGs/wfont_wchar.c b/WINGs/wfont_wchar.c dissimilarity index 92% index cfc6f03c..85c75a12 100644 --- a/WINGs/wfont_wchar.c +++ b/WINGs/wfont_wchar.c @@ -1,599 +1,543 @@ - -#include "wconfig.h" - -#ifdef XFT - -#include -#include - -#if defined(HAVE_MBSNRTOWCS) -# define __USE_GNU -#endif - -#ifdef HAVE_WCHAR_H -# include -#endif - -#include - -#include "WINGsP.h" - -#include -#include -#include - - -// && defined(HAVE_MBSTATE_T___COUNT) -// in configure.ac use AC_CHECK_MEMBER(struct mbstate_t.__count, -// have=1, have=0, [#include ]) -#if defined(HAVE_MBSNRTOWCS) - -static size_t -wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len) -{ - mbstate_t ps; - size_t n; - - memset(&ps, 0, sizeof(mbstate_t)); - n = mbsnrtowcs(dest, src, nbytes, len, &ps); - if (n!=(size_t)-1 && *src) { - *src -= ps.__count; - } - - return n; -} - -#elif defined(HAVE_MBRTOWC) - -// This is 8 times slower than the version above. -static size_t -wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len) -{ - mbstate_t ps; - const char *ptr; - size_t n; - int nb; - - if (nbytes==0) - return 0; - - memset(&ps, 0, sizeof(mbstate_t)); - - if (dest == NULL) { - for (ptr=*src, n=0; nbytes>0; n++) { - nb = mbrtowc(NULL, ptr, nbytes, &ps); - if (nb == -1) { - return ((size_t)-1); - } else if (nb==0 || nb==-2) { - return n; - } - ptr += nb; - nbytes -= nb; - } - } - - for (ptr=*src, n=0; n0; n++, dest++) { - nb = mbrtowc(dest, ptr, nbytes, &ps); - if (nb == -2) { - *src = ptr; - return n; - } else if (nb == -1) { - *src = ptr; - return ((size_t)-1); - } else if (nb == 0) { - *src = NULL; - return n; - } - ptr += nb; - nbytes -= nb; - } - - *src = ptr; - return n; -} - -#else - -// Not only 8 times slower than the version based on mbsnrtowcs -// but also this version is not thread safe nor reentrant - -static size_t -wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len) -{ - const char *ptr; - size_t n; - int nb; - - if (nbytes==0) - return 0; - - mbtowc(NULL, NULL, 0); /* reset shift state */ - - if (dest == NULL) { - for (ptr=*src, n=0; nbytes>0; n++) { - nb = mbtowc(NULL, ptr, nbytes); - if (nb == -1) { - mbtowc(NULL, NULL, 0); - nb = mbtowc(NULL, ptr, strlen(ptr)); - return (nb == -1 ? (size_t)-1 : n); - } else if (nb==0) { - return n; - } - ptr += nb; - nbytes -= nb; - } - } - - for (ptr=*src, n=0; n0; n++, dest++) { - nb = mbtowc(dest, ptr, nbytes); - if (nb == -1) { - mbtowc(NULL, NULL, 0); - nb = mbtowc(NULL, ptr, strlen(ptr)); - *src = ptr; - return (nb == -1 ? (size_t)-1 : n); - } else if (nb == 0) { - *src = NULL; - return n; - } - ptr += nb; - nbytes -= nb; - } - - *src = ptr; - return n; -} - -#endif - - -#define DEFAULT_SIZE 12 - -static char* -fixXLFD(char *xlfd, int size) -{ - char *fname, *ptr; - - fname = wmalloc(strlen(xlfd) + 20); - if (strstr(xlfd, "%d")!=NULL) - sprintf(fname, xlfd, size ? size : DEFAULT_SIZE); - else - strcpy(fname, xlfd); - - if ((ptr = strchr(fname, ','))) { - *ptr = 0; - } - - return fname; -} - - -static Bool -hasProperty(FcPattern *pattern, const char *property) -{ - FcValue val; - - if (FcPatternGet(pattern, property, 0, &val)==FcResultMatch) { - return True; - } - - return False; -} - - -static Bool -hasPropertyWithStringValue(FcPattern *pattern, const char *object, char *value) -{ - FcChar8 *str; - int id; - - if (!value || value[0]==0) - return True; - - id = 0; - while (FcPatternGetString(pattern, object, id, &str)==FcResultMatch) { - if (strcasecmp(value, (char*)str) == 0) { - return True; - } - id++; - } - - return False; -} - - -// also handle an xlfd with %d for size? -static char* -makeFontOfSize(char *font, int size, char *fallback) -{ - FcPattern *pattern; - char *result; - - if (font[0]=='-') { - char *fname; - - fname = fixXLFD(font, size); - pattern = XftXlfdParse(fname, False, False); - wfree(fname); - } else { - pattern = FcNameParse(font); - } - - //FcPatternPrint(pattern); - if (size > 0) { - FcPatternDel(pattern, "pixelsize"); - FcPatternAddDouble(pattern, "pixelsize", (double)size); - } else if (size==0 && !hasProperty(pattern, "size") && - !hasProperty(pattern, "pixelsize")) { - FcPatternAddDouble(pattern, "pixelsize", (double)DEFAULT_SIZE); - } - - if (fallback && !hasPropertyWithStringValue(pattern, "family", fallback)) { - FcPatternAddString(pattern, "family", fallback); - } - - result = FcNameUnparse(pattern); - FcPatternDestroy(pattern); - - return result; -} - - -WMFont* -WMCreateFont(WMScreen *scrPtr, char *fontName) -{ - WMFont *font; - Display *display = scrPtr->display; - char *fname, *ptr; - - /* This is for back-compat (to allow reading of old xlfd descriptions) */ - if (fontName[0]=='-' && (ptr = strchr(fontName, ','))) { - // warn for deprecation - fname = wmalloc(ptr - fontName + 1); - strncpy(fname, fontName, ptr - fontName); - fname[ptr - fontName] = 0; - } else { - fname = wstrdup(fontName); - } - - font = WMHashGet(scrPtr->fontCache, fname); - if (font) { - WMRetainFont(font); - wfree(fname); - return font; - } - - font = wmalloc(sizeof(WMFont)); - memset(font, 0, sizeof(WMFont)); - - font->screen = scrPtr; - - // remove - printf("WMCreateFont: %s\n", fname); - - if (fname[0] == '-') { - // Backward compat thing. Remove in a later version - font->font = XftFontOpenXlfd(display, scrPtr->screen, fname); - } else { - font->font = XftFontOpenName(display, scrPtr->screen, fname); - } - if (!font->font) { - wfree(font); - wfree(fname); - return NULL; - } - font->height = font->font->ascent+font->font->descent; - font->y = font->font->ascent; - - font->refCount = 1; - - font->name = fname; - - assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL); - - return font; -} - - -WMFont* -WMRetainFont(WMFont *font) -{ - wassertrv(font!=NULL, NULL); - - font->refCount++; - - return font; -} - - -void -WMReleaseFont(WMFont *font) -{ - wassertr(font!=NULL); - - font->refCount--; - if (font->refCount < 1) { - XftFontClose(font->screen->display, font->font); - if (font->name) { - WMHashRemove(font->screen->fontCache, font->name); - wfree(font->name); - } - wfree(font); - } -} - - -Bool -WMIsAntialiasingEnabled(WMScreen *scrPtr) -{ - return scrPtr->antialiasedText; -} - - -unsigned int -WMFontHeight(WMFont *font) -{ - wassertrv(font!=NULL, 0); - - return font->height; -} - - -char* -WMGetFontName(WMFont *font) -{ - wassertrv(font!=NULL, NULL); - - return font->name; -} - - -WMFont* -WMDefaultSystemFont(WMScreen *scrPtr) -{ - return WMRetainFont(scrPtr->normalFont); -} - - -WMFont* -WMDefaultBoldSystemFont(WMScreen *scrPtr) -{ - return WMRetainFont(scrPtr->boldFont); -} - - -WMFont* -WMSystemFontOfSize(WMScreen *scrPtr, int size) -{ - WMFont *font; - char *fontSpec; - - fontSpec = makeFontOfSize(WINGsConfiguration.systemFont, size, "sans"); - - font = WMCreateFont(scrPtr, fontSpec); - - if (!font) { - wwarning(_("could not load font %s."), fontSpec); - } - - wfree(fontSpec); - - return font; -} - - -WMFont* -WMBoldSystemFontOfSize(WMScreen *scrPtr, int size) -{ - WMFont *font; - char *fontSpec; - - fontSpec = makeFontOfSize(WINGsConfiguration.boldSystemFont, size, "sans"); - - font = WMCreateFont(scrPtr, fontSpec); - - if (!font) { - wwarning(_("could not load font %s."), fontSpec); - } - - wfree(fontSpec); - - return font; -} - - -int -WMWidthOfString(WMFont *font, char *text, int length) -{ - XGlyphInfo extents; - - wassertrv(font!=NULL, 0); - wassertrv(text!=NULL, 0); - - if (font->screen->useWideChar) { - wchar_t *wtext; - const char *mtext; - int len; - - wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1)); - mtext = text; - len = wmbsnrtowcs(wtext, &mtext, length, length); - if (len>0) { - wtext[len] = L'\0'; /* not really necessary here */ - XftTextExtents32(font->screen->display, font->font, - (XftChar32 *)wtext, len, &extents); - } else { - if (len==-1) { - wwarning(_("Conversion to widechar failed (possible " - "invalid multibyte sequence): '%s':(pos %d)\n"), - text, mtext-text+1); - } - extents.xOff = 0; - } - wfree(wtext); - } else if (font->screen->useMultiByte) { - XftTextExtentsUtf8(font->screen->display, font->font, - (XftChar8 *)text, length, &extents); - } else { - XftTextExtents8(font->screen->display, font->font, - (XftChar8 *)text, length, &extents); - } - - return extents.xOff; /* don't ask :P */ -} - - - -void -WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font, - int x, int y, char *text, int length) -{ - XftColor xftcolor; - - wassertr(font!=NULL); - - xftcolor.color.red = color->color.red; - xftcolor.color.green = color->color.green; - xftcolor.color.blue = color->color.blue; - xftcolor.color.alpha = color->alpha;; - xftcolor.pixel = W_PIXEL(color); - - XftDrawChange(scr->xftdraw, d); - - if (font->screen->useWideChar) { - wchar_t *wtext; - const char *mtext; - int len; - - wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1)); - mtext = text; - len = wmbsnrtowcs(wtext, &mtext, length, length); - if (len>0) { - XftDrawString32(scr->xftdraw, &xftcolor, font->font, - x, y + font->y, (XftChar32*)wtext, len); - } else if (len==-1) { - wwarning(_("Conversion to widechar failed (possible invalid " - "multibyte sequence): '%s':(pos %d)\n"), - text, mtext-text+1); - /* we can draw normal text, or we can draw as much widechar - * text as was already converted until the error. go figure */ - /*XftDrawString8(scr->xftdraw, &xftcolor, font->font, - x, y + font->y, (XftChar8*)text, length);*/ - } - wfree(wtext); - } else if (font->screen->useMultiByte) { - XftDrawStringUtf8(scr->xftdraw, &xftcolor, font->font, - x, y + font->y, (XftChar8*)text, length); - } else { - XftDrawString8(scr->xftdraw, &xftcolor, font->font, - x, y + font->y, (XftChar8*)text, length); - } -} - - -void -WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background, - WMFont *font, int x, int y, char *text, int length) -{ - XftColor textColor; - XftColor bgColor; - - wassertr(font!=NULL); - - textColor.color.red = color->color.red; - textColor.color.green = color->color.green; - textColor.color.blue = color->color.blue; - textColor.color.alpha = color->alpha;; - textColor.pixel = W_PIXEL(color); - - bgColor.color.red = background->color.red; - bgColor.color.green = background->color.green; - bgColor.color.blue = background->color.blue; - bgColor.color.alpha = background->alpha;; - bgColor.pixel = W_PIXEL(background); - - XftDrawChange(scr->xftdraw, d); - - XftDrawRect(scr->xftdraw, &bgColor, x, y, - WMWidthOfString(font, text, length), - font->height); - - if (font->screen->useWideChar) { - wchar_t *wtext; - const char *mtext; - int len; - - mtext = text; - wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1)); - len = wmbsnrtowcs(wtext, &mtext, length, length); - if (len>0) { - XftDrawString32(scr->xftdraw, &textColor, font->font, - x, y + font->y, (XftChar32*)wtext, len); - } else if (len==-1) { - wwarning(_("Conversion to widechar failed (possible invalid " - "multibyte sequence): '%s':(pos %d)\n"), - text, mtext-text+1); - /* we can draw normal text, or we can draw as much widechar - * text as was already converted until the error. go figure */ - /*XftDrawString8(scr->xftdraw, &textColor, font->font, - x, y + font->y, (XftChar8*)text, length);*/ - } - wfree(wtext); - } else if (font->screen->useMultiByte) { - XftDrawStringUtf8(scr->xftdraw, &textColor, font->font, - x, y + font->y, (XftChar8*)text, length); - } else { - XftDrawString8(scr->xftdraw, &textColor, font->font, - x, y + font->y, (XftChar8*)text, length); - } -} - - -WMFont* -WMCopyFontWithStyle(WMScreen *scrPtr, WMFont *font, WMFontStyle style) -{ - FcPattern *pattern; - WMFont *copy; - char *name; - - if (!font) - return NULL; - - pattern = FcNameParse(WMGetFontName(font)); - switch (style) { - case WFSNormal: - FcPatternDel(pattern, "weight"); - FcPatternDel(pattern, "slant"); - FcPatternAddString(pattern, "weight", "regular"); - FcPatternAddString(pattern, "weight", "medium"); - FcPatternAddString(pattern, "slant", "roman"); - break; - case WFSBold: - FcPatternDel(pattern, "weight"); - FcPatternAddString(pattern, "weight", "bold"); - break; - case WFSEmphasized: - FcPatternDel(pattern, "slant"); - FcPatternAddString(pattern, "slant", "italic"); - FcPatternAddString(pattern, "slant", "oblique"); - break; - case WFSBoldEmphasized: - FcPatternDel(pattern, "weight"); - FcPatternDel(pattern, "slant"); - FcPatternAddString(pattern, "weight", "bold"); - FcPatternAddString(pattern, "slant", "italic"); - FcPatternAddString(pattern, "slant", "oblique"); - break; - } - - name = FcNameUnparse(pattern); - copy = WMCreateFont(scrPtr, name); - FcPatternDestroy(pattern); - wfree(name); - - return copy; -} - - -#endif /* XFT */ - - + +#include "wconfig.h" + +#ifdef XFT + +#include +#include + +#if defined(HAVE_MBSNRTOWCS) +# define __USE_GNU +#endif + +#ifdef HAVE_WCHAR_H +# include +#endif + +#include + +#include "WINGsP.h" + +#include +#include +#include + +// && defined(HAVE_MBSTATE_T___COUNT) +// in configure.ac use AC_CHECK_MEMBER(struct mbstate_t.__count, +// have=1, have=0, [#include ]) +#if defined(HAVE_MBSNRTOWCS) + +static size_t wmbsnrtowcs(wchar_t * dest, const char **src, size_t nbytes, size_t len) +{ + mbstate_t ps; + size_t n; + + memset(&ps, 0, sizeof(mbstate_t)); + n = mbsnrtowcs(dest, src, nbytes, len, &ps); + if (n != (size_t) - 1 && *src) { + *src -= ps.__count; + } + + return n; +} + +#elif defined(HAVE_MBRTOWC) + +// This is 8 times slower than the version above. +static size_t wmbsnrtowcs(wchar_t * dest, const char **src, size_t nbytes, size_t len) +{ + mbstate_t ps; + const char *ptr; + size_t n; + int nb; + + if (nbytes == 0) + return 0; + + memset(&ps, 0, sizeof(mbstate_t)); + + if (dest == NULL) { + for (ptr = *src, n = 0; nbytes > 0; n++) { + nb = mbrtowc(NULL, ptr, nbytes, &ps); + if (nb == -1) { + return ((size_t) - 1); + } else if (nb == 0 || nb == -2) { + return n; + } + ptr += nb; + nbytes -= nb; + } + } + + for (ptr = *src, n = 0; n < len && nbytes > 0; n++, dest++) { + nb = mbrtowc(dest, ptr, nbytes, &ps); + if (nb == -2) { + *src = ptr; + return n; + } else if (nb == -1) { + *src = ptr; + return ((size_t) - 1); + } else if (nb == 0) { + *src = NULL; + return n; + } + ptr += nb; + nbytes -= nb; + } + + *src = ptr; + return n; +} + +#else + +// Not only 8 times slower than the version based on mbsnrtowcs +// but also this version is not thread safe nor reentrant + +static size_t wmbsnrtowcs(wchar_t * dest, const char **src, size_t nbytes, size_t len) +{ + const char *ptr; + size_t n; + int nb; + + if (nbytes == 0) + return 0; + + mbtowc(NULL, NULL, 0); /* reset shift state */ + + if (dest == NULL) { + for (ptr = *src, n = 0; nbytes > 0; n++) { + nb = mbtowc(NULL, ptr, nbytes); + if (nb == -1) { + mbtowc(NULL, NULL, 0); + nb = mbtowc(NULL, ptr, strlen(ptr)); + return (nb == -1 ? (size_t) - 1 : n); + } else if (nb == 0) { + return n; + } + ptr += nb; + nbytes -= nb; + } + } + + for (ptr = *src, n = 0; n < len && nbytes > 0; n++, dest++) { + nb = mbtowc(dest, ptr, nbytes); + if (nb == -1) { + mbtowc(NULL, NULL, 0); + nb = mbtowc(NULL, ptr, strlen(ptr)); + *src = ptr; + return (nb == -1 ? (size_t) - 1 : n); + } else if (nb == 0) { + *src = NULL; + return n; + } + ptr += nb; + nbytes -= nb; + } + + *src = ptr; + return n; +} + +#endif + +#define DEFAULT_SIZE 12 + +static char *fixXLFD(char *xlfd, int size) +{ + char *fname, *ptr; + + fname = wmalloc(strlen(xlfd) + 20); + if (strstr(xlfd, "%d") != NULL) + sprintf(fname, xlfd, size ? size : DEFAULT_SIZE); + else + strcpy(fname, xlfd); + + if ((ptr = strchr(fname, ','))) { + *ptr = 0; + } + + return fname; +} + +static Bool hasProperty(FcPattern * pattern, const char *property) +{ + FcValue val; + + if (FcPatternGet(pattern, property, 0, &val) == FcResultMatch) { + return True; + } + + return False; +} + +static Bool hasPropertyWithStringValue(FcPattern * pattern, const char *object, char *value) +{ + FcChar8 *str; + int id; + + if (!value || value[0] == 0) + return True; + + id = 0; + while (FcPatternGetString(pattern, object, id, &str) == FcResultMatch) { + if (strcasecmp(value, (char *)str) == 0) { + return True; + } + id++; + } + + return False; +} + +// also handle an xlfd with %d for size? +static char *makeFontOfSize(char *font, int size, char *fallback) +{ + FcPattern *pattern; + char *result; + + if (font[0] == '-') { + char *fname; + + fname = fixXLFD(font, size); + pattern = XftXlfdParse(fname, False, False); + wfree(fname); + } else { + pattern = FcNameParse(font); + } + + //FcPatternPrint(pattern); + if (size > 0) { + FcPatternDel(pattern, "pixelsize"); + FcPatternAddDouble(pattern, "pixelsize", (double)size); + } else if (size == 0 && !hasProperty(pattern, "size") && !hasProperty(pattern, "pixelsize")) { + FcPatternAddDouble(pattern, "pixelsize", (double)DEFAULT_SIZE); + } + + if (fallback && !hasPropertyWithStringValue(pattern, "family", fallback)) { + FcPatternAddString(pattern, "family", fallback); + } + + result = FcNameUnparse(pattern); + FcPatternDestroy(pattern); + + return result; +} + +WMFont *WMCreateFont(WMScreen * scrPtr, char *fontName) +{ + WMFont *font; + Display *display = scrPtr->display; + char *fname, *ptr; + + /* This is for back-compat (to allow reading of old xlfd descriptions) */ + if (fontName[0] == '-' && (ptr = strchr(fontName, ','))) { + // warn for deprecation + fname = wmalloc(ptr - fontName + 1); + strncpy(fname, fontName, ptr - fontName); + fname[ptr - fontName] = 0; + } else { + fname = wstrdup(fontName); + } + + font = WMHashGet(scrPtr->fontCache, fname); + if (font) { + WMRetainFont(font); + wfree(fname); + return font; + } + + font = wmalloc(sizeof(WMFont)); + memset(font, 0, sizeof(WMFont)); + + font->screen = scrPtr; + + // remove + printf("WMCreateFont: %s\n", fname); + + if (fname[0] == '-') { + // Backward compat thing. Remove in a later version + font->font = XftFontOpenXlfd(display, scrPtr->screen, fname); + } else { + font->font = XftFontOpenName(display, scrPtr->screen, fname); + } + if (!font->font) { + wfree(font); + wfree(fname); + return NULL; + } + font->height = font->font->ascent + font->font->descent; + font->y = font->font->ascent; + + font->refCount = 1; + + font->name = fname; + + assert(WMHashInsert(scrPtr->fontCache, font->name, font) == NULL); + + return font; +} + +WMFont *WMRetainFont(WMFont * font) +{ + wassertrv(font != NULL, NULL); + + font->refCount++; + + return font; +} + +void WMReleaseFont(WMFont * font) +{ + wassertr(font != NULL); + + font->refCount--; + if (font->refCount < 1) { + XftFontClose(font->screen->display, font->font); + if (font->name) { + WMHashRemove(font->screen->fontCache, font->name); + wfree(font->name); + } + wfree(font); + } +} + +Bool WMIsAntialiasingEnabled(WMScreen * scrPtr) +{ + return scrPtr->antialiasedText; +} + +unsigned int WMFontHeight(WMFont * font) +{ + wassertrv(font != NULL, 0); + + return font->height; +} + +char *WMGetFontName(WMFont * font) +{ + wassertrv(font != NULL, NULL); + + return font->name; +} + +WMFont *WMDefaultSystemFont(WMScreen * scrPtr) +{ + return WMRetainFont(scrPtr->normalFont); +} + +WMFont *WMDefaultBoldSystemFont(WMScreen * scrPtr) +{ + return WMRetainFont(scrPtr->boldFont); +} + +WMFont *WMSystemFontOfSize(WMScreen * scrPtr, int size) +{ + WMFont *font; + char *fontSpec; + + fontSpec = makeFontOfSize(WINGsConfiguration.systemFont, size, "sans"); + + font = WMCreateFont(scrPtr, fontSpec); + + if (!font) { + wwarning(_("could not load font %s."), fontSpec); + } + + wfree(fontSpec); + + return font; +} + +WMFont *WMBoldSystemFontOfSize(WMScreen * scrPtr, int size) +{ + WMFont *font; + char *fontSpec; + + fontSpec = makeFontOfSize(WINGsConfiguration.boldSystemFont, size, "sans"); + + font = WMCreateFont(scrPtr, fontSpec); + + if (!font) { + wwarning(_("could not load font %s."), fontSpec); + } + + wfree(fontSpec); + + return font; +} + +int WMWidthOfString(WMFont * font, char *text, int length) +{ + XGlyphInfo extents; + + wassertrv(font != NULL, 0); + wassertrv(text != NULL, 0); + + if (font->screen->useWideChar) { + wchar_t *wtext; + const char *mtext; + int len; + + wtext = (wchar_t *) wmalloc(sizeof(wchar_t) * (length + 1)); + mtext = text; + len = wmbsnrtowcs(wtext, &mtext, length, length); + if (len > 0) { + wtext[len] = L'\0'; /* not really necessary here */ + XftTextExtents32(font->screen->display, font->font, (XftChar32 *) wtext, len, &extents); + } else { + if (len == -1) { + wwarning(_("Conversion to widechar failed (possible " + "invalid multibyte sequence): '%s':(pos %d)\n"), + text, mtext - text + 1); + } + extents.xOff = 0; + } + wfree(wtext); + } else if (font->screen->useMultiByte) { + XftTextExtentsUtf8(font->screen->display, font->font, (XftChar8 *) text, length, &extents); + } else { + XftTextExtents8(font->screen->display, font->font, (XftChar8 *) text, length, &extents); + } + + return extents.xOff; /* don't ask :P */ +} + +void WMDrawString(WMScreen * scr, Drawable d, WMColor * color, WMFont * font, int x, int y, char *text, int length) +{ + XftColor xftcolor; + + wassertr(font != NULL); + + xftcolor.color.red = color->color.red; + xftcolor.color.green = color->color.green; + xftcolor.color.blue = color->color.blue; + xftcolor.color.alpha = color->alpha;; + xftcolor.pixel = W_PIXEL(color); + + XftDrawChange(scr->xftdraw, d); + + if (font->screen->useWideChar) { + wchar_t *wtext; + const char *mtext; + int len; + + wtext = (wchar_t *) wmalloc(sizeof(wchar_t) * (length + 1)); + mtext = text; + len = wmbsnrtowcs(wtext, &mtext, length, length); + if (len > 0) { + XftDrawString32(scr->xftdraw, &xftcolor, font->font, + x, y + font->y, (XftChar32 *) wtext, len); + } else if (len == -1) { + wwarning(_("Conversion to widechar failed (possible invalid " + "multibyte sequence): '%s':(pos %d)\n"), text, mtext - text + 1); + /* we can draw normal text, or we can draw as much widechar + * text as was already converted until the error. go figure */ + /*XftDrawString8(scr->xftdraw, &xftcolor, font->font, + x, y + font->y, (XftChar8*)text, length); */ + } + wfree(wtext); + } else if (font->screen->useMultiByte) { + XftDrawStringUtf8(scr->xftdraw, &xftcolor, font->font, x, y + font->y, (XftChar8 *) text, length); + } else { + XftDrawString8(scr->xftdraw, &xftcolor, font->font, x, y + font->y, (XftChar8 *) text, length); + } +} + +void +WMDrawImageString(WMScreen * scr, Drawable d, WMColor * color, WMColor * background, + WMFont * font, int x, int y, char *text, int length) +{ + XftColor textColor; + XftColor bgColor; + + wassertr(font != NULL); + + textColor.color.red = color->color.red; + textColor.color.green = color->color.green; + textColor.color.blue = color->color.blue; + textColor.color.alpha = color->alpha;; + textColor.pixel = W_PIXEL(color); + + bgColor.color.red = background->color.red; + bgColor.color.green = background->color.green; + bgColor.color.blue = background->color.blue; + bgColor.color.alpha = background->alpha;; + bgColor.pixel = W_PIXEL(background); + + XftDrawChange(scr->xftdraw, d); + + XftDrawRect(scr->xftdraw, &bgColor, x, y, WMWidthOfString(font, text, length), font->height); + + if (font->screen->useWideChar) { + wchar_t *wtext; + const char *mtext; + int len; + + mtext = text; + wtext = (wchar_t *) wmalloc(sizeof(wchar_t) * (length + 1)); + len = wmbsnrtowcs(wtext, &mtext, length, length); + if (len > 0) { + XftDrawString32(scr->xftdraw, &textColor, font->font, + x, y + font->y, (XftChar32 *) wtext, len); + } else if (len == -1) { + wwarning(_("Conversion to widechar failed (possible invalid " + "multibyte sequence): '%s':(pos %d)\n"), text, mtext - text + 1); + /* we can draw normal text, or we can draw as much widechar + * text as was already converted until the error. go figure */ + /*XftDrawString8(scr->xftdraw, &textColor, font->font, + x, y + font->y, (XftChar8*)text, length); */ + } + wfree(wtext); + } else if (font->screen->useMultiByte) { + XftDrawStringUtf8(scr->xftdraw, &textColor, font->font, x, y + font->y, (XftChar8 *) text, length); + } else { + XftDrawString8(scr->xftdraw, &textColor, font->font, x, y + font->y, (XftChar8 *) text, length); + } +} + +WMFont *WMCopyFontWithStyle(WMScreen * scrPtr, WMFont * font, WMFontStyle style) +{ + FcPattern *pattern; + WMFont *copy; + char *name; + + if (!font) + return NULL; + + pattern = FcNameParse(WMGetFontName(font)); + switch (style) { + case WFSNormal: + FcPatternDel(pattern, "weight"); + FcPatternDel(pattern, "slant"); + FcPatternAddString(pattern, "weight", "regular"); + FcPatternAddString(pattern, "weight", "medium"); + FcPatternAddString(pattern, "slant", "roman"); + break; + case WFSBold: + FcPatternDel(pattern, "weight"); + FcPatternAddString(pattern, "weight", "bold"); + break; + case WFSEmphasized: + FcPatternDel(pattern, "slant"); + FcPatternAddString(pattern, "slant", "italic"); + FcPatternAddString(pattern, "slant", "oblique"); + break; + case WFSBoldEmphasized: + FcPatternDel(pattern, "weight"); + FcPatternDel(pattern, "slant"); + FcPatternAddString(pattern, "weight", "bold"); + FcPatternAddString(pattern, "slant", "italic"); + FcPatternAddString(pattern, "slant", "oblique"); + break; + } + + name = FcNameUnparse(pattern); + copy = WMCreateFont(scrPtr, name); + FcPatternDestroy(pattern); + wfree(name); + + return copy; +} + +#endif /* XFT */