Added byline
[anjuta.git] / plugins / debug-manager / debug_tree.c
blob9ed0cfaf2ecdfbcf41f31e08aa9723cdbbd5ff75
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 debug_tree.c
4 Copyright (C) 2006 Sébastien Granjoux
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
21 // TODO:
22 // Alloc string in DmaVariableData object, so treeview can use POINTER
23 // => no need to free data after getting the value
24 // => value can be access more easily if we have the tree viex
25 // => do the same for variable name
27 // Add a function to get all arguments
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
33 #include "debug_tree.h"
35 #include "plugin.h"
36 #include "memory.h"
38 /*#define DEBUG*/
39 #include <libanjuta/anjuta-debug.h>
41 #include <glib/gi18n.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <ctype.h>
46 #include <assert.h>
48 /* Types
49 *---------------------------------------------------------------------------*/
51 enum _DataType
53 TYPE_ROOT,
54 TYPE_UNKNOWN,
55 TYPE_POINTER,
56 TYPE_ARRAY,
57 TYPE_STRUCT,
58 TYPE_VALUE,
59 TYPE_REFERENCE,
60 TYPE_NAME
63 typedef enum _DataType DataType;
65 enum {AUTO_UPDATE_WATCH = 1 << 0};
67 /* Common data */
68 typedef struct _CommonDebugTree CommonDebugTree;
69 typedef struct _DmaVariablePacket DmaVariablePacket;
70 typedef struct _DmaVariableData DmaVariableData;
72 struct _CommonDebugTree {
73 guint initialized;
74 DebugTree* current;
75 DebugTree* user;
76 GList *tree_list;
79 /* The debug tree object */
80 struct _DebugTree {
81 DmaDebuggerQueue *debugger;
82 AnjutaPlugin *plugin;
83 GtkWidget* view; /* the tree widget */
84 gboolean auto_expand;
87 struct _DmaVariablePacket {
88 DmaVariableData *data;
89 GtkTreeModel *model;
90 guint from;
91 GtkTreeRowReference* reference;
92 DmaDebuggerQueue *debugger;
93 DmaVariablePacket* next;
96 struct _DmaVariableData {
97 gboolean modified; /* Set by tree update */
99 /* Value from debugger */
100 gboolean changed; /* Set by global update */
101 gboolean exited; /* variable outside scope */
102 gboolean deleted; /* variable should be deleted */
104 gboolean auto_update;
106 DmaVariablePacket* packet;
108 gchar* name;
111 /* Constant
112 *---------------------------------------------------------------------------*/
114 #define UNKNOWN_VALUE "???"
115 #define UNKNOWN_TYPE "?"
116 #define AUTO_UPDATE 'U'
118 enum {
119 VARIABLE_COLUMN,
120 VALUE_COLUMN,
121 TYPE_COLUMN,
122 ROOT_COLUMN,
123 DTREE_ENTRY_COLUMN,
124 N_COLUMNS
127 static gchar *tree_title[] = {
128 N_("Variable"), N_("Value"), N_("Type")
131 /* Global variable
132 *---------------------------------------------------------------------------*/
134 static GList* gTreeList = NULL;
136 /* Helper functions
137 *---------------------------------------------------------------------------*/
139 static void
140 my_gtk_tree_model_foreach_child (GtkTreeModel *const model,
141 GtkTreeIter *const parent,
142 GtkTreeModelForeachFunc func,
143 gpointer user_data)
145 GtkTreeIter iter;
146 gboolean success = gtk_tree_model_iter_children(model, &iter, parent);
148 while(success)
150 success = (!func(model, NULL, &iter, user_data) &&
151 gtk_tree_model_iter_next (model, &iter));
155 static gint
156 my_gtk_tree_model_child_position (GtkTreeModel *model,
157 GtkTreeIter *iter)
159 GtkTreePath *path;
160 gint pos;
162 path = gtk_tree_model_get_path (model, iter);
163 if (path == NULL) return -1;
165 for (pos = 0; gtk_tree_path_prev (path); pos++);
166 gtk_tree_path_free (path);
168 return pos;
171 static gboolean
172 get_current_iter (GtkTreeView *view, GtkTreeIter* iter)
174 GtkTreeSelection *selection;
176 selection = gtk_tree_view_get_selection (view);
177 return gtk_tree_selection_get_selected (selection, NULL, iter);
180 static DmaVariableData *
181 dma_variable_data_new(const gchar *const name, gboolean auto_update)
183 DmaVariableData *data;
185 data = g_new0 (DmaVariableData, 1);
186 if (name != NULL)
188 data->name = g_strdup (name);
191 data->auto_update = auto_update;
193 return data;
196 static void
197 dma_variable_data_free(DmaVariableData * data)
199 DmaVariablePacket* pack;
201 /* Mark the data as invalid, the packet structure will
202 * be free later in the callback */
203 for (pack = data->packet; pack != NULL; pack = pack->next)
205 pack->data= NULL;
208 if (data->name != NULL)
210 g_free (data->name);
213 g_free(data);
216 /* ------------------------------------------------------------------ */
218 static DmaVariablePacket *
219 dma_variable_packet_new(GtkTreeModel *model,
220 GtkTreeIter *iter,
221 DmaDebuggerQueue *debugger,
222 DmaVariableData *data,
223 guint from)
225 GtkTreePath *path;
227 g_return_val_if_fail (model, NULL);
228 g_return_val_if_fail (iter, NULL);
230 DmaVariablePacket *pack = g_new (DmaVariablePacket, 1);
232 pack->data = data;
233 pack->from = from;
234 pack->model = GTK_TREE_MODEL (model);
235 path = gtk_tree_model_get_path(model, iter);
236 pack->reference = gtk_tree_row_reference_new (model, path);
237 gtk_tree_path_free (path);
238 pack->debugger = debugger;
239 pack->next = data->packet;
240 data->packet = pack;
242 return pack;
245 static void
246 dma_variable_packet_free (DmaVariablePacket* pack)
248 if (pack->data != NULL)
250 /* Remove from packet data list */
251 DmaVariablePacket **find;
253 for (find = &pack->data->packet; *find != NULL; find = &(*find)->next)
255 if (*find == pack)
257 *find = pack->next;
258 break;
263 gtk_tree_row_reference_free (pack->reference);
265 g_free (pack);
268 static gboolean
269 dma_variable_packet_get_iter (DmaVariablePacket* pack, GtkTreeIter *iter)
271 GtkTreePath *path;
272 gboolean ok;
274 path = gtk_tree_row_reference_get_path (pack->reference);
275 ok = gtk_tree_model_get_iter (pack->model, iter, path);
276 gtk_tree_path_free (path);
278 return ok;
281 /* DebugTree private functions
282 *---------------------------------------------------------------------------*/
284 static void
285 debug_tree_cell_data_func (GtkTreeViewColumn *tree_column,
286 GtkCellRenderer *cell, GtkTreeModel *tree_model,
287 GtkTreeIter *iter, gpointer data)
289 gchar *value;
290 static const gchar *colors[] = {"black", "red"};
291 GValue gvalue = {0, };
292 DmaVariableData *node = NULL;
294 gtk_tree_model_get (tree_model, iter, VALUE_COLUMN, &value, -1);
295 g_value_init (&gvalue, G_TYPE_STRING);
296 g_value_set_static_string (&gvalue, value);
297 g_object_set_property (G_OBJECT (cell), "text", &gvalue);
299 gtk_tree_model_get (tree_model, iter, DTREE_ENTRY_COLUMN, &node, -1);
301 if (node)
303 g_value_reset (&gvalue);
304 g_value_set_static_string (&gvalue,
305 colors[(node && node->modified ? 1 : 0)]);
307 g_object_set_property (G_OBJECT (cell), "foreground", &gvalue);
309 g_free (value);
312 static gboolean
313 delete_child(GtkTreeModel *model, GtkTreePath* path,
314 GtkTreeIter* iter, gpointer user_data)
316 DmaVariableData *data;
317 DmaDebuggerQueue *debugger = (DmaDebuggerQueue *)user_data;
319 g_return_val_if_fail (model,TRUE);
320 g_return_val_if_fail (iter,TRUE);
322 gtk_tree_model_get(model, iter, DTREE_ENTRY_COLUMN, &data, -1);
324 /* Dummy node (data == NULL) are used when child are not known */
325 if (data != NULL)
327 dma_variable_data_free(data);
328 my_gtk_tree_model_foreach_child (model, iter, delete_child, debugger);
331 return FALSE;
334 static gboolean
335 delete_parent(GtkTreeModel *model, GtkTreePath* path,
336 GtkTreeIter* iter, gpointer user_data)
338 DmaVariableData *data;
339 DmaDebuggerQueue *debugger = (DmaDebuggerQueue *)user_data;
341 g_return_val_if_fail (model,TRUE);
342 g_return_val_if_fail (iter,TRUE);
344 gtk_tree_model_get(model, iter, DTREE_ENTRY_COLUMN, &data, -1);
346 /* Dummy node (data == NULL) are used as a place holder in watch box */
347 if (data != NULL)
349 if (debugger)
351 if (data->name)
353 /* Object has been created in debugger and is not a child
354 * (destroyed with their parent) */
355 dma_queue_delete_variable (debugger, data->name);
359 dma_variable_data_free(data);
361 my_gtk_tree_model_foreach_child (model, iter, delete_child, debugger);
364 return FALSE;
367 static void
368 debug_tree_remove_children (GtkTreeModel *model, DmaDebuggerQueue *debugger, GtkTreeIter* parent, GtkTreeIter* first)
370 gboolean child;
371 GtkTreeIter iter;
373 if (first != NULL)
375 /* Start with first child */
376 child = TRUE;
377 iter = *first;
379 else
381 /* Remove all children */
382 child = gtk_tree_model_iter_children(model, &iter, parent);
385 while (child)
387 delete_child (model, NULL, &iter, debugger);
389 child = gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
393 static void
394 debug_tree_model_add_dummy_children (GtkTreeModel *model, GtkTreeIter *parent)
396 GtkTreeIter iter;
398 gtk_tree_store_append(GTK_TREE_STORE(model), &iter, parent);
399 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
400 VARIABLE_COLUMN, "",
401 VALUE_COLUMN, "",
402 TYPE_COLUMN, "",
403 ROOT_COLUMN, parent == NULL ? TRUE : FALSE,
404 DTREE_ENTRY_COLUMN, NULL, -1);
407 static void
408 debug_tree_add_children (GtkTreeModel *model, DmaDebuggerQueue *debugger, GtkTreeIter* parent, guint from, const GList *children)
410 GList *child;
411 GtkTreeIter iter;
412 gboolean valid;
414 valid = gtk_tree_model_iter_nth_child (model, &iter, parent, from);
416 /* Add new children */
417 for (child = g_list_first ((GList *)children); child != NULL; child = g_list_next (child))
419 IAnjutaDebuggerVariableObject *var = (IAnjutaDebuggerVariableObject *)child->data;
420 DmaVariableData *data;
422 if (!valid)
424 /* Add new tree node */
425 gtk_tree_store_append(GTK_TREE_STORE(model), &iter, parent);
427 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
428 TYPE_COLUMN, var->type == NULL ? UNKNOWN_TYPE : var->type,
429 VALUE_COLUMN, var->value == NULL ? UNKNOWN_VALUE : var->value,
430 VARIABLE_COLUMN, var->expression,
431 ROOT_COLUMN, FALSE,
432 DTREE_ENTRY_COLUMN, NULL,-1);
433 data = NULL;
435 else
437 /* Update tree node */
438 if (var->type != NULL)
439 gtk_tree_store_set(GTK_TREE_STORE(model), &iter, TYPE_COLUMN, var->type, -1);
440 if (var->value != NULL)
441 gtk_tree_store_set(GTK_TREE_STORE(model), &iter, VALUE_COLUMN, var->value, -1);
442 if (var->expression != NULL)
443 gtk_tree_store_set(GTK_TREE_STORE(model), &iter, VARIABLE_COLUMN, var->expression, -1);
444 gtk_tree_model_get(model, &iter, DTREE_ENTRY_COLUMN, &data, -1);
446 if (var->name == NULL)
448 /* Dummy node representing additional children */
449 if (data != NULL)
451 dma_variable_data_free (data);
452 gtk_tree_store_set(GTK_TREE_STORE (model), &iter, DTREE_ENTRY_COLUMN, NULL, -1);
453 data = NULL;
458 if ((var->name != NULL) && (data == NULL))
460 /* Create new data */
461 data = dma_variable_data_new(var->name, TRUE);
462 gtk_tree_store_set(GTK_TREE_STORE(model), &iter, DTREE_ENTRY_COLUMN, data, -1);
465 /* Clear all children if they exist */
466 debug_tree_remove_children (model, debugger, &iter, NULL);
467 if ((var->children != 0) || var->has_more || (var->name == NULL))
469 /* Add dummy children */
470 debug_tree_model_add_dummy_children (model, &iter);
473 valid = gtk_tree_model_iter_next (model, &iter);
476 /* Clear remaining old children */
477 if (valid) debug_tree_remove_children (model, debugger, parent, &iter);
480 /*---------------------------------------------------------------------------*/
482 static void
483 gdb_var_evaluate_expression (const gchar *value,
484 gpointer user_data, GError* err)
486 DmaVariablePacket *pack = (DmaVariablePacket *) user_data;
487 GtkTreeIter iter;
489 g_return_if_fail (pack != NULL);
491 if ((err != NULL)
492 || (pack->data == NULL)
493 || !dma_variable_packet_get_iter (pack, &iter))
495 /* Command failed or item has been deleted */
496 dma_variable_packet_free (pack);
498 return;
501 pack->data->changed = FALSE;
502 gtk_tree_store_set(GTK_TREE_STORE (pack->model), &iter, VALUE_COLUMN, value, -1);
503 dma_variable_packet_free (pack);
506 static void
507 gdb_var_list_children (const GList *children, gpointer user_data, GError *err)
509 DmaVariablePacket *pack = (DmaVariablePacket *) user_data;
510 GtkTreeIter iter;
512 g_return_if_fail (pack != NULL);
514 if ((err != NULL)
515 || (pack->data == NULL)
516 || !dma_variable_packet_get_iter (pack, &iter))
518 /* Command failed or item has been deleted */
519 dma_variable_packet_free (pack);
521 return;
524 debug_tree_add_children (pack->model, pack->debugger, &iter, pack->from, children);
526 dma_variable_packet_free (pack);
529 static void
530 gdb_var_create (IAnjutaDebuggerVariableObject *variable, gpointer user_data, GError *err)
532 DmaVariablePacket *pack = (DmaVariablePacket *) user_data;
533 GtkTreeIter iter;
535 g_return_if_fail (pack != NULL);
537 if (err != NULL)
539 /* Command failed */
540 dma_variable_packet_free (pack);
542 return;
544 if ((pack->data == NULL)
545 || !dma_variable_packet_get_iter (pack, &iter))
547 /* Item has been deleted, but not removed from debugger as it was not
548 * created at this time, so remove it now */
549 if ((pack->debugger) && (variable->name))
551 dma_queue_delete_variable (pack->debugger, variable->name);
553 dma_variable_packet_free (pack);
555 return;
558 DmaVariableData *data = pack->data;
560 if ((variable->name != NULL) && (data->name == NULL))
562 data->name = strdup (variable->name);
564 data->changed = TRUE;
565 data->deleted = FALSE;
566 data->exited = FALSE;
568 gtk_tree_store_set(GTK_TREE_STORE(pack->model), &iter,
569 TYPE_COLUMN, variable->type,
570 VALUE_COLUMN, variable->value, -1);
573 if ((variable->children == 0) && !variable->has_more)
575 debug_tree_remove_children (pack->model, pack->debugger, &iter, NULL);
577 else
579 debug_tree_model_add_dummy_children (pack->model, &iter);
583 /* Request value and/or children if they are missing
584 * reusing same packet if possible */
585 if (variable->value == NULL)
587 dma_queue_evaluate_variable (
588 pack->debugger,
589 variable->name,
590 (IAnjutaDebuggerCallback)gdb_var_evaluate_expression,
591 pack);
593 else
595 dma_variable_packet_free (pack);
599 /* ------------------------------------------------------------------ */
601 static void
602 on_treeview_row_expanded (GtkTreeView *treeview,
603 GtkTreeIter *iter,
604 GtkTreePath *path,
605 gpointer user_data)
607 DebugTree *tree = (DebugTree *)user_data;
609 if (tree->debugger != NULL)
611 GtkTreeModel *const model = gtk_tree_view_get_model (treeview);
612 DmaVariableData *data;
614 gtk_tree_model_get (model, iter, DTREE_ENTRY_COLUMN, &data, -1);
616 if ((data != NULL) && (data->name != NULL))
618 /* Expand variable node */
619 GtkTreeIter child;
621 if (gtk_tree_model_iter_children (model, &child, iter))
623 DmaVariableData *child_data;
625 gtk_tree_model_get (model, &child, DTREE_ENTRY_COLUMN, &child_data, -1);
626 if ((child_data == NULL) || (child_data->name == NULL))
628 /* Dummy children, get the real children */
629 DmaVariablePacket *pack;
631 pack = dma_variable_packet_new(model, iter, tree->debugger, data, 0);
632 dma_queue_list_children (
633 tree->debugger,
634 data->name,
636 (IAnjutaDebuggerCallback)gdb_var_list_children,
637 pack);
641 else
643 /* Dummy node representing additional children */
644 GtkTreeIter parent;
646 if (gtk_tree_model_iter_parent (model, &parent, iter))
648 gtk_tree_model_get (model, &parent, DTREE_ENTRY_COLUMN, &data, -1);
649 if ((data != NULL) && (data->name != NULL))
651 DmaVariablePacket *pack;
652 guint from;
653 gint pos;
655 pos = my_gtk_tree_model_child_position (model, iter);
656 from = pos < 0 ? 0 : pos;
658 pack = dma_variable_packet_new(model, &parent, tree->debugger, data, from);
659 dma_queue_list_children (
660 tree->debugger,
661 data->name,
662 from,
663 (IAnjutaDebuggerCallback)gdb_var_list_children,
664 pack);
670 return;
673 static void
674 on_debug_tree_variable_changed (GtkCellRendererText *cell,
675 gchar *path_string,
676 gchar *text,
677 gpointer user_data)
679 DebugTree *tree = (DebugTree *)user_data;
680 GtkTreeIter iter;
681 GtkTreeModel * model;
683 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
684 if (gtk_tree_model_get_iter_from_string (model, &iter, path_string))
686 debug_tree_remove (tree, &iter);
688 if ((text != NULL) && (*text != '\0'))
690 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, -1};
692 var.expression = text;
693 debug_tree_add_watch (tree, &var, TRUE);
695 else
697 debug_tree_add_dummy (tree, NULL);
702 static void
703 on_debug_tree_value_changed (GtkCellRendererText *cell,
704 gchar *path_string,
705 gchar *text,
706 gpointer user_data)
708 DebugTree *tree = (DebugTree *)user_data;
709 GtkTreeIter iter;
710 GtkTreeModel * model;
712 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
714 if (gtk_tree_model_get_iter_from_string (model, &iter, path_string))
716 DmaVariableData *item;
717 DmaVariablePacket *tran;
719 gtk_tree_model_get (model, &iter, DTREE_ENTRY_COLUMN, &item, -1);
720 if ((item != NULL) && (item->name != NULL) && (tree->debugger != NULL))
722 /* Variable is valid */
723 dma_queue_assign_variable (tree->debugger, item->name, text);
724 tran = dma_variable_packet_new(model, &iter, tree->debugger, item, 0);
725 dma_queue_evaluate_variable (
726 tree->debugger,
727 item->name,
728 (IAnjutaDebuggerCallback) gdb_var_evaluate_expression,
729 tran);
734 static GtkWidget *
735 debug_tree_create (DebugTree *tree, GtkTreeView *view)
737 GtkCellRenderer *renderer;
738 GtkTreeViewColumn *column;
739 GtkTreeModel * model = GTK_TREE_MODEL (gtk_tree_store_new
740 (N_COLUMNS,
741 G_TYPE_STRING,
742 G_TYPE_STRING,
743 G_TYPE_STRING,
744 G_TYPE_BOOLEAN,
745 G_TYPE_POINTER));
747 if (view == NULL)
749 view = GTK_TREE_VIEW (gtk_tree_view_new ());
752 gtk_tree_view_set_model (view, GTK_TREE_MODEL (model));
754 GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
755 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
756 g_object_unref (G_OBJECT (model));
758 /* Columns */
759 column = gtk_tree_view_column_new ();
760 renderer = gtk_cell_renderer_text_new ();
761 gtk_tree_view_column_pack_start (column, renderer, TRUE);
762 gtk_tree_view_column_add_attribute (column, renderer, "text", VARIABLE_COLUMN);
763 gtk_tree_view_column_add_attribute (column, renderer, "editable", ROOT_COLUMN);
764 g_signal_connect(renderer, "edited", (GCallback) on_debug_tree_variable_changed, tree);
765 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
766 gtk_tree_view_column_set_resizable (column, TRUE);
767 gtk_tree_view_column_set_title (column, _(tree_title[0]));
768 gtk_tree_view_append_column (view, column);
769 gtk_tree_view_set_expander_column (view, column);
771 column = gtk_tree_view_column_new ();
772 renderer = gtk_cell_renderer_text_new ();
773 gtk_tree_view_column_pack_start (column, renderer, TRUE);
774 gtk_tree_view_column_set_cell_data_func (column, renderer,
775 debug_tree_cell_data_func, NULL, NULL);
776 gtk_tree_view_column_add_attribute (column, renderer, "text", VALUE_COLUMN);
777 g_object_set(renderer, "editable", TRUE, NULL);
778 g_signal_connect(renderer, "edited", (GCallback) on_debug_tree_value_changed, tree);
779 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
780 gtk_tree_view_column_set_resizable (column, TRUE);
781 gtk_tree_view_column_set_title (column, _(tree_title[1]));
782 gtk_tree_view_append_column (view, column);
785 column = gtk_tree_view_column_new ();
786 renderer = gtk_cell_renderer_text_new ();
787 gtk_tree_view_column_pack_start (column, renderer, TRUE);
788 gtk_tree_view_column_add_attribute (column, renderer, "text", TYPE_COLUMN);
789 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
790 gtk_tree_view_column_set_resizable (column, TRUE);
791 gtk_tree_view_column_set_title (column, _(tree_title[2]));
792 gtk_tree_view_append_column (view, column);
794 return GTK_WIDGET (view);
797 /* Public functions
798 *---------------------------------------------------------------------------*/
800 /* clear the display of the debug tree and reset the title */
801 void
802 debug_tree_remove_all (DebugTree *tree)
804 GtkTreeModel *model;
806 g_return_if_fail (tree);
807 g_return_if_fail (tree->view);
809 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
810 debug_tree_remove_model (tree, model);
813 static gboolean
814 debug_tree_find_name (const GtkTreeModel *model, GtkTreeIter *iter, const gchar *name)
816 size_t len = 0;
817 GtkTreeIter parent_iter;
818 GtkTreeIter* parent = NULL;
820 for (;;)
822 const gchar *ptr;
824 /* Check if we look for a child variable */
825 ptr = strchr(name + len + 1, '.');
826 if (ptr != NULL)
828 /* Child variable */
829 gboolean search;
831 len = ptr - name;
832 for (search = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), iter, parent);
833 search != FALSE;
834 search = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), iter))
836 DmaVariableData *iData;
837 gtk_tree_model_get (GTK_TREE_MODEL (model), iter, DTREE_ENTRY_COLUMN, &iData, -1);
839 if ((iData != NULL) && (iData->name != NULL) && (name[len] == '.') && (strncmp (name, iData->name, len) == 0))
841 break;
845 if (search == TRUE)
847 parent_iter = *iter;
848 parent = &parent_iter;
849 continue;
851 else
853 return FALSE;
856 else
858 /* Variable without any child */
859 gboolean search;
861 for (search = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), iter, parent);
862 search != FALSE;
863 search = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), iter))
865 DmaVariableData *iData;
866 gtk_tree_model_get (GTK_TREE_MODEL (model), iter, DTREE_ENTRY_COLUMN, &iData, -1);
868 if ((iData != NULL) && (iData->name != NULL) && (strcmp (name, iData->name) == 0))
870 return TRUE;
874 return FALSE;
879 void
880 debug_tree_replace_list (DebugTree *tree, const GList *expressions)
882 GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW(tree->view));
883 GtkTreeIter iter;
884 gboolean valid;
885 GList *list = g_list_copy ((GList *)expressions);
887 /* Keep in the tree only the variable in the list */
888 valid = gtk_tree_model_get_iter_first (model, &iter);
889 while (valid)
891 GList *find = NULL;
892 gchar *exp;
893 DmaVariableData *node;
895 gtk_tree_model_get (model, &iter,
896 VARIABLE_COLUMN, &exp,
897 DTREE_ENTRY_COLUMN, &node, -1);
899 if ((node->deleted == FALSE) && (node->exited == FALSE) && (exp != NULL))
901 find = g_list_find_custom (list, exp, (GCompareFunc)strcmp);
904 if (find)
906 /* Keep variable in tree, remove in add list */
907 list = g_list_delete_link (list, find);
908 valid = gtk_tree_model_iter_next (model, &iter);
910 else
912 /* Remove variable from the tree */
913 delete_parent(model, NULL, &iter, tree->debugger);
914 valid = gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
918 /* Create new variable */
919 while (list)
921 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, -1};
923 var.expression = (gchar *)(list->data);
924 debug_tree_add_watch (tree, &var, TRUE);
926 list = g_list_delete_link (list, list);
930 void
931 debug_tree_add_dummy (DebugTree *tree, GtkTreeIter *parent)
933 GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW(tree->view));
935 debug_tree_model_add_dummy_children (model, parent);
938 /* Get a IAnjutaVariable as argument in order to use the same function without
939 * variable object, currently only the expression field is set */
941 void
942 debug_tree_add_watch (DebugTree *tree, const IAnjutaDebuggerVariableObject* var, gboolean auto_update)
944 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
945 GtkTreeIter iter;
946 DmaVariableData *data;
948 /* Allocate data */
949 data = dma_variable_data_new(var->name, auto_update);
951 /* Add node in tree */
952 gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL);
953 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
954 TYPE_COLUMN, var->type == NULL ? UNKNOWN_TYPE : var->type,
955 VALUE_COLUMN, var->value == NULL ? UNKNOWN_VALUE : var->value,
956 VARIABLE_COLUMN, var->expression,
957 ROOT_COLUMN, TRUE,
958 DTREE_ENTRY_COLUMN, data, -1);
960 if (tree->debugger != NULL)
962 if ((var->value == NULL) || (var->children == -1))
964 if (var->name == NULL)
966 /* Need to create variable before to get value */
967 DmaVariablePacket *pack;
969 pack = dma_variable_packet_new(model, &iter, tree->debugger, data, 0);
970 dma_queue_create_variable (
971 tree->debugger,
972 var->expression,
973 (IAnjutaDebuggerCallback)gdb_var_create,
974 pack);
976 else
978 DEBUG_PRINT("%s", "You shouldn't read this, debug_tree_add_watch");
979 if (var->value == NULL)
981 /* Get value */
982 DmaVariablePacket *pack =
984 pack = dma_variable_packet_new(model, &iter, tree->debugger, data, 0);
985 dma_queue_evaluate_variable (
986 tree->debugger,
987 var->name,
988 (IAnjutaDebuggerCallback)gdb_var_evaluate_expression,
989 pack);
996 static void
997 on_add_watch (gpointer data, gpointer user_data)
999 DebugTree* this = (DebugTree *)user_data;
1000 gboolean auto_update = ((const gchar *)data)[0] & AUTO_UPDATE_WATCH ? TRUE : FALSE;
1001 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, -1};
1003 var.expression = &((gchar *)data)[1];
1004 debug_tree_add_watch (this, &var, auto_update);
1007 void
1008 debug_tree_add_full_watch_list (DebugTree *this, GList *expressions)
1010 g_list_foreach (expressions, on_add_watch, this);
1013 static void
1014 on_add_manual_watch (gpointer data, gpointer user_data)
1016 DebugTree* this = (DebugTree *)user_data;
1017 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, -1};
1019 var.expression = &((gchar *)data)[0];
1020 debug_tree_add_watch (this, &var, FALSE);
1023 static void
1024 on_add_auto_watch (gpointer data, gpointer user_data)
1026 DebugTree* this = (DebugTree *)user_data;
1027 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, -1};
1029 var.expression = &((gchar *)data)[0];
1030 debug_tree_add_watch (this, &var, TRUE);
1033 void
1034 debug_tree_add_watch_list (DebugTree *this, GList *expressions, gboolean auto_update)
1036 g_list_foreach (expressions, auto_update ? on_add_auto_watch : on_add_manual_watch, this);
1039 static void
1040 on_debug_tree_changed (gpointer data, gpointer user_data)
1042 IAnjutaDebuggerVariableObject *var = (IAnjutaDebuggerVariableObject *)data;
1044 if (var->name != NULL)
1046 /* Search corresponding variable in one tree */
1047 GList *list;
1049 for (list = g_list_first (gTreeList); list != NULL; list = g_list_next (list))
1051 DebugTree *tree = (DebugTree *)list->data;
1053 GtkTreeIter iter;
1054 GtkTreeModel *model;
1056 model = debug_tree_get_model (tree);
1058 if (debug_tree_find_name (model, &iter, var->name))
1060 DmaVariableData *data;
1061 gtk_tree_model_get (model, &iter, DTREE_ENTRY_COLUMN, &data, -1);
1063 if (data != NULL)
1065 data->changed = var->changed;
1066 data->exited = var->exited;
1067 data->deleted = var->deleted;
1070 return;
1076 static gboolean
1077 debug_tree_update_real (GtkTreeModel *model, DmaDebuggerQueue *debugger, GtkTreeIter* iter, gboolean force)
1079 DmaVariableData *data = NULL;
1080 GtkTreeIter child;
1081 gboolean search;
1082 gboolean refresh = TRUE;
1084 gtk_tree_model_get (model, iter, DTREE_ENTRY_COLUMN, &data, -1);
1085 if (data == NULL) return FALSE;
1088 if ((data->deleted) && (data->name != NULL) && (force || data->auto_update))
1090 /* Variable deleted (by example if type change), try to recreate it */
1091 dma_queue_delete_variable (debugger, data->name);
1092 g_free (data->name);
1093 data->name = NULL;
1096 if (data->name == NULL)
1098 /* Check is the variable creation is not pending */
1099 if (data->packet == NULL)
1101 /* Variable need to be created first */
1102 gchar *exp;
1103 DmaVariablePacket *pack;
1105 gtk_tree_model_get (model, iter, VARIABLE_COLUMN, &exp, -1);
1106 pack = dma_variable_packet_new(model, iter, debugger, data, 0);
1107 dma_queue_create_variable (
1108 debugger,
1109 exp,
1110 (IAnjutaDebuggerCallback)gdb_var_create,
1111 pack);
1112 g_free (exp);
1115 return FALSE;
1117 else if (force || (data->auto_update && data->changed))
1119 DmaVariablePacket *pack = dma_variable_packet_new(model, iter, debugger, data, 0);
1120 refresh = data->modified != (data->changed != FALSE);
1121 data->modified = (data->changed != FALSE);
1122 dma_queue_evaluate_variable (
1123 debugger,
1124 data->name,
1125 (IAnjutaDebuggerCallback)gdb_var_evaluate_expression,
1126 pack);
1127 data->changed = FALSE;
1129 else
1131 refresh = data->modified;
1132 data->modified = FALSE;
1135 /* update children */
1136 for (search = gtk_tree_model_iter_children(model, &child, iter);
1137 search == TRUE;
1138 search = gtk_tree_model_iter_next (model, &child))
1140 if (debug_tree_update_real (model, debugger, &child, force))
1142 refresh = data->modified == TRUE;
1143 data->modified = TRUE;
1147 if (refresh)
1149 GtkTreePath *path;
1150 path = gtk_tree_model_get_path (model, iter);
1151 gtk_tree_model_row_changed (model, path, iter);
1152 gtk_tree_path_free (path);
1155 return data->modified;
1159 /* Get information from debugger and update variable with automatic update */
1160 static void
1161 on_debug_tree_update_all (const GList *change, gpointer user_data, GError* err)
1163 DmaDebuggerQueue *debugger = (DmaDebuggerQueue *)user_data;
1164 GList *list;
1166 if (err != NULL) return;
1168 // Update all variables information from debugger data
1169 g_list_foreach ((GList *)change, on_debug_tree_changed, NULL);
1171 // Update all tree models
1172 for (list = g_list_first (gTreeList); list != NULL; list = g_list_next (list))
1174 DebugTree* tree = (DebugTree*)list->data;
1176 GtkTreeModel* model;
1177 GtkTreeIter iter;
1178 gboolean valid;
1180 model = debug_tree_get_model (tree);
1182 // Update this tree
1183 for (valid = gtk_tree_model_get_iter_first (model, &iter);
1184 valid;
1185 valid = gtk_tree_model_iter_next (model, &iter))
1187 debug_tree_update_real (model, debugger, &iter, FALSE);
1192 void
1193 debug_tree_update_all (DmaDebuggerQueue *debugger)
1195 dma_queue_update_variable (debugger,
1196 (IAnjutaDebuggerCallback)on_debug_tree_update_all,
1197 debugger);
1200 /* Update all variables in the specified tree */
1201 void
1202 debug_tree_update_tree (DebugTree *this)
1204 GtkTreeModel *model;
1205 GtkTreeIter iter;
1206 gboolean valid;
1208 model = gtk_tree_view_get_model (GTK_TREE_VIEW (this->view));
1210 // Update this tree
1211 for (valid = gtk_tree_model_get_iter_first (model, &iter);
1212 valid;
1213 valid = gtk_tree_model_iter_next (model, &iter))
1215 debug_tree_update_real (model, this->debugger, &iter, TRUE);
1219 GList*
1220 debug_tree_get_full_watch_list (DebugTree *this)
1222 GtkTreeIter iter;
1223 GtkTreeModel *model;
1224 GList* list = NULL;
1226 model = gtk_tree_view_get_model (GTK_TREE_VIEW (this->view));
1228 if (gtk_tree_model_get_iter_first (model, &iter) == TRUE)
1232 DmaVariableData *data;
1233 gchar *exp;
1234 gchar *exp_with_flag;
1236 gtk_tree_model_get(model, &iter, DTREE_ENTRY_COLUMN, &data,
1237 VARIABLE_COLUMN, &exp, -1);
1239 if (data != NULL)
1241 exp_with_flag = g_strconcat (" ", exp, NULL);
1242 exp_with_flag[0] = data->auto_update ? AUTO_UPDATE_WATCH : ' ';
1243 list = g_list_prepend (list, exp_with_flag);
1245 g_free (exp);
1246 } while (gtk_tree_model_iter_next (model, &iter) == TRUE);
1249 list = g_list_reverse (list);
1251 return list;
1255 GtkWidget *
1256 debug_tree_get_tree_widget (DebugTree *this)
1258 return this->view;
1261 gboolean
1262 debug_tree_get_current (DebugTree *tree, GtkTreeIter* iter)
1264 return get_current_iter (GTK_TREE_VIEW (tree->view), iter);
1267 /* Return TRUE if iter is still valid (point to next item) */
1268 gboolean
1269 debug_tree_remove (DebugTree *tree, GtkTreeIter* iter)
1271 GtkTreeModel *model;
1273 g_return_val_if_fail (tree, FALSE);
1274 g_return_val_if_fail (tree->view, FALSE);
1275 g_return_val_if_fail (iter, FALSE);
1277 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1279 delete_parent (model, NULL, iter, tree->debugger);
1280 return gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
1283 gboolean
1284 debug_tree_update (DebugTree* tree, GtkTreeIter* iter, gboolean force)
1286 if (tree->debugger != NULL)
1288 GtkTreeModel *model;
1290 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1291 return debug_tree_update_real (model, tree->debugger, iter, force);
1293 else
1295 return FALSE;
1299 void
1300 debug_tree_set_auto_update (DebugTree* this, GtkTreeIter* iter, gboolean state)
1302 GtkTreeModel *model;
1303 DmaVariableData *data;
1305 model = gtk_tree_view_get_model (GTK_TREE_VIEW (this->view));
1306 gtk_tree_model_get(model, iter, DTREE_ENTRY_COLUMN, &data, -1);
1307 if (data != NULL)
1309 data->auto_update = state;
1313 gboolean
1314 debug_tree_get_auto_update (DebugTree* this, GtkTreeIter* iter)
1316 GtkTreeModel *model;
1317 DmaVariableData *data;
1319 model = gtk_tree_view_get_model (GTK_TREE_VIEW (this->view));
1320 gtk_tree_model_get(model, iter, DTREE_ENTRY_COLUMN, &data, -1);
1322 if (data != NULL)
1324 return data->auto_update;
1326 else
1328 return FALSE;
1332 void
1333 debug_tree_connect (DebugTree *this, DmaDebuggerQueue* debugger)
1335 this->debugger = debugger;
1338 static gboolean
1339 on_disconnect_variable (GtkTreeModel *model,
1340 GtkTreePath *path,
1341 GtkTreeIter *iter,
1342 gpointer user_data)
1344 DmaVariableData *data;
1346 gtk_tree_model_get (model, iter, DTREE_ENTRY_COLUMN, &data, -1);
1348 if (data != NULL)
1350 g_free (data->name);
1351 data->name = NULL;
1354 return FALSE;
1357 void
1358 debug_tree_disconnect (DebugTree *this)
1360 GtkTreeModel *model;
1362 this->debugger = NULL;
1363 model = gtk_tree_view_get_model (GTK_TREE_VIEW (this->view));
1365 /* Remove all variable name */
1366 gtk_tree_model_foreach (model, on_disconnect_variable, NULL);
1369 GtkTreeModel *
1370 debug_tree_get_model (DebugTree *tree)
1372 return gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1375 void
1376 debug_tree_set_model (DebugTree *tree, GtkTreeModel *model)
1378 gtk_tree_view_set_model (GTK_TREE_VIEW (tree->view), model);
1381 void
1382 debug_tree_new_model (DebugTree *tree)
1384 GtkTreeModel * model = GTK_TREE_MODEL (gtk_tree_store_new
1385 (N_COLUMNS,
1386 G_TYPE_STRING,
1387 G_TYPE_STRING,
1388 G_TYPE_STRING,
1389 G_TYPE_BOOLEAN,
1390 G_TYPE_POINTER));
1392 gtk_tree_view_set_model (GTK_TREE_VIEW (tree->view), model);
1395 void
1396 debug_tree_remove_model (DebugTree *tree, GtkTreeModel *model)
1398 my_gtk_tree_model_foreach_child (model, NULL, delete_parent, tree->debugger);
1399 gtk_tree_store_clear (GTK_TREE_STORE (model));
1402 gchar *
1403 debug_tree_get_selected (DebugTree *tree)
1405 GtkTreeIter iter;
1406 gchar *exp = NULL;
1408 if (get_current_iter (GTK_TREE_VIEW (tree->view), &iter))
1410 GtkTreeModel *model;
1412 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1413 if (model != NULL)
1415 gtk_tree_model_get(model, &iter, VARIABLE_COLUMN, &exp, -1);
1419 return exp;
1422 gchar *
1423 debug_tree_get_first (DebugTree *tree)
1425 GtkTreeIter iter;
1426 gchar *exp = NULL;
1427 GtkTreeModel *model;
1429 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1430 if (model != NULL)
1432 if (gtk_tree_model_get_iter_first (model, &iter))
1434 gtk_tree_model_get(model, &iter, VARIABLE_COLUMN, &exp, -1);
1438 return exp;
1441 gchar*
1442 debug_tree_find_variable_value (DebugTree *tree, const gchar *name)
1444 GtkTreeModel *model;
1445 GtkTreeIter iter;
1447 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1449 if (gtk_tree_model_get_iter_first (model, &iter))
1451 gchar *exp;
1452 gchar *value;
1455 gtk_tree_model_get(model, &iter, VARIABLE_COLUMN, &exp,
1456 VALUE_COLUMN, &value, -1);
1458 if (strcmp (exp, name) == 0)
1460 return value;
1462 } while (gtk_tree_model_iter_next (model, &iter));
1465 return NULL;
1468 /* Debugging functions
1469 *---------------------------------------------------------------------------*/
1471 static void
1472 debug_tree_dump_iter (GtkTreeModel *model, GtkTreeIter *iter, guint indent)
1474 gchar *expression;
1475 gchar *value;
1476 gchar *type;
1477 DmaVariableData *node;
1478 GtkTreeIter child;
1479 gboolean valid;
1481 gtk_tree_model_get (model, iter,
1482 VARIABLE_COLUMN, &expression,
1483 VALUE_COLUMN, &value,
1484 TYPE_COLUMN, &type,
1485 DTREE_ENTRY_COLUMN, &node,
1486 -1);
1487 if (node != NULL)
1489 g_message ("%*s %s | %s | %s | %s | %d%d%d%d%d", indent, "",
1490 expression, value, type, node->name,
1491 node->modified, node->changed, node->exited, node->deleted, node->auto_update);
1493 else
1495 g_message ("%*s %s | %s | %s | %s | %c%c%c%c%c", indent, "",
1496 expression, value, type, "???",
1497 '?','?','?','?','?');
1499 g_free (expression);
1500 g_free (value);
1501 g_free (type);
1503 for (valid = gtk_tree_model_iter_children (model, &child, iter);
1504 valid;
1505 valid = gtk_tree_model_iter_next (model, &child))
1507 debug_tree_dump_iter (model, &child, indent + 4);
1511 void
1512 debug_tree_dump (void)
1514 GList *list;
1516 for (list = g_list_first (gTreeList); list != NULL; list = g_list_next (list))
1518 DebugTree* tree = (DebugTree*)list->data;
1520 GtkTreeModel* model;
1521 GtkTreeIter iter;
1522 gboolean valid;
1524 model = debug_tree_get_model (tree);
1525 g_message ("Tree model %p MCEDU", model);
1526 for (valid = gtk_tree_model_get_iter_first (model, &iter);
1527 valid;
1528 valid = gtk_tree_model_iter_next (model, &iter))
1530 debug_tree_dump_iter (model, &iter, 4);
1535 /* Constructor & Destructor
1536 *---------------------------------------------------------------------------*/
1538 /* return a pointer to a newly allocated DebugTree object */
1539 DebugTree *
1540 debug_tree_new_with_view (AnjutaPlugin *plugin, GtkTreeView *view)
1542 DebugTree *tree = g_new0 (DebugTree, 1);
1544 tree->plugin = plugin;
1545 tree->view = debug_tree_create(tree, view);
1546 tree->auto_expand = FALSE;
1548 /* Add this tree in list */
1549 gTreeList = g_list_prepend (gTreeList, tree);
1551 /* Connect signal */
1552 g_signal_connect(GTK_TREE_VIEW (tree->view), "row_expanded", G_CALLBACK (on_treeview_row_expanded), tree);
1555 return tree;
1559 /* return a pointer to a newly allocated DebugTree object */
1560 DebugTree *
1561 debug_tree_new (AnjutaPlugin* plugin)
1563 return debug_tree_new_with_view (plugin, NULL);
1566 /* DebugTree destructor */
1567 void
1568 debug_tree_free (DebugTree * tree)
1570 g_return_if_fail (tree);
1572 debug_tree_remove_all (tree);
1574 /* Remove from list */
1575 gTreeList = g_list_remove (gTreeList, tree);
1577 g_signal_handlers_disconnect_by_func (GTK_TREE_VIEW (tree->view),
1578 G_CALLBACK (on_treeview_row_expanded), tree);
1580 gtk_widget_destroy (tree->view);
1583 g_free (tree);