/src/pidgin/libpurple/roomlist.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * @file roomlist.c Room List API |
3 | | * @ingroup core |
4 | | */ |
5 | | |
6 | | /* purple |
7 | | * |
8 | | * Purple is the legal property of its developers, whose names are too numerous |
9 | | * to list here. Please refer to the COPYRIGHT file distributed with this |
10 | | * source distribution. |
11 | | * |
12 | | * This program is free software; you can redistribute it and/or modify |
13 | | * it under the terms of the GNU General Public License as published by |
14 | | * the Free Software Foundation; either version 2 of the License, or |
15 | | * (at your option) any later version. |
16 | | * |
17 | | * This program is distributed in the hope that it will be useful, |
18 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | | * GNU General Public License for more details. |
21 | | * |
22 | | * You should have received a copy of the GNU General Public License |
23 | | * along with this program; if not, write to the Free Software |
24 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
25 | | */ |
26 | | |
27 | | #include "internal.h" |
28 | | |
29 | | #include "account.h" |
30 | | #include "connection.h" |
31 | | #include "debug.h" |
32 | | #include "glibcompat.h" |
33 | | #include "roomlist.h" |
34 | | #include "server.h" |
35 | | |
36 | | |
37 | | static PurpleRoomlistUiOps *ops = NULL; |
38 | | |
39 | | /**************************************************************************/ |
40 | | /** @name Room List API */ |
41 | | /**************************************************************************/ |
42 | | /*@{*/ |
43 | | |
44 | | void purple_roomlist_show_with_account(PurpleAccount *account) |
45 | 0 | { |
46 | 0 | if (ops && ops->show_with_account) |
47 | 0 | ops->show_with_account(account); |
48 | 0 | } |
49 | | |
50 | | PurpleRoomlist *purple_roomlist_new(PurpleAccount *account) |
51 | 0 | { |
52 | 0 | PurpleRoomlist *list; |
53 | |
|
54 | 0 | g_return_val_if_fail(account != NULL, NULL); |
55 | | |
56 | 0 | list = g_new0(PurpleRoomlist, 1); |
57 | 0 | list->account = account; |
58 | 0 | list->rooms = NULL; |
59 | 0 | list->fields = NULL; |
60 | 0 | list->ref = 1; |
61 | |
|
62 | 0 | if (ops && ops->create) |
63 | 0 | ops->create(list); |
64 | |
|
65 | 0 | return list; |
66 | 0 | } |
67 | | |
68 | | void purple_roomlist_ref(PurpleRoomlist *list) |
69 | 0 | { |
70 | 0 | g_return_if_fail(list != NULL); |
71 | | |
72 | 0 | list->ref++; |
73 | 0 | purple_debug_misc("roomlist", "reffing list, ref count now %d\n", list->ref); |
74 | 0 | } |
75 | | |
76 | | static void purple_roomlist_room_destroy(PurpleRoomlist *list, PurpleRoomlistRoom *r) |
77 | 0 | { |
78 | 0 | GList *l, *j; |
79 | |
|
80 | 0 | for (l = list->fields, j = r->fields; l && j; l = l->next, j = j->next) { |
81 | 0 | PurpleRoomlistField *f = l->data; |
82 | 0 | if (f->type == PURPLE_ROOMLIST_FIELD_STRING) |
83 | 0 | g_free(j->data); |
84 | 0 | } |
85 | |
|
86 | 0 | g_list_free(r->fields); |
87 | 0 | g_free(r->name); |
88 | 0 | g_free(r); |
89 | 0 | } |
90 | | |
91 | | static void purple_roomlist_field_destroy(PurpleRoomlistField *f) |
92 | 0 | { |
93 | 0 | g_free(f->label); |
94 | 0 | g_free(f->name); |
95 | 0 | g_free(f); |
96 | 0 | } |
97 | | |
98 | | static void purple_roomlist_destroy(PurpleRoomlist *list) |
99 | 0 | { |
100 | 0 | GList *l; |
101 | |
|
102 | 0 | purple_debug_misc("roomlist", "destroying list %p\n", list); |
103 | |
|
104 | 0 | if (ops && ops->destroy) |
105 | 0 | ops->destroy(list); |
106 | |
|
107 | 0 | for (l = list->rooms; l; l = l->next) { |
108 | 0 | PurpleRoomlistRoom *r = l->data; |
109 | 0 | purple_roomlist_room_destroy(list, r); |
110 | 0 | } |
111 | 0 | g_list_free(list->rooms); |
112 | |
|
113 | 0 | g_list_free_full(list->fields, |
114 | 0 | (GDestroyNotify)purple_roomlist_field_destroy); |
115 | |
|
116 | 0 | g_free(list); |
117 | 0 | } |
118 | | |
119 | | void purple_roomlist_unref(PurpleRoomlist *list) |
120 | 0 | { |
121 | 0 | g_return_if_fail(list != NULL); |
122 | 0 | g_return_if_fail(list->ref > 0); |
123 | | |
124 | 0 | list->ref--; |
125 | |
|
126 | 0 | purple_debug_misc("roomlist", "unreffing list, ref count now %d\n", list->ref); |
127 | 0 | if (list->ref == 0) |
128 | 0 | purple_roomlist_destroy(list); |
129 | 0 | } |
130 | | |
131 | | void purple_roomlist_set_fields(PurpleRoomlist *list, GList *fields) |
132 | 0 | { |
133 | 0 | g_return_if_fail(list != NULL); |
134 | | |
135 | 0 | list->fields = fields; |
136 | |
|
137 | 0 | if (ops && ops->set_fields) |
138 | 0 | ops->set_fields(list, fields); |
139 | 0 | } |
140 | | |
141 | | void purple_roomlist_set_in_progress(PurpleRoomlist *list, gboolean in_progress) |
142 | 0 | { |
143 | 0 | g_return_if_fail(list != NULL); |
144 | | |
145 | 0 | list->in_progress = in_progress; |
146 | |
|
147 | 0 | if (ops && ops->in_progress) |
148 | 0 | ops->in_progress(list, in_progress); |
149 | 0 | } |
150 | | |
151 | | gboolean purple_roomlist_get_in_progress(PurpleRoomlist *list) |
152 | 0 | { |
153 | 0 | g_return_val_if_fail(list != NULL, FALSE); |
154 | | |
155 | 0 | return list->in_progress; |
156 | 0 | } |
157 | | |
158 | | void purple_roomlist_room_add(PurpleRoomlist *list, PurpleRoomlistRoom *room) |
159 | 0 | { |
160 | 0 | g_return_if_fail(list != NULL); |
161 | 0 | g_return_if_fail(room != NULL); |
162 | | |
163 | 0 | list->rooms = g_list_append(list->rooms, room); |
164 | |
|
165 | 0 | if (ops && ops->add_room) |
166 | 0 | ops->add_room(list, room); |
167 | 0 | } |
168 | | |
169 | | PurpleRoomlist *purple_roomlist_get_list(PurpleConnection *gc) |
170 | 0 | { |
171 | 0 | PurplePlugin *prpl = NULL; |
172 | 0 | PurplePluginProtocolInfo *prpl_info = NULL; |
173 | |
|
174 | 0 | g_return_val_if_fail(gc != NULL, NULL); |
175 | 0 | g_return_val_if_fail(PURPLE_CONNECTION_IS_CONNECTED(gc), NULL); |
176 | | |
177 | 0 | prpl = purple_connection_get_prpl(gc); |
178 | |
|
179 | 0 | if(prpl != NULL) |
180 | 0 | prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); |
181 | |
|
182 | 0 | if(prpl_info && prpl_info->roomlist_get_list) |
183 | 0 | return prpl_info->roomlist_get_list(gc); |
184 | | |
185 | 0 | return NULL; |
186 | 0 | } |
187 | | |
188 | | void purple_roomlist_cancel_get_list(PurpleRoomlist *list) |
189 | 0 | { |
190 | 0 | PurplePlugin *prpl = NULL; |
191 | 0 | PurplePluginProtocolInfo *prpl_info = NULL; |
192 | 0 | PurpleConnection *gc; |
193 | |
|
194 | 0 | g_return_if_fail(list != NULL); |
195 | | |
196 | 0 | gc = purple_account_get_connection(list->account); |
197 | |
|
198 | 0 | g_return_if_fail(gc != NULL); |
199 | | |
200 | 0 | if(gc) |
201 | 0 | prpl = purple_connection_get_prpl(gc); |
202 | |
|
203 | 0 | if(prpl) |
204 | 0 | prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); |
205 | |
|
206 | 0 | if(prpl_info && prpl_info->roomlist_cancel) |
207 | 0 | prpl_info->roomlist_cancel(list); |
208 | 0 | } |
209 | | |
210 | | void purple_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category) |
211 | 0 | { |
212 | 0 | PurplePlugin *prpl = NULL; |
213 | 0 | PurplePluginProtocolInfo *prpl_info = NULL; |
214 | 0 | PurpleConnection *gc; |
215 | |
|
216 | 0 | g_return_if_fail(list != NULL); |
217 | 0 | g_return_if_fail(category != NULL); |
218 | 0 | g_return_if_fail(category->type & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY); |
219 | | |
220 | 0 | gc = purple_account_get_connection(list->account); |
221 | 0 | g_return_if_fail(gc != NULL); |
222 | | |
223 | 0 | if(gc) |
224 | 0 | prpl = purple_connection_get_prpl(gc); |
225 | |
|
226 | 0 | if(prpl) |
227 | 0 | prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); |
228 | |
|
229 | 0 | if(prpl_info && prpl_info->roomlist_expand_category) |
230 | 0 | prpl_info->roomlist_expand_category(list, category); |
231 | 0 | } |
232 | | |
233 | | GList * purple_roomlist_get_fields(PurpleRoomlist *list) |
234 | 0 | { |
235 | 0 | return list->fields; |
236 | 0 | } |
237 | | |
238 | | /*@}*/ |
239 | | |
240 | | /**************************************************************************/ |
241 | | /** @name Room API */ |
242 | | /**************************************************************************/ |
243 | | /*@{*/ |
244 | | |
245 | | PurpleRoomlistRoom *purple_roomlist_room_new(PurpleRoomlistRoomType type, const gchar *name, |
246 | | PurpleRoomlistRoom *parent) |
247 | 0 | { |
248 | 0 | PurpleRoomlistRoom *room; |
249 | |
|
250 | 0 | g_return_val_if_fail(name != NULL, NULL); |
251 | | |
252 | 0 | room = g_new0(PurpleRoomlistRoom, 1); |
253 | 0 | room->type = type; |
254 | 0 | room->name = g_strdup(name); |
255 | 0 | room->parent = parent; |
256 | |
|
257 | 0 | return room; |
258 | 0 | } |
259 | | |
260 | | void purple_roomlist_room_add_field(PurpleRoomlist *list, PurpleRoomlistRoom *room, gconstpointer field) |
261 | 0 | { |
262 | 0 | PurpleRoomlistField *f; |
263 | |
|
264 | 0 | g_return_if_fail(list != NULL); |
265 | 0 | g_return_if_fail(room != NULL); |
266 | 0 | g_return_if_fail(list->fields != NULL); |
267 | | |
268 | | /* If this is the first call for this room, grab the first field in |
269 | | * the Roomlist's fields. Otherwise, grab the field that is one |
270 | | * more than the number of fields already present for the room. |
271 | | * (This works because g_list_nth_data() is zero-indexed and |
272 | | * g_list_length() is one-indexed.) */ |
273 | 0 | if (!room->fields) |
274 | 0 | f = list->fields->data; |
275 | 0 | else |
276 | 0 | f = g_list_nth_data(list->fields, g_list_length(room->fields)); |
277 | |
|
278 | 0 | g_return_if_fail(f != NULL); |
279 | | |
280 | 0 | switch(f->type) { |
281 | 0 | case PURPLE_ROOMLIST_FIELD_STRING: |
282 | 0 | room->fields = g_list_append(room->fields, g_strdup(field)); |
283 | 0 | break; |
284 | 0 | case PURPLE_ROOMLIST_FIELD_BOOL: |
285 | 0 | case PURPLE_ROOMLIST_FIELD_INT: |
286 | 0 | room->fields = g_list_append(room->fields, GINT_TO_POINTER(field)); |
287 | 0 | break; |
288 | 0 | } |
289 | 0 | } |
290 | | |
291 | | void purple_roomlist_room_join(PurpleRoomlist *list, PurpleRoomlistRoom *room) |
292 | 0 | { |
293 | 0 | GHashTable *components; |
294 | 0 | GList *l, *j; |
295 | 0 | PurpleConnection *gc; |
296 | |
|
297 | 0 | g_return_if_fail(list != NULL); |
298 | 0 | g_return_if_fail(room != NULL); |
299 | | |
300 | 0 | gc = purple_account_get_connection(list->account); |
301 | 0 | if (!gc) |
302 | 0 | return; |
303 | | |
304 | 0 | components = g_hash_table_new(g_str_hash, g_str_equal); |
305 | |
|
306 | 0 | g_hash_table_replace(components, "name", room->name); |
307 | 0 | for (l = list->fields, j = room->fields; l && j; l = l->next, j = j->next) { |
308 | 0 | PurpleRoomlistField *f = l->data; |
309 | |
|
310 | 0 | g_hash_table_replace(components, f->name, j->data); |
311 | 0 | } |
312 | |
|
313 | 0 | serv_join_chat(gc, components); |
314 | |
|
315 | 0 | g_hash_table_destroy(components); |
316 | 0 | } |
317 | | |
318 | | PurpleRoomlistRoomType purple_roomlist_room_get_type(PurpleRoomlistRoom *room) |
319 | 0 | { |
320 | 0 | return room->type; |
321 | 0 | } |
322 | | |
323 | | const char * purple_roomlist_room_get_name(PurpleRoomlistRoom *room) |
324 | 0 | { |
325 | 0 | return room->name; |
326 | 0 | } |
327 | | |
328 | | PurpleRoomlistRoom * purple_roomlist_room_get_parent(PurpleRoomlistRoom *room) |
329 | 0 | { |
330 | 0 | return room->parent; |
331 | 0 | } |
332 | | |
333 | | GList * purple_roomlist_room_get_fields(PurpleRoomlistRoom *room) |
334 | 0 | { |
335 | 0 | return room->fields; |
336 | 0 | } |
337 | | |
338 | | /*@}*/ |
339 | | |
340 | | /**************************************************************************/ |
341 | | /** @name Room Field API */ |
342 | | /**************************************************************************/ |
343 | | /*@{*/ |
344 | | |
345 | | PurpleRoomlistField *purple_roomlist_field_new(PurpleRoomlistFieldType type, |
346 | | const gchar *label, const gchar *name, |
347 | | gboolean hidden) |
348 | 0 | { |
349 | 0 | PurpleRoomlistField *f; |
350 | |
|
351 | 0 | g_return_val_if_fail(label != NULL, NULL); |
352 | 0 | g_return_val_if_fail(name != NULL, NULL); |
353 | | |
354 | 0 | f = g_new0(PurpleRoomlistField, 1); |
355 | |
|
356 | 0 | f->type = type; |
357 | 0 | f->label = g_strdup(label); |
358 | 0 | f->name = g_strdup(name); |
359 | 0 | f->hidden = hidden; |
360 | |
|
361 | 0 | return f; |
362 | 0 | } |
363 | | |
364 | | PurpleRoomlistFieldType purple_roomlist_field_get_type(PurpleRoomlistField *field) |
365 | 0 | { |
366 | 0 | return field->type; |
367 | 0 | } |
368 | | |
369 | | const char * purple_roomlist_field_get_label(PurpleRoomlistField *field) |
370 | 0 | { |
371 | 0 | return field->label; |
372 | 0 | } |
373 | | |
374 | | gboolean purple_roomlist_field_get_hidden(PurpleRoomlistField *field) |
375 | 0 | { |
376 | 0 | return field->hidden; |
377 | 0 | } |
378 | | |
379 | | /*@}*/ |
380 | | |
381 | | /**************************************************************************/ |
382 | | /** @name UI Registration Functions */ |
383 | | /**************************************************************************/ |
384 | | /*@{*/ |
385 | | |
386 | | |
387 | | void purple_roomlist_set_ui_ops(PurpleRoomlistUiOps *ui_ops) |
388 | 0 | { |
389 | 0 | ops = ui_ops; |
390 | 0 | } |
391 | | |
392 | | PurpleRoomlistUiOps *purple_roomlist_get_ui_ops(void) |
393 | 0 | { |
394 | 0 | return ops; |
395 | 0 | } |
396 | | |
397 | | /*@}*/ |