# HG changeset patch # User Yoshiki Yazawa # Date 1210410658 -32400 # Node ID 312a745dece62ecb244e284849d4d0a89e9a15bc # Parent e740ceed9337db54697661b4c6182c5cdf1b7416 added letter counter diff -r e740ceed9337 -r 312a745dece6 pidgin-twitter.c --- a/pidgin-twitter.c Tue May 06 22:11:03 2008 +0900 +++ b/pidgin-twitter.c Sat May 10 18:10:58 2008 +0900 @@ -29,13 +29,16 @@ #include "connection.h" #include "version.h" #include "sound.h" +#include "gtkconv.h" #define RECIPIENT 0 #define SENDER 1 #define COMMAND 2 #define PSEUDO 3 -#define PIDGINTWITTER_PLUGIN_ID "pidgin_twitter" +#define PLUGIN_ID "gtk-honeyplanet-pidgin_twitter" +#define PLUGIN_NAME "pidgin-twitter" + #define OPT_PIDGINTWITTER "/plugins/pidgin_twitter" #define OPT_TRANSLATE_RECIPIENT OPT_PIDGINTWITTER "/translate_recipient" #define OPT_TRANSLATE_SENDER OPT_PIDGINTWITTER "/translate_sender" @@ -46,17 +49,27 @@ #define OPT_ESCAPE_PSEUDO OPT_PIDGINTWITTER "/escape_pseudo" #define OPT_USERLIST_RECIPIENT OPT_PIDGINTWITTER "/userlist_recipient" #define OPT_USERLIST_SENDER OPT_PIDGINTWITTER "/userlist_sender" +#define OPT_COUNTER OPT_PIDGINTWITTER "/counter" + #define RECIPIENT_FORMAT "@%s" #define SENDER_FORMAT "%s: " -#define DEFAULT_LIST "(list of users: separated with ' ,:;')" +#define DEFAULT_LIST "(list of users: separated with ' ,:;')" + -#define twitter_debug(fmt, ...) purple_debug(PURPLE_DEBUG_INFO, PIDGINTWITTER_PLUGIN_ID, \ +#define twitter_debug(fmt, ...) purple_debug(PURPLE_DEBUG_INFO, PLUGIN_NAME, \ fmt, ## __VA_ARGS__); -#define twitter_error(fmt, ...) purple_debug(PURPLE_DEBUG_ERROR, PIDGINTWITTER_PLUGIN_ID, \ +#define twitter_error(fmt, ...) purple_debug(PURPLE_DEBUG_ERROR, PLUGIN_NAME, \ /* globals */ static GRegex *regp[4]; +/* prototypes */ +static gboolean is_twitter_conv(PurpleConversation *conv); +static void attach_to_gtkconv(PidginConversation *gtkconv, gpointer null); +static void detach_from_gtkconv(PidginConversation *gtkconv, gpointer null); +static void escape(gchar **str); + + static void escape(gchar **str) { @@ -115,7 +128,8 @@ twitter_debug("proto = %s\n", proto); twitter_debug("recipient = %s\n", recipient); - if(!strcmp(proto, "prpl-jabber") && !strcmp(recipient, "twitter@twitter.com")) { + if(!strcmp(proto, "prpl-jabber") && + !strcmp(recipient, "twitter@twitter.com")) { /* escape */ if(purple_prefs_get_bool(OPT_ESCAPE_PSEUDO)) { escape(buffer); @@ -169,7 +183,8 @@ const gchar *list; gchar **candidates = NULL, **candidate = NULL; - list = purple_prefs_get_string(which ? OPT_USERLIST_SENDER : OPT_USERLIST_RECIPIENT); + list = purple_prefs_get_string(which ? OPT_USERLIST_SENDER : + OPT_USERLIST_RECIPIENT); g_return_if_fail(list != NULL); if(!strcmp(list, DEFAULT_LIST)) return; @@ -238,6 +253,192 @@ return FALSE; } +static void +insert_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *position, + gchar *new_text, gint new_text_length, gpointer user_data) +{ + PidginConversation *gtkconv = (PidginConversation *)user_data; + GtkWidget *box, *counter = NULL; + gchar *markup = NULL; + + g_return_if_fail(gtkconv != NULL); + + guint count = gtk_text_buffer_get_char_count(textbuffer) + + (unsigned int)g_utf8_strlen(new_text, -1); + + twitter_debug("new_text = %s utf8_strlen = %ld new_text_length = %d\n", + new_text, g_utf8_strlen(new_text, -1), new_text_length); + + markup = g_markup_printf_escaped("%u", + count<=140 ? "black" : "red", + count); + + box = gtkconv->toolbar; + counter = g_object_get_data(G_OBJECT(box), + PLUGIN_ID "-counter"); + if (counter) + gtk_label_set_markup(GTK_LABEL(counter), markup); + + g_free(markup); +} + +static void +delete_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *start_pos, + GtkTextIter *end_pos, gpointer user_data) +{ + PidginConversation *gtkconv = (PidginConversation *)user_data; + GtkWidget *box, *counter = NULL; + gchar *markup = NULL; + + g_return_if_fail(gtkconv != NULL); + + guint count = gtk_text_buffer_get_char_count(textbuffer) - + (gtk_text_iter_get_offset(end_pos) - + gtk_text_iter_get_offset(start_pos)); + + markup = g_markup_printf_escaped("%u", + count<=140 ? "black" : "red", + count); + + box = gtkconv->toolbar; + counter = g_object_get_data(G_OBJECT(box), + PLUGIN_ID "-counter"); + if (counter) + gtk_label_set_markup(GTK_LABEL(counter), markup); + + g_free(markup); +} + + +static void +detach_from_window(void) +{ + GList *list; + + for (list = pidgin_conv_windows_get_list(); list; list = list->next) { + PidginWindow *win = list->data; + PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); + if(is_twitter_conv(conv)) + detach_from_gtkconv(PIDGIN_CONVERSATION(conv), NULL); + } +} + +static void +detach_from_gtkconv(PidginConversation *gtkconv, gpointer null) +{ + GtkWidget *box, *counter = NULL, *sep = NULL; + + g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry_buffer), + (GFunc)insert_text_cb, gtkconv); + g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry_buffer), + (GFunc)delete_text_cb, gtkconv); + + box = gtkconv->toolbar; + + /* remove counter */ + counter = g_object_get_data(G_OBJECT(box), + PLUGIN_ID "-counter"); + if (counter) { + gtk_container_remove(GTK_CONTAINER(box), counter); + g_object_unref(counter); + g_object_set_data(G_OBJECT(box), + PLUGIN_ID "-counter", NULL); + } + /* remove separator */ + sep = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-sep"); + if (sep) { + gtk_container_remove(GTK_CONTAINER(box), sep); + g_object_unref(sep); + g_object_set_data(G_OBJECT(box), + PLUGIN_ID "-sep", NULL); + } + + gtk_widget_queue_draw(pidgin_conv_get_window(gtkconv)->window); +} + +static void +attach_to_window(void) +{ + GList *list; + + for (list = pidgin_conv_windows_get_list(); list; list = list->next) { + PidginWindow *win = list->data; + PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); + if(is_twitter_conv(conv)) + attach_to_gtkconv(PIDGIN_CONVERSATION(conv), NULL); + } +} + +static void +attach_to_gtkconv(PidginConversation *gtkconv, gpointer null) +{ + GtkWidget *box, *sep, *counter; + + box = gtkconv->toolbar; + counter = g_object_get_data(G_OBJECT(box), + PLUGIN_ID "-counter"); + g_return_if_fail(counter == NULL); + + /* make counter object */ + counter = gtk_label_new(NULL); + gtk_widget_set_name(counter, "counter_label"); + gtk_label_set_text(GTK_LABEL(counter), "0"); + gtk_box_pack_end(GTK_BOX(box), counter, FALSE, FALSE, 0); + gtk_widget_show_all(counter); + g_object_set_data(G_OBJECT(box), + PLUGIN_ID "-counter", counter); + + /* make separator object */ + sep = gtk_vseparator_new(); + gtk_box_pack_end(GTK_BOX(box), sep, FALSE, FALSE, 0); + gtk_widget_show_all(sep); + g_object_set_data(G_OBJECT(box), + PLUGIN_ID "-sep", sep); + + /* connect signals, etc. */ + g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text", + G_CALLBACK(insert_text_cb), gtkconv); + g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range", + G_CALLBACK(delete_text_cb), gtkconv); + + /* redraw window */ + gtk_widget_queue_draw(pidgin_conv_get_window(gtkconv)->window); +} + +static gboolean +is_twitter_conv(PurpleConversation *conv) +{ + const char *name = purple_conversation_get_name(conv); + PurpleAccount *account = purple_conversation_get_account(conv); + const gchar *proto = purple_account_get_protocol_id(account); + + twitter_debug("is_twitter_conv\n"); + twitter_debug("name = %s\n", name); + twitter_debug("proto = %s\n", proto); + + if(!strcmp(name, "twitter@twitter.com") && + !strcmp(proto, "prpl-jabber")) { + return TRUE; + } + + return FALSE; +} + +static void +conv_created_cb(PurpleConversation *conv, gpointer null) +{ + PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); + g_return_if_fail(gtkconv != NULL); + + /* only attach to twitter conversation window */ + if(is_twitter_conv(conv)) { + gboolean enabled = purple_prefs_get_bool(OPT_COUNTER); + if(enabled) { + attach_to_gtkconv(gtkconv, NULL); + } + } +} + static gboolean load_plugin(PurplePlugin * plugin) { @@ -246,6 +447,9 @@ plugin, PURPLE_CALLBACK(writing_im_cb), NULL); purple_signal_connect(purple_conversations_get_handle(), "sending-im-msg", plugin, PURPLE_CALLBACK(sending_im_cb), NULL); + purple_signal_connect(purple_conversations_get_handle(), + "conversation-created", + plugin, PURPLE_CALLBACK(conv_created_cb), NULL); /* compile regex */ regp[RECIPIENT] = g_regex_new("@([A-Za-z0-9_]+)", 0, 0, NULL); @@ -257,6 +461,12 @@ "^\\s*(?:[\"#$%&'()*+,\\-./:;<=>?\\[\\\\\\]_`{|}~]|[^\\s\\x21-\\x7E])*([dDfFgGlLmMnNtTwW]{1})(?:\\Z|\\s+|[^\\x21-\\x7E]+\\Z)", G_REGEX_RAW, 0, NULL); + /* attach counter to the existing twitter window*/ + gboolean enabled = purple_prefs_get_bool(OPT_COUNTER); + if(enabled) { + attach_to_window(); + } + return TRUE; } @@ -265,14 +475,42 @@ { twitter_debug("pidgin-twitter unload called\n"); + /* disconnect from signal */ + purple_signal_disconnect(purple_conversations_get_handle(), + "writing-im-msg", + plugin, PURPLE_CALLBACK(writing_im_cb)); + purple_signal_disconnect(purple_conversations_get_handle(), + "sending-im-msg", + plugin, PURPLE_CALLBACK(sending_im_cb)); + purple_signal_disconnect(purple_conversations_get_handle(), + "conversation-created", + plugin, PURPLE_CALLBACK(conv_created_cb)); + + /* unreference regp */ g_regex_unref(regp[RECIPIENT]); g_regex_unref(regp[SENDER]); g_regex_unref(regp[COMMAND]); g_regex_unref(regp[PSEUDO]); + /* detach from twitter window */ + detach_from_window(); + return TRUE; } +static void +counter_prefs_cb(const char *name, PurplePrefType type, + gconstpointer val, gpointer data) +{ + gboolean enabled = purple_prefs_get_bool(OPT_COUNTER); + if(enabled) { + attach_to_window(); //xxx shoud check whether already attached or not. + } + else { + detach_from_window(); + } +} + static PurplePluginPrefFrame * get_plugin_pref_frame(PurplePlugin * plugin) { @@ -282,10 +520,9 @@ PurplePluginPrefFrame *frame = purple_plugin_pref_frame_new(); /* frame title */ - pref = purple_plugin_pref_new_with_label("Pidgin-Twitter Configuration"); + pref = purple_plugin_pref_new_with_label("Translation Configurations"); purple_plugin_pref_frame_add(frame, pref); - /* translation settings */ pref = purple_plugin_pref_new_with_name_and_label( OPT_TRANSLATE_RECIPIENT, @@ -297,12 +534,38 @@ "Translate sender name to link"); purple_plugin_pref_frame_add(frame, pref); - /* escape pseudo command settings */ + + + + + /* frame title */ + pref = purple_plugin_pref_new_with_label("Miscellaneous Configurations"); + purple_plugin_pref_frame_add(frame, pref); + + /* escape pseudo command setting */ pref = purple_plugin_pref_new_with_name_and_label( OPT_ESCAPE_PSEUDO, "Escape pseudo command string"); purple_plugin_pref_frame_add(frame, pref); + /* comaescape pseudo command setting */ + pref = purple_plugin_pref_new_with_name_and_label( + OPT_COUNTER, + "Show text counter"); + purple_plugin_pref_frame_add(frame, pref); + + /* xxx */ + purple_prefs_connect_callback(plugin, OPT_COUNTER, + counter_prefs_cb, NULL); + + + + + + /* frame title */ + pref = purple_plugin_pref_new_with_label("Sound Configurations"); + purple_plugin_pref_frame_add(frame, pref); + /* sound settings for recipient */ pref = purple_plugin_pref_new_with_name_and_label( OPT_PLAYSOUND_RECIPIENT, @@ -334,7 +597,7 @@ purple_plugin_pref_frame_add(frame, pref); - /* sound settings for sender */ + /* sound setting for sender */ pref = purple_plugin_pref_new_with_name_and_label( OPT_PLAYSOUND_SENDER, "Play sound if sender of a message is in the sender list"); @@ -380,9 +643,9 @@ 0, /**< flags */ NULL, /**< deps */ PURPLE_PRIORITY_DEFAULT, /**< priority */ - PIDGINTWITTER_PLUGIN_ID, /**< id */ + PLUGIN_ID, /**< id */ "Pidgin-Twitter", /**< name */ - "0.5.2", /**< version */ + "0.6.0", /**< version */ "replaces usernames with links and play sounds", /** summary */ "replaces usernames with links and play sounds", /** desc */ "Yoshiki Yazawa (yaz@honeyplanet.jp)", /**< author */ @@ -413,6 +676,8 @@ purple_prefs_add_string(OPT_USERLIST_RECIPIENT, DEFAULT_LIST); purple_prefs_add_int(OPT_SOUNDID_SENDER, PURPLE_SOUND_POUNCE_DEFAULT); purple_prefs_add_string(OPT_USERLIST_SENDER, DEFAULT_LIST); + + purple_prefs_add_bool(OPT_COUNTER, TRUE); } PURPLE_INIT_PLUGIN(pidgin_twitter, init_plugin, info)