/pidgin/main: 1e0b4fac0fed: Convert the Debug Window to a GtkWeb...

Elliott Sales de Andrade qulogic at pidgin.im
Tue Jul 24 04:03:42 EDT 2012


Changeset: 1e0b4fac0fed9ae313fc60838c9c7e9fd26746d1
Author:	 Elliott Sales de Andrade <qulogic at pidgin.im>
Date:	 2012-07-22 01:01 -0400
Branch:	 default
URL: http://hg.pidgin.im/pidgin/main/rev/1e0b4fac0fed

Description:

Convert the Debug Window to a GtkWebView.

diffstat:

 pidgin/gtkdebug.c |  478 ++++++++++++++++++++++++++++-------------------------
 1 files changed, 253 insertions(+), 225 deletions(-)

diffs (truncated from 685 to 300 lines):

diff --git a/pidgin/gtkdebug.c b/pidgin/gtkdebug.c
--- a/pidgin/gtkdebug.c
+++ b/pidgin/gtkdebug.c
@@ -33,8 +33,8 @@
 
 #include "gtkdebug.h"
 #include "gtkdialogs.h"
-#include "gtkimhtml.h"
 #include "gtkutils.h"
+#include "gtkwebview.h"
 #include "pidginstock.h"
 
 #include <gdk/gdkkeysyms.h>
@@ -47,8 +47,6 @@
 	GtkWidget *expression;
 	GtkWidget *filterlevel;
 
-	GtkListStore *store;
-
 	gboolean paused;
 
 	gboolean invert;
@@ -57,21 +55,30 @@
 	GRegex *regex;
 } DebugWindow;
 
-static const char debug_fg_colors[][8] = {
-	"#000000",    /**< All debug levels. */
-	"#666666",    /**< Misc.             */
-	"#000000",    /**< Information.      */
-	"#660000",    /**< Warnings.         */
-	"#FF0000",    /**< Errors.           */
-	"#FF0000",    /**< Fatal errors.     */
-};
+#define EMPTY_HTML \
+	"<html><head><style>" \
+	"body{white-space:pre-wrap;}" \
+	"div.l0{color:#000000;}"                    /* All debug levels. */ \
+	"div.l1{color:#666666;}"                    /* Misc.             */ \
+	"div.l2{color:#000000;}"                    /* Information.      */ \
+	"div.l3{color:#660000;}"                    /* Warnings.         */ \
+	"div.l4{color:#FF0000;}"                    /* Errors.           */ \
+	"div.l5{color:#FF0000;font-weight:bold;}"   /* Fatal errors.     */ \
+	/* Filter levels */ \
+	"div#pause~div{display:none;}" \
+	"body.l1 div.l0{display:none;}" \
+	"body.l2 div.l0,body.l2 div.l1{display:none;}" \
+	"body.l3 div.l0,body.l3 div.l1,body.l3 div.l2{display:none;}" \
+	"body.l4 div.l0,body.l4 div.l1,body.l4 div.l2,body.l4 div.l3{display:none;}" \
+	"body.l5 div.l0,body.l5 div.l1,body.l5 div.l2,body.l5 div.l3,body.l5 div.l4{display:none;}" \
+	/* Regex */ \
+	"div.hide{display:none;}" \
+	"span.regex{background-color:#ffafaf;font-weight:bold;}" \
+	"</style></head></html>"
 
 static DebugWindow *debug_win = NULL;
 static guint debug_enabled_timer = 0;
 
-static void regex_filter_all(DebugWindow *win);
-static void regex_show_all(DebugWindow *win);
-
 static gint
 debug_window_destroy(GtkWidget *w, GdkEvent *event, void *unused)
 {
@@ -125,7 +132,7 @@
 		return;
 	}
 
-	tmp = gtk_imhtml_get_text(GTK_IMHTML(win->text), NULL, NULL);
+	tmp = gtk_webview_get_body_text(GTK_WEBVIEW(win->text));
 	fprintf(fp, "Pidgin Debug Log : %s\n", purple_date_format_full(NULL));
 	fprintf(fp, "%s", tmp);
 	g_free(tmp);
