[geany/geany-plugins] 093fdc: Merge pull request #18 from cesspit/master

Frank Lanitz git-noreply at xxxxx
Wed Mar 14 20:00:10 UTC 2012


Branch:      refs/heads/master
Author:      Frank Lanitz <frank at frank.uvena.de>
Committer:   Frank Lanitz <frank at frank.uvena.de>
Date:        Wed, 14 Mar 2012 20:00:10
Commit:      093fdc6260681ea6baa5657bb1d8ca2ef9f9ced8
             https://github.com/geany/geany-plugins/commit/093fdc6260681ea6baa5657bb1d8ca2ef9f9ced8

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 at apetukhov.ru>
+
+	* switching between frames by clicking a frame arrow in the stack window
+
 18-02-2012 	Alexander Petukhov <devel at 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).



More information about the Plugins-Commits mailing list