Get rid of wchar_t for good
This commit is contained in:
parent
b8dc6bb3cc
commit
da3a4842f1
|
@ -44,8 +44,6 @@ include_directories (${ZLIB_INCLUDE_DIRS}
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
include (CheckFunctionExists)
|
include (CheckFunctionExists)
|
||||||
CHECK_FUNCTION_EXISTS ("wcwidth" HAVE_WCWIDTH)
|
|
||||||
|
|
||||||
set (CMAKE_REQUIRED_LIBRARIES ${dependencies_LIBRARIES})
|
set (CMAKE_REQUIRED_LIBRARIES ${dependencies_LIBRARIES})
|
||||||
CHECK_FUNCTION_EXISTS ("resize_term" HAVE_RESIZE_TERM)
|
CHECK_FUNCTION_EXISTS ("resize_term" HAVE_RESIZE_TERM)
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#define GETTEXT_PACKAGE PROJECT_NAME
|
#define GETTEXT_PACKAGE PROJECT_NAME
|
||||||
#define GETTEXT_DIRNAME "${CMAKE_INSTALL_PREFIX}/share/locale"
|
#define GETTEXT_DIRNAME "${CMAKE_INSTALL_PREFIX}/share/locale"
|
||||||
|
|
||||||
#cmakedefine HAVE_WCWIDTH
|
|
||||||
#cmakedefine HAVE_RESIZE_TERM
|
#cmakedefine HAVE_RESIZE_TERM
|
||||||
|
|
||||||
#endif /* ! CONFIG_H */
|
#endif /* ! CONFIG_H */
|
||||||
|
|
113
src/sdtui.c
113
src/sdtui.c
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* StarDict terminal UI
|
* 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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* 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 <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
@ -57,17 +54,6 @@ unichar_width (gunichar ch)
|
||||||
return 1 + g_unichar_iswide (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 -------------------------------------------------------------
|
// --- Application -------------------------------------------------------------
|
||||||
|
|
||||||
/** Data relating to one entry within the dictionary. */
|
/** Data relating to one entry within the dictionary. */
|
||||||
|
@ -87,7 +73,7 @@ struct application
|
||||||
GMainLoop * loop; //!< Main loop
|
GMainLoop * loop; //!< Main loop
|
||||||
termo_t * tk; //!< termo handle
|
termo_t * tk; //!< termo handle
|
||||||
guint tk_timeout; //!< termo timeout
|
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
|
StardictDict * dict; //!< The current dictionary
|
||||||
guint show_help : 1; //!< Whether help can be shown
|
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->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);
|
app_reload_view (self);
|
||||||
}
|
}
|
||||||
|
@ -255,36 +243,44 @@ app_destroy (Application *self)
|
||||||
g_free (self->search_label);
|
g_free (self->search_label);
|
||||||
g_array_free (self->input, TRUE);
|
g_array_free (self->input, TRUE);
|
||||||
|
|
||||||
g_iconv_close (self->utf8_to_wchar);
|
g_iconv_close (self->ucs4_to_locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Write the given utf-8 string padded with spaces.
|
/** 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.
|
||||||
* @param[in] n The number of characters to write, or -1 for the whole string.
|
* @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.
|
* @param[in] attrs Text attributes for the text, without padding.
|
||||||
* To change the attributes of all output, use attrset().
|
* To change the attributes of all output, use attrset().
|
||||||
* @return The number of wide characters written.
|
* @return The number of characters output.
|
||||||
*/
|
*/
|
||||||
static gsize
|
static gsize
|
||||||
app_add_utf8_string (Application *self, const gchar *str, int attrs, int n)
|
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)
|
if (!n)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Compute how many wide characters fit in the limit
|
glong ucs4_len;
|
||||||
gint cols, i;
|
gunichar *ucs4 = g_utf8_to_ucs4_fast (str, -1, &ucs4_len);
|
||||||
for (cols = i = 0; i < wide_len; i++)
|
|
||||||
{
|
|
||||||
if (!is_character_in_locale (wide_str[i]))
|
|
||||||
wide_str[i] = error;
|
|
||||||
|
|
||||||
gint width = wcwidth (wide_str[i]);
|
// Replace invalid chars and compute how many characters fit in the limit
|
||||||
|
gint cols, i;
|
||||||
|
for (cols = i = 0; i < ucs4_len; i++)
|
||||||
|
{
|
||||||
|
if (!app_is_character_in_locale (self, ucs4[i]))
|
||||||
|
ucs4[i] = '?';
|
||||||
|
|
||||||
|
gint width = unichar_width (ucs4[i]);
|
||||||
if (n >= 0 && cols + width > n)
|
if (n >= 0 && cols + width > n)
|
||||||
break;
|
break;
|
||||||
cols += width;
|
cols += width;
|
||||||
|
@ -294,49 +290,46 @@ app_add_utf8_string (Application *self, const gchar *str, int attrs, int n)
|
||||||
n = cols;
|
n = cols;
|
||||||
|
|
||||||
// Append ellipsis if the whole string didn't fit
|
// Append ellipsis if the whole string didn't fit
|
||||||
|
gunichar ellipsis = L'…';
|
||||||
|
gint ellipsis_width = unichar_width (ellipsis);
|
||||||
|
|
||||||
gint len = i;
|
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)
|
if (cols + ellipsis_width > n)
|
||||||
cols -= wcwidth (wide_str[len - 1]);
|
cols -= unichar_width (ucs4[len - 1]);
|
||||||
else
|
else
|
||||||
len++;
|
len++;
|
||||||
|
|
||||||
wide_str[len - 1] = ellipsis;
|
ucs4[len - 1] = ellipsis;
|
||||||
cols += wcwidth (ellipsis);
|
cols += ellipsis_width;
|
||||||
}
|
}
|
||||||
else if (n >= 3 && len >= 3)
|
else if (n >= 3 && len >= 3)
|
||||||
{
|
{
|
||||||
// With zero-width characters this overflows
|
// With zero-width characters this overflows
|
||||||
// It's just a fallback anyway
|
// It's just a fallback anyway
|
||||||
cols -= wcwidth (wide_str[len - 1]);
|
cols -= unichar_width (ucs4[len - 1]); ucs4[len - 1] = '.';
|
||||||
cols -= wcwidth (wide_str[len - 2]);
|
cols -= unichar_width (ucs4[len - 2]); ucs4[len - 2] = '.';
|
||||||
cols -= wcwidth (wide_str[len - 3]);
|
cols -= unichar_width (ucs4[len - 3]); ucs4[len - 3] = '.';
|
||||||
cols += 3;
|
cols += 3;
|
||||||
|
|
||||||
wide_str[len - 1] = L'.';
|
|
||||||
wide_str[len - 2] = L'.';
|
|
||||||
wide_str[len - 3] = L'.';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cchar_t cch;
|
guchar *locale_str;
|
||||||
for (i = 0; i < len; i++)
|
gsize locale_str_len;
|
||||||
{
|
locale_str = (guchar *) g_convert_with_iconv ((const gchar *) ucs4,
|
||||||
if (setcchar (&cch, &wide_str[i], attrs, 0, NULL) == OK)
|
len * sizeof *ucs4, self->ucs4_to_locale, NULL, &locale_str_len, NULL);
|
||||||
add_wch (&cch);
|
g_return_val_if_fail (locale_str != NULL, 0);
|
||||||
else
|
|
||||||
// This shouldn't happen
|
|
||||||
cols -= wcwidth (wide_str[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
setcchar (&cch, &padding, A_NORMAL, 0, NULL);
|
for (gsize i = 0; i < locale_str_len; i++)
|
||||||
|
addch (locale_str[i] | attrs);
|
||||||
while (cols++ < n)
|
while (cols++ < n)
|
||||||
add_wch (&cch);
|
addch (' ');
|
||||||
|
|
||||||
g_free (wide_str);
|
g_free (locale_str);
|
||||||
|
g_free (ucs4);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,7 +447,7 @@ app_redraw_view (Application *self)
|
||||||
|
|
||||||
guint left_width = app_get_left_column_width (self);
|
guint left_width = app_get_left_column_width (self);
|
||||||
app_add_utf8_string (self, ve->word, 0, left_width);
|
app_add_utf8_string (self, ve->word, 0, left_width);
|
||||||
addwstr (L" ");
|
addstr (" ");
|
||||||
app_add_utf8_string (self,
|
app_add_utf8_string (self,
|
||||||
ve->definitions[k], 0, COLS - left_width - 1);
|
ve->definitions[k], 0, COLS - left_width - 1);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue