1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) 2007 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
22 * Handle breakpoints, mainly the graphical interface as the communication
23 * with the debugger is handled by the corresponding debugger plugin. The
24 * grahical interface includes:
25 * - A dialog including a tree view with all breakpoints
26 * - Several associated dialog (create a new breakpoints, confirmation...)
27 * - The markers in the editor plugin
29 * The list of breakpoints is kept in the tree view (GtkTreeModel).
31 * The AnjutaDebuggerBreakpoint object is used to communicate with the debugger plugin,
32 * it includes all useful information for a breakpoint. Part of this structure
33 * is filled by the debugger plugin, another part by the debug manager plugin.
34 * This object is normally created and destroyed by the debug manager, but
35 * the debugger plugin could create one too (but never destroy it).
37 * The BreakpointItem object includes a AnjutaDebuggerBreakpoint and adds all useful
38 * information for the graphical interface (pointer to the editor...)
39 *---------------------------------------------------------------------------*/
53 #include <libgnomevfs/gnome-vfs-utils.h>
55 #include <libanjuta/resources.h>
56 #include <libanjuta/anjuta-debug.h>
57 #include <libanjuta/interfaces/ianjuta-document-manager.h>
58 #include <libanjuta/interfaces/ianjuta-markable.h>
59 #include <libanjuta/interfaces/ianjuta-file.h>
60 #include <libanjuta/interfaces/ianjuta-debugger-breakpoint.h>
62 #include "breakpoints.h"
63 #include "utilities.h"
66 /* Markers definition */
67 #define BREAKPOINT_ENABLED IANJUTA_MARKABLE_BREAKPOINT_ENABLED
68 #define BREAKPOINT_DISABLED IANJUTA_MARKABLE_BREAKPOINT_DISABLED
69 #define BREAKPOINT_NONE -1
71 typedef struct _BreakpointItem BreakpointItem
;
72 typedef struct _BreakpointPacket BreakpointPacket
;
75 struct _BreakpointItem
77 IAnjutaDebuggerBreakpointItem bp
; /* Breakpoint data */
80 gint handle
; /* Handle to mark in editor */
81 IAnjutaEditor
*editor
;
84 gint changed
; /* Bit field tagging change in breakpoint */
92 struct _BreakpointsDBase
94 DebugManagerPlugin
*plugin
;
95 DmaDebuggerQueue
*debugger
;
100 gchar
*cond_history
, *loc_history
;
104 GtkTreeView
*treeview
;
105 GtkWidget
*add_button
;
106 GtkWidget
*remove_button
;
107 GtkWidget
*jumpto_button
;
108 GtkWidget
*properties_button
;
109 GtkWidget
*removeall_button
;
110 GtkWidget
*enableall_button
;
111 GtkWidget
*disableall_button
;
114 GtkActionGroup
*debugger_group
;
115 GtkActionGroup
*permanent_group
;
117 /* Editor watch id */
135 *---------------------------------------------------------------------------*/
137 /* BreakItem functions
138 *---------------------------------------------------------------------------*/
141 breakpoint_item_update_from_debugger (BreakpointItem
*bi
, const IAnjutaDebuggerBreakpointItem
* bp
)
143 if (bp
== NULL
) return;
146 if (bp
->type
& IANJUTA_DEBUGGER_BREAKPOINT_REMOVED
)
148 bi
->bp
.type
|= IANJUTA_DEBUGGER_BREAKPOINT_REMOVED
;
151 if (bp
->type
& IANJUTA_DEBUGGER_BREAKPOINT_ON_LINE
)
153 bi
->bp
.type
|= IANJUTA_DEBUGGER_BREAKPOINT_ON_LINE
;
154 g_free (bi
->bp
.file
);
155 bi
->bp
.file
= g_strdup (bp
->file
);
156 bi
->bp
.line
= bp
->line
;
157 if ((bi
->uri
== NULL
) && (g_path_is_absolute (bp
->file
)))
158 bi
->uri
= gnome_vfs_get_uri_from_local_path (bp
->file
);
160 if (bp
->type
& IANJUTA_DEBUGGER_BREAKPOINT_ON_FUNCTION
)
162 bi
->bp
.type
|= IANJUTA_DEBUGGER_BREAKPOINT_ON_FUNCTION
;
163 g_free (bi
->bp
.function
);
164 bi
->bp
.function
= g_strdup (bp
->function
);
166 if (bp
->type
& IANJUTA_DEBUGGER_BREAKPOINT_ON_ADDRESS
)
168 bi
->bp
.type
|= IANJUTA_DEBUGGER_BREAKPOINT_ON_ADDRESS
;
169 bi
->bp
.address
= bp
->address
;
171 if (bp
->type
& IANJUTA_DEBUGGER_BREAKPOINT_WITH_TIME
)
173 bi
->bp
.times
= bp
->times
;
175 if (bp
->type
& IANJUTA_DEBUGGER_BREAKPOINT_WITH_TEMPORARY
)
177 bi
->bp
.temporary
= bp
->temporary
;
179 if ((bp
->type
& IANJUTA_DEBUGGER_BREAKPOINT_WITH_ENABLE
) &&
180 !(bi
->changed
& IANJUTA_DEBUGGER_BREAKPOINT_WITH_ENABLE
))
182 bi
->bp
.enable
= bp
->enable
;
184 if ((bp
->type
& IANJUTA_DEBUGGER_BREAKPOINT_WITH_CONDITION
) &&
185 !(bi
->changed
& IANJUTA_DEBUGGER_BREAKPOINT_WITH_CONDITION
))
187 g_free (bi
->bp
.condition
);
188 bi
->bp
.condition
= bp
->condition
== NULL
? NULL
: g_strdup (bp
->condition
);
190 if ((bp
->type
& IANJUTA_DEBUGGER_BREAKPOINT_WITH_IGNORE
) &&
191 !(bi
->changed
& IANJUTA_DEBUGGER_BREAKPOINT_WITH_IGNORE
))
193 bi
->bp
.ignore
= bp
->ignore
;
198 breakpoint_item_ref (BreakpointItem
*bi
)
204 breakpoint_item_unref (BreakpointItem
*bi
)
206 g_return_val_if_fail (bi
!= NULL
, FALSE
);
209 if (bi
->ref
> 0) return FALSE
;
211 /* Remove from list */
212 gtk_list_store_remove (bi
->bd
->model
, &bi
->iter
);
214 if (bi
->editor
!= NULL
)
216 g_object_remove_weak_pointer (G_OBJECT (bi
->editor
), (gpointer
*)(gpointer
)&bi
->editor
);
220 g_free ((char *)bi
->bp
.file
);
222 g_free ((char *)bi
->bp
.function
);
223 bi
->bp
.function
= NULL
;
224 g_free ((char *)bi
->bp
.condition
);
225 bi
->bp
.condition
= NULL
;
230 /* BreakItem constructor & destructor
231 *---------------------------------------------------------------------------*/
233 static BreakpointItem
*
234 breakpoint_item_new (BreakpointsDBase
*bd
)
237 bi
= g_new0 (BreakpointItem
, 1);
245 gtk_list_store_append (bd
->model
, &bi
->iter
);
246 gtk_list_store_set (bd
->model
, &bi
->iter
, DATA_COLUMN
, bi
, -1);
251 static BreakpointItem
*
252 breakpoint_item_new_from_uri (BreakpointsDBase
*bd
, const gchar
* uri
, guint line
, gboolean enable
)
256 g_return_val_if_fail (uri
!= NULL
, NULL
);
258 bi
= breakpoint_item_new (bd
);
260 bi
->uri
= g_strdup (uri
);
261 bi
->bp
.type
= IANJUTA_DEBUGGER_BREAKPOINT_ON_LINE
| IANJUTA_DEBUGGER_BREAKPOINT_WITH_ENABLE
;
262 bi
->bp
.file
= gnome_vfs_get_local_path_from_uri (uri
);
264 bi
->bp
.enable
= enable
;
269 static BreakpointItem
*
270 breakpoint_item_new_from_string (BreakpointsDBase
*bd
, const gchar
* string
, const gchar
* uri
)
274 bi
= breakpoint_item_new (bd
);
278 /* break at address */
279 if ((string
[1] == '0') && ((string
[2] == 'x') || (string
[2] == 'X')))
281 bi
->bp
.address
= strtoul (string
+ 3, NULL
, 16);
285 bi
->bp
.address
= strtoul (string
+ 3, NULL
, 10);
287 bi
->bp
.type
= IANJUTA_DEBUGGER_BREAKPOINT_ON_ADDRESS
;
289 else if ((uri
!= NULL
) && isdigit (*string
))
291 bi
->uri
= g_strdup (uri
);
292 bi
->bp
.file
= gnome_vfs_get_local_path_from_uri (uri
);
293 bi
->bp
.line
= strtoul (string
, NULL
, 10);
294 bi
->bp
.type
= IANJUTA_DEBUGGER_BREAKPOINT_ON_LINE
;
300 ptr
= strchr (string
, ':');
304 /* break on function */
305 bi
->bp
.function
= g_strdup (string
);
306 bi
->bp
.type
= IANJUTA_DEBUGGER_BREAKPOINT_ON_FUNCTION
;
310 if (isdigit (ptr
[1]))
312 bi
->bp
.line
= strtoul (ptr
+ 1, NULL
, 10);
313 bi
->bp
.type
= IANJUTA_DEBUGGER_BREAKPOINT_ON_LINE
;
317 bi
->bp
.function
= g_strdup (ptr
+ 1);
318 bi
->bp
.type
= IANJUTA_DEBUGGER_BREAKPOINT_ON_FUNCTION
;
320 bi
->bp
.file
= g_strndup (string
, ptr
- string
);
321 bi
->uri
= gnome_vfs_get_uri_from_local_path (bi
->bp
.file
);
325 bi
->bp
.enable
= TRUE
;
326 bi
->bp
.type
|= IANJUTA_DEBUGGER_BREAKPOINT_WITH_ENABLE
;
331 /* User interface functions
332 *---------------------------------------------------------------------------*/
335 breakpoints_dbase_set_in_editor (BreakpointsDBase
*bd
, BreakpointItem
*bi
)
337 IAnjutaMarkable
*ed
= NULL
;
340 g_return_if_fail (bi
!= NULL
);
342 if (bi
->editor
== NULL
)
347 ed
= IANJUTA_MARKABLE (bi
->editor
);
348 if (bi
->handle
!= -1)
350 line
= ianjuta_markable_location_from_handle (ed
, bi
->handle
, NULL
);
352 /* Remove old mark */
353 ianjuta_markable_unmark (ed
, line
, BREAKPOINT_ENABLED
, NULL
);
354 ianjuta_markable_unmark (ed
, line
, BREAKPOINT_DISABLED
,NULL
);
362 bi
->handle
= ianjuta_markable_mark (ed
, line
, bi
->bp
.enable
? BREAKPOINT_ENABLED
: BREAKPOINT_DISABLED
, NULL
);
366 breakpoints_dbase_clear_in_editor (BreakpointsDBase
*bd
, BreakpointItem
*bi
)
371 g_return_if_fail (bi
!= NULL
);
373 if (bi
->editor
== NULL
)
375 /* No editor, no need to remove marker */
380 ed
= IANJUTA_MARKABLE (bi
->editor
);
381 line
= ianjuta_markable_location_from_handle (ed
, bi
->handle
, NULL
);
383 /* Remove old mark */
384 ianjuta_markable_unmark (ed
, line
, BREAKPOINT_ENABLED
, NULL
);
385 ianjuta_markable_unmark (ed
, line
, BREAKPOINT_DISABLED
,NULL
);
392 breakpoints_dbase_update_in_treeview (BreakpointsDBase
*bd
, BreakpointItem
*bi
)
398 const gchar
*filename
;
401 adr
= g_strdup_printf ("0x%lx", bi
->bp
.address
);
402 if (bi
->bp
.file
!= NULL
)
404 filename
= strrchr(bi
->bp
.file
, G_DIR_SEPARATOR
);
405 filename
= filename
== NULL
? bi
->bp
.file
: filename
+ 1; /* display name only */
406 format
= bi
->bp
.function
== NULL
? "%s:%d" : "%s:%d in %s";
410 filename
= bi
->bp
.function
;
411 format
= filename
== NULL
? "??" : "%s";
413 location
= g_strdup_printf (format
, filename
, bi
->bp
.line
, bi
->bp
.function
);
416 pass
= g_strdup_printf ("%d", bi
->bp
.ignore
);
418 else if (bi
->bp
.ignore
)
420 pass
= g_strdup_printf ("%d of %d", bi
->bp
.times
, bi
->bp
.ignore
);
424 pass
= g_strdup_printf ("%d", bi
->bp
.times
);
430 else if (bi
->bp
.temporary
)
432 format
= "temporary (%d)";
436 format
= "permanent (%d)";
438 state
= g_strdup_printf (format
, bi
->bp
.id
);
440 gtk_list_store_set (bd
->model
, &bi
->iter
,
441 ENABLED_COLUMN
, bi
->bp
.enable
,
442 LOCATION_COLUMN
, location
,
444 TYPE_COLUMN
, "breakpoint",
445 CONDITION_COLUMN
, bi
->bp
.condition
,
456 breakpoints_dbase_breakpoint_removed (BreakpointsDBase
*bd
, BreakpointItem
*bi
)
459 breakpoints_dbase_clear_in_editor (bd
, bi
);
462 bi
->bp
.type
|= IANJUTA_DEBUGGER_BREAKPOINT_REMOVED
;
463 g_signal_emit_by_name (bd
->plugin
, "breakpoint-changed", &bi
->bp
);
465 breakpoint_item_unref (bi
);
469 breakpoints_dbase_breakpoint_updated (BreakpointsDBase
*bd
, BreakpointItem
*bi
)
471 if ((bi
->bp
.id
== 0) && (bi
->bp
.temporary
))
473 /* Temporary breakpoint are never pending */
474 breakpoints_dbase_breakpoint_removed (bd
, bi
);
478 /* Update treeview and marker */
479 breakpoints_dbase_update_in_treeview (bd
, bi
);
481 breakpoints_dbase_set_in_editor (bd
, bi
);
484 g_signal_emit_by_name (bi
->bd
->plugin
, "breakpoint-changed", &bi
->bp
);
489 on_editor_saved (IAnjutaEditor
*editor
, const gchar
* uri
, BreakpointsDBase
*bd
)
492 GtkTreeModel
*model
= GTK_TREE_MODEL (bd
->model
);
494 g_return_if_fail (model
!= NULL
);
495 /* Update breakpoint position */
496 if (gtk_tree_model_get_iter_first (model
, &iter
))
502 gtk_tree_model_get (GTK_TREE_MODEL (bd
->model
), &iter
, DATA_COLUMN
, &bi
, -1);
504 if ((bi
->editor
== editor
) && (bi
->handle
!= -1))
508 line
= ianjuta_markable_location_from_handle (IANJUTA_MARKABLE (editor
), bi
->handle
, NULL
);
509 if (line
!= bi
->bp
.line
)
512 breakpoints_dbase_breakpoint_updated (bd
, bi
);
515 } while (gtk_tree_model_iter_next (model
, &iter
));
520 breakpoints_dbase_connect_to_editor (BreakpointsDBase
*bd
, IAnjutaEditor
* ed
)
522 if (!g_signal_handler_find (ed
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, bd
))
524 /* signal is not already connected */
525 g_signal_connect (ed
, "saved", G_CALLBACK (on_editor_saved
), bd
);
530 breakpoints_dbase_disconnect_from_editors (BreakpointsDBase
*bd
)
533 GtkTreeModel
*model
= GTK_TREE_MODEL (bd
->model
);
535 if (gtk_tree_model_get_iter_first (model
, &iter
))
541 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
543 if (bi
->editor
!= NULL
)
545 g_signal_handlers_disconnect_matched (bi
->editor
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, bd
);
547 } while (gtk_tree_model_iter_next (model
, &iter
));
552 breakpoints_dbase_set_all_in_editor (BreakpointsDBase
* bd
, IAnjutaEditor
* te
)
558 g_return_if_fail (te
!= NULL
);
559 g_return_if_fail (bd
!= NULL
);
560 g_return_if_fail (bd
->treeview
!= NULL
);
562 uri
= ianjuta_file_get_uri (IANJUTA_FILE (te
), NULL
);
566 if (!IANJUTA_IS_MARKABLE (te
))
568 /* Nothing to do, editor does not support mark */
572 model
= gtk_tree_view_get_model (bd
->treeview
);
574 if (gtk_tree_model_get_iter_first (model
, &iter
))
580 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
582 if ((bi
->editor
== NULL
) && (strcmp (uri
, bi
->uri
) == 0))
586 g_object_add_weak_pointer (G_OBJECT (te
), (gpointer
)&bi
->editor
);
587 breakpoints_dbase_connect_to_editor (bd
, te
);
589 if (bi
->editor
== te
)
591 breakpoints_dbase_set_in_editor (bd
, bi
);
593 } while (gtk_tree_model_iter_next (model
, &iter
));
599 on_added_current_editor (AnjutaPlugin
*plugin
, const char *name
,
600 const GValue
*value
, gpointer user_data
)
602 BreakpointsDBase
*bd
= (BreakpointsDBase
*)user_data
;
605 editor
= g_value_get_object (value
);
607 /* Restore breakpoints */
608 if (IANJUTA_IS_EDITOR (editor
))
609 breakpoints_dbase_set_all_in_editor (bd
, IANJUTA_EDITOR (editor
));
613 on_removed_current_editor (AnjutaPlugin
*plugin
,
614 const char *name
, gpointer data
)
616 /* Nothing do to here */
620 *---------------------------------------------------------------------------*/
623 ianjuta_debugger_breakpoint_is_equal (const IAnjutaDebuggerBreakpointItem
*bpa
, const IAnjutaDebuggerBreakpointItem
*bpb
)
625 g_return_val_if_fail ((bpa
!= NULL
) && (bpb
!= NULL
), FALSE
);
627 /* Special case if both pointer are equal */
628 if (bpa
== bpb
) return TRUE
;
630 /* Compare their id */
631 if (bpa
->id
== bpb
->id
) return TRUE
;
633 /* If both breakpoint id are define (!=0) and different */
634 if ((bpa
->id
!= 0) && (bpb
->id
!= 0)) return FALSE
;
636 /* Check line and file */
637 if (bpa
->type
& bpb
->type
& IANJUTA_DEBUGGER_BREAKPOINT_ON_LINE
)
639 if (bpa
->line
!= bpb
->line
) return FALSE
;
640 if (strcmp(bpa
->file
, bpb
->file
) != 0) return FALSE
;
643 /* Check function name */
644 if (bpa
->type
& bpb
->type
& IANJUTA_DEBUGGER_BREAKPOINT_ON_FUNCTION
)
646 if (strcmp(bpa
->function
, bpb
->function
) != 0) return FALSE
;
650 if (bpa
->type
& bpb
->type
& IANJUTA_DEBUGGER_BREAKPOINT_ON_ADDRESS
)
652 if (bpa
->address
!= bpb
->address
) return FALSE
;
655 /* Check conditions */
656 if (bpa
->type
& bpb
->type
& IANJUTA_DEBUGGER_BREAKPOINT_WITH_CONDITION
)
658 if (strcmp(bpa
->condition
, bpb
->condition
) != 0) return FALSE
;
664 static BreakpointItem
*
665 breakpoints_dbase_find_breakpoint (BreakpointsDBase
*bd
, const IAnjutaDebuggerBreakpointItem
*bp
)
670 g_return_val_if_fail (bd
->treeview
!= NULL
, NULL
);
672 model
= gtk_tree_view_get_model (bd
->treeview
);
674 if (gtk_tree_model_get_iter_first (model
, &iter
))
680 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
682 if (ianjuta_debugger_breakpoint_is_equal (&bi
->bp
, bp
)) return bi
;
683 } while (gtk_tree_model_iter_next (model
, &iter
));
689 /* Debugger functions
690 *---------------------------------------------------------------------------*/
693 on_breakpoint_callback (const gpointer data
, gpointer breakpoint
, GError
* err
);
696 breakpoints_dbase_remove_in_debugger (BreakpointsDBase
*bd
, BreakpointItem
*bi
)
700 /* Remove breakpoint in debugger */
701 breakpoint_item_ref (bi
);
702 ok
= dma_queue_remove_breakpoint (
705 on_breakpoint_callback
,
707 if (!ok
) breakpoint_item_unref (bi
);
713 breakpoints_dbase_add_in_debugger (BreakpointsDBase
*bd
, BreakpointItem
*bi
)
719 /* Breakpoint already exist, remove it first */
720 breakpoint_item_ref (bi
);
721 ok
= dma_queue_remove_breakpoint (
724 on_breakpoint_callback
,
726 if (!ok
) breakpoint_item_unref (bi
);
730 if (bi
->bp
.condition
!= NULL
)
732 bi
->changed
= IANJUTA_DEBUGGER_BREAKPOINT_WITH_CONDITION
;
734 if (bi
->bp
.ignore
!= 0)
736 bi
->changed
= IANJUTA_DEBUGGER_BREAKPOINT_WITH_IGNORE
;
738 if (bi
->bp
.enable
!= TRUE
)
740 bi
->changed
= IANJUTA_DEBUGGER_BREAKPOINT_WITH_ENABLE
;
743 /* Add breakpoint in debugger */
744 if (bi
->bp
.type
& IANJUTA_DEBUGGER_BREAKPOINT_ON_LINE
)
746 breakpoint_item_ref (bi
);
747 ok
= dma_queue_add_breakpoint_at_line (
751 on_breakpoint_callback
,
754 else if (bi
->bp
.type
& IANJUTA_DEBUGGER_BREAKPOINT_ON_FUNCTION
)
756 breakpoint_item_ref (bi
);
757 ok
= dma_queue_add_breakpoint_at_function (
759 bi
->bp
.file
== NULL
? "" : bi
->bp
.file
,
761 on_breakpoint_callback
,
764 else if ((bi
->bp
.type
& IANJUTA_DEBUGGER_BREAKPOINT_ON_ADDRESS
)
765 && dma_debugger_queue_is_supported(bd
->debugger
, HAS_ADDRESS_BREAKPOINT
))
767 breakpoint_item_ref (bi
);
768 ok
= dma_queue_add_breakpoint_at_address (
771 on_breakpoint_callback
,
774 if (!ok
) breakpoint_item_unref (bi
);
780 breakpoints_dbase_update_in_debugger (BreakpointsDBase
*bd
, BreakpointItem
*bi
)
784 if (bi
->changed
& IANJUTA_DEBUGGER_BREAKPOINT_WITH_ENABLE
)
786 bi
->changed
&= ~IANJUTA_DEBUGGER_BREAKPOINT_WITH_ENABLE
;
787 breakpoint_item_ref (bi
);
788 ok
= dma_queue_enable_breakpoint (
792 on_breakpoint_callback
,
794 if (!ok
) breakpoint_item_unref (bi
);
797 if ((bi
->changed
& IANJUTA_DEBUGGER_BREAKPOINT_WITH_CONDITION
)
798 && dma_debugger_queue_is_supported(bd
->debugger
, HAS_CONDITION_BREAKPOINT
))
800 bi
->changed
&= ~IANJUTA_DEBUGGER_BREAKPOINT_WITH_CONDITION
;
801 breakpoint_item_ref (bi
);
802 ok
= dma_queue_condition_breakpoint (
806 on_breakpoint_callback
,
808 if (!ok
) breakpoint_item_unref (bi
);
810 if ((bi
->changed
& IANJUTA_DEBUGGER_BREAKPOINT_WITH_IGNORE
)
811 && dma_debugger_queue_is_supported(bd
->debugger
, HAS_IGNORE_BREAKPOINT
))
813 bi
->changed
&= ~IANJUTA_DEBUGGER_BREAKPOINT_WITH_IGNORE
;
814 breakpoint_item_ref (bi
);
815 ok
= dma_queue_ignore_breakpoint (
819 on_breakpoint_callback
,
821 if (!ok
) breakpoint_item_unref (bi
);
826 on_breakpoint_callback (const gpointer data
, gpointer user_data
, GError
* err
)
828 const IAnjutaDebuggerBreakpointItem
* bp
= (const IAnjutaDebuggerBreakpointItem
*)data
;
829 BreakpointItem
*bi
= (BreakpointItem
*)user_data
;
830 BreakpointsDBase
*bd
= bi
->bd
;
832 if (breakpoint_item_unref (bi
))
834 /* Breakpoint item has been destroyed */
840 if ((bp
!= NULL
) && (bp
->type
& IANJUTA_DEBUGGER_BREAKPOINT_REMOVED
))
842 breakpoints_dbase_breakpoint_removed (bd
, bi
);
846 breakpoint_item_update_from_debugger (bi
, bp
);
847 breakpoints_dbase_update_in_debugger (bd
, bi
);
848 breakpoints_dbase_breakpoint_updated (bd
, bi
);
854 void on_update_breakpoint_from_debugger (gpointer data
, gpointer user_data
)
856 IAnjutaDebuggerBreakpointItem
*bp
= (IAnjutaDebuggerBreakpointItem
*)data
;
857 BreakpointsDBase
*bd
= (BreakpointsDBase
*)user_data
;
860 bi
= breakpoints_dbase_find_breakpoint (bd
, bp
);
864 /* Breakpoint exist in the debugger but not in the manager, create it */
865 bi
= breakpoint_item_new (bd
);
867 breakpoint_item_update_from_debugger (bi
, bp
);
868 bi
->changed
|= IANJUTA_DEBUGGER_BREAKPOINT_UPDATED
;
872 gboolean
on_update_breakpoint_in_ui (GtkTreeModel
*model
, GtkTreePath
*path
,
873 GtkTreeIter
*iter
, gpointer user_data
)
876 BreakpointsDBase
*bd
;
878 gtk_tree_model_get (model
, iter
, DATA_COLUMN
, &bi
, -1);
881 if (bi
->changed
& IANJUTA_DEBUGGER_BREAKPOINT_UPDATED
)
883 /* Breakpoint is present in debugger */
884 bi
->changed
&= ~IANJUTA_DEBUGGER_BREAKPOINT_UPDATED
;
888 /* Breakpoint is not present in debugger */
891 breakpoints_dbase_breakpoint_updated (bd
, bi
);
897 on_breakpoint_list_callback (const gpointer data
, gpointer user_data
, GError
* err
)
899 GList
*list
= (GList
*)data
;
900 BreakpointsDBase
*bd
= (BreakpointsDBase
*)user_data
;
902 /* Update all breakpoints */
903 g_list_foreach (list
, on_update_breakpoint_from_debugger
, bd
);
905 /* Remove all not updated breakpoints */
906 gtk_tree_model_foreach (GTK_TREE_MODEL (bd
->model
), on_update_breakpoint_in_ui
, bd
);
910 breakpoints_dbase_list_all_in_debugger (BreakpointsDBase
*bd
)
912 g_return_if_fail (bd
->debugger
!= NULL
);
914 dma_queue_list_breakpoint (bd
->debugger
, on_breakpoint_list_callback
, bd
);
918 *---------------------------------------------------------------------------*/
920 /* Send all breakpoints in debugger */
923 breakpoints_dbase_add_all_in_debugger (BreakpointsDBase
*bd
)
926 GtkTreeModel
*model
= GTK_TREE_MODEL (bd
->model
);
928 g_return_if_fail (bd
->treeview
!= NULL
);
930 if (gtk_tree_model_get_iter_first (model
, &iter
))
936 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
937 breakpoints_dbase_add_in_debugger (bd
, bi
);
938 } while (gtk_tree_model_iter_next (model
, &iter
));
942 /* Send all pending breakpoints in debugger */
945 breakpoints_dbase_add_all_pending_in_debugger (BreakpointsDBase
*bd
)
948 GtkTreeModel
*model
= GTK_TREE_MODEL (bd
->model
);
950 if (gtk_tree_model_get_iter_first (model
, &iter
))
956 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
960 breakpoints_dbase_add_in_debugger (bd
, bi
);
962 } while (gtk_tree_model_iter_next (model
, &iter
));
966 /* Remove all breakpoints in debugger but do not delete them */
969 breakpoints_dbase_remove_all_in_debugger (BreakpointsDBase
*bd
)
972 GtkTreeModel
*model
= GTK_TREE_MODEL (bd
->model
);
974 if (gtk_tree_model_get_iter_first (model
, &iter
))
982 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
983 next
= gtk_tree_model_iter_next (model
, &iter
);
986 breakpoints_dbase_breakpoint_updated (bd
, bi
);
987 /* breakpoints_dbase_breakpoint_updated can delete pending breakpoints
988 * the iterator of the breakpoint can be invalidated */
993 /* Add breakpoint in tree view, in editor and in debugger */
996 breakpoints_dbase_add_breakpoint (BreakpointsDBase
*bd
, BreakpointItem
*bi
)
1000 /* Add in current editor if possible */
1001 ed
= dma_get_current_editor (ANJUTA_PLUGIN(bd
->plugin
));
1002 if ((ed
!= NULL
) && IANJUTA_IS_MARKABLE (ed
))
1006 uri
= ianjuta_file_get_uri (IANJUTA_FILE (ed
), NULL
);
1007 if ((uri
!= NULL
) && (strcmp (uri
, bi
->uri
) == 0))
1011 g_object_add_weak_pointer (G_OBJECT (ed
), (gpointer
)&bi
->editor
);
1012 breakpoints_dbase_connect_to_editor (bd
, ed
);
1017 if (bd
->debugger
!= NULL
)
1019 breakpoints_dbase_add_in_debugger (bd
, bi
);
1023 breakpoints_dbase_breakpoint_updated (bd
, bi
);
1027 /* Remove breakpoint in tree view, in editor and in debugger */
1030 breakpoints_dbase_remove_breakpoint (BreakpointsDBase
*bd
, BreakpointItem
*bi
)
1032 if (bd
->debugger
!= NULL
)
1034 if (breakpoints_dbase_remove_in_debugger (bd
, bi
)) return;
1036 breakpoints_dbase_breakpoint_removed (bd
, bi
);
1039 /* Enable or disable breakpoint in tree view, in editor and in debugger */
1042 breakpoints_dbase_enable_breakpoint (BreakpointsDBase
*bd
, BreakpointItem
*bi
, gboolean enable
)
1044 bi
->bp
.enable
= enable
;
1045 bi
->changed
|= IANJUTA_DEBUGGER_BREAKPOINT_WITH_ENABLE
;
1047 if (bd
->debugger
!= NULL
)
1049 breakpoints_dbase_update_in_debugger (bd
, bi
);
1053 breakpoints_dbase_breakpoint_updated (bd
, bi
);
1057 /* Toggle breakpoint enable in tree view, in editor and in debugger */
1060 breakpoints_dbase_toggle_enable (BreakpointsDBase
*bd
, GtkTreeModel
*model
, GtkTreeIter iter
)
1064 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
1066 breakpoints_dbase_enable_breakpoint (bd
, bi
, bi
->bp
.enable
? FALSE
: TRUE
);
1069 /* Update breakpoint in tree view, in editor and in debugger */
1072 breakpoints_dbase_update_breakpoint (BreakpointsDBase
*bd
, BreakpointItem
*bi
)
1074 if (bd
->debugger
!= NULL
)
1076 breakpoints_dbase_update_in_debugger (bd
, bi
);
1080 breakpoints_dbase_breakpoint_updated (bd
, bi
);
1084 /* Remove all breakpoints in tree view, in editor and in debugger */
1087 breakpoints_dbase_remove_all (BreakpointsDBase
*bd
)
1090 GtkTreeModel
*model
= GTK_TREE_MODEL (bd
->model
);
1093 if (gtk_tree_model_get_iter_first (model
, &iter
))
1101 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
1102 next
= gtk_tree_model_iter_next (model
, &iter
);
1104 breakpoints_dbase_remove_breakpoint (bd
, bi
);
1105 /* Avoid an infinite loop if the breakpoint is not removed due to
1111 /* Enable or disable all breakpoints in tree view, in editor and in debugger */
1114 breakpoints_dbase_enable_all (BreakpointsDBase
*bd
, gboolean enable
)
1117 GtkTreeModel
*model
= GTK_TREE_MODEL (bd
->model
);
1119 if (gtk_tree_model_get_iter_first (model
, &iter
))
1125 gtk_tree_model_get (GTK_TREE_MODEL (bd
->model
), &iter
, DATA_COLUMN
, &bi
, -1);
1127 breakpoints_dbase_enable_breakpoint (bd
, bi
, enable
);
1128 } while (gtk_tree_model_iter_next (model
, &iter
));
1132 static BreakpointItem
*
1133 breakpoints_dbase_find_breakpoint_from_mark (BreakpointsDBase
*bd
, IAnjutaEditor
*ed
, guint line
)
1136 GtkTreeModel
*model
= GTK_TREE_MODEL (bd
->model
);
1138 if (gtk_tree_model_get_iter_first (model
, &iter
))
1144 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
1146 if ((bi
->editor
== ed
) && (bi
->handle
!= -1)
1147 && (ianjuta_markable_location_from_handle (IANJUTA_MARKABLE(ed
), bi
->handle
, NULL
) == line
))
1151 } while (gtk_tree_model_iter_next (model
, &iter
));
1157 static BreakpointItem
*
1158 breakpoints_dbase_find_breakpoint_from_line (BreakpointsDBase
*bd
, const gchar
* uri
, guint line
)
1161 GtkTreeModel
*model
= GTK_TREE_MODEL (bd
->model
);
1163 if (gtk_tree_model_get_iter_first (model
, &iter
))
1169 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
1171 if ((line
== bi
->bp
.line
) && (strcmp (uri
, bi
->uri
) == 0)) return bi
;
1172 } while (gtk_tree_model_iter_next (model
, &iter
));
1179 breakpoints_dbase_get_breakpoint_list (BreakpointsDBase
*bd
)
1183 GtkTreeModel
*model
= GTK_TREE_MODEL (bd
->model
);
1185 if (gtk_tree_model_get_iter_first (model
, &iter
))
1191 gtk_tree_model_get (GTK_TREE_MODEL (bd
->model
), &iter
, DATA_COLUMN
, &bi
, -1);
1193 if ((bi
->bp
.type
& (IANJUTA_DEBUGGER_BREAKPOINT_ON_LINE
| IANJUTA_DEBUGGER_BREAKPOINT_ON_FUNCTION
))
1194 && (bi
->bp
.temporary
== FALSE
))
1196 /* Only permanent breakpoint are saved */
1197 list
= g_list_prepend (list
, g_strdup_printf("%d:%s:%u:%u:%s", bi
->bp
.enable
? 1 : 0, bi
->uri
, bi
->bp
.line
, bi
->bp
.ignore
, bi
->bp
.condition
== NULL
? "" : bi
->bp
.condition
));
1199 } while (gtk_tree_model_iter_next (model
, &iter
));
1202 list
= g_list_reverse (list
);
1208 on_add_breakpoint_list (gpointer data
, gpointer user_data
)
1210 BreakpointsDBase
* bd
= (BreakpointsDBase
*)user_data
;
1212 gchar
*uri
= (gchar
*)data
;
1219 pos
= strrchr (uri
, ':');
1222 pos
= strrchr (uri
, ':');
1224 ignore
= strtoul (pos
+ 1, NULL
, 10);
1225 pos
= strrchr (uri
, ':');
1227 line
= strtoul (pos
+ 1, NULL
, 10);
1228 enable
= uri
[0] == '0' ? FALSE
: TRUE
;
1229 bi
= breakpoint_item_new_from_uri (bd
, uri
+ 2, line
, enable
);
1233 bi
->bp
.condition
= g_strdup (cond
);
1235 bi
->bp
.ignore
= ignore
;
1237 breakpoints_dbase_add_breakpoint (bd
, bi
);
1241 breakpoints_dbase_add_breakpoint_list (BreakpointsDBase
*bd
, GList
*list
)
1243 g_list_foreach (list
, on_add_breakpoint_list
, bd
);
1246 /* Debugger Callbacks
1247 *---------------------------------------------------------------------------*/
1250 on_breakpoint_sharedlib_event (BreakpointsDBase
*bd
)
1252 breakpoints_dbase_add_all_pending_in_debugger (bd
);
1256 on_program_running (BreakpointsDBase
*bd
)
1258 /* Deactivate breakpoint functions */
1259 gtk_action_group_set_sensitive (bd
->debugger_group
, FALSE
);
1263 on_program_stopped (BreakpointsDBase
*bd
)
1265 g_return_if_fail (bd
->debugger
!= NULL
);
1267 gtk_action_group_set_sensitive (bd
->debugger_group
, TRUE
);
1269 /* Refresh breakpoint
1270 * Hit count could have changed by example */
1271 breakpoints_dbase_list_all_in_debugger (bd
);
1275 on_program_exited (BreakpointsDBase
*bd
)
1277 g_return_if_fail (bd
->debugger
!= NULL
);
1279 gtk_action_group_set_sensitive (bd
->debugger_group
, TRUE
);
1283 on_program_unloaded (BreakpointsDBase
*bd
)
1285 g_return_if_fail (bd
->debugger
!= NULL
);
1287 breakpoints_dbase_remove_all_in_debugger (bd
);
1288 bd
->debugger
= NULL
;
1289 gtk_action_group_set_sensitive (bd
->debugger_group
, TRUE
);
1291 /* Disconnect from other debugger signal */
1292 g_signal_handlers_disconnect_by_func (bd
->plugin
, G_CALLBACK (on_breakpoint_sharedlib_event
), bd
);
1293 g_signal_handlers_disconnect_by_func (bd
->plugin
, G_CALLBACK (on_program_stopped
), bd
);
1294 g_signal_handlers_disconnect_by_func (bd
->plugin
, G_CALLBACK (on_program_running
), bd
);
1295 g_signal_handlers_disconnect_by_func (bd
->plugin
, G_CALLBACK (on_program_exited
), bd
);
1296 g_signal_handlers_disconnect_by_func (bd
->plugin
, G_CALLBACK (on_program_unloaded
), bd
);
1300 on_program_loaded (BreakpointsDBase
*bd
)
1302 DmaDebuggerQueue
* debugger
;
1304 DEBUG_PRINT("on program loaded in breakpoints %p bd %p", bd
->debugger
, bd
);
1305 /* Debugger shouldn't be connected */
1306 g_return_if_fail (bd
->debugger
== NULL
);
1308 debugger
= dma_debug_manager_get_queue (ANJUTA_PLUGIN_DEBUG_MANAGER (bd
->plugin
));
1309 if (!dma_debugger_queue_is_supported (debugger
, HAS_BREAKPOINT
)) return;
1311 bd
->debugger
= debugger
;
1312 breakpoints_dbase_add_all_in_debugger (bd
);
1314 /* Connect to other debugger signal */
1315 g_signal_connect_swapped (bd
->plugin
, "sharedlib-event", G_CALLBACK (on_breakpoint_sharedlib_event
), bd
);
1316 g_signal_connect_swapped (bd
->plugin
, "program-unloaded", G_CALLBACK (on_program_unloaded
), bd
);
1317 g_signal_connect_swapped (bd
->plugin
, "program-stopped", G_CALLBACK (on_program_stopped
), bd
);
1318 g_signal_connect_swapped (bd
->plugin
, "program-exited", G_CALLBACK (on_program_exited
), bd
);
1319 g_signal_connect_swapped (bd
->plugin
, "program-running", G_CALLBACK (on_program_running
), bd
);
1323 on_debugger_started (BreakpointsDBase
*bd
)
1325 GtkTreeViewColumn
*column
;
1326 DmaDebuggerQueue
* debugger
;
1328 debugger
= dma_debug_manager_get_queue (ANJUTA_PLUGIN_DEBUG_MANAGER (bd
->plugin
));
1330 /* Remove breakpoint attributes not supported by current debugger */
1331 if (!dma_debugger_queue_is_supported(debugger
, HAS_ADDRESS_BREAKPOINT
))
1333 column
= gtk_tree_view_get_column (bd
->treeview
, ADDRESS_COLUMN
);
1334 gtk_tree_view_column_set_visible (column
, FALSE
);
1336 if (!dma_debugger_queue_is_supported(debugger
, HAS_IGNORE_BREAKPOINT
))
1338 column
= gtk_tree_view_get_column (bd
->treeview
, PASS_COLUMN
);
1339 gtk_tree_view_column_set_visible (column
, FALSE
);
1341 if (!dma_debugger_queue_is_supported(debugger
, HAS_CONDITION_BREAKPOINT
))
1343 column
= gtk_tree_view_get_column (bd
->treeview
, CONDITION_COLUMN
);
1344 gtk_tree_view_column_set_visible (column
, FALSE
);
1349 on_debugger_stopped (BreakpointsDBase
*bd
)
1351 /* Restore breakpoint attributes not supported by current debugger */
1352 GtkTreeViewColumn
*column
;
1354 column
= gtk_tree_view_get_column (bd
->treeview
, ADDRESS_COLUMN
);
1355 gtk_tree_view_column_set_visible (column
, TRUE
);
1356 column
= gtk_tree_view_get_column (bd
->treeview
, PASS_COLUMN
);
1357 gtk_tree_view_column_set_visible (column
, TRUE
);
1358 column
= gtk_tree_view_get_column (bd
->treeview
, CONDITION_COLUMN
);
1359 gtk_tree_view_column_set_visible (column
, TRUE
);
1363 /* Saving preferences callbacks
1364 *---------------------------------------------------------------------------*/
1367 on_session_save (AnjutaShell
*shell
, AnjutaSessionPhase phase
, AnjutaSession
*session
, BreakpointsDBase
*bd
)
1371 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
1374 list
= breakpoints_dbase_get_breakpoint_list (bd
);
1376 anjuta_session_set_string_list (session
, "Debugger", "Breakpoint", list
);
1380 on_session_load (AnjutaShell
*shell
, AnjutaSessionPhase phase
, AnjutaSession
*session
, BreakpointsDBase
*bd
)
1384 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
1387 breakpoints_dbase_remove_all (bd
);
1388 list
= anjuta_session_get_string_list (session
, "Debugger", "Breakpoint");
1390 breakpoints_dbase_add_breakpoint_list (bd
, list
);
1393 /* Breakpoint edit dialog
1394 *---------------------------------------------------------------------------*/
1397 breakpoints_dbase_edit_breakpoint (BreakpointsDBase
*bd
, BreakpointItem
*bi
)
1401 GtkWidget
*location_label
, *location_entry
;
1402 GtkWidget
*condition_entry
, *condition_label
;
1403 GtkWidget
*pass_entry
, *pass_label
;
1405 gchar
*location
= NULL
;
1407 gboolean new_break
= FALSE
;
1409 gxml
= glade_xml_new (GLADE_FILE
,
1410 "breakpoint_properties_dialog", NULL
);
1411 dialog
= glade_xml_get_widget (gxml
, "breakpoint_properties_dialog");
1412 gtk_window_set_transient_for (GTK_WINDOW (dialog
),
1413 GTK_WINDOW (ANJUTA_PLUGIN (bd
->plugin
)->shell
));
1414 location_label
= glade_xml_get_widget (gxml
, "breakpoint_location_label");
1415 location_entry
= glade_xml_get_widget (gxml
, "breakpoint_location_entry");
1416 condition_entry
= glade_xml_get_widget (gxml
, "breakpoint_condition_entry");
1417 condition_label
= glade_xml_get_widget (gxml
, "breakpoint_condition_label");
1418 pass_entry
= glade_xml_get_widget (gxml
, "breakpoint_pass_entry");
1419 pass_label
= glade_xml_get_widget (gxml
, "breakpoint_pass_label");
1421 if (!dma_debugger_queue_is_supported(bd
->debugger
, HAS_IGNORE_BREAKPOINT
))
1423 gtk_widget_hide (pass_entry
);
1424 gtk_widget_hide (pass_label
);
1426 if (!dma_debugger_queue_is_supported(bd
->debugger
, HAS_CONDITION_BREAKPOINT
))
1428 gtk_widget_hide (condition_entry
);
1429 gtk_widget_hide (condition_label
);
1437 /* New breakpoint */
1438 gtk_widget_show (location_entry
);
1439 gtk_widget_hide (location_label
);
1441 /* Get current editor and line */
1442 te
= dma_get_current_editor (ANJUTA_PLUGIN(bd
->plugin
));
1445 uri
= ianjuta_file_get_uri (IANJUTA_FILE (te
), NULL
);
1446 line
= ianjuta_editor_get_lineno (te
, NULL
);
1448 //NULL uri ia ok here
1449 bi
= breakpoint_item_new_from_uri (bd
, uri
, line
, TRUE
);
1454 /* Update breakpoint */
1455 gtk_widget_hide (location_entry
);
1456 gtk_widget_show (location_label
);
1459 if (bi
->uri
!= NULL
)
1461 if (bi
->bp
.line
!= 0)
1464 location
= g_strdup_printf ("%s:%d", bi
->bp
.file
, bi
->bp
.line
);
1468 // file and function
1469 location
= g_strdup_printf ("%s:%s", bi
->bp
.file
, bi
->bp
.function
);
1472 else if (bi
->bp
.address
!= 0)
1475 location
= g_strdup_printf ("*%lx", bi
->bp
.address
);
1478 if (GTK_WIDGET_VISIBLE(location_entry
))
1480 gtk_entry_set_text (GTK_ENTRY (location_entry
), location
== NULL
? "" : location
);
1484 gtk_label_set_text (GTK_LABEL (location_label
), location
== NULL
? "" : location
);
1487 if (bi
->bp
.condition
&& strlen (bi
->bp
.condition
) > 0)
1488 gtk_entry_set_text (GTK_ENTRY (condition_entry
), bi
->bp
.condition
);
1490 buff
= g_strdup_printf ("%d", bi
->bp
.ignore
);
1491 gtk_entry_set_text (GTK_ENTRY (pass_entry
), buff
);
1494 if (gtk_dialog_run (GTK_DIALOG (dialog
)) == GTK_RESPONSE_OK
)
1496 const gchar
*condition
;
1498 const gchar
*new_location
;
1500 ignore
= atoi (gtk_entry_get_text (GTK_ENTRY (pass_entry
)));
1501 condition
= gtk_entry_get_text (GTK_ENTRY (condition_entry
));
1502 while (isspace(*condition
)) condition
++;
1503 if (*condition
== '\0') condition
= NULL
;
1505 if (GTK_WIDGET_VISIBLE(location_entry
))
1507 new_location
= gtk_entry_get_text (GTK_ENTRY (location_entry
));
1508 while (isspace(*new_location
)) new_location
++;
1510 if ((location
== NULL
) || (strcmp (new_location
, location
) != 0))
1512 /* location has been changed, create a new breakpoint */
1513 breakpoint_item_unref (bi
);
1516 if (*new_location
!= '\0')
1518 bi
= breakpoint_item_new_from_string (bd
, new_location
, uri
);
1524 new_location
= NULL
;
1529 if (bi
->bp
.ignore
!= ignore
)
1531 bi
->bp
.ignore
= ignore
;
1532 bi
->changed
|= IANJUTA_DEBUGGER_BREAKPOINT_WITH_IGNORE
;
1534 if ((condition
!= bi
->bp
.condition
) && ((condition
== NULL
) || (bi
->bp
.condition
== NULL
) || (strcmp (bi
->bp
.condition
, condition
) != 0)))
1536 if (bi
->bp
.condition
) g_free ((char *)bi
->bp
.condition
);
1537 bi
->bp
.condition
= condition
!= NULL
? g_strdup (condition
) : NULL
;
1538 bi
->changed
|= IANJUTA_DEBUGGER_BREAKPOINT_WITH_CONDITION
;
1540 if (new_location
!= NULL
)
1542 breakpoints_dbase_add_breakpoint (bd
, bi
);
1546 breakpoints_dbase_update_breakpoint (bd
, bi
);
1552 /* Remove breakpoint if a new one has been created */
1553 breakpoint_item_unref (bi
);
1557 gtk_widget_destroy (dialog
);
1558 g_object_unref (gxml
);
1561 /* Breakpoint actions list
1562 *---------------------------------------------------------------------------*/
1565 on_jump_to_breakpoint_activate (GtkAction
* action
, BreakpointsDBase
*bd
)
1567 GtkTreeModel
*model
;
1568 GtkTreeSelection
*selection
;
1572 selection
= gtk_tree_view_get_selection (bd
->treeview
);
1573 valid
= gtk_tree_selection_get_selected (selection
, &model
, &iter
);
1578 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
1580 g_signal_emit_by_name (bd
->plugin
, "location-changed", bi
->bp
.address
, bi
->uri
, bi
->bp
.line
);
1585 on_toggle_breakpoint_activate (GtkAction
* action
, BreakpointsDBase
*bd
)
1592 /* Get current editor and line */
1593 te
= dma_get_current_editor (ANJUTA_PLUGIN (bd
->plugin
));
1594 if (te
== NULL
) return; /* Missing editor */
1595 uri
= ianjuta_file_get_uri (IANJUTA_FILE (te
), NULL
);
1596 if (uri
== NULL
) return; /* File not saved yet, it's not possible to put a breakpoint in it */
1597 line
= ianjuta_editor_get_lineno (te
, NULL
);
1599 /* Find corresponding breakpoint
1600 * Try to find right mark (it could have moved) first */
1601 bi
= breakpoints_dbase_find_breakpoint_from_mark (bd
, te
, line
);
1604 bi
= breakpoints_dbase_find_breakpoint_from_line (bd
, uri
, line
);
1609 bi
= breakpoint_item_new_from_uri (bd
, uri
, line
, TRUE
);
1611 breakpoints_dbase_add_breakpoint (bd
, bi
);
1615 breakpoints_dbase_remove_breakpoint (bd
, bi
);
1621 on_disable_all_breakpoints_activate (GtkAction
* action
, BreakpointsDBase
*bd
)
1623 breakpoints_dbase_enable_all (bd
, FALSE
);
1627 on_clear_all_breakpoints_activate (GtkAction
* action
, BreakpointsDBase
*bd
)
1631 dialog
= gtk_message_dialog_new (GTK_WINDOW (ANJUTA_PLUGIN (bd
->plugin
)->shell
),
1632 GTK_DIALOG_DESTROY_WITH_PARENT
,
1633 GTK_MESSAGE_QUESTION
,
1635 _("Are you sure you want to delete all the breakpoints?"));
1636 gtk_dialog_add_buttons (GTK_DIALOG (dialog
),
1637 GTK_STOCK_CANCEL
, GTK_RESPONSE_NO
,
1638 GTK_STOCK_DELETE
, GTK_RESPONSE_YES
,
1641 gtk_window_set_transient_for (GTK_WINDOW (dialog
),
1642 GTK_WINDOW (ANJUTA_PLUGIN (bd
->plugin
)->shell
) );
1644 if (gtk_dialog_run (GTK_DIALOG (dialog
)) == GTK_RESPONSE_YES
)
1646 breakpoints_dbase_remove_all (bd
);
1648 gtk_widget_destroy (dialog
);
1652 on_add_breakpoint_activate (GtkAction
* action
, BreakpointsDBase
*bd
)
1654 breakpoints_dbase_edit_breakpoint (bd
, NULL
);
1658 on_remove_breakpoint_activate (GtkAction
* action
, BreakpointsDBase
*bd
)
1660 GtkTreeModel
*model
;
1661 GtkTreeSelection
*selection
;
1665 selection
= gtk_tree_view_get_selection (bd
->treeview
);
1666 valid
= gtk_tree_selection_get_selected (selection
, &model
, &iter
);
1671 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
1672 breakpoints_dbase_remove_breakpoint (bd
, bi
);
1677 on_edit_breakpoint_activate (GtkAction
* action
, BreakpointsDBase
*bd
)
1679 GtkTreeModel
*model
;
1680 GtkTreeSelection
*selection
;
1684 selection
= gtk_tree_view_get_selection (bd
->treeview
);
1685 valid
= gtk_tree_selection_get_selected (selection
, &model
, &iter
);
1690 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
1691 breakpoints_dbase_edit_breakpoint (bd
, bi
);
1696 on_treeview_enabled_toggled (GtkCellRendererToggle
*cell
,
1698 BreakpointsDBase
*bd
)
1700 GtkTreeModel
*model
;
1704 path
= gtk_tree_path_new_from_string (path_str
);
1706 model
= gtk_tree_view_get_model (bd
->treeview
);
1707 gtk_tree_model_get_iter (model
, &iter
, path
);
1709 breakpoints_dbase_toggle_enable (bd
, model
, iter
);
1713 on_enable_breakpoint_activate (GtkAction
* action
, BreakpointsDBase
*bd
)
1715 GtkTreeModel
*model
;
1716 GtkTreeSelection
*selection
;
1720 selection
= gtk_tree_view_get_selection (bd
->treeview
);
1721 valid
= gtk_tree_selection_get_selected (selection
, &model
, &iter
);
1724 breakpoints_dbase_toggle_enable (bd
, model
, iter
);
1728 static GtkActionEntry actions_debugger_breakpoints
[] = {
1730 "ActionMenuDmaBreakpoints", /* Action name */
1731 NULL
, /* Stock icon, if any */
1732 N_("_Breakpoints"), /* Display label */
1733 NULL
, /* short-cut */
1735 NULL
/* action callback */
1738 "ActionDmaToggleBreakpoint", /* Action name */
1739 ANJUTA_STOCK_BREAKPOINT_TOGGLE
, /* Stock icon, if any */
1740 N_("Toggle Breakpoint"), /* Display label */
1741 "<control>b", /* short-cut */
1742 N_("Toggle breakpoint at the current location"), /* Tooltip */
1743 G_CALLBACK (on_toggle_breakpoint_activate
) /* action callback */
1746 "ActionDmaSetBreakpoint", /* Action name */
1747 ANJUTA_STOCK_BREAKPOINT_ENABLED
, /* Stock icon, if any */
1748 N_("Add Breakpoint..."), /* Display label */
1749 NULL
, /* short-cut */
1750 N_("Add a breakpoint"), /* Tooltip */
1751 G_CALLBACK (on_add_breakpoint_activate
) /* action callback */
1754 "ActionDmaClearBreakpoint", /* Action name */
1755 ANJUTA_STOCK_BREAKPOINT_CLEAR
, /* Stock icon, if any */
1756 N_("Remove Breakpoint"), /* Display label */
1757 NULL
, /* short-cut */
1758 N_("Remove a breakpoint"), /* Tooltip */
1759 G_CALLBACK (on_remove_breakpoint_activate
) /* action callback */
1762 "ActionDmaEditBreakpoint", /* Action name */
1763 NULL
, /* Stock icon, if any */
1764 N_("Edit Breakpoint"), /* Display label */
1765 NULL
, /* short-cut */
1766 N_("Edit breakpoint properties"), /* Tooltip */
1767 G_CALLBACK (on_edit_breakpoint_activate
) /* action callback */
1770 "ActionDmaEnableDisableBreakpoint", /* Action name */
1771 NULL
, /* Stock icon, if any */
1772 N_("Enable Breakpoint"), /* Display label */
1773 NULL
, /* short-cut */
1774 N_("Enable a breakpoint"), /* Tooltip */
1775 G_CALLBACK (on_enable_breakpoint_activate
) /* action callback */
1778 "ActionDmaDisableAllBreakpoints", /* Action name */
1779 ANJUTA_STOCK_BREAKPOINT_DISABLED
, /* Stock icon, if any */
1780 N_("Disable All Breakpoints"), /* Display label */
1781 NULL
, /* short-cut */
1782 N_("Deactivate all breakpoints"), /* Tooltip */
1783 G_CALLBACK (on_disable_all_breakpoints_activate
)/* action callback */
1786 "ActionDmaClearAllBreakpoints", /* Action name */
1787 ANJUTA_STOCK_BREAKPOINT_CLEAR
, /* Stock icon, if any */
1788 N_("C_lear All Breakpoints"), /* Display label */
1789 NULL
, /* short-cut */
1790 N_("Delete all breakpoints"), /* Tooltip */
1791 G_CALLBACK (on_clear_all_breakpoints_activate
)/* action callback */
1795 static GtkActionEntry actions_permanent_breakpoints
[] = {
1797 "ActionDmaJumpToBreakpoint", /* Action name */
1798 NULL
, /* Stock icon, if any */
1799 N_("Jump to Breakpoint"), /* Display label */
1800 NULL
, /* short-cut */
1801 N_("Jump to breakpoint location"), /* Tooltip */
1802 G_CALLBACK (on_jump_to_breakpoint_activate
) /* action callback */
1806 /* Breakpoint list window
1807 *---------------------------------------------------------------------------*/
1810 on_breakpoints_button_press (GtkWidget
* widget
, GdkEventButton
* bevent
, BreakpointsDBase
*bd
)
1812 if (bevent
->button
== 3)
1816 GtkTreeModel
*model
;
1817 GtkTreeSelection
*selection
;
1821 ui
= anjuta_shell_get_ui (ANJUTA_PLUGIN(bd
->plugin
)->shell
, NULL
);
1822 popup
= GTK_MENU (gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui
), "/PopupBreakpoint"));
1824 selection
= gtk_tree_view_get_selection (bd
->treeview
);
1825 valid
= gtk_tree_selection_get_selected (selection
, &model
, &iter
);
1831 const gchar
* tooltip
;
1833 gtk_tree_model_get (model
, &iter
, DATA_COLUMN
, &bi
, -1);
1834 action
= gtk_action_group_get_action (bd
->debugger_group
, "ActionDmaEnableDisableBreakpoint");
1835 g_return_val_if_fail (action
!= NULL
, FALSE
);
1838 label
= N_("Disable Breakpoint");
1839 tooltip
= N_("Disable a breakpoint");
1843 label
= N_("Enable Breakpoint");
1844 tooltip
= N_("Enable a breakpoint");
1847 g_object_set (G_OBJECT (action
),
1853 gtk_menu_popup (popup
, NULL
, NULL
, NULL
, NULL
,
1854 bevent
->button
, bevent
->time
);
1856 else if ((bevent
->type
== GDK_2BUTTON_PRESS
) && (bevent
->button
== 1))
1858 /* Double left mouse click */
1859 on_jump_to_breakpoint_activate (NULL
, bd
);
1866 create_breakpoint_gui(BreakpointsDBase
*bd
)
1868 static const gchar
*column_names
[COLUMNS_NB
] = {
1869 N_("Enabled"), N_("Location"), N_("Address"), N_("Type"),
1870 N_("Condition"), N_("Pass count"), N_("State")};
1871 static GType column_type
[COLUMNS_NB
] = {
1872 G_TYPE_BOOLEAN
, G_TYPE_STRING
, G_TYPE_STRING
, G_TYPE_STRING
,
1873 G_TYPE_STRING
, G_TYPE_STRING
, G_TYPE_STRING
, G_TYPE_POINTER
};
1875 GtkCellRenderer
*renderer
;
1876 GtkTreeViewColumn
*column
;
1877 GtkTreeModel
*model
;
1880 g_return_if_fail (bd
->treeview
== NULL
);
1881 g_return_if_fail (bd
->window
== NULL
);
1882 g_return_if_fail (bd
->debugger_group
== NULL
);
1883 g_return_if_fail (bd
->permanent_group
== NULL
);
1885 /* breakpoints window */
1886 bd
->model
= gtk_list_store_newv (COLUMNS_NB
, column_type
);
1887 model
= GTK_TREE_MODEL (bd
->model
);
1888 bd
->treeview
= GTK_TREE_VIEW (gtk_tree_view_new_with_model (model
));
1889 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (bd
->treeview
),
1890 GTK_SELECTION_SINGLE
);
1891 g_object_unref (G_OBJECT (model
));
1893 renderer
= gtk_cell_renderer_toggle_new ();
1894 column
= gtk_tree_view_column_new_with_attributes (_(column_names
[0]),
1899 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1900 gtk_tree_view_append_column (bd
->treeview
, column
);
1901 g_signal_connect (renderer
, "toggled",
1902 G_CALLBACK (on_treeview_enabled_toggled
), bd
);
1904 renderer
= gtk_cell_renderer_text_new ();
1905 for (i
= ENABLED_COLUMN
+ 1; i
< (COLUMNS_NB
- 1); i
++)
1908 gtk_tree_view_column_new_with_attributes (_(column_names
[i
]),
1909 renderer
, "text", i
, NULL
);
1910 gtk_tree_view_column_set_sizing (column
,
1911 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1912 gtk_tree_view_append_column (bd
->treeview
, column
);
1915 /* Register menu actions */
1916 ui
= anjuta_shell_get_ui (ANJUTA_PLUGIN(bd
->plugin
)->shell
, NULL
);
1917 bd
->debugger_group
=
1918 anjuta_ui_add_action_group_entries (ui
, "ActionGroupBreakpoint",
1919 _("Breakpoint operations"),
1920 actions_debugger_breakpoints
,
1921 G_N_ELEMENTS (actions_debugger_breakpoints
),
1922 GETTEXT_PACKAGE
, TRUE
, bd
);
1923 bd
->permanent_group
=
1924 anjuta_ui_add_action_group_entries (ui
, "ActionGroupBreakpoint",
1925 _("Breakpoint operations"),
1926 actions_permanent_breakpoints
,
1927 G_N_ELEMENTS (actions_permanent_breakpoints
),
1928 GETTEXT_PACKAGE
, TRUE
, bd
);
1930 /* Add breakpoint window */
1931 bd
->window
= gtk_scrolled_window_new (NULL
, NULL
);
1932 gtk_widget_show (bd
->window
);
1933 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (bd
->window
),
1934 GTK_POLICY_AUTOMATIC
,
1935 GTK_POLICY_AUTOMATIC
);
1936 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (bd
->window
),
1938 gtk_container_add (GTK_CONTAINER (bd
->window
), GTK_WIDGET (bd
->treeview
));
1939 gtk_widget_show_all (bd
->window
);
1940 anjuta_shell_add_widget (ANJUTA_PLUGIN(bd
->plugin
)->shell
,
1942 "AnjutaDebuggerBreakpoints", _("Breakpoints"),
1943 ANJUTA_STOCK_BREAKPOINT_ENABLED
, ANJUTA_SHELL_PLACEMENT_BOTTOM
,
1946 /* Add popup menu */
1947 g_signal_connect (bd
->treeview
, "button-press-event", G_CALLBACK (on_breakpoints_button_press
), bd
);
1951 destroy_breakpoint_gui (BreakpointsDBase
*bd
)
1955 /* Remove menu actions */
1956 ui
= anjuta_shell_get_ui (ANJUTA_PLUGIN (bd
->plugin
)->shell
, NULL
);
1957 if (bd
->debugger_group
)
1959 anjuta_ui_remove_action_group (ui
, bd
->debugger_group
);
1960 bd
->debugger_group
= NULL
;
1962 if (bd
->permanent_group
)
1964 anjuta_ui_remove_action_group (ui
, bd
->permanent_group
);
1965 bd
->permanent_group
= NULL
;
1968 /* Destroy breakpoint window */
1969 if (bd
->window
!= NULL
)
1971 gtk_widget_destroy (bd
->window
);
1976 /* Constructor & Destructor
1977 *---------------------------------------------------------------------------*/
1980 breakpoints_dbase_new (DebugManagerPlugin
*plugin
)
1982 BreakpointsDBase
*bd
;
1984 bd
= g_new0 (BreakpointsDBase
, 1);
1986 bd
->plugin
= plugin
;
1988 /* Create graphical user inteface */
1989 create_breakpoint_gui (bd
);
1991 /* Connect to Load and Save event */
1992 g_signal_connect (ANJUTA_PLUGIN(bd
->plugin
)->shell
, "save-session",
1993 G_CALLBACK (on_session_save
), bd
);
1994 g_signal_connect (ANJUTA_PLUGIN(bd
->plugin
)->shell
, "load-session",
1995 G_CALLBACK (on_session_load
), bd
);
1997 /* Connect on load program */
1998 g_signal_connect_swapped (bd
->plugin
, "program-loaded", G_CALLBACK (on_program_loaded
), bd
);
1999 g_signal_connect_swapped (bd
->plugin
, "debugger-started", G_CALLBACK (on_debugger_started
), bd
);
2000 g_signal_connect_swapped (bd
->plugin
, "debugger-stopped", G_CALLBACK (on_debugger_stopped
), bd
);
2003 anjuta_plugin_add_watch (ANJUTA_PLUGIN(bd
->plugin
), "document_manager_current_editor",
2004 on_added_current_editor
,
2005 on_removed_current_editor
, bd
);
2012 breakpoints_dbase_destroy (BreakpointsDBase
* bd
)
2014 g_return_if_fail (bd
!= NULL
);
2016 /* Disconnect all signal */
2017 g_signal_handlers_disconnect_matched (ANJUTA_PLUGIN(bd
->plugin
)->shell
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, bd
);
2018 g_signal_handlers_disconnect_matched (bd
->plugin
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, bd
);
2019 breakpoints_dbase_disconnect_from_editors (bd
);
2020 anjuta_plugin_remove_watch (ANJUTA_PLUGIN(bd
->plugin
), bd
->editor_watch
, FALSE
);
2022 /* This is necessary to clear the editor of breakpoint markers */
2023 breakpoints_dbase_remove_all (bd
);
2025 /* Destroy graphical user interface */
2026 destroy_breakpoint_gui (bd
);
2028 g_free (bd
->cond_history
);
2029 g_free (bd
->loc_history
);