Support entering super/subscript with numeric keypad (Bug #634904)
[gcalctool.git] / src / unit.c
blob723fd3a45ec5fa2eed00838a9194442302afde48
1 /*
2 * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * Copyright (C) 2008-2011 Robert Ancell.
4 *
5 * This program is free software: you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation, either version 2 of the License, or (at your option) any later
8 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9 * license.
12 #include <string.h>
14 #include "unit.h"
15 #include "mp-serializer.h"
16 #include "mp-equation.h"
17 #include "currency-manager.h" // FIXME: Move out of here
19 struct UnitPrivate
21 gchar *name;
22 gchar *display_name;
23 gchar *format;
24 GList *symbols;
25 gchar *from_function;
26 gchar *to_function;
27 MpSerializer *serializer;
30 G_DEFINE_TYPE (Unit, unit, G_TYPE_OBJECT);
33 Unit *
34 unit_new(const gchar *name,
35 const gchar *display_name,
36 const gchar *format,
37 const gchar *from_function,
38 const gchar *to_function,
39 const gchar *symbols)
41 Unit *unit = g_object_new(unit_get_type(), NULL);
42 gchar **symbol_names;
43 int i;
45 unit->priv->name = g_strdup(name);
46 unit->priv->display_name = g_strdup(display_name);
47 unit->priv->format = g_strdup(format);
48 unit->priv->from_function = g_strdup(from_function);
49 unit->priv->to_function = g_strdup(to_function);
50 symbol_names = g_strsplit(symbols, ",", 0);
51 for (i = 0; symbol_names[i]; i++)
52 unit->priv->symbols = g_list_append(unit->priv->symbols, g_strdup(symbol_names[i]));
53 g_free(symbol_names);
55 return unit;
59 const gchar *
60 unit_get_name(Unit *unit)
62 return unit->priv->name;
66 const gchar *
67 unit_get_display_name(Unit *unit)
69 return unit->priv->display_name;
73 gboolean
74 unit_matches_symbol(Unit *unit, const gchar *symbol)
76 GList *iter;
78 for (iter = unit->priv->symbols; iter; iter = iter->next) {
79 gchar *s = iter->data;
80 if (strcmp(s, symbol) == 0)
81 return TRUE;
84 return FALSE;
88 const GList *
89 unit_get_symbols(Unit *unit)
91 return unit->priv->symbols;
95 static int
96 variable_is_defined(const char *name, void *data)
98 return TRUE;
102 static int
103 get_variable(const char *name, MPNumber *z, void *data)
105 MPNumber *x = data;
106 mp_set_from_mp(x, z);
107 return TRUE;
111 static gboolean
112 solve_function(const gchar *function, const MPNumber *x, MPNumber *z)
114 MPEquationOptions options;
115 int ret;
117 memset(&options, 0, sizeof(options));
118 options.base = 10;
119 options.wordlen = 32;
120 options.variable_is_defined = variable_is_defined;
121 options.get_variable = get_variable;
122 options.callback_data = (void *)x;
123 ret = mp_equation_parse(function, &options, z, NULL);
124 if (ret) {
125 g_warning("Failed to convert value: %s", function);
126 return FALSE;
129 return TRUE;
133 gboolean
134 unit_convert_from(Unit *unit, const MPNumber *x, MPNumber *z)
136 if (unit->priv->from_function)
137 return solve_function(unit->priv->from_function, x, z);
138 else {
139 // FIXME: Hack to make currency work
140 const MPNumber *r;
141 r = currency_manager_get_value(currency_manager_get_default(), unit->priv->name);
142 if (!r)
143 return FALSE;
144 mp_divide(x, r, z);
146 return TRUE;
151 gboolean
152 unit_convert_to(Unit *unit, const MPNumber *x, MPNumber *z)
154 if (unit->priv->from_function)
155 return solve_function(unit->priv->to_function, x, z);
156 else {
157 // FIXME: Hack to make currency work
158 const MPNumber *r;
159 r = currency_manager_get_value(currency_manager_get_default(), unit->priv->name);
160 if (!r)
161 return FALSE;
162 mp_multiply(x, r, z);
164 return TRUE;
169 gchar *
170 unit_format(Unit *unit, MPNumber *x)
172 gchar *number_text, *text;
174 number_text = mp_serializer_to_string(unit->priv->serializer, x);
175 text = g_strdup_printf(unit->priv->format, number_text);
176 g_free(number_text);
178 return text;
182 static void
183 unit_class_init(UnitClass *klass)
185 g_type_class_add_private(klass, sizeof(UnitPrivate));
189 static void
190 unit_init(Unit *unit)
192 unit->priv = G_TYPE_INSTANCE_GET_PRIVATE(unit, unit_get_type(), UnitPrivate);
193 unit->priv->serializer = mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 2);