# HG changeset patch # User Yoshiki Yazawa # Date 1216900834 -32400 # Node ID 4e9d0fd93fb6d179a479b4b43167751112ffcfff # Parent 3abee459c81c807bf5055b0e6996f140af3946c3 - in saving icon file for twitter, proper extension is used. - pointers to hash tables are organized as an array. - removed unused code. - resolved redundant code with hash table array. diff -r 3abee459c81c -r 4e9d0fd93fb6 pidgin-twitter.c --- a/pidgin-twitter.c Thu Jul 24 06:40:41 2008 +0900 +++ b/pidgin-twitter.c Thu Jul 24 21:00:34 2008 +0900 @@ -26,12 +26,12 @@ #define NUM_REGP 10 static GRegex *regp[NUM_REGP]; static gboolean suppress_oops = FALSE; -static GHashTable *icon_data_by_user = NULL; // twitter -static GHashTable *icon_data_by_user2 = NULL; // wassr -static GHashTable *icon_data_by_user3 = NULL; // identi.ca +static GHashTable *icon_hash[3]; /* twitter, wassr, identica. */ static GHashTable *conv_hash = NULL; + static GList *statuseslist = NULL; static GList *postedlist = NULL; + static gchar *wassr_post = NULL; static gchar *identica_post = NULL; @@ -90,7 +90,7 @@ gchar *head, *tail; /* head and tail of html */ gchar *begin, *end; /* begin:< end:> */ gchar *html, *str; /* copied src and str to be returned */ -// gchar *vis1, *vis2; /* begin and end of address part */ +/* gchar *vis1, *vis2; */ /* begin and end of address part */ gchar *startp; /* starting point marker */ gchar **tagp; /* tag iterator */ gchar *tmp, *tmp2; /* scratches */ @@ -511,7 +511,7 @@ PurpleConversation *conv = (PurpleConversation *)data; if(!conv) - return FALSE; //cease fetch + return FALSE; /* cease fetch */ const char *screen_name = purple_prefs_get_string(OPT_SCREEN_NAME_TWITTER); @@ -817,8 +817,8 @@ g_free(match); } else if(which == SENDER) { - gchar *match1 = g_match_info_fetch(match_info, 1); //preceding CR|LF - gchar *match2 = g_match_info_fetch(match_info, 2); //sender + gchar *match1 = g_match_info_fetch(match_info, 1); /*preceding CR|LF*/ + gchar *match2 = g_match_info_fetch(match_info, 2); /* sender */ const gchar *format = NULL; switch(service) { @@ -842,8 +842,8 @@ g_free(match2); } else if(service == wassr_service && which == CHANNEL) { - gchar *match1 = g_match_info_fetch(match_info, 1); //before channel - gchar *match2 = g_match_info_fetch(match_info, 2); //channel + gchar *match1 = g_match_info_fetch(match_info, 1); /*before channel*/ + gchar *match2 = g_match_info_fetch(match_info, 2); /* channel */ const gchar *format = CHANNEL_FORMAT_WASSR; g_snprintf(sub, 128, format, match1 ? match1: "", match2, match2); @@ -869,14 +869,14 @@ data->service = service; regp_id = which; /* for future use --yaz */ - newstr = g_regex_replace_eval(regp[regp_id], // compiled regex - *str, // subject string - -1, // length of the subject string - 0, // start position - 0, // match options - eval, // function to be called for each match - data, // user data - NULL); // error handler + newstr = g_regex_replace_eval(regp[regp_id], /* compiled regex */ + *str, /* subject string */ + -1, /* length of the subject string */ + 0, /* start position */ + 0, /* match options */ + eval, /* function to be called for each match */ + data, /* user data */ + NULL); /* error handler */ g_free(data); data = NULL; @@ -1128,10 +1128,6 @@ gint service = get_service_type(conv); switch(service) { case twitter_service: -#if 0 - if(purple_prefs_get_bool(OPT_API_BASE_POST)) - g_source_remove_by_user_data((gpointer)conv); -#endif detach_from_conv(conv, NULL); break; case wassr_service: @@ -1420,7 +1416,7 @@ /* only attach to twitter conversation window */ switch(service) { case twitter_service: - /* api based retrieve */ //xxx should configurable + /* api based retrieve */ /* xxx should configurable */ if(purple_prefs_get_bool(OPT_API_BASE_POST)) { get_status_with_api((gpointer)conv); g_timeout_add_seconds( @@ -1456,13 +1452,13 @@ case twitter_service: if(purple_prefs_get_bool(OPT_API_BASE_POST)) g_source_remove_by_user_data((gpointer)conv); - hash = icon_data_by_user; + hash = icon_hash[twitter_service]; break; case wassr_service: - hash = icon_data_by_user2; + hash = icon_hash[wassr_service]; break; case identica_service: - hash = icon_data_by_user3; + hash = icon_hash[identica_service]; break; default: twitter_debug("unknown service\n"); @@ -1594,13 +1590,13 @@ /* insert icon */ switch(service) { case twitter_service: - hash = icon_data_by_user; + hash = icon_hash[twitter_service]; break; case wassr_service: - hash = icon_data_by_user2; + hash = icon_hash[wassr_service]; break; case identica_service: - hash = icon_data_by_user3; + hash = icon_hash[identica_service]; break; default: twitter_debug("unknown service\n"); @@ -1641,13 +1637,13 @@ switch(service) { case twitter_service: - hash = icon_data_by_user; + hash = icon_hash[twitter_service]; break; case wassr_service: - hash = icon_data_by_user2; + hash = icon_hash[wassr_service]; break; case identica_service: - hash = icon_data_by_user3; + hash = icon_hash[identica_service]; break; default: twitter_debug("unknown service\n"); @@ -1691,18 +1687,18 @@ gchar *url = NULL; gint regp_id = -1; + if(service == twitter_service) { + data = (icon_data *)g_hash_table_lookup( + icon_hash[twitter_service], user_name); + regp_id = IMAGE_TWITTER; + } + if(service == identica_service) { data = (icon_data *)g_hash_table_lookup( - icon_data_by_user3, user_name); + icon_hash[identica_service], user_name); regp_id = IMAGE_IDENTICA; } - if(service == twitter_service) { - data = (icon_data *)g_hash_table_lookup( - icon_data_by_user, user_name); - regp_id = IMAGE_TWITTER; - } - if(!url_text) { if(data) { data->requested = FALSE; @@ -1716,7 +1712,7 @@ /* setup image url */ g_regex_match(regp[regp_id], url_text, 0, &match_info); if(!g_match_info_matches(match_info)) { - twitter_debug("no image found\n"); + twitter_debug("no image url found\n"); g_match_info_free(match_info); if(data) { @@ -1734,6 +1730,28 @@ *slash = '\0'; gchar *tmp = g_strdup_printf("%s/%s", url, purple_url_encode(slash+1)); + + gchar *startp = slash + 1; + gchar *ext = NULL; + do { + ext = strrchr(startp, '.'); + if(ext) { + if(!strcasecmp(ext, ".jpg") || !strcasecmp(ext, ".jpeg")) { + data->img_type = "jpg"; + break; + } + else if(!strcasecmp(ext, ".png")) { + data->img_type = "png"; + break; + } + else if(!strcasecmp(ext, ".gif")) { + data->img_type = "gif"; + break; + } + startp = ext; + } + } while(ext); + g_free(url); url = tmp; @@ -1780,6 +1798,13 @@ return dest; } +static gchar *ext_list[] = { + "png", + "gif", + "jpg", + NULL +}; + /* this function will be called when requested icon has been retrieved */ static void got_icon_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, @@ -1799,13 +1824,13 @@ switch(service) { case twitter_service: - hash = icon_data_by_user; + hash = icon_hash[twitter_service]; break; case wassr_service: - hash = icon_data_by_user2; + hash = icon_hash[wassr_service]; break; case identica_service: - hash = icon_data_by_user3; + hash = icon_hash[identica_service]; break; default: twitter_debug("unknown service\n"); @@ -1820,8 +1845,8 @@ user_name, error_message); if(data) data->requested = FALSE; + goto fin_got_icon_cb; - return; } if(data) { @@ -1833,8 +1858,8 @@ if(data->icon_id > 0) { twitter_debug("%s's icon has already been downloaded\n", user_name); + goto fin_got_icon_cb; - return; } } @@ -1848,6 +1873,7 @@ gdk_pixbuf_get_rowstride(pixbuf) * gdk_pixbuf_get_height(pixbuf), user_name); + if(!data) { twitter_debug("allocate icon_data (shouldn't be called)\n"); data = g_new0(icon_data, 1); @@ -1867,13 +1893,16 @@ switch(service) { case twitter_service: - filename = g_strdup_printf("%s_twitter.gif", user_name); + filename = g_strdup_printf("%s_twitter.%s", + user_name, data->img_type); break; case wassr_service: - filename = g_strdup_printf("%s_wassr.png", user_name); + filename = g_strdup_printf("%s_wassr.%s", + user_name, data->img_type); break; case identica_service: - filename = g_strdup_printf("%s_identica.png", user_name); + filename = g_strdup_printf("%s_identica.%s", + user_name, data->img_type); break; default: twitter_debug("unknown service\n"); @@ -1910,16 +1939,16 @@ switch(service) { case twitter_service: - hash = icon_data_by_user; + hash = icon_hash[twitter_service]; suffix = "twitter"; break; case wassr_service: - hash = icon_data_by_user2; + hash = icon_hash[wassr_service]; suffix = "wassr"; break; case identica_service: suffix = "identica"; - hash = icon_data_by_user3; + hash = icon_hash[identica_service]; break; default: twitter_debug("unknown service\n"); @@ -1941,52 +1970,49 @@ /* check if saved file exists */ if(suffix) { gchar *filename = NULL; - - filename = g_strdup_printf("%s_%s.gif", user_name, suffix); - path = g_build_filename( - purple_prefs_get_string(OPT_ICON_DIR), filename, NULL); - - if(!g_file_test(path, G_FILE_TEST_EXISTS)) { - g_free(path); - filename = g_strdup_printf("%s_%s.png", user_name, suffix); - path = g_build_filename( - purple_prefs_get_string(OPT_ICON_DIR), filename, NULL); - } - - g_free(filename); - } - - twitter_debug("path = %s\n", path); - - /* make image from file, if file exists */ - if(g_file_test(path, G_FILE_TEST_EXISTS)) { - gchar *imgdata = NULL; - size_t len; - GError *err = NULL; - GdkPixbuf *pixbuf = NULL; - - if (!g_file_get_contents(path, &imgdata, &len, &err)) { - twitter_debug("Error reading %s: %s\n", - path, err->message); - g_error_free(err); - } - - pixbuf = make_scaled_pixbuf(imgdata, len); - - if(pixbuf) { - data->icon_id = - purple_imgstore_add_with_id(pixbuf, - gdk_pixbuf_get_rowstride(pixbuf) * - gdk_pixbuf_get_height(pixbuf), - user_name); - - twitter_debug("icon data has been loaded from file\n"); - insert_requested_icon(user_name, service); - } - - g_free(path); - return; - } + gchar **extp; + + for(extp = ext_list; *extp; extp++) { + filename = g_strdup_printf("%s_%s.%s", user_name, suffix, *extp); + path = g_build_filename(purple_prefs_get_string(OPT_ICON_DIR), + filename, NULL); + + twitter_debug("path = %s\n", path); + + /* make image from file, if file exists */ + if(g_file_test(path, G_FILE_TEST_EXISTS)) { + gchar *imgdata = NULL; + size_t len; + GError *err = NULL; + GdkPixbuf *pixbuf = NULL; + + if (!g_file_get_contents(path, &imgdata, &len, &err)) { + twitter_debug("Error reading %s: %s\n", + path, err->message); + g_error_free(err); + } + + pixbuf = make_scaled_pixbuf(imgdata, len); + + if(pixbuf) { + data->icon_id = + purple_imgstore_add_with_id( + pixbuf, + gdk_pixbuf_get_rowstride(pixbuf) * + gdk_pixbuf_get_height(pixbuf), + user_name); + + data->img_type = *extp; + + twitter_debug("icon data has been loaded from file\n"); + insert_requested_icon(user_name, service); + } + + g_free(path); + return; + } + } /* for */ + } /* suffix */ /* Return if user's icon has been requested already. */ if(data->requested) @@ -1994,10 +2020,7 @@ else data->requested = TRUE; - - /* Create the URL of the user's icon. - * See http://twitter.g.hatena.ne.jp/ikko615/20080107/1199703400 - */ + /* Create the URL for an user's icon. */ switch(service) { case twitter_service: url = g_strdup_printf("http://twitter.com/%s", user_name); @@ -2046,13 +2069,13 @@ switch(service) { case twitter_service: - hash = icon_data_by_user; + hash = icon_hash[twitter_service]; break; case wassr_service: - hash = icon_data_by_user2; + hash = icon_hash[wassr_service]; break; case identica_service: - hash = icon_data_by_user3; + hash = icon_hash[identica_service]; break; default: twitter_debug("unknown service\n"); @@ -2062,6 +2085,7 @@ if(hash) data = (icon_data *)g_hash_table_lookup(hash, user_name); + /* proper place to allocate icon_data */ if(!data) { data = g_new0(icon_data, 1); g_hash_table_insert(hash, g_strdup(user_name), data); @@ -2072,7 +2096,8 @@ static gboolean displaying_im_cb(PurpleAccount *account, const char *who, char **message, - PurpleConversation *conv, PurpleMessageFlags flags, void *unused) + PurpleConversation *conv, PurpleMessageFlags flags, + void *unused) { GtkIMHtml *imhtml; GtkTextBuffer *text_buffer; @@ -2143,13 +2168,13 @@ switch(service) { case twitter_service: - hash = icon_data_by_user; + hash = icon_hash[twitter_service]; break; case wassr_service: - hash = icon_data_by_user2; + hash = icon_hash[wassr_service]; break; case identica_service: - hash = icon_data_by_user3; + hash = icon_hash[identica_service]; break; default: twitter_debug("unknown service\n"); @@ -2228,10 +2253,11 @@ account = purple_buddy_get_account(b); if (is_twitter_account(account, name)) { PurpleConversation *gconv; - gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, account); + gconv = purple_find_conversation_with_account( + PURPLE_CONV_TYPE_IM, name, account); if (!gconv) { - gconv = purple_conversation_new(PURPLE_CONV_TYPE_IM, - account, name); + gconv = purple_conversation_new( + PURPLE_CONV_TYPE_IM, account, name); } } } @@ -2254,6 +2280,8 @@ static gboolean load_plugin(PurplePlugin *plugin) { + int i; + /* connect to signal */ purple_signal_connect(purple_conversations_get_handle(), "writing-im-msg", plugin, PURPLE_CALLBACK(writing_im_cb), NULL); @@ -2288,16 +2316,15 @@ regp[IMAGE_IDENTICA] = g_regex_new(P_IMAGE_IDENTICA, 0, 0, NULL); regp[IMAGE_TWITTER] = g_regex_new(P_IMAGE_TWITTER, 0, 0, NULL); - - icon_data_by_user = g_hash_table_new_full(g_str_hash, g_str_equal, + for(i = twitter_service; i <= identica_service; i++) { + icon_hash[i] = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); - icon_data_by_user2 = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, NULL); - icon_data_by_user3 = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, NULL); + } + conv_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); + /* attach counter to the existing twitter window */ if(purple_prefs_get_bool(OPT_COUNTER)) { attach_to_window(); @@ -2328,13 +2355,20 @@ if(data->request_list) { twitter_debug("somehow, request_list != NULL\n"); } - - return; +} + +static void +cleanup_hash_entry_func(gpointer key, gpointer value, gpointer user_data) +{ + remove_marks_func(key, value, user_data); + cancel_fetch_func(key, value, user_data); } static gboolean unload_plugin(PurplePlugin *plugin) { + int i; + twitter_debug("called\n"); /* disconnect from signal */ @@ -2364,25 +2398,20 @@ plugin, PURPLE_CALLBACK(signed_on_cb)); /* unreference regp */ - int i; for(i = 0; i < NUM_REGP; i++) { g_regex_unref(regp[i]); } /* remove mark list in each hash entry */ - g_hash_table_foreach(icon_data_by_user, (GHFunc)remove_marks_func, NULL); - g_hash_table_foreach(icon_data_by_user2, (GHFunc)remove_marks_func, NULL); - g_hash_table_foreach(icon_data_by_user3, (GHFunc)remove_marks_func, NULL); - /* cancel request that has not been finished yet */ - g_hash_table_foreach(icon_data_by_user, (GHFunc)cancel_fetch_func, NULL); - g_hash_table_foreach(icon_data_by_user2, (GHFunc)cancel_fetch_func, NULL); - g_hash_table_foreach(icon_data_by_user3, (GHFunc)cancel_fetch_func, NULL); - - /* destroy hash table for icon_data */ - g_hash_table_destroy(icon_data_by_user); //XXX all memory freed? --yaz - g_hash_table_destroy(icon_data_by_user2); - g_hash_table_destroy(icon_data_by_user3); + for(i = twitter_service; i <= identica_service; i++) { + /* delete mark list and stop requeset for each hash table */ + g_hash_table_foreach(icon_hash[i], + (GHFunc)cleanup_hash_entry_func, NULL); + /* destroy hash table for icon_data */ + g_hash_table_destroy(icon_hash[i]); + } + g_hash_table_destroy(conv_hash); /* detach from twitter window */ @@ -2435,13 +2464,13 @@ icon_size_prefs_cb(const char *name, PurplePrefType type, gconstpointer val, gpointer data) { + int i; + /* invalidate icon cache */ - g_hash_table_foreach(icon_data_by_user, - (GHFunc)invalidate_icon_data_func, NULL); - g_hash_table_foreach(icon_data_by_user2, - (GHFunc)invalidate_icon_data_func, NULL); - g_hash_table_foreach(icon_data_by_user3, - (GHFunc)invalidate_icon_data_func, NULL); + for(i = twitter_service; i <= identica_service; i++) { + g_hash_table_foreach(icon_hash[i], + (GHFunc)invalidate_icon_data_func, NULL); + } } static void @@ -2549,7 +2578,7 @@ g_signal_connect(e, "toggled", G_CALLBACK(bool_toggled_cb), &e); - purple_prefs_connect_callback(plugin, OPT_API_BASE_POST, // xxx divide? + purple_prefs_connect_callback(plugin, OPT_API_BASE_POST, /* xxx divide? */ api_base_post_cb, NULL); e = GTK_WIDGET(gtk_builder_get_object (builder, "account_api_password")); @@ -2625,7 +2654,7 @@ purple_prefs_get_bool(OPT_COUNTER)); g_signal_connect(e, "toggled", G_CALLBACK(bool_toggled_cb), &e); - purple_prefs_connect_callback(plugin, OPT_COUNTER, //xxx + purple_prefs_connect_callback(plugin, OPT_COUNTER, /* xxx */ counter_prefs_cb, NULL); e = GTK_WIDGET(gtk_builder_get_object (builder, "utility_pseudo")); diff -r 3abee459c81c -r 4e9d0fd93fb6 pidgin-twitter.h --- a/pidgin-twitter.h Thu Jul 24 06:40:41 2008 +0900 +++ b/pidgin-twitter.h Thu Jul 24 21:00:34 2008 +0900 @@ -39,7 +39,7 @@ /* service id */ enum { - unknown_service = 0, + unknown_service = -1, twitter_service, wassr_service, identica_service @@ -47,10 +47,11 @@ /* container to hold icon data */ typedef struct _icon_data { - gint icon_id; // image id - gboolean requested; // TRUE if download icon has been requested - GList *request_list; // marker list - PurpleUtilFetchUrlData *fetch_data; // icon fetch data + gint icon_id; /* image id */ + gboolean requested; /* TRUE if download icon has been requested */ + GList *request_list; /* marker list */ + PurpleUtilFetchUrlData *fetch_data; /* icon fetch data */ + const gchar *img_type; /* image type */ } icon_data; /* used by got_icon_cb */ @@ -194,7 +195,7 @@ static gboolean load_plugin(PurplePlugin *plugin); static gboolean unload_plugin(PurplePlugin *plugin); static void counter_prefs_cb(const char *name, PurplePrefType type, gconstpointer val, gpointer data); -//static PurplePluginPrefFrame *get_plugin_pref_frame(PurplePlugin *plugin); + static void init_plugin(PurplePlugin *plugin); static void remove_marks_func(gpointer key, gpointer value, gpointer user_data); static void cancel_fetch_func(gpointer key, gpointer value, gpointer user_data); @@ -207,4 +208,9 @@ static gboolean get_status_with_api(gpointer data); static void read_timestamp(const char *str, struct tm *res); +static void strip_markup(gchar **str, gboolean escape); +static gchar *strip_html_markup(const gchar *src); +static GtkWidget *prefs_get_frame(PurplePlugin *plugin); + + #endif