summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2014-10-16 01:50:20 +0200
committerPřemysl Janouch <p.janouch@gmail.com>2014-11-19 03:31:47 +0100
commitda3a4842f11684dfafa15b347717b845a4ba82c3 (patch)
treee7ed73df6bf86c7b40b21b970212f03882dad159
parentb8dc6bb3cc2554f0fbadf37b0178f22e0766df2d (diff)
downloadtdv-da3a4842f11684dfafa15b347717b845a4ba82c3.tar.gz
tdv-da3a4842f11684dfafa15b347717b845a4ba82c3.tar.xz
tdv-da3a4842f11684dfafa15b347717b845a4ba82c3.zip
Get rid of wchar_t for good
-rw-r--r--CMakeLists.txt2
-rw-r--r--config.h.in1
-rw-r--r--src/sdtui.c109
3 files changed, 51 insertions, 61 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 813d86c..d52a1bb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,8 +44,6 @@ include_directories (${ZLIB_INCLUDE_DIRS}
# Configuration
include (CheckFunctionExists)
-CHECK_FUNCTION_EXISTS ("wcwidth" HAVE_WCWIDTH)
-
set (CMAKE_REQUIRED_LIBRARIES ${dependencies_LIBRARIES})
CHECK_FUNCTION_EXISTS ("resize_term" HAVE_RESIZE_TERM)
diff --git a/config.h.in b/config.h.in
index f125acb..b8382c1 100644
--- a/config.h.in
+++ b/config.h.in
@@ -8,7 +8,6 @@
#define GETTEXT_PACKAGE PROJECT_NAME
#define GETTEXT_DIRNAME "${CMAKE_INSTALL_PREFIX}/share/locale"
-#cmakedefine HAVE_WCWIDTH
#cmakedefine HAVE_RESIZE_TERM
#endif /* ! CONFIG_H */
diff --git a/src/sdtui.c b/src/sdtui.c
index 3dbcb03..4834b56 100644
--- a/src/sdtui.c
+++ b/src/sdtui.c
@@ -1,7 +1,7 @@
/*
* StarDict terminal UI
*
- * Copyright (c) 2013, Přemysl Janouch <p.janouch@gmail.com>
+ * Copyright (c) 2013 - 2014, Přemysl Janouch <p.janouch@gmail.com>
* All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -18,9 +18,6 @@
*
*/
-#define _XOPEN_SOURCE 500 //!< wcwidth
-#define _XOPEN_SOURCE_EXTENDED //!< Yes, we want ncursesw.
-
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
@@ -57,17 +54,6 @@ unichar_width (gunichar ch)
return 1 + g_unichar_iswide (ch);
}
-#ifndef HAVE_WCWIDTH
-#define wcwidth(x) 1
-#endif // ! HAVE_WCWIDTH
-
-static gboolean
-is_character_in_locale (wchar_t c)
-{
- wchar_t s[] = { c, 0 };
- return wcstombs (NULL, s, 0) != (size_t) -1;
-}
-
// --- Application -------------------------------------------------------------
/** Data relating to one entry within the dictionary. */
@@ -87,7 +73,7 @@ struct application
GMainLoop * loop; //!< Main loop
termo_t * tk; //!< termo handle
guint tk_timeout; //!< termo timeout
- GIConv utf8_to_wchar; //!< utf-8 -> wchar_t conversion
+ GIConv ucs4_to_locale; //!< UTF-32 -> locale conversion
StardictDict * dict; //!< The current dictionary
guint show_help : 1; //!< Whether help can be shown
@@ -235,7 +221,9 @@ app_init (Application *self, const gchar *filename)
self->division = 0.5;
- self->utf8_to_wchar = g_iconv_open ("wchar_t//translit", "utf-8");
+ const char *charset;
+ (void) g_get_charset (&charset);
+ self->ucs4_to_locale = g_iconv_open (charset, "UTF-32");
app_reload_view (self);
}
@@ -255,36 +243,44 @@ app_destroy (Application *self)
g_free (self->search_label);
g_array_free (self->input, TRUE);
- g_iconv_close (self->utf8_to_wchar);
+ g_iconv_close (self->ucs4_to_locale);
+}
+
+/** Returns if the Unicode character is representable in the current locale. */
+static gboolean
+app_is_character_in_locale (Application *self, gunichar ch)
+{
+ gchar *tmp = g_convert_with_iconv ((const gchar *) &ch, sizeof ch,
+ self->ucs4_to_locale, NULL, NULL, NULL);
+ if (!tmp)
+ return FALSE;
+ g_free (tmp);
+ return TRUE;
}
-/** Write the given utf-8 string padded with spaces.
+/** Write the given UTF-8 string padded with spaces.
* @param[in] n The number of characters to write, or -1 for the whole string.
* @param[in] attrs Text attributes for the text, without padding.
* To change the attributes of all output, use attrset().
- * @return The number of wide characters written.
+ * @return The number of characters output.
*/
static gsize
app_add_utf8_string (Application *self, const gchar *str, int attrs, int n)
{
- wchar_t *wide_str = (wchar_t *) g_convert_with_iconv
- (str, -1, self->utf8_to_wchar, NULL, NULL, NULL);
- g_return_val_if_fail (wide_str != NULL, 0);
-
- ssize_t wide_len = wcslen (wide_str);
- wchar_t padding = L' ', error = L'?', ellipsis = L'…';
-
if (!n)
return 0;
- // Compute how many wide characters fit in the limit
+ glong ucs4_len;
+ gunichar *ucs4 = g_utf8_to_ucs4_fast (str, -1, &ucs4_len);
+
+ // Replace invalid chars and compute how many characters fit in the limit
gint cols, i;
- for (cols = i = 0; i < wide_len; i++)
+ for (cols = i = 0; i < ucs4_len; i++)
{
- if (!is_character_in_locale (wide_str[i]))
- wide_str[i] = error;
+ if (!app_is_character_in_locale (self, ucs4[i]))
+ ucs4[i] = '?';
- gint width = wcwidth (wide_str[i]);
+ gint width = unichar_width (ucs4[i]);
if (n >= 0 && cols + width > n)
break;
cols += width;
@@ -294,49 +290,46 @@ app_add_utf8_string (Application *self, const gchar *str, int attrs, int n)
n = cols;
// Append ellipsis if the whole string didn't fit
+ gunichar ellipsis = L'…';
+ gint ellipsis_width = unichar_width (ellipsis);
+
gint len = i;
- if (len != wide_len)
+ if (len != ucs4_len)
{
- if (is_character_in_locale (ellipsis))
+ if (app_is_character_in_locale (self, ellipsis))
{
- if (cols + wcwidth (ellipsis) > n)
- cols -= wcwidth (wide_str[len - 1]);
+ if (cols + ellipsis_width > n)
+ cols -= unichar_width (ucs4[len - 1]);
else
len++;
- wide_str[len - 1] = ellipsis;
- cols += wcwidth (ellipsis);
+ ucs4[len - 1] = ellipsis;
+ cols += ellipsis_width;
}
else if (n >= 3 && len >= 3)
{
// With zero-width characters this overflows
// It's just a fallback anyway
- cols -= wcwidth (wide_str[len - 1]);
- cols -= wcwidth (wide_str[len - 2]);
- cols -= wcwidth (wide_str[len - 3]);
+ cols -= unichar_width (ucs4[len - 1]); ucs4[len - 1] = '.';
+ cols -= unichar_width (ucs4[len - 2]); ucs4[len - 2] = '.';
+ cols -= unichar_width (ucs4[len - 3]); ucs4[len - 3] = '.';
cols += 3;
-
- wide_str[len - 1] = L'.';
- wide_str[len - 2] = L'.';
- wide_str[len - 3] = L'.';
}
}
- cchar_t cch;
- for (i = 0; i < len; i++)
- {
- if (setcchar (&cch, &wide_str[i], attrs, 0, NULL) == OK)
- add_wch (&cch);
- else
- // This shouldn't happen
- cols -= wcwidth (wide_str[i]);
- }
+ guchar *locale_str;
+ gsize locale_str_len;
+ locale_str = (guchar *) g_convert_with_iconv ((const gchar *) ucs4,
+ len * sizeof *ucs4, self->ucs4_to_locale, NULL, &locale_str_len, NULL);
+ g_return_val_if_fail (locale_str != NULL, 0);
- setcchar (&cch, &padding, A_NORMAL, 0, NULL);
+ for (gsize i = 0; i < locale_str_len; i++)
+ addch (locale_str[i] | attrs);
while (cols++ < n)
- add_wch (&cch);
+ addch (' ');
- g_free (wide_str);
+ g_free (locale_str);
+ g_free (ucs4);
return n;
}
@@ -454,7 +447,7 @@ app_redraw_view (Application *self)
guint left_width = app_get_left_column_width (self);
app_add_utf8_string (self, ve->word, 0, left_width);
- addwstr (L" ");
+ addstr (" ");
app_add_utf8_string (self,
ve->definitions[k], 0, COLS - left_width - 1);