diff --git a/src/embeddedvideo.c b/src/embeddedvideo.c index 2c7f1ed..5ad4bbe 100644 --- a/src/embeddedvideo.c +++ b/src/embeddedvideo.c @@ -16,9 +16,9 @@ #include #include -static GHashTable *ht_buttons = NULL; /* */ -static GHashTable *ht_signal_handlers_it = NULL; /* */ -static GHashTable *ht_signal_handlers_eua = NULL; /* */ +static GHashTable *ht_buttons = NULL; /* */ +static GHashTable *ht_signal_handlers_it = NULL; /* */ +static GHashTable *ht_signal_handlers_eua = NULL; /* */ static void insert_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *location, @@ -52,13 +52,13 @@ attach_to_conversation(gpointer data, gpointer user_data) GtkIMHtml *imhtml = GTK_IMHTML(gtkconv->imhtml); g_assert(GTK_IS_IMHTML(imhtml)); - gulong it_handler_id = g_signal_connect_after(G_OBJECT(imhtml->text_buffer), + gulong handler_id = g_signal_connect_after(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(insert_text_cb), imhtml); - g_hash_table_insert(ht_signal_handlers_it, imhtml->text_buffer, (gpointer) it_handler_id); + g_hash_table_insert(ht_signal_handlers_it, imhtml->text_buffer, (gpointer) handler_id); - gulong eua_handler_id = g_signal_connect(G_OBJECT(imhtml->text_buffer), + handler_id = g_signal_connect(G_OBJECT(imhtml->text_buffer), "end-user-action", G_CALLBACK(videoframes_text_buffer_end_user_action_cb), NULL); - g_hash_table_insert(ht_signal_handlers_eua, imhtml->text_buffer, (gpointer) eua_handler_id); + g_hash_table_insert(ht_signal_handlers_eua, imhtml->text_buffer, (gpointer) handler_id); } static void @@ -70,14 +70,14 @@ detach_from_conversation(gpointer data, gpointer user_data) GtkIMHtml *imhtml = GTK_IMHTML(gtkconv->imhtml); g_assert(GTK_IS_IMHTML(imhtml)); - gulong it_handler_id = (gulong) g_hash_table_lookup(ht_signal_handlers_it, + gulong handler_id = (gulong) g_hash_table_lookup(ht_signal_handlers_it, imhtml->text_buffer); - g_signal_handler_disconnect(imhtml->text_buffer, it_handler_id); + g_signal_handler_disconnect(imhtml->text_buffer, handler_id); g_hash_table_remove(ht_signal_handlers_it, imhtml->text_buffer); - gulong eua_handler_id = (gulong) g_hash_table_lookup(ht_signal_handlers_eua, + handler_id = (gulong) g_hash_table_lookup(ht_signal_handlers_eua, imhtml->text_buffer); - g_signal_handler_disconnect(imhtml->text_buffer, eua_handler_id); + g_signal_handler_disconnect(imhtml->text_buffer, handler_id); g_hash_table_remove(ht_signal_handlers_eua, imhtml->text_buffer); } @@ -116,7 +116,7 @@ plugin_load(PurplePlugin *plugin) ht_buttons = g_hash_table_new_full(g_direct_hash, g_direct_equal, (GDestroyNotify) videoframes_remove_button, NULL); - /* Create hash tables for signal handlers. */ + /* Create the hash tables for signal handlers. */ ht_signal_handlers_it = g_hash_table_new(g_direct_hash, g_direct_equal); ht_signal_handlers_eua = g_hash_table_new(g_direct_hash, g_direct_equal); @@ -138,17 +138,17 @@ plugin_unload(PurplePlugin *plugin) { /* Disconnect signals for future conversations. */ void *conv_handle = purple_conversations_get_handle(); - purple_signal_disconnect(conv_handle, "deleting-conversation", plugin, - PURPLE_CALLBACK(deleting_conversation_cb)); purple_signal_disconnect(conv_handle, "conversation-created", plugin, PURPLE_CALLBACK(conversation_created_cb)); + purple_signal_disconnect(conv_handle, "deleting-conversation", plugin, + PURPLE_CALLBACK(deleting_conversation_cb)); /* Detach from current conversations. */ g_list_foreach(purple_get_conversations(), detach_from_conversation, NULL); - /* Destroy hash tables for signal handlers. */ - g_hash_table_destroy(ht_signal_handlers_eua); + /* Destroy the hash tables for signal handlers. */ g_hash_table_destroy(ht_signal_handlers_it); + g_hash_table_destroy(ht_signal_handlers_eua); /* Remove all the inserted buttons and destroy the hash table. Every button will automatically remove its video frame if it has one. */ diff --git a/src/videoframes.c b/src/videoframes.c index 6e60295..8af8550 100644 --- a/src/videoframes.c +++ b/src/videoframes.c @@ -22,7 +22,8 @@ static gboolean navigation_policy_decision_requested_cb(WebKitWebView *, WebKitWebNavigationAction *, WebKitWebPolicyDecision *, gpointer); -static GHashTable *ht_button_info = NULL; /* */ +static GHashTable *ht_button_info = NULL; /* */ +static GHashTable *ht_button_location = NULL; /* */ ButtonInfo * button_info_new(GtkIMHtml *imhtml, GtkTextIter *location, @@ -35,8 +36,7 @@ button_info_new(GtkIMHtml *imhtml, GtkTextIter *location, location, TRUE); info->website = website; info->url = g_string_new_len(text, len); - info->iter = location; - info->insert_newline = -1; + info->has_newline = FALSE; return info; } @@ -54,50 +54,14 @@ videoframes_init() { ht_button_info = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) button_info_free); + ht_button_location = g_hash_table_new(g_direct_hash, g_direct_equal); } void videoframes_destroy() { g_hash_table_destroy(ht_button_info); -} - -void -videoframes_text_buffer_check_newline(gpointer key, gpointer values, gpointer user_data) -{ - GtkWidget *button = (GtkWidget *) key; - ButtonInfo *button_info = (ButtonInfo *) values; - - if (button_info->insert_newline != -1) - return ; - - GtkTextIter iter; - - gtk_text_buffer_get_iter_at_mark(button_info->imhtml->text_buffer, - &iter, button_info->mark); - button_info->insert_newline = 0; - - while (gtk_text_iter_forward_char(&iter)) { - gunichar crt_unichar = gtk_text_iter_get_char(&iter); - - if (crt_unichar == G_UNICODE_BREAK_LINE_FEED) - break ; - if (g_unichar_isgraph(crt_unichar)) { - button_info->insert_newline = 1; - break ; - } - } - - if (purple_prefs_get_bool("/plugins/gtk/embeddedvideo/show-video")) { - videoframes_toggle_button(button); - gtk_text_buffer_get_end_iter(button_info->imhtml->text_buffer, button_info->iter); - } -} - -void -videoframes_text_buffer_end_user_action_cb(GtkTextBuffer* text_buffer, gpointer user_data) -{ - g_hash_table_foreach(ht_button_info, videoframes_text_buffer_check_newline, NULL); + g_hash_table_destroy(ht_button_location); } GtkWidget * @@ -127,9 +91,10 @@ videoframes_insert_new_button(GtkIMHtml *imhtml, GtkTextIter *location, G_CALLBACK(videoframes_toggle_button_cb), NULL); gtk_widget_show_all(button); - /* Add some information to the button. */ + /* Add some information regarding the button. */ g_hash_table_insert(ht_button_info, button, button_info_new(imhtml, location, website, text, len)); + g_hash_table_insert(ht_button_location, button, location); /* Insert the button into the conversation. */ GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor( @@ -195,14 +160,11 @@ videoframes_toggle_button_cb(GtkWidget *button) gtk_widget_show_all(web_view); /* Insert the web view into the conversation. */ - /* FIXME: Is this "\n" enough? What about those who use unicode chars? - What could happen on Windows without "\r"? - */ gtk_text_buffer_insert(info->imhtml->text_buffer, &iter, "\n", 1); GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor( info->imhtml->text_buffer, &iter); gtk_text_view_add_child_at_anchor(&info->imhtml->text_view, web_view, anchor); - if (info->insert_newline == 1) + if (info->has_newline == TRUE) gtk_text_buffer_insert(info->imhtml->text_buffer, &iter, "\n", 1); } else { @@ -213,7 +175,7 @@ videoframes_toggle_button_cb(GtkWidget *button) /* Remove the video from the conversation. The web view is implicitly destroyed. */ GtkTextIter next_iter = iter; - gtk_text_iter_forward_chars(&next_iter, 2 + (info->insert_newline)); + gtk_text_iter_forward_chars(&next_iter, 2 + (int) info->has_newline); gtk_text_buffer_delete(info->imhtml->text_buffer, &iter, &next_iter); } @@ -316,3 +278,39 @@ videoframes_generate_page(WebsiteInfo *website, GString *url) return ret; } + +void +videoframes_text_buffer_check_newline(gpointer key, gpointer value, gpointer user_data) +{ + GtkWidget *button = (GtkWidget *) key; + GtkTextIter *location = (GtkTextIter *) value; + ButtonInfo *info = (ButtonInfo *) g_hash_table_lookup(ht_button_info, key); + + GtkTextIter iter; + gtk_text_buffer_get_iter_at_mark(info->imhtml->text_buffer, &iter, info->mark); + + while (gtk_text_iter_forward_char(&iter)) { + gunichar crt_unichar = gtk_text_iter_get_char(&iter); + + if (g_unichar_break_type(crt_unichar) == G_UNICODE_BREAK_LINE_FEED) + break; + + if (g_unichar_isgraph(crt_unichar)) { + info->has_newline = TRUE; + break; + } + } + + if (purple_prefs_get_bool("/plugins/gtk/embeddedvideo/show-video")) { + videoframes_toggle_button(button); + gtk_text_buffer_get_end_iter(info->imhtml->text_buffer, location); + } +} + +void +videoframes_text_buffer_end_user_action_cb(GtkTextBuffer* text_buffer, gpointer user_data) +{ + g_hash_table_foreach(ht_button_location, videoframes_text_buffer_check_newline, NULL); + g_hash_table_remove_all(ht_button_location); +} + diff --git a/src/videoframes.h b/src/videoframes.h index 1b3f101..779eca8 100644 --- a/src/videoframes.h +++ b/src/videoframes.h @@ -17,8 +17,7 @@ struct _ButtonInfo GtkTextMark *mark; WebsiteInfo *website; GString *url; - GtkTextIter *iter; - gint insert_newline; + gboolean has_newline; }; ButtonInfo * button_info_new(GtkIMHtml *, GtkTextIter *, @@ -27,12 +26,12 @@ void button_info_free(ButtonInfo *); void videoframes_init(); void videoframes_destroy(); -void videoframes_text_buffer_check_new_line(gpointer, gpointer, gpointer); -void videoframes_text_buffer_end_user_action_cb(GtkTextBuffer *, gpointer); GtkWidget * videoframes_insert_new_button(GtkIMHtml *, GtkTextIter *, WebsiteInfo *, gchar *, gint); void videoframes_remove_button(GtkWidget *); void videoframes_toggle_button(GtkWidget *); gchar * videoframes_generate_page(WebsiteInfo *, GString *); +void videoframes_text_buffer_check_newline(gpointer, gpointer, gpointer); +void videoframes_text_buffer_end_user_action_cb(GtkTextBuffer *, gpointer); #endif