changeset 16964:ab45289d2c36

Allow saving custom smileys by right-clicking on them. And use the custom smileys only on the received messages, not for the system/etc. messages.
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Wed, 09 May 2007 01:21:15 +0000
parents 919515748253
children fc3f3714b72a 825f0fe66304
files pidgin/gtkconv.c pidgin/gtkimhtml.c
diffstat 2 files changed, 93 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/pidgin/gtkconv.c	Wed May 09 00:02:17 2007 +0000
+++ b/pidgin/gtkconv.c	Wed May 09 01:21:15 2007 +0000
@@ -4978,6 +4978,8 @@
 	char *bracket;
 	int tag_count = 0;
 	gboolean is_rtl_message = FALSE;
+	GtkSmileyTree *tree = NULL;
+	GHashTable *smiley_data = NULL;
 
 	g_return_if_fail(conv != NULL);
 	gtkconv = PIDGIN_CONVERSATION(conv);
@@ -5121,6 +5123,17 @@
 		gtk_font_options |= GTK_IMHTML_USE_POINTSIZE;
 	}
 
+	if (!(flags & PURPLE_MESSAGE_RECV))
+	{
+		/* Temporarily revert to the original smiley-data to avoid showing up
+		 * custom smileys of the buddy when sending message
+		 */
+		tree = GTK_IMHTML(gtkconv->imhtml)->default_smilies;
+		GTK_IMHTML(gtkconv->imhtml)->default_smilies =
+								GTK_IMHTML(gtkconv->entry)->default_smilies;
+		smiley_data = GTK_IMHTML(gtkconv->imhtml)->smiley_data;
+		GTK_IMHTML(gtkconv->imhtml)->smiley_data = GTK_IMHTML(gtkconv->entry)->smiley_data;
+	}
 
 	/* TODO: These colors should not be hardcoded so log.c can use them */
 	if (flags & PURPLE_MESSAGE_RAW) {
@@ -5152,25 +5165,11 @@
 		 * escaped entities making the string longer */
 		int tag_start_offset = alias ? (strlen(alias_escaped) - strlen(alias)) : 0;
 		int tag_end_offset = 0;
-		GtkSmileyTree *tree = NULL;
-		GHashTable *smiley_data = NULL;
 
 		/* Enforce direction on alias */
 		if (is_rtl_message)
 			str_embed_direction_chars(&alias_escaped);
 
-		if (flags & PURPLE_MESSAGE_SEND)
-		{
-			/* Temporarily revert to the original smiley-data to avoid showing up
-			 * custom smileys of the buddy when sending message
-			 */
-			tree = GTK_IMHTML(gtkconv->imhtml)->default_smilies;
-			GTK_IMHTML(gtkconv->imhtml)->default_smilies =
-									GTK_IMHTML(gtkconv->entry)->default_smilies;
-			smiley_data = GTK_IMHTML(gtkconv->imhtml)->smiley_data;
-			GTK_IMHTML(gtkconv->imhtml)->smiley_data = GTK_IMHTML(gtkconv->entry)->smiley_data;
-		}
-
 		if (flags & PURPLE_MESSAGE_WHISPER) {
 			str = g_malloc(1024);
 
@@ -5312,13 +5311,6 @@
 		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml),
 							 with_font_tag, gtk_font_options | gtk_font_options_all);
 
-		if (flags & PURPLE_MESSAGE_SEND)
-		{
-			/* Restore the smiley-data */
-			GTK_IMHTML(gtkconv->imhtml)->default_smilies = tree;
-			GTK_IMHTML(gtkconv->imhtml)->smiley_data = smiley_data;
-		}
-
 		g_free(with_font_tag);
 		g_free(new_message);
 	}
@@ -5344,6 +5336,13 @@
 		gtkconv_set_unseen(gtkconv, unseen);
 	}
 
+	if (!(flags & PURPLE_MESSAGE_RECV))
+	{
+		/* Restore the smiley-data */
+		GTK_IMHTML(gtkconv->imhtml)->default_smilies = tree;
+		GTK_IMHTML(gtkconv->imhtml)->smiley_data = smiley_data;
+	}
+
 	purple_signal_emit(pidgin_conversations_get_handle(),
 		(type == PURPLE_CONV_TYPE_IM ? "displayed-im-msg" : "displayed-chat-msg"),
 		account, name, displaying, conv, flags);
@@ -5607,15 +5606,25 @@
 				icon, smiley->icon, smiley->smile);
 #endif
 		if (icon) {
+			GList *wids;
 			gtk_widget_show(icon);
 
 			anchor = GTK_TEXT_CHILD_ANCHOR(current->data);
+			wids = gtk_text_child_anchor_get_widgets(anchor);
 
 			g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", purple_unescape_html(smiley->smile), g_free);
 			g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley->smile), g_free);
 
-			if (smiley->imhtml)
-				gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(smiley->imhtml), icon, anchor);
+			if (smiley->imhtml) {
+				if (wids) {
+					GList *children = gtk_container_get_children(GTK_CONTAINER(wids->data));
+					g_list_foreach(children, (GFunc)gtk_widget_destroy, NULL);
+					g_list_free(children);
+					gtk_container_add(GTK_CONTAINER(wids->data), icon);
+				} else
+					gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(smiley->imhtml), icon, anchor);
+			}
+			g_list_free(wids);
 		}
 
 	}
