[anjuta] debug-manager: Merge stack and thread debugger window



commit bb16c16f9d2abfe3beb1bd6cce909a3bdce7f9ad
Author: SÃbastien Granjoux <seb sfo free fr>
Date:   Fri Oct 21 22:20:31 2011 +0200

    debug-manager: Merge stack and thread debugger window

 manuals/anjuta-manual/C/debug-stack.page       |   19 +-
 manuals/anjuta-manual/C/debug-thread.page      |  105 ----
 manuals/anjuta-manual/Makefile.am              |    1 -
 plugins/debug-manager/Makefile.am              |    2 -
 plugins/debug-manager/anjuta-debug-manager.xml |    4 -
 plugins/debug-manager/plugin.c                 |  186 +++----
 plugins/debug-manager/stack_trace.c            |  685 +++++++++++++++---------
 plugins/debug-manager/threads.c                |  644 ----------------------
 plugins/debug-manager/threads.h                |   38 --
 po/POTFILES.in                                 |    1 -
 10 files changed, 533 insertions(+), 1152 deletions(-)
---
diff --git a/manuals/anjuta-manual/C/debug-stack.page b/manuals/anjuta-manual/C/debug-stack.page
index fb2c37c..e59b1a2 100644
--- a/manuals/anjuta-manual/C/debug-stack.page
+++ b/manuals/anjuta-manual/C/debug-stack.page
@@ -29,6 +29,10 @@
     Each stack frame is numbered starting from 0 for the current function.
     You can only view the stack frames while the debugger is running.</p>
 
+    <p>Moreover, a program can be composed of several threads. Each thread is
+    executed independently and has its own registers, stack and local
+    variables, but shares all global variables.</p>
+
     <steps>
       <item>
         <p>From the <gui>main menu</gui>, select <guiseq><gui>View</gui>
@@ -37,7 +41,8 @@
       </item>
     </steps>
 
-    <p>Each stack frame contains the following information:</p>	
+    <p>The stacks are displayed in a tree view having their corresponding
+    thread as parent and displaying the following information:</p>	
 
     <terms>
       <item>
@@ -48,6 +53,10 @@
         the active stack frame to examine local variables in other functions.</p>
       </item>
       <item>
+        <title>Thread</title>
+        <p>This is a number corresponding to each thread.</p>
+      </item>
+      <item>
         <title>Frame</title>
         <p>This is the frame number starting from 0 for the current function.
         The first function of your program, for example <code>main()</code> in a C program,
@@ -80,7 +89,7 @@
 
 
   <section>
-    <title>Change the current stack frame</title>
+    <title>Change the current stack frame or thread</title>
 
     <steps>
       <item>
@@ -90,6 +99,12 @@
         <p>Right-click and select <gui>Set current frame</gui>.</p>
       </item>
     </steps>
+
+    <p>Clicking on a stack frame in the same thread changes only the
+    stack frame, allowing to see other local variables. But doing it
+    in another thread will change both the stack frame
+    and the thread. The register values will be different and the
+    debugger will restart in the selected thread.</p>
   </section>
 
 
diff --git a/manuals/anjuta-manual/Makefile.am b/manuals/anjuta-manual/Makefile.am
index b7af61a..d247eaf 100644
--- a/manuals/anjuta-manual/Makefile.am
+++ b/manuals/anjuta-manual/Makefile.am
@@ -33,7 +33,6 @@ DOC_PAGES = \
 	debug-run.page \
 	debug-stack.page \
 	debug-step.page \
-	debug-thread.page \
 	debug-tips.page \
 	debug-watch.page \
 	directory-project-backend.page \
diff --git a/plugins/debug-manager/Makefile.am b/plugins/debug-manager/Makefile.am
index 90f9e98..cd7ba5c 100644
--- a/plugins/debug-manager/Makefile.am
+++ b/plugins/debug-manager/Makefile.am
@@ -87,8 +87,6 @@ libanjuta_debug_manager_la_SOURCES = \
 	sparse_buffer.h \
 	sparse_view.c \
 	sparse_view.h \
-	threads.c \
-	threads.h \
 	command.c \
 	command.h \
 	variable.c \
diff --git a/plugins/debug-manager/anjuta-debug-manager.xml b/plugins/debug-manager/anjuta-debug-manager.xml
index 168e973..44c8f92 100644
--- a/plugins/debug-manager/anjuta-debug-manager.xml
+++ b/plugins/debug-manager/anjuta-debug-manager.xml
@@ -86,10 +86,6 @@
 		<menuitem name="UpdateAllWatch" action="ActionDmaUpdateAllWatch" />
 		<menuitem name="RemoveAllWatch" action="ActionDmaRemoveAllWatch" />
 	</popup>
-	<popup name="PopupThread">
-		<menuitem name="SetCurrentThread" action="ActionDmaSetCurrentThread" />
-		<menuitem name="JumpToThread" action="ActionDmaJumpToThread" />
-	</popup>
 	<popup name="PopupSignals">
 		<menuitem name="SendSignal" action="ActionDmaSignalSend" />
 		<menuitem name="UpdateSignalList" action="ActionDmaSignalUpdate" />
diff --git a/plugins/debug-manager/plugin.c b/plugins/debug-manager/plugin.c
index e9b5831..5224347 100644
--- a/plugins/debug-manager/plugin.c
+++ b/plugins/debug-manager/plugin.c
@@ -26,7 +26,6 @@
 
 #include "breakpoints.h"
 #include "stack_trace.h"
-#include "threads.h"
 #include "info.h"
 #include "memory.h"
 #include "disassemble.h"
@@ -68,7 +67,7 @@ struct _DebugManagerPlugin
 
 	/* Debugger queue */
 	DmaDebuggerQueue *queue;
-	
+
 	/* Menu item */
 	gint uiid;
 	GtkActionGroup *start_group;
@@ -88,22 +87,21 @@ struct _DebugManagerPlugin
 	guint pc_line;
 	gulong pc_address;
 	gboolean busy;
-	
+
 	/* Debugger components */
 	BreakpointsDBase *breakpoints;
 	DmaStart *start;
 	StackTrace *stack;
 	CpuRegisters *registers;
 	Sharedlibs *sharedlibs;
-	Signals *signals;	
+	Signals *signals;
 	DmaMemory *memory;
 	DmaDisassemble *disassemble;
-	DmaThreads *thread;
 	DmaVariableDBase *variable;
-	
+
 
 	GtkWidget *user_command_dialog;
-	
+
 	/* Logging view */
 	IAnjutaMessageView* view;
 };
@@ -132,10 +130,10 @@ register_stock_icons (AnjutaPlugin *plugin)
         REGISTER_ICON ("locals.png", "gdb-locals-icon");
         REGISTER_ICON_FULL ("anjuta-watch", "gdb-watch-icon");
         REGISTER_ICON_FULL ("anjuta-breakpoint-toggle", ANJUTA_STOCK_BREAKPOINT_TOGGLE);
-        REGISTER_ICON_FULL ("anjuta-breakpoint-clear", ANJUTA_STOCK_BREAKPOINT_CLEAR);		
+        REGISTER_ICON_FULL ("anjuta-breakpoint-clear", ANJUTA_STOCK_BREAKPOINT_CLEAR);
     	/* We have no -24 version for the next two */
 		REGISTER_ICON ("anjuta-breakpoint-disabled-16.png", ANJUTA_STOCK_BREAKPOINT_DISABLED);
-        REGISTER_ICON ("anjuta-breakpoint-enabled-16.png", ANJUTA_STOCK_BREAKPOINT_ENABLED);				
+        REGISTER_ICON ("anjuta-breakpoint-enabled-16.png", ANJUTA_STOCK_BREAKPOINT_ENABLED);
 		REGISTER_ICON_FULL ("anjuta-attach", "debugger-attach");
 		REGISTER_ICON_FULL ("anjuta-step-into", "debugger-step-into");
 		REGISTER_ICON_FULL ("anjuta-step-out", "debugger-step-out");
