[gcalctool] Improve conversion bar
- From: Robert Ancell <rancell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcalctool] Improve conversion bar
- Date: Mon, 29 Nov 2010 04:40:46 +0000 (UTC)
commit 3ba2f24a8a5de3e58ce8eab1c6e5cfab7568fc11
Author: Robert Ancell <robert ancell canonical com>
Date: Mon Nov 29 13:33:40 2010 +1100
Improve conversion bar
NEWS | 1 +
data/buttons-advanced.ui | 49 ++++++---
data/org.gnome.gcalctool.gschema.xml.in | 10 ++
src/Makefile.am | 6 +-
src/gcalctool.c | 9 ++
src/math-buttons.c | 163 +++++++++++++++++++---------
src/math-equation.c | 81 ++++++++++++--
src/math-equation.h | 6 +
src/mp-equation.c | 176 +-----------------------------
src/units.c | 182 +++++++++++++++++++++++++++++++
src/units.h | 8 ++
11 files changed, 438 insertions(+), 253 deletions(-)
---
diff --git a/NEWS b/NEWS
index ccefe61..6bda71d 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ 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
Overview of changes in gcalctool 5.91.2
diff --git a/data/buttons-advanced.ui b/data/buttons-advanced.ui
index 691c4be..607afdc 100644
--- a/data/buttons-advanced.ui
+++ b/data/buttons-advanced.ui
@@ -12,9 +12,38 @@
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
- <object class="GtkComboBox" id="convert_from_combo">
+ <object class="GtkHBox" id="hbox3">
<property name="visible">True</property>
- <property name="focus_on_click">False</property>
+ <child>
+ <object class="GtkComboBox" id="convert_from_combo">
+ <property name="visible">True</property>
+ <property name="focus_on_click">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" comments="This is between the unit selector dropdowns, for example: meters in kilometers"> in </property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="convert_to_combo">
+ <property name="visible">True</property>
+ <property name="focus_on_click">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">False</property>
@@ -22,25 +51,15 @@
</packing>
</child>
<child>
- <object class="GtkLabel" id="label7">
+ <object class="GtkLabel" id="convert_result_label">
<property name="visible">True</property>
- <property name="label" translatable="yes" comments="This is between the unit selector dropdowns, for example: meters in kilometers"> in </property>
+ <property name="xalign">1</property>
+ <property name="label">1m = 100cm</property>
</object>
<packing>
- <property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
- <child>
- <object class="GtkComboBox" id="convert_to_combo">
- <property name="visible">True</property>
- <property name="focus_on_click">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">2</property>
- </packing>
- </child>
</object>
<packing>
<property name="expand">False</property>
diff --git a/data/org.gnome.gcalctool.gschema.xml.in b/data/org.gnome.gcalctool.gschema.xml.in
index eff5b95..909e4a1 100644
--- a/data/org.gnome.gcalctool.gschema.xml.in
+++ b/data/org.gnome.gcalctool.gschema.xml.in
@@ -71,5 +71,15 @@
<_summary>Target currency</_summary>
<_description>Currency to convert the current calculation into</_description>
</key>
+ <key type="s" name="source-units">
+ <default>'degrees'</default>
+ <_summary>Source units</_summary>
+ <_description>Units of the current calculation</_description>
+ </key>
+ <key type="s" name="target-units">
+ <default>'radians'</default>
+ <_summary>Target units</_summary>
+ <_description>Units to convert the current calculation into</_description>
+ </key>
</schema>
</schemalist>
diff --git a/src/Makefile.am b/src/Makefile.am
index 4691314..0404e3f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,6 +43,8 @@ gcalctool_SOURCES = \
mp-serializer.h \
financial.c \
financial.h \
+ units.c \
+ units.h \
unittest.c \
unittest.h
@@ -61,7 +63,9 @@ gcalccmd_SOURCES = \
mp-serializer.c \
mp-serializer.h\
math-enums.c \
- math-enums.h
+ math-enums.h \
+ units.c \
+ units.h
gcalccmd_LDADD = \
$(GCALCCMD_LIBS) \
diff --git a/src/gcalctool.c b/src/gcalctool.c
index e9121f4..146f270 100644
--- a/src/gcalctool.c
+++ b/src/gcalctool.c
@@ -195,6 +195,8 @@ quit_cb(MathWindow *window)
g_settings_set_enum(settings, "button-mode", math_buttons_get_mode(buttons));
g_settings_set_string(settings, "source-currency", math_equation_get_source_currency(equation));
g_settings_set_string(settings, "target-currency", math_equation_get_target_currency(equation));
+ g_settings_set_string(settings, "source-units", math_equation_get_source_units(equation));
+ g_settings_set_string(settings, "target-units", math_equation_get_target_units(equation));
g_settings_sync();
currency_free_resources();
@@ -212,6 +214,7 @@ main(int argc, char **argv)
MPAngleUnit angle_units;
ButtonMode button_mode;
gchar *source_currency, *target_currency;
+ gchar *source_units, *target_units;
g_type_init();
@@ -236,6 +239,8 @@ main(int argc, char **argv)
button_mode = g_settings_get_enum(settings, "button-mode");
source_currency = g_settings_get_string(settings, "source-currency");
target_currency = g_settings_get_string(settings, "target-currency");
+ source_units = g_settings_get_string(settings, "source-units");
+ target_units = g_settings_get_string(settings, "target-units");
equation = math_equation_new();
math_equation_set_accuracy(equation, accuracy);
@@ -246,8 +251,12 @@ main(int argc, char **argv)
math_equation_set_angle_units(equation, angle_units);
math_equation_set_source_currency(equation, source_currency);
math_equation_set_target_currency(equation, target_currency);
+ math_equation_set_source_units(equation, source_units);
+ math_equation_set_target_units(equation, target_units);
g_free(source_currency);
g_free(target_currency);
+ g_free(source_units);
+ g_free(target_units);
gtk_init(&argc, &argv);
diff --git a/src/math-buttons.c b/src/math-buttons.c
index 209d900..bdf2f13 100644
--- a/src/math-buttons.c
+++ b/src/math-buttons.c
@@ -22,6 +22,7 @@
#include "financial.h"
#include "currency.h"
#include "mp-serializer.h"
+#include "units.h"
enum {
PROP_0,
@@ -56,7 +57,7 @@ struct MathButtonsPrivate
GtkWidget *convert_from_combo;
GtkWidget *convert_to_combo;
- gchar *previous_ans;
+ GtkWidget *convert_result_label;
GtkWidget *base_combo;
GtkWidget *base_label;
@@ -313,12 +314,12 @@ static char *finc_dialog_fields[][5] = {
#define MAX_UNITS 20
struct Unit {
- char* ui_name;
- char* internal_name;
+ char *ui_name;
+ char *internal_name;
};
struct UnitCategory {
- char* name;
+ char *name;
struct Unit units[MAX_UNITS];
};
@@ -337,7 +338,7 @@ static struct UnitCategory categories[] = {
/* Length unit */
{N_("Light Years"), "lightyears"},
/* Length unit */
- {N_("Astronomical Unit"), "au"},
+ {N_("Astronomical Units"), "au"},
/* Length unit */
{N_("Nautical Miles"), "nm"},
/* Length unit */
@@ -617,10 +618,47 @@ update_currency_label(MathButtons *buttons)
static void
+update_conversion_bar(MathButtons *buttons)
+{
+ MPNumber x, z;
+ gboolean enabled;
+ gchar *label;
+ const gchar *source_units, *target_units;
+ char *source_value, *target_value;
+
+ if (!buttons->priv->convert_result_label)
+ return;
+
+ enabled = math_equation_get_number(buttons->priv->equation, &x);
+
+ source_units = math_equation_get_source_units(buttons->priv->equation);
+ target_units = math_equation_get_target_units(buttons->priv->equation);
+ if (!source_units || !target_units)
+ enabled = FALSE;
+ else if (!units_convert(&x, source_units, target_units, &z))
+ enabled = FALSE;
+
+ gtk_widget_set_sensitive(buttons->priv->convert_result_label, enabled);
+ if (!enabled)
+ return;
+
+ mp_serializer_to_specific_string(&x, 10, 2, TRUE, TRUE, &source_value);
+ mp_serializer_to_specific_string(&z, 10, 2, TRUE, TRUE, &target_value);
+
+ label = g_strdup_printf("%s %s = %s %s", source_value, source_units, target_value, target_units);
+ gtk_label_set_text(GTK_LABEL(buttons->priv->convert_result_label), label);
+ g_free(source_value);
+ g_free(target_value);
+ g_free(label);
+}
+
+
+static void
display_changed_cb(MathEquation *equation, GParamSpec *spec, MathButtons *buttons)
{
update_currency_label(buttons);
update_bit_panel(buttons);
+ update_conversion_bar(buttons);
}
@@ -628,76 +666,98 @@ static void
convert_from_combobox_changed_cb(GtkWidget *combo, MathButtons *buttons)
{
GtkTreeModel *model;
- GtkTreeIter iter, unittype;
- int typeindex, i;
+ GtkTreeIter iter;
+ int typeindex, unitindex, i;
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, &typeindex, 2, &unitindex, -1);
- if (!gtk_tree_model_iter_parent(model, &unittype, &iter))
- return;
-
- gtk_tree_model_get(model, &unittype, 1, &typeindex, -1);
-
- model = GTK_TREE_MODEL(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT));
+ model = GTK_TREE_MODEL(gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT));
for (i = 0; categories[typeindex].units[i].ui_name != NULL; i++) {
+ if (i == unitindex)
+ continue;
gtk_list_store_append(GTK_LIST_STORE(model), &iter);
- gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, categories[typeindex].units[i].ui_name, 1, i, -1);
+ gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, categories[typeindex].units[i].ui_name, 1, typeindex, 2, i, -1);
}
gtk_combo_box_set_model(GTK_COMBO_BOX(buttons->priv->convert_to_combo), model);
+
+ math_equation_set_source_units(buttons->priv->equation, categories[typeindex].units[unitindex].internal_name);
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(buttons->priv->convert_to_combo), 0);
}
static void
-convert_to_combobox_changed_cb(GtkWidget *combo, MathButtons *buttons)
+source_units_changed_cb(MathEquation *equation, GParamSpec *spec, MathButtons *buttons)
{
GtkTreeModel *model;
- GtkTreeIter iter, catiter;
- gchar *from, *to, *display;
- int category, fromindex, toindex;
-
- 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, &toindex, -1);
+ GtkTreeIter iter;
model = gtk_combo_box_get_model(GTK_COMBO_BOX(buttons->priv->convert_from_combo));
- gtk_combo_box_get_active_iter(GTK_COMBO_BOX(buttons->priv->convert_from_combo), &iter);
- if (!gtk_tree_model_iter_parent(model, &catiter, &iter))
+ if (!gtk_tree_model_get_iter_first(model, &iter))
return;
+ do
+ {
+ GtkTreeIter child_iter;
- gtk_tree_model_get(model, &catiter, 1, &category, -1);
- gtk_tree_model_get(model, &iter, 1, &fromindex, -1);
+ if (gtk_tree_model_iter_children(model, &child_iter, &iter))
+ {
+ do
+ {
+ gint i, j;
+
+ gtk_tree_model_get(model, &child_iter, 1, &i, 2, &j, -1);
+ if (strcmp(categories[i].units[j].internal_name, math_equation_get_source_units(equation)) == 0)
+ {
+ gtk_combo_box_set_active_iter(GTK_COMBO_BOX(buttons->priv->convert_from_combo), &child_iter);
+ update_conversion_bar(buttons);
+ return;
+ }
+ } while (gtk_tree_model_iter_next(model, &child_iter));
+ }
+ } while (gtk_tree_model_iter_next(model, &iter));
+}
- from = categories[category].units[fromindex].internal_name;
- to = categories[category].units[toindex].internal_name;
- if (buttons->priv->previous_ans == NULL) {
- display = math_equation_get_display(buttons->priv->equation);
- buttons->priv->previous_ans = display;
- }
- else {
- display = buttons->priv->previous_ans;
- }
- math_equation_set(buttons->priv->equation, g_strdup_printf("%s %s in %s", display, from, to));
+static void
+convert_to_combobox_changed_cb(GtkWidget *combo, MathButtons *buttons)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ int category, toindex;
+
+ 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, &category, 2, &toindex, -1);
+ math_equation_set_target_units(buttons->priv->equation, categories[category].units[toindex].internal_name);
}
+
static void
-update_conversion_combos(MathEquation *equation, MathButtons *buttons)
+target_units_changed_cb(MathEquation *equation, GParamSpec *spec, MathButtons *buttons)
{
GtkTreeModel *model;
GtkTreeIter iter;
- model = gtk_combo_box_get_model(GTK_COMBO_BOX(buttons->priv->convert_from_combo));
- gtk_tree_model_get_iter_first(model, &iter);
- gtk_combo_box_set_active_iter(GTK_COMBO_BOX(buttons->priv->convert_from_combo), &iter);
-
- model = GTK_TREE_MODEL(gtk_list_store_new(1, G_TYPE_STRING));
- gtk_combo_box_set_model(GTK_COMBO_BOX(buttons->priv->convert_to_combo), model);
+ model = gtk_combo_box_get_model(GTK_COMBO_BOX(buttons->priv->convert_to_combo));
+ if (!gtk_tree_model_get_iter_first(model, &iter))
+ return;
+ do
+ {
+ gint i, j;
- g_free(buttons->priv->previous_ans);
- buttons->priv->previous_ans = NULL;
+ gtk_tree_model_get(model, &iter, 1, &i, 2, &j, -1);
+ if (strcmp(categories[i].units[j].internal_name, math_equation_get_target_units(equation)) == 0)
+ {
+ gtk_combo_box_set_active_iter(GTK_COMBO_BOX(buttons->priv->convert_to_combo), &iter);
+ update_conversion_bar(buttons);
+ return;
+ }
+ } while (gtk_tree_model_iter_next(model, &iter));
}
+
static void
base_combobox_changed_cb(GtkWidget *combo, MathButtons *buttons)
{
@@ -992,10 +1052,10 @@ load_mode(MathButtons *buttons, ButtonMode mode)
GtkCellRenderer *renderer;
int i, j;
-// buttons->priv->angle_label = GET_WIDGET(builder, "angle_label");
+ buttons->priv->convert_result_label = GET_WIDGET(builder, "convert_result_label");
buttons->priv->convert_from_combo = GET_WIDGET(builder, "convert_from_combo");
- from_model = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
+ from_model = gtk_tree_store_new(3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
gtk_combo_box_set_model(GTK_COMBO_BOX(buttons->priv->convert_from_combo), GTK_TREE_MODEL(from_model));
for (i = 0; i < sizeof(categories) / sizeof(categories[0]); i++) {
@@ -1003,7 +1063,7 @@ load_mode(MathButtons *buttons, ButtonMode mode)
gtk_tree_store_set(from_model, &parent, 0, categories[i].name, 1, i, -1);
for (j = 0; categories[i].units[j].ui_name != NULL; j++) {
gtk_tree_store_append(from_model, &iter, &parent);
- gtk_tree_store_set(from_model, &iter, 0, categories[i].units[j].ui_name, 1, j, -1);
+ gtk_tree_store_set(from_model, &iter, 0, categories[i].units[j].ui_name, 1, i, 2, j, -1);
}
}
renderer = gtk_cell_renderer_text_new();
@@ -1021,7 +1081,10 @@ load_mode(MathButtons *buttons, ButtonMode mode)
g_signal_connect(buttons->priv->convert_from_combo, "changed", G_CALLBACK(convert_from_combobox_changed_cb), buttons);
g_signal_connect(buttons->priv->convert_to_combo, "changed", G_CALLBACK(convert_to_combobox_changed_cb), buttons);
- g_signal_connect(buttons->priv->equation, "answer-changed", G_CALLBACK(update_conversion_combos), buttons);
+ g_signal_connect(buttons->priv->equation, "notify::source-units", G_CALLBACK(source_units_changed_cb), buttons);
+ g_signal_connect(buttons->priv->equation, "notify::target-units", G_CALLBACK(target_units_changed_cb), buttons);
+ source_units_changed_cb(buttons->priv->equation, NULL, buttons);
+ target_units_changed_cb(buttons->priv->equation, NULL, buttons);
}
if (mode == PROGRAMMING) {
diff --git a/src/math-equation.c b/src/math-equation.c
index 7764eed..7bbb3da 100644
--- a/src/math-equation.c
+++ b/src/math-equation.c
@@ -49,6 +49,8 @@ enum {
PROP_ANGLE_UNITS,
PROP_SOURCE_CURRENCY,
PROP_TARGET_CURRENCY,
+ PROP_SOURCE_UNITS,
+ PROP_TARGET_UNITS,
PROP_SERIALIZER
};
@@ -76,6 +78,8 @@ struct MathEquationPrivate
MPAngleUnit angle_units; /* Units for trigonometric functions */
char *source_currency;
char *target_currency;
+ char *source_units;
+ char *target_units;
NumberMode number_mode; /* ??? */
gboolean can_super_minus; /* TRUE if entering minus can generate a superscript minus */
@@ -292,8 +296,6 @@ reformat_display(MathEquation *equation, gint old_base)
/* Add/remove thousands separators */
reformat_separators(equation);
-
- g_signal_emit_by_name(equation, "answer-changed");
}
@@ -649,6 +651,7 @@ math_equation_set_source_currency(MathEquation *equation, const gchar *currency)
g_object_notify(G_OBJECT(equation), "source-currency");
}
+
const gchar *
math_equation_get_source_currency(MathEquation *equation)
{
@@ -679,6 +682,41 @@ math_equation_get_target_currency(MathEquation *equation)
void
+math_equation_set_source_units(MathEquation *equation, const gchar *units)
+{
+ if (strcmp(equation->priv->source_units, units) == 0)
+ return;
+ g_free(equation->priv->source_units);
+ equation->priv->source_units = g_strdup(units);
+ g_object_notify(G_OBJECT(equation), "source-units");
+}
+
+const gchar *
+math_equation_get_source_units(MathEquation *equation)
+{
+ return equation->priv->source_units;
+}
+
+
+void
+math_equation_set_target_units(MathEquation *equation, const gchar *units)
+{
+ if (strcmp(equation->priv->target_units, units) == 0)
+ return;
+ g_free(equation->priv->target_units);
+ equation->priv->target_units = g_strdup(units);
+ g_object_notify(G_OBJECT(equation), "target-units");
+}
+
+
+const gchar *
+math_equation_get_target_units(MathEquation *equation)
+{
+ return equation->priv->target_units;
+}
+
+
+void
math_equation_set_status(MathEquation *equation, const gchar *status)
{
if (strcmp(equation->priv->state.status, status) == 0)
@@ -1177,7 +1215,6 @@ math_equation_look_for_answer(gpointer data)
}
g_slice_free(SolveData, result);
- g_signal_emit_by_name(equation, "answer-changed");
return false;
}
@@ -1419,6 +1456,12 @@ math_equation_set_property(GObject *object,
case PROP_TARGET_CURRENCY:
math_equation_set_target_currency(self, g_value_get_string(value));
break;
+ case PROP_SOURCE_UNITS:
+ math_equation_set_source_units(self, g_value_get_string(value));
+ break;
+ case PROP_TARGET_UNITS:
+ math_equation_set_target_units(self, g_value_get_string(value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@@ -1481,6 +1524,12 @@ math_equation_get_property(GObject *object,
case PROP_TARGET_CURRENCY:
g_value_set_string(value, self->priv->target_currency);
break;
+ case PROP_SOURCE_UNITS:
+ g_value_set_string(value, self->priv->source_units);
+ break;
+ case PROP_TARGET_UNITS:
+ g_value_set_string(value, self->priv->target_units);
+ break;
case PROP_SERIALIZER:
g_value_set_object(value, self->priv->serializer);
break;
@@ -1627,22 +1676,26 @@ math_equation_class_init(MathEquationClass *klass)
"",
G_PARAM_READWRITE));
g_object_class_install_property(object_class,
+ PROP_SOURCE_UNITS,
+ g_param_spec_string("source-units",
+ "source-units",
+ "Source Units",
+ "",
+ G_PARAM_READWRITE));
+ g_object_class_install_property(object_class,
+ PROP_TARGET_UNITS,
+ g_param_spec_string("target-units",
+ "target-units",
+ "target Units",
+ "",
+ G_PARAM_READWRITE));
+ g_object_class_install_property(object_class,
PROP_SERIALIZER,
g_param_spec_object("serializer",
"serializer",
"Serializer",
MP_TYPE_SERIALIZER,
G_PARAM_READABLE));
-
- g_signal_new("answer-changed",
- G_TYPE_FROM_CLASS(object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
}
@@ -1798,6 +1851,8 @@ math_equation_init(MathEquation *equation)
// FIXME: Pick based on locale
equation->priv->source_currency = g_strdup(currency_names[0].short_name);
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();
equation->priv->queue = g_async_queue_new();
diff --git a/src/math-equation.h b/src/math-equation.h
index 066413f..697324a 100644
--- a/src/math-equation.h
+++ b/src/math-equation.h
@@ -97,6 +97,12 @@ const gchar *math_equation_get_source_currency(MathEquation *equation);
void math_equation_set_target_currency(MathEquation *equation, const gchar *currency);
const gchar *math_equation_get_target_currency(MathEquation *equation);
+void math_equation_set_source_units(MathEquation *equation, const gchar *units);
+const gchar *math_equation_get_source_units(MathEquation *equation);
+
+void math_equation_set_target_units(MathEquation *equation, const gchar *units);
+const gchar *math_equation_get_target_units(MathEquation *equation);
+
gboolean math_equation_in_solve(MathEquation *equation);
const MPNumber *math_equation_get_answer(MathEquation *equation);
diff --git a/src/mp-equation.c b/src/mp-equation.c
index d09c64e..1e443ab 100644
--- a/src/mp-equation.c
+++ b/src/mp-equation.c
@@ -22,6 +22,7 @@
#include "mp-equation-private.h"
#include "mp-equation-parser.h"
#include "mp-equation-lexer.h"
+#include "units.h"
extern int _mp_equation_parse(yyscan_t yyscanner);
@@ -246,184 +247,11 @@ get_function(MPEquationParserState *state, const char *name, const MPNumber *x,
static int
-do_convert(const char *units[][2], const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z)
-{
- int x_index, z_index;
- MPNumber x_factor, z_factor;
-
- for (x_index = 0; units[x_index][0] != NULL && strcmp(units[x_index][0], x_units) != 0; x_index++);
- if (units[x_index][0] == NULL)
- return 0;
- for (z_index = 0; units[z_index][0] != NULL && strcmp(units[z_index][0], z_units) != 0; z_index++);
- if (units[z_index][0] == NULL)
- return 0;
-
- mp_set_from_string(units[x_index][1], 10, &x_factor);
- mp_set_from_string(units[z_index][1], 10, &z_factor);
- mp_multiply(x, &x_factor, z);
- mp_divide(z, &z_factor, z);
-
- return 1;
-}
-
-
-static int
convert(MPEquationParserState *state, const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z)
{
- const char *angle_units[][2] = {
- /* FIXME: Approximations of 1/(units in a circle)
- * Therefore, 360 deg != 400 grads */
- {"grad", "0.0025"},
- {"gradian", "0.0025"},
- {"gradians", "0.0025"},
- {"deg", "0.002777778"},
- {"degree", "0.002777778"},
- {"degrees", "0.002777778"},
- {"rad", "0.159154943"},
- {"radian", "0.159154943"},
- {"radians", "0.159154943"},
- {NULL, NULL}
- };
-
- const char *length_units[][2] = {
- {"parsec", "30857000000000000"},
- {"parsecs", "30857000000000000"},
- {"pc", "30857000000000000"},
- {"lightyear", "9460730472580800"},
- {"lightyears", "9460730472580800"},
- {"ly", "9460730472580800"},
- {"au", "149597870691"},
- {"nm", "1852000"},
- {"mile", "1609.344"},
- {"miles", "1609.344"},
- {"mi", "1609.344"},
- {"kilometer", "1000"},
- {"kilometers", "1000"},
- {"km", "1000"},
- {"kms", "1000"},
- {"cable", "219.456"},
- {"cables", "219.456"},
- {"cb", "219.456"},
- {"fathom", "1.8288"},
- {"fathoms", "1.8288"},
- {"ftm", "1.8288"},
- {"meter", "1"},
- {"meters", "1"},
- {"m", "1"},
- {"yard", "0.9144"},
- {"yards", "0.9144"},
- {"yd", "0.9144"},
- {"foot", "0.3048"},
- {"feet", "0.3048"},
- {"ft", "0.3048"},
- {"inch", "0.0254"},
- {"inches", "0.0254"},
- {"centimeter", "0.01"},
- {"centimeters", "0.01"},
- {"cm", "0.01"},
- {"cms", "0.01"},
- {"millimeter", "0.001"},
- {"millimeters", "0.001"},
- {"mm", "0.001"},
- {"micrometer", "0.000001"},
- {"micrometers", "0.000001"},
- {"um", "0.000001"},
- {"nanometer", "0.000000001"},
- {"nanometers", "0.000000001"},
- {NULL, NULL}
- };
-
- const char *area_units[][2] = {
- {"hectare", "10000"},
- {"hectares", "10000"},
- {"acre", "4046.8564224"},
- {"acres", "4046.8564224"},
- {"m²", "1"},
- {"cm²", "0.001"},
- {"mm²", "0.000001"},
- {NULL, NULL}
- };
-
- const char *volume_units[][2] = {
- {"m³", "1000"},
- {"gallon", "3.785412"},
- {"gallons", "3.785412"},
- {"gal", "3.785412"},
- {"litre", "1"},
- {"litres", "1"},
- {"liter", "1"},
- {"liters", "1"},
- {"L", "1"},
- {"quart", "0.9463529"},
- {"quarts", "0.9463529"},
- {"qt", "0.9463529"},
- {"pint", "0.4731765"},
- {"pints", "0.4731765"},
- {"pt", "0.4731765"},
- {"millilitre", "0.001"},
- {"millilitres", "0.001"},
- {"milliliter", "0.001"},
- {"milliliters", "0.001"},
- {"mL", "0.001"},
- {"cm³", "0.001"},
- {"mm³", "0.000001"},
- {NULL, NULL}
- };
-
- const char *weight_units[][2] = {
- {"tonne", "1000"},
- {"tonnes", "1000"},
- {"kilograms", "1"},
- {"kilogramme", "1"},
- {"kilogrammes", "1"},
- {"kg", "1"},
- {"kgs", "1"},
- {"pound", "0.45359237"},
- {"pounds", "0.45359237"},
- {"lb", "0.45359237"},
- {"ounce", "0.02834952"},
- {"ounces", "0.02834952"},
- {"oz", "0.02834952"},
- {"gram", "0.001"},
- {"grams", "0.001"},
- {"gramme", "0.001"},
- {"grammes", "0.001"},
- {"g", "0.001"},
- {NULL, NULL}
- };
-
- const char *time_units[][2] = {
- {"year", "31557600"},
- {"years", "31557600"},
- {"day", "86400"},
- {"days", "86400"},
- {"hour", "3600"},
- {"hours", "3600"},
- {"minute", "60"},
- {"minutes", "60"},
- {"second", "1"},
- {"seconds", "1"},
- {"s", "1"},
- {"millisecond", "0.001"},
- {"milliseconds", "0.001"},
- {"ms", "0.001"},
- {"microsecond", "0.000001"},
- {"microseconds", "0.000001"},
- {"us", "0.000001"},
- {NULL, NULL}
- };
-
- if (do_convert(angle_units, x, x_units, z_units, z) ||
- do_convert(length_units, x, x_units, z_units, z) ||
- do_convert(area_units, x, x_units, z_units, z) ||
- do_convert(volume_units, x, x_units, z_units, z) ||
- do_convert(weight_units, x, x_units, z_units, z) ||
- do_convert(time_units, x, x_units, z_units, z))
+ if (!units_convert(x, x_units, z_units, z))
return 1;
- if (state->options->convert)
- return state->options->convert(x, x_units, z_units, z, state->options->callback_data);
-
return 0;
}
diff --git a/src/units.c b/src/units.c
new file mode 100644
index 0000000..6fc4bd8
--- /dev/null
+++ b/src/units.c
@@ -0,0 +1,182 @@
+#include <string.h>
+
+#include "units.h"
+
+static const char *angle_units[][2] = {
+ /* FIXME: Approximations of 1/(units in a circle)
+ * Therefore, 360 deg != 400 grads */
+ {"grad", "0.0025"},
+ {"gradian", "0.0025"},
+ {"gradians", "0.0025"},
+ {"deg", "0.002777778"},
+ {"degree", "0.002777778"},
+ {"degrees", "0.002777778"},
+ {"rad", "0.159154943"},
+ {"radian", "0.159154943"},
+ {"radians", "0.159154943"},
+ {NULL, NULL}
+};
+
+static const char *length_units[][2] = {
+ {"parsec", "30857000000000000"},
+ {"parsecs", "30857000000000000"},
+ {"pc", "30857000000000000"},
+ {"lightyear", "9460730472580800"},
+ {"lightyears", "9460730472580800"},
+ {"ly", "9460730472580800"},
+ {"au", "149597870691"},
+ {"nm", "1852000"},
+ {"mile", "1609.344"},
+ {"miles", "1609.344"},
+ {"mi", "1609.344"},
+ {"kilometer", "1000"},
+ {"kilometers", "1000"},
+ {"km", "1000"},
+ {"kms", "1000"},
+ {"cable", "219.456"},
+ {"cables", "219.456"},
+ {"cb", "219.456"},
+ {"fathom", "1.8288"},
+ {"fathoms", "1.8288"},
+ {"ftm", "1.8288"},
+ {"meter", "1"},
+ {"meters", "1"},
+ {"m", "1"},
+ {"yard", "0.9144"},
+ {"yards", "0.9144"},
+ {"yd", "0.9144"},
+ {"foot", "0.3048"},
+ {"feet", "0.3048"},
+ {"ft", "0.3048"},
+ {"inch", "0.0254"},
+ {"inches", "0.0254"},
+ {"centimeter", "0.01"},
+ {"centimeters", "0.01"},
+ {"cm", "0.01"},
+ {"cms", "0.01"},
+ {"millimeter", "0.001"},
+ {"millimeters", "0.001"},
+ {"mm", "0.001"},
+ {"micrometer", "0.000001"},
+ {"micrometers", "0.000001"},
+ {"um", "0.000001"},
+ {"nanometer", "0.000000001"},
+ {"nanometers", "0.000000001"},
+ {NULL, NULL}
+};
+
+static const char *area_units[][2] = {
+ {"hectare", "10000"},
+ {"hectares", "10000"},
+ {"acre", "4046.8564224"},
+ {"acres", "4046.8564224"},
+ {"m²", "1"},
+ {"cm²", "0.001"},
+ {"mm²", "0.000001"},
+ {NULL, NULL}
+};
+
+static const char *volume_units[][2] = {
+ {"m³", "1000"},
+ {"gallon", "3.785412"},
+ {"gallons", "3.785412"},
+ {"gal", "3.785412"},
+ {"litre", "1"},
+ {"litres", "1"},
+ {"liter", "1"},
+ {"liters", "1"},
+ {"L", "1"},
+ {"quart", "0.9463529"},
+ {"quarts", "0.9463529"},
+ {"qt", "0.9463529"},
+ {"pint", "0.4731765"},
+ {"pints", "0.4731765"},
+ {"pt", "0.4731765"},
+ {"millilitre", "0.001"},
+ {"millilitres", "0.001"},
+ {"milliliter", "0.001"},
+ {"milliliters", "0.001"},
+ {"mL", "0.001"},
+ {"cm³", "0.001"},
+ {"mm³", "0.000001"},
+ {NULL, NULL}
+};
+
+static const char *weight_units[][2] = {
+ {"tonne", "1000"},
+ {"tonnes", "1000"},
+ {"kilograms", "1"},
+ {"kilogramme", "1"},
+ {"kilogrammes", "1"},
+ {"kg", "1"},
+ {"kgs", "1"},
+ {"pound", "0.45359237"},
+ {"pounds", "0.45359237"},
+ {"lb", "0.45359237"},
+ {"ounce", "0.02834952"},
+ {"ounces", "0.02834952"},
+ {"oz", "0.02834952"},
+ {"gram", "0.001"},
+ {"grams", "0.001"},
+ {"gramme", "0.001"},
+ {"grammes", "0.001"},
+ {"g", "0.001"},
+ {NULL, NULL}
+};
+
+static const char *time_units[][2] = {
+ {"year", "31557600"},
+ {"years", "31557600"},
+ {"day", "86400"},
+ {"days", "86400"},
+ {"hour", "3600"},
+ {"hours", "3600"},
+ {"minute", "60"},
+ {"minutes", "60"},
+ {"second", "1"},
+ {"seconds", "1"},
+ {"s", "1"},
+ {"millisecond", "0.001"},
+ {"milliseconds", "0.001"},
+ {"ms", "0.001"},
+ {"microsecond", "0.000001"},
+ {"microseconds", "0.000001"},
+ {"us", "0.000001"},
+ {NULL, NULL}
+};
+
+static gboolean
+do_convert(const char *units[][2], const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z)
+{
+ int x_index, z_index;
+ MPNumber x_factor, z_factor;
+
+ for (x_index = 0; units[x_index][0] != NULL && strcmp(units[x_index][0], x_units) != 0; x_index++);
+ if (units[x_index][0] == NULL)
+ return FALSE;
+ for (z_index = 0; units[z_index][0] != NULL && strcmp(units[z_index][0], z_units) != 0; z_index++);
+ if (units[z_index][0] == NULL)
+ return FALSE;
+
+ mp_set_from_string(units[x_index][1], 10, &x_factor);
+ mp_set_from_string(units[z_index][1], 10, &z_factor);
+ mp_multiply(x, &x_factor, z);
+ mp_divide(z, &z_factor, z);
+
+ return TRUE;
+}
+
+
+gboolean
+units_convert(const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z)
+{
+ if (do_convert(angle_units, x, x_units, z_units, z) ||
+ do_convert(length_units, x, x_units, z_units, z) ||
+ do_convert(area_units, x, x_units, z_units, z) ||
+ do_convert(volume_units, x, x_units, z_units, z) ||
+ do_convert(weight_units, x, x_units, z_units, z) ||
+ do_convert(time_units, x, x_units, z_units, z))
+ return TRUE;
+
+ return FALSE;
+}
diff --git a/src/units.h b/src/units.h
new file mode 100644
index 0000000..715b111
--- /dev/null
+++ b/src/units.h
@@ -0,0 +1,8 @@
+#ifndef UNITS_H
+#define UNITS_H
+
+#include "mp.h"
+
+gboolean units_convert(const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z);
+
+#endif /* UNITS_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]