1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) 2000 Kh. Naba Kumar Singh
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any laterdversion.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "debug_tree.h"
31 #include <libanjuta/anjuta-debug.h>
34 typedef struct _DmaThreadLocal
41 typedef struct _DmaThreadAndFrame
50 DmaDebuggerQueue
*debugger
;
53 DebugTree
*debug_tree
;
55 DmaThreadLocal
* current
;
60 locals_updated (const gpointer data
, gpointer user_data
, GError
*error
)
62 const GList
*list
= (const GList
*)data
;
63 Locals
*self
= (Locals
*) user_data
;
65 g_return_if_fail (self
!= NULL
);
70 debug_tree_replace_list (self
->debug_tree
, list
);
74 *---------------------------------------------------------------------------*/
77 create_locals_gui (Locals
*self
)
79 g_return_if_fail (self
->debug_tree
== NULL
);
80 g_return_if_fail (self
->main_w
== NULL
);
82 self
->debug_tree
= debug_tree_new (self
->plugin
);
83 debug_tree_connect (self
->debug_tree
, self
->debugger
);
85 /* Create local window */
88 main_w
= gtk_scrolled_window_new (NULL
, NULL
);
89 gtk_widget_show (main_w
);
90 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (main_w
),
92 GTK_POLICY_AUTOMATIC
);
93 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (main_w
),
95 gtk_container_add (GTK_CONTAINER (main_w
), debug_tree_get_tree_widget (self
->debug_tree
));
96 gtk_widget_show_all (main_w
);
97 self
->main_w
= main_w
;
99 anjuta_shell_add_widget (self
->plugin
->shell
,
101 /* This is the list of local variables. */
102 "AnjutaDebuggerLocals", _("Locals"),
103 "gdb-locals-icon", ANJUTA_SHELL_PLACEMENT_BOTTOM
,
108 destroy_locals_gui (Locals
*self
)
110 if (self
->debug_tree
!= NULL
)
112 debug_tree_free (self
->debug_tree
);
113 self
->debug_tree
= NULL
;
116 if (self
->main_w
!= NULL
)
118 gtk_widget_destroy (GTK_WIDGET (self
->main_w
));
124 on_clear_locals (gpointer data
, gpointer user_data
)
126 DmaThreadLocal
*frame
= (DmaThreadLocal
*) data
;
127 Locals
*self
= (Locals
*)user_data
;
129 debug_tree_remove_model (self
->debug_tree
, frame
->model
);
130 g_object_unref (G_OBJECT (frame
->model
));
135 dma_thread_clear_all_locals (Locals
*self
)
137 /* Clear all GtkListStore */
138 g_list_foreach (self
->list
, (GFunc
)on_clear_locals
, self
);
139 g_list_free (self
->list
);
141 self
->current
= NULL
;
146 on_find_local (gconstpointer a
, gconstpointer b
)
148 const DmaThreadLocal
*frame
= (const DmaThreadLocal
*)a
;
149 const DmaThreadAndFrame
*comp
= (const DmaThreadAndFrame
*)b
;
151 return !((frame
->thread
== comp
->thread
) && (frame
->frame
== comp
->frame
));
154 static DmaThreadLocal
*
155 dma_thread_find_local (Locals
*self
, gint thread
, guint frame
)
158 DmaThreadAndFrame comp
= {thread
, frame
};
160 list
= g_list_find_custom (self
->list
, (gconstpointer
) &comp
, on_find_local
);
162 return list
== NULL
? NULL
: (DmaThreadLocal
*)list
->data
;
166 dma_thread_add_local (Locals
*self
, GtkTreeModel
*model
, gint thread
, guint frame
)
168 DmaThreadLocal
*local
;
170 local
= g_new (DmaThreadLocal
, 1);
171 local
->thread
= thread
;
172 local
->frame
= frame
;
173 local
->model
= model
;
174 g_object_ref (G_OBJECT (model
));
176 self
->list
= g_list_append (self
->list
, local
);
177 self
->current
= local
;
181 *---------------------------------------------------------------------------*/
183 static void locals_update (Locals
*self
, gint thread
)
186 DmaThreadLocal
*frame
;
188 /* Delete all local tree except the main one. It allow to keep the selected
189 * and the expanded item in the common case. */
190 self
->current
= NULL
;
191 for (list
= g_list_first (self
->list
); list
!= NULL
;)
193 frame
= (DmaThreadLocal
*)list
->data
;
195 if ((frame
->thread
== thread
) && (frame
->frame
== 0))
197 self
->current
= frame
;
198 debug_tree_set_model (self
->debug_tree
, frame
->model
);
199 list
= g_list_next (list
);
205 debug_tree_remove_model (self
->debug_tree
, frame
->model
);
206 g_object_unref (G_OBJECT (frame
->model
));
208 next
= g_list_next (list
);
209 self
->list
= g_list_delete_link (self
->list
, list
);
214 /* Add new frame if needed */
215 if (self
->current
== NULL
)
217 dma_thread_add_local (self
, debug_tree_get_model (self
->debug_tree
), thread
, 0);
220 /* Update all variables in all tree, so including watches */
221 debug_tree_update_all (self
->debugger
);
223 /* List new local variables and display them in local window */
224 dma_queue_list_local (self
->debugger
, locals_updated
, self
);
228 locals_change_frame (Locals
*self
, guint frame
, gint thread
)
230 DmaThreadLocal
*local
;
232 /* Check if we really need a change */
233 if ((self
->current
!= NULL
) && (self
->current
->thread
== thread
) && (self
->current
->frame
== frame
)) return;
235 local
= dma_thread_find_local (self
, thread
, frame
);
238 /* Find frame already read */
239 self
->current
= local
;
240 debug_tree_set_model (self
->debug_tree
, self
->current
->model
);
245 debug_tree_new_model (self
->debug_tree
);
246 dma_thread_add_local (self
, debug_tree_get_model (self
->debug_tree
), thread
, frame
);
248 /* List new local variables and display them in local window */
249 dma_queue_list_local (self
->debugger
, locals_updated
, self
);
253 on_program_moved (Locals
*self
, guint pid
, gint thread
)
255 locals_update (self
, thread
);
259 on_frame_changed (Locals
*self
, guint frame
, gint thread
)
261 /* Change thread and frame*/
262 locals_change_frame (self
, frame
, thread
);
266 on_program_exited (Locals
*self
)
268 /* Disconnect signals */
269 g_signal_handlers_disconnect_by_func (self
->plugin
, on_program_exited
, self
);
270 g_signal_handlers_disconnect_by_func (self
->plugin
, on_program_moved
, self
);
271 g_signal_handlers_disconnect_by_func (self
->plugin
, on_frame_changed
, self
);
273 dma_thread_clear_all_locals (self
);
275 destroy_locals_gui (self
);
279 on_program_started (Locals
*self
)
281 if (!dma_debugger_queue_is_supported (self
->debugger
, HAS_VARIABLE
)) return;
283 create_locals_gui (self
);
285 g_signal_connect_swapped (self
->plugin
, "program-exited", G_CALLBACK (on_program_exited
), self
);
286 g_signal_connect_swapped (self
->plugin
, "program-moved", G_CALLBACK (on_program_moved
), self
);
287 g_signal_connect_swapped (self
->plugin
, "frame-changed", G_CALLBACK (on_frame_changed
), self
);
291 *---------------------------------------------------------------------------*/
294 locals_find_variable_value (Locals
*l
, const gchar
*name
)
296 return debug_tree_find_variable_value (l
->debug_tree
, name
);
299 /* Constructor & Destructor
300 *---------------------------------------------------------------------------*/
303 locals_new (DebugManagerPlugin
*plugin
)
305 Locals
*self
= g_new0 (Locals
, 1);
307 self
->plugin
= ANJUTA_PLUGIN (plugin
);
308 self
->debugger
= dma_debug_manager_get_queue (plugin
);
310 g_signal_connect_swapped (self
->plugin
, "program-started", G_CALLBACK (on_program_started
), self
);
316 locals_free (Locals
*self
)
318 g_return_if_fail (self
!= NULL
);
320 g_signal_handlers_disconnect_matched (self
->plugin
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, self
);
322 dma_thread_clear_all_locals (self
);
325 destroy_locals_gui (self
);