Mercurial > pidgin
annotate src/roomlist.c @ 13967:99b9b58b19dd
[gaim-migrate @ 16523]
Fix a crazy MSN crash. Basically it's possible to have more than one
slplink associated with a given switchboard, but our code did not
allow for that. I think it happens when you're in a multi-user
chat and you do stuff with multiple users that involves slplinks.
Like maybe file transfer and buddy icon related stuff.
Tracking this down took an ungodly amount of time, but thanks to
Meebo for letting me do it :-)
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 20 Jul 2006 07:31:15 +0000 |
parents | 5e2a365af01b |
children | 8bda65b88e49 |
rev | line source |
---|---|
8113 | 1 /** |
2 * @file roomlist.c Room List API | |
3 * @ingroup core | |
4 * | |
5 * gaim | |
6 * | |
8146 | 7 * Gaim is the legal property of its developers, whose names are too numerous |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
8113 | 10 * |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 */ | |
25 | |
26 #include <glib.h> | |
27 | |
28 #include "account.h" | |
29 #include "connection.h" | |
30 #include "debug.h" | |
31 #include "roomlist.h" | |
8199 | 32 #include "server.h" |
8113 | 33 |
34 | |
35 static GaimRoomlistUiOps *ops = NULL; | |
36 | |
37 /**************************************************************************/ | |
38 /** @name Room List API */ | |
39 /**************************************************************************/ | |
40 /*@{*/ | |
41 | |
8352 | 42 void gaim_roomlist_show_with_account(GaimAccount *account) |
43 { | |
44 if (ops && ops->show_with_account) | |
45 ops->show_with_account(account); | |
46 } | |
47 | |
8113 | 48 GaimRoomlist *gaim_roomlist_new(GaimAccount *account) |
49 { | |
50 GaimRoomlist *list; | |
51 | |
52 g_return_val_if_fail(account != NULL, NULL); | |
53 | |
54 list = g_new0(GaimRoomlist, 1); | |
55 list->account = account; | |
56 list->rooms = NULL; | |
57 list->fields = NULL; | |
58 list->ref = 1; | |
59 | |
10027 | 60 if (ops && ops->create) |
61 ops->create(list); | |
8113 | 62 |
63 return list; | |
64 } | |
65 | |
66 void gaim_roomlist_ref(GaimRoomlist *list) | |
67 { | |
68 g_return_if_fail(list != NULL); | |
69 | |
70 list->ref++; | |
71 gaim_debug_misc("roomlist", "reffing list, ref count now %d\n", list->ref); | |
72 } | |
73 | |
74 static void gaim_roomlist_room_destroy(GaimRoomlist *list, GaimRoomlistRoom *r) | |
75 { | |
76 GList *l, *j; | |
77 | |
78 for (l = list->fields, j = r->fields; l && j; l = l->next, j = j->next) { | |
79 GaimRoomlistField *f = l->data; | |
80 if (f->type == GAIM_ROOMLIST_FIELD_STRING) | |
81 g_free(j->data); | |
82 } | |
83 | |
84 g_list_free(r->fields); | |
85 g_free(r->name); | |
86 g_free(r); | |
87 } | |
88 | |
89 static void gaim_roomlist_field_destroy(GaimRoomlistField *f) | |
90 { | |
91 g_free(f->label); | |
92 g_free(f->name); | |
93 g_free(f); | |
94 } | |
95 | |
96 static void gaim_roomlist_destroy(GaimRoomlist *list) | |
97 { | |
98 GList *l; | |
99 | |
100 gaim_debug_misc("roomlist", "destroying list %p\n", list); | |
101 | |
102 if (ops && ops->destroy) | |
103 ops->destroy(list); | |
104 | |
105 if (list->rooms) { | |
106 for (l = list->rooms; l; l = l->next) { | |
107 GaimRoomlistRoom *r = l->data; | |
108 gaim_roomlist_room_destroy(list, r); | |
109 } | |
110 g_list_free(list->rooms); | |
111 } | |
112 | |
113 if (list->fields) { | |
114 for (l = list->fields; l; l = l->next) { | |
115 GaimRoomlistField *f = l->data; | |
116 gaim_roomlist_field_destroy(f); | |
117 } | |
118 g_list_free(list->fields); | |
119 } | |
120 | |
121 g_free(list); | |
122 } | |
123 | |
124 void gaim_roomlist_unref(GaimRoomlist *list) | |
125 { | |
126 g_return_if_fail(list != NULL); | |
12250
5e2a365af01b
[gaim-migrate @ 14552]
Richard Laager <rlaager@wiktel.com>
parents:
10027
diff
changeset
|
127 g_return_if_fail(list->ref > 0); |
8113 | 128 |
129 list->ref--; | |
130 | |
131 gaim_debug_misc("roomlist", "unreffing list, ref count now %d\n", list->ref); | |
132 if (list->ref == 0) | |
133 gaim_roomlist_destroy(list); | |
134 } | |
135 | |
136 void gaim_roomlist_set_fields(GaimRoomlist *list, GList *fields) | |
137 { | |
138 g_return_if_fail(list != NULL); | |
139 | |
140 list->fields = fields; | |
141 | |
142 if (ops && ops->set_fields) | |
143 ops->set_fields(list, fields); | |
144 } | |
145 | |
146 void gaim_roomlist_set_in_progress(GaimRoomlist *list, gboolean in_progress) | |
147 { | |
148 g_return_if_fail(list != NULL); | |
149 | |
8199 | 150 list->in_progress = in_progress; |
151 | |
8113 | 152 if (ops && ops->in_progress) |
153 ops->in_progress(list, in_progress); | |
154 } | |
155 | |
8199 | 156 gboolean gaim_roomlist_get_in_progress(GaimRoomlist *list) |
157 { | |
158 g_return_val_if_fail(list != NULL, FALSE); | |
159 | |
160 return list->in_progress; | |
161 } | |
162 | |
8113 | 163 void gaim_roomlist_room_add(GaimRoomlist *list, GaimRoomlistRoom *room) |
164 { | |
165 g_return_if_fail(list != NULL); | |
166 g_return_if_fail(room != NULL); | |
167 | |
168 list->rooms = g_list_append(list->rooms, room); | |
169 | |
170 if (ops && ops->add_room) | |
171 ops->add_room(list, room); | |
172 } | |
173 | |
174 GaimRoomlist *gaim_roomlist_get_list(GaimConnection *gc) | |
175 { | |
176 GaimPluginProtocolInfo *prpl_info = NULL; | |
177 | |
178 g_return_val_if_fail(gc != NULL, NULL); | |
179 | |
180 if (gc->prpl != NULL) | |
181 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
182 | |
183 if (prpl_info && prpl_info->roomlist_get_list) | |
184 return prpl_info->roomlist_get_list(gc); | |
185 return NULL; | |
186 } | |
187 | |
188 void gaim_roomlist_cancel_get_list(GaimRoomlist *list) | |
189 { | |
190 GaimPluginProtocolInfo *prpl_info = NULL; | |
191 GaimConnection *gc; | |
192 | |
193 g_return_if_fail(list != NULL); | |
194 | |
195 gc = gaim_account_get_connection(list->account); | |
196 | |
197 g_return_if_fail(gc != NULL); | |
198 | |
199 if (gc != NULL && gc->prpl != NULL) | |
200 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
201 | |
202 if (prpl_info && prpl_info->roomlist_cancel) | |
203 prpl_info->roomlist_cancel(list); | |
204 } | |
205 | |
8584 | 206 void gaim_roomlist_expand_category(GaimRoomlist *list, GaimRoomlistRoom *category) |
8113 | 207 { |
208 GaimPluginProtocolInfo *prpl_info = NULL; | |
209 GaimConnection *gc; | |
210 | |
211 g_return_if_fail(list != NULL); | |
8584 | 212 g_return_if_fail(category != NULL); |
213 g_return_if_fail(category->type & GAIM_ROOMLIST_ROOMTYPE_CATEGORY); | |
8113 | 214 |
215 gc = gaim_account_get_connection(list->account); | |
216 g_return_if_fail(gc != NULL); | |
217 | |
218 if (gc->prpl != NULL) | |
219 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
220 | |
8584 | 221 if (prpl_info && prpl_info->roomlist_expand_category) |
222 prpl_info->roomlist_expand_category(list, category); | |
8113 | 223 } |
224 | |
225 /*@}*/ | |
226 | |
227 /**************************************************************************/ | |
228 /** @name Room API */ | |
229 /**************************************************************************/ | |
230 /*@{*/ | |
231 | |
232 GaimRoomlistRoom *gaim_roomlist_room_new(GaimRoomlistRoomType type, const gchar *name, | |
233 GaimRoomlistRoom *parent) | |
234 { | |
235 GaimRoomlistRoom *room; | |
236 | |
237 g_return_val_if_fail(name != NULL, NULL); | |
238 | |
239 room = g_new0(GaimRoomlistRoom, 1); | |
240 room->type = type; | |
241 room->name = g_strdup(name); | |
242 room->parent = parent; | |
243 | |
244 return room; | |
245 } | |
246 | |
247 void gaim_roomlist_room_add_field(GaimRoomlist *list, GaimRoomlistRoom *room, gconstpointer field) | |
248 { | |
249 GaimRoomlistField *f; | |
250 | |
251 g_return_if_fail(list != NULL); | |
252 g_return_if_fail(room != NULL); | |
253 g_return_if_fail(list->fields != NULL); | |
254 | |
255 if (!room->fields) | |
256 f = list->fields->data; | |
257 else | |
258 f = g_list_nth_data(list->fields, g_list_length(room->fields)); | |
259 | |
260 g_return_if_fail(f != NULL); | |
261 | |
262 switch(f->type) { | |
263 case GAIM_ROOMLIST_FIELD_STRING: | |
264 room->fields = g_list_append(room->fields, g_strdup(field)); | |
265 break; | |
266 case GAIM_ROOMLIST_FIELD_BOOL: | |
267 case GAIM_ROOMLIST_FIELD_INT: | |
268 room->fields = g_list_append(room->fields, GINT_TO_POINTER(field)); | |
269 break; | |
270 } | |
271 } | |
272 | |
8199 | 273 void gaim_roomlist_room_join(GaimRoomlist *list, GaimRoomlistRoom *room) |
274 { | |
275 GHashTable *components; | |
276 GList *l, *j; | |
277 GaimConnection *gc; | |
278 | |
279 g_return_if_fail(list != NULL); | |
280 g_return_if_fail(room != NULL); | |
281 | |
282 gc = gaim_account_get_connection(list->account); | |
283 if (!gc) | |
284 return; | |
285 | |
286 components = g_hash_table_new(g_str_hash, g_str_equal); | |
287 | |
288 g_hash_table_replace(components, "name", room->name); | |
289 for (l = list->fields, j = room->fields; l && j; l = l->next, j = j->next) { | |
290 GaimRoomlistField *f = l->data; | |
291 | |
292 g_hash_table_replace(components, f->name, j->data); | |
293 } | |
294 | |
295 serv_join_chat(gc, components); | |
296 | |
297 g_hash_table_destroy(components); | |
298 } | |
299 | |
8113 | 300 /*@}*/ |
301 | |
302 /**************************************************************************/ | |
303 /** @name Room Field API */ | |
304 /**************************************************************************/ | |
305 /*@{*/ | |
306 | |
307 GaimRoomlistField *gaim_roomlist_field_new(GaimRoomlistFieldType type, | |
308 const gchar *label, const gchar *name, | |
309 gboolean hidden) | |
310 { | |
311 GaimRoomlistField *f; | |
312 | |
313 g_return_val_if_fail(label != NULL, NULL); | |
314 g_return_val_if_fail(name != NULL, NULL); | |
315 | |
316 f = g_new0(GaimRoomlistField, 1); | |
317 | |
318 f->type = type; | |
319 f->label = g_strdup(label); | |
320 f->name = g_strdup(name); | |
321 f->hidden = hidden; | |
322 | |
323 return f; | |
324 } | |
325 | |
326 /*@}*/ | |
327 | |
328 /**************************************************************************/ | |
329 /** @name UI Registration Functions */ | |
330 /**************************************************************************/ | |
331 /*@{*/ | |
332 | |
333 | |
334 void gaim_roomlist_set_ui_ops(GaimRoomlistUiOps *ui_ops) | |
335 { | |
336 ops = ui_ops; | |
337 } | |
338 | |
339 GaimRoomlistUiOps *gaim_roomlist_get_ui_ops(void) | |
340 { | |
341 return ops; | |
342 } | |
343 | |
344 /*@}*/ |