[gdm] Improve ordering of languages in language list
- From: Ray Strode <halfline src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gdm] Improve ordering of languages in language list
- Date: Wed, 15 Sep 2010 19:15:34 +0000 (UTC)
commit 2963103357ee4680236ad10ef2652aad0010b174
Author: Takao Fujiwara <tfujiwar redhat com>
Date: Wed Sep 15 15:13:58 2010 -0400
Improve ordering of languages in language list
glibc's default collation order doesn't provide a
nice ordering. It ends up interleaving latin and
non-latin scripts.
https://bugzilla.gnome.org/show_bug.cgi?id=610081
gui/simple-greeter/gdm-chooser-widget.c | 97 ++++++++++++++++++++++++++++++-
1 files changed, 95 insertions(+), 2 deletions(-)
---
diff --git a/gui/simple-greeter/gdm-chooser-widget.c b/gui/simple-greeter/gdm-chooser-widget.c
index 043928d..db2d9b2 100644
--- a/gui/simple-greeter/gdm-chooser-widget.c
+++ b/gui/simple-greeter/gdm-chooser-widget.c
@@ -30,6 +30,7 @@
#include <dirent.h>
#include <sys/stat.h>
#include <syslog.h>
+#include <locale.h>
#include <glib.h>
#include <glib/gi18n.h>
@@ -1546,6 +1547,98 @@ path_is_separator (GdmChooserWidget *widget,
}
static int
+gdm_multilingual_collate (const gchar *text_a, const gchar *text_b)
+{
+ PangoDirection direction_a;
+ PangoDirection direction_b;
+ const gchar *p_a;
+ const gchar *p_b;
+ gchar *org_locale = NULL;
+ gchar *sub_a;
+ gchar *sub_b;
+ gunichar ch_a;
+ gunichar ch_b;
+ GUnicodeScript script_a;
+ GUnicodeScript script_b;
+ gboolean composed_alpha_a;
+ gboolean composed_alpha_b;
+ gboolean all_alpha_a;
+ gboolean all_alpha_b;
+ int result;
+
+ direction_a = pango_find_base_dir (text_a, -1);
+ direction_b = pango_find_base_dir (text_b, -1);
+ if ((direction_a == PANGO_DIRECTION_LTR ||
+ direction_a == PANGO_DIRECTION_NEUTRAL) &&
+ direction_b == PANGO_DIRECTION_RTL)
+ return -1;
+ if (direction_a == PANGO_DIRECTION_RTL &&
+ (direction_b == PANGO_DIRECTION_LTR ||
+ direction_b == PANGO_DIRECTION_NEUTRAL))
+ return 1;
+
+ if (!g_get_charset (NULL)) {
+ org_locale = g_strdup (setlocale (LC_ALL, NULL));
+ if (!setlocale (LC_ALL, "en_US.UTF-8")) {
+ setlocale (LC_ALL, org_locale);
+ g_free (org_locale);
+ org_locale = NULL;
+ }
+ }
+
+ result = 0;
+ all_alpha_a = all_alpha_b = TRUE;
+ for (p_a = text_a, p_b = text_b;
+ p_a && *p_a && p_b && *p_b;
+ p_a = g_utf8_next_char (p_a), p_b = g_utf8_next_char (p_b)) {
+ ch_a = g_utf8_get_char (p_a);
+ ch_b = g_utf8_get_char (p_b);
+ script_a = g_unichar_get_script (ch_a);
+ script_b = g_unichar_get_script (ch_b);
+ composed_alpha_a = (script_a == G_UNICODE_SCRIPT_LATIN ||
+ script_a == G_UNICODE_SCRIPT_GREEK ||
+ script_a == G_UNICODE_SCRIPT_CYRILLIC );
+ composed_alpha_b = (script_b == G_UNICODE_SCRIPT_LATIN ||
+ script_b == G_UNICODE_SCRIPT_GREEK ||
+ script_b == G_UNICODE_SCRIPT_CYRILLIC );
+ all_alpha_a &= composed_alpha_a;
+ all_alpha_b &= composed_alpha_b;
+ if (all_alpha_a && !composed_alpha_b &&
+ ch_b >= 0x530) {
+ result = -1;
+ break;
+ } else if (!composed_alpha_a && all_alpha_b &&
+ ch_a >= 0x530) {
+ result = 1;
+ break;
+ } else if (ch_a != ch_b) {
+ sub_a = g_strndup (text_a, g_utf8_next_char (p_a) - text_a);
+ sub_b = g_strndup (text_b, g_utf8_next_char (p_b) - text_b);
+ result = g_utf8_collate (sub_a, sub_b);
+ g_free (sub_a);
+ g_free (sub_b);
+ if (result != 0) {
+ break;
+ }
+ }
+ }
+ if (result != 0) {
+ if (org_locale) {
+ setlocale (LC_ALL, org_locale);
+ g_free (org_locale);
+ org_locale = NULL;
+ }
+ return result;
+ }
+ if (org_locale) {
+ setlocale (LC_ALL, org_locale);
+ g_free (org_locale);
+ org_locale = NULL;
+ }
+ return g_utf8_collate (text_a, text_b);
+}
+
+static int
compare_item (GtkTreeModel *model,
GtkTreeIter *a,
GtkTreeIter *b,
@@ -1636,9 +1729,9 @@ compare_item (GtkTreeModel *model,
g_debug ("GdmChooserWidget: unable to parse markup: '%s'", name_b);
}
if (text_a != NULL && text_b != NULL) {
- result = g_utf8_collate (text_a, text_b);
+ result = gdm_multilingual_collate (text_a, text_b);
} else {
- result = g_utf8_collate (name_a, name_b);
+ result = gdm_multilingual_collate (name_a, name_b);
}
g_free (text_a);
g_free (text_b);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]