Branch: refs/heads/master Author: Frank Lanitz frank@frank.uvena.de Committer: Frank Lanitz frank@frank.uvena.de Date: Wed, 14 Mar 2012 20:00:10 Commit: 093fdc6260681ea6baa5657bb1d8ca2ef9f9ced8 https://github.com/geany/geany-plugins/commit/093fdc6260681ea6baa5657bb1d8ca...
Log Message: ----------- Merge pull request #18 from cesspit/master
switching between frames by clicking a frame arrow in the stack window
Modified Paths: -------------- debugger/ChangeLog debugger/TODO debugger/src/Makefile.am debugger/src/breakpoints.h debugger/src/callbacks.c debugger/src/cell_renderers/cellrendererbreakicon.c debugger/src/cell_renderers/cellrendererbreakicon.h debugger/src/cell_renderers/cellrendererframeicon.c debugger/src/cell_renderers/cellrendererframeicon.h debugger/src/dbm_gdb.c debugger/src/debug.c debugger/src/debug.h debugger/src/debug_module.h debugger/src/pixbuf.h debugger/src/stree.c debugger/src/stree.h debugger/src/utils.h
Modified: debugger/ChangeLog 4 files changed, 4 insertions(+), 0 deletions(-) =================================================================== @@ -1,3 +1,7 @@ +10-03-2012 Alexander Petukhov devel@apetukhov.ru + + * switching between frames by clicking a frame arrow in the stack window + 18-02-2012 Alexander Petukhov devel@apetukhov.ru
* threads info added to the stack window
Modified: debugger/TODO 4 files changed, 3 insertions(+), 1 deletions(-) =================================================================== @@ -2,12 +2,13 @@ BUGS: - terminal stops to produce any output after some debug seesions - tooltip appears even if a pointer in no longer inside editor window - check possible memory leaks on a)gtk_tree_row_reference_get_path b)missing unrefs on tree/list stores +- cell_renderer_toogle SIGSEGV in cell_renderer_toggle_activate when activating a cell using a keyboard (event->button == NULL) +- debug geany with debugger project. switch frames then step over -> continue instead, then close geany being debugged -> dbm_gdb.c:502 (no step reason, probably the record from the previos step command???)
FEATURES: - custom tooltip with sticking facilities - don't hide a tooltip until run hasn't happent, move it if document is being scrolled - use lexer to lookup for a symbol under cursor when presenting a tooltip -- jump to a frame (change frame that affects locals, watch etc., caused by clicking a frame in the stack trace tab/margin stack marker) - geany menu integration - toolbar buttons - margin context menu @@ -22,3 +23,4 @@ FEATURES: - interrupt thread using stack window - custom tooltip on breaks and stack trace windows with code snippet around break or frame - font from the geany settings for a message window +- a button in the upper right path of a right notebook for a hiding/showing button panel
Modified: debugger/src/Makefile.am 2 files changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -62,6 +62,8 @@ debugger_la_SOURCES = \ wtree.h \ cell_renderers/cellrendererbreakicon.c \ cell_renderers/cellrendererbreakicon.h \ + cell_renderers/cellrendererframeicon.c \ + cell_renderers/cellrendererframeicon.h \ cell_renderers/cellrenderertoggle.c \ cell_renderers/cellrenderertoggle.h
Modified: debugger/src/breakpoints.h 3 files changed, 2 insertions(+), 1 deletions(-) =================================================================== @@ -27,7 +27,8 @@ BS_DISABLED } break_state;
-typedef void (*move_to_line_cb)(char* file, int line); +typedef void (*move_to_line_cb)(const char* file, int line); +typedef void (*select_frame_cb)(int frame_number);
gboolean breaks_init(move_to_line_cb callback); void breaks_destroy();
Modified: debugger/src/callbacks.c 26 files changed, 14 insertions(+), 12 deletions(-) =================================================================== @@ -67,24 +67,26 @@ void set_markers_for_file(const gchar* file) /* set frames markers if exists */ if (DBS_STOPPED == debug_get_state()) { + int active_frame_index = debug_get_active_frame(); + GList *iter = debug_get_stack(); - if (iter) + int frame_index = 0; + for (; iter; iter = iter->next, frame_index++) { - frame *f = (frame*)iter->data; - if (f->have_source && !strcmp(f->file, file)) - { - markers_add_current_instruction(f->file, f->line); - } - - iter = iter->next; - while (iter) + if (iter) { - f = (frame*)iter->data; + frame *f = (frame*)iter->data; if (f->have_source && !strcmp(f->file, file)) { - markers_add_frame(f->file, f->line); + if (active_frame_index == frame_index) + { + markers_add_current_instruction(f->file, f->line); + } + else + { + markers_add_frame(f->file, f->line); + } } - iter = iter->next; } } }
Modified: debugger/src/cell_renderers/cellrendererbreakicon.c 2 files changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -205,7 +205,7 @@ static void cell_renderer_break_icon_render(GtkCellRenderer *cell, GdkDrawable * { CellRendererBreakIcon *cellbreakpoint = (CellRendererBreakIcon*) cell; - GdkPixbuf *pixbuf; + GdkPixbuf *pixbuf = NULL; GdkRectangle pix_rect; GdkRectangle draw_rect;
Modified: debugger/src/cell_renderers/cellrendererbreakicon.h 2 files changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -54,7 +54,7 @@ struct _CellRendererBreakIconClass { GtkCellRendererClass parent_class;
- void (*clicked)(GtkCellRendererToggle *cell_renderer_toggle, const gchar *path); + void (*clicked)(CellRendererBreakIcon *cell_renderer_toggle, const gchar *path); };
GType cell_renderer_break_icon_get_type(void);
Modified: debugger/src/cell_renderers/cellrendererframeicon.c 343 files changed, 343 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,343 @@ +/* + * cellrendererframeicon.c + * + * Copyright 2012 Alexander Petukhov <devel(at)apetukhov.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +/* + * cell renderer class that renders frame icon, that in turn depends on whether a + * row is the first vhildren (uppermost frame) and whether a renderer is under the cursor + */ + +#include <string.h> +#include <geanyplugin.h> + +#include "cellrendererframeicon.h" + +enum { + PROP_0, + PROP_PIXBUF_ACTIVE, + PROP_PIXBUF_HIGHLIGHTED, + PROP_ACTIVE_FRAME, +}; + +static gpointer parent_class; +static guint clicked_signal; + +/* + * activate callback + */ +static gint cell_renderer_frame_icon_activate(GtkCellRenderer *cell, GdkEvent *event, GtkWidget *widget, const gchar *path, + GdkRectangle *background_area, GdkRectangle *cell_area, GtkCellRendererState flags) +{ + if (event->button.x >= cell_area->x && + event->button.x < (cell_area->x + cell_area->width)) + { + g_signal_emit (cell, clicked_signal, 0, path); + } + return TRUE; +} + +/* + * property getter + */ +static void cell_renderer_frame_icon_get_property(GObject *object, guint param_id, GValue *value, GParamSpec *pspec) +{ + CellRendererFrameIcon *cellframe = CELL_RENDERER_FRAME_ICON(object); + switch (param_id) + { + case PROP_PIXBUF_ACTIVE: + g_value_set_object (value, cellframe->pixbuf_active); + break; + case PROP_PIXBUF_HIGHLIGHTED: + g_value_set_object (value, cellframe->pixbuf_highlighted); + break; + case PROP_ACTIVE_FRAME: + g_value_set_boolean(value, cellframe->active_frame); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +/* + * property setter + */ +static void cell_renderer_frame_icon_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec) +{ + CellRendererFrameIcon *cellframe = CELL_RENDERER_FRAME_ICON(object); + switch (param_id) + { + case PROP_PIXBUF_ACTIVE: + if (cellframe->pixbuf_active) + { + g_object_unref(cellframe->pixbuf_active); + } + cellframe->pixbuf_active = (GdkPixbuf*)g_value_dup_object(value); + break; + case PROP_PIXBUF_HIGHLIGHTED: + if (cellframe->pixbuf_highlighted) + { + g_object_unref(cellframe->pixbuf_highlighted); + } + cellframe->pixbuf_highlighted = (GdkPixbuf*)g_value_dup_object(value); + break; + case PROP_ACTIVE_FRAME: + { + cellframe->active_frame = g_value_get_boolean(value); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +/* + * get size of a cell + */ +static void cell_renderer_frame_icon_get_size(GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area, + gint *x_offset, gint *y_offset, gint *width, gint *height) +{ + CellRendererFrameIcon *cellframe = (CellRendererFrameIcon *) cell; + gint pixbuf_width = 0; + gint pixbuf_height = 0; + gint calc_width; + gint calc_height; + + if (cellframe->pixbuf_active) + { + pixbuf_width = gdk_pixbuf_get_width (cellframe->pixbuf_active); + pixbuf_height = gdk_pixbuf_get_height (cellframe->pixbuf_active); + } + if (cellframe->pixbuf_highlighted) + { + pixbuf_width = MAX (pixbuf_width, gdk_pixbuf_get_width (cellframe->pixbuf_highlighted)); + pixbuf_height = MAX (pixbuf_height, gdk_pixbuf_get_height (cellframe->pixbuf_highlighted)); + } + + calc_width = (gint) cell->xpad * 2 + pixbuf_width; + calc_height = (gint) cell->ypad * 2 + pixbuf_height; + + if (cell_area && pixbuf_width > 0 && pixbuf_height > 0) + { + if (x_offset) + { + *x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? + (1.0 - cell->xalign) : cell->xalign) * + (cell_area->width - calc_width)); + *x_offset = MAX (*x_offset, 0); + } + if (y_offset) + { + *y_offset = (cell->yalign * (cell_area->height - calc_height)); + *y_offset = MAX (*y_offset, 0); + } + } + else + { + if (x_offset) *x_offset = 0; + if (y_offset) *y_offset = 0; + } + + if (width) + *width = calc_width; + + if (height) + *height = calc_height; +} + +/* + * render a cell + */ +static void cell_renderer_frame_icon_render(GtkCellRenderer *cell, GdkDrawable *window, GtkWidget *widget, + GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags) +{ + CellRendererFrameIcon *cellframe = (CellRendererFrameIcon*) cell; + + GdkPixbuf *pixbuf = NULL; + + GdkRectangle pix_rect; + GdkRectangle draw_rect; + cairo_t *cr; + + cell_renderer_frame_icon_get_size (cell, widget, cell_area, + &pix_rect.x, + &pix_rect.y, + &pix_rect.width, + &pix_rect.height); + + pix_rect.x += cell_area->x + cell->xpad; + pix_rect.y += cell_area->y + cell->ypad; + pix_rect.width -= cell->xpad * 2; + pix_rect.height -= cell->ypad * 2; + + if (!gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect) || + !gdk_rectangle_intersect (expose_area, &draw_rect, &draw_rect)) + return; + + if (cellframe->active_frame) + { + pixbuf = cellframe->pixbuf_active; + } + else if (flags & GTK_CELL_RENDERER_PRELIT) + { + pixbuf = cellframe->pixbuf_highlighted; + } + + if (!pixbuf) + return; + + cr = gdk_cairo_create (window); + + gdk_cairo_set_source_pixbuf (cr, pixbuf, pix_rect.x, pix_rect.y); + gdk_cairo_rectangle (cr, &draw_rect); + cairo_fill (cr); + + cairo_destroy (cr); +} + +/* + * init instance + */ +static void cell_renderer_frame_icon_init (CellRendererFrameIcon *cell) +{ + cell->active_frame = FALSE; + + GtkCellRenderer *cell_renderer = (GtkCellRenderer*)cell; + + cell_renderer->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE; + + cell->pixbuf_active = cell->pixbuf_highlighted = 0; +} + +/* + * finalizes an instance (frees pixbuffers) + */ +static void cell_renderer_frame_icon_finalize (GObject *object) +{ + CellRendererFrameIcon *cell = (CellRendererFrameIcon*)object; + + GdkPixbuf *pixbufs[] = { cell->pixbuf_active, cell->pixbuf_highlighted }; + int i; + for(i = 0; i < 2; i++) + { + if (pixbufs[i]) + { + g_object_unref(pixbufs[i]); + } + } + + (*G_OBJECT_CLASS (parent_class)->finalize) (object); +} + +/* + * init class + */ +static void cell_renderer_frame_icon_class_init (CellRendererFrameIconClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS(class); + + parent_class = g_type_class_peek_parent(class); + + object_class->get_property = cell_renderer_frame_icon_get_property; + object_class->set_property = cell_renderer_frame_icon_set_property; + + object_class->finalize = cell_renderer_frame_icon_finalize; + + cell_class->get_size = cell_renderer_frame_icon_get_size; + cell_class->render = cell_renderer_frame_icon_render; + + cell_class->activate = cell_renderer_frame_icon_activate; + + g_object_class_install_property (object_class, + PROP_PIXBUF_ACTIVE, + g_param_spec_object ( + "pixbuf_active", + "Pixbuf Object", + "Active frame image", + GDK_TYPE_PIXBUF, + G_PARAM_READWRITE) + ); + + g_object_class_install_property (object_class, + PROP_PIXBUF_HIGHLIGHTED, + g_param_spec_object ( + "pixbuf_highlighted", + "Pixbuf Object", + "Highlighted frame image", + GDK_TYPE_PIXBUF, + G_PARAM_READWRITE) + ); + + g_object_class_install_property (object_class, + PROP_ACTIVE_FRAME, + g_param_spec_boolean ("active_frame", "Activeness", "Is a frame active", FALSE, G_PARAM_READWRITE) + ); + + clicked_signal = g_signal_new ("clicked", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CellRendererFrameIconClass, clicked), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); +} + +/* + * registers a type + */ +GType cell_renderer_frame_icon_get_type(void) +{ + static GType cell_frame_icon_type = 0; + + if(0 == cell_frame_icon_type) + { + static const GTypeInfo cell_frame_icon_info = + { + sizeof (CellRendererFrameIconClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) cell_renderer_frame_icon_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (CellRendererFrameIcon), + 0, /* n_preallocs */ + (GInstanceInitFunc) cell_renderer_frame_icon_init, + }; + + /* Derive from GtkCellRenderer */ + cell_frame_icon_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, + "CellRendererFrameIcon", + &cell_frame_icon_info, + 0); + } + + return cell_frame_icon_type; +} + +/* + * creates new renderer + */ +GtkCellRenderer* cell_renderer_frame_icon_new() +{ + return g_object_new(TYPE_CELL_RENDERER_FRAME_ICON, NULL); +}
Modified: debugger/src/cell_renderers/cellrendererframeicon.h 61 files changed, 61 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,61 @@ +/* + * cellrendererframeicon.h + * + * Copyright 2012 Alexander Petukhov <devel(at)apetukhov.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef __CELL_RENDERER_FRAME_ICON_H__ +#define __CELL_RENDERER_FRAME_ICON_H__ + +#include <gtk/gtkcellrenderer.h> + +G_BEGIN_DECLS + +#define TYPE_CELL_RENDERER_FRAME_ICON (cell_renderer_frame_icon_get_type ()) +#define CELL_RENDERER_FRAME_ICON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CELL_RENDERER_FRAME_ICON, CellRendererFrameIcon)) +#define CELL_RENDERER_FRAME_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_CELL_RENDERER_FRAME_ICON, CellRendererFrameIconClass)) +#define IS_CELL_RENDERER_FRAME_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CELL_RENDERER_FRAME_ICON)) +#define IS_CELL_RENDERER_FRAME_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CELL_RENDERER_FRAME_ICON)) +#define CELL_RENDERER_FRAME_ICON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_CELL_RENDERER_FRAME_ICON, CellRendererFrameIconClass)) + +typedef struct _CellRendererFrameIcon CellRendererFrameIcon; +typedef struct _CellRendererFrameIconClass CellRendererFrameIconClass; + +struct _CellRendererFrameIcon +{ + GtkCellRenderer parent; + + guint GSEAL (active_frame); + + GdkPixbuf *GSEAL (pixbuf_active); + GdkPixbuf *GSEAL (pixbuf_highlighted); +}; + +struct _CellRendererFrameIconClass +{ + GtkCellRendererClass parent_class; + + void (*clicked)(CellRendererFrameIcon *cell_renderer_toggle, const gchar *path); +}; + +GType cell_renderer_frame_icon_get_type(void); +GtkCellRenderer* cell_renderer_frame_icon_new (void); + +G_END_DECLS + +#endif /* __CELL_RENDERER_FRAME_ICON_H__ */
Modified: debugger/src/dbm_gdb.c 31 files changed, 30 insertions(+), 1 deletions(-) =================================================================== @@ -117,6 +117,9 @@ enum sr { and it's nessesary to refresh files list */ static gboolean file_refresh_needed = FALSE;
+/* current frame number */ +static int active_frame = 0; + /* forward declarations */ void stop(); variable* add_watch(gchar* expression); @@ -499,6 +502,8 @@ static gboolean on_read_from_gdb(GIOChannel * src, GIOCondition cond, gpointer d gchar *thread_id = strstr(reason + strlen(reason) + 1,"thread-id="") + strlen("thread-id=""); *(strchr(thread_id, '"')) = '\0'; + active_frame = 0; + if (SR_BREAKPOINT_HIT == stop_reason || SR_END_STEPPING_RANGE == stop_reason) { /* update autos */ @@ -1029,6 +1034,29 @@ gboolean remove_break(breakpoint* bp) }
/* + * get active frame + */ +int get_active_frame() +{ + return active_frame; +} + +/* + * select frame + */ +void set_active_frame(int frame_number) +{ + gchar *command = g_strdup_printf("-stack-select-frame %i", frame_number); + if (RC_DONE == exec_sync_command(command, TRUE, NULL)) + { + active_frame = frame_number; + update_autos(); + update_watches(); + } + g_free(command); +} + +/* * gets stack */ GList* get_stack() @@ -1452,7 +1480,7 @@ void update_autos() /* add current autos to the list */ GList *unevaluated = NULL; - const char *gdb_commands[] = { "-stack-list-arguments 0 0 0", "-stack-list-locals 0" }; + const char *gdb_commands[] = { g_strdup_printf("-stack-list-arguments 0 %i %i", active_frame, active_frame), "-stack-list-locals 0" }; int i, size = sizeof (gdb_commands) / sizeof(char*); for (i = 0; i < size; i++) { @@ -1498,6 +1526,7 @@ void update_autos() } g_free(record); } + g_free((void*)gdb_commands[0]); /* get values for the autos (without incorrect variables) */ get_variables(autos);
Modified: debugger/src/debug.c 105 files changed, 77 insertions(+), 28 deletions(-) =================================================================== @@ -151,46 +151,60 @@ static GHashTable *calltips = NULL;
/* - * removes stack margin markers + * remove stack margin markers */ void remove_stack_markers() { - frame *current = (frame*)stack->data; - if (current->have_source) - { - markers_remove_current_instruction(current->file, current->line); - } - GList *iter = stack->next; - while (iter) + int active_frame_index = active_module->get_active_frame(); + + GList *iter; + int frame_index; + for (iter = stack, frame_index = 0; iter; iter = iter->next, frame_index++) { - frame *next = (frame*)iter->data; - if (next->have_source) + if (iter) { - markers_remove_frame(next->file, next->line); + frame *f = (frame*)iter->data; + if (f->have_source) + { + if (active_frame_index == frame_index) + { + markers_remove_current_instruction(f->file, f->line); + } + else + { + markers_remove_frame(f->file, f->line); + } + } } - iter = iter->next; } }
/* - * removes stack margin markers + * add stack margin markers */ - void add_stack_markers() +static void add_stack_markers() { - frame *current = (frame*)stack->data; - if (current->have_source) - { - markers_add_current_instruction(current->file, current->line); - } - GList *iter = stack->next; - while (iter) + int active_frame_index = active_module->get_active_frame(); + + GList *iter; + int frame_index; + for (iter = stack, frame_index = 0; iter; iter = iter->next, frame_index++) { - frame *next = (frame*)iter->data; - if (next->have_source) + if (iter) { - markers_add_frame(next->file, next->line); + frame *f = (frame*)iter->data; + if (f->have_source) + { + if (active_frame_index == frame_index) + { + markers_add_current_instruction(f->file, f->line); + } + else + { + markers_add_frame(f->file, f->line); + } + } } - iter = iter->next; } }
@@ -643,7 +657,7 @@ static void on_debugger_stopped (int thread_id) }
/* clear stack tree view */ - stree_set_current_thread_id(thread_id); + stree_set_active_thread_id(thread_id);
/* get current stack trace and put in the tree view */ stack = active_module->get_stack(); @@ -806,7 +820,7 @@ static void on_debugger_exited (int code) /* * called from debugger module to show a message in debugger messages pane */ -static void on_debugger_message (const gchar* message, const gchar *color) +void on_debugger_message (const gchar* message, const gchar *color) { gchar *msg = g_strdup_printf("%s\n", message);
@@ -873,6 +887,33 @@ static void on_thread_added (int thread_id) * Interface functions */
+/* + * called when a frame in the stack tree has been selected + */ +static void on_select_frame(int frame_number) +{ + frame *f = (frame*)g_list_nth(stack, active_module->get_active_frame())->data; + markers_remove_current_instruction(f->file, f->line); + markers_add_frame(f->file, f->line); + + active_module->set_active_frame(frame_number); + + /* clear calltips cache */ + g_hash_table_remove_all(calltips); + + /* autos */ + GList *autos = active_module->get_autos(); + update_variables(GTK_TREE_VIEW(atree), NULL, autos); + + /* watches */ + GList *watches = active_module->get_watches(); + update_variables(GTK_TREE_VIEW(wtree), NULL, watches); + + f = (frame*)g_list_nth(stack, frame_number)->data; + markers_remove_frame(f->file, f->line); + markers_add_current_instruction(f->file, f->line); +} + /* * init debug related GUI (watch tree view) * arguments: @@ -909,7 +950,7 @@ void debug_init() gtk_container_add(GTK_CONTAINER(tab_autos), atree); /* create stack trace page */ - stree = stree_init(editor_open_position); + stree = stree_init(editor_open_position, on_select_frame); tab_call_stack = gtk_scrolled_window_new( gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(stree )), gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(stree )) @@ -1314,3 +1355,11 @@ void debug_on_file_open(GeanyDocument *doc) if (g_list_find_custom(read_only_pages, (gpointer)file, (GCompareFunc)g_strcmp0)) scintilla_send_message(doc->editor->sci, SCI_SETREADONLY, 1, 0); } + +/* + * get active frame index + */ +int debug_get_active_frame() +{ + return active_module->get_active_frame(); +}
Modified: debugger/src/debug.h 1 files changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -48,4 +48,5 @@ gchar* debug_get_calltip_for_expression(gchar* expression); GList* debug_get_stack(); void debug_restart(); +int debug_get_active_frame();
Modified: debugger/src/debug_module.h 8 files changed, 7 insertions(+), 1 deletions(-) =================================================================== @@ -108,8 +108,12 @@ enum dbs {
gboolean (*set_break) (breakpoint* bp, break_set_activity bsa); gboolean (*remove_break) (breakpoint* bp); + GList* (*get_stack) (); - + + void (*set_active_frame)(int frame_number); + int (*get_active_frame)(); + GList* (*get_autos) (); GList* (*get_watches) (); @@ -141,6 +145,8 @@ enum dbs { set_break, \ remove_break, \ get_stack, \ + set_active_frame, \ + get_active_frame, \ get_autos, \ get_watches, \ get_files, \
Modified: debugger/src/pixbuf.h 1 files changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -27,6 +27,7 @@ extern GdkPixbuf *local_pixbuf; extern GdkPixbuf *watch_pixbuf;
+extern GdkPixbuf *frame_pixbuf; extern GdkPixbuf *frame_current_pixbuf;
void pixbufs_init();
Modified: debugger/src/stree.c 172 files changed, 112 insertions(+), 60 deletions(-) =================================================================== @@ -36,6 +36,8 @@ #include "debug_module.h" #include "pixbuf.h"
+#include "cell_renderers/cellrendererframeicon.h" + /* Tree view columns */ enum { @@ -46,25 +48,57 @@ enum S_LAST_VISIBLE, S_HAVE_SOURCE, S_THREAD_ID, + S_ACTIVE, S_N_COLUMNS };
/* hash table to keep thread nodes in the tree */ static GHashTable *threads;
-/* current_thread_id */ -static glong current_thread_id = 0; +/* active thread and frame */ +static glong active_thread_id = 0; +static int active_frame_index = 0;
-/* double click callback pointer */ -static move_to_line_cb callback = NULL; +/* callbacks */ +static select_frame_cb select_frame = NULL; +static move_to_line_cb move_to_line = NULL;
/* tree view, model and store handles */ -static GtkWidget* tree = NULL; -static GtkTreeModel* model = NULL; -static GtkTreeStore* store = NULL; +static GtkWidget *tree = NULL; +static GtkTreeModel *model = NULL; +static GtkTreeStore *store = NULL;
-/* selection callback id */ -static gulong selection_callback = 0; +/* cell renderer for a frame arrow */ +static GtkCellRenderer *renderer_arrow = NULL; + +/* + * frame arrow clicked callback + */ +static void on_frame_arrow_clicked(CellRendererFrameIcon *cell_renderer, gchar *path, gpointer user_data) +{ + GtkTreePath *new_active_frame = gtk_tree_path_new_from_string (path); + if (gtk_tree_path_get_indices(new_active_frame)[1] != active_frame_index) + { + GtkTreeIter iter; + + GtkTreeRowReference *reference = (GtkTreeRowReference*)g_hash_table_lookup(threads, (gpointer)active_thread_id); + GtkTreePath *old_active_frame = gtk_tree_row_reference_get_path(reference); + gtk_tree_path_append_index(old_active_frame, active_frame_index); + + gtk_tree_model_get_iter(model, &iter, old_active_frame); + gtk_tree_store_set (store, &iter, S_ACTIVE, FALSE, -1); + + active_frame_index = gtk_tree_path_get_indices(new_active_frame)[1]; + select_frame(active_frame_index); + + gtk_tree_model_get_iter(model, &iter, new_active_frame); + gtk_tree_store_set (store, &iter, S_ACTIVE, TRUE, -1); + + gtk_tree_path_free(old_active_frame); + } + + gtk_tree_path_free(new_active_frame); +}
/* * shows a tooltip for a file name @@ -79,21 +113,33 @@ static gboolean on_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean key GtkTreeViewColumn *column = NULL; if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bx, by, &tpath, &column, NULL, NULL)) { - if (2 == gtk_tree_path_get_depth(tpath) && column == gtk_tree_view_get_column(GTK_TREE_VIEW(widget), S_FILEPATH)) + if (2 == gtk_tree_path_get_depth(tpath)) { - GtkTreeIter iter; - gtk_tree_model_get_iter(model, &iter, tpath); - - gchar *path = NULL; - gtk_tree_model_get(model, &iter, S_FILEPATH, &path, -1); - - gtk_tooltip_set_text(tooltip, path); - - gtk_tree_view_set_tooltip_row(GTK_TREE_VIEW(widget), tooltip, tpath); - - show = TRUE; + gint start_pos, width; + gtk_tree_view_column_cell_get_position(column, renderer_arrow, &start_pos, &width); + + if (column == gtk_tree_view_get_column(GTK_TREE_VIEW(widget), S_FILEPATH)) + { + GtkTreeIter iter; + gtk_tree_model_get_iter(model, &iter, tpath); + + gchar *path = NULL; + gtk_tree_model_get(model, &iter, S_FILEPATH, &path, -1); + + gtk_tooltip_set_text(tooltip, path); + + gtk_tree_view_set_tooltip_row(GTK_TREE_VIEW(widget), tooltip, tpath); + + show = TRUE;
- g_free(path); + g_free(path); + } + else if (column == gtk_tree_view_get_column(GTK_TREE_VIEW(widget), S_ADRESS && bx >= start_pos && bx < start_pos + width)) + { + gtk_tooltip_set_text(tooltip, gtk_tree_path_get_indices(tpath)[1] == active_frame_index ? _("Active frame") : _("Switch to a frame")); + gtk_tree_view_set_tooltip_row(GTK_TREE_VIEW(widget), tooltip, tpath); + show = TRUE; + } } gtk_tree_path_free(tpath); } @@ -102,17 +148,13 @@ static gboolean on_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean key }
/* - * shows arrow icon for the current frame, hides renderer for a thread row + * shows arrow icon for the frame rows, hides renderer for a thread ones */ -static void on_render_icon(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, +static void on_render_arrow(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) { GtkTreePath *tpath = gtk_tree_model_get_path(model, iter); - gboolean frame_row = 1 != gtk_tree_path_get_depth(tpath); - - g_object_set(cell, "visible", frame_row, NULL); - g_object_set(cell, "pixbuf", (frame_row && 0 == gtk_tree_path_get_indices(tpath)[1]) ? (gpointer)frame_current_pixbuf : NULL, NULL); - + g_object_set(cell, "visible", 1 != gtk_tree_path_get_depth(tpath), NULL); gtk_tree_path_free(tpath); }
@@ -123,7 +165,7 @@ static void on_render_line(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell GtkTreeIter *iter, gpointer data) { GtkTreePath *tpath = gtk_tree_model_get_path(model, iter); - + if (1 == gtk_tree_path_get_depth(tpath)) { g_object_set(cell, "text", "", NULL); @@ -169,7 +211,8 @@ static gboolean on_msgwin_button_press(GtkWidget *widget, GdkEventButton *event, if (event->type == GDK_BUTTON_PRESS) { GtkTreePath *pressed_path = NULL; - if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tree), (int)event->x, (int)event->y, &pressed_path, NULL, NULL, NULL)) + GtkTreeViewColumn *column = NULL; + if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tree), (int)event->x, (int)event->y, &pressed_path, &column, NULL, NULL)) { if (2 == gtk_tree_path_get_depth(pressed_path)) { @@ -203,7 +246,7 @@ static gboolean on_msgwin_button_press(GtkWidget *widget, GdkEventButton *event, S_FILEPATH, &file, S_LINE, &line, -1); - callback(file, line); + move_to_line(file, line);
g_free(file); } @@ -223,8 +266,13 @@ static gboolean on_msgwin_button_press(GtkWidget *widget, GdkEventButton *event, /* * Tree view selection changed callback */ -void on_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) +static void on_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) { + if (!gtk_tree_selection_count_selected_rows(treeselection)) + { + return; + } + GList *rows = gtk_tree_selection_get_selected_rows(treeselection, &model); GtkTreePath *path = (GtkTreePath*)rows->data;
@@ -232,7 +280,7 @@ void on_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) { GtkTreeIter iter; gtk_tree_model_get_iter ( - gtk_tree_view_get_model(GTK_TREE_VIEW(tree)), + model, &iter, path); gboolean have_source; @@ -253,8 +301,8 @@ void on_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) S_FILEPATH, &file, S_LINE, &line, -1); - callback(file, line); - + + move_to_line(file, line); g_free(file); } } @@ -266,9 +314,10 @@ void on_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) /* * inits stack trace tree */ -GtkWidget* stree_init(move_to_line_cb cb) +GtkWidget* stree_init(move_to_line_cb ml, select_frame_cb sf) { - callback = cb; + move_to_line = ml; + select_frame = sf;
/* create tree view */ store = gtk_tree_store_new ( @@ -279,6 +328,7 @@ void on_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) G_TYPE_INT, G_TYPE_STRING, G_TYPE_INT, + G_TYPE_INT, G_TYPE_INT); model = GTK_TREE_MODEL(store); @@ -290,12 +340,11 @@ void on_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(tree), FALSE); /* connect signals */ - - selection_callback = g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree))), "changed", G_CALLBACK (on_selection_changed), NULL); + g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree))), "changed", G_CALLBACK (on_selection_changed), NULL);
/* for clicking on already selected frame */ g_signal_connect(G_OBJECT(tree), "button-press-event", G_CALLBACK(on_msgwin_button_press), NULL); - + g_signal_connect(G_OBJECT(tree), "query-tooltip", G_CALLBACK (on_query_tooltip), NULL);
/* creating columns */ @@ -305,15 +354,18 @@ void on_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) column = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(column, _("Address"));
- GtkCellRenderer *renderer_arrow = gtk_cell_renderer_pixbuf_new (); + renderer_arrow = cell_renderer_frame_icon_new (); + g_object_set(renderer_arrow, "pixbuf_active", (gpointer)frame_current_pixbuf, NULL); + g_object_set(renderer_arrow, "pixbuf_highlighted", (gpointer)frame_pixbuf, NULL); gtk_tree_view_column_pack_start(column, renderer_arrow, TRUE); - gtk_tree_view_column_set_cell_data_func(column, renderer_arrow, on_render_icon, NULL, NULL); + gtk_tree_view_column_set_attributes(column, renderer_arrow, "active_frame", S_ACTIVE, NULL); + gtk_tree_view_column_set_cell_data_func(column, renderer_arrow, on_render_arrow, NULL, NULL); + g_signal_connect (G_OBJECT(renderer_arrow), "clicked", G_CALLBACK(on_frame_arrow_clicked), NULL);
GtkCellRenderer *renderer_address = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start(column, renderer_address, TRUE); gtk_tree_view_column_set_attributes(column, renderer_address, "text", S_ADRESS, NULL);
- gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
/* function */ @@ -357,7 +409,7 @@ void on_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) */ void stree_add(frame *f) { - GtkTreeRowReference *reference = (GtkTreeRowReference*)g_hash_table_lookup(threads, (gpointer)current_thread_id); + GtkTreeRowReference *reference = (GtkTreeRowReference*)g_hash_table_lookup(threads, (gpointer)active_thread_id); GtkTreeIter thread_iter; gtk_tree_model_get_iter(model, &thread_iter, gtk_tree_row_reference_get_path(reference));
@@ -378,12 +430,8 @@ void stree_add(frame *f) */ void stree_clear() { - g_signal_handler_disconnect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree))), selection_callback); - gtk_tree_store_clear(store); g_hash_table_remove_all(threads); - - selection_callback = g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree))), "changed", G_CALLBACK (on_selection_changed), NULL); }
/* @@ -393,18 +441,22 @@ void stree_select_first_frame() { gtk_tree_view_expand_all(GTK_TREE_VIEW(tree)); - GtkTreeRowReference *reference = (GtkTreeRowReference*)g_hash_table_lookup(threads, (gpointer)current_thread_id); + GtkTreeRowReference *reference = (GtkTreeRowReference*)g_hash_table_lookup(threads, (gpointer)active_thread_id); GtkTreeIter thread_iter, frame_iter; gtk_tree_model_get_iter(model, &thread_iter, gtk_tree_row_reference_get_path(reference)); if(gtk_tree_model_iter_children(model, &frame_iter, &thread_iter)) { + gtk_tree_store_set (store, &frame_iter, S_ACTIVE, TRUE, -1); + GtkTreePath* path = gtk_tree_model_get_path(model, &frame_iter); gtk_tree_selection_select_path ( gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)), path); - + gtk_tree_path_free(path); + + active_frame_index = 0; } }
@@ -413,8 +465,11 @@ void stree_select_first_frame() */ void stree_destroy() { - g_hash_table_destroy(threads); - threads = NULL; + if (threads) + { + g_hash_table_destroy(threads); + threads = NULL; + } }
/* @@ -477,6 +532,7 @@ void stree_remove_thread(int thread_id) gtk_tree_model_get_iter(model, &iter, tpath);
gtk_tree_store_remove(store, &iter); + g_hash_table_remove(threads, (gpointer)(glong)thread_id); }
@@ -485,26 +541,22 @@ void stree_remove_thread(int thread_id) */ void stree_remove_frames() { - GtkTreeRowReference *reference = (GtkTreeRowReference*)g_hash_table_lookup(threads, (gpointer)current_thread_id); + GtkTreeRowReference *reference = (GtkTreeRowReference*)g_hash_table_lookup(threads, (gpointer)active_thread_id); GtkTreeIter thread_iter; gtk_tree_model_get_iter(model, &thread_iter, gtk_tree_row_reference_get_path(reference));
- g_signal_handler_disconnect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree))), selection_callback); - GtkTreeIter child; if (gtk_tree_model_iter_children(model, &child, &thread_iter)) { while(gtk_tree_store_remove(GTK_TREE_STORE(model), &child)) ; } - - selection_callback = g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree))), "changed", G_CALLBACK (on_selection_changed), NULL); }
/* * set current thread id */ -void stree_set_current_thread_id(int thread_id) +void stree_set_active_thread_id(int thread_id) { - current_thread_id = thread_id; + active_thread_id = thread_id; }
Modified: debugger/src/stree.h 4 files changed, 2 insertions(+), 2 deletions(-) =================================================================== @@ -19,7 +19,7 @@ * MA 02110-1301, USA. */
-GtkWidget* stree_init(move_to_line_cb cb); +GtkWidget* stree_init(move_to_line_cb ml, select_frame_cb sf); void stree_destroy();
void stree_add(frame *f); @@ -31,4 +31,4 @@ void stree_select_first_frame(); void stree_remove_frames();
-void stree_set_current_thread_id(int thread_id); +void stree_set_active_thread_id(int thread_id);
Modified: debugger/src/utils.h 2 files changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -19,5 +19,5 @@ * MA 02110-1301, USA. */
-void editor_open_position(char* file, int line); +void editor_open_position(const char* file, int line); GString* get_word_at_position(ScintillaObject *sci, int position);
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: TBD).