[gcalctool] Fix crash in scientific mode Add new automatic display mode that switches from fixed to scientific w



commit 8f864023cf7fcee2f415928b60883bd80b2ffa7d
Author: Robert Ancell <robert ancell canonical com>
Date:   Mon Nov 29 18:23:31 2010 +1100

    Fix crash in scientific mode
    Add new automatic display mode that switches from fixed to scientific when numbers are too large

 NEWS                                    |    3 ++
 data/org.gnome.gcalctool.gschema.xml.in |    9 +++--
 src/Makefile.am                         |    4 +-
 src/gcalccmd.c                          |    2 +-
 src/gcalctool.c                         |    2 +-
 src/math-buttons.c                      |    4 +-
 src/math-equation.c                     |    4 +-
 src/math-preferences.c                  |    4 ++
 src/math-variables.c                    |    2 +-
 src/mp-binary.c                         |    2 +-
 src/mp-serializer.c                     |   48 ++++++++++++++++++++++---------
 src/mp-serializer.h                     |    9 +++--
 src/unittest.c                          |    2 +-
 13 files changed, 62 insertions(+), 33 deletions(-)
---
diff --git a/NEWS b/NEWS
index 6bda71d..a4d4e9a 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,9 @@ Overview of changes in gcalctool 5.91.3
     * Fix incorrect calculation of tanh
     * Fix dropping of decimal points when thousand separator is '.' (Bug #635517)
     * Improve conversion bar
+    * Fix crash in scientific mode
+    * Add new automatic display mode that switches from fixed to scientific when
+      numbers are too large
 
 Overview of changes in gcalctool 5.91.2
 
diff --git a/data/org.gnome.gcalctool.gschema.xml.in b/data/org.gnome.gcalctool.gschema.xml.in
index 909e4a1..51dfaa0 100644
--- a/data/org.gnome.gcalctool.gschema.xml.in
+++ b/data/org.gnome.gcalctool.gschema.xml.in
@@ -1,9 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <schemalist>
   <enum id="org.gnome.gcalctool.NumberFormat">
-    <value value="0" nick="fixed"/>
-    <value value="1" nick="scientific"/>
-    <value value="2" nick="engineering"/>
+    <value value="0" nick="automatic"/>
+    <value value="1" nick="fixed"/>
+    <value value="2" nick="scientific"/>
+    <value value="3" nick="engineering"/>
   </enum>
   <enum id="org.gnome.gcalctool.ButtonMode">
     <value value="0" nick="basic"/>
@@ -47,7 +48,7 @@
       <_description>Indicates whether any trailing zeroes after the  numeric point should be shown in the display value.</_description>
     </key>
     <key name="number-format" enum="org.gnome.gcalctool.NumberFormat">
-      <default>'fixed'</default>
+      <default>'automatic'</default>
       <_summary>Number format</_summary>
       <_description>The format to display numbers in</_description>
     </key>
diff --git a/src/Makefile.am b/src/Makefile.am
index 0404e3f..070f235 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -93,10 +93,10 @@ mp-equation-lexer.o: mp-equation-parser.h
 mp-equation.c: mp-equation-lexer.h mp-equation-parser.h
 
 # Generate enum types
-math-enums.h: math-enums.h.template
+math-enums.h: math-enums.h.template mp-serializer.h
 	$(AM_V_GEN)$(GLIB_MKENUMS) --template $(srcdir)/math-enums.h.template $(srcdir)/mp-serializer.h > math-enums.h
 
-math-enums.c: math-enums.c.template math-enums.h
+math-enums.c: math-enums.c.template math-enums.h mp-serializer.h
 	$(AM_V_GEN)$(GLIB_MKENUMS) --template $(srcdir)/math-enums.c.template $(srcdir)/mp-serializer.h > math-enums.c
 
 # Fix dependencies
diff --git a/src/gcalccmd.c b/src/gcalccmd.c
index 190df8f..5fb2d45 100644
--- a/src/gcalccmd.c
+++ b/src/gcalccmd.c
@@ -87,7 +87,7 @@ main(int argc, char **argv)
     g_type_init ();
     setlocale(LC_ALL, "");
 
-    result_serializer = mp_serializer_new(10, 9);
+    result_serializer = mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 9);
 
     equation = (char *) malloc(MAXLINE * sizeof(char));
     while (1) {
diff --git a/src/gcalctool.c b/src/gcalctool.c
index f0f3467..b2bb23b 100644
--- a/src/gcalctool.c
+++ b/src/gcalctool.c
@@ -62,7 +62,7 @@ solve(const char *equation)
         exit(1);
     }
     else {
-        result_str = mp_serializer_to_string(mp_serializer_new(10, 9), &result);
+        result_str = mp_serializer_to_string(mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 9), &result);
         printf("%s\n", result_str);
         exit(0);
     }