@@ -145,9 +152,7 @@
 static void
 clear_cb(GtkWidget *w, DebugWindow *win)
 {
-	gtk_imhtml_clear(GTK_IMHTML(win->text));
-
-	gtk_list_store_clear(win->store);
+	gtk_webview_load_html_string(GTK_WEBVIEW(win->text), EMPTY_HTML);
 }
 
 static void
@@ -155,11 +160,19 @@
 {
 	win->paused = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(w));
 
-	if(!win->paused) {
-		if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
-			regex_filter_all(win);
-		else
-			regex_show_all(win);
+	if (win->paused) {
+		gtk_webview_append_html(GTK_WEBVIEW(win->text), "<div id=pause></div>");
+	} else {
+		WebKitDOMDocument *dom;
+		WebKitDOMElement *pause;
+
+		dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(win->text));
+		pause = webkit_dom_document_get_element_by_id(dom, "pause");
+		if (pause) {
+			WebKitDOMNode *parent;
+			parent = webkit_dom_node_get_parent_node(WEBKIT_DOM_NODE(pause));
+			webkit_dom_node_remove_child(parent, WEBKIT_DOM_NODE(pause), NULL);
+		}
 	}
 }
 
@@ -183,22 +196,133 @@
 }
 
 static void
-regex_highlight_clear(DebugWindow *win) {
-	GtkIMHtml *imhtml = GTK_IMHTML(win->text);
-	GtkTextIter s, e;
+regex_toggle_div(WebKitDOMNode *div)
+{
+	WebKitDOMDOMTokenList *classes;
 
-	gtk_text_buffer_get_start_iter(imhtml->text_buffer, &s);
-	gtk_text_buffer_get_end_iter(imhtml->text_buffer, &e);
-	gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "regex", &s, &e);
+	if (!WEBKIT_DOM_IS_HTML_ELEMENT(div))
+		return;
+
+	classes = webkit_dom_html_element_get_class_list(WEBKIT_DOM_HTML_ELEMENT(div));
+	webkit_dom_dom_token_list_toggle(classes, "hide", NULL);
 }
 
 static void
