/* -*-c-*- -------------- mixgtk_mixvm.c : * Implementation of the functions declared in mixgtk_mixvm.h * ------------------------------------------------------------------ * $Id: mixgtk_mixvm.c,v 1.10 2002/04/10 23:39:40 jao Exp $ * ------------------------------------------------------------------ * Copyright (C) 2001, 2002 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include "mixgtk_widgets.h" #include "mixgtk_mixvm.h" #include "mixgtk_cmd_dispatcher.h" #include "mixgtk_input.h" /* register widgets */ #define REGISTER_NO_ (MIXGTK_WIDGET_rI6 - MIXGTK_WIDGET_rA + 1) static GtkEntry *reg_entries_[REGISTER_NO_]; static GtkTooltips *tips_ = NULL; static GtkEntry *loc_entry_; static GtkWidget *goto_ = NULL; static GtkEntry *goto_entry_ = NULL; static GtkToggleButton *over_button_; static GtkToggleButton *cmp_buttons_[3]; static GtkCList *memory_; static GtkLabel *laptime_; static GtkLabel *progtime_; static GtkLabel *uptime_; static mix_vm_t *vm_; #define GOTO_ENTRY_NAME_ "goto_entry" static void init_goto_ (void) { goto_ = mixgtk_widget_factory_get_dialog (MIXGTK_GOTO_DIALOG); g_assert (goto_ != NULL); goto_entry_ = GTK_ENTRY (mixgtk_widget_factory_get_child_by_name ( MIXGTK_GOTO_DIALOG, GOTO_ENTRY_NAME_)); g_assert (goto_entry_ != NULL); } static void update_register_ (mixgtk_widget_id_t reg) { static gchar BUFFER[20]; mix_word_t tipval = MIX_WORD_ZERO; switch (reg) { case MIXGTK_WIDGET_rA: tipval = mix_vm_get_rA (vm_); mix_word_print_to_buffer (tipval, BUFFER); break; case MIXGTK_WIDGET_rX: tipval = mix_vm_get_rX (vm_); mix_word_print_to_buffer (tipval, BUFFER); break; case MIXGTK_WIDGET_rJ: tipval = mix_short_to_word_fast (mix_vm_get_rJ (vm_)); mix_short_print_to_buffer (mix_vm_get_rJ (vm_), BUFFER); break; case MIXGTK_WIDGET_rI1: case MIXGTK_WIDGET_rI2: case MIXGTK_WIDGET_rI3: case MIXGTK_WIDGET_rI4: case MIXGTK_WIDGET_rI5: case MIXGTK_WIDGET_rI6: { gint k = reg - MIXGTK_WIDGET_rI1 + 1; tipval = mix_short_to_word_fast (mix_vm_get_rI (vm_, k)); mix_short_print_to_buffer (mix_vm_get_rI (vm_, k), BUFFER); } break; default: g_assert_not_reached (); } gtk_entry_set_text (reg_entries_[reg - MIXGTK_WIDGET_rA], BUFFER); g_snprintf (BUFFER, 20, "%s%ld", mix_word_is_negative (tipval)? "-" : "", mix_word_magnitude (tipval)); gtk_tooltips_set_tip (tips_, GTK_WIDGET (reg_entries_[reg - MIXGTK_WIDGET_rA]), BUFFER, NULL); } static void on_mem_adj_change_ (GtkAdjustment *adj) { mixgtk_mixvm_update_cells (); } /* initialise the mixvm widgets */ gboolean mixgtk_mixvm_init (mix_vm_t *vm, mixgtk_dialog_id_t top) { int k; gchar *text[] = {"", ""}; GtkWidget *scrol; GtkAdjustment *adj; g_return_val_if_fail (vm != NULL, FALSE); vm_ = vm; if (!tips_) tips_ = gtk_tooltips_new (); for (k = 0; k < REGISTER_NO_; ++k) { reg_entries_[k] = GTK_ENTRY (mixgtk_widget_factory_get (top, MIXGTK_WIDGET_rA + k)); g_return_val_if_fail (reg_entries_[k] != NULL, FALSE); } loc_entry_ = GTK_ENTRY (mixgtk_widget_factory_get (top, MIXGTK_WIDGET_LOC)); g_return_val_if_fail (loc_entry_ != NULL, FALSE); uptime_ = GTK_LABEL (mixgtk_widget_factory_get (top, MIXGTK_WIDGET_UPTIME)); g_return_val_if_fail (uptime_ != NULL, FALSE); progtime_ = GTK_LABEL (mixgtk_widget_factory_get (top, MIXGTK_WIDGET_PROGTIME)); g_return_val_if_fail (progtime_ != NULL, FALSE); laptime_ = GTK_LABEL (mixgtk_widget_factory_get (top, MIXGTK_WIDGET_LAPTIME)); g_return_val_if_fail (laptime_ != NULL, FALSE); over_button_ = GTK_TOGGLE_BUTTON (mixgtk_widget_factory_get (top, MIXGTK_WIDGET_OVER)); g_return_val_if_fail (over_button_ != NULL, FALSE); for (k = 0; k < 3; ++k) { cmp_buttons_[k] = GTK_TOGGLE_BUTTON (mixgtk_widget_factory_get (top, MIXGTK_WIDGET_CMP_L +k)); g_return_val_if_fail (cmp_buttons_[k] != NULL, FALSE); } memory_ = GTK_CLIST (mixgtk_widget_factory_get (top, MIXGTK_WIDGET_CELLS)); g_return_val_if_fail (memory_ != NULL, FALSE); gtk_clist_set_column_justification (memory_, 0, GTK_JUSTIFY_CENTER); gtk_clist_set_column_justification (memory_, 1, GTK_JUSTIFY_CENTER); gtk_clist_freeze (memory_); for (k = 0; k< MIX_VM_CELL_NO; ++k) { gchar buffer[20]; g_snprintf (buffer, 20, "%04d", k); text[0] = buffer; gtk_clist_append (memory_, text); } gtk_clist_thaw (memory_); scrol = mixgtk_widget_factory_get (top, MIXGTK_WIDGET_CELLS_SCROLL); g_return_val_if_fail (scrol != NULL, FALSE); adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrol)); gtk_signal_connect (GTK_OBJECT (adj), "value_changed", GTK_SIGNAL_FUNC (on_mem_adj_change_), NULL); goto_ = NULL; return TRUE; } /* update register widgets */ void mixgtk_mixvm_update_registers (void) { gint k; for (k = MIXGTK_WIDGET_rA; k <= MIXGTK_WIDGET_rI6; ++k) update_register_ (k); } /* update the overflow toggle */ void mixgtk_mixvm_update_over_toggle (void) { g_assert (over_button_); gtk_toggle_button_set_active (over_button_, mix_vm_get_overflow (vm_)); } /* update the comparison flag */ void mixgtk_mixvm_update_cmp (void) { gint toggle; g_assert (cmp_buttons_); toggle = mix_vm_get_cmpflag (vm_); gtk_toggle_button_set_active (cmp_buttons_[toggle], TRUE); } /* update the memory cells */ void mixgtk_mixvm_update_cells (void) { static gchar BUFFER[20]; gint k = 0; g_assert (memory_); gtk_clist_freeze (memory_); while (gtk_clist_row_is_visible (memory_, k) == GTK_VISIBILITY_NONE) ++k; while (gtk_clist_row_is_visible (memory_, k) != GTK_VISIBILITY_NONE) { mix_word_print_to_buffer (mix_vm_get_addr_contents (vm_, k), BUFFER); gtk_clist_set_text (memory_, k, 1, BUFFER); ++k; } gtk_clist_thaw (memory_); } void mixgtk_mixvm_update_cells_to_address (gint address) { g_assert (memory_); if (address >= MIX_VM_CELL_NO) return; gtk_clist_freeze (memory_); gtk_clist_moveto (memory_, address, 0, 0, 0); gtk_clist_thaw (memory_); mixgtk_mixvm_update_cells (); } /* update the loc pointer */ void mixgtk_mixvm_update_loc (void) { enum {SIZE = 10 }; static gchar BUFFER[SIZE]; mix_short_t locval; g_assert (loc_entry_); locval = mix_vm_get_prog_count (vm_); g_snprintf (BUFFER, SIZE, "%04d", mix_short_magnitude (locval)); gtk_entry_set_text (loc_entry_, BUFFER); } /* update times */ void mixgtk_mixvm_update_times (void) { enum {SIZE = 20 }; static gchar BUFFER[SIZE]; gint uptime, progtime, laptime; g_assert (uptime_ && progtime_ && laptime_); mixgtk_cmd_dispatcher_get_times (&uptime, &progtime, &laptime); g_snprintf (BUFFER, SIZE, "%d", uptime); gtk_label_set_text (uptime_, BUFFER); g_snprintf (BUFFER, SIZE, "%d", progtime); gtk_label_set_text (progtime_, BUFFER); g_snprintf (BUFFER, SIZE, "%d", laptime); gtk_label_set_text (laptime_, BUFFER); } /* update all mixvm widgets */ void mixgtk_mixvm_update_vm_widgets (void) { mixgtk_mixvm_update_registers (); mixgtk_mixvm_update_loc (); mixgtk_mixvm_update_over_toggle (); mixgtk_mixvm_update_cmp (); mixgtk_mixvm_update_cells (); mixgtk_mixvm_update_times (); } /* update cmp flag */ void on_cmp_e_toggled (GtkWidget *widget, gpointer data) { if (GTK_TOGGLE_BUTTON (widget)->active) mix_vm_set_cmpflag (vm_, mix_EQ); } void on_cmp_l_toggled (GtkWidget *widget, gpointer data) { if (GTK_TOGGLE_BUTTON (widget)->active) mix_vm_set_cmpflag (vm_, mix_LESS); } void on_cmp_g_toggled (GtkWidget *widget, gpointer data) { if (GTK_TOGGLE_BUTTON (widget)->active) mix_vm_set_cmpflag (vm_, mix_GREAT); } void on_overflow_toggled (GtkWidget *widget, gpointer data) { mix_vm_set_overflow (vm_, GTK_TOGGLE_BUTTON (widget)->active); } void on_loc_arrow_clicked (GtkWidget *widget, gpointer data) { gint address = mix_short_magnitude (mix_vm_get_prog_count (vm_)); mixgtk_mixvm_update_cells_to_address (address); } static void register_AX_ (mix_word_t w, gpointer reg) { gint k = GPOINTER_TO_INT (reg); if (k == 0) mix_vm_set_rA (vm_, w); else mix_vm_set_rX (vm_, w); update_register_ (MIXGTK_WIDGET_rA + k); } static void register_j_ (mix_word_t w, gpointer data) { if (mix_word_is_negative (w)) mix_word_reverse_sign (w); mix_vm_set_rJ (vm_, mix_word_to_short_fast (w)); update_register_ (MIXGTK_WIDGET_rJ); } static void register_i_ (mix_word_t w, gpointer reg) { mix_vm_set_rI (vm_, GPOINTER_TO_INT (reg), mix_word_to_short_fast (w)); update_register_ (MIXGTK_WIDGET_rI1 - 1 + GPOINTER_TO_INT (reg)); } gboolean on_register_click (GtkWidget *w, GdkEvent *e, gpointer data) { enum {SIZE = 20}; static gchar BUFFER[SIZE]; gint k; if (w == GTK_WIDGET (reg_entries_[0])) mixgtk_input_word (_("Register A"), mix_vm_get_rA (vm_), register_AX_, GINT_TO_POINTER (0)); else if (w == GTK_WIDGET (reg_entries_[1])) mixgtk_input_word (_("Register X"), mix_vm_get_rX (vm_), register_AX_, GINT_TO_POINTER(1)); else if (w == GTK_WIDGET (reg_entries_[2])) mixgtk_input_short (_("Register J"), mix_vm_get_rJ (vm_), register_j_, NULL); else for (k = 1; k < 7; ++k) { if (w == GTK_WIDGET (reg_entries_[2 + k])) { g_snprintf (BUFFER, SIZE, _("Register I%d"), k); mixgtk_input_short (BUFFER, mix_vm_get_rI (vm_, k), register_i_, GINT_TO_POINTER (k)); break; } } return FALSE; } static void mem_cell_ (mix_word_t w, gpointer a) { mix_short_t addr = mix_short_new (GPOINTER_TO_INT (a)); mix_vm_set_addr_contents (vm_, addr, w); mixgtk_mixvm_update_cells (); } void on_memory_cells_select_row (GtkCList *w, gint row, gint col, GdkEvent *e, gpointer data) { enum {SIZE = 30}; static gchar BUFFER[SIZE]; g_snprintf (BUFFER, SIZE, _("Memory cell no. %d"), row); mixgtk_input_word (BUFFER, mix_vm_get_addr_contents (vm_, mix_short_new (row)), mem_cell_, GINT_TO_POINTER (row)); } void on_memory_cells_click_column (GtkCList *w, gint row, gpointer data) { if (!goto_) init_goto_ (); gtk_widget_show (goto_); } void on_goto_cancel_clicked (GtkWidget *w, gpointer data) { gtk_widget_hide (goto_); } void on_goto_ok_clicked (GtkWidget *w, gpointer data) { gchar *txt = gtk_entry_get_text (goto_entry_); mix_short_t addr = mix_short_new (atoi (txt)); if (addr < MIX_VM_CELL_NO) { gtk_widget_hide (goto_); mixgtk_mixvm_update_cells_to_address (addr); } }