Mercurial > pidgin
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 }; |