X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fcharset.c;h=61a34cbcf449a6dd0eb870cfc9dd239d83109cf5;hb=HEAD;hp=701fd2105bd6eb1afaf5a4e8a67cb64170c8abc3;hpb=de5c385e46039d2f7410b5ba4a61f92725d7ca9a;p=ncmpc.git diff --git a/src/charset.c b/src/charset.c index 701fd21..61a34cb 100644 --- a/src/charset.c +++ b/src/charset.c @@ -1,6 +1,6 @@ -/* - * (c) 2006 by Kalle Wallin - * Copyright (C) 2008 Max Kellermann +/* ncmpc (Ncurses MPD Client) + * (c) 2004-2017 The Music Player Daemon Project + * Project homepage: http://musicpd.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -11,21 +11,19 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "charset.h" -#include "i18n.h" #include #include #include -extern void screen_status_printf(const char *format, ...); - +#ifdef ENABLE_LOCALE static bool noconvert = true; static const char *charset; @@ -35,12 +33,31 @@ charset_init(void) noconvert = g_get_charset(&charset); return charset; } +#endif + +#ifdef HAVE_CURSES_ENHANCED +static inline unsigned +unicode_char_width(gunichar ch) +{ + if (g_unichar_iszerowidth(ch)) + return 0; + + if (g_unichar_iswide(ch)) + return 2; + + return 1; +} +#endif /* HAVE_CURSES_ENHANCED */ unsigned utf8_width(const char *str) { assert(str != NULL); +#if defined(ENABLE_MULTIBYTE) && !defined(HAVE_CURSES_ENHANCED) + return g_utf8_strlen(str, -1); +#else +#ifdef HAVE_CURSES_ENHANCED if (g_utf8_validate(str, -1, NULL)) { size_t len = g_utf8_strlen(str, -1); unsigned width = 0; @@ -48,68 +65,170 @@ utf8_width(const char *str) while (len--) { c = g_utf8_get_char(str); - width += g_unichar_iswide(c) ? 2 : 1; + width += unicode_char_width(c); str += g_unichar_to_utf8(c, NULL); } return width; } else +#endif return strlen(str); +#endif +} + +unsigned +locale_width(const char *p) +{ +#if defined(ENABLE_LOCALE) && defined(ENABLE_MULTIBYTE) + char *utf8; + unsigned width; + + if (noconvert) + return utf8_width(p); + + utf8 = locale_to_utf8(p); + width = utf8_width(utf8); + g_free(utf8); + + return width; +#else + return strlen(p); +#endif +} + +gcc_unused +static unsigned +ascii_cut_width(char *p, unsigned max_width) +{ + size_t length = strlen(p); + if (length <= (size_t)max_width) + return (unsigned)length; + + p[max_width] = 0; + return max_width; +} + +gcc_unused +static unsigned +narrow_cut_width(char *p, unsigned max_width) +{ + size_t length = g_utf8_strlen(p, -1); + if (length <= (size_t)max_width) + return (unsigned)length; + + *g_utf8_offset_to_pointer(p, max_width) = 0; + return max_width; +} + +gcc_unused +static unsigned +wide_cut_width(char *p, unsigned max_width) +{ + size_t length = g_utf8_strlen(p, -1); + unsigned width = 0, prev_width; + + while (length-- > 0) { + gunichar c = g_utf8_get_char(p); + prev_width = width; + width += g_unichar_iswide(c) ? 2 : 1; + if (width > max_width) { + /* too wide - cut the rest off */ + *p = 0; + return prev_width; + } + + p += g_unichar_to_utf8(c, NULL); + } + + return width; +} + +unsigned +utf8_cut_width(char *p, unsigned max_width) +{ + assert(p != NULL); + +#ifdef HAVE_CURSES_ENHANCED + if (!g_utf8_validate(p, -1, NULL)) + return ascii_cut_width(p, max_width); + + return wide_cut_width(p, max_width); +#elif defined(ENABLE_MULTIBYTE) && !defined(HAVE_CURSES_ENHANCED) + return narrow_cut_width(p, max_width); +#else + return ascii_cut_width(p, max_width); +#endif } char * utf8_to_locale(const char *utf8str) { - gchar *str; - gsize rb, wb; - GError *error; - +#ifdef ENABLE_LOCALE assert(utf8str != NULL); if (noconvert) return g_strdup(utf8str); - rb = 0; /* bytes read */ - wb = 0; /* bytes written */ - error = NULL; - str = g_locale_from_utf8(utf8str, - strlen(utf8str), - &wb, &rb, - &error); - if (error) { - screen_status_printf(_("Error: Unable to convert characters to %s"), - charset); - g_error_free(error); + gchar *str = g_convert_with_fallback(utf8str, -1, + charset, "utf-8", + NULL, NULL, NULL, NULL); + if (str == NULL) return g_strdup(utf8str); - } return str; +#else + return g_strdup(utf8str); +#endif } char * locale_to_utf8(const char *localestr) { - gchar *str; - gsize rb, wb; - GError *error; - +#ifdef ENABLE_LOCALE assert(localestr != NULL); if (noconvert) return g_strdup(localestr); - rb = 0; /* bytes read */ - wb = 0; /* bytes written */ - error = NULL; - str = g_locale_to_utf8(localestr, - strlen(localestr), - &wb, &rb, - &error); - if (error) { - screen_status_printf(_("Error: Unable to convert characters to UTF-8")); - g_error_free(error); + gchar *str = g_convert_with_fallback(localestr, -1, + "utf-8", charset, + NULL, NULL, NULL, NULL); + if (str == NULL) return g_strdup(localestr); - } return str; +#else + return g_strdup(localestr); +#endif +} + +char * +replace_utf8_to_locale(char *src) +{ +#ifdef ENABLE_LOCALE + assert(src != NULL); + + if (noconvert) + return src; + + return utf8_to_locale(src); +#else + return src; +#endif +} + + +char * +replace_locale_to_utf8(char *src) +{ +#ifdef ENABLE_LOCALE + assert(src != NULL); + + if (noconvert) + return src; + + return locale_to_utf8(src); +#else + return src; +#endif }