diff --git a/src/math-buttons.c b/src/math-buttons.c
index 697606a..de3b213 100644
--- a/src/math-buttons.c
+++ b/src/math-buttons.c
@@ -1055,7 +1055,7 @@ load_mode(MathButtons *buttons, ButtonMode mode)
         int i, j;
 
         buttons->priv->convert_result_label = GET_WIDGET(builder, "convert_result_label");
-        buttons->priv->units_serializer = mp_serializer_new(10, 2);
+        buttons->priv->units_serializer = mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 2);
 
         buttons->priv->convert_from_combo = GET_WIDGET(builder, "convert_from_combo");
         from_model = gtk_tree_store_new(3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
@@ -1147,7 +1147,7 @@ load_mode(MathButtons *buttons, ButtonMode mode)
         buttons->priv->target_currency_combo = GET_WIDGET(builder, "target_currency_combo");
         buttons->priv->currency_label = GET_WIDGET(builder, "currency_label");
 
-        buttons->priv->currency_serializer = mp_serializer_new(10, 2);
+        buttons->priv->currency_serializer = mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 2);
 
         model = gtk_list_store_new(1, G_TYPE_STRING);
 
diff --git a/src/math-equation.c b/src/math-equation.c
index 0a431ce..3dbab8d 100644
--- a/src/math-equation.c
+++ b/src/math-equation.c
@@ -1578,7 +1578,7 @@ math_equation_class_init(MathEquationClass *klass)
     g_type_class_add_private(klass, sizeof(MathEquationPrivate));
   
     number_mode_type = g_enum_register_static("NumberMode", number_mode_values);
-    number_format_type = math_display_format_get_type();
+    number_format_type = math_mp_display_format_get_type();
     angle_unit_type = g_enum_register_static("AngleUnit", angle_unit_values);
 
     g_object_class_install_property(object_class,
@@ -1853,7 +1853,7 @@ math_equation_init(MathEquation *equation)
     equation->priv->target_currency = g_strdup(currency_names[0].short_name);
     equation->priv->source_units = g_strdup("");
     equation->priv->target_units = g_strdup("");
-    equation->priv->serializer = mp_serializer_new(10, 9);
+    equation->priv->serializer = mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 9);
     equation->priv->queue = g_async_queue_new();
 
     mp_set_from_integer(0, &equation->priv->state.ans);
diff --git a/src/math-preferences.c b/src/math-preferences.c
index 74b2316..9bc59df 100644
--- a/src/math-preferences.c
+++ b/src/math-preferences.c
@@ -268,6 +268,10 @@ create_gui(MathPreferencesDialog *dialog)
     model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
     gtk_list_store_append(GTK_LIST_STORE(model), &iter);
     gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
+                       /* Number display mode combo: Automatic, e.g. 1234 (or scientific for large number 1.234Ã?10^99) */
+                       _("Automatic"), 1, MP_DISPLAY_FORMAT_AUTOMATIC, -1);
+    gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+    gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
                        /* Number display mode combo: Fixed, e.g. 1234 */
                        _("Fixed"), 1, MP_DISPLAY_FORMAT_FIXED, -1);
     gtk_list_store_append(GTK_LIST_STORE(model), &iter);
