From 300160e73da486946ae513f1d039dcd7b85ff17c Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Mon, 20 Mar 2006 22:46:46 +0000 Subject: Version 1.2.1 imported git-archimport-id: mdk@sv.gnu.org/mdk--devel--1--patch-1 --- mixgtk/mixgtk_mixal.c | 580 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 580 insertions(+) create mode 100644 mixgtk/mixgtk_mixal.c (limited to 'mixgtk/mixgtk_mixal.c') diff --git a/mixgtk/mixgtk_mixal.c b/mixgtk/mixgtk_mixal.c new file mode 100644 index 0000000..50d09a7 --- /dev/null +++ b/mixgtk/mixgtk_mixal.c @@ -0,0 +1,580 @@ +/* -*-c-*- -------------- mixgtk_mixal.c : + * Implementation of the functions declared in mixgtk_mixal.h + * ------------------------------------------------------------------ + * $Id: mixgtk_mixal.c,v 1.22 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include +#include + +#include "mixgtk_widgets.h" +#include "mixgtk_config.h" +#include "mixgtk_fontsel.h" +#include "mixgtk_mixal.h" + +static mix_vm_t *vm_ = NULL; +static GtkTreeView *clist_ = NULL; +static GtkListStore *clist_store_ = NULL; + +static gulong lineno_; +static GtkStatusbar *status_ = NULL; +static gint status_context_ = 0; +static GPtrArray *tips_text_ = NULL; + +static GtkWidget *symbols_dlg_ = NULL; +static GtkTreeView *symbols_view_ = NULL; +static GtkListStore *symbols_store_ = NULL; +static const gchar *SYMBOLS_VIEW_NAME_ = "symbols_view"; + +static const gchar *bp_stock_id_ = NULL; +static const gchar *pc_stock_id_ = NULL; +static const guint bp_stock_size_ = GTK_ICON_SIZE_MENU; + +enum { + CLIST_BP_ID_COL, + CLIST_BP_SIZE_COL, + CLIST_ADDRESS_COL, + CLIST_BYTECODE_COL, + CLIST_CODE_COL, + CLIST_ADDRESS_NO_COL, + CLIST_LINE_NO_COL, + CLIST_COL_NO +}; + +enum { + SYMBOLS_NAME_COL, + SYMBOLS_VALUE_COL, + SYMBOLS_WORD_COL, + SYMBOLS_COL_NO +}; + + +static gboolean +mixal_event_ (GtkWidget *w, GdkEvent *event, gpointer data); + + +static void +init_symbols_ (void) +{ + GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); + + symbols_dlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_SYMBOLS_DIALOG); + g_assert (symbols_dlg_); + symbols_view_ = GTK_TREE_VIEW + (mixgtk_widget_factory_get_child_by_name + (MIXGTK_SYMBOLS_DIALOG, SYMBOLS_VIEW_NAME_)); + g_assert (symbols_view_); + + mixgtk_fontsel_set_font (MIX_FONT_SYMBOLS, GTK_WIDGET (symbols_view_)); + + symbols_store_ = gtk_list_store_new (SYMBOLS_COL_NO, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (symbols_store_), + SYMBOLS_NAME_COL, + GTK_SORT_ASCENDING); + + gtk_tree_view_set_model (symbols_view_, GTK_TREE_MODEL (symbols_store_)); + g_object_unref (G_OBJECT (symbols_store_)); + gtk_tree_view_append_column + (symbols_view_, + gtk_tree_view_column_new_with_attributes ("Name", renderer, + "text", SYMBOLS_NAME_COL, + NULL)); + gtk_tree_view_append_column + (symbols_view_, + gtk_tree_view_column_new_with_attributes ("Value", renderer, + "text", SYMBOLS_VALUE_COL, + NULL)); + gtk_tree_view_append_column + (symbols_view_, + gtk_tree_view_column_new_with_attributes ("", renderer, + "text", SYMBOLS_WORD_COL, + NULL)); +} + +static void +insert_symbol_ (gpointer symbol, gpointer value, gpointer data) +{ + enum {DEC_SIZE = 25, WORD_SIZE = 20}; + static gchar DEC[DEC_SIZE], WORD[WORD_SIZE]; + + GtkTreeIter iter; + + mix_word_t w = (mix_word_t)GPOINTER_TO_INT (value); + g_snprintf (DEC, DEC_SIZE, "%s%ld", + mix_word_is_negative (w)? "-" : "+", + mix_word_magnitude (w)); + mix_word_print_to_buffer (w, WORD); + + gtk_list_store_append (symbols_store_, &iter); + gtk_list_store_set (symbols_store_, &iter, + SYMBOLS_NAME_COL, (const gchar*)symbol, + SYMBOLS_VALUE_COL, DEC, + SYMBOLS_WORD_COL, WORD, + -1); +} + +static void +fill_symbols_ (const mix_symbol_table_t *table) +{ + if (symbols_view_) + gtk_list_store_clear (symbols_store_); + else + init_symbols_ (); + + mix_symbol_table_foreach (((mix_symbol_table_t *)table), + insert_symbol_, NULL); +} + +static void +init_clist_ (void) +{ + GtkStockItem item; + + GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); + GtkCellRenderer *bprenderer = gtk_cell_renderer_pixbuf_new (); + + clist_ = GTK_TREE_VIEW (gtk_tree_view_new ()); + + clist_store_ = gtk_list_store_new (CLIST_COL_NO, + G_TYPE_STRING, + G_TYPE_INT, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_INT, + G_TYPE_INT); + + gtk_tree_view_set_model (clist_, GTK_TREE_MODEL (clist_store_)); + g_object_unref (G_OBJECT (clist_store_)); + gtk_tree_view_set_rules_hint (clist_, TRUE); + + gtk_tree_view_append_column + (clist_, + gtk_tree_view_column_new_with_attributes ("", bprenderer, + "stock-id", CLIST_BP_ID_COL, + "stock-size", CLIST_BP_SIZE_COL, + NULL)); + gtk_tree_view_append_column + (clist_, + gtk_tree_view_column_new_with_attributes ("Address", renderer, + "text", CLIST_ADDRESS_COL, + NULL)); + gtk_tree_view_append_column + (clist_, + gtk_tree_view_column_new_with_attributes ("Bytecode", renderer, + "text", CLIST_BYTECODE_COL, + NULL)); + gtk_tree_view_append_column + (clist_, + gtk_tree_view_column_new_with_attributes ("Source", renderer, + "text", CLIST_CODE_COL, + NULL)); + + if (gtk_stock_lookup (GTK_STOCK_STOP, &item)) + { + bp_stock_id_ = item.stock_id; + } + + if (gtk_stock_lookup (GTK_STOCK_GO_FORWARD, &item)) + { + pc_stock_id_ = item.stock_id; + } + + symbols_dlg_ = NULL; + symbols_view_ = NULL; + + g_signal_connect (G_OBJECT (clist_), "event", + G_CALLBACK (mixal_event_), NULL); + + + mixgtk_fontsel_set_font (MIX_FONT_MIXAL, GTK_WIDGET (clist_)); + + gtk_widget_show (GTK_WIDGET (clist_)); + +} + + +/* initialise the mixal widgets */ +GtkWidget * +mixgtk_mixal_init (mix_vm_t *vm) +{ + if (vm != NULL) vm_ = vm; + + if (vm_ == NULL) return FALSE; + + if (clist_ == NULL) init_clist_ (); + + status_ = NULL; + + return GTK_WIDGET (clist_); +} + +void +mixgtk_mixal_reparent (GtkStatusbar *status) +{ + g_assert (status != NULL); + mixgtk_mixal_pop_status (); + status_ = status; + status_context_ = gtk_statusbar_get_context_id (status_, "MIXAL status"); +} + +void +mixgtk_mixal_update_fonts (void) +{ + mixgtk_fontsel_set_font (MIX_FONT_MIXAL, GTK_WIDGET (clist_)); + mixgtk_fontsel_set_font (MIX_FONT_SYMBOLS, GTK_WIDGET (symbols_view_)); +} + +void +mixgtk_mixal_pop_status (void) +{ + if (status_ != NULL) + gtk_statusbar_pop (status_, status_context_); +} + +/* load the corresponding mixal file */ +static void +update_tips_ (const mix_symbol_table_t *table, + const gchar *line) +{ + enum {SIZE = 256}; + static gchar BUFFER[256]; + static const gchar *DELIMITERS = " /+*=-()\t,:\n"; + if (line) + { + guint k = 0; + gchar *tip = g_strdup (""); + gchar *new_tip; + gchar **tokens; + gchar *text = g_strdup (line); + text = g_strdelimit (text, DELIMITERS, ' '); + tokens = g_strsplit (g_strstrip (text), " ", -1); + while (tokens[k]) + { + if (mix_symbol_table_is_defined (table, tokens[k])) + { + mix_word_t val = mix_symbol_table_value (table, tokens[k]); + g_snprintf (BUFFER, SIZE, "[ %s = %s%ld ]", tokens[k], + mix_word_is_negative (val)? "-" : "+", + mix_word_magnitude (val)); + new_tip = g_strconcat (tip, " ", BUFFER, NULL); + g_free (tip); + tip = new_tip; + } + ++k; + } + g_ptr_array_add (tips_text_, (gpointer)tip); + g_strfreev (tokens); + g_free (text); + } +} + +void +mixgtk_mixal_load_file (void) +{ + enum {ADDR_SIZE = 20, CONT_SIZE = 200, WORD_SIZE = 20}; + static gchar ADDR[ADDR_SIZE], CONT[CONT_SIZE], WORD[WORD_SIZE]; + + const mix_src_file_t *file; + GtkTreeIter iter; + + g_assert (vm_); + g_assert (clist_); + + gtk_list_store_clear (clist_store_); + if (tips_text_) + { + g_ptr_array_free (tips_text_, TRUE); + tips_text_ = NULL; + } + + file = mix_vm_get_src_file (vm_); + if (file != NULL) + { + gint k; + + mix_address_t addr; + const mix_symbol_table_t *table = mix_vm_get_symbol_table (vm_); + + if (table) tips_text_ = g_ptr_array_new (); + + lineno_ = mix_src_file_get_line_no (file); + + for (k = 0; k < lineno_; ++k) + { + gchar *line = + g_strchomp ((gchar *)mix_src_file_get_line (file, k + 1)); + + g_snprintf (CONT, CONT_SIZE, " %03d: %s", k + 1, line); + addr = mix_vm_get_lineno_address (vm_, k + 1); + if (addr != MIX_VM_CELL_NO) + { + g_snprintf (ADDR, ADDR_SIZE, "%04d", mix_short_magnitude (addr)); + mix_word_print_to_buffer (mix_vm_get_addr_contents (vm_, addr), + WORD); + } + else + { + g_snprintf (ADDR, ADDR_SIZE, _("N/A")); + g_snprintf (WORD, WORD_SIZE, _("N/A")); + } + gtk_list_store_append (clist_store_, &iter); + gtk_list_store_set (clist_store_, &iter, + CLIST_ADDRESS_NO_COL, mix_short_magnitude (addr), + CLIST_LINE_NO_COL, k + 1, + CLIST_ADDRESS_COL, ADDR, + CLIST_CODE_COL, CONT, + CLIST_BYTECODE_COL, WORD, + CLIST_BP_SIZE_COL, bp_stock_size_, + -1); + if (table) update_tips_ (table, line); + } + if (table) fill_symbols_ (table); + } + else + { + lineno_ = 0; + gtk_list_store_append (clist_store_, &iter); + gtk_list_store_set (clist_store_, &iter, + CLIST_ADDRESS_NO_COL, MIX_VM_CELL_NO, + CLIST_LINE_NO_COL, 0, + CLIST_ADDRESS_COL, "", + CLIST_CODE_COL, _("Source not available"), + CLIST_BYTECODE_COL, "", + -1); + } +} + + +/* update the widgets */ +static gint +find_address_ (gint address) +{ + GtkTreeIter iter; + gint addr; + gint row = 0; + gboolean valid = + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (clist_store_), &iter); + + while (valid) + { + ++row; + gtk_tree_model_get (GTK_TREE_MODEL (clist_store_), &iter, + CLIST_ADDRESS_NO_COL, &addr, -1); + if (addr == address) return row; + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (clist_store_), &iter); + } + return 0; +} + +static void +update_bp_ (gint row) +{ + if (row > 0) + { + GtkTreePath *path = gtk_tree_path_new_from_indices (row - 1, -1); + GtkTreeIter iter; + + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (clist_store_), &iter, path)) + { + gint address; + const gchar *id = NULL; + + gtk_tree_model_get (GTK_TREE_MODEL (clist_store_), &iter, + CLIST_ADDRESS_NO_COL, &address, -1); + if (mix_vm_has_breakpoint_at_address (vm_, address)) + id = bp_stock_id_; + else if (address == + (gint) mix_short_magnitude (mix_vm_get_prog_count (vm_))) + id = pc_stock_id_; + + gtk_list_store_set (clist_store_, &iter, CLIST_BP_ID_COL, id, -1); + } + gtk_tree_path_free (path); + } +} + +static void +select_row_ (gint row) +{ + static gint previous = 0; + + if (row > 0 && previous != row) + { + GtkTreePath *path = gtk_tree_path_new_from_indices (row - 1, -1); + GtkTreeIter iter; + + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (clist_store_), &iter, path)) + { + gtk_list_store_set (clist_store_, &iter, + CLIST_BP_ID_COL, pc_stock_id_, + -1); + update_bp_ (previous); + previous = row; + gtk_tree_view_scroll_to_cell (clist_, path, NULL, FALSE, 0.3, 0); + } + gtk_tree_path_free (path); + } +} + +void +mixgtk_mixal_update (void) +{ + gint addr = 0; + + g_assert (vm_); + + addr = (gint) mix_short_magnitude (mix_vm_get_prog_count (vm_)); + select_row_ (find_address_ (addr)); +} + +/* breakpoints */ +void +mixgtk_mixal_update_bp_at_address (guint addr) +{ + update_bp_ (find_address_ ((gint)addr)); +} + +void +mixgtk_mixal_update_bp_at_line (guint line) +{ + update_bp_ ((gint)line); +} + +void +mixgtk_mixal_update_bp_all (void) +{ + gint k; + for (k = 1; k <= lineno_; ++k) update_bp_ (k); + mixgtk_mixal_update (); +} + +/* callbacks */ +static void +mixal_row_clicked_ (GtkTreeIter *iter) +{ + + gint addr = MIX_VM_CELL_NO; + gtk_tree_model_get (GTK_TREE_MODEL (clist_store_), + iter, CLIST_ADDRESS_NO_COL, &addr, -1); + + if (addr < MIX_VM_CELL_NO) + { + gboolean 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); + update_bp_ (find_address_ (addr)); + } +} + +static void +mixal_motion_ (GtkTreeIter *iter) +{ + static gint last_row = 0; + static guint last_message = 0; + + gint row = last_row; + + gtk_tree_model_get (GTK_TREE_MODEL (clist_store_), iter, + CLIST_LINE_NO_COL, &row, -1); + + if (row > 0 && row != last_row && tips_text_) + { + const gchar *msg = NULL; + last_row = row; + if (last_message) + gtk_statusbar_remove (status_, status_context_, last_message); + msg = (const gchar *)g_ptr_array_index (tips_text_, row - 1); + if (msg) + last_message = gtk_statusbar_push (status_, status_context_, msg); + else + last_message = 0; + } +} + +static gboolean +mixal_event_ (GtkWidget *w, GdkEvent *event, gpointer data) +{ + GdkEventType type = event->type; + if ((type == GDK_BUTTON_PRESS || type == GDK_MOTION_NOTIFY) + && (gtk_tree_view_get_bin_window (clist_) == event->any.window)) + { + gdouble x = (type == GDK_BUTTON_PRESS)? event->button.x : event->motion.x; + gdouble y = (type == GDK_BUTTON_PRESS)? event->button.y : event->motion.y; + GtkTreeIter iter; + GtkTreePath *path = NULL; + GtkTreeViewColumn *col = NULL; + if (gtk_tree_view_get_path_at_pos (clist_, x, y, &path, &col, NULL, NULL) + && gtk_tree_model_get_iter (GTK_TREE_MODEL (clist_store_), + &iter, path)) + { + if (type == GDK_BUTTON_PRESS) mixal_row_clicked_ (&iter); + else mixal_motion_ (&iter); + } + if (path) gtk_tree_path_free (path); + return TRUE; + } + return FALSE; +} + +void +on_symbol_ok_clicked () +{ + gtk_widget_hide (symbols_dlg_); +} + +void +on_symbols_activate () +{ + if (!symbols_dlg_) init_symbols_ (); + gtk_widget_show (symbols_dlg_); +} + +void +on_mixal_leave_notify_event () +{ + if (status_ != NULL) gtk_statusbar_pop (status_, status_context_); +} + +void +on_mixal_font_activate () +{ + GtkWidget *w[] = { GTK_WIDGET (clist_) }; + mixgtk_fontsel_query_font (MIX_FONT_MIXAL, w, 1); +} + +void +on_symbols_font_activate () +{ + if (symbols_view_ != NULL) + { + GtkWidget *w[] = { GTK_WIDGET (symbols_view_) }; + mixgtk_fontsel_query_font (MIX_FONT_SYMBOLS, w, 1); + } + else + mixgtk_fontsel_query_font (MIX_FONT_SYMBOLS, NULL, 0); +} -- cgit v1.2.3