--- a/pidgin/gtkimhtml.c	Wed May 09 00:02:17 2007 +0000
+++ b/pidgin/gtkimhtml.c	Wed May 09 01:21:15 2007 +0000
@@ -1872,18 +1872,8 @@
 }
 
 static GdkPixbufAnimation *
-gtk_smiley_tree_image (GtkIMHtml     *imhtml,
-		       const gchar   *sml,
-		       const gchar   *text)
+gtk_smiley_get_image(GtkIMHtmlSmiley *smiley)
 {
-
-	GtkIMHtmlSmiley *smiley;
-
-	smiley = gtk_imhtml_smiley_get(imhtml,sml,text);
-
-	if (!smiley)
-		return NULL;
-
 	if (!smiley->icon && smiley->file) {
 		smiley->icon = gdk_pixbuf_animation_new_from_file(smiley->file, NULL);
 	} else if (!smiley->icon && smiley->loader) {
@@ -1895,6 +1885,21 @@
 	return smiley->icon;
 }
 
+static GdkPixbufAnimation *
+gtk_smiley_tree_image (GtkIMHtml     *imhtml,
+		       const gchar   *sml,
+		       const gchar   *text)
+{
+	GtkIMHtmlSmiley *smiley;
+
+	smiley = gtk_imhtml_smiley_get(imhtml,sml,text);
+
+	if (!smiley)
+		return NULL;
+
+	return gtk_smiley_get_image(smiley);
+}
+
 #define VALID_TAG(x)	if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) {	\
 				*tag = g_strndup (string, strlen (x));		\
 				*len = strlen (x) + 1;				\
@@ -3363,6 +3368,29 @@
 		return FALSE; /* Let clicks go through if we didn't catch anything */
 
 }
+
+static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley)
+{
+	GdkPixbufAnimation *anim = NULL;
+	GdkPixbuf *pix = NULL;
+	GtkIMHtmlScalable *image = NULL;
+	gboolean ret;
+	
+	if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3)
+		return FALSE;
+
+	anim = gtk_smiley_get_image(smiley);
+	if (!anim)
+		return FALSE;
+
+	pix = gdk_pixbuf_animation_get_static_image(anim);
+	image = gtk_imhtml_image_new(pix, NULL, 0);
+	ret = gtk_imhtml_image_clicked(w, event, (GtkIMHtmlImage*)image);
+	g_object_set_data_full(G_OBJECT(w), "image-data", image, (GDestroyNotify)gtk_imhtml_image_free);
+	g_object_unref(G_OBJECT(pix));
+	return ret;
+}
+
 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale)
 {
 	GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
@@ -4378,9 +4406,10 @@
 	GdkPixbuf *pixbuf = NULL;
 	GdkPixbufAnimation *annipixbuf = NULL;
 	GtkWidget *icon = NULL;
-	GtkTextChildAnchor *anchor;
+	GtkTextChildAnchor *anchor = NULL;
 	char *unescaped = purple_unescape_html(smiley);
 	GtkIMHtmlSmiley *imhtml_smiley = gtk_imhtml_smiley_get(imhtml, sml, unescaped);
+	GtkWidget *ebox = NULL;
 
 	if (imhtml->format_functions & GTK_IMHTML_SMILEY) {
 		annipixbuf = gtk_smiley_tree_image(imhtml, sml, unescaped);
@@ -4397,6 +4426,7 @@
 					if (anim) {
 						GdkPixbuf *pb = gdk_pixbuf_animation_get_static_image(anim);
 						gtk_image_set_from_pixbuf(image, pb);
+						g_object_unref(G_OBJECT(pb));
 					}
 				} else {
  					imhtml->num_animations++;
@@ -4407,6 +4437,12 @@
 		}
 	}
 
+	if (imhtml_smiley->flags & GTK_IMHTML_SMILEY_CUSTOM) {
+		ebox = gtk_event_box_new();
+		gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
+		gtk_widget_show(ebox);
+	}
+
 	if (icon) {
 		anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
 		g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(unescaped), g_free);
@@ -4419,14 +4455,26 @@
 		g_signal_connect(G_OBJECT(icon), "expose-event", G_CALLBACK(image_expose), NULL);
 
 		gtk_widget_show(icon);
-		gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor);
+		if (ebox)
+			gtk_container_add(GTK_CONTAINER(ebox), icon);
+		gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox ? ebox : icon, anchor);
 	} else if (imhtml_smiley != NULL && (imhtml->format_functions & GTK_IMHTML_SMILEY)) {
 		anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
 		imhtml_smiley->anchors = g_slist_append(imhtml_smiley->anchors, anchor);
+		if (ebox) {
+			GtkWidget *img = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_MENU);
+			gtk_container_add(GTK_CONTAINER(ebox), img);
+			gtk_widget_show(img);
+			gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox, anchor);
+		}
 	} else {
 		gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1);
 	}
 
+	if (ebox) {
+		g_signal_connect(G_OBJECT(ebox), "event", G_CALLBACK(gtk_imhtml_smiley_clicked), imhtml_smiley);
+	}
+
 	g_free(unescaped);
 }