diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mate-calc.c | 3 | ||||
| -rw-r--r-- | src/math-equation.c | 70 | ||||
| -rw-r--r-- | src/math-equation.h | 8 | ||||
| -rw-r--r-- | src/math-preferences.c | 29 | ||||
| -rw-r--r-- | src/mp-convert.c | 23 | ||||
| -rw-r--r-- | src/mp-equation-lexer.l | 2 | ||||
| -rw-r--r-- | src/mp-equation.h | 3 | ||||
| -rw-r--r-- | src/mp.h | 5 | ||||
| -rw-r--r-- | src/preferences.ui | 44 |
9 files changed, 176 insertions, 11 deletions
diff --git a/src/mate-calc.c b/src/mate-calc.c index da95462..91f27eb 100644 --- a/src/mate-calc.c +++ b/src/mate-calc.c @@ -21,6 +21,7 @@ #include "math-window.h" #include "math-preferences.h" +#include "math-equation.h" #include "mp-equation.h" #include "unit-manager.h" #include "utility.h" @@ -219,6 +220,7 @@ int main(int argc, char **argv) show_hist = g_settings_get_boolean(g_settings_var, "show-history"); number_format = g_settings_get_enum(g_settings_var, "number-format"); angle_units = g_settings_get_enum(g_settings_var, "angle-units"); + RadixChar radix_char = g_settings_get_enum(g_settings_var, "radix-char"); button_mode = g_settings_get_enum(g_settings_var, "button-mode"); source_currency = g_settings_get_string(g_settings_var, "source-currency"); target_currency = g_settings_get_string(g_settings_var, "target-currency"); @@ -232,6 +234,7 @@ int main(int argc, char **argv) math_equation_set_show_trailing_zeroes(equation, show_zeroes); math_equation_set_number_format(equation, number_format); math_equation_set_angle_units(equation, angle_units); + math_equation_set_radix_char(equation, radix_char); math_equation_set_source_currency(equation, source_currency); math_equation_set_target_currency(equation, target_currency); math_equation_set_source_units(equation, source_units); diff --git a/src/math-equation.c b/src/math-equation.c index 2ce3ab8..63947b7 100644 --- a/src/math-equation.c +++ b/src/math-equation.c @@ -40,6 +40,7 @@ enum { PROP_BASE, PROP_WORD_SIZE, PROP_ANGLE_UNITS, + PROP_RADIX_CHAR, PROP_SOURCE_CURRENCY, PROP_TARGET_CURRENCY, PROP_SOURCE_UNITS, @@ -47,7 +48,7 @@ enum { PROP_SERIALIZER }; -static GType number_mode_type, number_format_type, angle_unit_type; +static GType number_mode_type, number_format_type, angle_unit_type, radix_char_type; /* Expression mode state */ typedef struct { @@ -67,6 +68,7 @@ struct MathEquationPrivate gint word_size; /* Word size in bits */ MPAngleUnit angle_units; /* Units for trigonometric functions */ + RadixChar radix_char; /* Decimal separator character preference */ char *source_currency; char *target_currency; char *source_units; @@ -274,13 +276,19 @@ reformat_separators(MathEquation *equation) } static void +reformat_separators_cb(gpointer user_data) +{ + reformat_separators(MATH_EQUATION(user_data)); +} + +static void reformat_display(MathEquation *equation) { /* Change ans */ reformat_ans(equation); /* Add/remove thousands separators */ - reformat_separators(equation); + g_idle_add_once(reformat_separators_cb, equation); g_signal_emit_by_name(equation, "display-changed"); } @@ -630,6 +638,34 @@ math_equation_get_angle_units(MathEquation *equation) } void +math_equation_set_radix_char(MathEquation *equation, RadixChar radix_char) +{ + g_return_if_fail(equation != NULL); + if (equation->priv->radix_char == radix_char) + return; + equation->priv->radix_char = radix_char; + + /* Update the serializer radix character and thousands separator */ + if (radix_char == RADIX_COMMA) { + mp_serializer_set_radix(equation->priv->serializer, ','); + mp_serializer_set_thousands_separator(equation->priv->serializer, '.'); + } + else { + mp_serializer_set_radix(equation->priv->serializer, '.'); + mp_serializer_set_thousands_separator(equation->priv->serializer, ','); + } + + g_object_notify(G_OBJECT(equation), "radix-char"); +} + +RadixChar +math_equation_get_radix_char(MathEquation *equation) +{ + g_return_val_if_fail(equation != NULL, RADIX_DOT); + return equation->priv->radix_char; +} + +void math_equation_set_source_currency(MathEquation *equation, const gchar *currency) { g_return_if_fail(equation != NULL); @@ -816,8 +852,7 @@ math_equation_get_equation(MathEquation *equation) } g_free(text); - text = eq_text->str; - g_string_free(eq_text, FALSE); + text = g_string_free(eq_text, FALSE); return text; } @@ -1136,6 +1171,7 @@ parse(MathEquation *equation, const char *text, MPNumber *z, char **error_token) options.base = mp_serializer_get_base(equation->priv->serializer); options.wordlen = equation->priv->word_size; options.angle_units = equation->priv->angle_units; + options.radix_char = (equation->priv->radix_char == RADIX_COMMA) ? ',' : '.'; options.variable_is_defined = variable_is_defined; options.get_variable = get_variable; options.set_variable = set_variable; @@ -1523,6 +1559,9 @@ math_equation_set_property(GObject *object, case PROP_ANGLE_UNITS: math_equation_set_angle_units(self, g_value_get_int(value)); break; + case PROP_RADIX_CHAR: + math_equation_set_radix_char(self, g_value_get_int(value)); + break; case PROP_SOURCE_CURRENCY: math_equation_set_source_currency(self, g_value_get_string(value)); break; @@ -1590,6 +1629,9 @@ math_equation_get_property(GObject *object, case PROP_ANGLE_UNITS: g_value_set_enum(value, self->priv->angle_units); break; + case PROP_RADIX_CHAR: + g_value_set_enum(value, self->priv->radix_char); + break; case PROP_SOURCE_CURRENCY: g_value_set_string(value, self->priv->source_currency); break; @@ -1639,6 +1681,12 @@ math_equation_class_init(MathEquationClass *klass) {MP_GRADIANS, "gradians", "gradians"}, {0, NULL, NULL} }; + static GEnumValue radix_char_values[] = + { + {RADIX_DOT, "dot", "dot"}, + {RADIX_COMMA, "comma", "comma"}, + {0, NULL, NULL} + }; GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->get_property = math_equation_get_property; @@ -1648,6 +1696,7 @@ math_equation_class_init(MathEquationClass *klass) number_mode_type = g_enum_register_static("NumberMode", number_mode_values); number_format_type = math_mp_display_format_get_type(); angle_unit_type = g_enum_register_static("AngleUnit", angle_unit_values); + radix_char_type = g_enum_register_static("RadixChar", radix_char_values); g_object_class_install_property(object_class, PROP_STATUS, @@ -1730,6 +1779,14 @@ math_equation_class_init(MathEquationClass *klass) MP_DEGREES, G_PARAM_READWRITE)); g_object_class_install_property(object_class, + PROP_RADIX_CHAR, + g_param_spec_enum("radix-char", + "radix-char", + "Radix character", + radix_char_type, + RADIX_DOT, + G_PARAM_READWRITE)); + g_object_class_install_property(object_class, PROP_SOURCE_CURRENCY, g_param_spec_string("source-currency", "source-currency", @@ -1879,7 +1936,7 @@ insert_text_cb(MathEquation *equation, equation->priv->state.entered_multiply = strcmp(text, "×") == 0; /* Update thousands separators */ - reformat_separators(equation); + g_idle_add_once(reformat_separators_cb, equation); g_object_notify(G_OBJECT(equation), "display"); } @@ -1896,7 +1953,7 @@ delete_range_cb(MathEquation *equation, equation->priv->state.entered_multiply = FALSE; /* Update thousands separators */ - reformat_separators(equation); + g_idle_add_once(reformat_separators_cb, 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"); @@ -1938,6 +1995,7 @@ math_equation_init(MathEquation *equation) equation->priv->state.status = g_strdup(""); equation->priv->word_size = 32; equation->priv->angle_units = MP_DEGREES; + equation->priv->radix_char = RADIX_DOT; /* Default to dot separator */ // FIXME: Pick based on locale equation->priv->source_currency = g_strdup(""); equation->priv->target_currency = g_strdup(""); diff --git a/src/math-equation.h b/src/math-equation.h index 954334c..af3b67b 100644 --- a/src/math-equation.h +++ b/src/math-equation.h @@ -44,6 +44,11 @@ typedef enum { SUBSCRIPT } NumberMode; +typedef enum { + RADIX_DOT = 0, + RADIX_COMMA = 1 +} RadixChar; + GType math_equation_get_type(void); MathEquation *math_equation_new(void); @@ -84,6 +89,9 @@ gint math_equation_get_word_size(MathEquation *equation); void math_equation_set_angle_units(MathEquation *equation, MPAngleUnit angle_unit); MPAngleUnit math_equation_get_angle_units(MathEquation *equation); +void math_equation_set_radix_char(MathEquation *equation, RadixChar radix_char); +RadixChar math_equation_get_radix_char(MathEquation *equation); + void math_equation_set_source_currency(MathEquation *equation, const gchar *currency); const gchar *math_equation_get_source_currency(MathEquation *equation); diff --git a/src/math-preferences.c b/src/math-preferences.c index 41e43a6..023080c 100644 --- a/src/math-preferences.c +++ b/src/math-preferences.c @@ -95,6 +95,21 @@ word_size_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog) math_equation_set_word_size(dialog->priv->equation, value); } +void radix_char_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog); +G_MODULE_EXPORT +void +radix_char_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog) +{ + RadixChar value; + GtkTreeModel *model; + GtkTreeIter iter; + + model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); + gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter); + gtk_tree_model_get(model, &iter, 1, &value, -1); + math_equation_set_radix_char(dialog->priv->equation, value); +} + void decimal_places_spin_change_value_cb(GtkWidget *spin, MathPreferencesDialog *dialog); G_MODULE_EXPORT void @@ -198,6 +213,13 @@ angle_unit_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *d } static void +radix_char_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog) +{ + set_combo_box_from_int(GET_WIDGET(dialog->priv->ui, "radix_char_combobox"), math_equation_get_radix_char(equation)); + g_settings_set_enum(g_settings_var, "radix-char", math_equation_get_radix_char(equation)); +} + +static void create_gui(MathPreferencesDialog *dialog) { GtkWidget *widget; @@ -275,6 +297,11 @@ create_gui(MathPreferencesDialog *dialog) gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE); gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 0); + widget = GET_WIDGET(dialog->priv->ui, "radix_char_combobox"); + renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE); + gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 0); + /* Label used in preferences dialog. The %d is replaced by a spinbutton */ string = _("Show %d decimal _places"); tokens = g_strsplit(string, "%d", 2); @@ -308,6 +335,7 @@ create_gui(MathPreferencesDialog *dialog) g_signal_connect(dialog->priv->equation, "notify::number-format", G_CALLBACK(number_format_cb), dialog); g_signal_connect(dialog->priv->equation, "notify::word-size", G_CALLBACK(word_size_cb), dialog); g_signal_connect(dialog->priv->equation, "notify::angle-units", G_CALLBACK(angle_unit_cb), dialog); + g_signal_connect(dialog->priv->equation, "notify::radix-char", G_CALLBACK(radix_char_cb), dialog); accuracy_cb(dialog->priv->equation, NULL, dialog); show_thousands_separators_cb(dialog->priv->equation, NULL, dialog); @@ -315,6 +343,7 @@ create_gui(MathPreferencesDialog *dialog) number_format_cb(dialog->priv->equation, NULL, dialog); word_size_cb(dialog->priv->equation, NULL, dialog); angle_unit_cb(dialog->priv->equation, NULL, dialog); + radix_char_cb(dialog->priv->equation, NULL, dialog); } static void diff --git a/src/mp-convert.c b/src/mp-convert.c index 5f097c8..97d4c07 100644 --- a/src/mp-convert.c +++ b/src/mp-convert.c @@ -15,6 +15,7 @@ #include <ctype.h> #include <math.h> #include <langinfo.h> +#include <glib.h> #include "mp.h" @@ -217,8 +218,8 @@ set_from_sexagesimal(const char *str, int length, MPNumber *z) return false; } -bool -mp_set_from_string(const char *str, int default_base, MPNumber *z) +static bool +mp_set_from_string_internal(const char *str, int default_base, gunichar radix_char, MPNumber *z) { int i, base, negate = 0, multiplier = 0, base_multiplier = 1; const char *c, *end; @@ -287,9 +288,10 @@ mp_set_from_string(const char *str, int default_base, MPNumber *z) mp_clear(&fraction); } - if (*c == '.') { + /* Check for the specified radix character */ + if (g_utf8_get_char(c) == radix_char) { has_fraction = TRUE; - c++; + c = g_utf8_next_char(c); } /* Convert fractional part */ @@ -327,3 +329,16 @@ mp_set_from_string(const char *str, int default_base, MPNumber *z) return false; } + +bool +mp_set_from_string_with_radix(const char *str, int default_base, gunichar radix_char, MPNumber *z) +{ + return mp_set_from_string_internal(str, default_base, radix_char, z); +} + +bool +mp_set_from_string(const char *str, int default_base, MPNumber *z) +{ + /* Default to period for backward compatibility */ + return mp_set_from_string_internal(str, default_base, '.', z); +} diff --git a/src/mp-equation-lexer.l b/src/mp-equation-lexer.l index 6899f8f..1cd93ea 100644 --- a/src/mp-equation-lexer.l +++ b/src/mp-equation-lexer.l @@ -103,7 +103,7 @@ IN [iI][nN] {OR} {return tOR;} {XOR} {return tXOR;} {IN} {return tIN;} -{NUMBER} {if (mp_set_from_string(yytext, _mp_equation_get_extra(yyscanner)->options->base, &yylval->int_t) != 0) REJECT; return tNUMBER;} +{NUMBER} {if (mp_set_from_string_with_radix(yytext, _mp_equation_get_extra(yyscanner)->options->base, _mp_equation_get_extra(yyscanner)->options->radix_char, &yylval->int_t) != 0) REJECT; return tNUMBER;} {SUP_NUM} {yylval->integer = super_atoi(yytext); return tSUPNUM;} {NSUP_NUM} {yylval->integer = super_atoi(yytext); return tNSUPNUM;} {SUB_NUM} {yylval->integer = sub_atoi(yytext); return tSUBNUM;} diff --git a/src/mp-equation.h b/src/mp-equation.h index d7eddd3..f5ff19f 100644 --- a/src/mp-equation.h +++ b/src/mp-equation.h @@ -36,6 +36,9 @@ typedef struct { /* Units for angles (e.g. radians, degrees) */ MPAngleUnit angle_units; + /* Radix character to use for decimal separator */ + gunichar radix_char; + // FIXME: // int enable_builtins; @@ -255,6 +255,11 @@ void mp_set_from_random(MPNumber *z); */ bool mp_set_from_string(const char *text, int default_base, MPNumber *z); +/* Sets z from a string representation in 'text' using the specified radix character. + * Returns true on success. + */ +bool mp_set_from_string_with_radix(const char *text, int default_base, gunichar radix_char, MPNumber *z); + /* Returns x as a native single-precision floating point number */ float mp_to_float(const MPNumber *x); diff --git a/src/preferences.ui b/src/preferences.ui index ca1e2da..e19ed33 100644 --- a/src/preferences.ui +++ b/src/preferences.ui @@ -54,6 +54,24 @@ </row> </data> </object> + <object class="GtkListStore" id="number_base_model"> + <columns> + <!-- column-name label --> + <column type="gchararray"/> + <!-- column-name radix_char --> + <column type="gint"/> + </columns> + <data> + <row> + <col id="0" translatable="yes" comments="Radix character combo: use dot as decimal separator and comma as thousands separator">Dot (123,456.789)</col> + <col id="1">0</col> + </row> + <row> + <col id="0" translatable="yes" comments="Radix character combo: use comma as decimal separator and dot as thousands separator">Comma (123.456,789)</col> + <col id="1">1</col> + </row> + </data> + </object> <object class="GtkDialog" id="preferences_dialog"> <property name="can_focus">False</property> <property name="border_width">8</property> @@ -184,6 +202,32 @@ </packing> </child> <child> + <object class="GtkLabel" id="label12"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" comments="Preferences dialog: label for radix and thousands separator combo box">_Separators:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">radix_char_combobox</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">4</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="radix_char_combobox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="model">number_base_model</property> + <signal name="changed" handler="radix_char_combobox_changed_cb" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">4</property> + </packing> + </child> + <child> <object class="GtkAlignment" id="alignment1"> <property name="visible">True</property> <property name="can_focus">False</property> |
