From 6b302e55d01e3fd2c60b13706fff023cb999436f Mon Sep 17 00:00:00 2001 From: sgranjoux Date: Sat, 24 Mar 2007 08:49:50 +0000 Subject: [PATCH] * plugins/debug-manager/threads.c, plugins/debug-manager/debug_tree.c, plugins/debug-manager/debug_tree.h, plugins/debug-manager/locals.c, plugins/debug-manager/registers.c, plugins/debug-manager/stack_trace.c: Allow to change current thread updating register, stack and locals Allow to change current stack frame updating locals * plugins/gdb/debugger.c: Read argument of selected stack frame * plugins/debug-manager/data_view.c: Fix an unrelated bug git-svn-id: http://svn.gnome.org/svn/anjuta/trunk@2883 1dbfb86a-d425-0410-a06b-cb591aac69f6 --- ChangeLog | 17 ++ plugins/debug-manager/data_view.c | 2 +- plugins/debug-manager/debug_tree.c | 63 +++++-- plugins/debug-manager/debug_tree.h | 30 ++-- plugins/debug-manager/locals.c | 200 +++++++++++++++++----- plugins/debug-manager/registers.c | 323 ++++++++++++++++++++++++++---------- plugins/debug-manager/stack_trace.c | 230 ++++++++++++++++--------- plugins/debug-manager/threads.c | 59 ++++++- plugins/gdb/debugger.c | 14 +- 9 files changed, 693 insertions(+), 245 deletions(-) diff --git a/ChangeLog b/ChangeLog index afb65451..09f7bd87 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2007-03-24 Sebastien Granjoux + + * plugins/debug-manager/threads.c, + plugins/debug-manager/debug_tree.c, + plugins/debug-manager/debug_tree.h, + plugins/debug-manager/locals.c, + plugins/debug-manager/registers.c, + plugins/debug-manager/stack_trace.c: + Allow to change current thread updating register, stack and locals + Allow to change current stack frame updating locals + + * plugins/gdb/debugger.c: + Read argument of selected stack frame + + * plugins/debug-manager/data_view.c: + Fix an unrelated bug + 2007-03-23 Naba Kumar * plugins/document-manager/anjuta-docman.c, diff --git a/plugins/debug-manager/data_view.c b/plugins/debug-manager/data_view.c index 7f8c04fd..f1f5412c 100644 --- a/plugins/debug-manager/data_view.c +++ b/plugins/debug-manager/data_view.c @@ -281,7 +281,7 @@ dma_data_view_goto_activate (GtkWidget *menu_item, gtk_entry_set_text (GTK_ENTRY (view->goto_entry), "0x"); gtk_widget_show (view->goto_window); - gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE); + gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view->address), FALSE); gtk_widget_grab_focus (view->goto_entry); send_focus_change (view->goto_entry, TRUE); gtk_editable_set_position (GTK_EDITABLE (view->goto_entry), -1); diff --git a/plugins/debug-manager/debug_tree.c b/plugins/debug-manager/debug_tree.c index 948e142d..72e00246 100644 --- a/plugins/debug-manager/debug_tree.c +++ b/plugins/debug-manager/debug_tree.c @@ -80,7 +80,6 @@ struct _DebugTree { IAnjutaDebugger *debugger; AnjutaPlugin *plugin; GtkWidget* view; /* the tree widget */ - GSList* free_list; gboolean auto_expand; }; @@ -789,8 +788,7 @@ debug_tree_remove_all (DebugTree *tree) g_return_if_fail (tree->view); model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view)); - my_gtk_tree_model_foreach_child (model, NULL, delete_parent, tree); - gtk_tree_store_clear (GTK_TREE_STORE (model)); + debug_tree_remove_model (tree, model); } static gboolean @@ -1068,7 +1066,7 @@ on_debug_tree_changed (gpointer data, gpointer user_data) GtkTreeIter iter; GtkTreeModel *model; - model = gtk_tree_view_get_model (GTK_TREE_VIEW (((DebugTree *)tree->data)->view)); + model = GTK_TREE_MODEL (tree->data); if (debug_tree_find_name (model, &iter, var->name)) { @@ -1328,6 +1326,39 @@ debug_tree_disconnect (DebugTree *this) this->debugger = NULL; } +GtkTreeModel * +debug_tree_get_model (DebugTree *tree) +{ + return gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view)); +} + +void +debug_tree_set_model (DebugTree *tree, GtkTreeModel *model) +{ + gtk_tree_view_set_model (GTK_TREE_VIEW (tree->view), model); +} + +void +debug_tree_new_model (DebugTree *tree) +{ + GtkTreeModel * model = GTK_TREE_MODEL (gtk_tree_store_new + (N_COLUMNS, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_BOOLEAN, + G_TYPE_POINTER)); + + gtk_tree_view_set_model (GTK_TREE_VIEW (tree->view), model); +} + +void +debug_tree_remove_model (DebugTree *tree, GtkTreeModel *model) +{ + my_gtk_tree_model_foreach_child (model, NULL, delete_parent, tree); + gtk_tree_store_clear (GTK_TREE_STORE (model)); +} + /* Constructor & Destructor *---------------------------------------------------------------------------*/ @@ -1336,13 +1367,15 @@ DebugTree * debug_tree_new_with_view (AnjutaPlugin *plugin, GtkTreeView *view) { DebugTree *tree = g_new0 (DebugTree, 1); + GtkTreeModel *model; tree->plugin = plugin; tree->view = debug_tree_create(tree, view); tree->auto_expand = FALSE; - /* Add this tree in list */ - gTreeList = g_list_prepend (gTreeList, tree); + /* Add this model in list */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view)); + gTreeList = g_list_prepend (gTreeList, model); /* Connect signal */ g_signal_connect(GTK_TREE_VIEW (tree->view), "row_expanded", G_CALLBACK (on_treeview_row_expanded), tree); @@ -1361,22 +1394,24 @@ debug_tree_new (AnjutaPlugin* plugin) /* DebugTree destructor */ void -debug_tree_free (DebugTree * d_tree) +debug_tree_free (DebugTree * tree) { + GtkTreeModel *model; // AnjutaUI *ui; - g_return_if_fail (d_tree); + g_return_if_fail (tree); - debug_tree_remove_all (d_tree); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view)); + debug_tree_remove_all (tree); /* Remove from list */ - gTreeList = g_list_remove (gTreeList, d_tree); + gTreeList = g_list_remove (gTreeList, model); - g_signal_handlers_disconnect_by_func (GTK_TREE_VIEW (d_tree->view), - G_CALLBACK (on_treeview_row_expanded), d_tree); + g_signal_handlers_disconnect_by_func (GTK_TREE_VIEW (tree->view), + G_CALLBACK (on_treeview_row_expanded), tree); - gtk_widget_destroy (d_tree->view); + gtk_widget_destroy (tree->view); - g_free (d_tree); + g_free (tree); } diff --git a/plugins/debug-manager/debug_tree.h b/plugins/debug-manager/debug_tree.h index c12a9d2e..765c3386 100644 --- a/plugins/debug-manager/debug_tree.h +++ b/plugins/debug-manager/debug_tree.h @@ -31,29 +31,33 @@ typedef struct _DebugTree DebugTree; DebugTree* debug_tree_new (AnjutaPlugin* plugin); DebugTree* debug_tree_new_with_view (AnjutaPlugin *plugin, GtkTreeView *view); -void debug_tree_free (DebugTree *this); +void debug_tree_free (DebugTree *tree); -void debug_tree_connect (DebugTree *this, IAnjutaDebugger *debugger); -void debug_tree_disconnect (DebugTree *this); +void debug_tree_connect (DebugTree *tree, IAnjutaDebugger *debugger); +void debug_tree_disconnect (DebugTree *tree); -void debug_tree_remove_all (DebugTree *this); -void debug_tree_replace_list (DebugTree *this, const GList *expressions); -void debug_tree_add_watch (DebugTree *this, const IAnjutaDebuggerVariable* var, gboolean auto_update); -void debug_tree_add_dummy (DebugTree *this, GtkTreeIter *parent); -void debug_tree_add_full_watch_list (DebugTree *this, GList *expressions); -void debug_tree_add_watch_list (DebugTree *this, GList *expressions, gboolean auto_update); -void debug_tree_update_all (DebugTree *this); +void debug_tree_remove_all (DebugTree *tree); +void debug_tree_replace_list (DebugTree *tree, const GList *expressions); +void debug_tree_add_watch (DebugTree *tree, const IAnjutaDebuggerVariable* var, gboolean auto_update); +void debug_tree_add_dummy (DebugTree *tree, GtkTreeIter *parent); +void debug_tree_add_full_watch_list (DebugTree *tree, GList *expressions); +void debug_tree_add_watch_list (DebugTree *tree, GList *expressions, gboolean auto_update); +void debug_tree_update_all (DebugTree *tree); -GList* debug_tree_get_full_watch_list (DebugTree *this); +GList* debug_tree_get_full_watch_list (DebugTree *tree); GtkWidget *debug_tree_get_tree_widget (DebugTree *tree); gboolean debug_tree_get_current (DebugTree *tree, GtkTreeIter* iter); gboolean debug_tree_remove (DebugTree *tree, GtkTreeIter* iter); gboolean debug_tree_update (DebugTree *tree, GtkTreeIter* iter, gboolean force); -void debug_tree_set_auto_update (DebugTree* this, GtkTreeIter* iter, gboolean state); -gboolean debug_tree_get_auto_update (DebugTree* this, GtkTreeIter* iter); +void debug_tree_set_auto_update (DebugTree* tree, GtkTreeIter* iter, gboolean state); +gboolean debug_tree_get_auto_update (DebugTree* tree, GtkTreeIter* iter); +GtkTreeModel *debug_tree_get_model (DebugTree *tree); +void debug_tree_set_model (DebugTree *tree, GtkTreeModel *model); +void debug_tree_new_model (DebugTree *tree); +void debug_tree_remove_model (DebugTree *tree, GtkTreeModel *model); G_END_DECLS diff --git a/plugins/debug-manager/locals.c b/plugins/debug-manager/locals.c index 1ba70270..87447f05 100644 --- a/plugins/debug-manager/locals.c +++ b/plugins/debug-manager/locals.c @@ -27,21 +27,39 @@ /*#define DEBUG*/ #include + +typedef struct _DmaThreadLocal +{ + GtkTreeModel *model; + guint thread; + guint frame; +} DmaThreadLocal; + +typedef struct _DmaThreadAndFrame +{ + guint thread; + guint frame; +} DmaThreadAndFrame; + struct _Locals { + AnjutaPlugin *plugin; IAnjutaDebugger *debugger; + GtkWidget *main_w; DebugTree *debug_tree; - AnjutaPlugin *plugin; + + DmaThreadLocal* current; + GList *list; }; static void locals_updated (const gpointer data, gpointer user_data, GError *error) { const GList *list = (const GList *)data; - Locals *locals = (Locals*) user_data; + Locals *self = (Locals*) user_data; - g_return_if_fail (locals != NULL); + g_return_if_fail (self != NULL); if (error != NULL) return; @@ -49,23 +67,23 @@ locals_updated (const gpointer data, gpointer user_data, GError *error) if (g_list_length ((GList*)list) < 1) return; - debug_tree_replace_list (locals->debug_tree, list); - debug_tree_update_all(locals->debug_tree); + debug_tree_replace_list (self->debug_tree, list); + debug_tree_update_all(self->debug_tree); } /* Private functions *---------------------------------------------------------------------------*/ static void -create_locals_gui (Locals *l) +create_locals_gui (Locals *self) { - if (l->debug_tree == NULL) + if (self->debug_tree == NULL) { - l->debug_tree = debug_tree_new (l->plugin); - debug_tree_connect (l->debug_tree, l->debugger); + self->debug_tree = debug_tree_new (self->plugin); + debug_tree_connect (self->debug_tree, self->debugger); } - if (l->main_w == NULL) + if (self->main_w == NULL) { /* Create local window */ GtkWidget *main_w; @@ -77,12 +95,12 @@ create_locals_gui (Locals *l) GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (main_w), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (main_w), debug_tree_get_tree_widget (l->debug_tree)); + gtk_container_add (GTK_CONTAINER (main_w), debug_tree_get_tree_widget (self->debug_tree)); gtk_widget_show_all (main_w); - l->main_w = main_w; + self->main_w = main_w; - anjuta_shell_add_widget (l->plugin->shell, - l->main_w, + anjuta_shell_add_widget (self->plugin->shell, + self->main_w, "AnjutaDebuggerLocals", _("Locals"), "gdb-locals-icon", ANJUTA_SHELL_PLACEMENT_BOTTOM, NULL); @@ -90,39 +108,124 @@ create_locals_gui (Locals *l) } static void -destroy_locals_gui (Locals *l) +destroy_locals_gui (Locals *self) { - if (l->debug_tree != NULL) + if (self->debug_tree != NULL) { - debug_tree_free (l->debug_tree); - l->debug_tree = NULL; + debug_tree_free (self->debug_tree); + self->debug_tree = NULL; } - if (l->main_w != NULL) + if (self->main_w != NULL) { - gtk_widget_destroy (GTK_WIDGET (l->main_w)); - l->main_w = NULL; + gtk_widget_destroy (GTK_WIDGET (self->main_w)); + self->main_w = NULL; } } +static void +on_clear_locals (gpointer data, gpointer user_data) +{ + DmaThreadLocal *frame = (DmaThreadLocal *) data; + Locals *self = (Locals *)user_data; + + debug_tree_remove_model (self->debug_tree, frame->model); + g_object_unref (G_OBJECT (frame->model)); + g_free (frame); +} + +static void +dma_thread_clear_all_locals (Locals *self) +{ + /* Clear all GtkListStore */ + g_list_foreach (self->list, (GFunc)on_clear_locals, self); + g_list_free (self->list); + + self->current = NULL; + self->list = NULL; +} + +static gboolean +on_find_local (gconstpointer a, gconstpointer b) +{ + const DmaThreadLocal *frame = (const DmaThreadLocal *)a; + const DmaThreadAndFrame *comp = (const DmaThreadAndFrame *)b; + + return !((frame->thread == comp->thread) && (frame->frame == comp->frame)); +} + +static DmaThreadLocal * +dma_thread_find_local (Locals *self, guint thread, guint frame) +{ + GList *list; + DmaThreadAndFrame comp = {thread, frame}; + + list = g_list_find_custom (self->list, (gconstpointer) &comp, on_find_local); + + return list == NULL ? NULL : (DmaThreadLocal *)list->data; +} + +static void +dma_thread_add_local (Locals *self, GtkTreeModel *model, guint thread, guint frame) +{ + DmaThreadLocal *local; + + local = g_new (DmaThreadLocal, 1); + local->thread = thread; + local->frame = frame; + local->model = model; + g_object_ref (G_OBJECT (model)); + + self->list = g_list_append (self->list, local); + self->current = local; +} + /* Private functions *---------------------------------------------------------------------------*/ -static void locals_update (Locals *locals) +static void locals_update (Locals *self, guint thread) +{ + dma_thread_clear_all_locals (self); + + dma_thread_add_local (self, debug_tree_get_model (self->debug_tree), thread, 0); + + ianjuta_debugger_list_local (self->debugger, locals_updated, self, NULL); +} + +static void +locals_clear (Locals *self) { - ianjuta_debugger_list_local (locals->debugger, locals_updated, locals, NULL); + g_return_if_fail (self != NULL); + dma_thread_clear_all_locals (self); + debug_tree_remove_all (self->debug_tree); } static void -locals_clear (Locals *l) +locals_change_frame (Locals *self, guint frame, guint thread) { - g_return_if_fail (l != NULL); - debug_tree_remove_all (l->debug_tree); + DmaThreadLocal *local; + + /* Check if we really need a change */ + if ((self->current != NULL) && (self->current->thread == thread) && (self->current->frame == frame)) return; + + local = dma_thread_find_local (self, thread, frame); + if (local != NULL) + { + /* Find frame already read */ + self->current = local; + debug_tree_set_model (self->debug_tree, self->current->model); + + return; + } + + debug_tree_new_model (self->debug_tree); + dma_thread_add_local (self, debug_tree_get_model (self->debug_tree), thread, frame); + ianjuta_debugger_list_local (self->debugger, locals_updated, self, NULL); } static void -on_program_stopped (Locals *l) +on_program_stopped (Locals *l, guint thread) { - locals_update (l); + locals_update (l, thread); } static void @@ -138,6 +241,13 @@ on_debugger_stopped (Locals *l) destroy_locals_gui (l); } +static void +on_frame_changed (Locals *self, guint frame, guint thread) +{ + /* Change thread and frame*/ + locals_change_frame (self, frame, thread); +} + /* Constructor & Destructor *---------------------------------------------------------------------------*/ @@ -146,37 +256,39 @@ locals_new (AnjutaPlugin *plugin, IAnjutaDebugger* debugger) { DebugTree *debug_tree; - Locals *locals = g_new0 (Locals, 1); + Locals *self = g_new0 (Locals, 1); debug_tree = debug_tree_new (plugin); - locals->debugger = debugger; + self->debugger = debugger; if (debugger != NULL) g_object_ref (debugger); - locals->plugin = plugin; + self->plugin = plugin; - g_signal_connect_swapped (locals->debugger, "debugger-started", G_CALLBACK (on_debugger_started), locals); - g_signal_connect_swapped (locals->debugger, "debugger-stopped", G_CALLBACK (on_debugger_stopped), locals); - g_signal_connect_swapped (locals->debugger, "program-stopped", G_CALLBACK (on_program_stopped), locals); + g_signal_connect_swapped (self->debugger, "debugger-started", G_CALLBACK (on_debugger_started), self); + g_signal_connect_swapped (self->debugger, "debugger-stopped", G_CALLBACK (on_debugger_stopped), self); + g_signal_connect_swapped (self->debugger, "program-stopped", G_CALLBACK (on_program_stopped), self); + g_signal_connect_swapped (self->debugger, "frame-changed", G_CALLBACK (on_frame_changed), self); - return locals; + return self; } void -locals_free (Locals *l) +locals_free (Locals *self) { - g_return_if_fail (l != NULL); + g_return_if_fail (self != NULL); /* Destroy gui */ - destroy_locals_gui (l); + destroy_locals_gui (self); /* Disconnect from debugger */ - if (l->debugger != NULL) + if (self->debugger != NULL) { - g_signal_handlers_disconnect_by_func (l->debugger, G_CALLBACK (on_debugger_started), l); - g_signal_handlers_disconnect_by_func (l->debugger, G_CALLBACK (on_debugger_stopped), l); - g_signal_handlers_disconnect_by_func (l->debugger, G_CALLBACK (on_program_stopped), l); - g_object_unref (l->debugger); + g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_debugger_started), self); + g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_debugger_stopped), self); + g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_program_stopped), self); + g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_frame_changed), self); + g_object_unref (self->debugger); } - g_free (l); + g_free (self); } diff --git a/plugins/debug-manager/registers.c b/plugins/debug-manager/registers.c index 05211e6a..b18a5f5b 100644 --- a/plugins/debug-manager/registers.c +++ b/plugins/debug-manager/registers.c @@ -28,6 +28,7 @@ #include +/*#define DEBUG*/ #include #include @@ -43,12 +44,22 @@ /* Types *---------------------------------------------------------------------------*/ +typedef struct _DmaThreadRegisterList +{ + GtkTreeModel *model; + guint thread; + guint last_update; +} DmaThreadRegisterList; + struct _CpuRegisters { IAnjutaDebugger *debugger; AnjutaPlugin *plugin; - GtkTreeModel *model; + DmaThreadRegisterList* current; + GList *list; + GtkTreeView *treeview; GtkWidget *scrolledwindow; + guint current_update; }; enum @@ -68,10 +79,41 @@ enum /* Private functions *---------------------------------------------------------------------------*/ +/* Handle list of registers for each thread + *---------------------------------------------------------------------------*/ + +static gboolean +on_copy_register_name (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer user_data) +{ + GtkListStore *list = (GtkListStore *)user_data; + GtkTreeIter dest; + guint num; + gchar *name; + + gtk_tree_model_get(model, iter, + NUMBER_COLUMN, &num, + NAME_COLUMN, &name, + -1); + + gtk_list_store_append (list, &dest); + gtk_list_store_set(list, &dest, + NUMBER_COLUMN, num, + NAME_COLUMN, name, + VALUE_COLUMN, REGISTER_UNKNOWN_VALUE, + FLAG_COLUMN, 0, + -1); + g_free (name); + + return FALSE; +} + static void on_cpu_registers_updated (const GList *registers, gpointer user_data, GError *error) { - CpuRegisters *this = (CpuRegisters *)user_data; + CpuRegisters *self = (CpuRegisters *)user_data; const GList *node; GtkListStore *list; @@ -79,8 +121,12 @@ on_cpu_registers_updated (const GList *registers, gpointer user_data, GError *er gboolean valid; /* Get first item in list view */ - valid = gtk_tree_model_get_iter_first (this->model, &iter); - list = GTK_LIST_STORE (this->model); + valid = gtk_tree_model_get_iter_first (self->current->model, &iter); + list = GTK_LIST_STORE (self->current->model); + + if (registers == NULL) return; + + self->current->last_update = self->current_update; for(node = registers;node != NULL; node = g_list_next (node)) { @@ -89,9 +135,9 @@ on_cpu_registers_updated (const GList *registers, gpointer user_data, GError *er gchar *value; /* Look for corresponding item in list view */ - for (;valid; valid = gtk_tree_model_iter_next (this->model, &iter)) + for (;valid; valid = gtk_tree_model_iter_next (self->current->model, &iter)) { - gtk_tree_model_get (this->model, &iter, NUMBER_COLUMN, &id, -1); + gtk_tree_model_get (self->current->model, &iter, NUMBER_COLUMN, &id, -1); if (id >= reg->num) break; } @@ -127,7 +173,7 @@ on_cpu_registers_updated (const GList *registers, gpointer user_data, GError *er /* Update value */ if (reg->value != NULL) { - gtk_tree_model_get (this->model, &iter, VALUE_COLUMN, &value, -1); + gtk_tree_model_get (self->current->model, &iter, VALUE_COLUMN, &value, -1); if ((value != NULL) && (strcmp (value, reg->value) == 0)) { /* Same value */ @@ -147,58 +193,170 @@ on_cpu_registers_updated (const GList *registers, gpointer user_data, GError *er } static void +cpu_registers_update (CpuRegisters *self) +{ + if ((self->debugger != NULL) && GTK_WIDGET_MAPPED (self->scrolledwindow)) + { + ianjuta_cpu_debugger_update_register ( + IANJUTA_CPU_DEBUGGER (self->debugger), + (IAnjutaDebuggerCallback)on_cpu_registers_updated, + self, + NULL); + } +} + +static DmaThreadRegisterList* +dma_thread_create_new_register_list (CpuRegisters *self, guint thread) +{ + DmaThreadRegisterList *regs; + GtkListStore *store; + + if ((self->list != NULL) + && (((DmaThreadRegisterList *)g_list_first (self->list)->data)->thread == 0)) + { + /* List as been created but not associated to a thread */ + + regs = ((DmaThreadRegisterList *)g_list_first (self->list)->data); + + regs->thread = thread; + + return regs; + } + + /* Create new list store */ + store = gtk_list_store_new (COLUMNS_NB, + G_TYPE_UINT, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_UINT); + + regs = g_new (DmaThreadRegisterList, 1); + regs->thread = thread; + regs->model = GTK_TREE_MODEL (store); + regs->last_update = 0; + + if (self->list == NULL) + { + self->current = regs; + + /* List is empty, ask debugger to get all register name */ + ianjuta_cpu_debugger_list_register ( + IANJUTA_CPU_DEBUGGER (self->debugger), + (IAnjutaDebuggerCallback)on_cpu_registers_updated, + self, + NULL); + } + else + { + /* One register list already exist, copy register name and ID */ + + gtk_tree_model_foreach (((DmaThreadRegisterList *)g_list_first (self->list)->data)->model, + on_copy_register_name, store); + } + self->list = g_list_append (self->list, regs); + + return regs; +} + +static void +on_clear_register_list (gpointer data, gpointer user_data) +{ + DmaThreadRegisterList *regs = (DmaThreadRegisterList *) data; + + g_object_unref (G_OBJECT (regs->model)); + g_free (regs); +} + +static void +dma_thread_clear_all_register_list (CpuRegisters *self) +{ + /* Clear all GtkListStore */ + g_list_foreach (self->list, (GFunc)on_clear_register_list, NULL); + g_list_free (self->list); + + self->current = NULL; + self->list = NULL; +} + +static gboolean +on_find_register_list (gconstpointer a, gconstpointer b) +{ + const DmaThreadRegisterList *regs = (const DmaThreadRegisterList *)a; + guint thread = (guint)b; + + return regs->thread != thread; +} + +static void +dma_thread_set_register_list (CpuRegisters *self, guint thread) +{ + GList *list; + DmaThreadRegisterList *regs; + + if (self->current->thread != thread) + { + list = g_list_find_custom (self->list, (gconstpointer) thread, on_find_register_list); + + if (list == NULL) + { + /* Create new find */ + regs = dma_thread_create_new_register_list(self, thread); + } + else + { + regs = (DmaThreadRegisterList *)list->data; + } + self->current = regs; + gtk_tree_view_set_model (self->treeview, regs->model); + } + + if (self->current_update != self->current->last_update) + { + cpu_registers_update (self); + } +} + +static void on_cpu_registers_changed (GtkCellRendererText *cell, gchar *path_string, gchar *text, gpointer user_data) { - CpuRegisters *this = (CpuRegisters *)user_data; + CpuRegisters *self = (CpuRegisters *)user_data; GtkTreeIter iter; - if (gtk_tree_model_get_iter_from_string (this->model, &iter, path_string)) + if (gtk_tree_model_get_iter_from_string (self->current->model, &iter, path_string)) { IAnjutaDebuggerRegister reg; gchar *name; - gtk_tree_model_get (this->model, &iter, NUMBER_COLUMN, ®.num, NAME_COLUMN, &name, -1); + gtk_tree_model_get (self->current->model, &iter, NUMBER_COLUMN, ®.num, NAME_COLUMN, &name, -1); reg.value = text; reg.name = name; - ianjuta_cpu_debugger_write_register (IANJUTA_CPU_DEBUGGER (this->debugger), ®, NULL); + ianjuta_cpu_debugger_write_register (IANJUTA_CPU_DEBUGGER (self->debugger), ®, NULL); ianjuta_cpu_debugger_update_register ( - IANJUTA_CPU_DEBUGGER (this->debugger), + IANJUTA_CPU_DEBUGGER (self->debugger), (IAnjutaDebuggerCallback)on_cpu_registers_updated, - this, + self, NULL); g_free (name); } } static void -cpu_registers_update (CpuRegisters *this) +on_program_stopped (CpuRegisters *self, guint thread) { - if ((this->debugger != NULL) && GTK_WIDGET_MAPPED (this->scrolledwindow)) - { - ianjuta_cpu_debugger_update_register ( - IANJUTA_CPU_DEBUGGER (this->debugger), - (IAnjutaDebuggerCallback)on_cpu_registers_updated, - this, - NULL); - } + self->current_update++; + dma_thread_set_register_list (self, thread); } static void -on_program_stopped (CpuRegisters *this) +on_map (GtkWidget* widget, CpuRegisters *self) { - cpu_registers_update (this); -} - -static void -on_map (GtkWidget* widget, CpuRegisters *this) -{ - if (ianjuta_debugger_get_status (this->debugger, NULL) == IANJUTA_DEBUGGER_PROGRAM_STOPPED) + if (ianjuta_debugger_get_status (self->debugger, NULL) == IANJUTA_DEBUGGER_PROGRAM_STOPPED) { - cpu_registers_update (this); + cpu_registers_update (self); } } @@ -225,55 +383,47 @@ cpu_registers_value_cell_data_func (GtkTreeViewColumn *tree_column, static void -create_cpu_registers_gui (CpuRegisters *this) +create_cpu_registers_gui (CpuRegisters *self) { - GtkListStore *store; GtkCellRenderer *renderer; GtkTreeViewColumn *column; - GtkTreeView *treeview; /* Create list store */ - store = gtk_list_store_new (COLUMNS_NB, - G_TYPE_UINT, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_UINT); - this->model = GTK_TREE_MODEL (store); + dma_thread_create_new_register_list (self, 0); /* Create list view */ - treeview = GTK_TREE_VIEW (gtk_tree_view_new_with_model (GTK_TREE_MODEL (store))); - gtk_tree_selection_set_mode (gtk_tree_view_get_selection (treeview), + self->treeview = GTK_TREE_VIEW (gtk_tree_view_new_with_model (self->current->model)); + gtk_tree_selection_set_mode (gtk_tree_view_get_selection (self->treeview), GTK_SELECTION_SINGLE); - g_object_unref (G_OBJECT (store)); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (N_("Register"), renderer, "text", NAME_COLUMN, NULL); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column (treeview, column); + gtk_tree_view_append_column (self->treeview, column); renderer = gtk_cell_renderer_text_new (); g_object_set(renderer, "editable", TRUE, NULL); - g_signal_connect(renderer, "edited", (GCallback) on_cpu_registers_changed, this); + g_signal_connect(renderer, "edited", (GCallback) on_cpu_registers_changed, self); column = gtk_tree_view_column_new_with_attributes (N_("Value"), renderer, NULL); gtk_tree_view_column_set_cell_data_func (column, renderer, cpu_registers_value_cell_data_func, NULL, NULL); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column (treeview, column); + gtk_tree_view_append_column (self->treeview, column); /* Add register window */ - this->scrolledwindow = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (this->scrolledwindow), + self->scrolledwindow = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (this->scrolledwindow), + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (self->scrolledwindow), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (this->scrolledwindow), GTK_WIDGET (treeview)); - g_signal_connect(this->scrolledwindow, "map", (GCallback) on_map, this); + gtk_container_add (GTK_CONTAINER (self->scrolledwindow), GTK_WIDGET (self->treeview)); + g_signal_connect(self->scrolledwindow, "map", (GCallback) on_map, self); - anjuta_shell_add_widget (this->plugin->shell, - this->scrolledwindow, + anjuta_shell_add_widget (self->plugin->shell, + self->scrolledwindow, "AnjutaDebuggerRegisters", _("Registers"), NULL, ANJUTA_SHELL_PLACEMENT_LEFT, NULL); @@ -281,31 +431,33 @@ create_cpu_registers_gui (CpuRegisters *this) } static void -on_debugger_started (CpuRegisters *this) +on_debugger_started (CpuRegisters *self) { - create_cpu_registers_gui (this); - ianjuta_cpu_debugger_list_register ( - IANJUTA_CPU_DEBUGGER (this->debugger), - (IAnjutaDebuggerCallback)on_cpu_registers_updated, - this, - NULL); + create_cpu_registers_gui (self); + self->current_update = 0; } static void -destroy_cpu_registers_gui (CpuRegisters *this) +destroy_cpu_registers_gui (CpuRegisters *self) { - if (this->scrolledwindow != NULL) + if (self->scrolledwindow != NULL) { - gtk_list_store_clear (GTK_LIST_STORE (this->model)); - gtk_widget_destroy (this->scrolledwindow); - this->scrolledwindow = NULL; + dma_thread_clear_all_register_list (self); + gtk_widget_destroy (self->scrolledwindow); + self->scrolledwindow = NULL; } } static void -on_debugger_stopped (CpuRegisters *this) +on_debugger_stopped (CpuRegisters *self) +{ + destroy_cpu_registers_gui (self); +} + +static void +on_frame_changed (CpuRegisters *self, guint frame, guint thread) { - destroy_cpu_registers_gui (this); + dma_thread_set_register_list (self, thread); } /* Constructor & Destructor @@ -314,33 +466,36 @@ on_debugger_stopped (CpuRegisters *this) CpuRegisters* cpu_registers_new(AnjutaPlugin *plugin, IAnjutaDebugger *debugger) { - CpuRegisters* this; + CpuRegisters* self; - this = g_new0 (CpuRegisters, 1); + self = g_new0 (CpuRegisters, 1); - this->debugger = debugger; + self->debugger = debugger; if (debugger != NULL) g_object_ref (debugger); - this->plugin = plugin; + self->plugin = plugin; + self->list = NULL; - g_signal_connect_swapped (this->debugger, "debugger-started", G_CALLBACK (on_debugger_started), this); - g_signal_connect_swapped (this->debugger, "debugger-stopped", G_CALLBACK (on_debugger_stopped), this); - g_signal_connect_swapped (this->debugger, "program-stopped", G_CALLBACK (on_program_stopped), this); + g_signal_connect_swapped (self->debugger, "debugger-started", G_CALLBACK (on_debugger_started), self); + g_signal_connect_swapped (self->debugger, "debugger-stopped", G_CALLBACK (on_debugger_stopped), self); + g_signal_connect_swapped (self->debugger, "program-stopped", G_CALLBACK (on_program_stopped), self); + g_signal_connect_swapped (self->debugger, "frame_changed", G_CALLBACK (on_frame_changed), self); - return this; + return self; } void -cpu_registers_free(CpuRegisters* this) +cpu_registers_free(CpuRegisters* self) { - g_return_if_fail (this != NULL); + g_return_if_fail (self != NULL); - destroy_cpu_registers_gui (this); - if (this->debugger != NULL) + destroy_cpu_registers_gui (self); + if (self->debugger != NULL) { - g_signal_handlers_disconnect_by_func (this->debugger, G_CALLBACK (on_debugger_started), this); - g_signal_handlers_disconnect_by_func (this->debugger, G_CALLBACK (on_debugger_stopped), this); - g_signal_handlers_disconnect_by_func (this->debugger, G_CALLBACK (on_program_stopped), this); - g_object_unref (this->debugger); + g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_debugger_started), self); + g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_debugger_stopped), self); + g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_program_stopped), self); + g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_frame_changed), self); + g_object_unref (self->debugger); } - g_free(this); + g_free(self); } diff --git a/plugins/debug-manager/stack_trace.c b/plugins/debug-manager/stack_trace.c index f8a8b564..324d372e 100644 --- a/plugins/debug-manager/stack_trace.c +++ b/plugins/debug-manager/stack_trace.c @@ -41,25 +41,27 @@ #define ANJUTA_PIXMAP_POINTER PACKAGE_PIXMAPS_DIR"/pointer.png" -typedef struct _StackTraceGui StackTraceGui; -struct _StackTraceGui +typedef struct _DmaThreadStackTrace { - GtkWidget *scrolledwindow; - GtkTreeView *clist; - GtkMenu *menu; - GtkWidget *menu_set; - GtkWidget *menu_info; - GtkWidget *menu_update; - GtkWidget *menu_view; -}; + GtkTreeModel *model; + guint thread; +} DmaThreadStackTrace; struct _StackTrace { AnjutaPlugin *plugin; IAnjutaDebugger *debugger; + GtkActionGroup *action_group; - StackTraceGui widgets; + + DmaThreadStackTrace* current; + GList *list; + gint current_frame; + + GtkTreeView *treeview; + GtkMenu *menu; + GtkWidget *scrolledwindow; }; enum { @@ -94,12 +96,12 @@ get_current_index (StackTrace* st) { GtkTreeIter iter; - if (get_current_iter (st->widgets.clist, &iter)) + if (get_current_iter (st->treeview, &iter)) { GtkTreeModel *model; gint frame_no; - model = gtk_tree_view_get_model (st->widgets.clist); + model = gtk_tree_view_get_model (st->treeview); gtk_tree_model_get (model, &iter, STACK_TRACE_FRAME_COLUMN, &frame_no, -1); return frame_no; @@ -114,28 +116,33 @@ get_current_index (StackTrace* st) *---------------------------------------------------------------------------*/ static void -stack_trace_clear (StackTrace * st) +on_clear_stack_trace (gpointer data, gpointer user_data) { - GtkTreeModel* model; + DmaThreadStackTrace *trace = (DmaThreadStackTrace *) data; - model = gtk_tree_view_get_model (st->widgets.clist); - gtk_list_store_clear (GTK_LIST_STORE (model)); + g_object_unref (G_OBJECT (trace->model)); + g_free (trace); } -/* Callback functions - *---------------------------------------------------------------------------*/ +static void +dma_thread_clear_all_stack_trace (StackTrace *self) +{ + /* Clear all GtkListStore */ + g_list_foreach (self->list, (GFunc)on_clear_stack_trace, NULL); + g_list_free (self->list); + + self->current = NULL; + self->list = NULL; +} static void -on_stack_trace_updated (const GList *stack, gpointer data) +on_stack_trace_updated (const GList *stack, gpointer user_data) { - StackTrace *st; + StackTrace *self = (StackTrace *)user_data; const GList *node; GtkListStore *model; - st = (StackTrace *) data; - stack_trace_clear (st); - - model = GTK_LIST_STORE (gtk_tree_view_get_model (st->widgets.clist)); + model = GTK_LIST_STORE (self->current->model); for (node = stack; node != NULL; node = node->next) { @@ -151,7 +158,7 @@ on_stack_trace_updated (const GList *stack, gpointer data) gtk_list_store_append (model, &iter); /* if we are on the current frame set iterator and pixmap correctly */ - if (frame->level == st->current_frame) + if (frame->level == self->current_frame) pic = gdk_pixbuf_new_from_file (ANJUTA_PIXMAP_POINTER, NULL); else pic = NULL; @@ -185,15 +192,92 @@ on_stack_trace_updated (const GList *stack, gpointer data) } } +static DmaThreadStackTrace* +dma_thread_create_new_stack_trace (StackTrace *self, guint thread) +{ + DmaThreadStackTrace *trace; + GtkListStore *store; + + /* Create new list store */ + store = gtk_list_store_new (STACK_TRACE_N_COLUMNS, + GDK_TYPE_PIXBUF, + G_TYPE_UINT, + G_TYPE_STRING, + G_TYPE_UINT, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + + trace = g_new (DmaThreadStackTrace, 1); + trace->thread = thread; + trace->model = GTK_TREE_MODEL (store); + + self->current = trace; + + /* Ask debugger to get all frame data */ + ianjuta_debugger_list_frame ( + self->debugger, + (IAnjutaDebuggerCallback)on_stack_trace_updated, + self, + NULL); + + self->list = g_list_append (self->list, trace); + + return trace; +} + +static gboolean +on_find_stack_trace (gconstpointer a, gconstpointer b) +{ + const DmaThreadStackTrace *trace = (const DmaThreadStackTrace *)a; + guint thread = (guint)b; + + return trace->thread != thread; +} + +static void +dma_thread_set_stack_trace (StackTrace *self, guint thread) +{ + GList *list; + DmaThreadStackTrace *trace; + + if ((self->current == NULL) || (self->current->thread != thread)) + { + self->current_frame = 0; + + list = g_list_find_custom (self->list, (gconstpointer) thread, on_find_stack_trace); + + if (list == NULL) + { + /* Create new stack trace */ + trace = dma_thread_create_new_stack_trace(self, thread); + } + else + { + trace = (DmaThreadStackTrace *)list->data; + self->current = trace; + } + gtk_tree_view_set_model (self->treeview, trace->model); + } +} + +/* Callback functions + *---------------------------------------------------------------------------*/ + static void -on_stack_trace_frame_changed (StackTrace *st, guint frame, guint thread) +on_frame_changed (StackTrace *self, guint frame, guint thread) { GtkTreeIter iter; GtkTreeModel *model; + + /* Change thread */ + dma_thread_set_stack_trace (self, thread); - st->current_frame = frame; + /* Change frame */ + self->current_frame = frame; - model = gtk_tree_view_get_model (st->widgets.clist); + model = self->current->model; /* Clear old pointer */ if(gtk_tree_model_get_iter_first (model, &iter)) @@ -207,7 +291,7 @@ on_stack_trace_frame_changed (StackTrace *st, guint frame, guint thread) } /* Set pointer to current frame */ - if (gtk_tree_model_iter_nth_child (model, &iter, NULL, st->current_frame)) + if (gtk_tree_model_iter_nth_child (model, &iter, NULL, self->current_frame)) { GdkPixbuf *pointer_pix = gdk_pixbuf_new_from_file (ANJUTA_PIXMAP_POINTER, NULL); @@ -253,7 +337,7 @@ on_stack_view_src_activate (GtkAction *action, gpointer user_data) StackTrace* st = (StackTrace*) user_data; - view = st->widgets.clist; + view = st->treeview; selection = gtk_tree_view_get_selection (view); if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return; @@ -285,8 +369,8 @@ on_stack_trace_button_press (GtkWidget *widget, GdkEventButton *bevent, gpointer if ((bevent->type == GDK_BUTTON_PRESS) && (bevent->button == 3)) { /* Right mouse click */ - g_return_val_if_fail (st->widgets.menu != NULL, FALSE); - gtk_menu_popup (GTK_MENU (st->widgets.menu), NULL, NULL, NULL, NULL, + g_return_val_if_fail (st->menu != NULL, FALSE); + gtk_menu_popup (GTK_MENU (st->menu), NULL, NULL, NULL, NULL, bevent->button, bevent->time); } else if ((bevent->type == GDK_2BUTTON_PRESS) && (bevent->button == 1)) @@ -298,17 +382,6 @@ on_stack_trace_button_press (GtkWidget *widget, GdkEventButton *bevent, gpointer return FALSE; } -static void -stack_trace_update (StackTrace *st) -{ - st->current_frame = 0; - ianjuta_debugger_list_frame ( - st->debugger, - (IAnjutaDebuggerCallback)on_stack_trace_updated, - st, - NULL); -} - /* Actions table *---------------------------------------------------------------------------*/ @@ -340,7 +413,7 @@ create_stack_trace_gui(StackTrace *st) GtkCellRenderer *renderer; AnjutaUI *ui; - g_return_if_fail (st->widgets.scrolledwindow == NULL); + g_return_if_fail (st->scrolledwindow == NULL); /* Create tree view */ model = GTK_TREE_MODEL(gtk_list_store_new (STACK_TRACE_N_COLUMNS, @@ -352,10 +425,10 @@ create_stack_trace_gui(StackTrace *st) G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING)); - st->widgets.clist = GTK_TREE_VIEW (gtk_tree_view_new_with_model (model)); + st->treeview = GTK_TREE_VIEW (gtk_tree_view_new_with_model (model)); g_object_unref (G_OBJECT (model)); - selection = gtk_tree_view_get_selection (st->widgets.clist); + selection = gtk_tree_view_get_selection (st->treeview); gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); /* Columns */ @@ -366,8 +439,8 @@ create_stack_trace_gui(StackTrace *st) gtk_tree_view_column_pack_start (column, renderer, TRUE); gtk_tree_view_column_add_attribute (column, renderer, "pixbuf", STACK_TRACE_ACTIVE_COLUMN); - gtk_tree_view_append_column (st->widgets.clist, column); - gtk_tree_view_set_expander_column (st->widgets.clist, + gtk_tree_view_append_column (st->treeview, column); + gtk_tree_view_set_expander_column (st->treeview, column); column = gtk_tree_view_column_new (); @@ -378,8 +451,8 @@ create_stack_trace_gui(StackTrace *st) gtk_tree_view_column_add_attribute (column, renderer, "text", STACK_TRACE_FRAME_COLUMN); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column (st->widgets.clist, column); - gtk_tree_view_set_expander_column (st->widgets.clist, + gtk_tree_view_append_column (st->treeview, column); + gtk_tree_view_set_expander_column (st->treeview, column); column = gtk_tree_view_column_new (); @@ -389,7 +462,7 @@ create_stack_trace_gui(StackTrace *st) STACK_TRACE_FILE_COLUMN); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_column_set_title (column, _("File")); - gtk_tree_view_append_column (st->widgets.clist, column); + gtk_tree_view_append_column (st->treeview, column); column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_text_new (); @@ -398,7 +471,7 @@ create_stack_trace_gui(StackTrace *st) STACK_TRACE_LINE_COLUMN); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_column_set_title (column, _("Line")); - gtk_tree_view_append_column (st->widgets.clist, column); + gtk_tree_view_append_column (st->treeview, column); column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_text_new (); @@ -407,7 +480,7 @@ create_stack_trace_gui(StackTrace *st) STACK_TRACE_FUNC_COLUMN); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_column_set_title (column, _("Function")); - gtk_tree_view_append_column (st->widgets.clist, column); + gtk_tree_view_append_column (st->treeview, column); column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_text_new (); @@ -416,7 +489,7 @@ create_stack_trace_gui(StackTrace *st) STACK_TRACE_ADDR_COLUMN); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_column_set_title (column, _("Address")); - gtk_tree_view_append_column (st->widgets.clist, column); + gtk_tree_view_append_column (st->treeview, column); column = gtk_tree_view_column_new (); renderer = gtk_cell_renderer_text_new (); @@ -425,29 +498,29 @@ create_stack_trace_gui(StackTrace *st) STACK_TRACE_ARGS_COLUMN); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_column_set_title (column, _("Arguments")); - gtk_tree_view_append_column (st->widgets.clist, column); + gtk_tree_view_append_column (st->treeview, column); /* Create popup menu */ ui = anjuta_shell_get_ui (st->plugin->shell, NULL); - st->widgets.menu = GTK_MENU (gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui), "/PopupStack")); + st->menu = GTK_MENU (gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui), "/PopupStack")); /* Connect signal */ - g_signal_connect (st->widgets.clist, "button-press-event", G_CALLBACK (on_stack_trace_button_press), st); - g_signal_connect (st->widgets.clist, "row-activated", G_CALLBACK (on_stack_trace_row_activated), st); + g_signal_connect (st->treeview, "button-press-event", G_CALLBACK (on_stack_trace_button_press), st); + g_signal_connect (st->treeview, "row-activated", G_CALLBACK (on_stack_trace_row_activated), st); /* Add stack window */ - st->widgets.scrolledwindow = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (st->widgets.scrolledwindow), + st->scrolledwindow = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (st->scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (st->widgets.scrolledwindow), + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (st->scrolledwindow), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (st->widgets.scrolledwindow), - GTK_WIDGET (st->widgets.clist)); - gtk_widget_show_all (st->widgets.scrolledwindow); + gtk_container_add (GTK_CONTAINER (st->scrolledwindow), + GTK_WIDGET (st->treeview)); + gtk_widget_show_all (st->scrolledwindow); anjuta_shell_add_widget (st->plugin->shell, - st->widgets.scrolledwindow, + st->scrolledwindow, "AnjutaDebuggerStack", _("Stack"), "gdb-stack-icon", ANJUTA_SHELL_PLACEMENT_BOTTOM, NULL); @@ -457,30 +530,31 @@ create_stack_trace_gui(StackTrace *st) static void destroy_stack_trace_gui (StackTrace *st) { - if (st->widgets.scrolledwindow != NULL) + if (st->scrolledwindow != NULL) { - gtk_widget_destroy (st->widgets.scrolledwindow); - st->widgets.scrolledwindow = NULL; + gtk_widget_destroy (st->scrolledwindow); + st->scrolledwindow = NULL; } } static void -on_program_stopped (StackTrace *st) +on_program_stopped (StackTrace *self, guint thread) { - stack_trace_update (st); + dma_thread_clear_all_stack_trace (self); + dma_thread_set_stack_trace (self, thread); } static void -on_debugger_started (StackTrace *st) +on_debugger_started (StackTrace *self) { - create_stack_trace_gui (st); + create_stack_trace_gui (self); } static void -on_debugger_stopped (StackTrace *st) +on_debugger_stopped (StackTrace *self) { - stack_trace_clear (st); - destroy_stack_trace_gui (st); + dma_thread_clear_all_stack_trace (self); + destroy_stack_trace_gui (self); } /* Public functions @@ -514,7 +588,7 @@ stack_trace_new (IAnjutaDebugger *debugger, AnjutaPlugin *plugin) g_signal_connect_swapped (st->debugger, "debugger-started", G_CALLBACK (on_debugger_started), st); g_signal_connect_swapped (st->debugger, "debugger-stopped", G_CALLBACK (on_debugger_stopped), st); g_signal_connect_swapped (st->debugger, "program-stopped", G_CALLBACK (on_program_stopped), st); - g_signal_connect_swapped (st->debugger, "frame-changed", G_CALLBACK (on_stack_trace_frame_changed), st); + g_signal_connect_swapped (st->debugger, "frame-changed", G_CALLBACK (on_frame_changed), st); return st; } @@ -532,7 +606,7 @@ stack_trace_free (StackTrace * st) g_signal_handlers_disconnect_by_func (st->debugger, G_CALLBACK (on_debugger_started), st); g_signal_handlers_disconnect_by_func (st->debugger, G_CALLBACK (on_debugger_stopped), st); g_signal_handlers_disconnect_by_func (st->debugger, G_CALLBACK (on_program_stopped), st); - g_signal_handlers_disconnect_by_func (st->debugger, G_CALLBACK (on_stack_trace_frame_changed), st); + g_signal_handlers_disconnect_by_func (st->debugger, G_CALLBACK (on_frame_changed), st); g_object_unref (st->debugger); } diff --git a/plugins/debug-manager/threads.c b/plugins/debug-manager/threads.c index 895d0899..7b2b6043 100644 --- a/plugins/debug-manager/threads.c +++ b/plugins/debug-manager/threads.c @@ -30,7 +30,7 @@ #include #include -#define DEBUG +/*#define DEBUG*/ #include #include #include @@ -165,9 +165,13 @@ on_threads_src_activate (GtkAction *action, gpointer user_data) THREAD_URI_COLUMN, &uri, THREAD_LINE_COLUMN, &line, -1); - - goto_location_in_editor (self->plugin, uri, line); - g_free (uri); + + /* URI is NULL if file is unknown */ + if (uri != NULL) + { + goto_location_in_editor (self->plugin, uri, line); + g_free (uri); + } } static void @@ -276,7 +280,6 @@ on_list_thread (const GList *threads, gpointer user_data) gtk_list_store_append (model, &iter); - DEBUG_PRINT("frame thread %d current thread %d", frame->thread, self->current_thread); /* if we are on the current frame set iterator and pixmap correctly */ if (frame->thread == self->current_thread) pic = gdk_pixbuf_new_from_file (ANJUTA_PIXMAP_POINTER, NULL); @@ -457,10 +460,6 @@ dma_threads_create_gui(DmaThreads *self) ui = anjuta_shell_get_ui (self->plugin->shell, NULL); self->menu = GTK_MENU (gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui), "/PopupThread")); - /* FIXME: Temporary disable set thread menu item */ - GtkAction *action = anjuta_ui_get_action (ui, "ActionGroupThread", "ActionDmaSetCurrentThread"); - gtk_action_set_sensitive (GTK_ACTION (action), FALSE); - /* Connect signal */ g_signal_connect (self->list, "button-press-event", G_CALLBACK (on_threads_button_press), self); g_signal_connect (self->list, "row-activated", G_CALLBACK (on_threads_row_activated), self); @@ -514,9 +513,51 @@ on_debugger_stopped (DmaThreads *self) dma_destroy_threads_gui (self); } +static gboolean +on_mark_selected_thread (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) +{ + DmaThreads* self = (DmaThreads *)user_data; + GdkPixbuf *pic; + guint thread; + + gtk_tree_model_get (model, iter, THREAD_ACTIVE_COLUMN, &pic, THREAD_ID_COLUMN, &thread, -1); + + if (pic != NULL) + { + /* Remove previously selected thread marker */ + gdk_pixbuf_unref (pic); + pic = NULL; + } + + if (self->current_thread == thread) + { + /* Create marker if needed */ + pic = gdk_pixbuf_new_from_file (ANJUTA_PIXMAP_POINTER, NULL); + } + + gtk_list_store_set (GTK_LIST_STORE (model), iter, + THREAD_ACTIVE_COLUMN, pic, -1); + + if (pic != NULL) + { + gdk_pixbuf_unref (pic); + } + + return FALSE; +} + static void on_frame_changed (DmaThreads *self, guint frame, guint thread) { + if (thread != self->current_thread) + { + GtkTreeModel *model; + + self->current_thread = thread; + model = gtk_tree_view_get_model (self->list); + + gtk_tree_model_foreach (model, on_mark_selected_thread, self); + } } /* Constructor & Destructor diff --git a/plugins/gdb/debugger.c b/plugins/gdb/debugger.c index 490e1ac5..c03efeac 100644 --- a/plugins/gdb/debugger.c +++ b/plugins/gdb/debugger.c @@ -108,6 +108,7 @@ struct _DebuggerPriv pid_t inferior_pid; gint gnome_terminal_type; guint current_thread; + guint current_frame; GObject* instance; @@ -950,6 +951,7 @@ debugger_process_frame (Debugger *debugger, const GDBMIValue *val) { debugger->priv->current_thread = strtoul (gdbmi_value_literal_get (thread), NULL, 0); } + debugger->priv->current_frame = 0; frame = gdbmi_value_hash_lookup (val, "frame"); if (frame) @@ -2596,11 +2598,14 @@ debugger_list_local_finish (Debugger *debugger, const GDBMIValue *mi_results, co void debugger_list_local (Debugger *debugger, IAnjutaDebuggerCallback callback, gpointer user_data) { + gchar *buff; DEBUG_PRINT ("In function: debugger_list_local()"); g_return_if_fail (IS_DEBUGGER (debugger)); - debugger_queue_command (debugger, "-stack-list-arguments 0 0 0", TRUE, TRUE, NULL, NULL, NULL); + buff = g_strdup_printf("-stack-list-arguments 0 %d %d", debugger->priv->current_frame, debugger->priv->current_frame); + debugger_queue_command (debugger, buff, TRUE, TRUE, NULL, NULL, NULL); + g_free (buff); debugger_queue_command (debugger, "-stack-list-locals 0", TRUE, FALSE, debugger_list_local_finish, callback, user_data); } @@ -2648,11 +2653,15 @@ debugger_list_argument_finish (Debugger *debugger, const GDBMIValue *mi_results, void debugger_list_argument (Debugger *debugger, IAnjutaDebuggerCallback callback, gpointer user_data) { + gchar *buff; + DEBUG_PRINT ("In function: debugger_list_argument()"); g_return_if_fail (IS_DEBUGGER (debugger)); - debugger_queue_command (debugger, "-stack-list-argument 0 0 0", TRUE, FALSE, debugger_list_argument_finish, callback, user_data); + buff = g_strdup_printf("-stack-list-arguments 0 %d %d", debugger->priv->current_frame, debugger->priv->current_frame); + debugger_queue_command (debugger, buff, TRUE, FALSE, debugger_list_argument_finish, callback, user_data); + g_free (buff); } static void @@ -3438,6 +3447,7 @@ debugger_set_frame_finish (Debugger *debugger, const GDBMIValue *mi_results, con { guint frame = (guint)debugger->priv->current_cmd.user_data; + debugger->priv->current_frame = frame; g_signal_emit_by_name (debugger->priv->instance, "frame-changed", frame, debugger->priv->current_thread); } -- 2.11.4.GIT