-regex_match(DebugWindow *win, const gchar *text) {
-	GtkIMHtml *imhtml = GTK_IMHTML(win->text);
+regex_highlight_clear(WebKitDOMDocument *dom)
+{
+	WebKitDOMNodeList *nodes;
+	gulong i;
+
+	/* Remove highlighting SPANs */
+	nodes = webkit_dom_document_get_elements_by_class_name(dom, "regex");
+	i = webkit_dom_node_list_get_length(nodes);
+	while (i--) {
+		WebKitDOMNode *span, *parent;
+		char *content;
+		WebKitDOMText *text;
+		GError *err = NULL;
+
+		span = webkit_dom_node_list_item(nodes, i);
+		parent = webkit_dom_node_get_parent_node(span);
+
+		content = webkit_dom_node_get_text_content(span);
+		text = webkit_dom_document_create_text_node(dom, content);
+		g_free(content);
+
+		webkit_dom_node_replace_child(parent, WEBKIT_DOM_NODE(text), span, &err);
+	}
+}
+
+static void
+regex_highlight_text_nodes(WebKitDOMDocument *dom, WebKitDOMNode *div,
+                           gint start_pos, gint end_pos)
+{
+	GSList *data = NULL;
+	WebKitDOMNode *node;
+	WebKitDOMRange *range;
+	WebKitDOMElement *span;
+	gint ind, end_ind;
+	gint this_start, this_end;
+
+	ind = 0;
+	webkit_dom_node_normalize(div);
+	node = div;
+
+	/* First, find the container nodes and offsets to apply highlighting. */
+	do {
+		if (webkit_dom_node_get_node_type(node) == 3/*TEXT_NODE*/) {
+			/* The GObject model does not correctly reflect the type, hence the
+			   regular cast. */
+			end_ind = ind + webkit_dom_character_data_get_length((WebKitDOMCharacterData*)node);
+
+			if (start_pos <= ind)
+				this_start = 0;
+			else if (start_pos < end_ind)
+				this_start = start_pos - ind;
+			else
+				this_start = -1;
+
+			if (end_pos < end_ind)
+				this_end = end_pos - ind;
+			else
+				this_end = end_ind - ind;
+
+			if (this_start != -1 && this_start < this_end) {
+				data = g_slist_prepend(data, GINT_TO_POINTER(this_end));
+				data = g_slist_prepend(data, GINT_TO_POINTER(this_start));
+				data = g_slist_prepend(data, node);
+			}
+
+			ind = end_ind;
+		}
+
+		if (webkit_dom_node_has_child_nodes(node)) {
+			node = webkit_dom_node_get_first_child(node);
+		} else {
+			while (node != div) {
+				WebKitDOMNode *next;
+
+				next = webkit_dom_node_get_next_sibling(node);
+				if (next) {
+					node = next;
+					break;
+				} else {
+					node = webkit_dom_node_get_parent_node(node);
+				}
+			}
+		}
+	} while (node != div);
+
+	/* Second, apply highlighting to saved sections. Changing the DOM is
+	   automatically reflected in all WebKit API, so we have to do this after
+	   finding the offsets, or things could get complicated. */
+	while (data) {
+		node = WEBKIT_DOM_NODE(data->data);
+		data = g_slist_delete_link(data, data);
+		this_start = GPOINTER_TO_INT(data->data);
+		data = g_slist_delete_link(data, data);
+		this_end = GPOINTER_TO_INT(data->data);
+		data = g_slist_delete_link(data, data);
+
+		range = webkit_dom_document_create_range(dom);
+		webkit_dom_range_set_start(range, node, this_start, NULL);
+		webkit_dom_range_set_end(range, node, this_end, NULL);
+		span = webkit_dom_document_create_element(dom, "span", NULL);
+		webkit_dom_html_element_set_class_name(WEBKIT_DOM_HTML_ELEMENT(span),
+		                                       "regex");
+		webkit_dom_range_surround_contents(range, WEBKIT_DOM_NODE(span), NULL);
+	}
+}
+
+static void
+regex_match(DebugWindow *win, WebKitDOMDocument *dom, WebKitDOMNode *div)
+{
 	GMatchInfo *match_info;
+	gchar *text;
 	gchar *plaintext;
 
-	if(!text)
+	text = webkit_dom_node_get_text_content(div);
+	if (!text)
 		return;
 
 	/* I don't like having to do this, but we need it for highlighting.  Plus
@@ -206,37 +330,22 @@
 	 */
 	plaintext = purple_markup_strip_html(text);
 
-	/* we do a first pass to see if it matches at all.  If it does we append
-	 * it, and work out the offsets to highlight.
+	/* We do a first pass to see if it matches at all.  If it does we work out
+	 * the offsets to highlight.
 	 */
-	if(g_regex_match(win->regex, plaintext, 0, &match_info) != win->invert) {
-		gchar *p = plaintext;
-		GtkTextIter ins;
-		gint i, offset = 0;
-
-		gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &ins,
-							gtk_text_buffer_get_insert(imhtml->text_buffer));
-		i = gtk_text_iter_get_offset(&ins);
-
-		gtk_imhtml_append_text(imhtml, text, 0);
-
+	if (g_regex_match(win->regex, plaintext, 0, &match_info) != win->invert) {
 		/* If we're not highlighting or the expression is inverted, we're
 		 * done and move on.
 		 */
-		if(!win->highlight || win->invert) {
+		if (!win->highlight || win->invert) {
 			g_free(plaintext);
 			g_match_info_free(match_info);
 			return;
 		}
 
-		/* we use a do-while to highlight the first match, and then continue
-		 * if necessary...
-		 */
-		do
-		{
+		do {
 			gint m, count;
 			gint start_pos, end_pos;
-			GtkTextIter ms, me;
 
 			if (!g_match_info_matches(match_info))
 				break;
@@ -254,111 +363,47 @@
 				if (end_pos == -1)
 					break;
 
-				gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ms,



More information about the Commits mailing list