diff --git a/src/math-variables.c b/src/math-variables.c
index a57a509..1d9becc 100644
--- a/src/math-variables.c
+++ b/src/math-variables.c
@@ -162,7 +162,7 @@ math_variables_init(MathVariables *variables)
     variables->priv = G_TYPE_INSTANCE_GET_PRIVATE (variables, math_variables_get_type(), MathVariablesPrivate);
     variables->priv->registers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
     variables->priv->file_name = g_build_filename(g_get_user_data_dir(), "gcalctool", "registers", NULL);
-    variables->priv->serializer = mp_serializer_new(10, 50);
+    variables->priv->serializer = mp_serializer_new(MP_DISPLAY_FORMAT_SCIENTIFIC, 10, 50);
     mp_serializer_set_radix(variables->priv->serializer, '.');
     registers_load(variables);
 }
diff --git a/src/mp-binary.c b/src/mp-binary.c
index 7f033db..968a210 100644
--- a/src/mp-binary.c
+++ b/src/mp-binary.c
@@ -46,7 +46,7 @@ to_hex_string(const MPNumber *x)
     MpSerializer *serializer;
     gchar *result;
 
-    serializer = mp_serializer_new(16, 0);
+    serializer = mp_serializer_new(MP_DISPLAY_FORMAT_FIXED, 16, 0);
     result = mp_serializer_to_string(serializer, x);
     g_object_unref(serializer);
 
diff --git a/src/mp-serializer.c b/src/mp-serializer.c
index 79eb942..9d2b052 100644
--- a/src/mp-serializer.c
+++ b/src/mp-serializer.c
@@ -54,9 +54,10 @@ struct MpSerializerPrivate
 G_DEFINE_TYPE(MpSerializer, mp_serializer, G_TYPE_OBJECT);
 
 MpSerializer *
