Enlightenment CVS committal Author : kwo Project : e16 Module : e
Dir : e16/e/src Modified Files: lang.c lang.h tclass.h text.c ttfont.c Log Message: Fix shortening text to fit available space in certain combinations of locale and font type. =================================================================== RCS file: /cvs/e/e16/e/src/lang.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -3 -r1.12 -r1.13 --- lang.c 18 Oct 2006 18:19:14 -0000 1.12 +++ lang.c 12 Nov 2006 00:39:19 -0000 1.13 @@ -143,6 +143,125 @@ #endif } +/* + * Stuff to do mb/utf8 <-> wc conversions. + */ +#if HAVE_ICONV +static iconv_t iconv_cd_str2wcs = NULL; +static iconv_t iconv_cd_wcs2str = NULL; +#endif + +int +EwcOpen(int utf8) +{ +#if HAVE_ICONV + const char *enc; + + if (utf8) + enc = "UTF-8"; + else + enc = nl_langinfo(CODESET); + + iconv_cd_str2wcs = iconv_open("WCHAR_T", enc); + iconv_cd_wcs2str = iconv_open(enc, "WCHAR_T"); + + if (iconv_cd_str2wcs && iconv_cd_wcs2str) + return 0; + + EwcClose(); + return -1; +#else + /* NB! This case will not work properly if needed MB encoding is utf8 + * but locale isn't */ + utf8 = 0; + return 0; +#endif +} + +void +EwcClose(void) +{ +#if HAVE_ICONV + if (iconv_cd_str2wcs) + iconv_close(iconv_cd_str2wcs); + iconv_cd_str2wcs = NULL; + if (iconv_cd_wcs2str) + iconv_close(iconv_cd_wcs2str); + iconv_cd_wcs2str = NULL; +#endif +} + +int +EwcStrToWcs(const char *str, int len, wchar_t * wcs, int wcl) +{ +#if HAVE_ICONV + size_t ni, no, rc; + + if (!wcs) + { + char buf[4096], *po; + + ni = len; + no = 4096; + po = buf; + rc = iconv(iconv_cd_str2wcs, (char **)(&str), &ni, &po, &no); + if (rc == (size_t) (-1) || no == 0) + return -1; + wcl = (4096 - no) / sizeof(wchar_t); + return wcl; + } + + ni = len; + no = wcl * sizeof(wchar_t); + rc = iconv(iconv_cd_str2wcs, (char **)(&str), &ni, (char **)(&wcs), &no); + if (rc == (size_t) (-1)) + return 0; + return wcl - no / sizeof(wchar_t); +#else + if (!wcs) + return mbstowcs(NULL, str, 0); + + mbstowcs(wcs, str, wcl); + wcs[wcl] = (wchar_t) '\0'; + + len = 0; + return wcl; +#endif +} + +int +EwcWcsToStr(const wchar_t * wcs, int wcl, char *str, int len) +{ +#if HAVE_ICONV + size_t ni, no, rc; + + ni = wcl * sizeof(wchar_t); + no = len; + rc = iconv(iconv_cd_wcs2str, (char **)(&wcs), &ni, &str, &no); + if (rc == (size_t) (-1)) + return 0; + return len - no; +#else + int i, j, n; + + j = 0; + for (i = 0; i < wcl; i++) + { + if (j + (int)MB_CUR_MAX > len) + break; + n = wctomb(str + j, wcs[i]); + if (n > 0) + j += n; + } + str[j] = '\0'; + return j; +#endif +} + +/* + * Setup + */ + static struct { char *internal; =================================================================== RCS file: /cvs/e/e16/e/src/lang.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -3 -r1.2 -r1.3 --- lang.h 21 Apr 2006 23:47:30 -0000 1.2 +++ lang.h 12 Nov 2006 00:39:19 -0000 1.3 @@ -24,6 +24,8 @@ #ifndef _LANG_H_ #define _LANG_H_ +#include <stdlib.h> + #include "config.h" #ifdef ENABLE_NLS @@ -48,5 +50,12 @@ char *EstrUtf82Int(const char *str, int len); const char *EstrInt2Enc(const char *str, int want_utf8); void EstrInt2EncFree(const char *str, int want_utf8); + +int EwcOpen(int utf8); +void EwcClose(void); +int EwcStrToWcs(const char *str, int len, wchar_t * wcs, + int wcl); +int EwcWcsToStr(const wchar_t * wcs, int wcl, char *str, + int len); #endif /* _LANG_H_ */ =================================================================== RCS file: /cvs/e/e16/e/src/tclass.h,v retrieving revision 1.17 retrieving revision 1.18 diff -u -3 -r1.17 -r1.18 --- tclass.h 22 Oct 2006 14:09:50 -0000 1.17 +++ tclass.h 12 Nov 2006 00:39:19 -0000 1.18 @@ -101,8 +101,8 @@ /* text.c */ TextState *TextclassGetTextState(TextClass * tclass, int state, int active, int sticky); -void TextstateTextFitMB(TextState * ts, char **ptext, int *pw, - int textwidth_limit); +void TextstateTextFit(TextState * ts, char **ptext, int *pw, + int textwidth_limit); void TextstateTextDraw(TextState * ts, Win win, Drawable draw, const char *text, int x, int y, int w, int h, const EImageBorder * pad, =================================================================== RCS file: /cvs/e/e16/e/src/text.c,v retrieving revision 1.79 retrieving revision 1.80 diff -u -3 -r1.79 -r1.80 --- text.c 30 Oct 2006 21:06:01 -0000 1.79 +++ text.c 12 Nov 2006 00:39:19 -0000 1.80 @@ -258,6 +258,151 @@ return NULL; } +static void +TextstateTextFit1(TextState * ts, char **ptext, int *pw, int textwidth_limit) +{ + char *text = *ptext; + int hh, ascent; + char *new_line; + int nuke_count = 0, nc2; + int len; + + len = strlen(text); + if (len <= 1) + return; + new_line = Emalloc(len + 10); + if (!new_line) + return; + + while (*pw > textwidth_limit) + { + nuke_count++; + + if (nuke_count >= len - 1) + { + new_line[0] = text[0]; + memcpy(new_line + 1, "...", 4); + break; + } + + nc2 = (len - nuke_count) / 2; + memcpy(new_line, text, nc2); + memcpy(new_line + nc2, "...", 3); + strcpy(new_line + nc2 + 3, text + nc2 + nuke_count); + + ts->ops->TextSize(ts, new_line, 0, pw, &hh, &ascent); + } + + Efree(text); + *ptext = new_line; +} + +#if FONT_TYPE_XFONT +static void +TextstateTextFit2(TextState * ts, char **ptext, int *pw, int textwidth_limit) +{ + char *text = *ptext; + int hh, ascent; + char *new_line; + int nuke_count = 0; + int len; + + len = strlen(text); + new_line = Emalloc(len + 20); + if (!new_line) + return; + + while (*pw > textwidth_limit) + { + nuke_count += 2; + + if (nuke_count > len) + { + memcpy(new_line, text, 2); + memcpy(new_line + 2, ". . . ", 7); + break; + } + + new_line[0] = 0; + strncat(new_line, text, (len - nuke_count) / 4); + strcat(new_line, ". . . "); + strcat(new_line, text + ((len - nuke_count) / 4) + nuke_count); + + ts->ops->TextSize(ts, new_line, 0, pw, &hh, &ascent); + } + + Efree(text); + *ptext = new_line; +} +#endif /* FONT_TYPE_XFONT */ + +static void +TextstateTextFitMB(TextState * ts, char **ptext, int *pw, int textwidth_limit) +{ + char *text = *ptext; + int hh, ascent; + char *new_line; + int nuke_count = 0, nc2; + int len; + wchar_t *wc_line = NULL; + int wc_len; + + if (EwcOpen(ts->need_utf8 || Mode.locale.utf8_int)) + return; + + len = strlen(text); + wc_len = EwcStrToWcs(text, len, NULL, 0); + if (wc_len <= 1) + goto done; + + wc_line = (wchar_t *) Emalloc((wc_len + 1) * sizeof(wchar_t)); + if (!wc_line) + goto done; + + if (EwcStrToWcs(text, len, wc_line, wc_len) <= 0) + goto done; + + new_line = Emalloc(len + 10); + if (!new_line) + goto done; + + while (*pw > textwidth_limit) + { + nuke_count++; + int len_mb; + + if (nuke_count >= wc_len - 1) + { + int mlen; + + mlen = mblen(text, MB_CUR_MAX); + if (mlen < 0) + mlen = 1; + + memcpy(new_line, text, mlen); + strcpy(new_line + mlen, "..."); + break; + } + + nc2 = (wc_len - nuke_count) / 2; + len_mb = EwcWcsToStr(wc_line, nc2, new_line, len + 10); + memcpy(new_line + len_mb, "...", 3); + len_mb += 3; + len_mb += EwcWcsToStr(wc_line + nc2 + nuke_count, + wc_len - nc2 - nuke_count, + new_line + len_mb, len + 10 - len_mb); + new_line[len_mb] = '\0'; + + ts->ops->TextSize(ts, new_line, 0, pw, &hh, &ascent); + } + Efree(text); + *ptext = new_line; + done: + if (wc_line) + Efree(wc_line); + EwcClose(); +} + #if FONT_TYPE_XFT /* * Xft @@ -397,7 +542,7 @@ } const FontOps FontOpsXft = { - _xft_Load, _xft_Unload, _xft_TextSize, TextstateTextFitMB, _xft_TextDraw, + _xft_Load, _xft_Unload, _xft_TextSize, TextstateTextFit, _xft_TextDraw, _xft_FdcInit, _xft_FdcFini, _xft_FdcSetDrawable, _xft_FdcSetColor }; #endif /* FONT_TYPE_XFT */ @@ -525,7 +670,7 @@ } const FontOps FontOpsXfs = { - _xfs_Load, _xfs_Unload, _xfs_TextSize, TextstateTextFitMB, _xfs_TextDraw, + _xfs_Load, _xfs_Unload, _xfs_TextSize, TextstateTextFit, _xfs_TextDraw, _xfs_FdcInit, NULL, _xfs_FdcSetDrawable, _xfs_FdcSetColor }; #endif /* FONT_TYPE_XFS */ @@ -642,62 +787,11 @@ _xfont_TextFit(TextState * ts, char **ptext, int *pw, int textwidth_limit) { FontCtxXfont *fdc = (FontCtxXfont *) ts->fdc; - char *text = *ptext; - int hh, ascent; - char *new_line; - int nuke_count = 0; - int len; if (fdc->font->min_byte1 == 0 && fdc->font->max_byte1 == 0) - { - len = strlen(text); - new_line = Emalloc(len + 10); - if (!new_line) - return; - - while (*pw > textwidth_limit) - { - nuke_count++; - if (nuke_count > len) - { - new_line[0] = 0; - strncat(new_line, text, 1); - strcat(new_line, "..."); - break; - } - new_line[0] = 0; - strncat(new_line, text, (len - nuke_count) / 2); - strcat(new_line, "..."); - strcat(new_line, text + ((len - nuke_count) / 2) + nuke_count); - ts->ops->TextSize(ts, new_line, 0, pw, &hh, &ascent); - } - } + TextstateTextFit1(ts, ptext, pw, textwidth_limit); else - { - len = strlen(text); - new_line = Emalloc(len + 20); - if (!new_line) - return; - - while (*pw > textwidth_limit) - { - nuke_count += 2; - if (nuke_count > len) - { - new_line[0] = 0; - strncat(new_line, text, 1); - strcat(new_line, ". . . "); - break; - } - new_line[0] = 0; - strncat(new_line, text, (len - nuke_count) / 4); - strcat(new_line, ". . . "); - strcat(new_line, text + ((len - nuke_count) / 4) + nuke_count); - ts->ops->TextSize(ts, new_line, 0, pw, &hh, &ascent); - } - } - Efree(text); - *ptext = new_line; + TextstateTextFit2(ts, ptext, pw, textwidth_limit); } const FontOps FontOpsXfont = { @@ -809,83 +903,12 @@ } void -TextstateTextFitMB(TextState * ts, char **ptext, int *pw, int textwidth_limit) +TextstateTextFit(TextState * ts, char **ptext, int *pw, int textwidth_limit) { - char *text = *ptext; - int hh, ascent; - char *new_line; - int nuke_count = 0; - int len; - wchar_t *wc_line = NULL; - int wc_len; - - len = strlen(text); - new_line = Emalloc(len + 10); - if (!new_line) - return; - - wc_len = mbstowcs(NULL, text, 0); - if (wc_len > 0) - { - wc_line = (wchar_t *) Emalloc((wc_len + 1) * sizeof(wchar_t)); - mbstowcs(wc_line, text, len); - wc_line[wc_len] = (wchar_t) '\0'; - } - - while (*pw > textwidth_limit) - { - nuke_count++; - if (nuke_count > wc_len) - { - int mlen; - - new_line[0] = 0; - if (MB_CUR_MAX > 1 && wc_len > 0) - { /* if multibyte locale,... */ - mlen = mblen(text, MB_CUR_MAX); - if (mlen < 0) - mlen = 1; - } - else - mlen = 1; - - strncat(new_line, text, mlen); - strcat(new_line, "..."); - break; - } - new_line[0] = 0; - if (MB_CUR_MAX > 1 && wc_len > 0) - { - int j, k, len_mb; - - for (j = k = 0; k < (wc_len - nuke_count) / 2; k++) - { - len_mb = wctomb(new_line + j, wc_line[k]); - if (len_mb > 0) - j += len_mb; - } - new_line[j] = '\0'; - strcat(new_line, "..."); - j += 3; - len_mb = wcstombs(new_line + j, - wc_line + (wc_len - nuke_count) / 2 + - nuke_count, len + 10 - j); - if (len_mb > 0) - j += len_mb; - new_line[j] = '\0'; - } - else - { - strncat(new_line, text, (len - nuke_count) / 2); - strcat(new_line, "..."); - strcat(new_line, text + ((len - nuke_count) / 2) + nuke_count); - } - ts->ops->TextSize(ts, new_line, 0, pw, &hh, &ascent); - } - Efree(text); - *ptext = new_line; - if (wc_line) - Efree(wc_line); + if (ts->need_utf8 || MB_CUR_MAX > 1) + TextstateTextFitMB(ts, ptext, pw, textwidth_limit); + else + TextstateTextFit1(ts, ptext, pw, textwidth_limit); } void =================================================================== RCS file: /cvs/e/e16/e/src/ttfont.c,v retrieving revision 1.56 retrieving revision 1.57 diff -u -3 -r1.56 -r1.57 --- ttfont.c 22 Oct 2006 14:09:50 -0000 1.56 +++ ttfont.c 12 Nov 2006 00:39:19 -0000 1.57 @@ -194,7 +194,7 @@ } const FontOps FontOpsIft = { - _ift_Load, _ift_Unload, _ift_TextSize, TextstateTextFitMB, _ift_TextDraw, + _ift_Load, _ift_Unload, _ift_TextSize, TextstateTextFit, _ift_TextDraw, _ift_FdcInit, NULL, _ift_FdcSetDrawable, _ift_FdcSetColor }; ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ enlightenment-cvs mailing list enlightenment-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs