# HG changeset patch # User mikanbako # Date 1214750908 -32400 # Node ID 0b93dd0e0de18237dc59792c6c24fe0b9feb612f # Parent 846110b420090bf271ab6c72d3d794569e9bddb9 fixed the data structure of marks that are positions of inserting user's icons. diff -r 846110b42009 -r 0b93dd0e0de1 pidgin-twitter.c --- a/pidgin-twitter.c Sat Jun 28 13:59:02 2008 +0900 +++ b/pidgin-twitter.c Sun Jun 29 23:48:28 2008 +0900 @@ -27,7 +27,7 @@ static GHashTable *icon_id_by_user; static GList *requested_users = NULL; static GList *requestings = NULL; -static GList *requested_icon_marks = NULL; +static GHashTable *icon_mark_list_by_user; /* this function is a modified clone of purple_markup_strip_html() */ static char * @@ -700,25 +700,36 @@ } static void -delete_requested_icon_marks(PidginConversation* conv) { +delete_requested_icon_marks(PidginConversation *conv) { GtkTextBuffer *text_buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(conv->imhtml)); - GList *mark_list = g_list_first(requested_icon_marks); + GList *user_name_list = g_hash_table_get_keys(icon_mark_list_by_user); + GList *current_user; + + for(current_user = g_list_first(user_name_list); current_user; + current_user = g_list_next(current_user)) { + gchar *user_name = current_user->data; + GList *mark_list = g_hash_table_lookup(icon_mark_list_by_user, + user_name); - /* delete the marks in the buffer that will be closed. */ - while(mark_list) { - GtkTextMark *mark = mark_list->data; - GList *next = g_list_next(mark_list); - - if(gtk_text_mark_get_buffer(mark) == text_buffer) { - /* the mark will be freed in the function */ - gtk_text_buffer_delete_mark(text_buffer, mark); - requested_icon_marks = g_list_delete_link( - requested_icon_marks, mark_list); + /* delete the marks in the buffer that will be closed. */ + GList *current = g_list_first(mark_list); + while(current) { + GtkTextMark *mark = current->data; + GList *next = g_list_next(current); + + if(gtk_text_mark_get_buffer(mark) == text_buffer) { + /* the mark will be freed in the function */ + gtk_text_buffer_delete_mark(text_buffer, mark); + mark_list = g_list_delete_link(mark_list, current); + } + + current = next; } - mark_list = next; + g_hash_table_insert(icon_mark_list_by_user, user_name, mark_list); } + g_list_free(user_name_list); } static void @@ -908,19 +919,13 @@ } static void -insert_requested_icon(gpointer data, gpointer user_data) +insert_icon_at_mark(GtkTextMark *requested_mark, const gchar *user_name) { - GtkTextMark *requested_mark = (GtkTextMark *)data; - gchar *user_name = (gchar *)user_data; GList *win_list; GtkIMHtml *target_imhtml = NULL; GtkTextBuffer *target_buffer = NULL; - GtkTextIter inserting_point, next_line; - gchar *message; -// GMatchInfo *match_info = NULL; -// gchar *user_name_in_message; + GtkTextIter inserting_point; int icon_id; - GList *entry_of_mark; twitter_debug("called\n"); @@ -956,47 +961,6 @@ gtk_text_buffer_get_iter_at_mark(target_buffer, &inserting_point, requested_mark); - next_line = inserting_point; - gtk_text_iter_forward_line(&next_line); - - message = gtk_text_buffer_get_text(target_buffer, &inserting_point, &next_line, FALSE); - -#if 0 - g_regex_match(regp[USER], message, 0, &match_info); - if(!g_match_info_matches(match_info)) { - g_match_info_free(match_info); - g_regex_match(regp[USER_FIRST_LINE], message, 0, &match_info); - } - if(!g_match_info_matches(match_info)) { - twitter_debug("user's name was not matched : %s\n", message); - g_match_info_free(match_info); - g_free(message); - return; - } - - user_name_in_message = g_match_info_fetch(match_info, 1); - g_match_info_free(match_info); - g_free(message); - - /* Return if the message is not from the user who has this icon. */ - if(!g_str_equal(user_name, user_name_in_message)) { - g_free(user_name_in_message); - return; - } - g_free(user_name_in_message); -#endif - - - /* simple search works sufficiently */ - gchar *needle = g_strdup_printf("%s:", user_name); - if(!g_strstr_len(message, 256, needle)){ // xxx 256 is just a guess. - g_free(message); message = NULL; - g_free(needle); needle = NULL; - return; - } - twitter_debug("got needle %s\n", needle); - g_free(message); message = NULL; - g_free(needle); needle = NULL; /* insert icon */ icon_id = GPOINTER_TO_INT(g_hash_table_lookup(icon_id_by_user, user_name)); @@ -1006,12 +970,17 @@ /* insert icon actually */ gtk_imhtml_insert_image_at_iter(target_imhtml, icon_id, &inserting_point); + gtk_text_buffer_delete_mark(target_buffer, requested_mark); +} - /* mark the entry contains the deleted mark with NULL */ - entry_of_mark = g_list_find(requested_icon_marks, requested_mark); - entry_of_mark->data = NULL; +static void +insert_requested_icon(const gchar *user_name) +{ + GList *mark_list = g_hash_table_lookup(icon_mark_list_by_user, user_name); - gtk_text_buffer_delete_mark(target_buffer, requested_mark); + g_list_foreach(mark_list, (GFunc) insert_icon_at_mark, (gchar *)user_name); + g_hash_table_remove(icon_mark_list_by_user, user_name); + g_list_free(mark_list); } static void @@ -1036,14 +1005,20 @@ twitter_debug("%s's icon has already been downloaded\n", user_name); } - requested_users = g_list_remove(requested_users, user_name); + GList *deleting = g_list_find_custom(requested_users, + user_name, (GCompareFunc) strcmp); + if(deleting) { + g_free(deleting->data); + requested_users = g_list_delete_link(requested_users, deleting); + } g_free(user_name); return; } icon_id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, user_name); - g_hash_table_insert(icon_id_by_user, user_name, GINT_TO_POINTER(icon_id)); + g_hash_table_insert(icon_id_by_user, + g_strdup(user_name),GINT_TO_POINTER(icon_id)); const gchar *dirname = purple_prefs_get_string(OPT_ICON_DIR); @@ -1072,13 +1047,12 @@ user_name, icon_id); /* Insert the icon to messages that had been received. */ - g_list_foreach(requested_icon_marks, insert_requested_icon, user_name); - /* Remove the entries of the mark that inserted the icon. */ - requested_icon_marks = g_list_remove_all(requested_icon_marks, NULL); + insert_requested_icon(user_name); + g_free(user_name); } static void -request_icon(char *user_name) +request_icon(const char *user_name) { gchar *url = NULL; PurpleUtilFetchUrlData *fetch_data = NULL; @@ -1123,7 +1097,7 @@ g_free(filename); g_free(path); - g_list_foreach(requested_icon_marks, insert_requested_icon, user_name); + insert_requested_icon(user_name); return; } @@ -1132,8 +1106,8 @@ return; } - /* The string object are owned by the list. */ requested_users = g_list_append(requested_users, g_strdup(user_name)); + /* Create the URL of the user's icon. * See http://twitter.g.hatena.ne.jp/ikko615/20080107/1199703400 */ @@ -1149,6 +1123,16 @@ } static void +mark_icon_for_user(GtkTextMark *mark, const gchar *user_name) +{ + GList *mark_list = g_hash_table_lookup(icon_mark_list_by_user, user_name); + + mark_list = g_list_append(mark_list, mark); + g_hash_table_replace(icon_mark_list_by_user, + g_strdup(user_name), mark_list); +} + +static void displayed_im_cb(PurpleAccount *account, const char *who, char *message, PurpleConversation *conv, PurpleMessageFlags flags) { @@ -1186,16 +1170,14 @@ icon_id = GPOINTER_TO_INT(g_hash_table_lookup(icon_id_by_user, user_name)); - /* If the user's icon has not been downloaded, mark the message */ + /* If the user's icon has not been downloaded, + * mark the message and request the icon. */ if(!icon_id) { - requested_icon_marks = - g_list_append(requested_icon_marks, - gtk_text_buffer_create_mark( - text_buffer, NULL, - &inserting_point, FALSE)); twitter_debug("%s's icon has not been downloaded.\n", user_name); - /* request to attach icon to the buffer - * this function owns user_name string */ + mark_icon_for_user(gtk_text_buffer_create_mark( + text_buffer, NULL, &inserting_point, FALSE), + user_name); + /* request to attach icon to the buffer */ request_icon(user_name); g_free(user_name); user_name = NULL; return; @@ -1235,9 +1217,13 @@ regp[USER_FIRST_LINE] = g_regex_new(P_USER_FIRST_LINE, 0, 0, NULL); regp[USER_FORMATTED] = g_regex_new(P_USER_FORMATTED, G_REGEX_RAW, 0, NULL); - /* hash table for user's icons - * the key is owned by requested_user */ - icon_id_by_user = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); + /* hash table for user's icons */ + icon_id_by_user = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + + /* hash table for a list of marks that are alternative icons */ + icon_mark_list_by_user = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); /* attach counter to the existing twitter window */ if(purple_prefs_get_bool(OPT_COUNTER)) { @@ -1250,7 +1236,7 @@ static gboolean unload_plugin(PurplePlugin *plugin) { - GList *list; + GList *list, *current; twitter_debug("called\n"); @@ -1283,8 +1269,18 @@ g_regex_unref(regp[USER_FIRST_LINE]); g_regex_unref(regp[USER_FORMATTED]); - g_list_free(requested_icon_marks); - requested_icon_marks = NULL; + /* remove the hash table of marks that are alternative icons */ + list = g_hash_table_get_values(icon_mark_list_by_user); + for(current = g_list_first(list); current; + current = g_list_next(current)) { + /* Free a list of marks. + * Do not free the marks here + * because the marks are owned by GtkTextBuffers. + */ + g_list_free(current->data); + } + g_list_free(list); + g_hash_table_destroy(icon_mark_list_by_user); /* cancel request that has not been finished yet */ for(list = g_list_first(requestings); list; list = g_list_next(list)) { diff -r 846110b42009 -r 0b93dd0e0de1 pidgin-twitter.h --- a/pidgin-twitter.h Sat Jun 28 13:59:02 2008 +0900 +++ b/pidgin-twitter.h Sun Jun 29 23:48:28 2008 +0900 @@ -88,9 +88,11 @@ static void conv_created_cb(PurpleConversation *conv, gpointer null); static void deleting_conv_cb(PurpleConversation *conv); static gboolean receiving_im_cb(PurpleAccount *account, char **sender, char **buffer, PurpleConversation *conv, PurpleMessageFlags *flags, void *data); -static void insert_requested_icon(gpointer data, gpointer user_data); +static void insert_icon_at_mark(GtkTextMark *requested_mark, const gchar *user_name); +static void insert_requested_icon(const gchar *user_name); static void got_icon_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message); -static void request_icon(char *user_name); +static void request_icon(const char *user_name); +static void mark_icon_for_user(GtkTextMark *mark, const gchar *user_name); static void displayed_im_cb(PurpleAccount *account, const char *who, char *message, PurpleConversation *conv, PurpleMessageFlags flags); static gboolean load_plugin(PurplePlugin *plugin); static gboolean unload_plugin(PurplePlugin *plugin);