[gcalctool] More GObject refactoring
- From: Robert Ancell <rancell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcalctool] More GObject refactoring
- Date: Thu, 8 Apr 2010 08:50:03 +0000 (UTC)
commit 78da2055527ffbd5dc2cc5780545c694e8f9500f
Author: Robert Ancell <robert ancell gmail com>
Date: Thu Apr 8 18:46:32 2010 +1000
More GObject refactoring
data/buttons-programming.ui | 88 ---
data/gcalctool.ui | 2 +-
src/financial.c | 2 +-
src/math-buttons.c | 67 +-
src/math-display.c | 179 ++----
src/math-equation.c | 1652 ++++++++++++++++---------------------------
src/math-equation.h | 31 +-
src/mp-convert.c | 6 +-
src/mp-equation-lexer.l | 2 +-
src/ui.c | 11 +
10 files changed, 732 insertions(+), 1308 deletions(-)
---
diff --git a/data/buttons-programming.ui b/data/buttons-programming.ui
index 41e9931..0554bba 100644
--- a/data/buttons-programming.ui
+++ b/data/buttons-programming.ui
@@ -3113,94 +3113,6 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="calc_base_2_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="border_width">3</property>
- <property name="focus_on_click">False</property>
- <child internal-child="accessible">
- <object class="AtkObject" id="calc_base_2_button-atkobject">
- <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the base 2 button">Base 2</property>
- </object>
- </child>
- <signal name="clicked" handler="base_cb"/>
- <child>
- <object class="GtkLabel" id="base_2_label">
- <property name="visible">True</property>
- <property name="label"><i>x</i><sub>2</sub></property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="left_attach">3</property>
- <property name="right_attach">4</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
- <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="calc_base_8_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="border_width">3</property>
- <property name="focus_on_click">False</property>
- <child internal-child="accessible">
- <object class="AtkObject" id="calc_base_8_button-atkobject">
- <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the base 8 button">Base 8</property>
- </object>
- </child>
- <signal name="clicked" handler="base_cb"/>
- <child>
- <object class="GtkLabel" id="base_8_label">
- <property name="visible">True</property>
- <property name="label"><i>x</i><sub>8</sub></property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="left_attach">4</property>
- <property name="right_attach">5</property>
- <property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
- <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="calc_base_16_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="border_width">3</property>
- <property name="focus_on_click">False</property>
- <child internal-child="accessible">
- <object class="AtkObject" id="calc_base_16_button-atkobject">
- <property name="AtkObject::accessible-name" translatable="yes" comments="Accessible name for the base 16 button">Base 16</property>
- </object>
- </child>
- <signal name="clicked" handler="base_cb"/>
- <child>
- <object class="GtkLabel" id="base_16_label">
- <property name="visible">True</property>
- <property name="label"><i>x</i><sub>16</sub></property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="left_attach">4</property>
- <property name="right_attach">5</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
- <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
- </packing>
- </child>
- <child>
<object class="GtkButton" id="calc_character_button">
<property name="label">á</property>
<property name="visible">True</property>
diff --git a/data/gcalctool.ui b/data/gcalctool.ui
index 64beae7..30df304 100644
--- a/data/gcalctool.ui
+++ b/data/gcalctool.ui
@@ -10,7 +10,7 @@
<accel-groups>
<group name="accelgroup1"/>
</accel-groups>
- <signal name="key_press_event" handler="main_window_key_press_cb"/>
+ <signal name="key_press_event" handler="main_window_key_press_cb" after="yes"/>
<signal name="delete_event" handler="quit_cb"/>
<child>
<object class="GtkVBox" id="window_vbox">
diff --git a/src/financial.c b/src/financial.c
index b855f21..94a21c0 100644
--- a/src/financial.c
+++ b/src/financial.c
@@ -290,5 +290,5 @@ do_finc_expression(MathEquation *equation, int function, MPNumber *arg1, MPNumbe
calc_term(equation, &result, arg1, arg2, arg3);
break;
}
- display_set_number(equation, &result);
+ math_equation_set_number(equation, &result);
}
diff --git a/src/math-buttons.c b/src/math-buttons.c
index 85656d6..71269c7 100644
--- a/src/math-buttons.c
+++ b/src/math-buttons.c
@@ -49,6 +49,7 @@ struct MathButtonsPrivate
GList *superscript_toggles;
GList *subscript_toggles;
+ guint64 bits;
GtkWidget *bit_panel;
GtkWidget *bit_labels[MAXBITS];
@@ -384,9 +385,6 @@ load_mode(MathButtons *buttons, ButtonMode mode)
set_tint(GET_WIDGET(builder, "subscript_togglebutton"), &buttons->priv->colour_numbers, 2);
set_tint(GET_WIDGET(builder, "superscript_togglebutton"), &buttons->priv->colour_numbers, 2);
set_tint(GET_WIDGET(builder, "calc_exponential_button"), &buttons->priv->colour_numbers, 2);
- set_tint(GET_WIDGET(builder, "calc_base_2_button"), &buttons->priv->colour_numbers, 1);
- set_tint(GET_WIDGET(builder, "calc_base_8_button"), &buttons->priv->colour_numbers, 1);
- set_tint(GET_WIDGET(builder, "calc_base_16_button"), &buttons->priv->colour_numbers, 1);
set_tint(GET_WIDGET(builder, "calc_result_button"), &buttons->priv->colour_action, 2);
set_tint(GET_WIDGET(builder, "calc_factor_button"), &buttons->priv->colour_action, 2);
@@ -432,11 +430,6 @@ load_mode(MathButtons *buttons, ButtonMode mode)
set_tint(GET_WIDGET(builder, "calc_twos_complement_button"), &buttons->priv->colour_function, 1);
set_tint(GET_WIDGET(builder, "calc_not_button"), &buttons->priv->colour_function, 1);
- /* Set base button data */
- set_int_data(builder, "calc_base_2_button", "base", 2);
- set_int_data(builder, "calc_base_8_button", "base", 8);
- set_int_data(builder, "calc_base_16_button", "base", 16);
-
if (mode == PROGRAMMING) {
buttons->priv->character_code_dialog = GET_WIDGET(builder, "character_code_dialog");
buttons->priv->character_code_entry = GET_WIDGET(builder, "character_code_entry");
@@ -499,14 +492,6 @@ math_buttons_get_mode(MathButtons *buttons)
G_MODULE_EXPORT
void
-base_cb(GtkWidget *widget, MathButtons *buttons)
-{
- math_equation_set_base(buttons->priv->equation, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "base")));
-}
-
-
-G_MODULE_EXPORT
-void
exponent_cb(GtkWidget *widget, MathButtons *buttons)
{
math_equation_insert_exponent(buttons->priv->equation);
@@ -1001,7 +986,7 @@ currency_cb(GtkWidget *widget, MathButtons *buttons)
win = GTK_DIALOG(gtk_builder_get_object(buttons->priv->financial_ui, "currency_dialog"));
c_amount_upper = GTK_SPIN_BUTTON(gtk_builder_get_object(buttons->priv->financial_ui, "currency_amount_upper"));
c_amount_lower = GTK_SPIN_BUTTON(gtk_builder_get_object(buttons->priv->financial_ui, "currency_amount_lower"));
- if (display_is_usable_number(buttons->priv->equation, &display_val)) {
+ if (math_equation_get_number(buttons->priv->equation, &display_val)) {
double start_val = mp_cast_to_double(&display_val);
gtk_spin_button_set_value(c_amount_upper, start_val);
}
@@ -1014,7 +999,7 @@ currency_cb(GtkWidget *widget, MathButtons *buttons)
mp_set_from_string(result, &display_val);
g_free(result);
- display_set_number(buttons->priv->equation, &display_val);
+ math_equation_set_number(buttons->priv->equation, &display_val);
}
gtk_widget_hide(GTK_WIDGET(win));
@@ -1029,8 +1014,23 @@ character_code_dialog_response_cb(GtkWidget *dialog, gint response_id, MathButto
text = gtk_entry_get_text(GTK_ENTRY(buttons->priv->character_code_entry));
- if (response_id == GTK_RESPONSE_OK)
- math_equation_insert_character(buttons->priv->equation, text);
+ if (response_id == GTK_RESPONSE_OK) {
+ MPNumber x;
+ int i = 0;
+
+ mp_set_from_integer(0, &x);
+ while (TRUE) {
+ mp_add_integer(&x, text[i], &x);
+ if (text[i+1]) {
+ mp_shift(&x, 8, &x);
+ i++;
+ }
+ else
+ break;
+ }
+
+ math_equation_insert_number(buttons->priv->equation, text);
+ }
gtk_widget_hide(dialog);
}
@@ -1086,20 +1086,31 @@ set_subscript_cb(GtkWidget *widget, MathButtons *buttons)
static void
-bitfield_changed_cb(MathEquation *equation, MathButtons *buttons)
+display_changed_cb(MathEquation *equation, MathButtons *buttons)
{
+ gboolean enabled;
+ MPNumber x;
int i;
- const gchar *label;
- guint64 bits;
if (!buttons->priv->bit_panel)
return;
- gtk_widget_set_sensitive(buttons->priv->bit_panel, math_equation_get_bitfield_enabled(equation));
+ enabled = math_equation_get_number(equation, &x);
+ if (enabled) {
+ MPNumber max;
- bits = math_equation_get_bitfield(equation);
+ mp_set_from_unsigned_integer(G_MAXUINT64, &max);
+ if (mp_is_negative(&x) || mp_is_greater_than(&x, &max))
+ enabled = FALSE;
+ else
+ buttons->priv->bits = mp_cast_to_unsigned_int(&x);
+ }
+
+ gtk_widget_set_sensitive(buttons->priv->bit_panel, enabled);
for (i = 0; i < MAXBITS; i++) {
- if (bits & (1LL << (MAXBITS-i-1)))
+ const gchar *label;
+
+ if (buttons->priv->bits & (1LL << (MAXBITS-i-1)))
label = " 1";
else
label = " 0";
@@ -1141,7 +1152,9 @@ math_buttons_set_property (GObject *object,
case PROP_EQUATION:
self->priv->equation = g_value_get_object (value);
g_signal_connect(self->priv->equation, "number-mode-changed", G_CALLBACK(number_mode_changed_cb), self);
- g_signal_connect(self->priv->equation, "bitfield-changed", G_CALLBACK(bitfield_changed_cb), self);
+ g_signal_connect(self->priv->equation, "display-changed", G_CALLBACK(display_changed_cb), self);
+ number_mode_changed_cb(self->priv->equation, self);
+ display_changed_cb(self->priv->equation, self);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
diff --git a/src/math-display.c b/src/math-display.c
index 9724576..a76af4d 100644
--- a/src/math-display.c
+++ b/src/math-display.c
@@ -21,7 +21,6 @@
#include <gdk/gdkkeysyms.h>
#include "math-display.h"
-#include "ui.h" // FIXME: TEMP
enum {
PROP_0,
@@ -55,41 +54,42 @@ math_display_get_equation(MathDisplay *display)
static gboolean
-check_for_localized_numeric_point(MathDisplay *display, int keyval)
+display_key_press_cb(GtkWidget *widget, GdkEventKey *event, MathDisplay *display)
{
- gchar outbuf[10]; /* Minumum size 6. */
- gunichar ch;
+ int state;
+ guint32 c;
- ch = gdk_keyval_to_unicode(keyval);
- g_return_val_if_fail(g_unichar_validate(ch), FALSE);
-
- outbuf[g_unichar_to_utf8(ch, outbuf)] = '\0';
-
- return (strcmp(outbuf, math_equation_get_numeric_point_text(display->priv->equation)) == 0);
-}
-
-
-// FIXME: Should be able to replace by making display can_default
-G_MODULE_EXPORT
-gboolean
-main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, GCalctoolUI *ui)
-{
- MathDisplay *display;
- int i, state;
- const char *conversions[] = {"*", "/", NULL};
- const char *conversion_values[] = {"�", "÷", NULL };
-
- display = ui_get_display(ui);
-
- /* Only look at the modifiers we use */
state = event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK);
+ c = gdk_keyval_to_unicode(event->keyval);
- // FIXME: Convert event to character
- // FIXME: Or safer to intercept characters as they enter the text input (handles input methods)
+ /* Solve on enter */
+ if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) {
+ math_equation_solve(display->priv->equation);
+ return TRUE;
+ }
- if (check_for_localized_numeric_point(display, event->keyval) == TRUE) {
- event->state = 0;
- event->keyval = GDK_KP_Decimal;
+ /* Clear on escape */
+ if ((event->keyval == GDK_Escape && state == 0) ||
+ (event->keyval == GDK_BackSpace && state == GDK_CONTROL_MASK) ||
+ (event->keyval == GDK_Delete && state == GDK_SHIFT_MASK)) {
+ math_equation_clear(display->priv->equation);
+ return TRUE;
+ }
+
+ /* Substitute */
+ if (state == 0) {
+ if (c == '*') {
+ math_equation_insert(display->priv->equation, "Ã?");
+ return TRUE;
+ }
+ if (c == '/') {
+ math_equation_insert(display->priv->equation, "÷");
+ return TRUE;
+ }
+ if (c == '-') {
+ math_equation_insert_subtract(display->priv->equation);
+ return TRUE;
+ }
}
/* Shortcuts */
@@ -126,8 +126,12 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, GCalctoolUI *ui)
case GDK_u:
math_equation_insert(display->priv->equation, "µ");
return TRUE;
+ case GDK_minus:
+ math_equation_insert(display->priv->equation, "â?»");
+ return TRUE;
}
}
+
if (state == GDK_CONTROL_MASK || math_equation_get_number_mode(display->priv->equation) == SUPERSCRIPT) {
switch(event->keyval)
{
@@ -199,105 +203,21 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, GCalctoolUI *ui)
}
}
- /* Delete in display */
- if (event->keyval == GDK_Delete && state == 0 && (event->state & GDK_SHIFT_MASK) == 0) {
- math_equation_delete(display->priv->equation);
- return TRUE;
- }
- if (event->keyval == GDK_BackSpace && state == 0 && (event->state & GDK_SHIFT_MASK) == 0) {
- math_equation_backspace(display->priv->equation);
- return TRUE;
- }
-
- /* Clear display */
- if ((event->keyval == GDK_Escape && state == 0) ||
- (event->keyval == GDK_BackSpace && state == GDK_CONTROL_MASK) ||
- (event->keyval == GDK_Delete && state == GDK_SHIFT_MASK)) {
- math_equation_clear(display->priv->equation);
- return TRUE;
- }
-
- /* Solve */
- if ((event->keyval == GDK_Return && state == 0) ||
- (event->keyval == GDK_KP_Enter && state == 0)) {
- if (gtk_widget_has_focus(display->priv->display_item)) {
- math_equation_solve(display->priv->equation);
- return TRUE;
- }
- else {
- return FALSE;
- }
- }
-
- if (state == GDK_CONTROL_MASK && event->keyval == GDK_minus)
- {
- math_equation_insert(display->priv->equation, "â?»");
- return TRUE;
- }
-
- if (state != 0)
- return FALSE;
-
- // FIXME: event->string deprecated
-
- if (strcmp(event->string, "-") == 0 || strcmp(event->string, "â??") == 0) {
- math_equation_insert_subtract(display->priv->equation);
- return TRUE;
- }
-
- for (i = 0; conversions[i]; i++) {
- if (strcmp(event->string, conversions[i]) == 0) {
- math_equation_insert(display->priv->equation, conversion_values[i]);
- return TRUE;
- }
- }
- if (strcmp(event->string, ".") == 0) {
- math_equation_insert_numeric_point(display->priv->equation);
- return TRUE;
- }
-
- /* Some keyboards use this keyval for '^' (e.g. German) */
- if (event->keyval == GDK_dead_circumflex) {
- math_equation_insert(display->priv->equation, "^");
- return TRUE;
- }
-
- switch(*event->string)
- {
- case '<':
- // FIXME: Should open left shift menu (programming mode)
- return TRUE;
- case '>':
- // FIXME: Should open right shift menu (programming mode)
- return TRUE;
- case '\n':
- math_equation_solve(display->priv->equation);
- return TRUE;
- }
-
- /* Don't override space - it is used in UI */
- if (event->string[0] == ' ' && !gtk_widget_has_focus(display->priv->display_item))
- return FALSE;
-
- if (event->string[0] != '\0') {
- math_equation_insert(display->priv->equation, event->string);
- return TRUE;
- }
-
return FALSE;
}
-// FIXME: Kill this
-static void
-popup_paste_cb(GtkWidget *menu, MathDisplay *display)
+static gboolean
+key_press_cb(MathDisplay *display, GdkEventKey *event)
{
- math_equation_paste(display->priv->equation);
+ gboolean result;
+ g_signal_emit_by_name(display->priv->display_item, "key-press-event", event, &result);
+ return result;
}
static gboolean
-middle_click_paste_cb(GtkWidget *widget, GdkEventButton *event, MathDisplay *display)
+button_release_cb(GtkWidget *widget, GdkEventButton *event, MathDisplay *display)
{
if (event->button == 2)
math_equation_paste(display->priv->equation);
@@ -307,13 +227,6 @@ middle_click_paste_cb(GtkWidget *widget, GdkEventButton *event, MathDisplay *dis
static void
-paste_cb(GtkWidget *widget, MathDisplay *display)
-{
- math_equation_paste(display->priv->equation);
-}
-
-
-static void
status_changed_cb(MathEquation *equation, MathDisplay *display)
{
gtk_text_buffer_set_text(display->priv->info_buffer, math_equation_get_status(equation), -1);
@@ -323,17 +236,19 @@ status_changed_cb(MathEquation *equation, MathDisplay *display)
static void
create_gui(MathDisplay *display)
{
- GtkWidget *vbox, *info_view;
+ GtkWidget *event_box, *info_view;
PangoFontDescription *font_desc;
+
+ g_signal_connect(display, "key-press-event", G_CALLBACK(key_press_cb), display);
display->priv->display_item = gtk_text_view_new_with_buffer(GTK_TEXT_BUFFER(display->priv->equation));
- gtk_text_view_set_editable(GTK_TEXT_VIEW(display->priv->display_item), FALSE);
+ gtk_text_view_set_accepts_tab(GTK_TEXT_VIEW(display->priv->display_item), FALSE);
gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(display->priv->display_item), 8);
gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(display->priv->display_item), 2);
gtk_text_view_set_right_margin(GTK_TEXT_VIEW(display->priv->display_item), 6);
gtk_text_view_set_justification(GTK_TEXT_VIEW(display->priv->display_item), GTK_JUSTIFY_RIGHT);
- g_signal_connect(display->priv->display_item, "button-release-event", G_CALLBACK(middle_click_paste_cb), display);
- g_signal_connect(display->priv->display_item, "paste-clipboard", G_CALLBACK(paste_cb), display);
+ g_signal_connect(display->priv->display_item, "key-press-event", G_CALLBACK(display_key_press_cb), display);
+ g_signal_connect(display->priv->display_item, "button-release-event", G_CALLBACK(button_release_cb), display);
gtk_box_pack_start(GTK_BOX(display), display->priv->display_item, TRUE, TRUE, 0);
gtk_widget_ensure_style(display->priv->display_item);
diff --git a/src/math-equation.c b/src/math-equation.c
index 2f617ba..ec0b941 100644
--- a/src/math-equation.c
+++ b/src/math-equation.c
@@ -36,48 +36,36 @@
enum {
- STATUS_CHANGED,
- BITFIELD_CHANGED,
+ STATUS_CHANGED, // FIXME: Use g_object_notify and signal notify::status
+ DISPLAY_CHANGED,
NUMBER_MODE_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
-#define MAX_DIGITS 200
-#define UNDO_HISTORY_LENGTH 16 /* Arithmetic mode undo history length */
-#define MAX_DISPLAY 512
+#define MAX_DIGITS 512
/* Expression mode state */
typedef struct {
- MPNumber ans; /* Previously calculated answer */
- char *expression; /* Expression entered by user */
- int ans_start, ans_end; /* Start and end characters for ans variable in expression */
- int cursor;
+ MPNumber ans; /* Previously calculated answer */
+ gchar *expression; /* Expression entered by user */
+ gint ans_start, ans_end; /* Start and end characters for ans variable in expression */
+ gint cursor; /* ??? */
+ NumberMode number_mode; /* ??? */
+ gboolean can_super_minus; /* TRUE if entering minus can generate a superscript minus */
+ gboolean entered_multiply; /* Last insert was a multiply character */
} MathEquationState;
-/* Circular list of Arithmetic Precedence Mode states*/
-typedef struct {
- unsigned int begin;
- unsigned int end;
- unsigned int current;
- MathEquationState e[UNDO_HISTORY_LENGTH]; /* Expression mode state */
-} MathEquationHistory;
-
struct MathEquationPrivate
{
- gchar *status; /* ??? */
-
- guint64 bitfield; // FIXME: Move into ui-buttons.c
- gboolean bitfield_enabled; // FIXME: Move into ui-buttons.c
- char localized[MAX_DIGITS]; // FIXME: Obsolete now a TextBuffer
- gint cursor; // FIXME: Obsolete now a TextBuffer
+ gchar *status; /* Status text */
int show_tsep; /* Set if the thousands separator should be shown. */
int show_zeroes; /* Set if trailing zeroes should be shown. */
DisplayFormat format; /* Number display mode. */
int accuracy; /* Number of digits to show */
- int word_size; /* ??? */
- MPAngleUnit angle_unit; /* ??? */
+ int word_size; /* Word size in bits */
+ MPAngleUnit angle_unit; /* Units for trigonometric functions */
NumberMode number_mode; /* ??? */
gboolean can_super_minus; /* TRUE if entering minus can generate a superscript minus */
@@ -86,10 +74,10 @@ struct MathEquationPrivate
const char *tsep; /* Locale specific thousands separator. */
int tsep_count; /* Number of digits between separator. */
- char *last_text; /* Last text entered */
-
- MathEquationHistory h; /* History of expression mode states */
+ MathEquationState state; /* Equation state */
+ GList *history; /* History of expression mode states */
+ // FIXME: Replace with GtkClipboard
GdkAtom clipboard_atom; /* ??? */
GdkAtom primary_atom; /* ??? */
char *shelf; /* PUT selection shelf contents. */
@@ -97,25 +85,6 @@ struct MathEquationPrivate
G_DEFINE_TYPE (MathEquation, math_equation, GTK_TYPE_TEXT_BUFFER);
-/* Available functions */
-//FIXME: Obsolete
-enum
-{
- FN_TEXT,
- FN_CALCULATE,
- FN_CLEAR,
- FN_BACKSPACE,
- FN_DELETE,
- FN_TOGGLE_BIT,
- FN_SHIFT,
- FN_FACTORIZE,
- FN_STORE,
- FN_RECALL,
- FN_UNDO,
- FN_REDO,
- FN_PASTE,
- FN_INSERT_CHARACTER
-};
MathEquation *
math_equation_new()
@@ -124,986 +93,524 @@ math_equation_new()
}
-const gchar *
-math_equation_get_digit_text(MathEquation *equation, guint digit)
+//FIXME
+static void
+display_refresh(MathEquation *equation)
{
- return equation->priv->digits[digit];
-}
-
+ GtkTextIter iter;
-const gchar *
-math_equation_get_numeric_point_text(MathEquation *equation)
-{
- return equation->priv->radix;
+ /*FIXME
+ equation->priv->cursor = display_get_cursor(equation);
+ display_make_text(equation, equation->priv->localized, MAX_DIGITS, &equation->priv->cursor);
+ gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation), equation->priv->localized, -1);
+ if (equation->priv->cursor < 0)
+ gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(equation), &iter);
+ else
+ gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &iter, equation->priv->cursor);
+ gtk_text_buffer_place_cursor(GTK_TEXT_BUFFER(equation), &iter);*/
}
-void
-math_equation_set_status(MathEquation *equation, const gchar *status)
+static void
+display_push(MathEquation *equation)
{
- g_free(equation->priv->status);
- equation->priv->status = g_strdup(status);
- g_signal_emit(equation, signals[STATUS_CHANGED], 0);
-}
+ MathEquationState *state;
+ state = g_malloc0(sizeof(MathEquationState));
+ equation->priv->history = g_list_prepend(equation->priv->history, state);
-const gchar *
-math_equation_get_status(MathEquation *equation)
-{
- return equation->priv->status;
+ mp_set_from_mp(&equation->priv->state.ans, &state->ans);
+ state->expression = math_equation_get_display(equation);
+ state->ans_start = equation->priv->state.ans_start;
+ state->ans_end = equation->priv->state.ans_end;
+ g_object_get(G_OBJECT(equation), "cursor-position", &state->cursor, NULL);
+ state->number_mode = equation->priv->number_mode;
+ state->can_super_minus = equation->priv->can_super_minus;
+ state->entered_multiply = equation->priv->state.entered_multiply;
}
static void
-math_equation_set_bitfield(MathEquation *equation, gboolean enabled, guint64 bitfield)
+display_pop(MathEquation *equation)
{
- equation->priv->bitfield_enabled = enabled;
- equation->priv->bitfield = bitfield;
- g_signal_emit(equation, signals[BITFIELD_CHANGED], 0);
-}
-
+ GList *link;
+ MathEquationState *state;
+ GtkTextIter cursor;
-gboolean
-math_equation_get_bitfield_enabled(MathEquation *equation)
-{
- return equation->priv->bitfield_enabled;
-}
+ if (!equation->priv->history) {
+ math_equation_set_status(equation,
+ /* Error shown when trying to undo with no undo history */
+ _("No undo history"));
+ return;
+ }
+ link = equation->priv->history;
+ equation->priv->history = g_list_remove_link(equation->priv->history, link);
+ state = link->data;
+ g_list_free(link);
-guint64
-math_equation_get_bitfield(MathEquation *equation)
-{
- return equation->priv->bitfield;
+ gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation), state->expression, -1);
+ gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &cursor, state->cursor);
+ gtk_text_buffer_place_cursor(GTK_TEXT_BUFFER(equation), &cursor);
+ equation->priv->state.ans_start = state->ans_start;
+ equation->priv->state.ans_end = state->ans_end;
+ math_equation_set_number_mode(equation, state->number_mode);
+ equation->priv->can_super_minus = state->can_super_minus;
+ equation->priv->state.entered_multiply = state->entered_multiply;
+ g_free(state->expression);
+ g_free(state);
}
const gchar *
-math_equation_get_text(MathEquation *equation)
+math_equation_get_digit_text(MathEquation *equation, guint digit)
{
- return equation->priv->localized;
+ return equation->priv->digits[digit];
}
-gint
-math_equation_get_cursor(MathEquation *equation)
+const gchar *
+math_equation_get_numeric_point_text(MathEquation *equation)
{
- return equation->priv->cursor;
+ return equation->priv->radix;
}
void
-math_equation_set_number_mode(MathEquation *equation, NumberMode mode)
-{
- if (equation->priv->number_mode == mode)
- return;
-
- equation->priv->can_super_minus = mode == SUPERSCRIPT;
-
- equation->priv->number_mode = mode;
- g_signal_emit(equation, signals[NUMBER_MODE_CHANGED], 0);
-}
-
-
-NumberMode
-math_equation_get_number_mode(MathEquation *equation)
+math_equation_set_accuracy(MathEquation *equation, int accuracy)
{
- return equation->priv->number_mode;
+ equation->priv->accuracy = accuracy;
+ display_refresh(equation);
}
-static void display_do_function(MathEquation *equation, int function, gpointer arg, int cursor_start, int cursor_end);
-
-static void
-do_button(MathEquation *equation, int function, gpointer arg)
+int
+math_equation_get_accuracy(MathEquation *equation)
{
- GtkTextIter start, end;
- gint cursor_start, cursor_end;
-
- /* Can't enter superscript minus after entering digits */
- if (function == FN_TEXT && (strstr("�¹²³������", (char *)arg) != NULL || strcmp("�", (char *)arg) == 0))
- equation->priv->can_super_minus = FALSE;
-
- /* Disable super/subscript mode when finished entering */
- if (function == FN_CALCULATE ||
- function == FN_CLEAR ||
- (function == FN_TEXT && strstr("â?»â?°Â¹Â²Â³â?´â?µâ?¶â?·â?¸â?¹â??â??â??â??â??â??â??â??â??â??", (char *)arg) == NULL)) {
- math_equation_set_number_mode(equation, NORMAL);
- }
-
- if (gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(equation), &start, &end)) {
- cursor_start = gtk_text_iter_get_offset(&start);
- cursor_end = gtk_text_iter_get_offset(&end);
- }
- else {
- g_object_get(G_OBJECT(equation), "cursor-position", &cursor_start, NULL);
- if (cursor_start == gtk_text_buffer_get_char_count(GTK_TEXT_BUFFER(equation)))
- cursor_start = -1;
- cursor_end = cursor_start;
- }
-
- /* Some keyboards don't have a '^' button so convert two multiplies to one '^' */
- if (cursor_start == cursor_end &&
- function == FN_TEXT && equation->priv->last_text != NULL &&
- strcmp((char *)arg, "Ã?") == 0 && strcmp(equation->priv->last_text, "Ã?") == 0) {
- do_button(equation, FN_BACKSPACE, NULL);
- do_button(equation, FN_TEXT, "^");
- }
- else {
- display_do_function(equation, function, arg, cursor_start, cursor_end);
- if (function == FN_TEXT)
- equation->priv->last_text = (char *)arg;
- else
- equation->priv->last_text = NULL;
- }
+ return equation->priv->accuracy;
}
void
-math_equation_copy(MathEquation *equation)
+math_equation_set_show_thousands_separator(MathEquation *equation, gboolean visible)
{
- gchar *string = NULL;
- GtkTextIter start, end;
-
- if (gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(equation), &start, &end) == TRUE)
- string = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(equation), &start, &end, FALSE);
- else
- string = equation->priv->localized;
-
- if (equation->priv->shelf != NULL)
- g_free(equation->priv->shelf);
- equation->priv->shelf = g_locale_from_utf8(string, strlen(string), NULL, NULL, NULL);
- g_free(string);
-
- gtk_clipboard_set_text(gtk_clipboard_get(equation->priv->clipboard_atom), equation->priv->shelf, -1);
+ equation->priv->show_tsep = visible;
+ display_refresh(equation);
}
-static void
-on_paste(GtkClipboard *clipboard, const gchar *text, MathEquation *equation)
+gboolean
+math_equation_get_show_thousands_separator(MathEquation *equation)
{
- if (text != NULL)
- do_button(equation, FN_PASTE, (gpointer) text);
+ return equation->priv->show_tsep;
}
void
-math_equation_paste(MathEquation *equation)
+math_equation_set_show_trailing_zeroes(MathEquation *equation, gboolean visible)
{
- gtk_clipboard_request_text(gtk_clipboard_get(equation->priv->clipboard_atom),
- (GtkClipboardTextReceivedFunc)on_paste, equation);
+ equation->priv->show_zeroes = visible;
+ display_refresh(equation);
}
-void
-math_equation_store(MathEquation *equation, const gchar *name)
+gboolean
+math_equation_get_show_trailing_zeroes(MathEquation *equation)
{
- do_button(equation, FN_STORE, (gpointer)name);
+ return equation->priv->show_zeroes;
}
void
-math_equation_recall(MathEquation *equation, const gchar *name)
+math_equation_set_format(MathEquation *equation, DisplayFormat format)
{
- do_button(equation, FN_RECALL, (gpointer)name);
+ equation->priv->format = format;
+ display_refresh(equation);
}
-void
-math_equation_insert(MathEquation *equation, const gchar *text)
+DisplayFormat
+math_equation_get_format(MathEquation *equation)
{
- do_button(equation, FN_TEXT, (gpointer) text);
+ return equation->priv->format;
}
void
-math_equation_insert_digit(MathEquation *equation, unsigned int digit)
+math_equation_set_word_size(MathEquation *equation, int word_size)
{
- static const char *subscript_digits[] = {"â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", NULL};
- static const char *superscript_digits[] = {"�", "¹", "²", "³", "�", "�", "�", "�", "�", "�", NULL};
-
- if (equation->priv->number_mode == NORMAL || digit >= 10)
- math_equation_insert(equation, math_equation_get_digit_text(equation, digit));
- else if (equation->priv->number_mode == SUPERSCRIPT)
- math_equation_insert(equation, superscript_digits[digit]);
- else if (equation->priv->number_mode == SUBSCRIPT)
- math_equation_insert(equation, subscript_digits[digit]);
+ equation->priv->word_size = word_size;
}
-void
-math_equation_insert_numeric_point(MathEquation *equation)
+int
+math_equation_get_word_size(MathEquation *equation)
{
- math_equation_insert(equation, math_equation_get_numeric_point_text(equation));
+ return equation->priv->word_size;
}
void
-math_equation_insert_exponent(MathEquation *equation)
+math_equation_set_angle_unit(MathEquation *equation, MPAngleUnit angle_unit)
{
- math_equation_insert(equation, "Ã?10");
- math_equation_set_number_mode(equation, SUPERSCRIPT);
+ equation->priv->angle_unit = angle_unit;
}
-void
-math_equation_insert_character(MathEquation *equation, const char *character)
+MPAngleUnit
+math_equation_get_angle_unit(MathEquation *equation)
{
- do_button(equation, FN_INSERT_CHARACTER, (gpointer)character);
+ return equation->priv->angle_unit;
}
void
-math_equation_insert_subtract(MathEquation *equation)
+math_equation_set_base(MathEquation *equation, gint base)
{
- if (equation->priv->number_mode == SUPERSCRIPT && equation->priv->can_super_minus) {
- math_equation_insert(equation, "â?»");
- equation->priv->can_super_minus = FALSE;
- }
- else {
- math_equation_insert(equation, "â??");
- math_equation_set_number_mode(equation, NORMAL);
- }
+ // FIXME
}
-void
-math_equation_solve(MathEquation *equation)
+gint
+math_equation_get_base(MathEquation *equation)
{
- do_button(equation, FN_CALCULATE, NULL);
+ // FIXME
+ return 0;
}
void
-math_equation_factorize(MathEquation *equation)
-{
- do_button(equation, FN_FACTORIZE, NULL);
-}
-
-
-void math_equation_delete(MathEquation *equation)
-{
- do_button(equation, FN_DELETE, NULL);
-}
-
-
-void math_equation_backspace(MathEquation *equation)
+math_equation_set_status(MathEquation *equation, const gchar *status)
{
- do_button(equation, FN_BACKSPACE, NULL);
+ g_free(equation->priv->status);
+ equation->priv->status = g_strdup(status);
+ g_signal_emit(equation, signals[STATUS_CHANGED], 0);
}
-void
-math_equation_clear(MathEquation *equation)
+const gchar *
+math_equation_get_status(MathEquation *equation)
{
- do_button(equation, FN_CLEAR, NULL);
+ return equation->priv->status;
}
-void
-math_equation_shift(MathEquation *equation, gint count)
+gboolean
+math_equation_is_empty(MathEquation *equation)
{
- do_button(equation, FN_SHIFT, GINT_TO_POINTER(count));
+ return gtk_text_buffer_get_char_count(GTK_TEXT_BUFFER(equation)) == 0;
}
-void
-math_equation_toggle_bit(MathEquation *equation, guint bit)
+gboolean
+math_equation_is_result(MathEquation *equation)
{
- do_button(equation, FN_TOGGLE_BIT, GINT_TO_POINTER(bit));
-}
+ char *text;
+ gboolean result;
+ text = math_equation_get_equation(equation);
+ result = strcmp(text, "ans") == 0;
+ g_free(text);
-static MathEquationState *
-get_state(MathEquation *equation)
-{
- return &(equation->priv->h.e[equation->priv->h.current]);
+ return result;
}
-/* Add in the thousand separators characters if required and if we are
- * currently in the decimal numeric base, use the "right" radix character.
- */
-
-/* Add in the thousand separators characters if required */
-static void
-localize_expression(MathEquation *equation, char *dest, const char *src, int dest_length, int *cursor)
+gchar *
+math_equation_get_display(MathEquation *equation)
{
- GString *output;
- const char *c, *d;
- int digit_count = -1, read_cursor, new_cursor;
- gboolean after_radix = FALSE;
-
- if (cursor) {
- new_cursor = *cursor;
- } else {
- new_cursor = -1;
- }
-
- /* Scan expression looking for numbers and inserting separators */
- output = g_string_sized_new(dest_length);
- for (c = src, read_cursor = 1; *c; c = g_utf8_next_char(c), read_cursor++) {
- /* Insert separators between digits */
- if (*c >= '0' && *c <= '9') {
- /* Read ahead to find the number of digits */
- if (digit_count < 0) {
- digit_count = 1;
- for (d = c + 1; *d >= '0' && *d <= '9'; d++) {
- digit_count++;
- }
- }
-
- g_string_append_unichar(output, g_utf8_get_char(c));
-
- /* Insert separator after nth digit */
- if (equation->priv->show_tsep && equation->priv->format == DEC &&
- !after_radix && digit_count > 1 && digit_count % equation->priv->tsep_count == 1) {
- g_string_append(output, equation->priv->tsep);
- if (new_cursor > read_cursor) {
- new_cursor++;
- }
- read_cursor++;
- }
- digit_count--;
- }
- /* Ignore digits after the radix */
- else if (*c == '.') {
- digit_count = -1;
- after_radix = TRUE;
- g_string_append(output, equation->priv->radix);
- // FIXME: Handle cursor if radix is more than one character?
- }
- /* Reset when encountering other characters (e.g. '+') */
- else {
- digit_count = -1;
- after_radix = FALSE;
- g_string_append_unichar(output, g_utf8_get_char(c));
- }
- }
-
- strncpy(dest, output->str, dest_length - 1);
- g_string_free(output, TRUE);
+ GtkTextIter start, end;
- if (cursor != NULL && *cursor != -1) {
- *cursor = new_cursor;
- }
+ gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(equation), &start, &end);
+ return gtk_text_buffer_get_text(GTK_TEXT_BUFFER(equation), &start, &end, FALSE);
}
-static MPNumber *
-display_get_answer(MathEquation *equation)
+gchar *
+math_equation_get_equation(MathEquation *equation)
{
- return &get_state(equation)->ans;
-}
+ char *text, *t;
+ text = math_equation_get_display(equation);
-static int
-display_get_cursor(MathEquation *equation)
-{
- return get_state(equation)->cursor;
+ /* No ans to substitute */
+ if(equation->priv->state.ans_start < 0)
+ return text;
+
+ t = g_strdup_printf("%.*sans%s", equation->priv->state.ans_start, text, g_utf8_offset_to_pointer(text, equation->priv->state.ans_end));
+ g_free(text);
+ return t;
}
-static gboolean
-display_is_result(MathEquation *equation)
+gboolean
+math_equation_get_number(MathEquation *equation, MPNumber *z)
{
- MathEquationState *state;
+ gchar *text;
+ gboolean result;
- state = get_state(equation);
- if (state->ans_start == 0 && state->ans_end == g_utf8_strlen(state->expression, -1))
- return TRUE;
+ text = math_equation_get_display(equation);
+ result = !mp_set_from_string(text, z);
+ g_free (text);
- return FALSE;
+ return result;
}
-static void
-display_make_text(MathEquation *equation, char *localized, int length, int *cursor)
+void
+math_equation_set_number_mode(MathEquation *equation, NumberMode mode)
{
- char *str;
- MathEquationState *e;
-
- e = get_state(equation);
+ if (equation->priv->number_mode == mode)
+ return;
- /* Substitute answer register */
- if (display_is_result(equation)) {
- char temp[MAX_DIGITS];
- display_make_number(equation, temp, MAX_DIGITS, &e->ans);
- str = strdup(temp);
- }
- else
- str = strdup(e->expression);
+ equation->priv->can_super_minus = mode == SUPERSCRIPT;
- localize_expression(equation, localized, str, length, cursor);
- free(str);
+ equation->priv->number_mode = mode;
+ g_signal_emit(equation, signals[NUMBER_MODE_CHANGED], 0);
}
-static void
-display_refresh(MathEquation *equation)
+NumberMode
+math_equation_get_number_mode(MathEquation *equation)
{
- GtkTextIter iter;
-
- equation->priv->cursor = display_get_cursor(equation);
- display_make_text(equation, equation->priv->localized, MAX_DIGITS, &equation->priv->cursor);
- gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation), equation->priv->localized, -1);
- if (equation->priv->cursor < 0)
- gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(equation), &iter);
- else
- gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &iter, equation->priv->cursor);
- gtk_text_buffer_place_cursor(GTK_TEXT_BUFFER(equation), &iter);
+ return equation->priv->number_mode;
}
-static void
-display_set_string(MathEquation *equation, const char *value, int cursor)
+void
+math_equation_copy(MathEquation *equation)
{
- MathEquationState *e;
-
- if (value[0] == '\0')
- cursor = -1;
+ gchar *string = NULL;
+ GtkTextIter start, end;
- e = get_state(equation);
- free(e->expression);
- e->expression = strdup(value);
- e->cursor = cursor;
+ if (!gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(equation), &start, &end))
+ gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(equation), &start, &end);
- display_refresh(equation);
-}
+ string = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(equation), &start, &end, FALSE);
-static void
-display_clear(MathEquation *equation)
-{
- MathEquationState *state;
-
- state = get_state(equation);
- display_set_string(equation, "", -1);
- state->ans_start = -1;
- state->ans_end = -1;
-}
+ if (equation->priv->shelf != NULL)
+ g_free(equation->priv->shelf);
+ equation->priv->shelf = g_locale_from_utf8(string, strlen(string), NULL, NULL, NULL);
+ gtk_clipboard_set_text(gtk_clipboard_get(equation->priv->clipboard_atom), equation->priv->shelf, -1);
-static const char *
-get_text(MathEquation *equation)
-{
- return get_state(equation)->expression;
+ g_free(string);
}
-static char *
-get_expression(MathEquation *equation)
+static void
+on_paste(GtkClipboard *clipboard, const gchar *text, MathEquation *equation)
{
- MathEquationState *state;
-
- state = get_state(equation);
- if(state->ans_start >= 0)
- return g_strdup_printf("%.*sans%s", state->ans_start, state->expression, g_utf8_offset_to_pointer(state->expression, state->ans_end));
- else
- return g_strdup(state->expression);
-}
-
+ const char *input;
+ char c, *output, *clean_text;
+
+ /* Copy input to modify, no operation can make the clean string longer than
+ * the original string */
+ clean_text = strdup(text);
-static gboolean
-display_get_integer(MathEquation *equation, gint64 *value)
-{
- MPNumber t, min, max;
+ output = clean_text;
+ for (input = text; *input; input++) {
+ /* If the clipboard buffer contains any occurances of the "thousands
+ * separator", remove them.
+ */
+ if (equation->priv->tsep[0] != '\0' && strncmp(input, equation->priv->tsep, strlen(equation->priv->tsep)) == 0) {
+ input += strlen(equation->priv->tsep) - 1;
+ continue;
+ }
- if (!display_is_usable_number(equation, &t))
- return FALSE;
+ /* Replace radix with "." */
+ else if (strncmp(input, equation->priv->radix, strlen(equation->priv->radix)) == 0) {
+ input += strlen(equation->priv->radix) - 1;
+ c = '.';
+ }
- mp_set_from_integer(G_MININT64, &min);
- mp_set_from_integer(G_MAXINT64, &max);
- if (mp_is_less_than(&t, &min) || mp_is_greater_than(&t, &max))
- return FALSE;
+ /* Replace tabs with spaces */
+ else if (*input == '\t') {
+ c = ' ';
+ }
- *value = mp_cast_to_int(&t);
- return TRUE;
-}
+ /* Terminate on newlines */
+ else if (*input == '\r' || *input == '\n') {
+ c = '\0';
+ }
+ /* If an "A", "B", "C", "D" or "F" character is encountered, it
+ * will be converted to its lowercase equivalent. If an "E" is
+ * found, and the next character is a "-" or a "+", then it
+ * remains as an upper case "E" (it's assumed to be a possible
+ * exponential number), otherwise its converted to a lower case
+ * "e". See bugs #455889 and #469245 for more details.
+ */
+ else if (*input >= 'A' && *input <= 'F') {
+ c = *input;
+ if (*input == 'E') {
+ if (*(input+1) != '-' && *(input+1) != '+')
+ c = tolower(*input);
+ }
+ else
+ c = tolower(*input);
+ }
-static gboolean
-display_get_unsigned_integer(MathEquation *equation, guint64 *value)
-{
- MPNumber t, max;
+ else
+ c = *input;
- if (!display_is_usable_number(equation, &t))
- return FALSE;
-
- mp_set_from_unsigned_integer(G_MAXUINT64, &max);
- char string[MAX_DIGITS];
- if (mp_is_negative(&t) || mp_is_greater_than(&t, &max))
- return FALSE;
+ *output++ = c;
+ }
+ *output++ = '\0';
- *value = mp_cast_to_unsigned_int(&t);
- return TRUE;
+ math_equation_insert(equation, clean_text);
}
-// FIXME: Looses accuracy
void
-display_set_number(MathEquation *equation, const MPNumber *x)
+math_equation_paste(MathEquation *equation)
{
- char text[MAX_DISPLAY];
- int enabled;
- guint64 bit_value;
-
- display_make_number(equation, text, MAX_DISPLAY, x);
- display_set_string(equation, text, -1);
-
- enabled = display_get_unsigned_integer(equation, &bit_value);
- math_equation_set_bitfield(equation, enabled, bit_value);
+ gtk_clipboard_request_text(gtk_clipboard_get(equation->priv->clipboard_atom),
+ (GtkClipboardTextReceivedFunc)on_paste, equation);
}
void
-display_set_answer(MathEquation *equation)
-{
- MathEquationState *state;
- char text[MAX_DISPLAY];
-
- state = get_state(equation);
- display_make_number(equation, text, MAX_DISPLAY, &state->ans);
- display_set_string(equation, text, -1);
- state->ans_start = 0;
- state->ans_end = g_utf8_strlen(text, -1);
-}
-
-
-static void
-display_set_cursor(MathEquation *equation, int cursor)
-{
- MathEquationState *e;
-
- e = get_state(equation);
- e->cursor = cursor;
- display_refresh(equation);
-}
-
-
-static void
-display_convert(MathEquation *equation, DisplayFormat format)
+math_equation_store(MathEquation *equation, const gchar *name)
{
- DisplayFormat old_format;
-
- if (!display_is_result (equation))
- return;
-
- /* FIXME: A bit hacky... */
- old_format = equation->priv->format;
- equation->priv->format = format;
- display_set_answer(equation);
- equation->priv->format = old_format;
-}
-
+ MPNumber t;
-static void
-copy_state(MathEquationState *dst, MathEquationState *src)
-{
- memcpy(dst, src, sizeof(MathEquationState));
- dst->expression = strdup(src->expression);
+ if (!math_equation_get_number(equation, &t))
+ math_equation_set_status(equation, _("No sane value to store"));
+ else
+ register_set_value(name, &t);
}
-static void
-display_clear_stack(MathEquation *equation)
+void
+math_equation_recall(MathEquation *equation, const gchar *name)
{
- int i = equation->priv->h.begin;
- while (i != equation->priv->h.end) {
- if (i != equation->priv->h.current) {
- free(equation->priv->h.e[i].expression);
- equation->priv->h.e[i].expression = NULL;
- }
- i = ((i + 1) % UNDO_HISTORY_LENGTH);
- }
- equation->priv->h.begin = equation->priv->h.end = equation->priv->h.current;
+ math_equation_insert(equation, name);
}
-static void
-display_push(MathEquation *equation)
-{
- int c;
-
- if (equation->priv->h.current != equation->priv->h.end) {
- int i = equation->priv->h.current;
-
- do {
- i = ((i + 1) % UNDO_HISTORY_LENGTH);
- free(equation->priv->h.e[i].expression);
- equation->priv->h.e[i].expression = strdup("ans"); // FIXME: Use actual number
- equation->priv->h.e[i].ans_start = -1;
- equation->priv->h.e[i].ans_end = -1;
- } while (i != equation->priv->h.end);
- }
-
- equation->priv->h.end = equation->priv->h.current;
-
- c = equation->priv->h.current;
- equation->priv->h.end = equation->priv->h.current = ((equation->priv->h.current + 1) % UNDO_HISTORY_LENGTH);
- if (equation->priv->h.current == equation->priv->h.begin) {
- free(equation->priv->h.e[equation->priv->h.begin].expression);
- equation->priv->h.e[equation->priv->h.begin].expression = NULL;
- equation->priv->h.begin = ((equation->priv->h.begin + 1) % UNDO_HISTORY_LENGTH);
- }
-
- copy_state(&(equation->priv->h.e[equation->priv->h.current]), &(equation->priv->h.e[c]));
-}
-
+void
+math_equation_set(MathEquation *equation, const gchar *text)
-static void
-display_pop(MathEquation *equation)
{
- if (equation->priv->h.current != equation->priv->h.begin) {
- equation->priv->h.current = ((equation->priv->h.current - 1) % UNDO_HISTORY_LENGTH);
- math_equation_set_status(equation, "");
- } else {
- math_equation_set_status(equation, _("No undo history"));
- }
+ display_push(equation);
- display_refresh(equation);
+ gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation), text, -1);
+ equation->priv->state.ans_start = -1;
+ equation->priv->state.ans_end = -1;
}
-static void
-display_unpop(MathEquation *equation)
+void
+math_equation_set_answer(MathEquation *equation)
{
- if (equation->priv->h.current != equation->priv->h.end) {
- equation->priv->h.current = ((equation->priv->h.current + 1) % UNDO_HISTORY_LENGTH);
- math_equation_set_status(equation, "");
- } else {
- math_equation_set_status(equation, _("No redo steps"));
- }
- get_state(equation)->cursor = -1;
- display_refresh(equation);
-}
+ char text[MAX_DIGITS];
-
-static gboolean
-display_is_undo_step(MathEquation *equation)
-{
- return(equation->priv->h.current != equation->priv->h.begin);
+ display_push(equation);
+
+ display_make_number(equation, text, MAX_DIGITS, &equation->priv->state.ans);
+ math_equation_set(equation, text);
+ equation->priv->state.ans_start = 0;
+ equation->priv->state.ans_end = g_utf8_strlen(text, -1);
}
-static void
-display_insert(MathEquation *equation, int cursor_start, int cursor_end, const char *text)
+void
+math_equation_set_number(MathEquation *equation, const MPNumber *x)
{
- MathEquationState *state;
- char buf[MAX_DISPLAY];
-
- state = get_state(equation);
-
- /* If inside ans variable then modify number */
- if (state->ans_start >= 0 && cursor_start >= state->ans_start && cursor_start <= state->ans_end) {
- state->ans_start = -1;
- state->ans_end = -1;
- }
-
- if (cursor_start < 0) {
- snprintf(buf, MAX_DISPLAY, "%s%s", get_text(equation), text);
- display_set_string(equation, buf, -1);
- } else {
- GString *new_text;
- const char *c;
- gint cursor, new_cursor;
-
- /* Get display text and strip out thousand separators */
- new_text = g_string_new("");
- new_cursor = 0;
- if (cursor_start == 0) {
- g_string_append(new_text, text);
- new_cursor += g_utf8_strlen(text, -1);
- }
-
- cursor = 0;
- for (c = equation->priv->localized; *c; c = g_utf8_next_char(c), cursor++) {
- gboolean use = TRUE;
-
- /* Ignore selected part */
- if (cursor_start != cursor_end && cursor >= cursor_start && cursor < cursor_end)
- use = FALSE;
-
- /* Ignore thousands separators (if one exists) */
- if (equation->priv->tsep[0] != '\0' && strncmp(c, equation->priv->tsep, strlen(equation->priv->tsep)) == 0)
- use = FALSE;
-
- /* Copy existing text */
- if (use) {
- g_string_append_unichar(new_text, g_utf8_get_char(c));
- if (cursor < cursor_start)
- new_cursor++;
- }
-
- /* Insert text */
- if ((cursor + 1) == cursor_start) {
- g_string_append(new_text, text);
- new_cursor += g_utf8_strlen(text, -1);
- }
- }
- display_set_string(equation, new_text->str, new_cursor);
- g_string_free(new_text, TRUE);
- }
-
-}
+ char text[MAX_DIGITS];
+ display_push(equation);
-static void
-display_insert_number(MathEquation *equation, int cursor_start, int cursor_end, const MPNumber *value)
-{
- char text[MAX_DISPLAY];
- display_make_number(equation, text, MAX_DISPLAY, value);
- display_insert(equation, cursor_start, cursor_end, text);
+ display_make_number(equation, text, MAX_DIGITS, x);
+ math_equation_set(equation, text);
}
-static gboolean
-display_is_empty(MathEquation *equation)
+void
+math_equation_insert(MathEquation *equation, const gchar *text)
{
- return strcmp(get_text(equation), "") == 0;
-}
+ display_push(equation);
+ /* Replace ** with ^ (not on all keyboards) */
+ if (!gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(equation)) &&
+ strcmp(text, "Ã?") == 0 && equation->priv->state.entered_multiply) {
+ GtkTextIter iter;
-static void
-display_backspace(MathEquation *equation, int cursor_start, int cursor_end)
-{
- int cursor;
-
- /* Can't delete empty display */
- if (display_is_empty(equation))
+ gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &iter, gtk_text_buffer_get_insert(GTK_TEXT_BUFFER(equation)));
+ gtk_text_buffer_backspace(GTK_TEXT_BUFFER(equation), &iter, TRUE, TRUE);
+ gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(equation), "^", -1);
return;
-
- cursor = display_get_cursor(equation);
-
- /* If cursor is at end of the line then delete the last character preserving accuracy */
- if (cursor_start < 0) {
- int len;
- len = g_utf8_strlen(equation->priv->localized, -1);
- display_insert(equation, len - 1, len, "");
- } else if (cursor_start != cursor_end) {
- display_insert(equation, cursor_start, cursor_end, "");
- } else if (cursor_start > 0) {
- display_insert(equation, cursor_start - 1, cursor_start, "");
- }
-
-}
-
-static void
-display_delete(MathEquation *equation, int cursor_start, int cursor_end)
-{
- /* Delete selected block */
- if (cursor_start != cursor_end)
- display_insert(equation, cursor_start, cursor_end, "");
- else if (cursor_start >= 0)
- display_insert(equation, cursor_start, cursor_start + 1, "");
-}
-
-
-gboolean
-display_is_usable_number(MathEquation *equation, MPNumber *z)
-{
- if (display_is_empty(equation)) {
- mp_set_from_integer(0, z);
- return TRUE;
- } else if (display_is_result(equation)) {
- mp_set_from_mp(display_get_answer(equation), z);
- return TRUE;
- } else {
- return mp_set_from_string(get_text(equation), z) == 0;
}
-}
+ /* Start new equation when entering digits after existing result */
+ if(math_equation_is_result(equation) && g_unichar_isdigit(g_utf8_get_char(text)))
+ gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation), "", -1);
-static gboolean
-display_is_number_with_base(MathEquation *equation)
-{
- MPNumber t;
- const char *text;
- const char *sub_digits[] = { "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", NULL };
- int i;
-
- if (display_is_empty(equation))
- return FALSE;
-
- if (display_is_result(equation))
- return (equation->priv->format == BIN || equation->priv->format == OCT || equation->priv->format == HEX);
-
- /* See if it has a subscript suffix */
- text = get_text(equation);
- text += strlen (text);
- for (i = 0; sub_digits[i] != NULL; i++) {
- if (strcmp (text - strlen (sub_digits[i]), sub_digits[i]) == 0)
- return mp_set_from_string(get_text(equation), &t) == 0;
- }
+ /* Can't enter superscript minus after entering digits */
+ if (strstr("�¹²³������", text) != NULL || strcmp("�", text) == 0)
+ equation->priv->can_super_minus = FALSE;
- return FALSE;
-}
+ /* Disable super/subscript mode when finished entering */
+ if (strstr("â?»â?°Â¹Â²Â³â?´â?µâ?¶â?·â?¸â?¹â??â??â??â??â??â??â??â??â??â??", text) == NULL)
+ math_equation_set_number_mode(equation, NORMAL);
+ // FIXME: Add thousands separators
-void
-math_equation_set_accuracy(MathEquation *equation, int accuracy)
-{
- equation->priv->accuracy = accuracy;
- get_state(equation)->cursor = -1;
- display_refresh(equation);
+ gtk_text_buffer_delete_selection(GTK_TEXT_BUFFER(equation), FALSE, FALSE);
+ gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(equation), text, -1);
}
void
-math_equation_set_show_thousands_separator(MathEquation *equation, gboolean visible)
+math_equation_insert_digit(MathEquation *equation, unsigned int digit)
{
- equation->priv->show_tsep = visible;
- display_set_cursor(equation, -1);
- display_refresh(equation);
-}
-
+ static const char *subscript_digits[] = {"â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", NULL};
+ static const char *superscript_digits[] = {"�", "¹", "²", "³", "�", "�", "�", "�", "�", "�", NULL};
-void
-math_equation_set_show_trailing_zeroes(MathEquation *equation, gboolean visible)
-{
- equation->priv->show_zeroes = visible;
- get_state(equation)->cursor = -1;
- display_refresh(equation);
+ if (equation->priv->number_mode == NORMAL || digit >= 10)
+ math_equation_insert(equation, math_equation_get_digit_text(equation, digit));
+ else if (equation->priv->number_mode == SUPERSCRIPT)
+ math_equation_insert(equation, superscript_digits[digit]);
+ else if (equation->priv->number_mode == SUBSCRIPT)
+ math_equation_insert(equation, subscript_digits[digit]);
}
void
-math_equation_set_format(MathEquation *equation, DisplayFormat format)
+math_equation_insert_numeric_point(MathEquation *equation)
{
- equation->priv->format = format;
- get_state(equation)->cursor = -1;
- display_refresh(equation);
+ math_equation_insert(equation, math_equation_get_numeric_point_text(equation));
}
void
-math_equation_set_word_size(MathEquation *equation, int word_size)
+math_equation_insert_number(MathEquation *equation, const MPNumber *x)
{
- equation->priv->word_size = word_size;
+ char text[MAX_DIGITS];
+ display_make_number(equation, text, MAX_DIGITS, x);
+ math_equation_insert(equation, text);
}
void
-math_equation_set_angle_unit(MathEquation *equation, MPAngleUnit angle_unit)
+math_equation_insert_exponent(MathEquation *equation)
{
- equation->priv->angle_unit = angle_unit;
+ math_equation_insert(equation, "Ã?10");
+ math_equation_set_number_mode(equation, SUPERSCRIPT);
}
void
-math_equation_set_base(MathEquation *equation, gint base)
+math_equation_insert_subtract(MathEquation *equation)
{
- /* If has a number already in a base, then solve and convert it */
- if (!display_is_result(equation) && display_is_number_with_base(equation))
- math_equation_solve(equation);
-
- if (display_is_result(equation)) {
- if (base == 2)
- display_convert(equation, BIN);
- else if (base == 8)
- display_convert(equation, OCT);
- else if (base == 16)
- display_convert(equation, HEX);
- else
- display_convert(equation, DEC);
+ if (equation->priv->number_mode == SUPERSCRIPT && equation->priv->can_super_minus) {
+ math_equation_insert(equation, "â?»");
+ equation->priv->can_super_minus = FALSE;
}
else {
- if (base == 2)
- math_equation_insert(equation, "â??");
- else if (base == 8)
- math_equation_insert(equation, "â??");
- else if (base == 16)
- math_equation_insert(equation, "â??â??");
- }
-}
-
-
-/* Convert engineering or scientific number in the given base. */
-static void
-make_eng_sci(MathEquation *equation, char *target, int target_len, const MPNumber *x, int base_)
-{
- char fixed[MAX_DIGITS], *c;
- MPNumber t, z, base, base3, base10, base10inv, mantissa;
- int eng, exponent = 0;
- GString *string;
- const char *super_digits[] = {"�", "¹", "²", "³", "�", "�", "�", "�", "�", "�"};
-
- string = g_string_sized_new(target_len);
-
- eng = equation->priv->format == ENG;
-
- mp_abs(x, &z);
- if (mp_is_negative(x))
- g_string_append(string, "â??");
- mp_set_from_mp(&z, &mantissa);
-
- mp_set_from_integer(base_, &base);
- mp_xpowy_integer(&base, 3, &base3);
- mp_xpowy_integer(&base, 10, &base10);
- mp_set_from_integer(1, &t);
- mp_divide(&t, &base10, &base10inv);
-
- if (!mp_is_zero(&mantissa)) {
- while (!eng && mp_is_greater_equal(&mantissa, &base10)) {
- exponent += 10;
- mp_multiply(&mantissa, &base10inv, &mantissa);
- }
-
- while ((!eng && mp_is_greater_equal(&mantissa, &base)) ||
- (eng && (mp_is_greater_equal(&mantissa, &base3) || exponent % 3 != 0))) {
- exponent += 1;
- mp_divide(&mantissa, &base, &mantissa);
- }
-
- while (!eng && mp_is_less_than(&mantissa, &base10inv)) {
- exponent -= 10;
- mp_multiply(&mantissa, &base10, &mantissa);
- }
-
- mp_set_from_integer(1, &t);
- while (mp_is_less_than(&mantissa, &t) || (eng && exponent % 3 != 0)) {
- exponent -= 1;
- mp_multiply(&mantissa, &base, &mantissa);
- }
- }
-
- mp_cast_to_string(&mantissa, base_, equation->priv->accuracy, !equation->priv->show_zeroes, fixed, MAX_DIGITS);
- g_string_append(string, fixed);
- g_string_append_printf(string, "Ã?10");
- if (exponent < 0) {
- exponent = -exponent;
- g_string_append(string, "â?»");
- }
- snprintf(fixed, MAX_DIGITS, "%d", exponent);
- for (c = fixed; *c; c++)
- g_string_append(string, super_digits[*c - '0']);
-
- strncpy(target, string->str, target_len);
- g_string_free(string, TRUE);
-}
-
-
-/* Convert MP number to character string. */
-void
-display_make_number(MathEquation *equation, char *target, int target_len, const MPNumber *x)
-{
- switch(equation->priv->format) {
- case DEC:
- mp_cast_to_string(x, 10, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
- break;
- case BIN:
- mp_cast_to_string(x, 2, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
- break;
- case OCT:
- mp_cast_to_string(x, 8, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
- break;
- case HEX:
- mp_cast_to_string(x, 16, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
- break;
- case SCI:
- make_eng_sci(equation, target, target_len, x, 10);
- break;
- case ENG:
- make_eng_sci(equation, target, target_len, x, 10);
- break;
+ math_equation_insert(equation, "â??");
+ math_equation_set_number_mode(equation, NORMAL);
}
}
@@ -1143,7 +650,7 @@ get_variable(const char *name, MPNumber *z, void *data)
if (strcmp(lower_name, "rand") == 0)
mp_set_from_random(z);
else if (strcmp(lower_name, "ans") == 0)
- mp_set_from_mp(display_get_answer(equation), z);
+ mp_set_from_mp(&equation->priv->state.ans, z);
else {
t = register_get_value(name);
if (t)
@@ -1201,306 +708,319 @@ parse(MathEquation *equation, const char *text, MPNumber *z, char **error_token)
}
-static void
-do_paste(MathEquation *equation, int cursor_start, int cursor_end, const char *text)
+void
+math_equation_solve(MathEquation *equation)
{
- const char *input;
- char c, *output, *clean_text;
+ MPNumber z;
+ int result;
+ gchar *text, *error_token = NULL, *message = NULL;
+
+ if (math_equation_is_empty(equation))
+ return;
- /* Copy input to modify, no operation can make the clean string longer than
- * the original string */
- clean_text = strdup(text);
+ /* If showing a result return to the equation that caused it */
+ // FIXME: Result may not be here due to solve (i.e. the user may have entered "ans")
+ if (math_equation_is_result(equation)) {
+ display_pop(equation);
+ return;
+ }
- output = clean_text;
- for (input = text; *input; input++) {
- /* If the clipboard buffer contains any occurances of the "thousands
- * separator", remove them.
- */
- if (equation->priv->tsep[0] != '\0' && strncmp(input, equation->priv->tsep, strlen(equation->priv->tsep)) == 0) {
- input += strlen(equation->priv->tsep) - 1;
- continue;
- }
+ display_push(equation);
- /* Replace radix with "." */
- else if (strncmp(input, equation->priv->radix, strlen(equation->priv->radix)) == 0) {
- input += strlen(equation->priv->radix) - 1;
- c = '.';
- }
+ math_equation_set_number_mode(equation, NORMAL);
- /* Replace tabs with spaces */
- else if (*input == '\t') {
- c = ' ';
- }
+ text = math_equation_get_equation(equation);
+ result = parse(equation, text, &z, &error_token);
+ g_free(text);
- /* Terminate on newlines */
- else if (*input == '\r' || *input == '\n') {
- c = '\0';
- }
+ switch (result) {
+ case PARSER_ERR_NONE:
+ mp_set_from_mp(&z, &equation->priv->state.ans);
+ math_equation_set_answer(equation);
+ break;
- /* If an "A", "B", "C", "D" or "F" character is encountered, it
- * will be converted to its lowercase equivalent. If an "E" is
- * found, and the next character is a "-" or a "+", then it
- * remains as an upper case "E" (it's assumed to be a possible
- * exponential number), otherwise its converted to a lower case
- * "e". See bugs #455889 and #469245 for more details.
- */
- else if (*input >= 'A' && *input <= 'F') {
- c = *input;
- if (*input == 'E') {
- if (*(input+1) != '-' && *(input+1) != '+')
- c = tolower(*input);
- }
- else
- c = tolower(*input);
- }
+ case PARSER_ERR_OVERFLOW:
+ message = g_strdup(/* Error displayed to user when they perform a bitwise operation on numbers greater than the current word */
+ _("Overflow. Try a bigger word size"));
+ break;
- else
- c = *input;
+ case PARSER_ERR_UNKNOWN_VARIABLE:
+ message = g_strdup_printf(/* Error displayed to user when they an unknown variable is entered */
+ _("Unknown variable '%s'"), error_token);
+ break;
- *output++ = c;
- }
- *output++ = '\0';
+ case PARSER_ERR_UNKNOWN_FUNCTION:
+ message = g_strdup_printf(/* Error displayed to user when an unknown function is entered */
+ _("Function '%s' is not defined"), error_token);
+ break;
- display_insert(equation, cursor_start, cursor_end, clean_text);
-}
+ case PARSER_ERR_UNKNOWN_CONVERSION:
+ message = g_strdup(/* Error displayed to user when an conversion with unknown units is attempted */
+ _("Unknown conversion"));
+ break;
+ case PARSER_ERR_MP:
+ message = g_strdup(mp_get_error());
+ break;
-static void
-do_insert_character(MathEquation *equation, const unsigned char *text)
-{
- MPNumber value;
- int i = 0;
- mp_set_from_integer(0, &value);
- while (TRUE) {
- mp_add_integer(&value, text[i], &value);
- if (text[i+1]) {
- mp_shift(&value, 8, &value);
- i++;
- } else {
+ default:
+ message = g_strdup(/* Error displayed to user when they enter an invalid calculation */
+ _("Malformed expression"));
break;
- }
}
- display_set_number(equation, &value);
+
+ if (error_token)
+ free(error_token);
+
+ if (message) {
+ math_equation_set_status(equation, message);
+ g_free(message);
+ }
}
-/* Perform bitwise shift on display value. */
-static void
-do_shift(MathEquation *equation, int count)
+void
+math_equation_factorize(MathEquation *equation)
{
- MPNumber z;
-
- if (!display_is_usable_number(equation, &z)) {
- /* Translators: This message is displayed in the status bar when a bit
- shift operation is performed and the display does not contain a number */
- math_equation_set_status(equation, _("No sane value to bitwise shift"));
+ MPNumber x;
+ GList *factors, *factor;
+ GString *text;
+
+ if (!math_equation_get_number(equation, &x) || !mp_is_integer(&x)) {
+ /* Error displayed when trying to factorize a non-integer value */
+ math_equation_set_status(equation, _("Need an integer to factorize"));
+ return;
}
- else {
- mp_shift(&z, count, display_get_answer(equation));
- display_set_answer(equation);
+
+ factors = mp_factorize(&x);
+
+ text = g_string_new("");
+
+ for (factor = factors; factor; factor = factor->next) {
+ gchar temp[MAX_DIGITS];
+ MPNumber *n;
+
+ n = factor->data;
+ display_make_number(equation, temp, MAX_DIGITS, n);
+ g_string_append(text, temp);
+ if (factor->next)
+ g_string_append(text, "Ã?");
+ g_slice_free(MPNumber, n);
}
+ g_list_free(factors);
+
+ math_equation_set(equation, text->str);
+ g_string_free(text, TRUE);
}
-static void
-do_factorize(MathEquation *equation)
+void
+math_equation_delete(MathEquation *equation)
{
- MPNumber value;
+ gint cursor;
+ GtkTextIter start, end;
- if (!display_is_usable_number(equation, &value)) {
- /* Translators: Error displayed when trying to factorize a non-integer value */
- math_equation_set_status(equation, _("Need an integer to factorize"));
+ g_object_get(G_OBJECT(equation), "cursor-position", &cursor, NULL);
+ if (cursor >= gtk_text_buffer_get_char_count(GTK_TEXT_BUFFER(equation)))
return;
- }
- display_clear(equation);
- GList *factors = mp_factorize(&value);
+ display_push(equation);
+
+ gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &start, cursor);
+ gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &end, cursor+1);
+ gtk_text_buffer_delete(GTK_TEXT_BUFFER(equation), &start, &end);
+}
+
- display_insert_number(equation, -1, -1, factors->data);
- g_slice_free(MPNumber, factors->data);
+void
+math_equation_backspace(MathEquation *equation)
+{
+ /* Can't delete empty display */
+ if (math_equation_is_empty(equation))
+ return;
- GList *list = factors->next;
- for (; list != NULL; list = list->next) {
- display_insert(equation, -1, -1, "Ã?");
- display_insert_number(equation, -1, -1, list->data);
- g_slice_free(MPNumber, list->data);
+ display_push(equation);
+
+ if (gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(equation)))
+ gtk_text_buffer_delete_selection(GTK_TEXT_BUFFER(equation), FALSE, FALSE);
+ else {
+ GtkTextIter iter;
+ gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &iter, gtk_text_buffer_get_insert(GTK_TEXT_BUFFER(equation)));
+ gtk_text_buffer_backspace(GTK_TEXT_BUFFER(equation), &iter, TRUE, TRUE);
}
- g_list_free(factors);
}
-static void
-do_sto(MathEquation *equation, const char *name)
+void
+math_equation_clear(MathEquation *equation)
{
- MPNumber t;
+ MathEquationState *state;
- if (!display_is_usable_number(equation, &t))
- math_equation_set_status(equation, _("No sane value to store"));
- else
- register_set_value(name, &t);
+ math_equation_set_number_mode(equation, NORMAL);
+ math_equation_set(equation, "");
}
-static void
-display_do_function(MathEquation *equation, int function, gpointer arg, int cursor_start, int cursor_end)
+void
+math_equation_shift(MathEquation *equation, gint count)
{
- MPNumber *ans;
- int enabled;
- guint64 bit_value;
+ MPNumber z;
- switch (function) {
- case FN_UNDO:
- display_pop(equation);
- return;
+ if (!math_equation_get_number(equation, &z)) {
+ math_equation_set_status(equation,
+ /* This message is displayed in the status bar when a bit
+ shift operation is performed and the display does not contain a number */
+ _("No sane value to bitwise shift"));
+ return;
+ }
- case FN_REDO:
- display_unpop(equation);
- return;
+ display_push(equation);
+
+ mp_shift(&z, count, &equation->priv->state.ans);
+ math_equation_set_answer(equation);
+}
- default:
- break;
+
+void
+math_equation_toggle_bit(MathEquation *equation, guint bit)
+{
+ MPNumber x;
+ guint64 bits;
+ gboolean result;
+
+ result = math_equation_get_number(equation, &x);
+ if (result) {
+ MPNumber max;
+ mp_set_from_unsigned_integer(G_MAXUINT64, &max);
+ if (mp_is_negative(&x) || mp_is_greater_than(&x, &max))
+ result = FALSE;
+ else
+ bits = mp_cast_to_unsigned_int(&x);
}
- display_push(equation);
+ if (!result) {
+ math_equation_set_status(equation,
+ /* Message displayed when cannot toggle bit in display*/
+ _("Displayed value not an integer"));
+ return;
+ }
- display_set_cursor(equation, cursor_start);
- ans = display_get_answer(equation);
+ bits ^= (1LL << (63 - bit));
- math_equation_set_status(equation, "");
+ mp_set_from_unsigned_integer(bits, &x);
+ math_equation_set_number(equation, &x);
+}
- switch (function) {
- case FN_CLEAR:
- display_clear(equation);
- break;
- case FN_SHIFT:
- do_shift(equation, GPOINTER_TO_INT (arg));
- break;
+static gboolean
+display_get_integer(MathEquation *equation, gint64 *value)
+{
+ MPNumber t, min, max;
- case FN_FACTORIZE:
- do_factorize(equation);
- break;
+ if (!math_equation_get_number(equation, &t))
+ return FALSE;
- case FN_PASTE:
- do_paste(equation, cursor_start, cursor_end, (const char *)arg);
- return;
+ mp_set_from_integer(G_MININT64, &min);
+ mp_set_from_integer(G_MAXINT64, &max);
+ if (mp_is_less_than(&t, &min) || mp_is_greater_than(&t, &max))
+ return FALSE;
- case FN_INSERT_CHARACTER:
- do_insert_character(equation, (const unsigned char *)arg);
- return;
+ *value = mp_cast_to_int(&t);
+ return TRUE;
+}
- case FN_STORE:
- do_sto(equation, (const char *)arg);
- return;
- case FN_RECALL:
- display_insert(equation, cursor_start, cursor_end, (const char *)arg);
- break;
+/* Convert engineering or scientific number in the given base. */
+// FIXME: Move into mp-convert.c
+static void
+make_eng_sci(MathEquation *equation, char *target, int target_len, const MPNumber *x, int base_)
+{
+ char fixed[MAX_DIGITS], *c;
+ MPNumber t, z, base, base3, base10, base10inv, mantissa;
+ int eng, exponent = 0;
+ GString *string;
+ const char *super_digits[] = {"�", "¹", "²", "³", "�", "�", "�", "�", "�", "�"};
- case FN_BACKSPACE:
- display_backspace(equation, cursor_start, cursor_end);
- break;
+ string = g_string_sized_new(target_len);
- case FN_DELETE:
- display_delete(equation, cursor_start, cursor_end);
- break;
+ eng = equation->priv->format == ENG;
- case FN_TOGGLE_BIT:
- if (display_get_unsigned_integer(equation, &bit_value)) {
- char buf[MAX_DISPLAY];
- MPNumber MP;
+ mp_abs(x, &z);
+ if (mp_is_negative(x))
+ g_string_append(string, "â??");
+ mp_set_from_mp(&z, &mantissa);
- bit_value ^= (1LL << (63 - GPOINTER_TO_INT (arg)));
+ mp_set_from_integer(base_, &base);
+ mp_xpowy_integer(&base, 3, &base3);
+ mp_xpowy_integer(&base, 10, &base10);
+ mp_set_from_integer(1, &t);
+ mp_divide(&t, &base10, &base10inv);
- /* FIXME: Convert to string since we don't support setting MP numbers from 64 bit integers */
- snprintf(buf, MAX_DISPLAY, "%" G_GUINT64_FORMAT, bit_value);
- mp_set_from_string(buf, &MP);
- display_set_number(equation, &MP);
- }
- break;
+ if (!mp_is_zero(&mantissa)) {
+ while (!eng && mp_is_greater_equal(&mantissa, &base10)) {
+ exponent += 10;
+ mp_multiply(&mantissa, &base10inv, &mantissa);
+ }
- case FN_CALCULATE:
- /* If showing a result display the calculation that caused
- * this result */
- /* TODO: Work out why two undo steps are required and why
- * the cursor must be taken from the first undo */
- if (display_is_result(equation)) {
- display_pop(equation);
- if (display_is_undo_step(equation)) {
- display_pop(equation);
- }
-
- /* Do nothing */
- } else if (display_is_empty(equation)) {
- ;
-
- /* Solve the equation */
- } else {
- MPNumber z;
- int result;
- const char *message = NULL;
- char *text, *error_token;
-
- text = get_expression (equation);
- result = parse(equation,
- text,
- &z,
- &error_token);
- g_free(text);
-
- switch (result) {
- case PARSER_ERR_NONE:
- mp_set_from_mp(&z, ans);
- display_set_answer(equation);
- break;
-
- case PARSER_ERR_OVERFLOW:
- /* Translators: Error displayed to user when they perform a bitwise operation on numbers greater than the current word */
- message = _("Overflow. Try a bigger word size");
- break;
-
- case PARSER_ERR_UNKNOWN_VARIABLE:
- /* Translators: Error displayed to user when they an unknown variable is entered */
- message = g_strdup_printf(_("Unknown variable '%s'"), error_token);
- free(error_token);
- break;
-
- case PARSER_ERR_UNKNOWN_FUNCTION:
- /* Translators: Error displayed to user when an unknown function is entered */
- message = g_strdup_printf(_("Function '%s' is not defined"), error_token);
- free(error_token);
- break;
-
- case PARSER_ERR_UNKNOWN_CONVERSION:
- /* Translators: Error displayed to user when an conversion with unknown units is attempted */
- message = g_strdup_printf(_("Unknown conversion"));
- break;
-
- case PARSER_ERR_MP:
- message = mp_get_error();
- break;
-
- default:
- /* Translators: Error displayed to user when they enter an invalid calculation */
- message = _("Malformed expression");
- break;
- }
- if (message)
- math_equation_set_status(equation, message);
- }
- break;
+ while ((!eng && mp_is_greater_equal(&mantissa, &base)) ||
+ (eng && (mp_is_greater_equal(&mantissa, &base3) || exponent % 3 != 0))) {
+ exponent += 1;
+ mp_divide(&mantissa, &base, &mantissa);
+ }
+
+ while (!eng && mp_is_less_than(&mantissa, &base10inv)) {
+ exponent -= 10;
+ mp_multiply(&mantissa, &base10, &mantissa);
+ }
- case FN_TEXT:
- /* Start new equation when entering digits after existing result */
- if(display_is_result(equation) && g_unichar_isdigit(g_utf8_get_char((char*)arg)))
- display_clear(equation);
+ mp_set_from_integer(1, &t);
+ while (mp_is_less_than(&mantissa, &t) || (eng && exponent % 3 != 0)) {
+ exponent -= 1;
+ mp_multiply(&mantissa, &base, &mantissa);
+ }
+ }
- display_insert(equation, cursor_start, cursor_end, (const char *)arg);
- break;
+ mp_cast_to_string(&mantissa, base_, equation->priv->accuracy, !equation->priv->show_zeroes, fixed, MAX_DIGITS);
+ g_string_append(string, fixed);
+ g_string_append_printf(string, "Ã?10");
+ if (exponent < 0) {
+ exponent = -exponent;
+ g_string_append(string, "â?»");
}
+ snprintf(fixed, MAX_DIGITS, "%d", exponent);
+ for (c = fixed; *c; c++)
+ g_string_append(string, super_digits[*c - '0']);
- enabled = display_get_unsigned_integer(equation, &bit_value);
- math_equation_set_bitfield(equation, enabled, bit_value);
+ strncpy(target, string->str, target_len);
+ g_string_free(string, TRUE);
+}
+
+
+/* Convert MP number to character string. */
+//FIXME: What to do with this?
+void
+display_make_number(MathEquation *equation, char *target, int target_len, const MPNumber *x)
+{
+ switch(equation->priv->format) {
+ case DEC:
+ mp_cast_to_string(x, 10, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
+ break;
+ case BIN:
+ mp_cast_to_string(x, 2, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
+ break;
+ case OCT:
+ mp_cast_to_string(x, 8, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
+ break;
+ case HEX:
+ mp_cast_to_string(x, 16, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
+ break;
+ case SCI:
+ make_eng_sci(equation, target, target_len, x, 10);
+ break;
+ case ENG:
+ make_eng_sci(equation, target, target_len, x, 10);
+ break;
+ }
}
@@ -1519,11 +1039,11 @@ math_equation_class_init (MathEquationClass *klass)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
- signals[BITFIELD_CHANGED] =
- g_signal_new ("bitfield-changed",
+ signals[DISPLAY_CHANGED] =
+ g_signal_new ("display-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MathEquationClass, bitfield_changed),
+ G_STRUCT_OFFSET (MathEquationClass, display_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
@@ -1539,9 +1059,42 @@ math_equation_class_init (MathEquationClass *klass)
static void
+solve_cb (MathEquation *equation)
+{
+ math_equation_solve(equation);
+}
+
+
+static void
+insert_text_cb (MathEquation *equation,
+ GtkTextIter *location,
+ gchar *text,
+ gint len,
+ gpointer user_data)
+{
+ equation->priv->state.entered_multiply = strcmp(text, "Ã?") == 0;
+
+ // FIXME: Check if have split/appended ans
+ g_signal_emit(equation, signals[DISPLAY_CHANGED], 0);
+}
+
+
+static void
+delete_range_cb (MathEquation *equation,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ gpointer user_data)
+{
+ // FIXME: Check if have joined/deleted ans
+ // FIXME: A replace will emit this both for delete-range and insert-text, can it be avoided?
+ g_signal_emit(equation, signals[DISPLAY_CHANGED], 0);
+}
+
+
+static void
math_equation_init(MathEquation *equation)
{
- /* Translators: Digits localized for the given language */
+ /* Digits localized for the given language */
const char *digit_values = _("0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F");
const char *default_digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
gchar **digits;
@@ -1550,6 +1103,9 @@ math_equation_init(MathEquation *equation)
equation->priv = G_TYPE_INSTANCE_GET_PRIVATE (equation, math_equation_get_type(), MathEquationPrivate);
+ g_signal_connect_after(equation, "insert-text", G_CALLBACK(insert_text_cb), equation);
+ g_signal_connect_after(equation, "delete-range", G_CALLBACK(delete_range_cb), equation);
+
digits = g_strsplit(digit_values, ",", -1);
for (i = 0; i < 16; i++) {
if (use_default_digits || digits[i] == NULL) {
@@ -1561,10 +1117,12 @@ math_equation_init(MathEquation *equation)
}
g_strfreev(digits);
- equation->priv->radix = get_radix(); /* Locale specific radix string. */
- equation->priv->tsep = get_tsep(); /* Locale specific thousands separator. */
+ // FIXME: Take out of get.c
+ equation->priv->radix = get_radix();
+ equation->priv->tsep = get_tsep();
equation->priv->tsep_count = get_tsep_count();
+ // Use GtkClipboad instead
equation->priv->primary_atom = gdk_atom_intern("PRIMARY", FALSE);
equation->priv->clipboard_atom = gdk_atom_intern("CLIPBOARD", FALSE);
@@ -1576,9 +1134,7 @@ math_equation_init(MathEquation *equation)
equation->priv->word_size = 32;
equation->priv->angle_unit = MP_DEGREES;
- for (i = 0; i < UNDO_HISTORY_LENGTH; i++) {
- equation->priv->h.e[i].expression = strdup("");
- equation->priv->h.e[i].ans_start = -1;
- equation->priv->h.e[i].ans_end = -1;
- }
+ mp_set_from_integer(0, &equation->priv->state.ans);
+ equation->priv->state.ans_start = -1;
+ equation->priv->state.ans_end = -1;
}
diff --git a/src/math-equation.h b/src/math-equation.h
index ea60df9..ea2c0b2 100644
--- a/src/math-equation.h
+++ b/src/math-equation.h
@@ -40,8 +40,9 @@ typedef struct
{
GtkTextBufferClass parent_class;
- void (*status_changed)(MathEquation *display);
- void (*bitfield_changed)(MathEquation *display);
+ void (*status_changed)(MathEquation *display);
+ void (*display_changed)(MathEquation *display);
+//FIXME void (*equation_changed)(MathEquation *display);
void (*number_mode_changed)(MathEquation *display);
} MathEquationClass;
@@ -63,31 +64,49 @@ const gchar *math_equation_get_numeric_point_text(MathEquation *equation);
void math_equation_set_status(MathEquation *equation, const gchar *status);
const gchar *math_equation_get_status(MathEquation *equation);
-gboolean math_equation_get_bitfield_enabled(MathEquation *equation);
-guint64 math_equation_get_bitfield(MathEquation *equation);
+gboolean math_equation_is_empty(MathEquation *equation);
+gboolean math_equation_is_result(MathEquation *equation);
+gchar *math_equation_get_display(MathEquation *equation);
+gchar *math_equation_get_equation(MathEquation *equation);
+gboolean math_equation_get_number(MathEquation *equation, MPNumber *z);
void math_equation_set_number_mode(MathEquation *equation, NumberMode mode);
NumberMode math_equation_get_number_mode(MathEquation *equation);
//FIXME: Make get_
void math_equation_set_accuracy(MathEquation *equation, int accuracy);
+int math_equation_get_accuracy(MathEquation *equation);
+
void math_equation_set_show_thousands_separator(MathEquation *equation, gboolean visible);
+gboolean math_equation_get_show_thousands_separator(MathEquation *equation);
+
void math_equation_set_show_trailing_zeroes(MathEquation *equation, gboolean visible);
+gboolean math_equation_get_show_trailing_zeroes(MathEquation *equation);
+
void math_equation_set_format(MathEquation *equation, DisplayFormat format);
+DisplayFormat math_equation_get_format(MathEquation *equation);
+
void math_equation_set_word_size(MathEquation *equation, int word_size);
+int math_equation_get_word_size(MathEquation *equation);
+
void math_equation_set_angle_unit(MathEquation *equation, MPAngleUnit angle_unit);
+MPAngleUnit math_equation_get_angle_unit(MathEquation *equation);
+
void math_equation_set_base(MathEquation *equation, gint base);
+gint math_equation_get_base(MathEquation *equation);
void math_equation_copy(MathEquation *equation);
void math_equation_paste(MathEquation *equation);
void math_equation_store(MathEquation *equation, const gchar *name);
void math_equation_recall(MathEquation *equation, const gchar *name);
+void math_equation_set(MathEquation *equation, const gchar *text);
+void math_equation_set_answer(MathEquation *equation);
+void math_equation_set_number(MathEquation *equation, const MPNumber *x);
void math_equation_insert(MathEquation *equation, const gchar *text);
void math_equation_insert_digit(MathEquation *equation, guint digit);
void math_equation_insert_numeric_point(MathEquation *equation);
void math_equation_insert_subtract(MathEquation *equation);
void math_equation_insert_exponent(MathEquation *equation);
-void math_equation_insert_character(MathEquation *equation, const gchar *character);
void math_equation_solve(MathEquation *equation);
void math_equation_factorize(MathEquation *equation);
void math_equation_delete(MathEquation *equation);
@@ -97,8 +116,6 @@ void math_equation_shift(MathEquation *equation, gint count);
void math_equation_toggle_bit(MathEquation *equation, guint bit);
//FIXME: Obsolete
-void display_set_number(MathEquation *equation, const MPNumber *);
-gboolean display_is_usable_number(MathEquation *equation, MPNumber *);
void display_make_number(MathEquation *equation, char *target, int target_len, const MPNumber *x);
#endif /* MATH_EQUATION_H */
diff --git a/src/mp-convert.c b/src/mp-convert.c
index 7d19b2a..575b1c4 100644
--- a/src/mp-convert.c
+++ b/src/mp-convert.c
@@ -597,12 +597,12 @@ mp_cast_to_string(const MPNumber *x, int base, int accuracy, bool trim_zeroes, c
{
MPNumber x_real, x_im;
GString *string;
-
+
string = g_string_sized_new(buffer_length);
-
+
mp_real_component(x, &x_real);
mp_imaginary_component(x, &x_im);
-
+
mp_cast_to_string_real(&x_real, base, accuracy, trim_zeroes, FALSE, string);
if (mp_is_complex(x)) {
GString *s;
diff --git a/src/mp-equation-lexer.l b/src/mp-equation-lexer.l
index a3fd1ab..91638ea 100644
--- a/src/mp-equation-lexer.l
+++ b/src/mp-equation-lexer.l
@@ -103,7 +103,7 @@ IN [iI][nN]
return tVARIABLE;\
}\
}
-[ \t\n]
+[ \r\t\n]
. {return *yytext;}
%%
diff --git a/src/ui.c b/src/ui.c
index 7828de2..44a2409 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -19,6 +19,7 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
#include "ui.h"
#include "ui-preferences.h"
@@ -178,6 +179,16 @@ mode_changed_cb(GtkWidget *menu, GCalctoolUI *ui)
G_MODULE_EXPORT
+gboolean
+main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, GCalctoolUI *ui)
+{
+ gboolean result;
+ g_signal_emit_by_name(ui->priv->display, "key-press-event", event, &result);
+ return result;
+}
+
+
+G_MODULE_EXPORT
void
show_preferences_cb(GtkMenuItem *menu, GCalctoolUI *ui)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]