[gcalctool] Fix broken thousands separators code (Bug #628908)



commit d2d72ebd6b90a61c610b217c6274814e8474e346
Author: Robert Ancell <robert ancell canonical com>
Date:   Wed Oct 20 10:00:11 2010 +1100

    Fix broken thousands separators code (Bug #628908)

 NEWS                |    4 ++
 src/math-equation.c |  123 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/mp-serializer.c |    7 +++
 src/mp-serializer.h |    1 +
 4 files changed, 132 insertions(+), 3 deletions(-)
---
diff --git a/NEWS b/NEWS
index 2fc9656..4ac05d3 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+Overview of changes in gcalctool 5.91.2
+
+    * Fix broken thousands separators code (Bug #628908)
+
 Overview of changes in gcalctool 5.91.1
 
     * Clear display when an answer is displayed and a numeric point is inserted
diff --git a/src/math-equation.c b/src/math-equation.c
index 75e73fc..8bb71fc 100644
--- a/src/math-equation.c
+++ b/src/math-equation.c
@@ -178,12 +178,121 @@ reformat_ans(MathEquation *equation)
     g_free(ans_text);
 }
 
+
+static gint
+count_digits(MathEquation *equation, const gchar *text)
+{
+    const gchar *read_iter;
+    gint count = 0;
+
+    read_iter = text;
+    while (*read_iter != '\0') {
+        if (!g_unichar_isdigit(g_utf8_get_char(read_iter)))
+            return count;
+
+        read_iter = g_utf8_next_char(read_iter);
+
+        /* Allow a thousands separator between digits follow a digit */
+        if (g_utf8_get_char(read_iter) == mp_serializer_get_thousands_separator_text(equation->priv->serializer)) {
+            read_iter = g_utf8_next_char(read_iter);
+            if (!g_unichar_isdigit(g_utf8_get_char(read_iter)))
+                return count;
+        }
+
+        count++;
+    }
+
+    return count;
+}
+
+
+static void
+reformat_separators(MathEquation *equation)
+{
+    gchar *text, *read_iter;
+    gint ans_start, ans_end;
+    gint offset, digit_offset = 0;
+    gboolean in_number = FALSE, in_radix = FALSE, last_is_tsep = FALSE;
+
+    equation->priv->in_undo_operation = TRUE;
+    equation->priv->in_reformat = TRUE;
+
+    text = math_equation_get_display(equation);
+    get_ans_offsets(equation, &ans_start, &ans_end);
+    for (read_iter = text, offset = 0; *read_iter != '\0'; read_iter = g_utf8_next_char(read_iter), offset++) {
+        gunichar c;
+        gboolean expect_tsep;
+
+        /* See what digit this character is */
+        c = g_utf8_get_char(read_iter);
+
+        expect_tsep = mp_serializer_get_show_thousands_separators(equation->priv->serializer) &&
+                      in_number && !in_radix && !last_is_tsep &&
+                      digit_offset > 0 && digit_offset % mp_serializer_get_thousands_separator_count(equation->priv->serializer) == 0;
+        last_is_tsep = FALSE;
+
+        /* Don't mess with ans */
+        if (offset >= ans_start && offset <= ans_end) {
+            in_number = in_radix = FALSE;
+            continue;
+        }
+        if (g_unichar_isdigit(c)) {
+            if (!in_number)
+                digit_offset = count_digits(equation, read_iter);
+            in_number = TRUE;
+
+            /* Expected a thousands separator between these digits - insert it */
+            if (expect_tsep) {
+                GtkTextIter iter;
+                gchar buffer[7];
+                gint len;
+
+                gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &iter, offset);
+                len = g_unichar_to_utf8(mp_serializer_get_thousands_separator_text(equation->priv->serializer), buffer);
+                buffer[len] = '\0';
+                gtk_text_buffer_insert(GTK_TEXT_BUFFER(equation), &iter, buffer, -1);
+                offset++;
+                last_is_tsep = TRUE;
+            }
+
+            digit_offset--;
+        }
+        else if (c == mp_serializer_get_numeric_point_text(equation->priv->serializer)) {
+            in_number = in_radix = TRUE;
+        }
+        else if (c == mp_serializer_get_thousands_separator_text(equation->priv->serializer)) {
+            /* Didn't expect thousands separator - delete it */
+            if (!expect_tsep) {
+                GtkTextIter start, end;
+                gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &start, offset);
+                gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &end, offset + 1);
+                gtk_text_buffer_delete(GTK_TEXT_BUFFER(equation), &start, &end);
+                offset--;
+            }
+            else
+                last_is_tsep = TRUE;            
+        }
+        else {
+            in_number = in_radix = FALSE;
+        }
+    }
+
+    g_free(text);
+
+    equation->priv->in_reformat = FALSE;
+    equation->priv->in_undo_operation = FALSE;
+}
+
+
 static void
 reformat_display(MathEquation *equation, gint old_base)
 {
     /* Change ans */
     reformat_ans(equation);
 
+    /* Add/remove thousands separators */
+    reformat_separators(equation);
+
     g_signal_emit_by_name(equation, "answer-changed");
 }
 
