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 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
24 #include "stack_trace.h"
31 #include <glib/gi18n.h>
35 #include <libanjuta/resources.h>
36 #include <libanjuta/anjuta-debug.h>
37 #include <libanjuta/interfaces/ianjuta-editor.h>
38 #include <libanjuta/interfaces/ianjuta-document-manager.h>
40 #include "utilities.h"
44 #define ANJUTA_PIXMAP_POINTER PACKAGE_PIXMAPS_DIR"/pointer.png"
48 DebugManagerPlugin
*plugin
;
49 DmaDebuggerQueue
*debugger
;
51 GtkActionGroup
*action_group
;
56 gulong changed_handler
;
58 GtkTreeView
*treeview
;
60 GtkWidget
*scrolledwindow
;
63 typedef struct _StackPacket StackPacket
;
73 STACK_TRACE_ACTIVE_COLUMN
,
74 STACK_TRACE_THREAD_COLUMN
,
75 STACK_TRACE_FRAME_COLUMN
,
76 STACK_TRACE_FILE_COLUMN
,
77 STACK_TRACE_LINE_COLUMN
,
78 STACK_TRACE_FUNC_COLUMN
,
79 STACK_TRACE_ADDR_COLUMN
,
80 STACK_TRACE_ARGS_COLUMN
,
81 STACK_TRACE_DIRTY_COLUMN
,
82 STACK_TRACE_URI_COLUMN
,
83 STACK_TRACE_COLOR_COLUMN
,
88 *---------------------------------------------------------------------------*/
91 get_current_iter (GtkTreeView
*view
, GtkTreeIter
* iter
)
93 GtkTreeSelection
*selection
;
95 selection
= gtk_tree_view_get_selection (view
);
96 return gtk_tree_selection_get_selected (selection
, NULL
, iter
);
100 * returns TRUE if a frame is selected
103 get_current_frame_and_thread (StackTrace
* st
, guint
*frame
, gint
*thread
)
107 if (get_current_iter (st
->treeview
, &iter
))
113 model
= gtk_tree_view_get_model (st
->treeview
);
115 if (gtk_tree_model_iter_parent (model
, &parent
, &iter
))
117 gtk_tree_model_get (model
, &iter
, STACK_TRACE_FRAME_COLUMN
, &str
, -1);
120 *frame
= strtoul (str
, NULL
, 10);
123 gtk_tree_model_get (model
, &parent
, STACK_TRACE_THREAD_COLUMN
, &str
, -1);
127 gtk_tree_model_get (model
, &iter
, STACK_TRACE_THREAD_COLUMN
, &str
, -1);
129 *thread
= (str
!= NULL
) ? strtoul (str
, NULL
, 10) : 0;
132 return thread
!= 0 ? TRUE
: FALSE
;
141 my_gtk_tree_model_get_iter_last(GtkTreeModel
*model
, GtkTreeIter
*parent
, GtkTreeIter
*last
)
146 exist
= gtk_tree_model_iter_children(model
, &iter
, parent
);
147 if (!exist
) return FALSE
;
152 exist
= gtk_tree_model_iter_next(model
, &iter
);
160 my_gtk_tree_model_iter_prev(GtkTreeModel
*model
, GtkTreeIter
*iter
)
165 path
= gtk_tree_model_get_path (model
, iter
);
166 exist
= gtk_tree_path_prev (path
);
169 exist
= gtk_tree_model_get_iter (model
, iter
, path
);
171 gtk_tree_path_free (path
);
177 my_gtk_tree_iter_compare(GtkTreeModel
*model
, GtkTreeIter
*itera
, GtkTreeIter
*iterb
)
183 patha
= gtk_tree_model_get_path (model
, itera
);
184 pathb
= gtk_tree_model_get_path (model
, iterb
);
186 comp
= gtk_tree_path_compare (patha
, pathb
);
188 gtk_tree_path_free (patha
);
189 gtk_tree_path_free (pathb
);
195 find_thread (GtkTreeModel
*model
, GtkTreeIter
*iter
, guint thread
)
199 for (found
= gtk_tree_model_get_iter_first (model
, iter
); found
; found
= gtk_tree_model_iter_next (model
, iter
))
204 gtk_tree_model_get (model
, iter
, STACK_TRACE_THREAD_COLUMN
, &str
, -1);
207 id
= strtoul (str
, NULL
, 10);
209 if (id
== thread
) break;
217 *---------------------------------------------------------------------------*/
220 set_stack_frame (StackTrace
*self
, guint frame
, gint thread
)
227 model
= gtk_tree_view_get_model (self
->treeview
);
229 /* Clear old pointer */
230 valid
= find_thread (model
, &parent
, self
->current_thread
);
233 if (gtk_tree_model_iter_nth_child (model
, &iter
, &parent
, self
->current_frame
))
235 /* clear pixmap on the previous active frame */
236 gtk_tree_store_set (GTK_TREE_STORE (model
), &iter
,
237 STACK_TRACE_ACTIVE_COLUMN
, NULL
, -1);
241 if (self
->current_thread
!= thread
)
243 self
->current_thread
= thread
;
244 valid
= find_thread (model
, &parent
, self
->current_thread
);
247 /* Set pointer on current frame if possible */
248 self
->current_frame
= frame
;
251 if (gtk_tree_model_iter_nth_child (model
, &iter
, &parent
, self
->current_frame
))
253 GdkPixbuf
*pointer_pix
= gdk_pixbuf_new_from_file (ANJUTA_PIXMAP_POINTER
, NULL
);
255 gtk_tree_store_set (GTK_TREE_STORE(model
), &iter
,
256 STACK_TRACE_ACTIVE_COLUMN
, pointer_pix
,
258 g_object_unref (pointer_pix
);
264 on_stack_trace_updated (const GList
*stack
, gpointer user_data
, GError
*error
)
266 StackPacket
*packet
= (StackPacket
*)user_data
;
276 g_return_if_fail (packet
!= NULL
);
279 thread
= packet
->thread
;
280 if (packet
->unblock
) g_signal_handler_unblock (self
->plugin
, self
->changed_handler
);
281 g_slice_free (StackPacket
, packet
);
283 if (error
!= NULL
) return;
285 model
= gtk_tree_view_get_model (self
->treeview
);
287 if (!find_thread (model
, &parent
, thread
)) return;
289 /* Check if there are already some data */
290 exist
= my_gtk_tree_model_get_iter_last (GTK_TREE_MODEL (model
), &parent
, &iter
);
295 gtk_tree_model_get_value(model
, &iter
, STACK_TRACE_FRAME_COLUMN
, &val
);
296 if (!G_IS_VALUE (&val
))
298 /* Remove dummy child */
299 gtk_tree_store_remove (GTK_TREE_STORE (model
), &iter
);
305 for (node
= (const GList
*)g_list_last((GList
*)stack
); node
!= NULL
; node
= node
->prev
)
307 IAnjutaDebuggerFrame
*frame
;
314 frame
= (IAnjutaDebuggerFrame
*)node
->data
;
318 /* Check if it's the same stack frame */
324 gtk_tree_model_get (GTK_TREE_MODEL (model
), &iter
,
325 STACK_TRACE_ADDR_COLUMN
, &adr_str
,
326 STACK_TRACE_LINE_COLUMN
, &line_str
,
327 STACK_TRACE_ARGS_COLUMN
, &args
,
329 address
= adr_str
!= NULL
? strtoul (adr_str
, NULL
, 0) : 0;
330 line
= line_str
!= NULL
? strtoul (line_str
, NULL
, 10) : 0;
331 same
= (address
== frame
->address
) && (line
== frame
->line
);
332 if ((args
== NULL
) || (frame
->args
== NULL
))
334 same
= same
&& (args
== frame
->args
);
338 same
= same
&& (strcmp (args
, frame
->args
) == 0);
345 /* Same frame, just change the color */
346 frame_str
= g_strdup_printf ("%d", frame
->level
);
347 gtk_tree_store_set (GTK_TREE_STORE (model
), &iter
,
348 STACK_TRACE_ACTIVE_COLUMN
, NULL
,
349 STACK_TRACE_FRAME_COLUMN
, frame_str
,
350 STACK_TRACE_COLOR_COLUMN
, "black", -1);
353 /* Check previous frame */
354 exist
= my_gtk_tree_model_iter_prev (model
, &iter
);
355 if (!exist
|| (node
->prev
!= NULL
))
357 /* Last frame or Upper frame still exist */
360 /* Upper frame do not exist, remove all them */
363 /* New frame, remove all previous frame */
366 gtk_tree_model_iter_children (model
, &first
, &parent
);
367 while (my_gtk_tree_iter_compare (model
, &first
, &iter
) < 0)
369 gtk_tree_store_remove (GTK_TREE_STORE (model
), &first
);
371 gtk_tree_store_remove (GTK_TREE_STORE (model
), &first
);
383 gtk_tree_store_prepend (GTK_TREE_STORE (model
), &iter
, &parent
);
385 frame_str
= g_strdup_printf ("%d", frame
->level
);
386 adr_str
= g_strdup_printf ("0x%lx", frame
->address
);
389 if (g_path_is_absolute (frame
->file
))
391 GFile
*gio_file
= g_file_new_for_path (frame
->file
);
392 uri
= g_file_get_uri (gio_file
);
393 file
= strrchr(frame
->file
, G_DIR_SEPARATOR
) + 1;
394 g_object_unref (gio_file
);
401 line_str
= g_strdup_printf ("%d", frame
->line
);
406 file
= frame
->library
;
410 gtk_tree_store_set(GTK_TREE_STORE (model
), &iter
,
411 STACK_TRACE_ACTIVE_COLUMN
, NULL
,
412 STACK_TRACE_FRAME_COLUMN
, frame_str
,
413 STACK_TRACE_FILE_COLUMN
, file
,
414 STACK_TRACE_LINE_COLUMN
, line_str
,
415 STACK_TRACE_FUNC_COLUMN
, frame
->function
,
416 STACK_TRACE_ADDR_COLUMN
, adr_str
,
417 STACK_TRACE_ARGS_COLUMN
, frame
->args
,
418 STACK_TRACE_URI_COLUMN
, uri
,
419 STACK_TRACE_COLOR_COLUMN
, "red",
426 gtk_tree_store_set(GTK_TREE_STORE (model
), &parent
,
427 STACK_TRACE_DIRTY_COLUMN
, FALSE
,
430 /* Expand and show new path */
431 path
= gtk_tree_model_get_path (model
, &parent
);
432 gtk_tree_view_expand_row (self
->treeview
, path
, FALSE
);
433 if (self
->current_thread
== thread
)
435 set_stack_frame (self
, self
->current_frame
, self
->current_thread
);
436 gtk_tree_view_scroll_to_cell (self
->treeview
, path
, NULL
, FALSE
, 0, 0);
438 gtk_tree_path_free (path
);
443 list_stack_frame (StackTrace
*self
, guint thread
, gboolean update
)
450 model
= gtk_tree_view_get_model (self
->treeview
);
455 found
= find_thread (model
, &iter
, thread
);
458 /* Check if stack trace need to be updated */
459 gtk_tree_model_get(model
, &iter
, STACK_TRACE_DIRTY_COLUMN
, &dirty
, -1);
463 /* Update stack trace */
464 if (update
|| !found
|| dirty
)
468 if (thread
!= self
->current_thread
)
470 /* Change current thread temporarily */
471 dma_queue_set_thread (self
->debugger
, thread
);
472 g_signal_handler_block (self
->plugin
, self
->changed_handler
);
474 packet
= g_slice_new (StackPacket
);
475 packet
->thread
= thread
;
477 packet
->scroll
= update
;
478 packet
->unblock
= thread
!= self
->current_thread
;
479 dma_queue_list_frame (self
->debugger
,
480 (IAnjutaDebuggerCallback
)on_stack_trace_updated
,
482 if (thread
!= self
->current_thread
) dma_queue_set_thread (self
->debugger
, self
->current_thread
);
487 on_thread_updated (const GList
*threads
, gpointer user_data
)
489 StackTrace
*self
= (StackTrace
*)user_data
;
496 model
= gtk_tree_view_get_model (self
->treeview
);
498 /* Remove completed threads */
499 new_threads
= g_list_copy ((GList
*)threads
);
500 valid
= gtk_tree_model_get_iter_first (model
, &iter
);
506 gtk_tree_model_get(model
, &iter
, STACK_TRACE_THREAD_COLUMN
, &str
, -1);
507 thread
= (str
!= NULL
) ? strtoul (str
, NULL
, 10) : 0;
510 for (node
= new_threads
; node
!= NULL
; node
= node
->next
)
512 if (((IAnjutaDebuggerFrame
*)node
->data
)->thread
== thread
) break;
519 /* Thread still existing */
520 new_threads
= g_list_delete_link (new_threads
, node
);
521 /* Set content as dirty */
522 gtk_tree_store_set(GTK_TREE_STORE (model
), &iter
,
523 STACK_TRACE_DIRTY_COLUMN
, TRUE
,
524 STACK_TRACE_COLOR_COLUMN
, "black",
527 /* Update stack frame if it is visible */
528 path
= gtk_tree_model_get_path (model
, &iter
);
529 if (gtk_tree_view_row_expanded (self
->treeview
, path
))
531 list_stack_frame (self
, thread
, TRUE
);
533 gtk_tree_path_free (path
);
535 valid
= gtk_tree_model_iter_next (model
, &iter
);
539 /* Thread completed */
540 valid
= gtk_tree_store_remove (GTK_TREE_STORE (model
), &iter
);
545 /* Add new threads */
546 while (new_threads
!= NULL
)
551 str
= g_strdup_printf ("%d", ((IAnjutaDebuggerFrame
*)new_threads
->data
)->thread
);
552 gtk_tree_store_append (GTK_TREE_STORE (model
), &iter
, NULL
);
553 gtk_tree_store_set(GTK_TREE_STORE (model
), &iter
,
554 STACK_TRACE_THREAD_COLUMN
, str
,
555 STACK_TRACE_DIRTY_COLUMN
, TRUE
,
556 STACK_TRACE_COLOR_COLUMN
, "red",
560 /* Add a dummy child, to get the row expander */
561 gtk_tree_store_append (GTK_TREE_STORE (model
), &child
, &iter
);
563 new_threads
= g_list_delete_link (new_threads
, new_threads
);
568 list_threads (StackTrace
*self
)
570 dma_queue_list_thread (
572 (IAnjutaDebuggerCallback
)on_thread_updated
,
578 /* Callback functions
579 *---------------------------------------------------------------------------*/
582 on_stack_frame_set_activate (GtkAction
*action
, gpointer user_data
)
588 self
= (StackTrace
*) user_data
;
590 if (get_current_frame_and_thread (self
, &frame
, &thread
))
592 if (thread
!= self
->current_thread
)
594 dma_queue_set_thread (self
->debugger
, thread
);
595 dma_queue_set_frame (self
->debugger
, frame
);
596 set_stack_frame (self
, frame
, thread
);
597 list_stack_frame (self
, thread
, FALSE
);
599 else if (frame
!= self
->current_frame
)
601 dma_queue_set_frame (self
->debugger
, frame
);
602 set_stack_frame (self
, frame
, thread
);
603 list_stack_frame (self
, thread
, FALSE
);
609 on_stack_view_source_activate (GtkAction
*action
, gpointer user_data
)
612 GtkTreeSelection
*selection
;
621 StackTrace
* st
= (StackTrace
*) user_data
;
624 selection
= gtk_tree_view_get_selection (view
);
625 if (!gtk_tree_selection_get_selected (selection
, &model
, &iter
))
628 /* get the frame info */
629 gtk_tree_model_get (model
, &iter
,
630 STACK_TRACE_URI_COLUMN
, &uri
,
631 STACK_TRACE_LINE_COLUMN
, &line_str
,
632 STACK_TRACE_ADDR_COLUMN
, &adr_str
,
635 address
= adr_str
!= NULL
? strtoul (adr_str
, NULL
, 0) : 0;
636 line
= line_str
!= NULL
? strtoul (line_str
, NULL
, 0) : 0;
637 g_signal_emit_by_name (st
->plugin
, "location-changed", address
, uri
, line
);
644 on_got_stack_trace (const gchar
*trace
, gpointer user_data
, GError
*error
)
646 StackTrace
* st
= (StackTrace
*) user_data
;
647 IAnjutaDocumentManager
*docman
;
649 docman
= anjuta_shell_get_interface (ANJUTA_PLUGIN (st
->plugin
)->shell
, IAnjutaDocumentManager
, NULL
);
652 ianjuta_document_manager_add_buffer (docman
, "Stack Trace", trace
, NULL
);
657 on_stack_get_trace (GtkAction
*action
, gpointer user_data
)
659 StackTrace
* st
= (StackTrace
*) user_data
;
661 /* Ask debugger to get all frame data */
662 dma_queue_dump_stack_trace (
664 (IAnjutaDebuggerCallback
)on_got_stack_trace
,
669 on_stack_trace_row_activated (GtkTreeView
*treeview
,
671 GtkTreeViewColumn
*arg2
,
674 on_stack_frame_set_activate (NULL
, st
);
678 on_stack_trace_row_expanded (GtkTreeView
*treeview
,
687 model
= gtk_tree_view_get_model (treeview
);
689 gtk_tree_model_get (model
, iter
, STACK_TRACE_THREAD_COLUMN
, &str
, -1);
690 thread
= (str
!= NULL
) ? strtoul (str
, NULL
, 10) : 0;
693 list_stack_frame (st
, thread
, FALSE
);
697 on_stack_trace_button_press (GtkWidget
*widget
, GdkEventButton
*bevent
, gpointer user_data
)
699 StackTrace
*st
= (StackTrace
*) user_data
;
701 if ((bevent
->type
== GDK_BUTTON_PRESS
) && (bevent
->button
== 3))
703 /* Right mouse click */
704 g_return_val_if_fail (st
->menu
!= NULL
, FALSE
);
705 gtk_menu_popup (GTK_MENU (st
->menu
), NULL
, NULL
, NULL
, NULL
,
706 bevent
->button
, bevent
->time
);
708 else if ((bevent
->type
== GDK_2BUTTON_PRESS
) && (bevent
->button
== 1))
710 /* Double left mouse click */
711 on_stack_view_source_activate (NULL
, user_data
);
718 *---------------------------------------------------------------------------*/
720 static GtkActionEntry actions_stack_trace
[] = {
722 "ActionDmaSetCurrentFrame", /* Action name */
723 NULL
, /* Stock icon, if any */
724 N_("Set current frame"), /* Display label */
725 NULL
, /* short-cut */
727 G_CALLBACK (on_stack_frame_set_activate
) /* action callback */
730 "ActionDmaJumpToFrame",
735 G_CALLBACK (on_stack_view_source_activate
)
738 "ActionDmaDumpStackTrace",
740 N_("Get Stack trace"),
743 G_CALLBACK (on_stack_get_trace
)
748 create_stack_trace_gui(StackTrace
*st
)
751 GtkTreeSelection
*selection
;
752 GtkTreeViewColumn
*column
;
753 GtkCellRenderer
*renderer
;
756 g_return_if_fail (st
->scrolledwindow
== NULL
);
758 /* Create tree view */
759 model
= GTK_TREE_MODEL(gtk_tree_store_new (STACK_TRACE_N_COLUMNS
,
771 st
->treeview
= GTK_TREE_VIEW (gtk_tree_view_new_with_model (model
));
772 g_object_unref (G_OBJECT (model
));
774 selection
= gtk_tree_view_get_selection (st
->treeview
);
775 gtk_tree_selection_set_mode (selection
, GTK_SELECTION_SINGLE
);
778 column
= gtk_tree_view_column_new ();
779 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
780 gtk_tree_view_column_set_title (column
, _("Active"));
781 renderer
= gtk_cell_renderer_pixbuf_new ();
782 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
783 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
784 STACK_TRACE_ACTIVE_COLUMN
);
785 gtk_tree_view_append_column (st
->treeview
, column
);
787 column
= gtk_tree_view_column_new ();
788 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
789 gtk_tree_view_column_set_title (column
, _("Thread"));
790 renderer
= gtk_cell_renderer_text_new ();
791 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
792 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
793 STACK_TRACE_THREAD_COLUMN
);
794 gtk_tree_view_column_add_attribute (column
, renderer
, "foreground",
795 STACK_TRACE_COLOR_COLUMN
);
796 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
797 gtk_tree_view_append_column (st
->treeview
, column
);
798 gtk_tree_view_set_expander_column (st
->treeview
,
801 column
= gtk_tree_view_column_new ();
802 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
803 gtk_tree_view_column_set_title (column
, _("Frame"));
804 renderer
= gtk_cell_renderer_text_new ();
805 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
806 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
807 STACK_TRACE_FRAME_COLUMN
);
808 gtk_tree_view_column_add_attribute (column
, renderer
, "foreground",
809 STACK_TRACE_COLOR_COLUMN
);
810 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
811 gtk_tree_view_append_column (st
->treeview
, column
);
813 column
= gtk_tree_view_column_new ();
814 renderer
= gtk_cell_renderer_text_new ();
815 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
816 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
817 STACK_TRACE_FILE_COLUMN
);
818 gtk_tree_view_column_add_attribute (column
, renderer
, "foreground",
819 STACK_TRACE_COLOR_COLUMN
);
820 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
821 gtk_tree_view_column_set_title (column
, _("File"));
822 gtk_tree_view_append_column (st
->treeview
, column
);
824 column
= gtk_tree_view_column_new ();
825 renderer
= gtk_cell_renderer_text_new ();
826 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
827 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
828 STACK_TRACE_LINE_COLUMN
);
829 gtk_tree_view_column_add_attribute (column
, renderer
, "foreground",
830 STACK_TRACE_COLOR_COLUMN
);
831 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
832 gtk_tree_view_column_set_title (column
, _("Line"));
833 gtk_tree_view_append_column (st
->treeview
, column
);
835 column
= gtk_tree_view_column_new ();
836 renderer
= gtk_cell_renderer_text_new ();
837 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
838 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
839 STACK_TRACE_FUNC_COLUMN
);
840 gtk_tree_view_column_add_attribute (column
, renderer
, "foreground",
841 STACK_TRACE_COLOR_COLUMN
);
842 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
843 gtk_tree_view_column_set_title (column
, _("Function"));
844 gtk_tree_view_append_column (st
->treeview
, column
);
846 if (dma_debugger_queue_is_supported (st
->debugger
, HAS_MEMORY
))
848 /* Display address only if debugger has such concept */
849 column
= gtk_tree_view_column_new ();
850 renderer
= gtk_cell_renderer_text_new ();
851 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
852 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
853 STACK_TRACE_ADDR_COLUMN
);
854 gtk_tree_view_column_add_attribute (column
, renderer
, "foreground",
855 STACK_TRACE_COLOR_COLUMN
);
856 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
857 gtk_tree_view_column_set_title (column
, _("Address"));
858 gtk_tree_view_append_column (st
->treeview
, column
);
861 column
= gtk_tree_view_column_new ();
862 renderer
= gtk_cell_renderer_text_new ();
863 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
864 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
865 STACK_TRACE_ARGS_COLUMN
);
866 gtk_tree_view_column_add_attribute (column
, renderer
, "foreground",
867 STACK_TRACE_COLOR_COLUMN
);
868 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
869 gtk_tree_view_column_set_title (column
, _("Arguments"));
870 gtk_tree_view_append_column (st
->treeview
, column
);
872 /* Create popup menu */
873 ui
= anjuta_shell_get_ui (ANJUTA_PLUGIN(st
->plugin
)->shell
, NULL
);
874 st
->menu
= GTK_MENU (gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui
), "/PopupStack"));
877 g_signal_connect (st
->treeview
, "button-press-event", G_CALLBACK (on_stack_trace_button_press
), st
);
878 g_signal_connect (st
->treeview
, "row-activated", G_CALLBACK (on_stack_trace_row_activated
), st
);
879 g_signal_connect (st
->treeview
, "row-expanded", G_CALLBACK (on_stack_trace_row_expanded
), st
);
881 /* Add stack window */
882 st
->scrolledwindow
= gtk_scrolled_window_new (NULL
, NULL
);
883 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (st
->scrolledwindow
),
884 GTK_POLICY_AUTOMATIC
,
885 GTK_POLICY_AUTOMATIC
);
886 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (st
->scrolledwindow
),
888 gtk_container_add (GTK_CONTAINER (st
->scrolledwindow
),
889 GTK_WIDGET (st
->treeview
));
890 gtk_widget_show_all (st
->scrolledwindow
);
892 anjuta_shell_add_widget (ANJUTA_PLUGIN(st
->plugin
)->shell
,
894 "AnjutaDebuggerStack", _("Stack"),
895 "gdb-stack-icon", ANJUTA_SHELL_PLACEMENT_BOTTOM
,
901 destroy_stack_trace_gui (StackTrace
*st
)
903 if (st
->scrolledwindow
!= NULL
)
905 gtk_widget_destroy (st
->scrolledwindow
);
906 st
->scrolledwindow
= NULL
;
911 on_frame_changed (StackTrace
*self
, guint frame
, gint thread
)
913 set_stack_frame (self
, frame
, thread
);
914 list_stack_frame (self
, thread
, FALSE
);
918 on_program_moved (StackTrace
*self
, guint pid
, gint thread
)
920 set_stack_frame (self
, 0, thread
);
923 list_stack_frame (self
, thread
, TRUE
);
927 on_program_exited (StackTrace
*self
)
929 g_signal_handlers_disconnect_by_func (self
->plugin
, G_CALLBACK (on_program_exited
), self
);
930 g_signal_handlers_disconnect_by_func (self
->plugin
, G_CALLBACK (on_program_moved
), self
);
931 g_signal_handlers_disconnect_by_func (self
->plugin
, G_CALLBACK (on_frame_changed
), self
);
933 destroy_stack_trace_gui (self
);
937 on_program_started (StackTrace
*self
)
939 create_stack_trace_gui (self
);
940 self
->current_thread
= 0;
941 self
->current_frame
= 0;
943 g_signal_connect_swapped (self
->plugin
, "program-exited", G_CALLBACK (on_program_exited
), self
);
944 g_signal_connect_swapped (self
->plugin
, "program-moved", G_CALLBACK (on_program_moved
), self
);
945 self
->changed_handler
= g_signal_connect_swapped (self
->plugin
, "frame-changed", G_CALLBACK (on_frame_changed
), self
);
949 *---------------------------------------------------------------------------*/
951 /* Constructor & Destructor
952 *---------------------------------------------------------------------------*/
955 stack_trace_new (DebugManagerPlugin
*plugin
)
960 st
= g_new0 (StackTrace
, 1);
961 if (st
== NULL
) return NULL
;
964 st
->debugger
= dma_debug_manager_get_queue (plugin
);
966 /* Register actions */
967 ui
= anjuta_shell_get_ui (ANJUTA_PLUGIN(st
->plugin
)->shell
, NULL
);
969 anjuta_ui_add_action_group_entries (ui
, "ActionGroupStack",
970 _("Stack frame operations"),
972 G_N_ELEMENTS (actions_stack_trace
),
973 GETTEXT_PACKAGE
, TRUE
, st
);
975 g_signal_connect_swapped (st
->plugin
, "program-started", G_CALLBACK (on_program_started
), st
);
981 stack_trace_free (StackTrace
* st
)
985 g_return_if_fail (st
!= NULL
);
987 /* Disconnect from debugger */
988 g_signal_handlers_disconnect_matched (st
->plugin
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, st
);
990 /* Remove menu actions */
991 ui
= anjuta_shell_get_ui (ANJUTA_PLUGIN (st
->plugin
)->shell
, NULL
);
992 anjuta_ui_remove_action_group (ui
, st
->action_group
);
995 destroy_stack_trace_gui (st
);