[geany/geany-plugins] f194ba: scope - added memory.c, memory.h

Dimitar Zhekov git-noreply at geany.org
Thu Jan 17 17:42:57 UTC 2013


Branch:      refs/heads/master
Author:      Dimitar Zhekov <dimitar.zhekov at gmail.com>
Committer:   Dimitar Zhekov <dimitar.zhekov at gmail.com>
Date:        Thu, 17 Jan 2013 17:42:57 UTC
Commit:      f194ba8c143198dfb499a7169809ba2198b7350f
             https://github.com/geany/geany-plugins/commit/f194ba8c143198dfb499a7169809ba2198b7350f

Log Message:
-----------
scope - added memory.c, memory.h


Modified Paths:
--------------
    scope/src/memory.c
    scope/src/memory.h

Modified: scope/src/memory.c
414 files changed, 414 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,414 @@
+/*
+ *  memory.c
+ *
+ *  Copyright 2013 Dimitar Toshkov Zhekov <dimitar.zhekov at gmail.com>
+ *
+ *  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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "common.h"
+
+enum
+{
+	MEMORY_ADDR,
+	MEMORY_BYTES,
+	MEMORY_ASCII
+};
+
+static GtkListStore *store;
+static GtkTreeModel *model;
+static GtkTreeSelection *selection;
+
+static void on_memory_bytes_edited(G_GNUC_UNUSED GtkCellRendererText *renderer, gchar *path_str,
+	gchar *new_text, G_GNUC_UNUSED gpointer gdata)
+{
+	if (*new_text && (debug_state() & DS_SENDABLE))
+	{
+		GtkTreeIter iter;
+		const char *addr, *bytes;
+		guint i;
+
+		gtk_tree_model_get_iter_from_string(model, &iter, path_str);
+		gtk_tree_model_get(model, &iter, MEMORY_ADDR, &addr, MEMORY_BYTES, &bytes, -1);
+
+		for (i = 0; bytes[i]; i++)
+			if (!(isxdigit(bytes[i]) ? isxdigit(new_text[i]) : new_text[i] == ' '))
+				break;
+
+		if (bytes[i] || new_text[i])
+			dc_error("memory: invalid format");
+		else
+		{
+			utils_strchrepl(new_text, ' ', '\0');
+			debug_send_format(T, "07-data-write-memory-bytes 0x%s%s", addr, new_text);
+		}
+	}
+	else
+		plugin_blink();
+}
+
+static gboolean on_memory_entry_key_press(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
+	GtkEditable *editable)
+{
+	const char *text = gtk_entry_get_text(GTK_ENTRY(editable));
+	gint pos = gtk_editable_get_position(editable);
+
+	if (event->keyval <= 0x7F && ((isxdigit(event->keyval) && isxdigit(text[pos])) ||
+		(event->keyval == ' ' && text[pos] == ' ')) && event->state <= GDK_SHIFT_MASK)
+	{
+		char c = event->keyval;
+
+		gtk_editable_set_editable(editable, TRUE);
+		gtk_editable_delete_text(editable, pos, pos + 1);
+		gtk_editable_insert_text(editable, &c, 1, &pos);
+		gtk_editable_set_position(editable, pos);
+		gtk_editable_set_editable(editable, FALSE);
+		return TRUE;
+	}
+
+	return event->keyval == GDK_Insert || event->keyval == GDK_KP_Insert ||
+		event->keyval == GDK_space || event->keyval == GDK_KP_Space;
+}
+
+static const char *memory_font;
+
+static void on_memory_bytes_editing_started(G_GNUC_UNUSED GtkCellRenderer *cell,
+	GtkCellEditable *cell_editable, G_GNUC_UNUSED const gchar *path,
+	G_GNUC_UNUSED gpointer gdata)
+{
+	iff (GTK_IS_ENTRY(cell_editable), "memory_bytes: not an entry")
+	{
+		GtkEditable *editable = GTK_EDITABLE(cell_editable);
+
+		ui_widget_modify_font_from_string(GTK_WIDGET(editable), memory_font);
+		gtk_entry_set_overwrite_mode(GTK_ENTRY(editable), TRUE);
+		gtk_editable_set_editable(editable, FALSE);
+		gtk_editable_set_position(editable, 0);
+		g_signal_connect(editable, "key-press-event", G_CALLBACK(on_memory_entry_key_press),
+			editable);
+	}
+}
+
+static const TreeCell memory_cells[] =
+{
+	{ "memory_bytes", G_CALLBACK(on_memory_bytes_edited) },
+	{ NULL, NULL }
+};
+
+static guint pointer_size;
+static char *addr_format;
+#define MAX_BYTES_PER_LINE 128
+#define MAX_POINTER_SIZE 8
+
+static gint back_bytes_per_line;
+static gint bytes_per_line;
+static gint bytes_per_group = 1;
+
+static void memory_configure(void)
+{
+	gint groups_per_line;
+
+	back_bytes_per_line = pref_memory_bytes_per_line;
+	bytes_per_line = pref_memory_bytes_per_line;
+	if ((unsigned) (bytes_per_line - 8) > MAX_BYTES_PER_LINE - 8)
+		bytes_per_line = 16;
+
+	groups_per_line = bytes_per_line / bytes_per_group;
+	bytes_per_line = groups_per_line * bytes_per_group;
+}
+
+static guint64 memory_start;
+static guint memory_count = 0;
+#define MAX_BYTES (128 * MAX_BYTES_PER_LINE)  /* +1 incomplete line */
+
+static void write_block(guint64 start, const char *contents, guint count)
+{
+	if (!memory_count)
+		memory_start = start;
+
+	while (memory_count < MAX_BYTES)
+	{
+		GtkTreeIter iter;
+		char *addr = g_strdup_printf(addr_format, start);
+		GString *bytes = g_string_sized_new(bytes_per_line * 3);
+		GString *ascii = g_string_new(" ");
+		gint n = 0;
+
+		gtk_list_store_append(store, &iter);
+
+		while (n < bytes_per_line)
+		{
+			char locale;
+			gchar *utf8;
+
+			g_string_append_len(bytes, contents, 2);
+			contents += 2;
+			memory_count++;
+			locale = strtol(bytes->str + bytes->len - 2, NULL, 16);
+			utf8 = locale >= 0x20 ? g_locale_to_utf8(&locale, 1, NULL, NULL, NULL) : NULL;
+
+			if (utf8)
+			{
+				g_string_append(ascii, utf8);
+				g_free(utf8);
+			}
+			else
+				g_string_append_c(ascii, '.');  /* 0xfffd? */
+
+			if (++n % bytes_per_group == 0)
+				g_string_append_c(bytes, ' ');
+
+			if (!--count)
+				break;
+		}
+
+		while (n < bytes_per_line)
+		{
+			g_string_append(bytes, "  ");
+
+			if (++n % bytes_per_group == 0)
+				g_string_append_c(bytes, ' ');
+		}
+
+		gtk_list_store_set(store, &iter, MEMORY_ADDR, addr, MEMORY_BYTES, bytes->str,
+			MEMORY_ASCII, ascii->str, -1);
+
+		g_free(addr);
+		g_string_free(bytes, TRUE);
+		g_string_free(ascii, TRUE);
+
+		if (!count)
+			break;
+
+		start += bytes_per_line;
+	}
+
+	if (count)
+		dc_error("memory: too much data");
+}
+
+static void memory_node_read(const ParseNode *node, G_GNUC_UNUSED gpointer gdata)
+{
+	iff (node->type == PT_ARRAY, "memory: contains value")
+	{
+		GArray *nodes = (GArray *) node->value;
+		const char *begin = parse_find_value(nodes, "begin");
+		const char *contents = parse_find_value(nodes, "contents");
+
+		iff (begin && contents, "memory: no begin or contents")
+		{
+			guint64 start;
+			guint64 count = strlen(contents) / 2;
+
+			sscanf(begin, "%" G_GINT64_MODIFIER "i", &start);
+
+			iff (count, "memory: contents too short")
+				write_block(start, contents, count);
+		}
+	}
+}
+
+void on_memory_read_bytes(GArray *nodes)
+{
+	if (pointer_size <= MAX_POINTER_SIZE)
+	{
+		GtkTreeIter iter;
+		char *addr = NULL;
+
+		if (gtk_tree_selection_get_selected(selection, NULL, &iter))
+		{
+			gtk_tree_model_get(model, &iter, MEMORY_ADDR, &addr, -1);
+			addr = strdup(addr);
+		}
+
+		memory_clear();
+
+		if (pref_memory_bytes_per_line != back_bytes_per_line)
+		{
+			memory_configure();
+			gtk_tree_view_column_queue_resize(get_column("memory_bytes_column"));
+			gtk_tree_view_column_queue_resize(get_column("memory_ascii_column"));
+		}
+
+		array_foreach(parse_lead_array(nodes), (GFunc) memory_node_read,
+			GINT_TO_POINTER(TRUE));
+
+		if (addr)
+		{
+			if (model_find(model, &iter, MEMORY_ADDR, addr))
+				utils_tree_set_cursor(selection, &iter, -1);
+			g_free(addr);
+		}
+	}
+}
+
+void memory_clear(void)
+{
+	gtk_list_store_clear(store);
+	memory_count = 0;
+}
+
+gboolean memory_update(void)
+{
+	if (memory_count)
+	{
+		debug_send_format(T, "04-data-read-memory-bytes 0x%" G_GINT64_MODIFIER "x %u",
+			memory_start, memory_count);
+	}
+	return TRUE;
+}
+
+static void on_memory_refresh(G_GNUC_UNUSED const MenuItem *menu_item)
+{
+	debug_send_format(T, "-data-read-memory-bytes 0x%" G_GINT64_MODIFIER "x %u",
+		memory_start, memory_count);
+}
+
+static void on_memory_read(G_GNUC_UNUSED const MenuItem *menu_item)
+{
+	GString *command = g_string_new("-data-read-memory-bytes ");
+	gchar *expr = utils_get_default_selection();
+
+	if (expr)
+	{
+		g_string_append(command, expr);
+		g_free(expr);
+	}
+	else if (memory_count)
+	{
+		g_string_append_printf(command, "0x%" G_GINT64_MODIFIER "x %u", memory_start,
+			memory_count);
+	}
+
+	view_command_line(command->str, _("Read Memory"), " ", TRUE);
+	g_string_free(command, TRUE);
+}
+
+static void on_memory_copy(G_GNUC_UNUSED const MenuItem *menu_item)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	const char *addr, *bytes;
+	const gchar *ascii;
+	gchar *string;
+
+	gtk_tree_selection_get_selected(selection, &model, &iter);
+	gtk_tree_model_get(model, &iter, MEMORY_ADDR, &addr, MEMORY_BYTES, &bytes,
+		MEMORY_ASCII, &ascii, -1);
+	string = g_strdup_printf("%s%s%s", addr, bytes, ascii);
+	gtk_clipboard_set_text(gtk_widget_get_clipboard(menu_item->widget,
+		GDK_SELECTION_CLIPBOARD), string, -1);
+	g_free(string);
+}
+
+static void on_memory_clear(G_GNUC_UNUSED const MenuItem *menu_item)
+{
+	memory_clear();
+}
+
+static void on_memory_group_display(const MenuItem *menu_item)
+{
+	guint i;
+
+	for (i = 0; (1 << i) < bytes_per_group; i++);
+	menu_item_set_active(menu_item + i + 1, TRUE);
+}
+
+static void on_memory_group_update(const MenuItem *menu_item)
+{
+	bytes_per_group = 1 << GPOINTER_TO_INT(menu_item->gdata);
+	back_bytes_per_line = 0;
+
+	if (memory_count)
+		on_memory_refresh(menu_item);
+}
+
+#define DS_FRESHABLE (DS_SENDABLE | DS_EXTRA_2)
+#define DS_COPYABLE (DS_BASICS | DS_EXTRA_1)
+#define DS_CLEARABLE (DS_ACTIVE | DS_EXTRA_2)
+
+#define GROUP_ITEM(count, POWER) \
+	{ ("memory_group_"count), on_memory_group_update, DS_SENDABLE, NULL, \
+		GINT_TO_POINTER(POWER) }
+
+static MenuItem memory_menu_items[] =
+{
+	{ "memory_refresh", on_memory_refresh,       DS_FRESHABLE,  NULL, NULL },
+	{ "memory_read",    on_memory_read,          DS_SENDABLE,   NULL, NULL },
+	{ "memory_copy",    on_memory_copy,          DS_COPYABLE,   NULL, NULL },
+	{ "memory_clear",   on_memory_clear,         DS_CLEARABLE,  NULL, NULL },
+	{ "memory_group",   on_memory_group_display, DS_SENDABLE,   NULL, NULL },
+	GROUP_ITEM("1", 0),
+	GROUP_ITEM("2", 1),
+	GROUP_ITEM("4", 2),
+	GROUP_ITEM("8", 3),
+	{ NULL, NULL, 0, NULL, NULL }
+};
+
+static guint memory_menu_extra_state(void)
+{
+	return (gtk_tree_selection_get_selected(selection, NULL, NULL) << DS_INDEX_1) |
+		(memory_count != 0) << DS_INDEX_1;
+}
+
+static MenuInfo memory_menu_info = { memory_menu_items, memory_menu_extra_state, 0 };
+
+static gboolean on_memory_key_press(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
+	gpointer gdata)
+{
+	if (event->keyval == GDK_Insert || event->keyval == GDK_KP_Insert)
+	{
+		menu_item_execute(&memory_menu_info, (const MenuItem *) gdata, FALSE);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+void memory_init(void)
+{
+	GtkWidget *tree = GTK_WIDGET(view_connect("memory_view", &model, &selection,
+		memory_cells, "memory_window", NULL));
+
+	store = GTK_LIST_STORE(model);
+	memory_font = *pref_memory_font ? pref_memory_font : pref_vte_font;
+	ui_widget_modify_font_from_string(tree, memory_font);
+	g_signal_connect(get_object("memory_bytes"), "editing-started",
+		G_CALLBACK(on_memory_bytes_editing_started), NULL);
+	g_signal_connect(tree, "key-press-event", G_CALLBACK(on_memory_key_press),
+		(gpointer) menu_item_find(memory_menu_items, "memory_read"));
+
+	pointer_size = sizeof(void *) > sizeof &memory_init ? sizeof(void *) :
+		sizeof &memory_init;
+	addr_format = g_strdup_printf("%%0%u" G_GINT64_MODIFIER "x  ", pointer_size * 2);
+	memory_configure();
+
+	if (pointer_size > MAX_POINTER_SIZE)
+	{
+		msgwin_status_add(_("Scope: pointer size > 8, Data disabled."));
+		gtk_widget_hide(tree);
+	}
+	else
+		menu_connect("memory_menu", &memory_menu_info, tree);
+}
+
+void memory_finalize(void)
+{
+	g_free(addr_format);
+}


Modified: scope/src/memory.h
32 files changed, 32 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,32 @@
+/*
+ *  utils.h
+ *
+ *  Copyright 2013 Dimitar Toshkov Zhekov <dimitar.zhekov at gmail.com>
+ *
+ *  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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MEMORY_H
+
+void on_memory_read_bytes(GArray *nodes);
+void on_memory_modified(GArray *nodes);
+
+void memory_clear(void);
+gboolean memory_update(void);
+
+void memory_init(void);
+void memory_finalize(void);
+
+#define MEMORY_H 1
+#endif



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Plugins-Commits mailing list