@@ -652,7 +761,7 @@ math_equation_get_number(MathEquation *equation, MPNumber *z)
 }
 
 
-MpSerializer*
+MpSerializer *
 math_equation_get_serializer(MathEquation *equation)
 {
     return equation->priv->serializer;
@@ -1548,8 +1657,8 @@ pre_insert_text_cb(MathEquation  *equation,
 static gboolean
 on_delete(MathEquation *equation)
 {
-  equation->priv->in_delete = FALSE;  
-  return FALSE;
+    equation->priv->in_delete = FALSE;  
+    return FALSE;
 }
 
 
@@ -1593,6 +1702,10 @@ insert_text_cb(MathEquation  *equation,
         return;
 
     equation->priv->state.entered_multiply = strcmp(text, "Ã?") == 0;
+
+    /* Update thousands separators */
+    reformat_separators(equation);
+
     g_object_notify(G_OBJECT(equation), "display");
 }
 
@@ -1607,6 +1720,10 @@ delete_range_cb(MathEquation  *equation,
         return;
 
     equation->priv->state.entered_multiply = FALSE;
+
+    /* Update thousands separators */
+    reformat_separators(equation);
+
     // FIXME: A replace will emit this both for delete-range and insert-text, can it be avoided?
     g_object_notify(G_OBJECT(equation), "display");
 }
diff --git a/src/mp-serializer.c b/src/mp-serializer.c
index 43e3985..4b09971 100644
--- a/src/mp-serializer.c
+++ b/src/mp-serializer.c
@@ -349,6 +349,13 @@ mp_serializer_get_thousands_separator_text(MpSerializer *serializer)
 }
 
 
+gint
+mp_serializer_get_thousands_separator_count(MpSerializer *serializer)
+{
+    return serializer->priv->tsep_count;
+}
+
+
 void
 mp_serializer_set_show_thousands_separators(MpSerializer *serializer, gboolean visible)
 {
diff --git a/src/mp-serializer.h b/src/mp-serializer.h
index cef5c26..4f4bac9 100644
--- a/src/mp-serializer.h
+++ b/src/mp-serializer.h
@@ -55,6 +55,7 @@ void mp_serializer_to_specific_string(const MPNumber *z, int base, int accuracy,
 bool mp_serializer_from_string(MpSerializer *serializer, const char *str, MPNumber *z);
 
 gunichar mp_serializer_get_thousands_separator_text(MpSerializer *serializer);
+gint mp_serializer_get_thousands_separator_count(MpSerializer *serializer);
 gunichar mp_serializer_get_numeric_point_text(MpSerializer *serializer);
 void mp_serializer_set_base(MpSerializer *serializer, int base);
 int mp_serializer_get_base(MpSerializer *serializer);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]