[gnumeric] Sheet filter: make selecting error values work.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Sheet filter: make selecting error values work.
- Date: Fri, 9 Jan 2015 18:32:58 +0000 (UTC)
commit 9f4e5db3113eb5491e03a8849c974978f51f0505
Author: Morten Welinder <terra gnome org>
Date: Fri Jan 9 13:32:34 2015 -0500
Sheet filter: make selecting error values work.
ChangeLog | 5 ++
NEWS | 1 +
src/value.c | 174 +++++++++++++++++++++++++++++++++++++----------------------
3 files changed, 116 insertions(+), 64 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 756b82f..ba4fd5a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2015-01-09 Morten Welinder <terra gnome org>
+
+ * src/value.c (value_compare_real): Rewrite. Handle errors and
+ sort them later than other values. This fixes #742601.
+
2015-01-01 Morten Welinder <terra gnome org>
* src/gui-util.c (gnumeric_message_dialog_create): Use icon theme
diff --git a/NEWS b/NEWS
index ab8537b..c80fe32 100644
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,7 @@ Morten:
* Restore translations of function help texts.
* Fix import of extended float formula results from wk4 files.
* Fix ADDRESS problem.
+ * Fix sheet-filter problem with errors. [#742601]
Thomas Kluyver:
* Fix import of extended floats from wk4 files. [#739679]
diff --git a/src/value.c b/src/value.c
index a475014..62e80a2 100644
--- a/src/value.c
+++ b/src/value.c
@@ -1193,6 +1193,25 @@ compare_float_float (GnmValue const *va, GnmValue const *vb)
return IS_GREATER;
}
+static GnmValDiff
+compare_error_error (GnmValue const *va, GnmValue const *vb)
+{
+ GnmStdError ea = value_error_classify (va);
+ GnmStdError eb = value_error_classify (vb);
+ int i;
+
+ if (ea != eb)
+ return ea < eb ? IS_LESS : IS_GREATER;
+
+ if (ea != GNM_ERROR_UNKNOWN)
+ return IS_EQUAL;
+
+ /* Two unknown errors. Just compare strings. */
+ i = strcmp (value_peek_string (va), value_peek_string (vb));
+ return (i > 0 ? IS_GREATER : (i < 0 ? IS_LESS : IS_EQUAL));
+}
+
+
/**
* value_diff:
* @a: value a
@@ -1300,6 +1319,10 @@ gnm_string_cmp_ignorecase (gconstpointer gstr_a, gconstpointer gstr_b)
}
+/* This depends on the actual values of the enums. */
+#define PAIR(ta_,tb_) ((ta_) + (((tb_) >> 3) - 1))
+#define CPAIR(ta_,tb_) (1 ? PAIR((ta_),(tb_)) : sizeof (struct { int sanity_check[((ta_) >= (tb_)) * 2 - 1];
} ))
+
/*
* value_compare:
*
@@ -1315,7 +1338,8 @@ value_compare_real (GnmValue const *a, GnmValue const *b,
gboolean default_locale)
{
GnmValueType ta, tb;
- int t;
+ gboolean flip;
+ GnmValDiff res;
/* Handle trivial and double NULL case */
if (a == b)
@@ -1324,83 +1348,105 @@ value_compare_real (GnmValue const *a, GnmValue const *b,
ta = VALUE_IS_EMPTY (a) ? VALUE_EMPTY : a->v_any.type;
tb = VALUE_IS_EMPTY (b) ? VALUE_EMPTY : b->v_any.type;
- /* string > empty */
- if (ta == VALUE_STRING) {
- switch (tb) {
- /* Strings are > (empty, or number) */
- case VALUE_EMPTY :
- if (*a->v_str.val->str == '\0')
- return IS_EQUAL;
+ flip = (tb > ta);
+ if (flip) {
+ GnmValueType t = ta;
+ GnmValue const *v = a;
+ ta = tb;
+ tb = t;
+ a = b;
+ b = v;
+ }
- case VALUE_FLOAT:
- return IS_GREATER;
+ switch (PAIR (ta,tb)) {
+ case CPAIR (VALUE_EMPTY,VALUE_EMPTY):
+ g_assert_not_reached(); /* Should have hit trivial case. */
+ return IS_EQUAL;
- /* Strings are < FALSE ?? */
- case VALUE_BOOLEAN :
- return IS_LESS;
+ /* ---------------------------------------- */
- /* If both are strings compare as string */
- case VALUE_STRING :
- 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)
- return IS_LESS;
- else
- return IS_EQUAL;
+ case CPAIR (VALUE_BOOLEAN,VALUE_EMPTY): /* Blank is FALSE */
+ case CPAIR (VALUE_BOOLEAN,VALUE_BOOLEAN):
+ res = compare_bool_bool (a, b);
+ break;
- default :
- return TYPE_MISMATCH;
- }
- } else if (tb == VALUE_STRING) {
- switch (ta) {
- /* (empty, or number) < String */
- case VALUE_EMPTY :
- if (*b->v_str.val->str == '\0')
- return IS_EQUAL;
+ /* ---------------------------------------- */
- case VALUE_FLOAT :
- return IS_LESS;
+ case CPAIR (VALUE_FLOAT,VALUE_BOOLEAN):
+ /* Number < boolean (Why did excel do this ?? ) */
+ res = IS_LESS;
+ break;
+ case CPAIR (VALUE_FLOAT,VALUE_EMPTY): /* Blank is 0 */
+ case CPAIR (VALUE_FLOAT,VALUE_FLOAT):
+ res = compare_float_float (a, b);
+ break;
- /* Strings are < FALSE ?? */
- case VALUE_BOOLEAN :
- return IS_GREATER;
+ /* ---------------------------------------- */
- default :
- return TYPE_MISMATCH;
- }
- }
+ case CPAIR (VALUE_ERROR,VALUE_EMPTY):
+ case CPAIR (VALUE_ERROR,VALUE_BOOLEAN):
+ case CPAIR (VALUE_ERROR,VALUE_FLOAT):
+ /* Error > others */
+ res = IS_GREATER;
+ break;
- /* Booleans > all numbers (Why did excel do this ?? ) */
- if (ta == VALUE_BOOLEAN && tb == VALUE_FLOAT)
- return IS_GREATER;
- if (tb == VALUE_BOOLEAN && ta == VALUE_FLOAT)
- return IS_LESS;
+ case CPAIR (VALUE_ERROR,VALUE_ERROR):
+ res = compare_error_error (a, b);
+ break;
- switch ((ta > tb) ? ta : tb) {
- case VALUE_EMPTY: /* Empty Empty compare */
- return IS_EQUAL;
+ /* ---------------------------------------- */
- case VALUE_BOOLEAN:
- return compare_bool_bool (a, b);
+ case CPAIR (VALUE_STRING,VALUE_EMPTY): /* Blank is empty string */
+ /* String > empty, except empty string */
+ res = a->v_str.val->str[0] == '\0' ? IS_EQUAL : IS_GREATER;
+ break;
+
+ case CPAIR (VALUE_STRING,VALUE_BOOLEAN):
+ /* String < boolean */
+ res = IS_LESS;
+ break;
+
+ case CPAIR (VALUE_STRING,VALUE_FLOAT):
+ /* String > number */
+ res = IS_GREATER;
+ break;
+
+ case CPAIR (VALUE_STRING,VALUE_ERROR):
+ /* String < error */
+ res = IS_LESS;
+ break;
+
+ case CPAIR (VALUE_STRING,VALUE_STRING): {
+ GOString const *sa = a->v_str.val;
+ GOString const *sb = b->v_str.val;
+ int i = (default_locale
+ ? (case_sensitive
+ ? go_string_cmp (sa, sb)
+ : go_string_cmp_ignorecase (sa, sb))
+ : (case_sensitive
+ ? gnm_string_cmp (sa, sb)
+ : gnm_string_cmp_ignorecase (sa, sb)));
+ res = (i > 0 ? IS_GREATER : (i < 0 ? IS_LESS : IS_EQUAL));
+ break;
+ }
+
+ /* ---------------------------------------- */
- case VALUE_FLOAT:
- return compare_float_float (a, b);
default:
- return TYPE_MISMATCH;
+ res = TYPE_MISMATCH;
+ }
+
+ if (flip) {
+ if (res == IS_LESS)
+ res = IS_GREATER;
+ else if (res == IS_GREATER)
+ res = IS_LESS;
}
+
+ return res;
}
+#undef PAIR
+
GnmValDiff
value_compare (GnmValue const *a, GnmValue const *b, gboolean case_sensitive)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]