comparison src/prpl.c @ 6846:8ab95f4c9800

[gaim-migrate @ 7391] Added new buddy icon caching code. Each GaimBuddy has its own icon, and the complete list of all icons is now stored in a set of hashtables for quick retrieval. Buddy icons now live much happier in the core, with the magma and tooth fairies (that's where they really live). committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Mon, 15 Sep 2003 07:35:49 +0000
parents 636b5215552e
children dece74f05509
comparison
equal deleted inserted replaced
6845:5de4d9a4e0e2 6846:8ab95f4c9800
100 } 100 }
101 101
102 return NULL; 102 return NULL;
103 } 103 }
104 104
105 struct icon_data {
106 GaimConnection *gc;
107 char *who;
108 void *data;
109 int len;
110 };
111
112 static GList *icons = NULL;
113
114 static gint find_icon_data(gconstpointer a, gconstpointer b)
115 {
116 const struct icon_data *x = a;
117 const struct icon_data *y = b;
118
119 return ((x->gc != y->gc) || gaim_utf8_strcasecmp(x->who, y->who));
120 }
121
122 void set_icon_data(GaimConnection *gc, const char *who, void *data, int len)
123 {
124 GaimConversation *conv;
125 struct icon_data tmp;
126 GList *l;
127 struct icon_data *id;
128 GaimBuddy *b;
129 /* i'm going to vent here a little bit about normalize(). normalize()
130 * uses a static buffer, so when we call functions that use normalize() from
131 * functions that use normalize(), whose parameters are the result of running
132 * normalize(), bad things happen. To prevent some of this, we're going
133 * to make a copy of what we get from normalize(), so we know nothing else
134 * touches it, and buddy icons don't go to the wrong person. Some day I
135 * will kill normalize(), and dance on its grave. That will be a very happy
136 * day for everyone.
137 * --ndw
138 */
139 char *realwho = g_strdup(normalize(who));
140 tmp.gc = gc;
141 tmp.who = realwho;
142 tmp.data=NULL;
143 tmp.len = 0;
144 l = g_list_find_custom(icons, &tmp, find_icon_data);
145 id = l ? l->data : NULL;
146
147 if (id) {
148 g_free(id->data);
149 if (!data) {
150 icons = g_list_remove(icons, id);
151 g_free(id->who);
152 g_free(id);
153 g_free(realwho);
154 return;
155 }
156 } else if (data) {
157 id = g_new0(struct icon_data, 1);
158 icons = g_list_append(icons, id);
159 id->gc = gc;
160 id->who = g_strdup(realwho);
161 } else {
162 g_free(realwho);
163 return;
164 }
165
166 gaim_debug(GAIM_DEBUG_MISC, "prpl", "Got icon for %s (length %d)\n",
167 realwho, len);
168
169 id->data = g_memdup(data, len);
170 id->len = len;
171
172 /* Update the buddy icon for this user. */
173 conv = gaim_find_conversation_with_account(realwho, gc->account);
174
175 /* XXX Buddy Icon should probalby be part of struct buddy instead of this weird global
176 * linked list stuff. */
177
178 if ((b = gaim_find_buddy(gc->account, realwho)) != NULL) {
179 char *random = g_strdup_printf("%x", g_random_int());
180 char *filename = g_build_filename(gaim_user_dir(), "icons", random,
181 NULL);
182 char *dirname = g_build_filename(gaim_user_dir(), "icons", NULL);
183 char *old_icon = gaim_buddy_get_setting(b, "buddy_icon");
184 FILE *file = NULL;
185
186 g_free(random);
187
188 if(!g_file_test(dirname, G_FILE_TEST_IS_DIR)) {
189 gaim_debug(GAIM_DEBUG_INFO, "buddy icons",
190 "Creating icon cache directory.\n");
191
192 if(mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0)
193 gaim_debug(GAIM_DEBUG_ERROR, "buddy icons",
194 "Unable to create directory %s: %s\n",
195 dirname, strerror(errno));
196 }
197
198 g_free(dirname);
199
200 file = fopen(filename, "wb");
201 if (file) {
202 fwrite(data, 1, len, file);
203 fclose(file);
204 }
205
206 if(old_icon) {
207 unlink(old_icon);
208 g_free(old_icon);
209 }
210
211 gaim_buddy_set_setting(b, "buddy_icon", filename);
212 gaim_blist_save();
213
214 g_free(filename);
215
216 gaim_blist_update_buddy_icon(b);
217 }
218
219 if (conv != NULL && gaim_conversation_get_gc(conv) == gc)
220 gaim_gtkconv_update_buddy_icon(conv);
221
222 g_free(realwho);
223 }
224
225 void remove_icon_data(GaimConnection *gc)
226 {
227 GList *list = icons;
228 struct icon_data *id;
229
230 while (list) {
231 id = list->data;
232 if (id->gc == gc) {
233 g_free(id->data);
234 g_free(id->who);
235 list = icons = g_list_remove(icons, id);
236 g_free(id);
237 } else
238 list = list->next;
239 }
240 }
241
242 void *get_icon_data(GaimConnection *gc, const char *who, int *len)
243 {
244 struct icon_data tmp = { gc, normalize(who), NULL, 0 };
245 GList *l = g_list_find_custom(icons, &tmp, find_icon_data);
246 struct icon_data *id = l ? l->data : NULL;
247
248 if (id) {
249 *len = id->len;
250 return id->data;
251 }
252
253 *len = 0;
254 return NULL;
255 }
256
257 struct got_add { 105 struct got_add {
258 GaimConnection *gc; 106 GaimConnection *gc;
259 char *who; 107 char *who;
260 char *alias; 108 char *alias;
261 }; 109 };