[gnumeric] Fix locale specific sorting. [#638874]
- From: Andreas J. Guelzow <guelzow src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Fix locale specific sorting. [#638874]
- Date: Sun, 9 Jan 2011 21:56:37 +0000 (UTC)
commit 581f36434729dd80223af35743aef150be0d0b54
Author: Andreas J Guelzow <aguelzow pyrshep ca>
Date: Sun Jan 9 14:56:14 2011 -0700
Fix locale specific sorting. [#638874]
2011-01-09 Andreas J. Guelzow <aguelzow pyrshep ca>
* src/sort.c (sort_compare_cells): add argument and use it to
decide whether to use the cacheing version of value_compare
(sort_compare_sets): add argument and change all callers
(gnm_sort_contents): if we are not in the default locale, do not cache
collation keys
* src/value.h (value_compare_no_cache): new
* src/value.c (value_compare_no_cache): new
(value_compare_real): new
(value_cmp): use value_compare_real
(value_compare): use value_compare_real
(gnm_string_cmp): new
(gnm_string_cmp_ignorecase): new
ChangeLog | 15 ++++++++++++
NEWS | 1 +
src/sort.c | 42 ++++++++++++++++++++++++---------
src/value.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
src/value.h | 2 +
5 files changed, 115 insertions(+), 18 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index aa056aa..1b75bf4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2011-01-09 Andreas J. Guelzow <aguelzow pyrshep ca>
+
+ * src/sort.c (sort_compare_cells): add argument and use it to
+ decide whether to use the cacheing version of value_compare
+ (sort_compare_sets): add argument and change all callers
+ (gnm_sort_contents): if we are not in the default locale, do not cache
+ collation keys
+ * src/value.h (value_compare_no_cache): new
+ * src/value.c (value_compare_no_cache): new
+ (value_compare_real): new
+ (value_cmp): use value_compare_real
+ (value_compare): use value_compare_real
+ (gnm_string_cmp): new
+ (gnm_string_cmp_ignorecase): new
+
2011-01-08 Andreas J. Guelzow <aguelzow pyrshep ca>
* src/item-edit.c (item_edit_draw): add NULL argument to call of
diff --git a/NEWS b/NEWS
index f79b56e..4fcee28 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ Andreas:
* Fix leaks in potentially failing analysis tools.
* Make the row and column headers and selection match the theme better.
[#639019]
+ * Fix locale specific sorting. [#638874]
Jean:
* Only disable the formula bar when a chart sheet is selected. [#636031]
diff --git a/src/sort.c b/src/sort.c
index 59e6b98..716bcbe 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -1,3 +1,5 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
/*
* sort.c : Routines for sorting cell ranges
*
@@ -47,7 +49,8 @@ gnm_sort_data_length (GnmSortData const *data)
/* The routines to do the sorting */
static int
-sort_compare_cells (GnmCell const *ca, GnmCell const *cb, GnmSortClause *clause)
+sort_compare_cells (GnmCell const *ca, GnmCell const *cb,
+ GnmSortClause *clause, gboolean default_locale)
{
GnmValue *a, *b;
GnmValueType ta, tb;
@@ -75,7 +78,8 @@ sort_compare_cells (GnmCell const *ca, GnmCell const *cb, GnmSortClause *clause)
} else if (tb == VALUE_ERROR && ta != VALUE_ERROR) {
comp = IS_LESS;
} else {
- comp = value_compare (a, b, clause->cs);
+ comp = default_locale ? value_compare (a, b, clause->cs)
+ : value_compare_no_cache (a, b, clause->cs);
}
if (comp == IS_LESS) {
@@ -88,7 +92,8 @@ sort_compare_cells (GnmCell const *ca, GnmCell const *cb, GnmSortClause *clause)
}
static int
-sort_compare_sets (GnmSortData const *data, int indexa, int indexb)
+sort_compare_sets (GnmSortData const *data, int indexa, int indexb,
+ gboolean default_locale)
{
GnmCell *ca, *cb;
int clause = 0;
@@ -113,7 +118,8 @@ sort_compare_sets (GnmSortData const *data, int indexa, int indexb)
data->range->start.row + offset);
}
- result = sort_compare_cells (ca, cb, &(data->clauses[clause]));
+ result = sort_compare_cells (ca, cb, &(data->clauses[clause]),
+ default_locale);
if (result) {
return result;
}
@@ -130,7 +136,16 @@ sort_qsort_compare (void const *_a, void const *_b)
SortDataPerm const *a = (SortDataPerm const *)_a;
SortDataPerm const *b = (SortDataPerm const *)_b;
- return sort_compare_sets (a->data, a->index, b->index);
+ return sort_compare_sets (a->data, a->index, b->index, TRUE);
+}
+
+static int
+sort_qsort_compare_in_locale (void const *_a, void const *_b)
+{
+ SortDataPerm const *a = (SortDataPerm const *)_a;
+ SortDataPerm const *b = (SortDataPerm const *)_b;
+
+ return sort_compare_sets (a->data, a->index, b->index, FALSE);
}
@@ -285,19 +300,22 @@ gnm_sort_contents (GnmSortData *data, GOCmdContext *cc)
}
if (real_length > 1) {
- char *old_locale = NULL;
-
if (data->locale) {
- old_locale = g_strdup (go_setlocale (LC_ALL, NULL));
+ char *old_locale
+ = g_strdup (go_setlocale (LC_ALL, NULL));
go_setlocale (LC_ALL, data->locale);
- }
- qsort (perm, real_length, sizeof (SortDataPerm), sort_qsort_compare);
+ qsort (perm, real_length, sizeof (SortDataPerm),
+ g_str_has_prefix
+ (old_locale, data->locale)
+ ? sort_qsort_compare
+ : sort_qsort_compare_in_locale);
- if (old_locale) {
go_setlocale (LC_ALL, old_locale);
g_free (old_locale);
- }
+ } else
+ qsort (perm, real_length, sizeof (SortDataPerm),
+ sort_qsort_compare);
}
cur = 0;
diff --git a/src/value.c b/src/value.c
index c9611b6..3600be8 100644
--- a/src/value.c
+++ b/src/value.c
@@ -650,6 +650,12 @@ value_dup (GnmValue const *src)
return res;
}
+static GnmValDiff
+value_compare_real (GnmValue const *a, GnmValue const *b,
+ gboolean case_sensitive,
+ gboolean default_locale);
+
+
/**
* value_cmp :
* @ptr_a :
@@ -662,7 +668,7 @@ value_cmp (void const *ptr_a, void const *ptr_b)
{
GnmValue const *a = *(GnmValue const **)ptr_a;
GnmValue const *b = *(GnmValue const **)ptr_b;
- switch (value_compare (a, b, TRUE)) {
+ switch (value_compare_real (a, b, TRUE, TRUE)) {
case IS_EQUAL : return 0;
case IS_LESS : return -1;
case IS_GREATER : return 1;
@@ -1224,6 +1230,37 @@ value_diff (GnmValue const *a, GnmValue const *b)
}
}
+static int
+gnm_string_cmp (gconstpointer gstr_a, gconstpointer gstr_b)
+{
+ return (gstr_a == gstr_b)
+ ? 0
+ : g_utf8_collate (((GOString const *)gstr_a)->str,
+ ((GOString const *)gstr_b)->str);
+}
+
+static int
+gnm_string_cmp_ignorecase (gconstpointer gstr_a, gconstpointer gstr_b)
+{
+ gchar *a;
+ gchar *b;
+ int res;
+
+ if (gstr_a == gstr_b)
+ return 0;
+
+ a = g_utf8_casefold (((GOString const *)gstr_a)->str, -1);
+ b = g_utf8_casefold (((GOString const *)gstr_b)->str, -1);
+
+ res = g_utf8_collate (a, b);
+
+ g_free (a);
+ g_free (b);
+
+ return res;
+}
+
+
/**
* value_compare :
*
@@ -1233,8 +1270,10 @@ value_diff (GnmValue const *a, GnmValue const *b)
*
* IGNORES format.
*/
-GnmValDiff
-value_compare (GnmValue const *a, GnmValue const *b, gboolean case_sensitive)
+static GnmValDiff
+value_compare_real (GnmValue const *a, GnmValue const *b,
+ gboolean case_sensitive,
+ gboolean default_locale)
{
GnmValueType ta, tb;
int t;
@@ -1263,9 +1302,18 @@ value_compare (GnmValue const *a, GnmValue const *b, gboolean case_sensitive)
/* If both are strings compare as string */
case VALUE_STRING :
- t = case_sensitive
- ? go_string_cmp (a->v_str.val, b->v_str.val)
- : go_string_cmp_ignorecase (a->v_str.val, b->v_str.val);
+ t = (default_locale) ?
+ (case_sensitive
+ ? go_string_cmp
+ (a->v_str.val, b->v_str.val)
+ : go_string_cmp_ignorecase
+ (a->v_str.val, b->v_str.val))
+ : (case_sensitive
+ ? gnm_string_cmp
+ (a->v_str.val, b->v_str.val)
+ : gnm_string_cmp_ignorecase
+ (a->v_str.val, b->v_str.val));
+
if (t > 0)
return IS_GREATER;
else if (t < 0)
@@ -1315,6 +1363,19 @@ value_compare (GnmValue const *a, GnmValue const *b, gboolean case_sensitive)
}
}
+GnmValDiff
+value_compare (GnmValue const *a, GnmValue const *b, gboolean case_sensitive)
+{
+ return value_compare_real (a, b, case_sensitive, TRUE);
+}
+
+GnmValDiff
+value_compare_no_cache (GnmValue const *a, GnmValue const *b,
+ gboolean case_sensitive)
+{
+ return value_compare_real (a, b, case_sensitive, FALSE);
+}
+
void
value_set_fmt (GnmValue *v, GOFormat const *fmt)
{
diff --git a/src/value.h b/src/value.h
index 9ed22da..5aee330 100644
--- a/src/value.h
+++ b/src/value.h
@@ -136,6 +136,8 @@ GnmValue *value_dup (GnmValue const *v);
gnm_float value_diff (GnmValue const *a, GnmValue const *b);
GnmValDiff value_compare (GnmValue const *a, GnmValue const *b,
gboolean case_sensitive);
+GnmValDiff value_compare_no_cache (GnmValue const *a, GnmValue const *b,
+ gboolean case_sensitive);
int value_cmp (void const *ptr_a, void const *ptr_b);
int value_cmp_reverse (void const *ptr_a, void const *ptr_b);
gboolean value_equal (GnmValue const *a, GnmValue const *b);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]