@@ -153,7 +151,7 @@ static void
 show_program_counter_in_editor(DebugManagerPlugin *self)
 {
 	IAnjutaEditor *editor = self->current_editor;
-	
+
 	if ((editor != NULL) && (self->pc_editor == editor))
 	{
 		if (IANJUTA_IS_MARKABLE (editor))
@@ -166,12 +164,12 @@ show_program_counter_in_editor(DebugManagerPlugin *self)
 				ianjuta_editor_get_line_begin_position(editor, self->pc_line, NULL);
 			IAnjutaIterable *end =
 				ianjuta_editor_get_line_end_position(editor, self->pc_line, NULL);
-			
+
 			ianjuta_indicable_set(IANJUTA_INDICABLE(editor), begin, end,
 								  IANJUTA_INDICABLE_IMPORTANT, NULL);
 			g_object_unref (begin);
 			g_object_unref (end);
-		}		
+		}
 	}
 }
 
@@ -179,7 +177,7 @@ static void
 hide_program_counter_in_editor(DebugManagerPlugin *self)
 {
 	IAnjutaEditor *editor = self->current_editor;
-	
+
 	if ((editor != NULL) && (self->pc_editor == editor))
 	{
 		if (IANJUTA_IS_MARKABLE (editor))
@@ -188,8 +186,8 @@ hide_program_counter_in_editor(DebugManagerPlugin *self)
 		}
 		if (IANJUTA_IS_INDICABLE(editor))
 		{
-			ianjuta_indicable_clear(IANJUTA_INDICABLE(editor), NULL);			
-		}		
+			ianjuta_indicable_clear(IANJUTA_INDICABLE(editor), NULL);
+		}
 	}
 }
 
@@ -215,9 +213,9 @@ set_program_counter(DebugManagerPlugin *self, const gchar* filename, guint line,
 		if (docman)
 		{
 			IAnjutaEditor* editor;
-		
+
 			editor = ianjuta_document_manager_goto_file_line(docman, file, line, NULL);
-		
+
 			if (editor != NULL)
 			{
 				self->pc_editor = editor;
@@ -225,7 +223,7 @@ set_program_counter(DebugManagerPlugin *self, const gchar* filename, guint line,
 				self->pc_line = line;
 				show_program_counter_in_editor (self);
 			}
-		}		
+		}
 		g_object_unref (file);
 	}
 }
@@ -238,11 +236,11 @@ value_added_project_root_uri (AnjutaPlugin *plugin, const gchar *name,
 	const gchar *root_uri;
 
 	dm_plugin = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
-	
+
 	if (dm_plugin->project_root_uri)
 		g_free (dm_plugin->project_root_uri);
 	dm_plugin->project_root_uri = NULL;
-	
+
 	root_uri = g_value_get_string (value);
 	if (root_uri)
 	{
@@ -257,7 +255,7 @@ value_removed_project_root_uri (AnjutaPlugin *plugin, const gchar *name,
 	DebugManagerPlugin *dm_plugin;
 
 	dm_plugin = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
-	
+
 	if (dm_plugin->project_root_uri)
 		g_free (dm_plugin->project_root_uri);
 	dm_plugin->project_root_uri = NULL;
@@ -274,7 +272,7 @@ value_added_current_editor (AnjutaPlugin *plugin, const char *name,
 
 	editor = g_value_get_object (value);
 	DEBUG_PRINT("add value current editor %p",  editor);
-	
+
 	if (!IANJUTA_IS_EDITOR(editor))
 	{
 		self->current_editor = NULL;
@@ -283,7 +281,7 @@ value_added_current_editor (AnjutaPlugin *plugin, const char *name,
 
 	self->current_editor = IANJUTA_EDITOR (editor);
 	g_object_add_weak_pointer (G_OBJECT (self->current_editor), (gpointer *)(gpointer)&self->current_editor);
-		
+
 	/* Restore program counter marker */
 	show_program_counter_in_editor (self);
 
@@ -395,9 +393,9 @@ dma_plugin_debugger_started (DebugManagerPlugin *this)
 	AnjutaStatus* status;
 
 	DEBUG_PRINT ("%s", "DMA: dma_plugin_debugger_started");
-	
+
 	ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (this)->shell, NULL);
-	
+
 	/* Update ui */
 	action = gtk_action_group_get_action (this->start_group, "ActionDebuggerStop");
 	gtk_action_set_sensitive (action, TRUE);
@@ -421,7 +419,7 @@ dma_plugin_program_loaded (DebugManagerPlugin *this)
 	AnjutaStatus* status;
 
 	DEBUG_PRINT ("%s", "DMA: dma_plugin_program_loaded");
-	
+
 	/* Update ui */
 	ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (this)->shell, NULL);
 	gtk_action_group_set_sensitive (this->loaded_group, TRUE);
@@ -443,18 +441,18 @@ dma_plugin_program_running (DebugManagerPlugin *this)
 	AnjutaStatus* status;
 
 	DEBUG_PRINT ("%s", "DMA: dma_plugin_program_running");
-	
+
 	/* Update ui */
 	ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (this)->shell, NULL);
 	gtk_action_group_set_sensitive (this->loaded_group, TRUE);
 	gtk_action_group_set_sensitive (this->stopped_group, FALSE);
 	gtk_action_group_set_sensitive (this->running_group, TRUE);
-	
+
 	gtk_action_set_sensitive (this->run_stop_action, TRUE);
 	gtk_action_set_stock_id (this->run_stop_action, GTK_STOCK_MEDIA_PAUSE);
 	gtk_action_set_label (this->run_stop_action, _("Pa_use Program"));
 	gtk_action_set_tooltip (this->run_stop_action, _("Pauses the execution of the program"));
-	
+
 	status = anjuta_shell_get_status(ANJUTA_PLUGIN (this)->shell, NULL);
 	anjuta_status_set_default (status, _("Debugger"), _("Runningâ"));
 
@@ -468,9 +466,9 @@ dma_plugin_program_stopped (DebugManagerPlugin *this)
 {
 	AnjutaUI *ui;
 	AnjutaStatus* status;
-	
+
 	DEBUG_PRINT ("%s", "DMA: dma_plugin_program_broken");
-	
+
 	/* Update ui */
 	ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (this)->shell, NULL);
 	gtk_action_group_set_sensitive (this->loaded_group, TRUE);
@@ -504,7 +502,7 @@ dma_plugin_program_unload (DebugManagerPlugin *this)
 	AnjutaStatus* status;
 
 	DEBUG_PRINT ("%s", "DMA: dma_plugin_program_unload");
-	
+
 	/* Update ui */
 	ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (this)->shell, NULL);
 	gtk_action_group_set_visible (this->start_group, TRUE);
@@ -515,7 +513,7 @@ dma_plugin_program_unload (DebugManagerPlugin *this)
 	gtk_action_group_set_sensitive (this->stopped_group, FALSE);
 	gtk_action_group_set_visible (this->running_group, TRUE);
 	gtk_action_group_set_sensitive (this->running_group, FALSE);
-	
+
 	status = anjuta_shell_get_status(ANJUTA_PLUGIN (this)->shell, NULL);
 	anjuta_status_set_default (status, _("Debugger"), _("Unloaded"));
 }
@@ -532,7 +530,7 @@ dma_plugin_debugger_stopped (DebugManagerPlugin *self, GError *err)
 	DEBUG_PRINT ("%s", "DMA: dma_plugin_debugger_stopped");
 
 	dma_plugin_program_unload (self);
-	
+
 	/* Update ui */
 	ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (self)->shell, NULL);
 	gtk_action_group_set_visible (self->start_group, TRUE);
@@ -554,21 +552,21 @@ dma_plugin_debugger_stopped (DebugManagerPlugin *self, GError *err)
 
 	/* Remove user command dialog if existing */
 	if (self->user_command_dialog) gtk_widget_destroy (GTK_WIDGET (self->user_command_dialog));
-	
+
 	/* Display a warning if debugger stop unexpectedly */
 	if (err != NULL)
 	{
 		GtkWindow *parent = GTK_WINDOW (ANJUTA_PLUGIN(self)->shell);
 		anjuta_util_dialog_error (parent, _("Debugger terminated with error %d: %s\n"), err->code, err->message);
 	}