-mp_serializer_new(int base, int accuracy)
+mp_serializer_new(MpDisplayFormat format, int base, int accuracy)
 {
-    MpSerializer *serializer = g_object_new(mp_serializer_get_type(), NULL);
+    MpSerializer *serializer = g_object_new(mp_serializer_get_type(), /*"number-format", format,*/ NULL);
+    mp_serializer_set_number_format(serializer, format);
     mp_serializer_set_base(serializer, base);
     mp_serializer_set_accuracy(serializer, accuracy);
     return serializer;
@@ -273,14 +274,18 @@ mp_cast_to_exponential_string(MpSerializer *serializer, const MPNumber *x, gbool
     g_string_append(string, fixed);
     g_free(fixed);
     if (exponent != 0) {
+        gchar *super_value;
+
         g_string_append_printf(string, "Ã?10"); // FIXME: Use the current base
         if (exponent < 0) {
             exponent = -exponent;
             g_string_append(string, "â?»");
         }
-        snprintf(fixed, 1024, "%d", exponent);
-        for (c = fixed; *c; c++)
+
+        super_value = g_strdup_printf("%d", exponent);
+        for (c = super_value; *c; c++)
             g_string_append(string, super_digits[*c - '0']);
+        g_free (super_value);
     }
 
     result = g_strndup(string->str, string->len + 1);
@@ -293,8 +298,23 @@ mp_cast_to_exponential_string(MpSerializer *serializer, const MPNumber *x, gbool
 gchar *
 mp_serializer_to_string(MpSerializer *serializer, const MPNumber *x)
 {
+    gchar *s0, *s1;
     switch(serializer->priv->format) {
     default:
+    case MP_DISPLAY_FORMAT_AUTOMATIC:
+        s0 = mp_cast_to_string(serializer, x);
+        s1 = mp_cast_to_exponential_string(serializer, x, FALSE);
+        if (g_utf8_strlen(s0, -1) < g_utf8_strlen(s1, -1))
+        {
+            g_free(s1);
+            return s0;
+        }
+        else
+        {
+            g_free(s0);
+            return s1;
+        }
+      break;
     case MP_DISPLAY_FORMAT_FIXED:
         return mp_cast_to_string(serializer, x);
     case MP_DISPLAY_FORMAT_SCIENTIFIC:
@@ -476,7 +496,7 @@ mp_serializer_class_init(MpSerializerClass *klass)
 
     g_type_class_add_private(klass, sizeof(MpSerializerPrivate));
 
-    number_format_type = math_display_format_get_type();
+    number_format_type = math_mp_display_format_get_type();
 
     g_object_class_install_property(object_class,
                                     PROP_SHOW_THOUSANDS_SEPARATORS,
@@ -493,20 +513,20 @@ mp_serializer_class_init(MpSerializerClass *klass)
                                                          FALSE,
                                                          G_PARAM_READWRITE));
     g_object_class_install_property(object_class,
-                                    PROP_BASE,
-                                    g_param_spec_int("base",
-                                                     "base",
-                                                     "Default number base (derived from number-format)",
-                                                     2, 16, 10, 
-                                                     G_PARAM_READWRITE));
-    g_object_class_install_property(object_class,
                                     PROP_NUMBER_FORMAT,
                                     g_param_spec_enum("number-format",
                                                       "number-format",
                                                       "Display format",
                                                       number_format_type,
-                                                      MP_DISPLAY_FORMAT_FIXED,
+                                                      MP_DISPLAY_FORMAT_AUTOMATIC,
                                                       G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_BASE,
+                                    g_param_spec_int("base",
+                                                     "base",
+                                                     "Default number base",
+                                                     2, 16, 10, 
+                                                     G_PARAM_READWRITE));
 }
 
 
@@ -529,5 +549,5 @@ mp_serializer_init(MpSerializer *serializer)
     serializer->priv->accuracy = 9;
     serializer->priv->show_zeroes = FALSE;
     serializer->priv->show_tsep = FALSE;
-    serializer->priv->format = MP_DISPLAY_FORMAT_FIXED;
+    serializer->priv->format = MP_DISPLAY_FORMAT_AUTOMATIC;
 }
diff --git a/src/mp-serializer.h b/src/mp-serializer.h
index 5e2fd28..f4e0a9b 100644
--- a/src/mp-serializer.h
+++ b/src/mp-serializer.h
@@ -42,6 +42,7 @@ typedef struct {
 
 /* Number display mode. */
 typedef enum {
+    MP_DISPLAY_FORMAT_AUTOMATIC,
     MP_DISPLAY_FORMAT_FIXED,
     MP_DISPLAY_FORMAT_SCIENTIFIC,
     MP_DISPLAY_FORMAT_ENGINEERING
@@ -49,20 +50,20 @@ typedef enum {
 
 GType mp_serializer_get_type(void);
 
-MpSerializer *mp_serializer_new(int base, int accuracy);
+MpSerializer *mp_serializer_new(MpDisplayFormat format, int base, int accuracy);
 
 gchar *mp_serializer_to_string(MpSerializer *serializer, const MPNumber *z);
 gboolean mp_serializer_from_string(MpSerializer *serializer, const gchar *str, MPNumber *z);
 
+void mp_serializer_set_number_format(MpSerializer *serializer, MpDisplayFormat format);
+MpDisplayFormat mp_serializer_get_number_format(MpSerializer *serializer);
+
 void mp_serializer_set_base(MpSerializer *serializer, int base);
 int mp_serializer_get_base(MpSerializer *serializer);
 
 void mp_serializer_set_accuracy(MpSerializer *serializer, int accuracy);
 int mp_serializer_get_accuracy(MpSerializer *serializer);
 
-void mp_serializer_set_number_format(MpSerializer *serializer, MpDisplayFormat format);
-MpDisplayFormat mp_serializer_get_number_format(MpSerializer *serializer);
-
 void mp_serializer_set_radix(MpSerializer *serializer, gunichar radix);
 gunichar mp_serializer_get_radix(MpSerializer *serializer);
 
diff --git a/src/unittest.c b/src/unittest.c
index 6652080..40704dc 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -86,7 +86,7 @@ test(char *expression, char *expected, int expected_error)
         char *result_str;
         MpSerializer *serializer;
 
-        serializer = mp_serializer_new(options.base, 9);
+        serializer = mp_serializer_new(MP_DISPLAY_FORMAT_FIXED, options.base, 9);
         result_str = mp_serializer_to_string(serializer, &result);
         g_object_unref(serializer);
 



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