Integrate adding files with the file manager
[anjuta-git-plugin.git] / plugins / debug-manager / registers.c
blob74771f24823c376441f69b1b3d8294ef8af18f7c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 cpu_registers.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 later version.
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 "registers.h"
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <string.h>
30 #include <gnome.h>
32 /*#define DEBUG*/
33 #include <libanjuta/resources.h>
34 #include <libanjuta/anjuta-debug.h>
36 #include "utilities.h"
37 #include "queue.h"
39 /* Constants
40 *---------------------------------------------------------------------------*/
42 #define REGISTER_UNMODIFIED_COLOR "black"
43 #define REGISTER_MODIFIED_COLOR "red"
44 #define REGISTER_UNKNOWN_VALUE "??"
46 /* Types
47 *---------------------------------------------------------------------------*/
49 typedef struct _DmaThreadRegisterList
51 GtkTreeModel *model;
52 gint thread;
53 guint last_update;
54 } DmaThreadRegisterList;
56 struct _CpuRegisters
58 DmaDebuggerQueue *debugger;
59 AnjutaPlugin *plugin;
60 DmaThreadRegisterList* current;
61 GList *list;
62 GtkTreeView *treeview;
63 GtkWidget *window;
64 guint current_update;
67 enum
69 REGISTER_MODIFIED = 1 << 0,
72 enum
74 NUMBER_COLUMN,
75 NAME_COLUMN,
76 VALUE_COLUMN,
77 FLAG_COLUMN,
78 COLUMNS_NB
81 /* Private functions
82 *---------------------------------------------------------------------------*/
84 /* Handle list of registers for each thread
85 *---------------------------------------------------------------------------*/
87 static gboolean
88 on_copy_register_name (GtkTreeModel *model,
89 GtkTreePath *path,
90 GtkTreeIter *iter,
91 gpointer user_data)
93 GtkListStore *list = (GtkListStore *)user_data;
94 GtkTreeIter dest;
95 guint num;
96 gchar *name;
98 gtk_tree_model_get(model, iter,
99 NUMBER_COLUMN, &num,
100 NAME_COLUMN, &name,
101 -1);
103 gtk_list_store_append (list, &dest);
104 gtk_list_store_set(list, &dest,
105 NUMBER_COLUMN, num,
106 NAME_COLUMN, name,
107 VALUE_COLUMN, REGISTER_UNKNOWN_VALUE,
108 FLAG_COLUMN, 0,
109 -1);
110 g_free (name);
112 return FALSE;
115 static void
116 on_cpu_registers_updated (const GList *registers, gpointer user_data, GError *error)
118 CpuRegisters *self = (CpuRegisters *)user_data;
119 const GList *node;
121 GtkListStore *list;
122 GtkTreeIter iter;
123 gboolean valid;
125 if (error != NULL)
127 /* Command canceled */
129 return;
132 if (self->current == NULL)
134 /* Program has exited */
135 return;
138 /* Get first item in list view */
139 valid = gtk_tree_model_get_iter_first (self->current->model, &iter);
140 list = GTK_LIST_STORE (self->current->model);
142 self->current->last_update = self->current_update;
144 for(node = registers;node != NULL; node = g_list_next (node))
146 IAnjutaDebuggerRegisterData *reg = (IAnjutaDebuggerRegisterData *)node->data;
147 guint id;
148 gchar *value;
150 /* Look for corresponding item in list view */
151 for (;valid; valid = gtk_tree_model_iter_next (self->current->model, &iter))
153 gtk_tree_model_get (self->current->model, &iter, NUMBER_COLUMN, &id, -1);
154 if (id >= reg->num) break;
157 if (!valid)
159 /* Append new item in list view */
160 gtk_list_store_append (list, &iter);
161 gtk_list_store_set(list, &iter,
162 NUMBER_COLUMN, reg->num,
163 NAME_COLUMN, reg->name,
164 VALUE_COLUMN, reg->value == NULL ? REGISTER_UNKNOWN_VALUE : reg->value,
165 FLAG_COLUMN, 0,
166 -1);
168 else if (id != reg->num)
170 /* Insert new item in list view */
171 gtk_list_store_insert_before (list, &iter, &iter);
172 gtk_list_store_set(list, &iter,
173 NUMBER_COLUMN, reg->num,
174 NAME_COLUMN, reg->name,
175 VALUE_COLUMN, reg->value == NULL ? REGISTER_UNKNOWN_VALUE : reg->value,
176 FLAG_COLUMN, 0,
177 -1);
179 else
181 /* Update name */
182 if (reg->name != NULL)
184 gtk_list_store_set (list, &iter, NAME_COLUMN, reg->name, -1);
186 /* Update value */
187 if (reg->value != NULL)
189 gtk_tree_model_get (self->current->model, &iter, VALUE_COLUMN, &value, -1);
190 if ((value != NULL) && (strcmp (value, reg->value) == 0))
192 /* Same value */
193 gtk_list_store_set (list, &iter, FLAG_COLUMN, 0, -1);
195 else
197 /* New value */
198 gtk_list_store_set (list, &iter, VALUE_COLUMN, reg->value,
199 FLAG_COLUMN, REGISTER_MODIFIED,
200 -1);
202 if (value != NULL) g_free (value);
208 static void
209 cpu_registers_update (CpuRegisters *self)
211 if (GTK_WIDGET_MAPPED (self->window))
213 dma_queue_update_register (
214 self->debugger,
215 (IAnjutaDebuggerCallback)on_cpu_registers_updated,
216 self);
220 static DmaThreadRegisterList*
221 dma_thread_create_new_register_list (CpuRegisters *self, gint thread)
223 DmaThreadRegisterList *regs;
224 GtkListStore *store;
226 if ((self->list != NULL)
227 && (((DmaThreadRegisterList *)g_list_first (self->list)->data)->thread == 0))
229 /* List as been created but not associated to a thread */
231 regs = ((DmaThreadRegisterList *)g_list_first (self->list)->data);
233 regs->thread = thread;
235 return regs;
238 /* Create new list store */
239 store = gtk_list_store_new (COLUMNS_NB,
240 G_TYPE_UINT,
241 G_TYPE_STRING,
242 G_TYPE_STRING,
243 G_TYPE_UINT);
245 regs = g_new (DmaThreadRegisterList, 1);
246 regs->thread = thread;
247 regs->model = GTK_TREE_MODEL (store);
248 regs->last_update = 0;
250 if (self->list == NULL)
252 GError *err = NULL;
254 self->current = regs;
256 /* List is empty, ask debugger to get all register name */
257 dma_queue_list_register (
258 self->debugger,
259 (IAnjutaDebuggerCallback)on_cpu_registers_updated,
260 self);
262 if (err != NULL)
264 if (err->code == IANJUTA_DEBUGGER_NOT_IMPLEMENTED)
266 g_object_unref (G_OBJECT (regs->model));
267 g_free (regs);
268 self->current = NULL;
270 return NULL;
273 g_error_free (err);
276 else
278 /* One register list already exist, copy register name and ID */
280 gtk_tree_model_foreach (((DmaThreadRegisterList *)g_list_first (self->list)->data)->model,
281 on_copy_register_name, store);
283 self->list = g_list_append (self->list, regs);
285 return regs;
288 static void
289 on_clear_register_list (gpointer data, gpointer user_data)
291 DmaThreadRegisterList *regs = (DmaThreadRegisterList *) data;
293 g_object_unref (G_OBJECT (regs->model));
294 g_free (regs);
297 static void
298 dma_thread_clear_all_register_list (CpuRegisters *self)
300 self->current = NULL;
302 /* Clear all GtkListStore */
303 g_list_foreach (self->list, (GFunc)on_clear_register_list, NULL);
304 g_list_free (self->list);
306 self->list = NULL;
309 static gboolean
310 on_find_register_list (gconstpointer a, gconstpointer b)
312 const DmaThreadRegisterList *regs = (const DmaThreadRegisterList *)a;
313 guint thread = (gint)b;
315 return regs->thread != thread;
318 static void
319 dma_thread_set_register_list (CpuRegisters *self, gint thread)
321 GList *list;
322 DmaThreadRegisterList *regs;
324 if (self->current == NULL) return; /* No register list */
326 if (self->current->thread != thread)
328 list = g_list_find_custom (self->list, (gconstpointer) thread, on_find_register_list);
330 if (list == NULL)
332 /* Create new find */
333 regs = dma_thread_create_new_register_list(self, thread);
335 else
337 regs = (DmaThreadRegisterList *)list->data;
339 self->current = regs;
340 gtk_tree_view_set_model (self->treeview, regs->model);
343 if (self->current_update != self->current->last_update)
345 cpu_registers_update (self);
349 static void
350 on_cpu_registers_changed (GtkCellRendererText *cell,
351 gchar *path_string,
352 gchar *text,
353 gpointer user_data)
355 CpuRegisters *self = (CpuRegisters *)user_data;
356 GtkTreeIter iter;
358 if (gtk_tree_model_get_iter_from_string (self->current->model, &iter, path_string))
360 IAnjutaDebuggerRegisterData reg;
361 gchar *name;
363 gtk_tree_model_get (self->current->model, &iter, NUMBER_COLUMN, &reg.num, NAME_COLUMN, &name, -1);
364 reg.value = text;
365 reg.name = name;
367 dma_queue_write_register (self->debugger, &reg);
368 dma_queue_update_register (
369 self->debugger,
370 (IAnjutaDebuggerCallback)on_cpu_registers_updated,
371 self);
372 g_free (name);
376 static void
377 on_program_moved (CpuRegisters *self, guint pid, gint thread)
379 self->current_update++;
380 dma_thread_set_register_list (self, thread);
383 static void
384 on_frame_changed (CpuRegisters *self, guint frame, gint thread)
386 dma_thread_set_register_list (self, thread);
389 static void
390 destroy_cpu_registers_gui (CpuRegisters *self)
392 /* Destroy register window */
393 if (self->window != NULL)
395 gtk_widget_destroy (self->window);
396 self->window = NULL;
399 /* Destroy register list */
400 dma_thread_clear_all_register_list (self);
403 static void
404 on_program_exited (CpuRegisters *self)
406 /* Disconnect signals */
407 g_signal_handlers_disconnect_by_func (self->plugin, on_program_exited, self);
408 g_signal_handlers_disconnect_by_func (self->plugin, on_program_moved, self);
409 g_signal_handlers_disconnect_by_func (self->plugin, on_frame_changed, self);
411 destroy_cpu_registers_gui (self);
414 static void
415 on_map (GtkWidget* widget, CpuRegisters *self)
417 cpu_registers_update (self);
420 static void
421 cpu_registers_value_cell_data_func (GtkTreeViewColumn *tree_column,
422 GtkCellRenderer *cell, GtkTreeModel *tree_model,
423 GtkTreeIter *iter, gpointer data)
425 gchar *value;
426 guint flag;
427 GValue gvalue = {0, };
429 gtk_tree_model_get (tree_model, iter, VALUE_COLUMN, &value, FLAG_COLUMN, &flag, -1);
431 g_value_init (&gvalue, G_TYPE_STRING);
432 g_value_set_static_string (&gvalue, value);
433 g_object_set_property (G_OBJECT (cell), "text", &gvalue);
434 g_free (value);
436 g_value_reset (&gvalue);
437 g_value_set_static_string (&gvalue, flag & REGISTER_MODIFIED ? REGISTER_MODIFIED_COLOR : REGISTER_UNMODIFIED_COLOR);
438 g_object_set_property (G_OBJECT (cell), "foreground", &gvalue);
442 static gboolean
443 create_cpu_registers_gui (CpuRegisters *self)
445 GtkCellRenderer *renderer;
446 GtkTreeViewColumn *column;
448 g_return_val_if_fail (self->window == NULL, FALSE);
450 /* Create list store */
451 if (dma_thread_create_new_register_list (self, 0) == NULL)
453 /* Unable to create register list */
455 return FALSE;
458 /* Create list view */
459 self->treeview = GTK_TREE_VIEW (gtk_tree_view_new_with_model (self->current->model));
460 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (self->treeview),
461 GTK_SELECTION_SINGLE);
463 renderer = gtk_cell_renderer_text_new ();
464 column = gtk_tree_view_column_new_with_attributes (N_("Register"),
465 renderer, "text", NAME_COLUMN, NULL);
466 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
467 gtk_tree_view_append_column (self->treeview, column);
468 renderer = gtk_cell_renderer_text_new ();
469 g_object_set(renderer, "editable", TRUE, NULL);
470 g_signal_connect(renderer, "edited", (GCallback) on_cpu_registers_changed, self);
471 column = gtk_tree_view_column_new_with_attributes (N_("Value"),
472 renderer, NULL);
473 gtk_tree_view_column_set_cell_data_func (column, renderer,
474 cpu_registers_value_cell_data_func,
475 NULL, NULL);
476 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
477 gtk_tree_view_append_column (self->treeview, column);
479 /* Add register window */
480 self->window = gtk_scrolled_window_new (NULL, NULL);
481 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->window),
482 GTK_POLICY_AUTOMATIC,
483 GTK_POLICY_AUTOMATIC);
484 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (self->window),
485 GTK_SHADOW_IN);
486 gtk_container_add (GTK_CONTAINER (self->window), GTK_WIDGET (self->treeview));
487 g_signal_connect(self->window, "map", (GCallback) on_map, self);
489 anjuta_shell_add_widget (self->plugin->shell,
490 self->window,
491 "AnjutaDebuggerRegisters", _("Registers"),
492 NULL, ANJUTA_SHELL_PLACEMENT_LEFT,
493 NULL);
495 return TRUE;
498 static void
499 on_program_started (CpuRegisters *self)
501 if (!dma_debugger_queue_is_supported (self->debugger, HAS_REGISTER)) return;
503 /* If current debugger support access to cpu hardware */
504 if (!create_cpu_registers_gui (self)) return;
506 self->current_update = 0;
508 /* Connect remaining signal */
509 g_signal_connect_swapped (self->plugin, "program-exited", G_CALLBACK (on_program_exited), self);
510 g_signal_connect_swapped (self->plugin, "program-moved", G_CALLBACK (on_program_moved), self);
511 g_signal_connect_swapped (self->plugin, "frame-changed", G_CALLBACK (on_frame_changed), self);
514 /* Constructor & Destructor
515 *---------------------------------------------------------------------------*/
517 CpuRegisters*
518 cpu_registers_new(DebugManagerPlugin *plugin)
520 CpuRegisters* self;
522 g_return_val_if_fail (plugin != NULL, NULL);
524 self = g_new0 (CpuRegisters, 1);
526 self->plugin = ANJUTA_PLUGIN (plugin);
527 self->debugger = dma_debug_manager_get_queue (plugin);
529 g_signal_connect_swapped (self->plugin, "program-started", G_CALLBACK (on_program_started), self);
531 return self;
534 void
535 cpu_registers_free(CpuRegisters* self)
537 g_return_if_fail (self != NULL);
539 g_signal_handlers_disconnect_matched (self->plugin, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
541 destroy_cpu_registers_gui (self);
543 g_free(self);