-		
+
 }
 
 static void
 dma_plugin_signal_received (DebugManagerPlugin *self, const gchar *name, const gchar *description)
 {
 	GtkWindow *parent = GTK_WINDOW (ANJUTA_PLUGIN (self)->shell);
-	
+
 	/* Skip SIGINT signal */
 	if (strcmp(name, "SIGINT") != 0)
 	{
@@ -597,7 +595,7 @@ dma_plugin_location_changed (DebugManagerPlugin *self, gulong address, const gch
 
 /* Start/Stop menu functions
  *---------------------------------------------------------------------------*/
-	
+
 static void
 on_start_debug_activate (GtkAction* action, DebugManagerPlugin* this)
 {
@@ -708,7 +706,7 @@ on_run_to_cursor_action_activate (GtkAction* action, DebugManagerPlugin* plugin)
 		if ((plugin->disassemble != NULL) && (dma_disassemble_is_focus (plugin->disassemble)))
 		{
 			gulong address;
-			
+
 			address = dma_disassemble_get_current_address (plugin->disassemble);
 			dma_queue_run_to_address (plugin->queue, address);
 		}
@@ -725,9 +723,9 @@ on_run_to_cursor_action_activate (GtkAction* action, DebugManagerPlugin* plugin)
 			file = ianjuta_file_get_file (IANJUTA_FILE (editor), NULL);
 			if (file == NULL)
 				return;
-	
+
 			filename = g_file_get_path (file);
-	
+
 			line = ianjuta_editor_get_lineno (editor, NULL);
 			dma_queue_run_to (plugin->queue, filename, line);
 			g_free (filename);
@@ -744,7 +742,7 @@ on_run_from_cursor_action_activate (GtkAction* action, DebugManagerPlugin* plugi
 		if ((plugin->disassemble != NULL) && (dma_disassemble_is_focus (plugin->disassemble)))
 		{
 			gulong address;
-			
+
 			address = dma_disassemble_get_current_address (plugin->disassemble);
 			dma_queue_run_from_address (plugin->queue, address);
 		}
@@ -761,9 +759,9 @@ on_run_from_cursor_action_activate (GtkAction* action, DebugManagerPlugin* plugi
 			file = ianjuta_file_get_file (IANJUTA_FILE (editor), NULL);
 			if (file == NULL)
 				return;
-	
+
 			filename = g_file_get_path (file);
-	
+
 			line = ianjuta_editor_get_lineno (editor, NULL);
 			dma_queue_run_from (plugin->queue, filename, line);
 			g_free (filename);
@@ -812,7 +810,7 @@ on_debugger_custom_command_activate (GtkAction * action, DebugManagerPlugin *plu
 	    gtk_window_set_transient_for (GTK_WINDOW (plugin->user_command_dialog), GTK_WINDOW (ANJUTA_PLUGIN (plugin)->shell));
 
 		g_object_add_weak_pointer (G_OBJECT (plugin->user_command_dialog), (gpointer *)&plugin->user_command_dialog);
-	
+
         g_signal_connect_swapped (plugin->user_command_dialog, "response",
                                                           G_CALLBACK (gtk_widget_destroy),
                                                          plugin->user_command_dialog);
@@ -902,7 +900,7 @@ static GtkActionEntry actions_start[] =
 	{
 		"ActionDebuggerStop",
 		GTK_STOCK_STOP,
-		N_("Stop Debugger"), 
+		N_("Stop Debugger"),
 		NULL,
 		N_("Say goodbye to the debugger"),
 		G_CALLBACK (on_debugger_stop_activate)
@@ -910,7 +908,7 @@ static GtkActionEntry actions_start[] =
 	{
 		"ActionDebuggerAddSource",
 		NULL,
-		N_("Add source pathsâ"), 
+		N_("Add source pathsâ"),
 		NULL,
 		N_("Add additional source paths"),
 		G_CALLBACK (on_add_source_activate)
@@ -924,7 +922,7 @@ static GtkActionEntry actions_loaded[] =
 		NULL,                                            /* Stock icon, if any */
 		N_("Debugger Commandâ"),                       /* Display label */
 		NULL,                                            /* short-cut */
-		N_("Custom debugger command"),                   /* Tooltip */ 
+		N_("Custom debugger command"),                   /* Tooltip */
 		G_CALLBACK (on_debugger_custom_command_activate) /* action callback */
 	},
 	{
@@ -977,10 +975,10 @@ static GtkActionEntry actions_stopped[] =
 		N_("Step _In"),
 		"F5",
 		N_("Single step into function"),
-		G_CALLBACK (on_step_in_action_activate) 
+		G_CALLBACK (on_step_in_action_activate)
 	},
 	{
-		"ActionDebuggerStepOver", 
+		"ActionDebuggerStepOver",
 		"debugger-step-over",
 		N_("Step O_ver"),
 		"F6",
@@ -990,26 +988,26 @@ static GtkActionEntry actions_stopped[] =
 	{
 		"ActionDebuggerStepOut",
 		"debugger-step-out",
-		N_("Step _Out"),                    
-		"<shift>F5",                              
-		N_("Single step out of function"), 
-		G_CALLBACK (on_step_out_action_activate) 
+		N_("Step _Out"),
+		"<shift>F5",
+		N_("Single step out of function"),
+		G_CALLBACK (on_step_out_action_activate)
 	},
 	{
-		"ActionDebuggerRunToPosition",    
-		"debugger-run-to-cursor",                             
-		N_("_Run to Cursor"),           
-		"F8",                              
-		N_("Run to the cursor"),              
-		G_CALLBACK (on_run_to_cursor_action_activate) 
+		"ActionDebuggerRunToPosition",
+		"debugger-run-to-cursor",
+		N_("_Run to Cursor"),
+		"F8",
+		N_("Run to the cursor"),
+		G_CALLBACK (on_run_to_cursor_action_activate)
 	},
 	{
-		"ActionDebuggerRunFromPosition",    
-		"debugger-run-from-cursor",                             
-		N_("_Run from Cursor"),           
-		NULL,                              
-		N_("Run from the cursor"),              
-		G_CALLBACK (on_run_from_cursor_action_activate) 
+		"ActionDebuggerRunFromPosition",
+		"debugger-run-from-cursor",
+		N_("_Run from Cursor"),
+		NULL,
+		N_("Run from the cursor"),
+		G_CALLBACK (on_run_from_cursor_action_activate)
 	},
 	{
 		"ActionGdbCommand",
@@ -1066,10 +1064,10 @@ dma_plugin_activate (AnjutaPlugin* plugin)
 	DebugManagerPlugin *this;
 	static gboolean initialized = FALSE;
 	AnjutaUI *ui;
-	
+
 	DEBUG_PRINT ("%s", "DebugManagerPlugin: Activating Debug Manager pluginâ");
 	this = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
-	
+
     if (!initialized)
     {
 		initialized = TRUE;
@@ -1087,7 +1085,7 @@ dma_plugin_activate (AnjutaPlugin* plugin)
 	g_signal_connect (this, "program-moved", G_CALLBACK (dma_plugin_program_moved), this);
 	g_signal_connect (this, "signal-received", G_CALLBACK (dma_plugin_signal_received), this);
 	g_signal_connect (this, "location-changed", G_CALLBACK (dma_plugin_location_changed), this);
-	
+
 	/* Add all our debug manager actions */
 	ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (plugin)->shell, NULL);
 	this->start_group =
@@ -1113,21 +1111,18 @@ dma_plugin_activate (AnjutaPlugin* plugin)
 											_("Debugger operations"),
 											actions_running,
 											G_N_ELEMENTS (actions_running),
-											GETTEXT_PACKAGE, TRUE, this);	
+											GETTEXT_PACKAGE, TRUE, this);
 	this->uiid = anjuta_ui_merge (ui, UI_FILE);
-	
+
 	/* Get run_stop_action */
 	this->run_stop_action = anjuta_ui_get_action (ui, "ActionGroupDebugLoaded", "ActionDebuggerContinueSuspend");
 
 	/* Variable */
 	this->variable = dma_variable_dbase_new (this);
-	
+
 	/* Stack trace */
 	this->stack = stack_trace_new (this);
 
-	/* Thread list */
-	this->thread = dma_threads_new (this);
-	
 	/* Create breakpoints list */
 	this->breakpoints = breakpoints_dbase_new (this);
 
@@ -1150,20 +1145,20 @@ dma_plugin_activate (AnjutaPlugin* plugin)
 	this->signals = signals_new (this);
 
 	dma_plugin_debugger_stopped (this, 0);
-	
+
 	/* Add watches */
-	this->project_watch_id = 
+	this->project_watch_id =
 		anjuta_plugin_add_watch (plugin, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI,
 								 value_added_project_root_uri,
 								 value_removed_project_root_uri, NULL);
-	this->editor_watch_id = 
+	this->editor_watch_id =
 		anjuta_plugin_add_watch (plugin, IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT,
 								 value_added_current_editor,
 								 value_removed_current_editor, NULL);
-						 
+
     /* Connect to save session */
 	g_signal_connect (G_OBJECT (plugin->shell), "save_session",
-                                 G_CALLBACK (on_session_save), plugin);							 
+                                 G_CALLBACK (on_session_save), plugin);
 
 	return TRUE;
 }
@@ -1182,11 +1177,11 @@ dma_plugin_deactivate (AnjutaPlugin* plugin)
 	dma_plugin_debugger_stopped (this, 0);
 
 	g_signal_handlers_disconnect_by_func (plugin->shell, G_CALLBACK (on_session_save), plugin);
-	g_signal_handlers_disconnect_matched (plugin, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, plugin);	
+	g_signal_handlers_disconnect_matched (plugin, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, plugin);
 
 	anjuta_plugin_remove_watch (plugin, this->project_watch_id, FALSE);
 	anjuta_plugin_remove_watch (plugin, this->editor_watch_id, FALSE);
-	
+
 	dma_debugger_queue_free (this->queue);
 	this->queue = NULL;
 
@@ -1195,25 +1190,22 @@ dma_plugin_deactivate (AnjutaPlugin* plugin)
 
 	dma_variable_dbase_free (this->variable);
 	this->variable = NULL;
-	
+
 	breakpoints_dbase_destroy (this->breakpoints);
 	this->breakpoints = NULL;
-	
+
 	stack_trace_free (this->stack);
 	this->stack = NULL;
 
 	cpu_registers_free (this->registers);
 	this->registers = NULL;
-	
+
 	dma_memory_free (this->memory);
 	this->memory = NULL;
-	
+
 	dma_disassemble_free (this->disassemble);
 	this->disassemble = NULL;
-	
-	dma_threads_free (this->thread);
-	this->thread = NULL;
-	
+
 	dma_start_free (this->start);
 	this->start = NULL;
 
@@ -1241,7 +1233,7 @@ dma_plugin_deactivate (AnjutaPlugin* plugin)
 /* Public functions
  *---------------------------------------------------------------------------*/
 
-DmaDebuggerQueue* 
+DmaDebuggerQueue*
 dma_debug_manager_get_queue (DebugManagerPlugin *self)
 {
 	return self->queue;
@@ -1260,9 +1252,9 @@ static void
 dma_plugin_instance_init (GObject* obj)
 {
 	DebugManagerPlugin *plugin = ANJUTA_PLUGIN_DEBUG_MANAGER (obj);
-	
+
 	plugin->uiid = 0;
-	
+
 	plugin->project_root_uri = NULL;
 	plugin->queue = NULL;
 	plugin->current_editor = NULL;
@@ -1276,7 +1268,7 @@ dma_plugin_instance_init (GObject* obj)
 	plugin->view = NULL;
 
 	plugin->user_command_dialog = NULL;
-	
+
 	/* plugin->uri = NULL; */
 }
 
@@ -1289,7 +1281,7 @@ static void
 dma_plugin_dispose (GObject* obj)
 {
 	DebugManagerPlugin *plugin = ANJUTA_PLUGIN_DEBUG_MANAGER (obj);
-	
+
 	if (plugin->user_command_dialog != NULL)	gtk_widget_destroy (GTK_WIDGET (plugin->user_command_dialog));
 
 	G_OBJECT_CLASS (parent_class)->dispose (obj);
@@ -1312,14 +1304,14 @@ dma_plugin_finalize (GObject* obj)
 	{
 		g_object_remove_weak_pointer (G_OBJECT (self->current_editor), (gpointer *)(gpointer)&self->current_editor);
 	}
-	
+
 	G_OBJECT_CLASS (parent_class)->finalize (obj);
 }
 
 /* class_init intialize the class itself not the instance */
 
 static void
-dma_plugin_class_init (GObjectClass* klass) 
+dma_plugin_class_init (GObjectClass* klass)
 {
 	AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
 
diff --git a/plugins/debug-manager/stack_trace.c b/plugins/debug-manager/stack_trace.c
index 6cef131..fb05499 100644
--- a/plugins/debug-manager/stack_trace.c
+++ b/plugins/debug-manager/stack_trace.c
@@ -43,39 +43,42 @@
 
 #define ANJUTA_PIXMAP_POINTER PACKAGE_PIXMAPS_DIR"/pointer.png"
 
-typedef struct _DmaThreadStackTrace
-{
-	GtkTreeModel *model;
-	gint thread;
-	guint last_update;
-} DmaThreadStackTrace;
-
 struct _StackTrace
 {
 	DebugManagerPlugin *plugin;
 	DmaDebuggerQueue *debugger;
-	
+
 	GtkActionGroup *action_group;
-	
-	DmaThreadStackTrace* current;
-	GList *list;
 
-	gint current_frame;
-	guint current_update;
-	
+	gint current_thread;
+	guint current_frame;
+
+	gulong changed_handler;
+
 	GtkTreeView *treeview;
 	GtkMenu *menu;
 	GtkWidget *scrolledwindow;
 };
 
+typedef struct _StackPacket StackPacket;
+
+struct _StackPacket {
+	StackTrace* self;
+	guint thread;
+	gboolean scroll;
+	gboolean unblock;
+};
+
 enum {
 	STACK_TRACE_ACTIVE_COLUMN,
+	STACK_TRACE_THREAD_COLUMN,
 	STACK_TRACE_FRAME_COLUMN,
 	STACK_TRACE_FILE_COLUMN,
 	STACK_TRACE_LINE_COLUMN,
 	STACK_TRACE_FUNC_COLUMN,
 	STACK_TRACE_ADDR_COLUMN,
 	STACK_TRACE_ARGS_COLUMN,
+	STACK_TRACE_DIRTY_COLUMN,
 	STACK_TRACE_URI_COLUMN,
 	STACK_TRACE_COLOR_COLUMN,
 	STACK_TRACE_N_COLUMNS
@@ -84,46 +87,63 @@ enum {
 /* Helpers functions
  *---------------------------------------------------------------------------*/
 
-static gboolean 
+static gboolean
 get_current_iter (GtkTreeView *view, GtkTreeIter* iter)
 {
 	GtkTreeSelection *selection;
-	
+
 	selection = gtk_tree_view_get_selection (view);
 	return gtk_tree_selection_get_selected (selection, NULL, iter);
 }
 
 /*
- * returns the current stack frame or -1 on error
+ * returns TRUE if a frame is selected
  */
-static gint
-get_current_index (StackTrace* st)
+static gboolean
+get_current_frame_and_thread (StackTrace* st, guint *frame, gint *thread)
 {
 	GtkTreeIter iter;
-	
+
 	if (get_current_iter (st->treeview, &iter))
 	{
 		GtkTreeModel *model;
-		gint frame_no;
-	
-		model = gtk_tree_view_get_model (st->treeview);		
-		gtk_tree_model_get (model, &iter, STACK_TRACE_FRAME_COLUMN, &frame_no, -1);
-		
-		return frame_no;
+		GtkTreeIter parent;
+		gchar *str;
+
+		model = gtk_tree_view_get_model (st->treeview);
+		*frame = 0;
+		if (gtk_tree_model_iter_parent (model, &parent, &iter))
+		{
+			gtk_tree_model_get (model, &iter, STACK_TRACE_FRAME_COLUMN, &str, -1);
+			if (str != NULL)
+			{
+				*frame = strtoul (str, NULL, 10);
+				g_free (str);
+			}
+			gtk_tree_model_get (model, &parent, STACK_TRACE_THREAD_COLUMN, &str, -1);
+		}
+		else
+		{
+			gtk_tree_model_get (model, &iter, STACK_TRACE_THREAD_COLUMN, &str, -1);
+		}
+		*thread = (str != NULL) ? strtoul (str, NULL, 10) : 0;
+		g_free (str);
+
+		return thread != 0 ? TRUE : FALSE;
 	}
 	else
 	{
-		return -1;
+		return FALSE;
 	}
 }
 
 static gboolean
-my_gtk_tree_model_get_iter_last(GtkTreeModel *model, GtkTreeIter *last)
+my_gtk_tree_model_get_iter_last(GtkTreeModel *model, GtkTreeIter *parent, GtkTreeIter *last)
 {
 	gboolean exist;
  	GtkTreeIter iter;
 
-	exist = gtk_tree_model_get_iter_first(model, &iter);
+	exist = gtk_tree_model_iter_children(model, &iter, parent);
 	if (!exist) return FALSE;
 
 	do
@@ -132,7 +152,7 @@ my_gtk_tree_model_get_iter_last(GtkTreeModel *model, GtkTreeIter *last)
     	exist = gtk_tree_model_iter_next(model, &iter);
     }
 	while (exist);
-	
+
 	return TRUE;
 }
 
@@ -141,7 +161,7 @@ my_gtk_tree_model_iter_prev(GtkTreeModel *model, GtkTreeIter *iter)
 {
 	GtkTreePath* path;
 	gboolean exist;
-	
+
 	path = gtk_tree_model_get_path (model, iter);
 	exist = gtk_tree_path_prev (path);
 	if (exist)
@@ -149,7 +169,7 @@ my_gtk_tree_model_iter_prev(GtkTreeModel *model, GtkTreeIter *iter)
 		exist = gtk_tree_model_get_iter (model, iter, path);
 	}
 	gtk_tree_path_free (path);
-	
+
 	return exist;
 }
 
@@ -164,58 +184,132 @@ my_gtk_tree_iter_compare(GtkTreeModel *model, GtkTreeIter *itera, GtkTreeIter *i
 	pathb = gtk_tree_model_get_path (model, iterb);
 
 	comp = gtk_tree_path_compare (patha, pathb);
-	
+
 	gtk_tree_path_free (patha);
 	gtk_tree_path_free (pathb);
-	
+
 	return comp;
 }
 
+static gboolean
+find_thread (GtkTreeModel *model, GtkTreeIter *iter, guint thread)
+{
+	gboolean found;
+
+	for (found = gtk_tree_model_get_iter_first (model, iter); found; found = gtk_tree_model_iter_next (model, iter))
+	{
+		gchar *str;
+		guint id;
+
+		gtk_tree_model_get (model, iter, STACK_TRACE_THREAD_COLUMN, &str, -1);
+		if (str != NULL)
+		{
+			id = strtoul (str, NULL, 10);
+			g_free (str);
+			if (id == thread) break;
+		}
+	}
+
+	return found;
+}
+
 /* Private functions
  *---------------------------------------------------------------------------*/
 
 static void
-on_clear_stack_trace (gpointer data, gpointer user_data)
+set_stack_frame (StackTrace *self, guint frame, gint thread)
 {
-	DmaThreadStackTrace *trace = (DmaThreadStackTrace *) data;
-	
-	g_object_unref (G_OBJECT (trace->model));
-	g_free (trace);
-}
+	GtkTreeIter parent;
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+	gboolean valid;
 
-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;
+	model = gtk_tree_view_get_model (self->treeview);
+
+	/* Clear old pointer */
+	valid = find_thread (model, &parent, self->current_thread);
+	if (valid)
+	{
+		if (gtk_tree_model_iter_nth_child (model, &iter, &parent, self->current_frame))
+		{
+        	/* clear pixmap on the previous active frame */
+            gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
+            					STACK_TRACE_ACTIVE_COLUMN, NULL, -1);
+		}
+	}
+
+	if (self->current_thread != thread)
+	{
+		self->current_thread = thread;
+		valid = find_thread (model, &parent, self->current_thread);
+	}
+
+	/* Set pointer on current frame if possible */
+	self->current_frame = frame;
+	if (valid)
+	{
+		if (gtk_tree_model_iter_nth_child (model, &iter, &parent, self->current_frame))
+		{
+			GdkPixbuf *pointer_pix = gdk_pixbuf_new_from_file (ANJUTA_PIXMAP_POINTER, NULL);
+
+			gtk_tree_store_set (GTK_TREE_STORE(model), &iter,
+								STACK_TRACE_ACTIVE_COLUMN, pointer_pix,
+								-1);
+			g_object_unref (pointer_pix);
+		}
+	}
 }
 
 static void
 on_stack_trace_updated (const GList *stack, gpointer user_data, GError *error)
 {
-	StackTrace *self = (StackTrace *)user_data;
-	const GList *node;
-	GtkListStore *model;		
+	StackPacket *packet = (StackPacket *)user_data;
+	StackTrace *self;
+	guint thread;
+	gboolean scroll;
+	GtkTreeModel *model;
 	GtkTreeIter iter;
+	GtkTreeIter parent;
+	const GList *node;
 	gboolean exist;
-	GdkPixbuf *pic;
+	GtkTreePath *path;
+
+	g_return_if_fail (packet != NULL);
+
+	self = packet->self;
+	thread = packet->thread;
+	scroll = packet->scroll;
+	if (packet->unblock) g_signal_handler_unblock (self->plugin, self->changed_handler);
+	g_slice_free (StackPacket, packet);
 
 	if (error != NULL) return;
-	
-	model = GTK_LIST_STORE (self->current->model);
 
-	pic = gdk_pixbuf_new_from_file (ANJUTA_PIXMAP_POINTER, NULL);
-	
-	exist = my_gtk_tree_model_get_iter_last (GTK_TREE_MODEL (model), &iter);
-	
+	model = gtk_tree_view_get_model (self->treeview);
+
+	if (!find_thread (model, &parent, thread)) return;
+
+	/* Check if there are already some data */
+	exist = my_gtk_tree_model_get_iter_last (GTK_TREE_MODEL (model), &parent, &iter);
+	if (exist)
+	{
+		GValue val = {0};
+
+		gtk_tree_model_get_value(model, &iter, STACK_TRACE_FRAME_COLUMN, &val);
+		if (!G_IS_VALUE (&val))
+		{
+			/* Remove dummy child */
+			gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
+
+			exist = FALSE;
+		}
+	}
+
 	for (node = (const GList *)g_list_last((GList *)stack); node != NULL; node = node->prev)
 	{
 		IAnjutaDebuggerFrame *frame;
-		gchar *adr;
+		gchar *frame_str;
+		gchar *adr_str;
+		gchar *line_str;
 		gchar *uri;
 		gchar *file;
 
@@ -224,18 +318,18 @@ on_stack_trace_updated (const GList *stack, gpointer user_data, GError *error)
 		if (exist)
 		{
 			/* Check if it's the same stack frame */
-			gchar *adr;
 			gchar *args;
 			gulong address;
 			guint line;
 			gboolean same;
-			
+
 			gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
-									STACK_TRACE_ADDR_COLUMN, &adr,
-									STACK_TRACE_LINE_COLUMN, &line,
+									STACK_TRACE_ADDR_COLUMN, &adr_str,
+									STACK_TRACE_LINE_COLUMN, &line_str,
 									STACK_TRACE_ARGS_COLUMN, &args,
 								-1);
-			address = adr != NULL ? strtoul (adr, NULL, 0) : 0;
+			address = adr_str != NULL ? strtoul (adr_str, NULL, 0) : 0;
+			line = line_str != NULL ? strtoul (line_str, NULL, 10) : 0;
 			same = (address == frame->address) && (line == frame->line);
 			if ((args == NULL) || (frame->args == NULL))
 			{
@@ -245,19 +339,18 @@ on_stack_trace_updated (const GList *stack, gpointer user_data, GError *error)
 			{
 				same = same && (strcmp (args, frame->args) == 0);
 			}
-			g_free (adr);
-			g_free (args);
-			
+
 			if (same)
 			{
 				/* Same frame, just change the color */
-				gtk_list_store_set (model, &iter, 
-								   	STACK_TRACE_ACTIVE_COLUMN, frame->level == self->current_frame ? pic : NULL,
-									STACK_TRACE_FRAME_COLUMN, frame->level,
+				frame_str = g_strdup_printf ("%d", frame->level);
+				gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
+								   	STACK_TRACE_ACTIVE_COLUMN, NULL,
+									STACK_TRACE_FRAME_COLUMN, frame_str,
 								   	STACK_TRACE_COLOR_COLUMN, "black", -1);
-				
+
 				/* Check previous frame */
-				exist = my_gtk_tree_model_iter_prev (GTK_TREE_MODEL (model), &iter);
+				exist = my_gtk_tree_model_iter_prev (model, &iter);
 				if (!exist || (node->prev != NULL))
 				{
 					/* Last frame or Upper frame still exist */
@@ -265,16 +358,19 @@ on_stack_trace_updated (const GList *stack, gpointer user_data, GError *error)
 				}
 				/* Upper frame do not exist, remove all them */
 			}
-			
+			g_free (frame_str);
+			g_free (adr_str);
+			g_free (args);
+
 			/* New frame, remove all previous frame */
 			GtkTreeIter first;
-				
-			gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &first);
-			while (my_gtk_tree_iter_compare (GTK_TREE_MODEL (model), &first, &iter) < 0)
+
+			gtk_tree_model_iter_children (model, &first, &parent);
+			while (my_gtk_tree_iter_compare (model, &first, &iter) < 0)
 			{
-				gtk_list_store_remove (model, &first);
+				gtk_tree_store_remove (GTK_TREE_STORE (model), &first);
 			}
-			gtk_list_store_remove (model, &first);
+			gtk_tree_store_remove (GTK_TREE_STORE (model), &first);
 
 			if (same)
 			{
@@ -285,14 +381,15 @@ on_stack_trace_updated (const GList *stack, gpointer user_data, GError *error)
 				exist = FALSE;
 			}
 		}
-					
-		gtk_list_store_prepend (model, &iter);
 
-		adr = g_strdup_printf ("0x%lx", frame->address);
+		gtk_tree_store_prepend (GTK_TREE_STORE (model), &iter, &parent);
+
+		frame_str = g_strdup_printf ("%d", frame->level);
+		adr_str = g_strdup_printf ("0x%lx", frame->address);
 		if (frame->file)
 		{
 			if (g_path_is_absolute (frame->file))
-			{					
+			{
 				GFile *gio_file = g_file_new_for_path (frame->file);
 				uri = g_file_get_uri (gio_file);
 				file = strrchr(frame->file, G_DIR_SEPARATOR) + 1;
@@ -303,186 +400,214 @@ on_stack_trace_updated (const GList *stack, gpointer user_data, GError *error)
 				uri = NULL;
 				file = frame->file;
 			}
+			line_str = g_strdup_printf ("%d", frame->line);
 		}
 		else
 		{
 			uri = NULL;
 			file = frame->library;
+			line_str = NULL;
 		}
-		
-		gtk_list_store_set(model, &iter, 
-					   STACK_TRACE_ACTIVE_COLUMN, frame->level == self->current_frame ? pic : NULL,
-					   STACK_TRACE_FRAME_COLUMN, frame->level, 
+
+		gtk_tree_store_set(GTK_TREE_STORE (model), &iter,
+					   STACK_TRACE_ACTIVE_COLUMN, NULL,
+					   STACK_TRACE_FRAME_COLUMN, frame_str,
 					   STACK_TRACE_FILE_COLUMN, file,
-					   STACK_TRACE_LINE_COLUMN, frame->line,
+					   STACK_TRACE_LINE_COLUMN, line_str,
 					   STACK_TRACE_FUNC_COLUMN, frame->function,
-					   STACK_TRACE_ADDR_COLUMN, adr,
+					   STACK_TRACE_ADDR_COLUMN, adr_str,
 					   STACK_TRACE_ARGS_COLUMN, frame->args,
 					   STACK_TRACE_URI_COLUMN, uri,
 					   STACK_TRACE_COLOR_COLUMN, "red",
 					   -1);
 		g_free (uri);
-		g_free (adr);
+		g_free (line_str);
+		g_free (adr_str);
+		g_free (frame_str);
+	}
+	gtk_tree_store_set(GTK_TREE_STORE (model), &parent,
+	                   STACK_TRACE_DIRTY_COLUMN, FALSE,
+	                   -1);
+
+	/* Expand and show new path */
+	path = gtk_tree_model_get_path (model, &parent);
+	gtk_tree_view_expand_row (self->treeview, path, FALSE);
+	if (self->current_thread == thread)
+	{
+		set_stack_frame (self, self->current_frame, self->current_thread);
+		gtk_tree_view_scroll_to_cell (self->treeview, path, NULL, FALSE, 0, 0);
 	}
-	g_object_unref (pic);
-	
+	gtk_tree_path_free (path);
 }
 
-static DmaThreadStackTrace*
-dma_thread_create_new_stack_trace (StackTrace *self, gint 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,
-								   G_TYPE_STRING);
-		
-	trace = g_new (DmaThreadStackTrace, 1);
-	trace->thread = thread;
-	trace->model = GTK_TREE_MODEL (store);
-	trace->last_update = self->current_update;
-
-	self->current = trace;
-		
-	/* Ask debugger to get all frame data */
-	dma_queue_list_frame (
-			self->debugger,
-			(IAnjutaDebuggerCallback)on_stack_trace_updated,
-			self);
-	
-	self->list = g_list_append (self->list, trace);
-	
-	return trace;
-}
 
-static DmaThreadStackTrace*
-dma_thread_update_stack_trace (StackTrace *self, DmaThreadStackTrace *trace)
+static void
+list_stack_frame (StackTrace *self, guint thread, gboolean update)
 {
-	trace->last_update = self->current_update;
-	
-	/* Ask debugger to get all frame data */
-	dma_queue_list_frame (
-			self->debugger,
-			(IAnjutaDebuggerCallback)on_stack_trace_updated,
-			self);
-	
-	return trace;
-}
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gboolean found;
+	gboolean dirty;
 
-static gboolean
-on_find_stack_trace (gconstpointer a, gconstpointer b)
-{
-	const DmaThreadStackTrace *trace = (const DmaThreadStackTrace *)a;
-	guint thread = GPOINTER_TO_UINT(b);
-	
-	return trace->thread != thread;
+	model = gtk_tree_view_get_model (self->treeview);
+
+	if (!update)
+	{
+		/* Search thread */
+		found = find_thread (model, &iter, thread);
+		if (found)
+		{
+			/* Check if stack trace need to be updated */
+			gtk_tree_model_get(model, &iter, STACK_TRACE_DIRTY_COLUMN, &dirty, -1);
+		}
+	}
+
+	/* Update stack trace */
+	if (update || !found || dirty)
+	{
+		StackPacket *packet;
+
+		if (thread != self->current_thread)
+		{
+			/* Change current thread temporarily */
+			dma_queue_set_thread (self->debugger, thread);
+			g_signal_handler_block (self->plugin, self->changed_handler);
+		}
+		packet = g_slice_new (StackPacket);
+		packet->thread = thread;
+		packet->self = self;
+		packet->scroll = update;
+		packet->unblock = thread != self->current_thread;
+		dma_queue_list_frame (self->debugger,
+							(IAnjutaDebuggerCallback)on_stack_trace_updated,
+							packet);
+		if (thread != self->current_thread) dma_queue_set_thread (self->debugger, self->current_thread);
+	}
 }
 
 static void
-dma_thread_set_stack_trace (StackTrace *self, guint thread)
+on_thread_updated (const GList *threads, gpointer user_data)
 {
-	GList *list;
-	DmaThreadStackTrace *trace;
+	StackTrace *self = (StackTrace *)user_data;
+	GList *node;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gboolean valid;
+	GList *new_threads;
+
+	model = gtk_tree_view_get_model (self->treeview);
 
-	if ((self->current == NULL) || (self->current->thread != thread) || (self->current->last_update != self->current_update))
+	/* Remove completed threads */
+	new_threads = g_list_copy ((GList *)threads);
+	valid = gtk_tree_model_get_iter_first (model, &iter);
+	while (valid)
 	{
-		self->current_frame = 0;
-		
-		list = g_list_find_custom (self->list, GINT_TO_POINTER(thread), on_find_stack_trace);
-	
-		if (list == NULL)
+		gchar *str;
+		gint thread;
+
+		gtk_tree_model_get(model, &iter, STACK_TRACE_THREAD_COLUMN, &str, -1);
+		thread = (str != NULL) ? strtoul (str, NULL, 10) : 0;
+		g_free (str);
+
+		for (node = new_threads; node != NULL; node = node->next)
 		{
-			/* Create new stack trace */
-			trace = dma_thread_create_new_stack_trace(self, thread);
+			if (((IAnjutaDebuggerFrame *)node->data)->thread == thread) break;
 		}
-		else
+
+		if (node != NULL)
 		{
-			trace = (DmaThreadStackTrace *)list->data;
-			self->current = trace;
-			
-			if (trace->last_update != self->current_update)
+			GtkTreePath *path;
+
+			/* Thread still existing */
+			new_threads = g_list_delete_link (new_threads, node);
+			/* Set content as dirty */
+			gtk_tree_store_set(GTK_TREE_STORE (model), &iter,
+			                   STACK_TRACE_DIRTY_COLUMN, TRUE,
+			                   STACK_TRACE_COLOR_COLUMN, "black",
+			                   -1);
+
+			/* Update stack frame if it is visible */
+			path = gtk_tree_model_get_path (model, &iter);
+			if (gtk_tree_view_row_expanded (self->treeview, path))
 			{
-				/* Update stack trace */
-				dma_thread_update_stack_trace (self, trace);
+				list_stack_frame (self, thread, TRUE);
 			}
+			gtk_tree_path_free (path);
+
+			valid = gtk_tree_model_iter_next (model, &iter);
 		}
-		gtk_tree_view_set_model (self->treeview, trace->model);
+		else
+		{
+			/* Thread completed */
+			valid = gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
+		}
+	}
+
+
+	/* Add new threads */
+	while (new_threads != NULL)
+	{
+		GtkTreeIter child;
+		gchar *str;
+
+		str = g_strdup_printf ("%d", ((IAnjutaDebuggerFrame *)new_threads->data)->thread);
+		gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
+		gtk_tree_store_set(GTK_TREE_STORE (model), &iter,
+		                   STACK_TRACE_THREAD_COLUMN, str,
+		                   STACK_TRACE_DIRTY_COLUMN, TRUE,
+		                   STACK_TRACE_COLOR_COLUMN, "red",
+		                   -1);
+		g_free (str);
+
+		/* Add a dummy child, to get the row expander */
+		gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
+
+		new_threads = g_list_delete_link (new_threads, new_threads);
 	}
 }
 
+static void
+list_threads (StackTrace *self)
+{
+	dma_queue_list_thread (
+			self->debugger,
+			(IAnjutaDebuggerCallback)on_thread_updated,
+			self);
+}
+
+
+
 /* Callback functions
  *---------------------------------------------------------------------------*/
 
 static void
-on_frame_changed (StackTrace *self, guint frame, gint thread)
+on_stack_frame_set_activate (GtkAction *action, gpointer user_data)
 {
-	GtkTreeIter iter;
-	GtkTreeModel *model;
+	StackTrace *self;
+	gint thread;
+	guint frame;
 
-	/* Change thread */
-	dma_thread_set_stack_trace (self, thread);
-	
-	/* Change frame */
-	self->current_frame = frame;
-	
-	model = self->current->model;
-	
-	/* Clear old pointer */
-	if(gtk_tree_model_get_iter_first (model, &iter))
+	self = (StackTrace*) user_data;
+
+	if (get_current_frame_and_thread (self, &frame, &thread))
 	{
-    	do
+		if (thread != self->current_thread)
 		{
-        	/* clear pixmap on the previous active frame */
-            gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-            					STACK_TRACE_ACTIVE_COLUMN, NULL, -1);
-        } while (gtk_tree_model_iter_next (model, &iter));
-	}
-	
-	/* Set pointer to 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);
-		
-		/* set pointer on this frame */
-		gtk_list_store_set (GTK_LIST_STORE(model), &iter,
-							STACK_TRACE_ACTIVE_COLUMN, pointer_pix,
-							-1);
-		g_object_unref (pointer_pix);
+			dma_queue_set_thread (self->debugger, thread);
+			dma_queue_set_frame (self->debugger, frame);
+			set_stack_frame (self, frame, thread);
+			list_stack_frame (self, thread, FALSE);
+		}
+		else if (frame != self->current_frame)
+		{
+			dma_queue_set_frame (self->debugger, frame);
+			set_stack_frame (self, frame, thread);
+			list_stack_frame (self, thread, FALSE);
+		}
 	}
 }
 
 static void
-on_stack_frame_set_activate (GtkAction *action, gpointer user_data)
-{
-	StackTrace *st;
-	guint selected_frame;
-	
-	st = (StackTrace*) user_data;
-	
-	selected_frame = get_current_index (st);
-	
-	/* No frame selected */
-	if (selected_frame == -1)
-		return;
-	
-	/* current frame is already active */
-	if (selected_frame == st->current_frame)
-		return;
-	
-	/* issue a command to switch active frame to new location */
-	dma_queue_set_frame (st->debugger, selected_frame);
-}
-
-static void
 on_stack_view_source_activate (GtkAction *action, gpointer user_data)
 {
 	GtkTreeModel *model;
@@ -490,11 +615,12 @@ on_stack_view_source_activate (GtkAction *action, gpointer user_data)
 	GtkTreeIter iter;
 	GtkTreeView *view;
 	gchar *uri;
+	gchar *line_str;
 	guint line;
-	gchar *adr;
+	gchar *adr_str;
 	gulong address;
-	
-	StackTrace* st = (StackTrace*) user_data;		
+
+	StackTrace* st = (StackTrace*) user_data;
 
 	view = st->treeview;
 	selection = gtk_tree_view_get_selection (view);
@@ -504,14 +630,16 @@ on_stack_view_source_activate (GtkAction *action, gpointer user_data)
 	/* get the frame info */
 	gtk_tree_model_get (model, &iter,
 						STACK_TRACE_URI_COLUMN, &uri,
-						STACK_TRACE_LINE_COLUMN, &line,
-						STACK_TRACE_ADDR_COLUMN, &adr,
+						STACK_TRACE_LINE_COLUMN, &line_str,
+						STACK_TRACE_ADDR_COLUMN, &adr_str,
 						-1);
-	
-	address = adr != NULL ? strtoul (adr, NULL, 0) : 0;
+
+	address = adr_str != NULL ? strtoul (adr_str, NULL, 0) : 0;
+	line = line_str != NULL ? strtoul (line_str, NULL, 0) : 0;
 	g_signal_emit_by_name (st->plugin, "location-changed", address, uri, line);
 	g_free (uri);
-	g_free (adr);
+	g_free (line_str);
+	g_free (adr_str);
 }
 
 static void
@@ -530,7 +658,7 @@ on_got_stack_trace (const gchar *trace, gpointer user_data, GError *error)
 static void
 on_stack_get_trace (GtkAction *action, gpointer user_data)
 {
-	StackTrace* st = (StackTrace*) user_data;		
+	StackTrace* st = (StackTrace*) user_data;
 
 	/* Ask debugger to get all frame data */
 	dma_queue_dump_stack_trace (
@@ -548,6 +676,25 @@ on_stack_trace_row_activated           (GtkTreeView     *treeview,
 	on_stack_frame_set_activate (NULL, st);
 }
 
+static void
+on_stack_trace_row_expanded            (GtkTreeView     *treeview,
+                                        GtkTreeIter     *iter,
+                                        GtkTreePath     *path,
+                                        StackTrace      *st)
+{
+	GtkTreeModel *model;
+	gchar *str;
+	guint thread;
+
+	model = gtk_tree_view_get_model (treeview);
+
+	gtk_tree_model_get (model, iter, STACK_TRACE_THREAD_COLUMN, &str, -1);
+	thread = (str != NULL) ? strtoul (str, NULL, 10) : 0;
+	g_free (str);
+
+	list_stack_frame (st, thread, FALSE);
+}
+
 static gboolean
 on_stack_trace_button_press (GtkWidget *widget, GdkEventButton *bevent, gpointer user_data)
 {
@@ -565,7 +712,7 @@ on_stack_trace_button_press (GtkWidget *widget, GdkEventButton *bevent, gpointer
 		/* Double left mouse click */
 		on_stack_view_source_activate (NULL, user_data);
 	}
-	
+
 	return FALSE;
 }
 
@@ -597,7 +744,7 @@ static GtkActionEntry actions_stack_trace[] = {
 		NULL,
 		G_CALLBACK (on_stack_get_trace)
 	}
-};		
+};
 
 static void
 create_stack_trace_gui(StackTrace *st)
@@ -609,21 +756,23 @@ create_stack_trace_gui(StackTrace *st)
 	AnjutaUI *ui;
 
 	g_return_if_fail (st->scrolledwindow == NULL);
-	
+
 	/* Create tree view */
-	model = GTK_TREE_MODEL(gtk_list_store_new (STACK_TRACE_N_COLUMNS,
+	model = GTK_TREE_MODEL(gtk_tree_store_new (STACK_TRACE_N_COLUMNS,
 											   GDK_TYPE_PIXBUF,
-											   G_TYPE_UINT,
+	                                           G_TYPE_STRING,
+	                                           G_TYPE_STRING,
+											   G_TYPE_STRING,
 											   G_TYPE_STRING,
-											   G_TYPE_UINT,
 											   G_TYPE_STRING,
 											   G_TYPE_STRING,
 											   G_TYPE_STRING,
+	                                           G_TYPE_BOOLEAN,
 											   G_TYPE_STRING,
 											   G_TYPE_STRING));
 	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->treeview);
 	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
 
@@ -636,9 +785,21 @@ create_stack_trace_gui(StackTrace *st)
 	gtk_tree_view_column_add_attribute (column, renderer, "pixbuf",
 										STACK_TRACE_ACTIVE_COLUMN);
 	gtk_tree_view_append_column (st->treeview, column);
+
+	column = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+	gtk_tree_view_column_set_title (column, _("Thread"));
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_start (column, renderer, TRUE);
+	gtk_tree_view_column_add_attribute (column, renderer, "text",
+										STACK_TRACE_THREAD_COLUMN);
+	gtk_tree_view_column_add_attribute (column, renderer, "foreground",
+										STACK_TRACE_COLOR_COLUMN);
+	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+	gtk_tree_view_append_column (st->treeview, column);
 	gtk_tree_view_set_expander_column (st->treeview,
 									   column);
-	
+
 	column = gtk_tree_view_column_new ();
 	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
 	gtk_tree_view_column_set_title (column, _("Frame"));
@@ -650,9 +811,7 @@ create_stack_trace_gui(StackTrace *st)
 										STACK_TRACE_COLOR_COLUMN);
 	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
 	gtk_tree_view_append_column (st->treeview, column);
-	gtk_tree_view_set_expander_column (st->treeview,
-									   column);
-	
+
 	column = gtk_tree_view_column_new ();
 	renderer = gtk_cell_renderer_text_new ();
 	gtk_tree_view_column_pack_start (column, renderer, TRUE);
@@ -674,7 +833,7 @@ create_stack_trace_gui(StackTrace *st)
 	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->treeview, column);
-	
+
 	column = gtk_tree_view_column_new ();
 	renderer = gtk_cell_renderer_text_new ();
 	gtk_tree_view_column_pack_start (column, renderer, TRUE);
@@ -685,7 +844,7 @@ create_stack_trace_gui(StackTrace *st)
 	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->treeview, column);
-	
+
 	if (dma_debugger_queue_is_supported (st->debugger, HAS_MEMORY))
 	{
 		/* Display address only if debugger has such concept */
@@ -700,7 +859,7 @@ create_stack_trace_gui(StackTrace *st)
 		gtk_tree_view_column_set_title (column, _("Address"));
 		gtk_tree_view_append_column (st->treeview, column);
 	}
-	
+
 	column = gtk_tree_view_column_new ();
 	renderer = gtk_cell_renderer_text_new ();
 	gtk_tree_view_column_pack_start (column, renderer, TRUE);
@@ -711,15 +870,16 @@ create_stack_trace_gui(StackTrace *st)
 	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->treeview, column);
