/pidgin/main: bc5253318167: Show smiley images in the input entr...

Tomasz Wasilczyk twasilczyk at pidgin.im
Tue Apr 8 12:01:13 EDT 2014


Changeset: bc525331816791228c48650e79ddb38f4c605dff
Author:	 Tomasz Wasilczyk <twasilczyk at pidgin.im>
Date:	 2014-04-08 18:01 +0200
Branch:	 default
URL: https://hg.pidgin.im/pidgin/main/rev/bc5253318167

Description:

Show smiley images in the input entry and fix some smiley and inline image issues

diffstat:

 libpurple/protocols/gg/message-prpl.c |   4 +-
 pidgin/gtkconv.c                      |  47 +++++++++++-------------------
 pidgin/gtkwebview.c                   |  53 +++++++++++++++++++++++++++++++++-
 pidgin/gtkwebview.h                   |  11 +++++++
 pidgin/gtkwebviewtoolbar.c            |  40 +++++++++++++++++++------
 5 files changed, 112 insertions(+), 43 deletions(-)

diffs (truncated from 344 to 300 lines):

diff --git a/libpurple/protocols/gg/message-prpl.c b/libpurple/protocols/gg/message-prpl.c
--- a/libpurple/protocols/gg/message-prpl.c
+++ b/libpurple/protocols/gg/message-prpl.c
@@ -654,7 +654,7 @@ gchar * ggp_message_format_to_gg(PurpleC
 			if (style)
 				styles = ggp_html_css_attribs(style);
 
-			if ((val = g_hash_table_lookup(styles,
+			if (styles && (val = g_hash_table_lookup(styles,
 				"background-color")) != NULL)
 			{
 				int color = ggp_html_decode_color(val);
@@ -662,7 +662,7 @@ gchar * ggp_message_format_to_gg(PurpleC
 				font_new->bgcolor = color;
 			}
 
-			if ((val = g_hash_table_lookup(styles,
+			if (styles && (val = g_hash_table_lookup(styles,
 				"color")) != NULL)
 			{
 				int color = ggp_html_decode_color(val);
diff --git a/pidgin/gtkconv.c b/pidgin/gtkconv.c
--- a/pidgin/gtkconv.c
+++ b/pidgin/gtkconv.c
@@ -621,7 +621,7 @@ send_cb(GtkWidget *widget, PidginConvers
 	PurpleAccount *account;
 	PurpleConnection *gc;
 	PurpleMessageFlags flags = 0;
-	char *buf, *clean;
+	char *buf;
 
 	account = purple_conversation_get_account(conv);
 
@@ -637,17 +637,13 @@ send_cb(GtkWidget *widget, PidginConvers
 	if (!purple_account_is_connected(account))
 		return;
 
+	if (pidgin_webview_is_empty(PIDGIN_WEBVIEW(gtkconv->entry)))
+		return;
+
 	buf = pidgin_webview_get_body_html(PIDGIN_WEBVIEW(gtkconv->entry));
-	clean = pidgin_webview_get_body_text(PIDGIN_WEBVIEW(gtkconv->entry));
 
 	gtk_widget_grab_focus(gtkconv->entry);
 
-	if (!*clean) {
-		g_free(buf);
-		g_free(clean);
-		return;
-	}
-
 	purple_idle_touch();
 
 #if 0
@@ -678,7 +674,6 @@ send_cb(GtkWidget *widget, PidginConvers
 		purple_conversation_send_with_flags(conv, buf, flags);
 	}
 
-	g_free(clean);
 	g_free(buf);
 
 	conversation_entry_clear(gtkconv);
@@ -1951,24 +1946,22 @@ gtkconv_cycle_focus(PidginConversation *
 static void
 update_typing_inserting(PidginConversation *gtkconv)
 {
-	gchar *text;
+	gboolean is_empty;
 
 	g_return_if_fail(gtkconv != NULL);
 
-	text = pidgin_webview_get_body_text(PIDGIN_WEBVIEW(gtkconv->entry));
-
-	got_typing_keypress(gtkconv, text[0] == '\0' || !strcmp(text, "\n"));
-
-	g_free(text);
+	is_empty = pidgin_webview_is_empty(PIDGIN_WEBVIEW(gtkconv->entry));
+
+	got_typing_keypress(gtkconv, is_empty);
 }
 
 static gboolean
 update_typing_deleting_cb(PidginConversation *gtkconv)
 {
 	PurpleIMConversation *im = PURPLE_IM_CONVERSATION(gtkconv->active_conv);
-	gchar *text = pidgin_webview_get_body_text(PIDGIN_WEBVIEW(gtkconv->entry));
-
-	if (!*text || !strcmp(text, "\n")) {
+	gboolean is_empty = pidgin_webview_is_empty(PIDGIN_WEBVIEW(gtkconv->entry));
+
+	if (!is_empty) {
 		/* We deleted all the text, so turn off typing. */
 		purple_im_conversation_stop_send_typed_timeout(im);
 
@@ -1980,7 +1973,6 @@ update_typing_deleting_cb(PidginConversa
 		/* We're deleting, but not all of it, so it counts as typing. */
 		got_typing_keypress(gtkconv, FALSE);
 	}
-	g_free(text);
 
 	return FALSE;
 }
@@ -1988,16 +1980,14 @@ update_typing_deleting_cb(PidginConversa
 static void
 update_typing_deleting(PidginConversation *gtkconv)
 {
-	gchar *text;
+	gboolean is_empty;
 
 	g_return_if_fail(gtkconv != NULL);
 
-	text = pidgin_webview_get_body_text(PIDGIN_WEBVIEW(gtkconv->entry));
-
-	if (*text && strcmp(text, "\n"))
+	is_empty = pidgin_webview_is_empty(PIDGIN_WEBVIEW(gtkconv->entry));
+
+	if (!is_empty)
 		purple_timeout_add(0, (GSourceFunc)update_typing_deleting_cb, gtkconv);
-
-	g_free(text);
 }
 
 static gboolean
@@ -4926,7 +4916,7 @@ entry_popup_menu_cb(PidginWebView *webvi
 {
 	GtkWidget *menuitem;
 	PidginConversation *gtkconv = data;
-	char *tmp;
+	gboolean is_empty;
 
 	g_return_if_fail(menu != NULL);
 	g_return_if_fail(gtkconv != NULL);
@@ -4934,10 +4924,9 @@ entry_popup_menu_cb(PidginWebView *webvi
 	menuitem = pidgin_new_item_from_stock(NULL, _("_Send"), NULL,
 	                                      G_CALLBACK(send_cb), gtkconv,
 	                                      0, 0, NULL);
-	tmp = pidgin_webview_get_body_text(webview);
-	if (!tmp || !*tmp)
+	is_empty = pidgin_webview_is_empty(webview);
+	if (is_empty)
 		gtk_widget_set_sensitive(menuitem, FALSE);
-	g_free(tmp);
 	gtk_menu_shell_insert(GTK_MENU_SHELL(menu), menuitem, 0);
 
 	menuitem = gtk_separator_menu_item_new();
diff --git a/pidgin/gtkwebview.c b/pidgin/gtkwebview.c
--- a/pidgin/gtkwebview.c
+++ b/pidgin/gtkwebview.c
@@ -121,6 +121,9 @@ typedef struct _PidginWebViewPriv {
 
 static WebKitWebViewClass *parent_class = NULL;
 
+static GRegex *smileys_re = NULL;
+static GRegex *empty_html_re = NULL;
+
 
 /******************************************************************************
  * Helpers
@@ -1256,6 +1259,14 @@ pidgin_webview_class_init(PidginWebViewC
 
 	purple_prefs_add_none(PIDGIN_PREFS_ROOT "/webview");
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/webview/inspector_enabled", FALSE);
+
+	g_return_if_fail(smileys_re == NULL);
+	g_return_if_fail(empty_html_re == NULL);
+	smileys_re = g_regex_new("<img[^>]* class=\"emoticon "
+		"[^\"^>]*\"[^>]*alt=\"([^\"^>]+)\"[^>]*>",
+		G_REGEX_DOTALL | G_REGEX_OPTIMIZE, 0, NULL);
+	empty_html_re = g_regex_new("<(?!img)[^>]*>",
+		G_REGEX_DOTALL | G_REGEX_OPTIMIZE, 0, NULL);
 }
 
 static void
@@ -1680,20 +1691,28 @@ pidgin_webview_get_head_html(PidginWebVi
 	return html;
 }
 
+static gchar *
+pidgin_webview_strip_smileys(const gchar *text)
+{
+	return g_regex_replace(smileys_re, text, -1, 0, "\\1", 0, NULL);
+}
+
 gchar *
 pidgin_webview_get_body_html(PidginWebView *webview)
 {
 	WebKitDOMDocument *doc;
 	WebKitDOMHTMLElement *body;
-	gchar *html;
+	gchar *html, *stripped;
 
 	g_return_val_if_fail(webview != NULL, NULL);
 
 	doc = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview));
 	body = webkit_dom_document_get_body(doc);
 	html = webkit_dom_html_element_get_inner_html(body);
+	stripped = pidgin_webview_strip_smileys(html);
+	g_free(html);
 
-	return html;
+	return stripped;
 }
 
 gchar *
@@ -1734,6 +1753,36 @@ pidgin_webview_get_selected_text(PidginW
 		return NULL;
 }
 
+static gchar *
+pidgin_webview_strip_empty_html(const gchar *text)
+{
+	return g_regex_replace(empty_html_re, text, -1, 0, "", 0, NULL);
+}
+
+gboolean
+pidgin_webview_is_empty(PidginWebView *webview)
+{
+	gchar *html, *tmp;
+	gboolean is_empty;
+
+	g_return_val_if_fail(webview != NULL, TRUE);
+
+	html = pidgin_webview_get_body_html(webview);
+	tmp = purple_strreplace(html, " ", " ");
+	g_free(html);
+	html = tmp;
+
+	tmp = pidgin_webview_strip_empty_html(html);
+	g_free(html);
+	html = tmp;
+
+	g_strstrip(html);
+	is_empty = (html[0] == '\0');
+	g_free(html);
+
+	return is_empty;
+}
+
 void
 pidgin_webview_get_caret(PidginWebView *webview, WebKitDOMNode **container_ret,
 		glong *pos_ret)
diff --git a/pidgin/gtkwebview.h b/pidgin/gtkwebview.h
--- a/pidgin/gtkwebview.h
+++ b/pidgin/gtkwebview.h
@@ -415,6 +415,17 @@ gchar *pidgin_webview_get_body_text(Pidg
 gchar *pidgin_webview_get_selected_text(PidginWebView *webview);
 
 /**
+ * pidgin_webview_is_empty:
+ * @webview: the PidginWebView.
+ *
+ * Checks, if the @webview is empty.
+ *
+ * Returns %TRUES, if the @webview is empty, %FALSE otherwise.
+ */
+gboolean
+pidgin_webview_is_empty(PidginWebView *webview);
+
+/**
  * pidgin_webview_get_caret:
  * @webview:       The PidginWebView
  * @container_ret: A pointer to a pointer to a WebKitDOMNode. This pointer
diff --git a/pidgin/gtkwebviewtoolbar.c b/pidgin/gtkwebviewtoolbar.c
--- a/pidgin/gtkwebviewtoolbar.c
+++ b/pidgin/gtkwebviewtoolbar.c
@@ -702,15 +702,29 @@ close_smiley_dialog(PidginWebViewToolbar
 static void
 insert_smiley_text(GtkWidget *widget, PidginWebViewToolbar *toolbar)
 {
-	char *smiley_text, *escaped_smiley;
+	PurpleSmiley *smiley;
+	PurpleStoredImage *image;
+	int image_id;
+	gchar *escaped_smiley, *smiley_html;
+	const gchar *smiley_class;
 
-	smiley_text = g_object_get_data(G_OBJECT(widget), "smiley_text");
-	escaped_smiley = g_markup_escape_text(smiley_text, -1);
+	smiley = g_object_get_data(G_OBJECT(widget), "smiley");
+	smiley_class = g_object_get_data(G_OBJECT(widget), "smiley-class");
+	image = purple_smiley_get_image(smiley);
+	image_id = purple_imgstore_add_with_id(image);
+
+	escaped_smiley = g_markup_escape_text(
+		purple_smiley_get_shortcut(smiley), -1);
+	smiley_html = g_strdup_printf("<img src=\"" PURPLE_STORED_IMAGE_PROTOCOL
+		"%d\" class=\"emoticon %s-emoticon\" alt=\"%s\" title=\"%s\">",
+		image_id, smiley_class, escaped_smiley, escaped_smiley);
+
+	g_free(escaped_smiley);
 
 	pidgin_webview_append_html(PIDGIN_WEBVIEW(toolbar->webview),
-		escaped_smiley);
+		smiley_html);
 
-	g_free(escaped_smiley);
+	g_free(smiley_html);
 
 	close_smiley_dialog(toolbar);
 }



More information about the Commits mailing list