/* -*-c-*- -------------- mixgtk_mixal.c : * Implementation of the functions declared in mixgtk_mixal.h * ------------------------------------------------------------------ * Last change: Time-stamp: "01/04/01 15:23:18 jose" * ------------------------------------------------------------------ * Copyright (C) 2001 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_mixal.h" static mix_vm_t *vm_; static GtkCList *clist_; static GdkColor sel_color_; static GdkColor break_color_; static GdkColor plain_color_; static gulong lineno_; #define SEL_COLOR_ "lightgrey" #define BREAK_COLOR_ "red" #define PLAIN_COLOR_ "white" static gboolean init_color_ (GdkColor *c, const gchar *name) { static GdkColormap *cmap = NULL; if (!cmap) cmap = gtk_widget_get_colormap (GTK_WIDGET (clist_)); return (gdk_color_parse (name, c) && gdk_colormap_alloc_color (cmap, c, FALSE, TRUE)); } /* initialise the mixal widgets */ gboolean mixgtk_mixal_init (mix_vm_t *vm) { g_return_val_if_fail (vm != NULL, FALSE); vm_ = vm; clist_ = GTK_CLIST (mixgtk_widget_factory_get (MIXGTK_WIDGET_MIXAL)); g_return_val_if_fail (clist_ != NULL, FALSE); /* allocate colors */ g_return_val_if_fail (init_color_ (&sel_color_, SEL_COLOR_), FALSE); g_return_val_if_fail (init_color_ (&break_color_, BREAK_COLOR_), FALSE); g_return_val_if_fail (init_color_ (&plain_color_, PLAIN_COLOR_), FALSE); return TRUE; } /* load the corresponding mixal file */ void mixgtk_mixal_load_file (void) { enum {ADDR_SIZE = 20, CONT_SIZE = 200}; static gchar ADDR[ADDR_SIZE], CONT[CONT_SIZE]; static gchar *TEXT[] = {ADDR, CONT}; static gchar *NULL_TEXT[] = {NULL, NULL}; const mix_src_file_t *file; g_assert (vm_); g_assert (clist_); gtk_clist_clear (clist_); file = mix_vm_get_src_file (vm_); if (file != NULL) { gint k; mix_address_t addr; lineno_ = mix_src_file_get_line_no (file); gtk_clist_freeze (clist_); for (k = 0; k < lineno_; ++k) { const gchar *line = mix_src_file_get_line (file, k + 1); snprintf (CONT, CONT_SIZE, "%03d: %s", k + 1, line); addr = mix_vm_get_lineno_address (vm_, k + 1); if (addr != MIX_VM_CELL_NO) { sprintf (ADDR, "%04d: ", mix_short_magnitude (addr)); mix_word_print_to_buffer (mix_vm_get_addr_contents (vm_, addr), ADDR + strlen (ADDR)); } else ADDR[0] = '\0'; gtk_clist_append (clist_, TEXT); gtk_clist_set_row_data (clist_, k, GINT_TO_POINTER (mix_short_magnitude (addr))); } gtk_clist_append (clist_, NULL_TEXT); gtk_clist_set_row_data (clist_, k, GINT_TO_POINTER (MIX_VM_CELL_NO)); gtk_clist_unselect_row (clist_, 0, 0); gtk_clist_thaw (clist_); } else lineno_ = 0; } /* update the widgets */ static void reset_bg_ (gint row) { gint addr = GPOINTER_TO_INT (gtk_clist_get_row_data (clist_, row)); gboolean isset = mix_vm_has_breakpoint_at_address (vm_, addr); gtk_clist_set_background (clist_, row, isset ? &break_color_ : &plain_color_); } static void select_row_ (gint row) { static gint last = -1; gtk_clist_set_background (clist_, row, &sel_color_); if (gtk_clist_row_is_visible (clist_, row) != GTK_VISIBILITY_FULL) gtk_clist_moveto (clist_, row, 0, 0.25, 0); if (last != -1 && last != row) reset_bg_ (last); last = row; } void mixgtk_mixal_update (void) { gint addr = 0; gint k = 0; g_assert (vm_); g_assert (clist_); addr = mix_short_magnitude (mix_vm_get_prog_count (vm_)); k = gtk_clist_find_row_from_data (clist_, GINT_TO_POINTER (addr)); select_row_ (k); } /* breakpoints */ void mixgtk_mixal_update_bp_at_address (guint addr) { gint k; g_assert (vm_); g_assert (clist_); k = gtk_clist_find_row_from_data (clist_, GINT_TO_POINTER (addr)); reset_bg_ (k); } void mixgtk_mixal_update_bp_at_line (guint line) { if ( line < 1 ) return; while (line < lineno_) { gint addr = GPOINTER_TO_INT (gtk_clist_get_row_data (clist_, line - 1)); if (addr != MIX_VM_CELL_NO) break; ++line; } reset_bg_ (line - 1); } void mixgtk_mixal_update_bp_all () { gint k, addr; for (k = 0; k < lineno_; ++k) reset_bg_ (k); addr = mix_vm_get_prog_count (vm_); k = gtk_clist_find_row_from_data (clist_, GINT_TO_POINTER (addr)); select_row_ (k); } /* callbacks */ void on_mixal_select_row (GtkWidget *w, gint row, gint col, GdkEventButton *e, gpointer data) { gboolean isset; gint addr, pc; gtk_clist_unselect_row (clist_, row, col); addr = GPOINTER_TO_INT (gtk_clist_get_row_data (clist_, row)); pc = mix_vm_get_prog_count (vm_); if (addr < MIX_VM_CELL_NO && addr != pc) { isset = mix_vm_has_breakpoint_at_address (vm_, addr); if (isset) mix_vm_clear_breakpoint_address (vm_, addr); else mix_vm_set_breakpoint_address (vm_, addr); reset_bg_ (row); } }