-	
+
 	/* Create popup menu */
 	ui = anjuta_shell_get_ui (ANJUTA_PLUGIN(st->plugin)->shell, NULL);
 	st->menu = GTK_MENU (gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui), "/PopupStack"));
-	
+
 	/* Connect signal */
-	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);  
-	
+	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);
+	g_signal_connect (st->treeview, "row-expanded", G_CALLBACK (on_stack_trace_row_expanded), st);
+
 	/* Add stack window */
 	st->scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (st->scrolledwindow),
@@ -730,7 +890,7 @@ create_stack_trace_gui(StackTrace *st)
 	gtk_container_add (GTK_CONTAINER (st->scrolledwindow),
 					   GTK_WIDGET (st->treeview));
 	gtk_widget_show_all (st->scrolledwindow);
-	
+
 	anjuta_shell_add_widget (ANJUTA_PLUGIN(st->plugin)->shell,
 							 st->scrolledwindow,
 							 "AnjutaDebuggerStack", _("Stack"),
@@ -750,10 +910,19 @@ destroy_stack_trace_gui (StackTrace *st)
 }
 
 static void
+on_frame_changed (StackTrace *self, guint frame, gint thread)
+{
+	set_stack_frame (self, frame, thread);
+	list_stack_frame (self, thread, FALSE);
+}
+
+static void
 on_program_moved (StackTrace *self, guint pid, gint thread)
 {
-	self->current_update++;
-	dma_thread_set_stack_trace (self, thread);
+	set_stack_frame (self, 0, thread);
+
+	list_threads (self);
+	list_stack_frame (self, thread, TRUE);
 }
 
 static void
