Added byline
[anjuta.git] / plugins / debug-manager / locals.c
blob96897045e5e5819781f9cbca171bd60668993e30
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 locals.c
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
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
24 #include "locals.h"
26 #include "debug_tree.h"
28 #include "queue.h"
30 /*#define DEBUG*/
31 #include <libanjuta/anjuta-debug.h>
34 typedef struct _DmaThreadLocal
36 GtkTreeModel *model;
37 gint thread;
38 guint frame;
39 } DmaThreadLocal;
41 typedef struct _DmaThreadAndFrame
43 gint thread;
44 guint frame;
45 } DmaThreadAndFrame;
47 struct _Locals
49 AnjutaPlugin *plugin;
50 DmaDebuggerQueue *debugger;
52 GtkWidget *main_w;
53 DebugTree *debug_tree;
55 DmaThreadLocal* current;
56 GList *list;
59 static void
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);
67 if (error != NULL)
68 return;
70 debug_tree_replace_list (self->debug_tree, list);
73 /* Private functions
74 *---------------------------------------------------------------------------*/
76 static void
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 */
86 GtkWidget *main_w;
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),
91 GTK_POLICY_AUTOMATIC,
92 GTK_POLICY_AUTOMATIC);
93 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (main_w),
94 GTK_SHADOW_IN);
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,
100 self->main_w,
101 /* This is the list of local variables. */
102 "AnjutaDebuggerLocals", _("Locals"),
103 "gdb-locals-icon", ANJUTA_SHELL_PLACEMENT_BOTTOM,
104 NULL);
107 static void
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));
119 self->main_w = NULL;
123 static void
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));
131 g_free (frame);
134 static void
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;
142 self->list = NULL;
145 static gboolean
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)
157 GList *list;
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;
165 static void
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;
180 /* Private functions
181 *---------------------------------------------------------------------------*/
183 static void locals_update (Locals *self, gint thread)
185 GList *list;
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);
201 else
203 GList *next;
205 debug_tree_remove_model (self->debug_tree, frame->model);
206 g_object_unref (G_OBJECT (frame->model));
207 g_free (frame);
208 next = g_list_next (list);
209 self->list = g_list_delete_link (self->list, list);
210 list = next;
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);
227 static void
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);
236 if (local != NULL)
238 /* Find frame already read */
239 self->current = local;
240 debug_tree_set_model (self->debug_tree, self->current->model);
242 return;
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);
252 static void
253 on_program_moved (Locals *self, guint pid, gint thread)
255 locals_update (self, thread);
258 static void
259 on_frame_changed (Locals *self, guint frame, gint thread)
261 /* Change thread and frame*/
262 locals_change_frame (self, frame, thread);
265 static void
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);
278 static void
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);
290 /* Public function
291 *---------------------------------------------------------------------------*/
293 gchar*
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 *---------------------------------------------------------------------------*/
302 Locals *
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);
312 return self;
315 void
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);
324 /* Destroy gui */
325 destroy_locals_gui (self);
327 g_free (self);