@@ -762,20 +931,20 @@ on_program_exited (StackTrace *self)
 	g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_exited), self);
 	g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_moved), self);
 	g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_frame_changed), self);
-	
-	dma_thread_clear_all_stack_trace (self);
+
 	destroy_stack_trace_gui (self);
 }
 
 static void
 on_program_started (StackTrace *self)
 {
-	self->current_update = 0;
 	create_stack_trace_gui (self);
-	
+	self->current_thread = 0;
+	self->current_frame = 0;
+
 	g_signal_connect_swapped (self->plugin, "program-exited", G_CALLBACK (on_program_exited), self);
 	g_signal_connect_swapped (self->plugin, "program-moved", G_CALLBACK (on_program_moved), self);
-	g_signal_connect_swapped (self->plugin, "frame-changed", G_CALLBACK (on_frame_changed), self);
+	self->changed_handler = g_signal_connect_swapped (self->plugin, "frame-changed", G_CALLBACK (on_frame_changed), self);
 }
 
 /* Public functions
@@ -806,7 +975,7 @@ stack_trace_new (DebugManagerPlugin *plugin)
 											GETTEXT_PACKAGE, TRUE, st);
 
 	g_signal_connect_swapped (st->plugin, "program-started", G_CALLBACK (on_program_started), st);
-	
+
 	return st;
 }
 
@@ -814,18 +983,18 @@ void
 stack_trace_free (StackTrace * st)
 {
 	AnjutaUI *ui;
-	
+
 	g_return_if_fail (st != NULL);
 
 	/* Disconnect from debugger */
-	g_signal_handlers_disconnect_matched (st->plugin, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, st);	
+	g_signal_handlers_disconnect_matched (st->plugin, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, st);
 
 	/* Remove menu actions */
 	ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (st->plugin)->shell, NULL);
 	anjuta_ui_remove_action_group (ui, st->action_group);
-	
+
 	/* Destroy menu */
 	destroy_stack_trace_gui	(st);
-	
+
 	g_free (st);
 }
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f6eac01..c0b5e3f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -74,7 +74,6 @@ plugins/debug-manager/sparse_buffer.c
 plugins/debug-manager/sparse_view.c
 plugins/debug-manager/stack_trace.c
 plugins/debug-manager/start.c
-plugins/debug-manager/threads.c
 plugins/debug-manager/utilities.c
 plugins/debug-manager/watch.c
 plugins/devhelp/plugin.c



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]